@planningcenter/chat-react-native 3.13.0-rc.0 → 3.13.0-rc.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. package/build/components/conversation/message.js +1 -6
  2. package/build/components/conversation/message.js.map +1 -1
  3. package/build/components/display/badge.js +4 -4
  4. package/build/components/display/badge.js.map +1 -1
  5. package/build/components/display/button.d.ts.map +1 -1
  6. package/build/components/display/button.js +10 -2
  7. package/build/components/display/button.js.map +1 -1
  8. package/build/components/display/icon_button.d.ts.map +1 -1
  9. package/build/components/display/icon_button.js +2 -6
  10. package/build/components/display/icon_button.js.map +1 -1
  11. package/build/components/display/image.js +8 -1
  12. package/build/components/display/image.js.map +1 -1
  13. package/build/components/display/person.d.ts.map +1 -1
  14. package/build/components/display/person.js +3 -4
  15. package/build/components/display/person.js.map +1 -1
  16. package/build/components/display/spinner.d.ts.map +1 -1
  17. package/build/components/display/spinner.js +20 -31
  18. package/build/components/display/spinner.js.map +1 -1
  19. package/build/components/display/video_attachment_preview.d.ts.map +1 -1
  20. package/build/components/display/video_attachment_preview.js +4 -10
  21. package/build/components/display/video_attachment_preview.js.map +1 -1
  22. package/build/components/primitive/banner_primitive.d.ts.map +1 -1
  23. package/build/components/primitive/banner_primitive.js +5 -5
  24. package/build/components/primitive/banner_primitive.js.map +1 -1
  25. package/build/screens/conversation_details_screen.d.ts.map +1 -1
  26. package/build/screens/conversation_details_screen.js +20 -20
  27. package/build/screens/conversation_details_screen.js.map +1 -1
  28. package/build/screens/design_system_screen.d.ts.map +1 -1
  29. package/build/screens/design_system_screen.js +13 -17
  30. package/build/screens/design_system_screen.js.map +1 -1
  31. package/build/utils/index.d.ts +0 -1
  32. package/build/utils/index.d.ts.map +1 -1
  33. package/build/utils/index.js +0 -1
  34. package/build/utils/index.js.map +1 -1
  35. package/package.json +2 -2
  36. package/src/components/conversation/message.tsx +1 -6
  37. package/src/components/display/badge.tsx +4 -4
  38. package/src/components/display/button.tsx +11 -2
  39. package/src/components/display/icon_button.tsx +8 -10
  40. package/src/components/display/image.tsx +8 -1
  41. package/src/components/display/person.tsx +3 -4
  42. package/src/components/display/spinner.tsx +28 -36
  43. package/src/components/display/video_attachment_preview.tsx +4 -10
  44. package/src/components/primitive/banner_primitive.tsx +4 -5
  45. package/src/screens/conversation_details_screen.tsx +20 -20
  46. package/src/screens/design_system_screen.tsx +12 -18
  47. package/src/utils/index.ts +0 -1
  48. package/build/utils/space.d.ts +0 -3
  49. package/build/utils/space.d.ts.map +0 -1
  50. package/build/utils/space.js +0 -22
  51. package/build/utils/space.js.map +0 -1
  52. package/src/__tests__/utils/space.tsx +0 -60
  53. package/src/utils/space.ts +0 -39
@@ -147,17 +147,18 @@ export function IconButton({
147
147
  }}
148
148
  {...props}
149
149
  >
150
- {loading && (
150
+ {loading ? (
151
151
  <Spinner
152
152
  size={styles.spinner.fontSize}
153
153
  maxFontSizeMultiplier={maxFontSizeMultiplier || 0}
154
154
  />
155
+ ) : (
156
+ <Icon
157
+ name={name}
158
+ style={[styles.icon, iconStyle, disabled && styles.iconDisabled]}
159
+ maxFontSizeMultiplier={maxFontSizeMultiplier}
160
+ />
155
161
  )}
156
- <Icon
157
- name={name}
158
- style={[styles.icon, iconStyle, disabled && styles.disabled, loading && styles.loading]}
159
- maxFontSizeMultiplier={maxFontSizeMultiplier}
160
- />
161
162
  </Pressable>
162
163
  )
163
164
  }
@@ -227,12 +228,9 @@ const useStyles = ({
227
228
  fontSize: sizeStyleMap[size].fontSize,
228
229
  color: colorOptionMap[colorKey],
229
230
  },
230
- disabled: {
231
+ iconDisabled: {
231
232
  color: colors.iconColorDefaultDisabled,
232
233
  },
233
- loading: {
234
- opacity: 0,
235
- },
236
234
  spinner: {
237
235
  fontSize: sizeStyleMap[size].fontSize,
238
236
  },
@@ -100,7 +100,7 @@ export function Image({
100
100
  />
101
101
  {!hideLoader && isLoading && (
102
102
  <View style={[styles.loadingBackground, loadingBackgroundStyles]}>
103
- <Spinner size={loaderSize} />
103
+ <Spinner size={loaderSize} style={styles.spinner} />
104
104
  </View>
105
105
  )}
106
106
  </View>
@@ -135,5 +135,12 @@ const useStyles = ({ width, height, borderRadius }: Styles) => {
135
135
  width,
136
136
  height,
137
137
  },
138
+ spinner: {
139
+ width: '100%',
140
+ height: '100%',
141
+ justifyContent: 'center',
142
+ alignItems: 'center',
143
+ position: 'absolute',
144
+ },
138
145
  })
139
146
  }
@@ -5,7 +5,6 @@ import { MemberResource } from '../../types'
5
5
  import { Avatar } from './avatar'
6
6
  import { Text } from './text'
7
7
  import { Badge } from './badge'
8
- import { space } from '../../utils'
9
8
 
10
9
  // =================================
11
10
  // ====== Components ===============
@@ -43,10 +42,10 @@ const useStyles = () => {
43
42
  wrapper: {
44
43
  flexDirection: 'row',
45
44
  alignItems: 'center',
46
- gap: space(1),
45
+ gap: 8,
47
46
  },
48
47
  content: {
49
- gap: space(0.25),
48
+ gap: 2,
50
49
  flexShrink: 1,
51
50
  },
52
51
  name: {
@@ -54,7 +53,7 @@ const useStyles = () => {
54
53
  },
55
54
  badges: {
56
55
  flexDirection: 'row',
57
- gap: space(0.5),
56
+ gap: 4,
58
57
  },
59
58
  })
60
59
  }
@@ -1,5 +1,12 @@
1
- import React, { useEffect, useRef } from 'react'
2
- import { Animated, Easing, StyleProp, StyleSheet, View, ViewStyle } from 'react-native'
1
+ import React, { useEffect } from 'react'
2
+ import { StyleProp, StyleSheet, View, ViewStyle } from 'react-native'
3
+ import Animated, {
4
+ useSharedValue,
5
+ useAnimatedStyle,
6
+ withRepeat,
7
+ withTiming,
8
+ Easing,
9
+ } from 'react-native-reanimated'
3
10
  import { useFontScale, useTheme } from '../../hooks'
4
11
 
5
12
  // =================================
@@ -32,34 +39,32 @@ export function Spinner({
32
39
  maxFontSizeMultiplier = PREVENT_SCALING_DEFAULT,
33
40
  style,
34
41
  }: SpinnerProps) {
35
- const rotation = useRef(new Animated.Value(0)).current
42
+ const styles = useStyles({ maxFontSizeMultiplier, size })
36
43
 
37
- const animation = Animated.loop(
38
- Animated.timing(rotation, {
39
- toValue: 1,
40
- duration: 1000,
41
- easing: Easing.linear,
42
- useNativeDriver: true,
43
- })
44
- )
45
-
46
- const rotateValue = rotation.interpolate({
47
- inputRange: [0, 1],
48
- outputRange: ['0deg', '360deg'],
44
+ const rotation = useSharedValue(0)
45
+ const animatedStyle = useAnimatedStyle(() => {
46
+ return {
47
+ transform: [{ rotate: `${rotation.value}deg` }],
48
+ }
49
49
  })
50
50
 
51
- const styles = useStyles({ maxFontSizeMultiplier, rotateValue, size })
52
-
53
51
  useEffect(() => {
54
- animation.start()
55
- return () => animation.stop()
56
- }, [animation])
52
+ rotation.value = withRepeat(
53
+ withTiming(360, {
54
+ duration: 1000,
55
+ easing: Easing.linear,
56
+ }),
57
+ -1 // loops animation infinitely
58
+ )
57
59
 
58
- useEffect(() => () => rotation.setValue(0), [rotation])
60
+ return () => {
61
+ rotation.value = 0 // Reset rotation when Spinner unmounts
62
+ }
63
+ }, [rotation])
59
64
 
60
65
  return (
61
66
  <View style={[styles.container, style]}>
62
- <Animated.View style={styles.animatedContainer}>
67
+ <Animated.View style={[styles.animatedContainer, animatedStyle]}>
63
68
  <View style={styles.clipping}>
64
69
  <View style={[styles.circle, styles.spinner]} />
65
70
  </View>
@@ -75,32 +80,22 @@ export function Spinner({
75
80
 
76
81
  interface Styles {
77
82
  maxFontSizeMultiplier: number | undefined
78
- rotateValue: Animated.AnimatedInterpolation<string | number>
79
83
  size: number
80
84
  }
81
85
 
82
- const useStyles = ({ maxFontSizeMultiplier, rotateValue, size }: Styles) => {
86
+ const useStyles = ({ maxFontSizeMultiplier, size }: Styles) => {
83
87
  const { colors } = useTheme()
84
88
  const fontScale = useFontScale({ maxFontSizeMultiplier })
85
89
  const scalableSize = size * fontScale
86
90
 
87
91
  return StyleSheet.create({
88
92
  container: {
89
- width: '100%',
90
- height: '100%',
91
- position: 'absolute',
92
- top: 0,
93
- left: 0,
94
- zIndex: 200,
95
- justifyContent: 'center',
96
- alignItems: 'center',
97
93
  opacity: 0.7,
98
94
  },
99
95
  animatedContainer: {
100
96
  width: scalableSize,
101
97
  height: scalableSize,
102
98
  borderRadius: scalableSize / 2,
103
- transform: [{ rotate: rotateValue }],
104
99
  },
105
100
  circle: {
106
101
  width: scalableSize,
@@ -110,9 +105,6 @@ const useStyles = ({ maxFontSizeMultiplier, rotateValue, size }: Styles) => {
110
105
  borderWidth: 3,
111
106
  },
112
107
  spinner: {
113
- position: 'absolute',
114
- top: 0,
115
- left: 0,
116
108
  borderColor: colors.fillColorNeutral020,
117
109
  },
118
110
  track: {
@@ -29,9 +29,7 @@ export const VideoAttachmentPreview = ({
29
29
  if (loading) {
30
30
  return (
31
31
  <View style={styles.container}>
32
- <View style={styles.loadingContainer}>
33
- <Spinner size={20} />
34
- </View>
32
+ <Spinner size={20} style={styles.spinner} />
35
33
  </View>
36
34
  )
37
35
  }
@@ -98,13 +96,6 @@ const useStyles = ({ error }: Partial<VideoAttachmentPreviewProps>) => {
98
96
  borderRadius,
99
97
  padding: 4,
100
98
  },
101
- loadingContainer: {
102
- position: 'absolute',
103
- top: 0,
104
- left: 0,
105
- right: 0,
106
- bottom: 0,
107
- },
108
99
  contentContainer: {
109
100
  flexDirection: 'row',
110
101
  gap: 8,
@@ -149,5 +140,8 @@ const useStyles = ({ error }: Partial<VideoAttachmentPreviewProps>) => {
149
140
  transform: [{ translateX: 1 }],
150
141
  fontSize: 10,
151
142
  },
143
+ spinner: {
144
+ marginHorizontal: 'auto',
145
+ },
152
146
  })
153
147
  }
@@ -8,7 +8,6 @@ import {
8
8
  MAX_FONT_SIZE_MULTIPLIER,
9
9
  platformFontWeightMedium,
10
10
  platformPressedOpacityStyle,
11
- space,
12
11
  } from '../../utils'
13
12
  import { tokens } from '../../vendor/tapestry/tokens'
14
13
  import { useCreateAndroidRippleColor, useFontScale } from '../../hooks'
@@ -275,18 +274,18 @@ const useStyles = ({ appearance = 'neutral' }: Styles = {}) => {
275
274
  staticLayout: {
276
275
  flexDirection: 'row',
277
276
  backgroundColor: statusColorMap[appearance].background,
278
- padding: space(1.5),
279
- gap: space(1),
277
+ padding: 12,
278
+ gap: 8,
280
279
  borderRadius: tokens.borderRadiusMd,
281
280
  },
282
281
  content: {
283
- gap: space(0.5),
282
+ gap: 4,
284
283
  flex: 1,
285
284
  },
286
285
  icon: {
287
286
  color: statusColorMap[appearance].icon,
288
287
  fontSize: tokens.fontSizeMd,
289
- marginTop: (space(0.5) - LINE_HEIGHT_OFFSET) * fontScale,
288
+ marginTop: (4 - LINE_HEIGHT_OFFSET) * fontScale,
290
289
  },
291
290
  heading: {
292
291
  color: statusColorMap[appearance].text,
@@ -32,7 +32,6 @@ import {
32
32
  import { MemberResource, isDefined } from '../types'
33
33
  import { HeaderSubmitButton } from '../components/display/platform_modal_header_buttons'
34
34
  import { FlashList } from '@shopify/flash-list'
35
- import { space } from '../utils'
36
35
  import { tokens } from '../vendor/tapestry/tokens'
37
36
  import { ButtonAppearanceUnion } from '../components/display/utils/button_colors'
38
37
  import { GroupResource } from '../types/resources/group_resource'
@@ -519,7 +518,8 @@ function TeamsGroup({ teams }: { teams: GroupResource[] }) {
519
518
 
520
519
  const useStyles = ({ isStart, isEnd }: { isStart?: boolean; isEnd?: boolean } = {}) => {
521
520
  const { colors } = useTheme()
522
- const headerBottomPadding = space(0.5)
521
+ const headerBottomPadding = 4
522
+ const sectionBorderRadius = 8
523
523
 
524
524
  return StyleSheet.create({
525
525
  listContainer: {
@@ -527,50 +527,50 @@ const useStyles = ({ isStart, isEnd }: { isStart?: boolean; isEnd?: boolean } =
527
527
  backgroundColor: colors.surfaceColor080,
528
528
  },
529
529
  contentContainer: {
530
- padding: space(2),
530
+ padding: 16,
531
531
  },
532
532
  sectionOuterBase: {
533
- paddingLeft: space(2),
533
+ paddingLeft: 16,
534
534
  backgroundColor: colors.surfaceColor100,
535
- borderTopLeftRadius: isStart ? space(1) : 0,
536
- borderTopRightRadius: isStart ? space(1) : 0,
537
- borderBottomLeftRadius: isEnd ? space(1) : 0,
538
- borderBottomRightRadius: isEnd ? space(1) : 0,
539
- marginBottom: isEnd ? space(2) : 0,
535
+ borderTopLeftRadius: isStart ? sectionBorderRadius : 0,
536
+ borderTopRightRadius: isStart ? sectionBorderRadius : 0,
537
+ borderBottomLeftRadius: isEnd ? sectionBorderRadius : 0,
538
+ borderBottomRightRadius: isEnd ? sectionBorderRadius : 0,
539
+ marginBottom: isEnd ? 16 : 0,
540
540
  },
541
541
  sectionInnerBase: {
542
- paddingRight: space(2),
543
- paddingTop: isStart ? space(2) : space(1.5),
544
- paddingBottom: isEnd ? space(2) : space(1.5),
542
+ paddingRight: 16,
543
+ paddingTop: isStart ? 16 : 12,
544
+ paddingBottom: isEnd ? 16 : 12,
545
545
  },
546
546
  sectionInnerHeader: {
547
547
  paddingBottom: headerBottomPadding,
548
548
  },
549
549
  sectionInnerHeaderWithBottomBorder: {
550
- paddingBottom: space(2),
550
+ paddingBottom: 16,
551
551
  },
552
552
  sectionInnerBottomBorder: {
553
553
  borderBottomColor: colors.borderColorDefaultBase,
554
554
  borderBottomWidth: isEnd ? 0 : 1,
555
555
  },
556
556
  sectionInnerTitleInput: {
557
- paddingTop: space(1.5), // paddingVertical doesn't override the sectionInner padding
558
- paddingBottom: space(1.5),
557
+ paddingTop: 12, // paddingVertical doesn't override the sectionInner padding
558
+ paddingBottom: 12,
559
559
  },
560
560
  sectionInnerChildNotice: {
561
561
  paddingBottom: headerBottomPadding,
562
562
  },
563
563
  sectionInnerMiddleMiddle: {
564
564
  paddingTop: 0,
565
- paddingBottom: space(1.5),
565
+ paddingBottom: 12,
566
566
  },
567
567
  sectionInnerFirstMember: {
568
- paddingTop: space(1.5),
569
- paddingBottom: space(1.5),
568
+ paddingTop: 12,
569
+ paddingBottom: 12,
570
570
  },
571
571
  sectionInnerLastMember: {
572
572
  paddingTop: 0,
573
- paddingBottom: space(2),
573
+ paddingBottom: 16,
574
574
  },
575
575
  titleContainer: {
576
576
  gap: 4,
@@ -605,7 +605,7 @@ const useStyles = ({ isStart, isEnd }: { isStart?: boolean; isEnd?: boolean } =
605
605
  flexDirection: 'row',
606
606
  justifyContent: 'space-between',
607
607
  alignItems: 'center',
608
- gap: space(1),
608
+ gap: 8,
609
609
  },
610
610
  settingRowContent: {
611
611
  flex: 1,
@@ -24,7 +24,6 @@ import {
24
24
  ImageAttachmentPreview,
25
25
  } from '../components/display'
26
26
  import {
27
- space,
28
27
  MAX_FONT_SIZE_MULTIPLIER,
29
28
  platformPressedOpacityStyle,
30
29
  platformFontWeightMedium,
@@ -211,15 +210,13 @@ function ThemeSection({ isLast }: SectionProps) {
211
210
  // }
212
211
 
213
212
  function IndicatorsSection({ isLast }: SectionProps) {
214
- const styles = useStyles()
215
-
216
213
  return (
217
214
  <CollapsableSection title="Indicators" isLast={isLast}>
218
215
  <Group
219
216
  title="Spinner"
220
217
  description="Loading indicators that can be used within or close to atomic components. Not intended for full-screen loading."
221
218
  >
222
- <Row style={styles.spinnerContainer}>
219
+ <Row>
223
220
  <Spinner size={24} />
224
221
  </Row>
225
222
  </Group>
@@ -1159,11 +1156,11 @@ const useStyles = () => {
1159
1156
  backgroundColor: colors.fillColorNeutral100Inverted,
1160
1157
  },
1161
1158
  container: {
1162
- padding: space(3),
1159
+ padding: 24,
1163
1160
  },
1164
1161
  listItem: { color: colors.fillColorNeutral020 },
1165
1162
  section: {
1166
- gap: space(1),
1163
+ gap: 8,
1167
1164
  borderColor: colors.fillColorNeutral020,
1168
1165
  },
1169
1166
  sectionBorderTop: {
@@ -1176,30 +1173,30 @@ const useStyles = () => {
1176
1173
  flexDirection: 'row',
1177
1174
  justifyContent: 'space-between',
1178
1175
  alignItems: 'center',
1179
- paddingVertical: space(3),
1176
+ paddingVertical: 24,
1180
1177
  },
1181
1178
  sectionChildren: {
1182
- paddingBottom: space(3),
1183
- gap: space(6),
1179
+ paddingBottom: 24,
1180
+ gap: 48,
1184
1181
  },
1185
1182
  row: {
1186
- gap: space(2),
1183
+ gap: 16,
1187
1184
  flexDirection: 'row',
1188
1185
  alignItems: 'center',
1189
1186
  justifyContent: 'center',
1190
1187
  flexWrap: 'wrap',
1191
1188
  },
1192
1189
  column: {
1193
- gap: space(2),
1190
+ gap: 16,
1194
1191
  },
1195
1192
  columnCenter: {
1196
1193
  alignItems: 'center',
1197
1194
  },
1198
1195
  textRow: {
1199
- gap: space(1.5),
1196
+ gap: 12,
1200
1197
  },
1201
1198
  textGroup: {
1202
- gap: space(2.5),
1199
+ gap: 20,
1203
1200
  },
1204
1201
  mediumWeight: {
1205
1202
  fontWeight: platformFontWeightMedium,
@@ -1208,13 +1205,10 @@ const useStyles = () => {
1208
1205
  justifyContent: 'flex-start',
1209
1206
  },
1210
1207
  group: {
1211
- gap: space(3),
1208
+ gap: 24,
1212
1209
  },
1213
1210
  groupHeading: {
1214
- gap: space(1),
1215
- },
1216
- spinnerContainer: {
1217
- height: space(2.5),
1211
+ gap: 8,
1218
1212
  },
1219
1213
  image: {
1220
1214
  width: 100,
@@ -1,7 +1,6 @@
1
1
  export * from './session'
2
2
  export * from './theme'
3
3
  export * from './styles'
4
- export * from './space'
5
4
  export * from './client'
6
5
  export * from './uri'
7
6
  export * from './cache'
@@ -1,3 +0,0 @@
1
- export type SpacingValues = 0.25 | 0.5 | 1 | 1.5 | 2 | 2.5 | 3 | 3.5 | 4 | 4.5 | 5 | 5.5 | 6 | 6.5 | 7 | 7.5;
2
- export declare function space(value: SpacingValues): number;
3
- //# sourceMappingURL=space.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"space.d.ts","sourceRoot":"","sources":["../../src/utils/space.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,aAAa,GACrB,IAAI,GACJ,GAAG,GACH,CAAC,GACD,GAAG,GACH,CAAC,GACD,GAAG,GACH,CAAC,GACD,GAAG,GACH,CAAC,GACD,GAAG,GACH,CAAC,GACD,GAAG,GACH,CAAC,GACD,GAAG,GACH,CAAC,GACD,GAAG,CAAA;AAEP,wBAAgB,KAAK,CAAC,KAAK,EAAE,aAAa,GAAG,MAAM,CAalD"}
@@ -1,22 +0,0 @@
1
- import { tokens } from '../vendor/tapestry/tokens';
2
- export function space(value) {
3
- if (value === 0.25)
4
- return tokens.spacingFourth;
5
- if (value === 0.5)
6
- return tokens.spacingHalf;
7
- if (value < 1 || value > 7.5)
8
- return handleInvalidSpace(value);
9
- // Reject fractional values that are not 0 or 0.5
10
- const wholeValue = Math.floor(value);
11
- const fractionalValue = value % 1;
12
- if (fractionalValue !== 0 && fractionalValue !== 0.5)
13
- return handleInvalidSpace(value);
14
- // Deliver a whole value or add a half spacing token to it
15
- const remainderValue = fractionalValue === 0.5 ? tokens.spacingHalf : 0;
16
- return tokens[`spacing${wholeValue}`] + remainderValue;
17
- }
18
- function handleInvalidSpace(value) {
19
- console.warn(`Invalid space value: ${value} — Must be a whole or half number between 1–7.`);
20
- return 0;
21
- }
22
- //# sourceMappingURL=space.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"space.js","sourceRoot":"","sources":["../../src/utils/space.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,2BAA2B,CAAA;AAoBlD,MAAM,UAAU,KAAK,CAAC,KAAoB;IACxC,IAAI,KAAK,KAAK,IAAI;QAAE,OAAO,MAAM,CAAC,aAAa,CAAA;IAC/C,IAAI,KAAK,KAAK,GAAG;QAAE,OAAO,MAAM,CAAC,WAAW,CAAA;IAC5C,IAAI,KAAK,GAAG,CAAC,IAAI,KAAK,GAAG,GAAG;QAAE,OAAO,kBAAkB,CAAC,KAAK,CAAC,CAAA;IAE9D,iDAAiD;IACjD,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAA8B,CAAA;IACjE,MAAM,eAAe,GAAG,KAAK,GAAG,CAAC,CAAA;IACjC,IAAI,eAAe,KAAK,CAAC,IAAI,eAAe,KAAK,GAAG;QAAE,OAAO,kBAAkB,CAAC,KAAK,CAAC,CAAA;IAEtF,0DAA0D;IAC1D,MAAM,cAAc,GAAG,eAAe,KAAK,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAA;IACvE,OAAO,MAAM,CAAC,UAAU,UAAU,EAAE,CAAC,GAAG,cAAc,CAAA;AACxD,CAAC;AAED,SAAS,kBAAkB,CAAC,KAAa;IACvC,OAAO,CAAC,IAAI,CAAC,wBAAwB,KAAK,gDAAgD,CAAC,CAAA;IAC3F,OAAO,CAAC,CAAA;AACV,CAAC","sourcesContent":["import { tokens } from '../vendor/tapestry/tokens'\n\nexport type SpacingValues =\n | 0.25\n | 0.5\n | 1\n | 1.5\n | 2\n | 2.5\n | 3\n | 3.5\n | 4\n | 4.5\n | 5\n | 5.5\n | 6\n | 6.5\n | 7\n | 7.5\n\nexport function space(value: SpacingValues): number {\n if (value === 0.25) return tokens.spacingFourth\n if (value === 0.5) return tokens.spacingHalf\n if (value < 1 || value > 7.5) return handleInvalidSpace(value)\n\n // Reject fractional values that are not 0 or 0.5\n const wholeValue = Math.floor(value) as 1 | 2 | 3 | 4 | 5 | 6 | 7\n const fractionalValue = value % 1\n if (fractionalValue !== 0 && fractionalValue !== 0.5) return handleInvalidSpace(value)\n\n // Deliver a whole value or add a half spacing token to it\n const remainderValue = fractionalValue === 0.5 ? tokens.spacingHalf : 0\n return tokens[`spacing${wholeValue}`] + remainderValue\n}\n\nfunction handleInvalidSpace(value: number) {\n console.warn(`Invalid space value: ${value} — Must be a whole or half number between 1–7.`)\n return 0\n}\n"]}
@@ -1,60 +0,0 @@
1
- import { space, SpacingValues } from '../../utils/space'
2
- import { tokens } from '../../vendor/tapestry/tokens'
3
-
4
- describe('space function', () => {
5
- // Spy on console.warn to check for invalid inputs
6
- beforeEach(() => {
7
- jest.spyOn(console, 'warn').mockImplementation(() => {})
8
- })
9
-
10
- afterEach(() => {
11
- jest.restoreAllMocks()
12
- })
13
-
14
- const validTokenValues: Record<SpacingValues, number> = {
15
- 0.25: tokens.spacingFourth,
16
- 0.5: tokens.spacingHalf,
17
- 1: tokens.spacing1,
18
- 1.5: tokens.spacing1 + tokens.spacingHalf,
19
- 2: tokens.spacing2,
20
- 2.5: tokens.spacing2 + tokens.spacingHalf,
21
- 3: tokens.spacing3,
22
- 3.5: tokens.spacing3 + tokens.spacingHalf,
23
- 4: tokens.spacing4,
24
- 4.5: tokens.spacing4 + tokens.spacingHalf,
25
- 5: tokens.spacing5,
26
- 5.5: tokens.spacing5 + tokens.spacingHalf,
27
- 6: tokens.spacing6,
28
- 6.5: tokens.spacing6 + tokens.spacingHalf,
29
- 7: tokens.spacing7,
30
- 7.5: tokens.spacing7 + tokens.spacingHalf,
31
- }
32
-
33
- it('should return the correct token values for all valid SpacingValues', () => {
34
- Object.entries(validTokenValues).forEach(([value, expected]) => {
35
- expect(space(Number(value) as SpacingValues)).toBe(expected)
36
- })
37
- })
38
-
39
- it('should warn and return 0 for an invalid value less than 1 (e.g., 0.8)', () => {
40
- const result = space(0.8 as SpacingValues)
41
- expect(result).toBe(0)
42
- expect(console.warn).toHaveBeenCalledWith(warnText('0.8'))
43
- })
44
-
45
- it('should warn and return 0 for an invalid fractional value (e.g., 1.8)', () => {
46
- const result = space(1.8 as SpacingValues)
47
- expect(result).toBe(0)
48
- expect(console.warn).toHaveBeenCalledWith(warnText('1.8'))
49
- })
50
-
51
- it('should warn and return 0 for a value greater than 7.5 (e.g., 19)', () => {
52
- const result = space(19 as SpacingValues)
53
- expect(result).toBe(0)
54
- expect(console.warn).toHaveBeenCalledWith(warnText('19'))
55
- })
56
- })
57
-
58
- function warnText(value: string) {
59
- return `Invalid space value: ${value} — Must be a whole or half number between 1–7.`
60
- }
@@ -1,39 +0,0 @@
1
- import { tokens } from '../vendor/tapestry/tokens'
2
-
3
- export type SpacingValues =
4
- | 0.25
5
- | 0.5
6
- | 1
7
- | 1.5
8
- | 2
9
- | 2.5
10
- | 3
11
- | 3.5
12
- | 4
13
- | 4.5
14
- | 5
15
- | 5.5
16
- | 6
17
- | 6.5
18
- | 7
19
- | 7.5
20
-
21
- export function space(value: SpacingValues): number {
22
- if (value === 0.25) return tokens.spacingFourth
23
- if (value === 0.5) return tokens.spacingHalf
24
- if (value < 1 || value > 7.5) return handleInvalidSpace(value)
25
-
26
- // Reject fractional values that are not 0 or 0.5
27
- const wholeValue = Math.floor(value) as 1 | 2 | 3 | 4 | 5 | 6 | 7
28
- const fractionalValue = value % 1
29
- if (fractionalValue !== 0 && fractionalValue !== 0.5) return handleInvalidSpace(value)
30
-
31
- // Deliver a whole value or add a half spacing token to it
32
- const remainderValue = fractionalValue === 0.5 ? tokens.spacingHalf : 0
33
- return tokens[`spacing${wholeValue}`] + remainderValue
34
- }
35
-
36
- function handleInvalidSpace(value: number) {
37
- console.warn(`Invalid space value: ${value} — Must be a whole or half number between 1–7.`)
38
- return 0
39
- }