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.
Files changed (64) hide show
  1. package/.eslintrc.js +62 -0
  2. package/README.md +166 -0
  3. package/android/.gradle/9.0-milestone-1/checksums/checksums.lock +0 -0
  4. package/android/.gradle/9.0-milestone-1/fileChanges/last-build.bin +0 -0
  5. package/android/.gradle/9.0-milestone-1/fileHashes/fileHashes.lock +0 -0
  6. package/android/.gradle/9.0-milestone-1/gc.properties +0 -0
  7. package/android/.gradle/buildOutputCleanup/buildOutputCleanup.lock +0 -0
  8. package/android/.gradle/buildOutputCleanup/cache.properties +2 -0
  9. package/android/.gradle/config.properties +2 -0
  10. package/android/.gradle/vcs-1/gc.properties +0 -0
  11. package/android/.idea/AndroidProjectSystem.xml +6 -0
  12. package/android/.idea/appInsightsSettings.xml +23 -0
  13. package/android/.idea/caches/deviceStreaming.xml +1626 -0
  14. package/android/.idea/copilot.data.migration.agent.xml +6 -0
  15. package/android/.idea/copilot.data.migration.ask.xml +6 -0
  16. package/android/.idea/copilot.data.migration.ask2agent.xml +6 -0
  17. package/android/.idea/copilot.data.migration.edit.xml +6 -0
  18. package/android/.idea/gradle.xml +12 -0
  19. package/android/.idea/inspectionProfiles/Project_Default.xml +7 -0
  20. package/android/.idea/migrations.xml +10 -0
  21. package/android/.idea/misc.xml +10 -0
  22. package/android/.idea/runConfigurations.xml +17 -0
  23. package/android/.idea/vcs.xml +6 -0
  24. package/android/build.gradle +66 -0
  25. package/android/local.properties +8 -0
  26. package/android/src/main/AndroidManifest.xml +2 -0
  27. package/android/src/main/java/expo/modules/goliaexpoutils/Config.kt +77 -0
  28. package/android/src/main/java/expo/modules/goliaexpoutils/SegmentedControlModule.kt +69 -0
  29. package/android/src/main/java/expo/modules/goliaexpoutils/WaterViewModule.kt +99 -0
  30. package/android/src/main/java/expo/modules/goliaexpoutils/segmentedControl/ReactSegmentedControl.kt +61 -0
  31. package/android/src/main/java/expo/modules/goliaexpoutils/segmentedControl/SegmentedControl.kt +916 -0
  32. package/android/src/main/java/expo/modules/goliaexpoutils/waterView/ReactWaterView.kt +166 -0
  33. package/android/src/main/java/expo/modules/goliaexpoutils/waterView/WaterView.kt +494 -0
  34. package/build/ReactSegmentedControl.d.ts +34 -0
  35. package/build/ReactSegmentedControl.d.ts.map +1 -0
  36. package/build/ReactSegmentedControl.js +19 -0
  37. package/build/ReactSegmentedControl.js.map +1 -0
  38. package/build/ReactWaterView.d.ts +60 -0
  39. package/build/ReactWaterView.d.ts.map +1 -0
  40. package/build/ReactWaterView.js +51 -0
  41. package/build/ReactWaterView.js.map +1 -0
  42. package/build/index.d.ts +3 -0
  43. package/build/index.d.ts.map +1 -0
  44. package/build/index.js +3 -0
  45. package/build/index.js.map +1 -0
  46. package/bun.lock +2368 -0
  47. package/expo-module.config.json +10 -0
  48. package/ios/GoliaExpoUtils.podspec +24 -0
  49. package/ios/SegmentedControl/ReactSegmentedControl.swift +186 -0
  50. package/ios/SegmentedControl/SegmentedControlModule.swift +44 -0
  51. package/ios/WaterView/ReactWaterView.swift +238 -0
  52. package/ios/WaterView/WaterView.swift +148 -0
  53. package/ios/WaterView/WaterViewModule.swift +85 -0
  54. package/package.json +41 -0
  55. package/plugin/build/index.d.ts +6 -0
  56. package/plugin/build/index.js +132 -0
  57. package/plugin/src/index.ts +110 -0
  58. package/plugin/tsconfig.json +16 -0
  59. package/plugin/tsconfig.tsbuildinfo +1 -0
  60. package/prettier.config.ts +40 -0
  61. package/src/ReactSegmentedControl.tsx +75 -0
  62. package/src/ReactWaterView.tsx +117 -0
  63. package/src/index.ts +2 -0
  64. 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
+ [![npm version](https://img.shields.io/npm/v/golia-expo-utils.svg)](https://www.npmjs.com/package/golia-expo-utils)
4
+ [![Expo](https://img.shields.io/badge/Expo-SDK%2054+-000.svg)](https://expo.dev)
5
+ [![Platform](https://img.shields.io/badge/platform-android%20|%20ios-blue.svg)](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
File without changes
@@ -0,0 +1,2 @@
1
+ #Mon Jan 12 17:53:59 JST 2026
2
+ gradle.version=9.0-milestone-1
@@ -0,0 +1,2 @@
1
+ #Mon Jan 12 17:53:54 JST 2026
2
+ java.home=/Library/Java/JavaVirtualMachines/zulu-17.jdk/Contents/Home
File without changes
@@ -0,0 +1,6 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <project version="4">
3
+ <component name="AndroidProjectSystem">
4
+ <option name="providerId" value="com.android.tools.idea.GradleProjectSystem" />
5
+ </component>
6
+ </project>
@@ -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>