@momo-kits/calculator-keyboard 0.150.2-beta.20 → 0.150.2-beta.20-sp.2
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 +45 -3
- package/android/src/main/java/com/calculatorkeyboard/CalculatorKeyboardPackage.kt +1 -1
- package/android/src/main/java/com/calculatorkeyboard/CustomKeyboardView.kt +43 -31
- package/android/src/main/java/com/calculatorkeyboard/RCTInputCalculator.kt +27 -34
- package/ios/CalculatorKeyboardView.h +30 -0
- package/ios/CalculatorKeyboardView.mm +231 -0
- package/ios/NativeInputCalculator.h +11 -0
- package/ios/NativeInputCalculator.mm +200 -0
- package/package.json +75 -59
- package/react-native-calculator-keyboard.podspec +5 -4
- package/src/NativeInputCalculatorNativeComponent.ts +55 -0
- package/src/index.tsx +25 -34
- package/ios/CalculatorKeyboardView.swift +0 -153
- package/ios/InputCalculator-Bridging-Header.h +0 -23
- package/ios/InputCalculator.m +0 -85
- package/ios/InputCalculator.swift +0 -158
- package/ios/extension.swift +0 -23
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
#import "NativeInputCalculator.h"
|
|
2
|
+
#import "CalculatorKeyboardView.h"
|
|
3
|
+
|
|
4
|
+
#import <React/RCTConversions.h>
|
|
5
|
+
#import <React/RCTFabricComponentsPlugins.h>
|
|
6
|
+
#import <react/renderer/components/CalculatorKeyboardSpecs/ComponentDescriptors.h>
|
|
7
|
+
#import <react/renderer/components/CalculatorKeyboardSpecs/EventEmitters.h>
|
|
8
|
+
#import <react/renderer/components/CalculatorKeyboardSpecs/Props.h>
|
|
9
|
+
#import <react/renderer/components/CalculatorKeyboardSpecs/RCTComponentViewHelpers.h>
|
|
10
|
+
|
|
11
|
+
using namespace facebook::react;
|
|
12
|
+
|
|
13
|
+
@interface NativeInputCalculator () <RCTNativeInputCalculatorViewProtocol>
|
|
14
|
+
@end
|
|
15
|
+
|
|
16
|
+
@implementation NativeInputCalculator {
|
|
17
|
+
UITextField *_textField;
|
|
18
|
+
CalculatorKeyboardView *_keyboardView;
|
|
19
|
+
NSString *_lastValue;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
- (instancetype)initWithFrame:(CGRect)frame
|
|
23
|
+
{
|
|
24
|
+
if (self = [super initWithFrame:frame]) {
|
|
25
|
+
static const auto defaultProps = std::make_shared<const NativeInputCalculatorProps>();
|
|
26
|
+
_props = defaultProps;
|
|
27
|
+
|
|
28
|
+
// Create text field
|
|
29
|
+
_textField = [[UITextField alloc] initWithFrame:self.bounds];
|
|
30
|
+
_textField.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
|
|
31
|
+
_textField.delegate = (id<UITextFieldDelegate>)self;
|
|
32
|
+
|
|
33
|
+
// Create keyboard view
|
|
34
|
+
CGFloat bottomInset = [self getBottomInset];
|
|
35
|
+
CGRect keyboardFrame = CGRectMake(0, 0, UIScreen.mainScreen.bounds.size.width, 240 + bottomInset);
|
|
36
|
+
_keyboardView = [[CalculatorKeyboardView alloc] initWithFrame:keyboardFrame];
|
|
37
|
+
_keyboardView.input = (id)self; // Bridge pattern
|
|
38
|
+
|
|
39
|
+
// Set custom keyboard
|
|
40
|
+
_textField.inputView = _keyboardView;
|
|
41
|
+
|
|
42
|
+
[self addSubview:_textField];
|
|
43
|
+
}
|
|
44
|
+
return self;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
- (CGFloat)getBottomInset
|
|
48
|
+
{
|
|
49
|
+
UIWindow *window = UIApplication.sharedApplication.windows.firstObject;
|
|
50
|
+
CGFloat bottom = window.safeAreaInsets.bottom > 0 ? 21 : 0;
|
|
51
|
+
return bottom;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
#pragma mark - RCTComponentViewProtocol
|
|
55
|
+
|
|
56
|
+
+ (ComponentDescriptorProvider)componentDescriptorProvider
|
|
57
|
+
{
|
|
58
|
+
return concreteComponentDescriptorProvider<NativeInputCalculatorComponentDescriptor>();
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
- (void)updateProps:(const Props::Shared &)props oldProps:(const Props::Shared &)oldProps
|
|
62
|
+
{
|
|
63
|
+
const auto &oldViewProps = *std::static_pointer_cast<const NativeInputCalculatorProps>(_props);
|
|
64
|
+
const auto &newViewProps = *std::static_pointer_cast<const NativeInputCalculatorProps>(props);
|
|
65
|
+
|
|
66
|
+
// Update value
|
|
67
|
+
if (oldViewProps.value != newViewProps.value) {
|
|
68
|
+
NSString *newValue = RCTNSStringFromString(newViewProps.value);
|
|
69
|
+
if (![_lastValue isEqualToString:newValue]) {
|
|
70
|
+
_textField.text = newValue;
|
|
71
|
+
_lastValue = newValue;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// Update mode
|
|
76
|
+
if (oldViewProps.mode != newViewProps.mode) {
|
|
77
|
+
_keyboardView.keyboardMode = RCTNSStringFromString(newViewProps.mode);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// Update customKeyText
|
|
81
|
+
if (oldViewProps.customKeyText != newViewProps.customKeyText) {
|
|
82
|
+
_keyboardView.customKeyText = RCTNSStringFromString(newViewProps.customKeyText);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// Update customKeyBackground
|
|
86
|
+
if (oldViewProps.customKeyBackground != newViewProps.customKeyBackground) {
|
|
87
|
+
_keyboardView.customKeyBackground = RCTNSStringFromString(newViewProps.customKeyBackground);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// Update customKeyTextColor
|
|
91
|
+
if (oldViewProps.customKeyTextColor != newViewProps.customKeyTextColor) {
|
|
92
|
+
_keyboardView.customKeyTextColor = RCTNSStringFromString(newViewProps.customKeyTextColor);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// Update customKeyState
|
|
96
|
+
if (oldViewProps.customKeyState != newViewProps.customKeyState) {
|
|
97
|
+
_keyboardView.customKeyState = RCTNSStringFromString(newViewProps.customKeyState);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
[super updateProps:props oldProps:oldProps];
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
- (void)handleCommand:(const NSString *)commandName args:(const NSArray *)args
|
|
104
|
+
{
|
|
105
|
+
RCTNativeInputCalculatorHandleCommand(self, commandName, args);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
#pragma mark - RCTNativeInputCalculatorViewProtocol
|
|
109
|
+
|
|
110
|
+
- (void)focus
|
|
111
|
+
{
|
|
112
|
+
[_textField becomeFirstResponder];
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
- (void)blur
|
|
116
|
+
{
|
|
117
|
+
[_textField resignFirstResponder];
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
#pragma mark - Keyboard callbacks (called by CalculatorKeyboardView)
|
|
121
|
+
|
|
122
|
+
- (void)keyDidPress:(NSString *)key
|
|
123
|
+
{
|
|
124
|
+
[_textField insertText:key];
|
|
125
|
+
[self notifyTextChange];
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
- (void)clearText
|
|
129
|
+
{
|
|
130
|
+
_textField.text = @"";
|
|
131
|
+
[self notifyTextChange];
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
- (void)onBackSpace
|
|
135
|
+
{
|
|
136
|
+
if (_textField.text.length > 0) {
|
|
137
|
+
_textField.text = [_textField.text substringToIndex:_textField.text.length - 1];
|
|
138
|
+
[self notifyTextChange];
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
- (void)calculateResult
|
|
143
|
+
{
|
|
144
|
+
NSString *text = [_textField.text stringByReplacingOccurrencesOfString:@"×" withString:@"*"];
|
|
145
|
+
text = [text stringByReplacingOccurrencesOfString:@"÷" withString:@"/"];
|
|
146
|
+
|
|
147
|
+
NSString *pattern = @"^\\s*(-?\\d+(\\.\\d+)?\\s*[-+*/]\\s*)*-?\\d+(\\.\\d+)?\\s*$";
|
|
148
|
+
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:pattern options:0 error:nil];
|
|
149
|
+
NSRange range = NSMakeRange(0, text.length);
|
|
150
|
+
|
|
151
|
+
if ([regex firstMatchInString:text options:0 range:range]) {
|
|
152
|
+
NSExpression *expression = [NSExpression expressionWithFormat:text];
|
|
153
|
+
id result = [expression expressionValueWithObject:nil context:nil];
|
|
154
|
+
if ([result isKindOfClass:[NSNumber class]]) {
|
|
155
|
+
_textField.text = [result stringValue];
|
|
156
|
+
[self notifyTextChange];
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
- (void)emitCustomKey
|
|
162
|
+
{
|
|
163
|
+
if (_eventEmitter) {
|
|
164
|
+
auto emitter = std::static_pointer_cast<const NativeInputCalculatorEventEmitter>(_eventEmitter);
|
|
165
|
+
NativeInputCalculatorEventEmitter::OnCustomKeyEvent event{};
|
|
166
|
+
emitter->onCustomKeyEvent(event);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
- (void)emitKeyPress:(NSString *)key
|
|
171
|
+
{
|
|
172
|
+
if (_eventEmitter) {
|
|
173
|
+
auto emitter = std::static_pointer_cast<const NativeInputCalculatorEventEmitter>(_eventEmitter);
|
|
174
|
+
NativeInputCalculatorEventEmitter::OnKeyPress event{
|
|
175
|
+
.key = std::string([key UTF8String])
|
|
176
|
+
};
|
|
177
|
+
emitter->onKeyPress(event);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
- (void)notifyTextChange
|
|
182
|
+
{
|
|
183
|
+
_lastValue = _textField.text;
|
|
184
|
+
|
|
185
|
+
if (_eventEmitter) {
|
|
186
|
+
auto emitter = std::static_pointer_cast<const NativeInputCalculatorEventEmitter>(_eventEmitter);
|
|
187
|
+
NativeInputCalculatorEventEmitter::OnChange event{
|
|
188
|
+
.text = std::string([_textField.text UTF8String])
|
|
189
|
+
};
|
|
190
|
+
emitter->onChange(event);
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
@end
|
|
195
|
+
|
|
196
|
+
Class<RCTNativeInputCalculatorViewProtocol> NativeInputCalculatorCls(void)
|
|
197
|
+
{
|
|
198
|
+
return NativeInputCalculator.class;
|
|
199
|
+
}
|
|
200
|
+
|
package/package.json
CHANGED
|
@@ -1,61 +1,77 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
2
|
+
"name": "@momo-kits/calculator-keyboard",
|
|
3
|
+
"version": "0.150.2-beta.20-sp.2",
|
|
4
|
+
"description": "react native calculator keyboard",
|
|
5
|
+
"main": "./src/index.tsx",
|
|
6
|
+
"files": [
|
|
7
|
+
"src",
|
|
8
|
+
"lib",
|
|
9
|
+
"android",
|
|
10
|
+
"ios",
|
|
11
|
+
"cpp",
|
|
12
|
+
"*.podspec",
|
|
13
|
+
"react-native.config.js",
|
|
14
|
+
"!ios/build",
|
|
15
|
+
"!android/build",
|
|
16
|
+
"!android/gradle",
|
|
17
|
+
"!android/gradlew",
|
|
18
|
+
"!android/gradlew.bat",
|
|
19
|
+
"!android/local.properties",
|
|
20
|
+
"!**/__tests__",
|
|
21
|
+
"!**/__fixtures__",
|
|
22
|
+
"!**/__mocks__",
|
|
23
|
+
"!**/.*"
|
|
24
|
+
],
|
|
25
|
+
"scripts": {
|
|
26
|
+
"test": "jest",
|
|
27
|
+
"typecheck": "tsc",
|
|
28
|
+
"lint": "eslint \"**/*.{js,ts,tsx}\"",
|
|
29
|
+
"clean": "del-cli android/build example/android/build example/android/app/build example/ios/build lib",
|
|
30
|
+
"build": "bob build",
|
|
31
|
+
"release": "release-it"
|
|
32
|
+
},
|
|
33
|
+
"keywords": [
|
|
34
|
+
"react-native",
|
|
35
|
+
"ios",
|
|
36
|
+
"android"
|
|
37
|
+
],
|
|
38
|
+
"repository": {
|
|
39
|
+
"type": "git",
|
|
40
|
+
"url": "git+https://github.com/wem2017/react-native-calculator-keyboard.git/react-native-calculator-keyboard.git"
|
|
41
|
+
},
|
|
42
|
+
"author": "Dũng (Wem) <huynh.developer@gmail.com> (https://github.com/wem2017/react-native-calculator-keyboard.git)",
|
|
43
|
+
"license": "MIT",
|
|
44
|
+
"bugs": {
|
|
45
|
+
"url": "https://github.com/wem2017/react-native-calculator-keyboard.git/react-native-calculator-keyboard/issues"
|
|
46
|
+
},
|
|
47
|
+
"homepage": "https://github.com/wem2017/react-native-calculator-keyboard.git/react-native-calculator-keyboard#readme",
|
|
48
|
+
"publishConfig": {
|
|
49
|
+
"registry": "https://registry.npmjs.org/"
|
|
50
|
+
},
|
|
51
|
+
"codegenConfig": {
|
|
52
|
+
"name": "CalculatorKeyboardSpecs",
|
|
53
|
+
"type": "components",
|
|
54
|
+
"jsSrcsDir": "src",
|
|
55
|
+
"android": {
|
|
56
|
+
"javaPackageName": "com.calculatorkeyboard"
|
|
32
57
|
},
|
|
33
|
-
"
|
|
34
|
-
|
|
35
|
-
"
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
"
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
"react-native": "*"
|
|
54
|
-
},
|
|
55
|
-
"peerDependencies": {
|
|
56
|
-
"react": "*",
|
|
57
|
-
"react-native": "*",
|
|
58
|
-
"@momo-kits/foundation": "latest"
|
|
59
|
-
},
|
|
60
|
-
"dependencies": {}
|
|
61
|
-
}
|
|
58
|
+
"ios": {
|
|
59
|
+
"componentProvider": {
|
|
60
|
+
"NativeInputCalculator": "NativeInputCalculator"
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
},
|
|
64
|
+
"devDependencies": {
|
|
65
|
+
"react": "*",
|
|
66
|
+
"react-native": "*"
|
|
67
|
+
},
|
|
68
|
+
"peerDependencies": {
|
|
69
|
+
"react": "*",
|
|
70
|
+
"react-native": "*",
|
|
71
|
+
"@momo-kits/foundation": "latest"
|
|
72
|
+
},
|
|
73
|
+
"engines": {
|
|
74
|
+
"node": ">=18.0.0"
|
|
75
|
+
},
|
|
76
|
+
"dependencies": {}
|
|
77
|
+
}
|
|
@@ -5,7 +5,7 @@ folly_compiler_flags = '-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1
|
|
|
5
5
|
|
|
6
6
|
Pod::Spec.new do |s|
|
|
7
7
|
s.name = "react-native-calculator-keyboard"
|
|
8
|
-
s.version = "
|
|
8
|
+
s.version = package["version"]
|
|
9
9
|
s.summary = package["description"]
|
|
10
10
|
s.homepage = package["homepage"]
|
|
11
11
|
s.license = package["license"]
|
|
@@ -14,9 +14,10 @@ Pod::Spec.new do |s|
|
|
|
14
14
|
s.platforms = { :ios => min_ios_version_supported }
|
|
15
15
|
s.source = { :git => "https://github.com/wem2017/react-native-calculator-keyboard.git/react-native-calculator-keyboard.git", :tag => "#{s.version}" }
|
|
16
16
|
|
|
17
|
-
s.source_files = "ios/**/*.{h,m,mm
|
|
18
|
-
s.
|
|
19
|
-
|
|
17
|
+
s.source_files = "ios/**/*.{h,m,mm}"
|
|
18
|
+
# s.public_header_files = "ios/CalculatorKeyboardView.h"
|
|
19
|
+
# s.private_header_files = "ios/NativeInputCalculator.h"
|
|
20
|
+
|
|
20
21
|
# Use install_modules_dependencies helper to install the dependencies if React Native version >=0.71.0.
|
|
21
22
|
# See https://github.com/facebook/react-native/blob/febf6b7f33fdb4904669f99d795eba4c0f95d7bf/scripts/cocoapods/new_architecture.rb#L79.
|
|
22
23
|
if respond_to?(:install_modules_dependencies, true)
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import type * as React from 'react';
|
|
2
|
+
import type { HostComponent, ViewProps } from 'react-native';
|
|
3
|
+
import {
|
|
4
|
+
CodegenTypes,
|
|
5
|
+
codegenNativeComponent,
|
|
6
|
+
codegenNativeCommands,
|
|
7
|
+
} from 'react-native';
|
|
8
|
+
|
|
9
|
+
export type CustomKeyBackground = 'primary' | 'default' | string;
|
|
10
|
+
|
|
11
|
+
export enum CustomKeyState {
|
|
12
|
+
Default = 'default',
|
|
13
|
+
Disable = 'disable',
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export enum Mode {
|
|
17
|
+
NumDefault = 'NumDefault',
|
|
18
|
+
NumWithCTA = 'NumWithCTA',
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export type OnKeyPressEvent = Readonly<{
|
|
22
|
+
key: string;
|
|
23
|
+
}>;
|
|
24
|
+
|
|
25
|
+
export type OnChangeEvent = Readonly<{
|
|
26
|
+
text: string;
|
|
27
|
+
}>;
|
|
28
|
+
|
|
29
|
+
export interface NativeInputCalculatorProps extends ViewProps {
|
|
30
|
+
value?: string;
|
|
31
|
+
mode?: string;
|
|
32
|
+
customKeyText?: string;
|
|
33
|
+
customKeyBackground?: string;
|
|
34
|
+
customKeyTextColor?: string;
|
|
35
|
+
customKeyState?: string;
|
|
36
|
+
onKeyPress?: CodegenTypes.DirectEventHandler<OnKeyPressEvent>;
|
|
37
|
+
onCustomKeyEvent?: CodegenTypes.DirectEventHandler<{}>;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export interface NativeInputCalculatorCommands {
|
|
41
|
+
focus(
|
|
42
|
+
viewRef: React.ElementRef<HostComponent<NativeInputCalculatorProps>>,
|
|
43
|
+
): void;
|
|
44
|
+
blur(
|
|
45
|
+
viewRef: React.ElementRef<HostComponent<NativeInputCalculatorProps>>,
|
|
46
|
+
): void;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export const Commands = codegenNativeCommands<NativeInputCalculatorCommands>({
|
|
50
|
+
supportedCommands: ['focus', 'blur'],
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
export default codegenNativeComponent<NativeInputCalculatorProps>(
|
|
54
|
+
'NativeInputCalculator',
|
|
55
|
+
);
|
package/src/index.tsx
CHANGED
|
@@ -1,23 +1,17 @@
|
|
|
1
|
-
import
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { useContext } from 'react';
|
|
2
3
|
import { ApplicationContext, Colors } from '@momo-kits/foundation';
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
type NativeSyntheticEvent,
|
|
7
|
-
processColor,
|
|
8
|
-
requireNativeComponent,
|
|
9
|
-
type TextInputProps,
|
|
10
|
-
UIManager,
|
|
11
|
-
} from 'react-native';
|
|
4
|
+
import { type NativeSyntheticEvent, type TextInputProps } from 'react-native';
|
|
5
|
+
import NativeInputCalculator from './NativeInputCalculatorNativeComponent';
|
|
6
|
+
import { Commands } from './NativeInputCalculatorNativeComponent';
|
|
12
7
|
|
|
13
|
-
const
|
|
14
|
-
const NativeInput = requireNativeComponent<any>(NAME);
|
|
8
|
+
const NativeInput = NativeInputCalculator;
|
|
15
9
|
|
|
16
10
|
type KeyPressEvent = { nativeEvent: { key: string } };
|
|
17
11
|
|
|
18
12
|
interface InputCalculatorProps extends TextInputProps {
|
|
19
13
|
text?: string | undefined;
|
|
20
|
-
|
|
14
|
+
mode?: Mode;
|
|
21
15
|
onKeyPress?: (e: KeyPressEvent) => void;
|
|
22
16
|
customKeyText?: string | undefined;
|
|
23
17
|
customKeyBackground?: CustomKeyBackground;
|
|
@@ -32,6 +26,11 @@ export enum CustomKeyState {
|
|
|
32
26
|
Disable = 'disable',
|
|
33
27
|
}
|
|
34
28
|
|
|
29
|
+
export enum Mode {
|
|
30
|
+
NumDefault = 'NumDefault',
|
|
31
|
+
NumWithCTA = 'NumWithCTA',
|
|
32
|
+
}
|
|
33
|
+
|
|
35
34
|
export type InputCalculatorRef = {
|
|
36
35
|
focus: () => void;
|
|
37
36
|
blur: () => void;
|
|
@@ -44,7 +43,7 @@ const InputCalculator = React.forwardRef<
|
|
|
44
43
|
(
|
|
45
44
|
{
|
|
46
45
|
customKeyBackground = 'default',
|
|
47
|
-
|
|
46
|
+
mode = Mode.NumDefault,
|
|
48
47
|
customKeyText,
|
|
49
48
|
onKeyPress,
|
|
50
49
|
customKeyState = CustomKeyState.Default,
|
|
@@ -66,32 +65,24 @@ const InputCalculator = React.forwardRef<
|
|
|
66
65
|
let keyBackground = Colors.black_06;
|
|
67
66
|
let textKeyColor = Colors.black_20;
|
|
68
67
|
|
|
69
|
-
if (
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
68
|
+
if (mode === Mode.NumWithCTA) {
|
|
69
|
+
if (customKeyBackground === 'primary') {
|
|
70
|
+
keyBackground = theme.colors.primary;
|
|
71
|
+
textKeyColor = Colors.black_01;
|
|
72
|
+
}
|
|
73
73
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
74
|
+
if (customKeyState === CustomKeyState.Disable) {
|
|
75
|
+
keyBackground = theme.colors.background.disable;
|
|
76
|
+
textKeyColor = Colors.black_01;
|
|
77
|
+
}
|
|
77
78
|
}
|
|
78
79
|
|
|
79
80
|
React.useImperativeHandle(ref, () => ({
|
|
80
81
|
focus() {
|
|
81
|
-
|
|
82
|
-
if (!node) return;
|
|
83
|
-
const config = UIManager.getViewManagerConfig(NAME);
|
|
84
|
-
if (config?.Commands?.focus != null) {
|
|
85
|
-
UIManager.dispatchViewManagerCommand(node, config.Commands.focus, []);
|
|
86
|
-
}
|
|
82
|
+
if (nativeRef.current) Commands.focus(nativeRef.current);
|
|
87
83
|
},
|
|
88
84
|
blur() {
|
|
89
|
-
|
|
90
|
-
if (!node) return;
|
|
91
|
-
const config = UIManager.getViewManagerConfig(NAME);
|
|
92
|
-
if (config?.Commands?.blur != null) {
|
|
93
|
-
UIManager.dispatchViewManagerCommand(node, config.Commands.blur, []);
|
|
94
|
-
}
|
|
85
|
+
if (nativeRef.current) Commands.blur(nativeRef.current);
|
|
95
86
|
},
|
|
96
87
|
}));
|
|
97
88
|
|
|
@@ -102,7 +93,7 @@ const InputCalculator = React.forwardRef<
|
|
|
102
93
|
onChange={_onChange}
|
|
103
94
|
onKeyPress={onKeyPress}
|
|
104
95
|
value={text}
|
|
105
|
-
|
|
96
|
+
mode={mode}
|
|
106
97
|
customKeyText={customKeyText}
|
|
107
98
|
customKeyBackground={keyBackground}
|
|
108
99
|
customKeyTextColor={textKeyColor}
|
|
@@ -1,153 +0,0 @@
|
|
|
1
|
-
import UIKit
|
|
2
|
-
import Foundation
|
|
3
|
-
|
|
4
|
-
import UIKit
|
|
5
|
-
import Foundation
|
|
6
|
-
|
|
7
|
-
class CalculatorKeyboardView: UIView {
|
|
8
|
-
weak var input: InputCalculator?
|
|
9
|
-
|
|
10
|
-
private let keys: [[String]] = [
|
|
11
|
-
["1", "2", "3", "÷", "back"],
|
|
12
|
-
["4", "5", "6", "×", "="],
|
|
13
|
-
["7", "8", "9", "-", "Xong"],
|
|
14
|
-
["000", "0", "+"],
|
|
15
|
-
]
|
|
16
|
-
private let SEPARATOR_WIDTH: CGFloat = 4
|
|
17
|
-
private let specialKeys: Set<String> = ["=", "-", "×", "÷", "back", "+"]
|
|
18
|
-
|
|
19
|
-
var customKeyText: String? { didSet { updateCustomKeyTitle() } }
|
|
20
|
-
var customKeyBackground: String? { didSet { updateCustomKeyBackground() } }
|
|
21
|
-
var customKeyTextColor: String? { didSet { updateCustomKeyBackground() } }
|
|
22
|
-
var customKeyState: String? { didSet { updateCustomKeyBackground() } }
|
|
23
|
-
private weak var customKeyButton: UIButton?
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
override init(frame: CGRect) {
|
|
27
|
-
super.init(frame: frame)
|
|
28
|
-
setup()
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
required init?(coder aDecoder: NSCoder) {
|
|
32
|
-
fatalError("init(coder:) has not been implemented")
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
public func setKeyboardColor(_ color: UIColor) {
|
|
36
|
-
self.setup(color)
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
private func setup(_ color: UIColor = UIColor(hex: "#d8d8d8")) {
|
|
40
|
-
self.subviews.forEach { $0.removeFromSuperview() }
|
|
41
|
-
|
|
42
|
-
backgroundColor = UIColor(hex: "#f2f2f6")
|
|
43
|
-
let buttonWidth = (UIScreen.main.bounds.width - SEPARATOR_WIDTH * 2 - 4 * SEPARATOR_WIDTH) / 5
|
|
44
|
-
let buttonHeight: CGFloat = (240 - SEPARATOR_WIDTH * 2 - 3 * SEPARATOR_WIDTH) / 4
|
|
45
|
-
|
|
46
|
-
// Create a wrapper view
|
|
47
|
-
let contentView = UIView()
|
|
48
|
-
contentView.translatesAutoresizingMaskIntoConstraints = false
|
|
49
|
-
addSubview(contentView)
|
|
50
|
-
|
|
51
|
-
// Set contentView constraints
|
|
52
|
-
NSLayoutConstraint.activate([
|
|
53
|
-
contentView.leadingAnchor.constraint(equalTo: leadingAnchor, constant: SEPARATOR_WIDTH),
|
|
54
|
-
contentView.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -SEPARATOR_WIDTH),
|
|
55
|
-
contentView.topAnchor.constraint(equalTo: topAnchor, constant: SEPARATOR_WIDTH),
|
|
56
|
-
contentView.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -SEPARATOR_WIDTH)
|
|
57
|
-
])
|
|
58
|
-
|
|
59
|
-
// Add buttons to the wrapper view
|
|
60
|
-
var yOffset: CGFloat = 0
|
|
61
|
-
for (rowIndex, row) in keys.enumerated() {
|
|
62
|
-
var xOffset: CGFloat = 0
|
|
63
|
-
for (colIndex, key) in row.enumerated() {
|
|
64
|
-
let isCustomKey = colIndex == 4 && rowIndex == 2
|
|
65
|
-
let button = UIButton(type: .system)
|
|
66
|
-
button.backgroundColor = UIColor.white
|
|
67
|
-
button.layer.cornerRadius = 8
|
|
68
|
-
let title = isCustomKey ? (customKeyText ?? key) : key
|
|
69
|
-
button.setTitle(title, for: .normal)
|
|
70
|
-
button.setTitleColor(.black, for: .normal)
|
|
71
|
-
button.titleLabel?.font = UIFont.systemFont(ofSize: isCustomKey ? 18 : 24, weight: .medium)
|
|
72
|
-
button.nativeID = key
|
|
73
|
-
button.tag = isCustomKey ? 1 : 0
|
|
74
|
-
|
|
75
|
-
var buttonFrame = CGRect(x: xOffset, y: yOffset, width: buttonWidth, height: buttonHeight)
|
|
76
|
-
if isCustomKey {
|
|
77
|
-
buttonFrame.size.height = buttonHeight * 2 + SEPARATOR_WIDTH
|
|
78
|
-
}
|
|
79
|
-
if key == "000" {
|
|
80
|
-
buttonFrame.size.width = buttonWidth * 2 + SEPARATOR_WIDTH
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
button.frame = buttonFrame
|
|
84
|
-
|
|
85
|
-
if key == "back" {
|
|
86
|
-
button.setTitle("", for: .normal)
|
|
87
|
-
let image = UIImage(systemName: "delete.backward", withConfiguration: UIImage.SymbolConfiguration(weight: .bold))
|
|
88
|
-
button.setImage(image, for: .normal)
|
|
89
|
-
button.tintColor = .black
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
if specialKeys.contains(key) {
|
|
93
|
-
button.setTitleColor(.black, for: .normal)
|
|
94
|
-
button.backgroundColor = color
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
if isCustomKey {
|
|
98
|
-
self.customKeyButton = button
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
button.addTarget(self, action: #selector(keyPressed(_:)), for: .touchUpInside)
|
|
102
|
-
contentView.addSubview(button)
|
|
103
|
-
|
|
104
|
-
// Adjust xOffset for the next button in the row
|
|
105
|
-
xOffset += buttonFrame.width + SEPARATOR_WIDTH
|
|
106
|
-
}
|
|
107
|
-
// Adjust yOffset for the next row
|
|
108
|
-
yOffset += buttonHeight + SEPARATOR_WIDTH
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
private func updateCustomKeyTitle() {
|
|
113
|
-
guard let btn = customKeyButton, let title = customKeyText else { return }
|
|
114
|
-
btn.setTitle(title, for: .normal)
|
|
115
|
-
btn.setImage(nil, for: .normal)
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
private func updateCustomKeyBackground() {
|
|
119
|
-
guard let btn = customKeyButton,
|
|
120
|
-
let background = customKeyBackground,
|
|
121
|
-
let textColor = customKeyTextColor,
|
|
122
|
-
let state = customKeyState else { return }
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
btn.isEnabled = state != "disable"
|
|
127
|
-
btn.backgroundColor = UIColor(hex: background)
|
|
128
|
-
btn.setTitleColor(UIColor(hex: textColor), for: .normal)
|
|
129
|
-
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
@objc private func keyPressed(_ sender: UIButton) {
|
|
134
|
-
guard let key = sender.nativeID else { return }
|
|
135
|
-
let isCustomKey = sender.tag == 1
|
|
136
|
-
if (isCustomKey) {
|
|
137
|
-
input?.emitCustomKey()
|
|
138
|
-
return
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
input?.emitKeyPress(key)
|
|
142
|
-
switch key {
|
|
143
|
-
case "back":
|
|
144
|
-
input?.onBackSpace()
|
|
145
|
-
case "=":
|
|
146
|
-
input?.calculateResult()
|
|
147
|
-
case "+", "-", "÷", "×":
|
|
148
|
-
input?.keyDidPress(" \(key) ")
|
|
149
|
-
default:
|
|
150
|
-
input?.keyDidPress(key)
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
}
|