├── .npmignore
├── docs
├── ellipsis.jpeg
└── example.jpeg
├── android
├── src
│ └── main
│ │ ├── AndroidManifestNew.xml
│ │ ├── AndroidManifest.xml
│ │ └── java
│ │ └── com
│ │ └── stroketext
│ │ ├── StrokeTextPackage.java
│ │ ├── FontUtil.java
│ │ ├── StrokeTextViewManager.java
│ │ └── StrokeTextView.java
├── gradle.properties
└── build.gradle
├── .prettierrc.js
├── ios
├── StrokeText-Bridging-Header.h
├── StrokeTextViewManager.swift
├── StrokeTextViewManager.m
├── StrokedTextLabel.swift
└── StrokeTextView.swift
├── .github
└── workflows
│ └── npm-publish.yml
├── src
└── index.tsx
├── package.json
├── .gitignore
├── LICENSE
├── tsconfig.json
├── react-native-stroke-text.podspec
├── README.md
└── yarn.lock
/.npmignore:
--------------------------------------------------------------------------------
1 | /docs
2 |
--------------------------------------------------------------------------------
/docs/ellipsis.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/charmy/react-native-stroke-text/HEAD/docs/ellipsis.jpeg
--------------------------------------------------------------------------------
/docs/example.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/charmy/react-native-stroke-text/HEAD/docs/example.jpeg
--------------------------------------------------------------------------------
/android/src/main/AndroidManifestNew.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/android/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
--------------------------------------------------------------------------------
/.prettierrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | printWidth: 120,
3 | tabWidth: 2,
4 | useTabs: false,
5 | semi: true,
6 | singleQuote: false,
7 | trailingComma: "all",
8 | };
9 |
--------------------------------------------------------------------------------
/android/gradle.properties:
--------------------------------------------------------------------------------
1 | StrokeText_kotlinVersion=1.7.0
2 | StrokeText_minSdkVersion=21
3 | StrokeText_targetSdkVersion=31
4 | StrokeText_compileSdkVersion=31
5 | StrokeText_ndkversion=21.4.7075529
6 |
--------------------------------------------------------------------------------
/ios/StrokeText-Bridging-Header.h:
--------------------------------------------------------------------------------
1 | #import
2 | #import
3 | #import
4 | #import
5 | #import
6 | #import
7 |
--------------------------------------------------------------------------------
/ios/StrokeTextViewManager.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 | import UIKit
3 |
4 | @objc(StrokeTextViewManager)
5 | class StrokeTextViewManager: RCTViewManager {
6 |
7 | override func view() -> UIView! {
8 | let newView = StrokeTextView(bridge: self.bridge)
9 | return newView
10 | }
11 |
12 | @objc override static func requiresMainQueueSetup() -> Bool {
13 | return false
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/ios/StrokeTextViewManager.m:
--------------------------------------------------------------------------------
1 | #import
2 |
3 | @interface RCT_EXTERN_MODULE(StrokeTextViewManager, RCTViewManager)
4 |
5 | RCT_EXPORT_VIEW_PROPERTY(width, NSNumber)
6 | RCT_EXPORT_VIEW_PROPERTY(text, NSString)
7 | RCT_EXPORT_VIEW_PROPERTY(fontSize, NSNumber)
8 | RCT_EXPORT_VIEW_PROPERTY(color, NSString)
9 | RCT_EXPORT_VIEW_PROPERTY(strokeColor, NSString)
10 | RCT_EXPORT_VIEW_PROPERTY(strokeWidth, NSNumber)
11 | RCT_EXPORT_VIEW_PROPERTY(fontFamily, NSString)
12 | RCT_EXPORT_VIEW_PROPERTY(align, NSString)
13 | RCT_EXPORT_VIEW_PROPERTY(ellipsis, BOOL)
14 | RCT_EXPORT_VIEW_PROPERTY(numberOfLines, NSNumber)
15 |
16 | @end
17 |
--------------------------------------------------------------------------------
/.github/workflows/npm-publish.yml:
--------------------------------------------------------------------------------
1 | name: Publish CI
2 |
3 | on:
4 | release:
5 | types: [created]
6 |
7 | jobs:
8 | publish-npm:
9 | runs-on: ubuntu-latest
10 | permissions:
11 | contents: read
12 | id-token: write
13 | steps:
14 | - uses: actions/checkout@v4
15 | - uses: actions/setup-node@v4
16 | with:
17 | node-version: 18
18 | registry-url: https://registry.npmjs.org/
19 | - name: Build
20 | run: |
21 | yarn install
22 | yarn run build
23 | - run: npm publish --provenance --access public
24 | env:
25 | NODE_AUTH_TOKEN: ${{secrets.NPM_TOKEN}}
26 |
--------------------------------------------------------------------------------
/src/index.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { requireNativeComponent } from "react-native";
3 |
4 | const ComponentName = "StrokeTextView";
5 |
6 | type TextAlign = "center" | "left" | "right"
7 |
8 | export interface StrokeTextProps {
9 | width?: number;
10 | text: string;
11 | fontSize?: number;
12 | color?: string;
13 | strokeColor?: string;
14 | strokeWidth?: number;
15 | fontFamily?: string;
16 | align?: TextAlign;
17 | numberOfLines?: number;
18 | ellipsis?: boolean;
19 | }
20 |
21 | const NativeStrokeText = requireNativeComponent(ComponentName);
22 |
23 | export const StrokeText = (props: StrokeTextProps) => {
24 | return ;
25 | };
26 |
--------------------------------------------------------------------------------
/android/src/main/java/com/stroketext/StrokeTextPackage.java:
--------------------------------------------------------------------------------
1 | package com.stroketext;
2 |
3 | import com.facebook.react.ReactPackage;
4 | import com.facebook.react.bridge.NativeModule;
5 | import com.facebook.react.bridge.ReactApplicationContext;
6 | import com.facebook.react.uimanager.ViewManager;
7 |
8 | import java.util.Arrays;
9 | import java.util.Collections;
10 | import java.util.List;
11 |
12 | public class StrokeTextPackage implements ReactPackage {
13 | @Override
14 | public List createNativeModules(ReactApplicationContext reactContext) {
15 | return Collections.emptyList();
16 | }
17 |
18 | @Override
19 | public List createViewManagers(ReactApplicationContext reactContext) {
20 | return Arrays.asList(new StrokeTextViewManager());
21 | }
22 | }
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@charmy.tech/react-native-stroke-text",
3 | "version": "1.2.3",
4 | "description": "React Native Stroke/Outline Text",
5 | "main": "build/index.js",
6 | "source": "./src/",
7 | "author": "Charmy Inc. (https://github.com/charmy)",
8 | "license": "MIT",
9 | "homepage": "https://github.com/charmy/react-native-stroke-text#readme",
10 | "repository": "https://github.com/charmy/react-native-stroke-text",
11 | "bugs": {
12 | "url": "https://github.com/charmy/react-native-stroke-text"
13 | },
14 | "keywords": [
15 | "react-native",
16 | "stroke",
17 | "text",
18 | "outline"
19 | ],
20 | "scripts": {
21 | "build": "tsc"
22 | },
23 | "devDependencies": {
24 | "@babel/core": "^7.21.3",
25 | "@babel/runtime": "^7.21.0",
26 | "@types/node": "^18.15.3",
27 | "@types/react": "^18.0.28",
28 | "@types/react-native": "^0.71.3",
29 | "prettier": "^2.8.5",
30 | "typescript": "^5.0.2"
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # OSX
2 | #
3 | .DS_Store
4 |
5 | # XDE
6 | .expo/
7 |
8 | # VSCode
9 | .vscode/
10 | jsconfig.json
11 |
12 | # Xcode
13 | #
14 | build/
15 | *.pbxuser
16 | !default.pbxuser
17 | *.mode1v3
18 | !default.mode1v3
19 | *.mode2v3
20 | !default.mode2v3
21 | *.perspectivev3
22 | !default.perspectivev3
23 | xcuserdata
24 | *.xccheckout
25 | *.moved-aside
26 | DerivedData
27 | *.hmap
28 | *.ipa
29 | *.xcuserstate
30 | project.xcworkspace
31 |
32 | # Android/IJ
33 | #
34 | .classpath
35 | .cxx
36 | .gradle
37 | .idea
38 | .project
39 | .settings
40 | local.properties
41 | android.iml
42 |
43 | # Cocoapods
44 | #
45 | example/ios/Pods
46 |
47 | # Ruby
48 | example/vendor/
49 |
50 | # node.js
51 | #
52 | node_modules/
53 | npm-debug.log
54 | yarn-debug.log
55 | yarn-error.log
56 |
57 | # BUCK
58 | buck-out/
59 | \.buckd/
60 | android/app/libs
61 | android/keystores/debug.keystore
62 |
63 | # Yarn
64 | .yarn/*
65 | !.yarn/patches
66 | !.yarn/plugins
67 | !.yarn/releases
68 | !.yarn/sdks
69 | !.yarn/versions
70 |
71 | # Expo
72 | .expo/
73 |
74 | # Turborepo
75 | .turbo/
76 |
77 | /build
78 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2024 Charmy
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "esnext",
4 | "module": "es6",
5 | "lib": ["es6"],
6 | "allowJs": true,
7 | "jsx": "react-native",
8 | "noImplicitAny": false,
9 | "incremental": true /* Enable incremental compilation */,
10 | "isolatedModules": true,
11 | "strict": true,
12 | "moduleResolution": "node",
13 | "baseUrl": "./",
14 | "outDir": "build",
15 | "noEmitHelpers": true,
16 | "alwaysStrict": true,
17 | "strictFunctionTypes": true,
18 | "resolveJsonModule": true,
19 | "importHelpers": false,
20 | "experimentalDecorators": true,
21 | "strictPropertyInitialization": false,
22 | "allowSyntheticDefaultImports": true,
23 | "strictNullChecks": true,
24 | "skipDefaultLibCheck": true,
25 | "skipLibCheck": true,
26 | "esModuleInterop": true,
27 | "typeRoots": ["./node_modules/@types", "./@types"],
28 | "declaration": true /* Generates corresponding '.d.ts' file. */,
29 | "sourceMap": true /* Generates corresponding '.map' file. */
30 | },
31 | "exclude": [
32 | "node_modules",
33 | "build",
34 | ]
35 | }
36 |
--------------------------------------------------------------------------------
/android/src/main/java/com/stroketext/FontUtil.java:
--------------------------------------------------------------------------------
1 | package com.stroketext;
2 |
3 | import android.content.Context;
4 | import android.graphics.Typeface;
5 |
6 | import com.facebook.react.views.text.ReactFontManager;
7 |
8 | import java.io.IOException;
9 |
10 | public class FontUtil {
11 |
12 | public static Typeface getFont(Context context, String fontFamily) {
13 | Typeface typeface = getFontFromAssets(context, fontFamily);
14 | if (typeface == null) {
15 | typeface = getFontFromReactFontManager(context, fontFamily);
16 | }
17 | return typeface;
18 | }
19 |
20 | private static Typeface getFontFromAssets(Context context, String fontFamily) {
21 | String fontPath = findFontFile(context, "fonts/", fontFamily);
22 | if (fontPath != null) {
23 | return Typeface.createFromAsset(context.getAssets(), fontPath);
24 | }
25 | return null;
26 | }
27 |
28 | private static Typeface getFontFromReactFontManager(Context context, String fontFamily) {
29 | return ReactFontManager.getInstance().getTypeface(fontFamily, 0, context.getAssets());
30 | }
31 |
32 | private static String findFontFile(Context context, String folderPath, String fontName) {
33 | try {
34 | String[] files = context.getAssets().list(folderPath);
35 | for (String file : files) {
36 | if (file.startsWith(fontName) && (file.endsWith(".ttf") || file.endsWith(".otf"))) {
37 | return folderPath + file;
38 | }
39 | }
40 | } catch (IOException e) {
41 | e.printStackTrace();
42 | }
43 | return null;
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/react-native-stroke-text.podspec:
--------------------------------------------------------------------------------
1 | require "json"
2 |
3 | package = JSON.parse(File.read(File.join(__dir__, "package.json")))
4 | folly_compiler_flags = '-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1 -Wno-comma -Wno-shorten-64-to-32'
5 |
6 | Pod::Spec.new do |s|
7 | s.name = "react-native-stroke-text"
8 | s.version = package["version"]
9 | s.summary = package["description"]
10 | s.homepage = package["homepage"]
11 | s.license = package["license"]
12 | s.authors = package["author"]
13 |
14 | s.platforms = { :ios => "11.0" }
15 | s.source = { :git => ".git", :tag => "#{s.version}" }
16 |
17 | s.source_files = "ios/**/*.{h,m,mm,swift}"
18 |
19 | # Use install_modules_dependencies helper to install the dependencies if React Native version >=0.71.0.
20 | # See https://github.com/facebook/react-native/blob/febf6b7f33fdb4904669f99d795eba4c0f95d7bf/scripts/cocoapods/new_architecture.rb#L79.
21 | if respond_to?(:install_modules_dependencies, true)
22 | install_modules_dependencies(s)
23 | else
24 | s.dependency "React-Core"
25 |
26 | # Don't install the dependencies when we run `pod install` in the old architecture.
27 | if ENV['RCT_NEW_ARCH_ENABLED'] == '1' then
28 | s.compiler_flags = folly_compiler_flags + " -DRCT_NEW_ARCH_ENABLED=1"
29 | s.pod_target_xcconfig = {
30 | "HEADER_SEARCH_PATHS" => "\"$(PODS_ROOT)/boost\"",
31 | "OTHER_CPLUSPLUSFLAGS" => "-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1",
32 | "CLANG_CXX_LANGUAGE_STANDARD" => "c++17"
33 | }
34 | s.dependency "React-RCTFabric"
35 | s.dependency "React-Codegen"
36 | s.dependency "RCT-Folly"
37 | s.dependency "RCTRequired"
38 | s.dependency "RCTTypeSafety"
39 | s.dependency "ReactCommon/turbomodule/core"
40 | end
41 | end
42 | end
43 |
--------------------------------------------------------------------------------
/ios/StrokedTextLabel.swift:
--------------------------------------------------------------------------------
1 | import UIKit
2 |
3 | class StrokedTextLabel: UILabel {
4 | required init?(coder: NSCoder) {
5 | fatalError("init(coder:) has not been implemented")
6 | }
7 |
8 | override init(frame: CGRect) {
9 | super.init(frame: frame)
10 | self.numberOfLines = 0
11 | }
12 |
13 | private var textInsets: UIEdgeInsets = .zero
14 |
15 | public func updateTextInsets() {
16 | textInsets = UIEdgeInsets(top: outlineWidth, left: outlineWidth, bottom: outlineWidth, right: outlineWidth)
17 | }
18 |
19 | var outlineWidth: CGFloat = 0
20 | var outlineColor: UIColor = .clear
21 | var align: NSTextAlignment = .center
22 | var customWidth: CGFloat = 0
23 | var ellipsis: Bool = false
24 |
25 |
26 | override func drawText(in rect: CGRect) {
27 | let shadowOffset = self.shadowOffset
28 | let textColor = self.textColor
29 |
30 | self.lineBreakMode = ellipsis ? .byTruncatingTail : .byWordWrapping
31 |
32 | let adjustedRect = rect.inset(by: textInsets)
33 |
34 | let context = UIGraphicsGetCurrentContext()
35 | context?.setLineWidth(outlineWidth)
36 | context?.setLineJoin(.round)
37 | context?.setTextDrawingMode(.stroke)
38 | self.textAlignment = align
39 | self.textColor = outlineColor
40 |
41 | super.drawText(in: adjustedRect)
42 |
43 | context?.setTextDrawingMode(.fill)
44 | self.textColor = textColor
45 | self.shadowOffset = CGSize(width: 0, height: 0)
46 | super.drawText(in: adjustedRect)
47 |
48 | self.shadowOffset = shadowOffset
49 | }
50 |
51 | override var intrinsicContentSize: CGSize {
52 | var contentSize = super.intrinsicContentSize
53 | if customWidth > 0 {
54 | contentSize.width = customWidth
55 | } else {
56 | contentSize.width += outlineWidth
57 | }
58 |
59 | contentSize.height += outlineWidth
60 | return contentSize
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/android/build.gradle:
--------------------------------------------------------------------------------
1 | buildscript {
2 | repositories {
3 | google()
4 | mavenCentral()
5 | }
6 |
7 | dependencies {
8 | classpath "com.android.tools.build:gradle:7.2.1"
9 | }
10 | }
11 |
12 | def isNewArchitectureEnabled() {
13 | return rootProject.hasProperty("newArchEnabled") && rootProject.getProperty("newArchEnabled") == "true"
14 | }
15 |
16 | apply plugin: "com.android.library"
17 |
18 | if (isNewArchitectureEnabled()) {
19 | apply plugin: "com.facebook.react"
20 | }
21 |
22 | def getExtOrDefault(name) {
23 | return rootProject.ext.has(name) ? rootProject.ext.get(name) : project.properties["StrokeText_" + name]
24 | }
25 |
26 | def getExtOrIntegerDefault(name) {
27 | return rootProject.ext.has(name) ? rootProject.ext.get(name) : (project.properties["StrokeText_" + name]).toInteger()
28 | }
29 |
30 | def supportsNamespace() {
31 | def parsed = com.android.Version.ANDROID_GRADLE_PLUGIN_VERSION.tokenize('.')
32 | def major = parsed[0].toInteger()
33 | def minor = parsed[1].toInteger()
34 |
35 | // Namespace support was added in 7.3.0
36 | return (major == 7 && minor >= 3) || major >= 8
37 | }
38 |
39 | android {
40 | if (supportsNamespace()) {
41 | namespace "com.stroketext"
42 |
43 | sourceSets {
44 | main {
45 | manifest.srcFile "src/main/AndroidManifestNew.xml"
46 | }
47 | }
48 | }
49 |
50 | compileSdkVersion getExtOrIntegerDefault("compileSdkVersion")
51 |
52 | defaultConfig {
53 | minSdkVersion getExtOrIntegerDefault("minSdkVersion")
54 | targetSdkVersion getExtOrIntegerDefault("targetSdkVersion")
55 |
56 | }
57 |
58 | buildTypes {
59 | release {
60 | minifyEnabled false
61 | }
62 | }
63 |
64 | lintOptions {
65 | disable "GradleCompatible"
66 | }
67 |
68 | compileOptions {
69 | sourceCompatibility JavaVersion.VERSION_1_8
70 | targetCompatibility JavaVersion.VERSION_1_8
71 | }
72 | }
73 |
74 | repositories {
75 | mavenCentral()
76 | google()
77 | }
78 |
79 |
80 | dependencies {
81 | // For < 0.71, this will be from the local maven repo
82 | // For > 0.71, this will be replaced by `com.facebook.react:react-android:$version` by react gradle plugin
83 | //noinspection GradleDynamicVersion
84 | implementation "com.facebook.react:react-native:+"
85 | }
86 |
87 |
--------------------------------------------------------------------------------
/android/src/main/java/com/stroketext/StrokeTextViewManager.java:
--------------------------------------------------------------------------------
1 | package com.stroketext;
2 |
3 | import android.view.View;
4 |
5 | import com.facebook.react.uimanager.SimpleViewManager;
6 | import com.facebook.react.uimanager.ThemedReactContext;
7 | import com.facebook.react.uimanager.annotations.ReactProp;
8 |
9 | public class StrokeTextViewManager extends SimpleViewManager {
10 | public static final String REACT_CLASS = "StrokeTextView";
11 |
12 | @Override
13 | public String getName() {
14 | return REACT_CLASS;
15 | }
16 |
17 | @Override
18 | public View createViewInstance(ThemedReactContext reactContext) {
19 | return new StrokeTextView(reactContext);
20 | }
21 |
22 | @ReactProp(name = "text")
23 | public void setText(StrokeTextView view, String text) {
24 | view.setText(text);
25 | }
26 |
27 | @ReactProp(name = "fontSize")
28 | public void setFontSize(StrokeTextView view, float fontSize) {
29 | view.setFontSize(fontSize);
30 | }
31 |
32 | @ReactProp(name = "color")
33 | public void setColor(StrokeTextView view, String color) {
34 | view.setTextColor(color);
35 | }
36 |
37 | @ReactProp(name = "strokeColor")
38 | public void setStrokeColor(StrokeTextView view, String strokeColor) {
39 | view.setStrokeColor(strokeColor);
40 | }
41 |
42 | @ReactProp(name = "strokeWidth")
43 | public void setStrokeWidth(StrokeTextView view, float strokeWidth) {
44 | view.setStrokeWidth(strokeWidth);
45 | }
46 |
47 | @ReactProp(name = "fontFamily")
48 | public void setFontFamily(StrokeTextView view, String fontFamily) {
49 | view.setFontFamily(fontFamily);
50 | }
51 |
52 | @ReactProp(name = "align")
53 | public void setTextAlignment(StrokeTextView view, String align) {
54 | view.setTextAlignment(align);
55 | }
56 |
57 | @ReactProp(name = "numberOfLines")
58 | public void setNumberOfLines(StrokeTextView view, int numberOfLines) {
59 | view.setNumberOfLines(numberOfLines);
60 | }
61 |
62 | @ReactProp(name = "ellipsis")
63 | public void setEllipsis(StrokeTextView view, boolean ellipsis) {
64 | view.setEllipsis(ellipsis);
65 | }
66 |
67 | @ReactProp(name = "width")
68 | public void setWidth(StrokeTextView view, float width) {
69 | view.setCustomWidth(width);
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # React Native Stroke/Outline Text
2 |
3 | [](https://badge.fury.io/js/@charmy.tech%2Freact-native-stroke-text)
4 |
5 | Allows you to add stylish text with stroke effects to your mobile applications. It is perfect for creating visually
6 | appealing text elements with outline effects.
7 |
8 |
9 |
10 |
11 |
12 | ## Installation
13 |
14 | ```bash
15 | npm install @charmy.tech/react-native-stroke-text
16 | # or
17 | yarn add @charmy.tech/react-native-stroke-text
18 | ```
19 |
20 | ## Android
21 | min ```compileSdkVersion``` is required to be ```34```
22 | ## iOS
23 | Go to your ios folder and run:
24 |
25 | ```
26 | pod install
27 | ```
28 |
29 | ## Usage
30 |
31 | Here's a quick example to get you started with StrokeText:
32 |
33 | ```jsx
34 | import React from "react";
35 | import { StrokeText } from "@charmy.tech/react-native-stroke-text";
36 | import { View } from "react-native";
37 |
38 | export default function Screen() {
39 | return (
40 |
41 |
49 |
50 | );
51 | }
52 |
53 | ```
54 |
55 | ### Props
56 |
57 | The following table outlines the props available for the `StrokeText` component:
58 |
59 | | Prop | Type | Description |
60 | |-----------------|---------|-----------------------------------------------------------------|
61 | | `text` | string | The text content you want to display. |
62 | | `fontSize` | number | Size of the text font, defining how large the text will be. |
63 | | `color` | string | Color of the text, can use any valid color format. |
64 | | `strokeColor` | string | Color of the stroke (outline) around the text. |
65 | | `strokeWidth` | number | Width of the stroke, determining the thickness of the outline. |
66 | | `fontFamily` | string | Font family for the text, should match available project fonts. |
67 | | `align` | string | Text alignment (default: `center`) |
68 | | `numberOfLines` | number | Number of lines (default: `0`) |
69 | | `ellipsis` | boolean | Ellipsis (...) (default: `false`) |
70 | | `width` | number | Text width to enable ellipsis (default: `undefined`) |
71 |
72 | ## Ellipsis
73 |
74 | ```jsx
75 |
87 |
88 | ```
89 |
90 |
91 |
92 |
93 |
94 | ## Custom Font
95 |
96 | ### Bare React Native
97 |
98 | Create a `react-native.config.js` file in the root directory
99 |
100 | ```javascript
101 | module.exports = {
102 | project: {
103 | ios: {},
104 | android: {},
105 | },
106 | assets: ['/assets/fonts'], // or './src/assets/fonts'
107 | };
108 | ```
109 |
110 | ### Expo ([expo-font](https://docs.expo.dev/versions/latest/sdk/font/))
111 |
112 | ```tsx
113 | import { useFonts } from "expo-font";
114 | import { Dosis_400Regular } from "@expo-google-fonts/dosis";
115 |
116 |
117 | const [fontsLoaded, fontError] = useFonts({
118 | Danfo: require("./src/assets/fonts/Danfo-Regular.ttf"),
119 | "Dosis-Regular": Dosis_400Regular,
120 | });
121 | ```
122 |
123 | ## Contributing
124 |
125 | We welcome contributions to improve this component. Feel free to submit issues and enhancement requests.
126 |
127 | ## License
128 |
129 | Please refer to the project's license for usage rights and limitations.
130 |
--------------------------------------------------------------------------------
/ios/StrokeTextView.swift:
--------------------------------------------------------------------------------
1 | import UIKit
2 | import Foundation
3 |
4 | class StrokeTextView: RCTView {
5 | public var label: StrokedTextLabel
6 | weak var bridge: RCTBridge?
7 |
8 | private var fontCache: [String: UIFont] = [:]
9 |
10 | init(bridge: RCTBridge) {
11 | label = StrokedTextLabel()
12 | self.bridge = bridge
13 | super.init(frame: .zero)
14 | label.textColor = colorStringToUIColor(colorString: color)
15 | label.outlineColor = colorStringToUIColor(colorString: strokeColor)
16 | label.translatesAutoresizingMaskIntoConstraints = false
17 | self.addSubview(label)
18 | NSLayoutConstraint.activate([
19 | label.centerXAnchor.constraint(equalTo: self.centerXAnchor),
20 | label.centerYAnchor.constraint(equalTo: self.centerYAnchor)
21 | ])
22 | }
23 |
24 | override func layoutSubviews() {
25 | super.layoutSubviews()
26 | self.bridge?.uiManager.setSize(label.intrinsicContentSize, for: self)
27 | }
28 |
29 | required init?(coder aDecoder: NSCoder) {
30 | fatalError("init(coder:) has not been implemented")
31 | }
32 |
33 | @objc var width: NSNumber = 0 {
34 | didSet {
35 | if width != oldValue {
36 | self.label.customWidth = CGFloat(truncating: width)
37 | label.setNeedsDisplay()
38 | }
39 | }
40 | }
41 |
42 | @objc var text: String = "" {
43 | didSet {
44 | if text != oldValue {
45 | label.text = text
46 | label.setNeedsDisplay()
47 | }
48 | }
49 | }
50 |
51 | @objc var fontSize: NSNumber = 14 {
52 | didSet {
53 | if fontSize != oldValue {
54 | label.font = label.font.withSize(CGFloat(truncating: fontSize))
55 | label.setNeedsDisplay()
56 | }
57 | }
58 | }
59 |
60 | @objc var color: String = "#000000" {
61 | didSet {
62 | if color != oldValue {
63 | label.textColor = colorStringToUIColor(colorString: color)
64 | label.setNeedsDisplay()
65 | }
66 | }
67 | }
68 |
69 | @objc var strokeColor: String = "#FFFFFF" {
70 | didSet {
71 | if strokeColor != oldValue {
72 | label.outlineColor = colorStringToUIColor(colorString: strokeColor)
73 | label.setNeedsDisplay()
74 | }
75 | }
76 | }
77 |
78 | @objc var strokeWidth: NSNumber = 1 {
79 | didSet {
80 | if strokeWidth != oldValue {
81 | label.outlineWidth = CGFloat(truncating: strokeWidth)
82 | label.setNeedsDisplay()
83 | }
84 | }
85 | }
86 |
87 | @objc var fontFamily: String = "Helvetica" {
88 | didSet {
89 | if fontFamily != oldValue {
90 | let cacheKey = "\(fontFamily)-\(fontSize)"
91 | if let cachedFont = fontCache[cacheKey] {
92 | label.font = cachedFont
93 | } else {
94 | let newFont: UIFont?
95 | if let reactFont = RCTFont.update(nil, withFamily: fontFamily){
96 | newFont = reactFont.withSize(CGFloat(truncating: fontSize))
97 | } else {
98 | newFont = UIFont(name: fontFamily, size: CGFloat(truncating: fontSize))
99 | }
100 | if let validFont = newFont {
101 | fontCache[cacheKey] = validFont
102 | label.font = validFont
103 | }
104 | }
105 |
106 | label.setNeedsDisplay()
107 | }
108 | }
109 | }
110 |
111 | @objc var align: String = "center" {
112 | didSet {
113 | if align != oldValue {
114 | if align == "left" {
115 | label.align = .left
116 | } else if align == "right" {
117 | label.align = .right
118 | } else {
119 | label.align = .center
120 | }
121 |
122 | label.setNeedsDisplay()
123 | }
124 | }
125 | }
126 |
127 | @objc var ellipsis: Bool = false {
128 | didSet {
129 | if ellipsis != oldValue {
130 | label.ellipsis = ellipsis
131 | label.setNeedsDisplay()
132 | }
133 | }
134 | }
135 |
136 | @objc var numberOfLines: NSNumber = 0 {
137 | didSet {
138 | if numberOfLines != oldValue {
139 | label.numberOfLines = Int(truncating: numberOfLines)
140 | label.setNeedsDisplay()
141 | }
142 | }
143 | }
144 |
145 | private func colorStringToUIColor(colorString: String) -> UIColor {
146 | var string = colorString.trimmingCharacters(in: .whitespacesAndNewlines).uppercased()
147 |
148 | if string.hasPrefix("#") {
149 | if string.count == 4 {
150 | string = "#" + string.dropFirst().map { "\($0)\($0)" }.joined()
151 | }
152 | if string.count == 7 {
153 | var rgbValue: UInt64 = 0
154 | Scanner(string: String(string.dropFirst())).scanHexInt64(&rgbValue)
155 | return UIColor(
156 | red: CGFloat((rgbValue & 0xFF0000) >> 16) / 255.0,
157 | green: CGFloat((rgbValue & 0x00FF00) >> 8) / 255.0,
158 | blue: CGFloat(rgbValue & 0x0000FF) / 255.0,
159 | alpha: 1.0
160 | )
161 | }
162 | } else if string.hasPrefix("RGBA") {
163 | let components = string.dropFirst(5).dropLast(1).split(separator: ",").map { CGFloat(Double($0.trimmingCharacters(in: .whitespaces)) ?? 0) }
164 | if components.count == 4 {
165 | return UIColor(red: components[0] / 255.0, green: components[1] / 255.0, blue: components[2] / 255.0, alpha: components[3])
166 | }
167 | } else if string.hasPrefix("RGB") {
168 | let components = string.dropFirst(4).dropLast(1).split(separator: ",").map { CGFloat(Double($0.trimmingCharacters(in: .whitespaces)) ?? 0) }
169 | if components.count == 3 {
170 | return UIColor(red: components[0] / 255.0, green: components[1] / 255.0, blue: components[2] / 255.0, alpha: 1.0)
171 | }
172 | }
173 |
174 | return UIColor.gray
175 | }
176 | }
177 |
--------------------------------------------------------------------------------
/android/src/main/java/com/stroketext/StrokeTextView.java:
--------------------------------------------------------------------------------
1 | package com.stroketext;
2 |
3 | import android.graphics.Canvas;
4 | import android.graphics.Color;
5 | import android.graphics.Paint;
6 | import android.graphics.Typeface;
7 | import android.text.Layout;
8 | import android.text.StaticLayout;
9 | import android.text.TextPaint;
10 | import android.text.TextUtils;
11 | import android.util.TypedValue;
12 | import android.view.View;
13 |
14 | import com.facebook.react.bridge.ReactContext;
15 | import com.facebook.react.uimanager.ThemedReactContext;
16 | import com.facebook.react.uimanager.UIManagerModule;
17 |
18 | import java.util.HashMap;
19 | import java.util.Map;
20 |
21 | class StrokeTextView extends View {
22 | private String text = "";
23 | private float fontSize = 14;
24 | private int textColor = 0xFF000000;
25 | private int strokeColor = 0xFFFFFFFF;
26 | private float strokeWidth = 1;
27 | private String fontFamily = "sans-serif";
28 | private int numberOfLines = 0;
29 | private boolean ellipsis = false;
30 | private final TextPaint textPaint;
31 | private final TextPaint strokePaint;
32 | private Layout.Alignment alignment = Layout.Alignment.ALIGN_CENTER;
33 | private StaticLayout textLayout;
34 | private StaticLayout strokeLayout;
35 | private boolean layoutDirty = true;
36 | private float customWidth = 0;
37 | private final Map fontCache = new HashMap<>();
38 |
39 | public StrokeTextView(ThemedReactContext context) {
40 | super(context);
41 | textPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
42 | strokePaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
43 | }
44 |
45 | private void ensureLayout() {
46 | if (layoutDirty) {
47 | Typeface typeface = getFont(fontFamily);
48 | textPaint.setTypeface(typeface);
49 | textPaint.setTextSize(fontSize);
50 | textPaint.setColor(textColor);
51 | strokePaint.setStyle(Paint.Style.STROKE);
52 | strokePaint.setStrokeJoin(Paint.Join.ROUND);
53 | strokePaint.setStrokeCap(Paint.Cap.ROUND);
54 | strokePaint.setStrokeWidth(strokeWidth);
55 | strokePaint.setColor(strokeColor);
56 | strokePaint.setTypeface(typeface);
57 | strokePaint.setTextSize(fontSize);
58 |
59 | int width = (int) getCanvasWidth();
60 | CharSequence ellipsizedText = ellipsis ? TextUtils.ellipsize(text, textPaint, width, TextUtils.TruncateAt.END) : text;
61 | textLayout = new StaticLayout(ellipsizedText, textPaint, width, alignment, 1.0f, 0.0f, false);
62 | if (numberOfLines > 0 && numberOfLines < textLayout.getLineCount()) {
63 | int lineEnd = textLayout.getLineEnd(numberOfLines - 1);
64 | ellipsizedText = ellipsizedText.subSequence(0, lineEnd);
65 | textLayout = new StaticLayout(ellipsizedText, textPaint, width, alignment, 1.0f, 0.0f, false);
66 | }
67 | strokeLayout = new StaticLayout(ellipsizedText, strokePaint, width, alignment, 1.0f, 0.0f, false);
68 |
69 | layoutDirty = false;
70 | }
71 | }
72 |
73 | @Override
74 | protected void onSizeChanged(int w, int h, int oldw, int oldh) {
75 | layoutDirty = true;
76 | ensureLayout();
77 | }
78 |
79 | private float getCanvasWidth() {
80 | if (customWidth > 0) {
81 | return getScaledSize(customWidth);
82 | }
83 |
84 | String[] lines = text.split("\n");
85 | float maxLineWidth = 0;
86 | for (String line : lines) {
87 | float lineWidth = textPaint.measureText(line);
88 | if (lineWidth > maxLineWidth) {
89 | maxLineWidth = lineWidth;
90 | }
91 | }
92 |
93 | maxLineWidth += getScaledSize(strokeWidth) / 2;
94 | return maxLineWidth;
95 | }
96 |
97 | @Override
98 | protected void onDraw(Canvas canvas) {
99 | super.onDraw(canvas);
100 | ensureLayout();
101 | strokeLayout.draw(canvas);
102 | textLayout.draw(canvas);
103 | updateSize(textLayout.getWidth(), textLayout.getHeight());
104 | }
105 |
106 | private float getScaledSize(float size) {
107 | return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, size, getResources().getDisplayMetrics());
108 | }
109 |
110 | private void updateSize(int width, int height) {
111 | ReactContext reactContext = (ReactContext) getContext();
112 | reactContext.runOnNativeModulesQueueThread(
113 | new Runnable() {
114 | @Override
115 | public void run() {
116 | UIManagerModule uiManager = reactContext.getNativeModule(UIManagerModule.class);
117 | if (uiManager != null) {
118 | uiManager.updateNodeSize(getId(), width, height);
119 | }
120 | }
121 | });
122 | }
123 |
124 | public void setText(String text) {
125 | if (!this.text.equals(text)) {
126 | this.text = text;
127 | layoutDirty = true;
128 | invalidate();
129 | }
130 | }
131 |
132 | public void setFontSize(float fontSize) {
133 | float scaledFontSize = getScaledSize(fontSize);
134 | if (this.fontSize != scaledFontSize) {
135 | this.fontSize = scaledFontSize;
136 | layoutDirty = true;
137 | invalidate();
138 | }
139 | }
140 |
141 | public void setTextColor(String color) {
142 | int parsedColor = parseColor(color);
143 | if (this.textColor != parsedColor) {
144 | this.textColor = parsedColor;
145 | layoutDirty = true;
146 | invalidate();
147 | }
148 | }
149 |
150 | public void setStrokeColor(String color) {
151 | int parsedColor = parseColor(color);
152 | if (this.strokeColor != parsedColor) {
153 | this.strokeColor = parsedColor;
154 | layoutDirty = true;
155 | invalidate();
156 | }
157 | }
158 |
159 | public void setStrokeWidth(float strokeWidth) {
160 | float scaledStrokeWidth = getScaledSize(strokeWidth);
161 | if (this.strokeWidth != scaledStrokeWidth) {
162 | this.strokeWidth = scaledStrokeWidth;
163 | layoutDirty = true;
164 | invalidate();
165 | }
166 | }
167 |
168 | public void setFontFamily(String fontFamily) {
169 | if (!this.fontFamily.equals(fontFamily)) {
170 | this.fontFamily = fontFamily;
171 | layoutDirty = true;
172 | invalidate();
173 | }
174 | }
175 |
176 | public void setTextAlignment(String alignment) {
177 | Layout.Alignment newAlignment;
178 | if ("left".equals(alignment)) {
179 | newAlignment = Layout.Alignment.ALIGN_NORMAL;
180 | } else if ("right".equals(alignment)) {
181 | newAlignment = Layout.Alignment.ALIGN_OPPOSITE;
182 | } else if ("center".equals(alignment)) {
183 | newAlignment = Layout.Alignment.ALIGN_CENTER;
184 | } else {
185 | newAlignment = this.alignment;
186 | }
187 | if (this.alignment != newAlignment) {
188 | this.alignment = newAlignment;
189 | layoutDirty = true;
190 | invalidate();
191 | }
192 | }
193 |
194 | public void setNumberOfLines(int numberOfLines) {
195 | if (this.numberOfLines != numberOfLines) {
196 | this.numberOfLines = numberOfLines;
197 | layoutDirty = true;
198 | invalidate();
199 | }
200 | }
201 |
202 | public void setEllipsis(boolean ellipsis) {
203 | if (this.ellipsis != ellipsis) {
204 | this.ellipsis = ellipsis;
205 | layoutDirty = true;
206 | invalidate();
207 | }
208 | }
209 |
210 | public void setCustomWidth(float width) {
211 | if (!(this.customWidth == width)) {
212 | this.customWidth = width;
213 | layoutDirty = true;
214 | invalidate();
215 | }
216 | }
217 |
218 | private int parseColor(String color) {
219 | if (color.startsWith("#")) {
220 | return Color.parseColor(color);
221 | } else if (color.startsWith("rgb")) {
222 | return parseRgbColor(color);
223 | }
224 |
225 | return 0xFF000000;
226 | }
227 |
228 | private int parseRgbColor(String color) {
229 | String[] parts = color.replaceAll("[rgba()\\s]", "").split(",");
230 | int r = Integer.parseInt(parts[0]);
231 | int g = Integer.parseInt(parts[1]);
232 | int b = Integer.parseInt(parts[2]);
233 | int a = parts.length > 3 ? (int) (Float.parseFloat(parts[3]) * 255) : 255;
234 | return Color.argb(a, r, g, b);
235 | }
236 |
237 | private Typeface getFont(String fontFamily) {
238 | if (fontCache.containsKey(fontFamily)) {
239 | return fontCache.get(fontFamily);
240 | } else {
241 | Typeface typeface = FontUtil.getFont(getContext(), fontFamily);
242 | fontCache.put(fontFamily, typeface);
243 | return typeface;
244 | }
245 | }
246 | }
247 |
--------------------------------------------------------------------------------
/yarn.lock:
--------------------------------------------------------------------------------
1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
2 | # yarn lockfile v1
3 |
4 |
5 | "@ampproject/remapping@^2.2.0":
6 | version "2.2.1"
7 | resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.2.1.tgz#99e8e11851128b8702cd57c33684f1d0f260b630"
8 | integrity sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==
9 | dependencies:
10 | "@jridgewell/gen-mapping" "^0.3.0"
11 | "@jridgewell/trace-mapping" "^0.3.9"
12 |
13 | "@babel/code-frame@^7.22.13", "@babel/code-frame@^7.23.5":
14 | version "7.23.5"
15 | resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.23.5.tgz#9009b69a8c602293476ad598ff53e4562e15c244"
16 | integrity sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==
17 | dependencies:
18 | "@babel/highlight" "^7.23.4"
19 | chalk "^2.4.2"
20 |
21 | "@babel/compat-data@^7.23.5":
22 | version "7.23.5"
23 | resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.23.5.tgz#ffb878728bb6bdcb6f4510aa51b1be9afb8cfd98"
24 | integrity sha512-uU27kfDRlhfKl+w1U6vp16IuvSLtjAxdArVXPa9BvLkrr7CYIsxH5adpHObeAGY/41+syctUWOZ140a2Rvkgjw==
25 |
26 | "@babel/core@^7.21.3":
27 | version "7.23.7"
28 | resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.23.7.tgz#4d8016e06a14b5f92530a13ed0561730b5c6483f"
29 | integrity sha512-+UpDgowcmqe36d4NwqvKsyPMlOLNGMsfMmQ5WGCu+siCe3t3dfe9njrzGfdN4qq+bcNUt0+Vw6haRxBOycs4dw==
30 | dependencies:
31 | "@ampproject/remapping" "^2.2.0"
32 | "@babel/code-frame" "^7.23.5"
33 | "@babel/generator" "^7.23.6"
34 | "@babel/helper-compilation-targets" "^7.23.6"
35 | "@babel/helper-module-transforms" "^7.23.3"
36 | "@babel/helpers" "^7.23.7"
37 | "@babel/parser" "^7.23.6"
38 | "@babel/template" "^7.22.15"
39 | "@babel/traverse" "^7.23.7"
40 | "@babel/types" "^7.23.6"
41 | convert-source-map "^2.0.0"
42 | debug "^4.1.0"
43 | gensync "^1.0.0-beta.2"
44 | json5 "^2.2.3"
45 | semver "^6.3.1"
46 |
47 | "@babel/generator@^7.23.6":
48 | version "7.23.6"
49 | resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.23.6.tgz#9e1fca4811c77a10580d17d26b57b036133f3c2e"
50 | integrity sha512-qrSfCYxYQB5owCmGLbl8XRpX1ytXlpueOb0N0UmQwA073KZxejgQTzAmJezxvpwQD9uGtK2shHdi55QT+MbjIw==
51 | dependencies:
52 | "@babel/types" "^7.23.6"
53 | "@jridgewell/gen-mapping" "^0.3.2"
54 | "@jridgewell/trace-mapping" "^0.3.17"
55 | jsesc "^2.5.1"
56 |
57 | "@babel/helper-compilation-targets@^7.23.6":
58 | version "7.23.6"
59 | resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.23.6.tgz#4d79069b16cbcf1461289eccfbbd81501ae39991"
60 | integrity sha512-9JB548GZoQVmzrFgp8o7KxdgkTGm6xs9DW0o/Pim72UDjzr5ObUQ6ZzYPqA+g9OTS2bBQoctLJrky0RDCAWRgQ==
61 | dependencies:
62 | "@babel/compat-data" "^7.23.5"
63 | "@babel/helper-validator-option" "^7.23.5"
64 | browserslist "^4.22.2"
65 | lru-cache "^5.1.1"
66 | semver "^6.3.1"
67 |
68 | "@babel/helper-environment-visitor@^7.22.20":
69 | version "7.22.20"
70 | resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz#96159db61d34a29dba454c959f5ae4a649ba9167"
71 | integrity sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==
72 |
73 | "@babel/helper-function-name@^7.23.0":
74 | version "7.23.0"
75 | resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz#1f9a3cdbd5b2698a670c30d2735f9af95ed52759"
76 | integrity sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==
77 | dependencies:
78 | "@babel/template" "^7.22.15"
79 | "@babel/types" "^7.23.0"
80 |
81 | "@babel/helper-hoist-variables@^7.22.5":
82 | version "7.22.5"
83 | resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz#c01a007dac05c085914e8fb652b339db50d823bb"
84 | integrity sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==
85 | dependencies:
86 | "@babel/types" "^7.22.5"
87 |
88 | "@babel/helper-module-imports@^7.22.15":
89 | version "7.22.15"
90 | resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz#16146307acdc40cc00c3b2c647713076464bdbf0"
91 | integrity sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==
92 | dependencies:
93 | "@babel/types" "^7.22.15"
94 |
95 | "@babel/helper-module-transforms@^7.23.3":
96 | version "7.23.3"
97 | resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.23.3.tgz#d7d12c3c5d30af5b3c0fcab2a6d5217773e2d0f1"
98 | integrity sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ==
99 | dependencies:
100 | "@babel/helper-environment-visitor" "^7.22.20"
101 | "@babel/helper-module-imports" "^7.22.15"
102 | "@babel/helper-simple-access" "^7.22.5"
103 | "@babel/helper-split-export-declaration" "^7.22.6"
104 | "@babel/helper-validator-identifier" "^7.22.20"
105 |
106 | "@babel/helper-simple-access@^7.22.5":
107 | version "7.22.5"
108 | resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz#4938357dc7d782b80ed6dbb03a0fba3d22b1d5de"
109 | integrity sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==
110 | dependencies:
111 | "@babel/types" "^7.22.5"
112 |
113 | "@babel/helper-split-export-declaration@^7.22.6":
114 | version "7.22.6"
115 | resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz#322c61b7310c0997fe4c323955667f18fcefb91c"
116 | integrity sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==
117 | dependencies:
118 | "@babel/types" "^7.22.5"
119 |
120 | "@babel/helper-string-parser@^7.23.4":
121 | version "7.23.4"
122 | resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.23.4.tgz#9478c707febcbbe1ddb38a3d91a2e054ae622d83"
123 | integrity sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ==
124 |
125 | "@babel/helper-validator-identifier@^7.22.20":
126 | version "7.22.20"
127 | resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz#c4ae002c61d2879e724581d96665583dbc1dc0e0"
128 | integrity sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==
129 |
130 | "@babel/helper-validator-option@^7.23.5":
131 | version "7.23.5"
132 | resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.23.5.tgz#907a3fbd4523426285365d1206c423c4c5520307"
133 | integrity sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw==
134 |
135 | "@babel/helpers@^7.23.7":
136 | version "7.23.8"
137 | resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.23.8.tgz#fc6b2d65b16847fd50adddbd4232c76378959e34"
138 | integrity sha512-KDqYz4PiOWvDFrdHLPhKtCThtIcKVy6avWD2oG4GEvyQ+XDZwHD4YQd+H2vNMnq2rkdxsDkU82T+Vk8U/WXHRQ==
139 | dependencies:
140 | "@babel/template" "^7.22.15"
141 | "@babel/traverse" "^7.23.7"
142 | "@babel/types" "^7.23.6"
143 |
144 | "@babel/highlight@^7.23.4":
145 | version "7.23.4"
146 | resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.23.4.tgz#edaadf4d8232e1a961432db785091207ead0621b"
147 | integrity sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==
148 | dependencies:
149 | "@babel/helper-validator-identifier" "^7.22.20"
150 | chalk "^2.4.2"
151 | js-tokens "^4.0.0"
152 |
153 | "@babel/parser@^7.22.15", "@babel/parser@^7.23.6":
154 | version "7.23.6"
155 | resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.23.6.tgz#ba1c9e512bda72a47e285ae42aff9d2a635a9e3b"
156 | integrity sha512-Z2uID7YJ7oNvAI20O9X0bblw7Qqs8Q2hFy0R9tAfnfLkp5MW0UH9eUvnDSnFwKZ0AvgS1ucqR4KzvVHgnke1VQ==
157 |
158 | "@babel/runtime@^7.21.0":
159 | version "7.23.8"
160 | resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.23.8.tgz#8ee6fe1ac47add7122902f257b8ddf55c898f650"
161 | integrity sha512-Y7KbAP984rn1VGMbGqKmBLio9V7y5Je9GvU4rQPCPinCyNfUcToxIXl06d59URp/F3LwinvODxab5N/G6qggkw==
162 | dependencies:
163 | regenerator-runtime "^0.14.0"
164 |
165 | "@babel/template@^7.22.15":
166 | version "7.22.15"
167 | resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.22.15.tgz#09576efc3830f0430f4548ef971dde1350ef2f38"
168 | integrity sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==
169 | dependencies:
170 | "@babel/code-frame" "^7.22.13"
171 | "@babel/parser" "^7.22.15"
172 | "@babel/types" "^7.22.15"
173 |
174 | "@babel/traverse@^7.23.7":
175 | version "7.23.7"
176 | resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.23.7.tgz#9a7bf285c928cb99b5ead19c3b1ce5b310c9c305"
177 | integrity sha512-tY3mM8rH9jM0YHFGyfC0/xf+SB5eKUu7HPj7/k3fpi9dAlsMc5YbQvDi0Sh2QTPXqMhyaAtzAr807TIyfQrmyg==
178 | dependencies:
179 | "@babel/code-frame" "^7.23.5"
180 | "@babel/generator" "^7.23.6"
181 | "@babel/helper-environment-visitor" "^7.22.20"
182 | "@babel/helper-function-name" "^7.23.0"
183 | "@babel/helper-hoist-variables" "^7.22.5"
184 | "@babel/helper-split-export-declaration" "^7.22.6"
185 | "@babel/parser" "^7.23.6"
186 | "@babel/types" "^7.23.6"
187 | debug "^4.3.1"
188 | globals "^11.1.0"
189 |
190 | "@babel/types@^7.22.15", "@babel/types@^7.22.5", "@babel/types@^7.23.0", "@babel/types@^7.23.6":
191 | version "7.23.6"
192 | resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.23.6.tgz#be33fdb151e1f5a56877d704492c240fc71c7ccd"
193 | integrity sha512-+uarb83brBzPKN38NX1MkB6vb6+mwvR6amUulqAE7ccQw1pEl+bCia9TbdG1lsnFP7lZySvUn37CHyXQdfTwzg==
194 | dependencies:
195 | "@babel/helper-string-parser" "^7.23.4"
196 | "@babel/helper-validator-identifier" "^7.22.20"
197 | to-fast-properties "^2.0.0"
198 |
199 | "@jridgewell/gen-mapping@^0.3.0", "@jridgewell/gen-mapping@^0.3.2":
200 | version "0.3.3"
201 | resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz#7e02e6eb5df901aaedb08514203b096614024098"
202 | integrity sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==
203 | dependencies:
204 | "@jridgewell/set-array" "^1.0.1"
205 | "@jridgewell/sourcemap-codec" "^1.4.10"
206 | "@jridgewell/trace-mapping" "^0.3.9"
207 |
208 | "@jridgewell/resolve-uri@^3.1.0":
209 | version "3.1.1"
210 | resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz#c08679063f279615a3326583ba3a90d1d82cc721"
211 | integrity sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==
212 |
213 | "@jridgewell/set-array@^1.0.1":
214 | version "1.1.2"
215 | resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.2.tgz#7c6cf998d6d20b914c0a55a91ae928ff25965e72"
216 | integrity sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==
217 |
218 | "@jridgewell/sourcemap-codec@^1.4.10", "@jridgewell/sourcemap-codec@^1.4.14":
219 | version "1.4.15"
220 | resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz#d7c6e6755c78567a951e04ab52ef0fd26de59f32"
221 | integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==
222 |
223 | "@jridgewell/trace-mapping@^0.3.17", "@jridgewell/trace-mapping@^0.3.9":
224 | version "0.3.21"
225 | resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.21.tgz#5dc1df7b3dc4a6209e503a924e1ca56097a2bb15"
226 | integrity sha512-SRfKmRe1KvYnxjEMtxEr+J4HIeMX5YBg/qhRHpxEIGjhX1rshcHlnFUE9K0GazhVKWM7B+nARSkV8LuvJdJ5/g==
227 | dependencies:
228 | "@jridgewell/resolve-uri" "^3.1.0"
229 | "@jridgewell/sourcemap-codec" "^1.4.14"
230 |
231 | "@types/node@^18.15.3":
232 | version "18.19.8"
233 | resolved "https://registry.yarnpkg.com/@types/node/-/node-18.19.8.tgz#c1e42b165e5a526caf1f010747e0522cb2c9c36a"
234 | integrity sha512-g1pZtPhsvGVTwmeVoexWZLTQaOvXwoSq//pTL0DHeNzUDrFnir4fgETdhjhIxjVnN+hKOuh98+E1eMLnUXstFg==
235 | dependencies:
236 | undici-types "~5.26.4"
237 |
238 | "@types/prop-types@*":
239 | version "15.7.11"
240 | resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.11.tgz#2596fb352ee96a1379c657734d4b913a613ad563"
241 | integrity sha512-ga8y9v9uyeiLdpKddhxYQkxNDrfvuPrlFb0N1qnZZByvcElJaXthF1UhvCh9TLWJBEHeNtdnbysW7Y6Uq8CVng==
242 |
243 | "@types/react-native@^0.71.3":
244 | version "0.71.13"
245 | resolved "https://registry.yarnpkg.com/@types/react-native/-/react-native-0.71.13.tgz#5d9f154aa7808fbff8d5ad399812e21f434fd7da"
246 | integrity sha512-UBYrqo7AFmQdABbx0yuygRkLpTUsoWaERgvFCU4OxsY8SnYmS+n6ACbWV+GuUY8eBIcbfgrbPAVuwTW/1fpRYQ==
247 | dependencies:
248 | "@types/react" "*"
249 |
250 | "@types/react@*", "@types/react@^18.0.28":
251 | version "18.2.48"
252 | resolved "https://registry.yarnpkg.com/@types/react/-/react-18.2.48.tgz#11df5664642d0bd879c1f58bc1d37205b064e8f1"
253 | integrity sha512-qboRCl6Ie70DQQG9hhNREz81jqC1cs9EVNcjQ1AU+jH6NFfSAhVVbrrY/+nSF+Bsk4AOwm9Qa61InvMCyV+H3w==
254 | dependencies:
255 | "@types/prop-types" "*"
256 | "@types/scheduler" "*"
257 | csstype "^3.0.2"
258 |
259 | "@types/scheduler@*":
260 | version "0.16.8"
261 | resolved "https://registry.yarnpkg.com/@types/scheduler/-/scheduler-0.16.8.tgz#ce5ace04cfeabe7ef87c0091e50752e36707deff"
262 | integrity sha512-WZLiwShhwLRmeV6zH+GkbOFT6Z6VklCItrDioxUnv+u4Ll+8vKeFySoFyK/0ctcRpOmwAicELfmys1sDc/Rw+A==
263 |
264 | ansi-styles@^3.2.1:
265 | version "3.2.1"
266 | resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d"
267 | integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==
268 | dependencies:
269 | color-convert "^1.9.0"
270 |
271 | browserslist@^4.22.2:
272 | version "4.22.2"
273 | resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.22.2.tgz#704c4943072bd81ea18997f3bd2180e89c77874b"
274 | integrity sha512-0UgcrvQmBDvZHFGdYUehrCNIazki7/lUP3kkoi/r3YB2amZbFM9J43ZRkJTXBUZK4gmx56+Sqk9+Vs9mwZx9+A==
275 | dependencies:
276 | caniuse-lite "^1.0.30001565"
277 | electron-to-chromium "^1.4.601"
278 | node-releases "^2.0.14"
279 | update-browserslist-db "^1.0.13"
280 |
281 | caniuse-lite@^1.0.30001565:
282 | version "1.0.30001579"
283 | resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001579.tgz#45c065216110f46d6274311a4b3fcf6278e0852a"
284 | integrity sha512-u5AUVkixruKHJjw/pj9wISlcMpgFWzSrczLZbrqBSxukQixmg0SJ5sZTpvaFvxU0HoQKd4yoyAogyrAz9pzJnA==
285 |
286 | chalk@^2.4.2:
287 | version "2.4.2"
288 | resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424"
289 | integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==
290 | dependencies:
291 | ansi-styles "^3.2.1"
292 | escape-string-regexp "^1.0.5"
293 | supports-color "^5.3.0"
294 |
295 | color-convert@^1.9.0:
296 | version "1.9.3"
297 | resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8"
298 | integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==
299 | dependencies:
300 | color-name "1.1.3"
301 |
302 | color-name@1.1.3:
303 | version "1.1.3"
304 | resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25"
305 | integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==
306 |
307 | convert-source-map@^2.0.0:
308 | version "2.0.0"
309 | resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-2.0.0.tgz#4b560f649fc4e918dd0ab75cf4961e8bc882d82a"
310 | integrity sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==
311 |
312 | csstype@^3.0.2:
313 | version "3.1.3"
314 | resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.3.tgz#d80ff294d114fb0e6ac500fbf85b60137d7eff81"
315 | integrity sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==
316 |
317 | debug@^4.1.0, debug@^4.3.1:
318 | version "4.3.4"
319 | resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865"
320 | integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==
321 | dependencies:
322 | ms "2.1.2"
323 |
324 | electron-to-chromium@^1.4.601:
325 | version "1.4.638"
326 | resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.638.tgz#5564b750c2ceb64c0d2ef5a22b0748f63b66e0a3"
327 | integrity sha512-gpmbAG2LbfPKcDaL5m9IKutKjUx4ZRkvGNkgL/8nKqxkXsBVYykVULboWlqCrHsh3razucgDJDuKoWJmGPdItA==
328 |
329 | escalade@^3.1.1:
330 | version "3.1.1"
331 | resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40"
332 | integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==
333 |
334 | escape-string-regexp@^1.0.5:
335 | version "1.0.5"
336 | resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4"
337 | integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==
338 |
339 | gensync@^1.0.0-beta.2:
340 | version "1.0.0-beta.2"
341 | resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0"
342 | integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==
343 |
344 | globals@^11.1.0:
345 | version "11.12.0"
346 | resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e"
347 | integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==
348 |
349 | has-flag@^3.0.0:
350 | version "3.0.0"
351 | resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd"
352 | integrity sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==
353 |
354 | js-tokens@^4.0.0:
355 | version "4.0.0"
356 | resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"
357 | integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==
358 |
359 | jsesc@^2.5.1:
360 | version "2.5.2"
361 | resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4"
362 | integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==
363 |
364 | json5@^2.2.3:
365 | version "2.2.3"
366 | resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283"
367 | integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==
368 |
369 | lru-cache@^5.1.1:
370 | version "5.1.1"
371 | resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920"
372 | integrity sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==
373 | dependencies:
374 | yallist "^3.0.2"
375 |
376 | ms@2.1.2:
377 | version "2.1.2"
378 | resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009"
379 | integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==
380 |
381 | node-releases@^2.0.14:
382 | version "2.0.14"
383 | resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.14.tgz#2ffb053bceb8b2be8495ece1ab6ce600c4461b0b"
384 | integrity sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==
385 |
386 | picocolors@^1.0.0:
387 | version "1.0.0"
388 | resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c"
389 | integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==
390 |
391 | prettier@^2.8.5:
392 | version "2.8.8"
393 | resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.8.8.tgz#e8c5d7e98a4305ffe3de2e1fc4aca1a71c28b1da"
394 | integrity sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==
395 |
396 | regenerator-runtime@^0.14.0:
397 | version "0.14.1"
398 | resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz#356ade10263f685dda125100cd862c1db895327f"
399 | integrity sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==
400 |
401 | semver@^6.3.1:
402 | version "6.3.1"
403 | resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4"
404 | integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==
405 |
406 | supports-color@^5.3.0:
407 | version "5.5.0"
408 | resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f"
409 | integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==
410 | dependencies:
411 | has-flag "^3.0.0"
412 |
413 | to-fast-properties@^2.0.0:
414 | version "2.0.0"
415 | resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e"
416 | integrity sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==
417 |
418 | typescript@^5.0.2:
419 | version "5.3.3"
420 | resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.3.3.tgz#b3ce6ba258e72e6305ba66f5c9b452aaee3ffe37"
421 | integrity sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==
422 |
423 | undici-types@~5.26.4:
424 | version "5.26.5"
425 | resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-5.26.5.tgz#bcd539893d00b56e964fd2657a4866b221a65617"
426 | integrity sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==
427 |
428 | update-browserslist-db@^1.0.13:
429 | version "1.0.13"
430 | resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz#3c5e4f5c083661bd38ef64b6328c26ed6c8248c4"
431 | integrity sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==
432 | dependencies:
433 | escalade "^3.1.1"
434 | picocolors "^1.0.0"
435 |
436 | yallist@^3.0.2:
437 | version "3.1.1"
438 | resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd"
439 | integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==
440 |
--------------------------------------------------------------------------------