Skip to content

Commit 83b0ba4

Browse files
authored
Merge pull request #3 from jeongshin/feat/custom-component
Feat/custom component
2 parents 3ef2eea + 6896c71 commit 83b0ba4

File tree

8 files changed

+174
-118
lines changed

8 files changed

+174
-118
lines changed

.eslintignore

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,6 @@
33
**/*.d.ts
44

55
metro.config.js
6-
/dist
6+
dist/
7+
node_modules/
8+
lib/

.eslintrc.js

Lines changed: 0 additions & 28 deletions
This file was deleted.

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,4 @@ yarn-error.log
77
package-lock.json
88
yarn.lock
99
.idea/
10+
lib/

babel.config.js

Lines changed: 1 addition & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,3 @@
11
module.exports = {
2-
presets: ['module:metro-react-native-babel-preset', '@babel/preset-typescript'],
3-
sourceMaps: 'inline',
4-
plugins: [
5-
[
6-
'@babel/plugin-proposal-decorators',
7-
{
8-
legacy: true,
9-
},
10-
],
11-
[
12-
'@babel/plugin-transform-runtime',
13-
{
14-
helpers: true,
15-
regenerator: false,
16-
},
17-
],
18-
'@babel/proposal-object-rest-spread',
19-
],
2+
presets: ['module:@react-native/babel-preset'],
203
};

package.json

Lines changed: 80 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,29 @@
11
{
22
"name": "@mj-studio/react-native-spannable-string",
3-
"version": "1.1.3",
3+
"version": "1.1.4",
44
"description": "The simple Text builder for multiple styling in single Text component",
5-
"main": "dist/index.js",
6-
"types": "dist/index.d.ts",
5+
"main": "lib/commonjs/index",
6+
"module": "lib/module/index",
7+
"types": "lib/typescript/src/index.d.ts",
8+
"react-native": "src/index",
9+
"source": "src/index",
710
"files": [
8-
"dist/**/*"
11+
"src",
12+
"lib",
13+
"android",
14+
"ios",
15+
"cpp",
16+
"*.podspec",
17+
"!ios/build",
18+
"!android/build",
19+
"!android/gradle",
20+
"!android/gradlew",
21+
"!android/gradlew.bat",
22+
"!android/local.properties",
23+
"!**/__tests__",
24+
"!**/__fixtures__",
25+
"!**/__mocks__",
26+
"!**/.*"
927
],
1028
"private": false,
1129
"repository": {
@@ -20,47 +38,72 @@
2038
},
2139
"homepage": "https://github.com/mym0404/react-native-spannable-string",
2240
"scripts": {
23-
"prepare": "yarn c",
24-
"c": "yarn lint && yarn tsc",
25-
"lint": "eslint src --ext .ts,.tsx,.js,.jsx",
26-
"test": "jest"
41+
"prepare": "yarn t",
42+
"prepack": "yarn build",
43+
"typecheck": "tsc --noEmit",
44+
"lint": "eslint \"**/*.{js,ts,tsx}\"",
45+
"t": "yarn lint && yarn typecheck",
46+
"test": "jest",
47+
"build": "yarn t && bob build"
2748
},
2849
"peerDependencies": {
2950
"react": "*",
30-
"react-native": ">=0.50"
51+
"react-native": ">=0.60"
3152
},
3253
"dependencies": {},
3354
"devDependencies": {
34-
"@babel/cli": "^7.8.4",
35-
"@babel/core": "^7.8.7",
36-
"@babel/plugin-proposal-class-properties": "^7.8.3",
37-
"@babel/plugin-proposal-decorators": "7.8.3",
38-
"@babel/plugin-proposal-object-rest-spread": "^7.8.3",
39-
"@babel/plugin-transform-runtime": "7.8.3",
40-
"@babel/preset-typescript": "^7.8.3",
41-
"@babel/runtime": "^7.8.7",
42-
"@dooboo/eslint-config": "^0.5.6",
43-
"@types/react": "^16.9.23",
4455
"@types/react-native": "^0.61.21",
45-
"babel-preset-react-native": "^5.0.2",
46-
"eslint": "^7.14.0",
47-
"eslint-plugin-react-hooks": "^4.2.0",
48-
"import-sort-style-eslint": "^6.0.0",
49-
"jetifier": "^1.6.5",
50-
"metro-react-native-babel-preset": "^0.58.0",
51-
"prettier": "^2.2.1",
52-
"prettier-plugin-import-sort": "^0.0.6",
53-
"typescript": "4.1.2"
56+
"typescript": "5.1.5",
57+
"eslint": "^8.51.0",
58+
"eslint-config-prettier": "^9.0.0",
59+
"eslint-plugin-prettier": "^5.0.1",
60+
"prettier": "^3.0.3",
61+
"@react-native/eslint-config": "^0.73.1",
62+
"react": "18.2.0",
63+
"react-native": "0.73.6",
64+
"@types/react": "^18.2.44",
65+
"react-native-builder-bob": "^0.20.0"
5466
},
55-
"importSort": {
56-
".js, .jsx": {
57-
"style": "eslint",
58-
"options": {}
59-
},
60-
".ts, .tsx": {
61-
"parser": "typescript",
62-
"style": "eslint",
63-
"options": {}
67+
"eslintConfig": {
68+
"root": true,
69+
"extends": [
70+
"@react-native",
71+
"prettier"
72+
],
73+
"rules": {
74+
"prettier/prettier": [
75+
"error",
76+
{
77+
"quoteProps": "consistent",
78+
"singleQuote": true,
79+
"tabWidth": 2,
80+
"trailingComma": "es5",
81+
"useTabs": false
82+
}
83+
],
84+
"react-native/no-inline-styles": "off",
85+
"@typescript-eslint/no-shadow": "off"
6486
}
87+
},
88+
"prettier": {
89+
"quoteProps": "consistent",
90+
"singleQuote": true,
91+
"tabWidth": 2,
92+
"trailingComma": "es5",
93+
"useTabs": false
94+
},
95+
"react-native-builder-bob": {
96+
"source": "src",
97+
"output": "lib",
98+
"targets": [
99+
"commonjs",
100+
"module",
101+
[
102+
"typescript",
103+
{
104+
"project": "tsconfig.build.json"
105+
}
106+
]
107+
]
65108
}
66109
}

src/index.tsx

Lines changed: 66 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,35 @@
1-
import React, { ComponentType, ReactElement } from 'react';
2-
import { StyleProp, StyleSheet, Text, TextProps, TextStyle } from 'react-native';
3-
4-
type TextComponent = ComponentType<TextProps & any>;
5-
1+
import type { ComponentType, ReactElement } from 'react';
2+
import React from 'react';
3+
import type { StyleProp, TextProps, TextStyle } from 'react-native';
4+
import { StyleSheet, Text, View } from 'react-native';
5+
6+
type TextComponent = ComponentType<TextProps>;
7+
type Config = {
8+
additionalStyle?: StyleProp<TextStyle>;
9+
outerTextStyle?: StyleProp<TextStyle>;
10+
};
11+
type InnerConfig = {
12+
appendedStyle?: StyleProp<TextStyle>;
13+
outerStyle?: StyleProp<TextStyle>;
14+
};
615
export default class SpannableBuilder {
716
static getInstanceWithComponent(
817
baseComponent?: TextComponent,
9-
config?: { additionalStyle?: StyleProp<TextStyle>; outerTextStyle?: StyleProp<TextStyle> },
18+
config?: Config
1019
): SpannableBuilder {
11-
const BaseText = baseComponent || Text;
20+
const BaseText: TextComponent = baseComponent || Text;
1221

13-
const Wrapped = (props): ReactElement => {
22+
const Wrapped: TextComponent = (
23+
props: TextProps & InnerConfig
24+
): ReactElement => {
1425
const { style, children, appendedStyle, outerStyle } = props;
1526

16-
const flattenStyle = StyleSheet.flatten([config?.additionalStyle, style, outerStyle, appendedStyle]);
27+
const flattenStyle = StyleSheet.flatten([
28+
config?.additionalStyle,
29+
style,
30+
outerStyle,
31+
appendedStyle,
32+
]);
1733

1834
return (
1935
<BaseText style={flattenStyle} {...props}>
@@ -25,21 +41,30 @@ export default class SpannableBuilder {
2541
return new SpannableBuilder(Wrapped, config?.outerTextStyle);
2642
}
2743

28-
static getInstance(additionalStyle?: StyleProp<TextStyle>, outerTextStyle?: StyleProp<TextStyle>): SpannableBuilder {
44+
static getInstance(
45+
additionalStyle?: StyleProp<TextStyle>,
46+
outerTextStyle?: StyleProp<TextStyle>
47+
): SpannableBuilder {
2948
if (!additionalStyle) return new SpannableBuilder(Text);
3049

31-
return SpannableBuilder.getInstanceWithComponent(Text, { additionalStyle, outerTextStyle });
50+
return SpannableBuilder.getInstanceWithComponent(Text, {
51+
additionalStyle,
52+
outerTextStyle,
53+
});
3254
}
3355

34-
readonly #TextComponent: TextComponent;
56+
readonly #TextComponent: ComponentType<TextProps & InnerConfig>;
3557

3658
#order = '';
37-
readonly #textList: string[] = [];
59+
readonly #textList: (string | ReactElement)[] = [];
3860
readonly #customStyleList: StyleProp<TextStyle>[] = [];
3961

4062
readonly outerTextStyle?: StyleProp<TextStyle>;
4163

42-
constructor(textComponent: TextComponent, outerTextStyle?: StyleProp<TextStyle>) {
64+
constructor(
65+
textComponent: TextComponent,
66+
outerTextStyle?: StyleProp<TextStyle>
67+
) {
4368
this.#TextComponent = textComponent;
4469
this.outerTextStyle = outerTextStyle;
4570
}
@@ -93,6 +118,13 @@ export default class SpannableBuilder {
93118
return this;
94119
}
95120

121+
appendCustomComponent(component: ReactElement): this {
122+
this.#textList.push(component);
123+
this.#order += 'C';
124+
125+
return this;
126+
}
127+
96128
private appendWithDelimiter({
97129
appender,
98130
delimiter,
@@ -115,7 +147,11 @@ export default class SpannableBuilder {
115147
return this;
116148
}
117149

118-
appendCustomWithDelimiter(text: string, style: StyleProp<TextStyle>, delimiter = '$'): this {
150+
appendCustomWithDelimiter(
151+
text: string,
152+
style: StyleProp<TextStyle>,
153+
delimiter = '$'
154+
): this {
119155
return this.appendWithDelimiter({
120156
text,
121157
delimiter,
@@ -145,7 +181,11 @@ export default class SpannableBuilder {
145181
});
146182
}
147183

148-
appendColoredWithDelimiter(text: string, color: string, delimiter = '$'): this {
184+
appendColoredWithDelimiter(
185+
text: string,
186+
color: string,
187+
delimiter = '$'
188+
): this {
149189
return this.appendWithDelimiter({
150190
text,
151191
delimiter,
@@ -156,23 +196,30 @@ export default class SpannableBuilder {
156196
}
157197

158198
build(): ReactElement {
159-
const BaseText: TextComponent = this.#TextComponent;
199+
const BaseText = this.#TextComponent;
160200

161201
let idx = 0;
162202
let customStyleIdx = 0;
163203

164204
const result = (
165205
<BaseText outerStyle={this.outerTextStyle}>
166206
{[...this.#order].map((order, index) => {
207+
const key = `${order}${index}`;
208+
167209
switch (order) {
168210
case 'S':
169211
return (
170-
<BaseText key={order + index} appendedStyle={this.#customStyleList[customStyleIdx++]}>
212+
<BaseText
213+
key={key}
214+
appendedStyle={this.#customStyleList[customStyleIdx++]}
215+
>
171216
{this.#textList[idx++]}
172217
</BaseText>
173218
);
219+
case 'C':
220+
return <View key={key}>{this.#textList[idx++]}</View>;
174221
default:
175-
return <BaseText key={order + index}>{this.#textList[idx++]}</BaseText>;
222+
return <BaseText key={key}>{this.#textList[idx++]}</BaseText>;
176223
}
177224
})}
178225
</BaseText>

tsconfig.build.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"extends": "./tsconfig",
3+
"exclude": ["example"]
4+
}

0 commit comments

Comments
 (0)