react-native-tinyui 0.5.0 → 1.0.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/README.md +351 -22
- package/ios/ConcentricView/TinyuiConcentricView.h +12 -0
- package/ios/ConcentricView/TinyuiConcentricView.mm +60 -0
- package/ios/Core/Tinyui.mm +54 -0
- package/ios/Core/TinyuiComponentClasses.mm +44 -0
- package/ios/Menu/TinyuiMenuBuilder.swift +238 -0
- package/ios/Menu/TinyuiMenuProvider.swift +51 -85
- package/ios/Menu/TinyuiMenuView.mm +12 -35
- package/ios/Popover/TinyuiPopoverProvider.swift +198 -44
- package/ios/Popover/TinyuiPopoverView.mm +26 -1
- package/ios/SFSymbol/TinyuiSFSymbolEffects.h +9 -0
- package/ios/SFSymbol/TinyuiSFSymbolEffects.mm +180 -0
- package/ios/SFSymbol/TinyuiSFSymbolImage.h +8 -0
- package/ios/SFSymbol/TinyuiSFSymbolImage.mm +141 -0
- package/ios/SFSymbol/TinyuiSFSymbolShadowNode.h +31 -0
- package/ios/SFSymbol/TinyuiSFSymbolShadowNode.mm +30 -0
- package/ios/SFSymbol/TinyuiSFSymbolView.h +4 -0
- package/ios/SFSymbol/TinyuiSFSymbolView.mm +173 -0
- package/ios/Stepper/TinyuiStepperShadowNode.h +32 -0
- package/ios/Stepper/TinyuiStepperShadowNode.mm +28 -0
- package/ios/Stepper/TinyuiStepperView.h +12 -0
- package/ios/Stepper/TinyuiStepperView.mm +128 -0
- package/ios/TipKit/TinyuiTip.swift +31 -0
- package/ios/TipKit/TinyuiTipPopoverProvider.swift +276 -0
- package/ios/TipKit/TinyuiTipPopoverView.h +8 -0
- package/ios/TipKit/TinyuiTipPopoverView.mm +114 -0
- package/ios/TipKit/TinyuiTipsRuntime.swift +148 -0
- package/lib/module/ConcentricView/ConcentricViewNativeComponent.ts +14 -0
- package/lib/module/ConcentricView/index.js +29 -0
- package/lib/module/ConcentricView/index.js.map +1 -0
- package/lib/module/ConcentricView/types.js +4 -0
- package/lib/module/ConcentricView/types.js.map +1 -0
- package/lib/module/Menu/MenuNativeComponent.ts +1 -3
- package/lib/module/Menu/index.js +4 -9
- package/lib/module/Menu/index.js.map +1 -1
- package/lib/module/Menu/options.js +4 -12
- package/lib/module/Menu/options.js.map +1 -1
- package/lib/module/NativeTinyui.js.map +1 -1
- package/lib/module/Popover/index.js +4 -2
- package/lib/module/Popover/index.js.map +1 -1
- package/lib/module/SFSymbol/SFSymbolNativeComponent.ts +20 -0
- package/lib/module/SFSymbol/index.js +73 -0
- package/lib/module/SFSymbol/index.js.map +1 -0
- package/lib/module/SFSymbol/options.js +79 -0
- package/lib/module/SFSymbol/options.js.map +1 -0
- package/lib/module/SFSymbol/types.js +4 -0
- package/lib/module/SFSymbol/types.js.map +1 -0
- package/lib/module/Stepper/StepperNativeComponent.ts +29 -0
- package/lib/module/Stepper/index.js +75 -0
- package/lib/module/Stepper/index.js.map +1 -0
- package/lib/module/Stepper/types.js +4 -0
- package/lib/module/Stepper/types.js.map +1 -0
- package/lib/module/TipKit/Popover.js +89 -0
- package/lib/module/TipKit/Popover.js.map +1 -0
- package/lib/module/TipKit/TipPopoverNativeComponent.ts +37 -0
- package/lib/module/TipKit/index.js +28 -0
- package/lib/module/TipKit/index.js.map +1 -0
- package/lib/module/TipKit/types.js +4 -0
- package/lib/module/TipKit/types.js.map +1 -0
- package/lib/module/TipKit/validation.js +24 -0
- package/lib/module/TipKit/validation.js.map +1 -0
- package/lib/module/index.js +4 -0
- package/lib/module/index.js.map +1 -1
- package/lib/module/utils/getNativeTinyui.js.map +1 -1
- package/lib/typescript/src/ConcentricView/ConcentricViewNativeComponent.d.ts +7 -0
- package/lib/typescript/src/ConcentricView/ConcentricViewNativeComponent.d.ts.map +1 -0
- package/lib/typescript/src/ConcentricView/index.d.ts +4 -0
- package/lib/typescript/src/ConcentricView/index.d.ts.map +1 -0
- package/lib/typescript/src/ConcentricView/types.d.ts +6 -0
- package/lib/typescript/src/ConcentricView/types.d.ts.map +1 -0
- package/lib/typescript/src/Menu/MenuNativeComponent.d.ts +2 -3
- package/lib/typescript/src/Menu/MenuNativeComponent.d.ts.map +1 -1
- package/lib/typescript/src/Menu/index.d.ts +1 -1
- package/lib/typescript/src/Menu/index.d.ts.map +1 -1
- package/lib/typescript/src/Menu/options.d.ts +1 -5
- package/lib/typescript/src/Menu/options.d.ts.map +1 -1
- package/lib/typescript/src/Menu/types.d.ts +16 -4
- package/lib/typescript/src/Menu/types.d.ts.map +1 -1
- package/lib/typescript/src/NativeTinyui.d.ts +2 -0
- package/lib/typescript/src/NativeTinyui.d.ts.map +1 -1
- package/lib/typescript/src/Popover/index.d.ts.map +1 -1
- package/lib/typescript/src/Popover/types.d.ts +2 -0
- package/lib/typescript/src/Popover/types.d.ts.map +1 -1
- package/lib/typescript/src/SFSymbol/SFSymbolNativeComponent.d.ts +11 -0
- package/lib/typescript/src/SFSymbol/SFSymbolNativeComponent.d.ts.map +1 -0
- package/lib/typescript/src/SFSymbol/index.d.ts +4 -0
- package/lib/typescript/src/SFSymbol/index.d.ts.map +1 -0
- package/lib/typescript/src/SFSymbol/options.d.ts +86 -0
- package/lib/typescript/src/SFSymbol/options.d.ts.map +1 -0
- package/lib/typescript/src/SFSymbol/types.d.ts +113 -0
- package/lib/typescript/src/SFSymbol/types.d.ts.map +1 -0
- package/lib/typescript/src/Stepper/StepperNativeComponent.d.ts +21 -0
- package/lib/typescript/src/Stepper/StepperNativeComponent.d.ts.map +1 -0
- package/lib/typescript/src/Stepper/index.d.ts +4 -0
- package/lib/typescript/src/Stepper/index.d.ts.map +1 -0
- package/lib/typescript/src/Stepper/types.d.ts +24 -0
- package/lib/typescript/src/Stepper/types.d.ts.map +1 -0
- package/lib/typescript/src/TipKit/Popover.d.ts +3 -0
- package/lib/typescript/src/TipKit/Popover.d.ts.map +1 -0
- package/lib/typescript/src/TipKit/TipPopoverNativeComponent.d.ts +38 -0
- package/lib/typescript/src/TipKit/TipPopoverNativeComponent.d.ts.map +1 -0
- package/lib/typescript/src/TipKit/index.d.ts +10 -0
- package/lib/typescript/src/TipKit/index.d.ts.map +1 -0
- package/lib/typescript/src/TipKit/types.d.ts +46 -0
- package/lib/typescript/src/TipKit/types.d.ts.map +1 -0
- package/lib/typescript/src/TipKit/validation.d.ts +4 -0
- package/lib/typescript/src/TipKit/validation.d.ts.map +1 -0
- package/lib/typescript/src/index.d.ts +9 -1
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/lib/typescript/src/utils/getNativeTinyui.d.ts +1 -1
- package/lib/typescript/src/utils/getNativeTinyui.d.ts.map +1 -1
- package/package.json +37 -2
- package/{Tinyui.podspec → react-native-tinyui.podspec} +23 -2
- package/src/ConcentricView/ConcentricViewNativeComponent.ts +14 -0
- package/src/ConcentricView/index.tsx +34 -0
- package/src/ConcentricView/types.ts +6 -0
- package/src/Menu/MenuNativeComponent.ts +1 -3
- package/src/Menu/index.tsx +6 -6
- package/src/Menu/options.ts +2 -20
- package/src/Menu/types.ts +18 -4
- package/src/NativeTinyui.ts +2 -0
- package/src/Popover/index.tsx +8 -3
- package/src/Popover/types.ts +2 -0
- package/src/SFSymbol/SFSymbolNativeComponent.ts +20 -0
- package/src/SFSymbol/index.tsx +89 -0
- package/src/SFSymbol/options.ts +116 -0
- package/src/SFSymbol/types.ts +158 -0
- package/src/Stepper/StepperNativeComponent.ts +29 -0
- package/src/Stepper/index.tsx +91 -0
- package/src/Stepper/types.ts +24 -0
- package/src/TipKit/Popover.tsx +87 -0
- package/src/TipKit/TipPopoverNativeComponent.ts +37 -0
- package/src/TipKit/index.ts +47 -0
- package/src/TipKit/types.ts +57 -0
- package/src/TipKit/validation.ts +39 -0
- package/src/index.tsx +30 -0
- package/src/utils/getNativeTinyui.ts +8 -1
- package/ios/Core/TinyuiHostingHelpers.swift +0 -74
- package/ios/Menu/TinyuiMenuViewSwift.swift +0 -326
- package/ios/Popover/TinyuiPopoverViewSwift.swift +0 -88
package/README.md
CHANGED
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
# react-native-tinyui
|
|
2
2
|
|
|
3
|
-
Dependency-free, native iOS `Menu`, `Popover` and `LiquidGlassText` components for React Native's
|
|
3
|
+
Dependency-free, native iOS `Menu`, `Popover`, `TipKit`, `Stepper`, `ConcentricView`, `SFSymbol` and `LiquidGlassText` components for React Native's
|
|
4
4
|
New Architecture. The public API follows normal React composition patterns;
|
|
5
|
-
the native UI is
|
|
5
|
+
the native UI is exposed through Fabric components. `Menu`, `Popover`, `Stepper`, `ConcentricView` and `SFSymbol` are
|
|
6
|
+
implemented directly with UIKit; `LiquidGlassText` uses SwiftUI where needed.
|
|
6
7
|
|
|
7
8
|
The initial component behavior is inspired by
|
|
8
9
|
[`@expo/ui`](https://github.com/expo/expo/tree/main/packages/expo-ui), but this
|
|
9
10
|
package does not require Expo Modules or any other runtime package. The
|
|
10
|
-
React Native ↔
|
|
11
|
+
React Native ↔ native view integration follows the approach used by
|
|
11
12
|
[`react-native-pager-view`](https://github.com/callstack/react-native-pager-view):
|
|
12
|
-
a Fabric component
|
|
13
|
+
a Fabric component owns the platform view that renders its content.
|
|
13
14
|
|
|
14
15
|
## Requirements
|
|
15
16
|
|
|
@@ -45,6 +46,10 @@ Available components:
|
|
|
45
46
|
- `Menu`
|
|
46
47
|
- `Popover`
|
|
47
48
|
- `LiquidGlassText`
|
|
49
|
+
- `Stepper`
|
|
50
|
+
- `ConcentricView`
|
|
51
|
+
- `SFSymbol`
|
|
52
|
+
- `TipKit` (enables `TipKit.Popover`, `TipKit.configure` and `TipKit.invalidate`)
|
|
48
53
|
|
|
49
54
|
All components are enabled by default. Use an empty `components` array to
|
|
50
55
|
compile only the TurboModule core. Run `pod install` again whenever this list
|
|
@@ -57,6 +62,10 @@ Component-specific JavaScript entry points are also available:
|
|
|
57
62
|
import { Menu } from 'react-native-tinyui/menu';
|
|
58
63
|
import { Popover } from 'react-native-tinyui/popover';
|
|
59
64
|
import { LiquidGlassText } from 'react-native-tinyui/liquid-glass-text';
|
|
65
|
+
import { Stepper } from 'react-native-tinyui/stepper';
|
|
66
|
+
import { ConcentricView } from 'react-native-tinyui/concentric-view';
|
|
67
|
+
import { SFSymbol } from 'react-native-tinyui/sf-symbol';
|
|
68
|
+
import { TipKit } from 'react-native-tinyui/tip-kit';
|
|
60
69
|
```
|
|
61
70
|
|
|
62
71
|
The root `react-native-tinyui` imports remain supported for backwards
|
|
@@ -66,9 +75,8 @@ compatibility. JavaScript entry points provide cleaner dependency boundaries;
|
|
|
66
75
|
## Menu
|
|
67
76
|
|
|
68
77
|
`Menu` uses `children` as its trigger and receives its native menu entries
|
|
69
|
-
through the `options` prop.
|
|
70
|
-
|
|
71
|
-
menu.
|
|
78
|
+
through the `options` prop. A tap opens the native menu; `onActionPress`
|
|
79
|
+
receives every selected action's stable id and displayed title.
|
|
72
80
|
|
|
73
81
|
```tsx
|
|
74
82
|
import { Menu } from 'react-native-tinyui';
|
|
@@ -76,34 +84,40 @@ import { Menu } from 'react-native-tinyui';
|
|
|
76
84
|
<Menu
|
|
77
85
|
accessibilityLabel="Document actions"
|
|
78
86
|
title="Document actions"
|
|
79
|
-
|
|
87
|
+
onActionPress={({ nativeEvent }) => {
|
|
88
|
+
if (nativeEvent.id === 'rename') rename();
|
|
89
|
+
if (nativeEvent.id === 'toggle-pinned') togglePinned();
|
|
90
|
+
if (nativeEvent.id === 'copy-link') copyLink();
|
|
91
|
+
if (nativeEvent.id === 'invite-people') invitePeople();
|
|
92
|
+
if (nativeEvent.id === 'remove') remove();
|
|
93
|
+
}}
|
|
80
94
|
options={[
|
|
81
95
|
{
|
|
96
|
+
id: 'rename',
|
|
82
97
|
title: 'Rename',
|
|
83
98
|
systemImage: 'square.and.pencil',
|
|
84
|
-
onSelect: rename,
|
|
85
99
|
},
|
|
86
100
|
{
|
|
101
|
+
id: 'toggle-pinned',
|
|
87
102
|
title: 'Pinned',
|
|
88
103
|
state: 'on',
|
|
89
104
|
systemImage: 'pin',
|
|
90
|
-
onSelect: togglePinned,
|
|
91
105
|
},
|
|
92
106
|
{
|
|
93
107
|
type: 'submenu',
|
|
94
108
|
title: 'Share',
|
|
95
109
|
systemImage: 'square.and.arrow.up',
|
|
96
110
|
options: [
|
|
97
|
-
{
|
|
98
|
-
{
|
|
111
|
+
{ id: 'copy-link', title: 'Copy link' },
|
|
112
|
+
{ id: 'invite-people', title: 'Invite people' },
|
|
99
113
|
],
|
|
100
114
|
},
|
|
101
115
|
{ type: 'divider' },
|
|
102
116
|
{
|
|
117
|
+
id: 'remove',
|
|
103
118
|
title: 'Delete',
|
|
104
119
|
destructive: true,
|
|
105
120
|
systemImage: 'trash',
|
|
106
|
-
onSelect: remove,
|
|
107
121
|
},
|
|
108
122
|
]}
|
|
109
123
|
>
|
|
@@ -119,11 +133,14 @@ or `type: 'divider'` for structural entries; nested entries use their own
|
|
|
119
133
|
simply render no image.
|
|
120
134
|
|
|
121
135
|
Action options support `subtitle`, `state`, `destructive`, `disabled`, `hidden`,
|
|
122
|
-
and `keepOpen`.
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
136
|
+
and `keepOpen`. Set explicit `id` values when handling `onActionPress`; actions
|
|
137
|
+
without one receive a generated menu-path id. Use `icon` to load an image from
|
|
138
|
+
the containing app's asset catalog; `iconColor` tints either an asset image or
|
|
139
|
+
an SF Symbol and accepts React Native `ColorValue`s, including dynamic and
|
|
140
|
+
semantic iOS colors. UIKit doesn't expose custom menu title colors, so the
|
|
141
|
+
deprecated `titleColor` field is retained only for source compatibility; use
|
|
142
|
+
`destructive` for system red styling. Submenus support the same label fields
|
|
143
|
+
plus `destructive`, `disabled`, `hidden`, and `displayInline`.
|
|
127
144
|
|
|
128
145
|
## Popover
|
|
129
146
|
|
|
@@ -138,10 +155,9 @@ import { Popover, PopoverClose } from 'react-native-tinyui';
|
|
|
138
155
|
defaultOpen={false}
|
|
139
156
|
attachmentAnchor="bottom"
|
|
140
157
|
arrowEdge="top"
|
|
141
|
-
contentSize={{ width: 320, height: 220 }}
|
|
142
158
|
onOpenChange={(open) => console.log({ open })}
|
|
143
159
|
content={({ close }) => (
|
|
144
|
-
<View style={
|
|
160
|
+
<View style={{ width: 280, padding: 20 }}>
|
|
145
161
|
<Text>Any React Native content can be rendered here.</Text>
|
|
146
162
|
<PopoverClose close={close} style={styles.doneButton}>
|
|
147
163
|
<Text>Done</Text>
|
|
@@ -161,8 +177,114 @@ the `content` prop, which can be a node or a render function receiving
|
|
|
161
177
|
as `Popover.Close`) renders a `Pressable` that calls `close` when pressed.
|
|
162
178
|
|
|
163
179
|
Use `open` with `onOpenChange` for a controlled popover, or `defaultOpen` for an
|
|
164
|
-
uncontrolled one.
|
|
165
|
-
|
|
180
|
+
uncontrolled one. The layout of `content` determines the popover's preferred
|
|
181
|
+
size: set `width` and optionally `height` on its root view, or let its children
|
|
182
|
+
determine the height. Size changes are applied while the popover is visible.
|
|
183
|
+
UIKit may limit the displayed size to the available space on screen.
|
|
184
|
+
|
|
185
|
+
Keep the content background transparent to show the native popover material:
|
|
186
|
+
Liquid Glass on iOS 26+ when built with Xcode 26+, and the system popover
|
|
187
|
+
appearance on earlier iOS versions. `style` on `Popover` styles the trigger's
|
|
188
|
+
outer container, not the presented content.
|
|
189
|
+
|
|
190
|
+
## TipKit
|
|
191
|
+
|
|
192
|
+
`TipKit.Popover` anchors a native TipKit `TipUIPopoverViewController` to ordinary
|
|
193
|
+
React Native children on iOS 17+. The children retain their own touch handlers;
|
|
194
|
+
the tip appears automatically when both `enabled` and TipKit's eligibility allow
|
|
195
|
+
it. Its text, SF Symbol, action buttons, display history and invalidation use
|
|
196
|
+
Apple's TipKit framework. No additional package is required.
|
|
197
|
+
|
|
198
|
+
Configure TipKit once, **before mounting tips** (for example, during app startup):
|
|
199
|
+
|
|
200
|
+
```tsx
|
|
201
|
+
import { TipKit, SFSymbol } from 'react-native-tinyui';
|
|
202
|
+
import { Pressable } from 'react-native';
|
|
203
|
+
|
|
204
|
+
await TipKit.configure({ displayFrequency: 'daily' });
|
|
205
|
+
|
|
206
|
+
// Inside your screen:
|
|
207
|
+
<TipKit.Popover
|
|
208
|
+
tipId="favorite-feature-v1"
|
|
209
|
+
title="Keep your favorites close"
|
|
210
|
+
message="Save an item to find it quickly next time."
|
|
211
|
+
systemImage="star"
|
|
212
|
+
enabled={isScreenFocused && !hasFavorites}
|
|
213
|
+
maxDisplayCount={3}
|
|
214
|
+
actions={[{ id: 'learn-more', title: 'Learn more' }]}
|
|
215
|
+
onActionPress={({ id }) => {
|
|
216
|
+
if (id === 'learn-more') openHelp();
|
|
217
|
+
}}
|
|
218
|
+
onStatusChange={(status) => console.log(status)}
|
|
219
|
+
onVisibleChange={(visible) => console.log({ visible })}
|
|
220
|
+
onError={(error) => console.warn(error.message)}
|
|
221
|
+
>
|
|
222
|
+
<Pressable onPress={async () => {
|
|
223
|
+
await saveFavorite();
|
|
224
|
+
await TipKit.invalidate('favorite-feature-v1', 'actionPerformed');
|
|
225
|
+
}}>
|
|
226
|
+
<SFSymbol name="star" size={24} />
|
|
227
|
+
</Pressable>
|
|
228
|
+
</TipKit.Popover>;
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
| Prop | Description | Default |
|
|
232
|
+
| --- | --- | --- |
|
|
233
|
+
| `tipId` | Required stable identity for persistent history | — |
|
|
234
|
+
| `title` | Required nonempty title, already localized by the app | — |
|
|
235
|
+
| `message` | Supporting plain text | — |
|
|
236
|
+
| `systemImage` | SF Symbol name | — |
|
|
237
|
+
| `actions` | Buttons with unique nonempty `{ id, title }` values | `[]` |
|
|
238
|
+
| `enabled` | Allows presentation; does not override TipKit eligibility | `true` |
|
|
239
|
+
| `maxDisplayCount` | Positive integer; automatically invalidates after this many displays | Unlimited |
|
|
240
|
+
| `ignoresDisplayFrequency` | Exempts this tip from the app-wide display interval | `false` |
|
|
241
|
+
| `arrowEdge` | Preferred bubble edge: `top`, `bottom`, `leading`, `trailing`, `auto` | `auto` |
|
|
242
|
+
| `onStatusChange` | `{ status: 'pending' \| 'available' }` or `{ status: 'invalidated', reason }` | — |
|
|
243
|
+
| `onVisibleChange` | Whether the native bubble is actually visible | — |
|
|
244
|
+
| `onActionPress` | Receives the selected `{ id, title }`; does not automatically invalidate | — |
|
|
245
|
+
| `onError` | Receives `{ code, message }`; otherwise a warning is logged | — |
|
|
246
|
+
|
|
247
|
+
The component accepts standard `ViewProps` and a native view ref. `style` lays
|
|
248
|
+
out the anchor, not the bubble. UIKit chooses the bubble's size and may adapt
|
|
249
|
+
the arrow to available space; leading/trailing follow layout direction. Bubble
|
|
250
|
+
content is native text/images/actions; `children` supplies only the anchor.
|
|
251
|
+
Content edits apply to the next presentation; the currently visible bubble
|
|
252
|
+
retains the content and action labels it was presented with.
|
|
253
|
+
|
|
254
|
+
### Configuration and lifetime
|
|
255
|
+
|
|
256
|
+
`TipKit.configure({ displayFrequency })` returns a promise. Supported frequencies
|
|
257
|
+
are `immediate`, `hourly`, `daily` (default), `weekly` and `monthly`. This is an
|
|
258
|
+
app-wide TipKit setting. Repeating the same configuration is safe, including
|
|
259
|
+
after Fast Refresh; changing it later rejects with `E_TIPS_ALREADY_CONFIGURED`.
|
|
260
|
+
Coordinate this startup configuration with any other native TipKit integration.
|
|
261
|
+
Initialization errors reject the promise; an enabled view mounted too early
|
|
262
|
+
reports `E_TIPS_NOT_CONFIGURED` and can recover after configuration succeeds.
|
|
263
|
+
|
|
264
|
+
`TipKit.invalidate(tipId, reason = 'actionPerformed')` also returns a promise and
|
|
265
|
+
requires configuration first. It persistently invalidates the ID even when no
|
|
266
|
+
view for that tip is mounted. `reason` may be `actionPerformed` or `tipClosed`.
|
|
267
|
+
System invalidations can additionally report `displayCountExceeded`,
|
|
268
|
+
`displayDurationExceeded`, or `unknown` through `onStatusChange`.
|
|
269
|
+
|
|
270
|
+
Keep IDs stable across renders, app launches and translations. All instances
|
|
271
|
+
with the same ID share their TipKit history. Keep `maxDisplayCount` and
|
|
272
|
+
`ignoresDisplayFrequency` consistent for each ID; conflicting values report
|
|
273
|
+
`E_CONFLICTING_TIP_OPTIONS`. Use a deliberate new versioned ID for a new feature
|
|
274
|
+
tip. Hiding a tip, unmounting it or reconfiguring TinyUI never resets history.
|
|
275
|
+
|
|
276
|
+
Use `enabled={isScreenFocused && businessCondition}` with your navigation
|
|
277
|
+
library. TinyUI also waits for a visible anchor and a free presenter, and
|
|
278
|
+
dismisses on detachment or when the anchor leaves the visible area. It presents
|
|
279
|
+
at most one TinyUI tip at a time and waits while another modal occupies the
|
|
280
|
+
presenter. An outside dismissal suppresses immediate reopening for that mount;
|
|
281
|
+
toggle `enabled` off and on to allow another attempt, subject to TipKit's state.
|
|
282
|
+
The system close button can permanently invalidate a tip.
|
|
283
|
+
|
|
284
|
+
This first version exposes popover tips and JS eligibility conditions. Inline
|
|
285
|
+
`TipUIView`, native rule/event builders, TipGroup and datastore reset APIs are
|
|
286
|
+
not exposed. The example's **New demo tip** button deliberately creates another
|
|
287
|
+
ID for trying the behavior again without clearing the app's TipKit datastore.
|
|
166
288
|
|
|
167
289
|
## LiquidGlassText
|
|
168
290
|
|
|
@@ -230,6 +352,213 @@ their translated string directly.
|
|
|
230
352
|
The adapted Core Text outline implementation retains the upstream MIT notice in
|
|
231
353
|
[`ios/LiquidGlassText/GlassText-LICENSE`](ios/LiquidGlassText/GlassText-LICENSE).
|
|
232
354
|
|
|
355
|
+
## Stepper
|
|
356
|
+
|
|
357
|
+
`Stepper` bridges UIKit's
|
|
358
|
+
[`UIStepper`](https://developer.apple.com/documentation/uikit/uistepper) through
|
|
359
|
+
Fabric. It supports fractional steps, press-and-hold repeat, and wrapping at
|
|
360
|
+
the bounds on iOS 17+.
|
|
361
|
+
|
|
362
|
+
```tsx
|
|
363
|
+
import { useState } from 'react';
|
|
364
|
+
import { Stepper } from 'react-native-tinyui';
|
|
365
|
+
|
|
366
|
+
function Quantity() {
|
|
367
|
+
const [quantity, setQuantity] = useState(1);
|
|
368
|
+
return (
|
|
369
|
+
<Stepper
|
|
370
|
+
accessibilityLabel="Quantity"
|
|
371
|
+
value={quantity}
|
|
372
|
+
minimumValue={1}
|
|
373
|
+
maximumValue={10}
|
|
374
|
+
onValueChange={setQuantity}
|
|
375
|
+
/>
|
|
376
|
+
);
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
// Uncontrolled: UIKit owns the value after initialization.
|
|
380
|
+
<Stepper defaultValue={2.5} stepValue={0.5} maximumValue={5} wraps />;
|
|
381
|
+
```
|
|
382
|
+
|
|
383
|
+
| Prop | Description | Default |
|
|
384
|
+
| --- | --- | --- |
|
|
385
|
+
| `value` | Controlled numeric value | — |
|
|
386
|
+
| `defaultValue` | Initial value when uncontrolled; later changes are ignored | `0` |
|
|
387
|
+
| `minimumValue` | Lower bound | `0` |
|
|
388
|
+
| `maximumValue` | Upper bound, at least `minimumValue` | `100` |
|
|
389
|
+
| `stepValue` | Positive increment/decrement amount | `1` |
|
|
390
|
+
| `isContinuous` | Report changes during interaction; otherwise report on release | `true` |
|
|
391
|
+
| `autorepeat` | Repeatedly step while holding a button | `true` |
|
|
392
|
+
| `wraps` | Continue from the opposite bound when stepping past an end | `false` |
|
|
393
|
+
| `disabled` | Prevent user interaction | `false` |
|
|
394
|
+
| `onValueChange` | Callback receiving the new number after user interaction | — |
|
|
395
|
+
|
|
396
|
+
When `value` is supplied, update it in `onValueChange` to accept changes. Keeping
|
|
397
|
+
the same `value` restores the native control to that value. Omit `value` to let
|
|
398
|
+
UIKit manage the state. Programmatic value or range changes do not call
|
|
399
|
+
`onValueChange`.
|
|
400
|
+
|
|
401
|
+
All numeric props must be finite, `stepValue` must be positive, and
|
|
402
|
+
`maximumValue` must be at least `minimumValue`; invalid inputs throw a descriptive
|
|
403
|
+
error. Values are clamped to the current range. Equal bounds produce a fixed
|
|
404
|
+
value. Changing an uncontrolled range also clamps its current native value.
|
|
405
|
+
|
|
406
|
+
The component accepts standard `ViewProps` (except `children`) and a native view
|
|
407
|
+
ref. Native accessibility behavior is preserved; use `accessibilityLabel` to
|
|
408
|
+
name the value being adjusted. Fabric measures the native control's intrinsic
|
|
409
|
+
size. A larger `style` frame centers the native control without stretching
|
|
410
|
+
its buttons. Put padding on a surrounding `View`. Like UIKit's control, the
|
|
411
|
+
stepper shows the minus and plus buttons; render a separate `Text` for the value.
|
|
412
|
+
|
|
413
|
+
## ConcentricView
|
|
414
|
+
|
|
415
|
+
`ConcentricView` is a Fabric container that lets UIKit resolve its corner radii
|
|
416
|
+
relative to its containing view. On iOS 26+, it applies
|
|
417
|
+
[`UICornerRadius.containerConcentricRadius`](https://developer.apple.com/documentation/uikit/uicornerradius-c.class/containerconcentricradius)
|
|
418
|
+
through `UIView.cornerConfiguration`. UIKit handles geometry and layout changes.
|
|
419
|
+
Building this component requires **Xcode 26+**; on iOS 17–25 it uses
|
|
420
|
+
`minimumRadius` as a fixed corner radius.
|
|
421
|
+
|
|
422
|
+
```tsx
|
|
423
|
+
import { Text } from 'react-native';
|
|
424
|
+
import { ConcentricView } from 'react-native-tinyui';
|
|
425
|
+
|
|
426
|
+
<ConcentricView
|
|
427
|
+
minimumRadius={32}
|
|
428
|
+
style={{ padding: 12, backgroundColor: '#DCEBFF' }}
|
|
429
|
+
>
|
|
430
|
+
<ConcentricView
|
|
431
|
+
minimumRadius={12}
|
|
432
|
+
style={{ padding: 20, backgroundColor: '#3875D5' }}
|
|
433
|
+
>
|
|
434
|
+
<Text>UIKit resolves each corner.</Text>
|
|
435
|
+
</ConcentricView>
|
|
436
|
+
</ConcentricView>;
|
|
437
|
+
```
|
|
438
|
+
|
|
439
|
+
`minimumRadius` defaults to `0` and must be finite and nonnegative. It only
|
|
440
|
+
controls the fixed fallback radius before iOS 26; iOS 26+ resolves corners
|
|
441
|
+
entirely through UIKit, without a minimum radius. The component accepts
|
|
442
|
+
`children`, standard `ViewProps`, and a native view ref. It clips content
|
|
443
|
+
by default; use `style={{ overflow: 'visible' }}` to allow overflow. Avoid
|
|
444
|
+
`style.borderRadius` and individual corner radii on this component.
|
|
445
|
+
React Native's custom border, outline, and shadow drawing does not calculate
|
|
446
|
+
concentric radii; keep those decorations on a surrounding view when needed.
|
|
447
|
+
|
|
448
|
+
## SFSymbol
|
|
449
|
+
|
|
450
|
+
`SFSymbol` uses **UIKit `UIImageView` + Apple's Symbols framework**, exposed
|
|
451
|
+
through Fabric. It does not embed a SwiftUI hosting view. Xcode 26+ is required
|
|
452
|
+
to build; the deployment target remains iOS 17. Yoga measures the configured
|
|
453
|
+
symbol's natural size, so `style.width` and `style.height` are optional.
|
|
454
|
+
|
|
455
|
+
```tsx
|
|
456
|
+
import { useState } from 'react';
|
|
457
|
+
import { Button, PlatformColor, View } from 'react-native';
|
|
458
|
+
import { SFSymbol } from 'react-native-tinyui';
|
|
459
|
+
|
|
460
|
+
function Favorite() {
|
|
461
|
+
const [selected, setSelected] = useState(false);
|
|
462
|
+
const [trigger, setTrigger] = useState(0);
|
|
463
|
+
return (
|
|
464
|
+
<View>
|
|
465
|
+
<SFSymbol
|
|
466
|
+
name={selected ? 'heart.fill' : 'heart'}
|
|
467
|
+
size={32}
|
|
468
|
+
weight="semibold"
|
|
469
|
+
renderingMode="hierarchical"
|
|
470
|
+
color={PlatformColor('systemPinkColor')}
|
|
471
|
+
effect={{ type: 'bounce', trigger, options: { repeat: false } }}
|
|
472
|
+
contentTransition={{ type: 'magicReplace', direction: 'downUp' }}
|
|
473
|
+
/>
|
|
474
|
+
<Button title="Favorite" onPress={() => {
|
|
475
|
+
setSelected(!selected);
|
|
476
|
+
setTrigger(trigger + 1);
|
|
477
|
+
}} />
|
|
478
|
+
</View>
|
|
479
|
+
);
|
|
480
|
+
}
|
|
481
|
+
```
|
|
482
|
+
|
|
483
|
+
### Image configuration
|
|
484
|
+
|
|
485
|
+
| Prop | Values / behavior |
|
|
486
|
+
| --- | --- |
|
|
487
|
+
| `name` | Required complete symbol name, including variants such as `square.fill`. Missing symbols render empty. |
|
|
488
|
+
| `source` | `system` (default), or `asset` for a custom SF Symbol in the app's asset catalog. Ordinary bitmap assets are not accepted. |
|
|
489
|
+
| `size` | Positive point size; default `17`. |
|
|
490
|
+
| `weight` | `unspecified` (default), `ultraLight`, `thin`, `light`, `regular`, `medium`, `semibold`, `bold`, `heavy`, `black`. |
|
|
491
|
+
| `scale` | `default`, `unspecified`, `small`, `medium`, `large`. |
|
|
492
|
+
| `textStyle` | `extraLargeTitle`, `extraLargeTitle2`, `largeTitle`, `title1`–`title3`, `headline`, `subheadline`, `body`, `callout`, `footnote`, `caption1`, `caption2`. Overrides `size` and supplies the style's weight unless explicitly set. |
|
|
493
|
+
| `fontFamily` | Font/PostScript name used to derive symbol metrics; unknown fonts use system metrics. |
|
|
494
|
+
| `allowFontScaling` | Default `true`. Scales the base point size by React Native's `fontScale`, including when using `textStyle`. |
|
|
495
|
+
| `maxFontSizeMultiplier` | Cap on that scale, >= 1. Omitted or `0` means unlimited. |
|
|
496
|
+
| `renderingMode` | `automatic` (default), `monochrome`, `hierarchical`, `palette`, `multicolor`. |
|
|
497
|
+
| `color` | React Native `ColorValue`, including `PlatformColor` and `DynamicColorIOS`. Defaults to semantic label color. |
|
|
498
|
+
| `paletteColors` | One to three `ColorValue`s in primary, secondary, tertiary order, used in palette mode. If omitted, the palette uses `color`. |
|
|
499
|
+
| `variableValue` | Progress from `0` to `1`; omitted uses the symbol default. Requires a symbol with variable annotations. |
|
|
500
|
+
| `variableValueMode` | `automatic` (default), `color`, `draw` (iOS 26+). |
|
|
501
|
+
| `colorRenderingMode` | `automatic` (default), `flat`, `gradient` (iOS 26+). |
|
|
502
|
+
| `resizeMode` | `center` (default, natural point size), `contain`, `cover`, `stretch`, for explicitly sized frames. Use `style.overflow: 'hidden'` to clip. |
|
|
503
|
+
|
|
504
|
+
Standard `ViewProps`, styles and refs are supported. Symbols are decorative
|
|
505
|
+
(`accessible={false}`) by default; supply `accessible` and a meaningful
|
|
506
|
+
`accessibilityLabel` for standalone images. Use a `Pressable` for interactive icons.
|
|
507
|
+
|
|
508
|
+
### Preset effects
|
|
509
|
+
|
|
510
|
+
Pass one object to `effect`, or an array of **distinct** effect types to combine
|
|
511
|
+
compatible effects. UIKit determines how combined effects interact.
|
|
512
|
+
|
|
513
|
+
| `type` | Configuration | Minimum iOS |
|
|
514
|
+
| --- | --- | --- |
|
|
515
|
+
| `bounce`, `scale`, `appear`, `disappear` | `direction: 'up' \| 'down'`, `scope` | 17 |
|
|
516
|
+
| `pulse` | `scope` | 17 |
|
|
517
|
+
| `variableColor` | `iteration: 'iterative' \| 'cumulative'`, `reversing: boolean`, `inactiveLayers: 'hide' \| 'dim'` | 17 |
|
|
518
|
+
| `wiggle` | `direction: 'up' \| 'down' \| 'left' \| 'right' \| 'forward' \| 'backward' \| 'clockwise' \| 'counterClockwise'`, or `angle` in degrees clockwise from +x; `scope` | 18 |
|
|
519
|
+
| `rotate` | `direction: 'clockwise' \| 'counterClockwise'`, `scope` | 18 |
|
|
520
|
+
| `breathe` | `style: 'plain' \| 'pulse'`, `scope` | 18 |
|
|
521
|
+
| `drawOn` | `scope`, also accepting `individually` | 26 |
|
|
522
|
+
| `drawOff` | `scope`, also accepting `individually`; `reversed: boolean` | 26 |
|
|
523
|
+
|
|
524
|
+
`scope` is `byLayer` or `wholeSymbol`; omit any modifier to keep Apple's default.
|
|
525
|
+
Each preset also accepts:
|
|
526
|
+
|
|
527
|
+
- `active` (default `true`): apply/remove the effect. Scale and visibility
|
|
528
|
+
effects hold their state until removed. Disappear/Draw Off can hide the symbol.
|
|
529
|
+
- `trigger`: a number or string. Change it to replay an effect. Mounting or
|
|
530
|
+
changing effect configuration also applies it; unrelated rerenders do not.
|
|
531
|
+
- `animated` (default `true`): animate application/removal of the effect.
|
|
532
|
+
- `options.speed`: positive speed multiplier, default system speed.
|
|
533
|
+
- `options.repeat`: a positive integer play count, `'forever'`, or `false` for
|
|
534
|
+
one play. Omit to use the preset's native repetition behavior.
|
|
535
|
+
- `options.repeatBehavior`: `periodic` or `continuous` (iOS 18+).
|
|
536
|
+
Continuous repeats forever and cannot be combined with a count or delay.
|
|
537
|
+
- `options.repeatDelay`: nonnegative delay in seconds between periodic plays
|
|
538
|
+
(iOS 18+). Without a count, periodic/delayed repetition continues indefinitely.
|
|
539
|
+
|
|
540
|
+
Repetition options only affect presets that support repeating. For example,
|
|
541
|
+
`scale` is a held state, not a looping animation. Removing `effect` clears all
|
|
542
|
+
effects. Detached/recycled views stop animations; reattaching applies them again.
|
|
543
|
+
|
|
544
|
+
### Replacement transitions and compatibility
|
|
545
|
+
|
|
546
|
+
`contentTransition` animates changes to the name or image configuration. It
|
|
547
|
+
accepts `type: 'automatic' | 'replace' | 'magicReplace'`, optional
|
|
548
|
+
`direction: 'downUp' | 'upUp' | 'offUp'`, `scope: 'byLayer' | 'wholeSymbol'`, and
|
|
549
|
+
a positive `speed`. Direction and scope configure Replace and the Magic Replace
|
|
550
|
+
fallback; Automatic uses the system transition. The initial image is not transitioned.
|
|
551
|
+
|
|
552
|
+
Unsupported presets are ignored on earlier iOS versions. Magic Replace falls
|
|
553
|
+
back to the configured Replace before iOS 18. Continuous repetition falls back
|
|
554
|
+
to periodic repetition on iOS 17; custom repeat delay is ignored. Before iOS 26,
|
|
555
|
+
variable mode and gradient configuration are ignored. Actual animation, palette,
|
|
556
|
+
multicolor and variable/draw support depend on each symbol's native annotations.
|
|
557
|
+
|
|
558
|
+
`respectReduceMotion` defaults to `true`: repeating/discrete effects and content
|
|
559
|
+
transitions are suppressed while Reduce Motion is enabled, while scale and
|
|
560
|
+
visibility state changes apply instantly. Set it to `false` to opt out.
|
|
561
|
+
|
|
233
562
|
## Contributing
|
|
234
563
|
|
|
235
564
|
- [Development workflow](CONTRIBUTING.md#development-workflow)
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
#if TINYUI_FEATURE_CONCENTRIC_VIEW
|
|
2
|
+
|
|
3
|
+
#import "TinyuiConcentricView.h"
|
|
4
|
+
|
|
5
|
+
#import <react/renderer/components/TinyuiSpec/ComponentDescriptors.h>
|
|
6
|
+
#import <react/renderer/components/TinyuiSpec/Props.h>
|
|
7
|
+
#import <react/renderer/components/TinyuiSpec/RCTComponentViewHelpers.h>
|
|
8
|
+
|
|
9
|
+
using namespace facebook::react;
|
|
10
|
+
|
|
11
|
+
@interface TinyuiConcentricView () <RCTTinyuiConcentricViewViewProtocol>
|
|
12
|
+
@end
|
|
13
|
+
|
|
14
|
+
@implementation TinyuiConcentricView
|
|
15
|
+
|
|
16
|
+
+ (ComponentDescriptorProvider)componentDescriptorProvider
|
|
17
|
+
{
|
|
18
|
+
return concreteComponentDescriptorProvider<TinyuiConcentricViewComponentDescriptor>();
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
- (instancetype)initWithFrame:(CGRect)frame
|
|
22
|
+
{
|
|
23
|
+
if (self = [super initWithFrame:frame]) {
|
|
24
|
+
static const auto defaultProps = std::make_shared<const TinyuiConcentricViewProps>();
|
|
25
|
+
_props = defaultProps;
|
|
26
|
+
}
|
|
27
|
+
return self;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
- (void)finalizeUpdates:(RNComponentViewUpdateMask)updateMask
|
|
31
|
+
{
|
|
32
|
+
[super finalizeUpdates:updateMask];
|
|
33
|
+
[self applyCornerConfiguration];
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
- (void)traitCollectionDidChange:(UITraitCollection *)previousTraitCollection
|
|
37
|
+
{
|
|
38
|
+
[super traitCollectionDidChange:previousTraitCollection];
|
|
39
|
+
if ([self.traitCollection hasDifferentColorAppearanceComparedToTraitCollection:previousTraitCollection]) {
|
|
40
|
+
[self applyCornerConfiguration];
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
- (void)applyCornerConfiguration
|
|
45
|
+
{
|
|
46
|
+
// Fabric updates layer.cornerRadius while applying view styles. Configure
|
|
47
|
+
// UIKit afterwards so it owns the resolved radii, including on layout changes.
|
|
48
|
+
if (@available(iOS 26.0, *)) {
|
|
49
|
+
self.cornerConfiguration = [UICornerConfiguration configurationWithRadius:
|
|
50
|
+
[UICornerRadius containerConcentricRadius]];
|
|
51
|
+
} else {
|
|
52
|
+
const auto &props = *std::static_pointer_cast<const TinyuiConcentricViewProps>(_props);
|
|
53
|
+
self.layer.cornerRadius = props.minimumRadius;
|
|
54
|
+
self.layer.cornerCurve = kCACornerCurveContinuous;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
@end
|
|
59
|
+
|
|
60
|
+
#endif
|
package/ios/Core/Tinyui.mm
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
#import "Tinyui.h"
|
|
2
|
+
#if TINYUI_FEATURE_TIP_KIT
|
|
3
|
+
#import "Tinyui-Swift.h"
|
|
4
|
+
#endif
|
|
2
5
|
|
|
3
6
|
@implementation Tinyui
|
|
4
7
|
|
|
@@ -16,10 +19,61 @@
|
|
|
16
19
|
#if TINYUI_FEATURE_LIQUID_GLASS_TEXT
|
|
17
20
|
[components addObject:@"LiquidGlassText"];
|
|
18
21
|
#endif
|
|
22
|
+
#if TINYUI_FEATURE_STEPPER
|
|
23
|
+
[components addObject:@"Stepper"];
|
|
24
|
+
#endif
|
|
25
|
+
#if TINYUI_FEATURE_CONCENTRIC_VIEW
|
|
26
|
+
[components addObject:@"ConcentricView"];
|
|
27
|
+
#endif
|
|
28
|
+
#if TINYUI_FEATURE_SF_SYMBOL
|
|
29
|
+
[components addObject:@"SFSymbol"];
|
|
30
|
+
#endif
|
|
31
|
+
#if TINYUI_FEATURE_TIP_KIT
|
|
32
|
+
[components addObject:@"TipKit"];
|
|
33
|
+
#endif
|
|
19
34
|
|
|
20
35
|
return components;
|
|
21
36
|
}
|
|
22
37
|
|
|
38
|
+
- (void)configureTips:(NSString *)displayFrequency
|
|
39
|
+
resolve:(RCTPromiseResolveBlock)resolve
|
|
40
|
+
reject:(RCTPromiseRejectBlock)reject
|
|
41
|
+
{
|
|
42
|
+
#if TINYUI_FEATURE_TIP_KIT
|
|
43
|
+
dispatch_async(dispatch_get_main_queue(), ^{
|
|
44
|
+
[TinyuiTipsRuntime configure:displayFrequency completion:^(NSError *error) {
|
|
45
|
+
if (error != nil) {
|
|
46
|
+
reject(error.userInfo[@"code"] ?: @"E_TIPS_CONFIGURATION", error.localizedDescription, error);
|
|
47
|
+
} else {
|
|
48
|
+
resolve(nil);
|
|
49
|
+
}
|
|
50
|
+
}];
|
|
51
|
+
});
|
|
52
|
+
#else
|
|
53
|
+
reject(@"E_TIP_NOT_INSTALLED", @"Enable TipKit in react-native-tinyui.components and run pod install.", nil);
|
|
54
|
+
#endif
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
- (void)invalidateTip:(NSString *)tipId
|
|
58
|
+
reason:(NSString *)reason
|
|
59
|
+
resolve:(RCTPromiseResolveBlock)resolve
|
|
60
|
+
reject:(RCTPromiseRejectBlock)reject
|
|
61
|
+
{
|
|
62
|
+
#if TINYUI_FEATURE_TIP_KIT
|
|
63
|
+
dispatch_async(dispatch_get_main_queue(), ^{
|
|
64
|
+
[TinyuiTipsRuntime invalidate:tipId reason:reason completion:^(NSError *error) {
|
|
65
|
+
if (error != nil) {
|
|
66
|
+
reject(error.userInfo[@"code"] ?: @"E_TIP_INVALIDATION", error.localizedDescription, error);
|
|
67
|
+
} else {
|
|
68
|
+
resolve(nil);
|
|
69
|
+
}
|
|
70
|
+
}];
|
|
71
|
+
});
|
|
72
|
+
#else
|
|
73
|
+
reject(@"E_TIP_NOT_INSTALLED", @"Enable TipKit in react-native-tinyui.components and run pod install.", nil);
|
|
74
|
+
#endif
|
|
75
|
+
}
|
|
76
|
+
|
|
23
77
|
- (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:
|
|
24
78
|
(const facebook::react::ObjCTurboModule::InitParams &)params
|
|
25
79
|
{
|
|
@@ -35,6 +35,30 @@ TINYUI_DISABLED_COMPONENT(TinyuiPopoverView, TinyuiPopoverViewComponentDescripto
|
|
|
35
35
|
TINYUI_DISABLED_COMPONENT(TinyuiLiquidGlassTextView, TinyuiLiquidGlassTextViewComponentDescriptor)
|
|
36
36
|
#endif
|
|
37
37
|
|
|
38
|
+
#if TINYUI_FEATURE_STEPPER
|
|
39
|
+
#import "TinyuiStepperView.h"
|
|
40
|
+
#else
|
|
41
|
+
TINYUI_DISABLED_COMPONENT(TinyuiStepperView, TinyuiStepperViewComponentDescriptor)
|
|
42
|
+
#endif
|
|
43
|
+
|
|
44
|
+
#if TINYUI_FEATURE_CONCENTRIC_VIEW
|
|
45
|
+
#import "TinyuiConcentricView.h"
|
|
46
|
+
#else
|
|
47
|
+
TINYUI_DISABLED_COMPONENT(TinyuiConcentricView, TinyuiConcentricViewComponentDescriptor)
|
|
48
|
+
#endif
|
|
49
|
+
|
|
50
|
+
#if TINYUI_FEATURE_SF_SYMBOL
|
|
51
|
+
#import "TinyuiSFSymbolView.h"
|
|
52
|
+
#else
|
|
53
|
+
TINYUI_DISABLED_COMPONENT(TinyuiSFSymbolView, TinyuiSFSymbolViewComponentDescriptor)
|
|
54
|
+
#endif
|
|
55
|
+
|
|
56
|
+
#if TINYUI_FEATURE_TIP_KIT
|
|
57
|
+
#import "TinyuiTipPopoverView.h"
|
|
58
|
+
#else
|
|
59
|
+
TINYUI_DISABLED_COMPONENT(TinyuiTipPopoverView, TinyuiTipPopoverViewComponentDescriptor)
|
|
60
|
+
#endif
|
|
61
|
+
|
|
38
62
|
#undef TINYUI_DISABLED_COMPONENT
|
|
39
63
|
|
|
40
64
|
Class<RCTComponentViewProtocol> TinyuiMenuViewCls(void)
|
|
@@ -51,3 +75,23 @@ Class<RCTComponentViewProtocol> TinyuiLiquidGlassTextViewCls(void)
|
|
|
51
75
|
{
|
|
52
76
|
return TinyuiLiquidGlassTextView.class;
|
|
53
77
|
}
|
|
78
|
+
|
|
79
|
+
Class<RCTComponentViewProtocol> TinyuiStepperViewCls(void)
|
|
80
|
+
{
|
|
81
|
+
return TinyuiStepperView.class;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
Class<RCTComponentViewProtocol> TinyuiConcentricViewCls(void)
|
|
85
|
+
{
|
|
86
|
+
return TinyuiConcentricView.class;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
Class<RCTComponentViewProtocol> TinyuiSFSymbolViewCls(void)
|
|
90
|
+
{
|
|
91
|
+
return TinyuiSFSymbolView.class;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
Class<RCTComponentViewProtocol> TinyuiTipPopoverViewCls(void)
|
|
95
|
+
{
|
|
96
|
+
return TinyuiTipPopoverView.class;
|
|
97
|
+
}
|