@platform-blocks/ui 0.4.0 → 0.6.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.
Files changed (34) hide show
  1. package/lib/cjs/index.js +684 -1211
  2. package/lib/cjs/index.js.map +1 -1
  3. package/lib/components/Avatar/Avatar.d.ts +1 -1
  4. package/lib/components/Avatar/types.d.ts +3 -3
  5. package/lib/components/Carousel/types.d.ts +32 -0
  6. package/lib/components/DataTable/DataTable.d.ts +1 -1
  7. package/lib/components/DataTable/types.d.ts +2 -0
  8. package/lib/components/HoverCard/types.d.ts +4 -2
  9. package/lib/components/Popover/types.d.ts +2 -0
  10. package/lib/components/Slider/types.d.ts +29 -1
  11. package/lib/components/Switch/styles.d.ts +1 -1
  12. package/lib/components/TextArea/styles.d.ts +1 -1
  13. package/lib/components/index.d.ts +0 -2
  14. package/lib/core/providers/OverlayProvider.d.ts +1 -1
  15. package/lib/core/theme/PlatformBlocksProvider.d.ts +1 -5
  16. package/lib/esm/index.js +685 -1193
  17. package/lib/esm/index.js.map +1 -1
  18. package/lib/index.d.ts +0 -7
  19. package/package.json +1 -1
  20. package/lib/components/Can/Can.d.ts +0 -30
  21. package/lib/components/Can/PermissionDemo.d.ts +0 -2
  22. package/lib/components/Can/ability.d.ts +0 -89
  23. package/lib/components/Can/builder.d.ts +0 -113
  24. package/lib/components/Can/context.d.ts +0 -25
  25. package/lib/components/Can/index.d.ts +0 -6
  26. package/lib/components/Can/types.d.ts +0 -230
  27. package/lib/components/HoverCard/index.d.ts +0 -2
  28. package/lib/components/NavigationProgress/NavigationProgress.d.ts +0 -4
  29. package/lib/components/NavigationProgress/defaults.d.ts +0 -8
  30. package/lib/components/NavigationProgress/hooks/useNavigationProgressState.d.ts +0 -1
  31. package/lib/components/NavigationProgress/index.d.ts +0 -2
  32. package/lib/components/NavigationProgress/styles/resolver.d.ts +0 -1
  33. package/lib/components/NavigationProgress/tokens.d.ts +0 -4
  34. package/lib/components/NavigationProgress/types.d.ts +0 -30
package/lib/esm/index.js CHANGED
@@ -1164,25 +1164,50 @@ function OverlayRenderer({ style } = {}) {
1164
1164
  }) }));
1165
1165
  }
1166
1166
  function OverlayContent({ overlay, isTopmost, onBackdropPress }) {
1167
- var _a, _b, _c;
1167
+ var _a, _b, _c, _d, _e, _f;
1168
1168
  useTheme();
1169
1169
  const DEBUG = overlay.debug === true;
1170
1170
  if (DEBUG) {
1171
1171
  console.log('Rendering overlay content:');
1172
1172
  console.log('- anchor:', overlay.anchor);
1173
+ console.log('- placement:', overlay.placement);
1173
1174
  console.log('- strategy:', overlay.strategy);
1174
1175
  console.log('- zIndex:', overlay.zIndex);
1175
1176
  }
1177
+ // Check if this is a top-positioned overlay
1178
+ const isTopPlacement = (_a = overlay.placement) === null || _a === void 0 ? void 0 : _a.startsWith('top');
1179
+ // For top placements, we need to anchor from the bottom of the overlay
1180
+ // The anchor.y represents where the bottom of the overlay should be (top of the trigger minus offset)
1181
+ // So we use the estimated height to calculate where the top of the overlay would be
1176
1182
  const overlayStyle = {
1177
1183
  // Use fixed positioning on web for viewport-anchored overlays
1178
1184
  position: (Platform.OS === 'web' && overlay.strategy === 'fixed') ? 'fixed' : 'absolute',
1179
- top: ((_a = overlay.anchor) === null || _a === void 0 ? void 0 : _a.y) || 0,
1180
1185
  left: ((_b = overlay.anchor) === null || _b === void 0 ? void 0 : _b.x) || 0,
1181
1186
  zIndex: overlay.zIndex,
1182
1187
  width: overlay.width || (((_c = overlay.anchor) === null || _c === void 0 ? void 0 : _c.width) ? overlay.anchor.width : undefined),
1183
1188
  maxWidth: overlay.maxWidth,
1184
1189
  maxHeight: overlay.maxHeight,
1185
1190
  };
1191
+ if (isTopPlacement && Platform.OS === 'web') {
1192
+ // For top placements, position from the bottom of the overlay
1193
+ // anchor.y is where the top of the overlay should be, but we want to anchor from the bottom
1194
+ // so the overlay can grow upward naturally
1195
+ // The "bottom" of the anchor point is: viewport.height - (anchor.y + estimatedHeight)
1196
+ // But since we don't know actual height, use bottom anchoring relative to the trigger
1197
+ // Actually, anchor.y already accounts for the estimated height, so:
1198
+ // anchor.y = trigger.y - estimatedHeight - offset
1199
+ // We want the overlay's bottom edge to be at: trigger.y - offset
1200
+ // Which means: bottom = viewport.height - (trigger.y - offset) = viewport.height - anchor.y - estimatedHeight
1201
+ // Simpler: just set top and let it render, but the issue is the estimate is wrong
1202
+ // Better approach: use the anchor.y + anchor.height as the "bottom anchor point"
1203
+ // This is where the bottom of the overlay should be
1204
+ const bottomAnchorPoint = (((_d = overlay.anchor) === null || _d === void 0 ? void 0 : _d.y) || 0) + (((_e = overlay.anchor) === null || _e === void 0 ? void 0 : _e.height) || 0);
1205
+ overlayStyle.top = undefined;
1206
+ overlayStyle.bottom = `calc(100vh - ${bottomAnchorPoint}px)`;
1207
+ }
1208
+ else {
1209
+ overlayStyle.top = ((_f = overlay.anchor) === null || _f === void 0 ? void 0 : _f.y) || 0;
1210
+ }
1186
1211
  if (DEBUG) {
1187
1212
  console.log('- overlayStyle:', overlayStyle);
1188
1213
  }
@@ -6153,31 +6178,29 @@ const Button = (allProps) => {
6153
6178
  const { getDuration } = useReducedMotion$1();
6154
6179
  const { announce } = useAnnouncer();
6155
6180
  const { ref: focusRef} = useFocus(`button-${title || 'button'}`);
6181
+ // Track measured width for loading state preservation
6182
+ const [measuredWidth, setMeasuredWidth] = useState(null);
6183
+ const wasLoadingRef = useRef(loading);
6184
+ // When loading starts, we want to preserve the current measured width
6185
+ // When loading ends, clear the preserved width so it can resize naturally
6186
+ useEffect(() => {
6187
+ if (!loading && wasLoadingRef.current) {
6188
+ // Loading just ended, allow width to be recalculated
6189
+ setMeasuredWidth(null);
6190
+ }
6191
+ wasLoadingRef.current = loading;
6192
+ }, [loading]);
6193
+ const handleLayout = useCallback((event) => {
6194
+ // Only update measured width when not loading, so we capture the natural content width
6195
+ if (!loading) {
6196
+ const { width } = event.nativeEvent.layout;
6197
+ setMeasuredWidth(width);
6198
+ }
6199
+ // Call user's onLayout if provided
6200
+ onLayout === null || onLayout === void 0 ? void 0 : onLayout(event);
6201
+ }, [loading, onLayout]);
6156
6202
  // Determine button content - children takes precedence over title
6157
6203
  const buttonContent = children !== null && children !== void 0 ? children : title;
6158
- // Calculate minimum width for loading state based on content and size
6159
- const calculateMinWidth = () => {
6160
- if (!buttonContent || typeof buttonContent !== 'string')
6161
- return undefined;
6162
- // Base character width estimates based on size
6163
- const charWidthBySize = {
6164
- xs: 6,
6165
- sm: 7,
6166
- md: 8,
6167
- lg: 9,
6168
- xl: 10,
6169
- '2xl': 11,
6170
- '3xl': 12
6171
- };
6172
- const sizeKey = typeof size === 'string' ? size : 'md';
6173
- const charWidth = charWidthBySize[sizeKey] || 8;
6174
- const horizontalPadding = getSpacing(size) * 2; // Left + right padding
6175
- // Estimate content width: character count * average char width + padding
6176
- const contentWidth = buttonContent.length * charWidth + horizontalPadding;
6177
- // Add space for loader and gap when loading
6178
- const loaderWidth = getFontSize$1(size) + getSpacing(size) / 2; // Loader + margin
6179
- return Math.max(contentWidth, contentWidth + loaderWidth);
6180
- };
6181
6204
  // Determine what content to show based on loading state
6182
6205
  const displayContent = loading
6183
6206
  ? (loadingTitle !== undefined ? loadingTitle : '')
@@ -6216,12 +6239,12 @@ const Button = (allProps) => {
6216
6239
  const shadowStyles = getShadowStyles({ shadow: effectiveShadow }, theme, 'button');
6217
6240
  const spacingStyles = getSpacingStyles(spacingProps);
6218
6241
  const baseLayoutStyles = getLayoutStyles(layoutProps);
6219
- // Apply minimum width when loading to prevent size changes
6220
- const calculatedMinWidth = calculateMinWidth();
6242
+ // Apply measured width when loading to prevent size changes
6243
+ // Use the actual measured width instead of character-based estimates
6221
6244
  const layoutStyles = {
6222
6245
  ...baseLayoutStyles,
6223
- ...(loading && calculatedMinWidth && !layoutProps.width && !layoutProps.w && !layoutProps.fullWidth
6224
- ? { minWidth: calculatedMinWidth }
6246
+ ...(loading && measuredWidth && !layoutProps.width && !layoutProps.w && !layoutProps.fullWidth
6247
+ ? { width: measuredWidth, minWidth: measuredWidth }
6225
6248
  : {})
6226
6249
  };
6227
6250
  const iconSpacing = getSpacing(size) / 2;
@@ -6414,7 +6437,7 @@ const Button = (allProps) => {
6414
6437
  ...(Platform.OS !== 'web' ? { transform: [{ translateY: 1 }] } : {})
6415
6438
  } : null,
6416
6439
  style,
6417
- ], onPress: handleInternalPress, onLayout: onLayout, onPressIn: handlePressIn, onPressOut: handlePressOut, onHoverIn: onHoverIn, onHoverOut: onHoverOut, onLongPress: onLongPress, disabled: isInteractionDisabled, children: [variant === 'gradient' && hasLinearGradient$4 && (jsx(OptionalLinearGradient$6, { colors: resolvedCustomColor
6440
+ ], onPress: handleInternalPress, onLayout: handleLayout, onPressIn: handlePressIn, onPressOut: handlePressOut, onHoverIn: onHoverIn, onHoverOut: onHoverOut, onLongPress: onLongPress, disabled: isInteractionDisabled, children: [variant === 'gradient' && hasLinearGradient$4 && (jsx(OptionalLinearGradient$6, { colors: resolvedCustomColor
6418
6441
  ? [resolvedCustomColor, theme.colors.primary[7]]
6419
6442
  : [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 ? (jsxs(Fragment, { children: [jsx(Loader, { size: size, color: getLoaderColor(), style: !isIconButton ? { marginRight: iconSpacing } : undefined }), !isIconButton && renderButtonContent(displayContent)] })) : isIconButton ? (
6420
6443
  // Icon-only button
@@ -9732,593 +9755,6 @@ function UniversalCSS() {
9732
9755
  return null;
9733
9756
  }
9734
9757
 
9735
- /**
9736
- * Core Ability class for managing permissions
9737
- */
9738
- class AbilityCore {
9739
- constructor(rules = []) {
9740
- this.rules = [];
9741
- this.cache = new Map();
9742
- this.rules = [...rules];
9743
- }
9744
- /**
9745
- * Check if action is allowed on subject
9746
- */
9747
- can(action, subject, field) {
9748
- return this.check(action, subject, field).allowed;
9749
- }
9750
- /**
9751
- * Check if action is forbidden on subject
9752
- */
9753
- cannot(action, subject, field) {
9754
- return !this.can(action, subject, field);
9755
- }
9756
- /**
9757
- * Get detailed permission check result
9758
- */
9759
- check(action, subject, field) {
9760
- const cacheKey = this.getCacheKey(action, subject, field);
9761
- if (this.cache.has(cacheKey)) {
9762
- return this.cache.get(cacheKey);
9763
- }
9764
- const result = this.performCheck(action, subject, field);
9765
- this.cache.set(cacheKey, result);
9766
- return result;
9767
- }
9768
- /**
9769
- * Update ability rules and clear cache
9770
- */
9771
- update(rules) {
9772
- this.rules = [...rules];
9773
- this.cache.clear();
9774
- }
9775
- /**
9776
- * Get all current rules
9777
- */
9778
- getRules() {
9779
- return [...this.rules];
9780
- }
9781
- /**
9782
- * Clear all rules and cache
9783
- */
9784
- clear() {
9785
- this.rules = [];
9786
- this.cache.clear();
9787
- }
9788
- /**
9789
- * Perform the actual permission check
9790
- */
9791
- performCheck(action, subject, field) {
9792
- // Start with denied by default
9793
- let result = {
9794
- allowed: false,
9795
- reason: 'No matching permission rule found'
9796
- };
9797
- // Check rules in order (later rules can override earlier ones)
9798
- for (const rule of this.rules) {
9799
- if (this.ruleMatches(rule, action, subject, field)) {
9800
- result = {
9801
- allowed: !rule.inverted,
9802
- reason: rule.reason || (rule.inverted ? 'Access denied by rule' : 'Access granted by rule'),
9803
- rule
9804
- };
9805
- }
9806
- }
9807
- return result;
9808
- }
9809
- /**
9810
- * Check if a rule matches the current permission check
9811
- */
9812
- ruleMatches(rule, action, subject, field) {
9813
- // Check action match
9814
- const actions = Array.isArray(rule.action) ? rule.action : [rule.action];
9815
- if (!actions.includes(action) && !actions.includes('*')) {
9816
- return false;
9817
- }
9818
- // Check subject match
9819
- const subjects = Array.isArray(rule.subject) ? rule.subject : [rule.subject];
9820
- if (!this.subjectMatches(subjects, subject)) {
9821
- return false;
9822
- }
9823
- // Check field match (if specified)
9824
- if (field && rule.fields && !rule.fields.includes(field)) {
9825
- return false;
9826
- }
9827
- // Check conditions (if subject is an object)
9828
- if (rule.conditions && typeof subject === 'object' && subject !== null) {
9829
- return this.conditionsMatch(rule.conditions, subject);
9830
- }
9831
- return true;
9832
- }
9833
- /**
9834
- * Check if subject matches any of the rule subjects
9835
- */
9836
- subjectMatches(ruleSubjects, checkSubject) {
9837
- for (const ruleSubject of ruleSubjects) {
9838
- if (ruleSubject === '*')
9839
- return true;
9840
- if (ruleSubject === checkSubject)
9841
- return true;
9842
- // Handle class/constructor matching
9843
- if (typeof ruleSubject === 'function' && typeof checkSubject === 'object') {
9844
- if (checkSubject instanceof ruleSubject)
9845
- return true;
9846
- if (checkSubject.constructor === ruleSubject)
9847
- return true;
9848
- }
9849
- // Handle string matching for object types
9850
- if (typeof ruleSubject === 'string' && typeof checkSubject === 'object') {
9851
- if (checkSubject.__type === ruleSubject)
9852
- return true;
9853
- if (checkSubject.type === ruleSubject)
9854
- return true;
9855
- if (checkSubject.constructor.name === ruleSubject)
9856
- return true;
9857
- }
9858
- }
9859
- return false;
9860
- }
9861
- /**
9862
- * Check if conditions match the subject object
9863
- */
9864
- conditionsMatch(conditions, subject) {
9865
- for (const [key, expectedValue] of Object.entries(conditions)) {
9866
- const actualValue = subject[key];
9867
- if (!this.valuesMatch(actualValue, expectedValue)) {
9868
- return false;
9869
- }
9870
- }
9871
- return true;
9872
- }
9873
- /**
9874
- * Check if two values match (handles various comparison types)
9875
- */
9876
- valuesMatch(actual, expected) {
9877
- // Exact match
9878
- if (actual === expected)
9879
- return true;
9880
- // Array contains check
9881
- if (Array.isArray(expected) && expected.includes(actual))
9882
- return true;
9883
- if (Array.isArray(actual) && actual.includes(expected))
9884
- return true;
9885
- // Function/predicate check
9886
- if (typeof expected === 'function') {
9887
- return expected(actual);
9888
- }
9889
- // Regex match for strings
9890
- if (expected instanceof RegExp && typeof actual === 'string') {
9891
- return expected.test(actual);
9892
- }
9893
- // Object comparison (shallow)
9894
- if (typeof expected === 'object' && typeof actual === 'object' && expected !== null && actual !== null) {
9895
- return Object.keys(expected).every(key => this.valuesMatch(actual[key], expected[key]));
9896
- }
9897
- return false;
9898
- }
9899
- /**
9900
- * Generate cache key for permission check
9901
- */
9902
- getCacheKey(action, subject, field) {
9903
- const subjectKey = typeof subject === 'object'
9904
- ? JSON.stringify(subject)
9905
- : String(subject);
9906
- return `${action}:${subjectKey}:${field || ''}`;
9907
- }
9908
- }
9909
- /**
9910
- * Create a new Ability instance
9911
- */
9912
- function createAbility(rules = []) {
9913
- return new AbilityCore(rules);
9914
- }
9915
-
9916
- /**
9917
- * Permission Context
9918
- */
9919
- const PermissionContext = createContext(null);
9920
- /**
9921
- * Permission Provider Component
9922
- */
9923
- const PermissionProvider = ({ rules = [], user, children, dev = {} }) => {
9924
- const [ability] = useState(() => createAbility(rules));
9925
- const [currentUser, setCurrentUser] = useState(user);
9926
- const updateAbility = useCallback((newRules) => {
9927
- ability.update(newRules);
9928
- }, [ability]);
9929
- const can = useCallback((action, subject, field) => {
9930
- const result = ability.can(action, subject, field);
9931
- if (dev.logChecks) {
9932
- console.log(`[Permissions] Can ${action} ${subject}${field ? `.${field}` : ''}:`, result);
9933
- }
9934
- return result;
9935
- }, [ability, dev.logChecks]);
9936
- const cannot = useCallback((action, subject, field) => {
9937
- const result = ability.cannot(action, subject, field);
9938
- if (dev.logChecks) {
9939
- console.log(`[Permissions] Cannot ${action} ${subject}${field ? `.${field}` : ''}:`, result);
9940
- }
9941
- return result;
9942
- }, [ability, dev.logChecks]);
9943
- const setUser = useCallback((newUser) => {
9944
- setCurrentUser(newUser);
9945
- }, []);
9946
- const contextValue = useMemo(() => ({
9947
- ability,
9948
- updateAbility,
9949
- can,
9950
- cannot,
9951
- user: currentUser,
9952
- setUser
9953
- }), [ability, updateAbility, can, cannot, currentUser, setUser]);
9954
- return React__default.createElement(PermissionContext.Provider, { value: contextValue }, children);
9955
- };
9956
- /**
9957
- * Hook to access permission context
9958
- */
9959
- const usePermissions = (options = {}) => {
9960
- const context = useContext(PermissionContext);
9961
- if (!context) {
9962
- if (options.required) {
9963
- throw new Error('usePermissions must be used within a PermissionProvider');
9964
- }
9965
- if (options.debug) {
9966
- console.warn('[Permissions] usePermissions called outside of PermissionProvider');
9967
- }
9968
- // Return a fallback context that allows everything
9969
- return {
9970
- ability: createAbility([{ action: '*', subject: '*' }]),
9971
- updateAbility: () => { },
9972
- can: () => true,
9973
- cannot: () => false,
9974
- user: null,
9975
- setUser: () => { }
9976
- };
9977
- }
9978
- return context;
9979
- };
9980
- /**
9981
- * Hook to get the current ability instance
9982
- */
9983
- const useAbility = () => {
9984
- const { ability } = usePermissions();
9985
- return ability;
9986
- };
9987
-
9988
- /**
9989
- * Can Component - Renders children if permission is granted
9990
- */
9991
- const Can = ({ I: action, a: subject, field, children, fallback = null, ability: customAbility, style, testID, passthrough = false }) => {
9992
- const { ability: contextAbility } = usePermissions();
9993
- const ability = customAbility || contextAbility;
9994
- // Development passthrough
9995
- if (passthrough && __DEV__) {
9996
- return React__default.createElement(View, { style, testID }, children);
9997
- }
9998
- const hasPermission = subject
9999
- ? ability.can(action, subject, field)
10000
- : ability.can(action, '*', field);
10001
- if (hasPermission) {
10002
- return React__default.createElement(View, { style, testID }, children);
10003
- }
10004
- return React__default.createElement(View, { style, testID }, fallback);
10005
- };
10006
- /**
10007
- * Can Component with conditions - For object-level permissions
10008
- */
10009
- const CanWithConditions = ({ I: action, this: subject, field, children, fallback = null, ability: customAbility, style, testID, passthrough = false }) => {
10010
- const { ability: contextAbility } = usePermissions();
10011
- const ability = customAbility || contextAbility;
10012
- // Development passthrough
10013
- if (passthrough && __DEV__) {
10014
- return React__default.createElement(View, { style, testID }, children);
10015
- }
10016
- const hasPermission = ability.can(action, subject, field);
10017
- if (hasPermission) {
10018
- return React__default.createElement(View, { style, testID }, children);
10019
- }
10020
- return React__default.createElement(View, { style, testID }, fallback);
10021
- };
10022
- /**
10023
- * Cannot Component - Renders children if permission is NOT granted
10024
- */
10025
- const Cannot = ({ I: action, a: subject, field, children, fallback = null, ability: customAbility, style, testID, passthrough = false }) => {
10026
- const { ability: contextAbility } = usePermissions();
10027
- const ability = customAbility || contextAbility;
10028
- // Development passthrough
10029
- if (passthrough && __DEV__) {
10030
- return React__default.createElement(View, { style, testID }, fallback);
10031
- }
10032
- const hasPermission = subject
10033
- ? ability.can(action, subject, field)
10034
- : ability.can(action, '*', field);
10035
- if (!hasPermission) {
10036
- return React__default.createElement(View, { style, testID }, children);
10037
- }
10038
- return React__default.createElement(View, { style, testID }, fallback);
10039
- };
10040
- /**
10041
- * Permission Gate - Requires ALL permissions to pass
10042
- */
10043
- const PermissionGate = ({ permissions, children, fallback = null, ability: customAbility, onUnauthorized }) => {
10044
- const { ability: contextAbility } = usePermissions();
10045
- const ability = customAbility || contextAbility;
10046
- const allPermissionsGranted = permissions.every(({ action, subject, field }) => ability.can(action, subject, field));
10047
- React__default.useEffect(() => {
10048
- if (!allPermissionsGranted && onUnauthorized) {
10049
- onUnauthorized();
10050
- }
10051
- }, [allPermissionsGranted, onUnauthorized]);
10052
- if (allPermissionsGranted) {
10053
- return React__default.createElement(React__default.Fragment, null, children);
10054
- }
10055
- return React__default.createElement(React__default.Fragment, null, fallback);
10056
- };
10057
- /**
10058
- * Higher-Order Component for permission checking
10059
- */
10060
- function withCan(action, subject, field) {
10061
- return function CanHOC(Component) {
10062
- const WrappedComponent = (props) => {
10063
- const { fallback, ...componentProps } = props;
10064
- return React__default.createElement(Can, { I: action, a: subject, field, fallback }, React__default.createElement(Component, componentProps));
10065
- };
10066
- WrappedComponent.displayName = `withCan(${Component.displayName || Component.name})`;
10067
- return WrappedComponent;
10068
- };
10069
- }
10070
- /**
10071
- * Higher-Order Component for permission denial checking
10072
- */
10073
- function withCannot(action, subject, field) {
10074
- return function CannotHOC(Component) {
10075
- const WrappedComponent = (props) => {
10076
- const { fallback, ...componentProps } = props;
10077
- return React__default.createElement(Cannot, { I: action, a: subject, field, fallback }, React__default.createElement(Component, componentProps));
10078
- };
10079
- WrappedComponent.displayName = `withCannot(${Component.displayName || Component.name})`;
10080
- return WrappedComponent;
10081
- };
10082
- }
10083
-
10084
- /**
10085
- * Fluent API for building permissions
10086
- */
10087
- class PermissionBuilder {
10088
- constructor() {
10089
- this.rules = [];
10090
- }
10091
- /**
10092
- * Grant permission
10093
- */
10094
- allow(action, subject, field) {
10095
- this.rules.push({
10096
- action,
10097
- subject: subject || '*',
10098
- fields: field ? [field] : undefined,
10099
- inverted: false
10100
- });
10101
- return this;
10102
- }
10103
- /**
10104
- * Deny permission
10105
- */
10106
- forbid(action, subject, field) {
10107
- this.rules.push({
10108
- action,
10109
- subject: subject || '*',
10110
- fields: field ? [field] : undefined,
10111
- inverted: true
10112
- });
10113
- return this;
10114
- }
10115
- /**
10116
- * Conditional permission
10117
- */
10118
- allowIf(action, subject, conditions, field) {
10119
- this.rules.push({
10120
- action,
10121
- subject: subject || '*',
10122
- fields: field ? [field] : undefined,
10123
- inverted: false,
10124
- conditions
10125
- });
10126
- return this;
10127
- }
10128
- /**
10129
- * Conditional denial
10130
- */
10131
- forbidIf(action, subject, conditions, field) {
10132
- this.rules.push({
10133
- action,
10134
- subject: subject || '*',
10135
- fields: field ? [field] : undefined,
10136
- inverted: true,
10137
- conditions
10138
- });
10139
- return this;
10140
- }
10141
- /**
10142
- * Grant all actions on a subject
10143
- */
10144
- manage(subject) {
10145
- this.rules.push({
10146
- action: '*',
10147
- subject,
10148
- inverted: false
10149
- });
10150
- return this;
10151
- }
10152
- /**
10153
- * Forbid all actions on a subject
10154
- */
10155
- forbidAll(subject) {
10156
- this.rules.push({
10157
- action: '*',
10158
- subject,
10159
- inverted: true
10160
- });
10161
- return this;
10162
- }
10163
- /**
10164
- * Role-based permissions
10165
- */
10166
- role(roleName, callback) {
10167
- const roleBuilder = new RoleBuilder(roleName);
10168
- callback(roleBuilder);
10169
- this.rules.push(...roleBuilder.getRules());
10170
- return this;
10171
- }
10172
- /**
10173
- * Build the ability with all rules
10174
- */
10175
- build() {
10176
- return new AbilityCore(this.rules);
10177
- }
10178
- /**
10179
- * Get all rules
10180
- */
10181
- getRules() {
10182
- return [...this.rules];
10183
- }
10184
- /**
10185
- * Clear all rules
10186
- */
10187
- clear() {
10188
- this.rules = [];
10189
- return this;
10190
- }
10191
- /**
10192
- * Merge rules from another builder
10193
- */
10194
- merge(other) {
10195
- this.rules.push(...other.getRules());
10196
- return this;
10197
- }
10198
- }
10199
- /**
10200
- * Role-specific permission builder
10201
- */
10202
- class RoleBuilder {
10203
- constructor(roleName) {
10204
- this.roleName = roleName;
10205
- this.rules = [];
10206
- }
10207
- /**
10208
- * Grant permission for this role
10209
- */
10210
- can(action, subject, field) {
10211
- this.rules.push({
10212
- action,
10213
- subject: subject || '*',
10214
- fields: field ? [field] : undefined,
10215
- inverted: false,
10216
- conditions: { role: this.roleName }
10217
- });
10218
- return this;
10219
- }
10220
- /**
10221
- * Deny permission for this role
10222
- */
10223
- cannot(action, subject, field) {
10224
- this.rules.push({
10225
- action,
10226
- subject: subject || '*',
10227
- fields: field ? [field] : undefined,
10228
- inverted: true,
10229
- conditions: { role: this.roleName }
10230
- });
10231
- return this;
10232
- }
10233
- /**
10234
- * Manage all actions on subject for this role
10235
- */
10236
- manage(subject) {
10237
- this.rules.push({
10238
- action: '*',
10239
- subject,
10240
- inverted: false,
10241
- conditions: { role: this.roleName }
10242
- });
10243
- return this;
10244
- }
10245
- /**
10246
- * Get all rules for this role
10247
- */
10248
- getRules() {
10249
- return [...this.rules];
10250
- }
10251
- }
10252
- /**
10253
- * Common permission patterns
10254
- */
10255
- class PermissionPatterns {
10256
- /**
10257
- * Admin permissions - can do everything
10258
- */
10259
- static admin() {
10260
- return new PermissionBuilder()
10261
- .manage('*');
10262
- }
10263
- /**
10264
- * User permissions - basic CRUD on own resources
10265
- */
10266
- static user(userId) {
10267
- return new PermissionBuilder()
10268
- .allowIf('read', 'User', { id: userId })
10269
- .allowIf('update', 'User', { id: userId })
10270
- .allowIf('delete', 'User', { id: userId })
10271
- .allow('read', 'public');
10272
- }
10273
- /**
10274
- * Guest permissions - read-only public content
10275
- */
10276
- static guest() {
10277
- return new PermissionBuilder()
10278
- .allow('read', 'public');
10279
- }
10280
- /**
10281
- * Moderator permissions - manage content but not users
10282
- */
10283
- static moderator() {
10284
- return new PermissionBuilder()
10285
- .manage('Content')
10286
- .manage('Comment')
10287
- .allow('read', 'User')
10288
- .forbid('delete', 'User');
10289
- }
10290
- /**
10291
- * Owner permissions - full control over owned resources
10292
- */
10293
- static owner(ownerId) {
10294
- return new PermissionBuilder()
10295
- .allowIf('*', '*', { ownerId })
10296
- .allow('create', '*');
10297
- }
10298
- }
10299
- /**
10300
- * Helper function to create a new permission builder
10301
- */
10302
- function permissions() {
10303
- return new PermissionBuilder();
10304
- }
10305
- /**
10306
- * Helper function to create ability from rules array
10307
- */
10308
- function defineAbility(callback) {
10309
- const builder = new PermissionBuilder();
10310
- callback(builder);
10311
- return builder.build();
10312
- }
10313
- /**
10314
- * Helper function to create common role-based abilities
10315
- */
10316
- function defineRoleAbility(role, callback) {
10317
- const roleBuilder = new RoleBuilder(role);
10318
- callback(roleBuilder);
10319
- return new AbilityCore(roleBuilder.getRules());
10320
- }
10321
-
10322
9758
  const ThemeModeContext = createContext(null);
10323
9759
  // Default persistence using localStorage (web only)
10324
9760
  const defaultPersistence = {
@@ -10448,7 +9884,6 @@ const OverlayBoundary = React__default.memo(function OverlayBoundary({ enabled,
10448
9884
  const I18nBoundary = React__default.memo(function I18nBoundary({ locale, fallbackLocale, resources, children }) {
10449
9885
  return (jsx(I18nProvider, { initial: { locale, fallbackLocale, resources }, children: children }));
10450
9886
  });
10451
- const DEFAULT_PERMISSION_RULES = [{ action: '*', subject: '*' }];
10452
9887
  /**
10453
9888
  * Internal component that uses the enhanced theme mode when config is provided
10454
9889
  */
@@ -10486,30 +9921,20 @@ function PlatformBlocksContent({ children, theme, inherit = true, withCSSVariabl
10486
9921
  document.documentElement.setAttribute('data-platform-blocks-color-scheme', target);
10487
9922
  }
10488
9923
  }, [effectiveColorScheme, osColorScheme]);
10489
- const mainContent = (jsxs(ThemeBoundary, { theme: resolvedTheme, inherit: inherit, withCSSVariables: withCSSVariables, cssVariablesSelector: cssVariablesSelector, withGlobalCSS: withGlobalCSS, children: [children, withSpotlight && jsx(SpotlightController, { config: spotlightConfig })] }));
10490
- return (jsx(OverlayBoundary, { enabled: withOverlays, children: mainContent }));
9924
+ const mainContent = (jsx(ThemeBoundary, { theme: resolvedTheme, inherit: inherit, withCSSVariables: withCSSVariables, cssVariablesSelector: cssVariablesSelector, withGlobalCSS: withGlobalCSS, children: jsxs(OverlayBoundary, { enabled: withOverlays, children: [children, withSpotlight && jsx(SpotlightController, { config: spotlightConfig })] }) }));
9925
+ return mainContent;
10491
9926
  }
10492
9927
  /**
10493
9928
  * Main provider component for Platform Blocks library
10494
9929
  * Provides theme context and injects CSS variables
10495
9930
  */
10496
- function PlatformBlocksProvider({ children, theme, inherit = true, withCSSVariables = true, cssVariablesSelector = ':root', colorSchemeMode = 'auto', withOverlays = true, withSpotlight = false, withGlobalCSS = true, themeModeConfig, spotlightConfig, locale = 'en', fallbackLocale = 'en', i18nResources, direction, haptics, permissions }) {
9931
+ function PlatformBlocksProvider({ children, theme, inherit = true, withCSSVariables = true, cssVariablesSelector = ':root', colorSchemeMode = 'auto', withOverlays = true, withSpotlight = false, withGlobalCSS = true, themeModeConfig, spotlightConfig, locale = 'en', fallbackLocale = 'en', i18nResources, direction, haptics }) {
10497
9932
  const i18nStore = useMemo(() => i18nResources || { en: { translation: {} } }, [i18nResources]);
10498
9933
  const content = (jsx(PlatformBlocksContent, { theme: theme, inherit: inherit, withCSSVariables: withCSSVariables, cssVariablesSelector: cssVariablesSelector, colorSchemeMode: colorSchemeMode, withOverlays: withOverlays, withSpotlight: withSpotlight, withGlobalCSS: withGlobalCSS, spotlightConfig: spotlightConfig, themeModeConfig: themeModeConfig, children: children }));
10499
9934
  const themedTree = themeModeConfig ? (jsx(ThemeModeProvider, { config: themeModeConfig, children: content })) : (content);
10500
9935
  const directionConfig = direction === false ? null : (direction !== null && direction !== void 0 ? direction : {});
10501
9936
  const hapticsConfig = haptics === false ? null : (haptics !== null && haptics !== void 0 ? haptics : {});
10502
- const permissionConfig = permissions === false ? null : (() => {
10503
- const base = { ...(permissions !== null && permissions !== void 0 ? permissions : {}) };
10504
- if (base.rules === undefined) {
10505
- base.rules = DEFAULT_PERMISSION_RULES;
10506
- }
10507
- return base;
10508
- })();
10509
9937
  let enhancedTree = themedTree;
10510
- if (permissionConfig) {
10511
- enhancedTree = (jsx(PermissionProvider, { ...permissionConfig, children: enhancedTree }));
10512
- }
10513
9938
  if (hapticsConfig) {
10514
9939
  enhancedTree = (jsx(HapticsProvider, { ...hapticsConfig, children: enhancedTree }));
10515
9940
  }
@@ -10999,14 +10424,18 @@ function usePopoverPositioning(isOpen, options = {}) {
10999
10424
  // Get popover dimensions
11000
10425
  // Always use measureElement for robustness across platforms (RNW refs may not expose getBoundingClientRect)
11001
10426
  let popoverDimensions = { width: 200, height: 100 }; // sensible defaults for initial calculation
10427
+ let hasMeasuredPopover = false;
11002
10428
  if (popoverRef.current) {
11003
10429
  const popoverRect = await measureElement(popoverRef);
11004
10430
  if (popoverRect.width > 0 && popoverRect.height > 0) {
11005
10431
  popoverDimensions = { width: popoverRect.width, height: popoverRect.height };
10432
+ hasMeasuredPopover = true;
11006
10433
  }
11007
10434
  }
11008
10435
  // Calculate optimal position
11009
10436
  const result = calculateOverlayPositionEnhanced(anchorRect, popoverDimensions, positioningOptionsRef.current);
10437
+ // Mark whether this position is based on actual measurements
10438
+ result._hasMeasuredPopover = hasMeasuredPopover;
11010
10439
  setPosition(result);
11011
10440
  }
11012
10441
  catch (error) {
@@ -12056,7 +11485,7 @@ function AppShellBase(props, ref) {
12056
11485
  const breakpoint = useBreakpoint();
12057
11486
  // Determine if mobile based on breakpoint and platform
12058
11487
  const isMobile = Platform.OS !== 'web' || breakpoint === 'xs' || breakpoint === 'sm';
12059
- const headerConfig = layoutVisibility.header && !isMobile ? header : undefined;
11488
+ const headerConfig = layoutVisibility.header ? header : undefined;
12060
11489
  const navbarConfig = layoutVisibility.navbar ? navbar : undefined;
12061
11490
  const asideConfig = layoutVisibility.aside ? aside : undefined;
12062
11491
  const footerConfig = layoutVisibility.footer ? footer : undefined;
@@ -17148,9 +16577,7 @@ const createInputStyles = (theme, isRTL = false) => {
17148
16577
  ? theme.colors.error[5]
17149
16578
  : props.focused
17150
16579
  ? theme.colors.primary[5]
17151
- : props.disabled
17152
- ? theme.backgrounds.border
17153
- : 'transparent',
16580
+ : theme.backgrounds.border,
17154
16581
  // Optional focus shadow (web only) without affecting layout
17155
16582
  ...(props.focused && !props.disabled && typeof window !== 'undefined' && ((_a = theme.states) === null || _a === void 0 ? void 0 : _a.focusRing) && {
17156
16583
  boxShadow: `0 0 0 2px ${theme.states.focusRing}`,
@@ -17259,6 +16686,7 @@ const TextInputBase = factory((props, ref) => {
17259
16686
  const { value, onChangeText, onEnter, label, description, error, helperText, disabled, required, size = 'md', withAsterisk, placeholder, startSection, endSection, focused: focusedProp, accessibilityLabel, accessibilityHint, testID, textInputProps, style, radius, secureTextEntry, clearable, clearButtonLabel, onClear, inputRef, name, keyboardFocusId, ...rest } = otherProps;
17260
16687
  const renderDisclaimer = useDisclaimer(disclaimerData.disclaimer, disclaimerData.disclaimerProps);
17261
16688
  const [focused, setFocused] = useState(false);
16689
+ const [cursorVisible, setCursorVisible] = useState(true);
17262
16690
  const theme = useTheme();
17263
16691
  const { isRTL } = useDirection();
17264
16692
  const internalInputRef = useRef(null);
@@ -17330,6 +16758,16 @@ const TextInputBase = factory((props, ref) => {
17330
16758
  return '';
17331
16759
  return '•'.repeat(length);
17332
16760
  }, [isSecureEntry, normalizedValue]);
16761
+ // Blinking cursor for secure entry (simple interval toggle)
16762
+ useEffect(() => {
16763
+ if (focused && isSecureEntry) {
16764
+ setCursorVisible(true);
16765
+ const interval = setInterval(() => {
16766
+ setCursorVisible(v => !v);
16767
+ }, 530);
16768
+ return () => clearInterval(interval);
16769
+ }
16770
+ }, [focused, isSecureEntry]);
17333
16771
  const textColor = (_a = flattenedInputStyle === null || flattenedInputStyle === void 0 ? void 0 : flattenedInputStyle.color) !== null && _a !== void 0 ? _a : (styleProps.disabled ? theme.text.disabled : theme.text.primary);
17334
16772
  const resolvedInputStyle = useMemo(() => {
17335
16773
  const base = [styles.input];
@@ -17431,7 +16869,12 @@ const TextInputBase = factory((props, ref) => {
17431
16869
  }
17432
16870
  }, [keyboardManager, pendingFocusTarget, focusTargetId]);
17433
16871
  const disclaimerNode = renderDisclaimer();
17434
- return (jsxs(View, { style: [styles.container, spacingStyles, layoutStyles, style], ...rest, children: [jsx(FieldHeader, { label: label, description: description, required: required, withAsterisk: withAsterisk, disabled: disabled, error: !!error, size: size }), jsxs(View, { style: styles.inputContainer, children: [startSection && (jsx(View, { style: styles.startSection, children: startSection })), jsxs(View, { style: { flex: 1, position: 'relative', justifyContent: 'center' }, children: [jsx(TextInput, { ref: assignInputRef, value: value, onChangeText: onChangeText, onFocus: handleFocus, onBlur: handleBlur, onSubmitEditing: handleSubmitEditing, editable: !disabled, placeholder: placeholder, placeholderTextColor: theme.text.muted, style: resolvedInputStyle, selectionColor: selectionColorProp !== null && selectionColorProp !== void 0 ? selectionColorProp : textColor, testID: testID, secureTextEntry: isSecureEntry, ...inputAccessibilityProps, ...restTextInputProps }), isSecureEntry && maskedValue.length > 0 && (jsx(Text$1, { pointerEvents: "none", accessible: false, style: overlayStyle, numberOfLines: 1, ellipsizeMode: "clip", children: maskedValue }))] }), (showClearButton || endSection) && (jsxs(View, { style: styles.endSection, children: [showClearButton && (jsx(ClearButton, { onPress: handleClear, size: size, accessibilityLabel: clearButtonLabelText, hasRightSection: !!endSection })), endSection] }))] }), disclaimerNode, error && (jsx(Text$1, { style: styles.error, role: "alert", accessibilityLiveRegion: "polite", children: error })), helperText && !error && (jsx(Text$1, { style: styles.helperText, children: helperText }))] }));
16872
+ return (jsxs(View, { style: [styles.container, spacingStyles, layoutStyles, style], ...rest, children: [jsx(FieldHeader, { label: label, description: description, required: required, withAsterisk: withAsterisk, disabled: disabled, error: !!error, size: size }), jsxs(View, { style: styles.inputContainer, children: [startSection && (jsx(View, { style: styles.startSection, children: startSection })), jsxs(View, { style: { flex: 1, position: 'relative', justifyContent: 'center' }, children: [jsx(TextInput, { ref: assignInputRef, value: value, onChangeText: onChangeText, onFocus: handleFocus, onBlur: handleBlur, onSubmitEditing: handleSubmitEditing, editable: !disabled, placeholder: placeholder, placeholderTextColor: theme.text.muted, style: resolvedInputStyle, selectionColor: selectionColorProp !== null && selectionColorProp !== void 0 ? selectionColorProp : textColor, testID: testID, secureTextEntry: isSecureEntry, ...inputAccessibilityProps, ...restTextInputProps }), isSecureEntry && (jsxs(View, { pointerEvents: "none", style: [overlayStyle, { flexDirection: 'row', alignItems: 'center' }], children: [jsx(Text$1, { accessible: false, style: { color: textColor, fontSize: styles.input.fontSize, fontFamily: theme.fontFamily }, numberOfLines: 1, children: maskedValue }), focused && cursorVisible && (jsx(View, { style: {
16873
+ width: 1,
16874
+ height: styles.input.fontSize || 16,
16875
+ backgroundColor: textColor,
16876
+ marginLeft: 1,
16877
+ } }))] }))] }), (showClearButton || endSection) && (jsxs(View, { style: styles.endSection, children: [showClearButton && (jsx(ClearButton, { onPress: handleClear, size: size, accessibilityLabel: clearButtonLabelText, hasRightSection: !!endSection })), endSection] }))] }), disclaimerNode, error && (jsx(Text$1, { style: styles.error, role: "alert", accessibilityLiveRegion: "polite", children: error })), helperText && !error && (jsx(Text$1, { style: styles.helperText, children: helperText }))] }));
17435
16878
  });
17436
16879
 
17437
16880
  const getInputTypeConfig = (type) => {
@@ -17989,18 +17432,19 @@ const useTextAreaStyles = (props) => {
17989
17432
  ? theme.colors.error[5]
17990
17433
  : styleProps.focused
17991
17434
  ? theme.colors.primary[5]
17992
- : styleProps.disabled
17993
- ? theme.backgrounds.border
17994
- : 'transparent',
17435
+ : theme.backgrounds.border,
17995
17436
  borderRadius: DESIGN_TOKENS.radius.lg,
17996
- borderWidth: DESIGN_TOKENS.radius.xs,
17437
+ borderWidth: 2,
17997
17438
  paddingHorizontal: DESIGN_TOKENS.spacing.sm,
17998
17439
  paddingVertical: DESIGN_TOKENS.spacing.xs,
17440
+ // Match Input focus treatment on web
17999
17441
  ...(styleProps.focused && !styleProps.disabled && Platform.OS === 'web' && {
18000
17442
  boxShadow: `0 0 0 2px ${((_a = theme.states) === null || _a === void 0 ? void 0 : _a.focusRing) || theme.colors.primary[2]}`,
18001
17443
  }),
17444
+ // Light elevation similar to Input
18002
17445
  ...(!styleProps.disabled && theme.colorScheme === 'light' && {
18003
17446
  elevation: 1,
17447
+ boxShadow: '0 1px 2px rgba(0, 0, 0, 0.05)',
18004
17448
  }),
18005
17449
  opacity: styleProps.disabled ? DESIGN_TOKENS.opacity.disabled : 1,
18006
17450
  },
@@ -19682,7 +19126,7 @@ const useSwitchStyles = (props) => {
19682
19126
  ...(Platform.OS === 'web' && { userSelect: 'none' }),
19683
19127
  },
19684
19128
  labelContainer: {
19685
- flex: 1,
19129
+ flexShrink: 1,
19686
19130
  justifyContent: 'center',
19687
19131
  },
19688
19132
  labelDisabled: {
@@ -19851,8 +19295,8 @@ const Switch = factory((rawProps, ref) => {
19851
19295
  const LayoutComponent = isVertical ? Column : Row;
19852
19296
  // For vertical layouts (top/bottom), we want tighter spacing and center alignment
19853
19297
  const layoutProps = isVertical
19854
- ? { gap: 'xs', style: { alignItems: 'center' } }
19855
- : { gap: 'sm', style: { alignItems: 'center' } };
19298
+ ? { gap: 'xs', align: 'center' }
19299
+ : { gap: 'sm', align: 'center' };
19856
19300
  const disclaimerNode = renderDisclaimer();
19857
19301
  return (jsxs(View, { style: spacingStyles, children: [jsxs(LayoutComponent, { ...layoutProps, children: [labelPosition === 'top' && labelElement, labelPosition === 'left' && labelElement, switchElement, labelPosition === 'right' && labelElement, labelPosition === 'bottom' && labelElement] }), disclaimerNode ? (jsx(View, { style: { width: '100%' }, children: disclaimerNode })) : null] }));
19858
19302
  });
@@ -21047,105 +20491,116 @@ const useSliderGesture = (min, max, step, restrictToTicks, ticks, disabled) => {
21047
20491
  }, [min, max, step, restrictToTicks, ticks]);
21048
20492
  return { calculateNewValue };
21049
20493
  };
21050
- const SliderTrack = ({ disabled, theme, size, orientation, activeWidth = 0, activeLeft = SLIDER_CONSTANTS.THUMB_SIZE[size] / 2, isRange = false }) => {
20494
+ const SliderTrack = ({ disabled, theme, size, orientation, activeWidth = 0, activeLeft, isRange = false, trackColor, activeTrackColor, trackStyle, activeTrackStyle, trackHeight, thumbSize, }) => {
21051
20495
  const orientationProps = getOrientationProps(orientation);
21052
- const thumbSize = SLIDER_CONSTANTS.THUMB_SIZE[size];
21053
- const trackHeight = SLIDER_CONSTANTS.TRACK_HEIGHT[size];
21054
- const baseTrackStyle = {
20496
+ const resolvedThumbSize = thumbSize !== null && thumbSize !== void 0 ? thumbSize : SLIDER_CONSTANTS.THUMB_SIZE[size];
20497
+ const resolvedTrackHeight = trackHeight !== null && trackHeight !== void 0 ? trackHeight : SLIDER_CONSTANTS.TRACK_HEIGHT[size];
20498
+ const resolvedActiveLeft = activeLeft !== null && activeLeft !== void 0 ? activeLeft : (resolvedThumbSize / 2);
20499
+ const inactiveTrackBaseStyle = {
21055
20500
  position: 'absolute',
21056
- backgroundColor: disabled ? theme.colors.gray[2] : theme.colors.gray[3],
21057
- borderRadius: trackHeight / 2,
20501
+ backgroundColor: disabled && !trackColor ? theme.colors.gray[2] : (trackColor !== null && trackColor !== void 0 ? trackColor : theme.colors.gray[3]),
20502
+ borderRadius: resolvedTrackHeight / 2,
21058
20503
  };
21059
- const activeTrackStyle = {
20504
+ const activeTrackBaseStyle = {
21060
20505
  position: 'absolute',
21061
- backgroundColor: disabled ? theme.colors.gray[4] : theme.colors.primary[5],
21062
- borderRadius: trackHeight / 2,
20506
+ backgroundColor: disabled && !activeTrackColor ? theme.colors.gray[4] : (activeTrackColor !== null && activeTrackColor !== void 0 ? activeTrackColor : theme.colors.primary[5]),
20507
+ borderRadius: resolvedTrackHeight / 2,
21063
20508
  };
21064
20509
  if (orientationProps.isVertical) {
21065
- return (jsxs(Fragment, { children: [jsx(View, { style: {
21066
- ...baseTrackStyle,
21067
- top: thumbSize / 2,
21068
- bottom: thumbSize / 2,
21069
- width: trackHeight,
21070
- left: (thumbSize - trackHeight) / 2,
21071
- } }), activeWidth > 0 && (jsx(View, { style: {
21072
- ...activeTrackStyle,
21073
- // For range sliders, use activeLeft as top position; for single sliders, start from bottom
21074
- ...(isRange ? {
21075
- top: activeLeft,
21076
- height: activeWidth,
21077
- } : {
21078
- bottom: thumbSize / 2,
21079
- height: activeWidth,
21080
- }),
21081
- width: trackHeight,
21082
- left: (thumbSize - trackHeight) / 2,
21083
- } }))] }));
21084
- }
21085
- return (jsxs(Fragment, { children: [jsx(View, { style: {
21086
- ...baseTrackStyle,
21087
- left: thumbSize / 2,
21088
- right: thumbSize / 2,
21089
- height: trackHeight,
21090
- top: (SLIDER_CONSTANTS.CONTAINER_HEIGHT - trackHeight) / 2,
21091
- } }), activeWidth > 0 && (jsx(View, { style: {
21092
- ...activeTrackStyle,
21093
- left: activeLeft,
21094
- width: activeWidth,
21095
- height: trackHeight,
21096
- top: (SLIDER_CONSTANTS.CONTAINER_HEIGHT - trackHeight) / 2,
21097
- } }))] }));
21098
- };
21099
- const SliderTicks = ({ ticks, disabled, theme, size, orientation, keyPrefix = 'tick' }) => {
20510
+ return (jsxs(Fragment, { children: [jsx(View, { style: [
20511
+ {
20512
+ ...inactiveTrackBaseStyle,
20513
+ top: resolvedThumbSize / 2,
20514
+ bottom: resolvedThumbSize / 2,
20515
+ width: resolvedTrackHeight,
20516
+ left: (resolvedThumbSize - resolvedTrackHeight) / 2,
20517
+ },
20518
+ trackStyle,
20519
+ ] }), activeWidth > 0 && (jsx(View, { style: [
20520
+ {
20521
+ ...activeTrackBaseStyle,
20522
+ ...(isRange ? {
20523
+ top: activeLeft !== null && activeLeft !== void 0 ? activeLeft : resolvedActiveLeft,
20524
+ height: activeWidth,
20525
+ } : {
20526
+ bottom: resolvedThumbSize / 2,
20527
+ height: activeWidth,
20528
+ }),
20529
+ width: resolvedTrackHeight,
20530
+ left: (resolvedThumbSize - resolvedTrackHeight) / 2,
20531
+ },
20532
+ activeTrackStyle,
20533
+ ] }))] }));
20534
+ }
20535
+ return (jsxs(Fragment, { children: [jsx(View, { style: [
20536
+ {
20537
+ ...inactiveTrackBaseStyle,
20538
+ left: resolvedThumbSize / 2,
20539
+ right: resolvedThumbSize / 2,
20540
+ height: resolvedTrackHeight,
20541
+ top: (SLIDER_CONSTANTS.CONTAINER_HEIGHT - resolvedTrackHeight) / 2,
20542
+ },
20543
+ trackStyle,
20544
+ ] }), activeWidth > 0 && (jsx(View, { style: [
20545
+ {
20546
+ ...activeTrackBaseStyle,
20547
+ left: activeLeft !== null && activeLeft !== void 0 ? activeLeft : resolvedActiveLeft,
20548
+ width: activeWidth,
20549
+ height: resolvedTrackHeight,
20550
+ top: (SLIDER_CONSTANTS.CONTAINER_HEIGHT - resolvedTrackHeight) / 2,
20551
+ },
20552
+ activeTrackStyle,
20553
+ ] }))] }));
20554
+ };
20555
+ const SliderTicks = ({ ticks, disabled, theme, size, orientation, keyPrefix = 'tick', trackHeight, thumbSize, activeTickColor, tickColor, }) => {
21100
20556
  const orientationProps = getOrientationProps(orientation);
21101
- const thumbSize = SLIDER_CONSTANTS.THUMB_SIZE[size];
21102
- const trackHeight = SLIDER_CONSTANTS.TRACK_HEIGHT[size];
20557
+ const resolvedThumbSize = thumbSize !== null && thumbSize !== void 0 ? thumbSize : SLIDER_CONSTANTS.THUMB_SIZE[size];
20558
+ const resolvedTrackHeight = trackHeight !== null && trackHeight !== void 0 ? trackHeight : SLIDER_CONSTANTS.TRACK_HEIGHT[size];
20559
+ const inactiveColor = disabled && !tickColor ? theme.colors.gray[2] : (tickColor !== null && tickColor !== void 0 ? tickColor : theme.colors.gray[4]);
20560
+ const activeColor = disabled && !activeTickColor ? theme.colors.gray[4] : (activeTickColor !== null && activeTickColor !== void 0 ? activeTickColor : theme.colors.primary[5]);
21103
20561
  if (orientationProps.isVertical) {
21104
20562
  return (jsxs(Fragment, { children: [ticks.map((tick, index) => (jsx(View, { style: {
21105
20563
  position: 'absolute',
21106
- top: thumbSize / 2 + tick.position,
21107
- left: (thumbSize - trackHeight) / 2 - 3,
20564
+ top: resolvedThumbSize / 2 + tick.position,
20565
+ left: (resolvedThumbSize - resolvedTrackHeight) / 2 - 3,
21108
20566
  height: 2,
21109
- width: trackHeight + 6,
21110
- backgroundColor: tick.isActive
21111
- ? (disabled ? theme.colors.gray[4] : theme.colors.primary[5])
21112
- : (disabled ? theme.colors.gray[2] : theme.colors.gray[4]),
20567
+ width: resolvedTrackHeight + 6,
20568
+ backgroundColor: tick.isActive ? activeColor : inactiveColor,
21113
20569
  borderRadius: 1,
21114
20570
  } }, `${keyPrefix}-${tick.value}-${index}`))), ticks.map((tick, index) => (tick.label ? (jsx(View, { style: {
21115
20571
  position: 'absolute',
21116
- top: thumbSize / 2 + tick.position - 10,
21117
- left: thumbSize + 8,
20572
+ top: resolvedThumbSize / 2 + tick.position - 10,
20573
+ left: resolvedThumbSize + 8,
21118
20574
  height: 20,
21119
20575
  justifyContent: 'center',
21120
20576
  }, children: jsx(Text, { size: "xs", children: tick.label }) }, `${keyPrefix}-label-${tick.value}-${index}`)) : null))] }));
21121
20577
  }
21122
20578
  return (jsxs(Fragment, { children: [ticks.map((tick, index) => (jsx(View, { style: {
21123
20579
  position: 'absolute',
21124
- left: thumbSize / 2 + tick.position,
21125
- top: (SLIDER_CONSTANTS.CONTAINER_HEIGHT - trackHeight) / 2 - 3,
20580
+ left: resolvedThumbSize / 2 + tick.position,
20581
+ top: (SLIDER_CONSTANTS.CONTAINER_HEIGHT - resolvedTrackHeight) / 2 - 3,
21126
20582
  width: 2,
21127
- height: trackHeight + 6,
21128
- backgroundColor: tick.isActive
21129
- ? (disabled ? theme.colors.gray[4] : theme.colors.primary[5])
21130
- : (disabled ? theme.colors.gray[2] : theme.colors.gray[4]),
20583
+ height: resolvedTrackHeight + 6,
20584
+ backgroundColor: tick.isActive ? activeColor : inactiveColor,
21131
20585
  borderRadius: 1,
21132
20586
  } }, `${keyPrefix}-${tick.value}-${index}`))), ticks.map((tick, index) => (tick.label ? (jsx(View, { style: {
21133
20587
  position: 'absolute',
21134
- left: thumbSize / 2 + tick.position - 20,
20588
+ left: resolvedThumbSize / 2 + tick.position - 20,
21135
20589
  top: SLIDER_CONSTANTS.CONTAINER_HEIGHT + 8,
21136
20590
  width: 40,
21137
20591
  alignItems: 'center',
21138
20592
  }, children: jsx(Text, { size: "xs", style: { textAlign: 'center' }, children: tick.label }) }, `${keyPrefix}-label-${tick.value}-${index}`)) : null))] }));
21139
20593
  };
21140
- const SliderThumb = ({ position, disabled, theme, size, orientation, isDragging, zIndex = 1, panHandlers }) => {
20594
+ const SliderThumb = ({ position, disabled, theme, size, orientation, isDragging, zIndex = 1, panHandlers, thumbColor, thumbStyle, thumbSize, }) => {
21141
20595
  const orientationProps = getOrientationProps(orientation);
21142
- const thumbSize = SLIDER_CONSTANTS.THUMB_SIZE[size];
20596
+ const resolvedThumbSize = thumbSize !== null && thumbSize !== void 0 ? thumbSize : SLIDER_CONSTANTS.THUMB_SIZE[size];
20597
+ const resolvedThumbColor = disabled && !thumbColor ? theme.colors.gray[4] : (thumbColor !== null && thumbColor !== void 0 ? thumbColor : theme.colors.primary[5]);
21143
20598
  const baseStyle = {
21144
20599
  position: 'absolute',
21145
- width: thumbSize,
21146
- height: thumbSize,
21147
- backgroundColor: disabled ? theme.colors.gray[4] : theme.colors.primary[5],
21148
- borderRadius: thumbSize / 2,
20600
+ width: resolvedThumbSize,
20601
+ height: resolvedThumbSize,
20602
+ backgroundColor: resolvedThumbColor,
20603
+ borderRadius: resolvedThumbSize / 2,
21149
20604
  borderWidth: 2,
21150
20605
  borderColor: 'white',
21151
20606
  boxShadow: '0 2px 4px rgba(0, 0, 0, 0.2)',
@@ -21154,36 +20609,43 @@ const SliderThumb = ({ position, disabled, theme, size, orientation, isDragging,
21154
20609
  zIndex,
21155
20610
  };
21156
20611
  if (orientationProps.isVertical) {
21157
- return (jsx(View, { style: {
21158
- ...baseStyle,
21159
- top: position,
21160
- left: 0,
21161
- }, ...panHandlers }));
20612
+ return (jsx(View, { style: [
20613
+ baseStyle,
20614
+ {
20615
+ top: position,
20616
+ left: 0,
20617
+ },
20618
+ thumbStyle,
20619
+ ], ...panHandlers }));
21162
20620
  }
21163
- return (jsx(View, { style: {
21164
- ...baseStyle,
21165
- left: position,
21166
- top: (SLIDER_CONSTANTS.CONTAINER_HEIGHT - thumbSize) / 2,
21167
- }, ...panHandlers }));
20621
+ return (jsx(View, { style: [
20622
+ baseStyle,
20623
+ {
20624
+ left: position,
20625
+ top: (SLIDER_CONSTANTS.CONTAINER_HEIGHT - resolvedThumbSize) / 2,
20626
+ },
20627
+ thumbStyle,
20628
+ ], ...panHandlers }));
21168
20629
  };
21169
20630
  const SliderLabel = ({ label }) => (jsx(View, { style: { marginBottom: 8 }, children: typeof label === 'string' ? (jsx(Text, { size: "sm", weight: "medium", children: label })) : (label) }));
21170
- const SliderValueLabel = ({ value, position, size, orientation, isCard = false }) => {
20631
+ const SliderValueLabel = ({ value, position, size, orientation, isCard = false, thumbSize, }) => {
21171
20632
  const orientationProps = getOrientationProps(orientation);
21172
- const thumbSize = SLIDER_CONSTANTS.THUMB_SIZE[size];
20633
+ const resolvedThumbSize = thumbSize !== null && thumbSize !== void 0 ? thumbSize : SLIDER_CONSTANTS.THUMB_SIZE[size];
21173
20634
  // round number to 2 decimal places for display
21174
20635
  const displayValue = typeof value === 'number' ? value.toFixed(2) : value;
21175
20636
  if (orientationProps.isVertical) {
20637
+ const verticalLabelOffset = resolvedThumbSize + 16; // keep label clear of the thumb
21176
20638
  return (jsx(View, { style: {
21177
20639
  position: 'absolute',
21178
- top: position + (thumbSize / 2) - 10,
21179
- right: thumbSize + 8,
20640
+ top: position + (resolvedThumbSize / 2) - 10,
20641
+ right: verticalLabelOffset,
21180
20642
  height: 20,
21181
20643
  justifyContent: 'center',
21182
20644
  }, children: isCard ? (jsx(Card, { p: "xs", variant: "filled", children: jsx(Text, { size: "sm", children: displayValue }) })) : (jsx(Text, { size: "sm", children: displayValue })) }));
21183
20645
  }
21184
20646
  return (jsx(View, { style: {
21185
20647
  position: 'absolute',
21186
- left: position + (thumbSize / 2) - 50,
20648
+ left: position + (resolvedThumbSize / 2) - 50,
21187
20649
  bottom: SLIDER_CONSTANTS.CONTAINER_HEIGHT - 6, // Moved closer to thumb
21188
20650
  width: 100,
21189
20651
  alignItems: 'center',
@@ -21199,9 +20661,34 @@ const SLIDER_SIZE_SCALE = {
21199
20661
  '2xl': 'lg',
21200
20662
  '3xl': 'lg',
21201
20663
  };
20664
+ const resolvePaletteColor = (themeColors, scheme) => {
20665
+ if (!scheme || typeof scheme !== 'string') {
20666
+ return undefined;
20667
+ }
20668
+ const palette = themeColors[scheme];
20669
+ if (Array.isArray(palette)) {
20670
+ return palette;
20671
+ }
20672
+ return undefined;
20673
+ };
20674
+ const resolveSliderColors = (theme, { colorScheme, trackColor, activeTrackColor, thumbColor, tickColor, activeTickColor, }) => {
20675
+ var _a, _b;
20676
+ const palette = resolvePaletteColor(theme.colors, colorScheme);
20677
+ const schemeColor = (_b = (_a = palette === null || palette === void 0 ? void 0 : palette[5]) !== null && _a !== void 0 ? _a : (typeof colorScheme === 'string' ? colorScheme : undefined)) !== null && _b !== void 0 ? _b : theme.colors.primary[5];
20678
+ const resolvedActiveTrack = activeTrackColor !== null && activeTrackColor !== void 0 ? activeTrackColor : schemeColor;
20679
+ const defaultTrackColor = theme.colorScheme === 'dark' ? theme.colors.gray[6] : theme.colors.gray[3];
20680
+ const defaultTickColor = theme.colorScheme === 'dark' ? theme.colors.gray[5] : theme.colors.gray[4];
20681
+ return {
20682
+ trackColor: trackColor !== null && trackColor !== void 0 ? trackColor : defaultTrackColor,
20683
+ activeTrackColor: resolvedActiveTrack,
20684
+ thumbColor: thumbColor !== null && thumbColor !== void 0 ? thumbColor : resolvedActiveTrack,
20685
+ tickColor: tickColor !== null && tickColor !== void 0 ? tickColor : defaultTickColor,
20686
+ activeTickColor: activeTickColor !== null && activeTickColor !== void 0 ? activeTickColor : resolvedActiveTrack,
20687
+ };
20688
+ };
21202
20689
  // Optimized Single Slider Component
21203
20690
  const Slider = factory((props, ref) => {
21204
- const { value, defaultValue = 0, onChange, min = 0, max = 100, step = 1, disabled = false, size = 'md', orientation = 'horizontal', containerSize, fullWidth = true, label, valueLabel, valueLabelAlwaysOn = false, ticks, showTicks = false, restrictToTicks = false, style, ...spacingProps } = props;
20691
+ const { value, defaultValue = 0, onChange, min = 0, max = 100, step = 1, disabled = false, size = 'md', orientation = 'horizontal', containerSize, fullWidth = true, label, valueLabel, valueLabelAlwaysOn = false, ticks, showTicks = false, restrictToTicks = false, trackColor, activeTrackColor, thumbColor, trackSize, thumbSize: thumbSizeProp, colorScheme = 'primary', trackStyle, activeTrackStyle, thumbStyle, tickColor, activeTickColor, style, ...spacingProps } = props;
21205
20692
  const theme = useTheme();
21206
20693
  const [isDragging, setIsDragging] = useState(false);
21207
20694
  // Uncontrolled internal value
@@ -21230,14 +20717,31 @@ const Slider = factory((props, ref) => {
21230
20717
  : 'md'
21231
20718
  : (resolvedSliderSize !== null && resolvedSliderSize !== void 0 ? resolvedSliderSize : 'md');
21232
20719
  const orientationProps = getOrientationProps(orientation, containerSize);
21233
- const thumbSize = SLIDER_CONSTANTS.THUMB_SIZE[sliderSize];
20720
+ const thumbSize = thumbSizeProp !== null && thumbSizeProp !== void 0 ? thumbSizeProp : SLIDER_CONSTANTS.THUMB_SIZE[sliderSize];
20721
+ const trackHeight = trackSize !== null && trackSize !== void 0 ? trackSize : SLIDER_CONSTANTS.TRACK_HEIGHT[sliderSize];
21234
20722
  // Memoized processed value
21235
20723
  const clampedValue = useSliderValue(isControlled ? value : internal, min, max, step, restrictToTicks, ticks, false);
21236
20724
  // Memoized value label handling
20725
+ const defaultValueFormatter = useCallback((val) => Math.round(val).toString(), []);
20726
+ const resolvedValueLabel = useMemo(() => {
20727
+ if (valueLabel === null)
20728
+ return null;
20729
+ if (valueLabel)
20730
+ return valueLabel;
20731
+ return defaultValueFormatter;
20732
+ }, [valueLabel, defaultValueFormatter]);
21237
20733
  const labelConfig = useMemo(() => ({
21238
- shouldShow: valueLabel !== null && (valueLabelAlwaysOn || isDragging || (Platform.OS === 'web' && isHovering)),
21239
- formatter: valueLabel || ((val) => (Number.isInteger(val) ? val.toString() : val.toFixed(2)))
21240
- }), [valueLabel, valueLabelAlwaysOn, isDragging, isHovering]);
20734
+ shouldShow: !!resolvedValueLabel && (valueLabelAlwaysOn || isDragging || (Platform.OS === 'web' && isHovering)),
20735
+ formatter: resolvedValueLabel !== null && resolvedValueLabel !== void 0 ? resolvedValueLabel : defaultValueFormatter,
20736
+ }), [resolvedValueLabel, valueLabelAlwaysOn, isDragging, isHovering, defaultValueFormatter]);
20737
+ const sliderColors = useMemo(() => resolveSliderColors(theme, {
20738
+ colorScheme,
20739
+ trackColor,
20740
+ activeTrackColor,
20741
+ thumbColor,
20742
+ tickColor,
20743
+ activeTickColor,
20744
+ }), [theme, colorScheme, trackColor, activeTrackColor, thumbColor, tickColor, activeTickColor]);
21241
20745
  // Memoized position calculations
21242
20746
  const positions = useMemo(() => {
21243
20747
  var _a, _b;
@@ -21367,6 +20871,7 @@ const Slider = factory((props, ref) => {
21367
20871
  height: fullWidth && orientation === 'vertical' ? '100%' : orientationProps.containerHeight,
21368
20872
  justifyContent: 'center',
21369
20873
  position: 'relative',
20874
+ ...(Platform.OS === 'web' && orientation === 'vertical' ? { touchAction: 'none' } : null),
21370
20875
  }, onLayout: (event) => {
21371
20876
  // When fullWidth is enabled, track the actual container dimensions
21372
20877
  if (fullWidth) {
@@ -21380,11 +20885,11 @@ const Slider = factory((props, ref) => {
21380
20885
  }, onStartShouldSetResponder: () => !isDragging, onResponderGrant: handlePress, ...(Platform.OS === 'web' && {
21381
20886
  onMouseEnter: () => setIsHovering(true),
21382
20887
  onMouseLeave: () => setIsHovering(false),
21383
- }), ...panResponder.panHandlers, children: [jsx(SliderTrack, { disabled: disabled, theme: theme, size: sliderSize, orientation: orientation, activeWidth: positions.activeLength }), jsx(SliderTicks, { ticks: allTicks, disabled: disabled, theme: theme, size: sliderSize, orientation: orientation }), jsx(SliderThumb, { position: positions.thumbPosition, disabled: disabled, theme: theme, size: sliderSize, orientation: orientation, isDragging: isDragging }), labelConfig.shouldShow && (jsx(SliderValueLabel, { value: labelConfig.formatter(clampedValue), position: positions.thumbPosition, size: sliderSize, orientation: orientation, isCard: true }))] })] }));
20888
+ }), ...panResponder.panHandlers, children: [jsx(SliderTrack, { disabled: disabled, theme: theme, size: sliderSize, orientation: orientation, activeWidth: positions.activeLength, trackColor: sliderColors.trackColor, activeTrackColor: sliderColors.activeTrackColor, trackStyle: trackStyle, activeTrackStyle: activeTrackStyle, trackHeight: trackHeight, thumbSize: thumbSize }), jsx(SliderTicks, { ticks: allTicks, disabled: disabled, theme: theme, size: sliderSize, orientation: orientation, trackHeight: trackHeight, thumbSize: thumbSize, tickColor: sliderColors.tickColor, activeTickColor: sliderColors.activeTickColor }), jsx(SliderThumb, { position: positions.thumbPosition, disabled: disabled, theme: theme, size: sliderSize, orientation: orientation, isDragging: isDragging, thumbColor: sliderColors.thumbColor, thumbStyle: thumbStyle, thumbSize: thumbSize }), labelConfig.shouldShow && (jsx(SliderValueLabel, { value: labelConfig.formatter(clampedValue), position: positions.thumbPosition, size: sliderSize, orientation: orientation, isCard: true, thumbSize: thumbSize }))] })] }));
21384
20889
  });
21385
20890
  // Optimized Range Slider Component
21386
20891
  const RangeSlider = factory((props, ref) => {
21387
- const { value = [0, 100], onChange, min = 0, max = 100, step = 1, disabled = false, size = 'md', orientation = 'horizontal', containerSize, fullWidth = true, label, valueLabel, valueLabelAlwaysOn = false, ticks, showTicks = false, restrictToTicks = false, pushOnOverlap = true, style, ...spacingProps } = props;
20892
+ const { value = [0, 100], onChange, min = 0, max = 100, step = 1, disabled = false, size = 'md', orientation = 'horizontal', containerSize, fullWidth = true, label, valueLabel, valueLabelAlwaysOn = false, ticks, showTicks = false, restrictToTicks = false, pushOnOverlap = true, trackColor, activeTrackColor, thumbColor, trackSize, thumbSize: thumbSizeProp, colorScheme = 'primary', trackStyle, activeTrackStyle, thumbStyle, tickColor, activeTickColor, style, ...spacingProps } = props;
21388
20893
  const theme = useTheme();
21389
20894
  const [dragState, setDragState] = useState({ thumb: null });
21390
20895
  const [isHovering, setIsHovering] = useState(false);
@@ -21404,8 +20909,17 @@ const RangeSlider = factory((props, ref) => {
21404
20909
  : 'md'
21405
20910
  : (rangeResolvedSliderSize !== null && rangeResolvedSliderSize !== void 0 ? rangeResolvedSliderSize : 'md');
21406
20911
  const orientationProps = getOrientationProps(orientation, containerSize);
21407
- const thumbSize = SLIDER_CONSTANTS.THUMB_SIZE[sliderSize];
20912
+ const thumbSize = thumbSizeProp !== null && thumbSizeProp !== void 0 ? thumbSizeProp : SLIDER_CONSTANTS.THUMB_SIZE[sliderSize];
20913
+ const trackHeight = trackSize !== null && trackSize !== void 0 ? trackSize : SLIDER_CONSTANTS.TRACK_HEIGHT[sliderSize];
21408
20914
  useRef(null);
20915
+ const sliderColors = useMemo(() => resolveSliderColors(theme, {
20916
+ colorScheme,
20917
+ trackColor,
20918
+ activeTrackColor,
20919
+ thumbColor,
20920
+ tickColor,
20921
+ activeTickColor,
20922
+ }), [theme, colorScheme, trackColor, activeTrackColor, thumbColor, tickColor, activeTickColor]);
21409
20923
  // Memoized processed values
21410
20924
  const [minValue, maxValue] = useSliderValue(value, min, max, step, restrictToTicks, ticks, true);
21411
20925
  // Memoized backward compatibility handling
@@ -21641,6 +21155,7 @@ const RangeSlider = factory((props, ref) => {
21641
21155
  height: fullWidth && orientation === 'vertical' ? '100%' : orientationProps.containerHeight,
21642
21156
  justifyContent: 'center',
21643
21157
  position: 'relative',
21158
+ ...(Platform.OS === 'web' && orientation === 'vertical' ? { touchAction: 'none' } : null),
21644
21159
  }, onLayout: (event) => {
21645
21160
  // When fullWidth is enabled, track the actual container dimensions
21646
21161
  if (fullWidth) {
@@ -21654,7 +21169,7 @@ const RangeSlider = factory((props, ref) => {
21654
21169
  }, onStartShouldSetResponder: () => true, onResponderGrant: handleTrackPress, ...(Platform.OS === 'web' && {
21655
21170
  onMouseEnter: () => setIsHovering(true),
21656
21171
  onMouseLeave: () => setIsHovering(false),
21657
- }), collapsable: false, children: [jsx(SliderTrack, { disabled: disabled, theme: theme, size: sliderSize, orientation: orientation, activeWidth: positions.activeWidth, activeLeft: positions.activeLeft, isRange: true }), jsx(SliderTicks, { ticks: allTicks, disabled: disabled, theme: theme, size: sliderSize, orientation: orientation, keyPrefix: "range-tick" }), jsx(SliderThumb, { position: positions.minThumbPosition, disabled: disabled, theme: theme, size: sliderSize, orientation: orientation, isDragging: dragState.thumb === 'min', zIndex: dragState.thumb === 'min' ? 10 : 1, panHandlers: minThumbPanResponder.panHandlers }), jsx(SliderThumb, { position: positions.maxThumbPosition, disabled: disabled, theme: theme, size: sliderSize, orientation: orientation, isDragging: dragState.thumb === 'max', zIndex: dragState.thumb === 'max' ? 10 : 2, panHandlers: maxThumbPanResponder.panHandlers }), labelConfig.shouldShow && (jsxs(Fragment, { children: [jsx(SliderValueLabel, { value: labelConfig.formatter(minValue, 0), position: positions.minThumbPosition, size: sliderSize, orientation: orientation, isCard: true }), jsx(SliderValueLabel, { value: labelConfig.formatter(maxValue, 1), position: positions.maxThumbPosition, size: sliderSize, orientation: orientation, isCard: true })] }))] })] }));
21172
+ }), collapsable: false, children: [jsx(SliderTrack, { disabled: disabled, theme: theme, size: sliderSize, orientation: orientation, activeWidth: positions.activeWidth, activeLeft: positions.activeLeft, isRange: true, trackColor: sliderColors.trackColor, activeTrackColor: sliderColors.activeTrackColor, trackStyle: trackStyle, activeTrackStyle: activeTrackStyle, trackHeight: trackHeight, thumbSize: thumbSize }), jsx(SliderTicks, { ticks: allTicks, disabled: disabled, theme: theme, size: sliderSize, orientation: orientation, keyPrefix: "range-tick", trackHeight: trackHeight, thumbSize: thumbSize, tickColor: sliderColors.tickColor, activeTickColor: sliderColors.activeTickColor }), jsx(SliderThumb, { position: positions.minThumbPosition, disabled: disabled, theme: theme, size: sliderSize, orientation: orientation, isDragging: dragState.thumb === 'min', zIndex: dragState.thumb === 'min' ? 10 : 1, panHandlers: minThumbPanResponder.panHandlers, thumbColor: sliderColors.thumbColor, thumbStyle: thumbStyle, thumbSize: thumbSize }), jsx(SliderThumb, { position: positions.maxThumbPosition, disabled: disabled, theme: theme, size: sliderSize, orientation: orientation, isDragging: dragState.thumb === 'max', zIndex: dragState.thumb === 'max' ? 10 : 2, panHandlers: maxThumbPanResponder.panHandlers, thumbColor: sliderColors.thumbColor, thumbStyle: thumbStyle, thumbSize: thumbSize }), labelConfig.shouldShow && (jsxs(Fragment, { children: [jsx(SliderValueLabel, { value: labelConfig.formatter(minValue, 0), position: positions.minThumbPosition, size: sliderSize, orientation: orientation, isCard: true, thumbSize: thumbSize }), jsx(SliderValueLabel, { value: labelConfig.formatter(maxValue, 1), position: positions.maxThumbPosition, size: sliderSize, orientation: orientation, isCard: true, thumbSize: thumbSize })] }))] })] }));
21658
21173
  });
21659
21174
 
21660
21175
  const clampNumber$1 = (value, min, max) => Math.min(max, Math.max(min, value));
@@ -27395,7 +26910,7 @@ const MiniCalendar = ({ value, onChange, defaultValue, numberOfDays = 7, default
27395
26910
  }
27396
26911
  onChange === null || onChange === void 0 ? void 0 : onChange(date);
27397
26912
  }, [isControlled, maxDate, minDate, onChange]);
27398
- return (jsxs(View, { children: [jsxs(Flex, { direction: "row", justify: "space-between", align: "center", style: { marginBottom: 16 }, children: [jsx(Pressable, { onPress: handlePrevious, style: ({ pressed }) => [
26913
+ return (jsxs(View, { style: { alignSelf: 'flex-start' }, children: [jsxs(Flex, { direction: "row", justify: "space-between", align: "center", style: { marginBottom: 16 }, children: [jsx(Pressable, { onPress: handlePrevious, style: ({ pressed }) => [
27399
26914
  {
27400
26915
  padding: 8,
27401
26916
  borderRadius: 6,
@@ -27407,7 +26922,7 @@ const MiniCalendar = ({ value, onChange, defaultValue, numberOfDays = 7, default
27407
26922
  borderRadius: 6,
27408
26923
  backgroundColor: pressed ? theme.colors.gray[2] : 'transparent',
27409
26924
  },
27410
- ], ...nextControlProps, children: jsx(Icon, { name: "chevron-right", size: 16, color: theme.colors.gray[6] }) })] }), jsx(ScrollView, { horizontal: true, showsHorizontalScrollIndicator: false, children: jsx(Flex, { direction: "row", gap: 4, children: days.map((date) => {
26925
+ ], ...nextControlProps, children: jsx(Icon, { name: "chevron-right", size: 16, color: theme.colors.gray[6] }) })] }), jsx(ScrollView, { horizontal: true, showsHorizontalScrollIndicator: false, contentContainerStyle: { flexGrow: 0 }, style: { flexGrow: 0 }, children: jsx(Flex, { direction: "row", gap: 4, children: days.map((date) => {
27411
26926
  const isSelected = selectedDate ? dateUtils$1.isSameDay(date, selectedDate) : false;
27412
26927
  const isToday = dateUtils$1.isToday(date);
27413
26928
  const isWeekend = dateUtils$1.isWeekend(date);
@@ -30148,6 +29663,7 @@ function MenuBase(props, ref) {
30148
29663
  const overlayId = openOverlay({
30149
29664
  content: menuDropdown,
30150
29665
  anchor: { x: positionResult.x, y: positionResult.y, width: overlaySize.width, height: overlaySize.height },
29666
+ placement: positionResult.placement || position,
30151
29667
  closeOnClickOutside,
30152
29668
  closeOnEscape,
30153
29669
  strategy,
@@ -31548,13 +31064,13 @@ function Indicator({ size = 'sm', color, borderColor, borderWidth = 1, placement
31548
31064
 
31549
31065
  const AVATAR_ALLOWED_SIZES = ['xs', 'sm', 'md', 'lg', 'xl', '2xl', '3xl'];
31550
31066
  const AVATAR_SIZE_SCALE = {
31551
- xs: { avatar: 24, badge: 6, text: 'xs' },
31552
- sm: { avatar: 32, badge: 8, text: 'xs' },
31553
- md: { avatar: 40, badge: 10, text: 'sm' },
31554
- lg: { avatar: 48, badge: 12, text: 'md' },
31555
- xl: { avatar: 64, badge: 16, text: 'lg' },
31556
- '2xl': { avatar: 80, badge: 20, text: 'xl' },
31557
- '3xl': { avatar: 96, badge: 24, text: '2xl' },
31067
+ xs: { avatar: 24, indicator: 6, text: 'xs' },
31068
+ sm: { avatar: 32, indicator: 8, text: 'xs' },
31069
+ md: { avatar: 40, indicator: 10, text: 'sm' },
31070
+ lg: { avatar: 48, indicator: 12, text: 'md' },
31071
+ xl: { avatar: 64, indicator: 16, text: 'lg' },
31072
+ '2xl': { avatar: 80, indicator: 20, text: 'xl' },
31073
+ '3xl': { avatar: 96, indicator: 24, text: '2xl' },
31558
31074
  };
31559
31075
  const BASE_AVATAR_METRICS = AVATAR_SIZE_SCALE.md;
31560
31076
  function resolveAvatarMetrics(value) {
@@ -31572,11 +31088,11 @@ function resolveAvatarMetrics(value) {
31572
31088
  }
31573
31089
  function calculateNumericMetrics$1(value) {
31574
31090
  const ratio = value / BASE_AVATAR_METRICS.avatar;
31575
- const badge = Math.max(4, Math.round(BASE_AVATAR_METRICS.badge * ratio));
31091
+ const indicator = Math.max(4, Math.round(BASE_AVATAR_METRICS.indicator * ratio));
31576
31092
  const text = pickTextSize(value);
31577
31093
  return {
31578
31094
  avatar: value,
31579
- badge,
31095
+ indicator,
31580
31096
  text,
31581
31097
  };
31582
31098
  }
@@ -31595,9 +31111,9 @@ function pickTextSize(value) {
31595
31111
  return 'sm';
31596
31112
  return 'xs';
31597
31113
  }
31598
- function Avatar({ size = 'md', src, fallback, backgroundColor, textColor = 'white', online, badgeColor, style, accessibilityLabel, label, description, gap = 8, showText = true, }) {
31114
+ function Avatar({ size = 'md', src, fallback, backgroundColor, textColor = 'white', online, indicatorColor, style, accessibilityLabel, label, description, gap = 8, showText = true, }) {
31599
31115
  const theme = useTheme();
31600
- const { avatar: avatarSize, badge: badgeSize, text: textSize } = resolveAvatarMetrics(size);
31116
+ const { avatar: avatarSize, indicator: indicatorSize, text: textSize } = resolveAvatarMetrics(size);
31601
31117
  const avatarStyle = {
31602
31118
  width: avatarSize,
31603
31119
  height: avatarSize,
@@ -31615,7 +31131,7 @@ function Avatar({ size = 'md', src, fallback, backgroundColor, textColor = 'whit
31615
31131
  width: avatarSize,
31616
31132
  height: avatarSize,
31617
31133
  borderRadius: avatarSize / 2,
31618
- }, accessibilityLabel: accessibilityLabel })) : (jsx(Text, { size: textSize, color: textColor, weight: "semibold", style: { textAlign: 'center' }, children: fallback || '?' })) }), online && (jsx(Indicator, { size: badgeSize, color: badgeColor || theme.colors.success[5], borderColor: theme.colors.gray[0], placement: "bottom-right" }))] }));
31134
+ }, accessibilityLabel: accessibilityLabel })) : (jsx(Text, { size: textSize, color: textColor, weight: "semibold", style: { textAlign: 'center' }, children: fallback || '?' })) }), online && (jsx(Indicator, { size: indicatorSize, color: indicatorColor || theme.colors.success[5], borderColor: theme.colors.gray[0], placement: "bottom-right" }))] }));
31619
31135
  if (label || description) {
31620
31136
  return (jsxs(View, { style: { flexDirection: 'row', alignItems: 'center' }, children: [content, showText && (jsxs(View, { style: { marginLeft: gap, justifyContent: 'center' }, children: [label && (typeof label === 'string' ? (jsx(Text, { size: textSize, weight: "semibold", children: label })) : label), description && (typeof description === 'string' ? (jsx(Text, { size: textSize, color: theme.colors.gray[6], children: description })) : description)] }))] }));
31621
31137
  }
@@ -32117,7 +31633,7 @@ function usePopoverContext(component) {
32117
31633
  const DEFAULT_ARROW_SIZE = 7;
32118
31634
  const PopoverBase = (props, ref) => {
32119
31635
  var _a;
32120
- const { children, opened: controlledOpened, defaultOpened = false, onChange, onOpen, onClose, onDismiss, disabled = false, closeOnClickOutside = true, closeOnEscape = true, clickOutsideEvents, // currently not implemented
31636
+ const { children, opened: controlledOpened, defaultOpened = false, onChange, onOpen, onClose, onDismiss, trigger = 'click', disabled = false, closeOnClickOutside = true, closeOnEscape = true, clickOutsideEvents, // currently not implemented
32121
31637
  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, keyboardAvoidance = true, fallbackPlacements, boundary, withRoles = true, id, withArrow = false, arrowSize = DEFAULT_ARROW_SIZE, arrowRadius = 0, arrowOffset = 5, arrowPosition = 'center', onPositionChange, testID, ...rest } = props;
32122
31638
  const theme = useTheme();
32123
31639
  const { spacingProps } = extractSpacingProps(rest);
@@ -32129,9 +31645,18 @@ const PopoverBase = (props, ref) => {
32129
31645
  const openedRef = useRef(opened);
32130
31646
  const closingReasonRef = useRef(null);
32131
31647
  const anchorMeasurementsRef = useRef(null);
31648
+ const hoverTimeoutRef = useRef(null);
32132
31649
  useEffect(() => {
32133
31650
  openedRef.current = opened;
32134
31651
  }, [opened]);
31652
+ // Cleanup hover timeout on unmount
31653
+ useEffect(() => {
31654
+ return () => {
31655
+ if (hoverTimeoutRef.current) {
31656
+ clearTimeout(hoverTimeoutRef.current);
31657
+ }
31658
+ };
31659
+ }, []);
32135
31660
  const resolvedOffset = typeof offset === 'number' ? offset : (_a = offset === null || offset === void 0 ? void 0 : offset.mainAxis) !== null && _a !== void 0 ? _a : 8;
32136
31661
  const resolvedFlip = preventPositionChangeWhenVisible
32137
31662
  ? false
@@ -32144,7 +31669,7 @@ const PopoverBase = (props, ref) => {
32144
31669
  ? false
32145
31670
  : true;
32146
31671
  const resolvedStrategy = floatingStrategy !== null && floatingStrategy !== void 0 ? floatingStrategy : 'fixed';
32147
- const { position: positioningResult, anchorRef, popoverRef, showOverlay, hideOverlay, updatePosition } = useDropdownPositioning({
31672
+ const { position: positioningResult, anchorRef, popoverRef, showOverlay, hideOverlay, updatePosition, isPositioning } = useDropdownPositioning({
32148
31673
  isOpen: opened && !disabled && !!dropdownState,
32149
31674
  placement: position,
32150
31675
  offset: resolvedOffset,
@@ -32156,9 +31681,20 @@ const PopoverBase = (props, ref) => {
32156
31681
  fallbackPlacements,
32157
31682
  viewport,
32158
31683
  onClose: () => handleOverlayClose('dismiss'),
32159
- closeOnClickOutside,
31684
+ closeOnClickOutside: trigger === 'hover' ? false : closeOnClickOutside,
32160
31685
  closeOnEscape,
32161
31686
  });
31687
+ // Track if we've done measurement-based positioning to avoid flicker
31688
+ const hasPositionedRef = useRef(false);
31689
+ useEffect(() => {
31690
+ // Only mark as positioned when we have a measurement-based position
31691
+ if (opened && positioningResult && positioningResult._hasMeasuredPopover) {
31692
+ hasPositionedRef.current = true;
31693
+ }
31694
+ if (!opened) {
31695
+ hasPositionedRef.current = false;
31696
+ }
31697
+ }, [opened, positioningResult]);
32162
31698
  const popoverStyles = useMemo(() => createPopoverStyles(theme)({
32163
31699
  radius,
32164
31700
  shadow,
@@ -32262,6 +31798,28 @@ const PopoverBase = (props, ref) => {
32262
31798
  openPopover();
32263
31799
  }
32264
31800
  }, [closePopover, openPopover]);
31801
+ // Hover-specific handlers with delay to prevent glitching when moving between target and dropdown
31802
+ const handleHoverOpen = useCallback(() => {
31803
+ if (hoverTimeoutRef.current) {
31804
+ clearTimeout(hoverTimeoutRef.current);
31805
+ hoverTimeoutRef.current = null;
31806
+ }
31807
+ openPopover();
31808
+ }, [openPopover]);
31809
+ const handleHoverClose = useCallback(() => {
31810
+ if (hoverTimeoutRef.current) {
31811
+ clearTimeout(hoverTimeoutRef.current);
31812
+ }
31813
+ hoverTimeoutRef.current = setTimeout(() => {
31814
+ closePopover('programmatic');
31815
+ hoverTimeoutRef.current = null;
31816
+ }, 150); // Delay to allow mouse to move to dropdown
31817
+ }, [closePopover]);
31818
+ // Store hover handlers in refs to avoid causing re-renders in useEffect
31819
+ const hoverHandlersRef = useRef({ open: handleHoverOpen, close: handleHoverClose });
31820
+ useEffect(() => {
31821
+ hoverHandlersRef.current = { open: handleHoverOpen, close: handleHoverClose };
31822
+ }, [handleHoverOpen, handleHoverClose]);
32265
31823
  useEffect(() => {
32266
31824
  if (opened) {
32267
31825
  updateAnchorMeasurements();
@@ -32320,14 +31878,26 @@ const PopoverBase = (props, ref) => {
32320
31878
  if (typeof resolvedMaxHeight === 'number')
32321
31879
  sizeStyles.maxHeight = resolvedMaxHeight;
32322
31880
  const dropdownStyle = [popoverStyles.dropdown, dropdownState.style, sizeStyles];
32323
- const content = (jsxs(View, { ref: popoverRef, style: [popoverStyles.wrapper, widthOverride ? { width: widthOverride } : null], pointerEvents: dropdownState.trapFocus ? 'auto' : 'box-none', testID: dropdownState.testID, onLayout: handleDropdownLayout, ...dropdownState.containerProps, children: [jsx(View, { style: dropdownStyle, children: dropdownState.content }), withArrow && (jsx(View, { style: getArrowStyle(positioningResult.placement, arrowSize, arrowRadius, arrowOffset, arrowPosition, theme) }))] }));
31881
+ // Hover handlers for the dropdown to keep it open when mouse moves from target to dropdown
31882
+ const dropdownHoverHandlers = trigger === 'hover' && Platform.OS === 'web'
31883
+ ? {
31884
+ onMouseEnter: () => hoverHandlersRef.current.open(),
31885
+ onMouseLeave: () => hoverHandlersRef.current.close(),
31886
+ }
31887
+ : {};
31888
+ // Hide content until we have measurement-based positioning to prevent visual "snap"
31889
+ const hasMeasuredPosition = (positioningResult === null || positioningResult === void 0 ? void 0 : positioningResult._hasMeasuredPopover) === true;
31890
+ const visibilityStyle = !hasMeasuredPosition && Platform.OS === 'web'
31891
+ ? { opacity: 0 }
31892
+ : {};
31893
+ const content = (jsxs(View, { ref: popoverRef, style: [popoverStyles.wrapper, widthOverride ? { width: widthOverride } : null, visibilityStyle], pointerEvents: trigger === 'hover' ? 'auto' : (dropdownState.trapFocus ? 'auto' : 'box-none'), testID: dropdownState.testID, onLayout: handleDropdownLayout, ...dropdownHoverHandlers, ...dropdownState.containerProps, children: [jsx(View, { style: dropdownStyle, children: dropdownState.content }), withArrow && (jsx(View, { style: getArrowStyle(positioningResult.placement, arrowSize, arrowRadius, arrowOffset, arrowPosition, theme) }))] }));
32324
31894
  showOverlay(content, {
32325
31895
  width: widthOverride,
32326
31896
  maxHeight: resolvedMaxHeight,
32327
31897
  zIndex,
32328
31898
  });
32329
31899
  onPositionChange === null || onPositionChange === void 0 ? void 0 : onPositionChange(positioningResult.placement);
32330
- }, [opened, dropdownState, positioningResult, popoverRef, showOverlay, hideOverlay, popoverStyles.dropdown, popoverStyles.wrapper, width, maxHeight, minWidth, minHeight, maxWidth, withArrow, arrowSize, arrowRadius, arrowOffset, arrowPosition, theme, zIndex, onPositionChange, schedulePositionUpdate]);
31900
+ }, [opened, dropdownState, positioningResult, popoverRef, showOverlay, hideOverlay, popoverStyles.dropdown, popoverStyles.wrapper, width, maxHeight, minWidth, minHeight, maxWidth, withArrow, arrowSize, arrowRadius, arrowOffset, arrowPosition, theme, zIndex, onPositionChange, schedulePositionUpdate, trigger, isPositioning]);
32331
31901
  useEffect(() => {
32332
31902
  return () => {
32333
31903
  hideOverlay();
@@ -32348,6 +31918,8 @@ const PopoverBase = (props, ref) => {
32348
31918
  open: openPopover,
32349
31919
  close: () => closePopover('programmatic'),
32350
31920
  toggle: togglePopover,
31921
+ hoverOpen: handleHoverOpen,
31922
+ hoverClose: handleHoverClose,
32351
31923
  registerDropdown,
32352
31924
  unregisterDropdown,
32353
31925
  anchorRef,
@@ -32356,7 +31928,8 @@ const PopoverBase = (props, ref) => {
32356
31928
  withRoles,
32357
31929
  disabled,
32358
31930
  returnFocus,
32359
- }), [opened, openPopover, closePopover, togglePopover, registerDropdown, unregisterDropdown, anchorRef, targetId, dropdownId, withRoles, disabled, returnFocus]);
31931
+ trigger,
31932
+ }), [opened, openPopover, closePopover, togglePopover, handleHoverOpen, handleHoverClose, registerDropdown, unregisterDropdown, anchorRef, targetId, dropdownId, withRoles, disabled, returnFocus, trigger]);
32360
31933
  const setContainerRef = useCallback((node) => {
32361
31934
  if (typeof ref === 'function') {
32362
31935
  ref(node);
@@ -32406,16 +31979,44 @@ const PopoverTargetBase = (props, ref) => {
32406
31979
  : { id: context.targetId };
32407
31980
  const composedRef = mergeRefs(children.ref, externalTargetRef);
32408
31981
  const triggerHandlers = {};
32409
- triggerHandlers.onPress = (...args) => {
32410
- const tgt = targetProps;
32411
- if (tgt && typeof tgt.onPress === 'function') {
32412
- tgt.onPress(...args);
32413
- }
32414
- if (typeof childProps.onPress === 'function') {
32415
- childProps.onPress(...args);
32416
- }
32417
- context.toggle();
32418
- };
31982
+ const wrapperHoverHandlers = {};
31983
+ // Click trigger: toggle on press
31984
+ if (context.trigger === 'click') {
31985
+ triggerHandlers.onPress = (...args) => {
31986
+ const tgt = targetProps;
31987
+ if (tgt && typeof tgt.onPress === 'function') {
31988
+ tgt.onPress(...args);
31989
+ }
31990
+ if (typeof childProps.onPress === 'function') {
31991
+ childProps.onPress(...args);
31992
+ }
31993
+ context.toggle();
31994
+ };
31995
+ }
31996
+ // Hover trigger: open/close on mouse enter/leave (web only)
31997
+ // Applied to the wrapper View for reliable hover detection
31998
+ if (context.trigger === 'hover' && Platform.OS === 'web') {
31999
+ wrapperHoverHandlers.onMouseEnter = (...args) => {
32000
+ const tgt = targetProps;
32001
+ if (tgt && typeof tgt.onMouseEnter === 'function') {
32002
+ tgt.onMouseEnter(...args);
32003
+ }
32004
+ if (typeof childProps.onMouseEnter === 'function') {
32005
+ childProps.onMouseEnter(...args);
32006
+ }
32007
+ context.hoverOpen();
32008
+ };
32009
+ wrapperHoverHandlers.onMouseLeave = (...args) => {
32010
+ const tgt = targetProps;
32011
+ if (tgt && typeof tgt.onMouseLeave === 'function') {
32012
+ tgt.onMouseLeave(...args);
32013
+ }
32014
+ if (typeof childProps.onMouseLeave === 'function') {
32015
+ childProps.onMouseLeave(...args);
32016
+ }
32017
+ context.hoverClose();
32018
+ };
32019
+ }
32419
32020
  if (Platform.OS === 'web') {
32420
32021
  triggerHandlers.onKeyDown = (event) => {
32421
32022
  const tgt = targetProps;
@@ -32437,7 +32038,14 @@ const PopoverTargetBase = (props, ref) => {
32437
32038
  };
32438
32039
  }
32439
32040
  const dynamicRefProp = { [refProp]: composedRef };
32440
- delete sanitizedTargetProps.onPress;
32041
+ // Remove handlers that we're overriding from sanitizedTargetProps
32042
+ if (context.trigger === 'click') {
32043
+ delete sanitizedTargetProps.onPress;
32044
+ }
32045
+ if (context.trigger === 'hover') {
32046
+ delete sanitizedTargetProps.onMouseEnter;
32047
+ delete sanitizedTargetProps.onMouseLeave;
32048
+ }
32441
32049
  delete sanitizedTargetProps.onKeyDown;
32442
32050
  const mergedProps = {
32443
32051
  ...sanitizedTargetProps,
@@ -32449,7 +32057,7 @@ const PopoverTargetBase = (props, ref) => {
32449
32057
  mergedProps.disabled = true;
32450
32058
  }
32451
32059
  const anchorWrapperRef = mergeRefs(context.anchorRef, ref);
32452
- return (jsx(View, { ref: anchorWrapperRef, collapsable: false, children: cloneElement(children, mergedProps) }));
32060
+ return (jsx(View, { ref: anchorWrapperRef, collapsable: false, ...wrapperHoverHandlers, children: cloneElement(children, mergedProps) }));
32453
32061
  };
32454
32062
  const PopoverDropdownBase = (props, _ref) => {
32455
32063
  const { children, trapFocus = false, keepMounted, style, testID, ...rest } = props;
@@ -32493,8 +32101,11 @@ function getArrowStyle(placement, arrowSize, arrowRadius, arrowOffset, arrowPosi
32493
32101
  const [side, alignment] = placement.split('-');
32494
32102
  switch (side) {
32495
32103
  case 'top':
32104
+ // Arrow points down, hide the borders that overlap with content (top-left corner after rotation)
32496
32105
  return {
32497
32106
  ...base,
32107
+ borderTopWidth: 0,
32108
+ borderLeftWidth: 0,
32498
32109
  bottom: -arrowSize,
32499
32110
  left: alignment === 'end'
32500
32111
  ? `calc(100% - ${(arrowPosition === 'side' ? arrowOffset : arrowSize)}px)`
@@ -32504,8 +32115,11 @@ function getArrowStyle(placement, arrowSize, arrowRadius, arrowOffset, arrowPosi
32504
32115
  marginLeft: alignment || arrowPosition === 'side' ? 0 : -arrowSize,
32505
32116
  };
32506
32117
  case 'bottom':
32118
+ // Arrow points up, hide the borders that overlap with content (bottom-right corner after rotation)
32507
32119
  return {
32508
32120
  ...base,
32121
+ borderBottomWidth: 0,
32122
+ borderRightWidth: 0,
32509
32123
  top: -arrowSize,
32510
32124
  left: alignment === 'end'
32511
32125
  ? `calc(100% - ${(arrowPosition === 'side' ? arrowOffset : arrowSize)}px)`
@@ -32515,8 +32129,11 @@ function getArrowStyle(placement, arrowSize, arrowRadius, arrowOffset, arrowPosi
32515
32129
  marginLeft: alignment || arrowPosition === 'side' ? 0 : -arrowSize,
32516
32130
  };
32517
32131
  case 'left':
32132
+ // Arrow points right, hide the borders that overlap with content (bottom-left corner after rotation)
32518
32133
  return {
32519
32134
  ...base,
32135
+ borderBottomWidth: 0,
32136
+ borderLeftWidth: 0,
32520
32137
  right: -arrowSize,
32521
32138
  top: alignment === 'end'
32522
32139
  ? `calc(100% - ${(arrowPosition === 'side' ? arrowOffset : arrowSize)}px)`
@@ -32526,8 +32143,11 @@ function getArrowStyle(placement, arrowSize, arrowRadius, arrowOffset, arrowPosi
32526
32143
  marginTop: alignment || arrowPosition === 'side' ? 0 : -arrowSize,
32527
32144
  };
32528
32145
  case 'right':
32146
+ // Arrow points left, hide the borders that overlap with content (top-right corner after rotation)
32529
32147
  return {
32530
32148
  ...base,
32149
+ borderTopWidth: 0,
32150
+ borderRightWidth: 0,
32531
32151
  left: -arrowSize,
32532
32152
  top: alignment === 'end'
32533
32153
  ? `calc(100% - ${(arrowPosition === 'side' ? arrowOffset : arrowSize)}px)`
@@ -33448,7 +33068,7 @@ const filterData = (data, filters, columns, searchValue, rowFeatureToggle) => {
33448
33068
  return filteredData;
33449
33069
  };
33450
33070
  // DataTable component
33451
- const DataTable = ({ id, data, columns, loading = false, error = null, emptyMessage = 'No data available', searchable = true, searchPlaceholder = 'Search...', searchValue: controlledSearchValue, onSearchChange, sortBy = [], onSortChange, filters = [], onFilterChange, pagination, onPaginationChange, selectable = false, selectedRows = [], onSelectionChange, getRowId = (_, index) => index, onRowClick, editMode = false, onEditModeChange, onCellEdit, bulkActions = [], variant = 'default', density = 'normal', height, virtual = false, style, hoverHighlight = true, enableColumnResizing = false, rowFeatureToggle, initialHiddenColumns = [], onColumnVisibilityChange, onColumnSettings, showColumnVisibilityManager = true, rowsPerPageOptions = [10, 25, 50, 100], showRowsPerPageControl = true, rowActions, actionsColumnWidth = 100, fullWidth = true,
33071
+ const DataTable = ({ id, data, columns, loading = false, error = null, emptyMessage = 'No data available', searchable = true, searchPlaceholder = 'Search...', searchValue: controlledSearchValue, onSearchChange, sortBy = [], onSortChange, filters = [], onFilterChange, pagination, onPaginationChange, selectable = false, selectedRows = [], onSelectionChange, getRowId = (_, index) => index, onRowClick, editMode = false, onEditModeChange, onCellEdit, bulkActions = [], variant = 'default', striped: stripedProp, density = 'normal', height, virtual = false, style, hoverHighlight = true, enableColumnResizing = false, rowFeatureToggle, initialHiddenColumns = [], onColumnVisibilityChange, onColumnSettings, showColumnVisibilityManager = true, rowsPerPageOptions = [10, 25, 50, 100], showRowsPerPageControl = true, rowActions, actionsColumnWidth = 100, fullWidth = true,
33452
33072
  // Border styling props
33453
33073
  rowBorderWidth, rowBorderColor, rowBorderStyle = 'solid', columnBorderWidth, columnBorderColor, columnBorderStyle = 'solid', showOuterBorder = false, outerBorderWidth = 1, outerBorderColor,
33454
33074
  // Expandable rows props
@@ -33456,6 +33076,7 @@ expandableRowRender, initialExpandedRows = [], expandedRows: controlledExpandedR
33456
33076
  const { spacingProps, otherProps } = extractSpacingProps(props);
33457
33077
  const theme = useTheme();
33458
33078
  const { isRTL } = useDirection();
33079
+ const isStriped = stripedProp !== null && stripedProp !== void 0 ? stripedProp : variant === 'striped';
33459
33080
  // Local state
33460
33081
  const [internalSearchValue, setInternalSearchValue] = useState('');
33461
33082
  const [editingCell, setEditingCell] = useState(null);
@@ -33892,7 +33513,7 @@ expandableRowRender, initialExpandedRows = [], expandedRows: controlledExpandedR
33892
33513
  const rowElement = (jsxs(Fragment, { children: [jsxs(TableTr, { selected: isSelected, onPress: () => onRowClick === null || onRowClick === void 0 ? void 0 : onRowClick(row, rowIndex), style: {
33893
33514
  backgroundColor: isSelected
33894
33515
  ? theme.colors.primary[1]
33895
- : variant === 'striped' && rowIndex % 2 === 1
33516
+ : isStriped && rowIndex % 2 === 1
33896
33517
  ? theme.colors.gray[0]
33897
33518
  : 'transparent',
33898
33519
  borderBottomWidth: rowBorderWidth || (variant === 'bordered' ? 1 : 0),
@@ -33972,7 +33593,7 @@ expandableRowRender, initialExpandedRows = [], expandedRows: controlledExpandedR
33972
33593
  borderRadius: showOuterBorder ? 8 : 0
33973
33594
  };
33974
33595
  if (loading) {
33975
- return (jsxs(View, { style: [getSpacingStyles(spacingProps), style], ...otherProps, children: [renderHeader(), jsxs(Table, { striped: variant === 'striped', withTableBorder: variant === 'bordered', withRowBorders: variant !== 'default', verticalSpacing: density === 'compact' ? 'xs' : density === 'comfortable' ? 'lg' : 'sm', fullWidth: fullWidth, children: [jsxs(TableTr, { style: { backgroundColor: theme.colors.gray[0] }, children: [selectable && (jsx(TableTh, { w: 50, children: jsx(View, { style: { width: 20, height: 20, backgroundColor: theme.colors.gray[2], borderRadius: 4 } }) })), expandableRowRender && (jsx(TableTh, { w: 50, children: jsx(View, { style: { width: 20, height: 20, backgroundColor: theme.colors.gray[2], borderRadius: 4 } }) })), visibleColumns.map(column => (jsx(TableTh, { w: column.width || columnWidths[column.key], minWidth: column.minWidth, children: jsx(View, { style: {
33596
+ return (jsxs(View, { style: [getSpacingStyles(spacingProps), style], ...otherProps, children: [renderHeader(), jsxs(Table, { striped: isStriped, withTableBorder: variant === 'bordered', withRowBorders: variant !== 'default', verticalSpacing: density === 'compact' ? 'xs' : density === 'comfortable' ? 'lg' : 'sm', fullWidth: fullWidth, children: [jsxs(TableTr, { style: { backgroundColor: theme.colors.gray[0] }, children: [selectable && (jsx(TableTh, { w: 50, children: jsx(View, { style: { width: 20, height: 20, backgroundColor: theme.colors.gray[2], borderRadius: 4 } }) })), expandableRowRender && (jsx(TableTh, { w: 50, children: jsx(View, { style: { width: 20, height: 20, backgroundColor: theme.colors.gray[2], borderRadius: 4 } }) })), visibleColumns.map(column => (jsx(TableTh, { w: column.width || columnWidths[column.key], minWidth: column.minWidth, children: jsx(View, { style: {
33976
33597
  height: 20,
33977
33598
  backgroundColor: theme.colors.gray[2],
33978
33599
  borderRadius: 4,
@@ -33994,9 +33615,9 @@ expandableRowRender, initialExpandedRows = [], expandedRows: controlledExpandedR
33994
33615
  borderColor: theme.colors.error[2]
33995
33616
  }, children: [jsx(Icon, { name: "error", size: 32, color: theme.colors.error[5], style: { marginBottom: 12 } }), jsx(Text, { variant: "h6", color: theme.colors.error[7], style: { marginBottom: 8 }, children: "Error Loading Data" }), jsx(Text, { variant: "p", colorVariant: "muted", style: { textAlign: 'center' }, children: error })] })] }));
33996
33617
  }
33997
- return (jsxs(View, { style: [getSpacingStyles(spacingProps), style], ...otherProps, children: [renderHeader(), virtual ? (jsx(View, { style: [{ width: '100%', overflow: 'hidden' }, tableBorderStyle], children: jsx(ScrollView, { horizontal: true, showsHorizontalScrollIndicator: Platform.OS === 'web', contentContainerStyle: minWidthValue ? { minWidth: minWidthValue } : undefined, children: jsxs(View, { style: { flex: 1 }, children: [jsx(Table, { striped: variant === 'striped', withTableBorder: variant === 'bordered', withRowBorders: variant !== 'default', verticalSpacing: density === 'compact' ? 'xs' : density === 'comfortable' ? 'lg' : 'sm', fullWidth: fullWidth, children: headerRow }), processedData.length === 0 ? (jsx(Table, { striped: variant === 'striped', withTableBorder: variant === 'bordered', withRowBorders: variant !== 'default', verticalSpacing: density === 'compact' ? 'xs' : density === 'comfortable' ? 'lg' : 'sm', fullWidth: fullWidth, children: emptyStateRow })) : (jsx(FlashList, { data: processedData, keyExtractor: (item, index) => String(getRowId(item, index)), renderItem: renderVirtualRow, ...flashListSizingProps, extraData: flashListExtraData, contentContainerStyle: { flexGrow: 1 }, showsVerticalScrollIndicator: Platform.OS === 'web' }))] }) }) })) : (
33618
+ return (jsxs(View, { style: [getSpacingStyles(spacingProps), style], ...otherProps, children: [renderHeader(), virtual ? (jsx(View, { style: [{ width: '100%', overflow: 'hidden' }, tableBorderStyle], children: jsx(ScrollView, { horizontal: true, showsHorizontalScrollIndicator: Platform.OS === 'web', contentContainerStyle: minWidthValue ? { minWidth: minWidthValue } : undefined, children: jsxs(View, { style: { flex: 1 }, children: [jsx(Table, { striped: isStriped, withTableBorder: variant === 'bordered', withRowBorders: variant !== 'default', verticalSpacing: density === 'compact' ? 'xs' : density === 'comfortable' ? 'lg' : 'sm', fullWidth: fullWidth, children: headerRow }), processedData.length === 0 ? (jsx(Table, { striped: isStriped, withTableBorder: variant === 'bordered', withRowBorders: variant !== 'default', verticalSpacing: density === 'compact' ? 'xs' : density === 'comfortable' ? 'lg' : 'sm', fullWidth: fullWidth, children: emptyStateRow })) : (jsx(FlashList, { data: processedData, keyExtractor: (item, index) => String(getRowId(item, index)), renderItem: renderVirtualRow, ...flashListSizingProps, extraData: flashListExtraData, contentContainerStyle: { flexGrow: 1 }, showsVerticalScrollIndicator: Platform.OS === 'web' }))] }) }) })) : (
33998
33619
  // <TableScrollContainer style={tableBorderStyle} minWidth={minWidthValue}>
33999
- jsxs(Table, { striped: variant === 'striped', withTableBorder: variant === 'bordered', withRowBorders: variant !== 'default', verticalSpacing: density === 'compact' ? 'xs' : density === 'comfortable' ? 'lg' : 'sm', fullWidth //</TableScrollContainer>={fullWidth}
33620
+ jsxs(Table, { striped: isStriped, withTableBorder: variant === 'bordered', withRowBorders: variant !== 'default', verticalSpacing: density === 'compact' ? 'xs' : density === 'comfortable' ? 'lg' : 'sm', fullWidth //</TableScrollContainer>={fullWidth}
34000
33621
  : true, children: [headerRow, processedData.length === 0 ? emptyStateRow : nonVirtualRows] })
34001
33622
  // </TableScrollContainer>
34002
33623
  ), pagination && onPaginationChange && (jsx(View, { style: {
@@ -35661,104 +35282,6 @@ const Ring = factory((props, ref) => {
35661
35282
  return (jsxs(View, { ref: ref, style: [styles$8.container, spacingStyles, style], testID: testID, accessibilityLabel: accessibilityLabel !== null && accessibilityLabel !== void 0 ? accessibilityLabel : `Ring value ${Math.round(percent)} percent`, accessibilityRole: "progressbar", accessibilityValue: { min, max, now: Math.round(clampedValue) }, ...otherProps, children: [jsxs(View, { style: [styles$8.ringWrapper, { width: size, height: size }, ringStyle], children: [jsxs(Svg, { width: size, height: size, viewBox: `0 0 ${size} ${size}`, children: [jsx(Circle, { cx: size / 2, cy: size / 2, r: radius, stroke: defaultTrackColor, strokeWidth: thickness, fill: "transparent" }), jsx(Circle, { cx: size / 2, cy: size / 2, r: radius, stroke: resolvedProgressColor, strokeWidth: thickness, strokeLinecap: roundedCaps ? 'round' : 'butt', strokeDasharray: `${circumference} ${circumference}`, strokeDashoffset: dashOffset, fill: "transparent", transform: `rotate(-90 ${size / 2} ${size / 2})` })] }), jsx(View, { pointerEvents: "none", style: [styles$8.centerContent, { width: size, height: size }, contentStyle], children: centerContent })] }), caption !== undefined && caption !== null ? (React__default.isValidElement(caption) ? (caption) : (jsx(Text, { variant: "span", size: "xs", color: captionTextColor, weight: "600", style: [{ marginTop: 6, letterSpacing: 1 }, captionStyle], children: caption }))) : null] }));
35662
35283
  }, { displayName: 'Ring' });
35663
35284
 
35664
- const NAVIGATIONPROGRESS_DEFAULTS = {
35665
- size: 3,
35666
- color: 'primary',
35667
- zIndex: 9999,
35668
- overlay: true,
35669
- stepInterval: 500,
35670
- radius: 0,
35671
- };
35672
-
35673
- let subscribers = new Set();
35674
- let internalState = { value: 0, active: false };
35675
- let interval = null;
35676
- function broadcast() { subscribers.forEach(cb => cb({ ...internalState })); }
35677
- function schedule(intervalMs) {
35678
- clearInterval(interval);
35679
- interval = setInterval(() => {
35680
- if (!internalState.active)
35681
- return;
35682
- const remain = 100 - internalState.value;
35683
- const inc = Math.max(0.1, remain * 0.03);
35684
- internalState.value = Math.min(99, internalState.value + inc);
35685
- broadcast();
35686
- }, intervalMs);
35687
- }
35688
- const navigationProgress = {
35689
- start() { if (internalState.active)
35690
- return; internalState.active = true; if (internalState.value >= 100)
35691
- internalState.value = 0; broadcast(); schedule(NAVIGATIONPROGRESS_DEFAULTS.stepInterval); },
35692
- stop() { internalState.active = false; broadcast(); },
35693
- complete() { internalState.active = true; internalState.value = 100; broadcast(); setTimeout(() => { internalState.active = false; internalState.value = 0; broadcast(); }, 400); },
35694
- reset() { internalState.value = 0; internalState.active = false; broadcast(); },
35695
- set(v) { internalState.value = Math.max(0, Math.min(100, v)); broadcast(); },
35696
- increment(delta = 5) { internalState.value = Math.min(100, internalState.value + delta); broadcast(); },
35697
- decrement(delta = 5) { internalState.value = Math.max(0, internalState.value - delta); broadcast(); },
35698
- isActive() { return internalState.active; }
35699
- };
35700
- const NavigationProgress = ({ value, size = NAVIGATIONPROGRESS_DEFAULTS.size, color = NAVIGATIONPROGRESS_DEFAULTS.color, zIndex = NAVIGATIONPROGRESS_DEFAULTS.zIndex, overlay = NAVIGATIONPROGRESS_DEFAULTS.overlay, stepInterval = NAVIGATIONPROGRESS_DEFAULTS.stepInterval, radius = NAVIGATIONPROGRESS_DEFAULTS.radius, active = true, style }) => {
35701
- const theme = useTheme();
35702
- const scheme = useColorScheme();
35703
- const isDark = scheme === 'dark';
35704
- const progress = useSharedValue(0);
35705
- const opacity = useSharedValue(0);
35706
- useEffect(() => {
35707
- const sub = (s) => {
35708
- if (value == null) {
35709
- progress.value = withTiming(s.value, { duration: stepInterval });
35710
- opacity.value = withTiming(s.active ? 1 : 0, { duration: 150 });
35711
- }
35712
- };
35713
- subscribers.add(sub);
35714
- broadcast();
35715
- return () => { subscribers.delete(sub); };
35716
- }, [value, stepInterval, progress, opacity]);
35717
- useEffect(() => {
35718
- if (value != null) {
35719
- progress.value = withTiming(value, { duration: stepInterval });
35720
- opacity.value = withTiming(active ? 1 : 0, { duration: 150 });
35721
- }
35722
- }, [value, active, stepInterval]);
35723
- let resolvedColor = color;
35724
- if (theme.colors[color]) {
35725
- const bucket = theme.colors[color];
35726
- resolvedColor = bucket[5] || bucket[4] || bucket[0];
35727
- }
35728
- const barStyle = useAnimatedStyle(() => ({ width: `${progress.value}%` }));
35729
- const containerStyle = useAnimatedStyle(() => ({ opacity: opacity.value }));
35730
- return (jsxs(Animated.View, { style: [
35731
- {
35732
- position: overlay ? 'absolute' : 'relative',
35733
- top: 0,
35734
- left: 0,
35735
- right: 0,
35736
- height: size,
35737
- backgroundColor: isDark ? theme.colors.gray[3] : theme.colors.gray[2],
35738
- overflow: 'hidden',
35739
- zIndex,
35740
- borderRadius: radius,
35741
- pointerEvents: 'none'
35742
- },
35743
- containerStyle,
35744
- style
35745
- ], children: [jsx(Animated.View, { style: [{
35746
- position: 'absolute',
35747
- top: 0,
35748
- bottom: 0,
35749
- left: 0,
35750
- backgroundColor: resolvedColor,
35751
- borderRadius: radius,
35752
- }, barStyle] }), jsx(Animated.View, { style: [{
35753
- position: 'absolute',
35754
- top: 0,
35755
- bottom: 0,
35756
- right: 0,
35757
- width: 80,
35758
- backgroundColor: 'rgba(255,255,255,0.2)'
35759
- }, barStyle] })] }));
35760
- };
35761
-
35762
35285
  const DEFAULT_OPACITY = 0.6;
35763
35286
  const HEX_COLOR_REGEX = /^#?[0-9a-f]{3,8}$/i;
35764
35287
  const clampOpacity = (value) => {
@@ -35951,270 +35474,6 @@ const LoadingOverlay = React__default.forwardRef((props, ref) => {
35951
35474
  });
35952
35475
  LoadingOverlay.displayName = 'LoadingOverlay';
35953
35476
 
35954
- // A lightweight hover-activated floating panel similar to Mantine HoverCard
35955
- function HoverCardBase(props, ref) {
35956
- const { children, target, position = 'top', offset = 8, openDelay = 100, closeDelay = 150, opened: controlledOpened, shadow = 'md', radius = 'md', withinPortal = true, width, withArrow = false, closeOnEscape = true, onOpen, onClose, disabled = false, style, testID, zIndex = 3000, keepMounted = false, trigger = 'hover', } = props;
35957
- const [opened, setOpened] = useState(false);
35958
- const openTimeout = useRef(null);
35959
- const closeTimeout = useRef(null);
35960
- const containerRef = useRef(null);
35961
- const targetRef = useRef(null);
35962
- const overlayIdRef = useRef(null);
35963
- const overlayContentRef = useRef(null);
35964
- const isHoveringTargetRef = useRef(false);
35965
- const isHoveringOverlayRef = useRef(false);
35966
- const theme = useTheme();
35967
- const { openOverlay, closeOverlay, updateOverlay } = useOverlay();
35968
- const isOpened = controlledOpened !== undefined ? controlledOpened : opened;
35969
- const clearTimers = () => {
35970
- if (openTimeout.current) {
35971
- clearTimeout(openTimeout.current);
35972
- openTimeout.current = null;
35973
- }
35974
- if (closeTimeout.current) {
35975
- clearTimeout(closeTimeout.current);
35976
- closeTimeout.current = null;
35977
- }
35978
- };
35979
- const doOpen = useCallback(() => {
35980
- if (disabled)
35981
- return;
35982
- setOpened(true);
35983
- onOpen === null || onOpen === void 0 ? void 0 : onOpen();
35984
- }, [disabled, onOpen]);
35985
- const doClose = useCallback(() => {
35986
- setOpened(false);
35987
- onClose === null || onClose === void 0 ? void 0 : onClose();
35988
- }, [onClose]);
35989
- const scheduleOpen = useCallback(() => {
35990
- clearTimers();
35991
- openTimeout.current = setTimeout(doOpen, openDelay);
35992
- }, [doOpen, openDelay]);
35993
- const scheduleClose = useCallback(() => {
35994
- clearTimers();
35995
- closeTimeout.current = setTimeout(() => {
35996
- // Only close if neither target nor overlay are hovered (web)
35997
- if (Platform.OS === 'web') {
35998
- if (isHoveringTargetRef.current || isHoveringOverlayRef.current)
35999
- return;
36000
- }
36001
- doClose();
36002
- }, closeDelay);
36003
- }, [doClose, closeDelay]);
36004
- useEffect(() => () => clearTimers(), []);
36005
- // Escape key (web only)
36006
- useEffect(() => {
36007
- if (!closeOnEscape || Platform.OS !== 'web')
36008
- return;
36009
- const handler = (e) => { if (e.key === 'Escape')
36010
- doClose(); };
36011
- document.addEventListener('keydown', handler);
36012
- return () => document.removeEventListener('keydown', handler);
36013
- }, [closeOnEscape, doClose]);
36014
- const getInlinePositionStyle = () => {
36015
- const base = { position: 'absolute' };
36016
- switch (position) {
36017
- case 'top': return { ...base, bottom: '100%', left: 0, marginBottom: offset };
36018
- case 'bottom': return { ...base, top: '100%', left: 0, marginTop: offset };
36019
- case 'left': return { ...base, right: '100%', top: 0, marginRight: offset };
36020
- case 'right': return { ...base, left: '100%', top: 0, marginLeft: offset };
36021
- default: return { ...base, top: '100%', left: 0, marginTop: offset };
36022
- }
36023
- };
36024
- const shadowStyle = (() => {
36025
- switch (shadow) {
36026
- case 'sm':
36027
- return { boxShadow: '0 1px 2px rgba(0, 0, 0, 0.1)', elevation: 2 };
36028
- case 'md':
36029
- return { boxShadow: '0 2px 4px rgba(0, 0, 0, 0.15)', elevation: 4 };
36030
- case 'lg':
36031
- return { boxShadow: '0 4px 8px rgba(0, 0, 0, 0.2)', elevation: 8 };
36032
- default:
36033
- return {};
36034
- }
36035
- })();
36036
- const renderArrow = (placement) => {
36037
- if (!withArrow)
36038
- return null;
36039
- const base = { position: 'absolute', width: 0, height: 0 };
36040
- const color = theme.colors.gray[0];
36041
- const styles = {
36042
- top: { top: '100%', left: 12, borderLeftWidth: 6, borderRightWidth: 6, borderTopWidth: 6, borderLeftColor: 'transparent', borderRightColor: 'transparent', borderTopColor: color },
36043
- bottom: { bottom: '100%', left: 12, borderLeftWidth: 6, borderRightWidth: 6, borderBottomWidth: 6, borderLeftColor: 'transparent', borderRightColor: 'transparent', borderBottomColor: color },
36044
- left: { left: '100%', top: 12, borderTopWidth: 6, borderBottomWidth: 6, borderLeftWidth: 6, borderTopColor: 'transparent', borderBottomColor: 'transparent', borderLeftColor: color },
36045
- right: { right: '100%', top: 12, borderTopWidth: 6, borderBottomWidth: 6, borderRightWidth: 6, borderTopColor: 'transparent', borderBottomColor: 'transparent', borderRightColor: color },
36046
- };
36047
- const key = placement.split('-')[0];
36048
- return jsx(View, { style: { ...base, ...(styles[key] || styles.top) } });
36049
- };
36050
- const openPortal = useCallback(async () => {
36051
- if (!withinPortal || !isOpened || overlayIdRef.current)
36052
- return;
36053
- const rect = await measureElement(targetRef);
36054
- const estWidth = width || 240;
36055
- const estHeight = 160; // rough initial height
36056
- const pos = calculateOverlayPositionEnhanced(rect, { width: estWidth, height: estHeight }, {
36057
- placement: position,
36058
- offset,
36059
- viewport: getViewport(),
36060
- strategy: 'fixed'
36061
- });
36062
- const overlayContent = (jsxs(View, { ref: overlayContentRef, style: [
36063
- {
36064
- backgroundColor: theme.colors.gray[0],
36065
- borderRadius: getRadius$2(radius),
36066
- paddingHorizontal: getSpacing('md'),
36067
- paddingVertical: getSpacing('sm'),
36068
- borderWidth: 1,
36069
- borderColor: theme.colors.gray[3],
36070
- minWidth: width || 160,
36071
- maxWidth: width || 320,
36072
- },
36073
- shadowStyle,
36074
- ], ...(Platform.OS === 'web' && trigger === 'hover' ? {
36075
- onMouseEnter: () => { isHoveringOverlayRef.current = true; clearTimers(); },
36076
- onMouseLeave: () => { isHoveringOverlayRef.current = false; scheduleClose(); },
36077
- } : {}), children: [children, renderArrow(pos.placement)] }));
36078
- const id = openOverlay({
36079
- content: overlayContent,
36080
- anchor: { x: pos.x, y: pos.y, width: estWidth, height: estHeight },
36081
- trigger: trigger,
36082
- // For hover-triggered overlays, do NOT render a click-outside backdrop – it steals hover
36083
- // and immediately fires target onMouseLeave. We rely on pointer leave timers instead.
36084
- closeOnClickOutside: trigger !== 'hover',
36085
- closeOnEscape: closeOnEscape,
36086
- strategy: 'fixed',
36087
- onClose: () => { overlayIdRef.current = null; if (opened)
36088
- setOpened(false); onClose === null || onClose === void 0 ? void 0 : onClose(); },
36089
- zIndex
36090
- });
36091
- overlayIdRef.current = id;
36092
- }, [withinPortal, isOpened, overlayIdRef, position, offset, width, trigger, closeOnEscape, theme, radius, shadowStyle, children, opened, onClose, getSpacing, getRadius$2]);
36093
- const closePortal = useCallback(() => {
36094
- if (overlayIdRef.current) {
36095
- closeOverlay(overlayIdRef.current);
36096
- overlayIdRef.current = null;
36097
- }
36098
- }, [closeOverlay]);
36099
- useEffect(() => {
36100
- if (withinPortal) {
36101
- if (isOpened)
36102
- openPortal();
36103
- else
36104
- closePortal();
36105
- }
36106
- return () => { if (!isOpened)
36107
- closePortal(); };
36108
- }, [isOpened, withinPortal, openPortal, closePortal]);
36109
- useEffect(() => {
36110
- if (!withinPortal || Platform.OS !== 'web' || !isOpened || !overlayIdRef.current)
36111
- return;
36112
- const handler = () => {
36113
- Promise.all([measureElement(targetRef)]).then(([rect]) => {
36114
- var _a, _b;
36115
- const actualWidth = ((_a = overlayContentRef.current) === null || _a === void 0 ? void 0 : _a.offsetWidth) || width || 240;
36116
- const actualHeight = ((_b = overlayContentRef.current) === null || _b === void 0 ? void 0 : _b.offsetHeight) || 160;
36117
- const pos = calculateOverlayPositionEnhanced(rect, { width: actualWidth, height: actualHeight }, {
36118
- placement: position,
36119
- offset,
36120
- viewport: getViewport(),
36121
- strategy: 'fixed'
36122
- });
36123
- updateOverlay(overlayIdRef.current, { anchor: { x: pos.x, y: pos.y, width: actualWidth, height: actualHeight } });
36124
- });
36125
- };
36126
- window.addEventListener('resize', handler);
36127
- window.addEventListener('scroll', handler, true);
36128
- return () => {
36129
- window.removeEventListener('resize', handler);
36130
- window.removeEventListener('scroll', handler, true);
36131
- };
36132
- }, [withinPortal, isOpened, position, offset, width, updateOverlay]);
36133
- // Smart sizing: after content mounts, measure actual size and reposition if changed
36134
- useEffect(() => {
36135
- if (!withinPortal || !isOpened || !overlayIdRef.current)
36136
- return;
36137
- let frame;
36138
- const attempt = () => {
36139
- Promise.all([
36140
- measureElement(targetRef),
36141
- measureElement({ current: overlayContentRef.current })
36142
- ]).then(([targetRect, contentRect]) => {
36143
- if (!targetRect.width || !contentRect.width)
36144
- return; // skip invalid
36145
- const desiredWidth = width || contentRect.width;
36146
- const desiredHeight = contentRect.height;
36147
- // Recalculate with actual content size
36148
- const pos = calculateOverlayPositionEnhanced(targetRect, { width: desiredWidth, height: desiredHeight }, {
36149
- placement: position,
36150
- offset,
36151
- viewport: getViewport(),
36152
- strategy: 'fixed'
36153
- });
36154
- updateOverlay(overlayIdRef.current, { anchor: { x: pos.x, y: pos.y, width: desiredWidth, height: desiredHeight } });
36155
- });
36156
- };
36157
- // Delay a bit to allow layout
36158
- frame = setTimeout(attempt, 30);
36159
- return () => { if (frame)
36160
- clearTimeout(frame); };
36161
- }, [withinPortal, isOpened, position, offset, width, updateOverlay]);
36162
- const targetProps = {};
36163
- if (trigger === 'hover') {
36164
- if (Platform.OS === 'web') {
36165
- targetProps.onMouseEnter = () => { isHoveringTargetRef.current = true; scheduleOpen(); };
36166
- targetProps.onMouseLeave = () => { isHoveringTargetRef.current = false; scheduleClose(); };
36167
- }
36168
- else {
36169
- // fallback: tap to toggle on native
36170
- targetProps.onPress = () => {
36171
- if (isOpened) {
36172
- doClose();
36173
- }
36174
- else {
36175
- doOpen();
36176
- }
36177
- };
36178
- }
36179
- }
36180
- else if (trigger === 'click') {
36181
- targetProps.onPress = () => {
36182
- if (isOpened) {
36183
- doClose();
36184
- }
36185
- else {
36186
- doOpen();
36187
- }
36188
- };
36189
- }
36190
- const inlineContent = (isOpened || keepMounted) && !withinPortal ? (jsxs(View, { style: [
36191
- getInlinePositionStyle(),
36192
- {
36193
- backgroundColor: theme.colors.gray[0],
36194
- borderRadius: getRadius$2(radius),
36195
- paddingHorizontal: getSpacing('md'),
36196
- paddingVertical: getSpacing('sm'),
36197
- borderWidth: 1,
36198
- borderColor: theme.colors.gray[3],
36199
- minWidth: width,
36200
- zIndex,
36201
- },
36202
- shadowStyle,
36203
- ], pointerEvents: "auto", ...(Platform.OS === 'web' && trigger === 'hover' ? {
36204
- onMouseEnter: () => { isHoveringOverlayRef.current = true; clearTimers(); },
36205
- onMouseLeave: () => { isHoveringOverlayRef.current = false; scheduleClose(); },
36206
- } : {}), children: [children, renderArrow(position)] })) : null;
36207
- return (jsxs(View, { ref: ref, style: [{ position: 'relative', alignSelf: 'flex-start' }, style], testID: testID, children: [jsx(Pressable, { ref: (node) => { containerRef.current = node; targetRef.current = node; }, ...targetProps, style: ({ pressed }) => {
36208
- var _a;
36209
- return [
36210
- { opacity: pressed ? 0.85 : 1 },
36211
- (_a = target === null || target === void 0 ? void 0 : target.props) === null || _a === void 0 ? void 0 : _a.style,
36212
- ];
36213
- }, children: target }), inlineContent] }));
36214
- }
36215
- const HoverCard = factory(HoverCardBase);
36216
- HoverCard.displayName = 'HoverCard';
36217
-
36218
35477
  const ContextMenu = ({ children, items, closeOnSelect = true, longPressDelay = 350, maxHeight = 280, onOpen, onClose, open: controlledOpen, position: controlledPosition, portalId, style, }) => {
36219
35478
  var _a, _b;
36220
35479
  const [internalOpen, setInternalOpen] = useState(false);
@@ -37434,49 +36693,101 @@ const CarouselDot = memo(({ index, pageProgress, metrics, totalPages, loop, them
37434
36693
  : { marginHorizontal: metrics.margin, height: baseDotSize, justifyContent: 'center' };
37435
36694
  return (jsx(Pressable, { onPress: handlePress, accessibilityRole: "button", accessibilityLabel: `Go to slide ${index + 1}`, style: containerStyle, children: jsx(Animated.View, { style: [{ borderRadius: baseDotSize / 2 }, animatedStyle] }) }));
37436
36695
  });
36696
+ const getBreakpointName = (width) => {
36697
+ if (width >= 1200)
36698
+ return 'xl';
36699
+ if (width >= 992)
36700
+ return 'lg';
36701
+ if (width >= 768)
36702
+ return 'md';
36703
+ if (width >= 576)
36704
+ return 'sm';
36705
+ return 'xs';
36706
+ };
36707
+ const getViewportWidth = () => {
36708
+ if (Platform.OS === 'web' && typeof window !== 'undefined' && typeof window.innerWidth === 'number') {
36709
+ return window.innerWidth;
36710
+ }
36711
+ const dimensions = Dimensions.get('window');
36712
+ return typeof (dimensions === null || dimensions === void 0 ? void 0 : dimensions.width) === 'number' ? dimensions.width : 0;
36713
+ };
37437
36714
  // Optimized breakpoint hook with debouncing
37438
36715
  const useOptimizedBreakpoint = () => {
37439
- const [breakpoint, setBreakpoint] = useState('sm');
36716
+ const computeState = () => {
36717
+ const width = getViewportWidth();
36718
+ return {
36719
+ width,
36720
+ breakpoint: getBreakpointName(width),
36721
+ };
36722
+ };
36723
+ const [state, setState] = useState(computeState);
37440
36724
  useEffect(() => {
37441
36725
  let timeoutId;
37442
- const compute = () => {
37443
- const w = Platform.OS === 'web'
37444
- ? window.innerWidth
37445
- : Dimensions.get('window').width;
37446
- let newBreakpoint = 'sm';
37447
- if (w >= 1200)
37448
- newBreakpoint = 'xl';
37449
- else if (w >= 992)
37450
- newBreakpoint = 'lg';
37451
- else if (w >= 768)
37452
- newBreakpoint = 'md';
37453
- else if (w >= 576)
37454
- newBreakpoint = 'sm';
37455
- else
37456
- newBreakpoint = 'xs';
37457
- setBreakpoint(prev => prev !== newBreakpoint ? newBreakpoint : prev);
36726
+ const update = () => {
36727
+ const next = computeState();
36728
+ setState(prev => (prev.breakpoint === next.breakpoint && prev.width === next.width) ? prev : next);
37458
36729
  };
37459
- const debouncedCompute = () => {
36730
+ const debouncedUpdate = () => {
37460
36731
  clearTimeout(timeoutId);
37461
- timeoutId = setTimeout(compute, 100); // Debounce resize events
36732
+ timeoutId = setTimeout(update, 100); // Debounce resize events
37462
36733
  };
37463
- compute();
37464
- if (Platform.OS === 'web') {
37465
- window.addEventListener('resize', debouncedCompute, { passive: true });
36734
+ update();
36735
+ if (Platform.OS === 'web' && typeof window !== 'undefined') {
36736
+ window.addEventListener('resize', debouncedUpdate, { passive: true });
37466
36737
  return () => {
37467
- window.removeEventListener('resize', debouncedCompute);
36738
+ window.removeEventListener('resize', debouncedUpdate);
37468
36739
  clearTimeout(timeoutId);
37469
36740
  };
37470
36741
  }
37471
- return () => clearTimeout(timeoutId);
36742
+ const subscription = Dimensions.addEventListener('change', debouncedUpdate);
36743
+ return () => {
36744
+ subscription === null || subscription === void 0 ? void 0 : subscription.remove();
36745
+ clearTimeout(timeoutId);
36746
+ };
37472
36747
  }, []);
37473
- return breakpoint;
36748
+ return state;
36749
+ };
36750
+ const parseMediaQuery = (query) => {
36751
+ const minMatch = query.match(/min-width:\s*(\d+)px/);
36752
+ const maxMatch = query.match(/max-width:\s*(\d+)px/);
36753
+ return {
36754
+ min: minMatch ? parseInt(minMatch[1], 10) : undefined,
36755
+ max: maxMatch ? parseInt(maxMatch[1], 10) : undefined,
36756
+ };
36757
+ };
36758
+ const matchQuery = (query, width) => {
36759
+ const { min, max } = parseMediaQuery(query);
36760
+ if (min != null && width < min)
36761
+ return false;
36762
+ if (max != null && width > max)
36763
+ return false;
36764
+ return true;
36765
+ };
36766
+ const mergeBreakpointProps = (baseProps, breakpointProps, width) => {
36767
+ if (!breakpointProps)
36768
+ return baseProps;
36769
+ const sortedEntries = Object.entries(breakpointProps).sort((a, b) => {
36770
+ var _a, _b;
36771
+ const aMin = (_a = parseMediaQuery(a[0]).min) !== null && _a !== void 0 ? _a : 0;
36772
+ const bMin = (_b = parseMediaQuery(b[0]).min) !== null && _b !== void 0 ? _b : 0;
36773
+ return aMin - bMin;
36774
+ });
36775
+ let resolvedProps = { ...baseProps };
36776
+ sortedEntries.forEach(([query, value]) => {
36777
+ const shouldApply = width != null ? matchQuery(query, width) : (Platform.OS === 'web' && typeof window !== 'undefined' ? window.matchMedia(query).matches : false);
36778
+ if (shouldApply) {
36779
+ resolvedProps = { ...resolvedProps, ...value };
36780
+ }
36781
+ });
36782
+ return resolvedProps;
37474
36783
  };
37475
- const Carousel = (props) => {
37476
- const { children, orientation = 'horizontal', height = 200, w = 300, showDots = true, showArrows = true, loop = true, autoPlay = false, autoPlayInterval = 3000, itemsPerPage = 1, slideSize, slideGap, itemGap = 16, onSlideChange, style, itemStyle, arrowSize = 'md', dotSize = 'md', // currently uniform size; active expands
36784
+ const Carousel = (incomingProps) => {
36785
+ const { breakpoint, width: viewportWidth } = useOptimizedBreakpoint();
36786
+ const mergedProps = useMemo(() => mergeBreakpointProps(incomingProps, incomingProps.breakpoints, viewportWidth), [incomingProps, viewportWidth]);
36787
+ const { children, orientation = 'horizontal', height = 200, showDots = true, showArrows = true, loop = true, autoPlay = false, autoPlayInterval = 3000, itemsPerPage = 1, slidesToScroll, slideSize, slideGap, itemGap = 16, containScroll = 'trimSnaps', startIndex, align = 'start', dragFree = false, skipSnaps = true, dragThreshold, duration, breakpoints: _breakpoints, onSlideChange, style, itemStyle, arrowSize = 'md', dotSize = 'md', // currently uniform size; active expands
37477
36788
  snapToItem = true, // kept for API parity (engine handles snapping)
37478
36789
  windowSize = 0, // 0 means no virtualization
37479
- reducedMotion = false, ...rest } = props;
36790
+ reducedMotion = false, ...rest } = mergedProps;
37480
36791
  const { spacingProps, otherProps } = extractSpacingProps(rest);
37481
36792
  const spacingStyles = getSpacingStyles(spacingProps);
37482
36793
  const theme = useTheme();
@@ -37488,10 +36799,9 @@ const Carousel = (props) => {
37488
36799
  // progress holds absolute item progress (fractional, not modulo) supplied by engine
37489
36800
  const progress = useSharedValue(0);
37490
36801
  const [currentIndex, setCurrentIndex] = useState(0);
36802
+ const hasInitializedRef = useRef(false);
37491
36803
  const itemsArray = useMemo(() => React__default.Children.toArray(children), [children]);
37492
36804
  const totalItems = itemsArray.length;
37493
- // Use optimized breakpoint detection with debouncing
37494
- const breakpoint = useOptimizedBreakpoint();
37495
36805
  const resolvedGap = useMemo(() => {
37496
36806
  const raw = resolveResponsive(slideGap, breakpoint);
37497
36807
  if (raw == null)
@@ -37506,7 +36816,7 @@ const Carousel = (props) => {
37506
36816
  }, [slideGap, breakpoint, itemGap]);
37507
36817
  const isVertical = orientation === 'vertical';
37508
36818
  const containerSize = isVertical ? containerHeight : containerWidth;
37509
- const itemSize = useMemo(() => {
36819
+ const desiredItemSize = useMemo(() => {
37510
36820
  if (containerSize <= 0)
37511
36821
  return 0;
37512
36822
  const rawSize = resolveResponsive(slideSize, breakpoint);
@@ -37532,28 +36842,166 @@ const Carousel = (props) => {
37532
36842
  }
37533
36843
  return (containerSize - resolvedGap * (itemsPerPage - 1)) / itemsPerPage;
37534
36844
  }, [slideSize, breakpoint, containerSize, itemsPerPage, resolvedGap]);
36845
+ const hasLayout = isVertical ? containerHeight > 0 : containerWidth > 0;
36846
+ const baseItemsPerPage = Math.max(1, itemsPerPage);
36847
+ const slidesToScrollValue = Math.max(1, slidesToScroll !== null && slidesToScroll !== void 0 ? slidesToScroll : baseItemsPerPage);
36848
+ const containMode = containScroll === false
36849
+ ? 'none'
36850
+ : containScroll === 'keepSnaps'
36851
+ ? 'keepSnaps'
36852
+ : 'trimSnaps';
36853
+ const isDragFree = !!dragFree;
36854
+ const allowSkipSnaps = skipSnaps !== null && skipSnaps !== void 0 ? skipSnaps : true;
36855
+ const dragThresholdValue = typeof dragThreshold === 'number'
36856
+ ? Math.max(dragThreshold, 0)
36857
+ : undefined;
36858
+ const visibleSlides = useMemo(() => {
36859
+ if (!hasLayout || containerSize <= 0)
36860
+ return baseItemsPerPage;
36861
+ if (desiredItemSize <= 0)
36862
+ return baseItemsPerPage;
36863
+ const maxFit = Math.max(1, Math.floor((containerSize + resolvedGap) / (desiredItemSize + resolvedGap)));
36864
+ if (slideSize == null) {
36865
+ return Math.min(baseItemsPerPage, maxFit);
36866
+ }
36867
+ return maxFit;
36868
+ }, [hasLayout, containerSize, desiredItemSize, resolvedGap, baseItemsPerPage, slideSize]);
36869
+ const cardSize = useMemo(() => {
36870
+ if (!hasLayout)
36871
+ return desiredItemSize;
36872
+ if (visibleSlides <= 1) {
36873
+ if (desiredItemSize > 0)
36874
+ return desiredItemSize;
36875
+ return containerSize > 0 ? containerSize : desiredItemSize;
36876
+ }
36877
+ const totalGap = resolvedGap * (visibleSlides - 1);
36878
+ const available = Math.max(containerSize - totalGap, 0);
36879
+ return available / visibleSlides;
36880
+ }, [hasLayout, desiredItemSize, visibleSlides, resolvedGap, containerSize]);
36881
+ const slideExtent = useMemo(() => {
36882
+ if (!hasLayout || cardSize <= 0)
36883
+ return undefined;
36884
+ return cardSize + resolvedGap;
36885
+ }, [hasLayout, cardSize, resolvedGap]);
36886
+ const scrollStep = useMemo(() => {
36887
+ if (totalItems === 0)
36888
+ return slidesToScrollValue;
36889
+ return Math.min(slidesToScrollValue, Math.max(1, totalItems));
36890
+ }, [slidesToScrollValue, totalItems]);
36891
+ const maxScrollDistancePerSwipe = useMemo(() => {
36892
+ if (allowSkipSnaps || slideExtent == null)
36893
+ return undefined;
36894
+ return slideExtent * scrollStep;
36895
+ }, [allowSkipSnaps, slideExtent, scrollStep]);
36896
+ const lastStart = useMemo(() => Math.max(totalItems - visibleSlides, 0), [totalItems, visibleSlides]);
36897
+ const pageStartIndices = useMemo(() => {
36898
+ if (totalItems === 0)
36899
+ return [];
36900
+ if (loop) {
36901
+ const count = Math.max(1, Math.ceil(totalItems / scrollStep));
36902
+ return Array.from({ length: count }, (_, idx) => (idx * scrollStep) % totalItems);
36903
+ }
36904
+ const starts = [];
36905
+ const seen = new Set();
36906
+ const limit = containMode === 'none' ? Math.max(totalItems - 1, 0) : lastStart;
36907
+ const addStart = (value) => {
36908
+ if (!seen.has(value)) {
36909
+ seen.add(value);
36910
+ starts.push(Math.max(0, value));
36911
+ }
36912
+ };
36913
+ for (let start = 0; start <= limit; start += scrollStep) {
36914
+ const value = containMode === 'trimSnaps'
36915
+ ? Math.min(start, lastStart)
36916
+ : start;
36917
+ addStart(value);
36918
+ }
36919
+ if (containMode !== 'trimSnaps') {
36920
+ addStart(lastStart);
36921
+ }
36922
+ starts.sort((a, b) => a - b);
36923
+ return starts;
36924
+ }, [totalItems, loop, scrollStep, containMode, lastStart]);
36925
+ const pagedItems = useMemo(() => {
36926
+ if (!totalItems)
36927
+ return [];
36928
+ return pageStartIndices.map(start => {
36929
+ const group = [];
36930
+ for (let offset = 0; offset < visibleSlides; offset++) {
36931
+ const targetIndex = start + offset;
36932
+ if (loop) {
36933
+ const normalized = ((targetIndex % totalItems) + totalItems) % totalItems;
36934
+ group.push(itemsArray[normalized]);
36935
+ }
36936
+ else if (targetIndex < totalItems) {
36937
+ group.push(itemsArray[targetIndex]);
36938
+ }
36939
+ }
36940
+ return group;
36941
+ });
36942
+ }, [pageStartIndices, visibleSlides, loop, totalItems, itemsArray]);
36943
+ const totalPages = pagedItems.length;
36944
+ const normalizedStartIndex = useMemo(() => {
36945
+ if (!totalItems)
36946
+ return 0;
36947
+ const rawIndex = startIndex !== null && startIndex !== void 0 ? startIndex : 0;
36948
+ if (loop) {
36949
+ return ((rawIndex % totalItems) + totalItems) % totalItems;
36950
+ }
36951
+ return Math.max(0, Math.min(rawIndex, Math.max(totalItems - 1, 0)));
36952
+ }, [startIndex, totalItems, loop]);
36953
+ const initialPageStart = useMemo(() => {
36954
+ if (!totalItems)
36955
+ return 0;
36956
+ const base = Math.floor(normalizedStartIndex / scrollStep) * scrollStep;
36957
+ if (loop) {
36958
+ return totalItems ? base % totalItems : 0;
36959
+ }
36960
+ if (containMode === 'none') {
36961
+ return Math.min(base, Math.max(totalItems - 1, 0));
36962
+ }
36963
+ if (containMode === 'keepSnaps') {
36964
+ return Math.min(base, Math.max(totalItems - 1, 0));
36965
+ }
36966
+ return Math.min(base, lastStart);
36967
+ }, [normalizedStartIndex, scrollStep, loop, totalItems, containMode, lastStart]);
36968
+ const initialPageIndex = useMemo(() => {
36969
+ if (!pageStartIndices.length)
36970
+ return 0;
36971
+ const idx = pageStartIndices.indexOf(initialPageStart);
36972
+ return idx >= 0 ? idx : 0;
36973
+ }, [pageStartIndices, initialPageStart]);
37535
36974
  const handleLayout = useCallback((e) => {
37536
36975
  setContainerWidth(e.nativeEvent.layout.width);
37537
36976
  setContainerHeight(e.nativeEvent.layout.height);
37538
36977
  }, []);
37539
- const goTo = useCallback((index) => {
37540
- if (!carouselRef.current)
37541
- return;
37542
- if (totalItems === 0)
36978
+ const scrollToPage = useCallback((index, animated = true) => {
36979
+ if (!carouselRef.current || totalPages === 0)
37543
36980
  return;
37544
- const clamped = ((index % totalItems) + totalItems) % totalItems;
36981
+ const clamped = ((index % totalPages) + totalPages) % totalPages;
37545
36982
  const delta = clamped - currentIndex;
37546
- if (delta === 0)
36983
+ if (delta === 0) {
36984
+ if (!animated) {
36985
+ progress.value = clamped;
36986
+ setCurrentIndex(clamped);
36987
+ }
37547
36988
  return;
37548
- // For looping choose shortest path if loop enabled
36989
+ }
37549
36990
  let count = delta;
37550
36991
  if (loop) {
37551
- const alt = delta > 0 ? delta - totalItems : delta + totalItems;
36992
+ const alt = delta > 0 ? delta - totalPages : delta + totalPages;
37552
36993
  if (Math.abs(alt) < Math.abs(count))
37553
36994
  count = alt;
37554
36995
  }
37555
- carouselRef.current.scrollTo({ count, animated: true });
37556
- }, [carouselRef, totalItems, currentIndex, loop]);
36996
+ carouselRef.current.scrollTo({ count, animated });
36997
+ if (!animated) {
36998
+ progress.value = clamped;
36999
+ setCurrentIndex(clamped);
37000
+ }
37001
+ }, [carouselRef, totalPages, currentIndex, loop, progress]);
37002
+ const goTo = useCallback((index) => {
37003
+ scrollToPage(index, true);
37004
+ }, [scrollToPage]);
37557
37005
  const goPrev = useCallback(() => {
37558
37006
  if (!carouselRef.current)
37559
37007
  return;
@@ -37564,13 +37012,22 @@ const Carousel = (props) => {
37564
37012
  return;
37565
37013
  carouselRef.current.next();
37566
37014
  }, []);
37567
- const totalPages = useMemo(() => totalItems, [totalItems]);
37568
37015
  // Page progress derived directly from absolute item progress
37569
37016
  const pageProgress = useDerivedValue(() => {
37570
37017
  return progress.value;
37571
37018
  }, []);
37572
37019
  const arrowMetrics = useMemo(() => resolveCarouselArrowMetrics(arrowSize), [arrowSize]);
37573
37020
  const dotMetrics = useMemo(() => resolveCarouselDotMetrics(dotSize), [dotSize]);
37021
+ const alignJustify = useMemo(() => {
37022
+ switch (align) {
37023
+ case 'center':
37024
+ return 'center';
37025
+ case 'end':
37026
+ return 'flex-end';
37027
+ default:
37028
+ return 'flex-start';
37029
+ }
37030
+ }, [align]);
37574
37031
  // Memoized render functions to prevent unnecessary re-renders
37575
37032
  const renderDots = useMemo(() => {
37576
37033
  if (!showDots || totalPages <= 1)
@@ -37586,7 +37043,7 @@ const Carousel = (props) => {
37586
37043
  }, [showDots, totalPages, pageProgress, dotMetrics, loop, theme, goTo, isVertical, isRTL]);
37587
37044
  // Arrows
37588
37045
  const renderArrows = () => {
37589
- if (!showArrows || totalItems <= 1)
37046
+ if (!showArrows || totalPages <= 1)
37590
37047
  return null;
37591
37048
  const buttonSize = arrowMetrics.buttonSizeToken;
37592
37049
  const iconSize = arrowMetrics.iconSize;
@@ -37623,37 +37080,69 @@ const Carousel = (props) => {
37623
37080
  }, children: jsx(Button, { size: buttonSize, variant: "secondary", icon: jsx(Icon, { name: isRTL ? 'chevron-left' : 'chevron-right', size: iconSize }), onPress: goNext, radius: "full" }) })] }));
37624
37081
  };
37625
37082
  // Autoplay: if library autoPlay not sufficient for pause logic, we can just pass through for now.
37626
- const enableAutoPlay = autoPlay && totalItems > 1;
37083
+ const enableAutoPlay = autoPlay && totalPages > 1;
37084
+ useEffect(() => {
37085
+ if (!carouselRef.current || totalPages === 0 || !hasLayout)
37086
+ return;
37087
+ const controlledStart = startIndex != null;
37088
+ if (controlledStart) {
37089
+ scrollToPage(initialPageIndex, false);
37090
+ return;
37091
+ }
37092
+ if (!hasInitializedRef.current) {
37093
+ scrollToPage(initialPageIndex, false);
37094
+ hasInitializedRef.current = true;
37095
+ }
37096
+ }, [scrollToPage, initialPageIndex, startIndex, totalPages, hasLayout]);
37627
37097
  return (jsxs(View, { ref: containerRef, style: [
37628
37098
  {
37099
+ width: '100%',
37629
37100
  position: 'relative',
37630
37101
  ...(isVertical ? { flexDirection: 'row' } : {})
37631
37102
  },
37632
37103
  spacingStyles,
37633
37104
  style
37634
- ], onLayout: handleLayout, ...otherProps, children: [jsx(View, { style: { flex: 1 }, children: itemSize > 0 && (jsx(ReanimatedCarousel, { ref: carouselRef, width: isVertical ? containerWidth : itemSize, height: isVertical ? itemSize : height, style: isVertical ? { height: containerHeight } : { width: containerWidth }, vertical: isVertical, loop: loop, autoPlay: enableAutoPlay, autoPlayInterval: autoPlayInterval, data: itemsArray, pagingEnabled: snapToItem, windowSize: windowSize > 0 ? windowSize : undefined,
37105
+ ], onLayout: handleLayout, ...otherProps, children: [jsx(View, { style: { flex: 1 }, children: hasLayout && pagedItems.length > 0 && cardSize > 0 && (jsx(ReanimatedCarousel, { ref: carouselRef, width: isVertical ? containerWidth : containerWidth, height: isVertical ? containerHeight : height, style: isVertical ? { height: containerHeight } : { width: containerWidth }, vertical: isVertical, loop: loop, autoPlay: enableAutoPlay, autoPlayInterval: autoPlayInterval, data: pagedItems, pagingEnabled: isDragFree ? false : snapToItem, snapEnabled: isDragFree ? false : undefined, windowSize: windowSize > 0 ? windowSize : undefined, scrollAnimationDuration: duration,
37635
37106
  // Performance optimizations
37636
37107
  overscrollEnabled: false, enabled: !reducedMotion, withAnimation: reducedMotion ?
37637
37108
  { type: 'timing', config: { duration: 100 } } :
37638
- { type: 'spring', config: { damping: 60, stiffness: 150 } }, onProgressChange: (offset, absolute) => {
37109
+ { type: 'spring', config: { damping: 60, stiffness: 150 } }, maxScrollDistancePerSwipe: maxScrollDistancePerSwipe, minScrollDistancePerSwipe: dragThresholdValue, onProgressChange: (offset, absolute) => {
37639
37110
  // absolute may be undefined in some versions; fallback to offset
37640
37111
  const val = typeof absolute === 'number' ? absolute : offset;
37641
37112
  progress.value = val;
37642
- const ci = ((Math.round(val) % totalItems) + totalItems) % totalItems;
37113
+ const ci = totalPages > 0
37114
+ ? ((Math.round(val) % totalPages) + totalPages) % totalPages
37115
+ : 0;
37643
37116
  if (ci !== currentIndex) {
37644
37117
  setCurrentIndex(ci);
37645
37118
  onSlideChange === null || onSlideChange === void 0 ? void 0 : onSlideChange(ci);
37646
37119
  }
37647
- }, renderItem: ({ item, index }) => (jsx(View, { style: [
37648
- {
37649
- width: isVertical ? containerWidth : itemSize,
37650
- height: isVertical ? itemSize : height,
37651
- ...(isVertical
37652
- ? { marginBottom: index < itemsArray.length - 1 ? resolvedGap : 0 }
37653
- : { marginRight: index < itemsArray.length - 1 ? resolvedGap : 0 }),
37654
- },
37655
- itemStyle,
37656
- ], accessibilityLabel: `Carousel item ${index + 1} of ${totalItems}`, children: item })) })) }), renderArrows(), renderDots] }));
37120
+ }, renderItem: ({ item, index }) => {
37121
+ const pageItems = Array.isArray(item) ? item : [item];
37122
+ const pageWidth = isVertical ? containerWidth : containerWidth;
37123
+ const pageHeight = isVertical ? containerHeight : height;
37124
+ const justify = containMode === 'trimSnaps' ? 'flex-start' : alignJustify;
37125
+ return (jsx(View, { style: [
37126
+ {
37127
+ width: pageWidth,
37128
+ height: pageHeight,
37129
+ justifyContent: 'center',
37130
+ },
37131
+ itemStyle,
37132
+ ], accessibilityLabel: `Carousel item ${index + 1} of ${totalPages}`, children: jsx(View, { style: {
37133
+ flexDirection: isVertical ? 'column' : 'row',
37134
+ alignItems: 'stretch',
37135
+ justifyContent: justify,
37136
+ flexWrap: 'nowrap',
37137
+ flex: 1,
37138
+ }, children: pageItems.map((child, childIndex) => (jsx(View, { style: {
37139
+ width: isVertical ? '100%' : cardSize,
37140
+ height: isVertical ? cardSize : '100%',
37141
+ marginRight: !isVertical && childIndex < pageItems.length - 1 ? resolvedGap : 0,
37142
+ marginBottom: isVertical && childIndex < pageItems.length - 1 ? resolvedGap : 0,
37143
+ flexShrink: 0,
37144
+ }, children: child }, childIndex))) }) }));
37145
+ } })) }), renderArrows(), renderDots] }));
37657
37146
  };
37658
37147
 
37659
37148
  // Types extracted to types.ts
@@ -39574,11 +39063,14 @@ QRCodeSVG.displayName = 'QRCodeSVG';
39574
39063
  */
39575
39064
  function QRCode(props) {
39576
39065
  var _a;
39066
+ const theme = useTheme();
39577
39067
  const { spacingProps, otherProps: propsAfterSpacing } = extractSpacingProps(props);
39578
39068
  const { layoutProps, otherProps } = extractLayoutProps(propsAfterSpacing);
39579
- const { value, size = 400, backgroundColor = 'transparent', color = '#000000', errorCorrectionLevel = 'M', quietZone = 4, logo, style, testID, accessibilityLabel, onError, onLoadStart, // deprecated noop
39069
+ const { value, size = 400, backgroundColor = 'transparent', color, errorCorrectionLevel = 'M', quietZone = 4, logo, style, testID, accessibilityLabel, onError, onLoadStart, // deprecated noop
39580
39070
  onLoadEnd, // deprecated noop
39581
39071
  ...rest } = otherProps;
39072
+ // Default color to theme's primary text color for dark mode support
39073
+ const resolvedColor = color !== null && color !== void 0 ? color : theme.text.primary;
39582
39074
  const { copy } = useClipboard();
39583
39075
  const toast = useToast();
39584
39076
  const shouldCopyOnPress = !!otherProps.copyOnPress;
@@ -39594,7 +39086,7 @@ function QRCode(props) {
39594
39086
  });
39595
39087
  }
39596
39088
  }, [copy, copyValue, toast, otherProps.copyToastMessage, otherProps.copyToastTitle]);
39597
- const content = (jsxs(View, { style: { borderRadius: 8, overflow: 'hidden' }, children: [jsx(QRCodeSVG, { value: value, size: size, maxWidth: '100%', backgroundColor: backgroundColor, color: color, errorCorrectionLevel: errorCorrectionLevel, quietZone: quietZone, logo: logo, style: style, testID: testID, accessibilityLabel: accessibilityLabel, onError: onError, ...spacingProps, ...layoutProps, ...rest }), otherProps.showCopyButton && (jsx(CopyButton, { value: copyValue, iconOnly: true, size: "sm", style: { position: 'absolute', top: 8, right: 8 }, onCopy: () => { } }))] }));
39089
+ const content = (jsxs(View, { style: { borderRadius: 8, overflow: 'hidden' }, children: [jsx(QRCodeSVG, { value: value, size: size, maxWidth: '100%', backgroundColor: backgroundColor, color: resolvedColor, errorCorrectionLevel: errorCorrectionLevel, quietZone: quietZone, logo: logo, style: style, testID: testID, accessibilityLabel: accessibilityLabel, onError: onError, ...spacingProps, ...layoutProps, ...rest }), otherProps.showCopyButton && (jsx(CopyButton, { value: copyValue, iconOnly: true, size: "sm", style: { position: 'absolute', top: 8, right: 8 }, onCopy: () => { } }))] }));
39598
39090
  if (shouldCopyOnPress) {
39599
39091
  return (jsx(Pressable, { onPress: handleCopy, accessibilityLabel: accessibilityLabel || 'QR code', children: content }));
39600
39092
  }
@@ -41667,5 +41159,5 @@ function withPressAnimation(Component, animationProps) {
41667
41159
  */
41668
41160
  const AnimatedPressable = PressAnimation;
41669
41161
 
41670
- export { AbilityCore, AccessibilityProvider, Accordion, AmazonAppstoreBadge, AmazonAppstoreButton, AmazonMusicListenBadge, AmazonPrimeVideoBadge, AmazonStoreBadge, AnimatedPressable, AppLayoutProvider, AppLayoutRenderer, AppShell, AppShellAside, AppShellBottomNav, AppShellFooter, AppShellHeader, AppShellMain, AppShellNavbar, AppShellSection, AppStoreBadge, AppStoreButton, AppStoreDownloadBadge, AppleAppStoreButton, AppleMusicListenBadge, ApplePodcastsListenBadge, AutoComplete, Avatar, AvatarGroup, Badge, Block, Blockquote, Bold, BottomAppBar, BrandButton, BrandIcon, Breadcrumbs, Button, COMPONENT_SIZES$1 as COMPONENT_SIZES, COMPONENT_SIZE_ORDER, Calendar, Can, CanWithConditions, Cannot, Card, Carousel, Checkbox, Chip, ChromeWebStoreBadge, Cite, Code, CodeBlock, Collapse, ColorPicker, ColorSwatch, Column, ComponentWithDisclaimer, ContextMenu, CopyButton, DARK_THEME, DEFAULT_BREAKPOINTS, DEFAULT_COMPONENT_SIZE, DEFAULT_SOUND_IDS, DEFAULT_THEME, DataTable, DatePicker, DatePickerInput, Day, Dialog, DialogProvider, DialogRenderer, DirectionProvider, Disclaimer, DiscordJoinBadge, Divider, EmojiPicker, Emphasis, FDroidButton, FileInput, Flex, FloatingActions, Form, GalaxyStoreDownloadBadge, Gallery, Gauge, GitHubViewBadge, GooglePlayButton, GooglePlayDownloadBadge, Grid, GridItem, H1, H2, H3, H4, H5, H6, HapticsProvider, Heading1, Heading2, Heading3, Heading4, Heading5, Heading6, Highlight, HoverCard, HuaweiAppGalleryBadge, I18nProvider, Icon, IconButton, Image, Indicator, Input, Italic, Kbd, KeyCap, KeyboardAwareLayout, KeyboardManagerProvider, Knob, Link, ListGroup, ListGroupBody, ListGroupDivider, ListGroupItem, Loader, LoadingOverlay, Lottie, MacAppStoreButton, Mark, Markdown, Masonry, Menu, MenuDivider, MenuDropdown, MenuItem, MenuItemButton, MenuLabel, MicrosoftStoreButton, MicrosoftStoreDownloadBadge, MiniCalendar, Month, MonthPicker, MonthPickerInput, NavigationProgress, Notice, NumberInput, Overlay, OverlayProvider, P, Pagination, PasswordInput, PermissionBuilder, PermissionGate, PermissionPatterns, PermissionProvider, PhoneInput, PinInput, PlatformBlocksProvider, Popover, PressAnimation, Progress, QRCode, Radio, RadioGroup, RangeSlider, Rating, RedditJoinBadge, RichTextEditor, Ring, RoleBuilder, Row, SIZE_SCALES, Search, SegmentedControl, Select, ShimmerText, Skeleton, Slider, Small, SoundCloudListenBadge, SoundProvider, Space, Spoiler, SpotifyListenBadge, Spotlight, SpotlightProvider, StatusBarManager, StepperWithSubComponents as Stepper, Strong, Sub, Sup, Switch, Table, TableOfContents, Tabs, Text, TextArea, TextInputBase, ThemeModeProvider, TikTokWatchBadge, TimePickerInput as TimePicker, TimePickerInput, TimelineWithItems as Timeline, Title, TitleRegistryProvider, Toast, ToastProvider, ToggleBar, ToggleButton, ToggleGroup, Tooltip, Tree, TwitchWatchBadge, Underline, Video, Waveform, YearPicker, YearPickerInput, YouTubeMusicListenBadge, YouTubeWatchBadge, calculateOverlayPositionEnhanced, clampComponentSize, clearOverlayPositionCache, createSound, createSpotlightStore, createTheme, debounce$1 as debounce, defineAbility, defineAppLayout, defineRoleAbility, directSpotlight, extractDisclaimerProps, factory, getAllSounds, getColor, getFontSize, getHeight, getIconSize$1 as getIconSize, getLineHeight, getRadius$1 as getRadius, getScrollPosition, getShadow$1 as getShadow, getSize, getSoundsByCategory, getSpacing, getViewport, globalHotkeys, measureAsyncPerformance, measureElement, measurePerformance, navigationProgress, onDialogsRequested, onSpotlightRequested, onToastsRequested, permissions, pointInRect, polymorphicFactory, px, rem, resolveComponentSize, resolveResponsiveProp, resolveResponsiveValue, resolveSize, spotlight, throttle, useAbility, useAccessibility, useAppLayoutContext, useAppShell, useAppShellApi, useAppShellLayout, useBreakpoint, useColorScheme, useDialog, useDialogApi, useDialogs, useDirectSpotlightState, useDirection, useDirectionSafe, useDisclaimer, useDropdownPositioning, useEscapeKey, useFormContext, useGlobalHotkeys, useHaptics, useHapticsSettings, useHotkeys, useI18n, useKeyboardManager, useKeyboardManagerOptional, useNavbarHover, useOptionalFormContext, useOverlay, useOverlayApi, useOverlays, usePermissions, usePopoverPositioning, useSimpleDialog, useSound, useSpotlightStore, useSpotlightStoreInstance, useSpotlightToggle, useTheme, useThemeMode, useTitleRegistry, useTitleRegistryOptional, useToast, useToastApi, useToggleColorScheme, useTooltipPositioning, withCan, withCannot, withDisclaimer, withPressAnimation };
41162
+ export { AccessibilityProvider, Accordion, AmazonAppstoreBadge, AmazonAppstoreButton, AmazonMusicListenBadge, AmazonPrimeVideoBadge, AmazonStoreBadge, AnimatedPressable, AppLayoutProvider, AppLayoutRenderer, AppShell, AppShellAside, AppShellBottomNav, AppShellFooter, AppShellHeader, AppShellMain, AppShellNavbar, AppShellSection, AppStoreBadge, AppStoreButton, AppStoreDownloadBadge, AppleAppStoreButton, AppleMusicListenBadge, ApplePodcastsListenBadge, AutoComplete, Avatar, AvatarGroup, Badge, Block, Blockquote, Bold, BottomAppBar, BrandButton, BrandIcon, Breadcrumbs, Button, COMPONENT_SIZES$1 as COMPONENT_SIZES, COMPONENT_SIZE_ORDER, Calendar, Card, Carousel, Checkbox, Chip, ChromeWebStoreBadge, Cite, Code, CodeBlock, Collapse, ColorPicker, ColorSwatch, Column, ComponentWithDisclaimer, ContextMenu, CopyButton, DARK_THEME, DEFAULT_BREAKPOINTS, DEFAULT_COMPONENT_SIZE, DEFAULT_SOUND_IDS, DEFAULT_THEME, DataTable, DatePicker, DatePickerInput, Day, Dialog, DialogProvider, DialogRenderer, DirectionProvider, Disclaimer, DiscordJoinBadge, Divider, EmojiPicker, Emphasis, FDroidButton, FileInput, Flex, FloatingActions, Form, GalaxyStoreDownloadBadge, Gallery, Gauge, GitHubViewBadge, GooglePlayButton, GooglePlayDownloadBadge, Grid, GridItem, H1, H2, H3, H4, H5, H6, HapticsProvider, Heading1, Heading2, Heading3, Heading4, Heading5, Heading6, Highlight, HuaweiAppGalleryBadge, I18nProvider, Icon, IconButton, Image, Indicator, Input, Italic, Kbd, KeyCap, KeyboardAwareLayout, KeyboardManagerProvider, Knob, Link, ListGroup, ListGroupBody, ListGroupDivider, ListGroupItem, Loader, LoadingOverlay, Lottie, MacAppStoreButton, Mark, Markdown, Masonry, Menu, MenuDivider, MenuDropdown, MenuItem, MenuItemButton, MenuLabel, MicrosoftStoreButton, MicrosoftStoreDownloadBadge, MiniCalendar, Month, MonthPicker, MonthPickerInput, Notice, NumberInput, Overlay, OverlayProvider, P, Pagination, PasswordInput, PhoneInput, PinInput, PlatformBlocksProvider, Popover, PressAnimation, Progress, QRCode, Radio, RadioGroup, RangeSlider, Rating, RedditJoinBadge, RichTextEditor, Ring, Row, SIZE_SCALES, Search, SegmentedControl, Select, ShimmerText, Skeleton, Slider, Small, SoundCloudListenBadge, SoundProvider, Space, Spoiler, SpotifyListenBadge, Spotlight, SpotlightProvider, StatusBarManager, StepperWithSubComponents as Stepper, Strong, Sub, Sup, Switch, Table, TableOfContents, Tabs, Text, TextArea, TextInputBase, ThemeModeProvider, TikTokWatchBadge, TimePickerInput as TimePicker, TimePickerInput, TimelineWithItems as Timeline, Title, TitleRegistryProvider, Toast, ToastProvider, ToggleBar, ToggleButton, ToggleGroup, Tooltip, Tree, TwitchWatchBadge, Underline, Video, Waveform, YearPicker, YearPickerInput, YouTubeMusicListenBadge, YouTubeWatchBadge, calculateOverlayPositionEnhanced, clampComponentSize, clearOverlayPositionCache, createSound, createSpotlightStore, createTheme, debounce$1 as debounce, defineAppLayout, directSpotlight, extractDisclaimerProps, factory, getAllSounds, getColor, getFontSize, getHeight, getIconSize$1 as getIconSize, getLineHeight, getRadius$1 as getRadius, getScrollPosition, getShadow$1 as getShadow, getSize, getSoundsByCategory, getSpacing, getViewport, globalHotkeys, measureAsyncPerformance, measureElement, measurePerformance, onDialogsRequested, onSpotlightRequested, onToastsRequested, pointInRect, polymorphicFactory, px, rem, resolveComponentSize, resolveResponsiveProp, resolveResponsiveValue, resolveSize, spotlight, throttle, useAccessibility, useAppLayoutContext, useAppShell, useAppShellApi, useAppShellLayout, useBreakpoint, useColorScheme, useDialog, useDialogApi, useDialogs, useDirectSpotlightState, useDirection, useDirectionSafe, useDisclaimer, useDropdownPositioning, useEscapeKey, useFormContext, useGlobalHotkeys, useHaptics, useHapticsSettings, useHotkeys, useI18n, useKeyboardManager, useKeyboardManagerOptional, useNavbarHover, useOptionalFormContext, useOverlay, useOverlayApi, useOverlays, usePopoverPositioning, useSimpleDialog, useSound, useSpotlightStore, useSpotlightStoreInstance, useSpotlightToggle, useTheme, useThemeMode, useTitleRegistry, useTitleRegistryOptional, useToast, useToastApi, useToggleColorScheme, useTooltipPositioning, withDisclaimer, withPressAnimation };
41671
41163
  //# sourceMappingURL=index.js.map