react-native-tinyui 0.4.0 → 0.5.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 (34) hide show
  1. package/README.md +32 -31
  2. package/ios/LiquidGlassText/TinyuiLiquidGlassTextProvider.swift +64 -79
  3. package/ios/LiquidGlassText/TinyuiLiquidGlassTextShadowNode.h +46 -0
  4. package/ios/LiquidGlassText/TinyuiLiquidGlassTextShadowNode.mm +159 -0
  5. package/ios/LiquidGlassText/TinyuiLiquidGlassTextView.mm +6 -27
  6. package/ios/LiquidGlassText/TinyuiTextOutlineShape.swift +5 -2
  7. package/ios/Menu/TinyuiMenuProvider.swift +2 -2
  8. package/ios/Menu/TinyuiMenuView.mm +2 -1
  9. package/ios/Menu/TinyuiMenuViewSwift.swift +42 -124
  10. package/lib/module/LiquidGlassText/LiquidGlassTextNativeComponent.ts +2 -12
  11. package/lib/module/LiquidGlassText/index.js +60 -35
  12. package/lib/module/LiquidGlassText/index.js.map +1 -1
  13. package/lib/module/Menu/MenuNativeComponent.ts +6 -2
  14. package/lib/module/Menu/options.js +2 -2
  15. package/lib/module/Menu/options.js.map +1 -1
  16. package/lib/typescript/src/LiquidGlassText/LiquidGlassTextNativeComponent.d.ts +2 -8
  17. package/lib/typescript/src/LiquidGlassText/LiquidGlassTextNativeComponent.d.ts.map +1 -1
  18. package/lib/typescript/src/LiquidGlassText/index.d.ts +1 -1
  19. package/lib/typescript/src/LiquidGlassText/index.d.ts.map +1 -1
  20. package/lib/typescript/src/LiquidGlassText/types.d.ts +13 -22
  21. package/lib/typescript/src/LiquidGlassText/types.d.ts.map +1 -1
  22. package/lib/typescript/src/Menu/MenuNativeComponent.d.ts +2 -2
  23. package/lib/typescript/src/Menu/MenuNativeComponent.d.ts.map +1 -1
  24. package/lib/typescript/src/Menu/options.d.ts +41 -1
  25. package/lib/typescript/src/Menu/options.d.ts.map +1 -1
  26. package/lib/typescript/src/index.d.ts +1 -1
  27. package/lib/typescript/src/index.d.ts.map +1 -1
  28. package/package.json +1 -1
  29. package/src/LiquidGlassText/LiquidGlassTextNativeComponent.ts +2 -12
  30. package/src/LiquidGlassText/index.tsx +73 -39
  31. package/src/LiquidGlassText/types.ts +24 -50
  32. package/src/Menu/MenuNativeComponent.ts +6 -2
  33. package/src/Menu/options.ts +6 -2
  34. package/src/index.tsx +2 -4
@@ -1,23 +1,13 @@
1
1
  import {
2
2
  codegenNativeComponent,
3
+ type CodegenTypes,
3
4
  type ColorValue,
4
5
  type ViewProps,
5
6
  } from 'react-native';
6
- import type {
7
- DirectEventHandler,
8
- Double,
9
- } from 'react-native/Libraries/Types/CodegenTypes';
10
7
 
11
8
  export interface NativeLiquidGlassTextProps extends ViewProps {
12
- configuration: string;
9
+ configuration: CodegenTypes.UnsafeMixed;
13
10
  tintColor?: ColorValue;
14
- onContentSizeChange?: DirectEventHandler<
15
- Readonly<{
16
- width: Double;
17
- height: Double;
18
- configuration: string;
19
- }>
20
- >;
21
11
  }
22
12
 
23
13
  export default codegenNativeComponent<NativeLiquidGlassTextProps>(
@@ -1,21 +1,63 @@
1
- import { forwardRef, useState, type ComponentRef } from 'react';
2
- import type { View } from 'react-native';
1
+ import { forwardRef, type ComponentRef } from 'react';
2
+ import { StyleSheet, type TextStyle, type View } from 'react-native';
3
3
 
4
4
  import { assertComponentEnabled } from '../utils';
5
5
  import type { LiquidGlassTextProps } from './types';
6
6
  import NativeLiquidGlassTextView from './LiquidGlassTextNativeComponent';
7
7
 
8
+ function normalizeFontWeight(
9
+ fontWeight: TextStyle['fontWeight']
10
+ ): string | undefined {
11
+ if (fontWeight == null) {
12
+ return undefined;
13
+ }
14
+
15
+ const value = String(fontWeight);
16
+ const aliases: Readonly<Record<string, string>> = {
17
+ 'normal': 'regular',
18
+ 'ultralight': 'ultraLight',
19
+ 'condensed': 'regular',
20
+ 'condensedBold': 'bold',
21
+ '100': 'ultraLight',
22
+ '200': 'thin',
23
+ '300': 'light',
24
+ '400': 'regular',
25
+ '500': 'medium',
26
+ '600': 'semibold',
27
+ '700': 'bold',
28
+ '800': 'heavy',
29
+ '900': 'black',
30
+ };
31
+ return aliases[value] ?? value;
32
+ }
33
+
34
+ function resolveAlignment(
35
+ textAlign: TextStyle['textAlign']
36
+ ): 'leading' | 'center' | 'trailing' | undefined {
37
+ switch (textAlign) {
38
+ case 'center':
39
+ return 'center';
40
+ case 'right':
41
+ return 'trailing';
42
+ case 'left':
43
+ return 'leading';
44
+ default:
45
+ return undefined;
46
+ }
47
+ }
48
+
8
49
  export const LiquidGlassText = forwardRef<
9
50
  ComponentRef<typeof View>,
10
51
  LiquidGlassTextProps
11
52
  >(function LiquidGlassTextRoot(
12
53
  {
13
54
  text,
14
- glass = 'clear',
15
- font = 'body',
16
- fontWeight,
55
+ effect = 'clear',
56
+ tint,
57
+ interactive = false,
17
58
  fontDesign,
18
- multilineTextAlignment = 'leading',
59
+ textStyle,
60
+ multilineTextAlignment,
19
61
  style,
20
62
  accessibilityLabel,
21
63
  accessible = true,
@@ -26,20 +68,29 @@ export const LiquidGlassText = forwardRef<
26
68
  ) {
27
69
  assertComponentEnabled('LiquidGlassText');
28
70
 
29
- const [measurement, setMeasurement] = useState({
30
- width: 0,
31
- height: 0,
32
- });
33
- const configuration = JSON.stringify({
71
+ const flattenedTextStyle = StyleSheet.flatten(textStyle);
72
+ const normalizedTextStyle = flattenedTextStyle
73
+ ? {
74
+ fontSize: flattenedTextStyle.fontSize,
75
+ fontFamily: flattenedTextStyle.fontFamily,
76
+ fontWeight: normalizeFontWeight(flattenedTextStyle.fontWeight),
77
+ fontStyle: flattenedTextStyle.fontStyle,
78
+ letterSpacing: flattenedTextStyle.letterSpacing,
79
+ }
80
+ : undefined;
81
+ const resolvedAlignment =
82
+ multilineTextAlignment ??
83
+ resolveAlignment(flattenedTextStyle?.textAlign) ??
84
+ 'leading';
85
+
86
+ const configuration = {
34
87
  text,
35
- glass: typeof glass === 'string' ? glass : (glass.effect ?? 'clear'),
36
- interactive: typeof glass === 'object' && (glass.interactive ?? false),
37
- font: typeof font === 'string' ? { style: font } : font,
38
- fontWeight,
88
+ effect,
89
+ interactive,
39
90
  fontDesign,
40
- multilineTextAlignment,
41
- });
42
-
91
+ ...(normalizedTextStyle ? { textStyle: normalizedTextStyle } : {}),
92
+ multilineTextAlignment: resolvedAlignment,
93
+ };
43
94
  return (
44
95
  <NativeLiquidGlassTextView
45
96
  {...viewProps}
@@ -48,32 +99,15 @@ export const LiquidGlassText = forwardRef<
48
99
  accessibilityRole={accessibilityRole}
49
100
  accessibilityLabel={accessibilityLabel ?? text}
50
101
  configuration={configuration}
51
- tintColor={typeof glass === 'object' ? glass.tint : undefined}
52
- style={[{ width: measurement.width, height: measurement.height }, style]}
53
- onContentSizeChange={({ nativeEvent }) => {
54
- // Ignore measurements queued before a newer text/font update.
55
- if (nativeEvent.configuration !== configuration) {
56
- return;
57
- }
58
- setMeasurement((previous) =>
59
- previous.width === nativeEvent.width &&
60
- previous.height === nativeEvent.height
61
- ? previous
62
- : {
63
- width: nativeEvent.width,
64
- height: nativeEvent.height,
65
- }
66
- );
67
- }}
102
+ tintColor={tint ?? flattenedTextStyle?.color}
103
+ style={style}
68
104
  />
69
105
  );
70
106
  });
71
107
 
72
108
  export type {
73
- LiquidGlassTextFont,
74
109
  LiquidGlassTextFontDesign,
75
- LiquidGlassTextFontStyle,
76
- LiquidGlassTextFontWeight,
77
- LiquidGlassTextGlass,
110
+ LiquidGlassTextEffect,
78
111
  LiquidGlassTextProps,
112
+ LiquidGlassTextStyle,
79
113
  } from './types';
@@ -1,63 +1,37 @@
1
- import type { ColorValue, ViewProps } from 'react-native';
1
+ import type { ColorValue, StyleProp, TextStyle, ViewProps } from 'react-native';
2
2
 
3
3
  export type LiquidGlassTextFontDesign =
4
4
  'default' | 'serif' | 'monospaced' | 'rounded';
5
5
 
6
- export type LiquidGlassTextFontWeight =
7
- | 'ultraLight'
8
- | 'thin'
9
- | 'light'
10
- | 'regular'
11
- | 'medium'
12
- | 'semibold'
13
- | 'bold'
14
- | 'heavy'
15
- | 'black';
6
+ export type LiquidGlassTextEffect = 'clear' | 'regular' | 'identity';
16
7
 
17
- export type LiquidGlassTextFontStyle =
18
- | 'largeTitle'
19
- | 'title'
20
- | 'title2'
21
- | 'title3'
22
- | 'headline'
23
- | 'subheadline'
24
- | 'body'
25
- | 'callout'
26
- | 'footnote'
27
- | 'caption'
28
- | 'caption2';
29
-
30
- export type LiquidGlassTextFont =
31
- | LiquidGlassTextFontStyle
32
- | Readonly<{
33
- size: number;
34
- weight?: LiquidGlassTextFontWeight;
35
- design?: LiquidGlassTextFontDesign;
36
- /** PostScript name of a font installed in the containing app. */
37
- family?: string;
38
- }>;
39
-
40
- export type LiquidGlassTextGlass =
41
- | 'clear'
42
- | 'regular'
43
- | 'identity'
44
- | Readonly<{
45
- effect?: 'clear' | 'regular' | 'identity';
46
- tint?: ColorValue;
47
- interactive?: boolean;
48
- }>;
8
+ /** React Native text styles supported by the native glass renderer. */
9
+ export type LiquidGlassTextStyle = Readonly<
10
+ Pick<
11
+ TextStyle,
12
+ | 'color'
13
+ | 'fontFamily'
14
+ | 'fontSize'
15
+ | 'fontStyle'
16
+ | 'fontWeight'
17
+ | 'letterSpacing'
18
+ | 'textAlign'
19
+ >
20
+ >;
49
21
 
50
22
  export interface LiquidGlassTextProps extends Omit<ViewProps, 'children'> {
51
23
  /** Text to display. Pass translated strings from JavaScript if needed. */
52
24
  text: string;
53
- /** Defaults to clear. Native glass requires iOS 26+. */
54
- glass?: LiquidGlassTextGlass;
55
- /** SwiftUI text style or an explicit system/custom font. Defaults to body. */
56
- font?: LiquidGlassTextFont;
57
- /** Overrides the weight specified in font. */
58
- fontWeight?: LiquidGlassTextFontWeight;
59
- /** Overrides the design specified in font. */
25
+ /** Glass effect. Defaults to clear. Native glass requires iOS 26+. */
26
+ effect?: LiquidGlassTextEffect;
27
+ /** Glass tint and fallback text color. */
28
+ tint?: ColorValue;
29
+ /** Whether the glass responds to pointer and touch interaction. */
30
+ interactive?: boolean;
31
+ /** Overrides the system font design. */
60
32
  fontDesign?: LiquidGlassTextFontDesign;
33
+ /** Familiar React Native text styles. Explicit alignment takes precedence. */
34
+ textStyle?: StyleProp<LiquidGlassTextStyle>;
61
35
  /** Aligns explicit newline-separated lines. Defaults to leading. */
62
36
  multilineTextAlignment?: 'leading' | 'center' | 'trailing';
63
37
  }
@@ -1,8 +1,12 @@
1
- import { codegenNativeComponent, type ViewProps } from 'react-native';
1
+ import {
2
+ codegenNativeComponent,
3
+ type CodegenTypes,
4
+ type ViewProps,
5
+ } from 'react-native';
2
6
  import type { DirectEventHandler } from 'react-native/Libraries/Types/CodegenTypes';
3
7
 
4
8
  export interface NativeMenuProps extends ViewProps {
5
- menuConfig: string;
9
+ menuConfig: CodegenTypes.UnsafeMixed;
6
10
  title?: string;
7
11
  disabled?: boolean;
8
12
  hasPrimaryAction?: boolean;
@@ -48,8 +48,12 @@ type NativeMenuElement =
48
48
  | NativeMenuSection
49
49
  | NativeMenuSeparator;
50
50
 
51
+ interface NativeMenuConfiguration {
52
+ items: NativeMenuElement[];
53
+ }
54
+
51
55
  export interface SerializedMenuOptions {
52
- config: string;
56
+ config: NativeMenuConfiguration;
53
57
  callbacks: Map<string, () => void>;
54
58
  }
55
59
 
@@ -65,7 +69,7 @@ export function serializeMenuOptions(
65
69
 
66
70
  return {
67
71
  callbacks,
68
- config: JSON.stringify({ items }),
72
+ config: { items },
69
73
  };
70
74
  }
71
75
 
package/src/index.tsx CHANGED
@@ -24,10 +24,8 @@ export type { TinyuiComponent } from './utils';
24
24
 
25
25
  export { LiquidGlassText } from './LiquidGlassText';
26
26
  export type {
27
- LiquidGlassTextFont,
28
27
  LiquidGlassTextFontDesign,
29
- LiquidGlassTextFontStyle,
30
- LiquidGlassTextFontWeight,
31
- LiquidGlassTextGlass,
28
+ LiquidGlassTextEffect,
32
29
  LiquidGlassTextProps,
30
+ LiquidGlassTextStyle,
33
31
  } from './LiquidGlassText';