@retray-dev/ui-kit 9.3.0 → 10.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 (41) hide show
  1. package/COMPONENTS.md +122 -10
  2. package/CONSUMER.md +47 -7
  3. package/FONTS.md +54 -13
  4. package/README.md +40 -3
  5. package/dist/assets/fonts/Sohne-Bold.otf +0 -0
  6. package/dist/assets/fonts/Sohne-BoldItalic.otf +0 -0
  7. package/dist/assets/fonts/Sohne-ExtraBold.otf +0 -0
  8. package/dist/assets/fonts/Sohne-ExtraBoldItalic.otf +0 -0
  9. package/dist/assets/fonts/Sohne-ExtraLight.otf +0 -0
  10. package/dist/assets/fonts/Sohne-ExtraLightItalic.otf +0 -0
  11. package/dist/assets/fonts/Sohne-Italic.otf +0 -0
  12. package/dist/assets/fonts/Sohne-Light.otf +0 -0
  13. package/dist/assets/fonts/Sohne-LightItalic.otf +0 -0
  14. package/dist/assets/fonts/Sohne-Medium.otf +0 -0
  15. package/dist/assets/fonts/Sohne-MediumItalic.otf +0 -0
  16. package/dist/assets/fonts/Sohne-Regular.otf +0 -0
  17. package/dist/assets/fonts/Sohne-SemiBold.otf +0 -0
  18. package/dist/assets/fonts/Sohne-SemiBoldItalic.otf +0 -0
  19. package/dist/assets/fonts/SohneMono-Bold.otf +0 -0
  20. package/dist/assets/fonts/SohneMono-BoldItalic.otf +0 -0
  21. package/dist/assets/fonts/SohneMono-ExtraBold.otf +0 -0
  22. package/dist/assets/fonts/SohneMono-ExtraBoldItalic.otf +0 -0
  23. package/dist/assets/fonts/SohneMono-ExtraLight.otf +0 -0
  24. package/dist/assets/fonts/SohneMono-ExtraLightItalic.otf +0 -0
  25. package/dist/assets/fonts/SohneMono-Italic.otf +0 -0
  26. package/dist/assets/fonts/SohneMono-Light.otf +0 -0
  27. package/dist/assets/fonts/SohneMono-LightItalic.otf +0 -0
  28. package/dist/assets/fonts/SohneMono-Medium.otf +0 -0
  29. package/dist/assets/fonts/SohneMono-MediumItalic.otf +0 -0
  30. package/dist/assets/fonts/SohneMono-Regular.otf +0 -0
  31. package/dist/assets/fonts/SohneMono-SemiBold.otf +0 -0
  32. package/dist/assets/fonts/SohneMono-SemiBoldItalic.otf +0 -0
  33. package/dist/fonts.d.mts +39 -31
  34. package/dist/fonts.d.ts +39 -31
  35. package/dist/fonts.js +34 -39
  36. package/dist/fonts.mjs +35 -34
  37. package/package.json +4 -1
  38. package/scripts/build-apk.sh +84 -0
  39. package/scripts/copy-fonts.js +90 -0
  40. package/scripts/test-consumer-fonts.sh +82 -0
  41. package/src/fonts.ts +59 -39
package/COMPONENTS.md CHANGED
@@ -1,4 +1,4 @@
1
- # @retray-dev/ui-kit — Component Reference (v9.3.0)
1
+ # @retray-dev/ui-kit — Component Reference (v10.0.0)
2
2
 
3
3
  This file is the AI reference for this package. Add all three lines below to your project's `CLAUDE.md` to give Claude full context — components, setup guide, and usage examples:
4
4
 
@@ -129,9 +129,49 @@ module.exports = config
129
129
 
130
130
  All components use **Sohne** as the font family. You **must** load it before rendering any UI kit component.
131
131
 
132
+ ### How it works
133
+
134
+ 1. When you install `@retray-dev/ui-kit`, the **postinstall script** automatically copies 28 `.otf` font files to `assets/fonts/sohne/` in your project root
135
+ 2. You must define `SohneFonts` with static `require()` calls in your `App.tsx` (see boilerplate below)
136
+ 3. Pass it to `expo-font`'s `useFonts()` hook at your app root
137
+ 4. All library components reference fonts by family name (e.g., `fontFamily: 'Sohne-SemiBold'`)
138
+
139
+ ### SohneFonts boilerplate — copy this into your App.tsx
140
+
132
141
  ```tsx
133
142
  import { useFonts } from 'expo-font'
134
- import { SohneFonts } from '@retray-dev/ui-kit/fonts'
143
+
144
+ // Fonts copied to assets/fonts/sohne/ by @retray-dev/ui-kit postinstall
145
+ const SohneFonts = {
146
+ 'Sohne-ExtraLight': require('./assets/fonts/sohne/Sohne-ExtraLight.otf'),
147
+ 'Sohne-ExtraLightItalic': require('./assets/fonts/sohne/Sohne-ExtraLightItalic.otf'),
148
+ 'Sohne-Light': require('./assets/fonts/sohne/Sohne-Light.otf'),
149
+ 'Sohne-LightItalic': require('./assets/fonts/sohne/Sohne-LightItalic.otf'),
150
+ 'Sohne-Regular': require('./assets/fonts/sohne/Sohne-Regular.otf'),
151
+ 'Sohne-Italic': require('./assets/fonts/sohne/Sohne-Italic.otf'),
152
+ 'Sohne-Medium': require('./assets/fonts/sohne/Sohne-Medium.otf'),
153
+ 'Sohne-MediumItalic': require('./assets/fonts/sohne/Sohne-MediumItalic.otf'),
154
+ 'Sohne-SemiBold': require('./assets/fonts/sohne/Sohne-SemiBold.otf'),
155
+ 'Sohne-SemiBoldItalic': require('./assets/fonts/sohne/Sohne-SemiBoldItalic.otf'),
156
+ 'Sohne-Bold': require('./assets/fonts/sohne/Sohne-Bold.otf'),
157
+ 'Sohne-BoldItalic': require('./assets/fonts/sohne/Sohne-BoldItalic.otf'),
158
+ 'Sohne-ExtraBold': require('./assets/fonts/sohne/Sohne-ExtraBold.otf'),
159
+ 'Sohne-ExtraBoldItalic': require('./assets/fonts/sohne/Sohne-ExtraBoldItalic.otf'),
160
+ 'SohneMono-ExtraLight': require('./assets/fonts/sohne/SohneMono-ExtraLight.otf'),
161
+ 'SohneMono-ExtraLightItalic': require('./assets/fonts/sohne/SohneMono-ExtraLightItalic.otf'),
162
+ 'SohneMono-Light': require('./assets/fonts/sohne/SohneMono-Light.otf'),
163
+ 'SohneMono-LightItalic': require('./assets/fonts/sohne/SohneMono-LightItalic.otf'),
164
+ 'SohneMono-Regular': require('./assets/fonts/sohne/SohneMono-Regular.otf'),
165
+ 'SohneMono-Italic': require('./assets/fonts/sohne/SohneMono-Italic.otf'),
166
+ 'SohneMono-Medium': require('./assets/fonts/sohne/SohneMono-Medium.otf'),
167
+ 'SohneMono-MediumItalic': require('./assets/fonts/sohne/SohneMono-MediumItalic.otf'),
168
+ 'SohneMono-SemiBold': require('./assets/fonts/sohne/SohneMono-SemiBold.otf'),
169
+ 'SohneMono-SemiBoldItalic': require('./assets/fonts/sohne/SohneMono-SemiBoldItalic.otf'),
170
+ 'SohneMono-Bold': require('./assets/fonts/sohne/SohneMono-Bold.otf'),
171
+ 'SohneMono-BoldItalic': require('./assets/fonts/sohne/SohneMono-BoldItalic.otf'),
172
+ 'SohneMono-ExtraBold': require('./assets/fonts/sohne/SohneMono-ExtraBold.otf'),
173
+ 'SohneMono-ExtraBoldItalic': require('./assets/fonts/sohne/SohneMono-ExtraBoldItalic.otf'),
174
+ }
135
175
 
136
176
  export default function App() {
137
177
  const [fontsLoaded] = useFonts(SohneFonts)
@@ -142,18 +182,22 @@ export default function App() {
142
182
  }
143
183
  ```
144
184
 
145
- **How it works:**
146
- 1. Import `SohneFonts` from `@retray-dev/ui-kit/fonts` (separate export path)
147
- 2. Pass it to `expo-font`'s `useFonts()` hook at your app root
148
- 3. Metro resolves font files from `node_modules/@retray-dev/ui-kit/src/assets/fonts/` at bundle time
149
- 4. All library components reference fonts by family name (e.g., `fontFamily: 'Sohne-SemiBold'`)
185
+ ### .gitignore recommendation
150
186
 
151
- **Included weights:**
187
+ Fonts are copied to `assets/fonts/sohne/` on install. You can either:
188
+ - **Commit them** (no network needed during CI builds)
189
+ - **Ignore them** (re-copied on every `pnpm install`)
190
+
191
+ ```gitignore
192
+ # Sohne fonts — copied by @retray-dev/ui-kit postinstall
193
+ # Either commit these or ignore them (re-copied on install)
194
+ assets/fonts/sohne/
195
+ ```
196
+
197
+ **Included weights (28 files):**
152
198
  - Sohne: `Sohne-ExtraLight`, `Sohne-Light`, `Sohne-Regular`, `Sohne-Medium`, `Sohne-SemiBold`, `Sohne-Bold`, `Sohne-ExtraBold` + italic variants
153
199
  - SohneMono: `SohneMono-ExtraLight`, `SohneMono-Light`, `SohneMono-Regular`, `SohneMono-Medium`, `SohneMono-SemiBold`, `SohneMono-Bold`, `SohneMono-ExtraBold` + italic variants
154
200
 
155
- **Total: 28 font files** exported from the package. Font `.otf` files ship as raw assets in `src/assets/fonts/` — NOT bundled into `dist/`. Metro resolves `require()` calls at build time.
156
-
157
201
  Pair with `expo-splash-screen` in production:
158
202
  ```tsx
159
203
  import * as SplashScreen from 'expo-splash-screen'
@@ -572,6 +616,74 @@ import { SohneFonts } from '@retray-dev/ui-kit/fonts'
572
616
 
573
617
  ---
574
618
 
619
+ ## Migration Guide: v9 → v10
620
+
621
+ ### Breaking Changes
622
+
623
+ **1. `SohneFonts` export removed from `@retray-dev/ui-kit/fonts`**
624
+
625
+ The `SohneFonts` object with `require()` calls is no longer exported. Metro cannot reliably resolve `require()` from inside `node_modules`, especially in monorepos. The export now returns `undefined` and logs a deprecation warning.
626
+
627
+ **New approach — postinstall script:**
628
+ 1. When you install `@retray-dev/ui-kit`, a **postinstall script** automatically copies 28 `.otf` font files to `assets/fonts/sohne/` in your project root
629
+ 2. Define `SohneFonts` locally in your `App.tsx` with static `require()` calls (see below)
630
+ 3. Pass it to `expo-font`'s `useFonts()` hook
631
+
632
+ **Migration:**
633
+
634
+ ```diff
635
+ // App.tsx
636
+ import { useFonts } from 'expo-font'
637
+ -import { SohneFonts } from '@retray-dev/ui-kit/fonts'
638
+
639
+ +// Fonts copied to assets/fonts/sohne/ by @retray-dev/ui-kit postinstall
640
+ +const SohneFonts = {
641
+ + 'Sohne-ExtraLight': require('./assets/fonts/sohne/Sohne-ExtraLight.otf'),
642
+ + 'Sohne-ExtraLightItalic': require('./assets/fonts/sohne/Sohne-ExtraLightItalic.otf'),
643
+ + 'Sohne-Light': require('./assets/fonts/sohne/Sohne-Light.otf'),
644
+ + 'Sohne-LightItalic': require('./assets/fonts/sohne/Sohne-LightItalic.otf'),
645
+ + 'Sohne-Regular': require('./assets/fonts/sohne/Sohne-Regular.otf'),
646
+ + 'Sohne-Italic': require('./assets/fonts/sohne/Sohne-Italic.otf'),
647
+ + 'Sohne-Medium': require('./assets/fonts/sohne/Sohne-Medium.otf'),
648
+ + 'Sohne-MediumItalic': require('./assets/fonts/sohne/Sohne-MediumItalic.otf'),
649
+ + 'Sohne-SemiBold': require('./assets/fonts/sohne/Sohne-SemiBold.otf'),
650
+ + 'Sohne-SemiBoldItalic': require('./assets/fonts/sohne/Sohne-SemiBoldItalic.otf'),
651
+ + 'Sohne-Bold': require('./assets/fonts/sohne/Sohne-Bold.otf'),
652
+ + 'Sohne-BoldItalic': require('./assets/fonts/sohne/Sohne-BoldItalic.otf'),
653
+ + 'Sohne-ExtraBold': require('./assets/fonts/sohne/Sohne-ExtraBold.otf'),
654
+ + 'Sohne-ExtraBoldItalic': require('./assets/fonts/sohne/Sohne-ExtraBoldItalic.otf'),
655
+ + 'SohneMono-ExtraLight': require('./assets/fonts/sohne/SohneMono-ExtraLight.otf'),
656
+ + 'SohneMono-ExtraLightItalic': require('./assets/fonts/sohne/SohneMono-ExtraLightItalic.otf'),
657
+ + 'SohneMono-Light': require('./assets/fonts/sohne/SohneMono-Light.otf'),
658
+ + 'SohneMono-LightItalic': require('./assets/fonts/sohne/SohneMono-LightItalic.otf'),
659
+ + 'SohneMono-Regular': require('./assets/fonts/sohne/SohneMono-Regular.otf'),
660
+ + 'SohneMono-Italic': require('./assets/fonts/sohne/SohneMono-Italic.otf'),
661
+ + 'SohneMono-Medium': require('./assets/fonts/sohne/SohneMono-Medium.otf'),
662
+ + 'SohneMono-MediumItalic': require('./assets/fonts/sohne/SohneMono-MediumItalic.otf'),
663
+ + 'SohneMono-SemiBold': require('./assets/fonts/sohne/SohneMono-SemiBold.otf'),
664
+ + 'SohneMono-SemiBoldItalic': require('./assets/fonts/sohne/SohneMono-SemiBoldItalic.otf'),
665
+ + 'SohneMono-Bold': require('./assets/fonts/sohne/SohneMono-Bold.otf'),
666
+ + 'SohneMono-BoldItalic': require('./assets/fonts/sohne/SohneMono-BoldItalic.otf'),
667
+ + 'SohneMono-ExtraBold': require('./assets/fonts/sohne/SohneMono-ExtraBold.otf'),
668
+ + 'SohneMono-ExtraBoldItalic': require('./assets/fonts/sohne/SohneMono-ExtraBoldItalic.otf'),
669
+ +}
670
+
671
+ export default function App() {
672
+ const [fontsLoaded] = useFonts(SohneFonts)
673
+ // ...
674
+ }
675
+ ```
676
+
677
+ **.gitignore recommendation:**
678
+ ```gitignore
679
+ # Sohne fonts — copied by @retray-dev/ui-kit postinstall
680
+ assets/fonts/sohne/
681
+ ```
682
+
683
+ **Why this change:** Metro bundler requires `require()` calls to originate from the consumer's source tree, not from `node_modules`. The previous approach worked in simple setups but failed in monorepos and symlinked workspaces.
684
+
685
+ ---
686
+
575
687
  ## Components
576
688
 
577
689
  ---
package/CONSUMER.md CHANGED
@@ -119,9 +119,40 @@ module.exports = config
119
119
 
120
120
  ```tsx
121
121
  import { useFonts } from 'expo-font'
122
- import { SohneFonts } from '@retray-dev/ui-kit/fonts'
123
122
  import { RetrayProvider } from '@retray-dev/ui-kit'
124
123
 
124
+ // Fonts copied to assets/fonts/sohne/ by @retray-dev/ui-kit postinstall
125
+ const SohneFonts = {
126
+ 'Sohne-ExtraLight': require('./assets/fonts/sohne/Sohne-ExtraLight.otf'),
127
+ 'Sohne-ExtraLightItalic': require('./assets/fonts/sohne/Sohne-ExtraLightItalic.otf'),
128
+ 'Sohne-Light': require('./assets/fonts/sohne/Sohne-Light.otf'),
129
+ 'Sohne-LightItalic': require('./assets/fonts/sohne/Sohne-LightItalic.otf'),
130
+ 'Sohne-Regular': require('./assets/fonts/sohne/Sohne-Regular.otf'),
131
+ 'Sohne-Italic': require('./assets/fonts/sohne/Sohne-Italic.otf'),
132
+ 'Sohne-Medium': require('./assets/fonts/sohne/Sohne-Medium.otf'),
133
+ 'Sohne-MediumItalic': require('./assets/fonts/sohne/Sohne-MediumItalic.otf'),
134
+ 'Sohne-SemiBold': require('./assets/fonts/sohne/Sohne-SemiBold.otf'),
135
+ 'Sohne-SemiBoldItalic': require('./assets/fonts/sohne/Sohne-SemiBoldItalic.otf'),
136
+ 'Sohne-Bold': require('./assets/fonts/sohne/Sohne-Bold.otf'),
137
+ 'Sohne-BoldItalic': require('./assets/fonts/sohne/Sohne-BoldItalic.otf'),
138
+ 'Sohne-ExtraBold': require('./assets/fonts/sohne/Sohne-ExtraBold.otf'),
139
+ 'Sohne-ExtraBoldItalic': require('./assets/fonts/sohne/Sohne-ExtraBoldItalic.otf'),
140
+ 'SohneMono-ExtraLight': require('./assets/fonts/sohne/SohneMono-ExtraLight.otf'),
141
+ 'SohneMono-ExtraLightItalic': require('./assets/fonts/sohne/SohneMono-ExtraLightItalic.otf'),
142
+ 'SohneMono-Light': require('./assets/fonts/sohne/SohneMono-Light.otf'),
143
+ 'SohneMono-LightItalic': require('./assets/fonts/sohne/SohneMono-LightItalic.otf'),
144
+ 'SohneMono-Regular': require('./assets/fonts/sohne/SohneMono-Regular.otf'),
145
+ 'SohneMono-Italic': require('./assets/fonts/sohne/SohneMono-Italic.otf'),
146
+ 'SohneMono-Medium': require('./assets/fonts/sohne/SohneMono-Medium.otf'),
147
+ 'SohneMono-MediumItalic': require('./assets/fonts/sohne/SohneMono-MediumItalic.otf'),
148
+ 'SohneMono-SemiBold': require('./assets/fonts/sohne/SohneMono-SemiBold.otf'),
149
+ 'SohneMono-SemiBoldItalic': require('./assets/fonts/sohne/SohneMono-SemiBoldItalic.otf'),
150
+ 'SohneMono-Bold': require('./assets/fonts/sohne/SohneMono-Bold.otf'),
151
+ 'SohneMono-BoldItalic': require('./assets/fonts/sohne/SohneMono-BoldItalic.otf'),
152
+ 'SohneMono-ExtraBold': require('./assets/fonts/sohne/SohneMono-ExtraBold.otf'),
153
+ 'SohneMono-ExtraBoldItalic': require('./assets/fonts/sohne/SohneMono-ExtraBoldItalic.otf'),
154
+ }
155
+
125
156
  export default function App() {
126
157
  const [fontsLoaded] = useFonts(SohneFonts)
127
158
  if (!fontsLoaded) return null
@@ -234,14 +265,23 @@ npx expo install @shopify/react-native-skia expo-sensors
234
265
 
235
266
  ## Fonts
236
267
 
237
- All components use the **Sohne** font family. Load fonts before rendering any component:
268
+ All components use the **Sohne** font family.
238
269
 
239
- ```tsx
240
- import { useFonts } from 'expo-font'
241
- import { SohneFonts } from '@retray-dev/ui-kit/fonts'
270
+ ### How it works
271
+
272
+ 1. When you install `@retray-dev/ui-kit`, the **postinstall script** copies 28 `.otf` font files to `assets/fonts/sohne/` in your project
273
+ 2. You define `SohneFonts` with static `require()` calls in your `App.tsx` (see Provider Setup above for the full boilerplate)
274
+ 3. Metro resolves fonts from your project's `assets/` folder at bundle time
275
+
276
+ ### .gitignore recommendation
277
+
278
+ Fonts are copied to `assets/fonts/sohne/` on install. You can either:
279
+ - **Commit them** — no network needed during CI builds
280
+ - **Ignore them** — re-copied on every `pnpm install`
242
281
 
243
- const [fontsLoaded] = useFonts(SohneFonts)
244
- if (!fontsLoaded) return null
282
+ ```gitignore
283
+ # Sohne fonts — copied by @retray-dev/ui-kit postinstall
284
+ assets/fonts/sohne/
245
285
  ```
246
286
 
247
287
  See `FONTS.md` for the full font inventory and weight reference.
package/FONTS.md CHANGED
@@ -4,13 +4,51 @@
4
4
 
5
5
  All components in `@retray-dev/ui-kit` use the **Sohne** font family. Consumer apps must load these fonts at the app root using `expo-font`.
6
6
 
7
- ### Installation
7
+ ### How It Works
8
+
9
+ 1. When you install `@retray-dev/ui-kit`, the **postinstall script** automatically copies 28 `.otf` font files to `assets/fonts/sohne/` in your project root
10
+ 2. You must define `SohneFonts` with static `require()` calls in your `App.tsx` (see boilerplate below)
11
+ 3. Pass it to `expo-font`'s `useFonts()` hook at your app root
12
+ 4. All library components reference fonts by family name (e.g., `fontFamily: 'Sohne-SemiBold'`)
8
13
 
9
- The library includes Sohne font files as raw `.otf` assets. Import and load them:
14
+ ### SohneFonts Boilerplate
15
+
16
+ Copy this into your `App.tsx`:
10
17
 
11
18
  ```tsx
12
19
  import { useFonts } from 'expo-font'
13
- import { SohneFonts } from '@retray-dev/ui-kit/fonts'
20
+
21
+ // Fonts copied to assets/fonts/sohne/ by @retray-dev/ui-kit postinstall
22
+ const SohneFonts = {
23
+ 'Sohne-ExtraLight': require('./assets/fonts/sohne/Sohne-ExtraLight.otf'),
24
+ 'Sohne-ExtraLightItalic': require('./assets/fonts/sohne/Sohne-ExtraLightItalic.otf'),
25
+ 'Sohne-Light': require('./assets/fonts/sohne/Sohne-Light.otf'),
26
+ 'Sohne-LightItalic': require('./assets/fonts/sohne/Sohne-LightItalic.otf'),
27
+ 'Sohne-Regular': require('./assets/fonts/sohne/Sohne-Regular.otf'),
28
+ 'Sohne-Italic': require('./assets/fonts/sohne/Sohne-Italic.otf'),
29
+ 'Sohne-Medium': require('./assets/fonts/sohne/Sohne-Medium.otf'),
30
+ 'Sohne-MediumItalic': require('./assets/fonts/sohne/Sohne-MediumItalic.otf'),
31
+ 'Sohne-SemiBold': require('./assets/fonts/sohne/Sohne-SemiBold.otf'),
32
+ 'Sohne-SemiBoldItalic': require('./assets/fonts/sohne/Sohne-SemiBoldItalic.otf'),
33
+ 'Sohne-Bold': require('./assets/fonts/sohne/Sohne-Bold.otf'),
34
+ 'Sohne-BoldItalic': require('./assets/fonts/sohne/Sohne-BoldItalic.otf'),
35
+ 'Sohne-ExtraBold': require('./assets/fonts/sohne/Sohne-ExtraBold.otf'),
36
+ 'Sohne-ExtraBoldItalic': require('./assets/fonts/sohne/Sohne-ExtraBoldItalic.otf'),
37
+ 'SohneMono-ExtraLight': require('./assets/fonts/sohne/SohneMono-ExtraLight.otf'),
38
+ 'SohneMono-ExtraLightItalic': require('./assets/fonts/sohne/SohneMono-ExtraLightItalic.otf'),
39
+ 'SohneMono-Light': require('./assets/fonts/sohne/SohneMono-Light.otf'),
40
+ 'SohneMono-LightItalic': require('./assets/fonts/sohne/SohneMono-LightItalic.otf'),
41
+ 'SohneMono-Regular': require('./assets/fonts/sohne/SohneMono-Regular.otf'),
42
+ 'SohneMono-Italic': require('./assets/fonts/sohne/SohneMono-Italic.otf'),
43
+ 'SohneMono-Medium': require('./assets/fonts/sohne/SohneMono-Medium.otf'),
44
+ 'SohneMono-MediumItalic': require('./assets/fonts/sohne/SohneMono-MediumItalic.otf'),
45
+ 'SohneMono-SemiBold': require('./assets/fonts/sohne/SohneMono-SemiBold.otf'),
46
+ 'SohneMono-SemiBoldItalic': require('./assets/fonts/sohne/SohneMono-SemiBoldItalic.otf'),
47
+ 'SohneMono-Bold': require('./assets/fonts/sohne/SohneMono-Bold.otf'),
48
+ 'SohneMono-BoldItalic': require('./assets/fonts/sohne/SohneMono-BoldItalic.otf'),
49
+ 'SohneMono-ExtraBold': require('./assets/fonts/sohne/SohneMono-ExtraBold.otf'),
50
+ 'SohneMono-ExtraBoldItalic': require('./assets/fonts/sohne/SohneMono-ExtraBoldItalic.otf'),
51
+ }
14
52
 
15
53
  export default function App() {
16
54
  const [fontsLoaded] = useFonts(SohneFonts)
@@ -32,12 +70,11 @@ export default function App() {
32
70
  ```tsx
33
71
  import * as SplashScreen from 'expo-splash-screen'
34
72
  import { useFonts } from 'expo-font'
35
- import { SohneFonts } from '@retray-dev/ui-kit/fonts'
36
73
 
37
74
  SplashScreen.preventAutoHideAsync()
38
75
 
39
76
  export default function App() {
40
- const [fontsLoaded] = useFonts(SohneFonts)
77
+ const [fontsLoaded] = useFonts(SohneFonts) // Use the SohneFonts object above
41
78
 
42
79
  useEffect(() => {
43
80
  if (fontsLoaded) {
@@ -57,9 +94,20 @@ export default function App() {
57
94
  }
58
95
  ```
59
96
 
97
+ ### .gitignore Recommendation
98
+
99
+ Fonts are copied to `assets/fonts/sohne/` on install. You can either:
100
+ - **Commit them** — no network needed during CI builds
101
+ - **Ignore them** — re-copied on every `pnpm install`
102
+
103
+ ```gitignore
104
+ # Sohne fonts — copied by @retray-dev/ui-kit postinstall
105
+ assets/fonts/sohne/
106
+ ```
107
+
60
108
  ### Font Weights Included
61
109
 
62
- `SohneFonts` exports 28 `.otf` files total.
110
+ `SohneFonts` includes 28 `.otf` files total.
63
111
 
64
112
  **Sohne (14 files):**
65
113
  - `Sohne-ExtraLight`
@@ -93,13 +141,6 @@ export default function App() {
93
141
  - `SohneMono-ExtraBold`
94
142
  - `SohneMono-ExtraBoldItalic`
95
143
 
96
- ### How It Works
97
-
98
- 1. **Library components** reference fonts by family name (e.g., `fontFamily: 'Sohne-SemiBold'`)
99
- 2. **Consumer app** loads font files at startup via `useFonts(SohneFonts)`
100
- 3. **Metro bundler** resolves `require()` calls to `.otf` files in `node_modules/@retray-dev/ui-kit/src/assets/fonts/`
101
- 4. **React Native** maps family names to loaded font files
102
-
103
144
  Font files ship as raw assets — **not bundled into `dist/`**. Metro handles asset resolution natively.
104
145
 
105
146
  ### Peer Dependency
package/README.md CHANGED
@@ -46,11 +46,44 @@ module.exports = function (api) {
46
46
 
47
47
  ## Typography
48
48
 
49
- All components use **Sohne** font family. You must load the fonts at app root before rendering any component:
49
+ All components use **Sohne** font family. You must load the fonts at app root before rendering any component.
50
+
51
+ When you install `@retray-dev/ui-kit`, a **postinstall script** automatically copies 28 `.otf` font files to `assets/fonts/sohne/` in your project. Then define `SohneFonts` locally in your `App.tsx`:
50
52
 
51
53
  ```tsx
52
54
  import { useFonts } from 'expo-font'
53
- import { SohneFonts } from '@retray-dev/ui-kit/fonts'
55
+
56
+ // Fonts copied to assets/fonts/sohne/ by @retray-dev/ui-kit postinstall
57
+ const SohneFonts = {
58
+ 'Sohne-ExtraLight': require('./assets/fonts/sohne/Sohne-ExtraLight.otf'),
59
+ 'Sohne-ExtraLightItalic': require('./assets/fonts/sohne/Sohne-ExtraLightItalic.otf'),
60
+ 'Sohne-Light': require('./assets/fonts/sohne/Sohne-Light.otf'),
61
+ 'Sohne-LightItalic': require('./assets/fonts/sohne/Sohne-LightItalic.otf'),
62
+ 'Sohne-Regular': require('./assets/fonts/sohne/Sohne-Regular.otf'),
63
+ 'Sohne-Italic': require('./assets/fonts/sohne/Sohne-Italic.otf'),
64
+ 'Sohne-Medium': require('./assets/fonts/sohne/Sohne-Medium.otf'),
65
+ 'Sohne-MediumItalic': require('./assets/fonts/sohne/Sohne-MediumItalic.otf'),
66
+ 'Sohne-SemiBold': require('./assets/fonts/sohne/Sohne-SemiBold.otf'),
67
+ 'Sohne-SemiBoldItalic': require('./assets/fonts/sohne/Sohne-SemiBoldItalic.otf'),
68
+ 'Sohne-Bold': require('./assets/fonts/sohne/Sohne-Bold.otf'),
69
+ 'Sohne-BoldItalic': require('./assets/fonts/sohne/Sohne-BoldItalic.otf'),
70
+ 'Sohne-ExtraBold': require('./assets/fonts/sohne/Sohne-ExtraBold.otf'),
71
+ 'Sohne-ExtraBoldItalic': require('./assets/fonts/sohne/Sohne-ExtraBoldItalic.otf'),
72
+ 'SohneMono-ExtraLight': require('./assets/fonts/sohne/SohneMono-ExtraLight.otf'),
73
+ 'SohneMono-ExtraLightItalic': require('./assets/fonts/sohne/SohneMono-ExtraLightItalic.otf'),
74
+ 'SohneMono-Light': require('./assets/fonts/sohne/SohneMono-Light.otf'),
75
+ 'SohneMono-LightItalic': require('./assets/fonts/sohne/SohneMono-LightItalic.otf'),
76
+ 'SohneMono-Regular': require('./assets/fonts/sohne/SohneMono-Regular.otf'),
77
+ 'SohneMono-Italic': require('./assets/fonts/sohne/SohneMono-Italic.otf'),
78
+ 'SohneMono-Medium': require('./assets/fonts/sohne/SohneMono-Medium.otf'),
79
+ 'SohneMono-MediumItalic': require('./assets/fonts/sohne/SohneMono-MediumItalic.otf'),
80
+ 'SohneMono-SemiBold': require('./assets/fonts/sohne/SohneMono-SemiBold.otf'),
81
+ 'SohneMono-SemiBoldItalic': require('./assets/fonts/sohne/SohneMono-SemiBoldItalic.otf'),
82
+ 'SohneMono-Bold': require('./assets/fonts/sohne/SohneMono-Bold.otf'),
83
+ 'SohneMono-BoldItalic': require('./assets/fonts/sohne/SohneMono-BoldItalic.otf'),
84
+ 'SohneMono-ExtraBold': require('./assets/fonts/sohne/SohneMono-ExtraBold.otf'),
85
+ 'SohneMono-ExtraBoldItalic': require('./assets/fonts/sohne/SohneMono-ExtraBoldItalic.otf'),
86
+ }
54
87
 
55
88
  export default function App() {
56
89
  const [fontsLoaded] = useFonts(SohneFonts)
@@ -62,7 +95,11 @@ export default function App() {
62
95
  }
63
96
  ```
64
97
 
65
- The library ships 28 font files (14 Sohne base + 14 SohneMono, each with 7 weights + italic variants) as raw `.otf` files. Metro resolves them at bundle time.
98
+ **.gitignore recommendation:**
99
+ ```gitignore
100
+ # Sohne fonts — copied by @retray-dev/ui-kit postinstall
101
+ assets/fonts/sohne/
102
+ ```
66
103
 
67
104
  ## Setup
68
105
 
Binary file
package/dist/fonts.d.mts CHANGED
@@ -1,32 +1,40 @@
1
- declare const SohneFonts: {
2
- readonly 'Sohne-ExtraLight': number;
3
- readonly 'Sohne-ExtraLightItalic': number;
4
- readonly 'Sohne-Light': number;
5
- readonly 'Sohne-LightItalic': number;
6
- readonly 'Sohne-Regular': number;
7
- readonly 'Sohne-Italic': number;
8
- readonly 'Sohne-Medium': number;
9
- readonly 'Sohne-MediumItalic': number;
10
- readonly 'Sohne-SemiBold': number;
11
- readonly 'Sohne-SemiBoldItalic': number;
12
- readonly 'Sohne-Bold': number;
13
- readonly 'Sohne-BoldItalic': number;
14
- readonly 'Sohne-ExtraBold': number;
15
- readonly 'Sohne-ExtraBoldItalic': number;
16
- readonly 'SohneMono-ExtraLight': number;
17
- readonly 'SohneMono-ExtraLightItalic': number;
18
- readonly 'SohneMono-Light': number;
19
- readonly 'SohneMono-LightItalic': number;
20
- readonly 'SohneMono-Regular': number;
21
- readonly 'SohneMono-Italic': number;
22
- readonly 'SohneMono-Medium': number;
23
- readonly 'SohneMono-MediumItalic': number;
24
- readonly 'SohneMono-SemiBold': number;
25
- readonly 'SohneMono-SemiBoldItalic': number;
26
- readonly 'SohneMono-Bold': number;
27
- readonly 'SohneMono-BoldItalic': number;
28
- readonly 'SohneMono-ExtraBold': number;
29
- readonly 'SohneMono-ExtraBoldItalic': number;
30
- };
1
+ /**
2
+ * Sohne font family names for @retray-dev/ui-kit components.
3
+ *
4
+ * The postinstall script copies 28 .otf files to your project's assets/fonts/sohne/ folder.
5
+ * You must define SohneFonts with static require() calls in your App.tsx:
6
+ *
7
+ * @example
8
+ * import { useFonts } from 'expo-font'
9
+ *
10
+ * // Fonts copied to assets/fonts/sohne/ by @retray-dev/ui-kit postinstall
11
+ * const SohneFonts = {
12
+ * 'Sohne-ExtraLight': require('./assets/fonts/sohne/Sohne-ExtraLight.otf'),
13
+ * 'Sohne-ExtraLightItalic': require('./assets/fonts/sohne/Sohne-ExtraLightItalic.otf'),
14
+ * // ... see CONSUMER.md for full boilerplate
15
+ * }
16
+ *
17
+ * function App() {
18
+ * const [fontsLoaded] = useFonts(SohneFonts)
19
+ * if (!fontsLoaded) return null
20
+ * // render app
21
+ * }
22
+ *
23
+ * @see CONSUMER.md for the full SohneFonts boilerplate to copy into your App.tsx
24
+ */
25
+ /**
26
+ * Array of all 28 Sohne font family names.
27
+ * Use this for validation or programmatic checks — NOT for loading fonts.
28
+ * To load fonts, use the static require() boilerplate from CONSUMER.md.
29
+ */
30
+ declare const SohneFontNames: readonly ["Sohne-ExtraLight", "Sohne-ExtraLightItalic", "Sohne-Light", "Sohne-LightItalic", "Sohne-Regular", "Sohne-Italic", "Sohne-Medium", "Sohne-MediumItalic", "Sohne-SemiBold", "Sohne-SemiBoldItalic", "Sohne-Bold", "Sohne-BoldItalic", "Sohne-ExtraBold", "Sohne-ExtraBoldItalic", "SohneMono-ExtraLight", "SohneMono-ExtraLightItalic", "SohneMono-Light", "SohneMono-LightItalic", "SohneMono-Regular", "SohneMono-Italic", "SohneMono-Medium", "SohneMono-MediumItalic", "SohneMono-SemiBold", "SohneMono-SemiBoldItalic", "SohneMono-Bold", "SohneMono-BoldItalic", "SohneMono-ExtraBold", "SohneMono-ExtraBoldItalic"];
31
+ /** Type for any valid Sohne font family name */
32
+ type SohneFontName = (typeof SohneFontNames)[number];
33
+ /**
34
+ * @deprecated SohneFonts export removed in v10.0.0.
35
+ * Metro cannot resolve require() calls from node_modules reliably.
36
+ * Copy the static SohneFonts boilerplate from CONSUMER.md into your App.tsx instead.
37
+ */
38
+ declare const SohneFonts: undefined;
31
39
 
32
- export { SohneFonts };
40
+ export { type SohneFontName, SohneFontNames, SohneFonts };
package/dist/fonts.d.ts CHANGED
@@ -1,32 +1,40 @@
1
- declare const SohneFonts: {
2
- readonly 'Sohne-ExtraLight': number;
3
- readonly 'Sohne-ExtraLightItalic': number;
4
- readonly 'Sohne-Light': number;
5
- readonly 'Sohne-LightItalic': number;
6
- readonly 'Sohne-Regular': number;
7
- readonly 'Sohne-Italic': number;
8
- readonly 'Sohne-Medium': number;
9
- readonly 'Sohne-MediumItalic': number;
10
- readonly 'Sohne-SemiBold': number;
11
- readonly 'Sohne-SemiBoldItalic': number;
12
- readonly 'Sohne-Bold': number;
13
- readonly 'Sohne-BoldItalic': number;
14
- readonly 'Sohne-ExtraBold': number;
15
- readonly 'Sohne-ExtraBoldItalic': number;
16
- readonly 'SohneMono-ExtraLight': number;
17
- readonly 'SohneMono-ExtraLightItalic': number;
18
- readonly 'SohneMono-Light': number;
19
- readonly 'SohneMono-LightItalic': number;
20
- readonly 'SohneMono-Regular': number;
21
- readonly 'SohneMono-Italic': number;
22
- readonly 'SohneMono-Medium': number;
23
- readonly 'SohneMono-MediumItalic': number;
24
- readonly 'SohneMono-SemiBold': number;
25
- readonly 'SohneMono-SemiBoldItalic': number;
26
- readonly 'SohneMono-Bold': number;
27
- readonly 'SohneMono-BoldItalic': number;
28
- readonly 'SohneMono-ExtraBold': number;
29
- readonly 'SohneMono-ExtraBoldItalic': number;
30
- };
1
+ /**
2
+ * Sohne font family names for @retray-dev/ui-kit components.
3
+ *
4
+ * The postinstall script copies 28 .otf files to your project's assets/fonts/sohne/ folder.
5
+ * You must define SohneFonts with static require() calls in your App.tsx:
6
+ *
7
+ * @example
8
+ * import { useFonts } from 'expo-font'
9
+ *
10
+ * // Fonts copied to assets/fonts/sohne/ by @retray-dev/ui-kit postinstall
11
+ * const SohneFonts = {
12
+ * 'Sohne-ExtraLight': require('./assets/fonts/sohne/Sohne-ExtraLight.otf'),
13
+ * 'Sohne-ExtraLightItalic': require('./assets/fonts/sohne/Sohne-ExtraLightItalic.otf'),
14
+ * // ... see CONSUMER.md for full boilerplate
15
+ * }
16
+ *
17
+ * function App() {
18
+ * const [fontsLoaded] = useFonts(SohneFonts)
19
+ * if (!fontsLoaded) return null
20
+ * // render app
21
+ * }
22
+ *
23
+ * @see CONSUMER.md for the full SohneFonts boilerplate to copy into your App.tsx
24
+ */
25
+ /**
26
+ * Array of all 28 Sohne font family names.
27
+ * Use this for validation or programmatic checks — NOT for loading fonts.
28
+ * To load fonts, use the static require() boilerplate from CONSUMER.md.
29
+ */
30
+ declare const SohneFontNames: readonly ["Sohne-ExtraLight", "Sohne-ExtraLightItalic", "Sohne-Light", "Sohne-LightItalic", "Sohne-Regular", "Sohne-Italic", "Sohne-Medium", "Sohne-MediumItalic", "Sohne-SemiBold", "Sohne-SemiBoldItalic", "Sohne-Bold", "Sohne-BoldItalic", "Sohne-ExtraBold", "Sohne-ExtraBoldItalic", "SohneMono-ExtraLight", "SohneMono-ExtraLightItalic", "SohneMono-Light", "SohneMono-LightItalic", "SohneMono-Regular", "SohneMono-Italic", "SohneMono-Medium", "SohneMono-MediumItalic", "SohneMono-SemiBold", "SohneMono-SemiBoldItalic", "SohneMono-Bold", "SohneMono-BoldItalic", "SohneMono-ExtraBold", "SohneMono-ExtraBoldItalic"];
31
+ /** Type for any valid Sohne font family name */
32
+ type SohneFontName = (typeof SohneFontNames)[number];
33
+ /**
34
+ * @deprecated SohneFonts export removed in v10.0.0.
35
+ * Metro cannot resolve require() calls from node_modules reliably.
36
+ * Copy the static SohneFonts boilerplate from CONSUMER.md into your App.tsx instead.
37
+ */
38
+ declare const SohneFonts: undefined;
31
39
 
32
- export { SohneFonts };
40
+ export { type SohneFontName, SohneFontNames, SohneFonts };
package/dist/fonts.js CHANGED
@@ -1,44 +1,39 @@
1
1
  'use strict';
2
2
 
3
- var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
4
- get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
5
- }) : x)(function(x) {
6
- if (typeof require !== "undefined") return require.apply(this, arguments);
7
- throw Error('Dynamic require of "' + x + '" is not supported');
8
- });
9
-
10
3
  // src/fonts.ts
11
- var SohneFonts = {
12
- // Sohne base
13
- "Sohne-ExtraLight": __require("../src/assets/fonts/Sohne-ExtraLight.otf"),
14
- "Sohne-ExtraLightItalic": __require("../src/assets/fonts/Sohne-ExtraLightItalic.otf"),
15
- "Sohne-Light": __require("../src/assets/fonts/Sohne-Light.otf"),
16
- "Sohne-LightItalic": __require("../src/assets/fonts/Sohne-LightItalic.otf"),
17
- "Sohne-Regular": __require("../src/assets/fonts/Sohne-Regular.otf"),
18
- "Sohne-Italic": __require("../src/assets/fonts/Sohne-Italic.otf"),
19
- "Sohne-Medium": __require("../src/assets/fonts/Sohne-Medium.otf"),
20
- "Sohne-MediumItalic": __require("../src/assets/fonts/Sohne-MediumItalic.otf"),
21
- "Sohne-SemiBold": __require("../src/assets/fonts/Sohne-SemiBold.otf"),
22
- "Sohne-SemiBoldItalic": __require("../src/assets/fonts/Sohne-SemiBoldItalic.otf"),
23
- "Sohne-Bold": __require("../src/assets/fonts/Sohne-Bold.otf"),
24
- "Sohne-BoldItalic": __require("../src/assets/fonts/Sohne-BoldItalic.otf"),
25
- "Sohne-ExtraBold": __require("../src/assets/fonts/Sohne-ExtraBold.otf"),
26
- "Sohne-ExtraBoldItalic": __require("../src/assets/fonts/Sohne-ExtraBoldItalic.otf"),
27
- // SohneMono
28
- "SohneMono-ExtraLight": __require("../src/assets/fonts/SohneMono-ExtraLight.otf"),
29
- "SohneMono-ExtraLightItalic": __require("../src/assets/fonts/SohneMono-ExtraLightItalic.otf"),
30
- "SohneMono-Light": __require("../src/assets/fonts/SohneMono-Light.otf"),
31
- "SohneMono-LightItalic": __require("../src/assets/fonts/SohneMono-LightItalic.otf"),
32
- "SohneMono-Regular": __require("../src/assets/fonts/SohneMono-Regular.otf"),
33
- "SohneMono-Italic": __require("../src/assets/fonts/SohneMono-Italic.otf"),
34
- "SohneMono-Medium": __require("../src/assets/fonts/SohneMono-Medium.otf"),
35
- "SohneMono-MediumItalic": __require("../src/assets/fonts/SohneMono-MediumItalic.otf"),
36
- "SohneMono-SemiBold": __require("../src/assets/fonts/SohneMono-SemiBold.otf"),
37
- "SohneMono-SemiBoldItalic": __require("../src/assets/fonts/SohneMono-SemiBoldItalic.otf"),
38
- "SohneMono-Bold": __require("../src/assets/fonts/SohneMono-Bold.otf"),
39
- "SohneMono-BoldItalic": __require("../src/assets/fonts/SohneMono-BoldItalic.otf"),
40
- "SohneMono-ExtraBold": __require("../src/assets/fonts/SohneMono-ExtraBold.otf"),
41
- "SohneMono-ExtraBoldItalic": __require("../src/assets/fonts/SohneMono-ExtraBoldItalic.otf")
42
- };
4
+ var SohneFontNames = [
5
+ // Sohne base (14)
6
+ "Sohne-ExtraLight",
7
+ "Sohne-ExtraLightItalic",
8
+ "Sohne-Light",
9
+ "Sohne-LightItalic",
10
+ "Sohne-Regular",
11
+ "Sohne-Italic",
12
+ "Sohne-Medium",
13
+ "Sohne-MediumItalic",
14
+ "Sohne-SemiBold",
15
+ "Sohne-SemiBoldItalic",
16
+ "Sohne-Bold",
17
+ "Sohne-BoldItalic",
18
+ "Sohne-ExtraBold",
19
+ "Sohne-ExtraBoldItalic",
20
+ // SohneMono (14)
21
+ "SohneMono-ExtraLight",
22
+ "SohneMono-ExtraLightItalic",
23
+ "SohneMono-Light",
24
+ "SohneMono-LightItalic",
25
+ "SohneMono-Regular",
26
+ "SohneMono-Italic",
27
+ "SohneMono-Medium",
28
+ "SohneMono-MediumItalic",
29
+ "SohneMono-SemiBold",
30
+ "SohneMono-SemiBoldItalic",
31
+ "SohneMono-Bold",
32
+ "SohneMono-BoldItalic",
33
+ "SohneMono-ExtraBold",
34
+ "SohneMono-ExtraBoldItalic"
35
+ ];
36
+ var SohneFonts = void 0;
43
37
 
38
+ exports.SohneFontNames = SohneFontNames;
44
39
  exports.SohneFonts = SohneFonts;
package/dist/fonts.mjs CHANGED
@@ -1,37 +1,38 @@
1
- import { __require } from './chunk-Y6FXYEAI.mjs';
1
+ import './chunk-Y6FXYEAI.mjs';
2
2
 
3
3
  // src/fonts.ts
4
- var SohneFonts = {
5
- // Sohne base
6
- "Sohne-ExtraLight": __require("../src/assets/fonts/Sohne-ExtraLight.otf"),
7
- "Sohne-ExtraLightItalic": __require("../src/assets/fonts/Sohne-ExtraLightItalic.otf"),
8
- "Sohne-Light": __require("../src/assets/fonts/Sohne-Light.otf"),
9
- "Sohne-LightItalic": __require("../src/assets/fonts/Sohne-LightItalic.otf"),
10
- "Sohne-Regular": __require("../src/assets/fonts/Sohne-Regular.otf"),
11
- "Sohne-Italic": __require("../src/assets/fonts/Sohne-Italic.otf"),
12
- "Sohne-Medium": __require("../src/assets/fonts/Sohne-Medium.otf"),
13
- "Sohne-MediumItalic": __require("../src/assets/fonts/Sohne-MediumItalic.otf"),
14
- "Sohne-SemiBold": __require("../src/assets/fonts/Sohne-SemiBold.otf"),
15
- "Sohne-SemiBoldItalic": __require("../src/assets/fonts/Sohne-SemiBoldItalic.otf"),
16
- "Sohne-Bold": __require("../src/assets/fonts/Sohne-Bold.otf"),
17
- "Sohne-BoldItalic": __require("../src/assets/fonts/Sohne-BoldItalic.otf"),
18
- "Sohne-ExtraBold": __require("../src/assets/fonts/Sohne-ExtraBold.otf"),
19
- "Sohne-ExtraBoldItalic": __require("../src/assets/fonts/Sohne-ExtraBoldItalic.otf"),
20
- // SohneMono
21
- "SohneMono-ExtraLight": __require("../src/assets/fonts/SohneMono-ExtraLight.otf"),
22
- "SohneMono-ExtraLightItalic": __require("../src/assets/fonts/SohneMono-ExtraLightItalic.otf"),
23
- "SohneMono-Light": __require("../src/assets/fonts/SohneMono-Light.otf"),
24
- "SohneMono-LightItalic": __require("../src/assets/fonts/SohneMono-LightItalic.otf"),
25
- "SohneMono-Regular": __require("../src/assets/fonts/SohneMono-Regular.otf"),
26
- "SohneMono-Italic": __require("../src/assets/fonts/SohneMono-Italic.otf"),
27
- "SohneMono-Medium": __require("../src/assets/fonts/SohneMono-Medium.otf"),
28
- "SohneMono-MediumItalic": __require("../src/assets/fonts/SohneMono-MediumItalic.otf"),
29
- "SohneMono-SemiBold": __require("../src/assets/fonts/SohneMono-SemiBold.otf"),
30
- "SohneMono-SemiBoldItalic": __require("../src/assets/fonts/SohneMono-SemiBoldItalic.otf"),
31
- "SohneMono-Bold": __require("../src/assets/fonts/SohneMono-Bold.otf"),
32
- "SohneMono-BoldItalic": __require("../src/assets/fonts/SohneMono-BoldItalic.otf"),
33
- "SohneMono-ExtraBold": __require("../src/assets/fonts/SohneMono-ExtraBold.otf"),
34
- "SohneMono-ExtraBoldItalic": __require("../src/assets/fonts/SohneMono-ExtraBoldItalic.otf")
35
- };
4
+ var SohneFontNames = [
5
+ // Sohne base (14)
6
+ "Sohne-ExtraLight",
7
+ "Sohne-ExtraLightItalic",
8
+ "Sohne-Light",
9
+ "Sohne-LightItalic",
10
+ "Sohne-Regular",
11
+ "Sohne-Italic",
12
+ "Sohne-Medium",
13
+ "Sohne-MediumItalic",
14
+ "Sohne-SemiBold",
15
+ "Sohne-SemiBoldItalic",
16
+ "Sohne-Bold",
17
+ "Sohne-BoldItalic",
18
+ "Sohne-ExtraBold",
19
+ "Sohne-ExtraBoldItalic",
20
+ // SohneMono (14)
21
+ "SohneMono-ExtraLight",
22
+ "SohneMono-ExtraLightItalic",
23
+ "SohneMono-Light",
24
+ "SohneMono-LightItalic",
25
+ "SohneMono-Regular",
26
+ "SohneMono-Italic",
27
+ "SohneMono-Medium",
28
+ "SohneMono-MediumItalic",
29
+ "SohneMono-SemiBold",
30
+ "SohneMono-SemiBoldItalic",
31
+ "SohneMono-Bold",
32
+ "SohneMono-BoldItalic",
33
+ "SohneMono-ExtraBold",
34
+ "SohneMono-ExtraBoldItalic"
35
+ ];
36
+ var SohneFonts = void 0;
36
37
 
37
- export { SohneFonts };
38
+ export { SohneFontNames, SohneFonts };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@retray-dev/ui-kit",
3
- "version": "9.3.0",
3
+ "version": "10.0.0",
4
4
  "description": "Personal UI Kit for React Native / Expo",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",
@@ -25,6 +25,7 @@
25
25
  "files": [
26
26
  "dist",
27
27
  "src",
28
+ "scripts",
28
29
  "COMPONENTS.md",
29
30
  "CONSUMER.md",
30
31
  "EXAMPLES.md",
@@ -32,6 +33,7 @@
32
33
  "DESIGN.md"
33
34
  ],
34
35
  "scripts": {
36
+ "postinstall": "node scripts/copy-fonts.js",
35
37
  "build": "tsup",
36
38
  "dev": "tsup --watch",
37
39
  "typecheck": "tsc --noEmit",
@@ -45,6 +47,7 @@
45
47
  "lint:all": "pnpm lint && pnpm --filter retray-ui-kit-example lint",
46
48
  "format:all": "pnpm format && pnpm --filter retray-ui-kit-example format",
47
49
  "verify": "pnpm typecheck && pnpm lint && pnpm test && pnpm build",
50
+ "test:fonts": "./scripts/test-consumer-fonts.sh",
48
51
  "deploy": "pnpm typecheck && pnpm build && npm publish --access public"
49
52
  },
50
53
  "keywords": [
@@ -0,0 +1,84 @@
1
+ #!/usr/bin/env bash
2
+ #
3
+ # build-apk.sh — Build a standalone release APK of the example app for phone install.
4
+ #
5
+ # Produces: build-output/retray-ui-kit-example.apk (signed with debug keystore,
6
+ # installable on any Android phone via "Install unknown apps").
7
+ #
8
+ # Requirements (already set up on this machine):
9
+ # - Android SDK at $ANDROID_HOME (default: ~/Library/Android/sdk)
10
+ # - Java 17 (JDK)
11
+ # - pnpm, node
12
+ #
13
+ # Usage:
14
+ # ./scripts/build-apk.sh # full build
15
+ # ./scripts/build-apk.sh --install # build, then adb install to connected phone
16
+ # ./scripts/build-apk.sh --clean # wipe android/ + gradle cache first (slow, fixes weird errors)
17
+ #
18
+ set -euo pipefail
19
+
20
+ # --- resolve repo root regardless of cwd ---
21
+ ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
22
+ EXAMPLE="$ROOT/example"
23
+ OUT_DIR="$ROOT/build-output"
24
+ APK_NAME="retray-ui-kit-example.apk"
25
+
26
+ export ANDROID_HOME="${ANDROID_HOME:-$HOME/Library/Android/sdk}"
27
+
28
+ DO_INSTALL=false
29
+ DO_CLEAN=false
30
+ for arg in "$@"; do
31
+ case "$arg" in
32
+ --install) DO_INSTALL=true ;;
33
+ --clean) DO_CLEAN=true ;;
34
+ *) echo "Unknown arg: $arg"; exit 1 ;;
35
+ esac
36
+ done
37
+
38
+ echo "==> repo: $ROOT"
39
+ echo "==> sdk: $ANDROID_HOME"
40
+ [ -d "$ANDROID_HOME" ] || { echo "ERROR: Android SDK not found at $ANDROID_HOME"; exit 1; }
41
+
42
+ # --- 1. build the ui-kit (example depends on dist/) ---
43
+ echo "==> [1/4] Building @retray-dev/ui-kit ..."
44
+ ( cd "$ROOT" && pnpm build )
45
+
46
+ # --- 2. ensure deps + native android/ dir exist ---
47
+ echo "==> [2/4] Prebuild (generate android/ if missing) ..."
48
+ if $DO_CLEAN; then
49
+ echo " --clean: removing android/ and gradle build cache"
50
+ rm -rf "$EXAMPLE/android"
51
+ fi
52
+ # babel-preset-expo must be a top-level dep of example so Metro resolves it
53
+ # under pnpm hoisted layout. Declared in example/package.json devDependencies.
54
+ ( cd "$ROOT" && pnpm install --frozen-lockfile=false )
55
+ if [ ! -d "$EXAMPLE/android" ]; then
56
+ ( cd "$EXAMPLE" && CI=1 npx expo prebuild --platform android --no-install )
57
+ fi
58
+
59
+ # --- 3. assemble release APK ---
60
+ echo "==> [3/4] Gradle assembleRelease (first run ~7 min) ..."
61
+ ( cd "$EXAMPLE/android" && ANDROID_HOME="$ANDROID_HOME" ./gradlew assembleRelease )
62
+
63
+ # --- 4. copy to build-output/ ---
64
+ echo "==> [4/4] Copying APK ..."
65
+ SRC_APK="$EXAMPLE/android/app/build/outputs/apk/release/app-release.apk"
66
+ [ -f "$SRC_APK" ] || { echo "ERROR: APK not found at $SRC_APK"; exit 1; }
67
+ mkdir -p "$OUT_DIR"
68
+ cp "$SRC_APK" "$OUT_DIR/$APK_NAME"
69
+
70
+ echo ""
71
+ echo "✅ APK ready: $OUT_DIR/$APK_NAME ($(du -h "$OUT_DIR/$APK_NAME" | cut -f1))"
72
+
73
+ # --- optional install ---
74
+ if $DO_INSTALL; then
75
+ echo "==> adb install ..."
76
+ "$ANDROID_HOME/platform-tools/adb" install -r "$OUT_DIR/$APK_NAME"
77
+ echo "✅ Installed to connected device."
78
+ else
79
+ echo ""
80
+ echo "To put on your phone:"
81
+ echo " • USB: $ANDROID_HOME/platform-tools/adb install -r \"$OUT_DIR/$APK_NAME\""
82
+ echo " • or run again with --install"
83
+ echo " • or AirDrop/Drive the .apk and tap it (enable 'Install unknown apps')"
84
+ fi
@@ -0,0 +1,90 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Postinstall script: copies Sohne font files to consumer project's assets/fonts/sohne/
4
+ *
5
+ * This runs automatically when a consumer installs @retray-dev/ui-kit.
6
+ * Fonts are copied from dist/assets/fonts/ to <consumer-root>/assets/fonts/sohne/
7
+ * so Metro can resolve require() calls in the consumer's App.tsx.
8
+ */
9
+ const fs = require('fs')
10
+ const path = require('path')
11
+
12
+ // npm sets INIT_CWD to consumer project root, pnpm sets PROJECT_CWD
13
+ const consumerRoot =
14
+ process.env.INIT_CWD ||
15
+ process.env.PROJECT_CWD ||
16
+ process.cwd()
17
+
18
+ // Don't run when installing inside the ui-kit repo itself
19
+ const pkgPath = path.join(consumerRoot, 'package.json')
20
+ if (!fs.existsSync(pkgPath)) {
21
+ process.exit(0)
22
+ }
23
+
24
+ let pkg
25
+ try {
26
+ pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8'))
27
+ } catch {
28
+ // Can't read package.json — skip silently
29
+ process.exit(0)
30
+ }
31
+
32
+ // Skip if we're in the ui-kit repo itself
33
+ if (pkg.name === '@retray-dev/ui-kit') {
34
+ process.exit(0)
35
+ }
36
+
37
+ // Source: dist/assets/fonts/ (relative to this script in scripts/)
38
+ const src = path.join(__dirname, '..', 'dist', 'assets', 'fonts')
39
+
40
+ // Destination: consumer's assets/fonts/sohne/
41
+ const dest = path.join(consumerRoot, 'assets', 'fonts', 'sohne')
42
+
43
+ // If source doesn't exist (maybe dist not built yet), skip gracefully
44
+ if (!fs.existsSync(src)) {
45
+ console.warn('[ui-kit] Font source not found:', src)
46
+ console.warn('[ui-kit] Run `pnpm build` in the ui-kit package first, or fonts will need manual setup.')
47
+ process.exit(0)
48
+ }
49
+
50
+ // Create destination directory
51
+ try {
52
+ fs.mkdirSync(dest, { recursive: true })
53
+ } catch (err) {
54
+ console.warn('[ui-kit] Could not create font directory:', dest)
55
+ console.warn('[ui-kit] Error:', err.message)
56
+ console.warn('[ui-kit] You may need to copy fonts manually. See FONTS.md for setup.')
57
+ process.exit(0)
58
+ }
59
+
60
+ // Copy .otf files (skip if already exists to avoid overwriting user modifications)
61
+ const files = fs.readdirSync(src).filter(f => f.endsWith('.otf'))
62
+ let copied = 0
63
+ let skipped = 0
64
+
65
+ for (const file of files) {
66
+ const srcFile = path.join(src, file)
67
+ const destFile = path.join(dest, file)
68
+
69
+ if (fs.existsSync(destFile)) {
70
+ skipped++
71
+ continue
72
+ }
73
+
74
+ try {
75
+ fs.copyFileSync(srcFile, destFile)
76
+ copied++
77
+ } catch (err) {
78
+ console.warn(`[ui-kit] Failed to copy ${file}:`, err.message)
79
+ }
80
+ }
81
+
82
+ if (copied > 0) {
83
+ console.log(`[ui-kit] Copied ${copied} Sohne font files → assets/fonts/sohne/`)
84
+ }
85
+ if (skipped > 0 && copied === 0) {
86
+ // All fonts already present — no message needed
87
+ }
88
+ if (copied > 0 || (skipped > 0 && process.env.VERBOSE)) {
89
+ console.log('[ui-kit] Add SohneFonts to your App.tsx — see CONSUMER.md for the boilerplate.')
90
+ }
@@ -0,0 +1,82 @@
1
+ #!/usr/bin/env bash
2
+ # Verifies that dist/fonts.js paths resolve correctly from a consumer's perspective.
3
+ # Simulates what npm publish sends: packs the package, installs into a temp Expo app,
4
+ # then checks that Metro can find all .otf files without ../traversal.
5
+ #
6
+ # Run from repo root: ./scripts/test-consumer-fonts.sh
7
+ set -euo pipefail
8
+
9
+ ROOT="$(cd "$(dirname "$0")/.." && pwd)"
10
+ TMP="$(mktemp -d)"
11
+ PACK_DIR="$TMP/pack"
12
+
13
+ # Find npm — prefer nvm node, fallback to PATH
14
+ NPM_BIN=""
15
+ for node_dir in "$HOME"/.nvm/versions/node/*/bin; do
16
+ if [ -f "$node_dir/npm" ]; then NPM_BIN="$node_dir/npm"; fi
17
+ done
18
+ if [ -z "$NPM_BIN" ]; then NPM_BIN="npm"; fi
19
+
20
+ cleanup() { rm -rf "$TMP"; }
21
+ trap cleanup EXIT
22
+
23
+ echo "=== 1. Build ui-kit ==="
24
+ cd "$ROOT"
25
+ pnpm build
26
+
27
+ echo ""
28
+ echo "=== 2. Pack (simulates npm publish tarball) ==="
29
+ mkdir -p "$PACK_DIR"
30
+ cd "$ROOT"
31
+ TARBALL=$("$NPM_BIN" pack --pack-destination "$PACK_DIR" 2>/dev/null | tail -1)
32
+ TARBALL_PATH="$PACK_DIR/$TARBALL"
33
+ echo "Packed: $TARBALL_PATH"
34
+
35
+ echo ""
36
+ echo "=== 3. Verify tarball contents ==="
37
+ echo "Files in tarball matching fonts:"
38
+ tar -tzf "$TARBALL_PATH" | grep -E "(fonts|\.otf)" | sort
39
+
40
+ echo ""
41
+ echo "=== 4. Check dist/fonts.js paths stay within dist/ ==="
42
+ tar -xzf "$TARBALL_PATH" -C "$TMP" package/dist/fonts.js 2>/dev/null
43
+
44
+ FONTS_JS="$TMP/package/dist/fonts.js"
45
+ if grep -q "\.\./src" "$FONTS_JS"; then
46
+ echo "FAIL: dist/fonts.js still contains ../src traversal:"
47
+ grep "\.\./src" "$FONTS_JS"
48
+ exit 1
49
+ else
50
+ echo "OK: No ../src traversal found in dist/fonts.js"
51
+ fi
52
+
53
+ echo ""
54
+ echo "=== 5. Verify all 28 .otf files exist in dist/assets/fonts/ ==="
55
+ OTF_COUNT=$(tar -tzf "$TARBALL_PATH" | grep "^package/dist/assets/fonts/.*\.otf$" | wc -l | tr -d ' ')
56
+ if [ "$OTF_COUNT" -eq 28 ]; then
57
+ echo "OK: 28 .otf files present in dist/assets/fonts/ inside tarball"
58
+ else
59
+ echo "FAIL: expected 28 .otf files in dist/assets/fonts/, found $OTF_COUNT"
60
+ tar -tzf "$TARBALL_PATH" | grep "^package/dist/assets/fonts/.*\.otf$"
61
+ exit 1
62
+ fi
63
+
64
+ echo ""
65
+ echo "=== 6. Validate require paths — no ../traversal ==="
66
+ TRAVERSALS=$(grep -oE '"[^"]+\.otf"' "$FONTS_JS" | grep "\.\." || true)
67
+ if [ -n "$TRAVERSALS" ]; then
68
+ echo "FAIL: Traversal paths found in dist/fonts.js:"
69
+ echo "$TRAVERSALS"
70
+ exit 1
71
+ else
72
+ echo "OK: All .otf require() paths use ./ (within dist/)"
73
+ fi
74
+
75
+ echo ""
76
+ echo "=== PASS: Consumer font resolution looks correct ==="
77
+ echo "dist/fonts.js uses ./assets/fonts/ paths"
78
+ echo "All 28 .otf files are present in dist/assets/fonts/ in the tarball"
79
+ echo ""
80
+ echo "Consumer usage (no watchFolders hack needed):"
81
+ echo " import { SohneFonts } from '@retray-dev/ui-kit/fonts'"
82
+ echo " useFonts(SohneFonts)"
package/src/fonts.ts CHANGED
@@ -1,52 +1,72 @@
1
1
  /**
2
- * Sohne font family required by @retray-dev/ui-kit components.
2
+ * Sohne font family names for @retray-dev/ui-kit components.
3
3
  *
4
- * Consumer apps must load these fonts at app root using expo-font:
4
+ * The postinstall script copies 28 .otf files to your project's assets/fonts/sohne/ folder.
5
+ * You must define SohneFonts with static require() calls in your App.tsx:
5
6
  *
6
7
  * @example
7
8
  * import { useFonts } from 'expo-font'
8
- * import { SohneFonts } from '@retray-dev/ui-kit/fonts'
9
+ *
10
+ * // Fonts copied to assets/fonts/sohne/ by @retray-dev/ui-kit postinstall
11
+ * const SohneFonts = {
12
+ * 'Sohne-ExtraLight': require('./assets/fonts/sohne/Sohne-ExtraLight.otf'),
13
+ * 'Sohne-ExtraLightItalic': require('./assets/fonts/sohne/Sohne-ExtraLightItalic.otf'),
14
+ * // ... see CONSUMER.md for full boilerplate
15
+ * }
9
16
  *
10
17
  * function App() {
11
18
  * const [fontsLoaded] = useFonts(SohneFonts)
12
19
  * if (!fontsLoaded) return null
13
20
  * // render app
14
21
  * }
22
+ *
23
+ * @see CONSUMER.md for the full SohneFonts boilerplate to copy into your App.tsx
15
24
  */
16
- // `.otf` assets resolve to a Metro asset module id (number) via require() at the
17
- // consumer's build time. Paths are relative to dist/fonts.js (the compiled output).
18
- // Both dist/ and src/ are published in the package, so ../src/assets/fonts/ resolves correctly.
19
- declare const require: (path: string) => number
20
25
 
21
- export const SohneFonts = {
22
- // Sohne base
23
- 'Sohne-ExtraLight': require('../src/assets/fonts/Sohne-ExtraLight.otf'),
24
- 'Sohne-ExtraLightItalic': require('../src/assets/fonts/Sohne-ExtraLightItalic.otf'),
25
- 'Sohne-Light': require('../src/assets/fonts/Sohne-Light.otf'),
26
- 'Sohne-LightItalic': require('../src/assets/fonts/Sohne-LightItalic.otf'),
27
- 'Sohne-Regular': require('../src/assets/fonts/Sohne-Regular.otf'),
28
- 'Sohne-Italic': require('../src/assets/fonts/Sohne-Italic.otf'),
29
- 'Sohne-Medium': require('../src/assets/fonts/Sohne-Medium.otf'),
30
- 'Sohne-MediumItalic': require('../src/assets/fonts/Sohne-MediumItalic.otf'),
31
- 'Sohne-SemiBold': require('../src/assets/fonts/Sohne-SemiBold.otf'),
32
- 'Sohne-SemiBoldItalic': require('../src/assets/fonts/Sohne-SemiBoldItalic.otf'),
33
- 'Sohne-Bold': require('../src/assets/fonts/Sohne-Bold.otf'),
34
- 'Sohne-BoldItalic': require('../src/assets/fonts/Sohne-BoldItalic.otf'),
35
- 'Sohne-ExtraBold': require('../src/assets/fonts/Sohne-ExtraBold.otf'),
36
- 'Sohne-ExtraBoldItalic': require('../src/assets/fonts/Sohne-ExtraBoldItalic.otf'),
37
- // SohneMono
38
- 'SohneMono-ExtraLight': require('../src/assets/fonts/SohneMono-ExtraLight.otf'),
39
- 'SohneMono-ExtraLightItalic': require('../src/assets/fonts/SohneMono-ExtraLightItalic.otf'),
40
- 'SohneMono-Light': require('../src/assets/fonts/SohneMono-Light.otf'),
41
- 'SohneMono-LightItalic': require('../src/assets/fonts/SohneMono-LightItalic.otf'),
42
- 'SohneMono-Regular': require('../src/assets/fonts/SohneMono-Regular.otf'),
43
- 'SohneMono-Italic': require('../src/assets/fonts/SohneMono-Italic.otf'),
44
- 'SohneMono-Medium': require('../src/assets/fonts/SohneMono-Medium.otf'),
45
- 'SohneMono-MediumItalic': require('../src/assets/fonts/SohneMono-MediumItalic.otf'),
46
- 'SohneMono-SemiBold': require('../src/assets/fonts/SohneMono-SemiBold.otf'),
47
- 'SohneMono-SemiBoldItalic': require('../src/assets/fonts/SohneMono-SemiBoldItalic.otf'),
48
- 'SohneMono-Bold': require('../src/assets/fonts/SohneMono-Bold.otf'),
49
- 'SohneMono-BoldItalic': require('../src/assets/fonts/SohneMono-BoldItalic.otf'),
50
- 'SohneMono-ExtraBold': require('../src/assets/fonts/SohneMono-ExtraBold.otf'),
51
- 'SohneMono-ExtraBoldItalic': require('../src/assets/fonts/SohneMono-ExtraBoldItalic.otf'),
52
- } as const
26
+ /**
27
+ * Array of all 28 Sohne font family names.
28
+ * Use this for validation or programmatic checks — NOT for loading fonts.
29
+ * To load fonts, use the static require() boilerplate from CONSUMER.md.
30
+ */
31
+ export const SohneFontNames = [
32
+ // Sohne base (14)
33
+ 'Sohne-ExtraLight',
34
+ 'Sohne-ExtraLightItalic',
35
+ 'Sohne-Light',
36
+ 'Sohne-LightItalic',
37
+ 'Sohne-Regular',
38
+ 'Sohne-Italic',
39
+ 'Sohne-Medium',
40
+ 'Sohne-MediumItalic',
41
+ 'Sohne-SemiBold',
42
+ 'Sohne-SemiBoldItalic',
43
+ 'Sohne-Bold',
44
+ 'Sohne-BoldItalic',
45
+ 'Sohne-ExtraBold',
46
+ 'Sohne-ExtraBoldItalic',
47
+ // SohneMono (14)
48
+ 'SohneMono-ExtraLight',
49
+ 'SohneMono-ExtraLightItalic',
50
+ 'SohneMono-Light',
51
+ 'SohneMono-LightItalic',
52
+ 'SohneMono-Regular',
53
+ 'SohneMono-Italic',
54
+ 'SohneMono-Medium',
55
+ 'SohneMono-MediumItalic',
56
+ 'SohneMono-SemiBold',
57
+ 'SohneMono-SemiBoldItalic',
58
+ 'SohneMono-Bold',
59
+ 'SohneMono-BoldItalic',
60
+ 'SohneMono-ExtraBold',
61
+ 'SohneMono-ExtraBoldItalic',
62
+ ] as const
63
+
64
+ /** Type for any valid Sohne font family name */
65
+ export type SohneFontName = (typeof SohneFontNames)[number]
66
+
67
+ /**
68
+ * @deprecated SohneFonts export removed in v10.0.0.
69
+ * Metro cannot resolve require() calls from node_modules reliably.
70
+ * Copy the static SohneFonts boilerplate from CONSUMER.md into your App.tsx instead.
71
+ */
72
+ export const SohneFonts = undefined