@vvedantb/native-ui 0.17.2 → 0.18.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/AlertDialog.jsx +123 -0
- package/dist/AmbientBackground.jsx +73 -0
- package/dist/ArtifactList.jsx +59 -0
- package/dist/Avatar.jsx +285 -0
- package/dist/Badge.jsx +154 -0
- package/dist/BottomSheetContainer.jsx +208 -0
- package/dist/BulkActionBar.jsx +717 -0
- package/dist/Button.jsx +344 -0
- package/dist/CaptureButton.jsx +104 -0
- package/dist/Card.jsx +371 -0
- package/dist/Checkbox.jsx +177 -0
- package/dist/Chip.jsx +79 -0
- package/dist/ColorSwatches.jsx +159 -0
- package/dist/ConfirmDialog.jsx +157 -0
- package/dist/DateTimeField.jsx +204 -0
- package/dist/Dialog.jsx +614 -0
- package/dist/DividedList.jsx +120 -0
- package/dist/DropdownMenu.jsx +849 -0
- package/dist/EmptyState.jsx +434 -0
- package/dist/ExpoWebRoot.jsx +134 -0
- package/dist/FloatingFAB.jsx +95 -0
- package/dist/FloatingSurface.jsx +226 -0
- package/dist/FloatingTabBar.jsx +403 -0
- package/dist/HeaderIconButton.jsx +53 -0
- package/dist/IconButton.jsx +157 -0
- package/dist/Input.jsx +96 -0
- package/dist/Label.jsx +96 -0
- package/dist/LabeledSwitchRow.jsx +170 -0
- package/dist/LiquidGlass.jsx +2 -0
- package/dist/ListRow.jsx +281 -0
- package/dist/LoadingState.jsx +205 -0
- package/dist/PageIndicator.jsx +128 -0
- package/dist/PageTitle.jsx +205 -0
- package/dist/Pager.jsx +105 -0
- package/dist/PasswordInput.jsx +120 -0
- package/dist/PillTabs.jsx +300 -0
- package/dist/PinnedBotTile.jsx +212 -0
- package/dist/Progress.jsx +147 -0
- package/dist/SafeAreaContainer.jsx +38 -0
- package/dist/ScreenContainer.jsx +117 -0
- package/dist/SearchInput.jsx +150 -0
- package/dist/SectionLabel.jsx +128 -0
- package/dist/Select.jsx +223 -0
- package/dist/Separator.jsx +95 -0
- package/dist/Sheet.jsx +343 -0
- package/dist/SheetRow.jsx +198 -0
- package/dist/Skeleton.jsx +311 -0
- package/dist/Spinner.jsx +195 -0
- package/dist/StackPageHeader.jsx +160 -0
- package/dist/StatGrid.jsx +74 -0
- package/dist/StatusDot.jsx +129 -0
- package/dist/SurfaceRow.jsx +143 -0
- package/dist/SwipeableRow.jsx +50 -0
- package/dist/Switch.jsx +130 -0
- package/dist/Tabs.jsx +385 -0
- package/dist/Textarea.jsx +103 -0
- package/dist/ThemeToggle.jsx +78 -0
- package/dist/Toast.jsx +396 -0
- package/dist/ai/activity-step-detail.jsx +179 -0
- package/dist/ai/activity-step-label.js +816 -0
- package/dist/ai/activity-step-types.js +14 -0
- package/dist/ai/activity-step.jsx +98 -0
- package/dist/ai/activity-tasks-utils.js +172 -0
- package/dist/ai/activity-timeline.js +47 -0
- package/dist/ai/attachments.jsx +258 -0
- package/dist/ai/card-button.jsx +188 -0
- package/dist/ai/chain-of-thought.jsx +459 -0
- package/dist/ai/chat-jump-rail.jsx +57 -0
- package/dist/ai/chat-text.js +44 -0
- package/dist/ai/chat-thread.jsx +135 -0
- package/dist/ai/choice-question.jsx +925 -0
- package/dist/ai/code-block.jsx +574 -0
- package/dist/ai/collapsible.jsx +275 -0
- package/dist/ai/conversation.jsx +723 -0
- package/dist/ai/file-chip.jsx +198 -0
- package/dist/ai/icon-button.jsx +179 -0
- package/dist/ai/index.js +37 -0
- package/dist/ai/message-action-sheet.jsx +408 -0
- package/dist/ai/message-quote.jsx +241 -0
- package/dist/ai/message.jsx +739 -0
- package/dist/ai/prompt-input-menu.jsx +365 -0
- package/dist/ai/prompt-input.jsx +626 -0
- package/dist/ai/reasoning.jsx +446 -0
- package/dist/ai/reply-quote-chip.jsx +278 -0
- package/dist/ai/response-text.jsx +130 -0
- package/dist/ai/shimmer.jsx +149 -0
- package/dist/ai/sources.jsx +260 -0
- package/dist/ai/subagent-cards.jsx +645 -0
- package/dist/ai/suggestion.jsx +186 -0
- package/dist/ai/tool-approval-card.jsx +359 -0
- package/dist/ai/trace.jsx +728 -0
- package/dist/ai/unified-diff.jsx +280 -0
- package/dist/ai/use-streaming-disclosure.js +70 -0
- package/dist/auth/AuthProviders.jsx +27 -0
- package/dist/auth/AuthScreen.jsx +292 -0
- package/dist/auth/GoogleSignInButton.jsx +188 -0
- package/dist/auth/SecondFactorScreen.jsx +133 -0
- package/dist/auth/SignInScreen.jsx +482 -0
- package/dist/auth/authErrors.js +131 -0
- package/dist/auth/index.js +11 -0
- package/dist/auth/totp.js +378 -0
- package/dist/blur.js +36 -0
- package/dist/brand/AppIcons.jsx +118 -0
- package/dist/brand/AppMark.jsx +128 -0
- package/dist/brand/AppWordmark.jsx +138 -0
- package/dist/brand/GoogleMark.jsx +71 -0
- package/dist/brand/ProviderIcon.jsx +192 -0
- package/dist/brand/familyApps.js +33 -0
- package/dist/brand/index.js +11 -0
- package/dist/brand/svg.js +252 -0
- package/dist/brand/vProAppBenefits.js +19 -0
- package/dist/cn.js +5 -0
- package/dist/colors.js +15 -0
- package/dist/configureTheme.js +72 -0
- package/dist/controlStyles.js +520 -0
- package/dist/definiteSize.js +12 -0
- package/dist/dialogLayout.js +18 -0
- package/dist/entries/ai.js +4 -0
- package/dist/entries/ambient.js +3 -0
- package/dist/entries/auth.js +5 -0
- package/dist/entries/bottom-sheet.js +2 -0
- package/dist/entries/brand.js +2 -0
- package/dist/entries/button.js +2 -0
- package/dist/entries/date-time.js +3 -0
- package/dist/entries/expo-router.js +4 -0
- package/dist/entries/expo-web-root.js +3 -0
- package/dist/entries/floating.js +7 -0
- package/dist/entries/gesture-handler.js +4 -0
- package/dist/entries/keyboard-controller.js +4 -0
- package/dist/entries/layout.js +16 -0
- package/dist/entries/markdown.js +4 -0
- package/dist/entries/marketing.js +3 -0
- package/dist/entries/page-title.js +7 -0
- package/dist/entries/password-input.js +3 -0
- package/dist/entries/primitives.js +57 -0
- package/dist/entries/search-input.js +3 -0
- package/dist/entries/tab-bar.js +4 -0
- package/dist/entries/theme.js +7 -0
- package/dist/entries/toast.js +5 -0
- package/dist/entries/video.js +3 -0
- package/dist/entries/webview.js +4 -0
- package/dist/examples/AiChatGallery.jsx +509 -0
- package/dist/examples/ParityGallery.jsx +1307 -0
- package/dist/floating.js +62 -0
- package/dist/glassBlur.jsx +145 -0
- package/dist/gradient.js +17 -0
- package/dist/haptics.js +44 -0
- package/dist/highlight.js +382 -0
- package/dist/index.js +85 -0
- package/dist/initials.js +4 -0
- package/dist/loadingGrid.js +81 -0
- package/dist/markdown/Markdown.jsx +515 -0
- package/dist/markdown/MarkdownTable.jsx +443 -0
- package/dist/markdown/tableText.js +68 -0
- package/dist/marketing/PricingModal.jsx +608 -0
- package/dist/marketing/UpgradeToProCard.jsx +164 -0
- package/dist/marketing/pricing.js +34 -0
- package/dist/media/ImageGallery.jsx +580 -0
- package/dist/media/MediaCard.jsx +162 -0
- package/dist/media/imageGrid.js +54 -0
- package/dist/motion.js +33 -0
- package/dist/pagerSwipe.js +104 -0
- package/dist/palette.js +104 -0
- package/dist/primitives/button.jsx +127 -0
- package/dist/primitives/card.jsx +249 -0
- package/dist/primitives/icon.jsx +37 -0
- package/dist/primitives/input.jsx +56 -0
- package/dist/primitives/keyboard-controller.jsx +207 -0
- package/dist/primitives/keyboard-parts.jsx +75 -0
- package/dist/primitives/native-only-animated-view.jsx +68 -0
- package/dist/primitives/overlay.jsx +391 -0
- package/dist/primitives/pager-gesture.jsx +131 -0
- package/dist/primitives/select-host.jsx +103 -0
- package/dist/primitives/select.jsx +555 -0
- package/dist/primitives/sheet-drag.jsx +420 -0
- package/dist/primitives/sheet-gesture.jsx +219 -0
- package/dist/primitives/swipe-row-gesture.jsx +341 -0
- package/dist/primitives/switch.jsx +105 -0
- package/dist/primitives/text.jsx +145 -0
- package/dist/primitives/toast-drag-gesture.jsx +94 -0
- package/dist/primitives/use-controllable-state.js +40 -0
- package/dist/primitives/web-click-guard.js +69 -0
- package/dist/push.js +166 -0
- package/dist/relativeTime.js +70 -0
- package/dist/router/RouterStackPageHeader.jsx +53 -0
- package/dist/selectA11y.js +32 -0
- package/dist/settings/MoreFromProjectV.jsx +168 -0
- package/dist/settings/SettingsEmptyState.jsx +102 -0
- package/dist/settings/SettingsField.jsx +49 -0
- package/dist/settings/SettingsSection.jsx +101 -0
- package/dist/settings/SettingsStack.jsx +17 -0
- package/dist/settings/SettingsToggleRow.jsx +163 -0
- package/dist/settings/projectVMobileApps.js +126 -0
- package/dist/settings/relaxedSizeStyle.js +11 -0
- package/dist/sheetDrag.js +76 -0
- package/dist/svgA11y.js +46 -0
- package/dist/swipeRow.js +161 -0
- package/dist/tabBarRoutes.js +41 -0
- package/dist/tabIndicator.js +139 -0
- package/dist/tailwind-preset.cjs +255 -0
- package/dist/tailwind-preset.d.cts +55 -0
- package/dist/theme.jsx +62 -0
- package/dist/toastChrome.js +110 -0
- package/dist/toastDrag.js +51 -0
- package/dist/toastStore.js +54 -0
- package/dist/tokens.js +70 -0
- package/dist/typography.js +40 -0
- package/dist/useReduceMotion.js +32 -0
- package/dist/useReduceTransparency.js +27 -0
- package/dist/useScheme.js +15 -0
- package/dist/video/InlineVideo.jsx +115 -0
- package/dist/webview/HtmlView.jsx +169 -0
- package/dist/webview/HtmlView.web.jsx +63 -0
- package/dist/webview/htmlView.js +43 -0
- package/package.json +70 -33
- package/src/DropdownMenu.tsx +28 -16
- package/src/FloatingTabBar.tsx +78 -41
- package/src/ai/conversation.tsx +12 -8
- package/src/glassBlur.tsx +47 -22
- package/src/primitives/swipe-row-gesture.tsx +11 -2
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
import { c as _c } from "react/compiler-runtime";
|
|
2
|
+
import { useEffect, useRef, useState } from "react";
|
|
3
|
+
import { View } from "react-native";
|
|
4
|
+
import { WebView } from "react-native-webview";
|
|
5
|
+
import { HTML_VIEW_HEIGHT_SCRIPT, htmlViewNavigation, htmlViewPostScript, parseHtmlViewHeight } from "./htmlView";
|
|
6
|
+
/**
|
|
7
|
+
* An HTML page in a sandboxed `react-native-webview`, as the web's sandboxed
|
|
8
|
+
* `srcdoc` iframe: transparent on the screen behind it, scripts on, and no
|
|
9
|
+
* way out of its own document. A top-level link goes to `onOpenLink`; a
|
|
10
|
+
* popup (`target="_blank"`, `window.open`) does too; any other navigation is
|
|
11
|
+
* dropped. Incognito, with no DOM storage, cookies or file access, so the page
|
|
12
|
+
* keeps nothing between views and reaches nothing of the app's. It reports its
|
|
13
|
+
* height (`onContentHeight`) for a box that fits it.
|
|
14
|
+
*
|
|
15
|
+
* `@vvedantb/native-ui/webview` is the only entry that imports
|
|
16
|
+
* `react-native-webview` (an optional peer). On web, `HtmlView.web.tsx` draws a
|
|
17
|
+
* sandboxed iframe instead.
|
|
18
|
+
*/
|
|
19
|
+
export function HtmlView(t0) {
|
|
20
|
+
const $ = _c(31);
|
|
21
|
+
const {
|
|
22
|
+
html,
|
|
23
|
+
title,
|
|
24
|
+
height,
|
|
25
|
+
javaScriptEnabled: t1,
|
|
26
|
+
onOpenLink,
|
|
27
|
+
onContentHeight,
|
|
28
|
+
hostMessage,
|
|
29
|
+
testID
|
|
30
|
+
} = t0;
|
|
31
|
+
const javaScriptEnabled = t1 === undefined ? true : t1;
|
|
32
|
+
const ref = useRef(null);
|
|
33
|
+
const [loaded, setLoaded] = useState(false);
|
|
34
|
+
let t2;
|
|
35
|
+
let t3;
|
|
36
|
+
if ($[0] !== hostMessage || $[1] !== loaded) {
|
|
37
|
+
t2 = () => {
|
|
38
|
+
if (loaded && hostMessage) {
|
|
39
|
+
ref.current?.injectJavaScript(htmlViewPostScript(hostMessage));
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
t3 = [loaded, hostMessage];
|
|
43
|
+
$[0] = hostMessage;
|
|
44
|
+
$[1] = loaded;
|
|
45
|
+
$[2] = t2;
|
|
46
|
+
$[3] = t3;
|
|
47
|
+
} else {
|
|
48
|
+
t2 = $[2];
|
|
49
|
+
t3 = $[3];
|
|
50
|
+
}
|
|
51
|
+
useEffect(t2, t3);
|
|
52
|
+
let t4;
|
|
53
|
+
if ($[4] !== onOpenLink) {
|
|
54
|
+
t4 = url => {
|
|
55
|
+
if (htmlViewNavigation(url, true) === "open") {
|
|
56
|
+
onOpenLink(url);
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
$[4] = onOpenLink;
|
|
60
|
+
$[5] = t4;
|
|
61
|
+
} else {
|
|
62
|
+
t4 = $[5];
|
|
63
|
+
}
|
|
64
|
+
const openIfWeb = t4;
|
|
65
|
+
let t5;
|
|
66
|
+
if ($[6] !== height) {
|
|
67
|
+
t5 = {
|
|
68
|
+
height
|
|
69
|
+
};
|
|
70
|
+
$[6] = height;
|
|
71
|
+
$[7] = t5;
|
|
72
|
+
} else {
|
|
73
|
+
t5 = $[7];
|
|
74
|
+
}
|
|
75
|
+
let t6;
|
|
76
|
+
if ($[8] !== html) {
|
|
77
|
+
t6 = {
|
|
78
|
+
html
|
|
79
|
+
};
|
|
80
|
+
$[8] = html;
|
|
81
|
+
$[9] = t6;
|
|
82
|
+
} else {
|
|
83
|
+
t6 = $[9];
|
|
84
|
+
}
|
|
85
|
+
let t7;
|
|
86
|
+
if ($[10] === Symbol.for("react.memo_cache_sentinel")) {
|
|
87
|
+
t7 = ["*"];
|
|
88
|
+
$[10] = t7;
|
|
89
|
+
} else {
|
|
90
|
+
t7 = $[10];
|
|
91
|
+
}
|
|
92
|
+
const t8 = javaScriptEnabled ? HTML_VIEW_HEIGHT_SCRIPT : undefined;
|
|
93
|
+
let t9;
|
|
94
|
+
if ($[11] !== onContentHeight) {
|
|
95
|
+
t9 = event => {
|
|
96
|
+
const reported = parseHtmlViewHeight(event.nativeEvent.data);
|
|
97
|
+
if (reported !== null) {
|
|
98
|
+
onContentHeight?.(reported);
|
|
99
|
+
}
|
|
100
|
+
};
|
|
101
|
+
$[11] = onContentHeight;
|
|
102
|
+
$[12] = t9;
|
|
103
|
+
} else {
|
|
104
|
+
t9 = $[12];
|
|
105
|
+
}
|
|
106
|
+
let t10;
|
|
107
|
+
if ($[13] !== onOpenLink) {
|
|
108
|
+
t10 = request => {
|
|
109
|
+
const action = htmlViewNavigation(request.url, request.isTopFrame);
|
|
110
|
+
if (action === "open") {
|
|
111
|
+
onOpenLink(request.url);
|
|
112
|
+
}
|
|
113
|
+
return action === "load";
|
|
114
|
+
};
|
|
115
|
+
$[13] = onOpenLink;
|
|
116
|
+
$[14] = t10;
|
|
117
|
+
} else {
|
|
118
|
+
t10 = $[14];
|
|
119
|
+
}
|
|
120
|
+
let t11;
|
|
121
|
+
if ($[15] !== openIfWeb) {
|
|
122
|
+
t11 = event_0 => openIfWeb(event_0.nativeEvent.targetUrl);
|
|
123
|
+
$[15] = openIfWeb;
|
|
124
|
+
$[16] = t11;
|
|
125
|
+
} else {
|
|
126
|
+
t11 = $[16];
|
|
127
|
+
}
|
|
128
|
+
let t12;
|
|
129
|
+
if ($[17] === Symbol.for("react.memo_cache_sentinel")) {
|
|
130
|
+
t12 = () => setLoaded(true);
|
|
131
|
+
$[17] = t12;
|
|
132
|
+
} else {
|
|
133
|
+
t12 = $[17];
|
|
134
|
+
}
|
|
135
|
+
let t13;
|
|
136
|
+
if ($[18] === Symbol.for("react.memo_cache_sentinel")) {
|
|
137
|
+
t13 = {
|
|
138
|
+
backgroundColor: "transparent"
|
|
139
|
+
};
|
|
140
|
+
$[18] = t13;
|
|
141
|
+
} else {
|
|
142
|
+
t13 = $[18];
|
|
143
|
+
}
|
|
144
|
+
let t14;
|
|
145
|
+
if ($[19] !== javaScriptEnabled || $[20] !== t10 || $[21] !== t11 || $[22] !== t6 || $[23] !== t8 || $[24] !== t9 || $[25] !== title) {
|
|
146
|
+
t14 = <WebView ref={ref} source={t6} accessibilityLabel={title} originWhitelist={t7} javaScriptEnabled={javaScriptEnabled} injectedJavaScriptBeforeContentLoaded={t8} onMessage={t9} onShouldStartLoadWithRequest={t10} setSupportMultipleWindows={true} onOpenWindow={t11} onLoadEnd={t12} incognito={true} domStorageEnabled={false} thirdPartyCookiesEnabled={false} sharedCookiesEnabled={false} allowFileAccess={false} allowFileAccessFromFileURLs={false} allowUniversalAccessFromFileURLs={false} mixedContentMode="never" mediaPlaybackRequiresUserAction={true} nestedScrollEnabled={true} style={t13} />;
|
|
147
|
+
$[19] = javaScriptEnabled;
|
|
148
|
+
$[20] = t10;
|
|
149
|
+
$[21] = t11;
|
|
150
|
+
$[22] = t6;
|
|
151
|
+
$[23] = t8;
|
|
152
|
+
$[24] = t9;
|
|
153
|
+
$[25] = title;
|
|
154
|
+
$[26] = t14;
|
|
155
|
+
} else {
|
|
156
|
+
t14 = $[26];
|
|
157
|
+
}
|
|
158
|
+
let t15;
|
|
159
|
+
if ($[27] !== t14 || $[28] !== t5 || $[29] !== testID) {
|
|
160
|
+
t15 = <View testID={testID} style={t5}>{t14}</View>;
|
|
161
|
+
$[27] = t14;
|
|
162
|
+
$[28] = t5;
|
|
163
|
+
$[29] = testID;
|
|
164
|
+
$[30] = t15;
|
|
165
|
+
} else {
|
|
166
|
+
t15 = $[30];
|
|
167
|
+
}
|
|
168
|
+
return t15;
|
|
169
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { c as _c } from "react/compiler-runtime";
|
|
2
|
+
import { View } from "react-native";
|
|
3
|
+
/**
|
|
4
|
+
* `HtmlView` on web (`react-native-webview` has no web build): the page in a
|
|
5
|
+
* sandboxed `srcdoc` iframe at `height`, scrolling inside. Scripts, forms and
|
|
6
|
+
* popups only, with no `allow-same-origin`. It does not report a height or
|
|
7
|
+
* deliver `hostMessage`; the native view does.
|
|
8
|
+
*/
|
|
9
|
+
export function HtmlView(t0) {
|
|
10
|
+
const $ = _c(11);
|
|
11
|
+
const {
|
|
12
|
+
html,
|
|
13
|
+
title,
|
|
14
|
+
height,
|
|
15
|
+
javaScriptEnabled: t1,
|
|
16
|
+
testID
|
|
17
|
+
} = t0;
|
|
18
|
+
const javaScriptEnabled = t1 === undefined ? true : t1;
|
|
19
|
+
let t2;
|
|
20
|
+
if ($[0] !== height) {
|
|
21
|
+
t2 = {
|
|
22
|
+
height
|
|
23
|
+
};
|
|
24
|
+
$[0] = height;
|
|
25
|
+
$[1] = t2;
|
|
26
|
+
} else {
|
|
27
|
+
t2 = $[1];
|
|
28
|
+
}
|
|
29
|
+
const t3 = javaScriptEnabled ? "allow-scripts allow-forms allow-popups" : "";
|
|
30
|
+
let t4;
|
|
31
|
+
if ($[2] === Symbol.for("react.memo_cache_sentinel")) {
|
|
32
|
+
t4 = {
|
|
33
|
+
border: 0,
|
|
34
|
+
width: "100%",
|
|
35
|
+
height: "100%",
|
|
36
|
+
background: "transparent"
|
|
37
|
+
};
|
|
38
|
+
$[2] = t4;
|
|
39
|
+
} else {
|
|
40
|
+
t4 = $[2];
|
|
41
|
+
}
|
|
42
|
+
let t5;
|
|
43
|
+
if ($[3] !== html || $[4] !== t3 || $[5] !== title) {
|
|
44
|
+
t5 = <iframe title={title} srcDoc={html} sandbox={t3} style={t4} />;
|
|
45
|
+
$[3] = html;
|
|
46
|
+
$[4] = t3;
|
|
47
|
+
$[5] = title;
|
|
48
|
+
$[6] = t5;
|
|
49
|
+
} else {
|
|
50
|
+
t5 = $[6];
|
|
51
|
+
}
|
|
52
|
+
let t6;
|
|
53
|
+
if ($[7] !== t2 || $[8] !== t5 || $[9] !== testID) {
|
|
54
|
+
t6 = <View testID={testID} style={t2}>{t5}</View>;
|
|
55
|
+
$[7] = t2;
|
|
56
|
+
$[8] = t5;
|
|
57
|
+
$[9] = testID;
|
|
58
|
+
$[10] = t6;
|
|
59
|
+
} else {
|
|
60
|
+
t6 = $[10];
|
|
61
|
+
}
|
|
62
|
+
return t6;
|
|
63
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The pure half of `HtmlView`: which navigations the page may make, and the
|
|
3
|
+
* script that reports the page's height to the app.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
/** What `HtmlView` does with a navigation: let it load, hand it to `onOpenLink`, or drop it. */
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* The page never leaves its own document. Its first load (`about:`) and its
|
|
10
|
+
* frames load; a top-level http(s) link goes to `onOpenLink` (the system
|
|
11
|
+
* browser), as the web's sandboxed frame opens links in a new tab; any other
|
|
12
|
+
* scheme (`javascript:`, `intent:`, `file:`, `data:`) is dropped.
|
|
13
|
+
*/
|
|
14
|
+
export function htmlViewNavigation(url, isTopFrame) {
|
|
15
|
+
if (!isTopFrame) return "load";
|
|
16
|
+
if (url.startsWith("about:")) return "load";
|
|
17
|
+
return /^https?:\/\//i.test(url) ? "open" : "block";
|
|
18
|
+
}
|
|
19
|
+
const HEIGHT_PREFIX = "native-ui:height:";
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Runs in the page before its own scripts. It posts the document's height
|
|
23
|
+
* (`native-ui:height:<px>`) whenever it changes: the full scroll height when
|
|
24
|
+
* the content is taller than the view, else the content's own height, so the
|
|
25
|
+
* view can both grow and shrink to fit.
|
|
26
|
+
*/
|
|
27
|
+
export const HTML_VIEW_HEIGHT_SCRIPT = `(function(){var h,o;function z(){var r=document.documentElement,b=window.ReactNativeWebView;if(!r||!b)return;var v=Math.ceil(r.scrollHeight>r.clientHeight?r.scrollHeight:r.getBoundingClientRect().height);if(v===h)return;h=v;b.postMessage(${JSON.stringify(HEIGHT_PREFIX)}+v)}if(window.ResizeObserver){o=new ResizeObserver(z);o.observe(document.documentElement)}document.addEventListener("DOMContentLoaded",function(){if(o&&document.body)o.observe(document.body);z()});window.addEventListener("load",z)})();true;`;
|
|
28
|
+
|
|
29
|
+
/** The height in a message from `HTML_VIEW_HEIGHT_SCRIPT`; `null` for any other message. */
|
|
30
|
+
export function parseHtmlViewHeight(data) {
|
|
31
|
+
if (!data.startsWith(HEIGHT_PREFIX)) return null;
|
|
32
|
+
const height = Number(data.slice(HEIGHT_PREFIX.length));
|
|
33
|
+
return Number.isFinite(height) && height > 0 ? height : null;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Script that delivers `message` (a JSON string) to the page as a `message`
|
|
38
|
+
* event from its own window, as a host frame's `postMessage` would. In a
|
|
39
|
+
* WebView the page is the top window, so `event.source === window.parent`.
|
|
40
|
+
*/
|
|
41
|
+
export function htmlViewPostScript(message) {
|
|
42
|
+
return `window.postMessage(JSON.parse(${JSON.stringify(message)}),"*");true;`;
|
|
43
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vvedantb/native-ui",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.18.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"description": "Shared React Native / Expo UI primitives. Floating surfaces, forms, overlays, toasts, settings chrome, tab bar, AI chat parts, the family app marks, a NativeWind preset, the Expo web root and Clerk + Convex auth screens.",
|
|
6
6
|
"type": "module",
|
|
@@ -16,123 +16,153 @@
|
|
|
16
16
|
"exports": {
|
|
17
17
|
".": {
|
|
18
18
|
"types": "./src/index.ts",
|
|
19
|
-
"
|
|
19
|
+
"source": "./src/index.ts",
|
|
20
|
+
"default": "./dist/index.js"
|
|
20
21
|
},
|
|
21
22
|
"./tab-bar": {
|
|
22
23
|
"types": "./src/entries/tab-bar.ts",
|
|
23
|
-
"
|
|
24
|
+
"source": "./src/entries/tab-bar.ts",
|
|
25
|
+
"default": "./dist/entries/tab-bar.js"
|
|
24
26
|
},
|
|
25
27
|
"./brand": {
|
|
26
28
|
"types": "./src/entries/brand.ts",
|
|
27
|
-
"
|
|
29
|
+
"source": "./src/entries/brand.ts",
|
|
30
|
+
"default": "./dist/entries/brand.js"
|
|
28
31
|
},
|
|
29
32
|
"./button": {
|
|
30
33
|
"types": "./src/entries/button.ts",
|
|
31
|
-
"
|
|
34
|
+
"source": "./src/entries/button.ts",
|
|
35
|
+
"default": "./dist/entries/button.js"
|
|
32
36
|
},
|
|
33
37
|
"./primitives": {
|
|
34
38
|
"types": "./src/entries/primitives.ts",
|
|
35
|
-
"
|
|
39
|
+
"source": "./src/entries/primitives.ts",
|
|
40
|
+
"default": "./dist/entries/primitives.js"
|
|
36
41
|
},
|
|
37
42
|
"./search-input": {
|
|
38
43
|
"types": "./src/entries/search-input.ts",
|
|
39
|
-
"
|
|
44
|
+
"source": "./src/entries/search-input.ts",
|
|
45
|
+
"default": "./dist/entries/search-input.js"
|
|
40
46
|
},
|
|
41
47
|
"./password-input": {
|
|
42
48
|
"types": "./src/entries/password-input.ts",
|
|
43
|
-
"
|
|
49
|
+
"source": "./src/entries/password-input.ts",
|
|
50
|
+
"default": "./dist/entries/password-input.js"
|
|
44
51
|
},
|
|
45
52
|
"./page-title": {
|
|
46
53
|
"types": "./src/entries/page-title.ts",
|
|
47
|
-
"
|
|
54
|
+
"source": "./src/entries/page-title.ts",
|
|
55
|
+
"default": "./dist/entries/page-title.js"
|
|
48
56
|
},
|
|
49
57
|
"./toast": {
|
|
50
58
|
"types": "./src/entries/toast.ts",
|
|
51
|
-
"
|
|
59
|
+
"source": "./src/entries/toast.ts",
|
|
60
|
+
"default": "./dist/entries/toast.js"
|
|
52
61
|
},
|
|
53
62
|
"./theme": {
|
|
54
63
|
"types": "./src/entries/theme.ts",
|
|
55
|
-
"
|
|
64
|
+
"source": "./src/entries/theme.ts",
|
|
65
|
+
"default": "./dist/entries/theme.js"
|
|
56
66
|
},
|
|
57
67
|
"./floating": {
|
|
58
68
|
"types": "./src/entries/floating.ts",
|
|
59
|
-
"
|
|
69
|
+
"source": "./src/entries/floating.ts",
|
|
70
|
+
"default": "./dist/entries/floating.js"
|
|
60
71
|
},
|
|
61
72
|
"./layout": {
|
|
62
73
|
"types": "./src/entries/layout.ts",
|
|
63
|
-
"
|
|
74
|
+
"source": "./src/entries/layout.ts",
|
|
75
|
+
"default": "./dist/entries/layout.js"
|
|
64
76
|
},
|
|
65
77
|
"./marketing": {
|
|
66
78
|
"types": "./src/entries/marketing.ts",
|
|
67
|
-
"
|
|
79
|
+
"source": "./src/entries/marketing.ts",
|
|
80
|
+
"default": "./dist/entries/marketing.js"
|
|
68
81
|
},
|
|
69
82
|
"./ambient": {
|
|
70
83
|
"types": "./src/entries/ambient.ts",
|
|
71
|
-
"
|
|
84
|
+
"source": "./src/entries/ambient.ts",
|
|
85
|
+
"default": "./dist/entries/ambient.js"
|
|
72
86
|
},
|
|
73
87
|
"./bottom-sheet": {
|
|
74
88
|
"types": "./src/entries/bottom-sheet.ts",
|
|
75
|
-
"
|
|
89
|
+
"source": "./src/entries/bottom-sheet.ts",
|
|
90
|
+
"default": "./dist/entries/bottom-sheet.js"
|
|
76
91
|
},
|
|
77
92
|
"./gesture-handler": {
|
|
78
93
|
"types": "./src/entries/gesture-handler.ts",
|
|
79
|
-
"
|
|
94
|
+
"source": "./src/entries/gesture-handler.ts",
|
|
95
|
+
"default": "./dist/entries/gesture-handler.js"
|
|
80
96
|
},
|
|
81
97
|
"./keyboard-controller": {
|
|
82
98
|
"types": "./src/entries/keyboard-controller.ts",
|
|
83
|
-
"
|
|
99
|
+
"source": "./src/entries/keyboard-controller.ts",
|
|
100
|
+
"default": "./dist/entries/keyboard-controller.js"
|
|
84
101
|
},
|
|
85
102
|
"./video": {
|
|
86
103
|
"types": "./src/entries/video.ts",
|
|
87
|
-
"
|
|
104
|
+
"source": "./src/entries/video.ts",
|
|
105
|
+
"default": "./dist/entries/video.js"
|
|
88
106
|
},
|
|
89
107
|
"./webview": {
|
|
90
108
|
"types": "./src/entries/webview.ts",
|
|
91
|
-
"
|
|
109
|
+
"source": "./src/entries/webview.ts",
|
|
110
|
+
"default": "./dist/entries/webview.js"
|
|
92
111
|
},
|
|
93
112
|
"./date-time": {
|
|
94
113
|
"types": "./src/entries/date-time.ts",
|
|
95
|
-
"
|
|
114
|
+
"source": "./src/entries/date-time.ts",
|
|
115
|
+
"default": "./dist/entries/date-time.js"
|
|
96
116
|
},
|
|
97
117
|
"./ai": {
|
|
98
118
|
"types": "./src/entries/ai.ts",
|
|
99
|
-
"
|
|
119
|
+
"source": "./src/entries/ai.ts",
|
|
120
|
+
"default": "./dist/entries/ai.js"
|
|
100
121
|
},
|
|
101
122
|
"./gallery": {
|
|
102
123
|
"types": "./src/examples/ParityGallery.tsx",
|
|
103
|
-
"
|
|
124
|
+
"source": "./src/examples/ParityGallery.tsx",
|
|
125
|
+
"default": "./dist/examples/ParityGallery.jsx"
|
|
104
126
|
},
|
|
105
127
|
"./ai-gallery": {
|
|
106
128
|
"types": "./src/examples/AiChatGallery.tsx",
|
|
107
|
-
"
|
|
129
|
+
"source": "./src/examples/AiChatGallery.tsx",
|
|
130
|
+
"default": "./dist/examples/AiChatGallery.jsx"
|
|
108
131
|
},
|
|
109
132
|
"./blur": {
|
|
110
133
|
"types": "./src/blur.ts",
|
|
111
|
-
"
|
|
134
|
+
"source": "./src/blur.ts",
|
|
135
|
+
"default": "./dist/blur.js"
|
|
112
136
|
},
|
|
113
137
|
"./haptics": {
|
|
114
138
|
"types": "./src/haptics.ts",
|
|
115
|
-
"
|
|
139
|
+
"source": "./src/haptics.ts",
|
|
140
|
+
"default": "./dist/haptics.js"
|
|
116
141
|
},
|
|
117
142
|
"./push": {
|
|
118
143
|
"types": "./src/push.ts",
|
|
119
|
-
"
|
|
144
|
+
"source": "./src/push.ts",
|
|
145
|
+
"default": "./dist/push.js"
|
|
120
146
|
},
|
|
121
147
|
"./auth": {
|
|
122
148
|
"types": "./src/entries/auth.ts",
|
|
123
|
-
"
|
|
149
|
+
"source": "./src/entries/auth.ts",
|
|
150
|
+
"default": "./dist/entries/auth.js"
|
|
124
151
|
},
|
|
125
152
|
"./markdown": {
|
|
126
153
|
"types": "./src/entries/markdown.ts",
|
|
127
|
-
"
|
|
154
|
+
"source": "./src/entries/markdown.ts",
|
|
155
|
+
"default": "./dist/entries/markdown.js"
|
|
128
156
|
},
|
|
129
157
|
"./expo-router": {
|
|
130
158
|
"types": "./src/entries/expo-router.ts",
|
|
131
|
-
"
|
|
159
|
+
"source": "./src/entries/expo-router.ts",
|
|
160
|
+
"default": "./dist/entries/expo-router.js"
|
|
132
161
|
},
|
|
133
162
|
"./expo-web-root": {
|
|
134
163
|
"types": "./src/entries/expo-web-root.ts",
|
|
135
|
-
"
|
|
164
|
+
"source": "./src/entries/expo-web-root.ts",
|
|
165
|
+
"default": "./dist/entries/expo-web-root.js"
|
|
136
166
|
},
|
|
137
167
|
"./tailwind-preset": {
|
|
138
168
|
"types": "./src/tailwind-preset.d.cts",
|
|
@@ -143,6 +173,7 @@
|
|
|
143
173
|
},
|
|
144
174
|
"types": "./src/index.ts",
|
|
145
175
|
"files": [
|
|
176
|
+
"dist",
|
|
146
177
|
"src",
|
|
147
178
|
"LICENSE"
|
|
148
179
|
],
|
|
@@ -251,16 +282,22 @@
|
|
|
251
282
|
}
|
|
252
283
|
},
|
|
253
284
|
"devDependencies": {
|
|
285
|
+
"@babel/core": "^7.29.0",
|
|
286
|
+
"@babel/preset-typescript": "^7.28.0",
|
|
254
287
|
"@clerk/clerk-expo": "2.20.2",
|
|
255
288
|
"@types/react": "^19.1.0",
|
|
289
|
+
"babel-plugin-react-compiler": "1.0.0",
|
|
256
290
|
"react": "^19.1.0",
|
|
257
291
|
"typescript": "^5.9.0",
|
|
258
292
|
"vitest": "^3.2.0"
|
|
259
293
|
},
|
|
260
294
|
"scripts": {
|
|
261
|
-
"build": "node -
|
|
295
|
+
"build": "node scripts/build-dist.mjs && node scripts/check-exports.mjs",
|
|
296
|
+
"check:exports": "node scripts/check-exports.mjs",
|
|
297
|
+
"check:hermes": "node scripts/check-hermes-compat.mjs",
|
|
262
298
|
"test": "vitest run",
|
|
263
299
|
"typecheck": "tsc -p tsconfig.typecheck.json && pnpm run typecheck:consumer",
|
|
264
|
-
"typecheck:consumer": "tsc -p tsconfig.consumer.json"
|
|
300
|
+
"typecheck:consumer": "tsc -p tsconfig.consumer.json",
|
|
301
|
+
"build:baseline": "node scripts/build-dist.mjs --update"
|
|
265
302
|
}
|
|
266
303
|
}
|
package/src/DropdownMenu.tsx
CHANGED
|
@@ -319,9 +319,12 @@ function MenuRow({
|
|
|
319
319
|
onSelect?.();
|
|
320
320
|
if (closeOnSelect) setOpen(false);
|
|
321
321
|
}}
|
|
322
|
-
//
|
|
323
|
-
//
|
|
324
|
-
style
|
|
322
|
+
// The row layout is a plain style object. NativeWind's `Pressable`
|
|
323
|
+
// interop rebuilds `style` from the inline value on native and drops a
|
|
324
|
+
// function `style` entirely, so a layout kept in one stacked the icon
|
|
325
|
+
// above the label on Android (React Native's default column). The press
|
|
326
|
+
// highlight comes from the `pressed` render state as a background layer.
|
|
327
|
+
style={{
|
|
325
328
|
flexDirection: "row",
|
|
326
329
|
alignItems: "center",
|
|
327
330
|
minHeight: metrics.minHeight,
|
|
@@ -330,21 +333,30 @@ function MenuRow({
|
|
|
330
333
|
paddingRight: DROPDOWN_MENU.itemPaddingX,
|
|
331
334
|
paddingVertical: DROPDOWN_MENU.itemPaddingY,
|
|
332
335
|
borderRadius: DROPDOWN_MENU.itemRadius,
|
|
333
|
-
backgroundColor: pressed && !disabled ? palette.default[scheme] : "transparent",
|
|
334
336
|
opacity: disabled ? 0.5 : 1,
|
|
335
|
-
}
|
|
337
|
+
}}
|
|
336
338
|
>
|
|
337
|
-
{
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
339
|
+
{({ pressed }) => (
|
|
340
|
+
<>
|
|
341
|
+
{pressed && !disabled ? (
|
|
342
|
+
<View
|
|
343
|
+
pointerEvents="none"
|
|
344
|
+
style={[StyleSheet.absoluteFill, { borderRadius: DROPDOWN_MENU.itemRadius, backgroundColor: palette.default[scheme] }]}
|
|
345
|
+
/>
|
|
346
|
+
) : null}
|
|
347
|
+
{leading}
|
|
348
|
+
{/* A caller `className` lands here, off the Pressable (see the style note above). */}
|
|
349
|
+
<View className={cn("min-w-0 flex-1 flex-row items-center", className)}>
|
|
350
|
+
{typeof children === "string" ? (
|
|
351
|
+
<Text className="flex-1 font-instrument-sans" style={[metrics.text, { color }]}>
|
|
352
|
+
{children}
|
|
353
|
+
</Text>
|
|
354
|
+
) : (
|
|
355
|
+
children
|
|
356
|
+
)}
|
|
357
|
+
</View>
|
|
358
|
+
</>
|
|
359
|
+
)}
|
|
348
360
|
</Pressable>
|
|
349
361
|
);
|
|
350
362
|
}
|