diff --git a/.gitignore b/.gitignore index f52acef..4e0f0c5 100644 --- a/.gitignore +++ b/.gitignore @@ -51,6 +51,7 @@ project.xcworkspace build/ packages/*/lib/ packages/*/build/ +.rnlegal/ # Expo example examples/expo-example/android diff --git a/examples/expo-example/App.tsx b/examples/expo-example/App.tsx index 8d53c13..6c8dccc 100644 --- a/examples/expo-example/App.tsx +++ b/examples/expo-example/App.tsx @@ -1,3 +1,4 @@ +import './web-styles.css'; import { StatusBar } from 'expo-status-bar'; import { StyleSheet } from 'react-native'; import { MainScreen } from 'react-native-legal-common-example-ui'; diff --git a/examples/expo-example/index.js b/examples/expo-example/index.js index 1d6e981..9267cd5 100644 --- a/examples/expo-example/index.js +++ b/examples/expo-example/index.js @@ -1,3 +1,5 @@ +import '@expo/metro-runtime'; +import 'react-native-legal'; import { registerRootComponent } from 'expo'; import App from './App'; diff --git a/examples/expo-example/package.json b/examples/expo-example/package.json index 210991b..77d5e69 100644 --- a/examples/expo-example/package.json +++ b/examples/expo-example/package.json @@ -6,24 +6,30 @@ "start": "expo start --dev-client", "android": "expo run:android", "ios": "expo run:ios", - "web": "expo start --web", + "web": "yarn legal-generate:web && expo start --web", + "legal-generate:web": "react-native-legal legal-generate --dev-deps-mode=none --include-optional-deps --transitive-deps-mode=all", "typecheck": "tsc --noEmit" }, "dependencies": { + "@expo/metro-runtime": "~6.1.2", "expo": "^54.0.0", "expo-build-properties": "~1.0.8", "expo-splash-screen": "~31.0.9", "expo-status-bar": "~3.0.8", "react": "19.1.0", + "react-dom": "19.1.0", "react-native": "0.81.4", "react-native-legal": "workspace:*", "react-native-legal-common-example-ui": "workspace:*", - "react-native-safe-area-context": "5.6.1" + "react-native-safe-area-context": "5.6.1", + "react-native-web": "^0.21.0" }, "devDependencies": { "@babel/core": "7.27.4", "@babel/preset-env": "7.27.2", - "@types/react": "~19.1.12" + "@types/react": "~19.1.12", + "@types/react-dom": "^19", + "@types/react-native-web": "^0" }, "private": true } diff --git a/examples/expo-example/web-styles.css b/examples/expo-example/web-styles.css new file mode 100644 index 0000000..274b693 --- /dev/null +++ b/examples/expo-example/web-styles.css @@ -0,0 +1,3 @@ +dialog.rnl--dialog { + border-color: blueviolet; +} diff --git a/packages/react-native-legal/bin/commands/legal-generate.js b/packages/react-native-legal/bin/commands/legal-generate.js new file mode 100644 index 0000000..f99f1dd --- /dev/null +++ b/packages/react-native-legal/bin/commands/legal-generate.js @@ -0,0 +1,120 @@ +const fs = require('node:fs'); +const path = require('node:path'); + +const { scanDependencies } = require('@callstack/licenses'); + +const { createPluginScanOptionsFactory } = require('../../plugin-utils/build/common'); + +/** + * @param {import('commander').Command} program + * @returns {import('commander').Command} + */ +function generateLegal(program) { + return program + .command('legal-generate') + .description('Set up all native boilerplate for OSS licenses notice') + .option( + '--tm, --transitive-deps-mode [mode]', + 'Controls, which transitive dependencies are included:' + + `\n\u2063\t- 'all',` + + `\n\u2063\t- 'from-external-only' (only transitive dependencies of direct dependencies specified by non-workspace:... specifiers),` + + `\n\u2063\t- 'from-workspace-only' (only transitive dependencies of direct dependencies specified by \`workspace:\` specifier),` + + `\n\u2063\t- 'none'` + + '\n', // newline for auto-description of the default value + (val) => { + if (val === 'all' || val === 'from-external-only' || val === 'from-workspace-only' || val === 'none') { + return val; + } + + return 'all'; + }, + 'all', + ) + .option( + '--dm, --dev-deps-mode [mode]', + 'Controls, whether and how development dependencies are included:' + + `\n\u2063\t- 'root-only' (only direct devDependencies from the scanned project's root package.json)` + + `\n\u2063\t- 'none'` + + '\n', // newline for auto-description of the default value + (val) => { + if (val === 'root-only') { + return val; + } + + return 'none'; + }, + 'none', + ) + .option( + '--od, --include-optional-deps [include]', + 'Whether to include optionalDependencies in the scan; other flags apply', + (val) => val !== 'false', + true, + ) + .action((options) => { + const repoRootPath = path.resolve(process.cwd()); + const packageJsonPath = path.join(repoRootPath, 'package.json'); + + if (!fs.existsSync(packageJsonPath)) { + console.error(`package.json not found at ${packageJsonPath}`); + process.exit(1); + } + + /** @type {import('../plugin-utils/build/types').PluginScanOptions} */ + const { devDepsMode, includeOptionalDeps, transitiveDepsMode } = options; + + const scanOptionsFactory = createPluginScanOptionsFactory({ + devDepsMode, + includeOptionalDeps, + transitiveDepsMode, + }); + + const licenses = scanDependencies(packageJsonPath, scanOptionsFactory); + + const payload = Object.entries(licenses) + .map(([packageKey, licenseObj]) => { + return { + name: licenseObj.name, + version: licenseObj.version, + content: licenseObj.content ?? licenseObj.type ?? 'UNKNOWN', + packageKey, + ...(licenseObj.url && { source: licenseObj.url }), + }; + }) + .toSorted((first, second) => { + if (!first.version || !second.version) { + return first.name > second.name; + } + + if (first.name !== second.name) { + return first.name > second.name ? 1 : -1; + } + + const [firstMajor, firstMinor, firstPatch] = first.version.split('.').filter(Boolean); + const [secondMajor, secondMinor, secondPatch] = second.version.split('.').filter(Boolean); + + return `${first.name}.${firstMajor.padStart(10, '0')}.${(firstMinor ?? '0').padStart(10, '0')}.${( + firstPatch ?? '0' + ).padStart(10, '0')}` > + `${second.name}.${secondMajor.padStart(10, '0')}.${(secondMinor ?? '0').padStart(10, '0')}.${( + secondPatch ?? '0' + ).padStart(10, '0')}` + ? 1 + : -1; + }); + + const rnLegalConfigPath = path.join(__dirname, '..', '..', '.rnlegal'); + + if (!fs.existsSync(rnLegalConfigPath)) { + fs.mkdirSync(rnLegalConfigPath); + } + + const rnLegalConfigLibrariesPath = path.join(rnLegalConfigPath, 'libraries.json'); + + fs.writeFileSync(rnLegalConfigLibrariesPath, JSON.stringify(payload), { encoding: 'utf-8' }); + + console.log(`✅ Output written to ${rnLegalConfigLibrariesPath}`); + }); +} + +module.exports = generateLegal; diff --git a/packages/react-native-legal/bin/index.js b/packages/react-native-legal/bin/index.js new file mode 100755 index 0000000..7c23301 --- /dev/null +++ b/packages/react-native-legal/bin/index.js @@ -0,0 +1,28 @@ +#!/usr/bin/env node +const process = require('node:process'); + +// eslint-disable-next-line import/no-extraneous-dependencies +const { Command } = require('commander'); + +const { version } = require('../package.json'); + +const generateLegal = require('./commands/legal-generate'); + +const program = new Command(); + +program.name('react-native-legal For Web').description('Scan dependencies for Web projects').version(version); + +generateLegal(program); + +program + .command('help', { isDefault: false }) + .description('Show help message') + .action(() => { + program.outputHelp(); + }); + +if (!process.argv.slice(2).length) { + program.outputHelp(); +} else { + program.parse(process.argv); +} diff --git a/packages/react-native-legal/package.json b/packages/react-native-legal/package.json index 31cea27..95ae03f 100644 --- a/packages/react-native-legal/package.json +++ b/packages/react-native-legal/package.json @@ -12,6 +12,7 @@ "main": "lib/commonjs/index", "module": "lib/module/index", "types": "lib/typescript/index.d.ts", + "bin": "./bin/index.js", "react-native": "src/index", "source": "src/index", "repository": { @@ -59,6 +60,7 @@ }, "dependencies": { "@callstack/licenses": "^0.3.0", + "commander": "^14.0.0", "glob": "^7.1.3", "xcode": "^3.0.1", "xml2js": "^0.6.2" diff --git a/packages/react-native-legal/src/ReactNativeLegal.web.ts b/packages/react-native-legal/src/ReactNativeLegal.web.ts new file mode 100644 index 0000000..d49b52f --- /dev/null +++ b/packages/react-native-legal/src/ReactNativeLegal.web.ts @@ -0,0 +1,91 @@ +import './ReactNativeLegalStyles.css'; +import type { LibrariesResult } from './NativeReactNativeLegal'; + +function createElementWithClassName(tagName: K, className: string) { + const element = document.createElement(tagName); + + element.className = className; + + return element; +} + +export const ReactNativeLegal = { + getLibrariesAsync: () => { + const payload = require(`react-native-legal/.rnlegal/libraries.json`); + + return Promise.resolve({ + data: payload.map((library: any) => ({ + id: library.packageKey, + name: library.packageKey, + licenses: [{ licenseContent: library.content }], + })), + }); + }, + launchLicenseListScreen: (licenseHeaderText?: string) => { + const payload = require(`react-native-legal/.rnlegal/libraries.json`); + + const main = createElementWithClassName('main', 'rnl--main'); + const closeBtn = createElementWithClassName('span', 'rnl--close-button'); + + closeBtn.innerHTML = '×'; + + const closeBtnContainer = createElementWithClassName('div', 'rnl--close-button-container'); + + closeBtnContainer.ariaLabel = 'Close licenses dialog'; + closeBtnContainer.role = 'button'; + closeBtnContainer.appendChild(closeBtn); + + const headerContainer = createElementWithClassName('header', 'rnl--header-container'); + + headerContainer.appendChild(closeBtnContainer); + + main.appendChild(headerContainer); + + if (licenseHeaderText) { + const header = createElementWithClassName('h1', 'rnl--header'); + + header.innerText = licenseHeaderText; + + headerContainer.appendChild(header); + } + + payload.forEach((library: any) => { + const summary = createElementWithClassName('summary', 'rnl--summary'); + + summary.innerText = library.packageKey; + + const content = createElementWithClassName('p', 'rnl--summary-content'); + + content.innerText = library.content; + + const details = createElementWithClassName('details', 'rnl--summary-details'); + + details.appendChild(summary); + details.appendChild(content); + + main.appendChild(details); + }); + + const dialog = createElementWithClassName('dialog', 'rnl--dialog'); + + dialog.appendChild(main); + + document.querySelector('body')?.appendChild(dialog); + + closeBtnContainer.addEventListener( + 'click', + () => { + document.querySelector('body')?.removeChild(dialog); + }, + { once: true }, + ); + dialog.addEventListener( + 'close', + () => { + document.querySelector('body')?.removeChild(dialog); + }, + { once: true }, + ); + dialog.showModal(); + }, +}; diff --git a/packages/react-native-legal/src/ReactNativeLegalStyles.css b/packages/react-native-legal/src/ReactNativeLegalStyles.css new file mode 100644 index 0000000..7dffa55 --- /dev/null +++ b/packages/react-native-legal/src/ReactNativeLegalStyles.css @@ -0,0 +1,36 @@ +dialog.rnl--dialog { + height: 90%; + width: 90%; + border-radius: 20px; +} + +dialog.rnl--dialog::backdrop { + background-color: rgba(0,0,0,0.4); +} + +main.rnl--main { + display: flex; + align-self: stretch; + flex: 1; + flex-direction: column; + overflow: scroll; + width: 100%; +} + +.rnl--close-button { + font-size: 36px; + font-weight: 600; + padding: 10px; +} + +header.rnl--header-container { + display: flex; + align-items: center; + flex-direction: row-reverse; + justify-content: space-between; +} + +summary.rnl--summary { + font-size: 20px; + margin: 10px 0px; +} diff --git a/packages/visualizer/src/components/DependencyGraph.tsx b/packages/visualizer/src/components/DependencyGraph.tsx index 583bf32..bfed143 100644 --- a/packages/visualizer/src/components/DependencyGraph.tsx +++ b/packages/visualizer/src/components/DependencyGraph.tsx @@ -95,7 +95,7 @@ export default function DependencyGraph({ data }: DependencyGraphProps) { ); const graphRenderJobPendingRef = useRef(false); - const graphRenderJobDispatchRef = useRef(null); + const graphRenderJobDispatchRef = useRef | null>(null); /** * Graph render dispatch effect; used for first committing a new state diff --git a/yarn.lock b/yarn.lock index ea9cd2c..a1c158c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1855,6 +1855,13 @@ __metadata: languageName: node linkType: hard +"@babel/runtime@npm:^7.18.6": + version: 7.28.4 + resolution: "@babel/runtime@npm:7.28.4" + checksum: 10/6c9a70452322ea80b3c9b2a412bcf60771819213a67576c8cec41e88a95bb7bf01fc983754cda35dc19603eef52df22203ccbf7777b9d6316932f9fb77c25163 + languageName: node + linkType: hard + "@babel/template@npm:^7.25.0, @babel/template@npm:^7.27.1, @babel/template@npm:^7.27.2, @babel/template@npm:^7.3.3": version: 7.27.2 resolution: "@babel/template@npm:7.27.2" @@ -3261,6 +3268,26 @@ __metadata: languageName: node linkType: hard +"@expo/metro-runtime@npm:~6.1.2": + version: 6.1.2 + resolution: "@expo/metro-runtime@npm:6.1.2" + dependencies: + anser: "npm:^1.4.9" + pretty-format: "npm:^29.7.0" + stacktrace-parser: "npm:^0.1.10" + whatwg-fetch: "npm:^3.0.0" + peerDependencies: + expo: "*" + react: "*" + react-dom: "*" + react-native: "*" + peerDependenciesMeta: + react-dom: + optional: true + checksum: 10/ee761177f3c919c2bc2209beb6e19dedc1774b1855bec7b38f49a2a2d1aeb84ed916980723352d45a924ae47f6c487e1daadbf3e469d62f1efc9f3c6312f61e8 + languageName: node + linkType: hard + "@expo/metro@npm:~0.1.1": version: 0.1.1 resolution: "@expo/metro@npm:0.1.1" @@ -4920,6 +4947,13 @@ __metadata: languageName: node linkType: hard +"@react-native/normalize-colors@npm:^0.74.1": + version: 0.74.89 + resolution: "@react-native/normalize-colors@npm:0.74.89" + checksum: 10/2e2e2f950cc4c2896af6094cb045f1d6e8d73101960b9cadb67b944b1254a9204b8f78a075dafd22cff39bc154a0cbe48b57f262b5d319ecb823c84519352545 + languageName: node + linkType: hard + "@react-native/typescript-config@npm:0.81.4": version: 0.81.4 resolution: "@react-native/typescript-config@npm:0.81.4" @@ -6200,6 +6234,16 @@ __metadata: languageName: node linkType: hard +"@types/react-native-web@npm:^0": + version: 0.19.2 + resolution: "@types/react-native-web@npm:0.19.2" + dependencies: + "@types/react": "npm:*" + react-native: "npm:*" + checksum: 10/bc27ccb2737283b78b41dacf605fc99b137091b49cd9b0b1bd2fab8c7950107314a04fc2351b0fcaaaeddea9ec101937fb6df24014f221a275a58666f60cfda0 + languageName: node + linkType: hard + "@types/react-test-renderer@npm:^19.1.0": version: 19.1.0 resolution: "@types/react-test-renderer@npm:19.1.0" @@ -7236,7 +7280,7 @@ __metadata: languageName: node linkType: hard -"asap@npm:~2.0.6": +"asap@npm:~2.0.3, asap@npm:~2.0.6": version: 2.0.6 resolution: "asap@npm:2.0.6" checksum: 10/b244c0458c571945e4b3be0b14eb001bea5596f9868cc50cc711dc03d58a7e953517d3f0dad81ccde3ff37d1f074701fa76a6f07d41aaa992d7204a37b915dda @@ -8607,6 +8651,15 @@ __metadata: languageName: node linkType: hard +"cross-fetch@npm:^3.1.5": + version: 3.2.0 + resolution: "cross-fetch@npm:3.2.0" + dependencies: + node-fetch: "npm:^2.7.0" + checksum: 10/e4ab1d390a5b6ca8bb0605f028af2ffc1127d2e407b954654949f506d04873c4863ece264662c074865d7874060e35f938cec74fe7b5736d46d545e2685f6aec + languageName: node + linkType: hard + "cross-spawn@npm:^7.0.0, cross-spawn@npm:^7.0.2, cross-spawn@npm:^7.0.3, cross-spawn@npm:^7.0.5, cross-spawn@npm:^7.0.6": version: 7.0.6 resolution: "cross-spawn@npm:7.0.6" @@ -8625,6 +8678,15 @@ __metadata: languageName: node linkType: hard +"css-in-js-utils@npm:^3.1.0": + version: 3.1.0 + resolution: "css-in-js-utils@npm:3.1.0" + dependencies: + hyphenate-style-name: "npm:^1.0.3" + checksum: 10/bd2f569f1870389004cfacfd7b798c0f40933d34af1f040c391a08322d097790b9a9524affb2ba4d26122e9cb8f4256afb59edb6077dbe607506944a9c673c67 + languageName: node + linkType: hard + "cssom@npm:^0.5.0": version: 0.5.0 resolution: "cssom@npm:0.5.0" @@ -11009,6 +11071,28 @@ __metadata: languageName: node linkType: hard +"fbjs-css-vars@npm:^1.0.0": + version: 1.0.2 + resolution: "fbjs-css-vars@npm:1.0.2" + checksum: 10/72baf6d22c45b75109118b4daecb6c8016d4c83c8c0f23f683f22e9d7c21f32fff6201d288df46eb561e3c7d4bb4489b8ad140b7f56444c453ba407e8bd28511 + languageName: node + linkType: hard + +"fbjs@npm:^3.0.4": + version: 3.0.5 + resolution: "fbjs@npm:3.0.5" + dependencies: + cross-fetch: "npm:^3.1.5" + fbjs-css-vars: "npm:^1.0.0" + loose-envify: "npm:^1.0.0" + object-assign: "npm:^4.1.0" + promise: "npm:^7.1.1" + setimmediate: "npm:^1.0.5" + ua-parser-js: "npm:^1.0.35" + checksum: 10/71252595b00b06fb0475a295c74d81ada1cc499b7e11f2cde51fef04618affa568f5b7f4927f61720c23254b9144be28f8acb2086a5001cf65df8eec87c6ca5c + languageName: node + linkType: hard + "fdir@npm:^6.4.4": version: 6.4.6 resolution: "fdir@npm:6.4.6" @@ -12165,6 +12249,13 @@ __metadata: languageName: node linkType: hard +"hyphenate-style-name@npm:^1.0.3": + version: 1.1.0 + resolution: "hyphenate-style-name@npm:1.1.0" + checksum: 10/b9ed74e29181d96bd58a2d0e62fc4a19879db591dba268275829ff0ae595fcdf11faafaeaa63330a45c3004664d7db1f0fc7cdb372af8ee4615ed8260302c207 + languageName: node + linkType: hard + "iconv-lite@npm:0.4.24, iconv-lite@npm:^0.4.24": version: 0.4.24 resolution: "iconv-lite@npm:0.4.24" @@ -12299,6 +12390,15 @@ __metadata: languageName: node linkType: hard +"inline-style-prefixer@npm:^7.0.1": + version: 7.0.1 + resolution: "inline-style-prefixer@npm:7.0.1" + dependencies: + css-in-js-utils: "npm:^3.1.0" + checksum: 10/a430c962693f32a36bcec0124c9798bcf3725bb90468d493108c0242446a9cc92ff1967bdf99b6ce5331e7a9b75e6836bc9ba1b3d4756876b8ef48036acb2509 + languageName: node + linkType: hard + "internal-slot@npm:^1.1.0": version: 1.1.0 resolution: "internal-slot@npm:1.1.0" @@ -14834,6 +14934,13 @@ __metadata: languageName: node linkType: hard +"memoize-one@npm:^6.0.0": + version: 6.0.0 + resolution: "memoize-one@npm:6.0.0" + checksum: 10/28feaf7e9a870efef1187df110b876ce42deaf86c955f4111d72d23b96e44eed573469316e6ad0d2cc7fa3b1526978215617b126158015f957242c7493babca9 + languageName: node + linkType: hard + "meow@npm:^8.0.0, meow@npm:^8.1.2": version: 8.1.2 resolution: "meow@npm:8.1.2" @@ -15967,7 +16074,7 @@ __metadata: languageName: node linkType: hard -"node-fetch@npm:^2.5.0": +"node-fetch@npm:^2.5.0, node-fetch@npm:^2.7.0": version: 2.7.0 resolution: "node-fetch@npm:2.7.0" dependencies: @@ -16135,7 +16242,7 @@ __metadata: languageName: node linkType: hard -"object-assign@npm:^4.0.1, object-assign@npm:^4.1.1": +"object-assign@npm:^4.0.1, object-assign@npm:^4.1.0, object-assign@npm:^4.1.1": version: 4.1.1 resolution: "object-assign@npm:4.1.1" checksum: 10/fcc6e4ea8c7fe48abfbb552578b1c53e0d194086e2e6bbbf59e0a536381a292f39943c6e9628af05b5528aa5e3318bb30d6b2e53cadaf5b8fe9e12c4b69af23f @@ -16765,6 +16872,13 @@ __metadata: languageName: node linkType: hard +"postcss-value-parser@npm:^4.2.0": + version: 4.2.0 + resolution: "postcss-value-parser@npm:4.2.0" + checksum: 10/e4e4486f33b3163a606a6ed94f9c196ab49a37a7a7163abfcd469e5f113210120d70b8dd5e33d64636f41ad52316a3725655421eb9a1094f1bcab1db2f555c62 + languageName: node + linkType: hard + "postcss@npm:8.4.31": version: 8.4.31 resolution: "postcss@npm:8.4.31" @@ -16872,6 +16986,15 @@ __metadata: languageName: node linkType: hard +"promise@npm:^7.1.1": + version: 7.3.1 + resolution: "promise@npm:7.3.1" + dependencies: + asap: "npm:~2.0.3" + checksum: 10/37dbe58ca7b0716cc881f0618128f1fd6ff9c46cdc529a269fd70004e567126a449a94e9428e2d19b53d06182d11b45d0c399828f103e06b2bb87643319bd2e7 + languageName: node + linkType: hard + "promise@npm:^8.3.0": version: 8.3.0 resolution: "promise@npm:8.3.0" @@ -17264,16 +17387,21 @@ __metadata: dependencies: "@babel/core": "npm:7.27.4" "@babel/preset-env": "npm:7.27.2" + "@expo/metro-runtime": "npm:~6.1.2" "@types/react": "npm:~19.1.12" + "@types/react-dom": "npm:^19" + "@types/react-native-web": "npm:^0" expo: "npm:^54.0.0" expo-build-properties: "npm:~1.0.8" expo-splash-screen: "npm:~31.0.9" expo-status-bar: "npm:~3.0.8" react: "npm:19.1.0" + react-dom: "npm:19.1.0" react-native: "npm:0.81.4" react-native-legal: "workspace:*" react-native-legal-common-example-ui: "workspace:*" react-native-safe-area-context: "npm:5.6.1" + react-native-web: "npm:^0.21.0" languageName: unknown linkType: soft @@ -17284,6 +17412,7 @@ __metadata: "@callstack/licenses": "npm:^0.3.0" "@types/glob": "npm:^8.1.0" "@types/xml2js": "npm:^0.4.11" + commander: "npm:^14.0.0" expo: "npm:^54.0.0" expo-module-scripts: "npm:^5.0.7" glob: "npm:^7.1.3" @@ -17298,6 +17427,8 @@ __metadata: peerDependenciesMeta: expo: optional: true + bin: + react-native-legal: ./bin/index.js languageName: unknown linkType: soft @@ -17321,7 +17452,26 @@ __metadata: languageName: node linkType: hard -"react-native@npm:0.81.4": +"react-native-web@npm:^0.21.0": + version: 0.21.1 + resolution: "react-native-web@npm:0.21.1" + dependencies: + "@babel/runtime": "npm:^7.18.6" + "@react-native/normalize-colors": "npm:^0.74.1" + fbjs: "npm:^3.0.4" + inline-style-prefixer: "npm:^7.0.1" + memoize-one: "npm:^6.0.0" + nullthrows: "npm:^1.1.1" + postcss-value-parser: "npm:^4.2.0" + styleq: "npm:^0.1.3" + peerDependencies: + react: ^18.0.0 || ^19.0.0 + react-dom: ^18.0.0 || ^19.0.0 + checksum: 10/62cc21b514fd4abe3f9705bd9c835a7f6b910b41869f3c52d136e7ce758bbfa03f04e5df08ad430834faae236c575611430d69b4ca9cb87fb086c1a90392a784 + languageName: node + linkType: hard + +"react-native@npm:*, react-native@npm:0.81.4": version: 0.81.4 resolution: "react-native@npm:0.81.4" dependencies: @@ -18411,6 +18561,13 @@ __metadata: languageName: node linkType: hard +"setimmediate@npm:^1.0.5": + version: 1.0.5 + resolution: "setimmediate@npm:1.0.5" + checksum: 10/76e3f5d7f4b581b6100ff819761f04a984fa3f3990e72a6554b57188ded53efce2d3d6c0932c10f810b7c59414f85e2ab3c11521877d1dea1ce0b56dc906f485 + languageName: node + linkType: hard + "setprototypeof@npm:1.2.0": version: 1.2.0 resolution: "setprototypeof@npm:1.2.0" @@ -19226,6 +19383,13 @@ __metadata: languageName: node linkType: hard +"styleq@npm:^0.1.3": + version: 0.1.3 + resolution: "styleq@npm:0.1.3" + checksum: 10/9a75a1b635f8ebf5c0fdc3ffb56f466254f29aa1b2962ab2af776015d3b3bb1732a53edcda0c9ac9b97be96c22459db768feac0d61c1a319cc3954011ca9dcd8 + languageName: node + linkType: hard + "stylis@npm:4.2.0": version: 4.2.0 resolution: "stylis@npm:4.2.0" @@ -19906,6 +20070,15 @@ __metadata: languageName: node linkType: hard +"ua-parser-js@npm:^1.0.35": + version: 1.0.41 + resolution: "ua-parser-js@npm:1.0.41" + bin: + ua-parser-js: script/cli.js + checksum: 10/86f2b624ff13f5be86a7cc5172427960493c8c0f703fdc8de340d8701951a1478cdf7a76f1f510932bb25a2fce6a3e0ba750b631f026d85acdc6b2a6b0ba6138 + languageName: node + linkType: hard + "uglify-js@npm:^3.1.4": version: 3.19.3 resolution: "uglify-js@npm:3.19.3"