@platform-blocks/ui 0.4.0 → 0.5.0

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/lib/esm/index.js CHANGED
@@ -12056,7 +12056,7 @@ function AppShellBase(props, ref) {
12056
12056
  const breakpoint = useBreakpoint();
12057
12057
  // Determine if mobile based on breakpoint and platform
12058
12058
  const isMobile = Platform.OS !== 'web' || breakpoint === 'xs' || breakpoint === 'sm';
12059
- const headerConfig = layoutVisibility.header && !isMobile ? header : undefined;
12059
+ const headerConfig = layoutVisibility.header ? header : undefined;
12060
12060
  const navbarConfig = layoutVisibility.navbar ? navbar : undefined;
12061
12061
  const asideConfig = layoutVisibility.aside ? aside : undefined;
12062
12062
  const footerConfig = layoutVisibility.footer ? footer : undefined;
@@ -17148,9 +17148,7 @@ const createInputStyles = (theme, isRTL = false) => {
17148
17148
  ? theme.colors.error[5]
17149
17149
  : props.focused
17150
17150
  ? theme.colors.primary[5]
17151
- : props.disabled
17152
- ? theme.backgrounds.border
17153
- : 'transparent',
17151
+ : theme.backgrounds.border,
17154
17152
  // Optional focus shadow (web only) without affecting layout
17155
17153
  ...(props.focused && !props.disabled && typeof window !== 'undefined' && ((_a = theme.states) === null || _a === void 0 ? void 0 : _a.focusRing) && {
17156
17154
  boxShadow: `0 0 0 2px ${theme.states.focusRing}`,
@@ -21047,105 +21045,116 @@ const useSliderGesture = (min, max, step, restrictToTicks, ticks, disabled) => {
21047
21045
  }, [min, max, step, restrictToTicks, ticks]);
21048
21046
  return { calculateNewValue };
21049
21047
  };
21050
- const SliderTrack = ({ disabled, theme, size, orientation, activeWidth = 0, activeLeft = SLIDER_CONSTANTS.THUMB_SIZE[size] / 2, isRange = false }) => {
21048
+ const SliderTrack = ({ disabled, theme, size, orientation, activeWidth = 0, activeLeft, isRange = false, trackColor, activeTrackColor, trackStyle, activeTrackStyle, trackHeight, thumbSize, }) => {
21051
21049
  const orientationProps = getOrientationProps(orientation);
21052
- const thumbSize = SLIDER_CONSTANTS.THUMB_SIZE[size];
21053
- const trackHeight = SLIDER_CONSTANTS.TRACK_HEIGHT[size];
21054
- const baseTrackStyle = {
21050
+ const resolvedThumbSize = thumbSize !== null && thumbSize !== void 0 ? thumbSize : SLIDER_CONSTANTS.THUMB_SIZE[size];
21051
+ const resolvedTrackHeight = trackHeight !== null && trackHeight !== void 0 ? trackHeight : SLIDER_CONSTANTS.TRACK_HEIGHT[size];
21052
+ const resolvedActiveLeft = activeLeft !== null && activeLeft !== void 0 ? activeLeft : (resolvedThumbSize / 2);
21053
+ const inactiveTrackBaseStyle = {
21055
21054
  position: 'absolute',
21056
- backgroundColor: disabled ? theme.colors.gray[2] : theme.colors.gray[3],
21057
- borderRadius: trackHeight / 2,
21055
+ backgroundColor: disabled && !trackColor ? theme.colors.gray[2] : (trackColor !== null && trackColor !== void 0 ? trackColor : theme.colors.gray[3]),
21056
+ borderRadius: resolvedTrackHeight / 2,
21058
21057
  };
21059
- const activeTrackStyle = {
21058
+ const activeTrackBaseStyle = {
21060
21059
  position: 'absolute',
21061
- backgroundColor: disabled ? theme.colors.gray[4] : theme.colors.primary[5],
21062
- borderRadius: trackHeight / 2,
21060
+ backgroundColor: disabled && !activeTrackColor ? theme.colors.gray[4] : (activeTrackColor !== null && activeTrackColor !== void 0 ? activeTrackColor : theme.colors.primary[5]),
21061
+ borderRadius: resolvedTrackHeight / 2,
21063
21062
  };
21064
21063
  if (orientationProps.isVertical) {
21065
- return (jsxs(Fragment, { children: [jsx(View, { style: {
21066
- ...baseTrackStyle,
21067
- top: thumbSize / 2,
21068
- bottom: thumbSize / 2,
21069
- width: trackHeight,
21070
- left: (thumbSize - trackHeight) / 2,
21071
- } }), activeWidth > 0 && (jsx(View, { style: {
21072
- ...activeTrackStyle,
21073
- // For range sliders, use activeLeft as top position; for single sliders, start from bottom
21074
- ...(isRange ? {
21075
- top: activeLeft,
21076
- height: activeWidth,
21077
- } : {
21078
- bottom: thumbSize / 2,
21079
- height: activeWidth,
21080
- }),
21081
- width: trackHeight,
21082
- left: (thumbSize - trackHeight) / 2,
21083
- } }))] }));
21084
- }
21085
- return (jsxs(Fragment, { children: [jsx(View, { style: {
21086
- ...baseTrackStyle,
21087
- left: thumbSize / 2,
21088
- right: thumbSize / 2,
21089
- height: trackHeight,
21090
- top: (SLIDER_CONSTANTS.CONTAINER_HEIGHT - trackHeight) / 2,
21091
- } }), activeWidth > 0 && (jsx(View, { style: {
21092
- ...activeTrackStyle,
21093
- left: activeLeft,
21094
- width: activeWidth,
21095
- height: trackHeight,
21096
- top: (SLIDER_CONSTANTS.CONTAINER_HEIGHT - trackHeight) / 2,
21097
- } }))] }));
21098
- };
21099
- const SliderTicks = ({ ticks, disabled, theme, size, orientation, keyPrefix = 'tick' }) => {
21064
+ return (jsxs(Fragment, { children: [jsx(View, { style: [
21065
+ {
21066
+ ...inactiveTrackBaseStyle,
21067
+ top: resolvedThumbSize / 2,
21068
+ bottom: resolvedThumbSize / 2,
21069
+ width: resolvedTrackHeight,
21070
+ left: (resolvedThumbSize - resolvedTrackHeight) / 2,
21071
+ },
21072
+ trackStyle,
21073
+ ] }), activeWidth > 0 && (jsx(View, { style: [
21074
+ {
21075
+ ...activeTrackBaseStyle,
21076
+ ...(isRange ? {
21077
+ top: activeLeft !== null && activeLeft !== void 0 ? activeLeft : resolvedActiveLeft,
21078
+ height: activeWidth,
21079
+ } : {
21080
+ bottom: resolvedThumbSize / 2,
21081
+ height: activeWidth,
21082
+ }),
21083
+ width: resolvedTrackHeight,
21084
+ left: (resolvedThumbSize - resolvedTrackHeight) / 2,
21085
+ },
21086
+ activeTrackStyle,
21087
+ ] }))] }));
21088
+ }
21089
+ return (jsxs(Fragment, { children: [jsx(View, { style: [
21090
+ {
21091
+ ...inactiveTrackBaseStyle,
21092
+ left: resolvedThumbSize / 2,
21093
+ right: resolvedThumbSize / 2,
21094
+ height: resolvedTrackHeight,
21095
+ top: (SLIDER_CONSTANTS.CONTAINER_HEIGHT - resolvedTrackHeight) / 2,
21096
+ },
21097
+ trackStyle,
21098
+ ] }), activeWidth > 0 && (jsx(View, { style: [
21099
+ {
21100
+ ...activeTrackBaseStyle,
21101
+ left: activeLeft !== null && activeLeft !== void 0 ? activeLeft : resolvedActiveLeft,
21102
+ width: activeWidth,
21103
+ height: resolvedTrackHeight,
21104
+ top: (SLIDER_CONSTANTS.CONTAINER_HEIGHT - resolvedTrackHeight) / 2,
21105
+ },
21106
+ activeTrackStyle,
21107
+ ] }))] }));
21108
+ };
21109
+ const SliderTicks = ({ ticks, disabled, theme, size, orientation, keyPrefix = 'tick', trackHeight, thumbSize, activeTickColor, tickColor, }) => {
21100
21110
  const orientationProps = getOrientationProps(orientation);
21101
- const thumbSize = SLIDER_CONSTANTS.THUMB_SIZE[size];
21102
- const trackHeight = SLIDER_CONSTANTS.TRACK_HEIGHT[size];
21111
+ const resolvedThumbSize = thumbSize !== null && thumbSize !== void 0 ? thumbSize : SLIDER_CONSTANTS.THUMB_SIZE[size];
21112
+ const resolvedTrackHeight = trackHeight !== null && trackHeight !== void 0 ? trackHeight : SLIDER_CONSTANTS.TRACK_HEIGHT[size];
21113
+ const inactiveColor = disabled && !tickColor ? theme.colors.gray[2] : (tickColor !== null && tickColor !== void 0 ? tickColor : theme.colors.gray[4]);
21114
+ const activeColor = disabled && !activeTickColor ? theme.colors.gray[4] : (activeTickColor !== null && activeTickColor !== void 0 ? activeTickColor : theme.colors.primary[5]);
21103
21115
  if (orientationProps.isVertical) {
21104
21116
  return (jsxs(Fragment, { children: [ticks.map((tick, index) => (jsx(View, { style: {
21105
21117
  position: 'absolute',
21106
- top: thumbSize / 2 + tick.position,
21107
- left: (thumbSize - trackHeight) / 2 - 3,
21118
+ top: resolvedThumbSize / 2 + tick.position,
21119
+ left: (resolvedThumbSize - resolvedTrackHeight) / 2 - 3,
21108
21120
  height: 2,
21109
- width: trackHeight + 6,
21110
- backgroundColor: tick.isActive
21111
- ? (disabled ? theme.colors.gray[4] : theme.colors.primary[5])
21112
- : (disabled ? theme.colors.gray[2] : theme.colors.gray[4]),
21121
+ width: resolvedTrackHeight + 6,
21122
+ backgroundColor: tick.isActive ? activeColor : inactiveColor,
21113
21123
  borderRadius: 1,
21114
21124
  } }, `${keyPrefix}-${tick.value}-${index}`))), ticks.map((tick, index) => (tick.label ? (jsx(View, { style: {
21115
21125
  position: 'absolute',
21116
- top: thumbSize / 2 + tick.position - 10,
21117
- left: thumbSize + 8,
21126
+ top: resolvedThumbSize / 2 + tick.position - 10,
21127
+ left: resolvedThumbSize + 8,
21118
21128
  height: 20,
21119
21129
  justifyContent: 'center',
21120
21130
  }, children: jsx(Text, { size: "xs", children: tick.label }) }, `${keyPrefix}-label-${tick.value}-${index}`)) : null))] }));
21121
21131
  }
21122
21132
  return (jsxs(Fragment, { children: [ticks.map((tick, index) => (jsx(View, { style: {
21123
21133
  position: 'absolute',
21124
- left: thumbSize / 2 + tick.position,
21125
- top: (SLIDER_CONSTANTS.CONTAINER_HEIGHT - trackHeight) / 2 - 3,
21134
+ left: resolvedThumbSize / 2 + tick.position,
21135
+ top: (SLIDER_CONSTANTS.CONTAINER_HEIGHT - resolvedTrackHeight) / 2 - 3,
21126
21136
  width: 2,
21127
- height: trackHeight + 6,
21128
- backgroundColor: tick.isActive
21129
- ? (disabled ? theme.colors.gray[4] : theme.colors.primary[5])
21130
- : (disabled ? theme.colors.gray[2] : theme.colors.gray[4]),
21137
+ height: resolvedTrackHeight + 6,
21138
+ backgroundColor: tick.isActive ? activeColor : inactiveColor,
21131
21139
  borderRadius: 1,
21132
21140
  } }, `${keyPrefix}-${tick.value}-${index}`))), ticks.map((tick, index) => (tick.label ? (jsx(View, { style: {
21133
21141
  position: 'absolute',
21134
- left: thumbSize / 2 + tick.position - 20,
21142
+ left: resolvedThumbSize / 2 + tick.position - 20,
21135
21143
  top: SLIDER_CONSTANTS.CONTAINER_HEIGHT + 8,
21136
21144
  width: 40,
21137
21145
  alignItems: 'center',
21138
21146
  }, children: jsx(Text, { size: "xs", style: { textAlign: 'center' }, children: tick.label }) }, `${keyPrefix}-label-${tick.value}-${index}`)) : null))] }));
21139
21147
  };
21140
- const SliderThumb = ({ position, disabled, theme, size, orientation, isDragging, zIndex = 1, panHandlers }) => {
21148
+ const SliderThumb = ({ position, disabled, theme, size, orientation, isDragging, zIndex = 1, panHandlers, thumbColor, thumbStyle, thumbSize, }) => {
21141
21149
  const orientationProps = getOrientationProps(orientation);
21142
- const thumbSize = SLIDER_CONSTANTS.THUMB_SIZE[size];
21150
+ const resolvedThumbSize = thumbSize !== null && thumbSize !== void 0 ? thumbSize : SLIDER_CONSTANTS.THUMB_SIZE[size];
21151
+ const resolvedThumbColor = disabled && !thumbColor ? theme.colors.gray[4] : (thumbColor !== null && thumbColor !== void 0 ? thumbColor : theme.colors.primary[5]);
21143
21152
  const baseStyle = {
21144
21153
  position: 'absolute',
21145
- width: thumbSize,
21146
- height: thumbSize,
21147
- backgroundColor: disabled ? theme.colors.gray[4] : theme.colors.primary[5],
21148
- borderRadius: thumbSize / 2,
21154
+ width: resolvedThumbSize,
21155
+ height: resolvedThumbSize,
21156
+ backgroundColor: resolvedThumbColor,
21157
+ borderRadius: resolvedThumbSize / 2,
21149
21158
  borderWidth: 2,
21150
21159
  borderColor: 'white',
21151
21160
  boxShadow: '0 2px 4px rgba(0, 0, 0, 0.2)',
@@ -21154,36 +21163,43 @@ const SliderThumb = ({ position, disabled, theme, size, orientation, isDragging,
21154
21163
  zIndex,
21155
21164
  };
21156
21165
  if (orientationProps.isVertical) {
21157
- return (jsx(View, { style: {
21158
- ...baseStyle,
21159
- top: position,
21160
- left: 0,
21161
- }, ...panHandlers }));
21166
+ return (jsx(View, { style: [
21167
+ baseStyle,
21168
+ {
21169
+ top: position,
21170
+ left: 0,
21171
+ },
21172
+ thumbStyle,
21173
+ ], ...panHandlers }));
21162
21174
  }
21163
- return (jsx(View, { style: {
21164
- ...baseStyle,
21165
- left: position,
21166
- top: (SLIDER_CONSTANTS.CONTAINER_HEIGHT - thumbSize) / 2,
21167
- }, ...panHandlers }));
21175
+ return (jsx(View, { style: [
21176
+ baseStyle,
21177
+ {
21178
+ left: position,
21179
+ top: (SLIDER_CONSTANTS.CONTAINER_HEIGHT - resolvedThumbSize) / 2,
21180
+ },
21181
+ thumbStyle,
21182
+ ], ...panHandlers }));
21168
21183
  };
21169
21184
  const SliderLabel = ({ label }) => (jsx(View, { style: { marginBottom: 8 }, children: typeof label === 'string' ? (jsx(Text, { size: "sm", weight: "medium", children: label })) : (label) }));
21170
- const SliderValueLabel = ({ value, position, size, orientation, isCard = false }) => {
21185
+ const SliderValueLabel = ({ value, position, size, orientation, isCard = false, thumbSize, }) => {
21171
21186
  const orientationProps = getOrientationProps(orientation);
21172
- const thumbSize = SLIDER_CONSTANTS.THUMB_SIZE[size];
21187
+ const resolvedThumbSize = thumbSize !== null && thumbSize !== void 0 ? thumbSize : SLIDER_CONSTANTS.THUMB_SIZE[size];
21173
21188
  // round number to 2 decimal places for display
21174
21189
  const displayValue = typeof value === 'number' ? value.toFixed(2) : value;
21175
21190
  if (orientationProps.isVertical) {
21191
+ const verticalLabelOffset = resolvedThumbSize + 16; // keep label clear of the thumb
21176
21192
  return (jsx(View, { style: {
21177
21193
  position: 'absolute',
21178
- top: position + (thumbSize / 2) - 10,
21179
- right: thumbSize + 8,
21194
+ top: position + (resolvedThumbSize / 2) - 10,
21195
+ right: verticalLabelOffset,
21180
21196
  height: 20,
21181
21197
  justifyContent: 'center',
21182
21198
  }, children: isCard ? (jsx(Card, { p: "xs", variant: "filled", children: jsx(Text, { size: "sm", children: displayValue }) })) : (jsx(Text, { size: "sm", children: displayValue })) }));
21183
21199
  }
21184
21200
  return (jsx(View, { style: {
21185
21201
  position: 'absolute',
21186
- left: position + (thumbSize / 2) - 50,
21202
+ left: position + (resolvedThumbSize / 2) - 50,
21187
21203
  bottom: SLIDER_CONSTANTS.CONTAINER_HEIGHT - 6, // Moved closer to thumb
21188
21204
  width: 100,
21189
21205
  alignItems: 'center',
@@ -21199,9 +21215,34 @@ const SLIDER_SIZE_SCALE = {
21199
21215
  '2xl': 'lg',
21200
21216
  '3xl': 'lg',
21201
21217
  };
21218
+ const resolvePaletteColor = (themeColors, scheme) => {
21219
+ if (!scheme || typeof scheme !== 'string') {
21220
+ return undefined;
21221
+ }
21222
+ const palette = themeColors[scheme];
21223
+ if (Array.isArray(palette)) {
21224
+ return palette;
21225
+ }
21226
+ return undefined;
21227
+ };
21228
+ const resolveSliderColors = (theme, { colorScheme, trackColor, activeTrackColor, thumbColor, tickColor, activeTickColor, }) => {
21229
+ var _a, _b;
21230
+ const palette = resolvePaletteColor(theme.colors, colorScheme);
21231
+ const schemeColor = (_b = (_a = palette === null || palette === void 0 ? void 0 : palette[5]) !== null && _a !== void 0 ? _a : (typeof colorScheme === 'string' ? colorScheme : undefined)) !== null && _b !== void 0 ? _b : theme.colors.primary[5];
21232
+ const resolvedActiveTrack = activeTrackColor !== null && activeTrackColor !== void 0 ? activeTrackColor : schemeColor;
21233
+ const defaultTrackColor = theme.colorScheme === 'dark' ? theme.colors.gray[6] : theme.colors.gray[3];
21234
+ const defaultTickColor = theme.colorScheme === 'dark' ? theme.colors.gray[5] : theme.colors.gray[4];
21235
+ return {
21236
+ trackColor: trackColor !== null && trackColor !== void 0 ? trackColor : defaultTrackColor,
21237
+ activeTrackColor: resolvedActiveTrack,
21238
+ thumbColor: thumbColor !== null && thumbColor !== void 0 ? thumbColor : resolvedActiveTrack,
21239
+ tickColor: tickColor !== null && tickColor !== void 0 ? tickColor : defaultTickColor,
21240
+ activeTickColor: activeTickColor !== null && activeTickColor !== void 0 ? activeTickColor : resolvedActiveTrack,
21241
+ };
21242
+ };
21202
21243
  // Optimized Single Slider Component
21203
21244
  const Slider = factory((props, ref) => {
21204
- const { value, defaultValue = 0, onChange, min = 0, max = 100, step = 1, disabled = false, size = 'md', orientation = 'horizontal', containerSize, fullWidth = true, label, valueLabel, valueLabelAlwaysOn = false, ticks, showTicks = false, restrictToTicks = false, style, ...spacingProps } = props;
21245
+ const { value, defaultValue = 0, onChange, min = 0, max = 100, step = 1, disabled = false, size = 'md', orientation = 'horizontal', containerSize, fullWidth = true, label, valueLabel, valueLabelAlwaysOn = false, ticks, showTicks = false, restrictToTicks = false, trackColor, activeTrackColor, thumbColor, trackSize, thumbSize: thumbSizeProp, colorScheme = 'primary', trackStyle, activeTrackStyle, thumbStyle, tickColor, activeTickColor, style, ...spacingProps } = props;
21205
21246
  const theme = useTheme();
21206
21247
  const [isDragging, setIsDragging] = useState(false);
21207
21248
  // Uncontrolled internal value
@@ -21230,14 +21271,31 @@ const Slider = factory((props, ref) => {
21230
21271
  : 'md'
21231
21272
  : (resolvedSliderSize !== null && resolvedSliderSize !== void 0 ? resolvedSliderSize : 'md');
21232
21273
  const orientationProps = getOrientationProps(orientation, containerSize);
21233
- const thumbSize = SLIDER_CONSTANTS.THUMB_SIZE[sliderSize];
21274
+ const thumbSize = thumbSizeProp !== null && thumbSizeProp !== void 0 ? thumbSizeProp : SLIDER_CONSTANTS.THUMB_SIZE[sliderSize];
21275
+ const trackHeight = trackSize !== null && trackSize !== void 0 ? trackSize : SLIDER_CONSTANTS.TRACK_HEIGHT[sliderSize];
21234
21276
  // Memoized processed value
21235
21277
  const clampedValue = useSliderValue(isControlled ? value : internal, min, max, step, restrictToTicks, ticks, false);
21236
21278
  // Memoized value label handling
21279
+ const defaultValueFormatter = useCallback((val) => Math.round(val).toString(), []);
21280
+ const resolvedValueLabel = useMemo(() => {
21281
+ if (valueLabel === null)
21282
+ return null;
21283
+ if (valueLabel)
21284
+ return valueLabel;
21285
+ return defaultValueFormatter;
21286
+ }, [valueLabel, defaultValueFormatter]);
21237
21287
  const labelConfig = useMemo(() => ({
21238
- shouldShow: valueLabel !== null && (valueLabelAlwaysOn || isDragging || (Platform.OS === 'web' && isHovering)),
21239
- formatter: valueLabel || ((val) => (Number.isInteger(val) ? val.toString() : val.toFixed(2)))
21240
- }), [valueLabel, valueLabelAlwaysOn, isDragging, isHovering]);
21288
+ shouldShow: !!resolvedValueLabel && (valueLabelAlwaysOn || isDragging || (Platform.OS === 'web' && isHovering)),
21289
+ formatter: resolvedValueLabel !== null && resolvedValueLabel !== void 0 ? resolvedValueLabel : defaultValueFormatter,
21290
+ }), [resolvedValueLabel, valueLabelAlwaysOn, isDragging, isHovering, defaultValueFormatter]);
21291
+ const sliderColors = useMemo(() => resolveSliderColors(theme, {
21292
+ colorScheme,
21293
+ trackColor,
21294
+ activeTrackColor,
21295
+ thumbColor,
21296
+ tickColor,
21297
+ activeTickColor,
21298
+ }), [theme, colorScheme, trackColor, activeTrackColor, thumbColor, tickColor, activeTickColor]);
21241
21299
  // Memoized position calculations
21242
21300
  const positions = useMemo(() => {
21243
21301
  var _a, _b;
@@ -21367,6 +21425,7 @@ const Slider = factory((props, ref) => {
21367
21425
  height: fullWidth && orientation === 'vertical' ? '100%' : orientationProps.containerHeight,
21368
21426
  justifyContent: 'center',
21369
21427
  position: 'relative',
21428
+ ...(Platform.OS === 'web' && orientation === 'vertical' ? { touchAction: 'none' } : null),
21370
21429
  }, onLayout: (event) => {
21371
21430
  // When fullWidth is enabled, track the actual container dimensions
21372
21431
  if (fullWidth) {
@@ -21380,11 +21439,11 @@ const Slider = factory((props, ref) => {
21380
21439
  }, onStartShouldSetResponder: () => !isDragging, onResponderGrant: handlePress, ...(Platform.OS === 'web' && {
21381
21440
  onMouseEnter: () => setIsHovering(true),
21382
21441
  onMouseLeave: () => setIsHovering(false),
21383
- }), ...panResponder.panHandlers, children: [jsx(SliderTrack, { disabled: disabled, theme: theme, size: sliderSize, orientation: orientation, activeWidth: positions.activeLength }), jsx(SliderTicks, { ticks: allTicks, disabled: disabled, theme: theme, size: sliderSize, orientation: orientation }), jsx(SliderThumb, { position: positions.thumbPosition, disabled: disabled, theme: theme, size: sliderSize, orientation: orientation, isDragging: isDragging }), labelConfig.shouldShow && (jsx(SliderValueLabel, { value: labelConfig.formatter(clampedValue), position: positions.thumbPosition, size: sliderSize, orientation: orientation, isCard: true }))] })] }));
21442
+ }), ...panResponder.panHandlers, children: [jsx(SliderTrack, { disabled: disabled, theme: theme, size: sliderSize, orientation: orientation, activeWidth: positions.activeLength, trackColor: sliderColors.trackColor, activeTrackColor: sliderColors.activeTrackColor, trackStyle: trackStyle, activeTrackStyle: activeTrackStyle, trackHeight: trackHeight, thumbSize: thumbSize }), jsx(SliderTicks, { ticks: allTicks, disabled: disabled, theme: theme, size: sliderSize, orientation: orientation, trackHeight: trackHeight, thumbSize: thumbSize, tickColor: sliderColors.tickColor, activeTickColor: sliderColors.activeTickColor }), jsx(SliderThumb, { position: positions.thumbPosition, disabled: disabled, theme: theme, size: sliderSize, orientation: orientation, isDragging: isDragging, thumbColor: sliderColors.thumbColor, thumbStyle: thumbStyle, thumbSize: thumbSize }), labelConfig.shouldShow && (jsx(SliderValueLabel, { value: labelConfig.formatter(clampedValue), position: positions.thumbPosition, size: sliderSize, orientation: orientation, isCard: true, thumbSize: thumbSize }))] })] }));
21384
21443
  });
21385
21444
  // Optimized Range Slider Component
21386
21445
  const RangeSlider = factory((props, ref) => {
21387
- const { value = [0, 100], onChange, min = 0, max = 100, step = 1, disabled = false, size = 'md', orientation = 'horizontal', containerSize, fullWidth = true, label, valueLabel, valueLabelAlwaysOn = false, ticks, showTicks = false, restrictToTicks = false, pushOnOverlap = true, style, ...spacingProps } = props;
21446
+ const { value = [0, 100], onChange, min = 0, max = 100, step = 1, disabled = false, size = 'md', orientation = 'horizontal', containerSize, fullWidth = true, label, valueLabel, valueLabelAlwaysOn = false, ticks, showTicks = false, restrictToTicks = false, pushOnOverlap = true, trackColor, activeTrackColor, thumbColor, trackSize, thumbSize: thumbSizeProp, colorScheme = 'primary', trackStyle, activeTrackStyle, thumbStyle, tickColor, activeTickColor, style, ...spacingProps } = props;
21388
21447
  const theme = useTheme();
21389
21448
  const [dragState, setDragState] = useState({ thumb: null });
21390
21449
  const [isHovering, setIsHovering] = useState(false);
@@ -21404,8 +21463,17 @@ const RangeSlider = factory((props, ref) => {
21404
21463
  : 'md'
21405
21464
  : (rangeResolvedSliderSize !== null && rangeResolvedSliderSize !== void 0 ? rangeResolvedSliderSize : 'md');
21406
21465
  const orientationProps = getOrientationProps(orientation, containerSize);
21407
- const thumbSize = SLIDER_CONSTANTS.THUMB_SIZE[sliderSize];
21466
+ const thumbSize = thumbSizeProp !== null && thumbSizeProp !== void 0 ? thumbSizeProp : SLIDER_CONSTANTS.THUMB_SIZE[sliderSize];
21467
+ const trackHeight = trackSize !== null && trackSize !== void 0 ? trackSize : SLIDER_CONSTANTS.TRACK_HEIGHT[sliderSize];
21408
21468
  useRef(null);
21469
+ const sliderColors = useMemo(() => resolveSliderColors(theme, {
21470
+ colorScheme,
21471
+ trackColor,
21472
+ activeTrackColor,
21473
+ thumbColor,
21474
+ tickColor,
21475
+ activeTickColor,
21476
+ }), [theme, colorScheme, trackColor, activeTrackColor, thumbColor, tickColor, activeTickColor]);
21409
21477
  // Memoized processed values
21410
21478
  const [minValue, maxValue] = useSliderValue(value, min, max, step, restrictToTicks, ticks, true);
21411
21479
  // Memoized backward compatibility handling
@@ -21641,6 +21709,7 @@ const RangeSlider = factory((props, ref) => {
21641
21709
  height: fullWidth && orientation === 'vertical' ? '100%' : orientationProps.containerHeight,
21642
21710
  justifyContent: 'center',
21643
21711
  position: 'relative',
21712
+ ...(Platform.OS === 'web' && orientation === 'vertical' ? { touchAction: 'none' } : null),
21644
21713
  }, onLayout: (event) => {
21645
21714
  // When fullWidth is enabled, track the actual container dimensions
21646
21715
  if (fullWidth) {
@@ -21654,7 +21723,7 @@ const RangeSlider = factory((props, ref) => {
21654
21723
  }, onStartShouldSetResponder: () => true, onResponderGrant: handleTrackPress, ...(Platform.OS === 'web' && {
21655
21724
  onMouseEnter: () => setIsHovering(true),
21656
21725
  onMouseLeave: () => setIsHovering(false),
21657
- }), collapsable: false, children: [jsx(SliderTrack, { disabled: disabled, theme: theme, size: sliderSize, orientation: orientation, activeWidth: positions.activeWidth, activeLeft: positions.activeLeft, isRange: true }), jsx(SliderTicks, { ticks: allTicks, disabled: disabled, theme: theme, size: sliderSize, orientation: orientation, keyPrefix: "range-tick" }), jsx(SliderThumb, { position: positions.minThumbPosition, disabled: disabled, theme: theme, size: sliderSize, orientation: orientation, isDragging: dragState.thumb === 'min', zIndex: dragState.thumb === 'min' ? 10 : 1, panHandlers: minThumbPanResponder.panHandlers }), jsx(SliderThumb, { position: positions.maxThumbPosition, disabled: disabled, theme: theme, size: sliderSize, orientation: orientation, isDragging: dragState.thumb === 'max', zIndex: dragState.thumb === 'max' ? 10 : 2, panHandlers: maxThumbPanResponder.panHandlers }), labelConfig.shouldShow && (jsxs(Fragment, { children: [jsx(SliderValueLabel, { value: labelConfig.formatter(minValue, 0), position: positions.minThumbPosition, size: sliderSize, orientation: orientation, isCard: true }), jsx(SliderValueLabel, { value: labelConfig.formatter(maxValue, 1), position: positions.maxThumbPosition, size: sliderSize, orientation: orientation, isCard: true })] }))] })] }));
21726
+ }), collapsable: false, children: [jsx(SliderTrack, { disabled: disabled, theme: theme, size: sliderSize, orientation: orientation, activeWidth: positions.activeWidth, activeLeft: positions.activeLeft, isRange: true, trackColor: sliderColors.trackColor, activeTrackColor: sliderColors.activeTrackColor, trackStyle: trackStyle, activeTrackStyle: activeTrackStyle, trackHeight: trackHeight, thumbSize: thumbSize }), jsx(SliderTicks, { ticks: allTicks, disabled: disabled, theme: theme, size: sliderSize, orientation: orientation, keyPrefix: "range-tick", trackHeight: trackHeight, thumbSize: thumbSize, tickColor: sliderColors.tickColor, activeTickColor: sliderColors.activeTickColor }), jsx(SliderThumb, { position: positions.minThumbPosition, disabled: disabled, theme: theme, size: sliderSize, orientation: orientation, isDragging: dragState.thumb === 'min', zIndex: dragState.thumb === 'min' ? 10 : 1, panHandlers: minThumbPanResponder.panHandlers, thumbColor: sliderColors.thumbColor, thumbStyle: thumbStyle, thumbSize: thumbSize }), jsx(SliderThumb, { position: positions.maxThumbPosition, disabled: disabled, theme: theme, size: sliderSize, orientation: orientation, isDragging: dragState.thumb === 'max', zIndex: dragState.thumb === 'max' ? 10 : 2, panHandlers: maxThumbPanResponder.panHandlers, thumbColor: sliderColors.thumbColor, thumbStyle: thumbStyle, thumbSize: thumbSize }), labelConfig.shouldShow && (jsxs(Fragment, { children: [jsx(SliderValueLabel, { value: labelConfig.formatter(minValue, 0), position: positions.minThumbPosition, size: sliderSize, orientation: orientation, isCard: true, thumbSize: thumbSize }), jsx(SliderValueLabel, { value: labelConfig.formatter(maxValue, 1), position: positions.maxThumbPosition, size: sliderSize, orientation: orientation, isCard: true, thumbSize: thumbSize })] }))] })] }));
21658
21727
  });
21659
21728
 
21660
21729
  const clampNumber$1 = (value, min, max) => Math.min(max, Math.max(min, value));
@@ -31548,13 +31617,13 @@ function Indicator({ size = 'sm', color, borderColor, borderWidth = 1, placement
31548
31617
 
31549
31618
  const AVATAR_ALLOWED_SIZES = ['xs', 'sm', 'md', 'lg', 'xl', '2xl', '3xl'];
31550
31619
  const AVATAR_SIZE_SCALE = {
31551
- xs: { avatar: 24, badge: 6, text: 'xs' },
31552
- sm: { avatar: 32, badge: 8, text: 'xs' },
31553
- md: { avatar: 40, badge: 10, text: 'sm' },
31554
- lg: { avatar: 48, badge: 12, text: 'md' },
31555
- xl: { avatar: 64, badge: 16, text: 'lg' },
31556
- '2xl': { avatar: 80, badge: 20, text: 'xl' },
31557
- '3xl': { avatar: 96, badge: 24, text: '2xl' },
31620
+ xs: { avatar: 24, indicator: 6, text: 'xs' },
31621
+ sm: { avatar: 32, indicator: 8, text: 'xs' },
31622
+ md: { avatar: 40, indicator: 10, text: 'sm' },
31623
+ lg: { avatar: 48, indicator: 12, text: 'md' },
31624
+ xl: { avatar: 64, indicator: 16, text: 'lg' },
31625
+ '2xl': { avatar: 80, indicator: 20, text: 'xl' },
31626
+ '3xl': { avatar: 96, indicator: 24, text: '2xl' },
31558
31627
  };
31559
31628
  const BASE_AVATAR_METRICS = AVATAR_SIZE_SCALE.md;
31560
31629
  function resolveAvatarMetrics(value) {
@@ -31572,11 +31641,11 @@ function resolveAvatarMetrics(value) {
31572
31641
  }
31573
31642
  function calculateNumericMetrics$1(value) {
31574
31643
  const ratio = value / BASE_AVATAR_METRICS.avatar;
31575
- const badge = Math.max(4, Math.round(BASE_AVATAR_METRICS.badge * ratio));
31644
+ const indicator = Math.max(4, Math.round(BASE_AVATAR_METRICS.indicator * ratio));
31576
31645
  const text = pickTextSize(value);
31577
31646
  return {
31578
31647
  avatar: value,
31579
- badge,
31648
+ indicator,
31580
31649
  text,
31581
31650
  };
31582
31651
  }
@@ -31595,9 +31664,9 @@ function pickTextSize(value) {
31595
31664
  return 'sm';
31596
31665
  return 'xs';
31597
31666
  }
31598
- function Avatar({ size = 'md', src, fallback, backgroundColor, textColor = 'white', online, badgeColor, style, accessibilityLabel, label, description, gap = 8, showText = true, }) {
31667
+ function Avatar({ size = 'md', src, fallback, backgroundColor, textColor = 'white', online, indicatorColor, style, accessibilityLabel, label, description, gap = 8, showText = true, }) {
31599
31668
  const theme = useTheme();
31600
- const { avatar: avatarSize, badge: badgeSize, text: textSize } = resolveAvatarMetrics(size);
31669
+ const { avatar: avatarSize, indicator: indicatorSize, text: textSize } = resolveAvatarMetrics(size);
31601
31670
  const avatarStyle = {
31602
31671
  width: avatarSize,
31603
31672
  height: avatarSize,
@@ -31615,7 +31684,7 @@ function Avatar({ size = 'md', src, fallback, backgroundColor, textColor = 'whit
31615
31684
  width: avatarSize,
31616
31685
  height: avatarSize,
31617
31686
  borderRadius: avatarSize / 2,
31618
- }, accessibilityLabel: accessibilityLabel })) : (jsx(Text, { size: textSize, color: textColor, weight: "semibold", style: { textAlign: 'center' }, children: fallback || '?' })) }), online && (jsx(Indicator, { size: badgeSize, color: badgeColor || theme.colors.success[5], borderColor: theme.colors.gray[0], placement: "bottom-right" }))] }));
31687
+ }, accessibilityLabel: accessibilityLabel })) : (jsx(Text, { size: textSize, color: textColor, weight: "semibold", style: { textAlign: 'center' }, children: fallback || '?' })) }), online && (jsx(Indicator, { size: indicatorSize, color: indicatorColor || theme.colors.success[5], borderColor: theme.colors.gray[0], placement: "bottom-right" }))] }));
31619
31688
  if (label || description) {
31620
31689
  return (jsxs(View, { style: { flexDirection: 'row', alignItems: 'center' }, children: [content, showText && (jsxs(View, { style: { marginLeft: gap, justifyContent: 'center' }, children: [label && (typeof label === 'string' ? (jsx(Text, { size: textSize, weight: "semibold", children: label })) : label), description && (typeof description === 'string' ? (jsx(Text, { size: textSize, color: theme.colors.gray[6], children: description })) : description)] }))] }));
31621
31690
  }
@@ -33448,7 +33517,7 @@ const filterData = (data, filters, columns, searchValue, rowFeatureToggle) => {
33448
33517
  return filteredData;
33449
33518
  };
33450
33519
  // DataTable component
33451
- const DataTable = ({ id, data, columns, loading = false, error = null, emptyMessage = 'No data available', searchable = true, searchPlaceholder = 'Search...', searchValue: controlledSearchValue, onSearchChange, sortBy = [], onSortChange, filters = [], onFilterChange, pagination, onPaginationChange, selectable = false, selectedRows = [], onSelectionChange, getRowId = (_, index) => index, onRowClick, editMode = false, onEditModeChange, onCellEdit, bulkActions = [], variant = 'default', density = 'normal', height, virtual = false, style, hoverHighlight = true, enableColumnResizing = false, rowFeatureToggle, initialHiddenColumns = [], onColumnVisibilityChange, onColumnSettings, showColumnVisibilityManager = true, rowsPerPageOptions = [10, 25, 50, 100], showRowsPerPageControl = true, rowActions, actionsColumnWidth = 100, fullWidth = true,
33520
+ const DataTable = ({ id, data, columns, loading = false, error = null, emptyMessage = 'No data available', searchable = true, searchPlaceholder = 'Search...', searchValue: controlledSearchValue, onSearchChange, sortBy = [], onSortChange, filters = [], onFilterChange, pagination, onPaginationChange, selectable = false, selectedRows = [], onSelectionChange, getRowId = (_, index) => index, onRowClick, editMode = false, onEditModeChange, onCellEdit, bulkActions = [], variant = 'default', striped: stripedProp, density = 'normal', height, virtual = false, style, hoverHighlight = true, enableColumnResizing = false, rowFeatureToggle, initialHiddenColumns = [], onColumnVisibilityChange, onColumnSettings, showColumnVisibilityManager = true, rowsPerPageOptions = [10, 25, 50, 100], showRowsPerPageControl = true, rowActions, actionsColumnWidth = 100, fullWidth = true,
33452
33521
  // Border styling props
33453
33522
  rowBorderWidth, rowBorderColor, rowBorderStyle = 'solid', columnBorderWidth, columnBorderColor, columnBorderStyle = 'solid', showOuterBorder = false, outerBorderWidth = 1, outerBorderColor,
33454
33523
  // Expandable rows props
@@ -33456,6 +33525,7 @@ expandableRowRender, initialExpandedRows = [], expandedRows: controlledExpandedR
33456
33525
  const { spacingProps, otherProps } = extractSpacingProps(props);
33457
33526
  const theme = useTheme();
33458
33527
  const { isRTL } = useDirection();
33528
+ const isStriped = stripedProp !== null && stripedProp !== void 0 ? stripedProp : variant === 'striped';
33459
33529
  // Local state
33460
33530
  const [internalSearchValue, setInternalSearchValue] = useState('');
33461
33531
  const [editingCell, setEditingCell] = useState(null);
@@ -33892,7 +33962,7 @@ expandableRowRender, initialExpandedRows = [], expandedRows: controlledExpandedR
33892
33962
  const rowElement = (jsxs(Fragment, { children: [jsxs(TableTr, { selected: isSelected, onPress: () => onRowClick === null || onRowClick === void 0 ? void 0 : onRowClick(row, rowIndex), style: {
33893
33963
  backgroundColor: isSelected
33894
33964
  ? theme.colors.primary[1]
33895
- : variant === 'striped' && rowIndex % 2 === 1
33965
+ : isStriped && rowIndex % 2 === 1
33896
33966
  ? theme.colors.gray[0]
33897
33967
  : 'transparent',
33898
33968
  borderBottomWidth: rowBorderWidth || (variant === 'bordered' ? 1 : 0),
@@ -33972,7 +34042,7 @@ expandableRowRender, initialExpandedRows = [], expandedRows: controlledExpandedR
33972
34042
  borderRadius: showOuterBorder ? 8 : 0
33973
34043
  };
33974
34044
  if (loading) {
33975
- return (jsxs(View, { style: [getSpacingStyles(spacingProps), style], ...otherProps, children: [renderHeader(), jsxs(Table, { striped: variant === 'striped', withTableBorder: variant === 'bordered', withRowBorders: variant !== 'default', verticalSpacing: density === 'compact' ? 'xs' : density === 'comfortable' ? 'lg' : 'sm', fullWidth: fullWidth, children: [jsxs(TableTr, { style: { backgroundColor: theme.colors.gray[0] }, children: [selectable && (jsx(TableTh, { w: 50, children: jsx(View, { style: { width: 20, height: 20, backgroundColor: theme.colors.gray[2], borderRadius: 4 } }) })), expandableRowRender && (jsx(TableTh, { w: 50, children: jsx(View, { style: { width: 20, height: 20, backgroundColor: theme.colors.gray[2], borderRadius: 4 } }) })), visibleColumns.map(column => (jsx(TableTh, { w: column.width || columnWidths[column.key], minWidth: column.minWidth, children: jsx(View, { style: {
34045
+ return (jsxs(View, { style: [getSpacingStyles(spacingProps), style], ...otherProps, children: [renderHeader(), jsxs(Table, { striped: isStriped, withTableBorder: variant === 'bordered', withRowBorders: variant !== 'default', verticalSpacing: density === 'compact' ? 'xs' : density === 'comfortable' ? 'lg' : 'sm', fullWidth: fullWidth, children: [jsxs(TableTr, { style: { backgroundColor: theme.colors.gray[0] }, children: [selectable && (jsx(TableTh, { w: 50, children: jsx(View, { style: { width: 20, height: 20, backgroundColor: theme.colors.gray[2], borderRadius: 4 } }) })), expandableRowRender && (jsx(TableTh, { w: 50, children: jsx(View, { style: { width: 20, height: 20, backgroundColor: theme.colors.gray[2], borderRadius: 4 } }) })), visibleColumns.map(column => (jsx(TableTh, { w: column.width || columnWidths[column.key], minWidth: column.minWidth, children: jsx(View, { style: {
33976
34046
  height: 20,
33977
34047
  backgroundColor: theme.colors.gray[2],
33978
34048
  borderRadius: 4,
@@ -33994,9 +34064,9 @@ expandableRowRender, initialExpandedRows = [], expandedRows: controlledExpandedR
33994
34064
  borderColor: theme.colors.error[2]
33995
34065
  }, children: [jsx(Icon, { name: "error", size: 32, color: theme.colors.error[5], style: { marginBottom: 12 } }), jsx(Text, { variant: "h6", color: theme.colors.error[7], style: { marginBottom: 8 }, children: "Error Loading Data" }), jsx(Text, { variant: "p", colorVariant: "muted", style: { textAlign: 'center' }, children: error })] })] }));
33996
34066
  }
33997
- return (jsxs(View, { style: [getSpacingStyles(spacingProps), style], ...otherProps, children: [renderHeader(), virtual ? (jsx(View, { style: [{ width: '100%', overflow: 'hidden' }, tableBorderStyle], children: jsx(ScrollView, { horizontal: true, showsHorizontalScrollIndicator: Platform.OS === 'web', contentContainerStyle: minWidthValue ? { minWidth: minWidthValue } : undefined, children: jsxs(View, { style: { flex: 1 }, children: [jsx(Table, { striped: variant === 'striped', withTableBorder: variant === 'bordered', withRowBorders: variant !== 'default', verticalSpacing: density === 'compact' ? 'xs' : density === 'comfortable' ? 'lg' : 'sm', fullWidth: fullWidth, children: headerRow }), processedData.length === 0 ? (jsx(Table, { striped: variant === 'striped', withTableBorder: variant === 'bordered', withRowBorders: variant !== 'default', verticalSpacing: density === 'compact' ? 'xs' : density === 'comfortable' ? 'lg' : 'sm', fullWidth: fullWidth, children: emptyStateRow })) : (jsx(FlashList, { data: processedData, keyExtractor: (item, index) => String(getRowId(item, index)), renderItem: renderVirtualRow, ...flashListSizingProps, extraData: flashListExtraData, contentContainerStyle: { flexGrow: 1 }, showsVerticalScrollIndicator: Platform.OS === 'web' }))] }) }) })) : (
34067
+ return (jsxs(View, { style: [getSpacingStyles(spacingProps), style], ...otherProps, children: [renderHeader(), virtual ? (jsx(View, { style: [{ width: '100%', overflow: 'hidden' }, tableBorderStyle], children: jsx(ScrollView, { horizontal: true, showsHorizontalScrollIndicator: Platform.OS === 'web', contentContainerStyle: minWidthValue ? { minWidth: minWidthValue } : undefined, children: jsxs(View, { style: { flex: 1 }, children: [jsx(Table, { striped: isStriped, withTableBorder: variant === 'bordered', withRowBorders: variant !== 'default', verticalSpacing: density === 'compact' ? 'xs' : density === 'comfortable' ? 'lg' : 'sm', fullWidth: fullWidth, children: headerRow }), processedData.length === 0 ? (jsx(Table, { striped: isStriped, withTableBorder: variant === 'bordered', withRowBorders: variant !== 'default', verticalSpacing: density === 'compact' ? 'xs' : density === 'comfortable' ? 'lg' : 'sm', fullWidth: fullWidth, children: emptyStateRow })) : (jsx(FlashList, { data: processedData, keyExtractor: (item, index) => String(getRowId(item, index)), renderItem: renderVirtualRow, ...flashListSizingProps, extraData: flashListExtraData, contentContainerStyle: { flexGrow: 1 }, showsVerticalScrollIndicator: Platform.OS === 'web' }))] }) }) })) : (
33998
34068
  // <TableScrollContainer style={tableBorderStyle} minWidth={minWidthValue}>
33999
- jsxs(Table, { striped: variant === 'striped', withTableBorder: variant === 'bordered', withRowBorders: variant !== 'default', verticalSpacing: density === 'compact' ? 'xs' : density === 'comfortable' ? 'lg' : 'sm', fullWidth //</TableScrollContainer>={fullWidth}
34069
+ jsxs(Table, { striped: isStriped, withTableBorder: variant === 'bordered', withRowBorders: variant !== 'default', verticalSpacing: density === 'compact' ? 'xs' : density === 'comfortable' ? 'lg' : 'sm', fullWidth //</TableScrollContainer>={fullWidth}
34000
34070
  : true, children: [headerRow, processedData.length === 0 ? emptyStateRow : nonVirtualRows] })
34001
34071
  // </TableScrollContainer>
34002
34072
  ), pagination && onPaginationChange && (jsx(View, { style: {
@@ -37434,49 +37504,101 @@ const CarouselDot = memo(({ index, pageProgress, metrics, totalPages, loop, them
37434
37504
  : { marginHorizontal: metrics.margin, height: baseDotSize, justifyContent: 'center' };
37435
37505
  return (jsx(Pressable, { onPress: handlePress, accessibilityRole: "button", accessibilityLabel: `Go to slide ${index + 1}`, style: containerStyle, children: jsx(Animated.View, { style: [{ borderRadius: baseDotSize / 2 }, animatedStyle] }) }));
37436
37506
  });
37507
+ const getBreakpointName = (width) => {
37508
+ if (width >= 1200)
37509
+ return 'xl';
37510
+ if (width >= 992)
37511
+ return 'lg';
37512
+ if (width >= 768)
37513
+ return 'md';
37514
+ if (width >= 576)
37515
+ return 'sm';
37516
+ return 'xs';
37517
+ };
37518
+ const getViewportWidth = () => {
37519
+ if (Platform.OS === 'web' && typeof window !== 'undefined' && typeof window.innerWidth === 'number') {
37520
+ return window.innerWidth;
37521
+ }
37522
+ const dimensions = Dimensions.get('window');
37523
+ return typeof (dimensions === null || dimensions === void 0 ? void 0 : dimensions.width) === 'number' ? dimensions.width : 0;
37524
+ };
37437
37525
  // Optimized breakpoint hook with debouncing
37438
37526
  const useOptimizedBreakpoint = () => {
37439
- const [breakpoint, setBreakpoint] = useState('sm');
37527
+ const computeState = () => {
37528
+ const width = getViewportWidth();
37529
+ return {
37530
+ width,
37531
+ breakpoint: getBreakpointName(width),
37532
+ };
37533
+ };
37534
+ const [state, setState] = useState(computeState);
37440
37535
  useEffect(() => {
37441
37536
  let timeoutId;
37442
- const compute = () => {
37443
- const w = Platform.OS === 'web'
37444
- ? window.innerWidth
37445
- : Dimensions.get('window').width;
37446
- let newBreakpoint = 'sm';
37447
- if (w >= 1200)
37448
- newBreakpoint = 'xl';
37449
- else if (w >= 992)
37450
- newBreakpoint = 'lg';
37451
- else if (w >= 768)
37452
- newBreakpoint = 'md';
37453
- else if (w >= 576)
37454
- newBreakpoint = 'sm';
37455
- else
37456
- newBreakpoint = 'xs';
37457
- setBreakpoint(prev => prev !== newBreakpoint ? newBreakpoint : prev);
37537
+ const update = () => {
37538
+ const next = computeState();
37539
+ setState(prev => (prev.breakpoint === next.breakpoint && prev.width === next.width) ? prev : next);
37458
37540
  };
37459
- const debouncedCompute = () => {
37541
+ const debouncedUpdate = () => {
37460
37542
  clearTimeout(timeoutId);
37461
- timeoutId = setTimeout(compute, 100); // Debounce resize events
37543
+ timeoutId = setTimeout(update, 100); // Debounce resize events
37462
37544
  };
37463
- compute();
37464
- if (Platform.OS === 'web') {
37465
- window.addEventListener('resize', debouncedCompute, { passive: true });
37545
+ update();
37546
+ if (Platform.OS === 'web' && typeof window !== 'undefined') {
37547
+ window.addEventListener('resize', debouncedUpdate, { passive: true });
37466
37548
  return () => {
37467
- window.removeEventListener('resize', debouncedCompute);
37549
+ window.removeEventListener('resize', debouncedUpdate);
37468
37550
  clearTimeout(timeoutId);
37469
37551
  };
37470
37552
  }
37471
- return () => clearTimeout(timeoutId);
37553
+ const subscription = Dimensions.addEventListener('change', debouncedUpdate);
37554
+ return () => {
37555
+ subscription === null || subscription === void 0 ? void 0 : subscription.remove();
37556
+ clearTimeout(timeoutId);
37557
+ };
37472
37558
  }, []);
37473
- return breakpoint;
37559
+ return state;
37560
+ };
37561
+ const parseMediaQuery = (query) => {
37562
+ const minMatch = query.match(/min-width:\s*(\d+)px/);
37563
+ const maxMatch = query.match(/max-width:\s*(\d+)px/);
37564
+ return {
37565
+ min: minMatch ? parseInt(minMatch[1], 10) : undefined,
37566
+ max: maxMatch ? parseInt(maxMatch[1], 10) : undefined,
37567
+ };
37568
+ };
37569
+ const matchQuery = (query, width) => {
37570
+ const { min, max } = parseMediaQuery(query);
37571
+ if (min != null && width < min)
37572
+ return false;
37573
+ if (max != null && width > max)
37574
+ return false;
37575
+ return true;
37576
+ };
37577
+ const mergeBreakpointProps = (baseProps, breakpointProps, width) => {
37578
+ if (!breakpointProps)
37579
+ return baseProps;
37580
+ const sortedEntries = Object.entries(breakpointProps).sort((a, b) => {
37581
+ var _a, _b;
37582
+ const aMin = (_a = parseMediaQuery(a[0]).min) !== null && _a !== void 0 ? _a : 0;
37583
+ const bMin = (_b = parseMediaQuery(b[0]).min) !== null && _b !== void 0 ? _b : 0;
37584
+ return aMin - bMin;
37585
+ });
37586
+ let resolvedProps = { ...baseProps };
37587
+ sortedEntries.forEach(([query, value]) => {
37588
+ const shouldApply = width != null ? matchQuery(query, width) : (Platform.OS === 'web' && typeof window !== 'undefined' ? window.matchMedia(query).matches : false);
37589
+ if (shouldApply) {
37590
+ resolvedProps = { ...resolvedProps, ...value };
37591
+ }
37592
+ });
37593
+ return resolvedProps;
37474
37594
  };
37475
- const Carousel = (props) => {
37476
- const { children, orientation = 'horizontal', height = 200, w = 300, showDots = true, showArrows = true, loop = true, autoPlay = false, autoPlayInterval = 3000, itemsPerPage = 1, slideSize, slideGap, itemGap = 16, onSlideChange, style, itemStyle, arrowSize = 'md', dotSize = 'md', // currently uniform size; active expands
37595
+ const Carousel = (incomingProps) => {
37596
+ const { breakpoint, width: viewportWidth } = useOptimizedBreakpoint();
37597
+ const mergedProps = useMemo(() => mergeBreakpointProps(incomingProps, incomingProps.breakpoints, viewportWidth), [incomingProps, viewportWidth]);
37598
+ const { children, orientation = 'horizontal', height = 200, showDots = true, showArrows = true, loop = true, autoPlay = false, autoPlayInterval = 3000, itemsPerPage = 1, slidesToScroll, slideSize, slideGap, itemGap = 16, containScroll = 'trimSnaps', startIndex, align = 'start', dragFree = false, skipSnaps = true, dragThreshold, duration, breakpoints: _breakpoints, onSlideChange, style, itemStyle, arrowSize = 'md', dotSize = 'md', // currently uniform size; active expands
37477
37599
  snapToItem = true, // kept for API parity (engine handles snapping)
37478
37600
  windowSize = 0, // 0 means no virtualization
37479
- reducedMotion = false, ...rest } = props;
37601
+ reducedMotion = false, ...rest } = mergedProps;
37480
37602
  const { spacingProps, otherProps } = extractSpacingProps(rest);
37481
37603
  const spacingStyles = getSpacingStyles(spacingProps);
37482
37604
  const theme = useTheme();
@@ -37488,10 +37610,9 @@ const Carousel = (props) => {
37488
37610
  // progress holds absolute item progress (fractional, not modulo) supplied by engine
37489
37611
  const progress = useSharedValue(0);
37490
37612
  const [currentIndex, setCurrentIndex] = useState(0);
37613
+ const hasInitializedRef = useRef(false);
37491
37614
  const itemsArray = useMemo(() => React__default.Children.toArray(children), [children]);
37492
37615
  const totalItems = itemsArray.length;
37493
- // Use optimized breakpoint detection with debouncing
37494
- const breakpoint = useOptimizedBreakpoint();
37495
37616
  const resolvedGap = useMemo(() => {
37496
37617
  const raw = resolveResponsive(slideGap, breakpoint);
37497
37618
  if (raw == null)
@@ -37506,7 +37627,7 @@ const Carousel = (props) => {
37506
37627
  }, [slideGap, breakpoint, itemGap]);
37507
37628
  const isVertical = orientation === 'vertical';
37508
37629
  const containerSize = isVertical ? containerHeight : containerWidth;
37509
- const itemSize = useMemo(() => {
37630
+ const desiredItemSize = useMemo(() => {
37510
37631
  if (containerSize <= 0)
37511
37632
  return 0;
37512
37633
  const rawSize = resolveResponsive(slideSize, breakpoint);
@@ -37532,28 +37653,166 @@ const Carousel = (props) => {
37532
37653
  }
37533
37654
  return (containerSize - resolvedGap * (itemsPerPage - 1)) / itemsPerPage;
37534
37655
  }, [slideSize, breakpoint, containerSize, itemsPerPage, resolvedGap]);
37656
+ const hasLayout = isVertical ? containerHeight > 0 : containerWidth > 0;
37657
+ const baseItemsPerPage = Math.max(1, itemsPerPage);
37658
+ const slidesToScrollValue = Math.max(1, slidesToScroll !== null && slidesToScroll !== void 0 ? slidesToScroll : baseItemsPerPage);
37659
+ const containMode = containScroll === false
37660
+ ? 'none'
37661
+ : containScroll === 'keepSnaps'
37662
+ ? 'keepSnaps'
37663
+ : 'trimSnaps';
37664
+ const isDragFree = !!dragFree;
37665
+ const allowSkipSnaps = skipSnaps !== null && skipSnaps !== void 0 ? skipSnaps : true;
37666
+ const dragThresholdValue = typeof dragThreshold === 'number'
37667
+ ? Math.max(dragThreshold, 0)
37668
+ : undefined;
37669
+ const visibleSlides = useMemo(() => {
37670
+ if (!hasLayout || containerSize <= 0)
37671
+ return baseItemsPerPage;
37672
+ if (desiredItemSize <= 0)
37673
+ return baseItemsPerPage;
37674
+ const maxFit = Math.max(1, Math.floor((containerSize + resolvedGap) / (desiredItemSize + resolvedGap)));
37675
+ if (slideSize == null) {
37676
+ return Math.min(baseItemsPerPage, maxFit);
37677
+ }
37678
+ return maxFit;
37679
+ }, [hasLayout, containerSize, desiredItemSize, resolvedGap, baseItemsPerPage, slideSize]);
37680
+ const cardSize = useMemo(() => {
37681
+ if (!hasLayout)
37682
+ return desiredItemSize;
37683
+ if (visibleSlides <= 1) {
37684
+ if (desiredItemSize > 0)
37685
+ return desiredItemSize;
37686
+ return containerSize > 0 ? containerSize : desiredItemSize;
37687
+ }
37688
+ const totalGap = resolvedGap * (visibleSlides - 1);
37689
+ const available = Math.max(containerSize - totalGap, 0);
37690
+ return available / visibleSlides;
37691
+ }, [hasLayout, desiredItemSize, visibleSlides, resolvedGap, containerSize]);
37692
+ const slideExtent = useMemo(() => {
37693
+ if (!hasLayout || cardSize <= 0)
37694
+ return undefined;
37695
+ return cardSize + resolvedGap;
37696
+ }, [hasLayout, cardSize, resolvedGap]);
37697
+ const scrollStep = useMemo(() => {
37698
+ if (totalItems === 0)
37699
+ return slidesToScrollValue;
37700
+ return Math.min(slidesToScrollValue, Math.max(1, totalItems));
37701
+ }, [slidesToScrollValue, totalItems]);
37702
+ const maxScrollDistancePerSwipe = useMemo(() => {
37703
+ if (allowSkipSnaps || slideExtent == null)
37704
+ return undefined;
37705
+ return slideExtent * scrollStep;
37706
+ }, [allowSkipSnaps, slideExtent, scrollStep]);
37707
+ const lastStart = useMemo(() => Math.max(totalItems - visibleSlides, 0), [totalItems, visibleSlides]);
37708
+ const pageStartIndices = useMemo(() => {
37709
+ if (totalItems === 0)
37710
+ return [];
37711
+ if (loop) {
37712
+ const count = Math.max(1, Math.ceil(totalItems / scrollStep));
37713
+ return Array.from({ length: count }, (_, idx) => (idx * scrollStep) % totalItems);
37714
+ }
37715
+ const starts = [];
37716
+ const seen = new Set();
37717
+ const limit = containMode === 'none' ? Math.max(totalItems - 1, 0) : lastStart;
37718
+ const addStart = (value) => {
37719
+ if (!seen.has(value)) {
37720
+ seen.add(value);
37721
+ starts.push(Math.max(0, value));
37722
+ }
37723
+ };
37724
+ for (let start = 0; start <= limit; start += scrollStep) {
37725
+ const value = containMode === 'trimSnaps'
37726
+ ? Math.min(start, lastStart)
37727
+ : start;
37728
+ addStart(value);
37729
+ }
37730
+ if (containMode !== 'trimSnaps') {
37731
+ addStart(lastStart);
37732
+ }
37733
+ starts.sort((a, b) => a - b);
37734
+ return starts;
37735
+ }, [totalItems, loop, scrollStep, containMode, lastStart]);
37736
+ const pagedItems = useMemo(() => {
37737
+ if (!totalItems)
37738
+ return [];
37739
+ return pageStartIndices.map(start => {
37740
+ const group = [];
37741
+ for (let offset = 0; offset < visibleSlides; offset++) {
37742
+ const targetIndex = start + offset;
37743
+ if (loop) {
37744
+ const normalized = ((targetIndex % totalItems) + totalItems) % totalItems;
37745
+ group.push(itemsArray[normalized]);
37746
+ }
37747
+ else if (targetIndex < totalItems) {
37748
+ group.push(itemsArray[targetIndex]);
37749
+ }
37750
+ }
37751
+ return group;
37752
+ });
37753
+ }, [pageStartIndices, visibleSlides, loop, totalItems, itemsArray]);
37754
+ const totalPages = pagedItems.length;
37755
+ const normalizedStartIndex = useMemo(() => {
37756
+ if (!totalItems)
37757
+ return 0;
37758
+ const rawIndex = startIndex !== null && startIndex !== void 0 ? startIndex : 0;
37759
+ if (loop) {
37760
+ return ((rawIndex % totalItems) + totalItems) % totalItems;
37761
+ }
37762
+ return Math.max(0, Math.min(rawIndex, Math.max(totalItems - 1, 0)));
37763
+ }, [startIndex, totalItems, loop]);
37764
+ const initialPageStart = useMemo(() => {
37765
+ if (!totalItems)
37766
+ return 0;
37767
+ const base = Math.floor(normalizedStartIndex / scrollStep) * scrollStep;
37768
+ if (loop) {
37769
+ return totalItems ? base % totalItems : 0;
37770
+ }
37771
+ if (containMode === 'none') {
37772
+ return Math.min(base, Math.max(totalItems - 1, 0));
37773
+ }
37774
+ if (containMode === 'keepSnaps') {
37775
+ return Math.min(base, Math.max(totalItems - 1, 0));
37776
+ }
37777
+ return Math.min(base, lastStart);
37778
+ }, [normalizedStartIndex, scrollStep, loop, totalItems, containMode, lastStart]);
37779
+ const initialPageIndex = useMemo(() => {
37780
+ if (!pageStartIndices.length)
37781
+ return 0;
37782
+ const idx = pageStartIndices.indexOf(initialPageStart);
37783
+ return idx >= 0 ? idx : 0;
37784
+ }, [pageStartIndices, initialPageStart]);
37535
37785
  const handleLayout = useCallback((e) => {
37536
37786
  setContainerWidth(e.nativeEvent.layout.width);
37537
37787
  setContainerHeight(e.nativeEvent.layout.height);
37538
37788
  }, []);
37539
- const goTo = useCallback((index) => {
37540
- if (!carouselRef.current)
37789
+ const scrollToPage = useCallback((index, animated = true) => {
37790
+ if (!carouselRef.current || totalPages === 0)
37541
37791
  return;
37542
- if (totalItems === 0)
37543
- return;
37544
- const clamped = ((index % totalItems) + totalItems) % totalItems;
37792
+ const clamped = ((index % totalPages) + totalPages) % totalPages;
37545
37793
  const delta = clamped - currentIndex;
37546
- if (delta === 0)
37794
+ if (delta === 0) {
37795
+ if (!animated) {
37796
+ progress.value = clamped;
37797
+ setCurrentIndex(clamped);
37798
+ }
37547
37799
  return;
37548
- // For looping choose shortest path if loop enabled
37800
+ }
37549
37801
  let count = delta;
37550
37802
  if (loop) {
37551
- const alt = delta > 0 ? delta - totalItems : delta + totalItems;
37803
+ const alt = delta > 0 ? delta - totalPages : delta + totalPages;
37552
37804
  if (Math.abs(alt) < Math.abs(count))
37553
37805
  count = alt;
37554
37806
  }
37555
- carouselRef.current.scrollTo({ count, animated: true });
37556
- }, [carouselRef, totalItems, currentIndex, loop]);
37807
+ carouselRef.current.scrollTo({ count, animated });
37808
+ if (!animated) {
37809
+ progress.value = clamped;
37810
+ setCurrentIndex(clamped);
37811
+ }
37812
+ }, [carouselRef, totalPages, currentIndex, loop, progress]);
37813
+ const goTo = useCallback((index) => {
37814
+ scrollToPage(index, true);
37815
+ }, [scrollToPage]);
37557
37816
  const goPrev = useCallback(() => {
37558
37817
  if (!carouselRef.current)
37559
37818
  return;
@@ -37564,13 +37823,22 @@ const Carousel = (props) => {
37564
37823
  return;
37565
37824
  carouselRef.current.next();
37566
37825
  }, []);
37567
- const totalPages = useMemo(() => totalItems, [totalItems]);
37568
37826
  // Page progress derived directly from absolute item progress
37569
37827
  const pageProgress = useDerivedValue(() => {
37570
37828
  return progress.value;
37571
37829
  }, []);
37572
37830
  const arrowMetrics = useMemo(() => resolveCarouselArrowMetrics(arrowSize), [arrowSize]);
37573
37831
  const dotMetrics = useMemo(() => resolveCarouselDotMetrics(dotSize), [dotSize]);
37832
+ const alignJustify = useMemo(() => {
37833
+ switch (align) {
37834
+ case 'center':
37835
+ return 'center';
37836
+ case 'end':
37837
+ return 'flex-end';
37838
+ default:
37839
+ return 'flex-start';
37840
+ }
37841
+ }, [align]);
37574
37842
  // Memoized render functions to prevent unnecessary re-renders
37575
37843
  const renderDots = useMemo(() => {
37576
37844
  if (!showDots || totalPages <= 1)
@@ -37586,7 +37854,7 @@ const Carousel = (props) => {
37586
37854
  }, [showDots, totalPages, pageProgress, dotMetrics, loop, theme, goTo, isVertical, isRTL]);
37587
37855
  // Arrows
37588
37856
  const renderArrows = () => {
37589
- if (!showArrows || totalItems <= 1)
37857
+ if (!showArrows || totalPages <= 1)
37590
37858
  return null;
37591
37859
  const buttonSize = arrowMetrics.buttonSizeToken;
37592
37860
  const iconSize = arrowMetrics.iconSize;
@@ -37623,37 +37891,69 @@ const Carousel = (props) => {
37623
37891
  }, children: jsx(Button, { size: buttonSize, variant: "secondary", icon: jsx(Icon, { name: isRTL ? 'chevron-left' : 'chevron-right', size: iconSize }), onPress: goNext, radius: "full" }) })] }));
37624
37892
  };
37625
37893
  // Autoplay: if library autoPlay not sufficient for pause logic, we can just pass through for now.
37626
- const enableAutoPlay = autoPlay && totalItems > 1;
37894
+ const enableAutoPlay = autoPlay && totalPages > 1;
37895
+ useEffect(() => {
37896
+ if (!carouselRef.current || totalPages === 0 || !hasLayout)
37897
+ return;
37898
+ const controlledStart = startIndex != null;
37899
+ if (controlledStart) {
37900
+ scrollToPage(initialPageIndex, false);
37901
+ return;
37902
+ }
37903
+ if (!hasInitializedRef.current) {
37904
+ scrollToPage(initialPageIndex, false);
37905
+ hasInitializedRef.current = true;
37906
+ }
37907
+ }, [scrollToPage, initialPageIndex, startIndex, totalPages, hasLayout]);
37627
37908
  return (jsxs(View, { ref: containerRef, style: [
37628
37909
  {
37910
+ width: '100%',
37629
37911
  position: 'relative',
37630
37912
  ...(isVertical ? { flexDirection: 'row' } : {})
37631
37913
  },
37632
37914
  spacingStyles,
37633
37915
  style
37634
- ], onLayout: handleLayout, ...otherProps, children: [jsx(View, { style: { flex: 1 }, children: itemSize > 0 && (jsx(ReanimatedCarousel, { ref: carouselRef, width: isVertical ? containerWidth : itemSize, height: isVertical ? itemSize : height, style: isVertical ? { height: containerHeight } : { width: containerWidth }, vertical: isVertical, loop: loop, autoPlay: enableAutoPlay, autoPlayInterval: autoPlayInterval, data: itemsArray, pagingEnabled: snapToItem, windowSize: windowSize > 0 ? windowSize : undefined,
37916
+ ], onLayout: handleLayout, ...otherProps, children: [jsx(View, { style: { flex: 1 }, children: hasLayout && pagedItems.length > 0 && cardSize > 0 && (jsx(ReanimatedCarousel, { ref: carouselRef, width: isVertical ? containerWidth : containerWidth, height: isVertical ? containerHeight : height, style: isVertical ? { height: containerHeight } : { width: containerWidth }, vertical: isVertical, loop: loop, autoPlay: enableAutoPlay, autoPlayInterval: autoPlayInterval, data: pagedItems, pagingEnabled: isDragFree ? false : snapToItem, snapEnabled: isDragFree ? false : undefined, windowSize: windowSize > 0 ? windowSize : undefined, scrollAnimationDuration: duration,
37635
37917
  // Performance optimizations
37636
37918
  overscrollEnabled: false, enabled: !reducedMotion, withAnimation: reducedMotion ?
37637
37919
  { type: 'timing', config: { duration: 100 } } :
37638
- { type: 'spring', config: { damping: 60, stiffness: 150 } }, onProgressChange: (offset, absolute) => {
37920
+ { type: 'spring', config: { damping: 60, stiffness: 150 } }, maxScrollDistancePerSwipe: maxScrollDistancePerSwipe, minScrollDistancePerSwipe: dragThresholdValue, onProgressChange: (offset, absolute) => {
37639
37921
  // absolute may be undefined in some versions; fallback to offset
37640
37922
  const val = typeof absolute === 'number' ? absolute : offset;
37641
37923
  progress.value = val;
37642
- const ci = ((Math.round(val) % totalItems) + totalItems) % totalItems;
37924
+ const ci = totalPages > 0
37925
+ ? ((Math.round(val) % totalPages) + totalPages) % totalPages
37926
+ : 0;
37643
37927
  if (ci !== currentIndex) {
37644
37928
  setCurrentIndex(ci);
37645
37929
  onSlideChange === null || onSlideChange === void 0 ? void 0 : onSlideChange(ci);
37646
37930
  }
37647
- }, renderItem: ({ item, index }) => (jsx(View, { style: [
37648
- {
37649
- width: isVertical ? containerWidth : itemSize,
37650
- height: isVertical ? itemSize : height,
37651
- ...(isVertical
37652
- ? { marginBottom: index < itemsArray.length - 1 ? resolvedGap : 0 }
37653
- : { marginRight: index < itemsArray.length - 1 ? resolvedGap : 0 }),
37654
- },
37655
- itemStyle,
37656
- ], accessibilityLabel: `Carousel item ${index + 1} of ${totalItems}`, children: item })) })) }), renderArrows(), renderDots] }));
37931
+ }, renderItem: ({ item, index }) => {
37932
+ const pageItems = Array.isArray(item) ? item : [item];
37933
+ const pageWidth = isVertical ? containerWidth : containerWidth;
37934
+ const pageHeight = isVertical ? containerHeight : height;
37935
+ const justify = containMode === 'trimSnaps' ? 'flex-start' : alignJustify;
37936
+ return (jsx(View, { style: [
37937
+ {
37938
+ width: pageWidth,
37939
+ height: pageHeight,
37940
+ justifyContent: 'center',
37941
+ },
37942
+ itemStyle,
37943
+ ], accessibilityLabel: `Carousel item ${index + 1} of ${totalPages}`, children: jsx(View, { style: {
37944
+ flexDirection: isVertical ? 'column' : 'row',
37945
+ alignItems: 'stretch',
37946
+ justifyContent: justify,
37947
+ flexWrap: 'nowrap',
37948
+ flex: 1,
37949
+ }, children: pageItems.map((child, childIndex) => (jsx(View, { style: {
37950
+ width: isVertical ? '100%' : cardSize,
37951
+ height: isVertical ? cardSize : '100%',
37952
+ marginRight: !isVertical && childIndex < pageItems.length - 1 ? resolvedGap : 0,
37953
+ marginBottom: isVertical && childIndex < pageItems.length - 1 ? resolvedGap : 0,
37954
+ flexShrink: 0,
37955
+ }, children: child }, childIndex))) }) }));
37956
+ } })) }), renderArrows(), renderDots] }));
37657
37957
  };
37658
37958
 
37659
37959
  // Types extracted to types.ts