@studiokico/react-native-stroke-text 0.1.0 → 0.1.1

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.
@@ -57,7 +57,9 @@ class StrokeTextView(context: Context) : View(context) {
57
57
  private var textLayout: StaticLayout? = null // 여기가 핵심: 텍스트 레이아웃 엔진
58
58
 
59
59
  private fun createLayout(width: Int): StaticLayout? {
60
- if (text.isEmpty() || width <= 0) return null
60
+ if (text.isEmpty()) return null
61
+
62
+ val validWidth = if (width > 0) width else resources.displayMetrics.widthPixels
61
63
 
62
64
  val scaledFontSize = getScaledSize(fontSize)
63
65
  textPaint.textSize = scaledFontSize
@@ -69,7 +71,7 @@ class StrokeTextView(context: Context) : View(context) {
69
71
  else -> Layout.Alignment.ALIGN_NORMAL
70
72
  }
71
73
 
72
- val builder = StaticLayout.Builder.obtain(text, 0, text.length, textPaint, width)
74
+ val builder = StaticLayout.Builder.obtain(text, 0, text.length, textPaint, validWidth)
73
75
  .setAlignment(alignment)
74
76
  .setLineSpacing(0f, 1f)
75
77
  .setIncludePad(true)
@@ -87,13 +89,12 @@ class StrokeTextView(context: Context) : View(context) {
87
89
  override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
88
90
  val widthMode = MeasureSpec.getMode(widthMeasureSpec)
89
91
  val widthSize = MeasureSpec.getSize(widthMeasureSpec)
90
-
91
92
  val availableWidth = if (customWidth > 0) {
92
93
  getScaledSize(customWidth).toInt()
93
- } else if (widthMode != MeasureSpec.UNSPECIFIED) {
94
+ } else if (widthSize > 0) {
94
95
  widthSize
95
96
  } else {
96
- resources.displayMetrics.widthPixels // fallback
97
+ resources.displayMetrics.widthPixels
97
98
  }
98
99
 
99
100
  val scaledStrokeWidth = getScaledSize(strokeWidth)
@@ -120,7 +121,7 @@ class StrokeTextView(context: Context) : View(context) {
120
121
  }
121
122
  finalWidth = (ceil(maxLineWidth) + paddingLeft + paddingRight + (scaledStrokeWidth * 2)).toInt()
122
123
 
123
- if (widthMode == MeasureSpec.AT_MOST) {
124
+ if (widthMode == MeasureSpec.AT_MOST && widthSize > 0) {
124
125
  finalWidth = minOf(finalWidth, widthSize)
125
126
  }
126
127
  }
@@ -8,9 +8,6 @@
8
8
  #import <React/RCTFabricComponentsPlugins.h>
9
9
  #import <React/RCTConversions.h>
10
10
 
11
- // 2. Swift 클래스 import (프로젝트 설정에 따라 이름이 다를 수 있음)
12
- // 라이브러리 개발 중이라면 보통 "라이브러리이름-Swift.h" 입니다.
13
- // 예: react-native-stroke-text -> react_native_stroke_text-Swift.h
14
11
  #if __has_include("StrokeText-Swift.h")
15
12
  #import "StrokeText-Swift.h"
16
13
  #else
@@ -31,6 +31,21 @@ public class StrokeTextView: UILabel {
31
31
  self.numberOfLines = 0
32
32
  self.clipsToBounds = false
33
33
  self.backgroundColor = .clear
34
+
35
+ self.setContentCompressionResistancePriority(.required, for: .horizontal)
36
+ self.setContentCompressionResistancePriority(.required, for: .vertical)
37
+ }
38
+
39
+ public override func layoutSubviews() {
40
+ super.layoutSubviews()
41
+
42
+ if customWidth > 0 {
43
+ self.preferredMaxLayoutWidth = customWidth
44
+ } else {
45
+ if self.bounds.width > 0 {
46
+ self.preferredMaxLayoutWidth = self.bounds.width
47
+ }
48
+ }
34
49
  }
35
50
 
36
51
  public override func drawText(in rect: CGRect) {
@@ -40,18 +55,23 @@ public class StrokeTextView: UILabel {
40
55
  let context = UIGraphicsGetCurrentContext()
41
56
  context?.saveGState()
42
57
 
58
+ let height = self.textRect(forBounds: rect, limitedToNumberOfLines: self.numberOfLines).height
59
+ let topAlignedRect = CGRect(x: rect.origin.x, y: rect.origin.y, width: rect.width, height: height)
60
+
43
61
  if strokeWidth > 0 {
44
62
  context?.setLineWidth(strokeWidth)
45
63
  context?.setLineJoin(.round)
46
64
  context?.setTextDrawingMode(.stroke)
47
65
  self.textColor = strokeColor
48
- super.drawText(in: rect)
66
+
67
+ super.drawText(in: topAlignedRect)
49
68
  }
50
69
 
51
70
  context?.setTextDrawingMode(.fill)
52
71
  self.textColor = originalTextColor
53
72
  self.shadowOffset = CGSize.zero
54
- super.drawText(in: rect)
73
+
74
+ super.drawText(in: topAlignedRect)
55
75
 
56
76
  self.shadowOffset = shadowOffset
57
77
  context?.restoreGState()
@@ -59,7 +79,11 @@ public class StrokeTextView: UILabel {
59
79
 
60
80
  public override var intrinsicContentSize: CGSize {
61
81
  let size = super.intrinsicContentSize
62
- let extra = strokeWidth
63
- return CGSize(width: size.width + extra, height: size.height + extra)
82
+ let extra = strokeWidth * 2
83
+
84
+ let newWidth = size.width + extra
85
+ let newHeight = size.height + extra
86
+
87
+ return CGSize(width: newWidth, height: newHeight)
64
88
  }
65
89
  }
@@ -1,5 +1,72 @@
1
1
  "use strict";
2
2
 
3
- export { default as StrokeText } from './StrokeTextViewNativeComponent';
4
- export * from './StrokeTextViewNativeComponent';
3
+ import React from 'react';
4
+ import { StyleSheet, Text, View } from 'react-native';
5
+ import StrokeTextViewNativeComponent from './StrokeTextViewNativeComponent';
6
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
7
+ export const StrokeText = props => {
8
+ const {
9
+ style,
10
+ text,
11
+ fontSize = 14,
12
+ color,
13
+ strokeColor,
14
+ strokeWidth = 0,
15
+ fontFamily,
16
+ align = 'left',
17
+ numberOfLines,
18
+ ellipsis,
19
+ width,
20
+ ...rest
21
+ } = props;
22
+ const ghostTextStyle = {
23
+ fontSize: fontSize,
24
+ fontFamily: fontFamily,
25
+ textAlign: align || undefined,
26
+ width: width ? Number(width) : undefined,
27
+ margin: strokeWidth
28
+ };
29
+ return /*#__PURE__*/_jsxs(View, {
30
+ style: [styles.container, style],
31
+ children: [/*#__PURE__*/_jsx(Text, {
32
+ style: [ghostTextStyle, styles.ghostText],
33
+ numberOfLines: numberOfLines,
34
+ ellipsizeMode: ellipsis ? 'tail' : undefined,
35
+ children: text
36
+ }), /*#__PURE__*/_jsx(StrokeTextViewNativeComponent, {
37
+ style: styles.fill,
38
+ text: text,
39
+ fontSize: fontSize,
40
+ color: color,
41
+ strokeColor: strokeColor,
42
+ strokeWidth: strokeWidth,
43
+ fontFamily: fontFamily,
44
+ align: align,
45
+ numberOfLines: numberOfLines,
46
+ ellipsis: ellipsis,
47
+ width: width,
48
+ ...rest
49
+ })]
50
+ });
51
+ };
52
+ const styles = StyleSheet.create({
53
+ container: {
54
+ alignItems: 'center',
55
+ justifyContent: 'center'
56
+ },
57
+ ghostText: {
58
+ opacity: 0,
59
+ zIndex: -1,
60
+ includeFontPadding: false,
61
+ textAlignVertical: 'center'
62
+ },
63
+ fill: {
64
+ position: 'absolute',
65
+ left: 0,
66
+ right: 0,
67
+ top: 0,
68
+ bottom: 0
69
+ }
70
+ });
71
+ export default StrokeText;
5
72
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"names":["default","StrokeText"],"sourceRoot":"../../src","sources":["index.tsx"],"mappings":";;AAAA,SAASA,OAAO,IAAIC,UAAU,QAAQ,iCAAiC;AACvE,cAAc,iCAAiC","ignoreList":[]}
1
+ {"version":3,"names":["React","StyleSheet","Text","View","StrokeTextViewNativeComponent","jsx","_jsx","jsxs","_jsxs","StrokeText","props","style","text","fontSize","color","strokeColor","strokeWidth","fontFamily","align","numberOfLines","ellipsis","width","rest","ghostTextStyle","textAlign","undefined","Number","margin","styles","container","children","ghostText","ellipsizeMode","fill","create","alignItems","justifyContent","opacity","zIndex","includeFontPadding","textAlignVertical","position","left","right","top","bottom"],"sourceRoot":"../../src","sources":["index.tsx"],"mappings":";;AAAA,OAAOA,KAAK,MAAM,OAAO;AACzB,SACEC,UAAU,EACVC,IAAI,EACJC,IAAI,QAGC,cAAc;AACrB,OAAOC,6BAA6B,MAE7B,iCAAiC;AAAC,SAAAC,GAAA,IAAAC,IAAA,EAAAC,IAAA,IAAAC,KAAA;AAEzC,OAAO,MAAMC,UAAU,GAAIC,KAAkB,IAAwB;EACnE,MAAM;IACJC,KAAK;IACLC,IAAI;IACJC,QAAQ,GAAG,EAAE;IACbC,KAAK;IACLC,WAAW;IACXC,WAAW,GAAG,CAAC;IACfC,UAAU;IACVC,KAAK,GAAG,MAAM;IACdC,aAAa;IACbC,QAAQ;IACRC,KAAK;IACL,GAAGC;EACL,CAAC,GAAGZ,KAAK;EAET,MAAMa,cAAoC,GAAG;IAC3CV,QAAQ,EAAEA,QAAQ;IAClBI,UAAU,EAAEA,UAAU;IACtBO,SAAS,EAAEN,KAAK,IAAIO,SAAS;IAC7BJ,KAAK,EAAEA,KAAK,GAAGK,MAAM,CAACL,KAAK,CAAC,GAAGI,SAAS;IACxCE,MAAM,EAAEX;EACV,CAAC;EAED,oBACER,KAAA,CAACL,IAAI;IAACQ,KAAK,EAAE,CAACiB,MAAM,CAACC,SAAS,EAAElB,KAAK,CAAE;IAAAmB,QAAA,gBACrCxB,IAAA,CAACJ,IAAI;MACHS,KAAK,EAAE,CAACY,cAAc,EAAEK,MAAM,CAACG,SAAS,CAAE;MAC1CZ,aAAa,EAAEA,aAAc;MAC7Ba,aAAa,EAAEZ,QAAQ,GAAG,MAAM,GAAGK,SAAU;MAAAK,QAAA,EAE5ClB;IAAI,CACD,CAAC,eAEPN,IAAA,CAACF,6BAA6B;MAC5BO,KAAK,EAAEiB,MAAM,CAACK,IAAK;MACnBrB,IAAI,EAAEA,IAAK;MACXC,QAAQ,EAAEA,QAAS;MACnBC,KAAK,EAAEA,KAAM;MACbC,WAAW,EAAEA,WAAY;MACzBC,WAAW,EAAEA,WAAY;MACzBC,UAAU,EAAEA,UAAW;MACvBC,KAAK,EAAEA,KAAM;MACbC,aAAa,EAAEA,aAAc;MAC7BC,QAAQ,EAAEA,QAAS;MACnBC,KAAK,EAAEA,KAAM;MAAA,GACTC;IAAI,CACT,CAAC;EAAA,CACE,CAAC;AAEX,CAAC;AAED,MAAMM,MAAM,GAAG3B,UAAU,CAACiC,MAAM,CAAC;EAC/BL,SAAS,EAAE;IACTM,UAAU,EAAE,QAAQ;IACpBC,cAAc,EAAE;EAClB,CAAC;EACDL,SAAS,EAAE;IACTM,OAAO,EAAE,CAAC;IACVC,MAAM,EAAE,CAAC,CAAC;IACVC,kBAAkB,EAAE,KAAK;IACzBC,iBAAiB,EAAE;EACrB,CAAC;EACDP,IAAI,EAAE;IACJQ,QAAQ,EAAE,UAAU;IACpBC,IAAI,EAAE,CAAC;IACPC,KAAK,EAAE,CAAC;IACRC,GAAG,EAAE,CAAC;IACNC,MAAM,EAAE;EACV;AACF,CAAC,CAAC;AAGF,eAAepC,UAAU","ignoreList":[]}
@@ -1,3 +1,6 @@
1
- export { default as StrokeText } from './StrokeTextViewNativeComponent';
2
- export * from './StrokeTextViewNativeComponent';
1
+ import React from 'react';
2
+ import { type NativeProps } from './StrokeTextViewNativeComponent';
3
+ export declare const StrokeText: (props: NativeProps) => React.JSX.Element;
4
+ export type { NativeProps };
5
+ export default StrokeText;
3
6
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,MAAM,iCAAiC,CAAC;AACxE,cAAc,iCAAiC,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAQ1B,OAAsC,EACpC,KAAK,WAAW,EACjB,MAAM,iCAAiC,CAAC;AAEzC,eAAO,MAAM,UAAU,GAAI,OAAO,WAAW,KAAG,KAAK,CAAC,GAAG,CAAC,OAkDzD,CAAC;AAsBF,YAAY,EAAE,WAAW,EAAE,CAAC;AAC5B,eAAe,UAAU,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@studiokico/react-native-stroke-text",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "React Native Stroke Text (New Arch Only)",
5
5
  "main": "./lib/module/index.js",
6
6
  "types": "./lib/typescript/src/index.d.ts",
package/src/index.tsx CHANGED
@@ -1,2 +1,86 @@
1
- export { default as StrokeText } from './StrokeTextViewNativeComponent';
2
- export * from './StrokeTextViewNativeComponent';
1
+ import React from 'react';
2
+ import {
3
+ StyleSheet,
4
+ Text,
5
+ View,
6
+ type TextStyle,
7
+ type StyleProp,
8
+ } from 'react-native';
9
+ import StrokeTextViewNativeComponent, {
10
+ type NativeProps,
11
+ } from './StrokeTextViewNativeComponent';
12
+
13
+ export const StrokeText = (props: NativeProps): React.JSX.Element => {
14
+ const {
15
+ style,
16
+ text,
17
+ fontSize = 14,
18
+ color,
19
+ strokeColor,
20
+ strokeWidth = 0,
21
+ fontFamily,
22
+ align = 'left',
23
+ numberOfLines,
24
+ ellipsis,
25
+ width,
26
+ ...rest
27
+ } = props;
28
+
29
+ const ghostTextStyle: StyleProp<TextStyle> = {
30
+ fontSize: fontSize,
31
+ fontFamily: fontFamily,
32
+ textAlign: align || undefined,
33
+ width: width ? Number(width) : undefined,
34
+ margin: strokeWidth,
35
+ };
36
+
37
+ return (
38
+ <View style={[styles.container, style]}>
39
+ <Text
40
+ style={[ghostTextStyle, styles.ghostText]}
41
+ numberOfLines={numberOfLines}
42
+ ellipsizeMode={ellipsis ? 'tail' : undefined}
43
+ >
44
+ {text}
45
+ </Text>
46
+
47
+ <StrokeTextViewNativeComponent
48
+ style={styles.fill}
49
+ text={text}
50
+ fontSize={fontSize}
51
+ color={color}
52
+ strokeColor={strokeColor}
53
+ strokeWidth={strokeWidth}
54
+ fontFamily={fontFamily}
55
+ align={align}
56
+ numberOfLines={numberOfLines}
57
+ ellipsis={ellipsis}
58
+ width={width}
59
+ {...rest}
60
+ />
61
+ </View>
62
+ );
63
+ };
64
+
65
+ const styles = StyleSheet.create({
66
+ container: {
67
+ alignItems: 'center',
68
+ justifyContent: 'center',
69
+ },
70
+ ghostText: {
71
+ opacity: 0,
72
+ zIndex: -1,
73
+ includeFontPadding: false,
74
+ textAlignVertical: 'center',
75
+ },
76
+ fill: {
77
+ position: 'absolute',
78
+ left: 0,
79
+ right: 0,
80
+ top: 0,
81
+ bottom: 0,
82
+ },
83
+ });
84
+
85
+ export type { NativeProps };
86
+ export default StrokeText;