cpk-ui 0.8.0-beta.4 → 0.8.0-beta.5

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.
@@ -10,6 +10,11 @@ type Styles = {
10
10
  toggleElement?: StyleProp<ViewStyle>;
11
11
  };
12
12
  export type AccordionSizeType = 'small' | 'medium' | 'large' | number;
13
+ export type AccordionHeaderContext<T> = {
14
+ title: T;
15
+ expanded: boolean;
16
+ toggle: () => void;
17
+ };
13
18
  export type AccordionBaseProps<T = string, K = string> = {
14
19
  data: AccordionItemDataType<T, K>[];
15
20
  style?: StyleProp<ViewStyle>;
@@ -22,16 +27,21 @@ export type AccordionBaseProps<T = string, K = string> = {
22
27
  expandAllOnStart?: boolean;
23
28
  /** Array of indexes that should be expanded on start. Overrides expandAllOnStart */
24
29
  defaultExpandedIndexes?: number[];
30
+ /** Controlled disclosure, including an empty array to close every item. */
31
+ expandedIndexes?: readonly number[];
32
+ onExpandedChange?: (index: number, expanded: boolean) => void;
25
33
  animDuration?: number;
26
34
  activeOpacity?: number;
27
35
  toggleElementPosition?: 'left' | 'right';
28
36
  toggleElement?: ReactElement | null;
29
37
  renderTitle?: (title: T) => ReactElement;
38
+ /** Own the entire header, including independent menu/drag controls. */
39
+ renderHeader?: (context: AccordionHeaderContext<T>) => ReactElement;
30
40
  renderItem?: (body: K) => ReactElement;
31
41
  onPressItem?: (title: T | string, body: K | string) => void;
32
42
  };
33
43
  export type AccordionProps<T = string, K = string> = AccordionBaseProps<T, K>;
34
- declare function Accordion<T, K>({ style, toggleElementPosition, size, data, collapseOnStart, expandAllOnStart, defaultExpandedIndexes, ...rest }: AccordionProps<T, K>): ReactElement;
44
+ declare function Accordion<T, K>({ style, toggleElementPosition, size, data, collapseOnStart, expandAllOnStart, defaultExpandedIndexes, expandedIndexes, onExpandedChange, ...rest }: AccordionProps<T, K>): ReactElement;
35
45
  declare const _default: typeof Accordion;
36
46
  export default _default;
37
47
  export { Accordion };
@@ -1 +1 @@
1
- {"version":3,"file":"Accordion.d.ts","sourceRoot":"","sources":["../../../../src/components/uis/Accordion/Accordion.tsx"],"names":[],"mappings":"AAAA,OAAc,EAAU,KAAK,YAAY,EAAC,MAAM,OAAO,CAAC;AACxD,OAAO,KAAK,EAAC,SAAS,EAAE,SAAS,EAAE,SAAS,EAAC,MAAM,cAAc,CAAC;AAIlE,OAAO,KAAK,EAAC,qBAAqB,EAAC,MAAM,iBAAiB,CAAC;AAO3D,KAAK,MAAM,GAAG;IACZ,SAAS,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IACjC,cAAc,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IACtC,SAAS,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IACjC,aAAa,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IACrC,QAAQ,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAChC,aAAa,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;CACtC,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG,OAAO,GAAG,QAAQ,GAAG,OAAO,GAAG,MAAM,CAAC;AAEtE,MAAM,MAAM,kBAAkB,CAAC,CAAC,GAAG,MAAM,EAAE,CAAC,GAAG,MAAM,IAAI;IACvD,IAAI,EAAE,qBAAqB,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC;IACpC,KAAK,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAC7B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,iBAAiB,CAAC;IACzB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,+CAA+C;IAC/C,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,iFAAiF;IACjF,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,oFAAoF;IACpF,sBAAsB,CAAC,EAAE,MAAM,EAAE,CAAC;IAClC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,qBAAqB,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IACzC,aAAa,CAAC,EAAE,YAAY,GAAG,IAAI,CAAC;IACpC,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,YAAY,CAAC;IACzC,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,YAAY,CAAC;IACvC,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC,GAAG,MAAM,EAAE,IAAI,EAAE,CAAC,GAAG,MAAM,KAAK,IAAI,CAAC;CAC7D,CAAC;AAEF,MAAM,MAAM,cAAc,CAAC,CAAC,GAAG,MAAM,EAAE,CAAC,GAAG,MAAM,IAAI,kBAAkB,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;AAE9E,iBAAS,SAAS,CAAC,CAAC,EAAE,CAAC,EAAE,EACvB,KAAK,EACL,qBAA+B,EAC/B,IAAe,EACf,IAAI,EACJ,eAAe,EACf,gBAAgB,EAChB,sBAAsB,EACtB,GAAG,IAAI,EACR,EAAE,cAAc,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,YAAY,CAiDrC;wBAGuC,OAAO,SAAS;AAAxD,wBAAyD;AACzD,OAAO,EAAC,SAAS,EAAC,CAAC"}
1
+ {"version":3,"file":"Accordion.d.ts","sourceRoot":"","sources":["../../../../src/components/uis/Accordion/Accordion.tsx"],"names":[],"mappings":"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"}
@@ -6,7 +6,7 @@ import { AccordionItem } from './AccordionItem';
6
6
  const Container = styled(View) `
7
7
  flex-direction: column;
8
8
  `;
9
- function Accordion({ style, toggleElementPosition = 'right', size = 'medium', data, collapseOnStart, expandAllOnStart, defaultExpandedIndexes, ...rest }) {
9
+ function Accordion({ style, toggleElementPosition = 'right', size = 'medium', data, collapseOnStart, expandAllOnStart, defaultExpandedIndexes, expandedIndexes, onExpandedChange, ...rest }) {
10
10
  // Memoize accordion items rendering
11
11
  const accordionItems = useMemo(() => data.map((datum, titleKey) => {
12
12
  // Determine if this item should be collapsed on start
@@ -28,7 +28,7 @@ function Accordion({ style, toggleElementPosition = 'right', size = 'medium', da
28
28
  // Default: all items collapsed
29
29
  shouldCollapse = true;
30
30
  }
31
- return (_jsx(AccordionItem, { data: datum, testID: `${titleKey}`, toggleElementPosition: toggleElementPosition, size: size, collapseOnStart: shouldCollapse, ...rest }, titleKey));
31
+ return (_jsx(AccordionItem, { data: datum, testID: `${titleKey}`, toggleElementPosition: toggleElementPosition, size: size, collapseOnStart: shouldCollapse, expanded: expandedIndexes?.includes(titleKey), onExpandedChange: (expanded) => onExpandedChange?.(titleKey, expanded), ...rest }, titleKey));
32
32
  }), [
33
33
  data,
34
34
  toggleElementPosition,
@@ -36,6 +36,8 @@ function Accordion({ style, toggleElementPosition = 'right', size = 'medium', da
36
36
  collapseOnStart,
37
37
  expandAllOnStart,
38
38
  defaultExpandedIndexes,
39
+ expandedIndexes,
40
+ onExpandedChange,
39
41
  rest,
40
42
  ]);
41
43
  return _jsx(Container, { style: style, children: accordionItems });
@@ -4,11 +4,14 @@ export type AccordionItemDataType<T, K> = {
4
4
  title: T;
5
5
  items: K[];
6
6
  };
7
- type Props<T, K> = Omit<AccordionBaseProps<T, K>, 'data' | 'style'> & {
7
+ type Props<T, K> = Omit<AccordionBaseProps<T, K>, 'data' | 'style' | 'onExpandedChange'> & {
8
8
  testID: string;
9
- data: AccordionItemDataType<string, string> | AccordionItemDataType<T, K>;
9
+ data: AccordionItemDataType<T, K>;
10
+ expanded?: boolean;
11
+ onExpandedChange?: (expanded: boolean) => void;
10
12
  };
11
- export declare function AccordionItem<T, K>({ testID, data: data, size, shouldAnimate, collapseOnStart, animDuration, activeOpacity, toggleElement, toggleElementPosition, onPressItem, renderTitle, renderItem, styles, }: Props<T, K>): ReactElement;
13
+ /** One mounted body: no invisible duplicate controls or JS-frame height loop. */
14
+ export declare function AccordionItem<T, K>({ testID, data, size, shouldAnimate, collapseOnStart, expanded: controlledExpanded, onExpandedChange, animDuration, activeOpacity, toggleElement, toggleElementPosition, onPressItem, renderTitle, renderHeader, renderItem, styles, }: Props<T, K>): ReactElement;
12
15
  declare const _default: typeof AccordionItem;
13
16
  export default _default;
14
17
  //# sourceMappingURL=AccordionItem.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"AccordionItem.d.ts","sourceRoot":"","sources":["../../../../src/components/uis/Accordion/AccordionItem.tsx"],"names":[],"mappings":"AACA,OAAc,EAMZ,KAAK,YAAY,EAClB,MAAM,OAAO,CAAC;AAQf,OAAO,KAAK,EAAC,kBAAkB,EAAC,MAAM,aAAa,CAAC;AA+DpD,MAAM,MAAM,qBAAqB,CAAC,CAAC,EAAE,CAAC,IAAI;IACxC,KAAK,EAAE,CAAC,CAAC;IACT,KAAK,EAAE,CAAC,EAAE,CAAC;CACZ,CAAC;AAEF,KAAK,KAAK,CAAC,CAAC,EAAE,CAAC,IAAI,IAAI,CAAC,kBAAkB,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG;IACpE,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,qBAAqB,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,qBAAqB,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;CAC3E,CAAC;AAEF,wBAAgB,aAAa,CAAC,CAAC,EAAE,CAAC,EAAE,EAClC,MAAM,EACN,IAAI,EAAE,IAAI,EACV,IAAe,EACf,aAAoB,EACpB,eAAsB,EACtB,YAAkB,EAClB,aAAiB,EACjB,aAAa,EACb,qBAAqB,EACrB,WAAW,EACX,WAAW,EACX,UAAU,EACV,MAAM,GACP,EAAE,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,YAAY,CAmR5B;wBAG2C,OAAO,aAAa;AAAhE,wBAAiE"}
1
+ {"version":3,"file":"AccordionItem.d.ts","sourceRoot":"","sources":["../../../../src/components/uis/Accordion/AccordionItem.tsx"],"names":[],"mappings":"AAAA,OAAc,EAAoB,KAAK,YAAY,EAAC,MAAM,OAAO,CAAC;AAalE,OAAO,KAAK,EAAC,kBAAkB,EAAC,MAAM,aAAa,CAAC;AAEpD,MAAM,MAAM,qBAAqB,CAAC,CAAC,EAAE,CAAC,IAAI;IAAC,KAAK,EAAE,CAAC,CAAC;IAAC,KAAK,EAAE,CAAC,EAAE,CAAA;CAAC,CAAC;AAEjE,KAAK,KAAK,CAAC,CAAC,EAAE,CAAC,IAAI,IAAI,CACrB,kBAAkB,CAAC,CAAC,EAAE,CAAC,CAAC,EACxB,MAAM,GAAG,OAAO,GAAG,kBAAkB,CACtC,GAAG;IACF,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,qBAAqB,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAClC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,gBAAgB,CAAC,EAAE,CAAC,QAAQ,EAAE,OAAO,KAAK,IAAI,CAAC;CAChD,CAAC;AAEF,iFAAiF;AACjF,wBAAgB,aAAa,CAAC,CAAC,EAAE,CAAC,EAAE,EAClC,MAAM,EACN,IAAI,EACJ,IAAe,EACf,aAAoB,EACpB,eAAsB,EACtB,QAAQ,EAAE,kBAAkB,EAC5B,gBAAgB,EAChB,YAAkB,EAClB,aAAiB,EACjB,aAAa,EACb,qBAA+B,EAC/B,WAAW,EACX,WAAW,EACX,YAAY,EACZ,UAAU,EACV,MAAM,GACP,EAAE,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,YAAY,CA+M5B;wBAQ2C,OAAO,aAAa;AAAhE,wBAAiE"}
@@ -1,209 +1,121 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- // Caveat: Expo web needs React to be imported
3
- import React, { useCallback, useEffect, useMemo, useRef, useState, } from 'react';
4
- import { Animated, Easing, TouchableOpacity, View } from 'react-native';
5
- import { styled, css } from 'kstyled';
2
+ import React, { useMemo, useState } from 'react';
3
+ import { StyleSheet, TouchableOpacity, View } from 'react-native';
4
+ import Animated, { Easing, FadeIn, FadeOut, LinearTransition, ReduceMotion, useReducedMotion, } from 'react-native-reanimated';
5
+ import { useTheme } from '../../../providers/ThemeProvider';
6
6
  import { Icon } from '../Icon/Icon';
7
7
  import { Typography } from '../Typography/Typography';
8
- const TitleTouch = styled(TouchableOpacity) `
9
- height: ${({ $size = 'medium' }) => {
10
- if (typeof $size === 'number')
11
- return $size * 2.4;
12
- return $size === 'small' ? 40 : $size === 'large' ? 56 : 48;
13
- }};
14
- background-color: ${({ theme }) => theme.bg.basic};
15
-
16
- flex-direction: row;
17
- align-items: center;
18
- padding-top: ${({ $size = 'medium' }) => {
19
- if (typeof $size === 'number')
20
- return $size * 0.4;
21
- return $size === 'small' ? 6 : $size === 'large' ? 10 : 8;
22
- }};
23
- padding-bottom: ${({ $size = 'medium' }) => {
24
- if (typeof $size === 'number')
25
- return $size * 0.4;
26
- return $size === 'small' ? 6 : $size === 'large' ? 10 : 8;
27
- }};
28
- padding-left: ${({ $size = 'medium' }) => {
29
- if (typeof $size === 'number')
30
- return $size * 0.6;
31
- return $size === 'small' ? 10 : $size === 'large' ? 14 : 12;
32
- }};
33
- padding-right: ${({ $size = 'medium' }) => {
34
- if (typeof $size === 'number')
35
- return $size * 0.6;
36
- return $size === 'small' ? 10 : $size === 'large' ? 14 : 12;
37
- }};
38
- `;
39
- const StyledIcon = styled(Icon) `
40
- color: ${({ theme }) => theme.text.basic};
41
- font-weight: bold;
42
- font-size: ${({ $size = 'medium' }) => {
43
- if (typeof $size === 'number')
44
- return $size * 0.7;
45
- return $size === 'small' ? 12 : $size === 'large' ? 16 : 14;
46
- }};
47
- `;
48
- const ItemTouch = styled(TouchableOpacity) `
49
- background-color: ${({ theme }) => theme.bg.paper};
50
- padding-top: ${({ $size = 'medium' }) => {
51
- if (typeof $size === 'number')
52
- return $size * 0.4;
53
- return $size === 'small' ? 6 : $size === 'large' ? 10 : 8;
54
- }};
55
- padding-bottom: ${({ $size = 'medium' }) => {
56
- if (typeof $size === 'number')
57
- return $size * 0.4;
58
- return $size === 'small' ? 6 : $size === 'large' ? 10 : 8;
59
- }};
60
- padding-left: ${({ $size = 'medium' }) => {
61
- if (typeof $size === 'number')
62
- return $size * 0.6;
63
- return $size === 'small' ? 10 : $size === 'large' ? 14 : 12;
64
- }};
65
- padding-right: ${({ $size = 'medium' }) => {
66
- if (typeof $size === 'number')
67
- return $size * 0.6;
68
- return $size === 'small' ? 10 : $size === 'large' ? 14 : 12;
69
- }};
70
-
71
- flex-direction: row;
72
- align-items: center;
73
- `;
74
- export function AccordionItem({ testID, data: data, size = 'medium', shouldAnimate = true, collapseOnStart = true, animDuration = 200, activeOpacity = 1, toggleElement, toggleElementPosition, onPressItem, renderTitle, renderItem, styles, }) {
75
- // Calculate icon size based on accordion size
76
- const iconSize = typeof size === 'number'
77
- ? size * 0.7
8
+ /** One mounted body: no invisible duplicate controls or JS-frame height loop. */
9
+ export function AccordionItem({ testID, data, size = 'medium', shouldAnimate = true, collapseOnStart = true, expanded: controlledExpanded, onExpandedChange, animDuration = 200, activeOpacity = 1, toggleElement, toggleElementPosition = 'right', onPressItem, renderTitle, renderHeader, renderItem, styles, }) {
10
+ const { theme } = useTheme();
11
+ const reducedMotion = useReducedMotion();
12
+ const [localExpanded, setLocalExpanded] = useState(!collapseOnStart);
13
+ const expanded = controlledExpanded ?? localExpanded;
14
+ const duration = shouldAnimate && !reducedMotion ? animDuration : 0;
15
+ const transition = useMemo(() => LinearTransition.duration(duration)
16
+ .easing(Easing.bezier(0.23, 1, 0.32, 1))
17
+ .reduceMotion(ReduceMotion.System), [duration]);
18
+ const entering = useMemo(() => FadeIn.duration(duration).reduceMotion(ReduceMotion.System), [duration]);
19
+ const exiting = useMemo(() => FadeOut.duration(duration).reduceMotion(ReduceMotion.System), [duration]);
20
+ const toggle = () => {
21
+ if (controlledExpanded === undefined)
22
+ setLocalExpanded(!expanded);
23
+ onExpandedChange?.(!expanded);
24
+ };
25
+ const numeric = typeof size === 'number';
26
+ const titleHeight = numeric
27
+ ? size * 2.4
78
28
  : size === 'small'
79
- ? 12
29
+ ? 40
80
30
  : size === 'large'
81
- ? 16
82
- : 14;
83
- const defaultToggleElement = (_jsx(StyledIcon, { name: "CaretDown", "$size": size, size: iconSize }));
84
- const dropDownAnimValueRef = useRef(new Animated.Value(0));
85
- const rotateAnimValueRef = useRef(new Animated.Value(0));
86
- const fadeItemAnim = useRef(new Animated.Value(0)).current;
87
- const [itemHeight, setItemHeight] = useState(0);
88
- const [collapsed, setCollapsed] = useState(collapseOnStart);
89
- // Memoize animation configuration
90
- const animationConfig = useMemo(() => ({
91
- duration: animDuration,
92
- easing: Easing.linear,
93
- useNativeDriver: false,
94
- }), [animDuration]);
95
- useEffect(() => {
96
- Animated.timing(fadeItemAnim, {
97
- toValue: collapsed ? 0 : 1,
98
- duration: !collapsed ? 300 : 100,
99
- useNativeDriver: false,
100
- }).start();
101
- }, [fadeItemAnim, collapsed]);
102
- useEffect(() => {
103
- const targetValue = collapsed ? 0 : 1;
104
- if (!shouldAnimate) {
105
- rotateAnimValueRef.current.setValue(targetValue);
106
- dropDownAnimValueRef.current.setValue(targetValue);
107
- return;
108
- }
109
- const config = {
110
- ...animationConfig,
111
- toValue: targetValue,
112
- };
113
- Animated.parallel([
114
- Animated.timing(rotateAnimValueRef.current, config),
115
- Animated.timing(dropDownAnimValueRef.current, config),
116
- ]).start();
117
- }, [collapsed, shouldAnimate, animationConfig]);
118
- // Memoize callbacks
119
- const handleToggle = useCallback(() => {
120
- setCollapsed(!collapsed);
121
- }, [collapsed]);
122
- const handleItemPress = useCallback((body) => {
123
- onPressItem?.(data.title, body);
124
- }, [onPressItem, data.title]);
125
- const handleLayout = useCallback((e) => {
126
- setItemHeight(e.nativeEvent.layout.height);
127
- }, []);
128
- // Calculate margin based on size
129
- const toggleMargin = typeof size === 'number'
31
+ ? 56
32
+ : 48;
33
+ const vertical = numeric
34
+ ? size * 0.4
35
+ : size === 'small'
36
+ ? 6
37
+ : size === 'large'
38
+ ? 10
39
+ : 8;
40
+ const horizontal = numeric
130
41
  ? size * 0.6
131
42
  : size === 'small'
132
43
  ? 10
133
44
  : size === 'large'
134
45
  ? 14
135
46
  : 12;
136
- // Memoize toggle element container
137
- const toggleElContainer = useMemo(() => (_jsx(Animated.View, { style: [
138
- css `
139
- margin-right: ${toggleElementPosition === 'left'
140
- ? toggleMargin
141
- : 0}px;
142
- `,
143
- {
144
- transform: [
145
- {
146
- rotate: rotateAnimValueRef.current.interpolate({
147
- inputRange: [0, 1],
148
- outputRange: ['0deg', '180deg'],
149
- }),
150
- },
151
- ],
152
- },
153
- styles?.toggleElement,
154
- ], children: toggleElement || defaultToggleElement })), [
155
- toggleElement,
156
- defaultToggleElement,
157
- toggleElementPosition,
158
- toggleMargin,
159
- styles?.toggleElement,
160
- ]);
161
- // Memoize container styles
162
- const containerStyles = useMemo(() => [
163
- css `
164
- background-color: transparent;
165
- overflow: hidden;
166
- flex-direction: column-reverse;
167
- `,
168
- styles?.container,
169
- ], [styles?.container]);
170
- const titleContainerStyles = useMemo(() => [
171
- css `
172
- justify-content: ${toggleElementPosition === 'right'
173
- ? 'space-between'
174
- : 'flex-start'};
175
- `,
176
- styles?.titleContainer,
177
- ], [toggleElementPosition, styles?.titleContainer]);
178
- // Memoize animated styles
179
- const animatedItemStyles = useMemo(() => [
180
- {
181
- opacity: fadeItemAnim,
182
- height: dropDownAnimValueRef.current.interpolate({
183
- inputRange: [0, 1],
184
- outputRange: [0, itemHeight],
185
- }),
186
- },
187
- ], [fadeItemAnim, itemHeight]);
188
- // Calculate font sizes based on size prop
189
- const titleFontSize = typeof size === 'number'
47
+ const titleFontSize = numeric
190
48
  ? size
191
49
  : size === 'small'
192
50
  ? 14
193
51
  : size === 'large'
194
52
  ? 18
195
53
  : 16;
196
- const itemFontSize = typeof size === 'number'
54
+ const itemFontSize = numeric
197
55
  ? size * 0.875
198
56
  : size === 'small'
199
57
  ? 12
200
58
  : size === 'large'
201
59
  ? 16
202
60
  : 14;
203
- return (_jsxs(Animated.View, { style: containerStyles, children: [_jsx(View, { accessibilityElementsHidden: true, "aria-hidden": true, importantForAccessibility: "no-hide-descendants", onLayout: handleLayout, style: css `
204
- position: absolute;
205
- opacity: 0;
206
- `, testID: `measure-body-${testID}`, children: data.items.map((body, index) => (_jsx(ItemTouch, { accessible: false, activeOpacity: activeOpacity, disabled: true, onPress: () => handleItemPress(body), "$size": size, children: typeof body === 'string' && !renderItem ? (_jsx(Typography.Body3, { style: [{ fontSize: itemFontSize }, styles?.itemText], children: body })) : (renderItem?.(body)) }, `body-${index}`))) }), _jsx(Animated.View, { accessibilityElementsHidden: collapsed, accessibilityState: { expanded: !collapsed }, "aria-hidden": collapsed, importantForAccessibility: collapsed ? 'no-hide-descendants' : 'auto', style: animatedItemStyles, testID: `body-${testID}`, children: data.items.map((body, index) => (_jsx(ItemTouch, { activeOpacity: activeOpacity, disabled: collapsed, onPress: () => handleItemPress(body), style: styles?.itemContainer, "$size": size, children: typeof body === 'string' && !renderItem ? (_jsx(Typography.Body3, { style: [{ fontSize: itemFontSize }, styles?.itemText], children: body })) : (renderItem?.(body)) }, `body-${index}`))) }), _jsxs(TitleTouch, { activeOpacity: activeOpacity, "aria-expanded": !collapsed, onPress: handleToggle, accessibilityRole: "button", accessibilityLabel: typeof data.title === 'string' ? data.title : 'Accordion section', accessibilityState: { expanded: !collapsed }, accessibilityHint: collapsed ? 'Double tap to expand' : 'Double tap to collapse', style: titleContainerStyles, testID: `title-${testID}`, "$size": size, children: [toggleElementPosition === 'left' ? toggleElContainer : null, typeof data.title === 'string' && !renderTitle ? (_jsx(Typography.Heading4, { style: [{ fontSize: titleFontSize }, styles?.titleText], children: data.title })) : (renderTitle?.(data.title)), toggleElementPosition === 'right' ? toggleElContainer : null] })] }));
61
+ const iconSize = numeric
62
+ ? size * 0.7
63
+ : size === 'small'
64
+ ? 12
65
+ : size === 'large'
66
+ ? 16
67
+ : 14;
68
+ const toggleView = (_jsx(Animated.View, { style: [
69
+ {
70
+ marginRight: toggleElementPosition === 'left' ? horizontal : 0,
71
+ transform: [{ rotate: expanded ? '180deg' : '0deg' }],
72
+ transitionProperty: 'transform',
73
+ transitionDuration: duration,
74
+ transitionTimingFunction: 'ease-out',
75
+ },
76
+ styles?.toggleElement,
77
+ ], children: toggleElement === undefined ? (_jsx(Icon, { name: "CaretDown", color: theme.text.basic, size: iconSize })) : (toggleElement) }));
78
+ return (_jsxs(Animated.View, { collapsable: false, layout: transition, style: [layout.container, styles?.container], children: [renderHeader ? (renderHeader({ title: data.title, expanded, toggle })) : (_jsxs(TouchableOpacity, { activeOpacity: activeOpacity, "aria-expanded": expanded, accessibilityRole: "button", accessibilityLabel: typeof data.title === 'string' ? data.title : 'Accordion section', accessibilityState: { expanded }, accessibilityHint: expanded ? 'Double tap to collapse' : 'Double tap to expand', onPress: toggle, style: [
79
+ layout.title,
80
+ {
81
+ minHeight: titleHeight,
82
+ paddingVertical: vertical,
83
+ paddingHorizontal: horizontal,
84
+ backgroundColor: theme.bg.basic,
85
+ justifyContent: toggleElementPosition === 'right'
86
+ ? 'space-between'
87
+ : 'flex-start',
88
+ },
89
+ styles?.titleContainer,
90
+ ], testID: `title-${testID}`, children: [toggleElementPosition === 'left' ? toggleView : null, renderTitle ? (renderTitle(data.title)) : typeof data.title === 'string' ? (_jsx(Typography.Heading4, { style: [
91
+ { fontSize: titleFontSize, flexShrink: 1 },
92
+ styles?.titleText,
93
+ ], children: data.title })) : null, toggleElementPosition === 'right' ? toggleView : null] })), _jsx(Animated.View, { collapsable: false, layout: transition, accessibilityElementsHidden: !expanded, accessibilityState: { expanded }, "aria-hidden": !expanded, importantForAccessibility: expanded ? 'auto' : 'no-hide-descendants', pointerEvents: expanded ? 'auto' : 'none', style: [
94
+ layout.body,
95
+ {
96
+ height: expanded ? undefined : 0,
97
+ opacity: expanded ? 1 : 0,
98
+ transitionProperty: 'opacity',
99
+ transitionDuration: duration,
100
+ transitionTimingFunction: 'ease-out',
101
+ },
102
+ ], testID: `body-${testID}`, children: expanded ? (_jsx(Animated.View, { collapsable: false, entering: entering, exiting: exiting, children: data.items.map((body, index) => {
103
+ const content = renderItem ? (renderItem(body)) : typeof body === 'string' ? (_jsx(Typography.Body3, { style: [{ fontSize: itemFontSize }, styles?.itemText], children: body })) : null;
104
+ const itemStyle = [
105
+ {
106
+ backgroundColor: theme.bg.paper,
107
+ paddingVertical: vertical,
108
+ paddingHorizontal: horizontal,
109
+ },
110
+ styles?.itemContainer,
111
+ ];
112
+ // Do not wrap custom controls in a second pressable.
113
+ return onPressItem ? (_jsx(TouchableOpacity, { activeOpacity: activeOpacity, disabled: !expanded, onPress: () => onPressItem(data.title, body), style: itemStyle, children: content }, index)) : (_jsx(View, { style: itemStyle, children: content }, index));
114
+ }) })) : null })] }));
207
115
  }
208
- // Export memoized component for better performance
116
+ const layout = StyleSheet.create({
117
+ container: { overflow: 'hidden', flexDirection: 'column' },
118
+ title: { flexDirection: 'row', alignItems: 'center' },
119
+ body: { overflow: 'hidden' },
120
+ });
209
121
  export default React.memo(AccordionItem);
@@ -1 +1 @@
1
- {"version":3,"file":"Button.d.ts","sourceRoot":"","sources":["../../../../src/components/uis/Button/Button.tsx"],"names":[],"mappings":"AAAA,OAAc,EAAuB,KAAK,YAAY,EAAC,MAAM,OAAO,CAAC;AACrE,OAAO,KAAK,EACV,MAAM,EACN,SAAS,EACT,SAAS,EACT,uBAAuB,EACvB,SAAS,EACV,MAAM,cAAc,CAAC;AAStB,OAAO,KAAK,OAAO,MAAM,cAAc,CAAC;AAGxC,MAAM,MAAM,UAAU,GAAG,MAAM,GAAG,OAAO,GAAG,UAAU,CAAC;AACvD,MAAM,MAAM,eAAe,GACvB,SAAS,GACT,WAAW,GACX,SAAS,GACT,QAAQ,GACR,SAAS,GACT,MAAM,GACN,OAAO,CAAC;AACZ,MAAM,MAAM,cAAc,GAAG,OAAO,GAAG,QAAQ,GAAG,OAAO,GAAG,MAAM,CAAC;AAEnE,MAAM,MAAM,KAAK,GAAG;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,KAAK,CAAC,EAAE,eAAe,CAAC;IACxB,IAAI,CAAC,EAAE,cAAc,CAAC;IACtB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,cAAc,CAAC,EAAE,YAAY,CAAC;IAC9B,IAAI,CAAC,EAAE,MAAM,GAAG,YAAY,CAAC;IAC7B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B,UAAU,CAAC,EAAE,YAAY,CAAC;IAC1B,KAAK,CAAC,EAAE,SAAS,CAAC,IAAI,CAAC,SAAS,EAAE,cAAc,GAAG,SAAS,CAAC,CAAC,CAAC;IAC/D,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,uBAAuB,CAAC,SAAS,CAAC,CAAC;IAC7C,aAAa,CAAC,EAAE,uBAAuB,CAAC,eAAe,CAAC,CAAC;IACzD,uBAAuB,CAAC,EAAE,IAAI,CAC5B,uBAAuB,EACvB,SAAS,GAAG,eAAe,GAAG,OAAO,CACtC,CAAC;IACF,OAAO,CAAC,EAAE,IAAI,GAAG,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;IAC7C,cAAc,CAAC,EAAE,OAAO,CAAC,mBAAmB,CAAC;IAC7C,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B,CAAC;AAEF,KAAK,MAAM,GAAG;IACZ,SAAS,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IACjC,OAAO,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAC/B,OAAO,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAC/B,IAAI,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAC5B,QAAQ,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAChC,YAAY,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IACpC,OAAO,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;CAChC,CAAC;AAkKF,wBAAgB,MAAM,CAAC,EACrB,MAAM,EACN,IAAc,EACd,KAAiB,EACjB,IAAe,EACf,QAAQ,EACR,OAAe,EACf,cAAc,EACd,IAAI,EACJ,YAAY,EACZ,UAAU,EACV,KAAK,EACL,MAAM,EACN,OAAO,EACP,aAAmB,EACnB,uBAAuB,EACvB,YAAgB,EAChB,YAAY,EACZ,OAAgD,EAChD,cAAc,EACd,kBAAkB,GACnB,EAAE,KAAK,GAAG,YAAY,CA0MtB;wBAGoC,OAAO,MAAM;AAAlD,wBAAmD"}
1
+ {"version":3,"file":"Button.d.ts","sourceRoot":"","sources":["../../../../src/components/uis/Button/Button.tsx"],"names":[],"mappings":"AAAA,OAAc,EAAuB,KAAK,YAAY,EAAC,MAAM,OAAO,CAAC;AACrE,OAAO,KAAK,EACV,MAAM,EAEN,SAAS,EACT,SAAS,EACT,uBAAuB,EACvB,SAAS,EACV,MAAM,cAAc,CAAC;AAUtB,OAAO,KAAK,OAAO,MAAM,cAAc,CAAC;AAGxC,MAAM,MAAM,UAAU,GAAG,MAAM,GAAG,OAAO,GAAG,UAAU,CAAC;AACvD,MAAM,MAAM,eAAe,GACvB,SAAS,GACT,WAAW,GACX,SAAS,GACT,QAAQ,GACR,SAAS,GACT,MAAM,GACN,OAAO,CAAC;AACZ,MAAM,MAAM,cAAc,GAAG,OAAO,GAAG,QAAQ,GAAG,OAAO,GAAG,MAAM,CAAC;AAEnE,MAAM,MAAM,KAAK,GAAG;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,KAAK,CAAC,EAAE,eAAe,CAAC;IACxB,IAAI,CAAC,EAAE,cAAc,CAAC;IACtB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,cAAc,CAAC,EAAE,YAAY,CAAC;IAC9B,IAAI,CAAC,EAAE,MAAM,GAAG,YAAY,CAAC;IAC7B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B,UAAU,CAAC,EAAE,YAAY,CAAC;IAC1B,KAAK,CAAC,EAAE,SAAS,CAAC,IAAI,CAAC,SAAS,EAAE,cAAc,GAAG,SAAS,CAAC,CAAC,CAAC;IAC/D,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,uBAAuB,CAAC,SAAS,CAAC,CAAC;IAC7C,aAAa,CAAC,EAAE,uBAAuB,CAAC,eAAe,CAAC,CAAC;IACzD,uBAAuB,CAAC,EAAE,IAAI,CAC5B,uBAAuB,EACvB,SAAS,GAAG,eAAe,GAAG,OAAO,CACtC,CAAC;IACF,OAAO,CAAC,EAAE,IAAI,GAAG,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;IAC7C,cAAc,CAAC,EAAE,OAAO,CAAC,mBAAmB,CAAC;IAC7C,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B,CAAC;AAEF,KAAK,MAAM,GAAG;IACZ,SAAS,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IACjC,OAAO,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAC/B,OAAO,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAC/B,IAAI,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAC5B,QAAQ,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAChC,YAAY,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IACpC,OAAO,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;CAChC,CAAC;AAkKF,wBAAgB,MAAM,CAAC,EACrB,MAAM,EACN,IAAc,EACd,KAAiB,EACjB,IAAe,EACf,QAAQ,EACR,OAAe,EACf,cAAc,EACd,IAAI,EACJ,YAAY,EACZ,UAAU,EACV,KAAK,EACL,MAAM,EACN,OAAO,EACP,aAAmB,EACnB,uBAAuB,EACvB,YAAgB,EAChB,YAAY,EACZ,OAAgD,EAChD,cAAc,EACd,kBAAkB,GACnB,EAAE,KAAK,GAAG,YAAY,CA2OtB;wBAGoC,OAAO,MAAM;AAAlD,wBAAmD"}
@@ -1,11 +1,12 @@
1
1
  import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import React, { useCallback, useMemo } from 'react';
3
- import { TouchableHighlight, View } from 'react-native';
3
+ import { Platform, TouchableHighlight, View } from 'react-native';
4
4
  import { styled, css } from 'kstyled';
5
5
  import { useTheme } from '../../../providers/ThemeProvider';
6
6
  import { cloneElemWithDefaultColors } from '../../../utils/guards';
7
7
  import { LoadingIndicator } from '../LoadingIndicator/LoadingIndicator';
8
8
  import { Typography } from '../Typography/Typography';
9
+ import { CustomPressable } from '../CustomPressable/CustomPressable';
9
10
  import * as Haptics from 'expo-haptics';
10
11
  import { useHoverState } from '../../../hooks/useHoverState';
11
12
  const ButtonContainer = styled.View `
@@ -162,7 +163,9 @@ export function Button({ testID, type = 'solid', color = 'primary', size = 'medi
162
163
  element: startElement,
163
164
  backgroundColor: viewStyle?.backgroundColor,
164
165
  color: textStyle?.color,
165
- }), !text || typeof text === 'string' ? (_jsx(Typography.Body2, { style: compositeStyles.text, children: text })) : (text), cloneElemWithDefaultColors({
166
+ }), !text || typeof text === 'string' ? (
167
+ // Keep command labels on one line during Android intrinsic remeasurement.
168
+ _jsx(Typography.Body2, { numberOfLines: 1, style: compositeStyles.text, children: text })) : (text), cloneElemWithDefaultColors({
166
169
  element: endElement,
167
170
  backgroundColor: viewStyle?.backgroundColor,
168
171
  color: textStyle?.color,
@@ -175,7 +178,7 @@ export function Button({ testID, type = 'solid', color = 'primary', size = 'medi
175
178
  textStyle?.color,
176
179
  ]);
177
180
  // Memoize container renderer
178
- const renderContainer = useCallback(({ children, loadingView, }) => (_jsxs(ButtonContainer, { "$disabled": innerDisabled, "$size": size, style: [
181
+ const renderContainer = useCallback(({ children, loadingView, }) => (_jsxs(ButtonContainer, { collapsable: false, "$disabled": innerDisabled, "$size": size, style: [
179
182
  hovered && !innerDisabled && compositeStyles.hovered,
180
183
  compositeStyles.container,
181
184
  type === 'text' &&
@@ -184,7 +187,7 @@ export function Button({ testID, type = 'solid', color = 'primary', size = 'medi
184
187
  `,
185
188
  innerDisabled && compositeStyles.disabled,
186
189
  !!borderRadius && { borderRadius },
187
- ], testID: loading ? 'loading-view' : 'button-container', "$type": type, children: [_jsx(View, { collapsable: false, style: compositeStyles.content, children: children }), _jsx(View, { style: compositeStyles.loading, children: loading ? loadingView : null })] })), [
190
+ ], testID: loading ? 'loading-view' : 'button-container', "$type": type, children: [_jsx(View, { collapsable: false, style: compositeStyles.content, children: children }), _jsx(View, { collapsable: false, style: compositeStyles.loading, children: loading ? loadingView : null })] })), [
188
191
  innerDisabled,
189
192
  size,
190
193
  compositeStyles.container,
@@ -193,6 +196,7 @@ export function Button({ testID, type = 'solid', color = 'primary', size = 'medi
193
196
  compositeStyles.content,
194
197
  compositeStyles.loading,
195
198
  hovered,
199
+ borderRadius,
196
200
  type,
197
201
  loading,
198
202
  ]);
@@ -209,8 +213,20 @@ export function Button({ testID, type = 'solid', color = 'primary', size = 'medi
209
213
  style,
210
214
  css `
211
215
  border-radius: ${borderRadius}px;
216
+ overflow: hidden;
212
217
  `,
213
218
  ], [style, borderRadius, type]);
219
+ if (Platform.OS === 'android') {
220
+ return (_jsx(CustomPressable, { ...touchableHighlightProps, accessibilityLabel: accessibilityLabel ?? (typeof text === 'string' ? text : undefined), accessibilityRole: "button", accessibilityState: {
221
+ ...touchableHighlightProps?.accessibilityState,
222
+ busy: loading,
223
+ disabled: innerDisabled || loading,
224
+ }, disabled: innerDisabled || loading, hitSlop: hitSlop, onPress: handlePress, style: buttonStyles, testID: testID, android_ripple: {
225
+ color: touchableHighlightProps?.underlayColor ?? theme.role.underlay,
226
+ foreground: true,
227
+ borderless: false,
228
+ }, children: renderContainer({ children: ChildView, loadingView: LoadingView }) }));
229
+ }
214
230
  return (_jsx(TouchableHighlight, { accessibilityLabel: accessibilityLabel ?? (typeof text === 'string' ? text : undefined), accessibilityRole: "button", "aria-busy": loading, "aria-disabled": innerDisabled || loading || !onPress, activeOpacity: activeOpacity, delayPressIn: 30, disabled: innerDisabled || loading || !onPress, hitSlop: hitSlop, onPress: handlePress, style: buttonStyles, testID: testID, underlayColor: theme.role.underlay, ...touchableHighlightProps, accessibilityState: {
215
231
  ...touchableHighlightProps?.accessibilityState,
216
232
  busy: loading,
@@ -1 +1 @@
1
- {"version":3,"file":"CustomPressable.d.ts","sourceRoot":"","sources":["../../../../src/components/uis/CustomPressable/CustomPressable.tsx"],"names":[],"mappings":"AAAA,OAAc,EAAU,KAAK,YAAY,EAAC,MAAM,OAAO,CAAC;AACxD,OAAO,KAAK,EAAC,cAAc,EAAE,SAAS,EAAE,SAAS,EAAC,MAAM,cAAc,CAAC;AAOvE,iBAAS,eAAe,CACtB,KAAK,EAAE,cAAc,GAAG;IAAC,KAAK,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAA;CAAC,GACrD,YAAY,CAyCd;wBAG6C,OAAO,eAAe;AAApE,wBAAqE;AACrE,OAAO,EAAC,eAAe,EAAC,CAAC"}
1
+ {"version":3,"file":"CustomPressable.d.ts","sourceRoot":"","sources":["../../../../src/components/uis/CustomPressable/CustomPressable.tsx"],"names":[],"mappings":"AAAA,OAAc,EAAU,KAAK,YAAY,EAAC,MAAM,OAAO,CAAC;AACxD,OAAO,KAAK,EAAC,cAAc,EAAE,SAAS,EAAE,SAAS,EAAC,MAAM,cAAc,CAAC;AAMvE,iBAAS,eAAe,CACtB,KAAK,EAAE,cAAc,GAAG;IAAC,KAAK,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAA;CAAC,GACrD,YAAY,CAgDd;wBAG6C,OAAO,eAAe;AAApE,wBAAqE;AACrE,OAAO,EAAC,eAAe,EAAC,CAAC"}
@@ -1,25 +1,29 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import React, { useMemo } from 'react';
3
- import { Pressable } from 'react-native';
4
- import { css } from 'kstyled';
3
+ import { Platform, Pressable } from 'react-native';
5
4
  import { useTheme } from '../../../providers/ThemeProvider';
6
5
  const DEFAULT_HIT_SLOP = { top: 4, bottom: 4, left: 6, right: 6 };
7
6
  function CustomPressable(props) {
8
- const { accessibilityRole = 'button', children, style, hitSlop, ...restProps } = props;
7
+ const { accessibilityRole = 'button', children, style, hitSlop, android_ripple, ...restProps } = props;
9
8
  const { theme } = useTheme();
10
- const effectiveHitSlop = useMemo(() => hitSlop || DEFAULT_HIT_SLOP, [hitSlop]);
9
+ const effectiveHitSlop = useMemo(() => hitSlop ?? DEFAULT_HIT_SLOP, [hitSlop]);
11
10
  const styleFunction = useMemo(() => ({ pressed }) => {
12
- if (pressed) {
13
- return [
14
- css `
15
- background-color: ${theme.role.underlay};
16
- `,
17
- style,
18
- ];
19
- }
11
+ // Android paints one foreground ripple, including over filled children.
12
+ // Its native outline follows the caller's shape instead of the hit slop.
13
+ if (Platform.OS === 'android')
14
+ return [style, { overflow: 'hidden' }];
15
+ if (pressed)
16
+ return [style, { opacity: 0.72 }];
20
17
  return style;
21
18
  }, [theme.role.underlay, style]);
22
- return (_jsx(Pressable, { accessibilityRole: accessibilityRole, hitSlop: effectiveHitSlop, style: styleFunction, ...restProps, children: children }));
19
+ return (_jsx(Pressable, { accessibilityRole: accessibilityRole, hitSlop: effectiveHitSlop, android_ripple: Platform.OS === 'android'
20
+ ? {
21
+ color: theme.role.underlay,
22
+ foreground: true,
23
+ borderless: false,
24
+ ...android_ripple,
25
+ }
26
+ : android_ripple, style: styleFunction, ...restProps, children: children }));
23
27
  }
24
28
  // Export memoized component for better performance
25
29
  export default React.memo(CustomPressable);
@@ -1 +1 @@
1
- {"version":3,"file":"IconButton.d.ts","sourceRoot":"","sources":["../../../../src/components/uis/IconButton/IconButton.tsx"],"names":[],"mappings":"AAAA,OAAc,EAAuB,KAAK,YAAY,EAAC,MAAM,OAAO,CAAC;AACrE,OAAO,KAAK,EAAC,SAAS,EAAE,uBAAuB,EAAE,SAAS,EAAC,MAAM,cAAc,CAAC;AAIhF,OAAO,KAAK,EAAC,QAAQ,EAAC,MAAM,cAAc,CAAC;AAK3C,OAAO,KAAK,OAAO,MAAM,cAAc,CAAC;AAGxC,KAAK,MAAM,GAAG;IACZ,SAAS,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IACjC,IAAI,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAC5B,QAAQ,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAChC,OAAO,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;CAChC,CAAC;AAEF,KAAK,UAAU,GAAG,MAAM,GAAG,OAAO,GAAG,UAAU,CAAC;AAEhD,KAAK,eAAe,GAChB,SAAS,GACT,WAAW,GACX,SAAS,GACT,QAAQ,GACR,SAAS,GACT,MAAM,GACN,OAAO,CAAC;AAEZ,KAAK,cAAc,GAAG,OAAO,GAAG,QAAQ,GAAG,OAAO,GAAG,MAAM,CAAC;AAkD5D,MAAM,MAAM,eAAe,GAAG;IAC5B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,KAAK,CAAC,EAAE,eAAe,CAAC;IACxB,IAAI,CAAC,EAAE,cAAc,GAAG,MAAM,CAAC;IAC/B,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,cAAc,CAAC,EAAE,YAAY,CAAC;IAC9B,IAAI,CAAC,EAAE,QAAQ,CAAC;IAChB,WAAW,CAAC,EAAE,YAAY,CAAC;IAC3B,KAAK,CAAC,EAAE,SAAS,CAAC,IAAI,CAAC,SAAS,EAAE,cAAc,GAAG,SAAS,CAAC,CAAC,CAAC;IAC/D,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,uBAAuB,CAAC,SAAS,CAAC,CAAC;IAC7C,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,uBAAuB,CAAC,EAAE,IAAI,CAAC,uBAAuB,EAAE,SAAS,GAAG,OAAO,CAAC,CAAC;IAC7E,cAAc,CAAC,EAAE,OAAO,CAAC,mBAAmB,CAAC;IAC7C,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B,CAAC;AAEF,wBAAgB,UAAU,CAAC,EACzB,MAAM,EACN,IAAc,EACd,KAAiB,EACjB,IAAe,EACf,QAAQ,EACR,OAAe,EACf,cAAc,EACd,IAAI,EACJ,WAAW,EACX,KAAK,EACL,MAAM,EACN,OAAO,EACP,aAAoB,EACpB,uBAAuB,EACvB,cAAc,EACd,kBAAkB,GACnB,EAAE,eAAe,GAAG,YAAY,CAwLhC;wBAGwC,OAAO,UAAU;AAA1D,wBAA2D"}
1
+ {"version":3,"file":"IconButton.d.ts","sourceRoot":"","sources":["../../../../src/components/uis/IconButton/IconButton.tsx"],"names":[],"mappings":"AAAA,OAAc,EAAuB,KAAK,YAAY,EAAC,MAAM,OAAO,CAAC;AACrE,OAAO,KAAK,EAEV,SAAS,EACT,uBAAuB,EACvB,SAAS,EACV,MAAM,cAAc,CAAC;AAItB,OAAO,KAAK,EAAC,QAAQ,EAAC,MAAM,cAAc,CAAC;AAK3C,OAAO,KAAK,OAAO,MAAM,cAAc,CAAC;AAIxC,KAAK,MAAM,GAAG;IACZ,SAAS,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IACjC,IAAI,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAC5B,QAAQ,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAChC,OAAO,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;CAChC,CAAC;AAEF,KAAK,UAAU,GAAG,MAAM,GAAG,OAAO,GAAG,UAAU,CAAC;AAEhD,KAAK,eAAe,GAChB,SAAS,GACT,WAAW,GACX,SAAS,GACT,QAAQ,GACR,SAAS,GACT,MAAM,GACN,OAAO,CAAC;AAEZ,KAAK,cAAc,GAAG,OAAO,GAAG,QAAQ,GAAG,OAAO,GAAG,MAAM,CAAC;AAkD5D,MAAM,MAAM,eAAe,GAAG;IAC5B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,KAAK,CAAC,EAAE,eAAe,CAAC;IACxB,IAAI,CAAC,EAAE,cAAc,GAAG,MAAM,CAAC;IAC/B,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,cAAc,CAAC,EAAE,YAAY,CAAC;IAC9B,IAAI,CAAC,EAAE,QAAQ,CAAC;IAChB,WAAW,CAAC,EAAE,YAAY,CAAC;IAC3B,KAAK,CAAC,EAAE,SAAS,CAAC,IAAI,CAAC,SAAS,EAAE,cAAc,GAAG,SAAS,CAAC,CAAC,CAAC;IAC/D,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,uBAAuB,CAAC,SAAS,CAAC,CAAC;IAC7C,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,uBAAuB,CAAC,EAAE,IAAI,CAAC,uBAAuB,EAAE,SAAS,GAAG,OAAO,CAAC,CAAC;IAC7E,cAAc,CAAC,EAAE,OAAO,CAAC,mBAAmB,CAAC;IAC7C,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B,CAAC;AAEF,wBAAgB,UAAU,CAAC,EACzB,MAAM,EACN,IAAc,EACd,KAAiB,EACjB,IAAe,EACf,QAAQ,EACR,OAAe,EACf,cAAc,EACd,IAAI,EACJ,WAAW,EACX,KAAK,EACL,MAAM,EACN,OAAO,EACP,aAAoB,EACpB,uBAAuB,EACvB,cAAc,EACd,kBAAkB,GACnB,EAAE,eAAe,GAAG,YAAY,CAqNhC;wBAGwC,OAAO,UAAU;AAA1D,wBAA2D"}
@@ -1,16 +1,17 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import React, { useCallback, useMemo } from 'react';
3
- import { TouchableHighlight, View } from 'react-native';
3
+ import { Platform, TouchableHighlight, View } from 'react-native';
4
4
  import { css } from 'kstyled';
5
5
  import { Icon } from '../Icon/Icon';
6
6
  import { LoadingIndicator } from '../LoadingIndicator/LoadingIndicator';
7
7
  import { useTheme } from '../../../providers/ThemeProvider';
8
8
  import * as Haptics from 'expo-haptics';
9
9
  import { useHoverState } from '../../../hooks/useHoverState';
10
+ import { CustomPressable } from '../CustomPressable/CustomPressable';
10
11
  // Memoized styles calculation function
11
12
  const ButtonStyles = ({ theme, type, color, loading, disabled, }) => {
12
13
  const isDisabled = disabled || loading;
13
- let backgroundColor = theme.bg.basic;
14
+ let backgroundColor = 'transparent';
14
15
  let borderColor = 'transparent';
15
16
  let iconColor = theme.text.basic;
16
17
  if (type === 'solid') {
@@ -137,6 +138,13 @@ export function IconButton({ testID, type = 'solid', color = 'primary', size = '
137
138
  hovered && !disabled && compositeStyles.hovered,
138
139
  disabled && compositeStyles.disabled,
139
140
  ], [borderRadiusStr, compositeStyles, hovered, disabled]);
141
+ if (Platform.OS === 'android') {
142
+ return (_jsx(View, { style: containerStyles, children: _jsx(CustomPressable, { ...touchableHighlightProps, accessibilityLabel: accessibilityLabel ?? icon, accessibilityRole: "button", accessibilityState: {
143
+ ...touchableHighlightProps?.accessibilityState,
144
+ busy: loading,
145
+ disabled: !!disabled || loading,
146
+ }, disabled: disabled || loading, onPress: handlePress, style: { borderRadius: 99 }, testID: testID, children: _jsx(View, { collapsable: false, style: innerContainerStyles, testID: loading ? 'loading-view' : 'button-container', children: loading ? LoadingView : IconView }) }) }));
147
+ }
140
148
  return (_jsx(View, { style: containerStyles, children: _jsx(TouchableHighlight, { accessibilityLabel: accessibilityLabel ?? icon, accessibilityRole: "button", "aria-busy": loading, "aria-disabled": !!disabled || loading, activeOpacity: activeOpacity, delayPressIn: 50, disabled: disabled || loading, onPress: handlePress, style: css `
141
149
  border-radius: ${borderRadiusStr};
142
150
  `, testID: testID, underlayColor: theme.role.underlay, ...touchableHighlightProps, accessibilityState: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cpk-ui",
3
- "version": "0.8.0-beta.4",
3
+ "version": "0.8.0-beta.5",
4
4
  "main": "index",
5
5
  "react-native": "index",
6
6
  "module": "index",