golia-expo-utils 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/.eslintrc.js +62 -0
- package/README.md +166 -0
- package/android/.gradle/9.0-milestone-1/checksums/checksums.lock +0 -0
- package/android/.gradle/9.0-milestone-1/fileChanges/last-build.bin +0 -0
- package/android/.gradle/9.0-milestone-1/fileHashes/fileHashes.lock +0 -0
- package/android/.gradle/9.0-milestone-1/gc.properties +0 -0
- package/android/.gradle/buildOutputCleanup/buildOutputCleanup.lock +0 -0
- package/android/.gradle/buildOutputCleanup/cache.properties +2 -0
- package/android/.gradle/config.properties +2 -0
- package/android/.gradle/vcs-1/gc.properties +0 -0
- package/android/.idea/AndroidProjectSystem.xml +6 -0
- package/android/.idea/appInsightsSettings.xml +23 -0
- package/android/.idea/caches/deviceStreaming.xml +1626 -0
- package/android/.idea/copilot.data.migration.agent.xml +6 -0
- package/android/.idea/copilot.data.migration.ask.xml +6 -0
- package/android/.idea/copilot.data.migration.ask2agent.xml +6 -0
- package/android/.idea/copilot.data.migration.edit.xml +6 -0
- package/android/.idea/gradle.xml +12 -0
- package/android/.idea/inspectionProfiles/Project_Default.xml +7 -0
- package/android/.idea/migrations.xml +10 -0
- package/android/.idea/misc.xml +10 -0
- package/android/.idea/runConfigurations.xml +17 -0
- package/android/.idea/vcs.xml +6 -0
- package/android/build.gradle +66 -0
- package/android/local.properties +8 -0
- package/android/src/main/AndroidManifest.xml +2 -0
- package/android/src/main/java/expo/modules/goliaexpoutils/Config.kt +77 -0
- package/android/src/main/java/expo/modules/goliaexpoutils/SegmentedControlModule.kt +69 -0
- package/android/src/main/java/expo/modules/goliaexpoutils/WaterViewModule.kt +99 -0
- package/android/src/main/java/expo/modules/goliaexpoutils/segmentedControl/ReactSegmentedControl.kt +61 -0
- package/android/src/main/java/expo/modules/goliaexpoutils/segmentedControl/SegmentedControl.kt +916 -0
- package/android/src/main/java/expo/modules/goliaexpoutils/waterView/ReactWaterView.kt +166 -0
- package/android/src/main/java/expo/modules/goliaexpoutils/waterView/WaterView.kt +494 -0
- package/build/ReactSegmentedControl.d.ts +34 -0
- package/build/ReactSegmentedControl.d.ts.map +1 -0
- package/build/ReactSegmentedControl.js +19 -0
- package/build/ReactSegmentedControl.js.map +1 -0
- package/build/ReactWaterView.d.ts +60 -0
- package/build/ReactWaterView.d.ts.map +1 -0
- package/build/ReactWaterView.js +51 -0
- package/build/ReactWaterView.js.map +1 -0
- package/build/index.d.ts +3 -0
- package/build/index.d.ts.map +1 -0
- package/build/index.js +3 -0
- package/build/index.js.map +1 -0
- package/bun.lock +2368 -0
- package/expo-module.config.json +10 -0
- package/ios/GoliaExpoUtils.podspec +24 -0
- package/ios/SegmentedControl/ReactSegmentedControl.swift +186 -0
- package/ios/SegmentedControl/SegmentedControlModule.swift +44 -0
- package/ios/WaterView/ReactWaterView.swift +238 -0
- package/ios/WaterView/WaterView.swift +148 -0
- package/ios/WaterView/WaterViewModule.swift +85 -0
- package/package.json +41 -0
- package/plugin/build/index.d.ts +6 -0
- package/plugin/build/index.js +132 -0
- package/plugin/src/index.ts +110 -0
- package/plugin/tsconfig.json +16 -0
- package/plugin/tsconfig.tsbuildinfo +1 -0
- package/prettier.config.ts +40 -0
- package/src/ReactSegmentedControl.tsx +75 -0
- package/src/ReactWaterView.tsx +117 -0
- package/src/index.ts +2 -0
- package/tsconfig.json +9 -0
package/.eslintrc.js
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/** @type {import('eslint').Linter.Config} */
|
|
2
|
+
module.exports = {
|
|
3
|
+
extends: ['expo', 'plugin:react/recommended', 'plugin:@typescript-eslint/recommended'],
|
|
4
|
+
ignorePatterns: [
|
|
5
|
+
'**/node_modules/*',
|
|
6
|
+
'**/build/*',
|
|
7
|
+
'**/dist/*',
|
|
8
|
+
'**/plugin/build/*',
|
|
9
|
+
'**/ios/*',
|
|
10
|
+
'**/android/*',
|
|
11
|
+
'**/*.config.js',
|
|
12
|
+
],
|
|
13
|
+
plugins: ['perfectionist', 'unused-imports'],
|
|
14
|
+
root: true,
|
|
15
|
+
rules: {
|
|
16
|
+
'@typescript-eslint/no-explicit-any': 'off',
|
|
17
|
+
'@typescript-eslint/no-unused-vars': 'off',
|
|
18
|
+
'import/no-duplicates': 'off',
|
|
19
|
+
'import/no-unresolved': 'off',
|
|
20
|
+
'no-extend-native': 'off',
|
|
21
|
+
'no-unused-vars': 'off',
|
|
22
|
+
'perfectionist/sort-classes': [
|
|
23
|
+
'error',
|
|
24
|
+
{ groups: ['property', 'method', 'unknown'], order: 'asc', type: 'natural' },
|
|
25
|
+
],
|
|
26
|
+
'perfectionist/sort-imports': [
|
|
27
|
+
'error',
|
|
28
|
+
{
|
|
29
|
+
groups: [
|
|
30
|
+
'side-effect',
|
|
31
|
+
'style',
|
|
32
|
+
'type',
|
|
33
|
+
['builtin', 'external'],
|
|
34
|
+
['internal', 'tsconfig-path'],
|
|
35
|
+
['parent', 'sibling', 'index'],
|
|
36
|
+
'unknown',
|
|
37
|
+
],
|
|
38
|
+
internalPattern: ['^~/.+', '^@/.+'],
|
|
39
|
+
order: 'asc',
|
|
40
|
+
type: 'natural',
|
|
41
|
+
},
|
|
42
|
+
],
|
|
43
|
+
'perfectionist/sort-interfaces': [
|
|
44
|
+
'error',
|
|
45
|
+
{ groups: ['member', 'method', 'unknown'], order: 'asc', type: 'natural' },
|
|
46
|
+
],
|
|
47
|
+
'perfectionist/sort-objects': [
|
|
48
|
+
'error',
|
|
49
|
+
{ groups: ['property', 'method', 'unknown'], order: 'asc', type: 'natural' },
|
|
50
|
+
],
|
|
51
|
+
'react/display-name': 'off',
|
|
52
|
+
'react/jsx-curly-brace-presence': ['error', { children: 'never', props: 'never' }],
|
|
53
|
+
'react/jsx-uses-react': 'off',
|
|
54
|
+
'react/react-in-jsx-scope': 'off',
|
|
55
|
+
'unused-imports/no-unused-imports': 'error',
|
|
56
|
+
'unused-imports/no-unused-vars': [
|
|
57
|
+
'error',
|
|
58
|
+
{ args: 'after-used', argsIgnorePattern: '^_', vars: 'all', varsIgnorePattern: '^_' },
|
|
59
|
+
],
|
|
60
|
+
},
|
|
61
|
+
settings: { react: { version: 'detect' } },
|
|
62
|
+
}
|
package/README.md
ADDED
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
# golia-expo-utils
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/golia-expo-utils)
|
|
4
|
+
[](https://expo.dev)
|
|
5
|
+
[](https://github.com/expo/expo)
|
|
6
|
+
|
|
7
|
+
A high-performance, native UI library for Expo, featuring physics-based interactions and native components.
|
|
8
|
+
|
|
9
|
+
**Key Features:**
|
|
10
|
+
* 🌊 **WaterView:** A 60FPS physics-based fluid interaction component (Jetpack Compose on Android / Native on iOS).
|
|
11
|
+
* 🎛 **SegmentedControl:** A truly cross-platform native segmented control. On Android, it uses Jetpack Compose to perfectly mimic the iOS physical feel and visual style (sliding pill, glassmorphism).
|
|
12
|
+
* 🎨 **Native Asset Generation:** Built-in Config Plugin to automatically convert SVGs to Android Vector Drawables and iOS ImageSets.
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
## Installation
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
npm install golia-expo-utils
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
**Note:** Since this library contains native code and config plugins, you **must** use [CNG (Continuous Native Generation)](https://docs.expo.dev/workflow/prebuild/) or a development build. It will not work in Expo Go.
|
|
23
|
+
|
|
24
|
+
## Configuration (Required)
|
|
25
|
+
|
|
26
|
+
To enable the native icon system (for SegmentedControl) and ensure Android resources are generated correctly, you must configure the plugin in your `app.json` or `app.config.js`.
|
|
27
|
+
|
|
28
|
+
1. Create a folder `assets/native-icons` in your project root.
|
|
29
|
+
2. Place your `.svg` icons there (e.g., `star.svg`, `bell-ring.svg`).
|
|
30
|
+
3. Add the plugin to `app.json`:
|
|
31
|
+
|
|
32
|
+
```json
|
|
33
|
+
{
|
|
34
|
+
"expo": {
|
|
35
|
+
"plugins": [
|
|
36
|
+
[
|
|
37
|
+
"golia-expo-utils",
|
|
38
|
+
{
|
|
39
|
+
"icons": ["star", "bell-ring", "settings"]
|
|
40
|
+
}
|
|
41
|
+
]
|
|
42
|
+
]
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
Run prebuild to generate native assets:
|
|
49
|
+
```bash
|
|
50
|
+
npx expo prebuild
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
> **Plugin Magic 🪄**: The plugin will automatically convert your SVGs into Android Vector Drawables (XML) with `tint` support (replacing `currentColor` with black) and generate `keep.xml` to prevent resource stripping in release builds.
|
|
54
|
+
|
|
55
|
+
---
|
|
56
|
+
|
|
57
|
+
## Usage
|
|
58
|
+
|
|
59
|
+
### 1. WaterView
|
|
60
|
+
|
|
61
|
+
A physics-aware interactive view.
|
|
62
|
+
|
|
63
|
+
```tsx
|
|
64
|
+
import { WaterView } from 'golia-expo-utils';
|
|
65
|
+
|
|
66
|
+
// ... inside your component
|
|
67
|
+
<WaterView style={{ width: 300, height: 300 }}>
|
|
68
|
+
<WaterView.Effect
|
|
69
|
+
size={{ width: 80, height: 80 }}
|
|
70
|
+
bgColor="#007AFF"
|
|
71
|
+
shouldSpringBack={true}
|
|
72
|
+
restrictMode="edge" // or 'center'
|
|
73
|
+
initialOffsetX={0}
|
|
74
|
+
initialOffsetY={0}
|
|
75
|
+
onMove={(e) => console.log(e.nativeEvent)}
|
|
76
|
+
/>
|
|
77
|
+
</WaterView>
|
|
78
|
+
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
#### Props (WaterView.Effect)
|
|
82
|
+
|
|
83
|
+
| Prop | Type | Default | Description |
|
|
84
|
+
|---------------------|-------------------------------------|------------|---------------------------------------------------------------------------|
|
|
85
|
+
| `size` | `{ width: number, height: number }` | `100` | The size of the interactive ball (in points/dp). |
|
|
86
|
+
| `bgColor` | `string` | `blue` | The color of the ball. |
|
|
87
|
+
| `shouldSpringBack` | `boolean` | `false` | Whether the ball springs back to initial position after release. |
|
|
88
|
+
| `restrictMode` | `'edge'` \| `'center'` | `'edge'` | `'edge'`: Ball stays inside walls. `'center'`: Ball center stops at wall. |
|
|
89
|
+
| `allowX` / `allowY` | `boolean` | `true` | Lock movement axis. |
|
|
90
|
+
| `initialOffsetX` | `number` | `0` | Initial X position relative to center. |
|
|
91
|
+
| `initialOffsetY` | `number` | `0` | Initial Y position relative to center. |
|
|
92
|
+
| `minX` / `maxX` | `number` | `null` | Custom boundaries for X axis. |
|
|
93
|
+
| `minY` / `maxY` | `number` | `null` | Custom boundaries for Y axis. |
|
|
94
|
+
|
|
95
|
+
---
|
|
96
|
+
|
|
97
|
+
### 2. ReactSegmentedControl
|
|
98
|
+
|
|
99
|
+
A native segmented control that supports icons and text on both platforms.
|
|
100
|
+
|
|
101
|
+
```tsx
|
|
102
|
+
import { ReactSegmentedControl } from 'golia-expo-utils';
|
|
103
|
+
|
|
104
|
+
// Simple usage
|
|
105
|
+
<ReactSegmentedControl
|
|
106
|
+
items={['One', 'Two', 'Three']}
|
|
107
|
+
selectedIndex={0}
|
|
108
|
+
onValueChange={(event) => console.log(event.nativeEvent.index)}
|
|
109
|
+
/>
|
|
110
|
+
|
|
111
|
+
// With Icons (Requires plugin setup)
|
|
112
|
+
<ReactSegmentedControl
|
|
113
|
+
items={[
|
|
114
|
+
{ title: 'Favorites', icon: 'star' }, // 'star' must match assets/native-icons/star.svg
|
|
115
|
+
{ title: 'Recents', icon: 'clock' }
|
|
116
|
+
]}
|
|
117
|
+
activeColor="#007AFF"
|
|
118
|
+
style={{ height: 40 }}
|
|
119
|
+
/>
|
|
120
|
+
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
#### Props
|
|
124
|
+
|
|
125
|
+
| Prop | Type | Description |
|
|
126
|
+
|-----------------------|------------|------------------------------------------------------------------|
|
|
127
|
+
| `items` | `(string | SegmentItem)[]` | Array of strings or objects `{ title: string, icon: string }`. |
|
|
128
|
+
| `selectedIndex` | `number` | The currently selected index. |
|
|
129
|
+
| `onValueChange` | `function` | Callback when selection changes. Returns `{ value, index }`. |
|
|
130
|
+
| `activeColor` | `string` | Color of the selected segment indicator/text. |
|
|
131
|
+
| `textColor` | `string` | Color of the unselected text. |
|
|
132
|
+
| `ctrlBackgroundColor` | `string` | Background color of the control track. |
|
|
133
|
+
| `autoWidth` | `boolean` | If true, segments width is determined by content size. |
|
|
134
|
+
| `hapticEnabled` | `boolean` | Whether to trigger haptic feedback on selection (Default: true). |
|
|
135
|
+
| `enabled` | `boolean` | Whether the control is interactive. |
|
|
136
|
+
|
|
137
|
+
---
|
|
138
|
+
|
|
139
|
+
## Technical Details
|
|
140
|
+
|
|
141
|
+
### Android Implementation
|
|
142
|
+
|
|
143
|
+
* **WaterView**: Built with **Jetpack Compose**. Uses `graphicsLayer` for GPU-accelerated rendering and custom gesture detectors for low-latency, 60FPS physics interactions.
|
|
144
|
+
* **SegmentedControl**: Built with **Jetpack Compose**. Instead of using standard Material components, this is a fully custom implementation that replicates the **iOS look and feel** (sliding animations, spring physics, glassmorphism) using Compose's animation and drawing APIs.
|
|
145
|
+
|
|
146
|
+
### iOS Implementation
|
|
147
|
+
|
|
148
|
+
* **WaterView**: Built with UIKit and native physics engine.
|
|
149
|
+
* **SegmentedControl**: Custom implementation wrapping `UISegmentedControl` with image composition support.
|
|
150
|
+
|
|
151
|
+
---
|
|
152
|
+
|
|
153
|
+
## Troubleshooting
|
|
154
|
+
|
|
155
|
+
**Icons not showing on Android?**
|
|
156
|
+
|
|
157
|
+
1. Ensure your SVG is in `assets/native-icons/`.
|
|
158
|
+
2. Ensure the filename is in `app.json` plugin config.
|
|
159
|
+
3. Run `npx expo prebuild --clean --platform android` to regenerate resources.
|
|
160
|
+
4. The plugin automatically converts `currentColor` to `#000000` to allow native tinting. Ensure your SVG is valid.
|
|
161
|
+
|
|
162
|
+
---
|
|
163
|
+
|
|
164
|
+
## License
|
|
165
|
+
|
|
166
|
+
MIT
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
File without changes
|
|
Binary file
|
|
File without changes
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
+
<project version="4">
|
|
3
|
+
<component name="AppInsightsSettings">
|
|
4
|
+
<option name="tabSettings">
|
|
5
|
+
<map>
|
|
6
|
+
<entry key="Android Vitals">
|
|
7
|
+
<value>
|
|
8
|
+
<InsightsFilterSettings>
|
|
9
|
+
<option name="connection">
|
|
10
|
+
<ConnectionSetting>
|
|
11
|
+
<option name="appId" value="com.focusai.app.mobile" />
|
|
12
|
+
</ConnectionSetting>
|
|
13
|
+
</option>
|
|
14
|
+
<option name="signal" value="SIGNAL_UNSPECIFIED" />
|
|
15
|
+
<option name="timeIntervalDays" value="SEVEN_DAYS" />
|
|
16
|
+
<option name="visibilityType" value="ALL" />
|
|
17
|
+
</InsightsFilterSettings>
|
|
18
|
+
</value>
|
|
19
|
+
</entry>
|
|
20
|
+
</map>
|
|
21
|
+
</option>
|
|
22
|
+
</component>
|
|
23
|
+
</project>
|