app-studio 0.8.0 → 0.8.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 +76 -32
- package/dist/web/app-studio.umd.production.min.global.js.map +1 -1
- package/dist/web/index.cjs.map +1 -1
- package/dist/web/index.d.mts +14 -0
- package/dist/web/index.d.ts +14 -0
- package/dist/web/index.js.map +1 -1
- package/docs/Animation.md +2 -0
- package/docs/Components.md +12 -0
- package/docs/Design.md +2 -0
- package/docs/Events.md +2 -0
- package/docs/Hooks.md +2 -0
- package/docs/IframeSupport.md +2 -0
- package/docs/Native.md +428 -0
- package/docs/Providers.md +2 -0
- package/docs/README.md +4 -1
- package/docs/Responsive.md +2 -0
- package/docs/Styling.md +2 -0
- package/docs/Theming.md +53 -0
- package/package.json +1 -1
package/docs/Animation.md
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# Animation
|
|
2
2
|
|
|
3
|
+
> **React Native:** the entire animation system on this page compiles to CSS keyframes and `animation-timeline` rules, which **don't run** in React Native. The `Animation.*` helpers and the `animate` / `animateIn` / `animateOut` / `animateOn` props are accepted on native but have no visual effect. For motion on native, use `Animated` (RN core), `react-native-reanimated`, `LayoutAnimation`, or `moti`. See [Native.md → Animations](Native.md#animations).
|
|
4
|
+
|
|
3
5
|
## 1. Introduction
|
|
4
6
|
|
|
5
7
|
App-Studio provides a powerful animation system through the `Animation` object and the `Element` component. This system allows you to easily add dynamic and engaging animations, including:
|
package/docs/Components.md
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
App-Studio provides a comprehensive set of components built on the `Element` base component. This guide covers all the available components and their usage.
|
|
4
4
|
|
|
5
|
+
> **React Native:** every component on this page also ships in the native build, rendered with the matching RN primitive (`View`, `Pressable`, `Text`, `Image`, `TextInput`, `ScrollView`, `SafeAreaView`). See [Native.md](Native.md) for the full mapping table and a list of native-only / web-only props.
|
|
6
|
+
|
|
5
7
|
## Element
|
|
6
8
|
|
|
7
9
|
The `Element` component is the foundation of App-Studio. It is responsible for handling a large part of the styles of the other components. It takes care of responsiveness, shadow, margins, and padding among other properties.
|
|
@@ -75,6 +77,8 @@ import { Vertical, Horizontal, Center } from 'app-studio';
|
|
|
75
77
|
### Text
|
|
76
78
|
For displaying text content with theme support. Extends the basic `span` HTML element.
|
|
77
79
|
|
|
80
|
+
> **React Native:** renders `<Text>`. Adds `maxLines` (→ `numberOfLines`), `toUpperCase`, `isItalic`, `isStriked`, `isUnderlined`, `isSub`/`isSup`.
|
|
81
|
+
|
|
78
82
|
```tsx
|
|
79
83
|
import { Text } from 'app-studio';
|
|
80
84
|
|
|
@@ -117,6 +121,8 @@ import { Image } from 'app-studio';
|
|
|
117
121
|
/>
|
|
118
122
|
```
|
|
119
123
|
|
|
124
|
+
> **React Native:** `src` is translated to `{ uri: src }` automatically. To use a bundled asset, pass `source={require('./logo.png')}` instead. `alt` becomes `accessibilityLabel`.
|
|
125
|
+
|
|
120
126
|
## Form Components
|
|
121
127
|
|
|
122
128
|
### Form
|
|
@@ -129,6 +135,8 @@ Extends the basic `form` HTML element. It's used for creating forms and provides
|
|
|
129
135
|
</Form>
|
|
130
136
|
```
|
|
131
137
|
|
|
138
|
+
> **React Native:** `Form` is an alias for `View` — there is no `form` element on native. Drive submission manually from a `Button`'s `onPress` handler.
|
|
139
|
+
|
|
132
140
|
### Input
|
|
133
141
|
Extends the basic `input` HTML element with additional styling properties.
|
|
134
142
|
|
|
@@ -150,6 +158,8 @@ import { Input } from 'app-studio';
|
|
|
150
158
|
/>
|
|
151
159
|
```
|
|
152
160
|
|
|
161
|
+
> **React Native:** renders `<TextInput>`. Prefer `onChangeText={value => ...}` over `onChange`. The `on` map (hover/focus/etc.) is a no-op — use `TextInput`'s `onFocus`/`onBlur` props for focus styling.
|
|
162
|
+
|
|
153
163
|
### Button
|
|
154
164
|
Interactive button component with built-in states and animations.
|
|
155
165
|
|
|
@@ -172,6 +182,8 @@ import { Button } from 'app-studio';
|
|
|
172
182
|
</Button>
|
|
173
183
|
```
|
|
174
184
|
|
|
185
|
+
> **React Native:** renders `<Pressable accessibilityRole="button">`. Use `onPress` (or keep `onClick` — it is forwarded to `onPress`). String/number children are wrapped in `<Text>` automatically. The `on` map is dropped — express press feedback via `Pressable`'s `({ pressed }) => style` callback or RN's `Animated` API.
|
|
186
|
+
|
|
175
187
|
## Feedback Components
|
|
176
188
|
|
|
177
189
|
### Skeleton
|
package/docs/Design.md
CHANGED
|
@@ -4,6 +4,8 @@
|
|
|
4
4
|
|
|
5
5
|
The `app-studio` library provides a set of design props that simplify styling and enhance design integration. These props offer a more streamlined and efficient way to manage styling compared to using inline styles or CSS classes directly. They are particularly beneficial for implementing responsive and theme-aware styling, allowing you to easily adapt your components to different screen sizes and themes.
|
|
6
6
|
|
|
7
|
+
> **React Native:** the design props on this page (direct style props, `widthHeight`, `shadow`, `media`, theme color strings, the component-level `theme` override) all work the same on native. The `shadow` prop expands to RN's `shadowColor` / `shadowOffset` / `shadowOpacity` / `shadowRadius` plus an Android `elevation`. See [Native.md → Styling Props on Native](Native.md#styling-props-on-native) for the supported-property list and native-only behavior.
|
|
8
|
+
|
|
7
9
|
Here is an example:
|
|
8
10
|
|
|
9
11
|
```jsx
|
package/docs/Events.md
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
App-Studio provides intuitive ways to manage events in your CSS through the `on` prop and underscore-prefixed properties. These features are designed to offer convenient ways to style elements based on various interactive states, represented by CSS pseudo-classes like `hover`, `active`, and `focus`.
|
|
4
4
|
|
|
5
|
+
> **React Native:** the `on={{ hover, active, focus, ... }}` map and every underscore-prefixed state modifier (`_hover`, `_focus`, `_active`, `_disabled`, `_checked`, …) are **web-only** — they're accepted on native but produce no visual change. RN drives interaction state through `Pressable`'s render-prop API (`style={({ pressed, hovered }) => ...}`) and its `onPressIn` / `onPressOut` / `onHoverIn` / `onHoverOut` callbacks; for input focus, use `<TextInput>`'s `onFocus` / `onBlur` directly. The full list of no-op props is in [Native.md → Web-Only Props](Native.md#web-only-props-no-ops-on-native).
|
|
6
|
+
|
|
5
7
|
---
|
|
6
8
|
|
|
7
9
|
## 1. Introduction to Event-Based Styling
|
package/docs/Hooks.md
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
App-Studio provides a comprehensive set of React hooks to help you build interactive and responsive applications. This guide covers all the available hooks and their usage.
|
|
4
4
|
|
|
5
|
+
> **React Native:** the hooks below are listed by their web behavior. Most have native counterparts; some are exported as **no-op stubs** so shared component code keeps compiling (e.g. `useHover`, `useFocus`, `useClickOutside`, `useElementPosition`, `useKeyPress`, `useOnScreen`, `useInView`, `useIframeStyles`, `useScroll`). The full per-hook breakdown lives in [Native.md → Hooks on Native](Native.md#hooks-on-native).
|
|
6
|
+
|
|
5
7
|
## Iframe Support
|
|
6
8
|
|
|
7
9
|
Many hooks in App-Studio support working inside iframes for micro-frontend architectures, preview environments, and embedded widgets.
|
package/docs/IframeSupport.md
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# Iframe Support
|
|
2
2
|
|
|
3
|
+
> **React Native:** iframes don't exist on native — everything on this page is **web-only**. The hooks listed below (`useScroll`, `useScrollAnimation`, `useScrollDirection`, `useSmoothScroll`, `useClickOutside`, `useIframeStyles`) and the `targetWindow` provider option have no native counterpart. On native, drive scroll behavior from `ScrollView` / `FlatList` `onScroll` callbacks instead. See [Native.md → Hooks on Native](Native.md#hooks-on-native).
|
|
4
|
+
|
|
3
5
|
App-Studio provides first-class support for rendering components inside iframes. This enables use cases like:
|
|
4
6
|
|
|
5
7
|
- **Micro-frontend architectures** - Isolate different parts of your application
|
package/docs/Native.md
ADDED
|
@@ -0,0 +1,428 @@
|
|
|
1
|
+
# React Native
|
|
2
|
+
|
|
3
|
+
App-Studio ships a dedicated React Native build alongside its web build. The same import paths and prop-based styling API work in both environments — Metro picks the correct build automatically through the `react-native` export condition.
|
|
4
|
+
|
|
5
|
+
## Table of Contents
|
|
6
|
+
|
|
7
|
+
1. [Setup](#setup)
|
|
8
|
+
2. [Component Mapping](#component-mapping)
|
|
9
|
+
3. [Styling Props on Native](#styling-props-on-native)
|
|
10
|
+
4. [Web-Only Props (No-ops on Native)](#web-only-props-no-ops-on-native)
|
|
11
|
+
5. [Theme & Color Resolution](#theme--color-resolution)
|
|
12
|
+
6. [Responsive & Media Queries](#responsive--media-queries)
|
|
13
|
+
7. [Hooks on Native](#hooks-on-native)
|
|
14
|
+
8. [Accessibility & Test IDs](#accessibility--test-ids)
|
|
15
|
+
9. [Animations](#animations)
|
|
16
|
+
10. [Differences Cheat Sheet](#differences-cheat-sheet)
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## Setup
|
|
21
|
+
|
|
22
|
+
### Requirements
|
|
23
|
+
|
|
24
|
+
- React Native `>= 0.79` (Metro must support [package exports](https://reactnative.dev/blog/2023/06/21/package-exports-support); enabled by default in 0.79+).
|
|
25
|
+
- React `>= 17`.
|
|
26
|
+
|
|
27
|
+
### Install
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
npm install app-studio
|
|
31
|
+
# or
|
|
32
|
+
yarn add app-studio
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
App-Studio's only runtime dependencies (`color-convert`, `hyphenate-style-name`) are shared between web and native and require no extra Metro configuration.
|
|
36
|
+
|
|
37
|
+
### Import paths
|
|
38
|
+
|
|
39
|
+
Use the bare package name from any RN file — Metro resolves it to the native build:
|
|
40
|
+
|
|
41
|
+
```tsx
|
|
42
|
+
import {
|
|
43
|
+
View,
|
|
44
|
+
Text,
|
|
45
|
+
Button,
|
|
46
|
+
ThemeProvider,
|
|
47
|
+
ResponsiveProvider,
|
|
48
|
+
WindowSizeProvider,
|
|
49
|
+
} from 'app-studio';
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Two explicit subpaths are also available if you ever need to force a build:
|
|
53
|
+
|
|
54
|
+
- `app-studio/native` — always loads the native build (useful for inspecting the API in a web tool, or for monorepos with non-standard resolvers).
|
|
55
|
+
- `app-studio/web` — always loads the web build.
|
|
56
|
+
|
|
57
|
+
You should not need these subpaths in normal application code.
|
|
58
|
+
|
|
59
|
+
### Provider tree
|
|
60
|
+
|
|
61
|
+
The provider API is identical to web. A typical RN entrypoint looks like:
|
|
62
|
+
|
|
63
|
+
```tsx
|
|
64
|
+
import React from 'react';
|
|
65
|
+
import {
|
|
66
|
+
ThemeProvider,
|
|
67
|
+
ResponsiveProvider,
|
|
68
|
+
WindowSizeProvider,
|
|
69
|
+
AnalyticsProvider,
|
|
70
|
+
} from 'app-studio';
|
|
71
|
+
import RootScreen from './RootScreen';
|
|
72
|
+
|
|
73
|
+
export default function App() {
|
|
74
|
+
return (
|
|
75
|
+
<ThemeProvider>
|
|
76
|
+
<WindowSizeProvider>
|
|
77
|
+
<ResponsiveProvider>
|
|
78
|
+
<AnalyticsProvider trackEvent={(event) => console.log(event)}>
|
|
79
|
+
<RootScreen />
|
|
80
|
+
</AnalyticsProvider>
|
|
81
|
+
</ResponsiveProvider>
|
|
82
|
+
</WindowSizeProvider>
|
|
83
|
+
</ThemeProvider>
|
|
84
|
+
);
|
|
85
|
+
}
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
---
|
|
89
|
+
|
|
90
|
+
## Component Mapping
|
|
91
|
+
|
|
92
|
+
Every cross-platform primitive renders a familiar React Native node under the hood. Children are wrapped or forwarded as needed.
|
|
93
|
+
|
|
94
|
+
| App-Studio component | Native renders as | Notes |
|
|
95
|
+
| :---------------------------------- | :------------------------------------------------------------------------- | :---- |
|
|
96
|
+
| `Element`, `View`, `Div`, `Span` | `<View>` — or `<Pressable>` when `onPress`/`onClick` is provided | Children are wrapped between optional `before` / `after` slots. |
|
|
97
|
+
| `Horizontal` | `<View flexDirection="row">` | |
|
|
98
|
+
| `Vertical` | `<View flexDirection="column">` | |
|
|
99
|
+
| `Center` | `<View justifyContent="center" alignItems="center">` | |
|
|
100
|
+
| `HorizontalResponsive` | `<View flexDirection="row">` → `column` at `mobile` breakpoint | Uses `useWindowDimensions` + `ResponsiveProvider`. |
|
|
101
|
+
| `VerticalResponsive` | `<View flexDirection="column">` → `row` at `mobile` breakpoint | |
|
|
102
|
+
| `Scroll` | `<ScrollView>` | Pass standard RN scroll props (e.g. `contentContainerStyle`, `horizontal`). |
|
|
103
|
+
| `SafeArea` | `<SafeAreaView>` (from `react-native`) | For richer behavior use `react-native-safe-area-context` directly. |
|
|
104
|
+
| `Text` | `<Text>` | See [Text-specific props](#text). |
|
|
105
|
+
| `Image` | `<Image>` | `src` is translated to `{ uri: src }` automatically; `source` is also accepted. |
|
|
106
|
+
| `ImageBackground` | `<ImageBackground>` | Same `src` / `source` handling as `Image`. |
|
|
107
|
+
| `Form` | `<View>` | Form semantics don't exist in RN; treat it as an alias for `View`. |
|
|
108
|
+
| `Input` | `<TextInput>` | Use `onChangeText` (not `onChange`). |
|
|
109
|
+
| `Button` | `<Pressable accessibilityRole="button">` | String / number children are wrapped in `<Text>` automatically. |
|
|
110
|
+
| `Skeleton` | `<View accessibilityRole="progressbar">` | Static placeholder — see [Animations](#animations) for shimmer notes. |
|
|
111
|
+
|
|
112
|
+
### Text
|
|
113
|
+
|
|
114
|
+
Native `Text` accepts a few extra typographic props that translate to RN-friendly equivalents:
|
|
115
|
+
|
|
116
|
+
| Prop | Mapping |
|
|
117
|
+
| :-------------- | :----------------------------------------------------------------------- |
|
|
118
|
+
| `toUpperCase` | Converts string children to uppercase before rendering. |
|
|
119
|
+
| `isItalic` | Sets `fontStyle: 'italic'`. |
|
|
120
|
+
| `isStriked` | Sets `textDecorationLine: 'line-through'`. |
|
|
121
|
+
| `isUnderlined` | Sets `textDecorationLine: 'underline'`. |
|
|
122
|
+
| `isSub` / `isSup` | Forces `fontSize` to 12 unless an explicit size is provided. |
|
|
123
|
+
| `maxLines` | Sets RN's `numberOfLines` prop. |
|
|
124
|
+
|
|
125
|
+
```tsx
|
|
126
|
+
<Text fontSize={16} fontWeight="bold" maxLines={2} toUpperCase>
|
|
127
|
+
Important headline
|
|
128
|
+
</Text>
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
### Image
|
|
132
|
+
|
|
133
|
+
Pass either a remote URL via `src` (web-style) or a native `ImageSourcePropType` via `source`:
|
|
134
|
+
|
|
135
|
+
```tsx
|
|
136
|
+
<Image src="https://example.com/avatar.png" width={48} height={48} borderRadius={24} alt="User avatar" />
|
|
137
|
+
|
|
138
|
+
// or with a bundled asset
|
|
139
|
+
<Image source={require('./logo.png')} width={120} height={32} />
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
`alt` is forwarded as `accessibilityLabel`.
|
|
143
|
+
|
|
144
|
+
### Button
|
|
145
|
+
|
|
146
|
+
Wraps `Pressable`. A `disabled` prop short-circuits both `onPress` and `onClick`:
|
|
147
|
+
|
|
148
|
+
```tsx
|
|
149
|
+
<Button
|
|
150
|
+
paddingHorizontal={20}
|
|
151
|
+
paddingVertical={12}
|
|
152
|
+
backgroundColor="theme-primary"
|
|
153
|
+
borderRadius={8}
|
|
154
|
+
onPress={handleSubmit}
|
|
155
|
+
disabled={isSubmitting}
|
|
156
|
+
>
|
|
157
|
+
Submit
|
|
158
|
+
</Button>
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
String children become `<Text>` automatically; pass JSX directly for anything more complex.
|
|
162
|
+
|
|
163
|
+
---
|
|
164
|
+
|
|
165
|
+
## Styling Props on Native
|
|
166
|
+
|
|
167
|
+
All cross-platform style props you already use on web work the same way on native, with the same theme-aware color resolution. The native style engine accepts the subset of CSS properties that React Native supports.
|
|
168
|
+
|
|
169
|
+
### Supported style props
|
|
170
|
+
|
|
171
|
+
The following props are read by the native style engine and applied to the underlying `View` / `Text` / `Image` style. Anything not in this list is passed through to React Native as-is.
|
|
172
|
+
|
|
173
|
+
```
|
|
174
|
+
Layout & Flex: flex, flexDirection, flexBasis, flexGrow, flexShrink, flexWrap,
|
|
175
|
+
alignContent, alignItems, alignSelf, justifyContent, gap,
|
|
176
|
+
rowGap, columnGap, aspectRatio, direction, display, position,
|
|
177
|
+
top, right, bottom, left, start, end, zIndex, overflow,
|
|
178
|
+
|
|
179
|
+
Box model: width, height, minWidth, minHeight, maxWidth, maxHeight,
|
|
180
|
+
margin*, padding*, (including marginHorizontal/Vertical
|
|
181
|
+
and paddingHorizontal/Vertical), borderWidth*,
|
|
182
|
+
borderRadius*, borderColor*, borderStyle, borderCurve,
|
|
183
|
+
|
|
184
|
+
Typography: color, fontFamily, fontSize, fontStyle, fontWeight,
|
|
185
|
+
fontVariant, lineHeight, letterSpacing, textAlign,
|
|
186
|
+
textAlignVertical, textDecorationLine, textDecorationColor,
|
|
187
|
+
textDecorationStyle, textShadow*, textTransform,
|
|
188
|
+
verticalAlign, writingDirection, includeFontPadding,
|
|
189
|
+
|
|
190
|
+
Visual: backgroundColor, opacity, transform, transformOrigin,
|
|
191
|
+
shadowColor, shadowOffset, shadowOpacity, shadowRadius,
|
|
192
|
+
elevation, boxShadow, overlayColor, tintColor,
|
|
193
|
+
backfaceVisibility, objectFit, resizeMode
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
### Native-only convenience props
|
|
197
|
+
|
|
198
|
+
Two cross-platform props are expanded on native (they also exist on web with the same meaning):
|
|
199
|
+
|
|
200
|
+
| Prop | Behavior |
|
|
201
|
+
| :------------ | :------------------------------------------------------------------------------------ |
|
|
202
|
+
| `widthHeight` | Sets both `width` and `height` to the same value. |
|
|
203
|
+
| `shadow` | `true` or a number `0..1` — applies `shadowColor #000`, `shadowRadius 4`, `shadowOffset {0,1}`, `shadowOpacity` (defaulting to `0.2`), and a matching Android `elevation`. |
|
|
204
|
+
|
|
205
|
+
```tsx
|
|
206
|
+
<View widthHeight={48} backgroundColor="theme-primary" borderRadius={24} shadow={0.3} />
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
### `media`, `css`, and `style`
|
|
210
|
+
|
|
211
|
+
The native style engine reads styles from four sources, merged in this order (later sources override earlier ones):
|
|
212
|
+
|
|
213
|
+
1. Top-level style props on the component.
|
|
214
|
+
2. `media={{ breakpoint: { ... } }}` entries matching the current width.
|
|
215
|
+
3. `css={{ ... }}` (plain object only — raw CSS strings have no effect on native).
|
|
216
|
+
4. `style={{ ... }}` (standard RN `StyleProp`, including arrays). `StyleSheet.flatten` is applied automatically.
|
|
217
|
+
|
|
218
|
+
```tsx
|
|
219
|
+
<View
|
|
220
|
+
padding={12}
|
|
221
|
+
backgroundColor="color-gray-100"
|
|
222
|
+
media={{ tablet: { padding: 24 }, desktop: { padding: 32 } }}
|
|
223
|
+
css={{ borderColor: 'theme-primary', borderWidth: 1 }}
|
|
224
|
+
style={{ borderRadius: 12 }}
|
|
225
|
+
/>
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
### `onPress` & `onClick`
|
|
229
|
+
|
|
230
|
+
Native components accept both. If either is set on a non-pressable primitive (`Element`/`View`), the component automatically renders as `Pressable`. `onClick` is forwarded to `Pressable`'s `onPress` so web code that uses `onClick` keeps working.
|
|
231
|
+
|
|
232
|
+
---
|
|
233
|
+
|
|
234
|
+
## Web-Only Props (No-ops on Native)
|
|
235
|
+
|
|
236
|
+
To keep the prop API uniform across platforms, the native build *accepts* the following props but does nothing with them — they're silently dropped before reaching the underlying RN component. Code that targets both platforms can leave them in place.
|
|
237
|
+
|
|
238
|
+
**State modifiers (underscore-prefixed):** `_hover`, `_active`, `_focus`, `_visited`, `_disabled`, `_enabled`, `_checked`, `_unchecked`, `_invalid`, `_valid`, `_required`, `_optional`, `_selected`, `_target`, `_firstChild`, `_lastChild`, `_onlyChild`, `_firstOfType`, `_lastOfType`, `_empty`, `_focusVisible`, `_focusWithin`, `_placeholder`, `_groupHover`, `_groupFocus`, `_groupActive`, `_groupDisabled`, `_peerHover`, `_peerFocus`, `_peerActive`, `_peerDisabled`, `_peerChecked`.
|
|
239
|
+
|
|
240
|
+
**Pseudo-elements:** `_before`, `_after`, `_firstLetter`, `_firstLine`, `_selection`, `_backdrop`, `_marker`.
|
|
241
|
+
|
|
242
|
+
**`on={{ ... }}`** — the `on` map (hover/focus/active/etc.) is also a no-op. RN drives interactions through `Pressable` props (`onPressIn`, `onPressOut`, `onHoverIn`, etc.); use those directly when you need interaction-driven style changes.
|
|
243
|
+
|
|
244
|
+
**Other web-only props:**
|
|
245
|
+
|
|
246
|
+
- `as` — RN components don't have HTML tags; the underlying primitive is fixed.
|
|
247
|
+
- `className` — ignored.
|
|
248
|
+
- `css` raw CSS strings — only object-form `css` is read on native.
|
|
249
|
+
- CSS animations declared via `animate` / `animateIn` / `animateOut` / `animateOn` — see [Animations](#animations).
|
|
250
|
+
|
|
251
|
+
If you write a component that's truly platform-divergent, the cleanest path is to split it into `MyComponent.tsx` (web) and `MyComponent.native.tsx` (native) — Metro will pick the `.native` file automatically.
|
|
252
|
+
|
|
253
|
+
---
|
|
254
|
+
|
|
255
|
+
## Theme & Color Resolution
|
|
256
|
+
|
|
257
|
+
`ThemeProvider`, `useTheme`, and all the theme prop syntax work on native just like web. Pass color strings (`color-blue-500`, `theme-primary`, `light-white`, `dark-red-200`, `theme-primary-300` for 30% alpha, etc.) directly into any color-accepting prop and they resolve through the theme — no `getColor` call required:
|
|
258
|
+
|
|
259
|
+
```tsx
|
|
260
|
+
<View backgroundColor="theme-primary" padding={16}>
|
|
261
|
+
<Text color="color-white">Hello, native!</Text>
|
|
262
|
+
</View>
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
### Implementation detail
|
|
266
|
+
|
|
267
|
+
On web, alpha colors compile to `color-mix(...)` CSS. On native, the theme provider's `getColor` returns the resolved color string directly (hex or rgba), and the style engine substitutes it into any prop whose name contains `color` (case-insensitive) — `backgroundColor`, `borderColor`, `tintColor`, `shadowColor`, and so on.
|
|
268
|
+
|
|
269
|
+
### `useTheme` API
|
|
270
|
+
|
|
271
|
+
The native theme context exposes the same surface as web:
|
|
272
|
+
|
|
273
|
+
```tsx
|
|
274
|
+
const {
|
|
275
|
+
getColor, // (name) => resolved color string
|
|
276
|
+
getColorHex, // (name) => normalized hex
|
|
277
|
+
getColorRGBA, // (name, alpha?: 0..1000) => rgba(...)
|
|
278
|
+
getColorScheme, // (name) => palette or theme token name
|
|
279
|
+
getContrastColor, // (name) => 'black' | 'white'
|
|
280
|
+
theme,
|
|
281
|
+
colors,
|
|
282
|
+
themeMode,
|
|
283
|
+
setThemeMode,
|
|
284
|
+
} = useTheme();
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
`getColor` returns concrete color values (hex/rgba), so you can pass them to third-party RN libraries that expect a plain string.
|
|
288
|
+
|
|
289
|
+
### Scoped theme override
|
|
290
|
+
|
|
291
|
+
`Element`, `View`, etc. accept a `theme` prop that locally overrides theme tokens for that subtree. The override applies only to `theme-*` color tokens consumed by *that* component's style props — it does not propagate to child components.
|
|
292
|
+
|
|
293
|
+
```tsx
|
|
294
|
+
<Element backgroundColor="theme-primary" theme={{ primary: 'color-purple-500' }}>
|
|
295
|
+
...
|
|
296
|
+
</Element>
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
---
|
|
300
|
+
|
|
301
|
+
## Responsive & Media Queries
|
|
302
|
+
|
|
303
|
+
The native `ResponsiveProvider` is powered by `useWindowDimensions()` from React Native, so it reacts to device rotation and split-screen mode automatically.
|
|
304
|
+
|
|
305
|
+
**Default breakpoints (px):** `xs: 0`, `sm: 340`, `md: 560`, `lg: 1080`, `xl: 1300`.
|
|
306
|
+
**Default devices:** `mobile: [xs, sm]`, `tablet: [md, lg]`, `desktop: [lg, xl]`.
|
|
307
|
+
|
|
308
|
+
Pass `breakpoints` and `devices` props to `ResponsiveProvider` to customize them.
|
|
309
|
+
|
|
310
|
+
### `media` prop
|
|
311
|
+
|
|
312
|
+
Works the same as on web — keys can be breakpoint names or device names. On native, `media` styles are merged into the inline RN style object whenever the active breakpoint matches.
|
|
313
|
+
|
|
314
|
+
```tsx
|
|
315
|
+
<View
|
|
316
|
+
padding={12}
|
|
317
|
+
media={{
|
|
318
|
+
mobile: { padding: 12, flexDirection: 'column' },
|
|
319
|
+
tablet: { padding: 24, flexDirection: 'row' },
|
|
320
|
+
}}
|
|
321
|
+
/>
|
|
322
|
+
```
|
|
323
|
+
|
|
324
|
+
### `useResponsive`
|
|
325
|
+
|
|
326
|
+
```tsx
|
|
327
|
+
import { useResponsive } from 'app-studio';
|
|
328
|
+
|
|
329
|
+
function AdaptiveCard() {
|
|
330
|
+
const { screen, currentDevice, orientation, on } = useResponsive();
|
|
331
|
+
|
|
332
|
+
return (
|
|
333
|
+
<View flexDirection={on('mobile') ? 'column' : 'row'}>
|
|
334
|
+
<Text>{screen} · {currentDevice} · {orientation}</Text>
|
|
335
|
+
</View>
|
|
336
|
+
);
|
|
337
|
+
}
|
|
338
|
+
```
|
|
339
|
+
|
|
340
|
+
`screen` (alias for `currentBreakpoint`), `currentDevice`, `orientation`, `on(name)`, and `is(name)` behave identically to web.
|
|
341
|
+
|
|
342
|
+
---
|
|
343
|
+
|
|
344
|
+
## Hooks on Native
|
|
345
|
+
|
|
346
|
+
Some hooks are inherently web-only (DOM events, IntersectionObserver, keyboard listeners). On native they are exported as **safe stubs** so that shared component code keeps compiling — but you should not rely on them returning meaningful values.
|
|
347
|
+
|
|
348
|
+
| Hook | Native behavior |
|
|
349
|
+
| :-------------------- | :--------------------------------------------------------------------------------------------- |
|
|
350
|
+
| `useWindowSize` | ✅ Works. Backed by RN's `useWindowDimensions`. |
|
|
351
|
+
| `useWindowDimensions` | ✅ Works. Same data as `useWindowSize`. |
|
|
352
|
+
| `useResponsive` | ✅ Works. Reads from `ResponsiveProvider`. |
|
|
353
|
+
| `useBreakpoint` | ✅ Works. Same as `useResponsive` minus width/height. |
|
|
354
|
+
| `useTheme` | ✅ Works (covered above). |
|
|
355
|
+
| `useAnalytics` | ✅ Works. |
|
|
356
|
+
| `useMount` | ✅ Works. |
|
|
357
|
+
| `useHover` | ⚠️ Stub. Returns `{ isHovered: false, hoverProps: {} }`. Use RN's `Pressable` `onHoverIn`/`onHoverOut` if you need hover on a mouse-capable device. |
|
|
358
|
+
| `useActive` | ⚠️ Stub. Returns `{ isActive: false, activeProps: {} }`. Use `Pressable` `onPressIn`/`onPressOut`. |
|
|
359
|
+
| `useFocus` | ⚠️ Stub. Returns `{ isFocused: false, focusProps: {} }`. Use `TextInput`'s `onFocus`/`onBlur` directly. |
|
|
360
|
+
| `useClickOutside` | ⚠️ Stub. Returns a ref and `isOutside: false`. Patterns like outside-tap dismissal need a `Pressable` overlay in RN. |
|
|
361
|
+
| `useElementPosition` | ⚠️ Stub. RN equivalent is `measure()` on a `ref`. |
|
|
362
|
+
| `useKeyPress` | ⚠️ Stub. Returns `false`. Use `react-native-keyboard-events` or platform-specific code. |
|
|
363
|
+
| `useOnScreen` | ⚠️ Stub. Returns `{ ref, isOnScreen: true }` — assume always visible. |
|
|
364
|
+
| `useInView` | ⚠️ Stub. Returns `{ ref, inView: true }`. For real visibility tracking inside lists, prefer `FlatList`'s `viewabilityConfig` / `onViewableItemsChanged`. |
|
|
365
|
+
| `useIframeStyles` | ⚠️ Stub. iframes don't exist on native. |
|
|
366
|
+
| `useScroll` | ⚠️ Stub. Returns zeroed values and no-op scroll methods. Drive scroll behavior from `ScrollView`/`FlatList`'s `onScroll`. |
|
|
367
|
+
| `useScrollDirection`, `useSmoothScroll`, `useScrollAnimation`, `useInfiniteScroll` | ❌ Not exported on native. Build with RN's own scroll events. |
|
|
368
|
+
|
|
369
|
+
The stubs exist so a single component body can run on both platforms without conditionals — but on native you should branch when meaningful interaction state is required.
|
|
370
|
+
|
|
371
|
+
---
|
|
372
|
+
|
|
373
|
+
## Accessibility & Test IDs
|
|
374
|
+
|
|
375
|
+
The native build automatically rewrites two common web attributes to their RN equivalents:
|
|
376
|
+
|
|
377
|
+
| Web prop | Native prop |
|
|
378
|
+
| :------------- | :--------------------- |
|
|
379
|
+
| `data-testid` | `testID` |
|
|
380
|
+
| `aria-label` | `accessibilityLabel` |
|
|
381
|
+
|
|
382
|
+
So shared component code can keep using `data-testid="submit"` and it will be picked up by Detox/Maestro/Appium without any changes.
|
|
383
|
+
|
|
384
|
+
```tsx
|
|
385
|
+
<Button data-testid="submit" aria-label="Submit form" onPress={handleSubmit}>
|
|
386
|
+
Submit
|
|
387
|
+
</Button>
|
|
388
|
+
```
|
|
389
|
+
|
|
390
|
+
For RN-specific a11y APIs (`accessibilityRole`, `accessibilityState`, `accessibilityHint`, etc.) pass them through directly — they're forwarded untouched to the underlying primitive.
|
|
391
|
+
|
|
392
|
+
---
|
|
393
|
+
|
|
394
|
+
## Animations
|
|
395
|
+
|
|
396
|
+
The `Animation.*` presets and the `animate` / `animateIn` / `animateOut` / `animateOn` props compile to CSS keyframes, which **don't run** in React Native. On native these props are accepted but have no visual effect.
|
|
397
|
+
|
|
398
|
+
For motion on native, use one of:
|
|
399
|
+
|
|
400
|
+
- **`Animated` API** (`react-native` core) for simple interpolations.
|
|
401
|
+
- **`react-native-reanimated`** for performant, gesture-driven animations.
|
|
402
|
+
- **`LayoutAnimation`** for automatic layout transitions.
|
|
403
|
+
- **`moti`** for a declarative API similar to App-Studio's `animate` prop.
|
|
404
|
+
|
|
405
|
+
A native-flavored animation system is on the roadmap — see [next.md](../next.md) for status. Until then, drop down to the libraries above for native motion.
|
|
406
|
+
|
|
407
|
+
---
|
|
408
|
+
|
|
409
|
+
## Differences Cheat Sheet
|
|
410
|
+
|
|
411
|
+
| Concern | Web | Native |
|
|
412
|
+
| :---------------------------- | :--------------------------------------------- | :---------------------------------------------------------------------- |
|
|
413
|
+
| Underlying primitive | HTML elements (`div`, `span`, `button`, …) | RN primitives (`View`, `Pressable`, `Text`, `Image`, `TextInput`, …) |
|
|
414
|
+
| `as` prop | Selects HTML tag | Ignored |
|
|
415
|
+
| Pseudo-classes (`_hover`, `on`) | Compiled to CSS | Silently dropped — use `Pressable` event props instead |
|
|
416
|
+
| Pseudo-elements (`_before`, `_after`) | Compiled to CSS | Silently dropped — render real components instead |
|
|
417
|
+
| `className` | Applied to DOM element | Ignored |
|
|
418
|
+
| `css` raw string | Injected into stylesheet | Ignored (object form still works) |
|
|
419
|
+
| `style` | Standard CSSProperties | RN `StyleProp` (object, array, or `StyleSheet` reference) |
|
|
420
|
+
| Animations | CSS keyframes via `Animation.*` | No-op — bring `Animated` / Reanimated / Moti |
|
|
421
|
+
| `Image` source | `src` / `srcSet` | `src` (URI shorthand) or `source={...}` |
|
|
422
|
+
| `Input` change handler | `onChange` | `onChangeText` (RN-native) — `onChange` is also forwarded |
|
|
423
|
+
| Click handlers | `onClick` | `onPress` (preferred); `onClick` forwards to `onPress` |
|
|
424
|
+
| Test IDs | `data-testid` | `data-testid` (rewritten to `testID`) — or `testID` directly |
|
|
425
|
+
| A11y label | `aria-label` | `aria-label` (rewritten to `accessibilityLabel`) — or `accessibilityLabel` directly |
|
|
426
|
+
| `useScroll` family | Reads from `window` / scroll containers | Stubbed; use `ScrollView`/`FlatList` `onScroll` |
|
|
427
|
+
| `useInView` / `useOnScreen` | `IntersectionObserver` | Stubbed; use `FlatList` viewability |
|
|
428
|
+
| `useKeyPress` | DOM key events | Stubbed |
|
package/docs/Providers.md
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
App-Studio includes several context providers to manage global state and functionality.
|
|
4
4
|
|
|
5
|
+
> **React Native:** all four providers (`ThemeProvider`, `ResponsiveProvider`, `WindowSizeProvider`, `AnalyticsProvider`) are exported from the native build with the same API. On native, `ResponsiveProvider` and `WindowSizeProvider` are driven by RN's `useWindowDimensions()`, so they react to rotation and split-screen automatically. See [Native.md → Setup](Native.md#setup) for the recommended provider tree.
|
|
6
|
+
|
|
5
7
|
## ThemeProvider
|
|
6
8
|
|
|
7
9
|
Manages theme context including colors, dark/light mode, and design tokens.
|
package/docs/README.md
CHANGED
|
@@ -58,6 +58,8 @@ import { View, Text, Button, ThemeProvider, ResponsiveProvider } from 'app-studi
|
|
|
58
58
|
|
|
59
59
|
Metro resolves the package to App-Studio's native build through the `react-native` export condition. Use `app-studio/native` or `app-studio/web` only when you need an explicit platform subpath. Native exposes the cross-platform primitives/providers; web-only props such as `_hover`, pseudo-elements, CSS animations, and HTML `as` values are accepted as no-ops.
|
|
60
60
|
|
|
61
|
+
See the [React Native guide](Native.md) for component mapping, native-only props, hook behavior on native, and a side-by-side cheat sheet.
|
|
62
|
+
|
|
61
63
|
## Core Concepts
|
|
62
64
|
|
|
63
65
|
### Element Component
|
|
@@ -90,13 +92,14 @@ Explore these guides to learn more about App-Studio:
|
|
|
90
92
|
|
|
91
93
|
- [Components](Components.md) - Detailed documentation of all available components
|
|
92
94
|
- [Hooks](Hooks.md) - Guide to the React hooks provided by App-Studio
|
|
93
|
-
- [Theming](Theming.md) -
|
|
95
|
+
- [Theming](Theming.md) - Customize colors, theme tokens, color palettes, and component-level sub-theming via the `theme` prop
|
|
94
96
|
- [Styling](Styling.md) - Advanced styling guide covering state modifiers, pseudo-elements, media queries, and the CSS system
|
|
95
97
|
- [Animation](Animation.md) - Creating animations with App-Studio
|
|
96
98
|
- [Responsive Design](Responsive.md) - Building responsive layouts
|
|
97
99
|
- [Design System](Design.md) - Understanding the design system
|
|
98
100
|
- [Event Handling](Events.md) - Working with events and interactions
|
|
99
101
|
- [Providers](Providers.md) - Context providers for global state
|
|
102
|
+
- [React Native](Native.md) - Using App-Studio in React Native projects (component mapping, native-only props, hook differences)
|
|
100
103
|
- [Migration Guide](../codemod/README.md) - Migrating to App-Studio
|
|
101
104
|
|
|
102
105
|
---
|
package/docs/Responsive.md
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
Creating a responsive design is an essential part of modern web development. In App-Studio, two primary features help you achieve this: `useResponsive` hook and the `media` prop. This document provides an overview and examples for both approaches.
|
|
4
4
|
|
|
5
|
+
> **React Native:** both the `media` prop and `useResponsive` work on native. Width tracking is backed by RN's `useWindowDimensions`, so values update on rotation and split-screen. The default breakpoints (`xs: 0`, `sm: 340`, `md: 560`, `lg: 1080`, `xl: 1300`) and devices (`mobile`, `tablet`, `desktop`) are shared with web — override them by passing `breakpoints` / `devices` to `ResponsiveProvider`. See [Native.md → Responsive & Media Queries](Native.md#responsive--media-queries).
|
|
6
|
+
|
|
5
7
|
---
|
|
6
8
|
|
|
7
9
|
## 1. Media Prop for Responsive Design
|
package/docs/Styling.md
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
This guide covers advanced styling techniques in App-Studio, including state modifiers, pseudo-elements, media queries, and the underlying CSS system.
|
|
4
4
|
|
|
5
|
+
> **React Native:** state modifiers (`_hover`, `_focus`, `_disabled`, …), pseudo-elements (`_before`, `_after`, …), the `on={{ ... }}` map, and raw-string `css` are **web-only**. They are accepted on native but produce no output — express equivalent behavior with `Pressable`'s event props or RN's `Animated` API. Direct style props, the `media` map, object-form `css`, theme color strings, the `widthHeight` shorthand, and the `shadow` prop all work the same on native. See [Native.md → Styling Props on Native](Native.md#styling-props-on-native).
|
|
6
|
+
|
|
5
7
|
## Table of Contents
|
|
6
8
|
|
|
7
9
|
1. [State Modifiers](#state-modifiers)
|
package/docs/Theming.md
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
Theming is an essential part of any application. It allows you to maintain a consistent look and feel across your app. With App-Studio, theming becomes effortless through its `ThemeProvider` component. This document shows you how to set up theming in App-Studio.
|
|
4
4
|
|
|
5
|
+
> **React Native:** the entire color system documented here (singletons, palettes, theme tokens, `light-`/`dark-` prefixes, alpha shorthand, component-level `theme` overrides) works identically on native. The only implementation difference: on web, alpha colors compile to `color-mix(...)` CSS; on native the theme provider returns concrete hex/rgba strings that get substituted into RN style props. See [Native.md → Theme & Color Resolution](Native.md#theme--color-resolution).
|
|
6
|
+
|
|
5
7
|
## Available Colors Reference
|
|
6
8
|
|
|
7
9
|
App-Studio provides an extensive color system with three types of colors:
|
|
@@ -413,6 +415,57 @@ function Example() {
|
|
|
413
415
|
|
|
414
416
|
This direct access syntax works with all color-related properties and can be used with both singleton colors (like `white`, `black`) and palette colors (like `red-200`, `blue-500`). It provides a convenient way to reference specific theme colors without having to use the `getColor` function from the `useTheme` hook.
|
|
415
417
|
|
|
418
|
+
### Component-Level Sub-Theming
|
|
419
|
+
|
|
420
|
+
Any component that extends `Element` (`View`, `Text`, `Button`, etc.) accepts a `theme` prop that remaps `theme-*` tokens **for that single component**, without touching the global `ThemeProvider`. Useful when a screen needs one "branded" element (a Startup Studio launch button, a special card, a colored chip) while the rest of the UI keeps the global palette.
|
|
421
|
+
|
|
422
|
+
```javascript
|
|
423
|
+
import { View, Text } from 'app-studio';
|
|
424
|
+
|
|
425
|
+
function Example() {
|
|
426
|
+
return (
|
|
427
|
+
<View>
|
|
428
|
+
{/* Global theme-primary (no override) */}
|
|
429
|
+
<View backgroundColor="theme-primary" padding={20}>
|
|
430
|
+
<Text color="color-white">Global primary</Text>
|
|
431
|
+
</View>
|
|
432
|
+
|
|
433
|
+
{/* Same component, locally remapped to red */}
|
|
434
|
+
<View
|
|
435
|
+
backgroundColor="theme-primary"
|
|
436
|
+
theme={{ primary: 'color-red-500' }}
|
|
437
|
+
padding={20}
|
|
438
|
+
>
|
|
439
|
+
<Text color="color-white">Local primary = red-500</Text>
|
|
440
|
+
</View>
|
|
441
|
+
|
|
442
|
+
{/* Multiple slots at once */}
|
|
443
|
+
<View
|
|
444
|
+
backgroundColor="theme-primary"
|
|
445
|
+
borderColor="theme-secondary"
|
|
446
|
+
borderWidth={2}
|
|
447
|
+
borderStyle="solid"
|
|
448
|
+
theme={{
|
|
449
|
+
primary: 'color-indigo-600',
|
|
450
|
+
secondary: 'color-yellow-400',
|
|
451
|
+
}}
|
|
452
|
+
padding={20}
|
|
453
|
+
>
|
|
454
|
+
<Text color="color-white">indigo bg, yellow border</Text>
|
|
455
|
+
</View>
|
|
456
|
+
</View>
|
|
457
|
+
);
|
|
458
|
+
}
|
|
459
|
+
```
|
|
460
|
+
|
|
461
|
+
**What the `theme` prop accepts**: a `Partial<Theme>` where each value is itself a color token (`'color-red-500'`, `'theme-secondary'`) or a direct color string (`'#ff0000'`). The keys match the global `Theme` shape (`primary`, `secondary`, `success`, `error`, `warning`, `disabled`, `loading`).
|
|
462
|
+
|
|
463
|
+
**Alpha suffix works**: `theme-primary-200` on a component with `theme={{ primary: 'color-red-500' }}` resolves to `color-red-500` at 20% opacity via `color-mix()`.
|
|
464
|
+
|
|
465
|
+
**Dark mode**: overrides that point at palette tokens (e.g., `'color-red-500'`) keep responding to global dark-mode switching, because the resolution returns the underlying CSS variable. Overrides that point at raw hex literals (`'#ff0000'`) bypass the palette and do **not** swap with dark mode — use palette tokens whenever you need dark-mode reactivity.
|
|
466
|
+
|
|
467
|
+
**Scope**: the override applies only to the Element receiving the `theme` prop. Children that re-use `theme-primary` resolve against the global theme, not the parent's override. To remap an entire subtree, wrap it in a nested `ThemeProvider` instead, or set the `theme` prop on each child.
|
|
468
|
+
|
|
416
469
|
### Smart Text Contrast
|
|
417
470
|
|
|
418
471
|
For text that needs to be visible on any background color (light, dark, or dynamic gradients), App-Studio provides a smart contrast feature.
|