@platform-blocks/ui 0.6.1 → 0.7.1

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 (50) hide show
  1. package/README.md +0 -24
  2. package/lib/cjs/index.js +54 -18
  3. package/lib/cjs/index.js.map +1 -1
  4. package/lib/components/Accordion/types.d.ts +5 -5
  5. package/lib/components/AutoComplete/types.d.ts +3 -3
  6. package/lib/components/Avatar/types.d.ts +3 -3
  7. package/lib/components/Badge/types.d.ts +3 -3
  8. package/lib/components/Block/types.d.ts +2 -2
  9. package/lib/components/Blockquote/types.d.ts +2 -2
  10. package/lib/components/Breadcrumbs/types.d.ts +4 -4
  11. package/lib/components/Calendar/types.d.ts +2 -2
  12. package/lib/components/Carousel/types.d.ts +3 -3
  13. package/lib/components/Chip/types.d.ts +3 -3
  14. package/lib/components/CodeBlock/types.d.ts +4 -4
  15. package/lib/components/ColorPicker/types.d.ts +4 -4
  16. package/lib/components/CopyButton/types.d.ts +2 -2
  17. package/lib/components/DatePicker/types.d.ts +2 -2
  18. package/lib/components/Divider/types.d.ts +2 -2
  19. package/lib/components/Grid/types.d.ts +3 -3
  20. package/lib/components/HoverCard/types.d.ts +2 -2
  21. package/lib/components/Image/types.d.ts +3 -3
  22. package/lib/components/Indicator/types.d.ts +2 -2
  23. package/lib/components/Knob/components/SurfaceLayers.d.ts +2 -2
  24. package/lib/components/Knob/components/ThumbLayer.d.ts +1 -1
  25. package/lib/components/Knob/components/TickLayers.d.ts +2 -2
  26. package/lib/components/Knob/types.d.ts +11 -11
  27. package/lib/components/ListGroup/types.d.ts +4 -4
  28. package/lib/components/Loader/types.d.ts +2 -2
  29. package/lib/components/Masonry/types.d.ts +4 -4
  30. package/lib/components/Navigation/types.d.ts +2 -2
  31. package/lib/components/Notice/types.d.ts +2 -2
  32. package/lib/components/Pagination/types.d.ts +6 -6
  33. package/lib/components/Progress/types.d.ts +3 -3
  34. package/lib/components/QRCode/types.d.ts +2 -2
  35. package/lib/components/Rating/types.d.ts +2 -2
  36. package/lib/components/Ring/types.d.ts +7 -7
  37. package/lib/components/SegmentedControl/types.d.ts +4 -4
  38. package/lib/components/Skeleton/types.d.ts +2 -2
  39. package/lib/components/Slider/types.d.ts +7 -7
  40. package/lib/components/Spotlight/types.d.ts +6 -6
  41. package/lib/components/Tabs/types.d.ts +5 -5
  42. package/lib/components/Toast/types.d.ts +2 -2
  43. package/lib/components/Tooltip/types.d.ts +2 -2
  44. package/lib/components/Video/NativeVideoPlayer.d.ts +2 -2
  45. package/lib/components/Video/VideoControls.d.ts +2 -2
  46. package/lib/components/Video/YouTubePlayer.d.ts +2 -2
  47. package/lib/components/Video/types.d.ts +4 -4
  48. package/lib/esm/index.js +54 -18
  49. package/lib/esm/index.js.map +1 -1
  50. package/package.json +1 -1
package/README.md CHANGED
@@ -34,27 +34,3 @@ export function App() {
34
34
  );
35
35
  }
36
36
  ```
37
-
38
- Refer to the documentation site for component examples and API details. A dedicated “Keyboard Management” guide is available at `/keyboard` within the docs app.
39
-
40
- ## Keyboard Management
41
-
42
- Packages that render focusable inputs can opt into shared keyboard state by wrapping their tree in `KeyboardManagerProvider`. This unlocks the `useKeyboardManager()` hook and ensures components like `AutoComplete` and `Select` dismiss or refocus the keyboard consistently across web and native platforms.
43
-
44
- ```tsx
45
- import { KeyboardManagerProvider, KeyboardAwareLayout } from '@platform-blocks/ui';
46
-
47
- export function App() {
48
- return (
49
- <KeyboardManagerProvider>
50
- <KeyboardAwareLayout>
51
- {/* form inputs */}
52
- </KeyboardAwareLayout>
53
- </KeyboardManagerProvider>
54
- );
55
- }
56
- ```
57
-
58
- `KeyboardAwareLayout` is optional but recommended for screens where the on-screen keyboard could obscure lower inputs. Components expose a `refocusAfterSelect` prop that lets you override the default dismissal behavior when selections complete.
59
-
60
- For direct inputs, you can pass `keyboardFocusId` to make a field eligible for deferred refocus requests triggered via `KeyboardManagerProvider` (for example, when an overlay completes a selection and needs to restore focus to a specific input).
package/lib/cjs/index.js CHANGED
@@ -3527,6 +3527,35 @@ const containsPlatformText = (node) => {
3527
3527
  return false;
3528
3528
  });
3529
3529
  };
3530
+ /**
3531
+ * Check if children contain block-level elements (View, Pressable, etc.)
3532
+ * that would render as <div> on web, causing invalid nesting inside <p>.
3533
+ */
3534
+ const containsBlockElement = (node) => {
3535
+ return React.Children.toArray(node).some(child => {
3536
+ if (React.isValidElement(child)) {
3537
+ const childType = child.type;
3538
+ // Check for native RN components that render as div on web
3539
+ const displayName = (childType === null || childType === void 0 ? void 0 : childType.displayName) || (childType === null || childType === void 0 ? void 0 : childType.name) || '';
3540
+ const blockNames = new Set([
3541
+ 'View', 'Pressable', 'TouchableOpacity', 'TouchableHighlight',
3542
+ 'TouchableWithoutFeedback', 'ScrollView', 'FlatList', 'SectionList',
3543
+ 'SafeAreaView', 'KeyboardAvoidingView', 'Modal',
3544
+ ]);
3545
+ if (blockNames.has(displayName))
3546
+ return true;
3547
+ // Also check if it's a native 'div' element
3548
+ if (childType === 'div')
3549
+ return true;
3550
+ // Recurse into children
3551
+ const childProps = child.props;
3552
+ if (childProps === null || childProps === void 0 ? void 0 : childProps.children) {
3553
+ return containsBlockElement(childProps.children);
3554
+ }
3555
+ }
3556
+ return false;
3557
+ });
3558
+ };
3530
3559
  const Text = (allProps) => {
3531
3560
  const { spacingProps, otherProps } = extractSpacingProps(allProps);
3532
3561
  const { children, tx, txParams, variant = 'p', size, weight, align = 'left', color, colorVariant, lineHeight, tracking, uppercase, style, fontFamily, as, selectable = true, onPress, onLayout, value, numberOfLines, ellipsizeMode } = otherProps;
@@ -3571,6 +3600,10 @@ const Text = (allProps) => {
3571
3600
  // Avoid nested paragraphs when Text components are nested
3572
3601
  htmlTag = 'div';
3573
3602
  }
3603
+ if (htmlTag === 'p' && containsBlockElement(children)) {
3604
+ // Avoid <div> inside <p> when children contain View, Pressable, etc.
3605
+ htmlTag = 'div';
3606
+ }
3574
3607
  }
3575
3608
  // Platform-specific rendering
3576
3609
  if (reactNative.Platform.OS === 'web' && isHTMLVariant(htmlTag)) {
@@ -6722,23 +6755,25 @@ function Dialog({ visible, variant = 'modal', title, children, closable = true,
6722
6755
  }, visible && closable);
6723
6756
  // Pan responder for bottomsheet swipe-to-dismiss
6724
6757
  const panResponder = React.useRef(reactNative.PanResponder.create({
6758
+ onStartShouldSetPanResponderCapture: () => {
6759
+ // Never capture on touch start — let events reach children (buttons) first
6760
+ return false;
6761
+ },
6725
6762
  onStartShouldSetPanResponder: () => {
6726
- // Only allow responder when swipe gestures are enabled for bottom sheet
6763
+ // Claim in bubble phase (after children had their chance to claim).
6764
+ // If a Button/Pressable already claimed the touch, this won't fire.
6765
+ // If nothing claimed (e.g. drag handle, empty space), we take over for swipe tracking.
6727
6766
  return variant === 'bottomsheet' && bottomSheetSwipeZone !== 'none';
6728
6767
  },
6729
- onStartShouldSetPanResponderCapture: () => {
6730
- // Capture immediately for bottom sheet to ensure gesture responsiveness on native
6731
- return variant === 'bottomsheet' && bottomSheetSwipeZone !== 'none';
6768
+ onMoveShouldSetPanResponderCapture: () => {
6769
+ // Never capture moves let children handle their own gestures
6770
+ return false;
6732
6771
  },
6733
6772
  onMoveShouldSetPanResponder: (_, gestureState) => {
6734
- // Allow movement in any direction but prioritize downward movement
6773
+ // Claim the gesture when there's a clear vertical swipe movement
6735
6774
  return variant === 'bottomsheet' && bottomSheetSwipeZone !== 'none' && (Math.abs(gestureState.dy) > Math.abs(gestureState.dx) &&
6736
6775
  Math.abs(gestureState.dy) > 2);
6737
6776
  },
6738
- onMoveShouldSetPanResponderCapture: () => {
6739
- // Already captured on start; keep returning true for consistency
6740
- return variant === 'bottomsheet' && bottomSheetSwipeZone !== 'none';
6741
- },
6742
6777
  onPanResponderGrant: (evt) => {
6743
6778
  // Prevent default browser behavior (text selection, etc.) on web
6744
6779
  if (reactNative.Platform.OS === 'web') {
@@ -10842,7 +10877,7 @@ const Masonry = factory((props, ref) => {
10842
10877
  };
10843
10878
  const containerStyle = {
10844
10879
  ...spacingStyle,
10845
- ...style,
10880
+ ...reactNative.StyleSheet.flatten(style),
10846
10881
  };
10847
10882
  // Show loading state
10848
10883
  if (loading) {
@@ -14503,7 +14538,8 @@ const CodeBlock = (props) => {
14503
14538
  if (spoiler) {
14504
14539
  wrappedCodeContent = (jsxRuntime.jsx(Spoiler, { maxHeight: spoilerMaxHeight, children: scrollableCodeContent }));
14505
14540
  }
14506
- const userHasWidth = Boolean(style && (style.width !== undefined || style.flex !== undefined));
14541
+ const flatStyle = reactNative.StyleSheet.flatten(style);
14542
+ const userHasWidth = Boolean(flatStyle && (flatStyle.width !== undefined || flatStyle.flex !== undefined));
14507
14543
  const containerStyle = userHasWidth ? [{ marginBottom: 20 }, style, spacingStyles] : [styles.container, spacingStyles, style];
14508
14544
  const showHeaderBar = fileHeader && fileName && variant !== 'terminal';
14509
14545
  const inlineTitleVisible = variant === 'code' && (title || fileName);
@@ -16113,12 +16149,12 @@ const BrandButton = (props) => {
16113
16149
  return { backgroundColor: 'transparent', borderColor: 'transparent' };
16114
16150
  case 'plain':
16115
16151
  return {
16116
- backgroundColor: 'white',
16152
+ backgroundColor: theme.colorScheme === 'dark' ? theme.backgrounds.elevated : 'white',
16117
16153
  borderColor: 'transparent',
16118
16154
  paddingHorizontal: 16,
16119
16155
  minWidth: 0,
16120
16156
  height: 'auto',
16121
- color: 'black'
16157
+ color: theme.colorScheme === 'dark' ? theme.text.primary : 'black'
16122
16158
  };
16123
16159
  default: // primary/filled/secondary/gradient etc treat as filled brand color
16124
16160
  return {
@@ -16129,7 +16165,7 @@ const BrandButton = (props) => {
16129
16165
  }
16130
16166
  })();
16131
16167
  // Compute textColor override: outline/link use brand color, ghost uses default text color, filled-like use contrasting light text
16132
- const textColor = effectiveVariant === 'plain' ? 'black' :
16168
+ const textColor = effectiveVariant === 'plain' ? (theme.colorScheme === 'dark' ? theme.text.primary : 'black') :
16133
16169
  effectiveVariant === 'ghost'
16134
16170
  ? theme.text.primary
16135
16171
  : (effectiveVariant === 'outline' || effectiveVariant === 'link')
@@ -30976,7 +31012,7 @@ function Avatar({ size = 'md', src, fallback, backgroundColor, textColor = 'whit
30976
31012
  };
30977
31013
  const containerStyle = {
30978
31014
  position: 'relative',
30979
- ...style,
31015
+ ...reactNative.StyleSheet.flatten(style),
30980
31016
  };
30981
31017
  const content = (jsxRuntime.jsxs(reactNative.View, { style: containerStyle, children: [jsxRuntime.jsx(reactNative.View, { style: avatarStyle, children: src ? (jsxRuntime.jsx(reactNative.Image, { source: { uri: src }, style: {
30982
31018
  width: avatarSize,
@@ -30997,7 +31033,7 @@ function AvatarGroup({ children, limit, spacing = -8, style, size, bordered = tr
30997
31033
  const containerStyle = {
30998
31034
  flexDirection: 'row',
30999
31035
  alignItems: 'center',
31000
- ...style,
31036
+ ...reactNative.StyleSheet.flatten(style),
31001
31037
  };
31002
31038
  const avatarWrapperStyle = (index) => ({
31003
31039
  marginLeft: index > 0 ? spacing : 0,
@@ -37183,7 +37219,7 @@ function Image({ src, source, alt, accessibilityLabel, resizeMode = 'cover', siz
37183
37219
  const spacingStyles = getSpacingStyles(spacingProps);
37184
37220
  const containerStyles = {
37185
37221
  ...spacingStyles,
37186
- ...containerStyle,
37222
+ ...reactNative.StyleSheet.flatten(containerStyle),
37187
37223
  };
37188
37224
  const imageStyles = {
37189
37225
  width: finalWidth,
@@ -37192,7 +37228,7 @@ function Image({ src, source, alt, accessibilityLabel, resizeMode = 'cover', siz
37192
37228
  borderWidth,
37193
37229
  borderColor: borderColor || theme.colors.gray[3],
37194
37230
  borderRadius,
37195
- ...imageStyle,
37231
+ ...reactNative.StyleSheet.flatten(imageStyle),
37196
37232
  };
37197
37233
  if (finalWidth !== undefined) {
37198
37234
  containerStyles.width = finalWidth;