@idealyst/components 1.2.16 → 1.2.18

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@idealyst/components",
3
- "version": "1.2.16",
3
+ "version": "1.2.18",
4
4
  "description": "Shared component library for React and React Native",
5
5
  "documentation": "https://github.com/IdealystIO/idealyst-framework/tree/main/packages/components#readme",
6
6
  "readme": "README.md",
@@ -56,7 +56,7 @@
56
56
  "publish:npm": "npm publish"
57
57
  },
58
58
  "peerDependencies": {
59
- "@idealyst/theme": "^1.2.16",
59
+ "@idealyst/theme": "^1.2.18",
60
60
  "@mdi/js": ">=7.0.0",
61
61
  "@mdi/react": ">=1.0.0",
62
62
  "@react-native-vector-icons/common": ">=12.0.0",
@@ -106,7 +106,7 @@
106
106
  }
107
107
  },
108
108
  "devDependencies": {
109
- "@idealyst/theme": "^1.2.16",
109
+ "@idealyst/theme": "^1.2.18",
110
110
  "@idealyst/tooling": "^1.2.4",
111
111
  "@mdi/react": "^1.6.1",
112
112
  "@types/react": "^19.1.0",
@@ -92,4 +92,15 @@ export const viewStyles = defineStyle('View', (theme: Theme) => ({
92
92
  boxSizing: 'border-box',
93
93
  },
94
94
  }),
95
+ // Web-only: Wrapper for scrollable view
96
+ scrollableWrapper: {
97
+ _web: {
98
+ display: 'flex',
99
+ flexDirection: 'column',
100
+ flex: 1,
101
+ position: 'relative',
102
+ boxSizing: 'border-box',
103
+ minHeight: 0, // Important for flex children to allow shrinking
104
+ },
105
+ },
95
106
  }));
@@ -47,6 +47,8 @@ const View = forwardRef<HTMLDivElement, ViewProps>(({
47
47
  // Call style as function to get theme-reactive styles
48
48
  /** @ts-ignore */
49
49
  const webProps = getWebProps((viewStyles.view as any)({}));
50
+ /** @ts-ignore */
51
+ const wrapperWebProps = getWebProps(viewStyles.scrollableWrapper);
50
52
 
51
53
  const mergedRef = useMergeRefs(ref, webProps.ref);
52
54
 
@@ -54,7 +56,7 @@ const View = forwardRef<HTMLDivElement, ViewProps>(({
54
56
  // Wrapper: sizing and margin (positioning in parent layout)
55
57
  // Content: absolutely positioned with overflow:auto, visual styles (padding, background, border)
56
58
  if (scrollable) {
57
- // Extract layout/sizing styles for the wrapper, visual styles go to content
59
+ // Split user styles: layout/sizing to wrapper, visual styles to content
58
60
  const styleObj = (style as React.CSSProperties) || {};
59
61
  const {
60
62
  // Sizing - goes to wrapper
@@ -82,49 +84,46 @@ const View = forwardRef<HTMLDivElement, ViewProps>(({
82
84
  ...contentStyles
83
85
  } = styleObj;
84
86
 
85
- const wrapperStyles: React.CSSProperties = {
86
- display: 'flex',
87
- flexDirection: 'column',
88
- position: 'relative',
89
- boxSizing: 'border-box',
90
- // If no explicit sizing, flex-grow to fill remaining space
91
- ...(width === undefined && height === undefined && flex === undefined && { flex: 1 }),
92
- // Apply sizing
93
- width,
94
- height,
95
- minWidth,
96
- minHeight: minHeight ?? 0, // Important for flex children to allow shrinking
97
- maxWidth,
98
- maxHeight,
99
- // Apply flex properties
100
- flex,
101
- flexGrow,
102
- flexShrink,
103
- flexBasis,
104
- alignSelf,
105
- // Apply margin
106
- margin,
107
- marginTop,
108
- marginRight,
109
- marginBottom,
110
- marginLeft,
111
- marginBlock,
112
- marginInline,
87
+ // Determine flex behavior:
88
+ // - If explicit flex is provided, use it
89
+ // - If explicit width/height are provided (without flex), disable flex
90
+ // - Otherwise, let Unistyles' flex:1 apply
91
+ const hasExplicitSize = width !== undefined || height !== undefined;
92
+ const flexValue = flex !== undefined ? flex : (hasExplicitSize ? 'none' : undefined);
93
+
94
+ // Only include defined values in wrapper styles
95
+ const wrapperUserStyles: React.CSSProperties = {
96
+ ...(width !== undefined && { width }),
97
+ ...(height !== undefined && { height }),
98
+ ...(minWidth !== undefined && { minWidth }),
99
+ ...(minHeight !== undefined && { minHeight }),
100
+ ...(maxWidth !== undefined && { maxWidth }),
101
+ ...(maxHeight !== undefined && { maxHeight }),
102
+ ...(flexValue !== undefined && { flex: flexValue }),
103
+ ...(flexGrow !== undefined && { flexGrow }),
104
+ ...(flexShrink !== undefined && { flexShrink }),
105
+ ...(flexBasis !== undefined && { flexBasis }),
106
+ ...(alignSelf !== undefined && { alignSelf }),
107
+ ...(margin !== undefined && { margin }),
108
+ ...(marginTop !== undefined && { marginTop }),
109
+ ...(marginRight !== undefined && { marginRight }),
110
+ ...(marginBottom !== undefined && { marginBottom }),
111
+ ...(marginLeft !== undefined && { marginLeft }),
112
+ ...(marginBlock !== undefined && { marginBlock }),
113
+ ...(marginInline !== undefined && { marginInline }),
113
114
  };
114
115
 
115
116
  return (
116
- <div style={wrapperStyles}>
117
+ <div {...wrapperWebProps} style={wrapperUserStyles}>
117
118
  <div
118
119
  {...webProps}
119
120
  style={{
120
- // Content is block (not flex) for natural scrolling behavior
121
- display: 'block',
122
- // Absolutely positioned to fill wrapper
121
+ // Critical: position/overflow must be enforced for scrolling
123
122
  position: 'absolute',
124
123
  inset: 0,
125
124
  overflow: 'auto',
126
125
  boxSizing: 'border-box',
127
- // Apply visual styles (padding, background, border, etc.)
126
+ // User's visual styles
128
127
  ...contentStyles,
129
128
  }}
130
129
  ref={mergedRef}
@@ -165,6 +165,50 @@ export const ViewExamples = () => {
165
165
  </View>
166
166
  </View>
167
167
  </View>
168
+
169
+ {/* Scrollable with Flex Example */}
170
+ <View gap="md">
171
+ <Text typography="subtitle1">Scrollable with Flex</Text>
172
+ <Text typography="body2" color="secondary">
173
+ 200x300px container with 100px header and flex:1 scrollable area
174
+ </Text>
175
+ <View
176
+ border="thin"
177
+ radius="md"
178
+ style={{ width: 200, height: 300 }}
179
+ >
180
+ {/* Fixed 100px header */}
181
+ <View
182
+ background="tertiary"
183
+ padding="sm"
184
+ style={{ height: 100, justifyContent: 'center', alignItems: 'center' }}
185
+ >
186
+ <Text typography="subtitle2">Header (100px)</Text>
187
+ </View>
188
+ {/* Flex scrollable content */}
189
+ <View
190
+ scrollable
191
+ background="secondary"
192
+ padding="md"
193
+ style={{ flex: 1 }}
194
+ >
195
+ <View>
196
+ <Text typography="body2">Scrollable content below header</Text>
197
+ <Text typography="body2">Line 2</Text>
198
+ <Text typography="body2">Line 3</Text>
199
+ <Text typography="body2">Line 4</Text>
200
+ <Text typography="body2">Line 5</Text>
201
+ <Text typography="body2">Line 6</Text>
202
+ <Text typography="body2">Line 7</Text>
203
+ <Text typography="body2">Line 8</Text>
204
+ <Text typography="body2">Line 9</Text>
205
+ <Text typography="body2">Line 10</Text>
206
+ <Text typography="body2">Line 11</Text>
207
+ <Text typography="body2">Line 12: End</Text>
208
+ </View>
209
+ </View>
210
+ </View>
211
+ </View>
168
212
  </View>
169
213
  </Screen>
170
214
  );