@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
package/dist/swipeRow.js
ADDED
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The rules of a swipeable list row (`SwipeableRow`), as plain numbers, so
|
|
3
|
+
* they stay testable apart from the gesture. The offset is in points:
|
|
4
|
+
* positive when the row moves right (it reveals the leading actions),
|
|
5
|
+
* negative when it moves left (the trailing actions). Velocities are in
|
|
6
|
+
* points per second, the Gesture Handler unit. Each rule is a worklet, so the
|
|
7
|
+
* drag runs it on the UI thread.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
/** One action a swipe reveals behind a row. */
|
|
11
|
+
|
|
12
|
+
/** The revealed widths of each side (0 for a side with no actions) and the row's width. */
|
|
13
|
+
|
|
14
|
+
/** The width of one revealed action button. */
|
|
15
|
+
export const SWIPE_ACTION_WIDTH = 72;
|
|
16
|
+
|
|
17
|
+
/** Sideways travel (pt) before the drag takes the row: a tap, or a scroll, never moves it. */
|
|
18
|
+
export const SWIPE_ACTIVE_OFFSET_X = 12;
|
|
19
|
+
|
|
20
|
+
/** Vertical travel (pt) that hands the touch to the list's scroll first: a small diagonal drag scrolls. */
|
|
21
|
+
export const SWIPE_FAIL_OFFSET_Y = 8;
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* The pan's sideways thresholds. A row takes a sideways drag past
|
|
25
|
+
* `SWIPE_ACTIVE_OFFSET_X` either way. Inside a `Pager` it takes only the
|
|
26
|
+
* directions it has actions for, and a drag the other way fails it at once,
|
|
27
|
+
* so the pager behind moves instead (a Sessions row swiped right).
|
|
28
|
+
*/
|
|
29
|
+
export function swipeRowActivation(sides, insidePager) {
|
|
30
|
+
if (!insidePager || sides.leading > 0 && sides.trailing > 0) {
|
|
31
|
+
return {
|
|
32
|
+
activeOffsetX: [-SWIPE_ACTIVE_OFFSET_X, SWIPE_ACTIVE_OFFSET_X]
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
// Left (negative) reveals the trailing actions; right the leading ones.
|
|
36
|
+
return sides.trailing > 0 ? {
|
|
37
|
+
activeOffsetX: -SWIPE_ACTIVE_OFFSET_X,
|
|
38
|
+
failOffsetX: SWIPE_ACTIVE_OFFSET_X
|
|
39
|
+
} : {
|
|
40
|
+
activeOffsetX: SWIPE_ACTIVE_OFFSET_X,
|
|
41
|
+
failOffsetX: -SWIPE_ACTIVE_OFFSET_X
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/** How far ahead (s) the release velocity carries the row when deciding where it settles. */
|
|
46
|
+
const PROJECTION_S = 0.2;
|
|
47
|
+
|
|
48
|
+
/** How far a row moves past its reach: less and less the further the finger goes. */
|
|
49
|
+
function rubberband(overshoot) {
|
|
50
|
+
"worklet";
|
|
51
|
+
|
|
52
|
+
const constant = 0.55;
|
|
53
|
+
return overshoot * SWIPE_ACTION_WIDTH * constant / (SWIPE_ACTION_WIDTH + constant * overshoot);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Where the row sits for a finger `raw` points from where the drag caught
|
|
58
|
+
* it. Toward a side with actions it follows 1:1, out to its own width; toward
|
|
59
|
+
* a side with none, and past its width, it meets growing resistance.
|
|
60
|
+
*/
|
|
61
|
+
export function swipeRowOffset(raw, sides) {
|
|
62
|
+
"worklet";
|
|
63
|
+
|
|
64
|
+
const reveal = raw >= 0 ? sides.leading : sides.trailing;
|
|
65
|
+
const reach = reveal > 0 ? sides.width : 0;
|
|
66
|
+
const distance = Math.abs(raw);
|
|
67
|
+
if (distance <= reach) return raw;
|
|
68
|
+
return Math.sign(raw) * (reach + rubberband(distance - reach));
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/** How far the row must travel for a full swipe to commit the first action: half the row, and always past the revealed buttons. */
|
|
72
|
+
export function swipeFullAt(reveal, width) {
|
|
73
|
+
"worklet";
|
|
74
|
+
|
|
75
|
+
return Math.max(reveal + SWIPE_ACTION_WIDTH, width / 2);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/** The side whose first action a release here would commit (the full swipe is armed), or `null`. */
|
|
79
|
+
export function swipeRowArmed(x, sides) {
|
|
80
|
+
"worklet";
|
|
81
|
+
|
|
82
|
+
const side = x >= 0 ? "leading" : "trailing";
|
|
83
|
+
const reveal = sides[side];
|
|
84
|
+
if (reveal === 0 || Math.abs(x) < swipeFullAt(reveal, sides.width)) return null;
|
|
85
|
+
return side;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Where a released row goes, from where it is (`x`) carried on by its speed
|
|
89
|
+
* (`vx`): past the full-swipe point, with its buttons already in view, it
|
|
90
|
+
* commits the first action; past half its buttons it opens; else it closes.
|
|
91
|
+
* A flick the other way closes it however far it was.
|
|
92
|
+
*/
|
|
93
|
+
export function swipeRowSettle(x, vx, sides) {
|
|
94
|
+
"worklet";
|
|
95
|
+
|
|
96
|
+
if (x === 0) return {
|
|
97
|
+
kind: "close"
|
|
98
|
+
};
|
|
99
|
+
const side = x > 0 ? "leading" : "trailing";
|
|
100
|
+
const reveal = sides[side];
|
|
101
|
+
if (reveal === 0) return {
|
|
102
|
+
kind: "close"
|
|
103
|
+
};
|
|
104
|
+
// The projected travel toward this side: negative after a flick back past rest.
|
|
105
|
+
const reach = Math.sign(x) * (x + vx * PROJECTION_S);
|
|
106
|
+
if (Math.abs(x) > reveal && reach >= swipeFullAt(reveal, sides.width)) return {
|
|
107
|
+
kind: "commit",
|
|
108
|
+
side
|
|
109
|
+
};
|
|
110
|
+
if (reach > reveal / 2) return {
|
|
111
|
+
kind: "open",
|
|
112
|
+
side
|
|
113
|
+
};
|
|
114
|
+
return {
|
|
115
|
+
kind: "close"
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/** A row that can be closed from outside: the open row closes when another opens, a list scrolls or a row is tapped. */
|
|
120
|
+
|
|
121
|
+
let openRow = null;
|
|
122
|
+
|
|
123
|
+
/** Marks `row` as the open row, closing the one open before: one row is open at a time. */
|
|
124
|
+
export function markSwipeRowOpen(row) {
|
|
125
|
+
if (openRow && openRow !== row) openRow.close();
|
|
126
|
+
openRow = row;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/** Forgets `row` once it has closed itself. */
|
|
130
|
+
export function markSwipeRowClosed(row) {
|
|
131
|
+
if (openRow === row) openRow = null;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/** Whether a row is open. A touch on any row then only closes it. */
|
|
135
|
+
export function isSwipeRowOpen() {
|
|
136
|
+
return openRow !== null;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/** Closes the open row, if any. Pass it to a list's `onScrollBeginDrag`, so a scroll closes the row. */
|
|
140
|
+
export function closeSwipeRows() {
|
|
141
|
+
const row = openRow;
|
|
142
|
+
openRow = null;
|
|
143
|
+
row?.close();
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* The row's actions for VoiceOver and TalkBack, which cannot swipe a row:
|
|
148
|
+
* spread on the row's main pressable, so the actions rotor (iOS) or the
|
|
149
|
+
* actions menu (Android) offers each one, with its label.
|
|
150
|
+
*/
|
|
151
|
+
export function swipeActionsAccessibility(actions) {
|
|
152
|
+
return {
|
|
153
|
+
accessibilityActions: actions.map(action => ({
|
|
154
|
+
name: action.key,
|
|
155
|
+
label: action.label
|
|
156
|
+
})),
|
|
157
|
+
onAccessibilityAction: event => {
|
|
158
|
+
void actions.find(action => action.key === event.nativeEvent.actionName)?.onPress();
|
|
159
|
+
}
|
|
160
|
+
};
|
|
161
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
// Which routes `FloatingTabBar` draws. No React Native runtime import, so the
|
|
2
|
+
// tests can load this file.
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* The fields `FloatingTabBar` reads from a route's options (React
|
|
6
|
+
* Navigation's `BottomTabNavigationOptions`, and Expo Router's `href`).
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
/** The `display` a style resolves to: in an array the last one set wins, as in `StyleSheet.flatten`. */
|
|
10
|
+
function displayOf(style) {
|
|
11
|
+
if (Array.isArray(style)) {
|
|
12
|
+
let display;
|
|
13
|
+
for (const item of style) {
|
|
14
|
+
const value = displayOf(item);
|
|
15
|
+
if (value !== undefined) display = value;
|
|
16
|
+
}
|
|
17
|
+
return display;
|
|
18
|
+
}
|
|
19
|
+
return style && typeof style === "object" ? style.display : undefined;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Whether `FloatingTabBar` draws a tab for a route with these options. A route
|
|
24
|
+
* without a descriptor has none. Apps hide a tab with Expo Router's
|
|
25
|
+
* `options={{ href: null }}`. Expo Router's `Tabs` can drop `href` and pass
|
|
26
|
+
* `tabBarItemStyle: { display: "none" }` in its place, so both hide the tab.
|
|
27
|
+
* Hiding is display-only: `state.index` still counts every route.
|
|
28
|
+
*/
|
|
29
|
+
export function isTabBarRouteVisible(options) {
|
|
30
|
+
return options !== undefined && options.href !== null && displayOf(options.tabBarItemStyle) !== "none";
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Whether `FloatingTabBar` hides itself: the focused route's `tabBarStyle`
|
|
35
|
+
* resolves to `display: "none"`, the React Navigation way to hide the bar
|
|
36
|
+
* from a screen (`navigation.setOptions`, or Expo Router's `<Tabs.Screen
|
|
37
|
+
* options>` inside the screen).
|
|
38
|
+
*/
|
|
39
|
+
export function isTabBarHidden(options) {
|
|
40
|
+
return displayOf(options?.tabBarStyle) === "none";
|
|
41
|
+
}
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import { c as _c } from "react/compiler-runtime";
|
|
2
|
+
import { cssInterop } from "nativewind";
|
|
3
|
+
import { useState } from "react";
|
|
4
|
+
import Animated, { interpolate, interpolateColor, useAnimatedStyle } from "react-native-reanimated";
|
|
5
|
+
|
|
6
|
+
// The tab labels are `Animated.Text`s (their colour follows `progress`).
|
|
7
|
+
// NativeWind maps `className` only for components it knows, so it is told
|
|
8
|
+
// about this one, or the labels lose their font and size classes.
|
|
9
|
+
cssInterop(Animated.Text, {
|
|
10
|
+
className: "style"
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
/** A tab's box in its row, from its layout. */
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* The selected fill of a tab row linked to a `Pager`'s `progress` (`PillTabs`,
|
|
17
|
+
* `TabsList`): one indicator that slides with the pages between the measured
|
|
18
|
+
* tabs. The tabs sit on one line, so it moves on x and width only; its top
|
|
19
|
+
* and height are the first tab's. Until every tab has reported its layout,
|
|
20
|
+
* `measured` is false and each tab paints its own fill, so the first frame
|
|
21
|
+
* already shows the selection. `boxes` is every tab's box once all are
|
|
22
|
+
* measured (with or without `progress`), else empty.
|
|
23
|
+
*/
|
|
24
|
+
export function useTabIndicator(progress, count) {
|
|
25
|
+
const $ = _c(12);
|
|
26
|
+
let t0;
|
|
27
|
+
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
|
|
28
|
+
t0 = [];
|
|
29
|
+
$[0] = t0;
|
|
30
|
+
} else {
|
|
31
|
+
t0 = $[0];
|
|
32
|
+
}
|
|
33
|
+
const [layouts, setLayouts] = useState(t0);
|
|
34
|
+
let t1;
|
|
35
|
+
if ($[1] !== count || $[2] !== layouts) {
|
|
36
|
+
t1 = layouts.slice(0, count).filter(_temp);
|
|
37
|
+
$[1] = count;
|
|
38
|
+
$[2] = layouts;
|
|
39
|
+
$[3] = t1;
|
|
40
|
+
} else {
|
|
41
|
+
t1 = $[3];
|
|
42
|
+
}
|
|
43
|
+
const found = t1;
|
|
44
|
+
let t2;
|
|
45
|
+
if ($[4] !== count || $[5] !== found) {
|
|
46
|
+
t2 = found.length === count ? found : [];
|
|
47
|
+
$[4] = count;
|
|
48
|
+
$[5] = found;
|
|
49
|
+
$[6] = t2;
|
|
50
|
+
} else {
|
|
51
|
+
t2 = $[6];
|
|
52
|
+
}
|
|
53
|
+
const boxes = t2;
|
|
54
|
+
const measured = progress !== undefined && boxes.length > 0;
|
|
55
|
+
const style = useAnimatedStyle(() => {
|
|
56
|
+
const first = boxes[0];
|
|
57
|
+
if (!progress || !measured || !first) {
|
|
58
|
+
return {
|
|
59
|
+
opacity: 0
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
const pages = boxes.map(_temp2);
|
|
63
|
+
const at = pick => boxes.length === 1 ? pick(first) : interpolate(progress.get(), pages, boxes.map(pick), "clamp");
|
|
64
|
+
return {
|
|
65
|
+
opacity: 1,
|
|
66
|
+
top: first.y,
|
|
67
|
+
height: first.height,
|
|
68
|
+
width: at(_temp3),
|
|
69
|
+
transform: [{
|
|
70
|
+
translateX: at(_temp4)
|
|
71
|
+
}]
|
|
72
|
+
};
|
|
73
|
+
});
|
|
74
|
+
let t3;
|
|
75
|
+
if ($[7] === Symbol.for("react.memo_cache_sentinel")) {
|
|
76
|
+
t3 = index_0 => event => {
|
|
77
|
+
const box_2 = event.nativeEvent.layout;
|
|
78
|
+
setLayouts(current => {
|
|
79
|
+
const next = [...current];
|
|
80
|
+
next[index_0] = box_2;
|
|
81
|
+
return next;
|
|
82
|
+
});
|
|
83
|
+
};
|
|
84
|
+
$[7] = t3;
|
|
85
|
+
} else {
|
|
86
|
+
t3 = $[7];
|
|
87
|
+
}
|
|
88
|
+
const onLayout = t3;
|
|
89
|
+
let t4;
|
|
90
|
+
if ($[8] !== boxes || $[9] !== measured || $[10] !== style) {
|
|
91
|
+
t4 = {
|
|
92
|
+
measured,
|
|
93
|
+
style,
|
|
94
|
+
boxes,
|
|
95
|
+
onLayout
|
|
96
|
+
};
|
|
97
|
+
$[8] = boxes;
|
|
98
|
+
$[9] = measured;
|
|
99
|
+
$[10] = style;
|
|
100
|
+
$[11] = t4;
|
|
101
|
+
} else {
|
|
102
|
+
t4 = $[11];
|
|
103
|
+
}
|
|
104
|
+
return t4;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* A tab label's colour. With `progress` it blends from `muted` to `selected`
|
|
109
|
+
* as the pages reach tab `index`, so the label turns with the sliding fill
|
|
110
|
+
* under a swipe, not when the swipe settles. Without it, `fallback`.
|
|
111
|
+
*/
|
|
112
|
+
function _temp4(box_1) {
|
|
113
|
+
return box_1.x;
|
|
114
|
+
}
|
|
115
|
+
function _temp3(box_0) {
|
|
116
|
+
return box_0.width;
|
|
117
|
+
}
|
|
118
|
+
function _temp2(_, index) {
|
|
119
|
+
return index;
|
|
120
|
+
}
|
|
121
|
+
function _temp(box) {
|
|
122
|
+
return box !== undefined;
|
|
123
|
+
}
|
|
124
|
+
export function useTabLabelStyle(progress, index, colors, fallback) {
|
|
125
|
+
const {
|
|
126
|
+
selected,
|
|
127
|
+
muted
|
|
128
|
+
} = colors;
|
|
129
|
+
return useAnimatedStyle(() => {
|
|
130
|
+
if (!progress) {
|
|
131
|
+
return {
|
|
132
|
+
color: fallback
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
return {
|
|
136
|
+
color: interpolateColor(progress.get(), [index - 1, index, index + 1], [muted, selected, muted])
|
|
137
|
+
};
|
|
138
|
+
});
|
|
139
|
+
}
|
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@vvedantb/native-ui/tailwind-preset`: the NativeWind / Tailwind preset the
|
|
3
|
+
* Expo apps share. CommonJS, because `tailwind.config.js` `require`s it and
|
|
4
|
+
* Tailwind loads it outside Metro.
|
|
5
|
+
*
|
|
6
|
+
* const { nativeUiPreset, nativeUiContent } = require("@vvedantb/native-ui/tailwind-preset");
|
|
7
|
+
* module.exports = {
|
|
8
|
+
* content: ["./app/**\/*.{js,ts,tsx}", nativeUiContent()],
|
|
9
|
+
* presets: [nativeUiPreset()],
|
|
10
|
+
* };
|
|
11
|
+
*
|
|
12
|
+
* It nests `nativewind/preset`, so callers pass only this one. It sets
|
|
13
|
+
* `darkMode`, the `font-instrument-sans*` font classes (Instrument Sans unless
|
|
14
|
+
* `font` names other families), the colour keys native-ui
|
|
15
|
+
* classes use, `borderWidth.hairline` and, when asked, `borderRadius` from
|
|
16
|
+
* `--radius`.
|
|
17
|
+
* App colours, display fonts, keyframes and font-weight plugins stay in the
|
|
18
|
+
* app config.
|
|
19
|
+
*
|
|
20
|
+
* `color` maps a CSS variable name (without `--`) to a Tailwind colour, as the
|
|
21
|
+
* web `tokensPreset({ color })` of `@vvedantb/ui`. With `injectCssVariables`,
|
|
22
|
+
* the preset also writes those variables (light and dark) from `tokens.ts` and
|
|
23
|
+
* `palette.ts`, as space-separated RGB channels, and the default `color` is
|
|
24
|
+
* `rgbAlpha`.
|
|
25
|
+
*/
|
|
26
|
+
"use strict";
|
|
27
|
+
|
|
28
|
+
const fs = require("node:fs");
|
|
29
|
+
const path = require("node:path");
|
|
30
|
+
|
|
31
|
+
/** `var(--name)`. */
|
|
32
|
+
const cssVar = (name) => `var(--${name})`;
|
|
33
|
+
/** `hsl(var(--name))`, for variables that hold `h s% l%` channels. */
|
|
34
|
+
const hslVar = (name) => `hsl(var(--${name}))`;
|
|
35
|
+
/** `rgb(var(--name) / <alpha-value>)`, for variables that hold `r g b` channels. Keeps opacity modifiers. */
|
|
36
|
+
const rgbAlpha = (name) => `rgb(var(--${name}) / <alpha-value>)`;
|
|
37
|
+
|
|
38
|
+
/** The default families of the four font classes, as `fontFamily` in `typography.ts`. */
|
|
39
|
+
const INSTRUMENT_SANS = {
|
|
40
|
+
regular: "InstrumentSans_400Regular",
|
|
41
|
+
medium: "InstrumentSans_500Medium",
|
|
42
|
+
semibold: "InstrumentSans_600SemiBold",
|
|
43
|
+
bold: "InstrumentSans_700Bold",
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
/** The glob Tailwind scans for native-ui class names: this package's `src`, at its real path (pnpm symlinks resolve). */
|
|
47
|
+
function nativeUiContent() {
|
|
48
|
+
return path.join(__dirname, "**/*.{js,ts,tsx}").split(path.sep).join("/");
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Reads one `export const name = { … } as const;` object from a sibling
|
|
53
|
+
* `.ts` file. Plain object literals only, so no TypeScript loader is needed:
|
|
54
|
+
* `tokens.ts` and `palette.ts` stay the single source of the colours.
|
|
55
|
+
*/
|
|
56
|
+
function readConst(file, name) {
|
|
57
|
+
const source = fs.readFileSync(path.join(__dirname, file), "utf8");
|
|
58
|
+
const match = source.match(new RegExp(`export const ${name} = (\\{[\\s\\S]*?\\n\\}) as const;`));
|
|
59
|
+
if (!match) throw new Error(`@vvedantb/native-ui/tailwind-preset: no \`${name}\` object in ${file}`);
|
|
60
|
+
return new Function(`return (${match[1]});`)();
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
let cachedSchemeColors = null;
|
|
64
|
+
|
|
65
|
+
/** CSS variable name → `{ light, dark }` hex, from `tokens.ts` and `palette.ts`. */
|
|
66
|
+
function schemeColors() {
|
|
67
|
+
if (cachedSchemeColors) return cachedSchemeColors;
|
|
68
|
+
const tokens = readConst("tokens.ts", "tokens");
|
|
69
|
+
const palette = readConst("palette.ts", "palette");
|
|
70
|
+
const c = tokens.color;
|
|
71
|
+
cachedSchemeColors = {
|
|
72
|
+
background: c.background,
|
|
73
|
+
foreground: c.foreground,
|
|
74
|
+
border: c.border,
|
|
75
|
+
input: c.border,
|
|
76
|
+
ring: palette.primary,
|
|
77
|
+
separator: c.separator,
|
|
78
|
+
surface: c.surface,
|
|
79
|
+
"surface-foreground": c.foreground,
|
|
80
|
+
"surface-secondary": c.surfaceSecondary,
|
|
81
|
+
"surface-tertiary": palette.surfaceTertiary,
|
|
82
|
+
"surface-card": c.surfaceCard,
|
|
83
|
+
muted: c.muted,
|
|
84
|
+
"muted-foreground": c.muted,
|
|
85
|
+
primary: palette.primary,
|
|
86
|
+
"primary-foreground": palette.primaryForeground,
|
|
87
|
+
secondary: palette.default,
|
|
88
|
+
"secondary-foreground": palette.defaultForeground,
|
|
89
|
+
destructive: palette.danger,
|
|
90
|
+
"destructive-foreground": palette.dangerForeground,
|
|
91
|
+
accent: palette.primary,
|
|
92
|
+
"accent-foreground": palette.primaryForeground,
|
|
93
|
+
popover: palette.overlay,
|
|
94
|
+
"popover-foreground": palette.overlayForeground,
|
|
95
|
+
card: c.surfaceCard,
|
|
96
|
+
"card-foreground": c.foreground,
|
|
97
|
+
danger: palette.danger,
|
|
98
|
+
"danger-foreground": palette.dangerForeground,
|
|
99
|
+
success: palette.success,
|
|
100
|
+
"success-foreground": palette.successForeground,
|
|
101
|
+
warning: palette.warning,
|
|
102
|
+
"warning-foreground": palette.warningForeground,
|
|
103
|
+
default: palette.default,
|
|
104
|
+
"default-foreground": palette.defaultForeground,
|
|
105
|
+
overlay: palette.overlay,
|
|
106
|
+
"overlay-foreground": palette.overlayForeground,
|
|
107
|
+
field: c.surface,
|
|
108
|
+
"field-placeholder": palette.fieldPlaceholder,
|
|
109
|
+
};
|
|
110
|
+
return cachedSchemeColors;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/** `#rrggbb` as `r g b`. */
|
|
114
|
+
function channels(hex) {
|
|
115
|
+
const n = Number.parseInt(hex.slice(1, 7), 16);
|
|
116
|
+
return `${(n >> 16) & 255} ${(n >> 8) & 255} ${n & 255}`;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/** `--name: r g b` for every colour in one scheme. */
|
|
120
|
+
function cssVariables(scheme) {
|
|
121
|
+
return Object.fromEntries(
|
|
122
|
+
Object.entries(schemeColors()).map(([name, value]) => [`--${name}`, channels(value[scheme])]),
|
|
123
|
+
);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/** `--radius` from `tokens.radius.lg` (16), so `rounded-lg`, `-md` and `-sm` are 16, 14 and 12 as in `tokens.radius`. */
|
|
127
|
+
function radiusVariable() {
|
|
128
|
+
return { "--radius": `${readConst("tokens.ts", "tokens").radius.lg}px` };
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/** The Tailwind colour keys native-ui classes and the apps share. */
|
|
132
|
+
function themeColors(v) {
|
|
133
|
+
return {
|
|
134
|
+
background: v("background"),
|
|
135
|
+
foreground: v("foreground"),
|
|
136
|
+
border: v("border"),
|
|
137
|
+
input: v("input"),
|
|
138
|
+
ring: v("ring"),
|
|
139
|
+
separator: v("separator"),
|
|
140
|
+
surface: {
|
|
141
|
+
DEFAULT: v("surface"),
|
|
142
|
+
foreground: v("surface-foreground"),
|
|
143
|
+
secondary: v("surface-secondary"),
|
|
144
|
+
tertiary: v("surface-tertiary"),
|
|
145
|
+
card: v("surface-card"),
|
|
146
|
+
},
|
|
147
|
+
primary: { DEFAULT: v("primary"), foreground: v("primary-foreground") },
|
|
148
|
+
secondary: { DEFAULT: v("secondary"), foreground: v("secondary-foreground") },
|
|
149
|
+
destructive: { DEFAULT: v("destructive"), foreground: v("destructive-foreground") },
|
|
150
|
+
muted: { DEFAULT: v("muted"), foreground: v("muted-foreground") },
|
|
151
|
+
accent: { DEFAULT: v("accent"), foreground: v("accent-foreground") },
|
|
152
|
+
popover: { DEFAULT: v("popover"), foreground: v("popover-foreground") },
|
|
153
|
+
card: { DEFAULT: v("card"), foreground: v("card-foreground") },
|
|
154
|
+
danger: { DEFAULT: v("danger"), foreground: v("danger-foreground") },
|
|
155
|
+
success: { DEFAULT: v("success"), foreground: v("success-foreground") },
|
|
156
|
+
warning: { DEFAULT: v("warning"), foreground: v("warning-foreground") },
|
|
157
|
+
default: { DEFAULT: v("default"), foreground: v("default-foreground") },
|
|
158
|
+
overlay: { DEFAULT: v("overlay"), foreground: v("overlay-foreground") },
|
|
159
|
+
field: { DEFAULT: v("field"), placeholder: v("field-placeholder") },
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/** `nativewind/preset`, or none where NativeWind is not installed (this repository's tests). */
|
|
164
|
+
function nestedPresets() {
|
|
165
|
+
try {
|
|
166
|
+
return [require("nativewind/preset")];
|
|
167
|
+
} catch {
|
|
168
|
+
return [];
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/** `{ hairline: hairlineWidth() }` from `nativewind/theme`, or none without NativeWind. */
|
|
173
|
+
function hairlineBorder() {
|
|
174
|
+
try {
|
|
175
|
+
const { hairlineWidth } = require("nativewind/theme");
|
|
176
|
+
return typeof hairlineWidth === "function" ? { hairline: hairlineWidth() } : {};
|
|
177
|
+
} catch {
|
|
178
|
+
return {};
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/** A Tailwind plugin that writes the colour variables: `:root` (light) and the dark set for `darkMode`. */
|
|
183
|
+
function cssVariablesPlugin(darkMode) {
|
|
184
|
+
return function nativeUiCssVariables({ addBase }) {
|
|
185
|
+
const dark = cssVariables("dark");
|
|
186
|
+
addBase(
|
|
187
|
+
darkMode === "media"
|
|
188
|
+
? {
|
|
189
|
+
":root": { ...cssVariables("light"), ...radiusVariable() },
|
|
190
|
+
"@media (prefers-color-scheme: dark)": { ":root": dark },
|
|
191
|
+
}
|
|
192
|
+
: {
|
|
193
|
+
":root": { ...cssVariables("light"), ...radiusVariable() },
|
|
194
|
+
".dark:root, .dark": dark,
|
|
195
|
+
},
|
|
196
|
+
);
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
/**
|
|
201
|
+
* The preset. Options:
|
|
202
|
+
* - `darkMode`: `"class"` (default; `ThemeToggle` and `setColorScheme` need it) or `"media"`.
|
|
203
|
+
* - `color`: CSS variable name → colour value. Default `cssVar`, or `rgbAlpha` with `injectCssVariables`.
|
|
204
|
+
* - `injectCssVariables`: write the colour variables and `--radius` from `tokens.ts` and `palette.ts`. Default `false`.
|
|
205
|
+
* - `radiusVariable`: `rounded-lg`, `-md` and `-sm` from `var(--radius)`, as vibot and Velth. Default: on with
|
|
206
|
+
* `injectCssVariables`, else off, so an app without `--radius` keeps the Tailwind radii.
|
|
207
|
+
* - `font`: `{ regular, medium, semibold, bold }` family names for `sans` and the four `font-instrument-sans*`
|
|
208
|
+
* classes. Keys not given keep Instrument Sans. Pass the same names to `configureTheme({ font })`, which sets
|
|
209
|
+
* the JS styles; the app loads the font files.
|
|
210
|
+
*/
|
|
211
|
+
function nativeUiPreset(options = {}) {
|
|
212
|
+
const darkMode = options.darkMode === "media" ? "media" : "class";
|
|
213
|
+
const font = { ...INSTRUMENT_SANS };
|
|
214
|
+
for (const [key, value] of Object.entries(options.font || {})) if (value !== undefined) font[key] = value;
|
|
215
|
+
const inject = options.injectCssVariables === true;
|
|
216
|
+
const color = options.color || (inject ? rgbAlpha : cssVar);
|
|
217
|
+
const radius = options.radiusVariable ?? inject;
|
|
218
|
+
return {
|
|
219
|
+
darkMode,
|
|
220
|
+
presets: nestedPresets(),
|
|
221
|
+
theme: {
|
|
222
|
+
extend: {
|
|
223
|
+
colors: themeColors(color),
|
|
224
|
+
fontFamily: {
|
|
225
|
+
sans: [font.regular],
|
|
226
|
+
"instrument-sans": [font.regular],
|
|
227
|
+
"instrument-sans-medium": [font.medium],
|
|
228
|
+
"instrument-sans-semibold": [font.semibold],
|
|
229
|
+
"instrument-sans-bold": [font.bold],
|
|
230
|
+
},
|
|
231
|
+
borderRadius: radius
|
|
232
|
+
? {
|
|
233
|
+
lg: "var(--radius)",
|
|
234
|
+
md: "calc(var(--radius) - 2px)",
|
|
235
|
+
sm: "calc(var(--radius) - 4px)",
|
|
236
|
+
}
|
|
237
|
+
: {},
|
|
238
|
+
borderWidth: hairlineBorder(),
|
|
239
|
+
},
|
|
240
|
+
},
|
|
241
|
+
plugins: inject ? [cssVariablesPlugin(darkMode)] : [],
|
|
242
|
+
};
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
module.exports = {
|
|
246
|
+
nativeUiPreset,
|
|
247
|
+
nativeUiContent,
|
|
248
|
+
cssVar,
|
|
249
|
+
hslVar,
|
|
250
|
+
rgbAlpha,
|
|
251
|
+
cssVariables,
|
|
252
|
+
schemeColors,
|
|
253
|
+
INSTRUMENT_SANS,
|
|
254
|
+
};
|
|
255
|
+
module.exports.default = nativeUiPreset();
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/** Maps a CSS variable name (without `--`) to a Tailwind colour value. */
|
|
2
|
+
export type ColorFn = (name: string) => string;
|
|
3
|
+
|
|
4
|
+
type Colors = { [key: string]: string | Colors };
|
|
5
|
+
type CssDeclarations = Record<string, string>;
|
|
6
|
+
type AddBase = (base: Record<string, CssDeclarations | Record<string, CssDeclarations>>) => void;
|
|
7
|
+
|
|
8
|
+
export interface NativeUiPresetOptions {
|
|
9
|
+
/** Default `"class"`: `ThemeToggle` and NativeWind `setColorScheme` need it. */
|
|
10
|
+
darkMode?: "class" | "media";
|
|
11
|
+
/** Default `cssVar`, or `rgbAlpha` with `injectCssVariables`. */
|
|
12
|
+
color?: ColorFn;
|
|
13
|
+
/** Write the colour variables (as `r g b` channels) and `--radius` from `tokens.ts` and `palette.ts`. Default `false`. */
|
|
14
|
+
injectCssVariables?: boolean;
|
|
15
|
+
/** `rounded-lg`, `-md` and `-sm` from `var(--radius)`. Default: the value of `injectCssVariables`. */
|
|
16
|
+
radiusVariable?: boolean;
|
|
17
|
+
/**
|
|
18
|
+
* Family names for `sans` and the four `font-instrument-sans*` classes. Keys not given keep Instrument Sans.
|
|
19
|
+
* Pass the same names to `configureTheme({ font })`; the app loads the font files.
|
|
20
|
+
*/
|
|
21
|
+
font?: { regular?: string; medium?: string; semibold?: string; bold?: string };
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export interface NativeUiPreset {
|
|
25
|
+
darkMode: "class" | "media";
|
|
26
|
+
presets: unknown[];
|
|
27
|
+
theme: {
|
|
28
|
+
extend: {
|
|
29
|
+
colors: Colors;
|
|
30
|
+
fontFamily: Record<string, string[]>;
|
|
31
|
+
borderRadius: Record<string, string>;
|
|
32
|
+
borderWidth: Record<string, unknown>;
|
|
33
|
+
};
|
|
34
|
+
};
|
|
35
|
+
plugins: Array<(api: { addBase: AddBase }) => void>;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export declare const cssVar: ColorFn;
|
|
39
|
+
export declare const hslVar: ColorFn;
|
|
40
|
+
export declare const rgbAlpha: ColorFn;
|
|
41
|
+
export declare const INSTRUMENT_SANS: {
|
|
42
|
+
regular: "InstrumentSans_400Regular";
|
|
43
|
+
medium: "InstrumentSans_500Medium";
|
|
44
|
+
semibold: "InstrumentSans_600SemiBold";
|
|
45
|
+
bold: "InstrumentSans_700Bold";
|
|
46
|
+
};
|
|
47
|
+
export declare function nativeUiPreset(options?: NativeUiPresetOptions): NativeUiPreset;
|
|
48
|
+
/** Absolute glob of this package's `src/**\/*.{js,ts,tsx}`, for Tailwind `content`. */
|
|
49
|
+
export declare function nativeUiContent(): string;
|
|
50
|
+
/** CSS variable name → `{ light, dark }` hex, from `tokens.ts` and `palette.ts`. */
|
|
51
|
+
export declare function schemeColors(): Record<string, { light: string; dark: string }>;
|
|
52
|
+
/** `{ "--name": "r g b" }` for one scheme. */
|
|
53
|
+
export declare function cssVariables(scheme: "light" | "dark"): CssDeclarations;
|
|
54
|
+
declare const preset: NativeUiPreset;
|
|
55
|
+
export default preset;
|