@ecohouse/ui 0.1.23 → 0.1.24

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": "@ecohouse/ui",
3
- "version": "0.1.23",
3
+ "version": "0.1.24",
4
4
  "type": "module",
5
5
  "private": false,
6
6
  "description": "Cross-platform presentation-only UI components for EcoHouse (React Native + React Native Web)",
@@ -67,9 +67,15 @@ export const SegmentedToggle = forwardRef<ComponentRef<typeof View>, SegmentedTo
67
67
  const resolvedClassName = className?.trim() || undefined;
68
68
  const setContainerRef = useMemo(() => mergeRefs(containerRef, forwardedRef), [forwardedRef]);
69
69
  const progress = useRef(new Animated.Value(selectedIndex)).current;
70
+ const [contentWidths, setContentWidths] = useState<[number, number]>([0, 0]);
70
71
  const [containerWidth, setContainerWidth] = useState(0);
71
72
  const availableOptionWidth = Math.max(0, (containerWidth - 12) / 2);
72
- const optionWidth = fullWidth ? availableOptionWidth : OPTION_MIN_WIDTH;
73
+ const widestContentWidth = Math.max(...contentWidths);
74
+ const contentBasedOptionWidth =
75
+ widestContentWidth > 0
76
+ ? Math.max(OPTION_MIN_WIDTH, widestContentWidth + OPTION_HORIZONTAL_PADDING * 2)
77
+ : 0;
78
+ const optionWidth = fullWidth ? availableOptionWidth : contentBasedOptionWidth;
73
79
  const indicatorTranslateX = progress.interpolate({
74
80
  inputRange: [0, 1],
75
81
  outputRange: [0, optionWidth + 4],
@@ -123,7 +129,7 @@ export const SegmentedToggle = forwardRef<ComponentRef<typeof View>, SegmentedTo
123
129
  ]}
124
130
  />
125
131
  ) : null}
126
- {options.map(({ value: optionValue, label, icon: Icon }) => {
132
+ {options.map(({ value: optionValue, label, icon: Icon }, index) => {
127
133
  const selected = optionValue === selectedValue;
128
134
  const iconColor = selected ? colors.primary : colors.whiteAlpha20;
129
135
  const labelColor = selected ? colors.whiteAlpha86 : colors.whiteAlpha40;
@@ -141,10 +147,21 @@ export const SegmentedToggle = forwardRef<ComponentRef<typeof View>, SegmentedTo
141
147
  styles.option,
142
148
  fullWidth
143
149
  ? styles.optionFullWidth
144
- : { width: OPTION_MIN_WIDTH, minWidth: OPTION_MIN_WIDTH },
150
+ : [styles.optionContentWidth, optionWidth > 0 && { width: optionWidth }],
145
151
  ]}
146
152
  >
147
- <View style={styles.optionContent}>
153
+ <View
154
+ onLayout={(event) => {
155
+ const nextWidth = event.nativeEvent.layout.width;
156
+ setContentWidths((currentWidths) => {
157
+ if (currentWidths[index] === nextWidth) return currentWidths;
158
+ const nextWidths: [number, number] = [currentWidths[0], currentWidths[1]];
159
+ nextWidths[index] = nextWidth;
160
+ return nextWidths;
161
+ });
162
+ }}
163
+ style={styles.optionContent}
164
+ >
148
165
  {Icon ? <Icon size={ICON_SIZE} color={iconColor} /> : null}
149
166
  <Text numberOfLines={1} style={[styles.label, { color: labelColor }]}>
150
167
  {label}
@@ -196,6 +213,9 @@ const styles = StyleSheet.create({
196
213
  flex: 1,
197
214
  minWidth: 0,
198
215
  },
216
+ optionContentWidth: {
217
+ minWidth: OPTION_MIN_WIDTH,
218
+ },
199
219
  activeIndicator: {
200
220
  position: "absolute",
201
221
  top: 4,