react-native-tinyui 0.4.0 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +383 -53
- package/ios/ConcentricView/TinyuiConcentricView.h +12 -0
- package/ios/ConcentricView/TinyuiConcentricView.mm +60 -0
- package/ios/Core/Tinyui.mm +54 -0
- package/ios/Core/TinyuiComponentClasses.mm +44 -0
- package/ios/LiquidGlassText/TinyuiLiquidGlassTextProvider.swift +64 -79
- package/ios/LiquidGlassText/TinyuiLiquidGlassTextShadowNode.h +46 -0
- package/ios/LiquidGlassText/TinyuiLiquidGlassTextShadowNode.mm +159 -0
- package/ios/LiquidGlassText/TinyuiLiquidGlassTextView.mm +6 -27
- package/ios/LiquidGlassText/TinyuiTextOutlineShape.swift +5 -2
- package/ios/Menu/TinyuiMenuBuilder.swift +238 -0
- package/ios/Menu/TinyuiMenuProvider.swift +51 -85
- package/ios/Menu/TinyuiMenuView.mm +13 -35
- package/ios/Popover/TinyuiPopoverProvider.swift +198 -44
- package/ios/Popover/TinyuiPopoverView.mm +26 -1
- package/ios/SFSymbol/TinyuiSFSymbolEffects.h +9 -0
- package/ios/SFSymbol/TinyuiSFSymbolEffects.mm +180 -0
- package/ios/SFSymbol/TinyuiSFSymbolImage.h +8 -0
- package/ios/SFSymbol/TinyuiSFSymbolImage.mm +141 -0
- package/ios/SFSymbol/TinyuiSFSymbolShadowNode.h +31 -0
- package/ios/SFSymbol/TinyuiSFSymbolShadowNode.mm +30 -0
- package/ios/SFSymbol/TinyuiSFSymbolView.h +4 -0
- package/ios/SFSymbol/TinyuiSFSymbolView.mm +173 -0
- package/ios/Stepper/TinyuiStepperShadowNode.h +32 -0
- package/ios/Stepper/TinyuiStepperShadowNode.mm +28 -0
- package/ios/Stepper/TinyuiStepperView.h +12 -0
- package/ios/Stepper/TinyuiStepperView.mm +128 -0
- package/ios/TipKit/TinyuiTip.swift +31 -0
- package/ios/TipKit/TinyuiTipPopoverProvider.swift +276 -0
- package/ios/TipKit/TinyuiTipPopoverView.h +8 -0
- package/ios/TipKit/TinyuiTipPopoverView.mm +114 -0
- package/ios/TipKit/TinyuiTipsRuntime.swift +148 -0
- package/lib/module/ConcentricView/ConcentricViewNativeComponent.ts +14 -0
- package/lib/module/ConcentricView/index.js +29 -0
- package/lib/module/ConcentricView/index.js.map +1 -0
- package/lib/module/ConcentricView/types.js +4 -0
- package/lib/module/ConcentricView/types.js.map +1 -0
- package/lib/module/LiquidGlassText/LiquidGlassTextNativeComponent.ts +2 -12
- package/lib/module/LiquidGlassText/index.js +60 -35
- package/lib/module/LiquidGlassText/index.js.map +1 -1
- package/lib/module/Menu/MenuNativeComponent.ts +7 -5
- package/lib/module/Menu/index.js +4 -9
- package/lib/module/Menu/index.js.map +1 -1
- package/lib/module/Menu/options.js +4 -12
- package/lib/module/Menu/options.js.map +1 -1
- package/lib/module/NativeTinyui.js.map +1 -1
- package/lib/module/Popover/index.js +4 -2
- package/lib/module/Popover/index.js.map +1 -1
- package/lib/module/SFSymbol/SFSymbolNativeComponent.ts +20 -0
- package/lib/module/SFSymbol/index.js +73 -0
- package/lib/module/SFSymbol/index.js.map +1 -0
- package/lib/module/SFSymbol/options.js +79 -0
- package/lib/module/SFSymbol/options.js.map +1 -0
- package/lib/module/SFSymbol/types.js +4 -0
- package/lib/module/SFSymbol/types.js.map +1 -0
- package/lib/module/Stepper/StepperNativeComponent.ts +29 -0
- package/lib/module/Stepper/index.js +75 -0
- package/lib/module/Stepper/index.js.map +1 -0
- package/lib/module/Stepper/types.js +4 -0
- package/lib/module/Stepper/types.js.map +1 -0
- package/lib/module/TipKit/Popover.js +89 -0
- package/lib/module/TipKit/Popover.js.map +1 -0
- package/lib/module/TipKit/TipPopoverNativeComponent.ts +37 -0
- package/lib/module/TipKit/index.js +28 -0
- package/lib/module/TipKit/index.js.map +1 -0
- package/lib/module/TipKit/types.js +4 -0
- package/lib/module/TipKit/types.js.map +1 -0
- package/lib/module/TipKit/validation.js +24 -0
- package/lib/module/TipKit/validation.js.map +1 -0
- package/lib/module/index.js +4 -0
- package/lib/module/index.js.map +1 -1
- package/lib/module/utils/getNativeTinyui.js.map +1 -1
- package/lib/typescript/src/ConcentricView/ConcentricViewNativeComponent.d.ts +7 -0
- package/lib/typescript/src/ConcentricView/ConcentricViewNativeComponent.d.ts.map +1 -0
- package/lib/typescript/src/ConcentricView/index.d.ts +4 -0
- package/lib/typescript/src/ConcentricView/index.d.ts.map +1 -0
- package/lib/typescript/src/ConcentricView/types.d.ts +6 -0
- package/lib/typescript/src/ConcentricView/types.d.ts.map +1 -0
- package/lib/typescript/src/LiquidGlassText/LiquidGlassTextNativeComponent.d.ts +2 -8
- package/lib/typescript/src/LiquidGlassText/LiquidGlassTextNativeComponent.d.ts.map +1 -1
- package/lib/typescript/src/LiquidGlassText/index.d.ts +1 -1
- package/lib/typescript/src/LiquidGlassText/index.d.ts.map +1 -1
- package/lib/typescript/src/LiquidGlassText/types.d.ts +13 -22
- package/lib/typescript/src/LiquidGlassText/types.d.ts.map +1 -1
- package/lib/typescript/src/Menu/MenuNativeComponent.d.ts +4 -5
- package/lib/typescript/src/Menu/MenuNativeComponent.d.ts.map +1 -1
- package/lib/typescript/src/Menu/index.d.ts +1 -1
- package/lib/typescript/src/Menu/index.d.ts.map +1 -1
- package/lib/typescript/src/Menu/options.d.ts +40 -4
- package/lib/typescript/src/Menu/options.d.ts.map +1 -1
- package/lib/typescript/src/Menu/types.d.ts +16 -4
- package/lib/typescript/src/Menu/types.d.ts.map +1 -1
- package/lib/typescript/src/NativeTinyui.d.ts +2 -0
- package/lib/typescript/src/NativeTinyui.d.ts.map +1 -1
- package/lib/typescript/src/Popover/index.d.ts.map +1 -1
- package/lib/typescript/src/Popover/types.d.ts +2 -0
- package/lib/typescript/src/Popover/types.d.ts.map +1 -1
- package/lib/typescript/src/SFSymbol/SFSymbolNativeComponent.d.ts +11 -0
- package/lib/typescript/src/SFSymbol/SFSymbolNativeComponent.d.ts.map +1 -0
- package/lib/typescript/src/SFSymbol/index.d.ts +4 -0
- package/lib/typescript/src/SFSymbol/index.d.ts.map +1 -0
- package/lib/typescript/src/SFSymbol/options.d.ts +86 -0
- package/lib/typescript/src/SFSymbol/options.d.ts.map +1 -0
- package/lib/typescript/src/SFSymbol/types.d.ts +113 -0
- package/lib/typescript/src/SFSymbol/types.d.ts.map +1 -0
- package/lib/typescript/src/Stepper/StepperNativeComponent.d.ts +21 -0
- package/lib/typescript/src/Stepper/StepperNativeComponent.d.ts.map +1 -0
- package/lib/typescript/src/Stepper/index.d.ts +4 -0
- package/lib/typescript/src/Stepper/index.d.ts.map +1 -0
- package/lib/typescript/src/Stepper/types.d.ts +24 -0
- package/lib/typescript/src/Stepper/types.d.ts.map +1 -0
- package/lib/typescript/src/TipKit/Popover.d.ts +3 -0
- package/lib/typescript/src/TipKit/Popover.d.ts.map +1 -0
- package/lib/typescript/src/TipKit/TipPopoverNativeComponent.d.ts +38 -0
- package/lib/typescript/src/TipKit/TipPopoverNativeComponent.d.ts.map +1 -0
- package/lib/typescript/src/TipKit/index.d.ts +10 -0
- package/lib/typescript/src/TipKit/index.d.ts.map +1 -0
- package/lib/typescript/src/TipKit/types.d.ts +46 -0
- package/lib/typescript/src/TipKit/types.d.ts.map +1 -0
- package/lib/typescript/src/TipKit/validation.d.ts +4 -0
- package/lib/typescript/src/TipKit/validation.d.ts.map +1 -0
- package/lib/typescript/src/index.d.ts +10 -2
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/lib/typescript/src/utils/getNativeTinyui.d.ts +1 -1
- package/lib/typescript/src/utils/getNativeTinyui.d.ts.map +1 -1
- package/package.json +37 -2
- package/{Tinyui.podspec → react-native-tinyui.podspec} +23 -2
- package/src/ConcentricView/ConcentricViewNativeComponent.ts +14 -0
- package/src/ConcentricView/index.tsx +34 -0
- package/src/ConcentricView/types.ts +6 -0
- package/src/LiquidGlassText/LiquidGlassTextNativeComponent.ts +2 -12
- package/src/LiquidGlassText/index.tsx +73 -39
- package/src/LiquidGlassText/types.ts +24 -50
- package/src/Menu/MenuNativeComponent.ts +7 -5
- package/src/Menu/index.tsx +6 -6
- package/src/Menu/options.ts +4 -18
- package/src/Menu/types.ts +18 -4
- package/src/NativeTinyui.ts +2 -0
- package/src/Popover/index.tsx +8 -3
- package/src/Popover/types.ts +2 -0
- package/src/SFSymbol/SFSymbolNativeComponent.ts +20 -0
- package/src/SFSymbol/index.tsx +89 -0
- package/src/SFSymbol/options.ts +116 -0
- package/src/SFSymbol/types.ts +158 -0
- package/src/Stepper/StepperNativeComponent.ts +29 -0
- package/src/Stepper/index.tsx +91 -0
- package/src/Stepper/types.ts +24 -0
- package/src/TipKit/Popover.tsx +87 -0
- package/src/TipKit/TipPopoverNativeComponent.ts +37 -0
- package/src/TipKit/index.ts +47 -0
- package/src/TipKit/types.ts +57 -0
- package/src/TipKit/validation.ts +39 -0
- package/src/index.tsx +32 -4
- package/src/utils/getNativeTinyui.ts +8 -1
- package/ios/Core/TinyuiHostingHelpers.swift +0 -74
- package/ios/Menu/TinyuiMenuViewSwift.swift +0 -408
- package/ios/Popover/TinyuiPopoverViewSwift.swift +0 -88
|
@@ -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:
|
|
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,
|
|
2
|
-
import type
|
|
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
|
-
|
|
15
|
-
|
|
16
|
-
|
|
55
|
+
effect = 'clear',
|
|
56
|
+
tint,
|
|
57
|
+
interactive = false,
|
|
17
58
|
fontDesign,
|
|
18
|
-
|
|
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
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
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
|
-
|
|
36
|
-
interactive
|
|
37
|
-
font: typeof font === 'string' ? { style: font } : font,
|
|
38
|
-
fontWeight,
|
|
88
|
+
effect,
|
|
89
|
+
interactive,
|
|
39
90
|
fontDesign,
|
|
40
|
-
|
|
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={
|
|
52
|
-
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
|
-
|
|
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
|
|
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
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
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
|
-
|
|
55
|
-
/**
|
|
56
|
-
|
|
57
|
-
/**
|
|
58
|
-
|
|
59
|
-
/** Overrides the
|
|
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,13 +1,15 @@
|
|
|
1
|
-
import {
|
|
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:
|
|
9
|
+
menuConfig: CodegenTypes.UnsafeMixed;
|
|
6
10
|
title?: string;
|
|
7
11
|
disabled?: boolean;
|
|
8
|
-
|
|
9
|
-
onItemPress?: DirectEventHandler<Readonly<{ id: string }>>;
|
|
10
|
-
onPrimaryAction?: DirectEventHandler<null>;
|
|
12
|
+
onActionPress?: DirectEventHandler<Readonly<{ id: string; title: string }>>;
|
|
11
13
|
}
|
|
12
14
|
|
|
13
15
|
export default codegenNativeComponent<NativeMenuProps>('TinyuiMenuView', {
|
package/src/Menu/index.tsx
CHANGED
|
@@ -11,7 +11,7 @@ const MenuRoot = forwardRef<ComponentRef<typeof View>, MenuProps>(function Menu(
|
|
|
11
11
|
accessibilityLabel,
|
|
12
12
|
children,
|
|
13
13
|
disabled,
|
|
14
|
-
|
|
14
|
+
onActionPress,
|
|
15
15
|
options,
|
|
16
16
|
title,
|
|
17
17
|
testID,
|
|
@@ -21,17 +21,15 @@ const MenuRoot = forwardRef<ComponentRef<typeof View>, MenuProps>(function Menu(
|
|
|
21
21
|
) {
|
|
22
22
|
assertComponentEnabled('Menu');
|
|
23
23
|
|
|
24
|
-
const
|
|
24
|
+
const menuConfig = serializeMenuOptions(options);
|
|
25
25
|
|
|
26
26
|
return (
|
|
27
27
|
<View {...viewProps} ref={ref} collapsable={false}>
|
|
28
28
|
<NativeMenuView
|
|
29
29
|
accessibilityLabel={accessibilityLabel}
|
|
30
30
|
disabled={disabled}
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
onItemPress={(event) => callbacks.get(event.nativeEvent.id)?.()}
|
|
34
|
-
onPrimaryAction={onPrimaryAction}
|
|
31
|
+
menuConfig={menuConfig}
|
|
32
|
+
onActionPress={onActionPress}
|
|
35
33
|
testID={testID}
|
|
36
34
|
title={title}
|
|
37
35
|
>
|
|
@@ -45,6 +43,8 @@ export const Menu = MenuRoot as MenuComponent;
|
|
|
45
43
|
|
|
46
44
|
export type {
|
|
47
45
|
MenuActionOption,
|
|
46
|
+
MenuActionPressEvent,
|
|
47
|
+
MenuActionPressEventData,
|
|
48
48
|
MenuDividerOption,
|
|
49
49
|
MenuItemState,
|
|
50
50
|
MenuOption,
|
package/src/Menu/options.ts
CHANGED
|
@@ -48,9 +48,8 @@ type NativeMenuElement =
|
|
|
48
48
|
| NativeMenuSection
|
|
49
49
|
| NativeMenuSeparator;
|
|
50
50
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
callbacks: Map<string, () => void>;
|
|
51
|
+
interface NativeMenuConfiguration {
|
|
52
|
+
items: NativeMenuElement[];
|
|
54
53
|
}
|
|
55
54
|
|
|
56
55
|
function serializeColor(color: ColorValue | undefined): NativeMenuColor {
|
|
@@ -59,19 +58,12 @@ function serializeColor(color: ColorValue | undefined): NativeMenuColor {
|
|
|
59
58
|
|
|
60
59
|
export function serializeMenuOptions(
|
|
61
60
|
options: readonly MenuOption[]
|
|
62
|
-
):
|
|
63
|
-
|
|
64
|
-
const items = serializeOptions(options, callbacks, new Set(), 'root');
|
|
65
|
-
|
|
66
|
-
return {
|
|
67
|
-
callbacks,
|
|
68
|
-
config: JSON.stringify({ items }),
|
|
69
|
-
};
|
|
61
|
+
): NativeMenuConfiguration {
|
|
62
|
+
return { items: serializeOptions(options, new Set(), 'root') };
|
|
70
63
|
}
|
|
71
64
|
|
|
72
65
|
function serializeOptions(
|
|
73
66
|
options: readonly MenuOption[],
|
|
74
|
-
callbacks: Map<string, () => void>,
|
|
75
67
|
usedIds: Set<string>,
|
|
76
68
|
path: string
|
|
77
69
|
): NativeMenuElement[] {
|
|
@@ -97,7 +89,6 @@ function serializeOptions(
|
|
|
97
89
|
displayInline: option.displayInline ?? false,
|
|
98
90
|
children: serializeOptions(
|
|
99
91
|
option.options,
|
|
100
|
-
callbacks,
|
|
101
92
|
usedIds,
|
|
102
93
|
`${optionPath}.submenu`
|
|
103
94
|
),
|
|
@@ -110,7 +101,6 @@ function serializeOptions(
|
|
|
110
101
|
title: option.title,
|
|
111
102
|
children: serializeOptions(
|
|
112
103
|
option.options,
|
|
113
|
-
callbacks,
|
|
114
104
|
usedIds,
|
|
115
105
|
`${optionPath}.section`
|
|
116
106
|
),
|
|
@@ -123,10 +113,6 @@ function serializeOptions(
|
|
|
123
113
|
}
|
|
124
114
|
usedIds.add(id);
|
|
125
115
|
|
|
126
|
-
if (option.onSelect) {
|
|
127
|
-
callbacks.set(id, option.onSelect);
|
|
128
|
-
}
|
|
129
|
-
|
|
130
116
|
return {
|
|
131
117
|
type: 'action',
|
|
132
118
|
id,
|
package/src/Menu/types.ts
CHANGED
|
@@ -17,7 +17,11 @@ interface MenuOptionLabel {
|
|
|
17
17
|
icon?: string;
|
|
18
18
|
/** Tint applied to `icon` or `systemImage`. */
|
|
19
19
|
iconColor?: ColorValue;
|
|
20
|
-
/**
|
|
20
|
+
/**
|
|
21
|
+
* Retained for source compatibility. UIKit menu elements don't expose a
|
|
22
|
+
* public custom title-color API; use `destructive` for system red styling.
|
|
23
|
+
* @deprecated UIKit ignores custom menu title colors.
|
|
24
|
+
*/
|
|
21
25
|
titleColor?: ColorValue;
|
|
22
26
|
}
|
|
23
27
|
|
|
@@ -32,7 +36,6 @@ export interface MenuActionOption extends MenuOptionLabel {
|
|
|
32
36
|
hidden?: boolean;
|
|
33
37
|
/** Keep the menu visible after selection on iOS 16 and newer. */
|
|
34
38
|
keepOpen?: boolean;
|
|
35
|
-
onSelect?: () => void;
|
|
36
39
|
}
|
|
37
40
|
|
|
38
41
|
export interface MenuSubmenuOption extends MenuOptionLabel {
|
|
@@ -61,6 +64,17 @@ export interface MenuDividerOption {
|
|
|
61
64
|
export type MenuOption =
|
|
62
65
|
MenuActionOption | MenuSubmenuOption | MenuSectionOption | MenuDividerOption;
|
|
63
66
|
|
|
67
|
+
export interface MenuActionPressEventData {
|
|
68
|
+
/** The selected action's explicit id, or its generated menu-path id. */
|
|
69
|
+
id: string;
|
|
70
|
+
/** The selected action's displayed title. */
|
|
71
|
+
title: string;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export type MenuActionPressEvent = Readonly<{
|
|
75
|
+
nativeEvent: Readonly<MenuActionPressEventData>;
|
|
76
|
+
}>;
|
|
77
|
+
|
|
64
78
|
export interface MenuProps extends Omit<ViewProps, 'children'> {
|
|
65
79
|
/** The trigger element. */
|
|
66
80
|
children: ReactNode;
|
|
@@ -70,8 +84,8 @@ export interface MenuProps extends Omit<ViewProps, 'children'> {
|
|
|
70
84
|
options: readonly MenuOption[];
|
|
71
85
|
/** Prevents the trigger from opening the menu. */
|
|
72
86
|
disabled?: boolean;
|
|
73
|
-
/** Called
|
|
74
|
-
|
|
87
|
+
/** Called whenever an enabled action is selected. */
|
|
88
|
+
onActionPress?: (event: MenuActionPressEvent) => void;
|
|
75
89
|
}
|
|
76
90
|
|
|
77
91
|
export interface MenuComponent extends ForwardRefExoticComponent<
|
package/src/NativeTinyui.ts
CHANGED
|
@@ -7,6 +7,8 @@ export interface Spec extends TurboModule {
|
|
|
7
7
|
* based on the `react-native-tinyui.components` array in package.json.
|
|
8
8
|
*/
|
|
9
9
|
getEnabledComponents(): ReadonlyArray<string>;
|
|
10
|
+
configureTips(displayFrequency: string): Promise<void>;
|
|
11
|
+
invalidateTip(tipId: string, reason: string): Promise<void>;
|
|
10
12
|
}
|
|
11
13
|
|
|
12
14
|
export default TurboModuleRegistry.get<Spec>('Tinyui');
|
package/src/Popover/index.tsx
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { forwardRef, useCallback, useState, type ComponentRef } from 'react';
|
|
2
2
|
import type { ReactNode } from 'react';
|
|
3
|
-
import {
|
|
3
|
+
import { Pressable, StyleSheet, View } from 'react-native';
|
|
4
4
|
|
|
5
5
|
import { assertComponentEnabled } from '../utils';
|
|
6
6
|
import { PopoverClose } from './PopoverClose';
|
|
@@ -59,7 +59,11 @@ const PopoverRoot = forwardRef<ComponentRef<typeof View>, PopoverProps>(
|
|
|
59
59
|
}}
|
|
60
60
|
>
|
|
61
61
|
<Pressable onPress={() => setOpen(true)}>{children}</Pressable>
|
|
62
|
-
<View
|
|
62
|
+
<View
|
|
63
|
+
collapsable={false}
|
|
64
|
+
style={styles.content}
|
|
65
|
+
pointerEvents="box-none"
|
|
66
|
+
>
|
|
63
67
|
{renderedContent}
|
|
64
68
|
</View>
|
|
65
69
|
</NativePopoverView>
|
|
@@ -78,7 +82,8 @@ function renderContent(
|
|
|
78
82
|
const styles = StyleSheet.create({
|
|
79
83
|
content: {
|
|
80
84
|
position: 'absolute',
|
|
81
|
-
|
|
85
|
+
top: 0,
|
|
86
|
+
left: 0,
|
|
82
87
|
overflow: 'hidden',
|
|
83
88
|
},
|
|
84
89
|
});
|
package/src/Popover/types.ts
CHANGED
|
@@ -27,6 +27,8 @@ export interface PopoverProps extends Omit<ViewProps, 'children'> {
|
|
|
27
27
|
/**
|
|
28
28
|
* Content shown inside the popover. Pass a node, or a render function that
|
|
29
29
|
* receives `{ close }` to dismiss the popover from within the content.
|
|
30
|
+
* The content's layout determines the popover size, including live updates.
|
|
31
|
+
* Leave its background transparent to reveal the system popover material.
|
|
30
32
|
*/
|
|
31
33
|
content: PopoverContent;
|
|
32
34
|
/** Controlled presentation state. */
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import {
|
|
2
|
+
codegenNativeComponent,
|
|
3
|
+
type CodegenTypes,
|
|
4
|
+
type ViewProps,
|
|
5
|
+
} from 'react-native';
|
|
6
|
+
|
|
7
|
+
export interface NativeSFSymbolProps extends ViewProps {
|
|
8
|
+
configuration: CodegenTypes.UnsafeMixed;
|
|
9
|
+
effects: CodegenTypes.UnsafeMixed;
|
|
10
|
+
contentTransition: CodegenTypes.UnsafeMixed;
|
|
11
|
+
resizeMode?: CodegenTypes.WithDefault<string, 'center'>;
|
|
12
|
+
respectReduceMotion?: CodegenTypes.WithDefault<boolean, true>;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export default codegenNativeComponent<NativeSFSymbolProps>(
|
|
16
|
+
'TinyuiSFSymbolView',
|
|
17
|
+
{
|
|
18
|
+
excludedPlatforms: ['android'],
|
|
19
|
+
}
|
|
20
|
+
);
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { forwardRef, type ComponentRef } from 'react';
|
|
2
|
+
import { StyleSheet, useWindowDimensions, type View } from 'react-native';
|
|
3
|
+
|
|
4
|
+
import { assertComponentEnabled } from '../utils';
|
|
5
|
+
import NativeSFSymbolView from './SFSymbolNativeComponent';
|
|
6
|
+
import { serializeSFSymbol } from './options';
|
|
7
|
+
import type { SFSymbolProps } from './types';
|
|
8
|
+
|
|
9
|
+
export const SFSymbol = forwardRef<ComponentRef<typeof View>, SFSymbolProps>(
|
|
10
|
+
function SFSymbolRoot(
|
|
11
|
+
{
|
|
12
|
+
name,
|
|
13
|
+
source,
|
|
14
|
+
size,
|
|
15
|
+
weight,
|
|
16
|
+
scale,
|
|
17
|
+
textStyle,
|
|
18
|
+
fontFamily,
|
|
19
|
+
allowFontScaling,
|
|
20
|
+
maxFontSizeMultiplier,
|
|
21
|
+
renderingMode,
|
|
22
|
+
color,
|
|
23
|
+
paletteColors,
|
|
24
|
+
variableValue,
|
|
25
|
+
variableValueMode,
|
|
26
|
+
colorRenderingMode,
|
|
27
|
+
effect,
|
|
28
|
+
contentTransition,
|
|
29
|
+
respectReduceMotion = true,
|
|
30
|
+
resizeMode = 'center',
|
|
31
|
+
style,
|
|
32
|
+
accessible = false,
|
|
33
|
+
accessibilityRole = 'image',
|
|
34
|
+
...viewProps
|
|
35
|
+
},
|
|
36
|
+
ref
|
|
37
|
+
) {
|
|
38
|
+
assertComponentEnabled('SFSymbol');
|
|
39
|
+
const { fontScale } = useWindowDimensions();
|
|
40
|
+
const serialized = serializeSFSymbol(
|
|
41
|
+
{
|
|
42
|
+
name,
|
|
43
|
+
source,
|
|
44
|
+
size,
|
|
45
|
+
weight,
|
|
46
|
+
scale,
|
|
47
|
+
textStyle,
|
|
48
|
+
fontFamily,
|
|
49
|
+
allowFontScaling,
|
|
50
|
+
maxFontSizeMultiplier,
|
|
51
|
+
renderingMode,
|
|
52
|
+
color,
|
|
53
|
+
paletteColors,
|
|
54
|
+
variableValue,
|
|
55
|
+
variableValueMode,
|
|
56
|
+
colorRenderingMode,
|
|
57
|
+
effect,
|
|
58
|
+
contentTransition,
|
|
59
|
+
},
|
|
60
|
+
fontScale
|
|
61
|
+
);
|
|
62
|
+
|
|
63
|
+
return (
|
|
64
|
+
<NativeSFSymbolView
|
|
65
|
+
{...viewProps}
|
|
66
|
+
{...serialized}
|
|
67
|
+
ref={ref}
|
|
68
|
+
accessible={accessible}
|
|
69
|
+
accessibilityRole={accessibilityRole}
|
|
70
|
+
respectReduceMotion={respectReduceMotion}
|
|
71
|
+
resizeMode={resizeMode}
|
|
72
|
+
style={[styles.symbol, style]}
|
|
73
|
+
/>
|
|
74
|
+
);
|
|
75
|
+
}
|
|
76
|
+
);
|
|
77
|
+
|
|
78
|
+
const styles = StyleSheet.create({ symbol: { alignSelf: 'flex-start' } });
|
|
79
|
+
|
|
80
|
+
export type {
|
|
81
|
+
SFSymbolContentTransition,
|
|
82
|
+
SFSymbolEffect,
|
|
83
|
+
SFSymbolEffectOptions,
|
|
84
|
+
SFSymbolProps,
|
|
85
|
+
SFSymbolRenderingMode,
|
|
86
|
+
SFSymbolScale,
|
|
87
|
+
SFSymbolTextStyle,
|
|
88
|
+
SFSymbolWeight,
|
|
89
|
+
} from './types';
|