@idealyst/components 1.2.13 → 1.2.15

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 (95) hide show
  1. package/package.json +3 -3
  2. package/src/Accordion/Accordion.web.tsx +1 -1
  3. package/src/ActivityIndicator/ActivityIndicator.native.tsx +3 -3
  4. package/src/ActivityIndicator/ActivityIndicator.web.tsx +3 -3
  5. package/src/Alert/Alert.native.tsx +1 -1
  6. package/src/Alert/Alert.web.tsx +1 -1
  7. package/src/Avatar/Avatar.native.tsx +1 -1
  8. package/src/Badge/Badge.web.tsx +6 -2
  9. package/src/Badge/types.ts +5 -0
  10. package/src/Breadcrumb/Breadcrumb.native.tsx +20 -21
  11. package/src/Button/Button.native.tsx +3 -3
  12. package/src/Button/Button.web.tsx +5 -1
  13. package/src/Button/types.ts +5 -0
  14. package/src/Card/Card.web.tsx +4 -1
  15. package/src/Card/types.ts +5 -0
  16. package/src/Dialog/Dialog.native.tsx +3 -3
  17. package/src/Divider/Divider.web.tsx +2 -2
  18. package/src/Icon/Icon.web.tsx +2 -2
  19. package/src/Icon/types.ts +3 -0
  20. package/src/Image/Image.styles.tsx +5 -5
  21. package/src/Image/Image.web.tsx +3 -3
  22. package/src/List/List.native.tsx +1 -2
  23. package/src/List/List.web.tsx +1 -2
  24. package/src/List/ListSection.web.tsx +3 -3
  25. package/src/Menu/Menu.web.tsx +8 -10
  26. package/src/Menu/MenuItem.web.tsx +1 -1
  27. package/src/Popover/Popover.web.tsx +1 -1
  28. package/src/Pressable/Pressable.web.tsx +1 -1
  29. package/src/Progress/Progress.styles.tsx +76 -30
  30. package/src/Progress/Progress.web.tsx +13 -15
  31. package/src/SVGImage/SVGImage.web.tsx +1 -1
  32. package/src/Select/Select.web.tsx +2 -2
  33. package/src/Skeleton/Skeleton.native.tsx +3 -3
  34. package/src/Skeleton/Skeleton.web.tsx +3 -3
  35. package/src/Slider/Slider.native.tsx +2 -2
  36. package/src/Slider/Slider.styles.tsx +131 -44
  37. package/src/Slider/Slider.web.tsx +22 -22
  38. package/src/TabBar/TabBar.native.tsx +2 -2
  39. package/src/Text/Text.web.tsx +29 -3
  40. package/src/Text/types.ts +14 -1
  41. package/src/TextArea/TextArea.styles.tsx +96 -57
  42. package/src/TextArea/TextArea.web.tsx +19 -28
  43. package/src/Tooltip/Tooltip.web.tsx +3 -3
  44. package/src/Video/Video.styles.tsx +3 -3
  45. package/src/Video/Video.web.tsx +1 -1
  46. package/src/View/View.styles.tsx +2 -2
  47. package/src/View/View.web.tsx +93 -9
  48. package/src/View/types.ts +5 -1
  49. package/src/examples/ViewExamples.tsx +34 -0
  50. package/src/extensions/index.ts +0 -7
  51. package/src/hooks/useMergeRefs.ts +12 -6
  52. package/src/index.native.ts +1 -1
  53. package/src/index.ts +1 -1
  54. package/src/utils/accessibility/keyboardPatterns.ts +4 -0
  55. package/src/utils/accessibility/types.ts +5 -1
  56. package/src/utils/accessibility/useAnnounce.ts +1 -1
  57. package/src/utils/accessibility/useKeyboardNavigation.ts +1 -1
  58. package/src/utils/index.ts +0 -3
  59. package/src/utils/viewStyleProps.ts +2 -0
  60. package/src/Accordion/Accordion.styles.old.tsx +0 -298
  61. package/src/ActivityIndicator/ActivityIndicator.styles.old.tsx +0 -94
  62. package/src/Alert/Alert.styles.old.tsx +0 -209
  63. package/src/Avatar/Avatar.styles.old.tsx +0 -99
  64. package/src/Badge/Badge.styles.old.tsx +0 -157
  65. package/src/Breadcrumb/Breadcrumb.styles.old.tsx +0 -231
  66. package/src/Card/Card.styles.old.tsx +0 -160
  67. package/src/Checkbox/Checkbox.styles.old.tsx +0 -271
  68. package/src/Chip/Chip.styles.old.tsx +0 -184
  69. package/src/Dialog/Dialog.styles.old.tsx +0 -202
  70. package/src/Divider/Divider.styles.old.tsx +0 -172
  71. package/src/Icon/Icon.styles.old.tsx +0 -81
  72. package/src/Image/Image.styles.old.tsx +0 -69
  73. package/src/Input/Input.styles.old.tsx +0 -289
  74. package/src/List/List.styles.old.tsx +0 -242
  75. package/src/Menu/Menu.styles.old.tsx +0 -197
  76. package/src/Menu/MenuItem.styles.old.tsx +0 -114
  77. package/src/Popover/Popover.styles.old.tsx +0 -135
  78. package/src/Pressable/Pressable.styles.old.tsx +0 -27
  79. package/src/Progress/Progress.styles.old.tsx +0 -200
  80. package/src/RadioButton/RadioButton.styles.old.tsx +0 -175
  81. package/src/SVGImage/SVGImage.styles.old.tsx +0 -86
  82. package/src/Screen/Screen.styles.old.tsx +0 -87
  83. package/src/Select/Select.styles.old.tsx +0 -353
  84. package/src/Skeleton/Skeleton.styles.old.tsx +0 -67
  85. package/src/Slider/Slider.styles.old.tsx +0 -259
  86. package/src/Switch/Switch.styles.old.tsx +0 -203
  87. package/src/TabBar/TabBar.styles.old.tsx +0 -343
  88. package/src/Table/Table.styles.old.tsx +0 -311
  89. package/src/Text/Text.styles.old.tsx +0 -219
  90. package/src/TextArea/TextArea.styles.old.tsx +0 -213
  91. package/src/Tooltip/Tooltip.styles.old.tsx +0 -82
  92. package/src/Video/Video.styles.old.tsx +0 -51
  93. package/src/View/View.styles.old.tsx +0 -125
  94. package/src/extensions/applyExtension.ts +0 -210
  95. package/src/utils/buildSizeVariants.ts +0 -16
@@ -1,6 +1,5 @@
1
- import React, { forwardRef, useMemo } from 'react';
1
+ import React, { forwardRef } from 'react';
2
2
  import { getWebProps } from 'react-native-unistyles/web';
3
- import { useResponsiveStyle } from '@idealyst/theme';
4
3
  import { ViewProps } from './types';
5
4
  import { viewStyles } from './View.styles';
6
5
  import useMergeRefs from '../hooks/useMergeRefs';
@@ -22,12 +21,12 @@ const View = forwardRef<HTMLDivElement, ViewProps>(({
22
21
  margin,
23
22
  marginVertical,
24
23
  marginHorizontal,
25
- // Override props
26
- backgroundColor,
27
- borderRadius,
28
- borderWidth,
29
- borderColor,
30
- scrollable, // accepted but no-op on web - layout handles scrolling
24
+ // Override props (accepted but handled via style prop on web)
25
+ backgroundColor: _backgroundColor,
26
+ borderRadius: _borderRadius,
27
+ borderWidth: _borderWidth,
28
+ borderColor: _borderColor,
29
+ scrollable,
31
30
  style,
32
31
  testID,
33
32
  id,
@@ -48,9 +47,94 @@ const View = forwardRef<HTMLDivElement, ViewProps>(({
48
47
  // Call style as function to get theme-reactive styles
49
48
  /** @ts-ignore */
50
49
  const webProps = getWebProps((viewStyles.view as any)({}));
51
-
50
+
52
51
  const mergedRef = useMergeRefs(ref, webProps.ref);
53
52
 
53
+ // When scrollable, render a wrapper + content structure
54
+ // Wrapper: sizing and margin (positioning in parent layout)
55
+ // Content: absolutely positioned with overflow:auto, visual styles (padding, background, border)
56
+ if (scrollable) {
57
+ // Extract layout/sizing styles for the wrapper, visual styles go to content
58
+ const styleObj = (style as React.CSSProperties) || {};
59
+ const {
60
+ // Sizing - goes to wrapper
61
+ width,
62
+ height,
63
+ minWidth,
64
+ minHeight,
65
+ maxWidth,
66
+ maxHeight,
67
+ // Flex properties - goes to wrapper
68
+ flex,
69
+ flexGrow,
70
+ flexShrink,
71
+ flexBasis,
72
+ alignSelf,
73
+ // Margin - goes to wrapper (positioning in parent)
74
+ margin,
75
+ marginTop,
76
+ marginRight,
77
+ marginBottom,
78
+ marginLeft,
79
+ marginBlock,
80
+ marginInline,
81
+ // Everything else (padding, background, border, etc.) - goes to content
82
+ ...contentStyles
83
+ } = styleObj;
84
+
85
+ const wrapperStyles: React.CSSProperties = {
86
+ position: 'relative',
87
+ boxSizing: 'border-box',
88
+ // If no explicit sizing, flex-grow to fill remaining space
89
+ ...(width === undefined && height === undefined && flex === undefined && { flex: 1 }),
90
+ // Apply sizing
91
+ width,
92
+ height,
93
+ minWidth,
94
+ minHeight: minHeight ?? 0, // Important for flex children to allow shrinking
95
+ maxWidth,
96
+ maxHeight,
97
+ // Apply flex properties
98
+ flex,
99
+ flexGrow,
100
+ flexShrink,
101
+ flexBasis,
102
+ alignSelf,
103
+ // Apply margin
104
+ margin,
105
+ marginTop,
106
+ marginRight,
107
+ marginBottom,
108
+ marginLeft,
109
+ marginBlock,
110
+ marginInline,
111
+ };
112
+
113
+ return (
114
+ <div style={wrapperStyles}>
115
+ <div
116
+ {...webProps}
117
+ style={{
118
+ // Content is block (not flex) for natural scrolling behavior
119
+ display: 'block',
120
+ // Absolutely positioned to fill wrapper
121
+ position: 'absolute',
122
+ inset: 0,
123
+ overflow: 'auto',
124
+ boxSizing: 'border-box',
125
+ // Apply visual styles (padding, background, border, etc.)
126
+ ...contentStyles,
127
+ }}
128
+ ref={mergedRef}
129
+ id={id}
130
+ data-testid={testID}
131
+ >
132
+ {children}
133
+ </div>
134
+ </div>
135
+ );
136
+ }
137
+
54
138
  return (
55
139
  <div
56
140
  style={style as any}
package/src/View/types.ts CHANGED
@@ -87,7 +87,11 @@ export interface ViewProps extends ContainerStyleProps {
87
87
  style?: ViewStyleProp;
88
88
 
89
89
  /**
90
- * Enable scrollable content (uses ScrollView on native, overflow:auto on web)
90
+ * Enable scrollable content.
91
+ * - Native: Wraps children in a ScrollView
92
+ * - Web: Renders a wrapper + content structure where the wrapper fills available
93
+ * space (or uses explicit dimensions) and content is absolutely positioned with
94
+ * overflow:auto. Sizing/margin styles go to wrapper, visual styles to content.
91
95
  */
92
96
  scrollable?: boolean;
93
97
 
@@ -131,6 +131,40 @@ export const ViewExamples = () => {
131
131
  </View>
132
132
  </View>
133
133
  </View>
134
+
135
+ {/* Scrollable Example */}
136
+ <View gap="md">
137
+ <Text typography="subtitle1">Scrollable View</Text>
138
+ <Text typography="body2" color="secondary">
139
+ Fixed 200x200px container with scrollable content
140
+ </Text>
141
+ <View
142
+ scrollable
143
+ background="secondary"
144
+ padding="md"
145
+ radius="md"
146
+ border="thin"
147
+ style={{ width: 200, height: 200 }}
148
+ >
149
+ <View>
150
+ <Text typography="body2">Line 1: Scroll down to see more content</Text>
151
+ <Text typography="body2">Line 2</Text>
152
+ <Text typography="body2">Line 3</Text>
153
+ <Text typography="body2">Line 4</Text>
154
+ <Text typography="body2">Line 5</Text>
155
+ <Text typography="body2">Line 6</Text>
156
+ <Text typography="body2">Line 7</Text>
157
+ <Text typography="body2">Line 8</Text>
158
+ <Text typography="body2">Line 9</Text>
159
+ <Text typography="body2">Line 10</Text>
160
+ <Text typography="body2">Line 11</Text>
161
+ <Text typography="body2">Line 12</Text>
162
+ <Text typography="body2">Line 13</Text>
163
+ <Text typography="body2">Line 14</Text>
164
+ <Text typography="body2">Line 15: End of scrollable content</Text>
165
+ </View>
166
+ </View>
167
+ </View>
134
168
  </View>
135
169
  </Screen>
136
170
  );
@@ -49,13 +49,6 @@ export {
49
49
 
50
50
  // Internal API (for component stylesheets)
51
51
  export { getExtension, getReplacement } from './extendComponent';
52
- export {
53
- withExtension,
54
- withSimpleExtension,
55
- normalizeStyleFn,
56
- normalizeSimpleStyleFn,
57
- applyExtensions,
58
- } from './applyExtension';
59
52
 
60
53
  // Types
61
54
  export type {
@@ -1,14 +1,20 @@
1
1
  /**
2
- * Userful when workign with getWebProps and forwarding refs
3
- * @param refs
4
- * @returns
2
+ * Useful when working with getWebProps and forwarding refs.
3
+ * Accepts various ref types including callback refs and ref objects.
4
+ * Uses a permissive type to handle refs from different React type versions in monorepos.
5
+ * @param refs - Array of refs to merge (can include undefined values)
6
+ * @returns A ref callback that updates all provided refs
5
7
  */
6
- export default function useMergeRefs<T>(...refs: React.Ref<T>[]): React.RefCallback<T> {
7
- return (value: T) => {
8
+ export default function useMergeRefs<T>(
9
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
10
+ ...refs: any[]
11
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
12
+ ): any {
13
+ return (value: T | null) => {
8
14
  refs.forEach((ref) => {
9
15
  if (typeof ref === 'function') {
10
16
  ref(value);
11
- } else if (ref && 'current' in ref) {
17
+ } else if (ref && typeof ref === 'object' && 'current' in ref) {
12
18
  ref.current = value;
13
19
  }
14
20
  });
@@ -145,4 +145,4 @@ export type { PlatformAPI, PlatformSystem, PlatformSelectSpec } from './Platform
145
145
  // Event utilities
146
146
  export * from './utils/events';
147
147
 
148
- export type { AppTheme } from '@idealyst/theme';
148
+ export type { Theme as AppTheme } from '@idealyst/theme';
package/src/index.ts CHANGED
@@ -181,4 +181,4 @@ export type {
181
181
  SelectStyleableElements,
182
182
  } from './extensions';
183
183
 
184
- export type { AppTheme } from '@idealyst/theme';
184
+ export type { Theme as AppTheme } from '@idealyst/theme';
@@ -35,6 +35,10 @@ export const MENU_KEYS = {
35
35
  navigateVertical: ['ArrowUp', 'ArrowDown'] as const,
36
36
  /** Keys for navigating horizontal menus/menubars */
37
37
  navigateHorizontal: ['ArrowLeft', 'ArrowRight'] as const,
38
+ /** Keys for moving to next item (down or right) */
39
+ next: ['ArrowDown', 'ArrowRight'] as const,
40
+ /** Keys for moving to previous item (up or left) */
41
+ prev: ['ArrowUp', 'ArrowLeft'] as const,
38
42
  /** Keys for selecting an item */
39
43
  select: ['Enter', ' '] as const,
40
44
  /** Keys for jumping to first item */
@@ -66,7 +66,11 @@ export type AriaRole =
66
66
  | 'none'
67
67
  | 'presentation'
68
68
  | 'heading'
69
- | 'group';
69
+ | 'group'
70
+ // Additional composite/group roles
71
+ | 'radiogroup'
72
+ // React Native specific roles
73
+ | 'adjustable';
70
74
 
71
75
  /**
72
76
  * Base accessibility props shared across all components.
@@ -77,7 +77,7 @@ export function useAnnounce(options: UseAnnounceOptions = {}): UseAnnounceReturn
77
77
 
78
78
  const politeRegionRef = useRef<HTMLDivElement | null>(null);
79
79
  const assertiveRegionRef = useRef<HTMLDivElement | null>(null);
80
- const clearTimeoutRef = useRef<ReturnType<typeof setTimeout>>();
80
+ const clearTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);
81
81
 
82
82
  /**
83
83
  * Create a live region element.
@@ -103,7 +103,7 @@ export function useKeyboardNavigation({
103
103
  }: UseKeyboardNavigationOptions): UseKeyboardNavigationReturn {
104
104
  // Buffer for type-ahead search
105
105
  const searchBuffer = useRef('');
106
- const searchTimeout = useRef<ReturnType<typeof setTimeout>>();
106
+ const searchTimeout = useRef<ReturnType<typeof setTimeout> | null>(null);
107
107
 
108
108
  /**
109
109
  * Focus a specific item by index.
@@ -1,6 +1,3 @@
1
- // Size variant builder
2
- export { buildSizeVariants } from './buildSizeVariants';
3
-
4
1
  // View/container style variant builders
5
2
  export {
6
3
  buildGapVariants,
@@ -20,6 +20,8 @@ export interface BaseProps {
20
20
  export interface GapStyleProps {
21
21
  /** Gap between children (uses theme.sizes.view[size].spacing) */
22
22
  gap?: ViewStyleSize;
23
+ /** Alias for gap - spacing between children */
24
+ spacing?: ViewStyleSize;
23
25
  }
24
26
 
25
27
  /**
@@ -1,298 +0,0 @@
1
- import { StyleSheet } from 'react-native-unistyles';
2
- import { Theme, StylesheetStyles, Size } from '@idealyst/theme';
3
- import { buildSizeVariants } from '../utils/buildSizeVariants';
4
- import {
5
- buildGapVariants,
6
- buildPaddingVariants,
7
- buildPaddingVerticalVariants,
8
- buildPaddingHorizontalVariants,
9
- buildMarginVariants,
10
- buildMarginVerticalVariants,
11
- buildMarginHorizontalVariants,
12
- } from '../utils/buildViewStyleVariants';
13
- import { AccordionType } from './types';
14
- import { applyExtensions } from '../extensions/applyExtension';
15
-
16
- type AccordionSize = Size;
17
-
18
- type AccordionVariants = {
19
- size: AccordionSize;
20
- type: AccordionType;
21
- expanded: boolean;
22
- disabled: boolean;
23
- isLast: boolean;
24
- }
25
-
26
- export type ExpandedAccordionStyles = StylesheetStyles<keyof AccordionVariants>;
27
-
28
- type ItemDynamicProps = {
29
- type?: AccordionType;
30
- isLast?: boolean;
31
- };
32
-
33
- /**
34
- * Create type variants for container
35
- */
36
- function createContainerTypeVariants(theme: Theme) {
37
- return {
38
- standard: {
39
- gap: 0,
40
- },
41
- separated: {
42
- gap: 8,
43
- },
44
- bordered: {
45
- gap: 0,
46
- borderWidth: 1,
47
- borderStyle: 'solid' as const,
48
- borderColor: theme.colors.border.primary,
49
- borderRadius: 8,
50
- overflow: 'hidden' as const,
51
- },
52
- } as const;
53
- }
54
-
55
- /**
56
- * Get item styles based on type and isLast
57
- */
58
- function getItemTypeStyles(theme: Theme, type: AccordionType, isLast: boolean) {
59
- switch (type) {
60
- case 'standard':
61
- return {
62
- borderBottomWidth: isLast ? 0 : 1,
63
- borderBottomStyle: 'solid' as const,
64
- borderBottomColor: theme.colors.border.primary,
65
- };
66
- case 'separated':
67
- return {
68
- borderWidth: 1,
69
- borderStyle: 'solid' as const,
70
- borderColor: theme.colors.border.primary,
71
- borderRadius: 8,
72
- overflow: 'hidden' as const,
73
- };
74
- case 'bordered':
75
- return {
76
- borderBottomWidth: isLast ? 0 : 1,
77
- borderBottomStyle: 'solid' as const,
78
- borderBottomColor: theme.colors.border.primary,
79
- };
80
- default:
81
- return {};
82
- }
83
- }
84
-
85
- /**
86
- * Create dynamic item styles
87
- */
88
- function createItemStyles(theme: Theme) {
89
- return ({ type = 'standard', isLast = false }: ItemDynamicProps) => {
90
- const typeStyles = getItemTypeStyles(theme, type, isLast);
91
- return {
92
- display: 'flex' as const,
93
- flexDirection: 'column' as const,
94
- ...typeStyles,
95
- variants: {
96
- size: { xs: {}, sm: {}, md: {}, lg: {}, xl: {} },
97
- expanded: { true: {}, false: {} },
98
- disabled: { true: {}, false: {} },
99
- },
100
- } as const;
101
- };
102
- }
103
-
104
- /**
105
- * Create size variants for header
106
- */
107
- function createHeaderSizeVariants(theme: Theme) {
108
- return buildSizeVariants(theme, 'accordion', (size) => ({
109
- fontSize: size.headerFontSize,
110
- padding: size.headerPadding,
111
- }));
112
- }
113
-
114
- /**
115
- * Create size variants for icon
116
- */
117
- function createIconSizeVariants(theme: Theme) {
118
- return buildSizeVariants(theme, 'accordion', (size) => ({
119
- width: size.iconSize,
120
- height: size.iconSize,
121
- }));
122
- }
123
-
124
- /**
125
- * Create size variants for content inner
126
- */
127
- function createContentInnerSizeVariants(theme: Theme) {
128
- return buildSizeVariants(theme, 'accordion', (size) => ({
129
- fontSize: size.headerFontSize,
130
- padding: size.contentPadding,
131
- paddingTop: 0,
132
- }));
133
- }
134
-
135
- // Helper functions to create static styles wrapped in dynamic functions
136
- function createContainerStyles(theme: Theme) {
137
- return () => ({
138
- display: 'flex' as const,
139
- flexDirection: 'column' as const,
140
- variants: {
141
- size: { xs: {}, sm: {}, md: {}, lg: {}, xl: {} },
142
- type: createContainerTypeVariants(theme),
143
- expanded: { true: {}, false: {} },
144
- disabled: { true: {}, false: {} },
145
- isLast: { true: {}, false: {} },
146
- // Spacing variants from ContainerStyleProps
147
- gap: buildGapVariants(theme),
148
- padding: buildPaddingVariants(theme),
149
- paddingVertical: buildPaddingVerticalVariants(theme),
150
- paddingHorizontal: buildPaddingHorizontalVariants(theme),
151
- margin: buildMarginVariants(theme),
152
- marginVertical: buildMarginVerticalVariants(theme),
153
- marginHorizontal: buildMarginHorizontalVariants(theme),
154
- },
155
- });
156
- }
157
-
158
- function createHeaderStyles(theme: Theme) {
159
- return () => ({
160
- display: 'flex' as const,
161
- flexDirection: 'row' as const,
162
- alignItems: 'center' as const,
163
- justifyContent: 'space-between' as const,
164
- width: '100%' as const,
165
- backgroundColor: 'transparent' as const,
166
- color: theme.colors.text.primary,
167
- textAlign: 'left' as const,
168
- variants: {
169
- size: createHeaderSizeVariants(theme),
170
- type: { standard: {}, separated: {}, bordered: {} },
171
- expanded: {
172
- true: {
173
- fontWeight: '600' as const,
174
- },
175
- false: {
176
- fontWeight: '500' as const,
177
- },
178
- },
179
- disabled: {
180
- true: {
181
- opacity: 0.5,
182
- _web: {
183
- cursor: 'not-allowed' as const,
184
- },
185
- },
186
- false: {
187
- _web: {
188
- cursor: 'pointer' as const,
189
- _hover: {
190
- backgroundColor: theme.colors.surface.secondary,
191
- },
192
- },
193
- },
194
- },
195
- isLast: { true: {}, false: {} },
196
- } as const,
197
- _web: {
198
- border: 'none' as const,
199
- outline: 'none' as const,
200
- transition: 'background-color 0.2s ease' as const,
201
- },
202
- });
203
- }
204
-
205
- function createTitleStyles() {
206
- return () => ({
207
- flex: 1,
208
- variants: {
209
- size: { xs: {}, sm: {}, md: {}, lg: {}, xl: {} },
210
- type: { standard: {}, separated: {}, bordered: {} },
211
- expanded: { true: {}, false: {} },
212
- disabled: { true: {}, false: {} },
213
- isLast: { true: {}, false: {} },
214
- },
215
- });
216
- }
217
-
218
- function createIconStyles(theme: Theme) {
219
- return () => ({
220
- display: 'flex' as const,
221
- alignItems: 'center' as const,
222
- justifyContent: 'center' as const,
223
- marginLeft: 8,
224
- color: theme.intents.primary.primary,
225
- variants: {
226
- size: createIconSizeVariants(theme),
227
- type: { standard: {}, separated: {}, bordered: {} },
228
- expanded: {
229
- true: {
230
- _web: {
231
- transform: 'rotate(180deg)' as const,
232
- },
233
- },
234
- false: {
235
- _web: {
236
- transform: 'rotate(0deg)' as const,
237
- },
238
- },
239
- },
240
- disabled: { true: {}, false: {} },
241
- isLast: { true: {}, false: {} },
242
- },
243
- _web: {
244
- transition: 'transform 0.2s ease' as const,
245
- },
246
- });
247
- }
248
-
249
- function createContentStyles() {
250
- return () => ({
251
- overflow: 'hidden' as const,
252
- variants: {
253
- size: { xs: {}, sm: {}, md: {}, lg: {}, xl: {} },
254
- type: { standard: {}, separated: {}, bordered: {} },
255
- expanded: {
256
- true: {
257
- maxHeight: 2000,
258
- },
259
- false: {
260
- maxHeight: 0,
261
- },
262
- },
263
- disabled: { true: {}, false: {} },
264
- isLast: { true: {}, false: {} },
265
- },
266
- _web: {
267
- transition: 'height 0.15s ease, padding 0.3s ease' as const,
268
- },
269
- });
270
- }
271
-
272
- function createContentInnerStyles(theme: Theme) {
273
- return () => ({
274
- color: theme.colors.text.secondary,
275
- variants: {
276
- size: createContentInnerSizeVariants(theme),
277
- type: { standard: {}, separated: {}, bordered: {} },
278
- expanded: { true: {}, false: {} },
279
- disabled: { true: {}, false: {} },
280
- isLast: { true: {}, false: {} },
281
- },
282
- });
283
- }
284
-
285
- // Styles are inlined here instead of in @idealyst/theme because Unistyles' Babel transform on native cannot resolve function calls to extract variant structures.
286
- export const accordionStyles = StyleSheet.create((theme: Theme) => {
287
- // Apply extensions to main visual elements
288
-
289
- return applyExtensions('Accordion', theme, {container: createContainerStyles(theme),
290
- item: createItemStyles(theme),
291
- header: createHeaderStyles(theme),
292
- content: createContentStyles(),
293
- icon: createIconStyles(theme),
294
- // Additional styles (merged from return)
295
- // Minor utility styles (not extended)
296
- title: createTitleStyles()(),
297
- contentInner: createContentInnerStyles(theme)()});
298
- });
@@ -1,94 +0,0 @@
1
- import { StyleSheet } from 'react-native-unistyles';
2
- import { Theme, StylesheetStyles, Intent, Size} from '@idealyst/theme';
3
- import { buildSizeVariants } from '../utils/buildSizeVariants';
4
- import { applyExtensions } from '../extensions/applyExtension';
5
-
6
- type ActivityIndicatorSize = Size;
7
- type ActivityIndicatorIntent = Intent;
8
-
9
- type ActivityIndicatorVariants = {
10
- size: ActivityIndicatorSize;
11
- intent: ActivityIndicatorIntent;
12
- animating: boolean;
13
- }
14
-
15
- export type ExpandedActivityIndicatorStyles = StylesheetStyles<keyof ActivityIndicatorVariants>;
16
-
17
- export type ActivityIndicatorStylesheet = {
18
- container: ExpandedActivityIndicatorStyles;
19
- spinner: ExpandedActivityIndicatorStyles;
20
- }
21
-
22
- function createContainerSizeVariants(theme: Theme) {
23
- return buildSizeVariants(theme, 'activityIndicator', (size) => ({
24
- width: size.size,
25
- height: size.size,
26
- }));
27
- }
28
-
29
- function createSpinnerSizeVariants(theme: Theme) {
30
- return buildSizeVariants(theme, 'activityIndicator', (size) => ({
31
- width: size.size,
32
- height: size.size,
33
- borderWidth: size.borderWidth,
34
- }));
35
- }
36
-
37
- function getSpinnerColor(theme: Theme, intent: ActivityIndicatorIntent) {
38
- return theme.intents[intent].primary;
39
- }
40
-
41
- function createSpinnerStyles(theme: Theme) {
42
- return ({ intent }: Partial<ActivityIndicatorVariants>) => {
43
- const color = getSpinnerColor(theme, intent);
44
- return {
45
- borderRadius: 9999,
46
- borderStyle: 'solid',
47
- color,
48
- variants: {
49
- size: createSpinnerSizeVariants(theme),
50
- animating: {
51
- true: {},
52
- false: {},
53
- },
54
- },
55
- _web: {
56
- borderColor: 'transparent',
57
- borderTopColor: color,
58
- borderRightColor: color,
59
- animation: 'spin 1s linear infinite',
60
- boxSizing: 'border-box',
61
- },
62
- } as const;
63
- }
64
- }
65
-
66
- // Style creators for extension support
67
- function createContainerStyles(theme: Theme) {
68
- return () => ({
69
- alignItems: 'center' as const,
70
- justifyContent: 'center' as const,
71
- variants: {
72
- size: createContainerSizeVariants(theme),
73
- animating: {
74
- true: {
75
- opacity: 1,
76
- },
77
- false: {
78
- opacity: 0,
79
- },
80
- },
81
- },
82
- });
83
- }
84
-
85
- // Styles are inlined here instead of in @idealyst/theme because Unistyles' Babel
86
- // transform on native cannot resolve function calls to extract variant structures.
87
- // @ts-ignore - TS language server needs restart to pick up theme structure changes
88
- export const activityIndicatorStyles = StyleSheet.create((theme: Theme) => {
89
- // Apply extensions to main visual elements
90
- return applyExtensions('ActivityIndicator', theme, {
91
- container: createContainerStyles(theme),
92
- spinner: createSpinnerStyles(theme),
93
- });
94
- });