@utilitywarehouse/hearth-react-native 0.16.1 → 0.17.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/.turbo/turbo-build.log +1 -1
- package/.turbo/turbo-lint.log +14 -14
- package/CHANGELOG.md +156 -0
- package/build/components/Card/CardAction/CardActionRoot.js +12 -2
- package/build/components/Card/CardActions.context.d.ts +6 -0
- package/build/components/Card/CardActions.context.js +5 -0
- package/build/components/Card/CardActions.d.ts +7 -0
- package/build/components/Card/CardActions.js +29 -0
- package/build/components/Card/CardRoot.js +16 -104
- package/build/components/Card/helpers.d.ts +8 -0
- package/build/components/Card/helpers.js +146 -0
- package/build/components/Card/index.d.ts +2 -0
- package/build/components/Card/index.js +2 -0
- package/build/components/DateInput/DateInput.d.ts +1 -1
- package/build/components/DateInput/DateInput.js +2 -3
- package/build/components/DateInput/DateInput.props.d.ts +22 -1
- package/build/components/DateInput/DateInputSegment.d.ts +2 -16
- package/build/components/DateInput/DateInputSegment.js +3 -6
- package/build/components/ExpandableCard/ExpandableCardGroup.d.ts +1 -1
- package/build/components/ExpandableCard/ExpandableCardGroup.js +2 -2
- package/build/components/ExpandableCard/ExpandableCardGroup.props.d.ts +4 -0
- package/build/components/Input/Input.js +4 -3
- package/build/components/Input/Input.props.d.ts +9 -0
- package/build/components/List/List.context.d.ts +4 -2
- package/build/components/List/List.context.js +0 -2
- package/build/components/List/List.d.ts +1 -1
- package/build/components/List/List.js +25 -38
- package/build/components/List/List.props.d.ts +1 -0
- package/build/components/List/ListAction/ListAction.js +24 -7
- package/build/components/List/ListAction/ListAction.props.d.ts +1 -0
- package/build/components/List/ListItem/ListItemRoot.js +12 -4
- package/build/utils/isThemedImageProps.d.ts +1 -1
- package/package.json +2 -2
- package/src/components/Card/Card.docs.mdx +224 -66
- package/src/components/Card/Card.stories.tsx +29 -25
- package/src/components/Card/CardAction/CardAction.stories.tsx +239 -93
- package/src/components/Card/CardAction/CardActionRoot.tsx +15 -2
- package/src/components/Card/CardActions.context.ts +12 -0
- package/src/components/Card/CardActions.tsx +40 -0
- package/src/components/Card/CardRoot.tsx +27 -132
- package/src/components/Card/helpers.tsx +195 -0
- package/src/components/Card/index.ts +2 -0
- package/src/components/DateInput/DateInput.docs.mdx +47 -29
- package/src/components/DateInput/DateInput.props.ts +32 -1
- package/src/components/DateInput/DateInput.stories.tsx +10 -0
- package/src/components/DateInput/DateInput.tsx +12 -1
- package/src/components/DateInput/DateInputSegment.tsx +8 -23
- package/src/components/ExpandableCard/ExpandableCard.figma.tsx +33 -38
- package/src/components/ExpandableCard/ExpandableCardGroup.figma.tsx +34 -17
- package/src/components/ExpandableCard/ExpandableCardGroup.props.ts +5 -0
- package/src/components/ExpandableCard/ExpandableCardGroup.tsx +2 -0
- package/src/components/HighlightBanner/HighlightBanner.figma.tsx +46 -0
- package/src/components/IconButton/IconButton.figma.tsx +20 -30
- package/src/components/IconContainer/IconContainer.figma.tsx +7 -13
- package/src/components/IndicatorIconButton/IndicatorIconButton.figma.tsx +16 -0
- package/src/components/Input/Input.docs.mdx +55 -15
- package/src/components/Input/Input.figma.tsx +106 -40
- package/src/components/Input/Input.props.ts +9 -0
- package/src/components/Input/Input.tsx +21 -0
- package/src/components/Link/Link.figma.tsx +31 -38
- package/src/components/List/List.context.ts +2 -4
- package/src/components/List/List.docs.mdx +10 -5
- package/src/components/List/List.figma.tsx +42 -28
- package/src/components/List/List.props.ts +1 -0
- package/src/components/List/List.stories.tsx +43 -0
- package/src/components/List/List.tsx +38 -51
- package/src/components/List/ListAction/ListAction.figma.tsx +5 -13
- package/src/components/List/ListAction/ListAction.props.ts +1 -0
- package/src/components/List/ListAction/ListAction.tsx +40 -10
- package/src/components/List/ListItem/ListItem.figma.tsx +43 -27
- package/src/components/List/ListItem/ListItemRoot.tsx +15 -4
- package/src/utils/isThemedImageProps.ts +1 -1
- package/src/components/InlineLink/InlineLink.figma.tsx +0 -33
|
@@ -2,9 +2,12 @@ import { Meta, StoryObj } from '@storybook/react-native';
|
|
|
2
2
|
import * as Icons from '@utilitywarehouse/hearth-react-native-icons';
|
|
3
3
|
import { ElectricityMediumIcon, GasMediumIcon } from '@utilitywarehouse/hearth-react-native-icons';
|
|
4
4
|
import { View } from 'react-native';
|
|
5
|
+
import { BodyText } from '../../';
|
|
5
6
|
import { Badge } from '../../Badge';
|
|
6
7
|
import { Flex } from '../../Flex';
|
|
7
8
|
import Card from '../Card';
|
|
9
|
+
import CardActions from '../CardActions';
|
|
10
|
+
import CardContent from '../CardContent';
|
|
8
11
|
import CardAction from './CardAction';
|
|
9
12
|
|
|
10
13
|
const meta: Meta<typeof CardAction> = {
|
|
@@ -74,9 +77,11 @@ export const Playground: Story = {
|
|
|
74
77
|
// @ts-expect-error - This is a playground
|
|
75
78
|
const trailingIcon = args.trailingIcon === 'none' ? undefined : Icons[args.trailingIcon];
|
|
76
79
|
return (
|
|
77
|
-
<View style={{ width: '100%', maxWidth: 400 }}>
|
|
80
|
+
<View style={{ width: '100%', maxWidth: 400, gap: 16 }}>
|
|
78
81
|
<Card variant="emphasis">
|
|
79
|
-
<
|
|
82
|
+
<CardActions>
|
|
83
|
+
<CardAction {...args} leadingIcon={leadingIcon} trailingIcon={trailingIcon} />
|
|
84
|
+
</CardActions>
|
|
80
85
|
</Card>
|
|
81
86
|
</View>
|
|
82
87
|
);
|
|
@@ -90,12 +95,14 @@ export const WithLeadingIcon: Story = {
|
|
|
90
95
|
render: () => (
|
|
91
96
|
<View style={{ width: '100%', maxWidth: 400 }}>
|
|
92
97
|
<Card variant="emphasis">
|
|
93
|
-
<
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
98
|
+
<CardActions>
|
|
99
|
+
<CardAction
|
|
100
|
+
heading="Bills"
|
|
101
|
+
helperText="View your bills"
|
|
102
|
+
leadingIcon={ElectricityMediumIcon}
|
|
103
|
+
onPress={() => console.log('pressed')}
|
|
104
|
+
/>
|
|
105
|
+
</CardActions>
|
|
99
106
|
</Card>
|
|
100
107
|
</View>
|
|
101
108
|
),
|
|
@@ -108,12 +115,14 @@ export const WithTrailingIcon: Story = {
|
|
|
108
115
|
render: () => (
|
|
109
116
|
<View style={{ width: '100%', maxWidth: 400 }}>
|
|
110
117
|
<Card variant="emphasis">
|
|
111
|
-
<
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
118
|
+
<CardActions>
|
|
119
|
+
<CardAction
|
|
120
|
+
heading="Bills"
|
|
121
|
+
helperText="View your bills"
|
|
122
|
+
trailingIcon={ElectricityMediumIcon}
|
|
123
|
+
onPress={() => console.log('pressed')}
|
|
124
|
+
/>
|
|
125
|
+
</CardActions>
|
|
117
126
|
</Card>
|
|
118
127
|
</View>
|
|
119
128
|
),
|
|
@@ -127,33 +136,35 @@ export const WithIconContainer: Story = {
|
|
|
127
136
|
render: () => (
|
|
128
137
|
<View style={{ width: '100%', maxWidth: 400 }}>
|
|
129
138
|
<Card variant="emphasis">
|
|
130
|
-
<
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
139
|
+
<CardActions>
|
|
140
|
+
<CardAction
|
|
141
|
+
heading="Electricity"
|
|
142
|
+
helperText="Last reading 23/03/24"
|
|
143
|
+
leadingIcon={ElectricityMediumIcon}
|
|
144
|
+
iconContainer
|
|
145
|
+
iconContainerVariant="emphasis"
|
|
146
|
+
iconContainerColor="energy"
|
|
147
|
+
onPress={() => console.log('pressed')}
|
|
148
|
+
/>
|
|
149
|
+
<CardAction
|
|
150
|
+
heading="Gas"
|
|
151
|
+
helperText="Last reading 23/03/24"
|
|
152
|
+
leadingIcon={GasMediumIcon}
|
|
153
|
+
iconContainer
|
|
154
|
+
iconContainerVariant="emphasis"
|
|
155
|
+
iconContainerColor="energy"
|
|
156
|
+
onPress={() => console.log('pressed')}
|
|
157
|
+
/>
|
|
158
|
+
<CardAction
|
|
159
|
+
heading="Gas"
|
|
160
|
+
helperText="Last reading 23/03/24"
|
|
161
|
+
leadingIcon={GasMediumIcon}
|
|
162
|
+
iconContainer
|
|
163
|
+
iconContainerVariant="emphasis"
|
|
164
|
+
iconContainerColor="energy"
|
|
165
|
+
onPress={() => console.log('pressed')}
|
|
166
|
+
/>
|
|
167
|
+
</CardActions>
|
|
157
168
|
</Card>
|
|
158
169
|
</View>
|
|
159
170
|
),
|
|
@@ -166,34 +177,40 @@ export const WithBadge: Story = {
|
|
|
166
177
|
render: () => (
|
|
167
178
|
<Flex direction="column" space="md" style={{ width: '100%', maxWidth: 400 }}>
|
|
168
179
|
<Card variant="emphasis">
|
|
169
|
-
<
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
180
|
+
<CardActions>
|
|
181
|
+
<CardAction
|
|
182
|
+
heading="Badge at bottom"
|
|
183
|
+
helperText="Badge positioned below text"
|
|
184
|
+
leadingIcon={ElectricityMediumIcon}
|
|
185
|
+
badge={<Badge text="New" />}
|
|
186
|
+
badgePosition="bottom"
|
|
187
|
+
onPress={() => console.log('pressed')}
|
|
188
|
+
/>
|
|
189
|
+
</CardActions>
|
|
177
190
|
</Card>
|
|
178
191
|
<Card variant="emphasis">
|
|
179
|
-
<
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
192
|
+
<CardActions>
|
|
193
|
+
<CardAction
|
|
194
|
+
heading="Badge at middle"
|
|
195
|
+
helperText="Badge positioned between heading and helper text"
|
|
196
|
+
leadingIcon={ElectricityMediumIcon}
|
|
197
|
+
badge={<Badge text="New" />}
|
|
198
|
+
badgePosition="middle"
|
|
199
|
+
onPress={() => console.log('pressed')}
|
|
200
|
+
/>
|
|
201
|
+
</CardActions>
|
|
187
202
|
</Card>
|
|
188
203
|
<Card variant="emphasis">
|
|
189
|
-
<
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
204
|
+
<CardActions>
|
|
205
|
+
<CardAction
|
|
206
|
+
heading="Badge at right"
|
|
207
|
+
helperText="Badge positioned on the right side"
|
|
208
|
+
leadingIcon={ElectricityMediumIcon}
|
|
209
|
+
badge={<Badge text="New" />}
|
|
210
|
+
badgePosition="right"
|
|
211
|
+
onPress={() => console.log('pressed')}
|
|
212
|
+
/>
|
|
213
|
+
</CardActions>
|
|
197
214
|
</Card>
|
|
198
215
|
</Flex>
|
|
199
216
|
),
|
|
@@ -206,22 +223,26 @@ export const Sizes: Story = {
|
|
|
206
223
|
render: () => (
|
|
207
224
|
<Flex direction="column" space="md" style={{ width: '100%', maxWidth: 400 }}>
|
|
208
225
|
<Card variant="emphasis">
|
|
209
|
-
<
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
226
|
+
<CardActions>
|
|
227
|
+
<CardAction
|
|
228
|
+
heading="Medium size (default)"
|
|
229
|
+
helperText="Heading size is md"
|
|
230
|
+
size="md"
|
|
231
|
+
leadingIcon={ElectricityMediumIcon}
|
|
232
|
+
onPress={() => console.log('pressed')}
|
|
233
|
+
/>
|
|
234
|
+
</CardActions>
|
|
216
235
|
</Card>
|
|
217
236
|
<Card variant="emphasis">
|
|
218
|
-
<
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
237
|
+
<CardActions>
|
|
238
|
+
<CardAction
|
|
239
|
+
heading="Large size"
|
|
240
|
+
helperText="Heading size is lg"
|
|
241
|
+
size="lg"
|
|
242
|
+
leadingIcon={ElectricityMediumIcon}
|
|
243
|
+
onPress={() => console.log('pressed')}
|
|
244
|
+
/>
|
|
245
|
+
</CardActions>
|
|
225
246
|
</Card>
|
|
226
247
|
</Flex>
|
|
227
248
|
),
|
|
@@ -234,13 +255,15 @@ export const Loading: Story = {
|
|
|
234
255
|
render: () => (
|
|
235
256
|
<View style={{ width: '100%', maxWidth: 400 }}>
|
|
236
257
|
<Card variant="emphasis">
|
|
237
|
-
<
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
258
|
+
<CardActions>
|
|
259
|
+
<CardAction
|
|
260
|
+
heading="Loading"
|
|
261
|
+
helperText="This is loading"
|
|
262
|
+
loading
|
|
263
|
+
leadingIcon={ElectricityMediumIcon}
|
|
264
|
+
onPress={() => console.log('pressed')}
|
|
265
|
+
/>
|
|
266
|
+
</CardActions>
|
|
244
267
|
</Card>
|
|
245
268
|
</View>
|
|
246
269
|
),
|
|
@@ -253,14 +276,137 @@ export const Disabled: Story = {
|
|
|
253
276
|
render: () => (
|
|
254
277
|
<View style={{ width: '100%', maxWidth: 400 }}>
|
|
255
278
|
<Card variant="emphasis">
|
|
256
|
-
<
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
279
|
+
<CardActions>
|
|
280
|
+
<CardAction
|
|
281
|
+
heading="Disabled"
|
|
282
|
+
helperText="This is disabled"
|
|
283
|
+
disabled
|
|
284
|
+
leadingIcon={ElectricityMediumIcon}
|
|
285
|
+
onPress={() => console.log('pressed')}
|
|
286
|
+
/>
|
|
287
|
+
</CardActions>
|
|
263
288
|
</Card>
|
|
264
289
|
</View>
|
|
265
290
|
),
|
|
266
291
|
};
|
|
292
|
+
|
|
293
|
+
const CustomAction = ({ heading, ...props }: { heading: string }) => {
|
|
294
|
+
return <CardAction key={heading} heading={heading} {...props} onPress={() => null} />;
|
|
295
|
+
};
|
|
296
|
+
|
|
297
|
+
const CustomComponent = () => <BodyText>Multiple CardActions within a Card:</BodyText>;
|
|
298
|
+
|
|
299
|
+
export const WithCustomActions: Story = {
|
|
300
|
+
parameters: {
|
|
301
|
+
controls: { include: [] },
|
|
302
|
+
},
|
|
303
|
+
render: (args: any) => {
|
|
304
|
+
// @ts-expect-error - This is a playground
|
|
305
|
+
const leadingIcon = args.leadingIcon === 'none' ? undefined : Icons[args.leadingIcon];
|
|
306
|
+
// @ts-expect-error - This is a playground
|
|
307
|
+
const trailingIcon = args.trailingIcon === 'none' ? undefined : Icons[args.trailingIcon];
|
|
308
|
+
|
|
309
|
+
const actions = [{ text: 'Action 1' }, { text: 'Action 2' }, { text: 'Action 3' }];
|
|
310
|
+
return (
|
|
311
|
+
<View style={{ width: '100%', maxWidth: 400, gap: 16 }}>
|
|
312
|
+
{/* Example 1 */}
|
|
313
|
+
<Card variant="emphasis">
|
|
314
|
+
<BodyText>Multiple CardActions within a Card:</BodyText>
|
|
315
|
+
<CardActions>
|
|
316
|
+
{actions.map(action => (
|
|
317
|
+
<CustomAction
|
|
318
|
+
key={action.text}
|
|
319
|
+
{...args}
|
|
320
|
+
heading={action.text}
|
|
321
|
+
leadingIcon={leadingIcon}
|
|
322
|
+
trailingIcon={trailingIcon}
|
|
323
|
+
/>
|
|
324
|
+
))}
|
|
325
|
+
<CardAction
|
|
326
|
+
{...args}
|
|
327
|
+
leadingIcon={leadingIcon}
|
|
328
|
+
trailingIcon={trailingIcon}
|
|
329
|
+
onPress={() => null}
|
|
330
|
+
/>
|
|
331
|
+
</CardActions>
|
|
332
|
+
</Card>
|
|
333
|
+
{/* Example 2 */}
|
|
334
|
+
<Card variant="emphasis">
|
|
335
|
+
<CardActions>
|
|
336
|
+
{actions.map(action => (
|
|
337
|
+
<CustomAction
|
|
338
|
+
key={action.text}
|
|
339
|
+
{...args}
|
|
340
|
+
heading={action.text}
|
|
341
|
+
leadingIcon={leadingIcon}
|
|
342
|
+
trailingIcon={trailingIcon}
|
|
343
|
+
/>
|
|
344
|
+
))}
|
|
345
|
+
</CardActions>
|
|
346
|
+
</Card>
|
|
347
|
+
{/* Example 3 */}
|
|
348
|
+
<Card variant="emphasis">
|
|
349
|
+
<CardActions>
|
|
350
|
+
<CardAction
|
|
351
|
+
{...args}
|
|
352
|
+
leadingIcon={leadingIcon}
|
|
353
|
+
trailingIcon={trailingIcon}
|
|
354
|
+
onPress={() => null}
|
|
355
|
+
/>
|
|
356
|
+
<CardAction
|
|
357
|
+
{...args}
|
|
358
|
+
leadingIcon={leadingIcon}
|
|
359
|
+
trailingIcon={trailingIcon}
|
|
360
|
+
onPress={() => null}
|
|
361
|
+
/>
|
|
362
|
+
</CardActions>
|
|
363
|
+
</Card>
|
|
364
|
+
{/* Example 4 */}
|
|
365
|
+
<Card variant="emphasis">
|
|
366
|
+
<BodyText>Multiple CardActions within a Card:</BodyText>
|
|
367
|
+
</Card>
|
|
368
|
+
{/* Example 5 */}
|
|
369
|
+
<Card variant="emphasis">
|
|
370
|
+
<BodyText>Multiple CardActions within a Card:</BodyText>
|
|
371
|
+
<CardActions>
|
|
372
|
+
<CardAction
|
|
373
|
+
{...args}
|
|
374
|
+
leadingIcon={leadingIcon}
|
|
375
|
+
trailingIcon={trailingIcon}
|
|
376
|
+
onPress={() => null}
|
|
377
|
+
/>
|
|
378
|
+
<CardAction
|
|
379
|
+
{...args}
|
|
380
|
+
leadingIcon={leadingIcon}
|
|
381
|
+
trailingIcon={trailingIcon}
|
|
382
|
+
onPress={() => null}
|
|
383
|
+
/>
|
|
384
|
+
</CardActions>
|
|
385
|
+
</Card>
|
|
386
|
+
{/* Example 6 */}
|
|
387
|
+
<Card variant="emphasis">
|
|
388
|
+
<CardContent>
|
|
389
|
+
<CustomComponent />
|
|
390
|
+
</CardContent>
|
|
391
|
+
<CardActions>
|
|
392
|
+
{actions.map(action => (
|
|
393
|
+
<CustomAction
|
|
394
|
+
key={action.text}
|
|
395
|
+
{...args}
|
|
396
|
+
heading={action.text}
|
|
397
|
+
leadingIcon={leadingIcon}
|
|
398
|
+
trailingIcon={trailingIcon}
|
|
399
|
+
/>
|
|
400
|
+
))}
|
|
401
|
+
<CardAction
|
|
402
|
+
{...args}
|
|
403
|
+
leadingIcon={leadingIcon}
|
|
404
|
+
trailingIcon={trailingIcon}
|
|
405
|
+
onPress={() => null}
|
|
406
|
+
/>
|
|
407
|
+
</CardActions>
|
|
408
|
+
</Card>
|
|
409
|
+
</View>
|
|
410
|
+
);
|
|
411
|
+
},
|
|
412
|
+
};
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { ChevronRightSmallIcon } from '@utilitywarehouse/hearth-react-native-icons';
|
|
2
|
-
import { useMemo } from 'react';
|
|
2
|
+
import { useId, useLayoutEffect, useMemo } from 'react';
|
|
3
3
|
import { Pressable, View, ViewStyle } from 'react-native';
|
|
4
4
|
import { StyleSheet } from 'react-native-unistyles';
|
|
5
5
|
import { IconContainer } from '../../IconContainer';
|
|
6
6
|
import { Skeleton } from '../../Skeleton';
|
|
7
7
|
import { useCardContext } from '../Card.context';
|
|
8
|
+
import { useCardActionsContext } from '../CardActions.context';
|
|
8
9
|
import { CardActionContext, ICardActionContext } from './CardAction.context';
|
|
9
10
|
import type CardActionProps from './CardAction.props';
|
|
10
11
|
import CardActionContent from './CardActionContent';
|
|
@@ -45,7 +46,19 @@ const CardActionRoot = ({
|
|
|
45
46
|
const loadingTestID = isLoading ? `${testID}-loading` : testID;
|
|
46
47
|
|
|
47
48
|
const { variant, hasOnlyActions } = useCardContext();
|
|
48
|
-
const
|
|
49
|
+
const actionId = useId();
|
|
50
|
+
const actionsContext = useCardActionsContext();
|
|
51
|
+
|
|
52
|
+
useLayoutEffect(() => {
|
|
53
|
+
if (!actionsContext) {
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
return actionsContext.registerAction(actionId);
|
|
58
|
+
}, [actionId, actionsContext]);
|
|
59
|
+
|
|
60
|
+
const isFirstFromContext = actionsContext?.firstActionId === actionId;
|
|
61
|
+
const isFirst = props.isFirst ?? isFirstFromContext;
|
|
49
62
|
|
|
50
63
|
styles.useVariants({
|
|
51
64
|
showPressed,
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { createContext, useContext } from 'react';
|
|
2
|
+
|
|
3
|
+
export interface CardActionsContextValue {
|
|
4
|
+
firstActionId?: string;
|
|
5
|
+
registerAction: (id: string) => () => void;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export const CardActionsContext = createContext<CardActionsContextValue | null>(null);
|
|
9
|
+
|
|
10
|
+
export const useCardActionsContext = (): CardActionsContextValue | null => {
|
|
11
|
+
return useContext(CardActionsContext);
|
|
12
|
+
};
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { PropsWithChildren, useCallback, useRef, useState } from 'react';
|
|
2
|
+
import { View, ViewProps } from 'react-native';
|
|
3
|
+
import { StyleSheet } from 'react-native-unistyles';
|
|
4
|
+
import { CardActionsContext } from './CardActions.context';
|
|
5
|
+
|
|
6
|
+
const CardActions = ({ children, style, ...props }: PropsWithChildren<ViewProps>) => {
|
|
7
|
+
const orderRef = useRef<string[]>([]);
|
|
8
|
+
const [firstActionId, setFirstActionId] = useState<string | undefined>(undefined);
|
|
9
|
+
|
|
10
|
+
const registerAction = useCallback((id: string) => {
|
|
11
|
+
if (!orderRef.current.includes(id)) {
|
|
12
|
+
orderRef.current.push(id);
|
|
13
|
+
}
|
|
14
|
+
const nextFirst = orderRef.current[0];
|
|
15
|
+
setFirstActionId(prev => (prev === nextFirst ? prev : nextFirst));
|
|
16
|
+
return () => {
|
|
17
|
+
orderRef.current = orderRef.current.filter(currentId => currentId !== id);
|
|
18
|
+
const nextFirst = orderRef.current[0];
|
|
19
|
+
setFirstActionId(prev => (prev === nextFirst ? prev : nextFirst));
|
|
20
|
+
};
|
|
21
|
+
}, []);
|
|
22
|
+
|
|
23
|
+
return (
|
|
24
|
+
<CardActionsContext.Provider value={{ firstActionId, registerAction }}>
|
|
25
|
+
<View {...props} style={[styles.container, style]}>
|
|
26
|
+
{children}
|
|
27
|
+
</View>
|
|
28
|
+
</CardActionsContext.Provider>
|
|
29
|
+
);
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
CardActions.displayName = 'CardActions';
|
|
33
|
+
|
|
34
|
+
const styles = StyleSheet.create({
|
|
35
|
+
container: {
|
|
36
|
+
width: '100%',
|
|
37
|
+
},
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
export default CardActions;
|