@unif/react-native-chat 2.1.1 → 2.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -6
- package/lib/module/components/Attachments/AttachmentItem.js +3 -5
- package/lib/module/components/Attachments/AttachmentItem.js.map +1 -1
- package/lib/module/components/Message/MarkdownContent/MarkdownContent.js +16 -5
- package/lib/module/components/Message/MarkdownContent/MarkdownContent.js.map +1 -1
- package/lib/module/components/MessageList/MessageList.js +64 -156
- package/lib/module/components/MessageList/MessageList.js.map +1 -1
- package/lib/module/components/MessageList/MessageListRow.js +23 -0
- package/lib/module/components/MessageList/MessageListRow.js.map +1 -0
- package/lib/module/components/MessageList/useMessageListScroll.js +153 -0
- package/lib/module/components/MessageList/useMessageListScroll.js.map +1 -0
- package/lib/module/components/MessageList/webPrependAnchor/useWebPrependAnchor.web.js +35 -26
- package/lib/module/components/MessageList/webPrependAnchor/useWebPrependAnchor.web.js.map +1 -1
- package/lib/module/components/ProcessingProgress/ProcessingProgress.js +46 -0
- package/lib/module/components/ProcessingProgress/ProcessingProgress.js.map +1 -0
- package/lib/module/components/ProcessingProgress/ProcessingProgressPrefix.js +53 -0
- package/lib/module/components/ProcessingProgress/ProcessingProgressPrefix.js.map +1 -0
- package/lib/module/components/ProcessingProgress/constants.js +7 -0
- package/lib/module/components/ProcessingProgress/constants.js.map +1 -0
- package/lib/module/components/ProcessingProgress/index.js +4 -0
- package/lib/module/components/ProcessingProgress/index.js.map +1 -0
- package/lib/module/components/ProcessingProgress/styles.js +17 -0
- package/lib/module/components/ProcessingProgress/styles.js.map +1 -0
- package/lib/module/components/ProcessingProgress/types.js +2 -0
- package/lib/module/components/ProcessingProgress/types.js.map +1 -0
- package/lib/module/index.js +1 -0
- package/lib/module/index.js.map +1 -1
- package/lib/typescript/src/components/Attachments/AttachmentItem.d.ts.map +1 -1
- package/lib/typescript/src/components/Attachments/types.d.ts +1 -1
- package/lib/typescript/src/components/Attachments/types.d.ts.map +1 -1
- package/lib/typescript/src/components/Message/MarkdownContent/MarkdownContent.d.ts.map +1 -1
- package/lib/typescript/src/components/Message/MarkdownContent/types.d.ts +3 -0
- package/lib/typescript/src/components/Message/MarkdownContent/types.d.ts.map +1 -1
- package/lib/typescript/src/components/MessageList/MessageList.d.ts.map +1 -1
- package/lib/typescript/src/components/MessageList/MessageListRow.d.ts +11 -0
- package/lib/typescript/src/components/MessageList/MessageListRow.d.ts.map +1 -0
- package/lib/typescript/src/components/MessageList/useMessageListScroll.d.ts +21 -0
- package/lib/typescript/src/components/MessageList/useMessageListScroll.d.ts.map +1 -0
- package/lib/typescript/src/components/MessageList/webPrependAnchor/types.d.ts +2 -0
- package/lib/typescript/src/components/MessageList/webPrependAnchor/types.d.ts.map +1 -1
- package/lib/typescript/src/components/MessageList/webPrependAnchor/useWebPrependAnchor.web.d.ts.map +1 -1
- package/lib/typescript/src/components/ProcessingProgress/ProcessingProgress.d.ts +3 -0
- package/lib/typescript/src/components/ProcessingProgress/ProcessingProgress.d.ts.map +1 -0
- package/lib/typescript/src/components/ProcessingProgress/ProcessingProgressPrefix.d.ts +3 -0
- package/lib/typescript/src/components/ProcessingProgress/ProcessingProgressPrefix.d.ts.map +1 -0
- package/lib/typescript/src/components/ProcessingProgress/constants.d.ts +5 -0
- package/lib/typescript/src/components/ProcessingProgress/constants.d.ts.map +1 -0
- package/lib/typescript/src/components/ProcessingProgress/index.d.ts +3 -0
- package/lib/typescript/src/components/ProcessingProgress/index.d.ts.map +1 -0
- package/lib/typescript/src/components/ProcessingProgress/styles.d.ts +14 -0
- package/lib/typescript/src/components/ProcessingProgress/styles.d.ts.map +1 -0
- package/lib/typescript/src/components/ProcessingProgress/types.d.ts +9 -0
- package/lib/typescript/src/components/ProcessingProgress/types.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 +3 -3
- package/src/components/Attachments/AttachmentItem.tsx +2 -7
- package/src/components/Attachments/types.ts +1 -1
- package/src/components/Message/MarkdownContent/MarkdownContent.tsx +22 -5
- package/src/components/Message/MarkdownContent/types.ts +4 -0
- package/src/components/MessageList/MessageList.tsx +77 -176
- package/src/components/MessageList/MessageListRow.tsx +35 -0
- package/src/components/MessageList/useMessageListScroll.ts +216 -0
- package/src/components/MessageList/webPrependAnchor/types.ts +2 -0
- package/src/components/MessageList/webPrependAnchor/useWebPrependAnchor.web.ts +121 -87
- package/src/components/ProcessingProgress/ProcessingProgress.tsx +49 -0
- package/src/components/ProcessingProgress/ProcessingProgressPrefix.tsx +68 -0
- package/src/components/ProcessingProgress/constants.ts +4 -0
- package/src/components/ProcessingProgress/index.ts +2 -0
- package/src/components/ProcessingProgress/styles.ts +17 -0
- package/src/components/ProcessingProgress/types.ts +9 -0
- package/src/index.tsx +2 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { useId, useLayoutEffect, useRef } from 'react';
|
|
1
|
+
import { useCallback, useId, useLayoutEffect, useRef } from 'react';
|
|
2
2
|
import { Platform } from 'react-native';
|
|
3
3
|
import { USER_INTERACTION_EVENTS } from './constants';
|
|
4
4
|
import type {
|
|
@@ -26,8 +26,9 @@ function isWebElementLike(value: unknown): value is WebElementLike {
|
|
|
26
26
|
|
|
27
27
|
function sameKeys(left: readonly string[], right: readonly string[]): boolean {
|
|
28
28
|
return (
|
|
29
|
-
left
|
|
30
|
-
left.
|
|
29
|
+
left === right ||
|
|
30
|
+
(left.length === right.length &&
|
|
31
|
+
left.every((key, index) => key === right[index]))
|
|
31
32
|
);
|
|
32
33
|
}
|
|
33
34
|
|
|
@@ -79,111 +80,135 @@ export function useWebPrependAnchor({
|
|
|
79
80
|
|
|
80
81
|
const globals = globalThis as unknown as WebGlobals;
|
|
81
82
|
|
|
82
|
-
const getRowNativeID = (
|
|
83
|
-
`${rowNativeIDPrefix}-${encodeURIComponent(key)}
|
|
83
|
+
const getRowNativeID = useCallback(
|
|
84
|
+
(key: string) => `${rowNativeIDPrefix}-${encodeURIComponent(key)}`,
|
|
85
|
+
[rowNativeIDPrefix]
|
|
86
|
+
);
|
|
84
87
|
|
|
85
|
-
const getRows = (
|
|
86
|
-
|
|
87
|
-
(
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
88
|
+
const getRows = useCallback(
|
|
89
|
+
(scroller: WebElementLike): WebElementLike[] =>
|
|
90
|
+
Array.from(scroller.querySelectorAll('[id]')).filter(
|
|
91
|
+
(candidate): candidate is WebElementLike =>
|
|
92
|
+
isWebElementLike(candidate) &&
|
|
93
|
+
candidate.id.startsWith(`${rowNativeIDPrefix}-`)
|
|
94
|
+
),
|
|
95
|
+
[rowNativeIDPrefix]
|
|
96
|
+
);
|
|
91
97
|
|
|
92
|
-
const findRow = (
|
|
93
|
-
scroller: WebElementLike,
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
98
|
+
const findRow = useCallback(
|
|
99
|
+
(scroller: WebElementLike, id: string): WebElementLike | undefined => {
|
|
100
|
+
const candidate = globals.document?.getElementById(id);
|
|
101
|
+
return isWebElementLike(candidate) && scroller.contains(candidate)
|
|
102
|
+
? candidate
|
|
103
|
+
: undefined;
|
|
104
|
+
},
|
|
105
|
+
[globals]
|
|
106
|
+
);
|
|
101
107
|
|
|
102
|
-
const captureAnchor = (
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
const
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
108
|
+
const captureAnchor = useCallback(
|
|
109
|
+
(connection: WebPrependAnchorConnection) => {
|
|
110
|
+
const viewport = connection.scroller.getBoundingClientRect();
|
|
111
|
+
const firstVisible = getRows(connection.scroller).find((row) => {
|
|
112
|
+
const rect = row.getBoundingClientRect();
|
|
113
|
+
return rect.bottom > viewport.top && rect.top < viewport.bottom;
|
|
114
|
+
});
|
|
115
|
+
if (!firstVisible) return;
|
|
116
|
+
lastAnchorRef.current = {
|
|
117
|
+
id: firstVisible.id,
|
|
118
|
+
top: firstVisible.getBoundingClientRect().top - viewport.top,
|
|
119
|
+
scrollHeight: connection.scroller.scrollHeight,
|
|
120
|
+
scrollTop: connection.scroller.scrollTop,
|
|
121
|
+
};
|
|
122
|
+
},
|
|
123
|
+
[getRows]
|
|
124
|
+
);
|
|
116
125
|
|
|
117
|
-
const refreshResizeTargets = (
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
if (
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
126
|
+
const refreshResizeTargets = useCallback(
|
|
127
|
+
(connection: WebPrependAnchorConnection) => {
|
|
128
|
+
const resizeObserver = connection.resizeObserver;
|
|
129
|
+
if (!resizeObserver) return;
|
|
130
|
+
const nextTargets = new Set([
|
|
131
|
+
connection.scroller,
|
|
132
|
+
...getRows(connection.scroller),
|
|
133
|
+
]);
|
|
134
|
+
// RN Web exposes its content node here. Observe direct wrappers too:
|
|
135
|
+
// opposite header/footer resizes can leave the total height unchanged.
|
|
136
|
+
const content = connection.scroller.getInnerViewNode?.();
|
|
137
|
+
if (isWebElementLike(content)) {
|
|
138
|
+
nextTargets.add(content);
|
|
139
|
+
for (const child of Array.from(content.children ?? [])) {
|
|
140
|
+
if (isWebElementLike(child)) nextTargets.add(child);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
connection.resizeTargets.forEach((target) => {
|
|
144
|
+
if (!nextTargets.has(target)) resizeObserver.unobserve?.(target);
|
|
145
|
+
});
|
|
146
|
+
nextTargets.forEach((target) => {
|
|
147
|
+
if (!connection.resizeTargets.has(target))
|
|
148
|
+
resizeObserver.observe(target);
|
|
149
|
+
});
|
|
150
|
+
connection.resizeTargets = nextTargets;
|
|
151
|
+
},
|
|
152
|
+
[getRows]
|
|
153
|
+
);
|
|
132
154
|
|
|
133
|
-
const correctPrepend = (
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
155
|
+
const correctPrepend = useCallback(
|
|
156
|
+
(connection: WebPrependAnchorConnection) => {
|
|
157
|
+
const preservation = preservationRef.current;
|
|
158
|
+
if (!preservation) return;
|
|
159
|
+
const anchor = findRow(connection.scroller, preservation.id);
|
|
160
|
+
if (anchor) {
|
|
161
|
+
const viewport = connection.scroller.getBoundingClientRect();
|
|
162
|
+
const currentTop = anchor.getBoundingClientRect().top - viewport.top;
|
|
163
|
+
const delta = currentTop - preservation.top;
|
|
164
|
+
if (Math.abs(delta) > 0.5) {
|
|
165
|
+
connection.list.scrollToOffset({
|
|
166
|
+
offset: Math.max(0, connection.scroller.scrollTop + delta),
|
|
167
|
+
animated: false,
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
return;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
const heightDelta = Math.max(
|
|
174
|
+
0,
|
|
175
|
+
connection.scroller.scrollHeight - preservation.scrollHeight
|
|
176
|
+
);
|
|
177
|
+
if (heightDelta > 0) {
|
|
142
178
|
connection.list.scrollToOffset({
|
|
143
|
-
offset: Math.max(0,
|
|
179
|
+
offset: Math.max(0, preservation.scrollTop + heightDelta),
|
|
144
180
|
animated: false,
|
|
145
181
|
});
|
|
146
182
|
}
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
const heightDelta = Math.max(
|
|
151
|
-
0,
|
|
152
|
-
connection.scroller.scrollHeight - preservation.scrollHeight
|
|
153
|
-
);
|
|
154
|
-
if (heightDelta > 0) {
|
|
155
|
-
connection.list.scrollToOffset({
|
|
156
|
-
offset: Math.max(0, preservation.scrollTop + heightDelta),
|
|
157
|
-
animated: false,
|
|
158
|
-
});
|
|
159
|
-
}
|
|
160
|
-
};
|
|
183
|
+
},
|
|
184
|
+
[findRow]
|
|
185
|
+
);
|
|
161
186
|
|
|
162
|
-
const runFrame = () => {
|
|
187
|
+
const runFrame = useCallback(() => {
|
|
163
188
|
frameRef.current = undefined;
|
|
164
189
|
const connection = connectionRef.current;
|
|
165
190
|
if (!connection) return;
|
|
166
191
|
refreshResizeTargets(connection);
|
|
167
192
|
if (preservingPrependRef.current) correctPrepend(connection);
|
|
168
193
|
else captureAnchor(connection);
|
|
169
|
-
};
|
|
194
|
+
}, [captureAnchor, correctPrepend, refreshResizeTargets]);
|
|
170
195
|
|
|
171
|
-
const scheduleFrame = () => {
|
|
196
|
+
const scheduleFrame = useCallback(() => {
|
|
172
197
|
if (frameRef.current !== undefined) return;
|
|
173
198
|
if (globals.requestAnimationFrame) {
|
|
174
199
|
frameRef.current = globals.requestAnimationFrame(runFrame);
|
|
175
200
|
} else {
|
|
176
201
|
runFrame();
|
|
177
202
|
}
|
|
178
|
-
};
|
|
203
|
+
}, [globals, runFrame]);
|
|
179
204
|
|
|
180
|
-
const stopPreserving = () => {
|
|
205
|
+
const stopPreserving = useCallback(() => {
|
|
181
206
|
preservingPrependRef.current = false;
|
|
182
207
|
preservationRef.current = undefined;
|
|
183
208
|
lastAnchorRef.current = undefined;
|
|
184
|
-
};
|
|
209
|
+
}, []);
|
|
185
210
|
|
|
186
|
-
const disconnect = () => {
|
|
211
|
+
const disconnect = useCallback(() => {
|
|
187
212
|
const connection = connectionRef.current;
|
|
188
213
|
disconnectConnection(connection);
|
|
189
214
|
connectionRef.current = undefined;
|
|
@@ -191,9 +216,9 @@ export function useWebPrependAnchor({
|
|
|
191
216
|
globals.cancelAnimationFrame?.(frameRef.current);
|
|
192
217
|
frameRef.current = undefined;
|
|
193
218
|
}
|
|
194
|
-
};
|
|
219
|
+
}, [globals]);
|
|
195
220
|
|
|
196
|
-
const ensureConnected = () => {
|
|
221
|
+
const ensureConnected = useCallback(() => {
|
|
197
222
|
if (Platform.OS !== 'web') return;
|
|
198
223
|
const list = listRef.current;
|
|
199
224
|
const scroller = list ? list.getScrollableNode() : undefined;
|
|
@@ -241,12 +266,20 @@ export function useWebPrependAnchor({
|
|
|
241
266
|
scroller.addEventListener('scroll', scroll, { passive: true });
|
|
242
267
|
refreshResizeTargets(connection);
|
|
243
268
|
scheduleFrame();
|
|
244
|
-
}
|
|
269
|
+
}, [
|
|
270
|
+
captureAnchor,
|
|
271
|
+
disconnect,
|
|
272
|
+
globals,
|
|
273
|
+
listRef,
|
|
274
|
+
refreshResizeTargets,
|
|
275
|
+
scheduleFrame,
|
|
276
|
+
stopPreserving,
|
|
277
|
+
]);
|
|
245
278
|
|
|
246
|
-
const cancelPrependPreservation = () => {
|
|
279
|
+
const cancelPrependPreservation = useCallback(() => {
|
|
247
280
|
stopPreserving();
|
|
248
281
|
scheduleFrame();
|
|
249
|
-
};
|
|
282
|
+
}, [scheduleFrame, stopPreserving]);
|
|
250
283
|
|
|
251
284
|
useLayoutEffect(() => {
|
|
252
285
|
ensureConnected();
|
|
@@ -266,8 +299,9 @@ export function useWebPrependAnchor({
|
|
|
266
299
|
}
|
|
267
300
|
}
|
|
268
301
|
previousIdentityRef.current = itemsIdentity;
|
|
269
|
-
previousKeysRef.current =
|
|
270
|
-
|
|
302
|
+
previousKeysRef.current = keys;
|
|
303
|
+
if (!previousKeys || previousKeys !== keys || identityChanged)
|
|
304
|
+
scheduleFrame();
|
|
271
305
|
});
|
|
272
306
|
|
|
273
307
|
useLayoutEffect(
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { Text, View } from 'react-native';
|
|
2
|
+
import {
|
|
3
|
+
usePrefersReducedMotion,
|
|
4
|
+
useThemedStyles,
|
|
5
|
+
} from '@unif/react-native-design';
|
|
6
|
+
import { PROCESSING_PROGRESS_SEPARATOR } from './constants';
|
|
7
|
+
import { ProcessingProgressPrefix } from './ProcessingProgressPrefix';
|
|
8
|
+
import { createStyles } from './styles';
|
|
9
|
+
import type { ProcessingProgressProps } from './types';
|
|
10
|
+
|
|
11
|
+
export function ProcessingProgress({ progress }: ProcessingProgressProps) {
|
|
12
|
+
const styles = useThemedStyles(createStyles);
|
|
13
|
+
const reducedMotion = usePrefersReducedMotion();
|
|
14
|
+
const separatorIndex = progress.indexOf(PROCESSING_PROGRESS_SEPARATOR);
|
|
15
|
+
const prefix =
|
|
16
|
+
separatorIndex === -1 ? progress : progress.slice(0, separatorIndex);
|
|
17
|
+
const suffix = separatorIndex === -1 ? '' : progress.slice(separatorIndex);
|
|
18
|
+
|
|
19
|
+
return (
|
|
20
|
+
<View
|
|
21
|
+
style={styles.root}
|
|
22
|
+
accessible
|
|
23
|
+
accessibilityRole="text"
|
|
24
|
+
accessibilityLabel={progress}
|
|
25
|
+
accessibilityState={{ busy: true }}
|
|
26
|
+
aria-busy
|
|
27
|
+
accessibilityLiveRegion="polite"
|
|
28
|
+
>
|
|
29
|
+
<Text
|
|
30
|
+
testID="processing-progress-line"
|
|
31
|
+
style={styles.text}
|
|
32
|
+
numberOfLines={1}
|
|
33
|
+
ellipsizeMode="tail"
|
|
34
|
+
accessible={false}
|
|
35
|
+
aria-hidden
|
|
36
|
+
>
|
|
37
|
+
<ProcessingProgressPrefix
|
|
38
|
+
// Each prefix/motion generation owns its value, including late frames.
|
|
39
|
+
key={`${reducedMotion}:${prefix}`}
|
|
40
|
+
text={prefix}
|
|
41
|
+
reducedMotion={reducedMotion}
|
|
42
|
+
/>
|
|
43
|
+
{suffix ? (
|
|
44
|
+
<Text testID="processing-progress-suffix">{suffix}</Text>
|
|
45
|
+
) : null}
|
|
46
|
+
</Text>
|
|
47
|
+
</View>
|
|
48
|
+
);
|
|
49
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { memo, useEffect, useRef } from 'react';
|
|
2
|
+
import { Animated, Easing, Platform, Text } from 'react-native';
|
|
3
|
+
import { useTheme } from '@unif/react-native-design';
|
|
4
|
+
import {
|
|
5
|
+
PROCESSING_PROGRESS_SHINE_DURATION_MS,
|
|
6
|
+
PROCESSING_PROGRESS_SHINE_PEAK,
|
|
7
|
+
PROCESSING_PROGRESS_SHINE_RADIUS,
|
|
8
|
+
} from './constants';
|
|
9
|
+
import type { ProcessingProgressPrefixProps } from './types';
|
|
10
|
+
|
|
11
|
+
export const ProcessingProgressPrefix = memo(function Prefix({
|
|
12
|
+
text,
|
|
13
|
+
reducedMotion,
|
|
14
|
+
}: ProcessingProgressPrefixProps) {
|
|
15
|
+
const { colors, scheme } = useTheme();
|
|
16
|
+
const animation = useRef(
|
|
17
|
+
new Animated.Value(-PROCESSING_PROGRESS_SHINE_RADIUS)
|
|
18
|
+
).current;
|
|
19
|
+
const characters = Array.from(text);
|
|
20
|
+
|
|
21
|
+
useEffect(() => {
|
|
22
|
+
if (reducedMotion || !characters.length) return undefined;
|
|
23
|
+
const loop = Animated.loop(
|
|
24
|
+
Animated.timing(animation, {
|
|
25
|
+
toValue: characters.length + PROCESSING_PROGRESS_SHINE_RADIUS,
|
|
26
|
+
duration: PROCESSING_PROGRESS_SHINE_DURATION_MS,
|
|
27
|
+
easing: Easing.linear,
|
|
28
|
+
useNativeDriver: Platform.OS !== 'web',
|
|
29
|
+
isInteraction: false,
|
|
30
|
+
})
|
|
31
|
+
);
|
|
32
|
+
loop.start();
|
|
33
|
+
return () => loop.stop();
|
|
34
|
+
}, [animation, characters.length, reducedMotion]);
|
|
35
|
+
|
|
36
|
+
const baseColor =
|
|
37
|
+
scheme === 'dark' ? colors.foregroundMuted : colors.foreground;
|
|
38
|
+
|
|
39
|
+
if (reducedMotion) return <Text style={{ color: baseColor }}>{text}</Text>;
|
|
40
|
+
|
|
41
|
+
return (
|
|
42
|
+
<Text>
|
|
43
|
+
{characters.map((character, index) => (
|
|
44
|
+
<Animated.Text
|
|
45
|
+
key={`${index}:${character}`}
|
|
46
|
+
style={{
|
|
47
|
+
color: animation
|
|
48
|
+
.interpolate({
|
|
49
|
+
inputRange: [
|
|
50
|
+
index - PROCESSING_PROGRESS_SHINE_RADIUS,
|
|
51
|
+
index,
|
|
52
|
+
index + PROCESSING_PROGRESS_SHINE_RADIUS,
|
|
53
|
+
],
|
|
54
|
+
outputRange: [0, PROCESSING_PROGRESS_SHINE_PEAK, 0],
|
|
55
|
+
extrapolate: 'clamp',
|
|
56
|
+
})
|
|
57
|
+
.interpolate({
|
|
58
|
+
inputRange: [0, 1],
|
|
59
|
+
outputRange: [baseColor, colors.onPrimary],
|
|
60
|
+
}),
|
|
61
|
+
}}
|
|
62
|
+
>
|
|
63
|
+
{character}
|
|
64
|
+
</Animated.Text>
|
|
65
|
+
))}
|
|
66
|
+
</Text>
|
|
67
|
+
);
|
|
68
|
+
});
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { StyleSheet } from 'react-native';
|
|
2
|
+
import { r, space, type } from '@unif/react-native-design';
|
|
3
|
+
import type { ColorTokens } from '@unif/react-native-design';
|
|
4
|
+
|
|
5
|
+
export const createStyles = (colors: ColorTokens) =>
|
|
6
|
+
StyleSheet.create({
|
|
7
|
+
root: {
|
|
8
|
+
minWidth: 0,
|
|
9
|
+
paddingHorizontal: space[4],
|
|
10
|
+
paddingVertical: space[3],
|
|
11
|
+
},
|
|
12
|
+
text: {
|
|
13
|
+
color: colors.foregroundMuted,
|
|
14
|
+
fontSize: type.xs,
|
|
15
|
+
lineHeight: r(20),
|
|
16
|
+
},
|
|
17
|
+
});
|
package/src/index.tsx
CHANGED
|
@@ -53,6 +53,8 @@ export type {
|
|
|
53
53
|
ProcessStep,
|
|
54
54
|
ProcessStepStatus,
|
|
55
55
|
} from './components/Process';
|
|
56
|
+
export { ProcessingProgress } from './components/ProcessingProgress';
|
|
57
|
+
export type { ProcessingProgressProps } from './components/ProcessingProgress';
|
|
56
58
|
export { Feedback } from './components/Feedback';
|
|
57
59
|
export type { FeedbackProps, FeedbackTone } from './components/Feedback';
|
|
58
60
|
export { Sources } from './components/Sources';
|