@kbach/native 0.1.0 → 0.1.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 +302 -0
- package/package.json +2 -2
package/README.md
ADDED
|
@@ -0,0 +1,302 @@
|
|
|
1
|
+
# @kbach/native
|
|
2
|
+
|
|
3
|
+
Tailwind-like utility classes for **React Native and Expo**. One package includes everything: the core engine, JSX runtime, Babel plugin for compile-time optimization, and Metro config helper.
|
|
4
|
+
|
|
5
|
+
```tsx
|
|
6
|
+
import { View, Text, TouchableOpacity } from 'react-native';
|
|
7
|
+
import { styled } from '@kbach/native';
|
|
8
|
+
|
|
9
|
+
const Button = styled(
|
|
10
|
+
TouchableOpacity,
|
|
11
|
+
'bg-blue-7 pressed:bg-blue-8 dark:bg-indigo-6 rounded-xl px-6 py-3 items-center'
|
|
12
|
+
);
|
|
13
|
+
|
|
14
|
+
export default function Screen() {
|
|
15
|
+
return (
|
|
16
|
+
<View className="flex-1 bg-gray-2 dark:bg-gray-11 p-4">
|
|
17
|
+
<Text className="text-2xl font-bold text-gray-10 dark:text-white mb-4">
|
|
18
|
+
Hello Kbach
|
|
19
|
+
</Text>
|
|
20
|
+
<Button>
|
|
21
|
+
<Text className="text-white font-semibold">Press me</Text>
|
|
22
|
+
</Button>
|
|
23
|
+
</View>
|
|
24
|
+
);
|
|
25
|
+
}
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## Install
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
npm install @kbach/native
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
That's it. Core engine, Babel plugin, and Metro helpers are bundled — nothing else to install.
|
|
35
|
+
|
|
36
|
+
## Setup
|
|
37
|
+
|
|
38
|
+
### 1. babel.config.js
|
|
39
|
+
|
|
40
|
+
```js
|
|
41
|
+
const { createKbachConfig } = require('@kbach/native');
|
|
42
|
+
module.exports = createKbachConfig();
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
If you need to keep an existing Babel config:
|
|
46
|
+
|
|
47
|
+
```js
|
|
48
|
+
const { withKbachBabel } = require('@kbach/native');
|
|
49
|
+
|
|
50
|
+
module.exports = withKbachBabel({
|
|
51
|
+
presets: ['babel-preset-expo'],
|
|
52
|
+
plugins: [/* your existing plugins */],
|
|
53
|
+
});
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
### 2. metro.config.js
|
|
57
|
+
|
|
58
|
+
```js
|
|
59
|
+
const { getDefaultConfig } = require('expo/metro-config');
|
|
60
|
+
const { withKbach } = require('@kbach/native');
|
|
61
|
+
|
|
62
|
+
const config = getDefaultConfig(__dirname);
|
|
63
|
+
module.exports = withKbach(config);
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### 3. Wrap your app
|
|
67
|
+
|
|
68
|
+
```tsx
|
|
69
|
+
import { ThemeProvider } from '@kbach/native';
|
|
70
|
+
|
|
71
|
+
export default function App() {
|
|
72
|
+
return (
|
|
73
|
+
<ThemeProvider defaultMode="system">
|
|
74
|
+
<AppContent />
|
|
75
|
+
</ThemeProvider>
|
|
76
|
+
);
|
|
77
|
+
}
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
After changing `babel.config.js` or `metro.config.js`, clear the Metro cache:
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
npx expo start --clear
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
## API
|
|
87
|
+
|
|
88
|
+
### `className` prop
|
|
89
|
+
|
|
90
|
+
Works on any React Native component — `View`, `Text`, `TouchableOpacity`, `TextInput`, and third-party components.
|
|
91
|
+
|
|
92
|
+
```tsx
|
|
93
|
+
<View className="flex-1 bg-gray-2 dark:bg-gray-11 p-4" />
|
|
94
|
+
<Text className="text-lg font-bold text-gray-10 dark:text-white" />
|
|
95
|
+
<TouchableOpacity className="bg-blue-7 pressed:bg-blue-8 rounded-xl px-6 py-3" />
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### `styled(Component, classes)`
|
|
99
|
+
|
|
100
|
+
Pre-style any component. Handles interaction states (`pressed:`, `focus:`, etc.) automatically.
|
|
101
|
+
|
|
102
|
+
```tsx
|
|
103
|
+
import { styled } from '@kbach/native';
|
|
104
|
+
import { View, Text, TouchableOpacity, TextInput } from 'react-native';
|
|
105
|
+
|
|
106
|
+
const Card = styled(View, 'bg-white dark:bg-gray-9 rounded-2xl p-6 shadow');
|
|
107
|
+
const Title = styled(Text, 'text-2xl font-bold text-gray-10 dark:text-white');
|
|
108
|
+
const Button = styled(
|
|
109
|
+
TouchableOpacity,
|
|
110
|
+
'bg-blue-7 pressed:bg-blue-8 dark:bg-indigo-6 dark:pressed:bg-indigo-7 rounded-xl px-6 py-3'
|
|
111
|
+
);
|
|
112
|
+
const Input = styled(
|
|
113
|
+
TextInput,
|
|
114
|
+
'border border-gray-4 dark:border-gray-7 focus:border-blue-6 bg-white dark:bg-gray-8 rounded-lg px-4 py-3'
|
|
115
|
+
);
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
Pass extra classes at use time with the `tw` prop:
|
|
119
|
+
|
|
120
|
+
```tsx
|
|
121
|
+
<Card tw="mt-4 mb-2">
|
|
122
|
+
<Title tw="text-3xl">Hello</Title>
|
|
123
|
+
</Card>
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
### `useStyles(classes)`
|
|
127
|
+
|
|
128
|
+
Resolve classes to a style object inside a component. Use this when you need a value for the `style` prop.
|
|
129
|
+
|
|
130
|
+
```tsx
|
|
131
|
+
import { useStyles } from '@kbach/native';
|
|
132
|
+
import { View, Text } from 'react-native';
|
|
133
|
+
|
|
134
|
+
function Badge() {
|
|
135
|
+
const containerStyle = useStyles('bg-blue-6 dark:bg-indigo-6 px-3 py-1 rounded-full');
|
|
136
|
+
const textStyle = useStyles('text-white text-xs font-bold');
|
|
137
|
+
|
|
138
|
+
return (
|
|
139
|
+
<View style={containerStyle}>
|
|
140
|
+
<Text style={textStyle}>New</Text>
|
|
141
|
+
</View>
|
|
142
|
+
);
|
|
143
|
+
}
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
### `tw(classes)`
|
|
147
|
+
|
|
148
|
+
Resolve classes outside a component, for use in `StyleSheet.create()` or static contexts.
|
|
149
|
+
|
|
150
|
+
```tsx
|
|
151
|
+
import { StyleSheet } from 'react-native';
|
|
152
|
+
import { tw } from '@kbach/native';
|
|
153
|
+
|
|
154
|
+
const styles = StyleSheet.create({
|
|
155
|
+
container: tw('flex-1 bg-white p-4') as object,
|
|
156
|
+
title: tw('text-2xl font-bold text-gray-10') as object,
|
|
157
|
+
});
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
### `cx(...classes)`
|
|
161
|
+
|
|
162
|
+
Conditionally join class strings. Falsy values are ignored.
|
|
163
|
+
|
|
164
|
+
```tsx
|
|
165
|
+
import { cx } from '@kbach/native';
|
|
166
|
+
|
|
167
|
+
<View className={cx(
|
|
168
|
+
'p-4 rounded-xl',
|
|
169
|
+
isSelected && 'border-2 border-blue-6',
|
|
170
|
+
isDisabled && 'opacity-50',
|
|
171
|
+
)} />
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
### `useTheme()`
|
|
175
|
+
|
|
176
|
+
```tsx
|
|
177
|
+
import { useTheme } from '@kbach/native';
|
|
178
|
+
|
|
179
|
+
const { mode, resolvedMode, isDark, setMode, toggle } = useTheme();
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
| Value | Type | Description |
|
|
183
|
+
|---|---|---|
|
|
184
|
+
| `mode` | `'light' \| 'dark' \| 'system'` | User-selected mode |
|
|
185
|
+
| `resolvedMode` | `'light' \| 'dark'` | Resolved after system lookup |
|
|
186
|
+
| `isDark` | `boolean` | Shorthand for `resolvedMode === 'dark'` |
|
|
187
|
+
| `setMode(mode)` | `fn` | Set mode explicitly |
|
|
188
|
+
| `toggle()` | `fn` | Toggle between light and dark |
|
|
189
|
+
|
|
190
|
+
### `ThemeToggle`
|
|
191
|
+
|
|
192
|
+
Drop-in toggle component that works on both web and native.
|
|
193
|
+
|
|
194
|
+
```tsx
|
|
195
|
+
<ThemeToggle /> // button (default)
|
|
196
|
+
<ThemeToggle variant="switch" /> // toggle switch
|
|
197
|
+
<ThemeToggle variant="icon-button" /> // icon button
|
|
198
|
+
<ThemeToggle variant="button" includeSystem /> // three-way selector
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
## Modifiers
|
|
202
|
+
|
|
203
|
+
Up to **3 modifiers** can be chained in any order.
|
|
204
|
+
|
|
205
|
+
| Modifier | Trigger |
|
|
206
|
+
|---|---|
|
|
207
|
+
| `dark:` | Dark mode active |
|
|
208
|
+
| `light:` | Light mode active |
|
|
209
|
+
| `pressed:` | Touch pressed |
|
|
210
|
+
| `focus:` | Element focused |
|
|
211
|
+
| `active:` | Element active |
|
|
212
|
+
| `disabled:` | Element disabled |
|
|
213
|
+
|
|
214
|
+
```tsx
|
|
215
|
+
<View className="dark:bg-gray-10" />
|
|
216
|
+
<TouchableOpacity className="dark:pressed:bg-indigo-8" />
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
## Arbitrary values
|
|
220
|
+
|
|
221
|
+
```tsx
|
|
222
|
+
<View className="bg-[#6366f1]" />
|
|
223
|
+
<View className="p-[14px]" />
|
|
224
|
+
<Text className="text-[18px]" />
|
|
225
|
+
<View className="rounded-[20px]" />
|
|
226
|
+
<View className="bg-[rgba(99,102,241,0.15)]" />
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
## Negative values
|
|
230
|
+
|
|
231
|
+
```tsx
|
|
232
|
+
<View className="-mt-4" /> {/* marginTop: -16 */}
|
|
233
|
+
<View className="-mx-2" /> {/* marginHorizontal: -8 */}
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
## Color with opacity
|
|
237
|
+
|
|
238
|
+
```tsx
|
|
239
|
+
<View className="bg-blue-6/50" /> {/* 50% opacity */}
|
|
240
|
+
<View className="bg-gray-10/75" /> {/* 75% opacity */}
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
## Color scale
|
|
244
|
+
|
|
245
|
+
Colors use an 11-shade scale where **1 is lightest** and **11 is darkest**.
|
|
246
|
+
|
|
247
|
+
```
|
|
248
|
+
bg-gray-1 (near white) → bg-gray-6 (mid) → bg-gray-11 (near black)
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
Available families: `slate` `gray` `zinc` `neutral` `stone` `red` `orange` `amber` `yellow` `lime` `green` `emerald` `teal` `cyan` `sky` `blue` `indigo` `violet` `purple` `fuchsia` `pink` `rose`
|
|
252
|
+
|
|
253
|
+
## Common utilities
|
|
254
|
+
|
|
255
|
+
| Category | Examples |
|
|
256
|
+
|---|---|
|
|
257
|
+
| **Background** | `bg-white`, `bg-gray-10`, `bg-blue-6`, `bg-[#fff]` |
|
|
258
|
+
| **Text** | `text-sm`, `text-lg`, `text-2xl`, `text-gray-10`, `font-bold` |
|
|
259
|
+
| **Padding** | `p-4`, `px-6`, `py-3`, `pt-2`, `pb-4` |
|
|
260
|
+
| **Margin** | `m-4`, `mx-auto`, `mt-2`, `mb-4`, `-mt-4` |
|
|
261
|
+
| **Size** | `w-full`, `h-12`, `w-[200px]` |
|
|
262
|
+
| **Flex** | `flex-1`, `flex-row`, `items-center`, `justify-between`, `gap-4` |
|
|
263
|
+
| **Border** | `border`, `border-2`, `border-gray-4`, `rounded-xl`, `rounded-full` |
|
|
264
|
+
| **Shadow** | `shadow`, `shadow-md`, `shadow-lg` |
|
|
265
|
+
| **Opacity** | `opacity-50`, `opacity-75` |
|
|
266
|
+
|
|
267
|
+
## Configuration
|
|
268
|
+
|
|
269
|
+
```js
|
|
270
|
+
// kbach.config.js
|
|
271
|
+
module.exports = {
|
|
272
|
+
darkMode: 'attribute', // 'attribute' | 'class' | 'media'
|
|
273
|
+
|
|
274
|
+
theme: {
|
|
275
|
+
colors: {
|
|
276
|
+
brand: { 1: '#eff6ff', 6: '#3b82f6', 10: '#1e3a5f' },
|
|
277
|
+
},
|
|
278
|
+
},
|
|
279
|
+
|
|
280
|
+
extend: {
|
|
281
|
+
theme: {
|
|
282
|
+
colors: { brand: { 6: '#6366f1' } },
|
|
283
|
+
spacing: { 18: 72 },
|
|
284
|
+
},
|
|
285
|
+
},
|
|
286
|
+
|
|
287
|
+
plugins: [
|
|
288
|
+
({ addUtility, theme }) => {
|
|
289
|
+
addUtility('border-brand', {
|
|
290
|
+
borderColor: theme('colors.brand.6'),
|
|
291
|
+
borderWidth: 2,
|
|
292
|
+
});
|
|
293
|
+
},
|
|
294
|
+
],
|
|
295
|
+
};
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
```tsx
|
|
299
|
+
import { updateConfig } from '@kbach/native';
|
|
300
|
+
|
|
301
|
+
updateConfig({ extend: { theme: { colors: { brand: { 6: '#6366f1' } } } } });
|
|
302
|
+
```
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kbach/native",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"description": "Single-package Kbach install for React Native and Expo — includes core, components, Babel plugin, and Metro config",
|
|
5
5
|
"source": "./src/index.ts",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
},
|
|
35
35
|
"dependencies": {
|
|
36
36
|
"@kbach/core": "0.1.0",
|
|
37
|
-
"@kbach/react": "0.1.
|
|
37
|
+
"@kbach/react": "0.1.1",
|
|
38
38
|
"babel-plugin-kbach": "0.1.0"
|
|
39
39
|
},
|
|
40
40
|
"devDependencies": {
|