@platform-blocks/ui 0.1.2 → 0.2.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/cjs/index.js CHANGED
@@ -5,11 +5,9 @@ var React = require('react');
5
5
  var reactNative = require('react-native');
6
6
  var Animated = require('react-native-reanimated');
7
7
  var reactNativeSafeAreaContext = require('react-native-safe-area-context');
8
- var expoLinearGradient = require('expo-linear-gradient');
9
8
  var Svg = require('react-native-svg');
10
9
  var flashList = require('@shopify/flash-list');
11
10
  var MaskedView = require('@react-native-masked-view/masked-view');
12
- var DocumentPicker = require('expo-document-picker');
13
11
  var ReanimatedCarousel = require('react-native-reanimated-carousel');
14
12
 
15
13
  function _interopNamespaceDefault(e) {
@@ -30,7 +28,6 @@ function _interopNamespaceDefault(e) {
30
28
  }
31
29
 
32
30
  var React__namespace = /*#__PURE__*/_interopNamespaceDefault(React);
33
- var DocumentPicker__namespace = /*#__PURE__*/_interopNamespaceDefault(DocumentPicker);
34
31
 
35
32
  /**
36
33
  * Design tokens for consistent styling across the UI library
@@ -679,7 +676,7 @@ const DARK_THEME = {
679
676
  '#8E8E93',
680
677
  '#AEAEB2',
681
678
  '#C7C7CC',
682
- '#D1D16',
679
+ '#D1D1D6',
683
680
  '#E5E5EA'
684
681
  ],
685
682
  success: [
@@ -3170,6 +3167,21 @@ const convertToWebStyles = (rnStyles) => {
3170
3167
  });
3171
3168
  return webStyles;
3172
3169
  };
3170
+ const containsPlatformText = (node) => {
3171
+ return React.Children.toArray(node).some(child => {
3172
+ if (React.isValidElement(child)) {
3173
+ const childType = child.type;
3174
+ if ((childType === null || childType === void 0 ? void 0 : childType.__PLATFORM_BLOCKS_TEXT__) === true) {
3175
+ return true;
3176
+ }
3177
+ const childProps = child.props;
3178
+ if (childProps === null || childProps === void 0 ? void 0 : childProps.children) {
3179
+ return containsPlatformText(childProps.children);
3180
+ }
3181
+ }
3182
+ return false;
3183
+ });
3184
+ };
3173
3185
  const Text = (allProps) => {
3174
3186
  const { spacingProps, otherProps } = extractSpacingProps(allProps);
3175
3187
  const { children, tx, txParams, variant = 'p', size, weight, align = 'left', color, colorVariant, lineHeight, tracking, uppercase, style, fontFamily, as, selectable = true, onPress, onLayout, value, numberOfLines, ellipsizeMode } = otherProps;
@@ -3210,6 +3222,10 @@ const Text = (allProps) => {
3210
3222
  // Switch to div to prevent <h*> inside <p> DOM nesting warning / hydration error
3211
3223
  htmlTag = 'div';
3212
3224
  }
3225
+ if (htmlTag === 'p' && containsPlatformText(children)) {
3226
+ // Avoid nested paragraphs when Text components are nested
3227
+ htmlTag = 'div';
3228
+ }
3213
3229
  }
3214
3230
  // Platform-specific rendering
3215
3231
  if (reactNative.Platform.OS === 'web' && isHTMLVariant(htmlTag)) {
@@ -3247,6 +3263,7 @@ const Text = (allProps) => {
3247
3263
  // Fallback to React Native Text for mobile or non-HTML variants
3248
3264
  return (jsxRuntime.jsx(reactNative.Text, { style: [textStyles, spacingStyles, style], selectable: selectable, onPress: onPress, onLayout: onLayout, numberOfLines: numberOfLines, ellipsizeMode: ellipsizeMode, children: content }));
3249
3265
  };
3266
+ Text.__PLATFORM_BLOCKS_TEXT__ = true;
3250
3267
  // Helper function to check if variant is a valid HTML tag
3251
3268
  const isHTMLVariant = (variant) => {
3252
3269
  const htmlTags = [
@@ -4176,6 +4193,12 @@ const actionIcons = {
4176
4193
  variant: 'outlined',
4177
4194
  description: 'Magnifying glass and highlight circle to represent spotlight search.',
4178
4195
  },
4196
+ highlight: {
4197
+ content: 'm15.728 3.514 4.758 4.758-7.071 7.071-2.474.353a1 1 0 0 1-1.118-1.118l.353-2.474 7.552-7.03Zm-9.95 8.486 3.222 3.222-3 3H3a1 1 0 0 1-1-1v-2.999l3.778-3.223Z',
4198
+ viewBox: '0 0 24 24',
4199
+ variant: 'outlined',
4200
+ description: 'Highlighter marker illustrating text emphasis.',
4201
+ },
4179
4202
  minus: {
4180
4203
  content: 'M5 12h14',
4181
4204
  viewBox: '0 0 24 24',
@@ -4662,6 +4685,12 @@ const uiIcons = {
4662
4685
  variant: 'outlined',
4663
4686
  description: 'Tooltip badge with question mark for contextual hints.',
4664
4687
  },
4688
+ popover: {
4689
+ content: 'M4 6a2 2 0 0 1 2-2h12a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2h-5.17L12 19.17 9.17 16H6a2 2 0 0 1-2-2V6z',
4690
+ viewBox: '0 0 24 24',
4691
+ variant: 'outlined',
4692
+ description: 'Popover surface with speech arrow for contextual overlays.',
4693
+ },
4665
4694
  'layer-mask': {
4666
4695
  content: 'M5 4h4 M4 5v4 M19 4h-4 M20 5v4 M19 20h-4 M20 19v-4 M5 20h4 M4 19v-4 M9 9h12v10H9z M13 13h4v4h-4z',
4667
4696
  viewBox: '0 0 24 24',
@@ -4669,10 +4698,22 @@ const uiIcons = {
4669
4698
  description: 'Layered frame with inset window representing an overlay mask.',
4670
4699
  },
4671
4700
  slider: {
4672
- content: 'M7 14H5v5h5v-2H7v-3zM5 10h2V7h3V5H5v5zm12 7h-3v2h5v-5h-2v3zM14 5v2h3v3h2V5h-5z',
4701
+ content: 'M12 3a1 1 0 0 1 .993 .883l.007 .117v9.171a3.001 3.001 0 0 1 0 5.658v1.171a1 1 0 0 1 -1.993 .117l-.007 -.117v-1.17a3.002 3.002 0 0 1 -1.995 -2.654l-.005 -.176l.005 -.176a3.002 3.002 0 0 1 1.995 -2.654v-9.17a1 1 0 0 1 1 -1z',
4673
4702
  viewBox: '0 0 24 24',
4674
4703
  variant: 'outlined',
4675
- description: 'Slider control handles for adjustable inputs.',
4704
+ description: 'Horizontal slider track with centered thumb knob.',
4705
+ },
4706
+ hook: {
4707
+ content: 'M6 3v7a6 6 0 1 0 12 0v-2M6 6h6M10 13c0 2 1.5 3 3 3s3-1 3-3',
4708
+ viewBox: '0 0 24 24',
4709
+ variant: 'outlined',
4710
+ description: 'Fishing hook silhouette for representing hooks utilities.',
4711
+ },
4712
+ support: {
4713
+ content: 'M12 2a10 10 0 1 0 0 20 10 10 0 0 0 0-20Zm0 4a6 6 0 1 1 0 12 6 6 0 0 1 0-12Zm-4.95-.95 2.12 2.12-1.06 1.06-2.12-2.12 1.06-1.06Zm9.9 0 1.06 1.06-2.12 2.12-1.06-1.06 2.12-2.12ZM7.05 16.95l-1.06-1.06 2.12-2.12 1.06 1.06-2.12 2.12Zm9.9 0-2.12-2.12 1.06-1.06 2.12 2.12-1.06 1.06Z',
4714
+ viewBox: '0 0 24 24',
4715
+ variant: 'outlined',
4716
+ description: 'Life preserver style icon to represent support resources.',
4676
4717
  },
4677
4718
  input: {
4678
4719
  content: 'M4 6h16v2H4zM4 12h16v6H4z',
@@ -5618,6 +5659,65 @@ const createAccessibilityProps = (options) => {
5618
5659
  return accessibilityProps;
5619
5660
  };
5620
5661
 
5662
+ let linearGradientCache;
5663
+ let linearGradientAvailable = false;
5664
+ let warnedLinearGradient = false;
5665
+ const LinearGradientFallback = ({ children, style, colors }) => {
5666
+ if (__DEV__ && !warnedLinearGradient) {
5667
+ console.warn('expo-linear-gradient not installed; gradient-based components fall back to solid colors.');
5668
+ warnedLinearGradient = true;
5669
+ }
5670
+ const styles = [
5671
+ (colors === null || colors === void 0 ? void 0 : colors[0]) ? { backgroundColor: colors[0] } : undefined,
5672
+ ...(Array.isArray(style) ? style : style ? [style] : []),
5673
+ ].filter(Boolean);
5674
+ return React.createElement(reactNative.View, { style: styles }, children);
5675
+ };
5676
+ function resolveLinearGradient() {
5677
+ var _a, _b;
5678
+ if (linearGradientCache === undefined) {
5679
+ try {
5680
+ const mod = require('expo-linear-gradient');
5681
+ linearGradientCache = (_b = (_a = mod === null || mod === void 0 ? void 0 : mod.LinearGradient) !== null && _a !== void 0 ? _a : mod === null || mod === void 0 ? void 0 : mod.default) !== null && _b !== void 0 ? _b : mod;
5682
+ linearGradientAvailable = !!linearGradientCache;
5683
+ }
5684
+ catch (_c) {
5685
+ linearGradientCache = LinearGradientFallback;
5686
+ linearGradientAvailable = false;
5687
+ }
5688
+ }
5689
+ if (!linearGradientCache) {
5690
+ linearGradientCache = LinearGradientFallback;
5691
+ linearGradientAvailable = false;
5692
+ }
5693
+ return {
5694
+ LinearGradient: linearGradientCache,
5695
+ hasLinearGradient: linearGradientAvailable,
5696
+ };
5697
+ }
5698
+ let documentPickerCache;
5699
+ let warnedDocumentPicker = false;
5700
+ function resolveDocumentPicker() {
5701
+ if (documentPickerCache === undefined) {
5702
+ try {
5703
+ documentPickerCache = require('expo-document-picker');
5704
+ }
5705
+ catch (_a) {
5706
+ documentPickerCache = null;
5707
+ }
5708
+ }
5709
+ const hasDocumentPicker = !!(documentPickerCache === null || documentPickerCache === void 0 ? void 0 : documentPickerCache.getDocumentAsync);
5710
+ if (!hasDocumentPicker && __DEV__ && !warnedDocumentPicker) {
5711
+ console.warn('expo-document-picker not installed; native file picker support is disabled.');
5712
+ warnedDocumentPicker = true;
5713
+ }
5714
+ return {
5715
+ DocumentPicker: documentPickerCache,
5716
+ hasDocumentPicker,
5717
+ };
5718
+ }
5719
+
5720
+ const { LinearGradient: OptionalLinearGradient$4, hasLinearGradient: hasLinearGradient$3 } = resolveLinearGradient();
5621
5721
  const getButtonStyles = (theme, variant = 'filled', size = 'md', disabled = false, loading = false, height, radiusStyles, shadowStyles, customColor, isIconButton = false, fullWidth = false) => {
5622
5722
  const sizeConfig = getComponentSize(size);
5623
5723
  const horizontalSpacing = isIconButton ? 0 : sizeConfig.padding;
@@ -5741,6 +5841,7 @@ const Button = (allProps) => {
5741
5841
  const { title, children, onPress, onPressIn, onPressOut, onHoverIn, onHoverOut, onLongPress, onLayout, variant = 'filled', size = 'md', disabled = false, loading = false, loadingTitle, colorVariant, textColor: textColorProp, icon, startIcon, endIcon, tooltip, tooltipPosition = 'top', radius, style, testID, accessibilityLabel: accessibilityLabelProp, accessibilityHint: accessibilityHintProp, } = otherProps;
5742
5842
  // Theme
5743
5843
  const theme = useTheme();
5844
+ const effectiveVariant = variant === 'gradient' && !hasLinearGradient$3 ? 'filled' : variant;
5744
5845
  // Accessibility hooks
5745
5846
  const { getDuration } = useReducedMotion$1();
5746
5847
  const { announce } = useAnnouncer();
@@ -5804,7 +5905,7 @@ const Button = (allProps) => {
5804
5905
  const height = getHeight(size);
5805
5906
  const radiusStyles = createRadiusStyles(radius, height, 'button');
5806
5907
  // Handle shadow prop - use default 'sm' for primary/filled/secondary/gradient variants if no shadow specified
5807
- const effectiveShadow = (_a = shadowProps.shadow) !== null && _a !== void 0 ? _a : ((variant === 'filled' || variant === 'secondary' || variant === 'gradient') ? 'sm' : 'none');
5908
+ const effectiveShadow = (_a = shadowProps.shadow) !== null && _a !== void 0 ? _a : ((effectiveVariant === 'filled' || effectiveVariant === 'secondary' || effectiveVariant === 'gradient') ? 'sm' : 'none');
5808
5909
  const shadowStyles = getShadowStyles({ shadow: effectiveShadow }, theme, 'button');
5809
5910
  const spacingStyles = getSpacingStyles(spacingProps);
5810
5911
  const baseLayoutStyles = getLayoutStyles(layoutProps);
@@ -5839,7 +5940,7 @@ const Button = (allProps) => {
5839
5940
  return token; // raw css color
5840
5941
  };
5841
5942
  const resolvedCustomColor = resolveTokenColor(colorVariant);
5842
- const buttonStyles = getButtonStyles(theme, variant, size, disabled, loading, height, radiusStyles, shadowStyles, resolvedCustomColor, isIconButton, layoutProps.fullWidth || false);
5943
+ const buttonStyles = getButtonStyles(theme, effectiveVariant, size, disabled, loading, height, radiusStyles, shadowStyles, resolvedCustomColor, isIconButton, layoutProps.fullWidth || false);
5843
5944
  // derive contrasted text color if filled/filled background
5844
5945
  const pickContrast = (bg) => {
5845
5946
  if (!bg)
@@ -5858,12 +5959,12 @@ const Button = (allProps) => {
5858
5959
  if (textColorProp)
5859
5960
  return resolveTokenColor(textColorProp) || textColorProp;
5860
5961
  if (resolvedCustomColor) {
5861
- if (variant === 'filled' || variant === 'gradient')
5962
+ if (effectiveVariant === 'filled' || effectiveVariant === 'gradient')
5862
5963
  return pickContrast(resolvedCustomColor);
5863
- if (variant === 'outline' || variant === 'ghost' || variant === 'none' || variant === 'secondary')
5964
+ if (effectiveVariant === 'outline' || effectiveVariant === 'ghost' || effectiveVariant === 'none' || effectiveVariant === 'secondary')
5864
5965
  return resolvedCustomColor;
5865
5966
  }
5866
- switch (variant) {
5967
+ switch (effectiveVariant) {
5867
5968
  case 'filled': return '#FFFFFF';
5868
5969
  case 'gradient': return '#FFFFFF';
5869
5970
  case 'secondary': return theme.colors.gray[7];
@@ -5873,7 +5974,7 @@ const Button = (allProps) => {
5873
5974
  case 'none': return 'currentColor';
5874
5975
  default: return '#FFFFFF';
5875
5976
  }
5876
- }, [textColorProp, resolvedCustomColor, variant, theme.colors.gray, theme.colors.primary]);
5977
+ }, [textColorProp, resolvedCustomColor, effectiveVariant, theme.colors.gray, theme.colors.primary]);
5877
5978
  // Memoize text props
5878
5979
  const textProps = React.useMemo(() => ({
5879
5980
  size,
@@ -5889,11 +5990,11 @@ const Button = (allProps) => {
5889
5990
  // Memoize loader color calculation
5890
5991
  const loaderColor = React.useMemo(() => {
5891
5992
  if (resolvedCustomColor) {
5892
- if (variant === 'filled')
5993
+ if (effectiveVariant === 'filled')
5893
5994
  return pickContrast(resolvedCustomColor);
5894
5995
  return resolvedCustomColor;
5895
5996
  }
5896
- switch (variant) {
5997
+ switch (effectiveVariant) {
5897
5998
  case 'filled': return '#FFFFFF';
5898
5999
  case 'secondary': return theme.colors.gray[7];
5899
6000
  case 'outline': return theme.colors.primary[5];
@@ -5903,7 +6004,7 @@ const Button = (allProps) => {
5903
6004
  case 'none': return 'currentColor';
5904
6005
  default: return '#FFFFFF';
5905
6006
  }
5906
- }, [resolvedCustomColor, variant, theme.colors.gray, theme.colors.primary]);
6007
+ }, [resolvedCustomColor, effectiveVariant, theme.colors.gray, theme.colors.primary]);
5907
6008
  // Helper function to inject color into icon components
5908
6009
  const renderIconWithColor = (iconElement) => {
5909
6010
  if (!iconElement)
@@ -6004,14 +6105,14 @@ const Button = (allProps) => {
6004
6105
  },
6005
6106
  // subtle visual feedback beyond scale on supported platforms
6006
6107
  pressed && !isInteractionDisabled ? {
6007
- opacity: variant === 'ghost' || variant === 'none' ? 0.6 : 0.9,
6108
+ opacity: effectiveVariant === 'ghost' || effectiveVariant === 'none' ? 0.6 : 0.9,
6008
6109
  ...(reactNative.Platform.OS !== 'web' ? { transform: [{ translateY: 1 }] } : {})
6009
6110
  } : null,
6010
6111
  style,
6011
6112
  { minWidth: calculatedMinWidth }
6012
- ], onPress: handleInternalPress, onLayout: onLayout, onPressIn: handlePressIn, onPressOut: handlePressOut, onHoverIn: onHoverIn, onHoverOut: onHoverOut, onLongPress: onLongPress, disabled: isInteractionDisabled, children: [variant === 'gradient' && jsxRuntime.jsx(expoLinearGradient.LinearGradient, { colors: variant === 'gradient'
6013
- ? (resolvedCustomColor ? [resolvedCustomColor, theme.colors.primary[7]] : [theme.colors.primary[5], theme.colors.primary[7]])
6014
- : ['transparent', 'transparent'], style: { position: 'absolute', zIndex: -1, top: 0, left: 0, right: 0, bottom: 0, borderRadius: radiusStyles.borderRadius }, start: { x: 0, y: 0 }, end: { x: 1, y: 0 } }), loading ? (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx(Loader, { size: size, color: getLoaderColor(), style: !isIconButton ? { marginRight: iconSpacing } : undefined }), !isIconButton && renderButtonContent(displayContent)] })) : isIconButton ? (
6113
+ ], onPress: handleInternalPress, onLayout: onLayout, onPressIn: handlePressIn, onPressOut: handlePressOut, onHoverIn: onHoverIn, onHoverOut: onHoverOut, onLongPress: onLongPress, disabled: isInteractionDisabled, children: [variant === 'gradient' && hasLinearGradient$3 && (jsxRuntime.jsx(OptionalLinearGradient$4, { colors: resolvedCustomColor
6114
+ ? [resolvedCustomColor, theme.colors.primary[7]]
6115
+ : [theme.colors.primary[5], theme.colors.primary[7]], style: { position: 'absolute', zIndex: -1, top: 0, left: 0, right: 0, bottom: 0, borderRadius: radiusStyles.borderRadius }, start: { x: 0, y: 0 }, end: { x: 1, y: 0 } })), loading ? (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx(Loader, { size: size, color: getLoaderColor(), style: !isIconButton ? { marginRight: iconSpacing } : undefined }), !isIconButton && renderButtonContent(displayContent)] })) : isIconButton ? (
6015
6116
  // Icon-only button
6016
6117
  renderIconWithColor(icon)) : (
6017
6118
  // Regular button with text and optional side icons
@@ -6886,7 +6987,6 @@ const Flex = factory((props, ref) => {
6886
6987
  * Automatically mirrors to row-reverse in RTL
6887
6988
  */
6888
6989
  const Row$1 = React.forwardRef((props, ref) => {
6889
- // @ts-expect-error - factory components handle refs differently
6890
6990
  return jsxRuntime.jsx(Flex, { ...props, direction: "row", ref: ref });
6891
6991
  });
6892
6992
  Row$1.displayName = 'Row';
@@ -6895,7 +6995,6 @@ Row$1.displayName = 'Row';
6895
6995
  * Not affected by RTL (columns are vertical)
6896
6996
  */
6897
6997
  const Column$1 = React.forwardRef((props, ref) => {
6898
- // @ts-expect-error - factory components handle refs differently
6899
6998
  return jsxRuntime.jsx(Flex, { ...props, direction: "column", ref: ref });
6900
6999
  });
6901
7000
  Column$1.displayName = 'Column';
@@ -6952,6 +7051,280 @@ function useSimpleDialog() {
6952
7051
  };
6953
7052
  }
6954
7053
 
7054
+ const escapeRegExp$1 = (value) => value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
7055
+ const toHighlightArray = (value, trim) => {
7056
+ if (value === undefined || value === null) {
7057
+ return [];
7058
+ }
7059
+ const rawValues = Array.isArray(value) ? value : [value];
7060
+ return rawValues
7061
+ .filter((item) => item !== undefined && item !== null)
7062
+ .map((item) => String(item))
7063
+ .map((item) => (trim ? item.trim() : item))
7064
+ .filter((item) => item.length > 0);
7065
+ };
7066
+ const flattenStyleArray = (style) => {
7067
+ if (!Array.isArray(style)) {
7068
+ return style ? [style] : [];
7069
+ }
7070
+ return style.reduce((acc, item) => {
7071
+ acc.push(...flattenStyleArray(item));
7072
+ return acc;
7073
+ }, []);
7074
+ };
7075
+ const extractColorFromStyle = (style) => {
7076
+ for (const entry of flattenStyleArray(style)) {
7077
+ if (entry && typeof entry === 'object' && typeof entry.color === 'string') {
7078
+ return entry.color;
7079
+ }
7080
+ }
7081
+ return undefined;
7082
+ };
7083
+ const parseColor = (value) => {
7084
+ if (!value || typeof value !== 'string') {
7085
+ return undefined;
7086
+ }
7087
+ const trimmed = value.trim();
7088
+ if (trimmed.startsWith('#')) {
7089
+ let hex = trimmed.slice(1);
7090
+ if (hex.length === 3) {
7091
+ hex = hex.split('').map(char => char + char).join('');
7092
+ }
7093
+ if (hex.length === 6) {
7094
+ const r = parseInt(hex.slice(0, 2), 16);
7095
+ const g = parseInt(hex.slice(2, 4), 16);
7096
+ const b = parseInt(hex.slice(4, 6), 16);
7097
+ if ([r, g, b].every(component => !Number.isNaN(component))) {
7098
+ return { r, g, b };
7099
+ }
7100
+ }
7101
+ if (hex.length === 8) {
7102
+ const r = parseInt(hex.slice(0, 2), 16);
7103
+ const g = parseInt(hex.slice(2, 4), 16);
7104
+ const b = parseInt(hex.slice(4, 6), 16);
7105
+ if ([r, g, b].every(component => !Number.isNaN(component))) {
7106
+ return { r, g, b };
7107
+ }
7108
+ }
7109
+ }
7110
+ const rgbMatch = trimmed.match(/^rgba?\(([^)]+)\)$/i);
7111
+ if (rgbMatch) {
7112
+ const parts = rgbMatch[1].split(',').map(part => part.trim()).slice(0, 3);
7113
+ if (parts.length === 3) {
7114
+ const [r, g, b] = parts.map(part => parseFloat(part));
7115
+ if ([r, g, b].every(component => !Number.isNaN(component))) {
7116
+ return { r: Math.round(r), g: Math.round(g), b: Math.round(b) };
7117
+ }
7118
+ }
7119
+ }
7120
+ return undefined;
7121
+ };
7122
+ const getRelativeLuminance = ({ r, g, b }) => {
7123
+ const srgb = [r, g, b].map(channel => {
7124
+ const normalized = channel / 255;
7125
+ return normalized <= 0.03928 ? normalized / 12.92 : Math.pow((normalized + 0.055) / 1.055, 2.4);
7126
+ });
7127
+ return 0.2126 * srgb[0] + 0.7152 * srgb[1] + 0.0722 * srgb[2];
7128
+ };
7129
+ const mixRgb = (color, target, weight) => ({
7130
+ r: Math.round(color.r * (1 - weight) + target.r * weight),
7131
+ g: Math.round(color.g * (1 - weight) + target.g * weight),
7132
+ b: Math.round(color.b * (1 - weight) + target.b * weight),
7133
+ });
7134
+ const toRgba$1 = ({ r, g, b }, alpha) => `rgba(${r}, ${g}, ${b}, ${alpha})`;
7135
+ const resolvePaletteShade = (palette, preferredIndex, fallbackIndex) => {
7136
+ if (!palette || palette.length === 0) {
7137
+ return undefined;
7138
+ }
7139
+ const safePreferred = palette[Math.min(Math.max(preferredIndex, 0), palette.length - 1)];
7140
+ if (safePreferred) {
7141
+ return safePreferred;
7142
+ }
7143
+ return palette[Math.min(Math.max(fallbackIndex, 0), palette.length - 1)];
7144
+ };
7145
+ const createAdaptiveBackground = (baseColor, isTextLight, colorScheme) => {
7146
+ const rgb = parseColor(baseColor);
7147
+ if (!rgb) {
7148
+ return baseColor;
7149
+ }
7150
+ const target = isTextLight ? { r: 0, g: 0, b: 0 } : { r: 255, g: 255, b: 255 };
7151
+ const mixAmount = isTextLight ? (colorScheme === 'dark' ? 0.4 : 0.3) : (colorScheme === 'dark' ? 0.25 : 0.15);
7152
+ const alpha = isTextLight ? (colorScheme === 'dark' ? 0.7 : 0.8) : (colorScheme === 'dark' ? 0.55 : 0.88);
7153
+ const mixed = mixRgb(rgb, target, mixAmount);
7154
+ return toRgba$1(mixed, alpha);
7155
+ };
7156
+ const resolveHighlightBackground = (theme, highlightColor, isTextLight) => {
7157
+ var _a;
7158
+ const themeColors = theme.colors;
7159
+ const paletteFromProp = highlightColor ? themeColors[highlightColor] : undefined;
7160
+ const defaultPalette = theme.colors.highlight || theme.colors.amber || theme.colors.primary;
7161
+ const preferredPalette = paletteFromProp || defaultPalette;
7162
+ const highlightStateColor = (_a = theme.states) === null || _a === void 0 ? void 0 : _a.highlightBackground;
7163
+ let baseColor = paletteFromProp
7164
+ ? resolvePaletteShade(paletteFromProp, isTextLight ? 8 : 2, isTextLight ? 7 : 3)
7165
+ : undefined;
7166
+ if (!baseColor && highlightColor && !paletteFromProp) {
7167
+ baseColor = highlightColor;
7168
+ }
7169
+ if (!baseColor && highlightStateColor) {
7170
+ baseColor = highlightStateColor;
7171
+ }
7172
+ if (!baseColor && preferredPalette) {
7173
+ baseColor = resolvePaletteShade(preferredPalette, isTextLight ? 8 : 2, isTextLight ? 7 : 3);
7174
+ }
7175
+ if (!baseColor) {
7176
+ baseColor = isTextLight ? '#92400E' : '#FDE68A';
7177
+ }
7178
+ return createAdaptiveBackground(baseColor, isTextLight, theme.colorScheme);
7179
+ };
7180
+ const createBaseHighlightStyle = (theme, backgroundColor, textColor, includeColor) => ({
7181
+ backgroundColor,
7182
+ ...(includeColor ? { color: textColor } : {}),
7183
+ borderRadius: 4,
7184
+ paddingHorizontal: 4,
7185
+ paddingVertical: reactNative.Platform.OS === 'web' ? 0 : 2,
7186
+ });
7187
+ const Highlight = ({ children, highlight, highlightStyles, highlightColor, caseSensitive = false, trim = true, highlightProps, variant, ...rest }) => {
7188
+ var _a, _b;
7189
+ const theme = useTheme();
7190
+ const outerVariant = variant !== null && variant !== void 0 ? variant : 'span';
7191
+ const textContent = React.useMemo(() => {
7192
+ if (typeof children === 'string' || typeof children === 'number') {
7193
+ return String(children);
7194
+ }
7195
+ const parts = React.Children.toArray(children);
7196
+ if (parts.length === 0) {
7197
+ return '';
7198
+ }
7199
+ if (parts.every((part) => typeof part === 'string' || typeof part === 'number')) {
7200
+ return parts.map((part) => String(part)).join('');
7201
+ }
7202
+ return null;
7203
+ }, [children]);
7204
+ const highlightValues = React.useMemo(() => toHighlightArray(highlight, trim), [highlight, trim]);
7205
+ const highlightPropsValue = React.useMemo(() => highlightProps !== null && highlightProps !== void 0 ? highlightProps : {}, [highlightProps]);
7206
+ const highlightDerived = React.useMemo(() => {
7207
+ var _a, _b;
7208
+ const { style, as, variant: innerVariant, color: colorProp, ...restProps } = highlightPropsValue;
7209
+ return {
7210
+ style,
7211
+ color: colorProp,
7212
+ as: (_a = as) !== null && _a !== void 0 ? _a : (reactNative.Platform.OS === 'web' ? 'mark' : 'span'),
7213
+ variant: (_b = innerVariant) !== null && _b !== void 0 ? _b : 'span',
7214
+ rest: restProps,
7215
+ };
7216
+ }, [highlightPropsValue]);
7217
+ const outerColor = React.useMemo(() => {
7218
+ const restProps = rest;
7219
+ if ((restProps === null || restProps === void 0 ? void 0 : restProps.color) && typeof restProps.color === 'string') {
7220
+ return restProps.color;
7221
+ }
7222
+ const colorVariantKey = restProps === null || restProps === void 0 ? void 0 : restProps.colorVariant;
7223
+ if (typeof colorVariantKey === 'string') {
7224
+ const fromText = theme.text[colorVariantKey];
7225
+ if (fromText) {
7226
+ return fromText;
7227
+ }
7228
+ const palette = theme.colors[colorVariantKey];
7229
+ const paletteColor = resolvePaletteShade(palette, 6, palette ? palette.length - 1 : 6);
7230
+ if (paletteColor) {
7231
+ return paletteColor;
7232
+ }
7233
+ }
7234
+ return extractColorFromStyle(restProps === null || restProps === void 0 ? void 0 : restProps.style);
7235
+ }, [rest, theme]);
7236
+ const fallbackTextColor = (_b = (_a = theme.states) === null || _a === void 0 ? void 0 : _a.highlightText) !== null && _b !== void 0 ? _b : theme.text.primary;
7237
+ const { resolvedTextColor, isTextColorLight } = React.useMemo(() => {
7238
+ var _a, _b;
7239
+ const candidate = (_b = (_a = highlightDerived.color) !== null && _a !== void 0 ? _a : outerColor) !== null && _b !== void 0 ? _b : fallbackTextColor;
7240
+ const parsedCandidate = parseColor(candidate);
7241
+ if (parsedCandidate) {
7242
+ return {
7243
+ resolvedTextColor: candidate,
7244
+ isTextColorLight: getRelativeLuminance(parsedCandidate) > 0.6,
7245
+ };
7246
+ }
7247
+ const parsedFallback = parseColor(fallbackTextColor);
7248
+ if (parsedFallback) {
7249
+ return {
7250
+ resolvedTextColor: fallbackTextColor,
7251
+ isTextColorLight: getRelativeLuminance(parsedFallback) > 0.6,
7252
+ };
7253
+ }
7254
+ return {
7255
+ resolvedTextColor: candidate !== null && candidate !== void 0 ? candidate : fallbackTextColor,
7256
+ isTextColorLight: theme.colorScheme === 'dark',
7257
+ };
7258
+ }, [highlightDerived.color, outerColor, fallbackTextColor, theme.colorScheme]);
7259
+ const highlightBackground = React.useMemo(() => resolveHighlightBackground(theme, highlightColor, isTextColorLight), [theme, highlightColor, isTextColorLight]);
7260
+ const highlightColorProp = highlightDerived.color;
7261
+ const baseHighlightStyle = React.useMemo(() => createBaseHighlightStyle(theme, highlightBackground, resolvedTextColor, !highlightColorProp), [theme, highlightBackground, resolvedTextColor, highlightColorProp]);
7262
+ const overrideHighlightStyle = React.useMemo(() => (typeof highlightStyles === 'function' ? highlightStyles(theme) : highlightStyles), [highlightStyles, theme]);
7263
+ const highlightNodeStyle = React.useMemo(() => reactNative.StyleSheet.flatten([
7264
+ baseHighlightStyle,
7265
+ overrideHighlightStyle,
7266
+ highlightDerived.style,
7267
+ ]), [baseHighlightStyle, overrideHighlightStyle, highlightDerived.style]);
7268
+ const highlightVariant = highlightDerived.variant;
7269
+ const highlightAs = highlightDerived.as;
7270
+ const highlightRest = highlightDerived.rest;
7271
+ const highlightRegex = React.useMemo(() => {
7272
+ if (textContent === null || highlightValues.length === 0) {
7273
+ return null;
7274
+ }
7275
+ const escaped = highlightValues
7276
+ .map((value) => escapeRegExp$1(value))
7277
+ .filter((value) => value.length > 0)
7278
+ .sort((a, b) => b.length - a.length);
7279
+ if (escaped.length === 0) {
7280
+ return null;
7281
+ }
7282
+ return new RegExp(`(${escaped.join('|')})`, caseSensitive ? 'g' : 'gi');
7283
+ }, [textContent, highlightValues, caseSensitive]);
7284
+ const highlightNormalizedSet = React.useMemo(() => {
7285
+ if (caseSensitive) {
7286
+ return new Set(highlightValues);
7287
+ }
7288
+ return new Set(highlightValues.map((value) => value.toLowerCase()));
7289
+ }, [highlightValues, caseSensitive]);
7290
+ const renderedChildren = React.useMemo(() => {
7291
+ if (textContent === null) {
7292
+ return children;
7293
+ }
7294
+ if (!highlightRegex || highlightValues.length === 0) {
7295
+ return textContent;
7296
+ }
7297
+ const segments = textContent.split(highlightRegex);
7298
+ if (segments.length <= 1) {
7299
+ return textContent;
7300
+ }
7301
+ return segments.map((segment, index) => {
7302
+ if (!segment) {
7303
+ return null;
7304
+ }
7305
+ const normalizedSegment = caseSensitive ? segment : segment.toLowerCase();
7306
+ if (highlightNormalizedSet.has(normalizedSegment)) {
7307
+ return (jsxRuntime.jsx(Text, { variant: highlightVariant, as: highlightAs, color: highlightColorProp, ...highlightRest, style: highlightNodeStyle, children: segment }, `highlight-${index}`));
7308
+ }
7309
+ return (jsxRuntime.jsx(React.Fragment, { children: segment }, `text-${index}`));
7310
+ }).filter((item) => item !== null);
7311
+ }, [
7312
+ children,
7313
+ textContent,
7314
+ highlightRegex,
7315
+ highlightValues,
7316
+ caseSensitive,
7317
+ highlightNormalizedSet,
7318
+ highlightVariant,
7319
+ highlightAs,
7320
+ highlightRest,
7321
+ highlightNodeStyle,
7322
+ highlightColorProp,
7323
+ ]);
7324
+ return (jsxRuntime.jsx(Text, { variant: outerVariant, ...rest, children: renderedChildren }));
7325
+ };
7326
+ Highlight.displayName = 'Highlight';
7327
+
6955
7328
  function isAction(item) {
6956
7329
  return 'id' in item && 'label' in item;
6957
7330
  }
@@ -7370,7 +7743,7 @@ function SpotlightActionsList({ children, scrollable = true, maxHeight, style, s
7370
7743
  // Always use ScrollView for consistent behavior
7371
7744
  return (jsxRuntime.jsx(reactNative.ScrollView, { ref: scrollRef, style: [containerStyle, { maxHeight: calculatedMaxHeight }], showsVerticalScrollIndicator: true, onScroll: onScrollChange ? (e) => onScrollChange(e.nativeEvent.contentOffset.y) : undefined, scrollEventThrottle: 16, contentContainerStyle: undefined, children: children }));
7372
7745
  }
7373
- function SpotlightAction({ label, description, leftSection, rightSection, onPress, disabled = false, selected = false, children, style, innerRef, }) {
7746
+ function SpotlightAction({ label, description, leftSection, rightSection, onPress, disabled = false, selected = false, children, style, innerRef, highlightQuery, }) {
7374
7747
  const theme = useTheme();
7375
7748
  const [isHovered, setIsHovered] = React.useState(false);
7376
7749
  // Truncate long descriptions for cleaner list appearance
@@ -7423,7 +7796,7 @@ function SpotlightAction({ label, description, leftSection, rightSection, onPres
7423
7796
  !selected && pressed && pressedStyle,
7424
7797
  !selected && !pressed && isHovered && hoverStyle,
7425
7798
  style,
7426
- ], ...webHoverProps, children: jsxRuntime.jsxs(Block, { direction: "row", align: "center", style: styles$c.actionContent, children: [leftSection && (jsxRuntime.jsx(reactNative.View, { style: styles$c.actionLeftSection, children: leftSection })), jsxRuntime.jsxs(Block, { direction: "column", style: { flex: 1 }, children: [jsxRuntime.jsx(Text, { weight: "500", children: label }), truncatedDescription ? (jsxRuntime.jsx(Text, { variant: "small", children: truncatedDescription })) : null, children] }), rightSection ? (jsxRuntime.jsx(reactNative.View, { style: styles$c.actionRightSection, children: rightSection })) : null] }) }));
7799
+ ], ...webHoverProps, children: jsxRuntime.jsxs(Block, { direction: "row", align: "center", style: styles$c.actionContent, children: [leftSection && (jsxRuntime.jsx(reactNative.View, { style: styles$c.actionLeftSection, children: leftSection })), jsxRuntime.jsxs(Block, { direction: "column", style: { flex: 1 }, children: [jsxRuntime.jsx(Highlight, { highlight: highlightQuery, style: styles$c.actionLabel, highlightProps: { style: styles$c.actionLabel }, children: label }), truncatedDescription ? (jsxRuntime.jsx(Highlight, { highlight: highlightQuery, style: styles$c.actionDescription, highlightProps: { style: styles$c.actionDescription }, children: truncatedDescription })) : null, children] }), rightSection ? (jsxRuntime.jsx(reactNative.View, { style: styles$c.actionRightSection, children: rightSection })) : null] }) }));
7427
7800
  }
7428
7801
  function SpotlightActionsGroup({ label, children, style, }) {
7429
7802
  const theme = useTheme();
@@ -7441,7 +7814,7 @@ function SpotlightEmpty({ children, style }) {
7441
7814
  return (jsxRuntime.jsx(reactNative.View, { style: [styles$c.empty, style], children: jsxRuntime.jsx(Text, { size: "md", color: theme.text.secondary, style: styles$c.emptyText, children: children }) }));
7442
7815
  }
7443
7816
  // Main Spotlight component
7444
- function Spotlight({ actions, nothingFound = 'Nothing found...', highlightQuery = false, limit, scrollable = false, maxHeight, // Remove default - let it be calculated dynamically
7817
+ function Spotlight({ actions, nothingFound = 'Nothing found...', highlightQuery = true, limit, scrollable = false, maxHeight, // Remove default - let it be calculated dynamically
7445
7818
  shortcut = ['cmd+k', 'ctrl+k'], searchProps = {}, store, variant = 'modal', width = 600, height, }) {
7446
7819
  const spotlightStore = useSpotlightStore();
7447
7820
  // Set as default store if no custom store provided
@@ -7462,6 +7835,23 @@ shortcut = ['cmd+k', 'ctrl+k'], searchProps = {}, store, variant = 'modal', widt
7462
7835
  }, [shouldHandleToggleHotkey, currentStore]);
7463
7836
  useGlobalHotkeys('spotlight-toggle', ['mod+k', handleToggleHotkey]);
7464
7837
  const filteredActions = filterActions(actions, query, limit);
7838
+ const highlightValue = React.useMemo(() => {
7839
+ if (!highlightQuery) {
7840
+ return undefined;
7841
+ }
7842
+ if (highlightQuery !== true) {
7843
+ return highlightQuery;
7844
+ }
7845
+ const trimmed = query.trim();
7846
+ if (!trimmed) {
7847
+ return undefined;
7848
+ }
7849
+ const parts = trimmed.split(/\s+/).filter(Boolean);
7850
+ if (parts.length === 0) {
7851
+ return undefined;
7852
+ }
7853
+ return parts.length === 1 ? parts[0] : parts;
7854
+ }, [highlightQuery, query]);
7465
7855
  // Flatten all actions for keyboard navigation
7466
7856
  const flatActions = React.useMemo(() => {
7467
7857
  const flat = [];
@@ -7589,7 +7979,7 @@ shortcut = ['cmd+k', 'ctrl+k'], searchProps = {}, store, variant = 'modal', widt
7589
7979
  if (isAction(item)) {
7590
7980
  const isSelected = flatIndex === selectedIndex;
7591
7981
  flatIndex++; // Increment after checking
7592
- return (jsxRuntime.jsx(SpotlightAction, { label: item.label, description: item.description, selected: isSelected, innerRef: (el) => { itemRefs.current[flatIndex - 1] = el; }, onLayout: (e) => { itemLayouts.current[flatIndex - 1] = { y: e.nativeEvent.layout.y, height: e.nativeEvent.layout.height }; setLayoutVersion(v => v + 1); }, leftSection: typeof item.icon === 'string' ? (jsxRuntime.jsx(Icon, { name: item.icon, size: "md", color: "pink" })) : (item.icon), onPress: () => {
7982
+ return (jsxRuntime.jsx(SpotlightAction, { label: item.label, description: item.description, selected: isSelected, innerRef: (el) => { itemRefs.current[flatIndex - 1] = el; }, onLayout: (e) => { itemLayouts.current[flatIndex - 1] = { y: e.nativeEvent.layout.y, height: e.nativeEvent.layout.height }; setLayoutVersion(v => v + 1); }, highlightQuery: highlightValue, leftSection: typeof item.icon === 'string' ? (jsxRuntime.jsx(Icon, { name: item.icon, size: "md", color: "pink" })) : (item.icon), onPress: () => {
7593
7983
  var _a;
7594
7984
  (_a = item.onPress) === null || _a === void 0 ? void 0 : _a.call(item);
7595
7985
  currentStore.close();
@@ -7599,7 +7989,7 @@ shortcut = ['cmd+k', 'ctrl+k'], searchProps = {}, store, variant = 'modal', widt
7599
7989
  return (jsxRuntime.jsx(SpotlightActionsGroup, { label: item.group, children: item.actions.map((action) => {
7600
7990
  const isSelected = flatIndex === selectedIndex;
7601
7991
  flatIndex++; // Increment after checking
7602
- return (jsxRuntime.jsx(SpotlightAction, { label: action.label, description: action.description, selected: isSelected, innerRef: (el) => { itemRefs.current[flatIndex - 1] = el; }, onLayout: (e) => { itemLayouts.current[flatIndex - 1] = { y: e.nativeEvent.layout.y, height: e.nativeEvent.layout.height }; setLayoutVersion(v => v + 1); }, leftSection: typeof action.icon === 'string' ? (jsxRuntime.jsx(Icon, { name: action.icon, size: "md" })) : (action.icon), onPress: () => {
7992
+ return (jsxRuntime.jsx(SpotlightAction, { label: action.label, description: action.description, selected: isSelected, innerRef: (el) => { itemRefs.current[flatIndex - 1] = el; }, onLayout: (e) => { itemLayouts.current[flatIndex - 1] = { y: e.nativeEvent.layout.y, height: e.nativeEvent.layout.height }; setLayoutVersion(v => v + 1); }, highlightQuery: highlightValue, leftSection: typeof action.icon === 'string' ? (jsxRuntime.jsx(Icon, { name: action.icon, size: "md" })) : (action.icon), onPress: () => {
7603
7993
  var _a;
7604
7994
  (_a = action.onPress) === null || _a === void 0 ? void 0 : _a.call(action);
7605
7995
  currentStore.close();
@@ -7749,27 +8139,27 @@ class DirectSpotlightStateManager {
7749
8139
  return { ...this.state };
7750
8140
  }
7751
8141
  setState(updates) {
7752
- console.log('[DirectSpotlightStateManager] Setting state:', updates, 'from:', this.state);
8142
+ // console.log('[DirectSpotlightStateManager] Setting state:', updates, 'from:', this.state);
7753
8143
  this.state = { ...this.state, ...updates };
7754
8144
  this.notifyListeners();
7755
8145
  }
7756
8146
  open(query) {
7757
- console.log('[DirectSpotlightStateManager] Opening spotlight');
8147
+ // console.log('[DirectSpotlightStateManager] Opening spotlight');
7758
8148
  this.setState({
7759
8149
  opened: true,
7760
8150
  ...(query !== undefined && { query })
7761
8151
  });
7762
8152
  }
7763
8153
  close() {
7764
- console.log('[DirectSpotlightStateManager] Closing spotlight');
8154
+ // console.log('[DirectSpotlightStateManager] Closing spotlight');
7765
8155
  this.setState({ opened: false, query: '', selectedIndex: -1 });
7766
8156
  }
7767
8157
  setQuery(query) {
7768
- console.log('[DirectSpotlightStateManager] Setting query:', query);
8158
+ // console.log('[DirectSpotlightStateManager] Setting query:', query);
7769
8159
  this.setState({ query });
7770
8160
  }
7771
8161
  toggle() {
7772
- console.log('[DirectSpotlightStateManager] Toggling spotlight');
8162
+ // console.log('[DirectSpotlightStateManager] Toggling spotlight');
7773
8163
  this.setState({ opened: !this.state.opened });
7774
8164
  }
7775
8165
  subscribe(listener) {
@@ -7795,7 +8185,7 @@ const directSpotlightStateManager = new DirectSpotlightStateManager();
7795
8185
  function useDirectSpotlightState() {
7796
8186
  const [state, setState] = React.useState(() => {
7797
8187
  const globalState = directSpotlightStateManager.getState();
7798
- console.log('[useDirectSpotlightState] Initializing with:', globalState);
8188
+ // console.log('[useDirectSpotlightState] Initializing with:', globalState);
7799
8189
  return {
7800
8190
  opened: globalState.opened,
7801
8191
  query: globalState.query,
@@ -7803,9 +8193,9 @@ function useDirectSpotlightState() {
7803
8193
  };
7804
8194
  });
7805
8195
  React.useEffect(() => {
7806
- console.log('[useDirectSpotlightState] Setting up subscription');
8196
+ // console.log('[useDirectSpotlightState] Setting up subscription');
7807
8197
  const unsubscribe = directSpotlightStateManager.subscribe((globalState) => {
7808
- console.log('[useDirectSpotlightState] Global state changed:', globalState);
8198
+ // console.log('[useDirectSpotlightState] Global state changed:', globalState);
7809
8199
  setState({
7810
8200
  opened: globalState.opened,
7811
8201
  query: globalState.query,
@@ -7814,14 +8204,14 @@ function useDirectSpotlightState() {
7814
8204
  });
7815
8205
  // Sync with current state
7816
8206
  const currentState = directSpotlightStateManager.getState();
7817
- console.log('[useDirectSpotlightState] Syncing with current state:', currentState);
8207
+ // console.log('[useDirectSpotlightState] Syncing with current state:', currentState);
7818
8208
  setState({
7819
8209
  opened: currentState.opened,
7820
8210
  query: currentState.query,
7821
8211
  selectedIndex: currentState.selectedIndex
7822
8212
  });
7823
8213
  return () => {
7824
- console.log('[useDirectSpotlightState] Cleaning up subscription');
8214
+ // console.log('[useDirectSpotlightState] Cleaning up subscription');
7825
8215
  unsubscribe();
7826
8216
  };
7827
8217
  }, []);
@@ -9346,10 +9736,9 @@ const useTitleRegistration = (options) => {
9346
9736
  return { elementRef, id };
9347
9737
  };
9348
9738
 
9349
- // Mock LinearGradient for now - in a real app you'd use expo-linear-gradient or react-native-linear-gradient
9350
- const LinearGradient = ({ children, style, ...props }) => (jsxRuntime.jsx(reactNative.View, { style: [style, { backgroundColor: props.colors[0] }], children: children }));
9739
+ const { LinearGradient: OptionalLinearGradient$3, hasLinearGradient: hasLinearGradient$2 } = resolveLinearGradient();
9351
9740
  function Container(props) {
9352
- var _a, _b;
9741
+ var _a, _b, _c, _d;
9353
9742
  const theme = useTheme();
9354
9743
  // Extract spacing props and other props
9355
9744
  const { spacingProps, otherProps } = extractSpacingProps(props);
@@ -9380,7 +9769,10 @@ function Container(props) {
9380
9769
  opacity: (_b = backgroundImage.overlay.opacity) !== null && _b !== void 0 ? _b : 0.3,
9381
9770
  }
9382
9771
  : {};
9383
- return (jsxRuntime.jsxs(reactNative.ImageBackground, { source: { uri: backgroundImage.uri }, style: containerStyle, imageStyle: imageStyle, resizeMode: "cover", children: [backgroundImage.overlay && jsxRuntime.jsx(reactNative.View, { style: overlayStyle }), backgroundImage.gradient && (jsxRuntime.jsx(LinearGradient, { colors: backgroundImage.gradient.colors, locations: backgroundImage.gradient.locations, start: backgroundImage.gradient.start || { x: 0, y: 0 }, end: backgroundImage.gradient.end || { x: 0, y: 1 }, style: reactNative.StyleSheet.absoluteFillObject })), children] }));
9772
+ return (jsxRuntime.jsxs(reactNative.ImageBackground, { source: { uri: backgroundImage.uri }, style: containerStyle, imageStyle: imageStyle, resizeMode: "cover", children: [backgroundImage.overlay && jsxRuntime.jsx(reactNative.View, { style: overlayStyle }), backgroundImage.gradient && (hasLinearGradient$2 ? (jsxRuntime.jsx(OptionalLinearGradient$3, { colors: backgroundImage.gradient.colors, locations: backgroundImage.gradient.locations, start: backgroundImage.gradient.start || { x: 0, y: 0 }, end: backgroundImage.gradient.end || { x: 0, y: 1 }, style: reactNative.StyleSheet.absoluteFillObject })) : (jsxRuntime.jsx(reactNative.View, { style: [
9773
+ reactNative.StyleSheet.absoluteFillObject,
9774
+ { backgroundColor: (_d = (_c = backgroundImage.gradient.colors) === null || _c === void 0 ? void 0 : _c[0]) !== null && _d !== void 0 ? _d : 'transparent' },
9775
+ ] }))), children] }));
9384
9776
  }
9385
9777
 
9386
9778
  const Grid = factory((props, ref) => {
@@ -10512,6 +10904,7 @@ const Column = ({ direction = 'column', gap = 'sm', ...props }) => {
10512
10904
  };
10513
10905
  Row.displayName = 'Row';
10514
10906
 
10907
+ const { LinearGradient: OptionalLinearGradient$2, hasLinearGradient: hasLinearGradient$1 } = resolveLinearGradient();
10515
10908
  /**
10516
10909
  * GradientText Component
10517
10910
  *
@@ -10701,6 +11094,9 @@ const GradientText = React.forwardRef(({ children, colors, locations, angle = 0,
10701
11094
  return (jsxRuntime.jsx(Text, { ...textProps, children: children }));
10702
11095
  }
10703
11096
  // Web-specific gradient implementation with animation
11097
+ if (!hasLinearGradient$1) {
11098
+ return (jsxRuntime.jsx(reactNative.View, { ref: ref, testID: testID, style: styles$b.container, children: jsxRuntime.jsx(Text, { ...textProps, children: children }) }));
11099
+ }
10704
11100
  if (isWeb) {
10705
11101
  return (jsxRuntime.jsx(reactNative.View, { ref: containerRef, "data-testid": testID, style: { display: 'inline-block' }, children: jsxRuntime.jsx(Text, { ...textProps, "data-text-inner": "true", children: children }) }));
10706
11102
  }
@@ -10714,7 +11110,7 @@ const GradientText = React.forwardRef(({ children, colors, locations, angle = 0,
10714
11110
  const gradientLocations = colorLocations.length >= 2
10715
11111
  ? colorLocations
10716
11112
  : [0, 1];
10717
- return (jsxRuntime.jsx(MaskedView, { ref: ref, testID: testID, style: styles$b.container, maskElement: jsxRuntime.jsx(reactNative.View, { style: styles$b.maskContainer, children: jsxRuntime.jsx(Text, { ...textProps, style: [textProps.style, styles$b.maskText], children: children }) }), children: jsxRuntime.jsx(expoLinearGradient.LinearGradient, { colors: gradientColors, locations: gradientLocations, start: gradientStart, end: gradientEnd, style: styles$b.gradient, children: jsxRuntime.jsx(Text, { ...textProps, style: [textProps.style, styles$b.transparentText], children: children }) }) }));
11113
+ return (jsxRuntime.jsx(MaskedView, { ref: ref, testID: testID, style: styles$b.container, maskElement: jsxRuntime.jsx(reactNative.View, { style: styles$b.maskContainer, children: jsxRuntime.jsx(Text, { ...textProps, style: [textProps.style, styles$b.maskText], children: children }) }), children: jsxRuntime.jsx(OptionalLinearGradient$2, { colors: gradientColors, locations: gradientLocations, start: gradientStart, end: gradientEnd, style: styles$b.gradient, children: jsxRuntime.jsx(Text, { ...textProps, style: [textProps.style, styles$b.transparentText], children: children }) }) }));
10718
11114
  });
10719
11115
  GradientText.displayName = 'GradientText';
10720
11116
  const styles$b = reactNative.StyleSheet.create({
@@ -10760,6 +11156,7 @@ const styles$a = reactNative.StyleSheet.create({
10760
11156
  height: '100%',
10761
11157
  },
10762
11158
  });
11159
+ const { LinearGradient: OptionalLinearGradient$1} = resolveLinearGradient();
10763
11160
  const stripColorFromStyle = (styleValue) => {
10764
11161
  if (!styleValue) {
10765
11162
  return styleValue;
@@ -10829,10 +11226,13 @@ function ShimmerText(props) {
10829
11226
  const { spacingProps, otherProps } = extractSpacingProps(props);
10830
11227
  const spacingStyles = getSpacingStyles(spacingProps);
10831
11228
  const { children, text, color: baseColor = '#999999', colors, shimmerColor, duration = 1.8, delay = 0, repeatDelay = 0, repeat = true, once = false, direction = 'ltr', spread = 2, debug = false, onLayout: externalOnLayout, style, ...textProps } = otherProps;
11229
+ const isWeb = reactNative.Platform.OS === 'web';
11230
+ const gradientModuleAvailable = Boolean(OptionalLinearGradient$1);
10832
11231
  const content = (_a = children !== null && children !== void 0 ? children : text) !== null && _a !== void 0 ? _a : null;
10833
11232
  const normalizedSpread = Math.max(spread, MIN_SPREAD);
10834
11233
  const shouldRepeat = repeat && !once;
10835
- const shouldAnimate = once || shouldRepeat;
11234
+ const supportsShimmer = isWeb || gradientModuleAvailable;
11235
+ const shouldAnimate = supportsShimmer && (once || shouldRepeat);
10836
11236
  const extraDistance = normalizedSpread - 1;
10837
11237
  const minPosition = -extraDistance;
10838
11238
  const maxPosition = 1 + extraDistance;
@@ -10843,7 +11243,6 @@ function ShimmerText(props) {
10843
11243
  const debugFlag = Animated.useSharedValue(debug ? 1 : 0);
10844
11244
  const startX = Animated.useSharedValue(0);
10845
11245
  const endX = Animated.useSharedValue(0);
10846
- const isWeb = reactNative.Platform.OS === 'web';
10847
11246
  const [layout, setLayout] = React.useState({ width: 0, height: 0 });
10848
11247
  const [gradientWidth, setGradientWidth] = React.useState(0);
10849
11248
  const mountCountRef = React.useRef(0);
@@ -10876,7 +11275,7 @@ function ShimmerText(props) {
10876
11275
  console.log(`[ShimmerText] ${message}`);
10877
11276
  }, [debug]);
10878
11277
  React.useEffect(() => {
10879
- if (isWeb) {
11278
+ if (isWeb || !gradientModuleAvailable) {
10880
11279
  return;
10881
11280
  }
10882
11281
  mountCountRef.current += 1;
@@ -10919,7 +11318,7 @@ function ShimmerText(props) {
10919
11318
  logEvent('cleanup -> cancel animation');
10920
11319
  Animated.cancelAnimation(progress);
10921
11320
  };
10922
- }, [delay, duration, repeat, once, repeatDelay, progress, logEvent, debugFlag, isWeb, shouldAnimate, shouldRepeat]);
11321
+ }, [delay, duration, repeat, once, repeatDelay, progress, logEvent, debugFlag, isWeb, shouldAnimate, shouldRepeat, gradientModuleAvailable]);
10923
11322
  const handleLayout = React.useCallback((event) => {
10924
11323
  const { width, height } = event.nativeEvent.layout;
10925
11324
  setLayout((prev) => (prev.width === width && prev.height === height ? prev : { width, height }));
@@ -11005,6 +11404,9 @@ function ShimmerText(props) {
11005
11404
  };
11006
11405
  }, [isWeb, shouldAnimate, shouldRepeat, duration, delay, repeatDelay, direction, initialWebPosition, finalWebPosition, maxPosition, positionRange, minPosition]);
11007
11406
  const renderNative = () => {
11407
+ if (!gradientModuleAvailable || !OptionalLinearGradient$1) {
11408
+ return (jsxRuntime.jsx(Text, { ...textProps, color: baseColor, onLayout: externalOnLayout, style: style, children: content }));
11409
+ }
11008
11410
  if (layout.width === 0 || layout.height === 0) {
11009
11411
  return (jsxRuntime.jsx(Text, { ...textProps, color: baseColor, onLayout: handleLayout, style: style, children: content }));
11010
11412
  }
@@ -11017,7 +11419,7 @@ function ShimmerText(props) {
11017
11419
  height: layout.height,
11018
11420
  },
11019
11421
  gradientAnimatedStyle,
11020
- ], children: jsxRuntime.jsx(expoLinearGradient.LinearGradient, { colors: resolvedColors, locations: gradientLocations, start: { x: direction === 'rtl' ? 1 : 0, y: 0.5 }, end: { x: direction === 'rtl' ? 0 : 1, y: 0.5 }, style: styles$a.linearGradient }) }) }) })] }));
11422
+ ], children: jsxRuntime.jsx(OptionalLinearGradient$1, { colors: resolvedColors, locations: gradientLocations, start: { x: direction === 'rtl' ? 1 : 0, y: 0.5 }, end: { x: direction === 'rtl' ? 0 : 1, y: 0.5 }, style: styles$a.linearGradient }) }) }) })] }));
11021
11423
  };
11022
11424
  const renderWeb = () => {
11023
11425
  var _a;
@@ -11138,6 +11540,7 @@ const Heading4 = (props) => jsxRuntime.jsx(Title, { order: 4, ...props });
11138
11540
  const Heading5 = (props) => jsxRuntime.jsx(Title, { order: 5, ...props });
11139
11541
  const Heading6 = (props) => jsxRuntime.jsx(Title, { order: 6, ...props });
11140
11542
 
11543
+ const { LinearGradient: OptionalLinearGradient, hasLinearGradient } = resolveLinearGradient();
11141
11544
  const getIconButtonStyles = (theme, variant = 'filled', size = 'md', disabled = false, loading = false, height, radiusStyles, shadowStyles, customColor) => {
11142
11545
  const baseStyles = {
11143
11546
  flexDirection: 'row',
@@ -11302,6 +11705,7 @@ const IconButton = (allProps) => {
11302
11705
  ...restProps } = otherProps;
11303
11706
  const theme = useTheme();
11304
11707
  const { impactPressIn, impactPressOut } = useHaptics$1();
11708
+ const effectiveVariant = variant === 'gradient' && !hasLinearGradient ? 'filled' : variant;
11305
11709
  // Animation values
11306
11710
  const scaleAnim = React.useRef(new reactNative.Animated.Value(1)).current;
11307
11711
  const [isPressed, setIsPressed] = React.useState(false);
@@ -11312,9 +11716,9 @@ const IconButton = (allProps) => {
11312
11716
  // Create shadow styles
11313
11717
  const shadowStyles = getShadowStyles(shadowProps, theme);
11314
11718
  // Get button styles
11315
- const buttonStyles = React.useMemo(() => getIconButtonStyles(theme, variant, size, disabled, loading, height, radiusStyles, shadowStyles, colorVariant), [theme, variant, size, disabled, loading, height, radiusStyles, shadowStyles, colorVariant]);
11719
+ const buttonStyles = React.useMemo(() => getIconButtonStyles(theme, effectiveVariant, size, disabled, loading, height, radiusStyles, shadowStyles, colorVariant), [theme, effectiveVariant, size, disabled, loading, height, radiusStyles, shadowStyles, colorVariant]);
11316
11720
  // Get icon color
11317
- const resolvedIconColor = React.useMemo(() => getIconColor(theme, variant, colorVariant, iconColor), [theme, variant, colorVariant, iconColor]);
11721
+ const resolvedIconColor = React.useMemo(() => getIconColor(theme, effectiveVariant, colorVariant, iconColor), [theme, effectiveVariant, colorVariant, iconColor]);
11318
11722
  // Get icon size
11319
11723
  const resolvedIconSize = iconSize || getDefaultIconSize(size);
11320
11724
  const handlePressIn = () => {
@@ -11355,7 +11759,7 @@ const IconButton = (allProps) => {
11355
11759
  getLayoutStyles(layoutProps),
11356
11760
  { transform: [{ scale: scaleAnim }] },
11357
11761
  style,
11358
- ], children: variant === 'gradient' ? (jsxRuntime.jsx(expoLinearGradient.LinearGradient, { colors: [theme.colors.primary[4], theme.colors.primary[6]], start: { x: 0, y: 0 }, end: { x: 1, y: 1 }, style: [buttonStyles, { borderWidth: 0 }], children: jsxRuntime.jsx(reactNative.Pressable, { onPress: handlePress, onPressIn: handlePressIn, onPressOut: handlePressOut, onLayout: onLayout, disabled: disabled || loading, style: {
11762
+ ], children: variant === 'gradient' && hasLinearGradient ? (jsxRuntime.jsx(OptionalLinearGradient, { colors: [theme.colors.primary[4], theme.colors.primary[6]], start: { x: 0, y: 0 }, end: { x: 1, y: 1 }, style: [buttonStyles, { borderWidth: 0 }], children: jsxRuntime.jsx(reactNative.Pressable, { onPress: handlePress, onPressIn: handlePressIn, onPressOut: handlePressOut, onLayout: onLayout, disabled: disabled || loading, style: {
11359
11763
  width: '100%',
11360
11764
  height: '100%',
11361
11765
  alignItems: 'center',
@@ -11366,9 +11770,9 @@ const IconButton = (allProps) => {
11366
11770
  }, testID: testID, ...restProps, children: renderContent() }) })) : (jsxRuntime.jsx(reactNative.Pressable, { onPress: handlePress, onPressIn: handlePressIn, onPressOut: handlePressOut, onLayout: onLayout, disabled: disabled || loading, style: [
11367
11771
  buttonStyles,
11368
11772
  isPressed && !disabled && !loading && {
11369
- backgroundColor: variant === 'filled'
11773
+ backgroundColor: effectiveVariant === 'filled'
11370
11774
  ? theme.colors.primary[6]
11371
- : variant === 'secondary'
11775
+ : effectiveVariant === 'secondary'
11372
11776
  ? theme.colors.gray[2]
11373
11777
  : buttonStyles.backgroundColor,
11374
11778
  },
@@ -11414,7 +11818,8 @@ const getSeverityColor$1 = (severity) => {
11414
11818
  }
11415
11819
  };
11416
11820
  function ToastBase(props, ref) {
11417
- const { variant = 'filled', color = 'gray', sev, title, children, icon, withCloseButton = true, loading = false, closeButtonLabel = 'Close notification', onClose, visible = false, animationDuration = 300, autoHide = 4000, position = 'top', style, testID, radius, actions, dismissOnTap = false, maxWidth, persistent = false, animationConfig, swipeConfig, onSwipeDismiss, ...rest } = props;
11821
+ var _a, _b, _c;
11822
+ const { variant = 'filled', color = 'gray', sev, title, children, icon, withCloseButton = true, loading = false, closeButtonLabel = 'Close notification', onClose, visible = false, animationDuration = 300, autoHide = 4000, position = 'top', style, testID, radius, actions, dismissOnTap = false, maxWidth, persistent = false, animationConfig, swipeConfig, onSwipeDismiss, keepMounted = true, ...rest } = props;
11418
11823
  const { spacingProps, otherProps } = extractSpacingProps(rest);
11419
11824
  const spacingStyles = getSpacingStyles(spacingProps);
11420
11825
  const theme = useTheme();
@@ -11477,7 +11882,13 @@ function ToastBase(props, ref) {
11477
11882
  return { finalColor, isThemeColor, colorConfig };
11478
11883
  }, [sev, color, theme.colors]);
11479
11884
  const { finalColor, isThemeColor, colorConfig } = memoizedColors;
11480
- const [shouldRender, setShouldRender] = React.useState(visible);
11885
+ const shouldUnmountOnHide = !keepMounted;
11886
+ const [shouldRender, setShouldRender] = React.useState(shouldUnmountOnHide ? visible : true);
11887
+ React.useEffect(() => {
11888
+ if (!shouldUnmountOnHide) {
11889
+ setShouldRender(true);
11890
+ }
11891
+ }, [shouldUnmountOnHide]);
11481
11892
  const transformProperty = React.useMemo(() => (position === 'left' || position === 'right' ? 'translateX' : 'translateY'), [position]);
11482
11893
  // Animation styles
11483
11894
  const animatedStyle = Animated.useAnimatedStyle(() => {
@@ -11506,7 +11917,10 @@ function ToastBase(props, ref) {
11506
11917
  opacity: fadeAnimation.value,
11507
11918
  };
11508
11919
  }, [transformProperty, screenWidth, finalSwipeConfig, finalAnimationConfig]);
11509
- const { notifySuccess, notifyWarning, notifyError } = useHaptics$1();
11920
+ const haptics = useHaptics$1();
11921
+ const notifySuccess = (_a = haptics.notifySuccess) !== null && _a !== void 0 ? _a : (() => { });
11922
+ const notifyWarning = (_b = haptics.notifyWarning) !== null && _b !== void 0 ? _b : (() => { });
11923
+ const notifyError = (_c = haptics.notifyError) !== null && _c !== void 0 ? _c : (() => { });
11510
11924
  // Improved haptic feedback with error handling
11511
11925
  const triggerHapticFeedback = React.useCallback((severity) => {
11512
11926
  try {
@@ -11593,7 +12007,9 @@ function ToastBase(props, ref) {
11593
12007
  }, []);
11594
12008
  React.useEffect(() => {
11595
12009
  if (visible) {
11596
- setShouldRender(true);
12010
+ if (shouldUnmountOnHide) {
12011
+ setShouldRender(true);
12012
+ }
11597
12013
  // Reset swipe positions
11598
12014
  swipeX.value = 0;
11599
12015
  swipeY.value = 0;
@@ -11638,7 +12054,7 @@ function ToastBase(props, ref) {
11638
12054
  easing: Animated.Easing.in(Animated.Easing.back(1.1))
11639
12055
  }, (finished) => {
11640
12056
  'worklet';
11641
- if (finished) {
12057
+ if (finished && shouldUnmountOnHide) {
11642
12058
  Animated.runOnJS(handleShouldRenderUpdate)(false);
11643
12059
  }
11644
12060
  });
@@ -11652,7 +12068,7 @@ function ToastBase(props, ref) {
11652
12068
  clearTimeout(autoHideTimeoutRef.current);
11653
12069
  }
11654
12070
  };
11655
- }, [visible, finalAnimationConfig, autoHide, onClose, slideAnimation, fadeAnimation, swipeX, swipeY, position, persistent, triggerHapticFeedback, sev, getHiddenPosition, handleShouldRenderUpdate]);
12071
+ }, [visible, finalAnimationConfig, autoHide, onClose, slideAnimation, fadeAnimation, swipeX, swipeY, position, persistent, triggerHapticFeedback, sev, getHiddenPosition, handleShouldRenderUpdate, shouldUnmountOnHide]);
11656
12072
  const getToastStyles = () => {
11657
12073
  const baseStyles = {
11658
12074
  ...radiusStyles,
@@ -11777,7 +12193,7 @@ function ToastBase(props, ref) {
11777
12193
  const toastStyles = getToastStyles();
11778
12194
  const textColor = getTextColor();
11779
12195
  const iconColor = getIconColor();
11780
- if (!shouldRender) {
12196
+ if (shouldUnmountOnHide && !shouldRender) {
11781
12197
  return null;
11782
12198
  }
11783
12199
  // Check if swipe is enabled and gesture handler is available
@@ -14686,7 +15102,7 @@ const createInputStyles = (theme, isRTL = false) => {
14686
15102
  color: props.disabled ? theme.text.disabled : theme.text.primary,
14687
15103
  fontSize: px(theme.fontSizes.sm),
14688
15104
  fontWeight: '600',
14689
- marginBottom: 4
15105
+ marginBottom: 0
14690
15106
  },
14691
15107
  leftSection: {
14692
15108
  ...(isRTL ? { paddingLeft: px(theme.spacing.xs) } : { paddingRight: px(theme.spacing.xs) })
@@ -14714,8 +15130,15 @@ const FieldHeader = ({ label, description, required, withAsterisk, disabled, err
14714
15130
  const styles = getInputStyles({ size, disabled, error });
14715
15131
  if (!label && !description)
14716
15132
  return null;
14717
- const mb = marginBottom !== undefined ? marginBottom : (description ? 4 : 4);
14718
- return (jsxRuntime.jsxs(reactNative.View, { style: { marginBottom: mb }, testID: testID, children: [label && (jsxRuntime.jsxs(reactNative.Text, { style: styles.label, children: [label, required && withAsterisk && (jsxRuntime.jsx(reactNative.Text, { style: styles.required, accessibilityLabel: "required", children: ' *' }))] })), description && (jsxRuntime.jsx(reactNative.Text, { style: { fontSize: 12, color: theme.text.muted }, children: description }))] }));
15133
+ const hasDescription = Boolean(description);
15134
+ const resolvedMarginBottom = (() => {
15135
+ if (marginBottom !== undefined)
15136
+ return marginBottom;
15137
+ if (!hasDescription && !error)
15138
+ return 0;
15139
+ return 4;
15140
+ })();
15141
+ return (jsxRuntime.jsxs(reactNative.View, { style: { marginBottom: resolvedMarginBottom }, testID: testID, children: [label && (jsxRuntime.jsxs(reactNative.Text, { style: styles.label, children: [label, required && withAsterisk && (jsxRuntime.jsx(reactNative.Text, { style: styles.required, accessibilityLabel: "required", children: ' *' }))] })), description && (jsxRuntime.jsx(reactNative.Text, { style: { fontSize: 12, color: theme.text.muted }, children: description }))] }));
14719
15142
  };
14720
15143
 
14721
15144
  const TextInputBase = factory((props, ref) => {
@@ -17689,7 +18112,7 @@ const getCardStyles = (theme, variant = 'filled', padding, radiusStyles, shadowS
17689
18112
  ...(variant !== 'outline' && {
17690
18113
  ...DESIGN_TOKENS.shadow.sm && { boxShadow: DESIGN_TOKENS.shadow.sm },
17691
18114
  elevation: 1,
17692
- })
18115
+ }),
17693
18116
  };
17694
18117
  const variantStyles = {
17695
18118
  outline: {
@@ -18605,11 +19028,7 @@ const Search = factory((props, ref) => {
18605
19028
  fontSize: size === 'xs' ? 12 : size === 'sm' ? 14 : 16,
18606
19029
  }, children: placeholder }), jsxRuntime.jsx(Space, { w: 64 }), rightComponent || finalRight] }));
18607
19030
  }
18608
- return jsxRuntime.jsx(Input
18609
- // @ts-expect-error factory handles ref injection
18610
- , {
18611
- // @ts-expect-error factory handles ref injection
18612
- ref: ref, type: "search", value: internal.value, onChangeText: handleChange, onEnter: handleSubmit, placeholder: placeholder, size: size, radius: radius, leftSection: left, rightSection: finalRight, accessibilityLabel: accessibilityLabel, style: style });
19031
+ return jsxRuntime.jsx(Input, { ref: ref, type: "search", value: internal.value, onChangeText: handleChange, onEnter: handleSubmit, placeholder: placeholder, size: size, radius: radius, leftSection: left, rightSection: finalRight, accessibilityLabel: accessibilityLabel, style: style });
18613
19032
  });
18614
19033
  Search.displayName = 'Search';
18615
19034
 
@@ -18713,71 +19132,217 @@ const SIZE_CONFIG = {
18713
19132
  md: { fontSize: 'sm', padY: 8, padX: 12, gap: 10, radius: 8, minHeight: 38 },
18714
19133
  lg: { fontSize: 'md', padY: 10, padX: 14, gap: 12, radius: 10, minHeight: 44 },
18715
19134
  };
18716
- const MenuItemButton = (allProps) => {
19135
+ const MenuItemButton = React.forwardRef((allProps, ref) => {
18717
19136
  var _a;
18718
19137
  const { spacingProps, otherProps } = extractSpacingProps(allProps);
18719
- const { title, children, startIcon, endIcon, onPress, disabled = false, active = false, danger = false, fullWidth = true, size = 'sm', compact = false, rounded = false, style, onPressIn, onPressOut, onMouseDown, ...restProps } = otherProps;
19138
+ const { title, children, startIcon, endIcon, onPress, disabled = false, active = false, danger = false, fullWidth = true, size = 'sm', compact = false, rounded = false, style, onPressIn, onPressOut, onMouseDown, onMouseEnter, onMouseLeave, onHoverIn, onHoverOut, onFocus, onBlur, tone, hoverTone, activeTone, textColor: textColorOverride, hoverTextColor: hoverTextColorOverride, activeTextColor: activeTextColorOverride, testID, ...restProps } = otherProps;
18720
19139
  const theme = useTheme();
18721
19140
  const { isRTL } = useDirection();
18722
19141
  const spacingStyles = getSpacingStyles(spacingProps);
18723
19142
  const cfg = (_a = SIZE_CONFIG[size]) !== null && _a !== void 0 ? _a : SIZE_CONFIG.sm;
18724
19143
  const content = children || title;
18725
- const colors = React.useMemo(() => {
18726
- const base = {
18727
- text: theme.text.primary,
18728
- bg: 'transparent',
18729
- hoverBg: theme.colors.gray[1],
18730
- activeBg: theme.colors.primary[0],
18731
- activeText: theme.colors.primary[6],
18732
- dangerText: theme.colors.error[6],
18733
- dangerHoverBg: theme.colors.error[0],
18734
- dangerActiveBg: theme.colors.error[1],
18735
- };
18736
- if (danger) {
18737
- return {
18738
- ...base,
18739
- text: base.dangerText,
18740
- hoverBg: base.dangerHoverBg,
18741
- activeBg: base.dangerActiveBg,
18742
- activeText: base.dangerText,
18743
- };
18744
- }
18745
- if (active) {
18746
- return {
18747
- ...base,
18748
- bg: base.activeBg,
18749
- text: base.activeText,
18750
- };
19144
+ const [isHovered, setIsHovered] = React.useState(false);
19145
+ const [isPressed, setIsPressed] = React.useState(false);
19146
+ const resolveTone = React.useCallback((toneKey) => {
19147
+ if (danger)
19148
+ return 'danger';
19149
+ return toneKey !== null && toneKey !== void 0 ? toneKey : 'default';
19150
+ }, [danger]);
19151
+ const getPalette = React.useCallback((toneKey) => {
19152
+ var _a;
19153
+ const isDark = theme.colorScheme === 'dark';
19154
+ switch (toneKey) {
19155
+ case 'danger':
19156
+ return {
19157
+ text: theme.colors.error[6],
19158
+ bg: 'transparent',
19159
+ hoverBg: isDark ? theme.colors.error[3] : theme.colors.error[0],
19160
+ activeBg: isDark ? theme.colors.error[4] : theme.colors.error[1],
19161
+ activeText: theme.colors.error[6],
19162
+ };
19163
+ case 'success':
19164
+ return {
19165
+ text: isDark ? theme.colors.success[2] : theme.colors.success[6],
19166
+ bg: 'transparent',
19167
+ hoverBg: isDark ? theme.colors.success[4] : theme.colors.success[0],
19168
+ activeBg: isDark ? theme.colors.success[5] : theme.colors.success[1],
19169
+ activeText: isDark ? theme.colors.success[2] : theme.colors.success[6],
19170
+ };
19171
+ case 'warning':
19172
+ return {
19173
+ text: isDark ? theme.colors.warning[2] : theme.colors.warning[6],
19174
+ bg: 'transparent',
19175
+ hoverBg: isDark ? theme.colors.warning[4] : theme.colors.warning[0],
19176
+ activeBg: isDark ? theme.colors.warning[5] : theme.colors.warning[1],
19177
+ activeText: isDark ? theme.colors.warning[2] : theme.colors.warning[6],
19178
+ };
19179
+ default:
19180
+ return {
19181
+ text: theme.text.primary,
19182
+ bg: 'transparent',
19183
+ hoverBg: isDark ? theme.colors.gray[3] : theme.colors.gray[1],
19184
+ activeBg: isDark ? theme.colors.primary[4] : theme.colors.primary[0],
19185
+ activeText: isDark ? ((_a = theme.text.onPrimary) !== null && _a !== void 0 ? _a : theme.text.primary) : theme.colors.primary[6],
19186
+ };
18751
19187
  }
18752
- return base;
18753
- }, [theme, active, danger]);
18754
- const horizontalPad = cfg.padX;
18755
- const verticalPad = compact ? Math.max(2, cfg.padY - 4) : cfg.padY;
18756
- return (jsxRuntime.jsx(reactNative.View, { style: [fullWidth && { width: '100%' }, spacingStyles], children: jsxRuntime.jsxs(reactNative.Pressable, { disabled: disabled, onPress: disabled ? undefined : onPress, onPressIn: disabled ? undefined : onPressIn, onPressOut: disabled ? undefined : onPressOut, ...(reactNative.Platform.OS === 'web' && onMouseDown ? { onMouseDown } : {}), style: ({ pressed }) => [
18757
- {
18758
- flexDirection: isRTL ? 'row-reverse' : 'row',
18759
- alignItems: 'center',
18760
- minHeight: cfg.minHeight,
18761
- paddingHorizontal: horizontalPad,
18762
- paddingVertical: verticalPad,
18763
- width: fullWidth ? '100%' : undefined,
18764
- borderRadius: rounded ? 999 : cfg.radius,
18765
- backgroundColor: pressed ? colors.activeBg : colors.bg,
18766
- opacity: disabled ? 0.45 : 1,
18767
- gap: cfg.gap,
18768
- },
18769
- active && !danger && !pressed && { backgroundColor: colors.activeBg },
18770
- style
18771
- ], ...restProps, children: [startIcon && (jsxRuntime.jsx(reactNative.View, { style: { opacity: disabled ? 0.6 : 1 }, children: startIcon })), content && (typeof content === 'string' ? (jsxRuntime.jsx(Text, { size: cfg.fontSize, weight: active ? '600' : '500', color: danger ? colors.text : active ? colors.text : theme.text.primary, style: { flex: 1, overflow: 'hidden' }, children: content })) : content), endIcon && (jsxRuntime.jsx(reactNative.View, { style: isRTL ? { marginRight: cfg.gap, opacity: disabled ? 0.6 : 1 } : { marginLeft: cfg.gap, opacity: disabled ? 0.6 : 1 }, children: endIcon }))] }) }));
18772
- };
19188
+ }, [theme]);
19189
+ const baseTone = resolveTone(tone);
19190
+ const hoverToneResolved = resolveTone(hoverTone);
19191
+ const activeToneResolved = resolveTone(activeTone !== null && activeTone !== void 0 ? activeTone : tone);
19192
+ const basePalette = React.useMemo(() => getPalette(baseTone), [baseTone, getPalette]);
19193
+ const hoverPalette = React.useMemo(() => getPalette(hoverToneResolved), [hoverToneResolved, getPalette]);
19194
+ const activePalette = React.useMemo(() => getPalette(activeToneResolved), [activeToneResolved, getPalette]);
19195
+ const buttonBaseStyle = React.useMemo(() => ({
19196
+ flexDirection: isRTL ? 'row-reverse' : 'row',
19197
+ alignItems: 'center',
19198
+ minHeight: cfg.minHeight,
19199
+ paddingHorizontal: cfg.padX,
19200
+ paddingVertical: compact ? Math.max(2, cfg.padY - 4) : cfg.padY,
19201
+ width: fullWidth ? '100%' : undefined,
19202
+ borderRadius: rounded ? 999 : cfg.radius,
19203
+ opacity: disabled ? 0.45 : 1,
19204
+ gap: cfg.gap,
19205
+ backgroundColor: basePalette.bg,
19206
+ }), [isRTL, cfg, compact, fullWidth, rounded, disabled, basePalette.bg]);
19207
+ const handlePressIn = React.useCallback((event) => {
19208
+ if (!disabled)
19209
+ setIsPressed(true);
19210
+ onPressIn === null || onPressIn === void 0 ? void 0 : onPressIn(event);
19211
+ }, [disabled, onPressIn]);
19212
+ const handlePressOut = React.useCallback((event) => {
19213
+ if (!disabled)
19214
+ setIsPressed(false);
19215
+ onPressOut === null || onPressOut === void 0 ? void 0 : onPressOut(event);
19216
+ }, [disabled, onPressOut]);
19217
+ const handleHoverIn = React.useCallback((event) => {
19218
+ if (!disabled)
19219
+ setIsHovered(true);
19220
+ onHoverIn === null || onHoverIn === void 0 ? void 0 : onHoverIn(event);
19221
+ }, [disabled, onHoverIn]);
19222
+ const handleHoverOut = React.useCallback((event) => {
19223
+ if (!disabled)
19224
+ setIsHovered(false);
19225
+ onHoverOut === null || onHoverOut === void 0 ? void 0 : onHoverOut(event);
19226
+ }, [disabled, onHoverOut]);
19227
+ const handleMouseEnter = React.useCallback((event) => {
19228
+ if (!disabled)
19229
+ setIsHovered(true);
19230
+ onMouseEnter === null || onMouseEnter === void 0 ? void 0 : onMouseEnter(event);
19231
+ }, [disabled, onMouseEnter]);
19232
+ const handleMouseLeave = React.useCallback((event) => {
19233
+ if (!disabled)
19234
+ setIsHovered(false);
19235
+ onMouseLeave === null || onMouseLeave === void 0 ? void 0 : onMouseLeave(event);
19236
+ }, [disabled, onMouseLeave]);
19237
+ const isActive = active || isPressed;
19238
+ const baseText = textColorOverride !== null && textColorOverride !== void 0 ? textColorOverride : basePalette.text;
19239
+ const hoverText = hoverTextColorOverride !== null && hoverTextColorOverride !== void 0 ? hoverTextColorOverride : hoverPalette.text;
19240
+ const activeText = activeTextColorOverride !== null && activeTextColorOverride !== void 0 ? activeTextColorOverride : activePalette.activeText;
19241
+ const textColor = disabled
19242
+ ? theme.text.disabled
19243
+ : isActive
19244
+ ? activeText
19245
+ : isHovered
19246
+ ? hoverText
19247
+ : baseText;
19248
+ return (jsxRuntime.jsx(reactNative.View, { ref: ref, style: [fullWidth && { width: '100%' }, spacingStyles], children: jsxRuntime.jsxs(reactNative.Pressable, { disabled: disabled, onPress: disabled ? undefined : onPress, onPressIn: disabled ? undefined : handlePressIn, onPressOut: disabled ? undefined : handlePressOut, ...(reactNative.Platform.OS === 'web' && onMouseDown ? { onMouseDown } : {}), ...(reactNative.Platform.OS === 'web' ? { onMouseEnter: handleMouseEnter, onMouseLeave: handleMouseLeave } : {}), onHoverIn: handleHoverIn, onHoverOut: handleHoverOut, onFocus: onFocus, onBlur: onBlur, testID: testID, style: (pressableState) => {
19249
+ const { pressed } = pressableState;
19250
+ const hovered = pressableState.hovered || isHovered;
19251
+ const effectiveActive = isActive || pressed;
19252
+ return [
19253
+ buttonBaseStyle,
19254
+ !disabled && effectiveActive && { backgroundColor: activePalette.activeBg },
19255
+ !disabled && !effectiveActive && hovered && { backgroundColor: hoverPalette.hoverBg },
19256
+ style
19257
+ ];
19258
+ }, ...restProps, children: [startIcon && (jsxRuntime.jsx(reactNative.View, { style: { opacity: disabled ? 0.6 : 1 }, children: startIcon })), content && (typeof content === 'string' ? (jsxRuntime.jsx(Text, { size: cfg.fontSize, weight: active ? '600' : '500', color: textColor, style: { flex: 1, overflow: 'hidden' }, children: content })) : content), endIcon && (jsxRuntime.jsx(reactNative.View, { style: isRTL ? { marginRight: cfg.gap, opacity: disabled ? 0.6 : 1 } : { marginLeft: cfg.gap, opacity: disabled ? 0.6 : 1 }, children: endIcon }))] }) }));
19259
+ });
18773
19260
  MenuItemButton.displayName = 'MenuItemButton';
18774
19261
 
19262
+ function useMenuStyles() {
19263
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q;
19264
+ const theme = useTheme();
19265
+ const getPaletteColor = (palette, index) => {
19266
+ if (Array.isArray(palette)) {
19267
+ return palette[index];
19268
+ }
19269
+ return undefined;
19270
+ };
19271
+ const surfacePalette = (_a = theme.colors) === null || _a === void 0 ? void 0 : _a.surface;
19272
+ const grayPalette = (_b = theme.colors) === null || _b === void 0 ? void 0 : _b.gray;
19273
+ const lightSurfaceColor = (_h = (_g = (_e = (_c = getPaletteColor(surfacePalette, 4)) !== null && _c !== void 0 ? _c : (typeof ((_d = theme.backgrounds) === null || _d === void 0 ? void 0 : _d.surface) === 'string' ? theme.backgrounds.surface : undefined)) !== null && _e !== void 0 ? _e : (typeof ((_f = theme.backgrounds) === null || _f === void 0 ? void 0 : _f.base) === 'string' ? theme.backgrounds.base : undefined)) !== null && _g !== void 0 ? _g : getPaletteColor(grayPalette, 0)) !== null && _h !== void 0 ? _h : '#ffffff';
19274
+ const darkSurfaceColor = (_l = (_j = getPaletteColor(surfacePalette, 3)) !== null && _j !== void 0 ? _j : (typeof ((_k = theme.backgrounds) === null || _k === void 0 ? void 0 : _k.elevated) === 'string' ? theme.backgrounds.elevated : undefined)) !== null && _l !== void 0 ? _l : lightSurfaceColor;
19275
+ const fallbackRadius = (_q = (_o = (_m = theme.radii) === null || _m === void 0 ? void 0 : _m.md) !== null && _o !== void 0 ? _o : (_p = theme.radii) === null || _p === void 0 ? void 0 : _p.sm) !== null && _q !== void 0 ? _q : '8';
19276
+ const parsedRadius = typeof fallbackRadius === 'number'
19277
+ ? fallbackRadius
19278
+ : parseInt(`${fallbackRadius}`, 10) || 8;
19279
+ const dropdown = {
19280
+ backgroundColor: theme.colorScheme === 'dark' ? darkSurfaceColor : lightSurfaceColor,
19281
+ borderRadius: parsedRadius,
19282
+ // borderWidth: 3, // Temporarily increased for debugging
19283
+ // borderColor: '#ff0000', // Temporarily red for debugging
19284
+ boxShadow: '0 4px 8px rgba(0, 0, 0, 0.1)',
19285
+ elevation: 8,
19286
+ minWidth: 180,
19287
+ maxWidth: 320,
19288
+ overflow: 'hidden',
19289
+ };
19290
+ const item = {
19291
+ flexDirection: 'row',
19292
+ alignItems: 'center',
19293
+ paddingVertical: 8,
19294
+ paddingHorizontal: 12,
19295
+ minHeight: 36,
19296
+ };
19297
+ const itemPressed = {
19298
+ backgroundColor: theme.colors.gray[1],
19299
+ };
19300
+ const itemDisabled = {
19301
+ opacity: 0.5,
19302
+ };
19303
+ const itemDanger = {
19304
+ backgroundColor: theme.colors.error[0],
19305
+ };
19306
+ const itemDangerPressed = {
19307
+ backgroundColor: theme.colors.error[1],
19308
+ };
19309
+ const label = {
19310
+ paddingVertical: 6,
19311
+ paddingHorizontal: 12,
19312
+ };
19313
+ const divider = {
19314
+ height: 1,
19315
+ // backgroundColor: theme.colors.gray[2],
19316
+ // marginVertical: 4,
19317
+ };
19318
+ const leftSection = {
19319
+ marginRight: 8,
19320
+ };
19321
+ const rightSection = {
19322
+ marginLeft: 'auto',
19323
+ paddingLeft: 12,
19324
+ };
19325
+ return {
19326
+ dropdown,
19327
+ item,
19328
+ itemPressed,
19329
+ itemDisabled,
19330
+ itemDanger,
19331
+ itemDangerPressed,
19332
+ label,
19333
+ divider,
19334
+ leftSection,
19335
+ rightSection,
19336
+ };
19337
+ }
19338
+
18775
19339
  const Select = factory((allProps, ref) => {
18776
19340
  var _a;
18777
19341
  const { spacingProps, otherProps: propsAfterSpacing } = extractSpacingProps(allProps);
18778
19342
  const { layoutProps, otherProps } = extractLayoutProps(propsAfterSpacing);
18779
19343
  const { value: valueProp, defaultValue, onChange, options, placeholder = 'Select…', size = 'md', radius = 'md', disabled, label, helperText, description, error, renderOption, fullWidth, maxHeight = 260, closeOnSelect = true, clearable, clearButtonLabel, onClear } = otherProps;
18780
19344
  const theme = useTheme();
19345
+ const menuStyles = useMenuStyles();
18781
19346
  const { isRTL } = useDirection();
18782
19347
  const [open, setOpen] = React.useState(false);
18783
19348
  const [value, setValue] = React.useState((_a = valueProp !== null && valueProp !== void 0 ? valueProp : defaultValue) !== null && _a !== void 0 ? _a : null);
@@ -18785,6 +19350,8 @@ const Select = factory((allProps, ref) => {
18785
19350
  const triggerRef = React.useRef(null);
18786
19351
  const { openOverlay, closeOverlay, updateOverlay } = useOverlay();
18787
19352
  const overlayIdRef = React.useRef(null);
19353
+ const menuSignatureRef = React.useRef('');
19354
+ const menuLayoutRef = React.useRef(null);
18788
19355
  // keep controlled
18789
19356
  React.useEffect(() => { if (valueProp !== undefined)
18790
19357
  setValue(valueProp); }, [valueProp]);
@@ -18802,34 +19369,28 @@ const Select = factory((allProps, ref) => {
18802
19369
  const selectedOption = options.find((o) => o.value === value) || null;
18803
19370
  const showClearButton = !!(clearable && selectedOption && !disabled);
18804
19371
  const clearLabel = clearButtonLabel || 'Clear selection';
19372
+ const optionRowHeight = React.useMemo(() => {
19373
+ switch (size) {
19374
+ case 'xs':
19375
+ return 30;
19376
+ case 'sm':
19377
+ return 34;
19378
+ case 'lg':
19379
+ return 44;
19380
+ case 'xl':
19381
+ return 48;
19382
+ default:
19383
+ return 38;
19384
+ }
19385
+ }, [size]);
18805
19386
  const close = React.useCallback(() => {
18806
19387
  setOpen(false);
18807
19388
  if (overlayIdRef.current) {
18808
19389
  closeOverlay(overlayIdRef.current);
18809
19390
  overlayIdRef.current = null;
18810
19391
  }
19392
+ menuLayoutRef.current = null;
18811
19393
  }, [closeOverlay]);
18812
- const computeAnchor = React.useCallback(() => {
18813
- var _a;
18814
- if (reactNative.Platform.OS !== 'web')
18815
- return undefined;
18816
- if (!triggerRef.current)
18817
- return undefined;
18818
- try {
18819
- const node = triggerRef.current._node || triggerRef.current;
18820
- const rect = (_a = node === null || node === void 0 ? void 0 : node.getBoundingClientRect) === null || _a === void 0 ? void 0 : _a.call(node);
18821
- if (rect) {
18822
- setTriggerWidth(rect.width);
18823
- // In RTL, use rect.right instead of rect.left to align the dropdown
18824
- const xPos = isRTL ? rect.right - rect.width : rect.left;
18825
- return { x: xPos, y: rect.bottom + 4, width: rect.width, height: rect.height };
18826
- }
18827
- }
18828
- catch (_e) {
18829
- /* measurement failures are non-fatal on web */
18830
- }
18831
- return undefined;
18832
- }, [isRTL]);
18833
19394
  const measureTrigger = React.useCallback(() => {
18834
19395
  var _a, _b;
18835
19396
  if (reactNative.Platform.OS === 'web')
@@ -18845,29 +19406,167 @@ const Select = factory((allProps, ref) => {
18845
19406
  /* native measurement failures can be ignored safely */
18846
19407
  }
18847
19408
  }, []);
18848
- const getMenuContent = React.useCallback(() => menu, [ /* menu recomputed below */]);
18849
- const openPortal = React.useCallback(() => {
19409
+ const resolveDropdownPosition = React.useCallback(async (preferredSize) => {
19410
+ if (reactNative.Platform.OS !== 'web')
19411
+ return null;
19412
+ if (!triggerRef.current)
19413
+ return null;
19414
+ try {
19415
+ const anchorRect = await measureElement(triggerRef);
19416
+ if (!anchorRect || anchorRect.height === 0) {
19417
+ return null;
19418
+ }
19419
+ const optionCount = options.length || 1;
19420
+ const estimatedHeight = Math.min(maxHeight, Math.max(optionRowHeight * optionCount, optionRowHeight));
19421
+ const estimatedWidth = (anchorRect.width && anchorRect.width > 0) ? anchorRect.width : (triggerWidth || 200);
19422
+ const overlayWidth = (preferredSize === null || preferredSize === void 0 ? void 0 : preferredSize.width) && preferredSize.width > 0
19423
+ ? preferredSize.width
19424
+ : estimatedWidth;
19425
+ const overlayHeight = (preferredSize === null || preferredSize === void 0 ? void 0 : preferredSize.height) && preferredSize.height > 0
19426
+ ? Math.min(preferredSize.height, maxHeight)
19427
+ : estimatedHeight;
19428
+ const overlaySize = {
19429
+ width: overlayWidth,
19430
+ height: overlayHeight,
19431
+ };
19432
+ const position = calculateOverlayPositionEnhanced(anchorRect, overlaySize, {
19433
+ placement: 'auto',
19434
+ offset: 6,
19435
+ strategy: 'fixed',
19436
+ flip: true,
19437
+ shift: true,
19438
+ boundary: 8,
19439
+ });
19440
+ const finalWidth = position.finalWidth || overlaySize.width;
19441
+ const finalHeight = position.finalHeight || overlaySize.height;
19442
+ setTriggerWidth(prev => {
19443
+ if (prev !== null && Math.abs(prev - finalWidth) < 1) {
19444
+ return prev;
19445
+ }
19446
+ return finalWidth;
19447
+ });
19448
+ return {
19449
+ position,
19450
+ overlaySize: {
19451
+ width: finalWidth,
19452
+ height: finalHeight,
19453
+ },
19454
+ };
19455
+ }
19456
+ catch (error) {
19457
+ console.warn('Select: failed to resolve dropdown position', error);
19458
+ return null;
19459
+ }
19460
+ }, [options, maxHeight, optionRowHeight, triggerWidth]);
19461
+ const handleMenuLayoutChange = React.useCallback(async (layout) => {
19462
+ const previous = menuLayoutRef.current;
19463
+ if (previous) {
19464
+ const widthDiff = Math.abs(previous.width - (layout.width || 0));
19465
+ const heightDiff = Math.abs(previous.height - (layout.height || 0));
19466
+ if (widthDiff < 1 && heightDiff < 1) {
19467
+ return;
19468
+ }
19469
+ }
19470
+ menuLayoutRef.current = layout;
19471
+ if (!open || reactNative.Platform.OS !== 'web' || !overlayIdRef.current)
19472
+ return;
19473
+ const resolved = await resolveDropdownPosition({ width: layout.width, height: layout.height });
19474
+ if (!resolved)
19475
+ return;
19476
+ const { position, overlaySize } = resolved;
19477
+ updateOverlay(overlayIdRef.current, {
19478
+ anchor: {
19479
+ x: position.x,
19480
+ y: position.y,
19481
+ width: overlaySize.width,
19482
+ height: overlaySize.height,
19483
+ },
19484
+ });
19485
+ }, [open, resolveDropdownPosition, updateOverlay]);
19486
+ const handleMenuLayoutEvent = React.useCallback((event) => {
19487
+ const { width, height } = event.nativeEvent.layout || {};
19488
+ if (width === undefined || height === undefined)
19489
+ return;
19490
+ handleMenuLayoutChange({ width, height });
19491
+ }, [handleMenuLayoutChange]);
19492
+ const handleSelect = React.useCallback((opt) => {
19493
+ if (opt.disabled)
19494
+ return;
19495
+ if (valueProp === undefined)
19496
+ setValue(opt.value);
19497
+ onChange === null || onChange === void 0 ? void 0 : onChange(opt.value, opt);
19498
+ if (closeOnSelect)
19499
+ close();
19500
+ }, [onChange, valueProp, close, closeOnSelect]);
19501
+ const menu = React.useMemo(() => {
19502
+ const resolvedWidth = triggerWidth && triggerWidth > 0 ? triggerWidth : undefined;
19503
+ return (jsxRuntime.jsx(reactNative.View, { style: resolvedWidth ? { width: resolvedWidth, minWidth: resolvedWidth } : undefined, onLayout: reactNative.Platform.OS === 'web' ? handleMenuLayoutEvent : undefined, children: jsxRuntime.jsx(ListGroup, { variant: "default", size: "sm", style: {
19504
+ ...menuStyles.dropdown,
19505
+ maxHeight,
19506
+ ...(resolvedWidth ? { width: resolvedWidth, minWidth: resolvedWidth } : {}),
19507
+ }, children: jsxRuntime.jsx(reactNative.FlatList, { data: options, keyExtractor: o => String(o.value), renderItem: ({ item }) => {
19508
+ const selected = item.value === value;
19509
+ if (renderOption) {
19510
+ return jsxRuntime.jsx(reactNative.View, { children: renderOption(item, false, selected) });
19511
+ }
19512
+ const successPalette = theme.colors.success || [];
19513
+ const highlightColor = theme.colorScheme === 'dark'
19514
+ ? successPalette[4] || successPalette[5] || '#30D158'
19515
+ : successPalette[6] || successPalette[5] || '#2f9e44';
19516
+ const baseTextColor = item.disabled ? theme.text.disabled : theme.text.primary;
19517
+ const accentTextColor = item.disabled ? theme.text.disabled : highlightColor;
19518
+ return (jsxRuntime.jsx(MenuItemButton, { onPress: () => handleSelect(item), disabled: !!item.disabled, active: selected, tone: selected ? 'success' : 'default', hoverTone: "success", textColor: baseTextColor, hoverTextColor: accentTextColor, activeTextColor: accentTextColor, compact: true, rounded: false, style: { borderRadius: 0 }, children: item.label }));
19519
+ }, ItemSeparatorComponent: renderOption ? undefined : ListGroupDivider, style: { maxHeight }, bounces: false }) }) }));
19520
+ }, [menuStyles.dropdown, maxHeight, triggerWidth, options, value, renderOption, handleSelect, handleMenuLayoutEvent]);
19521
+ const getMenuContent = React.useCallback(() => menu, [menu]);
19522
+ const menuSignature = React.useMemo(() => {
19523
+ const optionSignature = options
19524
+ .map(opt => `${String(opt.value)}-${opt.label}-${opt.disabled ? '1' : '0'}`)
19525
+ .join('|');
19526
+ const valueSignature = typeof value === 'object' && value !== null
19527
+ ? JSON.stringify(value)
19528
+ : String(value !== null && value !== void 0 ? value : '');
19529
+ const triggerSig = triggerWidth != null ? `tw:${Math.round(triggerWidth)}` : 'tw:auto';
19530
+ return `${optionSignature}|value:${valueSignature}|${triggerSig}|render:${renderOption ? 'custom' : 'default'}`;
19531
+ }, [options, value, triggerWidth, renderOption]);
19532
+ const openPortal = React.useCallback(async () => {
18850
19533
  if (disabled || reactNative.Platform.OS !== 'web')
18851
19534
  return;
18852
- const anchor = computeAnchor();
19535
+ const resolved = await resolveDropdownPosition();
19536
+ if (!resolved) {
19537
+ close();
19538
+ return;
19539
+ }
19540
+ const { position, overlaySize } = resolved;
18853
19541
  const id = openOverlay({
18854
19542
  content: getMenuContent(),
18855
- anchor,
18856
- width: anchor === null || anchor === void 0 ? void 0 : anchor.width,
19543
+ anchor: {
19544
+ x: position.x,
19545
+ y: position.y,
19546
+ width: overlaySize.width,
19547
+ height: overlaySize.height,
19548
+ },
18857
19549
  strategy: 'fixed',
18858
19550
  zIndex: 1300,
18859
19551
  closeOnClickOutside: true,
18860
- onClose: () => { setOpen(false); }
19552
+ closeOnEscape: true,
19553
+ onClose: () => {
19554
+ setOpen(false);
19555
+ }
18861
19556
  });
18862
19557
  overlayIdRef.current = id;
18863
- }, [disabled, computeAnchor, openOverlay, getMenuContent]);
19558
+ menuSignatureRef.current = menuSignature;
19559
+ }, [disabled, resolveDropdownPosition, openOverlay, getMenuContent, close, menuSignature]);
18864
19560
  const toggle = React.useCallback(() => {
18865
19561
  if (disabled)
18866
19562
  return;
18867
19563
  setOpen(o => {
18868
19564
  const next = !o;
18869
- if (next && reactNative.Platform.OS === 'web')
18870
- openPortal();
19565
+ if (next && reactNative.Platform.OS === 'web') {
19566
+ openPortal().catch(() => {
19567
+ close();
19568
+ });
19569
+ }
18871
19570
  if (next && reactNative.Platform.OS !== 'web')
18872
19571
  measureTrigger();
18873
19572
  if (!next)
@@ -18876,21 +19575,37 @@ const Select = factory((allProps, ref) => {
18876
19575
  });
18877
19576
  }, [disabled, openPortal, close, measureTrigger]);
18878
19577
  React.useLayoutEffect(() => {
18879
- if (open && reactNative.Platform.OS === 'web' && overlayIdRef.current) {
18880
- const anchor = computeAnchor();
18881
- if (anchor)
18882
- updateOverlay(overlayIdRef.current, { anchor });
18883
- }
18884
- }, [open, value, options, computeAnchor, updateOverlay]);
18885
- const handleSelect = React.useCallback((opt) => {
18886
- if (opt.disabled)
19578
+ if (!open || reactNative.Platform.OS !== 'web' || !overlayIdRef.current)
18887
19579
  return;
18888
- if (valueProp === undefined)
18889
- setValue(opt.value);
18890
- onChange === null || onChange === void 0 ? void 0 : onChange(opt.value, opt);
18891
- if (closeOnSelect)
18892
- close();
18893
- }, [onChange, valueProp, close, closeOnSelect]);
19580
+ let cancelled = false;
19581
+ (async () => {
19582
+ const resolved = await resolveDropdownPosition();
19583
+ if (!resolved || cancelled)
19584
+ return;
19585
+ const { position, overlaySize } = resolved;
19586
+ updateOverlay(overlayIdRef.current, {
19587
+ anchor: {
19588
+ x: position.x,
19589
+ y: position.y,
19590
+ width: overlaySize.width,
19591
+ height: overlaySize.height,
19592
+ },
19593
+ });
19594
+ })();
19595
+ return () => {
19596
+ cancelled = true;
19597
+ };
19598
+ }, [open, value, options, resolveDropdownPosition, updateOverlay]);
19599
+ React.useEffect(() => {
19600
+ if (!open || reactNative.Platform.OS !== 'web' || !overlayIdRef.current)
19601
+ return;
19602
+ if (menuSignatureRef.current === menuSignature)
19603
+ return;
19604
+ menuSignatureRef.current = menuSignature;
19605
+ updateOverlay(overlayIdRef.current, {
19606
+ content: getMenuContent(),
19607
+ });
19608
+ }, [open, menuSignature, getMenuContent, updateOverlay]);
18894
19609
  const handleClear = React.useCallback((event) => {
18895
19610
  var _a;
18896
19611
  (_a = event === null || event === void 0 ? void 0 : event.stopPropagation) === null || _a === void 0 ? void 0 : _a.call(event);
@@ -18903,22 +19618,6 @@ const Select = factory((allProps, ref) => {
18903
19618
  onClear === null || onClear === void 0 ? void 0 : onClear();
18904
19619
  close();
18905
19620
  }, [disabled, valueProp, onChange, onClear, close]);
18906
- const menu = (jsxRuntime.jsx(ListGroup, { variant: "default", size: "sm", style: {
18907
- maxHeight,
18908
- width: triggerWidth || undefined,
18909
- minWidth: triggerWidth || undefined,
18910
- }, children: jsxRuntime.jsx(reactNative.FlatList, { data: options, keyExtractor: o => String(o.value), renderItem: ({ item, index }) => {
18911
- const selected = item.value === value;
18912
- if (renderOption) {
18913
- return jsxRuntime.jsx(reactNative.View, { children: renderOption(item, false, selected) });
18914
- }
18915
- const isLast = index === options.length - 1;
18916
- return (jsxRuntime.jsx(MenuItemButton, { onPress: () => handleSelect(item), disabled: !!item.disabled, active: selected, compact: true, rounded: false, style: {
18917
- borderRadius: 0,
18918
- borderBottomWidth: isLast ? 0 : reactNative.StyleSheet.hairlineWidth,
18919
- borderBottomColor: theme.colorScheme === 'dark' ? theme.colors.gray[4] : theme.colors.gray[2],
18920
- }, children: item.label }));
18921
- }, style: { maxHeight }, bounces: false }) }));
18922
19621
  const fieldContent = selectedOption ? (jsxRuntime.jsx(reactNative.Text, { style: { color: disabled ? theme.text.disabled : theme.text.primary }, children: selectedOption.label })) : (jsxRuntime.jsx(reactNative.Text, { style: { color: disabled ? theme.text.disabled : theme.text.muted }, children: placeholder }));
18923
19622
  return (jsxRuntime.jsxs(reactNative.View, { style: [defaultMinWidthStyle, fullWidthStyle, spacingStyles, layoutStyles,], children: [jsxRuntime.jsx(FieldHeader, { label: label, description: description, disabled: disabled, error: !!error, size: size }), jsxRuntime.jsxs(reactNative.Pressable, { ref: (node) => { triggerRef.current = node; if (typeof ref === 'function')
18924
19623
  ref(node);
@@ -18936,36 +19635,6 @@ const Select = factory((allProps, ref) => {
18936
19635
  });
18937
19636
 
18938
19637
  const debounce = require('lodash.debounce');
18939
- const HighlightedText = ({ text, query, highlight = false }) => {
18940
- const theme = useTheme();
18941
- const baseStyle = {
18942
- color: theme.text.primary,
18943
- fontSize: 15,
18944
- fontFamily: theme.fontFamily,
18945
- };
18946
- if (!highlight || !query) {
18947
- return (jsxRuntime.jsx(Text, { as: "span", variant: "span", style: baseStyle, children: text }));
18948
- }
18949
- const safeQuery = query.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
18950
- const regex = new RegExp(`(${safeQuery})`, 'gi');
18951
- const parts = text.split(regex);
18952
- const normalizedQuery = query.toLowerCase();
18953
- return (jsxRuntime.jsx(Text, { as: "span", variant: "span", style: baseStyle, children: parts.map((part, index) => {
18954
- var _a, _b, _c, _d;
18955
- if (!part) {
18956
- return null;
18957
- }
18958
- if (part.toLowerCase() === normalizedQuery) {
18959
- return (jsxRuntime.jsx(Text, { as: "span", variant: "span", style: {
18960
- backgroundColor: ((_a = theme.states) === null || _a === void 0 ? void 0 : _a.highlightBackground) || ((_b = theme.colors.highlight) === null || _b === void 0 ? void 0 : _b[2]) || theme.colors.primary[1],
18961
- fontWeight: '600',
18962
- color: ((_c = theme.states) === null || _c === void 0 ? void 0 : _c.highlightText) || ((_d = theme.colors.highlight) === null || _d === void 0 ? void 0 : _d[8]) || theme.colors.primary[7],
18963
- fontFamily: theme.fontFamily,
18964
- }, children: part }, `match-${index}`));
18965
- }
18966
- return (jsxRuntime.jsx(React.Fragment, { children: part }, `text-${index}`));
18967
- }) }));
18968
- };
18969
19638
  const DEFAULT_FALLBACK_PLACEMENTS$1 = ['top-start', 'top-end', 'top', 'bottom-start', 'bottom-end', 'bottom'];
18970
19639
  const defaultFilter = (item, query) => {
18971
19640
  return item.label.toLowerCase().includes(query.toLowerCase()) ||
@@ -19322,6 +19991,7 @@ const AutoComplete = factory((props, ref) => {
19322
19991
  }, [multiSelect, onSelect, useModal, displayProperty, onChangeText]);
19323
19992
  // Default item renderer - use stable reference to prevent loops
19324
19993
  const defaultRenderItem = React.useCallback((item, index, isSelected = false) => {
19994
+ const highlightQuery = highlightMatches ? currentQueryRef.current : undefined;
19325
19995
  return (jsxRuntime.jsx(MenuItemButton, { onPress: () => handleSelectSuggestion(item), disabled: item.disabled, active: isSelected, compact: true, rounded: false, style: [styles.menuItemButton, suggestionItemStyle], ...(reactNative.Platform.OS === 'web' ? {
19326
19996
  onMouseDown: (event) => {
19327
19997
  if (event === null || event === void 0 ? void 0 : event.preventDefault) {
@@ -19331,7 +20001,7 @@ const AutoComplete = factory((props, ref) => {
19331
20001
  event.stopPropagation();
19332
20002
  }
19333
20003
  },
19334
- } : {}), children: jsxRuntime.jsx(HighlightedText, { text: item.label, query: currentQueryRef.current, highlight: highlightMatches }) }));
20004
+ } : {}), children: jsxRuntime.jsx(Highlight, { highlight: highlightQuery, children: item.label }) }));
19335
20005
  }, [handleSelectSuggestion, highlightMatches, suggestionItemStyle]);
19336
20006
  // Render item with enhanced parameters - use refs to prevent infinite loops
19337
20007
  const renderSuggestionItem = React.useCallback((item, index) => {
@@ -19732,6 +20402,7 @@ const AutoComplete = factory((props, ref) => {
19732
20402
  });
19733
20403
  AutoComplete.displayName = 'AutoComplete';
19734
20404
 
20405
+ const { DocumentPicker: DocumentPickerModule, hasDocumentPicker } = resolveDocumentPicker();
19735
20406
  const isDocumentPickerAsset = (file) => typeof (file === null || file === void 0 ? void 0 : file.uri) === 'string';
19736
20407
  const getFileMetadata = (file) => {
19737
20408
  var _a, _b, _c, _d, _e;
@@ -19854,7 +20525,7 @@ maxFiles = 10, onUpload, onProgress, onFilesChange, onFileRemove, PreviewCompone
19854
20525
  });
19855
20526
  }, [imagePreview]);
19856
20527
  const processFiles = React.useCallback(async (fileList) => {
19857
- var _a;
20528
+ var _a, _b, _c;
19858
20529
  const filesToProcess = Array.isArray(fileList)
19859
20530
  ? [...fileList]
19860
20531
  : Array.from(fileList !== null && fileList !== void 0 ? fileList : []);
@@ -19873,7 +20544,7 @@ maxFiles = 10, onUpload, onProgress, onFilesChange, onFileRemove, PreviewCompone
19873
20544
  let previewUrl = await createFilePreview(file);
19874
20545
  const metadata = getFileMetadata(file);
19875
20546
  if (!previewUrl && reactNative.Platform.OS !== 'web' && isDocumentPickerAsset(file) && ((_a = metadata.type) === null || _a === void 0 ? void 0 : _a.startsWith('image/'))) {
19876
- previewUrl = metadata.uri;
20547
+ previewUrl = (_b = metadata.uri) !== null && _b !== void 0 ? _b : undefined;
19877
20548
  }
19878
20549
  const fileInput = {
19879
20550
  file,
@@ -19881,7 +20552,7 @@ maxFiles = 10, onUpload, onProgress, onFilesChange, onFileRemove, PreviewCompone
19881
20552
  name: metadata.name,
19882
20553
  size: metadata.size,
19883
20554
  type: metadata.type,
19884
- uri: metadata.uri,
20555
+ uri: (_c = metadata.uri) !== null && _c !== void 0 ? _c : undefined,
19885
20556
  previewUrl,
19886
20557
  status: validationError ? 'error' : 'pending',
19887
20558
  error: validationError || undefined,
@@ -19937,9 +20608,14 @@ maxFiles = 10, onUpload, onProgress, onFilesChange, onFileRemove, PreviewCompone
19937
20608
  }
19938
20609
  return;
19939
20610
  }
20611
+ const picker = DocumentPickerModule;
20612
+ if (!hasDocumentPicker || !(picker === null || picker === void 0 ? void 0 : picker.getDocumentAsync)) {
20613
+ console.warn('FileInput: expo-document-picker not installed, native file picker is disabled.');
20614
+ return;
20615
+ }
19940
20616
  try {
19941
20617
  const pickerTypes = accept.filter(type => !type.startsWith('.'));
19942
- const result = await DocumentPicker__namespace.getDocumentAsync({
20618
+ const result = await picker.getDocumentAsync({
19943
20619
  multiple,
19944
20620
  copyToCacheDirectory: true,
19945
20621
  type: pickerTypes.length > 0 ? pickerTypes : undefined,
@@ -22154,14 +22830,12 @@ const TimePicker = ({ value, defaultValue, onChange, format = 24, withSeconds =
22154
22830
  marginBottom: 12,
22155
22831
  textAlign: 'center',
22156
22832
  }, children: "Minute" }), jsxRuntime.jsx(reactNative.FlatList, { data: minuteOptions, keyExtractor: (item) => 'm-' + item, renderItem: ({ item }) => renderNumber(item, internal.minutes === item, () => commit({ minutes: item }, autoClose && !withSeconds)), style: [listCommon, { borderRadius: 12, backgroundColor: theme.colors.gray[1] }], contentContainerStyle: { paddingVertical: 8 }, showsVerticalScrollIndicator: false })] }), withSeconds && (jsxRuntime.jsxs(reactNative.View, { style: { width: columnWidth, alignItems: 'center' }, children: [jsxRuntime.jsx(Text, { size: "sm", weight: "medium", style: {
22157
- color: theme.colors.gray[6],
22158
22833
  marginBottom: 12,
22159
22834
  textAlign: 'center',
22160
22835
  }, children: "Second" }), jsxRuntime.jsx(reactNative.FlatList, { data: secondOptions, keyExtractor: (item) => 's-' + item, renderItem: ({ item }) => {
22161
22836
  var _a;
22162
22837
  return renderNumber(item, ((_a = internal.seconds) !== null && _a !== void 0 ? _a : 0) === item, () => commit({ seconds: item }, autoClose));
22163
22838
  }, style: [listCommon, { borderRadius: 12, backgroundColor: theme.colors.gray[1] }], contentContainerStyle: { paddingVertical: 8 }, showsVerticalScrollIndicator: false })] })), is12h && (jsxRuntime.jsxs(reactNative.View, { style: { alignItems: 'center' }, children: [jsxRuntime.jsx(Text, { size: "sm", weight: "medium", style: {
22164
- color: theme.colors.gray[6],
22165
22839
  marginBottom: 12,
22166
22840
  textAlign: 'center',
22167
22841
  }, children: "Period" }), jsxRuntime.jsx(Flex, { align: "center", justify: "center", style: {
@@ -23865,68 +24539,6 @@ const Breadcrumbs = factory((props, ref) => {
23865
24539
  });
23866
24540
  Breadcrumbs.displayName = 'Breadcrumbs';
23867
24541
 
23868
- function useMenuStyles() {
23869
- const theme = useTheme();
23870
- const dropdown = {
23871
- backgroundColor: theme.colorScheme === 'dark' ? theme.colors.surface[3] : theme.colors.surface[4],
23872
- borderRadius: parseInt(theme.radii.md),
23873
- // borderWidth: 3, // Temporarily increased for debugging
23874
- // borderColor: '#ff0000', // Temporarily red for debugging
23875
- boxShadow: '0 4px 8px rgba(0, 0, 0, 0.1)',
23876
- elevation: 8,
23877
- minWidth: 180,
23878
- maxWidth: 320,
23879
- overflow: 'hidden',
23880
- };
23881
- const item = {
23882
- flexDirection: 'row',
23883
- alignItems: 'center',
23884
- paddingVertical: 8,
23885
- paddingHorizontal: 12,
23886
- minHeight: 36,
23887
- };
23888
- const itemPressed = {
23889
- backgroundColor: theme.colors.gray[1],
23890
- };
23891
- const itemDisabled = {
23892
- opacity: 0.5,
23893
- };
23894
- const itemDanger = {
23895
- backgroundColor: theme.colors.error[0],
23896
- };
23897
- const itemDangerPressed = {
23898
- backgroundColor: theme.colors.error[1],
23899
- };
23900
- const label = {
23901
- paddingVertical: 6,
23902
- paddingHorizontal: 12,
23903
- };
23904
- const divider = {
23905
- height: 1,
23906
- // backgroundColor: theme.colors.gray[2],
23907
- // marginVertical: 4,
23908
- };
23909
- const leftSection = {
23910
- marginRight: 8,
23911
- };
23912
- const rightSection = {
23913
- marginLeft: 'auto',
23914
- paddingLeft: 12,
23915
- };
23916
- return {
23917
- dropdown,
23918
- item,
23919
- itemPressed,
23920
- itemDisabled,
23921
- itemDanger,
23922
- itemDangerPressed,
23923
- label,
23924
- divider,
23925
- leftSection,
23926
- rightSection,
23927
- };
23928
- }
23929
-
23930
24542
  const MenuContext = React.createContext(null);
23931
24543
  function useMenuContext() {
23932
24544
  const context = React.useContext(MenuContext);
@@ -24155,7 +24767,7 @@ function MenuBase(props, ref) {
24155
24767
  // Create a callback ref that works better with React Native Web
24156
24768
  const triggerCallbackRef = React.useCallback((node) => {
24157
24769
  triggerRef.current = node;
24158
- console.log('Trigger ref set to:', node);
24770
+ // console.log('Trigger ref set to:', node);
24159
24771
  }, []);
24160
24772
  const enhancedTrigger = React.isValidElement(triggerElement)
24161
24773
  ? React.cloneElement(triggerElement, {
@@ -24185,7 +24797,7 @@ function MenuBase(props, ref) {
24185
24797
  else if (ref) {
24186
24798
  ref.current = node;
24187
24799
  }
24188
- console.log('Combined ref set to:', node);
24800
+ // console.log('Combined ref set to:', node);
24189
24801
  }, [ref]);
24190
24802
  return (jsxRuntime.jsx(MenuContext.Provider, { value: { closeMenu: handleClose, opened: isOpened }, children: jsxRuntime.jsx(reactNative.View, { ref: combinedRef, style: getSpacingStyles(extractSpacingProps(spacingProps).spacingProps), testID: testID, ...(trigger === 'contextmenu' && reactNative.Platform.OS === 'web'
24191
24803
  ? {
@@ -24202,16 +24814,14 @@ function MenuBase(props, ref) {
24202
24814
  }
24203
24815
  : {}), onLayout: () => {
24204
24816
  // Force a re-render to ensure ref is available
24205
- if (containerRef.current) {
24206
- console.log('Menu container onLayout - container ref available:', containerRef.current);
24207
- }
24817
+ if (containerRef.current) ;
24208
24818
  }, children: enhancedTrigger }) }));
24209
24819
  }
24210
24820
  // Menu.Item component
24211
24821
  function MenuItemBase(props, ref) {
24212
- const { children, onPress, disabled = false, leftSection, rightSection, color = 'default', closeMenuOnClick = true, testID, ...spacingProps } = props;
24822
+ const { spacingProps, otherProps } = extractSpacingProps(props);
24823
+ const { children, onPress, disabled = false, leftSection, rightSection, color = 'default', closeMenuOnClick = true, testID, ...restProps } = otherProps;
24213
24824
  const { closeMenu } = useMenuContext();
24214
- const theme = useTheme();
24215
24825
  const handlePress = React.useCallback(() => {
24216
24826
  if (disabled)
24217
24827
  return;
@@ -24219,7 +24829,14 @@ function MenuItemBase(props, ref) {
24219
24829
  if (closeMenuOnClick)
24220
24830
  closeMenu();
24221
24831
  }, [disabled, onPress, closeMenuOnClick, closeMenu]);
24222
- return (jsxRuntime.jsx(ListGroupItem, { ref: ref, onPress: handlePress, disabled: disabled, danger: color === 'danger', leftSection: leftSection, rightSection: rightSection, textStyle: { color: color === 'danger' ? theme.colors.error[6] : theme.text.primary }, style: {}, ...spacingProps, testID: testID, children: children }));
24832
+ const tone = color === 'danger'
24833
+ ? 'danger'
24834
+ : color === 'success'
24835
+ ? 'success'
24836
+ : color === 'warning'
24837
+ ? 'warning'
24838
+ : 'default';
24839
+ return (jsxRuntime.jsx(MenuItemButton, { ref: ref, onPress: handlePress, disabled: disabled, startIcon: leftSection, endIcon: rightSection, tone: tone, testID: testID, ...spacingProps, ...restProps, children: children }));
24223
24840
  }
24224
24841
  // Menu.Label component
24225
24842
  function MenuLabelBase(props, ref) {
@@ -25764,6 +26381,467 @@ function Blockquote({ children, variant = 'default', size = 'md', color, quoteIc
25764
26381
  return content;
25765
26382
  }
25766
26383
 
26384
+ const createPopoverStyles = (theme) => (params) => {
26385
+ const radiusStyles = createRadiusStyles(params.radius);
26386
+ const shadowStyles = createShadowStyles(params.shadow, theme, 'popover');
26387
+ return reactNative.StyleSheet.create({
26388
+ wrapper: {
26389
+ position: 'relative',
26390
+ alignSelf: 'flex-start',
26391
+ overflow: 'visible',
26392
+ ...shadowStyles,
26393
+ },
26394
+ dropdown: {
26395
+ backgroundColor: theme.backgrounds.surface,
26396
+ borderColor: theme.backgrounds.border,
26397
+ borderWidth: 1,
26398
+ ...radiusStyles,
26399
+ overflow: 'hidden',
26400
+ minWidth: 0,
26401
+ },
26402
+ arrow: {
26403
+ position: 'absolute',
26404
+ width: params.arrowSize * 2,
26405
+ height: params.arrowSize * 2,
26406
+ backgroundColor: theme.backgrounds.surface,
26407
+ transform: [{ rotate: '45deg' }],
26408
+ },
26409
+ });
26410
+ };
26411
+
26412
+ const PopoverContext = React.createContext(null);
26413
+ function usePopoverContext(component) {
26414
+ const context = React.useContext(PopoverContext);
26415
+ if (!context) {
26416
+ throw new Error(`${component} must be used within Popover`);
26417
+ }
26418
+ return context;
26419
+ }
26420
+ const DEFAULT_ARROW_SIZE = 7;
26421
+ const PopoverBase = (props, ref) => {
26422
+ var _a;
26423
+ const { children, opened: controlledOpened, defaultOpened = false, onChange, onOpen, onClose, onDismiss, disabled = false, closeOnClickOutside = true, closeOnEscape = true, clickOutsideEvents, // currently not implemented
26424
+ trapFocus = false, keepMounted = false, returnFocus = false, withinPortal = true, withOverlay = false, overlayProps, width, minWidth, minHeight, maxWidth, maxHeight, radius, shadow, zIndex = 300, position = 'bottom', offset = 8, floatingStrategy = 'fixed', middlewares, preventPositionChangeWhenVisible = false, hideDetached = true, viewport, fallbackPlacements, boundary, withRoles = true, id, withArrow = false, arrowSize = DEFAULT_ARROW_SIZE, arrowRadius = 0, arrowOffset = 5, arrowPosition = 'center', onPositionChange, testID, ...rest } = props;
26425
+ const theme = useTheme();
26426
+ const { spacingProps } = extractSpacingProps(rest);
26427
+ const spacingStyles = getSpacingStyles(spacingProps);
26428
+ const isControlled = controlledOpened !== undefined;
26429
+ const [internalOpened, setInternalOpened] = React.useState(defaultOpened);
26430
+ const [dropdownState, setDropdownState] = React.useState(null);
26431
+ const opened = isControlled ? !!controlledOpened : internalOpened;
26432
+ const openedRef = React.useRef(opened);
26433
+ const closingReasonRef = React.useRef(null);
26434
+ const anchorMeasurementsRef = React.useRef(null);
26435
+ React.useEffect(() => {
26436
+ openedRef.current = opened;
26437
+ }, [opened]);
26438
+ const resolvedOffset = typeof offset === 'number' ? offset : (_a = offset === null || offset === void 0 ? void 0 : offset.mainAxis) !== null && _a !== void 0 ? _a : 8;
26439
+ const resolvedFlip = preventPositionChangeWhenVisible
26440
+ ? false
26441
+ : (middlewares === null || middlewares === void 0 ? void 0 : middlewares.flip) === false
26442
+ ? false
26443
+ : true;
26444
+ const resolvedShift = preventPositionChangeWhenVisible
26445
+ ? false
26446
+ : (middlewares === null || middlewares === void 0 ? void 0 : middlewares.shift) === false
26447
+ ? false
26448
+ : true;
26449
+ const resolvedStrategy = floatingStrategy !== null && floatingStrategy !== void 0 ? floatingStrategy : 'fixed';
26450
+ const { position: positioningResult, anchorRef, popoverRef, showOverlay, hideOverlay, updatePosition } = useDropdownPositioning({
26451
+ isOpen: opened && !disabled && !!dropdownState,
26452
+ placement: position,
26453
+ offset: resolvedOffset,
26454
+ strategy: resolvedStrategy,
26455
+ flip: resolvedFlip,
26456
+ shift: resolvedShift,
26457
+ boundary,
26458
+ fallbackPlacements,
26459
+ viewport,
26460
+ onClose: () => handleOverlayClose('dismiss'),
26461
+ closeOnClickOutside,
26462
+ closeOnEscape,
26463
+ });
26464
+ const popoverStyles = React.useMemo(() => createPopoverStyles(theme)({
26465
+ radius,
26466
+ shadow,
26467
+ arrowSize,
26468
+ }), [theme, radius, shadow, arrowSize]);
26469
+ const layoutUpdateTimeoutRef = React.useRef(null);
26470
+ const hasMeasuredLayoutRef = React.useRef(false);
26471
+ // Defer re-measuring to the next frame so overlay position uses final layout metrics
26472
+ const schedulePositionUpdate = React.useCallback(() => {
26473
+ if (layoutUpdateTimeoutRef.current) {
26474
+ clearTimeout(layoutUpdateTimeoutRef.current);
26475
+ }
26476
+ layoutUpdateTimeoutRef.current = setTimeout(() => {
26477
+ updatePosition();
26478
+ }, 16);
26479
+ }, [updatePosition]);
26480
+ React.useEffect(() => {
26481
+ return () => {
26482
+ if (layoutUpdateTimeoutRef.current) {
26483
+ clearTimeout(layoutUpdateTimeoutRef.current);
26484
+ layoutUpdateTimeoutRef.current = null;
26485
+ }
26486
+ };
26487
+ }, []);
26488
+ React.useEffect(() => {
26489
+ if (!opened) {
26490
+ hasMeasuredLayoutRef.current = false;
26491
+ if (layoutUpdateTimeoutRef.current) {
26492
+ clearTimeout(layoutUpdateTimeoutRef.current);
26493
+ layoutUpdateTimeoutRef.current = null;
26494
+ }
26495
+ }
26496
+ }, [opened]);
26497
+ React.useEffect(() => {
26498
+ hasMeasuredLayoutRef.current = false;
26499
+ }, [dropdownState]);
26500
+ const handleDropdownLayout = React.useCallback(() => {
26501
+ if (hasMeasuredLayoutRef.current) {
26502
+ return;
26503
+ }
26504
+ hasMeasuredLayoutRef.current = true;
26505
+ schedulePositionUpdate();
26506
+ }, [schedulePositionUpdate]);
26507
+ const updateAnchorMeasurements = React.useCallback(async () => {
26508
+ if (!anchorRef.current)
26509
+ return;
26510
+ try {
26511
+ const rect = await measureElement(anchorRef);
26512
+ anchorMeasurementsRef.current = { width: rect.width, height: rect.height };
26513
+ }
26514
+ catch (_a) {
26515
+ // noop – measurement failed (likely not mounted yet)
26516
+ }
26517
+ }, [anchorRef]);
26518
+ const commitOpen = React.useCallback(() => {
26519
+ if (openedRef.current || disabled)
26520
+ return;
26521
+ if (!isControlled) {
26522
+ setInternalOpened(true);
26523
+ }
26524
+ onChange === null || onChange === void 0 ? void 0 : onChange(true);
26525
+ onOpen === null || onOpen === void 0 ? void 0 : onOpen();
26526
+ openedRef.current = true;
26527
+ }, [disabled, isControlled, onChange, onOpen]);
26528
+ const commitClose = React.useCallback((reason) => {
26529
+ if (!openedRef.current)
26530
+ return;
26531
+ if (!isControlled) {
26532
+ setInternalOpened(false);
26533
+ }
26534
+ onChange === null || onChange === void 0 ? void 0 : onChange(false);
26535
+ onClose === null || onClose === void 0 ? void 0 : onClose();
26536
+ if (reason === 'dismiss') {
26537
+ onDismiss === null || onDismiss === void 0 ? void 0 : onDismiss();
26538
+ }
26539
+ openedRef.current = false;
26540
+ }, [isControlled, onChange, onClose, onDismiss]);
26541
+ const handleOverlayClose = React.useCallback((reason) => {
26542
+ var _a;
26543
+ const closingReason = (_a = closingReasonRef.current) !== null && _a !== void 0 ? _a : reason;
26544
+ closingReasonRef.current = null;
26545
+ commitClose(closingReason);
26546
+ }, [commitClose]);
26547
+ const openPopover = React.useCallback(() => {
26548
+ if (disabled)
26549
+ return;
26550
+ closingReasonRef.current = null;
26551
+ commitOpen();
26552
+ }, [commitOpen, disabled]);
26553
+ const closePopover = React.useCallback((reason = 'programmatic') => {
26554
+ if (!openedRef.current)
26555
+ return;
26556
+ closingReasonRef.current = reason;
26557
+ hideOverlay();
26558
+ }, [hideOverlay]);
26559
+ const togglePopover = React.useCallback(() => {
26560
+ if (openedRef.current) {
26561
+ closePopover('programmatic');
26562
+ }
26563
+ else {
26564
+ openPopover();
26565
+ }
26566
+ }, [closePopover, openPopover]);
26567
+ React.useEffect(() => {
26568
+ if (opened) {
26569
+ updateAnchorMeasurements();
26570
+ }
26571
+ }, [opened, updateAnchorMeasurements]);
26572
+ React.useEffect(() => {
26573
+ if (!opened) {
26574
+ closingReasonRef.current = null;
26575
+ hideOverlay();
26576
+ if (returnFocus && anchorRef.current && typeof anchorRef.current.focus === 'function') {
26577
+ anchorRef.current.focus();
26578
+ }
26579
+ return;
26580
+ }
26581
+ if (!dropdownState)
26582
+ return;
26583
+ updatePosition();
26584
+ }, [opened, dropdownState, updatePosition, hideOverlay, anchorRef, returnFocus]);
26585
+ React.useEffect(() => {
26586
+ var _a;
26587
+ if (!opened || !dropdownState) {
26588
+ hideOverlay();
26589
+ return;
26590
+ }
26591
+ if (!positioningResult) {
26592
+ return;
26593
+ }
26594
+ const computedFinalWidth = positioningResult.finalWidth && positioningResult.finalWidth > 0
26595
+ ? positioningResult.finalWidth
26596
+ : undefined;
26597
+ const widthOverride = (() => {
26598
+ var _a, _b;
26599
+ if (typeof width === 'number')
26600
+ return width;
26601
+ if (width === 'target') {
26602
+ return (_b = (_a = anchorMeasurementsRef.current) === null || _a === void 0 ? void 0 : _a.width) !== null && _b !== void 0 ? _b : computedFinalWidth;
26603
+ }
26604
+ return computedFinalWidth;
26605
+ })();
26606
+ const sizeStyles = {};
26607
+ if (typeof minWidth === 'number')
26608
+ sizeStyles.minWidth = minWidth;
26609
+ if (typeof minHeight === 'number')
26610
+ sizeStyles.minHeight = minHeight;
26611
+ if (typeof maxWidth === 'number')
26612
+ sizeStyles.maxWidth = maxWidth;
26613
+ const resolvedMaxHeight = typeof maxHeight === 'number' ? maxHeight : (_a = positioningResult.maxHeight) !== null && _a !== void 0 ? _a : maxHeight;
26614
+ if (typeof resolvedMaxHeight === 'number')
26615
+ sizeStyles.maxHeight = resolvedMaxHeight;
26616
+ const dropdownStyle = [popoverStyles.dropdown, dropdownState.style, sizeStyles];
26617
+ const content = (jsxRuntime.jsxs(reactNative.View, { ref: popoverRef, style: [popoverStyles.wrapper, widthOverride ? { width: widthOverride } : null], pointerEvents: dropdownState.trapFocus ? 'auto' : 'box-none', testID: dropdownState.testID, onLayout: handleDropdownLayout, ...dropdownState.containerProps, children: [jsxRuntime.jsx(reactNative.View, { style: dropdownStyle, children: dropdownState.content }), withArrow && (jsxRuntime.jsx(reactNative.View, { style: getArrowStyle(positioningResult.placement, arrowSize, arrowRadius, arrowOffset, arrowPosition, theme) }))] }));
26618
+ showOverlay(content, {
26619
+ width: widthOverride,
26620
+ maxHeight: resolvedMaxHeight,
26621
+ zIndex,
26622
+ });
26623
+ onPositionChange === null || onPositionChange === void 0 ? void 0 : onPositionChange(positioningResult.placement);
26624
+ }, [opened, dropdownState, positioningResult, popoverRef, showOverlay, hideOverlay, popoverStyles.dropdown, popoverStyles.wrapper, width, maxHeight, minWidth, minHeight, maxWidth, withArrow, arrowSize, arrowRadius, arrowOffset, arrowPosition, theme, zIndex, onPositionChange, schedulePositionUpdate]);
26625
+ React.useEffect(() => {
26626
+ return () => {
26627
+ hideOverlay();
26628
+ };
26629
+ }, [hideOverlay]);
26630
+ const registerDropdown = React.useCallback((dropdown) => {
26631
+ setDropdownState(dropdown);
26632
+ }, []);
26633
+ const unregisterDropdown = React.useCallback(() => {
26634
+ if (!keepMounted) {
26635
+ setDropdownState(null);
26636
+ }
26637
+ }, [keepMounted]);
26638
+ const targetId = React.useMemo(() => id ? `${id}-target` : `popover-target-${Math.random().toString(36).slice(2)}`, [id]);
26639
+ const dropdownId = React.useMemo(() => id ? `${id}-dropdown` : `popover-dropdown-${Math.random().toString(36).slice(2)}`, [id]);
26640
+ const contextValue = React.useMemo(() => ({
26641
+ opened,
26642
+ open: openPopover,
26643
+ close: () => closePopover('programmatic'),
26644
+ toggle: togglePopover,
26645
+ registerDropdown,
26646
+ unregisterDropdown,
26647
+ anchorRef,
26648
+ targetId,
26649
+ dropdownId,
26650
+ withRoles,
26651
+ disabled,
26652
+ returnFocus,
26653
+ }), [opened, openPopover, closePopover, togglePopover, registerDropdown, unregisterDropdown, anchorRef, targetId, dropdownId, withRoles, disabled, returnFocus]);
26654
+ const setContainerRef = React.useCallback((node) => {
26655
+ if (typeof ref === 'function') {
26656
+ ref(node);
26657
+ }
26658
+ else if (ref && 'current' in ref) {
26659
+ ref.current = node;
26660
+ }
26661
+ }, [ref]);
26662
+ return (jsxRuntime.jsx(PopoverContext.Provider, { value: contextValue, children: jsxRuntime.jsx(reactNative.View, { ref: setContainerRef, style: spacingStyles, testID: testID, children: children }) }));
26663
+ };
26664
+ function mergeRefs(...refs) {
26665
+ return (value) => {
26666
+ refs.forEach(ref => {
26667
+ if (!ref)
26668
+ return;
26669
+ if (typeof ref === 'function') {
26670
+ ref(value);
26671
+ }
26672
+ else if ('current' in ref) {
26673
+ ref.current = value;
26674
+ }
26675
+ });
26676
+ };
26677
+ }
26678
+ const PopoverTargetBase = (props, ref) => {
26679
+ var _a;
26680
+ const { children, popupType = 'dialog', refProp = 'ref', targetProps } = props;
26681
+ const context = usePopoverContext('Popover.Target');
26682
+ if (!React.isValidElement(children)) {
26683
+ throw new Error('Popover.Target expects a single React element child');
26684
+ }
26685
+ const childProps = children.props;
26686
+ const sanitizedTargetProps = { ...(targetProps !== null && targetProps !== void 0 ? targetProps : {}) };
26687
+ let externalTargetRef;
26688
+ if (refProp && Object.prototype.hasOwnProperty.call(sanitizedTargetProps, refProp)) {
26689
+ externalTargetRef = sanitizedTargetProps[refProp];
26690
+ delete sanitizedTargetProps[refProp];
26691
+ }
26692
+ const accessibilityProps = context.withRoles && reactNative.Platform.OS === 'web'
26693
+ ? {
26694
+ role: (_a = childProps.role) !== null && _a !== void 0 ? _a : 'button',
26695
+ 'aria-haspopup': popupType,
26696
+ 'aria-expanded': context.opened,
26697
+ 'aria-controls': context.opened ? context.dropdownId : undefined,
26698
+ id: context.targetId,
26699
+ }
26700
+ : { id: context.targetId };
26701
+ const composedRef = mergeRefs(children.ref, externalTargetRef);
26702
+ const triggerHandlers = {};
26703
+ triggerHandlers.onPress = (...args) => {
26704
+ const tgt = targetProps;
26705
+ if (tgt && typeof tgt.onPress === 'function') {
26706
+ tgt.onPress(...args);
26707
+ }
26708
+ if (typeof childProps.onPress === 'function') {
26709
+ childProps.onPress(...args);
26710
+ }
26711
+ context.toggle();
26712
+ };
26713
+ if (reactNative.Platform.OS === 'web') {
26714
+ triggerHandlers.onKeyDown = (event) => {
26715
+ const tgt = targetProps;
26716
+ if (tgt && typeof tgt.onKeyDown === 'function') {
26717
+ tgt.onKeyDown(event);
26718
+ }
26719
+ if (typeof childProps.onKeyDown === 'function') {
26720
+ childProps.onKeyDown(event);
26721
+ }
26722
+ if (event.defaultPrevented)
26723
+ return;
26724
+ if (event.key === 'Escape' && context.opened) {
26725
+ context.close();
26726
+ }
26727
+ if ((event.key === 'Enter' || event.key === ' ') && !context.opened) {
26728
+ event.preventDefault();
26729
+ context.open();
26730
+ }
26731
+ };
26732
+ }
26733
+ const dynamicRefProp = { [refProp]: composedRef };
26734
+ delete sanitizedTargetProps.onPress;
26735
+ delete sanitizedTargetProps.onKeyDown;
26736
+ const mergedProps = {
26737
+ ...sanitizedTargetProps,
26738
+ ...triggerHandlers,
26739
+ ...accessibilityProps,
26740
+ ...dynamicRefProp,
26741
+ };
26742
+ if (context.disabled) {
26743
+ mergedProps.disabled = true;
26744
+ }
26745
+ const anchorWrapperRef = mergeRefs(context.anchorRef, ref);
26746
+ return (jsxRuntime.jsx(reactNative.View, { ref: anchorWrapperRef, collapsable: false, children: React.cloneElement(children, mergedProps) }));
26747
+ };
26748
+ const PopoverDropdownBase = (props, _ref) => {
26749
+ const { children, trapFocus = false, keepMounted, style, testID, ...rest } = props;
26750
+ const context = usePopoverContext('Popover.Dropdown');
26751
+ const dropdownValue = React.useMemo(() => ({
26752
+ content: children,
26753
+ style,
26754
+ trapFocus,
26755
+ keepMounted,
26756
+ testID,
26757
+ containerProps: rest,
26758
+ }), [children, rest, style, trapFocus, keepMounted, testID]);
26759
+ React.useEffect(() => {
26760
+ context.registerDropdown(dropdownValue);
26761
+ return () => context.unregisterDropdown();
26762
+ }, [context, dropdownValue]);
26763
+ if (keepMounted) {
26764
+ return (jsxRuntime.jsx(reactNative.View, { style: { display: 'none' }, children: children }));
26765
+ }
26766
+ return null;
26767
+ };
26768
+ function getArrowStyle(placement, arrowSize, arrowRadius, arrowOffset, arrowPosition, theme) {
26769
+ if (reactNative.Platform.OS !== 'web') {
26770
+ return {
26771
+ width: 0,
26772
+ height: 0,
26773
+ opacity: 0,
26774
+ };
26775
+ }
26776
+ const base = {
26777
+ position: 'absolute',
26778
+ width: arrowSize * 2,
26779
+ height: arrowSize * 2,
26780
+ backgroundColor: theme.backgrounds.surface,
26781
+ transform: [{ rotate: '45deg' }],
26782
+ borderRadius: arrowRadius,
26783
+ borderColor: theme.backgrounds.border,
26784
+ borderWidth: 1,
26785
+ };
26786
+ const [side, alignment] = placement.split('-');
26787
+ switch (side) {
26788
+ case 'top':
26789
+ return {
26790
+ ...base,
26791
+ bottom: -arrowSize,
26792
+ left: alignment === 'end'
26793
+ ? `calc(100% - ${(arrowPosition === 'side' ? arrowOffset : arrowSize)}px)`
26794
+ : alignment === 'start'
26795
+ ? (arrowPosition === 'side' ? arrowOffset : arrowSize)
26796
+ : '50%',
26797
+ marginLeft: alignment || arrowPosition === 'side' ? 0 : -arrowSize,
26798
+ };
26799
+ case 'bottom':
26800
+ return {
26801
+ ...base,
26802
+ top: -arrowSize,
26803
+ left: alignment === 'end'
26804
+ ? `calc(100% - ${(arrowPosition === 'side' ? arrowOffset : arrowSize)}px)`
26805
+ : alignment === 'start'
26806
+ ? (arrowPosition === 'side' ? arrowOffset : arrowSize)
26807
+ : '50%',
26808
+ marginLeft: alignment || arrowPosition === 'side' ? 0 : -arrowSize,
26809
+ };
26810
+ case 'left':
26811
+ return {
26812
+ ...base,
26813
+ right: -arrowSize,
26814
+ top: alignment === 'end'
26815
+ ? `calc(100% - ${(arrowPosition === 'side' ? arrowOffset : arrowSize)}px)`
26816
+ : alignment === 'start'
26817
+ ? (arrowPosition === 'side' ? arrowOffset : arrowSize)
26818
+ : '50%',
26819
+ marginTop: alignment || arrowPosition === 'side' ? 0 : -arrowSize,
26820
+ };
26821
+ case 'right':
26822
+ return {
26823
+ ...base,
26824
+ left: -arrowSize,
26825
+ top: alignment === 'end'
26826
+ ? `calc(100% - ${(arrowPosition === 'side' ? arrowOffset : arrowSize)}px)`
26827
+ : alignment === 'start'
26828
+ ? (arrowPosition === 'side' ? arrowOffset : arrowSize)
26829
+ : '50%',
26830
+ marginTop: alignment || arrowPosition === 'side' ? 0 : -arrowSize,
26831
+ };
26832
+ default:
26833
+ return base;
26834
+ }
26835
+ }
26836
+ const Popover = factory(PopoverBase);
26837
+ const PopoverTarget = factory(PopoverTargetBase);
26838
+ const PopoverDropdown = factory(PopoverDropdownBase);
26839
+ Popover.Target = PopoverTarget;
26840
+ Popover.Dropdown = PopoverDropdown;
26841
+ Popover.displayName = 'Popover';
26842
+ PopoverTarget.displayName = 'Popover.Target';
26843
+ PopoverDropdown.displayName = 'Popover.Dropdown';
26844
+
25767
26845
  const getSpacingValue = (spacing, theme) => {
25768
26846
  if (typeof spacing === 'number')
25769
26847
  return spacing;
@@ -26858,7 +27936,6 @@ expandableRowRender, initialExpandedRows = [], expandedRows: controlledExpandedR
26858
27936
  else {
26859
27937
  setInternalSearchValue(value);
26860
27938
  }
26861
- setForceUpdateCounter(c => c + 1);
26862
27939
  }, [onSearchChange]);
26863
27940
  const handleSort = React.useCallback((columnKey) => {
26864
27941
  if (!onSortChange)
@@ -26996,43 +28073,44 @@ expandableRowRender, initialExpandedRows = [], expandedRows: controlledExpandedR
26996
28073
  alignItems: 'center',
26997
28074
  marginBottom: DESIGN_TOKENS.spacing.md,
26998
28075
  paddingHorizontal: DESIGN_TOKENS.spacing.xs
26999
- }, children: [jsxRuntime.jsx(Flex, { gap: DESIGN_TOKENS.spacing.md, align: "center", children: selectedRows.length > 0 && bulkActions.length > 0 && (jsxRuntime.jsxs(Flex, { gap: 8, children: [jsxRuntime.jsxs(Text, { variant: "caption", colorVariant: "muted", children: [selectedRows.length, " selected"] }), bulkActions.map(action => (jsxRuntime.jsx(Button, { variant: "outline", size: "sm", startIcon: action.icon, onPress: () => action.action(selectedRows, data), children: action.label }, action.key)))] })) }), jsxRuntime.jsxs(Flex, { gap: 8, children: [(searchable || columns.some(c => c.filterable)) && (jsxRuntime.jsxs(Menu, { position: "bottom-end", offset: 4, children: [jsxRuntime.jsxs(MenuDropdown, { children: [jsxRuntime.jsx(MenuLabel, { children: "Search & Filter" }), searchable && (jsxRuntime.jsxs(reactNative.View, { style: { borderBottomWidth: 1, borderBottomColor: theme.colors.gray[2] }, children: [jsxRuntime.jsx(Text, { variant: "caption", weight: "semibold", style: { marginBottom: 8 }, children: "Search" }), jsxRuntime.jsx(Input, { placeholder: searchPlaceholder, value: searchValue, onChangeText: handleSearchChange, leftSection: jsxRuntime.jsx(Icon, { name: "menu", size: 16 }), size: "sm" }, `search-input-${searchValue}`)] })), columns.some(c => c.filterable) && (jsxRuntime.jsxs(reactNative.View, { style: { padding: 12 }, children: [jsxRuntime.jsxs(Flex, { direction: "row", justify: "space-between", align: "center", style: { marginBottom: 8 }, children: [jsxRuntime.jsx(Text, { variant: "caption", weight: "semibold", children: "Filters" }), activeFilters.length > 0 && (jsxRuntime.jsx(Button, { variant: "ghost", size: "xs", onPress: () => {
27000
- setInternalFilters([]);
27001
- setForceUpdateCounter(c => c + 1);
27002
- }, children: "Clear all" }))] }), activeFilters.length > 0 && (jsxRuntime.jsx(reactNative.View, { style: { marginBottom: DESIGN_TOKENS.spacing.md, gap: DESIGN_TOKENS.spacing.xs }, children: activeFilters.map((filter, idx) => {
27003
- const column = columns.find(c => c.key === filter.column);
27004
- return (jsxRuntime.jsxs(reactNative.View, { style: {
27005
- flexDirection: 'row',
27006
- alignItems: 'center',
27007
- backgroundColor: theme.colors.primary[1],
27008
- paddingHorizontal: DESIGN_TOKENS.spacing.sm,
27009
- paddingVertical: DESIGN_TOKENS.spacing.xs,
27010
- borderRadius: DESIGN_TOKENS.radius.sm,
27011
- gap: DESIGN_TOKENS.spacing.xs
27012
- }, children: [jsxRuntime.jsxs(Text, { variant: "caption", style: { color: theme.colors.primary[7] }, children: [(column === null || column === void 0 ? void 0 : column.header) || filter.column, ": ", filter.operator, " \"", filter.value, "\""] }), jsxRuntime.jsx(reactNative.Pressable, { onPress: () => {
27013
- setInternalFilters(filters => filters.filter((_, i) => i !== idx));
27014
- setForceUpdateCounter(c => c + 1);
27015
- }, children: jsxRuntime.jsx(Icon, { name: "x", size: 12, color: theme.colors.primary[6] }) })] }, idx));
27016
- }) })), jsxRuntime.jsx(reactNative.View, { style: { gap: DESIGN_TOKENS.spacing.sm }, children: columns.filter(c => c.filterable).map(column => {
27017
- const currentFilter = getColumnFilter(column.key);
27018
- return (jsxRuntime.jsx(reactNative.View, { children: renderFilterControl(column) }, `${column.key}-${(currentFilter === null || currentFilter === void 0 ? void 0 : currentFilter.value) || 'no-filter'}`));
27019
- }) })] }))] }), jsxRuntime.jsxs(Button, { variant: "outline", size: "sm", startIcon: jsxRuntime.jsx(Icon, { name: "search", size: 14 }), children: ["Search", (searchValue || activeFilters.length > 0) && (jsxRuntime.jsx(reactNative.View, { style: {
27020
- width: 6,
27021
- height: 6,
27022
- borderRadius: 3,
27023
- backgroundColor: theme.colors.primary[5],
27024
- marginLeft: 4
27025
- } }))] })] }, `search-filter-${forceUpdateCounter}`)), onEditModeChange && (jsxRuntime.jsx(Button, { variant: editMode ? 'filled' : 'outline', size: "sm", onPress: () => onEditModeChange(!editMode), children: editMode ? 'Exit Edit' : 'Edit' })), showColumnVisibilityManager && (jsxRuntime.jsxs(Menu, { position: "bottom-end", offset: 4, children: [jsxRuntime.jsxs(MenuDropdown, { children: [jsxRuntime.jsx(MenuLabel, { children: "Column Visibility" }), jsxRuntime.jsxs(reactNative.View, { style: { padding: 8, maxHeight: 300 }, children: [jsxRuntime.jsx(ComponentWithDisclaimer, { disclaimer: "Selected view determines the layout style", disclaimerProps: { colorVariant: 'muted', size: 'sm' }, children: jsxRuntime.jsxs(Row, { children: [jsxRuntime.jsx(Button, { size: "xs", title: "Deselect All", variant: hiddenColumns.length === columns.length ? 'filled' : 'outline', onPress: () => setHiddenColumns(columns.map(c => c.key)), style: { marginBottom: 8 } }), jsxRuntime.jsx(Button, { size: "xs", title: "Select All", variant: hiddenColumns.length === 0 ? 'filled' : 'outline', onPress: () => setHiddenColumns([]), style: { marginBottom: 8 } })] }) }), jsxRuntime.jsx(reactNative.ScrollView, { style: { maxHeight: 200 }, children: columns.map(col => (jsxRuntime.jsx(Checkbox, { label: tempHeaderEdits[col.key] || col.header,
27026
- // checked={!hiddenColumns.includes(col.key)}
27027
- // disabled={col.disableHiding}
27028
- onChange: () => {
27029
- if (hiddenColumns.includes(col.key)) {
27030
- setHiddenColumns(prev => prev.filter(h => h !== col.key));
27031
- }
27032
- else {
27033
- setHiddenColumns(prev => [...prev, col.key]);
27034
- }
27035
- }, style: { marginBottom: 4 } }, col.key))) })] })] }), jsxRuntime.jsx(Button, { variant: "outline", size: "sm", startIcon: jsxRuntime.jsx(Icon, { name: "eye", size: 14 }), children: "Columns" })] }, `col-vis-${forceUpdateCounter}`))] })] }));
28076
+ }, children: [jsxRuntime.jsx(Flex, { gap: DESIGN_TOKENS.spacing.md, align: "center", children: selectedRows.length > 0 && bulkActions.length > 0 && (jsxRuntime.jsxs(Flex, { gap: 8, children: [jsxRuntime.jsxs(Text, { variant: "caption", colorVariant: "muted", children: [selectedRows.length, " selected"] }), bulkActions.map(action => (jsxRuntime.jsx(Button, { variant: "outline", size: "sm", startIcon: action.icon, onPress: () => action.action(selectedRows, data), children: action.label }, action.key)))] })) }), jsxRuntime.jsxs(Flex, { gap: 8, children: [(searchable || columns.some(c => c.filterable)) && (jsxRuntime.jsxs(Popover, { position: "bottom-end", offset: { mainAxis: 12 }, width: 320, trapFocus: true, children: [jsxRuntime.jsx(PopoverTarget, { children: jsxRuntime.jsxs(Button, { variant: "outline", size: "sm", startIcon: jsxRuntime.jsx(Icon, { name: "search", size: 14 }), children: ["Search", (searchValue || activeFilters.length > 0) && (jsxRuntime.jsx(reactNative.View, { style: {
28077
+ width: 6,
28078
+ height: 6,
28079
+ borderRadius: 3,
28080
+ backgroundColor: theme.colors.primary[5],
28081
+ marginLeft: 4
28082
+ } }))] }) }), jsxRuntime.jsx(PopoverDropdown, { children: jsxRuntime.jsxs(Flex, { direction: "column", gap: DESIGN_TOKENS.spacing.md, style: { width: 320 }, children: [jsxRuntime.jsx(Text, { variant: "caption", weight: "semibold", children: "Search & Filter" }), searchable && (jsxRuntime.jsx(reactNative.View, { style: {
28083
+ borderBottomWidth: 1,
28084
+ borderBottomColor: theme.colors.gray[2],
28085
+ paddingBottom: DESIGN_TOKENS.spacing.sm,
28086
+ }, children: jsxRuntime.jsxs(Flex, { direction: "column", gap: DESIGN_TOKENS.spacing.xs, children: [jsxRuntime.jsx(Text, { variant: "caption", weight: "semibold", children: "Search" }), jsxRuntime.jsx(Input, { placeholder: searchPlaceholder, value: searchValue, onChangeText: handleSearchChange, leftSection: jsxRuntime.jsx(Icon, { name: "menu", size: 16 }), size: "sm" })] }) })), columns.some(c => c.filterable) && (jsxRuntime.jsxs(Flex, { direction: "column", gap: DESIGN_TOKENS.spacing.sm, children: [jsxRuntime.jsxs(Flex, { direction: "row", justify: "space-between", align: "center", children: [jsxRuntime.jsx(Text, { variant: "caption", weight: "semibold", children: "Filters" }), activeFilters.length > 0 && (jsxRuntime.jsx(Button, { variant: "ghost", size: "xs", onPress: () => {
28087
+ setInternalFilters([]);
28088
+ setForceUpdateCounter(c => c + 1);
28089
+ }, children: "Clear all" }))] }), activeFilters.length > 0 && (jsxRuntime.jsx(Flex, { direction: "column", gap: DESIGN_TOKENS.spacing.xs, style: { marginBottom: DESIGN_TOKENS.spacing.sm }, children: activeFilters.map((filter, idx) => {
28090
+ const column = columns.find(c => c.key === filter.column);
28091
+ return (jsxRuntime.jsxs(reactNative.View, { style: {
28092
+ flexDirection: 'row',
28093
+ alignItems: 'center',
28094
+ backgroundColor: theme.colors.primary[1],
28095
+ paddingHorizontal: DESIGN_TOKENS.spacing.sm,
28096
+ paddingVertical: DESIGN_TOKENS.spacing.xs,
28097
+ borderRadius: DESIGN_TOKENS.radius.sm,
28098
+ gap: DESIGN_TOKENS.spacing.xs
28099
+ }, children: [jsxRuntime.jsxs(Text, { variant: "caption", style: { color: theme.colors.primary[7] }, children: [(column === null || column === void 0 ? void 0 : column.header) || filter.column, ": ", filter.operator, " \"", filter.value, "\""] }), jsxRuntime.jsx(reactNative.Pressable, { onPress: () => {
28100
+ setInternalFilters(filters => filters.filter((_, i) => i !== idx));
28101
+ setForceUpdateCounter(c => c + 1);
28102
+ }, children: jsxRuntime.jsx(Icon, { name: "x", size: 12, color: theme.colors.primary[6] }) })] }, idx));
28103
+ }) })), jsxRuntime.jsx(Flex, { direction: "column", gap: DESIGN_TOKENS.spacing.sm, children: columns.filter(c => c.filterable).map(column => {
28104
+ const currentFilter = getColumnFilter(column.key);
28105
+ return (jsxRuntime.jsx(reactNative.View, { children: renderFilterControl(column) }, `${column.key}-${(currentFilter === null || currentFilter === void 0 ? void 0 : currentFilter.value) || 'no-filter'}`));
28106
+ }) })] }))] }) })] })), onEditModeChange && (jsxRuntime.jsx(Button, { variant: editMode ? 'filled' : 'outline', size: "sm", onPress: () => onEditModeChange(!editMode), children: editMode ? 'Exit Edit' : 'Edit' })), showColumnVisibilityManager && (jsxRuntime.jsxs(Popover, { position: "bottom-end", offset: { mainAxis: 12 }, width: 280, trapFocus: true, children: [jsxRuntime.jsx(PopoverTarget, { children: jsxRuntime.jsx(Button, { variant: "outline", size: "sm", startIcon: jsxRuntime.jsx(Icon, { name: "eye", size: 14 }), children: "Columns" }) }), jsxRuntime.jsx(PopoverDropdown, { children: jsxRuntime.jsxs(reactNative.View, { style: { padding: 8, maxHeight: 300, width: 260 }, children: [jsxRuntime.jsx(ComponentWithDisclaimer, { disclaimer: "Selected view determines the layout style", disclaimerProps: { colorVariant: 'muted', size: 'sm' }, children: jsxRuntime.jsxs(Row, { children: [jsxRuntime.jsx(Button, { size: "xs", title: "Deselect All", variant: hiddenColumns.length === columns.length ? 'filled' : 'outline', onPress: () => setHiddenColumns(columns.map(c => c.key)), style: { marginBottom: 8 } }), jsxRuntime.jsx(Button, { size: "xs", title: "Select All", variant: hiddenColumns.length === 0 ? 'filled' : 'outline', onPress: () => setHiddenColumns([]), style: { marginBottom: 8 } })] }) }), jsxRuntime.jsx(reactNative.ScrollView, { style: { maxHeight: 200 }, children: columns.map(col => (jsxRuntime.jsx(Checkbox, { label: tempHeaderEdits[col.key] || col.header, onChange: () => {
28107
+ if (hiddenColumns.includes(col.key)) {
28108
+ setHiddenColumns(prev => prev.filter(h => h !== col.key));
28109
+ }
28110
+ else {
28111
+ setHiddenColumns(prev => [...prev, col.key]);
28112
+ }
28113
+ }, style: { marginBottom: 4 } }, col.key))) })] }) })] }))] })] }));
27036
28114
  const renderCell = React.useCallback((column, row, rowIndex) => {
27037
28115
  const value = getValue(row, column.accessor);
27038
28116
  const isEditing = (editingCell === null || editingCell === void 0 ? void 0 : editingCell.row) === rowIndex && (editingCell === null || editingCell === void 0 ? void 0 : editingCell.column) === column.key;
@@ -35327,6 +36405,7 @@ exports.Heading3 = Heading3;
35327
36405
  exports.Heading4 = Heading4;
35328
36406
  exports.Heading5 = Heading5;
35329
36407
  exports.Heading6 = Heading6;
36408
+ exports.Highlight = Highlight;
35330
36409
  exports.HoverCard = HoverCard;
35331
36410
  exports.HuaweiAppGalleryBadge = HuaweiAppGalleryBadge;
35332
36411
  exports.I18nProvider = I18nProvider;
@@ -35376,6 +36455,9 @@ exports.PermissionProvider = PermissionProvider;
35376
36455
  exports.PhoneInput = PhoneInput;
35377
36456
  exports.PinInput = PinInput;
35378
36457
  exports.PlatformBlocksProvider = PlatformBlocksProvider;
36458
+ exports.Popover = Popover;
36459
+ exports.PopoverDropdown = PopoverDropdown;
36460
+ exports.PopoverTarget = PopoverTarget;
35379
36461
  exports.PressAnimation = PressAnimation;
35380
36462
  exports.Progress = Progress;
35381
36463
  exports.QRCode = QRCode;