@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.
- package/README.md +0 -24
- package/lib/cjs/index.js +54 -18
- package/lib/cjs/index.js.map +1 -1
- package/lib/components/Accordion/types.d.ts +5 -5
- package/lib/components/AutoComplete/types.d.ts +3 -3
- package/lib/components/Avatar/types.d.ts +3 -3
- package/lib/components/Badge/types.d.ts +3 -3
- package/lib/components/Block/types.d.ts +2 -2
- package/lib/components/Blockquote/types.d.ts +2 -2
- package/lib/components/Breadcrumbs/types.d.ts +4 -4
- package/lib/components/Calendar/types.d.ts +2 -2
- package/lib/components/Carousel/types.d.ts +3 -3
- package/lib/components/Chip/types.d.ts +3 -3
- package/lib/components/CodeBlock/types.d.ts +4 -4
- package/lib/components/ColorPicker/types.d.ts +4 -4
- package/lib/components/CopyButton/types.d.ts +2 -2
- package/lib/components/DatePicker/types.d.ts +2 -2
- package/lib/components/Divider/types.d.ts +2 -2
- package/lib/components/Grid/types.d.ts +3 -3
- package/lib/components/HoverCard/types.d.ts +2 -2
- package/lib/components/Image/types.d.ts +3 -3
- package/lib/components/Indicator/types.d.ts +2 -2
- package/lib/components/Knob/components/SurfaceLayers.d.ts +2 -2
- package/lib/components/Knob/components/ThumbLayer.d.ts +1 -1
- package/lib/components/Knob/components/TickLayers.d.ts +2 -2
- package/lib/components/Knob/types.d.ts +11 -11
- package/lib/components/ListGroup/types.d.ts +4 -4
- package/lib/components/Loader/types.d.ts +2 -2
- package/lib/components/Masonry/types.d.ts +4 -4
- package/lib/components/Navigation/types.d.ts +2 -2
- package/lib/components/Notice/types.d.ts +2 -2
- package/lib/components/Pagination/types.d.ts +6 -6
- package/lib/components/Progress/types.d.ts +3 -3
- package/lib/components/QRCode/types.d.ts +2 -2
- package/lib/components/Rating/types.d.ts +2 -2
- package/lib/components/Ring/types.d.ts +7 -7
- package/lib/components/SegmentedControl/types.d.ts +4 -4
- package/lib/components/Skeleton/types.d.ts +2 -2
- package/lib/components/Slider/types.d.ts +7 -7
- package/lib/components/Spotlight/types.d.ts +6 -6
- package/lib/components/Tabs/types.d.ts +5 -5
- package/lib/components/Toast/types.d.ts +2 -2
- package/lib/components/Tooltip/types.d.ts +2 -2
- package/lib/components/Video/NativeVideoPlayer.d.ts +2 -2
- package/lib/components/Video/VideoControls.d.ts +2 -2
- package/lib/components/Video/YouTubePlayer.d.ts +2 -2
- package/lib/components/Video/types.d.ts +4 -4
- package/lib/esm/index.js +54 -18
- package/lib/esm/index.js.map +1 -1
- 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
|
-
//
|
|
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
|
-
|
|
6730
|
-
//
|
|
6731
|
-
return
|
|
6768
|
+
onMoveShouldSetPanResponderCapture: () => {
|
|
6769
|
+
// Never capture moves — let children handle their own gestures
|
|
6770
|
+
return false;
|
|
6732
6771
|
},
|
|
6733
6772
|
onMoveShouldSetPanResponder: (_, gestureState) => {
|
|
6734
|
-
//
|
|
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
|
|
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;
|