From 7c62626d68f51c178f6658792e5ea06b9e507d18 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Igor=20Furga=C5=82a?=
<74370735+exploIF@users.noreply.github.com>
Date: Thu, 18 Dec 2025 13:47:17 +0100
Subject: [PATCH 01/13] chore: release 0.2.1 (#338)
Release 0.2.1
---
example/ios/Podfile.lock | 2 +-
package.json | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock
index 6b971f4c6..d0536afba 100644
--- a/example/ios/Podfile.lock
+++ b/example/ios/Podfile.lock
@@ -2477,7 +2477,7 @@ PODS:
- React-perflogger (= 0.83.0)
- React-utils (= 0.83.0)
- SocketRocket
- - ReactNativeEnriched (0.2.0):
+ - ReactNativeEnriched (0.2.1):
- boost
- DoubleConversion
- fast_float
diff --git a/package.json b/package.json
index c285e8592..2a1dcf835 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "react-native-enriched",
- "version": "0.2.0",
+ "version": "0.2.1",
"description": "Rich Text Editor component for React Native",
"source": "./src/index.tsx",
"main": "./lib/module/index.js",
From da3476620d15ef6257473b833b559d1835319078 Mon Sep 17 00:00:00 2001
From: Maksymilian Rojek <58428606+maksymilianrojek@users.noreply.github.com>
Date: Fri, 19 Dec 2025 09:25:06 +0100
Subject: [PATCH 02/13] feat: initialize Vite + React web example (#326)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Initialize Vite + React web example
Changes:
- Created new web example in apps/example-web with React 19 and Vite
- Configured Turbo with build:web task
- Added workspace to monorepo configuration
- Updated ESLint and .gitignore for web build output
- Updated tsconfig files for monorepo setup - extracted common config
options to `tsconfig.base.json`
iOS/Android example app should work as before, no changes.
Running web example:
1. Install dependencies: `yarn install` in root directory
2. Start the dev server: `turbo run dev` in root or `yarn dev` in
/apps/example-web directory
3. The app should now be running at `http://localhost:5173`.
---------
Co-authored-by: Igor FurgaĆa <74370735+exploIF@users.noreply.github.com>
---
.github/workflows/ci.yml | 31 +
apps/example-web/README.md | 60 ++
apps/example-web/eslint.config.mjs | 32 +
apps/example-web/index.html | 15 +
apps/example-web/package.json | 35 +
apps/example-web/src/App.css | 5 +
apps/example-web/src/App.tsx | 12 +
apps/example-web/src/index.css | 11 +
apps/example-web/src/main.tsx | 13 +
apps/example-web/tsconfig.app.json | 8 +
apps/example-web/tsconfig.json | 7 +
apps/example-web/tsconfig.node.json | 9 +
apps/example-web/vite.config.ts | 7 +
eslint.config.mjs | 5 +-
package.json | 4 +-
tsconfig.base.json | 25 +
tsconfig.build.json | 2 +-
tsconfig.json | 24 +-
turbo.json | 10 +
yarn.lock | 1397 ++++++++++++++++++++++++++-
20 files changed, 1677 insertions(+), 35 deletions(-)
create mode 100644 apps/example-web/README.md
create mode 100644 apps/example-web/eslint.config.mjs
create mode 100644 apps/example-web/index.html
create mode 100644 apps/example-web/package.json
create mode 100644 apps/example-web/src/App.css
create mode 100644 apps/example-web/src/App.tsx
create mode 100644 apps/example-web/src/index.css
create mode 100644 apps/example-web/src/main.tsx
create mode 100644 apps/example-web/tsconfig.app.json
create mode 100644 apps/example-web/tsconfig.json
create mode 100644 apps/example-web/tsconfig.node.json
create mode 100644 apps/example-web/vite.config.ts
create mode 100644 tsconfig.base.json
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 354001449..70ddc92a0 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -53,6 +53,37 @@ jobs:
- name: Build package
run: yarn prepare
+ build-web:
+ runs-on: ubuntu-latest
+ env:
+ TURBO_CACHE_DIR: .turbo/web
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v4
+
+ - name: Setup
+ uses: ./.github/actions/setup
+
+ - name: Cache turborepo for Web
+ uses: actions/cache@v4
+ with:
+ path: ${{ env.TURBO_CACHE_DIR }}
+ key: ${{ runner.os }}-turborepo-web-${{ hashFiles('yarn.lock') }}
+ restore-keys: |
+ ${{ runner.os }}-turborepo-web-
+
+ - name: Check turborepo cache for Web
+ run: |
+ TURBO_CACHE_STATUS=$(node -p "($(yarn turbo run build:web --cache-dir="${{ env.TURBO_CACHE_DIR }}" --dry=json)).tasks.find(t => t.task === 'build:web').cache.status")
+
+ if [[ $TURBO_CACHE_STATUS == "HIT" ]]; then
+ echo "turbo_cache_hit=1" >> $GITHUB_ENV
+ fi
+
+ - name: Build example for Web
+ run: |
+ yarn turbo run build:web --cache-dir="${{ env.TURBO_CACHE_DIR }}"
+
build-android:
runs-on: ubuntu-latest
env:
diff --git a/apps/example-web/README.md b/apps/example-web/README.md
new file mode 100644
index 000000000..2b6b456df
--- /dev/null
+++ b/apps/example-web/README.md
@@ -0,0 +1,60 @@
+# React Native Enriched Web Example
+
+This is a [**Vite**](https://vite.dev) + [**React**](https://react.dev) web example for the React Native Enriched text input component, bootstrapped with Vite's React template.
+
+# Getting Started
+
+## Step 1: Install dependencies
+
+From the root of the monorepo, install all workspace dependencies:
+
+```sh
+yarn install
+```
+
+## Step 2: Start the development server
+
+Run the following command from the root of the monorepo or from the `apps/example-web` directory:
+
+```sh
+# From root - using Turbo
+yarn example-web dev
+
+# OR directly in this workspace
+yarn dev
+```
+
+The app should now be running at `http://localhost:5173`.
+
+## Step 3: Modify your app
+
+Now that you have the development server running, let's make changes!
+
+Open `src/App.tsx` in your text editor of choice and make some changes. When you save, your app will automatically update and reflect these changes.
+
+## Build for production
+
+To create an optimized production build:
+
+```sh
+yarn build:web
+```
+
+The built files will be in the `dist/` directory.
+
+## Preview the production build
+
+To preview the production build locally:
+
+```sh
+yarn preview
+```
+
+# Learn More
+
+To learn more about the tools and technologies used:
+
+- [Vite Documentation](https://vite.dev) - Learn more about Vite
+- [React Documentation](https://react.dev) - Learn more about React
+- [TypeScript Documentation](https://www.typescriptlang.org) - Learn more about TypeScript
+- [Turbo Documentation](https://turbo.build) - Learn more about Turbo monorepo management
diff --git a/apps/example-web/eslint.config.mjs b/apps/example-web/eslint.config.mjs
new file mode 100644
index 000000000..ba3351ee0
--- /dev/null
+++ b/apps/example-web/eslint.config.mjs
@@ -0,0 +1,32 @@
+import js from '@eslint/js';
+import globals from 'globals';
+import reactHooks from 'eslint-plugin-react-hooks';
+import reactRefresh from 'eslint-plugin-react-refresh';
+import reactX from 'eslint-plugin-react-x';
+import reactDom from 'eslint-plugin-react-dom';
+import tseslint from 'typescript-eslint';
+import { defineConfig, globalIgnores } from 'eslint/config';
+
+export default defineConfig([
+ globalIgnores(['dist']),
+ {
+ files: ['**/*.{ts,tsx}'],
+ extends: [
+ js.configs.recommended,
+ tseslint.configs.strictTypeChecked,
+ tseslint.configs.stylisticTypeChecked,
+ reactHooks.configs.flat.recommended,
+ reactRefresh.configs.vite,
+ reactX.configs['recommended-typescript'],
+ reactDom.configs.recommended,
+ ],
+ languageOptions: {
+ parserOptions: {
+ project: ['./tsconfig.node.json', './tsconfig.app.json'],
+ tsconfigRootDir: import.meta.dirname,
+ },
+ ecmaVersion: 2020,
+ globals: globals.browser,
+ },
+ },
+]);
diff --git a/apps/example-web/index.html b/apps/example-web/index.html
new file mode 100644
index 000000000..601bf5de6
--- /dev/null
+++ b/apps/example-web/index.html
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+ React Native Enriched Web Example
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/apps/example-web/package.json b/apps/example-web/package.json
new file mode 100644
index 000000000..8914d6437
--- /dev/null
+++ b/apps/example-web/package.json
@@ -0,0 +1,35 @@
+{
+ "name": "react-native-enriched-web-example",
+ "version": "0.0.1",
+ "private": true,
+ "type": "module",
+ "scripts": {
+ "dev": "vite",
+ "build:web": "tsc -b && vite build",
+ "preview": "vite preview",
+ "lint": "eslint . --ext ts,tsx"
+ },
+ "dependencies": {
+ "react": "^19.1.0",
+ "react-dom": "^19.1.0"
+ },
+ "devDependencies": {
+ "@eslint/js": "^9.39.1",
+ "@types/node": "^24.10.1",
+ "@types/react": "^19.1.0",
+ "@types/react-dom": "^19.2.3",
+ "@vitejs/plugin-react": "^5.1.1",
+ "eslint": "^9.22.0",
+ "eslint-plugin-react-dom": "^2.3.13",
+ "eslint-plugin-react-hooks": "^7.0.1",
+ "eslint-plugin-react-refresh": "^0.4.24",
+ "eslint-plugin-react-x": "^2.3.13",
+ "globals": "^16.5.0",
+ "typescript": "^5.8.3",
+ "typescript-eslint": "^8.46.4",
+ "vite": "^7.2.4"
+ },
+ "engines": {
+ "node": ">=20"
+ }
+}
diff --git a/apps/example-web/src/App.css b/apps/example-web/src/App.css
new file mode 100644
index 000000000..e624d07ac
--- /dev/null
+++ b/apps/example-web/src/App.css
@@ -0,0 +1,5 @@
+.container {
+ max-width: 800px;
+ margin: 0 auto;
+ padding: 2rem;
+}
diff --git a/apps/example-web/src/App.tsx b/apps/example-web/src/App.tsx
new file mode 100644
index 000000000..b6fa757c8
--- /dev/null
+++ b/apps/example-web/src/App.tsx
@@ -0,0 +1,12 @@
+import './App.css';
+
+function App() {
+ return (
+
+ );
+}
+
+export default App;
diff --git a/apps/example-web/src/index.css b/apps/example-web/src/index.css
new file mode 100644
index 000000000..83d89e877
--- /dev/null
+++ b/apps/example-web/src/index.css
@@ -0,0 +1,11 @@
+:root {
+ color: rgba(255, 255, 255, 0.87);
+ background-color: #242424;
+}
+
+@media (prefers-color-scheme: light) {
+ :root {
+ color: #213547;
+ background-color: #ffffff;
+ }
+}
diff --git a/apps/example-web/src/main.tsx b/apps/example-web/src/main.tsx
new file mode 100644
index 000000000..df7cd406f
--- /dev/null
+++ b/apps/example-web/src/main.tsx
@@ -0,0 +1,13 @@
+import { StrictMode } from 'react';
+import { createRoot } from 'react-dom/client';
+import './index.css';
+import App from './App';
+
+const rootElement = document.getElementById('root');
+if (!rootElement) throw new Error('Root element "#root" not found');
+
+createRoot(rootElement).render(
+
+
+
+);
diff --git a/apps/example-web/tsconfig.app.json b/apps/example-web/tsconfig.app.json
new file mode 100644
index 000000000..690114886
--- /dev/null
+++ b/apps/example-web/tsconfig.app.json
@@ -0,0 +1,8 @@
+{
+ "extends": "../../tsconfig.base.json",
+ "compilerOptions": {
+ "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
+ "types": ["vite/client"],
+ },
+ "include": ["src"]
+}
diff --git a/apps/example-web/tsconfig.json b/apps/example-web/tsconfig.json
new file mode 100644
index 000000000..1ffef600d
--- /dev/null
+++ b/apps/example-web/tsconfig.json
@@ -0,0 +1,7 @@
+{
+ "files": [],
+ "references": [
+ { "path": "./tsconfig.app.json" },
+ { "path": "./tsconfig.node.json" }
+ ]
+}
diff --git a/apps/example-web/tsconfig.node.json b/apps/example-web/tsconfig.node.json
new file mode 100644
index 000000000..c31ba89ef
--- /dev/null
+++ b/apps/example-web/tsconfig.node.json
@@ -0,0 +1,9 @@
+{
+ "extends": "../../tsconfig.base.json",
+ "compilerOptions": {
+ "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
+ "lib": ["ES2023"],
+ "types": ["node"],
+ },
+ "include": ["vite.config.ts"]
+}
diff --git a/apps/example-web/vite.config.ts b/apps/example-web/vite.config.ts
new file mode 100644
index 000000000..4a5def4c3
--- /dev/null
+++ b/apps/example-web/vite.config.ts
@@ -0,0 +1,7 @@
+import { defineConfig } from 'vite';
+import react from '@vitejs/plugin-react';
+
+// https://vite.dev/config/
+export default defineConfig({
+ plugins: [react()],
+});
diff --git a/eslint.config.mjs b/eslint.config.mjs
index 84f2a4d11..86d53e7db 100644
--- a/eslint.config.mjs
+++ b/eslint.config.mjs
@@ -33,9 +33,6 @@ export default defineConfig([
},
},
{
- ignores: [
- 'node_modules/',
- 'lib/'
- ],
+ ignores: ['node_modules/', 'lib/', 'apps/example-web/dist/'],
},
]);
diff --git a/package.json b/package.json
index 2a1dcf835..e326155ba 100644
--- a/package.json
+++ b/package.json
@@ -34,6 +34,7 @@
],
"scripts": {
"example": "yarn workspace react-native-enriched-example",
+ "example-web": "yarn workspace react-native-enriched-web-example",
"test": "jest --passWithNoTests",
"typecheck": "tsc",
"lint": "eslint \"**/*.{js,ts,tsx}\"",
@@ -98,7 +99,8 @@
"react-native": "*"
},
"workspaces": [
- "example"
+ "example",
+ "apps/example-web"
],
"packageManager": "yarn@3.6.1",
"jest": {
diff --git a/tsconfig.base.json b/tsconfig.base.json
new file mode 100644
index 000000000..fe36c9f68
--- /dev/null
+++ b/tsconfig.base.json
@@ -0,0 +1,25 @@
+{
+ "compilerOptions": {
+ "allowUnreachableCode": false,
+ "allowUnusedLabels": false,
+ "esModuleInterop": true,
+ "forceConsistentCasingInFileNames": true,
+ "jsx": "react-jsx",
+ "lib": ["ESNext", "DOM", "DOM.Iterable"],
+ "module": "ESNext",
+ "moduleResolution": "bundler",
+ "noEmit": true,
+ "noFallthroughCasesInSwitch": true,
+ "noImplicitReturns": true,
+ "noImplicitUseStrict": false,
+ "noStrictGenericChecks": false,
+ "noUncheckedIndexedAccess": true,
+ "noUnusedLocals": true,
+ "noUnusedParameters": true,
+ "resolveJsonModule": true,
+ "skipLibCheck": true,
+ "strict": true,
+ "target": "ESNext",
+ "verbatimModuleSyntax": true
+ }
+}
diff --git a/tsconfig.build.json b/tsconfig.build.json
index 3c0636adf..326236495 100644
--- a/tsconfig.build.json
+++ b/tsconfig.build.json
@@ -1,4 +1,4 @@
{
"extends": "./tsconfig",
- "exclude": ["example", "lib"]
+ "exclude": ["example", "apps", "lib"]
}
diff --git a/tsconfig.json b/tsconfig.json
index f8d112b29..37038f647 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -1,29 +1,9 @@
{
+ "extends": "./tsconfig.base.json",
"compilerOptions": {
"rootDir": ".",
"paths": {
"react-native-enriched": ["./src/index"]
- },
- "allowUnreachableCode": false,
- "allowUnusedLabels": false,
- "esModuleInterop": true,
- "forceConsistentCasingInFileNames": true,
- "jsx": "react-jsx",
- "lib": ["ESNext"],
- "module": "ESNext",
- "moduleResolution": "bundler",
- "noEmit": true,
- "noFallthroughCasesInSwitch": true,
- "noImplicitReturns": true,
- "noImplicitUseStrict": false,
- "noStrictGenericChecks": false,
- "noUncheckedIndexedAccess": true,
- "noUnusedLocals": true,
- "noUnusedParameters": true,
- "resolveJsonModule": true,
- "skipLibCheck": true,
- "strict": true,
- "target": "ESNext",
- "verbatimModuleSyntax": true
+ }
}
}
diff --git a/turbo.json b/turbo.json
index 405897eec..e490465c6 100644
--- a/turbo.json
+++ b/turbo.json
@@ -1,6 +1,16 @@
{
"$schema": "https://turbo.build/schema.json",
"pipeline": {
+ "build:web": {
+ "outputs": ["dist/**"],
+ "inputs": [
+ "package.json",
+ "src/**",
+ "tsconfig.json",
+ "vite.config.ts",
+ "index.html"
+ ]
+ },
"build:android": {
"env": ["ORG_GRADLE_PROJECT_newArchEnabled"],
"inputs": [
diff --git a/yarn.lock b/yarn.lock
index b0c641bbc..4c717b651 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -42,6 +42,17 @@ __metadata:
languageName: node
linkType: hard
+"@babel/code-frame@npm:^7.27.1":
+ version: 7.27.1
+ resolution: "@babel/code-frame@npm:7.27.1"
+ dependencies:
+ "@babel/helper-validator-identifier": ^7.27.1
+ js-tokens: ^4.0.0
+ picocolors: ^1.1.1
+ checksum: 5874edc5d37406c4a0bb14cf79c8e51ad412fb0423d176775ac14fc0259831be1bf95bdda9c2aa651126990505e09a9f0ed85deaa99893bc316d2682c5115bdc
+ languageName: node
+ linkType: hard
+
"@babel/compat-data@npm:^7.22.6, @babel/compat-data@npm:^7.26.8":
version: 7.26.8
resolution: "@babel/compat-data@npm:7.26.8"
@@ -49,6 +60,13 @@ __metadata:
languageName: node
linkType: hard
+"@babel/compat-data@npm:^7.27.2":
+ version: 7.28.5
+ resolution: "@babel/compat-data@npm:7.28.5"
+ checksum: d7bcb3ee713752dc27b89800bfb39f9ac5f3edc46b4f5bb9906e1fe6b6110c7b245dd502602ea66f93790480c228605e9a601f27c07016f24b56772e97bedbdf
+ languageName: node
+ linkType: hard
+
"@babel/core@npm:^7.11.6, @babel/core@npm:^7.12.3, @babel/core@npm:^7.20.0, @babel/core@npm:^7.23.9, @babel/core@npm:^7.25.2":
version: 7.26.10
resolution: "@babel/core@npm:7.26.10"
@@ -72,6 +90,29 @@ __metadata:
languageName: node
linkType: hard
+"@babel/core@npm:^7.24.4, @babel/core@npm:^7.28.5":
+ version: 7.28.5
+ resolution: "@babel/core@npm:7.28.5"
+ dependencies:
+ "@babel/code-frame": ^7.27.1
+ "@babel/generator": ^7.28.5
+ "@babel/helper-compilation-targets": ^7.27.2
+ "@babel/helper-module-transforms": ^7.28.3
+ "@babel/helpers": ^7.28.4
+ "@babel/parser": ^7.28.5
+ "@babel/template": ^7.27.2
+ "@babel/traverse": ^7.28.5
+ "@babel/types": ^7.28.5
+ "@jridgewell/remapping": ^2.3.5
+ convert-source-map: ^2.0.0
+ debug: ^4.1.0
+ gensync: ^1.0.0-beta.2
+ json5: ^2.2.3
+ semver: ^6.3.1
+ checksum: 1ee35b20448f73e9d531091ad4f9e8198dc8f0cebb783263fbff1807342209882ddcaf419be04111326b6f0e494222f7055d71da316c437a6a784d230c11ab9f
+ languageName: node
+ linkType: hard
+
"@babel/eslint-parser@npm:^7.25.1":
version: 7.27.0
resolution: "@babel/eslint-parser@npm:7.27.0"
@@ -99,6 +140,19 @@ __metadata:
languageName: node
linkType: hard
+"@babel/generator@npm:^7.28.5":
+ version: 7.28.5
+ resolution: "@babel/generator@npm:7.28.5"
+ dependencies:
+ "@babel/parser": ^7.28.5
+ "@babel/types": ^7.28.5
+ "@jridgewell/gen-mapping": ^0.3.12
+ "@jridgewell/trace-mapping": ^0.3.28
+ jsesc: ^3.0.2
+ checksum: 3e86fa0197bb33394a85a73dbbca92bb1b3f250a30294c7e327359c0978ad90f36f3d71c7f2965a3fc349cfa82becc8f87e7421c75796c8bc48dd9010dd866d1
+ languageName: node
+ linkType: hard
+
"@babel/helper-annotate-as-pure@npm:^7.25.9":
version: 7.25.9
resolution: "@babel/helper-annotate-as-pure@npm:7.25.9"
@@ -121,6 +175,19 @@ __metadata:
languageName: node
linkType: hard
+"@babel/helper-compilation-targets@npm:^7.27.2":
+ version: 7.27.2
+ resolution: "@babel/helper-compilation-targets@npm:7.27.2"
+ dependencies:
+ "@babel/compat-data": ^7.27.2
+ "@babel/helper-validator-option": ^7.27.1
+ browserslist: ^4.24.0
+ lru-cache: ^5.1.1
+ semver: ^6.3.1
+ checksum: 7b95328237de85d7af1dea010a4daa28e79f961dda48b652860d5893ce9b136fc8b9ea1f126d8e0a24963b09ba5c6631dcb907b4ce109b04452d34a6ae979807
+ languageName: node
+ linkType: hard
+
"@babel/helper-create-class-features-plugin@npm:^7.25.9, @babel/helper-create-class-features-plugin@npm:^7.27.0":
version: 7.27.0
resolution: "@babel/helper-create-class-features-plugin@npm:7.27.0"
@@ -166,6 +233,13 @@ __metadata:
languageName: node
linkType: hard
+"@babel/helper-globals@npm:^7.28.0":
+ version: 7.28.0
+ resolution: "@babel/helper-globals@npm:7.28.0"
+ checksum: d8d7b91c12dad1ee747968af0cb73baf91053b2bcf78634da2c2c4991fb45ede9bd0c8f9b5f3254881242bc0921218fcb7c28ae885477c25177147e978ce4397
+ languageName: node
+ linkType: hard
+
"@babel/helper-member-expression-to-functions@npm:^7.25.9":
version: 7.25.9
resolution: "@babel/helper-member-expression-to-functions@npm:7.25.9"
@@ -186,6 +260,16 @@ __metadata:
languageName: node
linkType: hard
+"@babel/helper-module-imports@npm:^7.27.1":
+ version: 7.27.1
+ resolution: "@babel/helper-module-imports@npm:7.27.1"
+ dependencies:
+ "@babel/traverse": ^7.27.1
+ "@babel/types": ^7.27.1
+ checksum: 92d01c71c0e4aacdc2babce418a9a1a27a8f7d770a210ffa0f3933f321befab18b655bc1241bebc40767516731de0b85639140c42e45a8210abe1e792f115b28
+ languageName: node
+ linkType: hard
+
"@babel/helper-module-transforms@npm:^7.25.9, @babel/helper-module-transforms@npm:^7.26.0":
version: 7.26.0
resolution: "@babel/helper-module-transforms@npm:7.26.0"
@@ -199,6 +283,19 @@ __metadata:
languageName: node
linkType: hard
+"@babel/helper-module-transforms@npm:^7.28.3":
+ version: 7.28.3
+ resolution: "@babel/helper-module-transforms@npm:7.28.3"
+ dependencies:
+ "@babel/helper-module-imports": ^7.27.1
+ "@babel/helper-validator-identifier": ^7.27.1
+ "@babel/traverse": ^7.28.3
+ peerDependencies:
+ "@babel/core": ^7.0.0
+ checksum: 7cf7b79da0fa626d6c84bfc7b35c079a2559caecaa2ff645b0f1db0d741507aa4df6b5b98a3283e8ac4e89094af271d805bf5701e5c4f916e622797b7c8cbb18
+ languageName: node
+ linkType: hard
+
"@babel/helper-optimise-call-expression@npm:^7.25.9":
version: 7.25.9
resolution: "@babel/helper-optimise-call-expression@npm:7.25.9"
@@ -265,6 +362,13 @@ __metadata:
languageName: node
linkType: hard
+"@babel/helper-string-parser@npm:^7.27.1":
+ version: 7.27.1
+ resolution: "@babel/helper-string-parser@npm:7.27.1"
+ checksum: 0a8464adc4b39b138aedcb443b09f4005d86207d7126e5e079177e05c3116107d856ec08282b365e9a79a9872f40f4092a6127f8d74c8a01c1ef789dacfc25d6
+ languageName: node
+ linkType: hard
+
"@babel/helper-validator-identifier@npm:^7.25.9":
version: 7.25.9
resolution: "@babel/helper-validator-identifier@npm:7.25.9"
@@ -272,6 +376,13 @@ __metadata:
languageName: node
linkType: hard
+"@babel/helper-validator-identifier@npm:^7.27.1, @babel/helper-validator-identifier@npm:^7.28.5":
+ version: 7.28.5
+ resolution: "@babel/helper-validator-identifier@npm:7.28.5"
+ checksum: 5a251a6848e9712aea0338f659a1a3bd334d26219d5511164544ca8ec20774f098c3a6661e9da65a0d085c745c00bb62c8fada38a62f08fa1f8053bc0aeb57e4
+ languageName: node
+ linkType: hard
+
"@babel/helper-validator-option@npm:^7.25.9":
version: 7.25.9
resolution: "@babel/helper-validator-option@npm:7.25.9"
@@ -279,6 +390,13 @@ __metadata:
languageName: node
linkType: hard
+"@babel/helper-validator-option@npm:^7.27.1":
+ version: 7.27.1
+ resolution: "@babel/helper-validator-option@npm:7.27.1"
+ checksum: db73e6a308092531c629ee5de7f0d04390835b21a263be2644276cb27da2384b64676cab9f22cd8d8dbd854c92b1d7d56fc8517cf0070c35d1c14a8c828b0903
+ languageName: node
+ linkType: hard
+
"@babel/helper-wrap-function@npm:^7.25.9":
version: 7.25.9
resolution: "@babel/helper-wrap-function@npm:7.25.9"
@@ -300,6 +418,16 @@ __metadata:
languageName: node
linkType: hard
+"@babel/helpers@npm:^7.28.4":
+ version: 7.28.4
+ resolution: "@babel/helpers@npm:7.28.4"
+ dependencies:
+ "@babel/template": ^7.27.2
+ "@babel/types": ^7.28.4
+ checksum: a8706219e0bd60c18bbb8e010aa122e9b14e7e7e67c21cc101e6f1b5e79dcb9a18d674f655997f85daaf421aa138cf284710bb04371a2255a0a3137f097430b4
+ languageName: node
+ linkType: hard
+
"@babel/parser@npm:^7.1.0, @babel/parser@npm:^7.14.7, @babel/parser@npm:^7.20.0, @babel/parser@npm:^7.20.7, @babel/parser@npm:^7.23.9, @babel/parser@npm:^7.25.3, @babel/parser@npm:^7.26.10, @babel/parser@npm:^7.27.0":
version: 7.27.0
resolution: "@babel/parser@npm:7.27.0"
@@ -311,6 +439,17 @@ __metadata:
languageName: node
linkType: hard
+"@babel/parser@npm:^7.24.4, @babel/parser@npm:^7.27.2, @babel/parser@npm:^7.28.5":
+ version: 7.28.5
+ resolution: "@babel/parser@npm:7.28.5"
+ dependencies:
+ "@babel/types": ^7.28.5
+ bin:
+ parser: ./bin/babel-parser.js
+ checksum: 5c2456e3f26c70d4a3ce1a220b529a91a2df26c54a2894fd0dea2342699ea1067ffdda9f0715eeab61da46ff546fd5661bc70be6d8d11977cbe21f5f0478819a
+ languageName: node
+ linkType: hard
+
"@babel/plugin-bugfix-firefox-class-in-computed-class-key@npm:^7.25.9":
version: 7.25.9
resolution: "@babel/plugin-bugfix-firefox-class-in-computed-class-key@npm:7.25.9"
@@ -1150,6 +1289,17 @@ __metadata:
languageName: node
linkType: hard
+"@babel/plugin-transform-react-jsx-self@npm:^7.27.1":
+ version: 7.27.1
+ resolution: "@babel/plugin-transform-react-jsx-self@npm:7.27.1"
+ dependencies:
+ "@babel/helper-plugin-utils": ^7.27.1
+ peerDependencies:
+ "@babel/core": ^7.0.0-0
+ checksum: 72cbae66a58c6c36f7e12e8ed79f292192d858dd4bb00e9e89d8b695e4c5cb6ef48eec84bffff421a5db93fd10412c581f1cccdb00264065df76f121995bdb68
+ languageName: node
+ linkType: hard
+
"@babel/plugin-transform-react-jsx-source@npm:^7.24.7":
version: 7.25.9
resolution: "@babel/plugin-transform-react-jsx-source@npm:7.25.9"
@@ -1161,6 +1311,17 @@ __metadata:
languageName: node
linkType: hard
+"@babel/plugin-transform-react-jsx-source@npm:^7.27.1":
+ version: 7.27.1
+ resolution: "@babel/plugin-transform-react-jsx-source@npm:7.27.1"
+ dependencies:
+ "@babel/helper-plugin-utils": ^7.27.1
+ peerDependencies:
+ "@babel/core": ^7.0.0-0
+ checksum: e2843362adb53692be5ee9fa07a386d2d8883daad2063a3575b3c373fc14cdf4ea7978c67a183cb631b4c9c8d77b2f48c24c088f8e65cc3600cb8e97d72a7161
+ languageName: node
+ linkType: hard
+
"@babel/plugin-transform-react-jsx@npm:^7.25.2, @babel/plugin-transform-react-jsx@npm:^7.25.9":
version: 7.25.9
resolution: "@babel/plugin-transform-react-jsx@npm:7.25.9"
@@ -1524,6 +1685,17 @@ __metadata:
languageName: node
linkType: hard
+"@babel/template@npm:^7.27.2":
+ version: 7.27.2
+ resolution: "@babel/template@npm:7.27.2"
+ dependencies:
+ "@babel/code-frame": ^7.27.1
+ "@babel/parser": ^7.27.2
+ "@babel/types": ^7.27.1
+ checksum: ff5628bc066060624afd970616090e5bba91c6240c2e4b458d13267a523572cbfcbf549391eec8217b94b064cf96571c6273f0c04b28a8567b96edc675c28e27
+ languageName: node
+ linkType: hard
+
"@babel/traverse--for-generate-function-map@npm:@babel/traverse@^7.25.3, @babel/traverse@npm:^7.20.0, @babel/traverse@npm:^7.25.3, @babel/traverse@npm:^7.25.9, @babel/traverse@npm:^7.26.10, @babel/traverse@npm:^7.26.5, @babel/traverse@npm:^7.26.8, @babel/traverse@npm:^7.27.0":
version: 7.27.0
resolution: "@babel/traverse@npm:7.27.0"
@@ -1539,6 +1711,21 @@ __metadata:
languageName: node
linkType: hard
+"@babel/traverse@npm:^7.27.1, @babel/traverse@npm:^7.28.3, @babel/traverse@npm:^7.28.5":
+ version: 7.28.5
+ resolution: "@babel/traverse@npm:7.28.5"
+ dependencies:
+ "@babel/code-frame": ^7.27.1
+ "@babel/generator": ^7.28.5
+ "@babel/helper-globals": ^7.28.0
+ "@babel/parser": ^7.28.5
+ "@babel/template": ^7.27.2
+ "@babel/types": ^7.28.5
+ debug: ^4.3.1
+ checksum: e028ee9654f44be7c2a2df268455cee72d5c424c9ae536785f8f7c8680356f7b977c77ad76909d07eeed09ff1e125ce01cf783011f66b56c838791a85fa6af04
+ languageName: node
+ linkType: hard
+
"@babel/types@npm:^7.0.0, @babel/types@npm:^7.20.0, @babel/types@npm:^7.20.7, @babel/types@npm:^7.25.2, @babel/types@npm:^7.25.9, @babel/types@npm:^7.26.10, @babel/types@npm:^7.27.0, @babel/types@npm:^7.3.3, @babel/types@npm:^7.4.4":
version: 7.27.0
resolution: "@babel/types@npm:7.27.0"
@@ -1549,6 +1736,16 @@ __metadata:
languageName: node
linkType: hard
+"@babel/types@npm:^7.27.1, @babel/types@npm:^7.28.4, @babel/types@npm:^7.28.5":
+ version: 7.28.5
+ resolution: "@babel/types@npm:7.28.5"
+ dependencies:
+ "@babel/helper-string-parser": ^7.27.1
+ "@babel/helper-validator-identifier": ^7.28.5
+ checksum: 5bc266af9e55ff92f9ddf33d83a42c9de1a87f9579d0ed62ef94a741a081692dd410a4fbbab18d514b83e135083ff05bc0e37003834801c9514b9d8ad748070d
+ languageName: node
+ linkType: hard
+
"@bcoe/v8-coverage@npm:^0.2.3":
version: 0.2.3
resolution: "@bcoe/v8-coverage@npm:0.2.3"
@@ -1765,6 +1962,188 @@ __metadata:
languageName: node
linkType: hard
+"@esbuild/aix-ppc64@npm:0.25.12":
+ version: 0.25.12
+ resolution: "@esbuild/aix-ppc64@npm:0.25.12"
+ conditions: os=aix & cpu=ppc64
+ languageName: node
+ linkType: hard
+
+"@esbuild/android-arm64@npm:0.25.12":
+ version: 0.25.12
+ resolution: "@esbuild/android-arm64@npm:0.25.12"
+ conditions: os=android & cpu=arm64
+ languageName: node
+ linkType: hard
+
+"@esbuild/android-arm@npm:0.25.12":
+ version: 0.25.12
+ resolution: "@esbuild/android-arm@npm:0.25.12"
+ conditions: os=android & cpu=arm
+ languageName: node
+ linkType: hard
+
+"@esbuild/android-x64@npm:0.25.12":
+ version: 0.25.12
+ resolution: "@esbuild/android-x64@npm:0.25.12"
+ conditions: os=android & cpu=x64
+ languageName: node
+ linkType: hard
+
+"@esbuild/darwin-arm64@npm:0.25.12":
+ version: 0.25.12
+ resolution: "@esbuild/darwin-arm64@npm:0.25.12"
+ conditions: os=darwin & cpu=arm64
+ languageName: node
+ linkType: hard
+
+"@esbuild/darwin-x64@npm:0.25.12":
+ version: 0.25.12
+ resolution: "@esbuild/darwin-x64@npm:0.25.12"
+ conditions: os=darwin & cpu=x64
+ languageName: node
+ linkType: hard
+
+"@esbuild/freebsd-arm64@npm:0.25.12":
+ version: 0.25.12
+ resolution: "@esbuild/freebsd-arm64@npm:0.25.12"
+ conditions: os=freebsd & cpu=arm64
+ languageName: node
+ linkType: hard
+
+"@esbuild/freebsd-x64@npm:0.25.12":
+ version: 0.25.12
+ resolution: "@esbuild/freebsd-x64@npm:0.25.12"
+ conditions: os=freebsd & cpu=x64
+ languageName: node
+ linkType: hard
+
+"@esbuild/linux-arm64@npm:0.25.12":
+ version: 0.25.12
+ resolution: "@esbuild/linux-arm64@npm:0.25.12"
+ conditions: os=linux & cpu=arm64
+ languageName: node
+ linkType: hard
+
+"@esbuild/linux-arm@npm:0.25.12":
+ version: 0.25.12
+ resolution: "@esbuild/linux-arm@npm:0.25.12"
+ conditions: os=linux & cpu=arm
+ languageName: node
+ linkType: hard
+
+"@esbuild/linux-ia32@npm:0.25.12":
+ version: 0.25.12
+ resolution: "@esbuild/linux-ia32@npm:0.25.12"
+ conditions: os=linux & cpu=ia32
+ languageName: node
+ linkType: hard
+
+"@esbuild/linux-loong64@npm:0.25.12":
+ version: 0.25.12
+ resolution: "@esbuild/linux-loong64@npm:0.25.12"
+ conditions: os=linux & cpu=loong64
+ languageName: node
+ linkType: hard
+
+"@esbuild/linux-mips64el@npm:0.25.12":
+ version: 0.25.12
+ resolution: "@esbuild/linux-mips64el@npm:0.25.12"
+ conditions: os=linux & cpu=mips64el
+ languageName: node
+ linkType: hard
+
+"@esbuild/linux-ppc64@npm:0.25.12":
+ version: 0.25.12
+ resolution: "@esbuild/linux-ppc64@npm:0.25.12"
+ conditions: os=linux & cpu=ppc64
+ languageName: node
+ linkType: hard
+
+"@esbuild/linux-riscv64@npm:0.25.12":
+ version: 0.25.12
+ resolution: "@esbuild/linux-riscv64@npm:0.25.12"
+ conditions: os=linux & cpu=riscv64
+ languageName: node
+ linkType: hard
+
+"@esbuild/linux-s390x@npm:0.25.12":
+ version: 0.25.12
+ resolution: "@esbuild/linux-s390x@npm:0.25.12"
+ conditions: os=linux & cpu=s390x
+ languageName: node
+ linkType: hard
+
+"@esbuild/linux-x64@npm:0.25.12":
+ version: 0.25.12
+ resolution: "@esbuild/linux-x64@npm:0.25.12"
+ conditions: os=linux & cpu=x64
+ languageName: node
+ linkType: hard
+
+"@esbuild/netbsd-arm64@npm:0.25.12":
+ version: 0.25.12
+ resolution: "@esbuild/netbsd-arm64@npm:0.25.12"
+ conditions: os=netbsd & cpu=arm64
+ languageName: node
+ linkType: hard
+
+"@esbuild/netbsd-x64@npm:0.25.12":
+ version: 0.25.12
+ resolution: "@esbuild/netbsd-x64@npm:0.25.12"
+ conditions: os=netbsd & cpu=x64
+ languageName: node
+ linkType: hard
+
+"@esbuild/openbsd-arm64@npm:0.25.12":
+ version: 0.25.12
+ resolution: "@esbuild/openbsd-arm64@npm:0.25.12"
+ conditions: os=openbsd & cpu=arm64
+ languageName: node
+ linkType: hard
+
+"@esbuild/openbsd-x64@npm:0.25.12":
+ version: 0.25.12
+ resolution: "@esbuild/openbsd-x64@npm:0.25.12"
+ conditions: os=openbsd & cpu=x64
+ languageName: node
+ linkType: hard
+
+"@esbuild/openharmony-arm64@npm:0.25.12":
+ version: 0.25.12
+ resolution: "@esbuild/openharmony-arm64@npm:0.25.12"
+ conditions: os=openharmony & cpu=arm64
+ languageName: node
+ linkType: hard
+
+"@esbuild/sunos-x64@npm:0.25.12":
+ version: 0.25.12
+ resolution: "@esbuild/sunos-x64@npm:0.25.12"
+ conditions: os=sunos & cpu=x64
+ languageName: node
+ linkType: hard
+
+"@esbuild/win32-arm64@npm:0.25.12":
+ version: 0.25.12
+ resolution: "@esbuild/win32-arm64@npm:0.25.12"
+ conditions: os=win32 & cpu=arm64
+ languageName: node
+ linkType: hard
+
+"@esbuild/win32-ia32@npm:0.25.12":
+ version: 0.25.12
+ resolution: "@esbuild/win32-ia32@npm:0.25.12"
+ conditions: os=win32 & cpu=ia32
+ languageName: node
+ linkType: hard
+
+"@esbuild/win32-x64@npm:0.25.12":
+ version: 0.25.12
+ resolution: "@esbuild/win32-x64@npm:0.25.12"
+ conditions: os=win32 & cpu=x64
+ languageName: node
+ linkType: hard
+
"@eslint-community/eslint-utils@npm:^4.2.0, @eslint-community/eslint-utils@npm:^4.4.0":
version: 4.6.1
resolution: "@eslint-community/eslint-utils@npm:4.6.1"
@@ -1776,6 +2155,17 @@ __metadata:
languageName: node
linkType: hard
+"@eslint-community/eslint-utils@npm:^4.7.0":
+ version: 4.9.0
+ resolution: "@eslint-community/eslint-utils@npm:4.9.0"
+ dependencies:
+ eslint-visitor-keys: ^3.4.3
+ peerDependencies:
+ eslint: ^6.0.0 || ^7.0.0 || >=8.0.0
+ checksum: ae9b98eea006d1354368804b0116b8b45017a4e47b486d1b9cfa048a8ed3dc69b9b074eb2b2acb14034e6897c24048fd42b6a6816d9dc8bb9daad79db7d478d2
+ languageName: node
+ linkType: hard
+
"@eslint-community/regexpp@npm:^4.10.0, @eslint-community/regexpp@npm:^4.12.1":
version: 4.12.1
resolution: "@eslint-community/regexpp@npm:4.12.1"
@@ -1783,6 +2173,81 @@ __metadata:
languageName: node
linkType: hard
+"@eslint-react/ast@npm:2.3.13":
+ version: 2.3.13
+ resolution: "@eslint-react/ast@npm:2.3.13"
+ dependencies:
+ "@eslint-react/eff": 2.3.13
+ "@typescript-eslint/types": ^8.49.0
+ "@typescript-eslint/typescript-estree": ^8.49.0
+ "@typescript-eslint/utils": ^8.49.0
+ string-ts: ^2.3.1
+ peerDependencies:
+ eslint: ^8.57.0 || ^9.0.0
+ typescript: ">=4.8.4 <6.0.0"
+ checksum: abe99c1a29bd3a94bec364982c08e9446681b6c4bb16d06a6d74c1517a333c872c2c0774c084fae9c58e3c8b8eabf357a6fce7eeac104bf8ba12cf5e20907304
+ languageName: node
+ linkType: hard
+
+"@eslint-react/core@npm:2.3.13":
+ version: 2.3.13
+ resolution: "@eslint-react/core@npm:2.3.13"
+ dependencies:
+ "@eslint-react/ast": 2.3.13
+ "@eslint-react/eff": 2.3.13
+ "@eslint-react/shared": 2.3.13
+ "@eslint-react/var": 2.3.13
+ "@typescript-eslint/scope-manager": ^8.49.0
+ "@typescript-eslint/types": ^8.49.0
+ "@typescript-eslint/utils": ^8.49.0
+ birecord: ^0.1.1
+ ts-pattern: ^5.9.0
+ peerDependencies:
+ eslint: ^8.57.0 || ^9.0.0
+ typescript: ">=4.8.4 <6.0.0"
+ checksum: 3b28923543e59988ac8125c8d8a147bab1a86145e3ab9b1125665710031b7364a6b60ef413a81cf1760e3a0671d7b9e4ffe5976bc6712a95d3d1ac40028e4f4a
+ languageName: node
+ linkType: hard
+
+"@eslint-react/eff@npm:2.3.13":
+ version: 2.3.13
+ resolution: "@eslint-react/eff@npm:2.3.13"
+ checksum: 3071491a3e76ce0b9adb6970a73a9f8c2226171e03f5826d8dbdefa04e23ac5bedd12c265596b5d2003e4102c8bde4407404de257024c9b489b047ddb6d1da60
+ languageName: node
+ linkType: hard
+
+"@eslint-react/shared@npm:2.3.13":
+ version: 2.3.13
+ resolution: "@eslint-react/shared@npm:2.3.13"
+ dependencies:
+ "@eslint-react/eff": 2.3.13
+ "@typescript-eslint/utils": ^8.49.0
+ ts-pattern: ^5.9.0
+ zod: ^4.1.13
+ peerDependencies:
+ eslint: ^8.57.0 || ^9.0.0
+ typescript: ">=4.8.4 <6.0.0"
+ checksum: 89afa3cfba767bef61e52442bd5632df13d63bdfafebb1077ac3181595830bcab68bcb7a2654eb6a28b46431fb72e6f9832dc91dc882595c79e308dce6959a78
+ languageName: node
+ linkType: hard
+
+"@eslint-react/var@npm:2.3.13":
+ version: 2.3.13
+ resolution: "@eslint-react/var@npm:2.3.13"
+ dependencies:
+ "@eslint-react/ast": 2.3.13
+ "@eslint-react/eff": 2.3.13
+ "@typescript-eslint/scope-manager": ^8.49.0
+ "@typescript-eslint/types": ^8.49.0
+ "@typescript-eslint/utils": ^8.49.0
+ ts-pattern: ^5.9.0
+ peerDependencies:
+ eslint: ^8.57.0 || ^9.0.0
+ typescript: ">=4.8.4 <6.0.0"
+ checksum: cd39fde45cf110e87b27d10f704bdf03d9c108355013a4b1448553a6da381b1f451c7a99930b5bd32e62d93f8138c983619e4f10e5d5e3e39d7e61fe5e77ce18
+ languageName: node
+ linkType: hard
+
"@eslint/compat@npm:^1.2.7":
version: 1.2.8
resolution: "@eslint/compat@npm:1.2.8"
@@ -1855,6 +2320,13 @@ __metadata:
languageName: node
linkType: hard
+"@eslint/js@npm:^9.39.1":
+ version: 9.39.2
+ resolution: "@eslint/js@npm:9.39.2"
+ checksum: 362aa447266fa5717e762b2b252f177345cb0d7b2954113db9773b3a28898f7cbbc807e07f8078995e6da3f62791f7c5fa2c03517b7170a8e76613cf7fd83c92
+ languageName: node
+ linkType: hard
+
"@eslint/object-schema@npm:^2.1.6":
version: 2.1.6
resolution: "@eslint/object-schema@npm:2.1.6"
@@ -2246,6 +2718,16 @@ __metadata:
languageName: node
linkType: hard
+"@jridgewell/gen-mapping@npm:^0.3.12":
+ version: 0.3.13
+ resolution: "@jridgewell/gen-mapping@npm:0.3.13"
+ dependencies:
+ "@jridgewell/sourcemap-codec": ^1.5.0
+ "@jridgewell/trace-mapping": ^0.3.24
+ checksum: f2105acefc433337145caa3c84bba286de954f61c0bc46279bbd85a9e6a02871089717fa060413cfb6a9d44189fe8313b2d1cabf3a2eb3284d208fd5f75c54ff
+ languageName: node
+ linkType: hard
+
"@jridgewell/gen-mapping@npm:^0.3.5":
version: 0.3.8
resolution: "@jridgewell/gen-mapping@npm:0.3.8"
@@ -2257,6 +2739,16 @@ __metadata:
languageName: node
linkType: hard
+"@jridgewell/remapping@npm:^2.3.5":
+ version: 2.3.5
+ resolution: "@jridgewell/remapping@npm:2.3.5"
+ dependencies:
+ "@jridgewell/gen-mapping": ^0.3.5
+ "@jridgewell/trace-mapping": ^0.3.24
+ checksum: 4a66a7397c3dc9c6b5c14a0024b1f98c5e1d90a0dbc1e5955b5038f2db339904df2a0ee8a66559fafb4fc23ff33700a2639fd40bbdd2e9e82b58b3bdf83738e3
+ languageName: node
+ linkType: hard
+
"@jridgewell/resolve-uri@npm:^3.1.0":
version: 3.1.2
resolution: "@jridgewell/resolve-uri@npm:3.1.2"
@@ -2288,6 +2780,13 @@ __metadata:
languageName: node
linkType: hard
+"@jridgewell/sourcemap-codec@npm:^1.5.0":
+ version: 1.5.5
+ resolution: "@jridgewell/sourcemap-codec@npm:1.5.5"
+ checksum: c2e36e67971f719a8a3a85ef5a5f580622437cc723c35d03ebd0c9c0b06418700ef006f58af742791f71f6a4fc68fcfaf1f6a74ec2f9a3332860e9373459dae7
+ languageName: node
+ linkType: hard
+
"@jridgewell/trace-mapping@npm:^0.3.12, @jridgewell/trace-mapping@npm:^0.3.18, @jridgewell/trace-mapping@npm:^0.3.24, @jridgewell/trace-mapping@npm:^0.3.25":
version: 0.3.25
resolution: "@jridgewell/trace-mapping@npm:0.3.25"
@@ -2298,6 +2797,16 @@ __metadata:
languageName: node
linkType: hard
+"@jridgewell/trace-mapping@npm:^0.3.28":
+ version: 0.3.31
+ resolution: "@jridgewell/trace-mapping@npm:0.3.31"
+ dependencies:
+ "@jridgewell/resolve-uri": ^3.1.0
+ "@jridgewell/sourcemap-codec": ^1.4.14
+ checksum: af8fda2431348ad507fbddf8e25f5d08c79ecc94594061ce402cf41bc5aba1a7b3e59bf0fd70a619b35f33983a3f488ceeba8faf56bff784f98bb5394a8b7d47
+ languageName: node
+ linkType: hard
+
"@nicolo-ribaudo/eslint-scope-5-internals@npm:5.1.1-v1":
version: 5.1.1-v1
resolution: "@nicolo-ribaudo/eslint-scope-5-internals@npm:5.1.1-v1"
@@ -3072,6 +3581,167 @@ __metadata:
languageName: node
linkType: hard
+"@rolldown/pluginutils@npm:1.0.0-beta.53":
+ version: 1.0.0-beta.53
+ resolution: "@rolldown/pluginutils@npm:1.0.0-beta.53"
+ checksum: ef4dbf6061620f5749879b09a990007ac4da32b92b830c46b8c3240675c7ea6e4cce80a2d0b5e23141eef055444f66cbe51382b7bd169aa63fcae5d07f8f9451
+ languageName: node
+ linkType: hard
+
+"@rollup/rollup-android-arm-eabi@npm:4.53.3":
+ version: 4.53.3
+ resolution: "@rollup/rollup-android-arm-eabi@npm:4.53.3"
+ conditions: os=android & cpu=arm
+ languageName: node
+ linkType: hard
+
+"@rollup/rollup-android-arm64@npm:4.53.3":
+ version: 4.53.3
+ resolution: "@rollup/rollup-android-arm64@npm:4.53.3"
+ conditions: os=android & cpu=arm64
+ languageName: node
+ linkType: hard
+
+"@rollup/rollup-darwin-arm64@npm:4.53.3":
+ version: 4.53.3
+ resolution: "@rollup/rollup-darwin-arm64@npm:4.53.3"
+ conditions: os=darwin & cpu=arm64
+ languageName: node
+ linkType: hard
+
+"@rollup/rollup-darwin-x64@npm:4.53.3":
+ version: 4.53.3
+ resolution: "@rollup/rollup-darwin-x64@npm:4.53.3"
+ conditions: os=darwin & cpu=x64
+ languageName: node
+ linkType: hard
+
+"@rollup/rollup-freebsd-arm64@npm:4.53.3":
+ version: 4.53.3
+ resolution: "@rollup/rollup-freebsd-arm64@npm:4.53.3"
+ conditions: os=freebsd & cpu=arm64
+ languageName: node
+ linkType: hard
+
+"@rollup/rollup-freebsd-x64@npm:4.53.3":
+ version: 4.53.3
+ resolution: "@rollup/rollup-freebsd-x64@npm:4.53.3"
+ conditions: os=freebsd & cpu=x64
+ languageName: node
+ linkType: hard
+
+"@rollup/rollup-linux-arm-gnueabihf@npm:4.53.3":
+ version: 4.53.3
+ resolution: "@rollup/rollup-linux-arm-gnueabihf@npm:4.53.3"
+ conditions: os=linux & cpu=arm & libc=glibc
+ languageName: node
+ linkType: hard
+
+"@rollup/rollup-linux-arm-musleabihf@npm:4.53.3":
+ version: 4.53.3
+ resolution: "@rollup/rollup-linux-arm-musleabihf@npm:4.53.3"
+ conditions: os=linux & cpu=arm & libc=musl
+ languageName: node
+ linkType: hard
+
+"@rollup/rollup-linux-arm64-gnu@npm:4.53.3":
+ version: 4.53.3
+ resolution: "@rollup/rollup-linux-arm64-gnu@npm:4.53.3"
+ conditions: os=linux & cpu=arm64 & libc=glibc
+ languageName: node
+ linkType: hard
+
+"@rollup/rollup-linux-arm64-musl@npm:4.53.3":
+ version: 4.53.3
+ resolution: "@rollup/rollup-linux-arm64-musl@npm:4.53.3"
+ conditions: os=linux & cpu=arm64 & libc=musl
+ languageName: node
+ linkType: hard
+
+"@rollup/rollup-linux-loong64-gnu@npm:4.53.3":
+ version: 4.53.3
+ resolution: "@rollup/rollup-linux-loong64-gnu@npm:4.53.3"
+ conditions: os=linux & cpu=loong64 & libc=glibc
+ languageName: node
+ linkType: hard
+
+"@rollup/rollup-linux-ppc64-gnu@npm:4.53.3":
+ version: 4.53.3
+ resolution: "@rollup/rollup-linux-ppc64-gnu@npm:4.53.3"
+ conditions: os=linux & cpu=ppc64 & libc=glibc
+ languageName: node
+ linkType: hard
+
+"@rollup/rollup-linux-riscv64-gnu@npm:4.53.3":
+ version: 4.53.3
+ resolution: "@rollup/rollup-linux-riscv64-gnu@npm:4.53.3"
+ conditions: os=linux & cpu=riscv64 & libc=glibc
+ languageName: node
+ linkType: hard
+
+"@rollup/rollup-linux-riscv64-musl@npm:4.53.3":
+ version: 4.53.3
+ resolution: "@rollup/rollup-linux-riscv64-musl@npm:4.53.3"
+ conditions: os=linux & cpu=riscv64 & libc=musl
+ languageName: node
+ linkType: hard
+
+"@rollup/rollup-linux-s390x-gnu@npm:4.53.3":
+ version: 4.53.3
+ resolution: "@rollup/rollup-linux-s390x-gnu@npm:4.53.3"
+ conditions: os=linux & cpu=s390x & libc=glibc
+ languageName: node
+ linkType: hard
+
+"@rollup/rollup-linux-x64-gnu@npm:4.53.3":
+ version: 4.53.3
+ resolution: "@rollup/rollup-linux-x64-gnu@npm:4.53.3"
+ conditions: os=linux & cpu=x64 & libc=glibc
+ languageName: node
+ linkType: hard
+
+"@rollup/rollup-linux-x64-musl@npm:4.53.3":
+ version: 4.53.3
+ resolution: "@rollup/rollup-linux-x64-musl@npm:4.53.3"
+ conditions: os=linux & cpu=x64 & libc=musl
+ languageName: node
+ linkType: hard
+
+"@rollup/rollup-openharmony-arm64@npm:4.53.3":
+ version: 4.53.3
+ resolution: "@rollup/rollup-openharmony-arm64@npm:4.53.3"
+ conditions: os=openharmony & cpu=arm64
+ languageName: node
+ linkType: hard
+
+"@rollup/rollup-win32-arm64-msvc@npm:4.53.3":
+ version: 4.53.3
+ resolution: "@rollup/rollup-win32-arm64-msvc@npm:4.53.3"
+ conditions: os=win32 & cpu=arm64
+ languageName: node
+ linkType: hard
+
+"@rollup/rollup-win32-ia32-msvc@npm:4.53.3":
+ version: 4.53.3
+ resolution: "@rollup/rollup-win32-ia32-msvc@npm:4.53.3"
+ conditions: os=win32 & cpu=ia32
+ languageName: node
+ linkType: hard
+
+"@rollup/rollup-win32-x64-gnu@npm:4.53.3":
+ version: 4.53.3
+ resolution: "@rollup/rollup-win32-x64-gnu@npm:4.53.3"
+ conditions: os=win32 & cpu=x64
+ languageName: node
+ linkType: hard
+
+"@rollup/rollup-win32-x64-msvc@npm:4.53.3":
+ version: 4.53.3
+ resolution: "@rollup/rollup-win32-x64-msvc@npm:4.53.3"
+ conditions: os=win32 & cpu=x64
+ languageName: node
+ linkType: hard
+
"@sideway/address@npm:^4.1.5":
version: 4.1.5
resolution: "@sideway/address@npm:4.1.5"
@@ -3134,7 +3804,7 @@ __metadata:
languageName: node
linkType: hard
-"@types/babel__core@npm:^7.1.14":
+"@types/babel__core@npm:^7.1.14, @types/babel__core@npm:^7.20.5":
version: 7.20.5
resolution: "@types/babel__core@npm:7.20.5"
dependencies:
@@ -3184,6 +3854,13 @@ __metadata:
languageName: node
linkType: hard
+"@types/estree@npm:1.0.8":
+ version: 1.0.8
+ resolution: "@types/estree@npm:1.0.8"
+ checksum: bd93e2e415b6f182ec4da1074e1f36c480f1d26add3e696d54fb30c09bc470897e41361c8fd957bf0985024f8fbf1e6e2aff977d79352ef7eb93a5c6dcff6c11
+ languageName: node
+ linkType: hard
+
"@types/estree@npm:^1.0.6":
version: 1.0.7
resolution: "@types/estree@npm:1.0.7"
@@ -3258,6 +3935,15 @@ __metadata:
languageName: node
linkType: hard
+"@types/node@npm:^24.10.1":
+ version: 24.10.4
+ resolution: "@types/node@npm:24.10.4"
+ dependencies:
+ undici-types: ~7.16.0
+ checksum: 27db63085116aec2b92a36405ab4e8838eafd361ab05ba043e16b70e58b41572145b8078244aa5fd51b1f80076b2e7422c848c31c5a0df0dc5e20053e24720d3
+ languageName: node
+ linkType: hard
+
"@types/normalize-package-data@npm:^2.4.0, @types/normalize-package-data@npm:^2.4.3":
version: 2.4.4
resolution: "@types/normalize-package-data@npm:2.4.4"
@@ -3265,6 +3951,15 @@ __metadata:
languageName: node
linkType: hard
+"@types/react-dom@npm:^19.2.3":
+ version: 19.2.3
+ resolution: "@types/react-dom@npm:19.2.3"
+ peerDependencies:
+ "@types/react": ^19.2.0
+ checksum: b9c548f7378979cd8384444ae6c96f7a933b98e341c271c33e74231f27bf3082f04ad7c2927f1b1e6d8af35ccf83e549fce4978ebe0a02ded5a8803aa5f80e06
+ languageName: node
+ linkType: hard
+
"@types/react@npm:^19.1.0":
version: 19.1.11
resolution: "@types/react@npm:19.1.11"
@@ -3313,6 +4008,26 @@ __metadata:
languageName: node
linkType: hard
+"@typescript-eslint/eslint-plugin@npm:8.49.0":
+ version: 8.49.0
+ resolution: "@typescript-eslint/eslint-plugin@npm:8.49.0"
+ dependencies:
+ "@eslint-community/regexpp": ^4.10.0
+ "@typescript-eslint/scope-manager": 8.49.0
+ "@typescript-eslint/type-utils": 8.49.0
+ "@typescript-eslint/utils": 8.49.0
+ "@typescript-eslint/visitor-keys": 8.49.0
+ ignore: ^7.0.0
+ natural-compare: ^1.4.0
+ ts-api-utils: ^2.1.0
+ peerDependencies:
+ "@typescript-eslint/parser": ^8.49.0
+ eslint: ^8.57.0 || ^9.0.0
+ typescript: ">=4.8.4 <6.0.0"
+ checksum: 0bae18dda8e8c86d8da311c382642e4e321e708ca7bad1ae86e43981b1679e99e7d9bd4e32d4874e8016cbe2e39f5a255a71f16cc2c64ec3471b23161e51afec
+ languageName: node
+ linkType: hard
+
"@typescript-eslint/eslint-plugin@npm:^7.1.1":
version: 7.18.0
resolution: "@typescript-eslint/eslint-plugin@npm:7.18.0"
@@ -3336,6 +4051,22 @@ __metadata:
languageName: node
linkType: hard
+"@typescript-eslint/parser@npm:8.49.0":
+ version: 8.49.0
+ resolution: "@typescript-eslint/parser@npm:8.49.0"
+ dependencies:
+ "@typescript-eslint/scope-manager": 8.49.0
+ "@typescript-eslint/types": 8.49.0
+ "@typescript-eslint/typescript-estree": 8.49.0
+ "@typescript-eslint/visitor-keys": 8.49.0
+ debug: ^4.3.4
+ peerDependencies:
+ eslint: ^8.57.0 || ^9.0.0
+ typescript: ">=4.8.4 <6.0.0"
+ checksum: 27a157372fec09d72b9d3b266ca18cc6d4db040df6d507c5c9d30f97375e0be373d5fde9d02bcd997e40f21738edcc7a2e51d5a56e3cdd600147637bc96d920b
+ languageName: node
+ linkType: hard
+
"@typescript-eslint/parser@npm:^7.1.1":
version: 7.18.0
resolution: "@typescript-eslint/parser@npm:7.18.0"
@@ -3354,6 +4085,19 @@ __metadata:
languageName: node
linkType: hard
+"@typescript-eslint/project-service@npm:8.49.0":
+ version: 8.49.0
+ resolution: "@typescript-eslint/project-service@npm:8.49.0"
+ dependencies:
+ "@typescript-eslint/tsconfig-utils": ^8.49.0
+ "@typescript-eslint/types": ^8.49.0
+ debug: ^4.3.4
+ peerDependencies:
+ typescript: ">=4.8.4 <6.0.0"
+ checksum: 378cd7e6982820aa0bb1dfe78a8cf133dc8192ad68b4e2a3ed1615a1a1b4542a1a20da08de6f5dee2a5804192aeceabe06e6c16a0453a8aaa43e495527e6af6a
+ languageName: node
+ linkType: hard
+
"@typescript-eslint/scope-manager@npm:5.62.0":
version: 5.62.0
resolution: "@typescript-eslint/scope-manager@npm:5.62.0"
@@ -3368,9 +4112,28 @@ __metadata:
version: 7.18.0
resolution: "@typescript-eslint/scope-manager@npm:7.18.0"
dependencies:
- "@typescript-eslint/types": 7.18.0
- "@typescript-eslint/visitor-keys": 7.18.0
- checksum: b982c6ac13d8c86bb3b949c6b4e465f3f60557c2ccf4cc229799827d462df56b9e4d3eaed7711d79b875422fc3d71ec1ebcb5195db72134d07c619e3c5506b57
+ "@typescript-eslint/types": 7.18.0
+ "@typescript-eslint/visitor-keys": 7.18.0
+ checksum: b982c6ac13d8c86bb3b949c6b4e465f3f60557c2ccf4cc229799827d462df56b9e4d3eaed7711d79b875422fc3d71ec1ebcb5195db72134d07c619e3c5506b57
+ languageName: node
+ linkType: hard
+
+"@typescript-eslint/scope-manager@npm:8.49.0, @typescript-eslint/scope-manager@npm:^8.49.0":
+ version: 8.49.0
+ resolution: "@typescript-eslint/scope-manager@npm:8.49.0"
+ dependencies:
+ "@typescript-eslint/types": 8.49.0
+ "@typescript-eslint/visitor-keys": 8.49.0
+ checksum: 85aae146729547df03a2ffdb4e447a10023e7c71b426a2a5d7eb3b2a82ec1bbd8ba214d619363994c500a4cf742fbb3f3743723aa13784649e0b9e909ab4529f
+ languageName: node
+ linkType: hard
+
+"@typescript-eslint/tsconfig-utils@npm:8.49.0, @typescript-eslint/tsconfig-utils@npm:^8.49.0":
+ version: 8.49.0
+ resolution: "@typescript-eslint/tsconfig-utils@npm:8.49.0"
+ peerDependencies:
+ typescript: ">=4.8.4 <6.0.0"
+ checksum: be26283df8cf05a3a8d17596ac52e51ec27017f27ec5588e2fa3b804c31758864732a24e1ab777ac3e3567dda9b55de5b18d318b6a6e56025baa4f117f371804
languageName: node
linkType: hard
@@ -3391,6 +4154,22 @@ __metadata:
languageName: node
linkType: hard
+"@typescript-eslint/type-utils@npm:8.49.0, @typescript-eslint/type-utils@npm:^8.0.0, @typescript-eslint/type-utils@npm:^8.49.0":
+ version: 8.49.0
+ resolution: "@typescript-eslint/type-utils@npm:8.49.0"
+ dependencies:
+ "@typescript-eslint/types": 8.49.0
+ "@typescript-eslint/typescript-estree": 8.49.0
+ "@typescript-eslint/utils": 8.49.0
+ debug: ^4.3.4
+ ts-api-utils: ^2.1.0
+ peerDependencies:
+ eslint: ^8.57.0 || ^9.0.0
+ typescript: ">=4.8.4 <6.0.0"
+ checksum: ce5795464be57b0a1cf5970103547a148e8971fe7cf1aafb9a62b40251c670fd1b03535edfc4622c520112705cd6ee5efd88124a7432d2fbbcfc5be54fbf131f
+ languageName: node
+ linkType: hard
+
"@typescript-eslint/types@npm:5.62.0":
version: 5.62.0
resolution: "@typescript-eslint/types@npm:5.62.0"
@@ -3405,6 +4184,13 @@ __metadata:
languageName: node
linkType: hard
+"@typescript-eslint/types@npm:8.49.0, @typescript-eslint/types@npm:^8.49.0":
+ version: 8.49.0
+ resolution: "@typescript-eslint/types@npm:8.49.0"
+ checksum: e604e27f9ff7dd4c7ae0060db5f506338b64cc302563841e729f4da7730a1e94176db8ae1f1c4c0c0c8df5086f127408dc050f27595a36d412f60ed0e09f5a64
+ languageName: node
+ linkType: hard
+
"@typescript-eslint/typescript-estree@npm:5.62.0":
version: 5.62.0
resolution: "@typescript-eslint/typescript-estree@npm:5.62.0"
@@ -3442,6 +4228,25 @@ __metadata:
languageName: node
linkType: hard
+"@typescript-eslint/typescript-estree@npm:8.49.0, @typescript-eslint/typescript-estree@npm:^8.49.0":
+ version: 8.49.0
+ resolution: "@typescript-eslint/typescript-estree@npm:8.49.0"
+ dependencies:
+ "@typescript-eslint/project-service": 8.49.0
+ "@typescript-eslint/tsconfig-utils": 8.49.0
+ "@typescript-eslint/types": 8.49.0
+ "@typescript-eslint/visitor-keys": 8.49.0
+ debug: ^4.3.4
+ minimatch: ^9.0.4
+ semver: ^7.6.0
+ tinyglobby: ^0.2.15
+ ts-api-utils: ^2.1.0
+ peerDependencies:
+ typescript: ">=4.8.4 <6.0.0"
+ checksum: a03545eefdf2487172602930fdd27c8810dc775bdfa4d9c3a45651c5f5465c5e1fc652f318c61ece7f4f35425231961434e96d4ffca84f10149fca111e1fc520
+ languageName: node
+ linkType: hard
+
"@typescript-eslint/utils@npm:7.18.0":
version: 7.18.0
resolution: "@typescript-eslint/utils@npm:7.18.0"
@@ -3456,6 +4261,21 @@ __metadata:
languageName: node
linkType: hard
+"@typescript-eslint/utils@npm:8.49.0, @typescript-eslint/utils@npm:^8.49.0":
+ version: 8.49.0
+ resolution: "@typescript-eslint/utils@npm:8.49.0"
+ dependencies:
+ "@eslint-community/eslint-utils": ^4.7.0
+ "@typescript-eslint/scope-manager": 8.49.0
+ "@typescript-eslint/types": 8.49.0
+ "@typescript-eslint/typescript-estree": 8.49.0
+ peerDependencies:
+ eslint: ^8.57.0 || ^9.0.0
+ typescript: ">=4.8.4 <6.0.0"
+ checksum: be1bdf2e4a8bb56bb0c39ba8b8a5f1fc187fb17a53af0ef4d50be95914027076dfac385b54d969fdaa2a42fa8a95f31d105457a3768875054a5507ebe6f6257a
+ languageName: node
+ linkType: hard
+
"@typescript-eslint/utils@npm:^5.10.0":
version: 5.62.0
resolution: "@typescript-eslint/utils@npm:5.62.0"
@@ -3494,6 +4314,32 @@ __metadata:
languageName: node
linkType: hard
+"@typescript-eslint/visitor-keys@npm:8.49.0":
+ version: 8.49.0
+ resolution: "@typescript-eslint/visitor-keys@npm:8.49.0"
+ dependencies:
+ "@typescript-eslint/types": 8.49.0
+ eslint-visitor-keys: ^4.2.1
+ checksum: 446d6345d9702bcdf8713a47561ea52657bbec1c8170b1559d9462e1d815b122adff35f1cc778ecb94f4459d51ac7aac7cafe9ec8d8319b2c7d7984a0edee6ba
+ languageName: node
+ linkType: hard
+
+"@vitejs/plugin-react@npm:^5.1.1":
+ version: 5.1.2
+ resolution: "@vitejs/plugin-react@npm:5.1.2"
+ dependencies:
+ "@babel/core": ^7.28.5
+ "@babel/plugin-transform-react-jsx-self": ^7.27.1
+ "@babel/plugin-transform-react-jsx-source": ^7.27.1
+ "@rolldown/pluginutils": 1.0.0-beta.53
+ "@types/babel__core": ^7.20.5
+ react-refresh: ^0.18.0
+ peerDependencies:
+ vite: ^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0
+ checksum: 57f4b54d60c30943befe5e2e2a67e9601611a1ae38fc886aeedc18f6fbab008c9afc2f8adf62d1e59b22946de73e2352d0f741a5e5c82c2f4db8998d5c9b8259
+ languageName: node
+ linkType: hard
+
"@vscode/sudo-prompt@npm:^9.0.0":
version: 9.3.1
resolution: "@vscode/sudo-prompt@npm:9.3.1"
@@ -4122,6 +4968,13 @@ __metadata:
languageName: node
linkType: hard
+"birecord@npm:^0.1.1":
+ version: 0.1.1
+ resolution: "birecord@npm:0.1.1"
+ checksum: 08a77636913171d274abd3c68d0a0d8352964c912cbc92b609151e2e097bb696e16289f6b7f5566921287892bbc5bcdae33b3a342438961792203d0d4ff73037
+ languageName: node
+ linkType: hard
+
"bl@npm:^4.1.0":
version: 4.1.0
resolution: "bl@npm:4.1.0"
@@ -4673,6 +5526,13 @@ __metadata:
languageName: node
linkType: hard
+"compare-versions@npm:^6.1.1":
+ version: 6.1.1
+ resolution: "compare-versions@npm:6.1.1"
+ checksum: 73fe6c4f52d22efe28f0a3be10df2afd704e10b3593360cd963e86b33a7a263c263b41a1361b69c30a0fe68bfa70fef90860c1cf2ef41502629d4402890fcd57
+ languageName: node
+ linkType: hard
+
"compressible@npm:~2.0.18":
version: 2.0.18
resolution: "compressible@npm:2.0.18"
@@ -5665,6 +6525,95 @@ __metadata:
languageName: node
linkType: hard
+"esbuild@npm:^0.25.0":
+ version: 0.25.12
+ resolution: "esbuild@npm:0.25.12"
+ dependencies:
+ "@esbuild/aix-ppc64": 0.25.12
+ "@esbuild/android-arm": 0.25.12
+ "@esbuild/android-arm64": 0.25.12
+ "@esbuild/android-x64": 0.25.12
+ "@esbuild/darwin-arm64": 0.25.12
+ "@esbuild/darwin-x64": 0.25.12
+ "@esbuild/freebsd-arm64": 0.25.12
+ "@esbuild/freebsd-x64": 0.25.12
+ "@esbuild/linux-arm": 0.25.12
+ "@esbuild/linux-arm64": 0.25.12
+ "@esbuild/linux-ia32": 0.25.12
+ "@esbuild/linux-loong64": 0.25.12
+ "@esbuild/linux-mips64el": 0.25.12
+ "@esbuild/linux-ppc64": 0.25.12
+ "@esbuild/linux-riscv64": 0.25.12
+ "@esbuild/linux-s390x": 0.25.12
+ "@esbuild/linux-x64": 0.25.12
+ "@esbuild/netbsd-arm64": 0.25.12
+ "@esbuild/netbsd-x64": 0.25.12
+ "@esbuild/openbsd-arm64": 0.25.12
+ "@esbuild/openbsd-x64": 0.25.12
+ "@esbuild/openharmony-arm64": 0.25.12
+ "@esbuild/sunos-x64": 0.25.12
+ "@esbuild/win32-arm64": 0.25.12
+ "@esbuild/win32-ia32": 0.25.12
+ "@esbuild/win32-x64": 0.25.12
+ dependenciesMeta:
+ "@esbuild/aix-ppc64":
+ optional: true
+ "@esbuild/android-arm":
+ optional: true
+ "@esbuild/android-arm64":
+ optional: true
+ "@esbuild/android-x64":
+ optional: true
+ "@esbuild/darwin-arm64":
+ optional: true
+ "@esbuild/darwin-x64":
+ optional: true
+ "@esbuild/freebsd-arm64":
+ optional: true
+ "@esbuild/freebsd-x64":
+ optional: true
+ "@esbuild/linux-arm":
+ optional: true
+ "@esbuild/linux-arm64":
+ optional: true
+ "@esbuild/linux-ia32":
+ optional: true
+ "@esbuild/linux-loong64":
+ optional: true
+ "@esbuild/linux-mips64el":
+ optional: true
+ "@esbuild/linux-ppc64":
+ optional: true
+ "@esbuild/linux-riscv64":
+ optional: true
+ "@esbuild/linux-s390x":
+ optional: true
+ "@esbuild/linux-x64":
+ optional: true
+ "@esbuild/netbsd-arm64":
+ optional: true
+ "@esbuild/netbsd-x64":
+ optional: true
+ "@esbuild/openbsd-arm64":
+ optional: true
+ "@esbuild/openbsd-x64":
+ optional: true
+ "@esbuild/openharmony-arm64":
+ optional: true
+ "@esbuild/sunos-x64":
+ optional: true
+ "@esbuild/win32-arm64":
+ optional: true
+ "@esbuild/win32-ia32":
+ optional: true
+ "@esbuild/win32-x64":
+ optional: true
+ bin:
+ esbuild: bin/esbuild
+ checksum: 3d1dc181338e2c44f4374508e9d0da3e7ae90f65d7f3f5d8076ff401a1726c5c9ecc86cfc825249349f1652e12d5ae13f02bcaa4d9487c88c7a11167f52ba353
+ languageName: node
+ linkType: hard
+
"escalade@npm:^3.1.1, escalade@npm:^3.2.0":
version: 3.2.0
resolution: "escalade@npm:3.2.0"
@@ -5817,6 +6766,28 @@ __metadata:
languageName: node
linkType: hard
+"eslint-plugin-react-dom@npm:^2.3.13":
+ version: 2.3.13
+ resolution: "eslint-plugin-react-dom@npm:2.3.13"
+ dependencies:
+ "@eslint-react/ast": 2.3.13
+ "@eslint-react/core": 2.3.13
+ "@eslint-react/eff": 2.3.13
+ "@eslint-react/shared": 2.3.13
+ "@eslint-react/var": 2.3.13
+ "@typescript-eslint/scope-manager": ^8.49.0
+ "@typescript-eslint/types": ^8.49.0
+ "@typescript-eslint/utils": ^8.49.0
+ compare-versions: ^6.1.1
+ string-ts: ^2.3.1
+ ts-pattern: ^5.9.0
+ peerDependencies:
+ eslint: ^8.57.0 || ^9.0.0
+ typescript: ">=4.8.4 <6.0.0"
+ checksum: ddd11e33d11c9ff9d6aa5437fe7798d22dca2359997d975fcbb3ca83e1113bae4bc7fb0e43bbbf338a576160d8fb2a900d4b8b818521c21c1c06e2523300ae3c
+ languageName: node
+ linkType: hard
+
"eslint-plugin-react-hooks@npm:^5.2.0":
version: 5.2.0
resolution: "eslint-plugin-react-hooks@npm:5.2.0"
@@ -5826,6 +6797,21 @@ __metadata:
languageName: node
linkType: hard
+"eslint-plugin-react-hooks@npm:^7.0.1":
+ version: 7.0.1
+ resolution: "eslint-plugin-react-hooks@npm:7.0.1"
+ dependencies:
+ "@babel/core": ^7.24.4
+ "@babel/parser": ^7.24.4
+ hermes-parser: ^0.25.1
+ zod: ^3.25.0 || ^4.0.0
+ zod-validation-error: ^3.5.0 || ^4.0.0
+ peerDependencies:
+ eslint: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0
+ checksum: d2216919137e6593309640c47d5cbeb903a2989b2ddc1197107b4b1967a8ec2e696d9586015c02cfa2468bdb4ce28b6866f9fd2b555ccbec635556f0a4e1f434
+ languageName: node
+ linkType: hard
+
"eslint-plugin-react-native-globals@npm:^0.1.1":
version: 0.1.2
resolution: "eslint-plugin-react-native-globals@npm:0.1.2"
@@ -5844,6 +6830,40 @@ __metadata:
languageName: node
linkType: hard
+"eslint-plugin-react-refresh@npm:^0.4.24":
+ version: 0.4.25
+ resolution: "eslint-plugin-react-refresh@npm:0.4.25"
+ peerDependencies:
+ eslint: ">=8.40"
+ checksum: 173175819b6e8b1f2cc6ac87084f5f1e99b3f57999fb5a3a91f176af669f3fec38dd17bfd6ddc5bbc529c3fece0802bbfa51995ff3f84d430fef5ad36c91b1ce
+ languageName: node
+ linkType: hard
+
+"eslint-plugin-react-x@npm:^2.3.13":
+ version: 2.3.13
+ resolution: "eslint-plugin-react-x@npm:2.3.13"
+ dependencies:
+ "@eslint-react/ast": 2.3.13
+ "@eslint-react/core": 2.3.13
+ "@eslint-react/eff": 2.3.13
+ "@eslint-react/shared": 2.3.13
+ "@eslint-react/var": 2.3.13
+ "@typescript-eslint/scope-manager": ^8.49.0
+ "@typescript-eslint/type-utils": ^8.49.0
+ "@typescript-eslint/types": ^8.49.0
+ "@typescript-eslint/utils": ^8.49.0
+ compare-versions: ^6.1.1
+ is-immutable-type: ^5.0.1
+ string-ts: ^2.3.1
+ ts-api-utils: ^2.1.0
+ ts-pattern: ^5.9.0
+ peerDependencies:
+ eslint: ^8.57.0 || ^9.0.0
+ typescript: ">=4.8.4 <6.0.0"
+ checksum: ef0319bc78cdac2c710e5535e11567cbe98eb26b31ca9d07806f6190e306842d90f3ea13cba140f5bec731d712da7d5e17881769aee900d7a8dc8d57391e4a52
+ languageName: node
+ linkType: hard
+
"eslint-plugin-react@npm:^7.30.1":
version: 7.37.5
resolution: "eslint-plugin-react@npm:7.37.5"
@@ -5913,6 +6933,13 @@ __metadata:
languageName: node
linkType: hard
+"eslint-visitor-keys@npm:^4.2.1":
+ version: 4.2.1
+ resolution: "eslint-visitor-keys@npm:4.2.1"
+ checksum: 3a77e3f99a49109f6fb2c5b7784bc78f9743b834d238cdba4d66c602c6b52f19ed7bcd0a5c5dbbeae3a8689fd785e76c001799f53d2228b278282cf9f699fff5
+ languageName: node
+ linkType: hard
+
"eslint@npm:^9.22.0":
version: 9.24.0
resolution: "eslint@npm:9.24.0"
@@ -6224,6 +7251,18 @@ __metadata:
languageName: node
linkType: hard
+"fdir@npm:^6.5.0":
+ version: 6.5.0
+ resolution: "fdir@npm:6.5.0"
+ peerDependencies:
+ picomatch: ^3 || ^4
+ peerDependenciesMeta:
+ picomatch:
+ optional: true
+ checksum: bd537daa9d3cd53887eed35efa0eab2dbb1ca408790e10e024120e7a36c6e9ae2b33710cb8381e35def01bc9c1d7eaba746f886338413e68ff6ebaee07b9a6e8
+ languageName: node
+ linkType: hard
+
"file-entry-cache@npm:^8.0.0":
version: 8.0.0
resolution: "file-entry-cache@npm:8.0.0"
@@ -6401,7 +7440,7 @@ __metadata:
languageName: node
linkType: hard
-"fsevents@npm:^2.3.2":
+"fsevents@npm:^2.3.2, fsevents@npm:~2.3.2, fsevents@npm:~2.3.3":
version: 2.3.3
resolution: "fsevents@npm:2.3.3"
dependencies:
@@ -6411,7 +7450,7 @@ __metadata:
languageName: node
linkType: hard
-"fsevents@patch:fsevents@^2.3.2#~builtin":
+"fsevents@patch:fsevents@^2.3.2#~builtin, fsevents@patch:fsevents@~2.3.2#~builtin, fsevents@patch:fsevents@~2.3.3#~builtin":
version: 2.3.3
resolution: "fsevents@patch:fsevents@npm%3A2.3.3#~builtin::version=2.3.3&hash=df0bf1"
dependencies:
@@ -6701,6 +7740,13 @@ __metadata:
languageName: node
linkType: hard
+"globals@npm:^16.5.0":
+ version: 16.5.0
+ resolution: "globals@npm:16.5.0"
+ checksum: e0363245cfc6e36ac6bf940415160a05d66e7985fa3856d5383ad49292b6d249d80fd03759e09d6491109648a121849b23b77c7391a11862923e6995268a7cd6
+ languageName: node
+ linkType: hard
+
"globalthis@npm:^1.0.4":
version: 1.0.4
resolution: "globalthis@npm:1.0.4"
@@ -6876,6 +7922,13 @@ __metadata:
languageName: node
linkType: hard
+"hermes-estree@npm:0.25.1":
+ version: 0.25.1
+ resolution: "hermes-estree@npm:0.25.1"
+ checksum: 97f42e9178dff61db017810b4f79f5a2cdbb3cde94b7d99ba84ed632ee2adfcae2244555587951b3151fc036676c68f48f57fbe2b49e253eb1f3f904d284a8b0
+ languageName: node
+ linkType: hard
+
"hermes-estree@npm:0.28.1":
version: 0.28.1
resolution: "hermes-estree@npm:0.28.1"
@@ -6933,6 +7986,15 @@ __metadata:
languageName: node
linkType: hard
+"hermes-parser@npm:^0.25.1":
+ version: 0.25.1
+ resolution: "hermes-parser@npm:0.25.1"
+ dependencies:
+ hermes-estree: 0.25.1
+ checksum: 4edcfaa3030931343b540182b83c432aba4cdcb1925952521ab4cfb7ab90c2c1543dfcb042ccd51d5e81e4bfe2809420e85902c2ff95ef7c6c64644ce17138ea
+ languageName: node
+ linkType: hard
+
"hosted-git-info@npm:^4.0.1":
version: 4.1.0
resolution: "hosted-git-info@npm:4.1.0"
@@ -7051,6 +8113,13 @@ __metadata:
languageName: node
linkType: hard
+"ignore@npm:^7.0.0":
+ version: 7.0.5
+ resolution: "ignore@npm:7.0.5"
+ checksum: d0862bf64d3d58bf34d5fb0a9f725bec9ca5ce8cd1aecc8f28034269e8f69b8009ffd79ca3eda96962a6a444687781cd5efdb8c7c8ddc0a6996e36d31c217f14
+ languageName: node
+ linkType: hard
+
"image-size@npm:^1.0.2":
version: 1.2.1
resolution: "image-size@npm:1.2.1"
@@ -7417,6 +8486,20 @@ __metadata:
languageName: node
linkType: hard
+"is-immutable-type@npm:^5.0.1":
+ version: 5.0.1
+ resolution: "is-immutable-type@npm:5.0.1"
+ dependencies:
+ "@typescript-eslint/type-utils": ^8.0.0
+ ts-api-utils: ^2.0.0
+ ts-declaration-location: ^1.0.4
+ peerDependencies:
+ eslint: "*"
+ typescript: ">=4.7.4"
+ checksum: ff9c6fabdfcf159c2931360e5f9a1cc1ed5577c4b0dc16b3c6fca178edb1f7a4932b6bb53955ccaac790865b3d90401940d565e5eee32bd2f88f4f0af36b7863
+ languageName: node
+ linkType: hard
+
"is-in-ci@npm:^1.0.0":
version: 1.0.0
resolution: "is-in-ci@npm:1.0.0"
@@ -9858,6 +10941,15 @@ __metadata:
languageName: node
linkType: hard
+"nanoid@npm:^3.3.11":
+ version: 3.3.11
+ resolution: "nanoid@npm:3.3.11"
+ bin:
+ nanoid: bin/nanoid.cjs
+ checksum: 3be20d8866a57a6b6d218e82549711c8352ed969f9ab3c45379da28f405363ad4c9aeb0b39e9abc101a529ca65a72ff9502b00bf74a912c4b64a9d62dfd26c29
+ languageName: node
+ linkType: hard
+
"natural-compare@npm:^1.4.0":
version: 1.4.0
resolution: "natural-compare@npm:1.4.0"
@@ -10597,6 +11689,13 @@ __metadata:
languageName: node
linkType: hard
+"picomatch@npm:^4.0.3":
+ version: 4.0.3
+ resolution: "picomatch@npm:4.0.3"
+ checksum: 6817fb74eb745a71445debe1029768de55fd59a42b75606f478ee1d0dc1aa6e78b711d041a7c9d5550e042642029b7f373dc1a43b224c4b7f12d23436735dba0
+ languageName: node
+ linkType: hard
+
"pirates@npm:^4.0.4":
version: 4.0.7
resolution: "pirates@npm:4.0.7"
@@ -10629,6 +11728,17 @@ __metadata:
languageName: node
linkType: hard
+"postcss@npm:^8.5.6":
+ version: 8.5.6
+ resolution: "postcss@npm:8.5.6"
+ dependencies:
+ nanoid: ^3.3.11
+ picocolors: ^1.1.1
+ source-map-js: ^1.2.1
+ checksum: 20f3b5d673ffeec2b28d65436756d31ee33f65b0a8bedb3d32f556fbd5973be38c3a7fb5b959a5236c60a5db7b91b0a6b14ffaac0d717dce1b903b964ee1c1bb
+ languageName: node
+ linkType: hard
+
"prelude-ls@npm:^1.2.1":
version: 1.2.1
resolution: "prelude-ls@npm:1.2.1"
@@ -10864,6 +11974,17 @@ __metadata:
languageName: node
linkType: hard
+"react-dom@npm:^19.1.0":
+ version: 19.2.3
+ resolution: "react-dom@npm:19.2.3"
+ dependencies:
+ scheduler: ^0.27.0
+ peerDependencies:
+ react: ^19.2.3
+ checksum: cb1f95df052802f5332cae78303b7fc6f58092d5c7f8d01f0401188b2e0157c1d273a041b900fcc4801f730c70ed17249bd5af170038692878ebe257f641488b
+ languageName: node
+ linkType: hard
+
"react-is@npm:^16.13.1":
version: 16.13.1
resolution: "react-is@npm:16.13.1"
@@ -10963,6 +12084,29 @@ __metadata:
languageName: unknown
linkType: soft
+"react-native-enriched-web-example@workspace:apps/example-web":
+ version: 0.0.0-use.local
+ resolution: "react-native-enriched-web-example@workspace:apps/example-web"
+ dependencies:
+ "@eslint/js": ^9.39.1
+ "@types/node": ^24.10.1
+ "@types/react": ^19.1.0
+ "@types/react-dom": ^19.2.3
+ "@vitejs/plugin-react": ^5.1.1
+ eslint: ^9.22.0
+ eslint-plugin-react-dom: ^2.3.13
+ eslint-plugin-react-hooks: ^7.0.1
+ eslint-plugin-react-refresh: ^0.4.24
+ eslint-plugin-react-x: ^2.3.13
+ globals: ^16.5.0
+ react: ^19.1.0
+ react-dom: ^19.1.0
+ typescript: ^5.8.3
+ typescript-eslint: ^8.46.4
+ vite: ^7.2.4
+ languageName: unknown
+ linkType: soft
+
"react-native-enriched@workspace:.":
version: 0.0.0-use.local
resolution: "react-native-enriched@workspace:."
@@ -11125,6 +12269,13 @@ __metadata:
languageName: node
linkType: hard
+"react-refresh@npm:^0.18.0":
+ version: 0.18.0
+ resolution: "react-refresh@npm:0.18.0"
+ checksum: c27d236e7b38f4a09c2b0134e6227fa62e2b71edad5f22bab40962fc0deba9e0f16930609a82b6a021ef4b4f0a4d405cf0fbb2b51a0f478809619a8226f20379
+ languageName: node
+ linkType: hard
+
"react@npm:19.1.0":
version: 19.1.0
resolution: "react@npm:19.1.0"
@@ -11139,6 +12290,13 @@ __metadata:
languageName: node
linkType: hard
+"react@npm:^19.1.0":
+ version: 19.2.3
+ resolution: "react@npm:19.2.3"
+ checksum: 506e369ae13cb46b7f303c0201aadf856642f482cdf5b1c3730c3a6d1762fd5a3ae1dd31196a4686bfbbe56456dcd0c48a4656c75cbcb45620e3028c54789ae9
+ languageName: node
+ linkType: hard
+
"read-package-up@npm:^11.0.0":
version: 11.0.0
resolution: "read-package-up@npm:11.0.0"
@@ -11553,6 +12711,87 @@ __metadata:
languageName: node
linkType: hard
+"rollup@npm:^4.43.0":
+ version: 4.53.3
+ resolution: "rollup@npm:4.53.3"
+ dependencies:
+ "@rollup/rollup-android-arm-eabi": 4.53.3
+ "@rollup/rollup-android-arm64": 4.53.3
+ "@rollup/rollup-darwin-arm64": 4.53.3
+ "@rollup/rollup-darwin-x64": 4.53.3
+ "@rollup/rollup-freebsd-arm64": 4.53.3
+ "@rollup/rollup-freebsd-x64": 4.53.3
+ "@rollup/rollup-linux-arm-gnueabihf": 4.53.3
+ "@rollup/rollup-linux-arm-musleabihf": 4.53.3
+ "@rollup/rollup-linux-arm64-gnu": 4.53.3
+ "@rollup/rollup-linux-arm64-musl": 4.53.3
+ "@rollup/rollup-linux-loong64-gnu": 4.53.3
+ "@rollup/rollup-linux-ppc64-gnu": 4.53.3
+ "@rollup/rollup-linux-riscv64-gnu": 4.53.3
+ "@rollup/rollup-linux-riscv64-musl": 4.53.3
+ "@rollup/rollup-linux-s390x-gnu": 4.53.3
+ "@rollup/rollup-linux-x64-gnu": 4.53.3
+ "@rollup/rollup-linux-x64-musl": 4.53.3
+ "@rollup/rollup-openharmony-arm64": 4.53.3
+ "@rollup/rollup-win32-arm64-msvc": 4.53.3
+ "@rollup/rollup-win32-ia32-msvc": 4.53.3
+ "@rollup/rollup-win32-x64-gnu": 4.53.3
+ "@rollup/rollup-win32-x64-msvc": 4.53.3
+ "@types/estree": 1.0.8
+ fsevents: ~2.3.2
+ dependenciesMeta:
+ "@rollup/rollup-android-arm-eabi":
+ optional: true
+ "@rollup/rollup-android-arm64":
+ optional: true
+ "@rollup/rollup-darwin-arm64":
+ optional: true
+ "@rollup/rollup-darwin-x64":
+ optional: true
+ "@rollup/rollup-freebsd-arm64":
+ optional: true
+ "@rollup/rollup-freebsd-x64":
+ optional: true
+ "@rollup/rollup-linux-arm-gnueabihf":
+ optional: true
+ "@rollup/rollup-linux-arm-musleabihf":
+ optional: true
+ "@rollup/rollup-linux-arm64-gnu":
+ optional: true
+ "@rollup/rollup-linux-arm64-musl":
+ optional: true
+ "@rollup/rollup-linux-loong64-gnu":
+ optional: true
+ "@rollup/rollup-linux-ppc64-gnu":
+ optional: true
+ "@rollup/rollup-linux-riscv64-gnu":
+ optional: true
+ "@rollup/rollup-linux-riscv64-musl":
+ optional: true
+ "@rollup/rollup-linux-s390x-gnu":
+ optional: true
+ "@rollup/rollup-linux-x64-gnu":
+ optional: true
+ "@rollup/rollup-linux-x64-musl":
+ optional: true
+ "@rollup/rollup-openharmony-arm64":
+ optional: true
+ "@rollup/rollup-win32-arm64-msvc":
+ optional: true
+ "@rollup/rollup-win32-ia32-msvc":
+ optional: true
+ "@rollup/rollup-win32-x64-gnu":
+ optional: true
+ "@rollup/rollup-win32-x64-msvc":
+ optional: true
+ fsevents:
+ optional: true
+ bin:
+ rollup: dist/bin/rollup
+ checksum: 7c5ed8f30285c731e00007726c99c6ad1f07e398d09afad53c648f32017b22b9f5d60ac99c65d60ad5334e69ffeeaa835fff88d26f21c8f1237e3d936a664056
+ languageName: node
+ linkType: hard
+
"run-applescript@npm:^7.0.0":
version: 7.0.0
resolution: "run-applescript@npm:7.0.0"
@@ -11647,7 +12886,7 @@ __metadata:
languageName: node
linkType: hard
-"scheduler@npm:0.27.0":
+"scheduler@npm:0.27.0, scheduler@npm:^0.27.0":
version: 0.27.0
resolution: "scheduler@npm:0.27.0"
checksum: 92644ead0a9443e20f9d24132fe93675b156209b9eeb35ea245f8a86768d0cc0fcca56f341eeef21d9b6dd8e72d6d5e260eb5a41d34b05cd605dd45a29f572ef
@@ -11937,6 +13176,13 @@ __metadata:
languageName: node
linkType: hard
+"source-map-js@npm:^1.2.1":
+ version: 1.2.1
+ resolution: "source-map-js@npm:1.2.1"
+ checksum: 4eb0cd997cdf228bc253bcaff9340afeb706176e64868ecd20efbe6efea931465f43955612346d6b7318789e5265bdc419bc7669c1cebe3db0eb255f57efa76b
+ languageName: node
+ linkType: hard
+
"source-map-support@npm:0.5.13":
version: 0.5.13
resolution: "source-map-support@npm:0.5.13"
@@ -12098,6 +13344,13 @@ __metadata:
languageName: node
linkType: hard
+"string-ts@npm:^2.3.1":
+ version: 2.3.1
+ resolution: "string-ts@npm:2.3.1"
+ checksum: a8b653bb916c6ca56a958e6c73ddb9d54009ff252208e8a7f30fe8a77019a1e1c4bb25d58f75ad0964d4198986707378a59213e83465c019e87ae5322ba215b6
+ languageName: node
+ linkType: hard
+
"string-width-cjs@npm:string-width@^4.2.0, string-width@npm:^4.1.0, string-width@npm:^4.2.0, string-width@npm:^4.2.3":
version: 4.2.3
resolution: "string-width@npm:4.2.3"
@@ -12425,6 +13678,16 @@ __metadata:
languageName: node
linkType: hard
+"tinyglobby@npm:^0.2.15":
+ version: 0.2.15
+ resolution: "tinyglobby@npm:0.2.15"
+ dependencies:
+ fdir: ^6.5.0
+ picomatch: ^4.0.3
+ checksum: 0e33b8babff966c6ab86e9b825a350a6a98a63700fa0bb7ae6cf36a7770a508892383adc272f7f9d17aaf46a9d622b455e775b9949a3f951eaaf5dfb26331d44
+ languageName: node
+ linkType: hard
+
"tmp@npm:^0.0.33":
version: 0.0.33
resolution: "tmp@npm:0.0.33"
@@ -12473,6 +13736,33 @@ __metadata:
languageName: node
linkType: hard
+"ts-api-utils@npm:^2.0.0, ts-api-utils@npm:^2.1.0":
+ version: 2.1.0
+ resolution: "ts-api-utils@npm:2.1.0"
+ peerDependencies:
+ typescript: ">=4.8.4"
+ checksum: 5b1ef89105654d93d67582308bd8dfe4bbf6874fccbcaa729b08fbb00a940fd4c691ca6d0d2b18c3c70878d9a7e503421b7cc473dbc3d0d54258b86401d4b15d
+ languageName: node
+ linkType: hard
+
+"ts-declaration-location@npm:^1.0.4":
+ version: 1.0.7
+ resolution: "ts-declaration-location@npm:1.0.7"
+ dependencies:
+ picomatch: ^4.0.2
+ peerDependencies:
+ typescript: ">=4.0.0"
+ checksum: d1bfa610fae8175389af580f25e8aab5dd5c7fb8daf83560fa8d555da8ef03542dde8552a9c3d1fb4beaed8670db863083c61413846d91cb3e5caea6636e45f7
+ languageName: node
+ linkType: hard
+
+"ts-pattern@npm:^5.9.0":
+ version: 5.9.0
+ resolution: "ts-pattern@npm:5.9.0"
+ checksum: cc2bce3fb99cf20a1b6640b44a086b936c1b366ea59ed700069e9540d2b1b98a103deeb8777a7996f40e461b0bb5abfab613d8423635debf25a294d4cc7d153b
+ languageName: node
+ linkType: hard
+
"tslib@npm:^1.8.1":
version: 1.14.1
resolution: "tslib@npm:1.14.1"
@@ -12690,6 +13980,21 @@ __metadata:
languageName: node
linkType: hard
+"typescript-eslint@npm:^8.46.4":
+ version: 8.49.0
+ resolution: "typescript-eslint@npm:8.49.0"
+ dependencies:
+ "@typescript-eslint/eslint-plugin": 8.49.0
+ "@typescript-eslint/parser": 8.49.0
+ "@typescript-eslint/typescript-estree": 8.49.0
+ "@typescript-eslint/utils": 8.49.0
+ peerDependencies:
+ eslint: ^8.57.0 || ^9.0.0
+ typescript: ">=4.8.4 <6.0.0"
+ checksum: fd91cffcf3c5de73a9ead2253dcb8516ed664fc9179d26c019e6be53f4d4429e280dd5c783c68789a4a2db34712e569468a6c9c7613fc918a310687ca53b91b1
+ languageName: node
+ linkType: hard
+
"typescript@npm:^5.8.3":
version: 5.9.2
resolution: "typescript@npm:5.9.2"
@@ -12745,6 +14050,13 @@ __metadata:
languageName: node
linkType: hard
+"undici-types@npm:~7.16.0":
+ version: 7.16.0
+ resolution: "undici-types@npm:7.16.0"
+ checksum: 1ef68fc6c5bad200c8b6f17de8e5bc5cfdcadc164ba8d7208cd087cfa8583d922d8316a7fd76c9a658c22b4123d3ff847429185094484fbc65377d695c905857
+ languageName: node
+ linkType: hard
+
"unicode-canonical-property-names-ecmascript@npm:^2.0.0":
version: 2.0.1
resolution: "unicode-canonical-property-names-ecmascript@npm:2.0.1"
@@ -12919,6 +14231,61 @@ __metadata:
languageName: node
linkType: hard
+"vite@npm:^7.2.4":
+ version: 7.2.7
+ resolution: "vite@npm:7.2.7"
+ dependencies:
+ esbuild: ^0.25.0
+ fdir: ^6.5.0
+ fsevents: ~2.3.3
+ picomatch: ^4.0.3
+ postcss: ^8.5.6
+ rollup: ^4.43.0
+ tinyglobby: ^0.2.15
+ peerDependencies:
+ "@types/node": ^20.19.0 || >=22.12.0
+ jiti: ">=1.21.0"
+ less: ^4.0.0
+ lightningcss: ^1.21.0
+ sass: ^1.70.0
+ sass-embedded: ^1.70.0
+ stylus: ">=0.54.8"
+ sugarss: ^5.0.0
+ terser: ^5.16.0
+ tsx: ^4.8.1
+ yaml: ^2.4.2
+ dependenciesMeta:
+ fsevents:
+ optional: true
+ peerDependenciesMeta:
+ "@types/node":
+ optional: true
+ jiti:
+ optional: true
+ less:
+ optional: true
+ lightningcss:
+ optional: true
+ sass:
+ optional: true
+ sass-embedded:
+ optional: true
+ stylus:
+ optional: true
+ sugarss:
+ optional: true
+ terser:
+ optional: true
+ tsx:
+ optional: true
+ yaml:
+ optional: true
+ bin:
+ vite: bin/vite.js
+ checksum: 181b04ef3baad6c2aa452861c1f0885a39445bcb84369e63a5e2b864b9a4c9a4b301c457cca4169f18076cf9ff8e5ab986f2d6c361f9d8fb1110e51b96d18866
+ languageName: node
+ linkType: hard
+
"vlq@npm:^1.0.0":
version: 1.0.1
resolution: "vlq@npm:1.0.1"
@@ -13317,3 +14684,19 @@ __metadata:
checksum: 1c474d4b30a8c130e679279c5c2c33a0d48eba9684ffa0252cc64846c121fb56c3f25457fef902edbe1e2d7a7872130073a9fc8e795299d75e13fa3f5f548f1b
languageName: node
linkType: hard
+
+"zod-validation-error@npm:^3.5.0 || ^4.0.0":
+ version: 4.0.2
+ resolution: "zod-validation-error@npm:4.0.2"
+ peerDependencies:
+ zod: ^3.25.0 || ^4.0.0
+ checksum: f16ccbc08c5345f28788beea814d82e1f047978414f1511bd97a171580d7dbe63cecc368caa352c1391e201539288c241d61145e57c6b84cb19112dc88a72098
+ languageName: node
+ linkType: hard
+
+"zod@npm:^3.25.0 || ^4.0.0, zod@npm:^4.1.13":
+ version: 4.1.13
+ resolution: "zod@npm:4.1.13"
+ checksum: e5459280d46567df0adc188b0c687d425e616a206d4a73ee3bacf62d246f5546e24ef45790c7c4762d3ce7659c5e41052a29445d32d0d272410be9fe23162d03
+ languageName: node
+ linkType: hard
From afb34aa9866f0e383e01e967769a3832a0f43058 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Kacper=20=C5=BB=C3=B3=C5=82kiewski?=
<74975508+kacperzolkiewski@users.noreply.github.com>
Date: Fri, 19 Dec 2025 09:32:27 +0100
Subject: [PATCH 03/13] fix: cursor position when inserting image (#337)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Fixes: #329
1. Go to Example app
2. Add `
` through `Set input's value`
button
3. See that cursor is applied after image
Before:
https://github.com/user-attachments/assets/258132ae-1bf4-43e5-b08f-b8ade46ade67
After:
https://github.com/user-attachments/assets/6dede546-471c-489c-81e5-7e36f80377d4
| OS | Implemented |
| ------- | :---------: |
| iOS | â
|
| Android | â |
---
ios/EnrichedTextInputView.mm | 6 ++++++
ios/attachments/ImageAttachment.mm | 4 +++-
2 files changed, 9 insertions(+), 1 deletion(-)
diff --git a/ios/EnrichedTextInputView.mm b/ios/EnrichedTextInputView.mm
index dcfc514a8..ab8a24166 100644
--- a/ios/EnrichedTextInputView.mm
+++ b/ios/EnrichedTextInputView.mm
@@ -851,6 +851,9 @@ - (void)updateProps:(Props::Shared const &)props
newViewProps.defaultValue != oldViewProps.defaultValue;
if (stylePropChanged) {
+ // we want to preserve the selection between props changes
+ NSRange prevSelectedRange = textView.selectedRange;
+
// now set the new config
config = newConfig;
@@ -887,6 +890,7 @@ - (void)updateProps:(Props::Shared const &)props
defaultTypingAttributes[NSParagraphStyleAttributeName] =
[[NSParagraphStyle alloc] init];
textView.typingAttributes = defaultTypingAttributes;
+ textView.selectedRange = prevSelectedRange;
// update the placeholder as well
[self refreshPlaceholderLabelStyles];
@@ -911,6 +915,7 @@ - (void)updateProps:(Props::Shared const &)props
[parser replaceWholeFromHtml:newDefaultValue
notifyAnyTextMayHaveBeenModified:!isFirstMount];
}
+ textView.selectedRange = NSRange(textView.textStorage.string.length, 0);
}
// placeholderTextColor
@@ -1332,6 +1337,7 @@ - (void)setValue:(NSString *)value {
// set recentlyChangedRange and check for changes
recentlyChangedRange = NSMakeRange(0, textView.textStorage.string.length);
+ textView.selectedRange = NSRange(textView.textStorage.string.length, 0);
[self anyTextMayHaveBeenModified];
}
diff --git a/ios/attachments/ImageAttachment.mm b/ios/attachments/ImageAttachment.mm
index 117f09908..f4f08b051 100644
--- a/ios/attachments/ImageAttachment.mm
+++ b/ios/attachments/ImageAttachment.mm
@@ -16,8 +16,10 @@ - (instancetype)initWithImageData:(ImageData *)data {
- (void)loadAsync {
NSURL *url = [NSURL URLWithString:self.uri];
- if (!url)
+ if (!url) {
+ self.image = [UIImage systemImageNamed:@"file"];
return;
+ }
dispatch_async(dispatch_get_global_queue(QOS_CLASS_USER_INITIATED, 0), ^{
NSData *bytes = [NSData dataWithContentsOfURL:url];
From c3c8400163ca506bccf6f86cfa6c9427afa33dad Mon Sep 17 00:00:00 2001
From: IvanIhnatsiuk
Date: Thu, 18 Dec 2025 15:43:59 +0100
Subject: [PATCH 04/13] fix: remove unused code
---
ios/EnrichedTextInputView.mm | 1 -
1 file changed, 1 deletion(-)
diff --git a/ios/EnrichedTextInputView.mm b/ios/EnrichedTextInputView.mm
index ab8a24166..9329085cd 100644
--- a/ios/EnrichedTextInputView.mm
+++ b/ios/EnrichedTextInputView.mm
@@ -1802,7 +1802,6 @@ - (void)anyTextMayHaveBeenModified {
[self tryUpdatingHeight];
// update active styles as well
[self tryUpdatingActiveStyles];
- // update drawing - schedule debounced relayout
}
- (void)didMoveToWindow {
From ab334a02fa394ff2a80c14fd8630640534e06f69 Mon Sep 17 00:00:00 2001
From: IvanIhnatsiuk
Date: Thu, 18 Dec 2025 17:05:15 +0100
Subject: [PATCH 05/13] fix: update contentSize size
---
ios/EnrichedTextInputView.mm | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/ios/EnrichedTextInputView.mm b/ios/EnrichedTextInputView.mm
index 9329085cd..38614ba28 100644
--- a/ios/EnrichedTextInputView.mm
+++ b/ios/EnrichedTextInputView.mm
@@ -1037,7 +1037,7 @@ - (CGSize)measureSize:(CGFloat)maxWidth {
[layoutManager ensureLayoutForTextContainer:container];
CGRect usedRect = [layoutManager usedRectForTextContainer:container];
-
+ textView.contentSize = CGSizeMake(maxWidth, ceil(usedRect.size.height));
return CGSizeMake(maxWidth, ceil(usedRect.size.height));
}
From 91e4910ecaa9d07b09b47e97ad6f939daf9e4e0a Mon Sep 17 00:00:00 2001
From: IvanIhnatsiuk
Date: Thu, 18 Dec 2025 17:58:19 +0100
Subject: [PATCH 06/13] fix: return anyTextHaveBeenModified
---
ios/EnrichedTextInputView.mm | 10 +++-------
1 file changed, 3 insertions(+), 7 deletions(-)
diff --git a/ios/EnrichedTextInputView.mm b/ios/EnrichedTextInputView.mm
index 38614ba28..f24994cfe 100644
--- a/ios/EnrichedTextInputView.mm
+++ b/ios/EnrichedTextInputView.mm
@@ -1037,8 +1037,9 @@ - (CGSize)measureSize:(CGFloat)maxWidth {
[layoutManager ensureLayoutForTextContainer:container];
CGRect usedRect = [layoutManager usedRectForTextContainer:container];
- textView.contentSize = CGSizeMake(maxWidth, ceil(usedRect.size.height));
- return CGSizeMake(maxWidth, ceil(usedRect.size.height));
+ CGSize contentSize = CGSizeMake(maxWidth, ceil(usedRect.size.height));
+ textView.contentSize = contentSize;
+ return contentSize;
}
// make sure the newest state is kept in _state property
@@ -1804,11 +1805,6 @@ - (void)anyTextMayHaveBeenModified {
[self tryUpdatingActiveStyles];
}
-- (void)didMoveToWindow {
- [super didMoveToWindow];
- [self layoutIfNeeded];
-}
-
// MARK: - UITextView delegate methods
- (void)textViewDidBeginEditing:(UITextView *)textView {
From 5cf1cf5e7330e2e1ed2645fd151f6290f2815691 Mon Sep 17 00:00:00 2001
From: IvanIhnatsiuk
Date: Fri, 19 Dec 2025 12:54:31 +0100
Subject: [PATCH 07/13] fix: use self.bounds.size
---
ios/EnrichedTextInputView.mm | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/ios/EnrichedTextInputView.mm b/ios/EnrichedTextInputView.mm
index f24994cfe..979ea3cc9 100644
--- a/ios/EnrichedTextInputView.mm
+++ b/ios/EnrichedTextInputView.mm
@@ -1039,7 +1039,7 @@ - (CGSize)measureSize:(CGFloat)maxWidth {
CGRect usedRect = [layoutManager usedRectForTextContainer:container];
CGSize contentSize = CGSizeMake(maxWidth, ceil(usedRect.size.height));
textView.contentSize = contentSize;
- return contentSize;
+ return self.bounds.size;
}
// make sure the newest state is kept in _state property
From 36d7f06ee880c0d7a677411b2d69ce379448e624 Mon Sep 17 00:00:00 2001
From: IvanIhnatsiuk
Date: Sat, 20 Dec 2025 16:21:14 +0100
Subject: [PATCH 08/13] fix: use contentSize
---
ios/EnrichedTextInputView.mm | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/ios/EnrichedTextInputView.mm b/ios/EnrichedTextInputView.mm
index 979ea3cc9..f24994cfe 100644
--- a/ios/EnrichedTextInputView.mm
+++ b/ios/EnrichedTextInputView.mm
@@ -1039,7 +1039,7 @@ - (CGSize)measureSize:(CGFloat)maxWidth {
CGRect usedRect = [layoutManager usedRectForTextContainer:container];
CGSize contentSize = CGSizeMake(maxWidth, ceil(usedRect.size.height));
textView.contentSize = contentSize;
- return self.bounds.size;
+ return contentSize;
}
// make sure the newest state is kept in _state property
From bd1e1ec2d1d09223885733ff86c9e10291806582 Mon Sep 17 00:00:00 2001
From: IvanIhnatsiuk
Date: Sun, 21 Dec 2025 17:46:51 +0100
Subject: [PATCH 09/13] feat: proper layout handling
---
example/ios/Podfile.lock | 184 +++++
example/package.json | 8 +-
example/src/App.tsx | 627 +-----------------
.../EditorScreen}/components/Button.tsx | 0
.../EditorScreen}/components/ColorPreview.tsx | 0
.../EditorScreen}/components/HtmlSection.tsx | 0
.../EditorScreen}/components/Icon.tsx | 2 +-
.../EditorScreen}/components/ImageModal.tsx | 0
.../EditorScreen}/components/LinkModal.tsx | 0
.../EditorScreen}/components/MentionPopup.tsx | 0
.../EditorScreen}/components/Toolbar.tsx | 0
.../components/ToolbarButton.tsx | 0
.../components/ToolbarColorButton.tsx | 0
.../EditorScreen}/components/ValueModal.tsx | 0
.../EditorScreen}/hooks/useChannelMention.ts | 0
.../EditorScreen}/hooks/useUserMention.ts | 0
example/src/screens/EditorScreen/index.tsx | 486 ++++++++++++++
.../utils/prepareImageDimensions.ts | 0
example/src/screens/MainScreen.tsx | 22 +
example/src/screens/PreviewScreen.tsx | 27 +
ios/EnrichedTextInputView.h | 1 -
ios/EnrichedTextInputView.mm | 112 +---
ios/inputTextView/InputTextView.h | 3 +
ios/inputTextView/InputTextView.mm | 63 +-
.../EnrichedTextInputViewShadowNode.h | 13 +-
.../EnrichedTextInputViewShadowNode.mm | 133 ++--
ios/internals/EnrichedTextInputViewState.cpp | 10 -
ios/internals/EnrichedTextInputViewState.h | 19 +-
ios/utils/LayoutManagerExtension.mm | 8 +-
yarn.lock | 284 +++++++-
30 files changed, 1215 insertions(+), 787 deletions(-)
rename example/src/{ => screens/EditorScreen}/components/Button.tsx (100%)
rename example/src/{ => screens/EditorScreen}/components/ColorPreview.tsx (100%)
rename example/src/{ => screens/EditorScreen}/components/HtmlSection.tsx (100%)
rename example/src/{ => screens/EditorScreen}/components/Icon.tsx (91%)
rename example/src/{ => screens/EditorScreen}/components/ImageModal.tsx (100%)
rename example/src/{ => screens/EditorScreen}/components/LinkModal.tsx (100%)
rename example/src/{ => screens/EditorScreen}/components/MentionPopup.tsx (100%)
rename example/src/{ => screens/EditorScreen}/components/Toolbar.tsx (100%)
rename example/src/{ => screens/EditorScreen}/components/ToolbarButton.tsx (100%)
rename example/src/{ => screens/EditorScreen}/components/ToolbarColorButton.tsx (100%)
rename example/src/{ => screens/EditorScreen}/components/ValueModal.tsx (100%)
rename example/src/{ => screens/EditorScreen}/hooks/useChannelMention.ts (100%)
rename example/src/{ => screens/EditorScreen}/hooks/useUserMention.ts (100%)
create mode 100644 example/src/screens/EditorScreen/index.tsx
rename example/src/{ => screens/EditorScreen}/utils/prepareImageDimensions.ts (100%)
create mode 100644 example/src/screens/MainScreen.tsx
create mode 100644 example/src/screens/PreviewScreen.tsx
delete mode 100644 ios/internals/EnrichedTextInputViewState.cpp
diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock
index d0536afba..90b4c67aa 100644
--- a/example/ios/Podfile.lock
+++ b/example/ios/Podfile.lock
@@ -1920,6 +1920,93 @@ PODS:
- ReactCommon/turbomodule/core
- SocketRocket
- Yoga
+ - react-native-safe-area-context (5.6.2):
+ - boost
+ - DoubleConversion
+ - fast_float
+ - fmt
+ - glog
+ - hermes-engine
+ - RCT-Folly
+ - RCT-Folly/Fabric
+ - RCTRequired
+ - RCTTypeSafety
+ - React-Core
+ - React-debug
+ - React-Fabric
+ - React-featureflags
+ - React-graphics
+ - React-ImageManager
+ - React-jsi
+ - react-native-safe-area-context/common (= 5.6.2)
+ - react-native-safe-area-context/fabric (= 5.6.2)
+ - React-NativeModulesApple
+ - React-RCTFabric
+ - React-renderercss
+ - React-rendererdebug
+ - React-utils
+ - ReactCodegen
+ - ReactCommon/turbomodule/bridging
+ - ReactCommon/turbomodule/core
+ - SocketRocket
+ - Yoga
+ - react-native-safe-area-context/common (5.6.2):
+ - boost
+ - DoubleConversion
+ - fast_float
+ - fmt
+ - glog
+ - hermes-engine
+ - RCT-Folly
+ - RCT-Folly/Fabric
+ - RCTRequired
+ - RCTTypeSafety
+ - React-Core
+ - React-debug
+ - React-Fabric
+ - React-featureflags
+ - React-graphics
+ - React-ImageManager
+ - React-jsi
+ - React-NativeModulesApple
+ - React-RCTFabric
+ - React-renderercss
+ - React-rendererdebug
+ - React-utils
+ - ReactCodegen
+ - ReactCommon/turbomodule/bridging
+ - ReactCommon/turbomodule/core
+ - SocketRocket
+ - Yoga
+ - react-native-safe-area-context/fabric (5.6.2):
+ - boost
+ - DoubleConversion
+ - fast_float
+ - fmt
+ - glog
+ - hermes-engine
+ - RCT-Folly
+ - RCT-Folly/Fabric
+ - RCTRequired
+ - RCTTypeSafety
+ - React-Core
+ - React-debug
+ - React-Fabric
+ - React-featureflags
+ - React-graphics
+ - React-ImageManager
+ - React-jsi
+ - react-native-safe-area-context/common
+ - React-NativeModulesApple
+ - React-RCTFabric
+ - React-renderercss
+ - React-rendererdebug
+ - React-utils
+ - ReactCodegen
+ - ReactCommon/turbomodule/bridging
+ - ReactCommon/turbomodule/core
+ - SocketRocket
+ - Yoga
- React-NativeModulesApple (0.83.0):
- boost
- DoubleConversion
@@ -2509,6 +2596,93 @@ PODS:
- SDWebImage (5.21.5):
- SDWebImage/Core (= 5.21.5)
- SDWebImage/Core (5.21.5)
+ - RNGestureHandler (2.29.1):
+ - boost
+ - DoubleConversion
+ - fast_float
+ - fmt
+ - glog
+ - hermes-engine
+ - RCT-Folly
+ - RCT-Folly/Fabric
+ - RCTRequired
+ - RCTTypeSafety
+ - React-Core
+ - React-debug
+ - React-Fabric
+ - React-featureflags
+ - React-graphics
+ - React-ImageManager
+ - React-jsi
+ - React-NativeModulesApple
+ - React-RCTFabric
+ - React-renderercss
+ - React-rendererdebug
+ - React-utils
+ - ReactCodegen
+ - ReactCommon/turbomodule/bridging
+ - ReactCommon/turbomodule/core
+ - SocketRocket
+ - Yoga
+ - RNScreens (4.19.0):
+ - boost
+ - DoubleConversion
+ - fast_float
+ - fmt
+ - glog
+ - hermes-engine
+ - RCT-Folly
+ - RCT-Folly/Fabric
+ - RCTRequired
+ - RCTTypeSafety
+ - React-Core
+ - React-debug
+ - React-Fabric
+ - React-featureflags
+ - React-graphics
+ - React-ImageManager
+ - React-jsi
+ - React-NativeModulesApple
+ - React-RCTFabric
+ - React-RCTImage
+ - React-renderercss
+ - React-rendererdebug
+ - React-utils
+ - ReactCodegen
+ - ReactCommon/turbomodule/bridging
+ - ReactCommon/turbomodule/core
+ - RNScreens/common (= 4.19.0)
+ - SocketRocket
+ - Yoga
+ - RNScreens/common (4.19.0):
+ - boost
+ - DoubleConversion
+ - fast_float
+ - fmt
+ - glog
+ - hermes-engine
+ - RCT-Folly
+ - RCT-Folly/Fabric
+ - RCTRequired
+ - RCTTypeSafety
+ - React-Core
+ - React-debug
+ - React-Fabric
+ - React-featureflags
+ - React-graphics
+ - React-ImageManager
+ - React-jsi
+ - React-NativeModulesApple
+ - React-RCTFabric
+ - React-RCTImage
+ - React-renderercss
+ - React-rendererdebug
+ - React-utils
+ - ReactCodegen
+ - ReactCommon/turbomodule/bridging
+ - ReactCommon/turbomodule/core
+ - SocketRocket
+ - Yoga
- SocketRocket (0.7.1)
- Yoga (0.0.0)
@@ -2558,6 +2732,7 @@ DEPENDENCIES:
- React-Mapbuffer (from `../node_modules/react-native/ReactCommon`)
- React-microtasksnativemodule (from `../node_modules/react-native/ReactCommon/react/nativemodule/microtasks`)
- react-native-image-picker (from `../node_modules/react-native-image-picker`)
+ - react-native-safe-area-context (from `../node_modules/react-native-safe-area-context`)
- React-NativeModulesApple (from `../node_modules/react-native/ReactCommon/react/nativemodule/core/platform/ios`)
- React-networking (from `../node_modules/react-native/ReactCommon/react/networking`)
- React-oscompat (from `../node_modules/react-native/ReactCommon/oscompat`)
@@ -2592,6 +2767,8 @@ DEPENDENCIES:
- ReactCodegen (from `build/generated/ios/ReactCodegen`)
- ReactCommon/turbomodule/core (from `../node_modules/react-native/ReactCommon`)
- ReactNativeEnriched (from `../..`)
+ - RNGestureHandler (from `../node_modules/react-native-gesture-handler`)
+ - RNScreens (from `../node_modules/react-native-screens`)
- SocketRocket (~> 0.7.1)
- Yoga (from `../node_modules/react-native/ReactCommon/yoga`)
@@ -2690,6 +2867,8 @@ EXTERNAL SOURCES:
:path: "../node_modules/react-native/ReactCommon/react/nativemodule/microtasks"
react-native-image-picker:
:path: "../node_modules/react-native-image-picker"
+ react-native-safe-area-context:
+ :path: "../node_modules/react-native-safe-area-context"
React-NativeModulesApple:
:path: "../node_modules/react-native/ReactCommon/react/nativemodule/core/platform/ios"
React-networking:
@@ -2758,6 +2937,10 @@ EXTERNAL SOURCES:
:path: "../node_modules/react-native/ReactCommon"
ReactNativeEnriched:
:path: "../.."
+ RNGestureHandler:
+ :path: "../node_modules/react-native-gesture-handler"
+ RNScreens:
+ :path: "../node_modules/react-native-screens"
Yoga:
:path: "../node_modules/react-native/ReactCommon/yoga"
@@ -2806,6 +2989,7 @@ SPEC CHECKSUMS:
React-Mapbuffer: d690542fbbded9d9526a0a883c439aa82e4cede3
React-microtasksnativemodule: b908076184179c0fd0db8713b5140f6e6e0e56c7
react-native-image-picker: 43e6cd4231e670030fe09b079d696fa5a634ccfc
+ react-native-safe-area-context: 54d812805f3c4e08a4580ad086cbde1d8780c2e4
React-NativeModulesApple: 153a3effe2df7d35881f3f0c126c8182b8643e5a
React-networking: 236c494a8d26fc5a776b3cfec7795a3e55143c91
React-oscompat: aedc0afbded67280de6bb6bfac8cfde0389e2b33
diff --git a/example/package.json b/example/package.json
index a13342262..2cc47fa1a 100644
--- a/example/package.json
+++ b/example/package.json
@@ -10,9 +10,15 @@
"build:ios": "react-native build-ios --scheme EnrichedTextInputExample --mode Debug --extra-params \"-sdk iphonesimulator CC=clang CPLUSPLUS=clang++ LD=clang LDPLUSPLUS=clang++ GCC_OPTIMIZATION_LEVEL=0 GCC_PRECOMPILE_PREFIX_HEADER=YES ASSETCATALOG_COMPILER_OPTIMIZATION=time DEBUG_INFORMATION_FORMAT=dwarf COMPILER_INDEX_STORE_ENABLE=NO\""
},
"dependencies": {
+ "@react-navigation/native": "^7.1.26",
+ "@react-navigation/native-stack": "^7.9.0",
+ "add": "^2.0.6",
"react": "19.2.0",
"react-native": "0.83.0",
- "react-native-image-picker": "^8.2.1"
+ "react-native-gesture-handler": "^2.29.1",
+ "react-native-image-picker": "^8.2.1",
+ "react-native-safe-area-context": "^5.6.2",
+ "react-native-screens": "^4.19.0"
},
"devDependencies": {
"@babel/core": "^7.25.2",
diff --git a/example/src/App.tsx b/example/src/App.tsx
index ebe6be5c6..8984926c7 100644
--- a/example/src/App.tsx
+++ b/example/src/App.tsx
@@ -1,91 +1,25 @@
+import { NavigationContainer } from '@react-navigation/native';
+import { createNativeStackNavigator } from '@react-navigation/native-stack';
import {
- View,
- StyleSheet,
- Text,
- ScrollView,
- Platform,
- Image,
-} from 'react-native';
-import {
- EnrichedTextInput,
- type OnChangeTextEvent,
- type EnrichedTextInputInstance,
- type OnLinkDetected,
- type OnChangeMentionEvent,
- type OnChangeHtmlEvent,
- type OnChangeStateEvent,
- type OnChangeSelectionEvent,
- type HtmlStyle,
-} from 'react-native-enriched';
-import { useRef, useState } from 'react';
-import { Button } from './components/Button';
-import { Toolbar } from './components/Toolbar';
-import { LinkModal } from './components/LinkModal';
-import { ValueModal } from './components/ValueModal';
-import { launchImageLibrary } from 'react-native-image-picker';
-import { type MentionItem, MentionPopup } from './components/MentionPopup';
-import { useUserMention } from './hooks/useUserMention';
-import { useChannelMention } from './hooks/useChannelMention';
-import { HtmlSection } from './components/HtmlSection';
-import { ImageModal } from './components/ImageModal';
-import {
- DEFAULT_IMAGE_HEIGHT,
- DEFAULT_IMAGE_WIDTH,
- prepareImageDimensions,
-} from './utils/prepareImageDimensions';
-import type { OnChangeColorEvent } from '../../src/EnrichedTextInputNativeComponent';
-import ColorPreview from './components/ColorPreview';
-
-type StylesState = OnChangeStateEvent;
-
-type CurrentLinkState = OnLinkDetected;
-
-interface Selection {
- start: number;
- end: number;
- text: string;
-}
-
-const PRIMARY_COLOR = '#000000';
-
-const DEFAULT_STYLE: StylesState = {
- isBold: false,
- isItalic: false,
- isUnderline: false,
- isStrikeThrough: false,
- isInlineCode: false,
- isH1: false,
- isH2: false,
- isH3: false,
- isH4: false,
- isH5: false,
- isH6: false,
- isBlockQuote: false,
- isCodeBlock: false,
- isOrderedList: false,
- isUnorderedList: false,
- isLink: false,
- isImage: false,
- isMention: false,
- isCheckList: false,
- isColored: false,
- isContent: false,
-};
-
-const DEFAULT_LINK_STATE = {
- text: '',
- url: '',
- start: 0,
- end: 0,
+ initialWindowMetrics,
+ SafeAreaProvider,
+} from 'react-native-safe-area-context';
+
+import { MainScreen } from './screens/MainScreen';
+import { EditorScreen } from './screens/EditorScreen/index';
+import { PreviewScreen } from './screens/PreviewScreen';
+import { enableFreeze, enableScreens } from 'react-native-screens';
+
+export type RootStackParamList = {
+ Main: undefined;
+ Editor: undefined;
+ Preview: { html: string };
};
-const DEBUG_SCROLLABLE = false;
+enableScreens(false);
+enableFreeze(false);
-// Enabling this prop fixes input flickering while auto growing.
-// However, it's still experimental and not tested well.
-// Disabled for now, as it's causing some strange issues.
-// See: https://github.com/software-mansion/react-native-enriched/issues/229
-const ANDROID_EXPERIMENTAL_SYNCHRONOUS_EVENTS = false;
+const Stack = createNativeStackNavigator();
const contentHtml = Array(1)
.fill(
@@ -98,522 +32,15 @@ const html = '' + contentHtml + '';
console.log(html);
export default function App() {
- const [isChannelPopupOpen, setIsChannelPopupOpen] = useState(false);
- const [isUserPopupOpen, setIsUserPopupOpen] = useState(false);
- const [isLinkModalOpen, setIsLinkModalOpen] = useState(false);
- const [isImageModalOpen, setIsImageModalOpen] = useState(false);
- const [isValueModalOpen, setIsValueModalOpen] = useState(false);
- const [currentHtml, setCurrentHtml] = useState('');
-
- const [selection, setSelection] = useState();
- const [stylesState, setStylesState] = useState(DEFAULT_STYLE);
- const [currentLink, setCurrentLink] =
- useState(DEFAULT_LINK_STATE);
- const [selectionColor, setSelectionColor] = useState(PRIMARY_COLOR);
-
- const ref = useRef(null);
-
- const userMention = useUserMention();
- const channelMention = useChannelMention();
-
- const insideCurrentLink =
- stylesState.isLink &&
- currentLink.url.length > 0 &&
- (currentLink.start || currentLink.end) &&
- selection &&
- selection.start >= currentLink.start &&
- selection.end <= currentLink.end;
-
- const handleChangeText = (e: OnChangeTextEvent) => {
- console.log('Text changed:', e.value);
- };
-
- const handleChangeHtml = (e: OnChangeHtmlEvent) => {
- console.log('HTML changed:', e.value);
- setCurrentHtml(e.value);
- };
-
- const handleChangeState = (state: OnChangeStateEvent) => {
- setStylesState(state);
- };
-
- const handleFocus = () => {
- ref.current?.focus();
- };
-
- const handleBlur = () => {
- ref.current?.blur();
- };
-
- const openLinkModal = () => {
- setIsLinkModalOpen(true);
- };
-
- const closeLinkModal = () => {
- setIsLinkModalOpen(false);
- };
-
- const openImageModal = () => {
- setIsImageModalOpen(true);
- };
-
- const closeImageModal = () => {
- setIsImageModalOpen(false);
- };
-
- const openUserMentionPopup = () => {
- setIsUserPopupOpen(true);
- };
-
- const closeUserMentionPopup = () => {
- setIsUserPopupOpen(false);
- userMention.onMentionChange('');
- };
-
- const openChannelMentionPopup = () => {
- setIsChannelPopupOpen(true);
- };
-
- const closeChannelMentionPopup = () => {
- setIsChannelPopupOpen(false);
- channelMention.onMentionChange('');
- };
-
- const openValueModal = () => {
- setIsValueModalOpen(true);
- };
-
- const closeValueModal = () => {
- setIsValueModalOpen(false);
- };
-
- const handleStartMention = (indicator: string) => {
- if (indicator === '@') {
- userMention.onMentionChange('');
- openUserMentionPopup();
- return;
- }
-
- channelMention.onMentionChange('');
- openChannelMentionPopup();
- };
-
- const handleEndMention = (indicator: string) => {
- const isUserMention = indicator === '@';
-
- if (isUserMention) {
- closeUserMentionPopup();
- userMention.onMentionChange('');
- return;
- }
-
- closeChannelMentionPopup();
- channelMention.onMentionChange('');
- };
-
- const submitLink = (text: string, url: string) => {
- if (!selection || url.length === 0) {
- closeLinkModal();
- return;
- }
-
- const newText = text.length > 0 ? text : url;
-
- if (insideCurrentLink) {
- ref.current?.setLink(currentLink.start, currentLink.end, newText, url);
- } else {
- ref.current?.setLink(selection.start, selection.end, newText, url);
- }
-
- closeLinkModal();
- };
-
- const submitSetValue = (value: string) => {
- ref.current?.setValue(value);
- closeValueModal();
- };
-
- const selectImage = async (
- width: number | undefined,
- height: number | undefined,
- remoteUrl?: string
- ) => {
- if (remoteUrl) {
- ref.current?.setImage(
- remoteUrl,
- width ?? DEFAULT_IMAGE_WIDTH,
- height ?? DEFAULT_IMAGE_HEIGHT
- );
- return;
- }
-
- const response = await launchImageLibrary({
- mediaType: 'photo',
- selectionLimit: 1,
- });
-
- if (response?.assets?.[0] === undefined) {
- return;
- }
-
- const asset = response.assets[0];
- const imageUri = Platform.OS === 'android' ? asset.originalPath : asset.uri;
-
- if (imageUri) {
- const { finalWidth, finalHeight } = prepareImageDimensions(
- asset,
- width,
- height
- );
- ref.current?.setImage(imageUri, finalWidth, finalHeight);
- }
- };
-
- const handleChangeMention = ({ indicator, text }: OnChangeMentionEvent) => {
- indicator === '@'
- ? userMention.onMentionChange(text)
- : channelMention.onMentionChange(text);
- indicator === '@'
- ? !isUserPopupOpen && setIsUserPopupOpen(true)
- : !isChannelPopupOpen && setIsChannelPopupOpen(true);
- };
-
- const handleUserMentionSelected = (item: MentionItem) => {
- ref.current?.setMention('@', `@${item.name}`, {
- id: item.id,
- type: 'user',
- });
- };
-
- const handleChannelMentionSelected = (item: MentionItem) => {
- ref.current?.setMention('#', `#${item.name}`, {
- id: item.id,
- type: 'channel',
- });
- };
-
- const handleFocusEvent = () => {
- console.log('Input focused');
- };
-
- const handleBlurEvent = () => {
- console.log('Input blurred');
- };
-
- const handleLinkDetected = (state: CurrentLinkState) => {
- console.log(state);
- setCurrentLink(state);
- };
-
- const handleSelectionChangeEvent = (sel: OnChangeSelectionEvent) => {
- setSelection(sel);
- };
-
- const handleSelectionColorChange = (e: OnChangeColorEvent) => {
- if (e.color) {
- setSelectionColor(e.color);
- }
- };
-
return (
- <>
-
- Enriched Text Input
-
- handleChangeText(e.nativeEvent)}
- onChangeHtml={(e) => handleChangeHtml(e.nativeEvent)}
- onChangeState={(e) => handleChangeState(e.nativeEvent)}
- defaultValue={html}
- onColorChangeInSelection={(e) => {
- handleSelectionColorChange(e.nativeEvent);
- }}
- onLinkDetected={handleLinkDetected}
- onMentionDetected={console.log}
- onStartMention={handleStartMention}
- onChangeMention={handleChangeMention}
- onEndMention={handleEndMention}
- onFocus={handleFocusEvent}
- onBlur={handleBlurEvent}
- onChangeSelection={(e) => handleSelectionChangeEvent(e.nativeEvent)}
- androidExperimentalSynchronousEvents={
- ANDROID_EXPERIMENTAL_SYNCHRONOUS_EVENTS
- }
- />
-
-
-
-
-
-
-
-
-
-
-
-
- >
+
+
+
+
+
+
+
+
+
);
}
-
-const htmlStyle: HtmlStyle = {
- h1: {
- fontSize: 72,
- bold: true,
- },
- h2: {
- fontSize: 60,
- bold: true,
- },
- h3: {
- fontSize: 50,
- bold: true,
- },
- h4: {
- fontSize: 40,
- bold: true,
- },
- h5: {
- fontSize: 30,
- bold: true,
- },
- h6: {
- fontSize: 24,
- bold: true,
- },
- blockquote: {
- borderColor: 'navy',
- borderWidth: 4,
- gapWidth: 16,
- color: 'navy',
- },
- codeblock: {
- color: 'green',
- borderRadius: 8,
- backgroundColor: 'aquamarine',
- },
- code: {
- color: 'purple',
- backgroundColor: 'yellow',
- },
- a: {
- color: 'blue',
- textDecorationLine: 'underline',
- },
- mention: {
- '#': {
- color: 'blue',
- backgroundColor: 'lightblue',
- textDecorationLine: 'underline',
- },
- '@': {
- color: 'green',
- backgroundColor: 'lightgreen',
- textDecorationLine: 'none',
- },
- },
- content: {
- image: {
- textColor: 'black',
- backgroundColor: 'lightgray',
- borderRadius: 4,
- paddingTop: 20,
- paddingBottom: 20,
- marginTop: 4,
- marginBottom: 4,
- paddingLeft: 0,
- paddingRight: 0,
- imageBorderRadiusTopLeft: 4,
- imageBorderRadiusBottomLeft: 4,
- imageResizeMode: 'stretch',
- imageWidth: 50,
- fontSize: 14,
- fontWeight: '900',
- fallbackImageURI: Image.resolveAssetSource(
- require('../assets/placeholder.png')
- ).uri,
- },
- video: {
- borderWidth: 1,
- borderColor: 'blue',
- textColor: 'blue',
- borderStyle: 'dotted',
- borderRadius: 4,
- paddingTop: 16,
- paddingBottom: 16,
- marginTop: 4,
- marginBottom: 4,
- },
- placeholder: {
- borderWidth: 1,
- borderColor: 'blue',
- textColor: 'blue',
- borderStyle: 'dotted',
- borderRadius: 4,
- paddingTop: 14,
- paddingBottom: 14,
- marginTop: 8,
- marginBottom: 8,
- imageWidth: 50,
- imageBorderRadiusTopLeft: 4,
- imageBorderRadiusBottomLeft: 4,
- imageResizeMode: 'cover',
- },
- test: {
- borderColor: 'red',
- borderWidth: 1,
- paddingTop: 10,
- paddingBottom: 10,
- borderRadius: 8,
- borderStyle: 'dashed',
- textColor: 'blue',
- },
- },
- img: {
- width: 50,
- height: 50,
- },
- ol: {
- gapWidth: 16,
- marginLeft: 24,
- markerColor: 'navy',
- markerFontWeight: 'bold',
- },
- ul: {
- bulletColor: 'aquamarine',
- bulletSize: 8,
- marginLeft: 24,
- gapWidth: 16,
- },
- checkbox: {
- imageWidth: 24,
- imageHeight: 24,
- checkedImage: require('../assets/images/checkbox_checked.png'),
- uncheckedImage: require('../assets/images/checkbox.png'),
- marginLeft: 0,
- gapWidth: 6,
- checkedTextColor: 'gray',
- },
- divider: {
- height: 24,
- color: 'gray',
- thickness: 2,
- },
-};
-
-const styles = StyleSheet.create({
- container: {
- flex: 1,
- backgroundColor: 'white',
- },
- content: {
- flexGrow: 1,
- padding: 16,
- paddingTop: 100,
- alignItems: 'center',
- },
- editor: {
- width: '100%',
- },
- label: {
- fontSize: 24,
- fontWeight: 'bold',
- textAlign: 'center',
- color: 'rgb(0, 26, 114)',
- },
- buttonStack: {
- flexDirection: 'row',
- alignItems: 'center',
- justifyContent: 'space-between',
- width: '100%',
- },
- button: {
- width: '45%',
- },
- valueButton: {
- width: '100%',
- },
- editorInput: {
- marginTop: 24,
- width: '100%',
- maxHeight: 300,
- backgroundColor: 'gainsboro',
- fontSize: 18,
- fontFamily: 'Nunito-Regular',
- paddingVertical: 12,
- paddingHorizontal: 14,
- },
- scrollPlaceholder: {
- marginTop: 24,
- width: '100%',
- height: 1000,
- backgroundColor: 'rgb(0, 26, 114)',
- },
-});
diff --git a/example/src/components/Button.tsx b/example/src/screens/EditorScreen/components/Button.tsx
similarity index 100%
rename from example/src/components/Button.tsx
rename to example/src/screens/EditorScreen/components/Button.tsx
diff --git a/example/src/components/ColorPreview.tsx b/example/src/screens/EditorScreen/components/ColorPreview.tsx
similarity index 100%
rename from example/src/components/ColorPreview.tsx
rename to example/src/screens/EditorScreen/components/ColorPreview.tsx
diff --git a/example/src/components/HtmlSection.tsx b/example/src/screens/EditorScreen/components/HtmlSection.tsx
similarity index 100%
rename from example/src/components/HtmlSection.tsx
rename to example/src/screens/EditorScreen/components/HtmlSection.tsx
diff --git a/example/src/components/Icon.tsx b/example/src/screens/EditorScreen/components/Icon.tsx
similarity index 91%
rename from example/src/components/Icon.tsx
rename to example/src/screens/EditorScreen/components/Icon.tsx
index 02927d180..8f315526d 100644
--- a/example/src/components/Icon.tsx
+++ b/example/src/screens/EditorScreen/components/Icon.tsx
@@ -1,5 +1,5 @@
import { Text, type TextStyle } from 'react-native';
-import glyphMap from '../../assets/icons/FontAwesome.json';
+import glyphMap from '../../../../assets/icons/FontAwesome.json';
import { type FC, memo } from 'react';
export type IconName = keyof typeof glyphMap;
diff --git a/example/src/components/ImageModal.tsx b/example/src/screens/EditorScreen/components/ImageModal.tsx
similarity index 100%
rename from example/src/components/ImageModal.tsx
rename to example/src/screens/EditorScreen/components/ImageModal.tsx
diff --git a/example/src/components/LinkModal.tsx b/example/src/screens/EditorScreen/components/LinkModal.tsx
similarity index 100%
rename from example/src/components/LinkModal.tsx
rename to example/src/screens/EditorScreen/components/LinkModal.tsx
diff --git a/example/src/components/MentionPopup.tsx b/example/src/screens/EditorScreen/components/MentionPopup.tsx
similarity index 100%
rename from example/src/components/MentionPopup.tsx
rename to example/src/screens/EditorScreen/components/MentionPopup.tsx
diff --git a/example/src/components/Toolbar.tsx b/example/src/screens/EditorScreen/components/Toolbar.tsx
similarity index 100%
rename from example/src/components/Toolbar.tsx
rename to example/src/screens/EditorScreen/components/Toolbar.tsx
diff --git a/example/src/components/ToolbarButton.tsx b/example/src/screens/EditorScreen/components/ToolbarButton.tsx
similarity index 100%
rename from example/src/components/ToolbarButton.tsx
rename to example/src/screens/EditorScreen/components/ToolbarButton.tsx
diff --git a/example/src/components/ToolbarColorButton.tsx b/example/src/screens/EditorScreen/components/ToolbarColorButton.tsx
similarity index 100%
rename from example/src/components/ToolbarColorButton.tsx
rename to example/src/screens/EditorScreen/components/ToolbarColorButton.tsx
diff --git a/example/src/components/ValueModal.tsx b/example/src/screens/EditorScreen/components/ValueModal.tsx
similarity index 100%
rename from example/src/components/ValueModal.tsx
rename to example/src/screens/EditorScreen/components/ValueModal.tsx
diff --git a/example/src/hooks/useChannelMention.ts b/example/src/screens/EditorScreen/hooks/useChannelMention.ts
similarity index 100%
rename from example/src/hooks/useChannelMention.ts
rename to example/src/screens/EditorScreen/hooks/useChannelMention.ts
diff --git a/example/src/hooks/useUserMention.ts b/example/src/screens/EditorScreen/hooks/useUserMention.ts
similarity index 100%
rename from example/src/hooks/useUserMention.ts
rename to example/src/screens/EditorScreen/hooks/useUserMention.ts
diff --git a/example/src/screens/EditorScreen/index.tsx b/example/src/screens/EditorScreen/index.tsx
new file mode 100644
index 000000000..6edcaf2de
--- /dev/null
+++ b/example/src/screens/EditorScreen/index.tsx
@@ -0,0 +1,486 @@
+import { View, StyleSheet, Text, ScrollView, Platform } from 'react-native';
+import {
+ EnrichedTextInput,
+ type OnChangeTextEvent,
+ type EnrichedTextInputInstance,
+ type OnLinkDetected,
+ type OnChangeMentionEvent,
+ type OnChangeHtmlEvent,
+ type OnChangeStateEvent,
+ type OnChangeSelectionEvent,
+ type HtmlStyle,
+} from 'react-native-enriched';
+import { useRef, useState } from 'react';
+import { Button } from './components/Button';
+import { Toolbar } from './components/Toolbar';
+import { LinkModal } from './components/LinkModal';
+import { ValueModal } from './components/ValueModal';
+import { launchImageLibrary } from 'react-native-image-picker';
+import { type MentionItem, MentionPopup } from './components/MentionPopup';
+import { useUserMention } from './hooks/useUserMention';
+import { useChannelMention } from './hooks/useChannelMention';
+import { HtmlSection } from './components/HtmlSection';
+import { ImageModal } from './components/ImageModal';
+import {
+ DEFAULT_IMAGE_HEIGHT,
+ DEFAULT_IMAGE_WIDTH,
+ prepareImageDimensions,
+} from './utils/prepareImageDimensions';
+import { useNavigation } from '@react-navigation/native';
+import type { RootStackParamList } from '../../App';
+import type { NativeStackNavigationProp } from '@react-navigation/native-stack';
+
+type StylesState = OnChangeStateEvent;
+
+type CurrentLinkState = OnLinkDetected;
+
+interface Selection {
+ start: number;
+ end: number;
+ text: string;
+}
+
+const DEFAULT_STYLE: StylesState = {
+ isBold: false,
+ isItalic: false,
+ isUnderline: false,
+ isStrikeThrough: false,
+ isInlineCode: false,
+ isH1: false,
+ isH2: false,
+ isH3: false,
+ isBlockQuote: false,
+ isCodeBlock: false,
+ isOrderedList: false,
+ isUnorderedList: false,
+ isLink: false,
+ isImage: false,
+ isMention: false,
+};
+
+const DEFAULT_LINK_STATE = {
+ text: '',
+ url: '',
+ start: 0,
+ end: 0,
+};
+
+const DEBUG_SCROLLABLE = false;
+
+// Enabling this prop fixes input flickering while auto growing.
+// However, it's still experimental and not tested well.
+// Disabled for now, as it's causing some strange issues.
+// See: https://github.com/software-mansion/react-native-enriched/issues/229
+const ANDROID_EXPERIMENTAL_SYNCHRONOUS_EVENTS = false;
+
+export function EditorScreen() {
+ const { navigate } =
+ useNavigation>();
+ const [isChannelPopupOpen, setIsChannelPopupOpen] = useState(false);
+ const [isUserPopupOpen, setIsUserPopupOpen] = useState(false);
+ const [isLinkModalOpen, setIsLinkModalOpen] = useState(false);
+ const [isImageModalOpen, setIsImageModalOpen] = useState(false);
+ const [isValueModalOpen, setIsValueModalOpen] = useState(false);
+ const [currentHtml, setCurrentHtml] = useState('');
+
+ const [selection, setSelection] = useState();
+ const [stylesState, setStylesState] = useState(DEFAULT_STYLE);
+ const [currentLink, setCurrentLink] =
+ useState(DEFAULT_LINK_STATE);
+
+ const ref = useRef(null);
+
+ const userMention = useUserMention();
+ const channelMention = useChannelMention();
+
+ const insideCurrentLink =
+ stylesState.isLink &&
+ currentLink.url.length > 0 &&
+ (currentLink.start || currentLink.end) &&
+ selection &&
+ selection.start >= currentLink.start &&
+ selection.end <= currentLink.end;
+
+ const handleChangeText = (e: OnChangeTextEvent) => {
+ console.log('Text changed:', e.value);
+ };
+
+ const handleChangeHtml = (e: OnChangeHtmlEvent) => {
+ console.log('HTML changed:', e.value);
+ setCurrentHtml(e.value);
+ };
+
+ const handleChangeState = (state: OnChangeStateEvent) => {
+ setStylesState(state);
+ };
+
+ const handleFocus = () => {
+ ref.current?.focus();
+ };
+
+ const handleBlur = () => {
+ ref.current?.blur();
+ };
+
+ const openLinkModal = () => {
+ setIsLinkModalOpen(true);
+ };
+
+ const closeLinkModal = () => {
+ setIsLinkModalOpen(false);
+ };
+
+ const openImageModal = () => {
+ setIsImageModalOpen(true);
+ };
+
+ const closeImageModal = () => {
+ setIsImageModalOpen(false);
+ };
+
+ const openUserMentionPopup = () => {
+ setIsUserPopupOpen(true);
+ };
+
+ const closeUserMentionPopup = () => {
+ setIsUserPopupOpen(false);
+ userMention.onMentionChange('');
+ };
+
+ const openChannelMentionPopup = () => {
+ setIsChannelPopupOpen(true);
+ };
+
+ const closeChannelMentionPopup = () => {
+ setIsChannelPopupOpen(false);
+ channelMention.onMentionChange('');
+ };
+
+ const openValueModal = () => {
+ setIsValueModalOpen(true);
+ };
+
+ const closeValueModal = () => {
+ setIsValueModalOpen(false);
+ };
+
+ const handleStartMention = (indicator: string) => {
+ if (indicator === '@') {
+ userMention.onMentionChange('');
+ openUserMentionPopup();
+ return;
+ }
+
+ channelMention.onMentionChange('');
+ openChannelMentionPopup();
+ };
+
+ const handleEndMention = (indicator: string) => {
+ const isUserMention = indicator === '@';
+
+ if (isUserMention) {
+ closeUserMentionPopup();
+ userMention.onMentionChange('');
+ return;
+ }
+
+ closeChannelMentionPopup();
+ channelMention.onMentionChange('');
+ };
+
+ const submitLink = (text: string, url: string) => {
+ if (!selection || url.length === 0) {
+ closeLinkModal();
+ return;
+ }
+
+ const newText = text.length > 0 ? text : url;
+
+ if (insideCurrentLink) {
+ ref.current?.setLink(currentLink.start, currentLink.end, newText, url);
+ } else {
+ ref.current?.setLink(selection.start, selection.end, newText, url);
+ }
+
+ closeLinkModal();
+ };
+
+ const submitSetValue = (value: string) => {
+ ref.current?.setValue(value);
+ closeValueModal();
+ };
+
+ const selectImage = async (
+ width: number | undefined,
+ height: number | undefined,
+ remoteUrl?: string
+ ) => {
+ if (remoteUrl) {
+ ref.current?.setImage(
+ remoteUrl,
+ width ?? DEFAULT_IMAGE_WIDTH,
+ height ?? DEFAULT_IMAGE_HEIGHT
+ );
+ return;
+ }
+
+ const response = await launchImageLibrary({
+ mediaType: 'photo',
+ selectionLimit: 1,
+ });
+
+ if (response?.assets?.[0] === undefined) {
+ return;
+ }
+
+ const asset = response.assets[0];
+ const imageUri = Platform.OS === 'android' ? asset.originalPath : asset.uri;
+
+ if (imageUri) {
+ const { finalWidth, finalHeight } = prepareImageDimensions(
+ asset,
+ width,
+ height
+ );
+ ref.current?.setImage(imageUri, finalWidth, finalHeight);
+ }
+ };
+
+ const handleChangeMention = ({ indicator, text }: OnChangeMentionEvent) => {
+ indicator === '@'
+ ? userMention.onMentionChange(text)
+ : channelMention.onMentionChange(text);
+ indicator === '@'
+ ? !isUserPopupOpen && setIsUserPopupOpen(true)
+ : !isChannelPopupOpen && setIsChannelPopupOpen(true);
+ };
+
+ const handleUserMentionSelected = (item: MentionItem) => {
+ ref.current?.setMention('@', `@${item.name}`, {
+ id: item.id,
+ type: 'user',
+ });
+ };
+
+ const handleChannelMentionSelected = (item: MentionItem) => {
+ ref.current?.setMention('#', `#${item.name}`, {
+ id: item.id,
+ type: 'channel',
+ });
+ };
+
+ const handleFocusEvent = () => {
+ console.log('Input focused');
+ };
+
+ const handleBlurEvent = () => {
+ console.log('Input blurred');
+ };
+
+ const handleLinkDetected = (state: CurrentLinkState) => {
+ console.log(state);
+ setCurrentLink(state);
+ };
+
+ const handleSelectionChangeEvent = (sel: OnChangeSelectionEvent) => {
+ setSelection(sel);
+ };
+
+ return (
+ <>
+
+ Enriched Text Input
+
+ handleChangeText(e.nativeEvent)}
+ onChangeHtml={(e) => handleChangeHtml(e.nativeEvent)}
+ onChangeState={(e) => handleChangeState(e.nativeEvent)}
+ onLinkDetected={handleLinkDetected}
+ onMentionDetected={console.log}
+ onStartMention={handleStartMention}
+ onChangeMention={handleChangeMention}
+ onEndMention={handleEndMention}
+ onFocus={handleFocusEvent}
+ onBlur={handleBlurEvent}
+ onChangeSelection={(e) => handleSelectionChangeEvent(e.nativeEvent)}
+ androidExperimentalSynchronousEvents={
+ ANDROID_EXPERIMENTAL_SYNCHRONOUS_EVENTS
+ }
+ />
+
+
+
+
+
+
+
+ navigate('Preview', { html: currentHtml })}
+ />
+
+ {DEBUG_SCROLLABLE && }
+
+
+
+
+
+
+ >
+ );
+}
+
+const htmlStyle: HtmlStyle = {
+ h1: {
+ fontSize: 40,
+ bold: true,
+ },
+ h2: {
+ fontSize: 32,
+ bold: true,
+ },
+ h3: {
+ fontSize: 24,
+ bold: true,
+ },
+ blockquote: {
+ borderColor: 'navy',
+ borderWidth: 4,
+ gapWidth: 16,
+ color: 'navy',
+ },
+ codeblock: {
+ color: 'green',
+ borderRadius: 8,
+ backgroundColor: 'aquamarine',
+ },
+ code: {
+ color: 'purple',
+ backgroundColor: 'yellow',
+ },
+ a: {
+ color: 'green',
+ textDecorationLine: 'underline',
+ },
+ mention: {
+ '#': {
+ color: 'blue',
+ backgroundColor: 'lightblue',
+ textDecorationLine: 'underline',
+ },
+ '@': {
+ color: 'green',
+ backgroundColor: 'lightgreen',
+ textDecorationLine: 'none',
+ },
+ },
+ ol: {
+ gapWidth: 16,
+ marginLeft: 24,
+ markerColor: 'navy',
+ markerFontWeight: 'bold',
+ },
+ ul: {
+ bulletColor: 'aquamarine',
+ bulletSize: 8,
+ marginLeft: 24,
+ gapWidth: 16,
+ },
+};
+
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ backgroundColor: 'white',
+ },
+ content: {
+ flexGrow: 1,
+ padding: 16,
+ alignItems: 'center',
+ },
+ editor: {
+ width: '100%',
+ },
+ label: {
+ fontSize: 24,
+ fontWeight: 'bold',
+ textAlign: 'center',
+ color: 'rgb(0, 26, 114)',
+ },
+ buttonStack: {
+ flexDirection: 'row',
+ alignItems: 'center',
+ justifyContent: 'space-between',
+ width: '100%',
+ },
+ button: {
+ width: '45%',
+ },
+ valueButton: {
+ width: '100%',
+ },
+ editorInput: {
+ marginTop: 24,
+ width: '100%',
+ maxHeight: 180,
+ backgroundColor: 'gainsboro',
+ fontSize: 18,
+ fontFamily: 'Nunito-Regular',
+ paddingVertical: 12,
+ paddingHorizontal: 14,
+ },
+ scrollPlaceholder: {
+ marginTop: 24,
+ width: '100%',
+ height: 1000,
+ backgroundColor: 'rgb(0, 26, 114)',
+ },
+});
diff --git a/example/src/utils/prepareImageDimensions.ts b/example/src/screens/EditorScreen/utils/prepareImageDimensions.ts
similarity index 100%
rename from example/src/utils/prepareImageDimensions.ts
rename to example/src/screens/EditorScreen/utils/prepareImageDimensions.ts
diff --git a/example/src/screens/MainScreen.tsx b/example/src/screens/MainScreen.tsx
new file mode 100644
index 000000000..ec96e231f
--- /dev/null
+++ b/example/src/screens/MainScreen.tsx
@@ -0,0 +1,22 @@
+import { View, Text, Button, StyleSheet } from 'react-native';
+import type { NativeStackScreenProps } from '@react-navigation/native-stack';
+import type { RootStackParamList } from '.././App';
+
+type Props = NativeStackScreenProps;
+
+export function MainScreen({ navigation }: Props) {
+ return (
+
+ Main Screen
+ navigation.navigate('Editor')}
+ />
+
+ );
+}
+
+const styles = StyleSheet.create({
+ container: { flex: 1, alignItems: 'center', justifyContent: 'center' },
+ title: { fontSize: 24, fontWeight: 'bold' },
+});
diff --git a/example/src/screens/PreviewScreen.tsx b/example/src/screens/PreviewScreen.tsx
new file mode 100644
index 000000000..8668caf00
--- /dev/null
+++ b/example/src/screens/PreviewScreen.tsx
@@ -0,0 +1,27 @@
+import { ScrollView, Text, StyleSheet } from 'react-native';
+import type { NativeStackScreenProps } from '@react-navigation/native-stack';
+import type { RootStackParamList } from '../App';
+
+type Props = NativeStackScreenProps;
+
+export function PreviewScreen({ route }: Props) {
+ const { html } = route.params;
+
+ return (
+
+ Preview
+ {html || LOREM}
+
+ );
+}
+
+const LOREM = `
+Lorem ipsum dolor sit amet, consectetur adipiscing elit.
+Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
+Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris.
+`.repeat(10);
+
+const styles = StyleSheet.create({
+ container: { padding: 16 },
+ title: { fontSize: 22, fontWeight: 'bold', marginBottom: 12 },
+});
diff --git a/ios/EnrichedTextInputView.h b/ios/EnrichedTextInputView.h
index 9bf2c3dd8..2fa673f5c 100644
--- a/ios/EnrichedTextInputView.h
+++ b/ios/EnrichedTextInputView.h
@@ -31,7 +31,6 @@ NS_ASSUME_NONNULL_BEGIN
@public
BOOL blockEmitting;
}
-- (CGSize)measureSize:(CGFloat)maxWidth;
- (void)emitOnLinkDetectedEvent:(NSString *)text
url:(NSString *)url
range:(NSRange)range;
diff --git a/ios/EnrichedTextInputView.mm b/ios/EnrichedTextInputView.mm
index f24994cfe..1613dca6c 100644
--- a/ios/EnrichedTextInputView.mm
+++ b/ios/EnrichedTextInputView.mm
@@ -71,8 +71,7 @@ - (instancetype)initWithFrame:(CGRect)frame {
_props = defaultProps;
[self setDefaults];
[self setupTextView];
- [self setupPlaceholderLabel];
- self.contentView = textView;
+ [self addSubview:textView];
}
return self;
}
@@ -358,7 +357,9 @@ - (void)setupTextView {
textView.delegate = self;
textView.input = self;
textView.layoutManager.input = self;
- TextBlockTapGestureRecognizer *blockTap =
+ textView.autoresizingMask =
+ UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
+ TextBlockTapGestureRecognizer *blockTap =
[[TextBlockTapGestureRecognizer alloc]
initWithTarget:self
action:@selector(onTextBlockTap:)];
@@ -372,25 +373,7 @@ - (void)setupTextView {
for (UIGestureRecognizer *gr in textView.gestureRecognizers) {
[gr requireGestureRecognizerToFail:blockTap];
}
- [textView addGestureRecognizer:blockTap];
-}
-
-- (void)setupPlaceholderLabel {
- _placeholderLabel = [[UILabel alloc] initWithFrame:CGRectZero];
- _placeholderLabel.translatesAutoresizingMaskIntoConstraints = NO;
- [textView addSubview:_placeholderLabel];
- [NSLayoutConstraint activateConstraints:@[
- [_placeholderLabel.leadingAnchor
- constraintEqualToAnchor:textView.leadingAnchor],
- [_placeholderLabel.widthAnchor
- constraintEqualToAnchor:textView.widthAnchor],
- [_placeholderLabel.topAnchor constraintEqualToAnchor:textView.topAnchor],
- [_placeholderLabel.bottomAnchor
- constraintEqualToAnchor:textView.bottomAnchor]
- ]];
- _placeholderLabel.lineBreakMode = NSLineBreakByTruncatingTail;
- _placeholderLabel.text = @"";
- _placeholderLabel.hidden = YES;
+ [textView addGestureRecognizer:blockTap];
}
// MARK: - Props
@@ -891,9 +874,6 @@ - (void)updateProps:(Props::Shared const &)props
[[NSParagraphStyle alloc] init];
textView.typingAttributes = defaultTypingAttributes;
textView.selectedRange = prevSelectedRange;
-
- // update the placeholder as well
- [self refreshPlaceholderLabelStyles];
}
// editable
@@ -920,24 +900,14 @@ - (void)updateProps:(Props::Shared const &)props
// placeholderTextColor
if (newViewProps.placeholderTextColor != oldViewProps.placeholderTextColor) {
- // some real color
- if (isColorMeaningful(newViewProps.placeholderTextColor)) {
- _placeholderColor =
- RCTUIColorFromSharedColor(newViewProps.placeholderTextColor);
- } else {
- _placeholderColor = nullptr;
- }
- [self refreshPlaceholderLabelStyles];
+ textView.placeholderColor =
+ RCTUIColorFromSharedColor(newViewProps.placeholderTextColor);
}
// placeholder
if (newViewProps.placeholder != oldViewProps.placeholder) {
- _placeholderLabel.text = [NSString fromCppString:newViewProps.placeholder];
- [self refreshPlaceholderLabelStyles];
- // additionally show placeholder on first mount if it should be there
- if (isFirstMount && textView.text.length == 0) {
- [self setPlaceholderLabelShown:YES];
- }
+ [textView
+ setPlaceholderText:[NSString fromCppString:newViewProps.placeholder]];
}
// mention indicators
@@ -1006,40 +976,17 @@ - (void)updateProps:(Props::Shared const &)props
if (isFirstMount && newViewProps.autoFocus) {
[textView reactFocus];
}
+ [textView updatePlaceholderVisibility];
}
-- (void)setPlaceholderLabelShown:(BOOL)shown {
- if (shown) {
- [self refreshPlaceholderLabelStyles];
- _placeholderLabel.hidden = NO;
- } else {
- _placeholderLabel.hidden = YES;
- }
-}
+- (void)updateLayoutMetrics:(const LayoutMetrics &)layoutMetrics
+ oldLayoutMetrics:(const LayoutMetrics &)oldLayoutMetrics {
+ [super updateLayoutMetrics:layoutMetrics oldLayoutMetrics:oldLayoutMetrics];
-- (void)refreshPlaceholderLabelStyles {
- NSMutableDictionary *newAttrs = [defaultTypingAttributes mutableCopy];
- if (_placeholderColor != nullptr) {
- newAttrs[NSForegroundColorAttributeName] = _placeholderColor;
- }
- NSAttributedString *newAttrStr =
- [[NSAttributedString alloc] initWithString:_placeholderLabel.text
- attributes:newAttrs];
- _placeholderLabel.attributedText = newAttrStr;
-}
-
-// MARK: - Measuring and states
-- (CGSize)measureSize:(CGFloat)maxWidth {
- NSTextContainer *container = textView.textContainer;
- NSLayoutManager *layoutManager = textView.layoutManager;
-
- container.size = CGSizeMake(maxWidth, CGFLOAT_MAX);
- [layoutManager ensureLayoutForTextContainer:container];
-
- CGRect usedRect = [layoutManager usedRectForTextContainer:container];
- CGSize contentSize = CGSizeMake(maxWidth, ceil(usedRect.size.height));
- textView.contentSize = contentSize;
- return contentSize;
+ textView.frame = UIEdgeInsetsInsetRect(
+ self.bounds, RCTUIEdgeInsetsFromEdgeInsets(layoutMetrics.borderWidth));
+ textView.textContainerInset = RCTUIEdgeInsetsFromEdgeInsets(
+ layoutMetrics.contentInsets - layoutMetrics.borderWidth);
}
// make sure the newest state is kept in _state property
@@ -1052,18 +999,22 @@ - (void)updateState:(State::Shared const &)state
// componentView) so we need to run a single height calculation for any
// initial values
if (oldState == nullptr) {
- [self tryUpdatingHeight];
+ [self commitState];
}
}
-- (void)tryUpdatingHeight {
+- (void)commitState {
if (_state == nullptr) {
return;
}
- _componentViewHeightUpdateCounter++;
- auto selfRef = wrapManagedObjectWeakly(self);
- _state->updateState(
- EnrichedTextInputViewState(_componentViewHeightUpdateCounter, selfRef));
+ NSAttributedString *currentAttributedText = [textView.attributedText copy];
+ NSAttributedString *snapshot =
+ currentAttributedText && currentAttributedText.length > 0
+ ? currentAttributedText
+ : [[NSAttributedString alloc]
+ initWithString:@"I"
+ attributes:textView.typingAttributes];
+ _state->updateState(EnrichedTextInputViewState(snapshot));
}
// MARK: - Active styles
@@ -1758,12 +1709,7 @@ - (void)anyTextMayHaveBeenModified {
}
// placholder management
- if (!_placeholderLabel.hidden && textView.textStorage.string.length > 0) {
- [self setPlaceholderLabelShown:NO];
- } else if (textView.textStorage.string.length == 0 &&
- _placeholderLabel.hidden) {
- [self setPlaceholderLabelShown:YES];
- }
+ [textView updatePlaceholderVisibility];
if (![textView.textStorage.string isEqualToString:_recentInputString]) {
// modified words handling
@@ -1800,7 +1746,7 @@ - (void)anyTextMayHaveBeenModified {
}
// update height on each character change
- [self tryUpdatingHeight];
+ [self commitState];
// update active styles as well
[self tryUpdatingActiveStyles];
}
diff --git a/ios/inputTextView/InputTextView.h b/ios/inputTextView/InputTextView.h
index 6ddac2e91..498ae68b3 100644
--- a/ios/inputTextView/InputTextView.h
+++ b/ios/inputTextView/InputTextView.h
@@ -3,4 +3,7 @@
@interface InputTextView : UITextView
@property(nonatomic, weak) id input;
+@property(nonatomic, copy, nullable) NSString *placeholderText;
+@property(nonatomic, strong, nullable) UIColor *placeholderColor;
+- (void)updatePlaceholderVisibility;
@end
diff --git a/ios/inputTextView/InputTextView.mm b/ios/inputTextView/InputTextView.mm
index a92d4c0f2..8f0ba994c 100644
--- a/ios/inputTextView/InputTextView.mm
+++ b/ios/inputTextView/InputTextView.mm
@@ -4,7 +4,23 @@
#import "TextInsertionUtils.h"
#import
-@implementation InputTextView
+@implementation InputTextView {
+ UILabel *placeholderView;
+};
+
+- (instancetype)initWithFrame:(CGRect)frame {
+ if ((self = [super initWithFrame:frame])) {
+ placeholderView = [[UILabel alloc] initWithFrame:self.bounds];
+ placeholderView.isAccessibilityElement = NO;
+ placeholderView.numberOfLines = 0;
+ [self addSubview:placeholderView];
+
+ self.textContainer.lineFragmentPadding = 0;
+ self.scrollEnabled = YES;
+ self.scrollsToTop = NO;
+ }
+ return self;
+}
- (void)copy:(id)sender {
EnrichedTextInputView *typedInput = (EnrichedTextInputView *)_input;
@@ -148,4 +164,49 @@ - (void)cut:(id)sender {
[typedInput anyTextMayHaveBeenModified];
}
+- (void)updatePlaceholderVisibility {
+ BOOL shouldShow =
+ self.placeholderText.length > 0 && self.textStorage.length == 0;
+
+ placeholderView.hidden = !shouldShow;
+}
+
+- (void)setText:(NSString *)text {
+ [super setText:text];
+ [self updatePlaceholderVisibility];
+}
+
+- (void)setAttributedText:(NSAttributedString *)attributedText {
+ [super setAttributedText:attributedText];
+ [self updatePlaceholderVisibility];
+}
+
+- (void)setPlaceholderText:(NSString *)newPlaceholderText {
+ EnrichedTextInputView *typedInput = (EnrichedTextInputView *)_input;
+ if (typedInput == nullptr) {
+ return;
+ }
+ _placeholderText = newPlaceholderText;
+ BOOL hasPlaceholder = newPlaceholderText && newPlaceholderText.length > 0;
+ NSString *placeholderText = hasPlaceholder ? newPlaceholderText : @"";
+ NSMutableDictionary *attributes =
+ [typedInput->defaultTypingAttributes mutableCopy];
+ attributes[NSForegroundColorAttributeName] = _placeholderColor;
+ placeholderView.attributedText =
+ [[NSAttributedString alloc] initWithString:placeholderText
+ attributes:attributes];
+ [self setNeedsLayout];
+}
+
+- (void)layoutSubviews {
+ [super layoutSubviews];
+
+ CGRect textFrame =
+ UIEdgeInsetsInsetRect(self.bounds, self.textContainerInset);
+ CGFloat placeholderHeight =
+ [placeholderView sizeThatFits:textFrame.size].height;
+ textFrame.size.height = MIN(placeholderHeight, textFrame.size.height);
+ placeholderView.frame = textFrame;
+}
+
@end
diff --git a/ios/internals/EnrichedTextInputViewShadowNode.h b/ios/internals/EnrichedTextInputViewShadowNode.h
index fc1359880..939a6b1f1 100644
--- a/ios/internals/EnrichedTextInputViewShadowNode.h
+++ b/ios/internals/EnrichedTextInputViewShadowNode.h
@@ -6,6 +6,8 @@
#include
#include
+#import
+
namespace facebook::react {
JSI_EXPORT extern const char EnrichedTextInputViewComponentName[];
@@ -17,14 +19,17 @@ class EnrichedTextInputViewShadowNode
: public ConcreteViewShadowNode<
EnrichedTextInputViewComponentName, EnrichedTextInputViewProps,
EnrichedTextInputViewEventEmitter, EnrichedTextInputViewState> {
+
public:
using ConcreteViewShadowNode::ConcreteViewShadowNode;
+
EnrichedTextInputViewShadowNode(const ShadowNodeFragment &fragment,
const ShadowNodeFamily::Shared &family,
ShadowNodeTraits traits);
EnrichedTextInputViewShadowNode(const ShadowNode &sourceShadowNode,
const ShadowNodeFragment &fragment);
void dirtyLayoutIfNeeded();
+
Size
measureContent(const LayoutContext &layoutContext,
const LayoutConstraints &layoutConstraints) const override;
@@ -37,8 +42,12 @@ class EnrichedTextInputViewShadowNode
}
private:
- int localForceHeightRecalculationCounter_;
- id setupMockTextInputView_() const;
+ NSAttributedString *getAttributedString() const;
+ void createTextStorage() const;
+ mutable NSTextStorage *textStorage_ = nil;
+ mutable NSLayoutManager *layoutManager_ = nil;
+ mutable NSTextContainer *textContainer_ = nil;
+ mutable NSAttributedString *prevAttributedText_ = nil;
};
} // namespace facebook::react
diff --git a/ios/internals/EnrichedTextInputViewShadowNode.mm b/ios/internals/EnrichedTextInputViewShadowNode.mm
index 6d560564e..508712837 100644
--- a/ios/internals/EnrichedTextInputViewShadowNode.mm
+++ b/ios/internals/EnrichedTextInputViewShadowNode.mm
@@ -1,6 +1,5 @@
#import "EnrichedTextInputViewShadowNode.h"
-#import "CoreText/CoreText.h"
-#import
+
#import
#import
#import
@@ -10,25 +9,36 @@
extern const char EnrichedTextInputViewComponentName[] =
"EnrichedTextInputView";
+void EnrichedTextInputViewShadowNode::createTextStorage() const {
+ if (textStorage_) {
+ return;
+ }
+
+ textContainer_ = [NSTextContainer new];
+ textContainer_.lineFragmentPadding = 0;
+ textContainer_.maximumNumberOfLines = 0;
+
+ layoutManager_ = [NSLayoutManager new];
+ [layoutManager_ addTextContainer:textContainer_];
+
+ textStorage_ = [NSTextStorage new];
+ [textStorage_ addLayoutManager:layoutManager_];
+ prevAttributedText_ = [NSAttributedString alloc];
+}
+
+void EnrichedTextInputViewShadowNode::dirtyLayoutIfNeeded() {
+ const auto state = this->getStateData();
+ if (![prevAttributedText_
+ isEqualToAttributedString:state.getAttributedText()]) {
+ YGNodeMarkDirty(&yogaNode_);
+ }
+}
+
EnrichedTextInputViewShadowNode::EnrichedTextInputViewShadowNode(
const ShadowNodeFragment &fragment, const ShadowNodeFamily::Shared &family,
ShadowNodeTraits traits)
: ConcreteViewShadowNode(fragment, family, traits) {
- localForceHeightRecalculationCounter_ = 0;
-}
-
-// mock input is used for the first measure calls that need to be done when the
-// real input isn't defined yet
-id EnrichedTextInputViewShadowNode::setupMockTextInputView_() const {
- // it's rendered far away from the viewport
- const int veryFarAway = 20000;
- const int mockSize = 1000;
- EnrichedTextInputView *mockTextInputView_ = [[EnrichedTextInputView alloc]
- initWithFrame:(CGRectMake(veryFarAway, veryFarAway, mockSize, mockSize))];
- const auto props = this->getProps();
- mockTextInputView_->blockEmitting = YES;
- [mockTextInputView_ updateProps:props oldProps:nullptr];
- return mockTextInputView_;
+ createTextStorage();
}
EnrichedTextInputViewShadowNode::EnrichedTextInputViewShadowNode(
@@ -37,67 +47,46 @@
dirtyLayoutIfNeeded();
}
-void EnrichedTextInputViewShadowNode::dirtyLayoutIfNeeded() {
- const auto state = this->getStateData();
- const int receivedCounter = state.getForceHeightRecalculationCounter();
+NSAttributedString *
+EnrichedTextInputViewShadowNode::getAttributedString() const {
+ NSAttributedString *attributedText = getStateData().getAttributedText();
- if (receivedCounter > localForceHeightRecalculationCounter_) {
- localForceHeightRecalculationCounter_ = receivedCounter;
- YGNodeMarkDirty(&yogaNode_);
+ if (!attributedText || attributedText.length == 0) {
+ // Fallback to a measurable placeholder
+ return [[NSAttributedString alloc] initWithString:@"I"];
}
+
+ return attributedText;
}
Size EnrichedTextInputViewShadowNode::measureContent(
- const LayoutContext &layoutContext,
- const LayoutConstraints &layoutConstraints) const {
- const auto state = this->getStateData();
- const auto componentRef = state.getComponentViewRef();
- RCTInternalGenericWeakWrapper *weakWrapper =
- (RCTInternalGenericWeakWrapper *)unwrapManagedObject(componentRef);
-
- if (weakWrapper != nullptr) {
- id componentObject = weakWrapper.object;
- EnrichedTextInputView *typedComponentObject =
- (EnrichedTextInputView *)componentObject;
-
- if (typedComponentObject != nullptr) {
- __block CGSize estimatedSize;
-
- // synchronously dispatch to main thread if needed
- if ([NSThread isMainThread]) {
- estimatedSize = [typedComponentObject
- measureSize:layoutConstraints.maximumSize.width];
- } else {
- dispatch_sync(dispatch_get_main_queue(), ^{
- estimatedSize = [typedComponentObject
- measureSize:layoutConstraints.maximumSize.width];
- });
- }
-
- return {estimatedSize.width,
- MIN(estimatedSize.height, layoutConstraints.maximumSize.height)};
- }
- } else {
- __block CGSize estimatedSize;
-
- // synchronously dispatch to main thread if needed
- if ([NSThread isMainThread]) {
- EnrichedTextInputView *mockTextInputView = setupMockTextInputView_();
- estimatedSize =
- [mockTextInputView measureSize:layoutConstraints.maximumSize.width];
- } else {
- dispatch_sync(dispatch_get_main_queue(), ^{
- EnrichedTextInputView *mockTextInputView = setupMockTextInputView_();
- estimatedSize =
- [mockTextInputView measureSize:layoutConstraints.maximumSize.width];
- });
- }
-
- return {estimatedSize.width,
- MIN(estimatedSize.height, layoutConstraints.maximumSize.height)};
- }
+ const LayoutContext &, const LayoutConstraints &constraints) const {
+
+ createTextStorage();
+
+ NSAttributedString *attributedText = getAttributedString();
+
+ CGSize maxSize = {constraints.maximumSize.width,
+ constraints.maximumSize.height ==
+ std::numeric_limits::infinity()
+ ? CGFLOAT_MAX
+ : constraints.maximumSize.height};
+
+ textContainer_.size = maxSize;
+
+ [textStorage_ replaceCharactersInRange:NSMakeRange(0, textStorage_.length)
+ withAttributedString:attributedText];
+
+ [layoutManager_ ensureLayoutForTextContainer:textContainer_];
+
+ CGSize usedSize =
+ [layoutManager_ usedRectForTextContainer:textContainer_].size;
+
+ auto width = std::min((Float)usedSize.width, constraints.maximumSize.width);
+ auto height =
+ std::min((Float)usedSize.height, constraints.maximumSize.height);
- return Size();
+ return Size(width, height);
}
} // namespace facebook::react
diff --git a/ios/internals/EnrichedTextInputViewState.cpp b/ios/internals/EnrichedTextInputViewState.cpp
deleted file mode 100644
index 6d0eea37f..000000000
--- a/ios/internals/EnrichedTextInputViewState.cpp
+++ /dev/null
@@ -1,10 +0,0 @@
-#include "EnrichedTextInputViewState.h"
-
-namespace facebook::react {
- int EnrichedTextInputViewState::getForceHeightRecalculationCounter() const {
- return forceHeightRecalculationCounter_;
- }
- std::shared_ptr EnrichedTextInputViewState::getComponentViewRef() const {
- return componentViewRef_;
- }
-} // namespace facebook::react
diff --git a/ios/internals/EnrichedTextInputViewState.h b/ios/internals/EnrichedTextInputViewState.h
index 3da93fe50..820a8c2aa 100644
--- a/ios/internals/EnrichedTextInputViewState.h
+++ b/ios/internals/EnrichedTextInputViewState.h
@@ -1,22 +1,21 @@
#pragma once
#include
+@class NSAttributedString;
+
namespace facebook::react {
class EnrichedTextInputViewState {
public:
- EnrichedTextInputViewState()
- : forceHeightRecalculationCounter_(0), componentViewRef_(nullptr) {}
- EnrichedTextInputViewState(int counter, std::shared_ptr ref) {
- forceHeightRecalculationCounter_ = counter;
- componentViewRef_ = ref;
- }
- int getForceHeightRecalculationCounter() const;
- std::shared_ptr getComponentViewRef() const;
+ EnrichedTextInputViewState() = default;
+
+ explicit EnrichedTextInputViewState(NSAttributedString *attributedText)
+ : attributedText_(attributedText) {}
+
+ NSAttributedString *getAttributedText() const { return attributedText_; }
private:
- int forceHeightRecalculationCounter_{};
- std::shared_ptr componentViewRef_{};
+ NSAttributedString *attributedText_ = nullptr;
};
} // namespace facebook::react
diff --git a/ios/utils/LayoutManagerExtension.mm b/ios/utils/LayoutManagerExtension.mm
index 5d1cb6cea..36f0fb140 100644
--- a/ios/utils/LayoutManagerExtension.mm
+++ b/ios/utils/LayoutManagerExtension.mm
@@ -375,11 +375,11 @@ - (void)drawLists:(EnrichedTextInputView *)typedInput
CGFloat bulletSize =
[typedInput->config
unorderedListBulletSize];
- CGFloat bulletX = usedRect.origin.x -
- gapWidth -
- bulletSize / 2;
+ CGFloat bulletX =
+ origin.x + usedRect.origin.x -
+ bulletSize / 2 - gapWidth;
CGFloat centerY =
- CGRectGetMidY(usedRect);
+ CGRectGetMidY(usedRect) + origin.y;
CGContextRef context =
UIGraphicsGetCurrentContext();
diff --git a/yarn.lock b/yarn.lock
index 4c717b651..747f72d4f 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1962,6 +1962,15 @@ __metadata:
languageName: node
linkType: hard
+"@egjs/hammerjs@npm:^2.0.17":
+ version: 2.0.17
+ resolution: "@egjs/hammerjs@npm:2.0.17"
+ dependencies:
+ "@types/hammerjs": ^2.0.36
+ checksum: 8945137cec5837edd70af3f2e0ea621543eb0aa3b667e6269ec6485350f4d120c2434b37c7c30b1cf42a65275dd61c1f24626749c616696d3956ac0c008c4766
+ languageName: node
+ linkType: hard
+
"@esbuild/aix-ppc64@npm:0.25.12":
version: 0.25.12
resolution: "@esbuild/aix-ppc64@npm:0.25.12"
@@ -3566,6 +3575,87 @@ __metadata:
languageName: node
linkType: hard
+"@react-navigation/core@npm:^7.13.7":
+ version: 7.13.7
+ resolution: "@react-navigation/core@npm:7.13.7"
+ dependencies:
+ "@react-navigation/routers": ^7.5.3
+ escape-string-regexp: ^4.0.0
+ fast-deep-equal: ^3.1.3
+ nanoid: ^3.3.11
+ query-string: ^7.1.3
+ react-is: ^19.1.0
+ use-latest-callback: ^0.2.4
+ use-sync-external-store: ^1.5.0
+ peerDependencies:
+ react: ">= 18.2.0"
+ checksum: aa5870970c2e3605bc310483a218fc6d1ec47e6fc5b4dc61d12ed8663abb6104c317f92292c7bf226175f9c5dfbc51e8cea7a2ece2b9d0d308f452dbed672b4f
+ languageName: node
+ linkType: hard
+
+"@react-navigation/elements@npm:^2.9.3":
+ version: 2.9.3
+ resolution: "@react-navigation/elements@npm:2.9.3"
+ dependencies:
+ color: ^4.2.3
+ use-latest-callback: ^0.2.4
+ use-sync-external-store: ^1.5.0
+ peerDependencies:
+ "@react-native-masked-view/masked-view": ">= 0.2.0"
+ "@react-navigation/native": ^7.1.26
+ react: ">= 18.2.0"
+ react-native: "*"
+ react-native-safe-area-context: ">= 4.0.0"
+ peerDependenciesMeta:
+ "@react-native-masked-view/masked-view":
+ optional: true
+ checksum: d202151d7003e80fce3ffa69a0ad8854f191ba7e4383201cde7ea672f6a922c9bea165453e70fb660028cc5485aa2a1f915783643218dc7647312b4de2ce48f3
+ languageName: node
+ linkType: hard
+
+"@react-navigation/native-stack@npm:^7.9.0":
+ version: 7.9.0
+ resolution: "@react-navigation/native-stack@npm:7.9.0"
+ dependencies:
+ "@react-navigation/elements": ^2.9.3
+ color: ^4.2.3
+ sf-symbols-typescript: ^2.1.0
+ warn-once: ^0.1.1
+ peerDependencies:
+ "@react-navigation/native": ^7.1.26
+ react: ">= 18.2.0"
+ react-native: "*"
+ react-native-safe-area-context: ">= 4.0.0"
+ react-native-screens: ">= 4.0.0"
+ checksum: 8c0d3f70f4322c853b5a8d8019f162ec1be0131f485954e53338cb505a663884ed697bb4101dcb2687dc836d00fc357ea1618639e62096c1e1c4232fe89fba11
+ languageName: node
+ linkType: hard
+
+"@react-navigation/native@npm:^7.1.26":
+ version: 7.1.26
+ resolution: "@react-navigation/native@npm:7.1.26"
+ dependencies:
+ "@react-navigation/core": ^7.13.7
+ escape-string-regexp: ^4.0.0
+ fast-deep-equal: ^3.1.3
+ nanoid: ^3.3.11
+ use-latest-callback: ^0.2.4
+ peerDependencies:
+ react: ">= 18.2.0"
+ react-native: "*"
+ checksum: 37d41b358b33ed5e9b1cddea62f8d3f9a60e160d89102609ce700003adeaab8df8e41db1c534f2d59acb4f279cc09e624f31298030d25beb06269c736e8230b9
+ languageName: node
+ linkType: hard
+
+"@react-navigation/routers@npm:^7.5.3":
+ version: 7.5.3
+ resolution: "@react-navigation/routers@npm:7.5.3"
+ dependencies:
+ nanoid: ^3.3.11
+ checksum: 1b8397ade6bbab51a60d2671fd88eca2e0cf22b9cd10bee16d3537bc5f05deea7dad8c116a809f580c87c5a6cceae7c4fc9f20644f45076ee8f00524e903fc4b
+ languageName: node
+ linkType: hard
+
"@release-it/conventional-changelog@npm:^9.0.2":
version: 9.0.4
resolution: "@release-it/conventional-changelog@npm:9.0.4"
@@ -3877,6 +3967,13 @@ __metadata:
languageName: node
linkType: hard
+"@types/hammerjs@npm:^2.0.36":
+ version: 2.0.46
+ resolution: "@types/hammerjs@npm:2.0.46"
+ checksum: caba6ec788d19905c71092670b58514b3d1f5eee5382bf9205e8df688d51e7857b7994e2dd7aed57fac8977bdf0e456d67fbaf23440a4385b8ce25fe2af1ec39
+ languageName: node
+ linkType: hard
+
"@types/istanbul-lib-coverage@npm:*, @types/istanbul-lib-coverage@npm:^2.0.0, @types/istanbul-lib-coverage@npm:^2.0.1":
version: 2.0.6
resolution: "@types/istanbul-lib-coverage@npm:2.0.6"
@@ -4410,6 +4507,13 @@ __metadata:
languageName: node
linkType: hard
+"add@npm:^2.0.6":
+ version: 2.0.6
+ resolution: "add@npm:2.0.6"
+ checksum: e2d23d40494565dfed4acd65e478570c444db5ac6c053551ed429c39ea0f2c99d83df63e7befec936df601827d2254d06a2fb6f7dcfd2022e810b25eab818b8c
+ languageName: node
+ linkType: hard
+
"agent-base@npm:^7.1.0, agent-base@npm:^7.1.2":
version: 7.1.3
resolution: "agent-base@npm:7.1.3"
@@ -5462,13 +5566,33 @@ __metadata:
languageName: node
linkType: hard
-"color-name@npm:~1.1.4":
+"color-name@npm:^1.0.0, color-name@npm:~1.1.4":
version: 1.1.4
resolution: "color-name@npm:1.1.4"
checksum: b0445859521eb4021cd0fb0cc1a75cecf67fceecae89b63f62b201cca8d345baf8b952c966862a9d9a2632987d4f6581f0ec8d957dfacece86f0a7919316f610
languageName: node
linkType: hard
+"color-string@npm:^1.9.0":
+ version: 1.9.1
+ resolution: "color-string@npm:1.9.1"
+ dependencies:
+ color-name: ^1.0.0
+ simple-swizzle: ^0.2.2
+ checksum: c13fe7cff7885f603f49105827d621ce87f4571d78ba28ef4a3f1a104304748f620615e6bf065ecd2145d0d9dad83a3553f52bb25ede7239d18e9f81622f1cc5
+ languageName: node
+ linkType: hard
+
+"color@npm:^4.2.3":
+ version: 4.2.3
+ resolution: "color@npm:4.2.3"
+ dependencies:
+ color-convert: ^2.0.1
+ color-string: ^1.9.0
+ checksum: 0579629c02c631b426780038da929cca8e8d80a40158b09811a0112a107c62e10e4aad719843b791b1e658ab4e800558f2e87ca4522c8b32349d497ecb6adeb4
+ languageName: node
+ linkType: hard
+
"colorette@npm:^1.0.7":
version: 1.4.0
resolution: "colorette@npm:1.4.0"
@@ -6015,6 +6139,13 @@ __metadata:
languageName: node
linkType: hard
+"decode-uri-component@npm:^0.2.2":
+ version: 0.2.2
+ resolution: "decode-uri-component@npm:0.2.2"
+ checksum: 95476a7d28f267292ce745eac3524a9079058bbb35767b76e3ee87d42e34cd0275d2eb19d9d08c3e167f97556e8a2872747f5e65cbebcac8b0c98d83e285f139
+ languageName: node
+ linkType: hard
+
"dedent@npm:^0.7.0":
version: 0.7.0
resolution: "dedent@npm:0.7.0"
@@ -7281,6 +7412,13 @@ __metadata:
languageName: node
linkType: hard
+"filter-obj@npm:^1.1.0":
+ version: 1.1.0
+ resolution: "filter-obj@npm:1.1.0"
+ checksum: cf2104a7c45ff48e7f505b78a3991c8f7f30f28bd8106ef582721f321f1c6277f7751aacd5d83026cb079d9d5091082f588d14a72e7c5d720ece79118fa61e10
+ languageName: node
+ linkType: hard
+
"finalhandler@npm:1.1.2":
version: 1.1.2
resolution: "finalhandler@npm:1.1.2"
@@ -7995,6 +8133,15 @@ __metadata:
languageName: node
linkType: hard
+"hoist-non-react-statics@npm:^3.3.0":
+ version: 3.3.2
+ resolution: "hoist-non-react-statics@npm:3.3.2"
+ dependencies:
+ react-is: ^16.7.0
+ checksum: b1538270429b13901ee586aa44f4cc3ecd8831c061d06cb8322e50ea17b3f5ce4d0e2e66394761e6c8e152cd8c34fb3b4b690116c6ce2bd45b18c746516cb9e8
+ languageName: node
+ linkType: hard
+
"hosted-git-info@npm:^4.0.1":
version: 4.1.0
resolution: "hosted-git-info@npm:4.1.0"
@@ -8314,6 +8461,13 @@ __metadata:
languageName: node
linkType: hard
+"is-arrayish@npm:^0.3.1":
+ version: 0.3.4
+ resolution: "is-arrayish@npm:0.3.4"
+ checksum: 09816634eb7b6e357067f6b49c7656b4aff6d8b25486553d086bab53ce0f929c0293906539503b2a317f3137b5a5cd7e9ea01305f6090c0037c4340d9121420d
+ languageName: node
+ linkType: hard
+
"is-async-function@npm:^2.0.0":
version: 2.1.1
resolution: "is-async-function@npm:2.1.1"
@@ -11908,6 +12062,18 @@ __metadata:
languageName: node
linkType: hard
+"query-string@npm:^7.1.3":
+ version: 7.1.3
+ resolution: "query-string@npm:7.1.3"
+ dependencies:
+ decode-uri-component: ^0.2.2
+ filter-obj: ^1.1.0
+ split-on-first: ^1.0.0
+ strict-uri-encode: ^2.0.0
+ checksum: 91af02dcd9cc9227a052841d5c2eecb80a0d6489d05625df506a097ef1c59037cfb5e907f39b84643cbfd535c955abec3e553d0130a7b510120c37d06e0f4346
+ languageName: node
+ linkType: hard
+
"queue-microtask@npm:^1.2.2":
version: 1.2.3
resolution: "queue-microtask@npm:1.2.3"
@@ -11985,7 +12151,16 @@ __metadata:
languageName: node
linkType: hard
-"react-is@npm:^16.13.1":
+"react-freeze@npm:^1.0.0":
+ version: 1.0.4
+ resolution: "react-freeze@npm:1.0.4"
+ peerDependencies:
+ react: ">=17.0.0"
+ checksum: 6b4d93209dff04a1f25d9f8e0c56a9a8a80e7889e8e8267299f34449c7e41a9ab90cad24569d03dd7173b56b7496576dba68f71f1d4e5c8be72f0633023668bc
+ languageName: node
+ linkType: hard
+
+"react-is@npm:^16.13.1, react-is@npm:^16.7.0":
version: 16.13.1
resolution: "react-is@npm:16.13.1"
checksum: f7a19ac3496de32ca9ae12aa030f00f14a3d45374f1ceca0af707c831b2a6098ef0d6bdae51bd437b0a306d7f01d4677fcc8de7c0d331eb47ad0f46130e53c5f
@@ -11999,6 +12174,13 @@ __metadata:
languageName: node
linkType: hard
+"react-is@npm:^19.1.0":
+ version: 19.2.3
+ resolution: "react-is@npm:19.2.3"
+ checksum: 3bb317292dc574632ec33093d38b8ff97abb6dc400e7b0375baef9429f148cf5ae0307e37de97358f3fad07edd159cda8fcb9d28aaaf0dcd8d408ee320638b83
+ languageName: node
+ linkType: hard
+
"react-native-builder-bob@npm:^0.40.13":
version: 0.40.13
resolution: "react-native-builder-bob@npm:0.40.13"
@@ -12076,11 +12258,17 @@ __metadata:
"@react-native/babel-preset": 0.83.0
"@react-native/metro-config": 0.83.0
"@react-native/typescript-config": 0.83.0
+ "@react-navigation/native": ^7.1.26
+ "@react-navigation/native-stack": ^7.9.0
"@types/react": ^19.2.0
+ add: ^2.0.6
react: 19.2.0
react-native: 0.83.0
react-native-builder-bob: ^0.40.13
+ react-native-gesture-handler: ^2.29.1
react-native-image-picker: ^8.2.1
+ react-native-safe-area-context: ^5.6.2
+ react-native-screens: ^4.19.0
languageName: unknown
linkType: soft
@@ -12141,6 +12329,20 @@ __metadata:
languageName: unknown
linkType: soft
+"react-native-gesture-handler@npm:^2.29.1":
+ version: 2.29.1
+ resolution: "react-native-gesture-handler@npm:2.29.1"
+ dependencies:
+ "@egjs/hammerjs": ^2.0.17
+ hoist-non-react-statics: ^3.3.0
+ invariant: ^2.2.4
+ peerDependencies:
+ react: "*"
+ react-native: "*"
+ checksum: dddabdb12ce31d68ef71796e8fcaa57acd4608cca14412f36ce36fee14911fb629f325f0ced86bea1336a64673a434e34cde32a63be8d33f29d9a7bed292c5b2
+ languageName: node
+ linkType: hard
+
"react-native-image-picker@npm:^8.2.1":
version: 8.2.1
resolution: "react-native-image-picker@npm:8.2.1"
@@ -12161,6 +12363,29 @@ __metadata:
languageName: node
linkType: hard
+"react-native-safe-area-context@npm:^5.6.2":
+ version: 5.6.2
+ resolution: "react-native-safe-area-context@npm:5.6.2"
+ peerDependencies:
+ react: "*"
+ react-native: "*"
+ checksum: 7b15cdd07df4f3650cf443fb322ee2d51b3ab45c652789cbea4cb48a8e6fd2b66e2be01e9f63e614ceaf28d9d228af681ca8857b2ed8dabe48f23964076d40c3
+ languageName: node
+ linkType: hard
+
+"react-native-screens@npm:^4.19.0":
+ version: 4.19.0
+ resolution: "react-native-screens@npm:4.19.0"
+ dependencies:
+ react-freeze: ^1.0.0
+ warn-once: ^0.1.0
+ peerDependencies:
+ react: "*"
+ react-native: "*"
+ checksum: a9c02936d9e699acd1801bd58d6a3a4353b05f52cddefa453428b57d531af74d920f40cfa2b92595ed471001dc5bbd6f8f41580895aa5eb8247a44b5e593e125
+ languageName: node
+ linkType: hard
+
"react-native@npm:0.81.0":
version: 0.81.0
resolution: "react-native@npm:0.81.0"
@@ -13011,6 +13236,13 @@ __metadata:
languageName: node
linkType: hard
+"sf-symbols-typescript@npm:^2.1.0":
+ version: 2.2.0
+ resolution: "sf-symbols-typescript@npm:2.2.0"
+ checksum: e380b37afec5dbc9f3aced06c6e82ebe13d1bc25a3d5966fc52bcfa891cb56951dabbe8a98fc4d96ef86b2c556b23cf9686fc17df6c4aa1ec839f92ae280486c
+ languageName: node
+ linkType: hard
+
"shebang-command@npm:^2.0.0":
version: 2.0.0
resolution: "shebang-command@npm:2.0.0"
@@ -13109,6 +13341,15 @@ __metadata:
languageName: node
linkType: hard
+"simple-swizzle@npm:^0.2.2":
+ version: 0.2.4
+ resolution: "simple-swizzle@npm:0.2.4"
+ dependencies:
+ is-arrayish: ^0.3.1
+ checksum: 9a2f6f39a6b9fab68f96903523bf19953ec21e5e843108154cf47a9cc0f78955dd44f64499ffb71a849ac10c758d9fab7533627c7ca3ab40b5c177117acfdc1b
+ languageName: node
+ linkType: hard
+
"sisteransi@npm:^1.0.5":
version: 1.0.5
resolution: "sisteransi@npm:1.0.5"
@@ -13251,6 +13492,13 @@ __metadata:
languageName: node
linkType: hard
+"split-on-first@npm:^1.0.0":
+ version: 1.1.0
+ resolution: "split-on-first@npm:1.1.0"
+ checksum: 16ff85b54ddcf17f9147210a4022529b343edbcbea4ce977c8f30e38408b8d6e0f25f92cd35b86a524d4797f455e29ab89eb8db787f3c10708e0b47ebf528d30
+ languageName: node
+ linkType: hard
+
"split2@npm:^4.0.0":
version: 4.2.0
resolution: "split2@npm:4.2.0"
@@ -13327,6 +13575,13 @@ __metadata:
languageName: node
linkType: hard
+"strict-uri-encode@npm:^2.0.0":
+ version: 2.0.0
+ resolution: "strict-uri-encode@npm:2.0.0"
+ checksum: eaac4cf978b6fbd480f1092cab8b233c9b949bcabfc9b598dd79a758f7243c28765ef7639c876fa72940dac687181b35486ea01ff7df3e65ce3848c64822c581
+ languageName: node
+ linkType: hard
+
"string-length@npm:^4.0.1":
version: 4.0.2
resolution: "string-length@npm:4.0.2"
@@ -14189,6 +14444,24 @@ __metadata:
languageName: node
linkType: hard
+"use-latest-callback@npm:^0.2.4":
+ version: 0.2.6
+ resolution: "use-latest-callback@npm:0.2.6"
+ peerDependencies:
+ react: ">=16.8"
+ checksum: 67a245bf91b23ef0d2d2c8a52845da62e006867bd9d93a99ca4d2f859101fcd54c7afd4f5a3b8bb5d24283f516e7e41bd8226250ee39affc33bd1cfd622a5cfb
+ languageName: node
+ linkType: hard
+
+"use-sync-external-store@npm:^1.5.0":
+ version: 1.6.0
+ resolution: "use-sync-external-store@npm:1.6.0"
+ peerDependencies:
+ react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
+ checksum: 61a62e910713adfaf91bdb72ff2cd30e5ba83687accaf3b6e75a903b45bf635f5722e3694af30d83a03e92cb533c0a5c699298d2fef639a03ffc86b469f4eee2
+ languageName: node
+ linkType: hard
+
"util-deprecate@npm:^1.0.1, util-deprecate@npm:~1.0.1":
version: 1.0.2
resolution: "util-deprecate@npm:1.0.2"
@@ -14302,6 +14575,13 @@ __metadata:
languageName: node
linkType: hard
+"warn-once@npm:^0.1.0, warn-once@npm:^0.1.1":
+ version: 0.1.1
+ resolution: "warn-once@npm:0.1.1"
+ checksum: e6a5a1f5a8dba7744399743d3cfb571db4c3947897875d4962a7c5b1bf2195ab4518c838cb4cea652e71729f21bba2e98dc75686f5fccde0fabbd894e2ed0c0d
+ languageName: node
+ linkType: hard
+
"wcwidth@npm:^1.0.1":
version: 1.0.1
resolution: "wcwidth@npm:1.0.1"
From 749316ef06bb506ab33dfe36fdf678b1bbd2b9a4 Mon Sep 17 00:00:00 2001
From: IvanIhnatsiuk
Date: Sun, 21 Dec 2025 17:53:23 +0100
Subject: [PATCH 10/13] fix: improve button layout
---
example/ios/Podfile.lock | 4 +++-
example/src/screens/EditorScreen/index.tsx | 1 +
2 files changed, 4 insertions(+), 1 deletion(-)
diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock
index 90b4c67aa..bdbd07e5c 100644
--- a/example/ios/Podfile.lock
+++ b/example/ios/Podfile.lock
@@ -3023,8 +3023,10 @@ SPEC CHECKSUMS:
ReactAppDependencyProvider: 23e2bca1661f8781e55fcc05a151fc1df97bc1fb
ReactCodegen: 10a61330b137caaad6f7fbe7f5d0e7a40d621700
ReactCommon: c6cd81778336e767e27fe63c6707dd6b735fff5c
- ReactNativeEnriched: 25a18081f894e4708100897ade2863f1d04ee893
SDWebImage: e9c98383c7572d713c1a0d7dd2783b10599b9838
+ ReactNativeEnriched: 7946e3775018cbf1a22df81ce06402c248c8cc69
+ RNGestureHandler: c85091a16541f644d23f43347d08b6d64b202837
+ RNScreens: 69f68c95d395bc4261d27c3aae7b4a458b947b7e
SocketRocket: d4aabe649be1e368d1318fdf28a022d714d65748
Yoga: 6ca93c8c13f56baeec55eb608577619b17a4d64e
diff --git a/example/src/screens/EditorScreen/index.tsx b/example/src/screens/EditorScreen/index.tsx
index 6edcaf2de..e6e527459 100644
--- a/example/src/screens/EditorScreen/index.tsx
+++ b/example/src/screens/EditorScreen/index.tsx
@@ -337,6 +337,7 @@ export function EditorScreen() {
style={styles.valueButton}
/>
navigate('Preview', { html: currentHtml })}
/>
From 5a30cfa450b8caade2441910b809099766bad372 Mon Sep 17 00:00:00 2001
From: IvanIhnatsiuk
Date: Sun, 21 Dec 2025 18:30:33 +0100
Subject: [PATCH 11/13] fix: better naming
---
.../EnrichedTextInputViewShadowNode.h | 8 ++---
.../EnrichedTextInputViewShadowNode.mm | 29 ++++++++++---------
2 files changed, 19 insertions(+), 18 deletions(-)
diff --git a/ios/internals/EnrichedTextInputViewShadowNode.h b/ios/internals/EnrichedTextInputViewShadowNode.h
index 939a6b1f1..c95de35de 100644
--- a/ios/internals/EnrichedTextInputViewShadowNode.h
+++ b/ios/internals/EnrichedTextInputViewShadowNode.h
@@ -44,10 +44,10 @@ class EnrichedTextInputViewShadowNode
private:
NSAttributedString *getAttributedString() const;
void createTextStorage() const;
- mutable NSTextStorage *textStorage_ = nil;
- mutable NSLayoutManager *layoutManager_ = nil;
- mutable NSTextContainer *textContainer_ = nil;
- mutable NSAttributedString *prevAttributedText_ = nil;
+ mutable NSTextStorage *_textStorage = nil;
+ mutable NSLayoutManager *_layoutManager = nil;
+ mutable NSTextContainer *_textContainer = nil;
+ mutable NSAttributedString *_prevAttributedText = nil;
};
} // namespace facebook::react
diff --git a/ios/internals/EnrichedTextInputViewShadowNode.mm b/ios/internals/EnrichedTextInputViewShadowNode.mm
index 508712837..780157c29 100644
--- a/ios/internals/EnrichedTextInputViewShadowNode.mm
+++ b/ios/internals/EnrichedTextInputViewShadowNode.mm
@@ -10,25 +10,25 @@
"EnrichedTextInputView";
void EnrichedTextInputViewShadowNode::createTextStorage() const {
- if (textStorage_) {
+ if (_textStorage) {
return;
}
- textContainer_ = [NSTextContainer new];
- textContainer_.lineFragmentPadding = 0;
- textContainer_.maximumNumberOfLines = 0;
+ _textContainer = [NSTextContainer new];
+ _textContainer.lineFragmentPadding = 0;
+ _textContainer.maximumNumberOfLines = 0;
- layoutManager_ = [NSLayoutManager new];
- [layoutManager_ addTextContainer:textContainer_];
+ _layoutManager = [NSLayoutManager new];
+ [_layoutManager addTextContainer:_textContainer];
- textStorage_ = [NSTextStorage new];
- [textStorage_ addLayoutManager:layoutManager_];
- prevAttributedText_ = [NSAttributedString alloc];
+ _textStorage = [NSTextStorage new];
+ [_textStorage addLayoutManager:_layoutManager];
+ _prevAttributedText = [NSAttributedString alloc];
}
void EnrichedTextInputViewShadowNode::dirtyLayoutIfNeeded() {
const auto state = this->getStateData();
- if (![prevAttributedText_
+ if (![_prevAttributedText
isEqualToAttributedString:state.getAttributedText()]) {
YGNodeMarkDirty(&yogaNode_);
}
@@ -65,6 +65,7 @@
createTextStorage();
NSAttributedString *attributedText = getAttributedString();
+ _prevAttributedText = attributedText;
CGSize maxSize = {constraints.maximumSize.width,
constraints.maximumSize.height ==
@@ -72,15 +73,15 @@
? CGFLOAT_MAX
: constraints.maximumSize.height};
- textContainer_.size = maxSize;
+ _textContainer.size = maxSize;
- [textStorage_ replaceCharactersInRange:NSMakeRange(0, textStorage_.length)
+ [_textStorage replaceCharactersInRange:NSMakeRange(0, +_textStorage.length)
withAttributedString:attributedText];
- [layoutManager_ ensureLayoutForTextContainer:textContainer_];
+ [_layoutManager ensureLayoutForTextContainer:_textContainer];
CGSize usedSize =
- [layoutManager_ usedRectForTextContainer:textContainer_].size;
+ [_layoutManager usedRectForTextContainer:_textContainer].size;
auto width = std::min((Float)usedSize.width, constraints.maximumSize.width);
auto height =
From 92d86dba952bcc80b3d6da20b84c7726922b1e23 Mon Sep 17 00:00:00 2001
From: IvanIhnatsiuk
Date: Sun, 21 Dec 2025 18:46:50 +0100
Subject: [PATCH 12/13] fix: remove default value
---
example/src/screens/EditorScreen/index.tsx | 1 -
1 file changed, 1 deletion(-)
diff --git a/example/src/screens/EditorScreen/index.tsx b/example/src/screens/EditorScreen/index.tsx
index e6e527459..0efbd3b4a 100644
--- a/example/src/screens/EditorScreen/index.tsx
+++ b/example/src/screens/EditorScreen/index.tsx
@@ -304,7 +304,6 @@ export function EditorScreen() {
selectionColor="deepskyblue"
cursorColor="dodgerblue"
autoCapitalize="sentences"
- defaultValue="Test
"
onChangeText={(e) => handleChangeText(e.nativeEvent)}
onChangeHtml={(e) => handleChangeHtml(e.nativeEvent)}
onChangeState={(e) => handleChangeState(e.nativeEvent)}
From 2edd414f842ccbe1d0258856600e63bf1a5b6400 Mon Sep 17 00:00:00 2001
From: IvanIhnatsiuk
Date: Mon, 22 Dec 2025 00:33:10 +0100
Subject: [PATCH 13/13] fix: rebase with latest development
---
example/ios/Podfile.lock | 10 ++--
.../EditorScreen/components/Toolbar.tsx | 56 +------------------
example/src/screens/EditorScreen/index.tsx | 9 ++-
3 files changed, 15 insertions(+), 60 deletions(-)
diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock
index bdbd07e5c..9cc1309a3 100644
--- a/example/ios/Podfile.lock
+++ b/example/ios/Podfile.lock
@@ -2593,9 +2593,6 @@ PODS:
- SDWebImage
- SocketRocket
- Yoga
- - SDWebImage (5.21.5):
- - SDWebImage/Core (= 5.21.5)
- - SDWebImage/Core (5.21.5)
- RNGestureHandler (2.29.1):
- boost
- DoubleConversion
@@ -2683,6 +2680,9 @@ PODS:
- ReactCommon/turbomodule/core
- SocketRocket
- Yoga
+ - SDWebImage (5.21.5):
+ - SDWebImage/Core (= 5.21.5)
+ - SDWebImage/Core (5.21.5)
- SocketRocket (0.7.1)
- Yoga (0.0.0)
@@ -3023,10 +3023,10 @@ SPEC CHECKSUMS:
ReactAppDependencyProvider: 23e2bca1661f8781e55fcc05a151fc1df97bc1fb
ReactCodegen: 10a61330b137caaad6f7fbe7f5d0e7a40d621700
ReactCommon: c6cd81778336e767e27fe63c6707dd6b735fff5c
- SDWebImage: e9c98383c7572d713c1a0d7dd2783b10599b9838
- ReactNativeEnriched: 7946e3775018cbf1a22df81ce06402c248c8cc69
+ ReactNativeEnriched: ecc4b6c829f460fc2959e9309ee0b22908764107
RNGestureHandler: c85091a16541f644d23f43347d08b6d64b202837
RNScreens: 69f68c95d395bc4261d27c3aae7b4a458b947b7e
+ SDWebImage: e9c98383c7572d713c1a0d7dd2783b10599b9838
SocketRocket: d4aabe649be1e368d1318fdf28a022d714d65748
Yoga: 6ca93c8c13f56baeec55eb608577619b17a4d64e
diff --git a/example/src/screens/EditorScreen/components/Toolbar.tsx b/example/src/screens/EditorScreen/components/Toolbar.tsx
index d39ee915b..28c99b48a 100644
--- a/example/src/screens/EditorScreen/components/Toolbar.tsx
+++ b/example/src/screens/EditorScreen/components/Toolbar.tsx
@@ -5,7 +5,6 @@ import type {
EnrichedTextInputInstance,
} from 'react-native-enriched';
import type { FC } from 'react';
-import { ToolbarColorButton } from './ToolbarColorButton';
const STYLE_ITEMS = [
{
@@ -40,18 +39,6 @@ const STYLE_ITEMS = [
name: 'heading-3',
text: 'H3',
},
- {
- name: 'heading-4',
- text: 'H4',
- },
- {
- name: 'heading-5',
- text: 'H5',
- },
- {
- name: 'heading-6',
- text: 'H6',
- },
{
name: 'quote',
icon: 'quote-right',
@@ -80,16 +67,6 @@ const STYLE_ITEMS = [
name: 'ordered-list',
icon: 'list-ol',
},
- {
- name: 'color',
- value: '#FF0000',
- text: 'A',
- },
- {
- name: 'color',
- value: '#E6FF5C',
- text: 'A',
- },
] as const;
type Item = (typeof STYLE_ITEMS)[number];
@@ -100,7 +77,6 @@ export interface ToolbarProps {
editorRef?: React.RefObject;
onOpenLinkModal: () => void;
onSelectImage: () => void;
- selectionColor: string | null;
}
export const Toolbar: FC = ({
@@ -108,7 +84,6 @@ export const Toolbar: FC = ({
editorRef,
onOpenLinkModal,
onSelectImage,
- selectionColor,
}) => {
const handlePress = (item: Item) => {
const currentRef = editorRef?.current;
@@ -139,15 +114,6 @@ export const Toolbar: FC = ({
case 'heading-3':
editorRef.current?.toggleH3();
break;
- case 'heading-4':
- editorRef.current?.toggleH4();
- break;
- case 'heading-5':
- editorRef.current?.toggleH5();
- break;
- case 'heading-6':
- editorRef.current?.toggleH6();
- break;
case 'code-block':
editorRef?.current?.toggleCodeBlock();
break;
@@ -172,10 +138,6 @@ export const Toolbar: FC = ({
}
};
- const handleColorButtonPress = (color: string) => {
- editorRef?.current?.setColor(color);
- };
-
const isActive = (item: Item) => {
switch (item.name) {
case 'bold':
@@ -194,12 +156,6 @@ export const Toolbar: FC = ({
return stylesState.isH2;
case 'heading-3':
return stylesState.isH3;
- case 'heading-4':
- return stylesState.isH4;
- case 'heading-5':
- return stylesState.isH5;
- case 'heading-6':
- return stylesState.isH6;
case 'code-block':
return stylesState.isCodeBlock;
case 'quote':
@@ -220,14 +176,7 @@ export const Toolbar: FC = ({
};
const renderItem = ({ item }: ListRenderItemInfo- ) => {
- return item.name === 'color' ? (
-
- ) : (
+ return (
= ({
);
};
- const keyExtractor = (item: Item) =>
- item.name === 'color' ? item.value : item.name;
+ const keyExtractor = (item: Item) => item.name;
return (
handleChangeText(e.nativeEvent)}
onChangeHtml={(e) => handleChangeHtml(e.nativeEvent)}
onChangeState={(e) => handleChangeState(e.nativeEvent)}