From ac4fd90162fb6298e0cd325bdbbfc3ebc6ad920d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mikl=C3=B3s=20Fazekas?= Date: Thu, 6 Nov 2025 05:45:37 +0100 Subject: [PATCH 01/24] feat: referencedAssets (ios) --- ios/HybridRiveFile.swift | 7 + ios/HybridRiveFileFactory.swift | 273 +++++++++++++++++++++++++++++--- ios/RCTLog.swift | 29 ++++ ios/RCTSwiftLog.h | 11 ++ ios/RCTSwiftLog.m | 38 +++++ ios/RiveReactNativeView.swift | 2 +- 6 files changed, 335 insertions(+), 25 deletions(-) create mode 100644 ios/RCTLog.swift create mode 100644 ios/RCTSwiftLog.h create mode 100644 ios/RCTSwiftLog.m diff --git a/ios/HybridRiveFile.swift b/ios/HybridRiveFile.swift index 1f8c74fb..1aeaffb0 100644 --- a/ios/HybridRiveFile.swift +++ b/ios/HybridRiveFile.swift @@ -1,7 +1,10 @@ import RiveRuntime +typealias ReferencedAssetCache = [String: RiveFileAsset] + class HybridRiveFile: HybridRiveFileSpec { var riveFile: RiveFile? + var referencedAssetCache: ReferencedAssetCache? public func setRiveFile(_ riveFile: RiveFile) { self.riveFile = riveFile @@ -45,6 +48,10 @@ class HybridRiveFile: HybridRiveFileSpec { return HybridViewModel(viewModel: vm) } + func updateReferencedAssets(referencedAssets: ReferencedAssetsType) { + + } + func release() throws { // iOS does not need to release the Rive file. riveFile = nil diff --git a/ios/HybridRiveFileFactory.swift b/ios/HybridRiveFileFactory.swift index 80e7d512..a9b9d95c 100644 --- a/ios/HybridRiveFileFactory.swift +++ b/ios/HybridRiveFileFactory.swift @@ -1,21 +1,231 @@ import NitroModules import RiveRuntime -class HybridRiveFileFactory: HybridRiveFileFactorySpec { + +final class Ref { + var value: T + init(_ value: T) { + self.value = value + } +} + +struct FileAndCache { + var file: RiveFile + var cache: [String: RiveFileAsset] +} + +private func isValidUrl(_ url: String) -> Bool { + if let url = URL(string: url) { + return url.scheme == "file" || url.scheme == "http" || url.scheme == "https" + } else { + return false + } + } + +func createIncorrectRiveURL(_ url: String) -> NSError { + return NSError(domain: RiveErrorDomain, code: 900, userInfo: [NSLocalizedDescriptionKey: "Unable to download Rive file from: \(url)", "name": "IncorrectRiveFileURL"]) +} + + +func createAssetFileError(_ assetName: String) -> NSError { + return NSError(domain: RiveErrorDomain, code: 801, userInfo: [NSLocalizedDescriptionKey: "Could not load Rive asset: \(assetName)", "name": "FileNotFound"]) +} + + + +final class HybridRiveFileFactory: HybridRiveFileFactorySpec { + private func handleRiveError(error: NSError) { + /*if isUserHandlingErrors { + let rnRiveError = RNRiveError.mapToRNRiveError(riveError: error) + if let safeRnRiveError = rnRiveError { + onRNRiveError(safeRnRiveError) + } + } else { */ + RCTLogError(error.localizedDescription) + /* } */ + } + + private func handleInvalidUrlError(url: String) { + handleRiveError(error: createIncorrectRiveURL(url)) + } + + private func downloadUrlAsset(url: String, listener: @escaping (Data) -> Void) { + guard isValidUrl(url) else { + handleInvalidUrlError(url: url) + return + } + if let fileUrl = URL(string: url), fileUrl.scheme == "file" { + do { + let data = try Data(contentsOf: fileUrl) + listener(data) + } catch { + handleInvalidUrlError(url: url) + } + return + } + + let queue = URLSession.shared + guard let requestUrl = URL(string: url) else { + handleInvalidUrlError(url: url) + return + } + + let request = URLRequest(url: requestUrl) + let task = queue.dataTask(with: request) {[weak self] data, response, error in + if error != nil { + self?.handleInvalidUrlError(url: url) + } else if let data = data { + listener(data) + } + } + + task.resume() + } + + private func processAssetBytes(_ data: Data, asset: RiveFileAsset, factory: RiveFactory) { + if (data.isEmpty == true) { + return; + } + DispatchQueue.global(qos: .background).async { + switch asset { + case let imageAsset as RiveImageAsset: + let decodedImage = factory.decodeImage(data) + DispatchQueue.main.async { + imageAsset.renderImage(decodedImage) + } + case let fontAsset as RiveFontAsset: + let decodedFont = factory.decodeFont(data) + DispatchQueue.main.async { + fontAsset.font(decodedFont) + } + case let audioAsset as RiveAudioAsset: + guard let decodedAudio = factory.decodeAudio(data) else { return } + DispatchQueue.main.async { + audioAsset.audio(decodedAudio) + } + default: + break + } + } + } + + private func handleSourceAssetId(_ sourceAssetId: String, asset: RiveFileAsset, factory: RiveFactory) { + guard URL(string: sourceAssetId) != nil else { + return + } + + downloadUrlAsset(url: sourceAssetId) { [weak self] data in + self?.processAssetBytes(data, asset: asset, factory: factory) + } + } + + private func handleSourceUrl(_ sourceUrl: String, asset: RiveFileAsset, factory: RiveFactory) { + downloadUrlAsset(url: sourceUrl) { [weak self] data in + self?.processAssetBytes(data, asset: asset, factory: factory) + } + } + + private func splitFileNameAndExtension(fileName: String) -> (name: String?, ext: String?)? { + let components = fileName.split(separator: ".") + let name = (fileName as NSString).deletingPathExtension; + let fileExtension = (fileName as NSString).pathExtension; + guard components.count == 2 else { return nil } + return (name: name, ext: fileExtension) + } + + + private func loadResourceAsset(sourceAsset: String, path: String?, listener: @escaping (Data) -> Void) { + guard let splitSourceAssetName = splitFileNameAndExtension(fileName: sourceAsset), + let name = splitSourceAssetName.name, + let ext = splitSourceAssetName.ext else { + handleRiveError(error: createAssetFileError(sourceAsset)) + return + } + + guard let folderUrl = Bundle.main.url(forResource: name, withExtension: ext) else { + handleRiveError(error: createAssetFileError(sourceAsset)) + return + } + + DispatchQueue.global(qos: .background).async { [weak self] in + do { + let fileData = try Data(contentsOf: folderUrl) + DispatchQueue.main.async { + listener(fileData) + } + } catch { + DispatchQueue.main.async { + self?.handleRiveError(error: createAssetFileError(sourceAsset)) + } + } + } + } + + private func handleSourceAsset(_ sourceAsset: String, path: String?, asset: RiveFileAsset, factory: RiveFactory) { + loadResourceAsset(sourceAsset: sourceAsset, path: path) {[weak self] data in + self?.processAssetBytes(data, asset: asset, factory: factory) + } + } + + private func loadAsset(source: ResolvedReferencedAsset, asset: RiveFileAsset, factory: RiveFactory) { + let sourceAssetId = source.sourceAssetId + let sourceUrl = source.sourceUrl + let sourceAsset = source.sourceAsset + + if let sourceAssetId = sourceAssetId { + handleSourceAssetId(sourceAssetId, asset: asset, factory: factory) + } else if let sourceUrl = sourceUrl { + handleSourceUrl(sourceUrl, asset: asset, factory: factory) + } else if let sourceAsset = sourceAsset { + handleSourceAsset(sourceAsset, path: source.path, asset: asset, factory: factory) + } + } + + func toCustomLoader(referencedAssets: ReferencedAssetsType?, cache: Ref) -> LoadAsset? { + guard let referencedAssets = referencedAssets, let referencedAssets = referencedAssets.data else { + return nil + } + return { (asset: RiveFileAsset, data: Data, factory: RiveFactory) -> Bool in + let assetByUniqueName = referencedAssets[asset.uniqueName()] + guard let assetData = assetByUniqueName ?? referencedAssets[asset.name()] else { + return false + } + let usedKey = assetByUniqueName != nil ? asset.uniqueName() : asset.name() + + cache.value[asset.uniqueName()] = asset + + self.loadAsset(source: assetData, asset: asset, factory: factory) + + return false + } + } + + private func buildRiveFile(data: Data, loadCdn: Bool,referencedAssets: ReferencedAssetsType?) throws -> FileAndCache { + var referencedAssetCache = Ref(ReferencedAssetCache()) + let riveFile = + if let customLoader = toCustomLoader(referencedAssets: referencedAssets, cache: referencedAssetCache) { + try RiveFile(data: data, loadCdn: loadCdn, customAssetLoader: customLoader) + } else { + try RiveFile(data: data, loadCdn: loadCdn) + } + return FileAndCache(file: riveFile, cache: referencedAssetCache.value) + } + // MARK: Public Methods - func fromURL(url: String, loadCdn: Bool) throws -> Promise<(any HybridRiveFileSpec)> { + func fromURL(url: String, loadCdn: Bool,referencedAssets: ReferencedAssetsType?) throws -> Promise<(any HybridRiveFileSpec)> { // TODO: should we make use of the underlying Rive iOS URL asset loading instead return Promise.async { do { guard let url = URL(string: url) else { throw RuntimeError.error(withMessage: "Invalid URL: \(url)") } - + let riveFile = try await withCheckedThrowingContinuation { continuation in DispatchQueue.global(qos: .userInitiated).async { do { - let riveData = try Data(contentsOf: url) - let riveFile = try RiveFile(data: riveData, loadCdn: true) + let data = try Data(contentsOf: url) + let riveFile = try self.buildRiveFile(data: data, loadCdn: loadCdn, referencedAssets: referencedAssets) + DispatchQueue.main.async { continuation.resume(returning: riveFile) } @@ -26,9 +236,10 @@ class HybridRiveFileFactory: HybridRiveFileFactorySpec { } } } - + let hybridRiveFile = HybridRiveFile() - hybridRiveFile.riveFile = riveFile + hybridRiveFile.riveFile = riveFile.file + hybridRiveFile.referencedAssetCache = riveFile.cache return hybridRiveFile } catch let error as NSError { throw RuntimeError.error(withMessage: "Failed to download Rive file: \(error.localizedDescription)") @@ -37,24 +248,23 @@ class HybridRiveFileFactory: HybridRiveFileFactorySpec { } } } - - func fromFileURL(fileURL: String, loadCdn: Bool) throws -> Promise<(any HybridRiveFileSpec)> { + + func fromFileURL(fileURL: String, loadCdn: Bool, referencedAssets: ReferencedAssetsType?) throws -> Promise<(any HybridRiveFileSpec)> { guard let url = URL(string:fileURL) else { throw RuntimeError.error(withMessage: "fromFileURL: Invalid URL: \(fileURL)") } - + guard url.isFileURL else { throw RuntimeError.error(withMessage: "fromFileURL: URL must be a file URL: \(fileURL)") } - + return Promise.async { do { let riveFile = try await withCheckedThrowingContinuation { continuation in DispatchQueue.global(qos: .userInitiated).async { do { let data = try Data(contentsOf: url) - - let riveFile = try RiveFile(data: data, loadCdn: loadCdn) + let riveFile = try self.buildRiveFile(data: data, loadCdn: loadCdn, referencedAssets: referencedAssets) DispatchQueue.main.async { continuation.resume(returning: riveFile) } @@ -65,9 +275,10 @@ class HybridRiveFileFactory: HybridRiveFileFactorySpec { } } } - + let hybridRiveFile = HybridRiveFile() - hybridRiveFile.riveFile = riveFile + hybridRiveFile.riveFile = riveFile.file + hybridRiveFile.referencedAssetCache = riveFile.cache return hybridRiveFile } catch let error as NSError { throw RuntimeError.error(withMessage: "Failed to load Rive file: \(error.localizedDescription)") @@ -76,18 +287,25 @@ class HybridRiveFileFactory: HybridRiveFileFactorySpec { } } } - - func fromResource(resource: String, loadCdn: Bool) throws -> Promise<(any HybridRiveFileSpec)> { + + func fromResource(resource: String, loadCdn: Bool, referencedAssets: ReferencedAssetsType?) throws -> Promise<(any HybridRiveFileSpec)> { guard let _ = Bundle.main.path(forResource: resource, ofType: "riv") else { throw RuntimeError.error(withMessage: "Could not find Rive file: \(resource).riv") } - + return Promise.async { do { + let riveFile = try await withCheckedThrowingContinuation { continuation in DispatchQueue.global(qos: .userInitiated).async { do { - let riveFile = try RiveFile(resource: resource, loadCdn: loadCdn) + var referencedAssetCache = Ref(ReferencedAssetCache()) + let riveFile = + if let customLoader = self.toCustomLoader(referencedAssets: referencedAssets, cache: referencedAssetCache) { + try RiveFile(resource: resource, loadCdn: loadCdn, customAssetLoader: customLoader) + } else { + try RiveFile(resource: resource, loadCdn: loadCdn) + } DispatchQueue.main.async { continuation.resume(returning: riveFile) } @@ -98,7 +316,7 @@ class HybridRiveFileFactory: HybridRiveFileFactorySpec { } } } - + let hybridRiveFile = HybridRiveFile() hybridRiveFile.riveFile = riveFile return hybridRiveFile @@ -109,15 +327,22 @@ class HybridRiveFileFactory: HybridRiveFileFactorySpec { } } } - - func fromBytes(bytes: ArrayBufferHolder, loadCdn: Bool) throws -> Promise<(any HybridRiveFileSpec)> { + + func fromBytes(bytes: ArrayBufferHolder, loadCdn: Bool, referencedAssets: ReferencedAssetsType?) throws -> Promise<(any HybridRiveFileSpec)> { let data = bytes.toData(copyIfNeeded: false) return Promise.async { do { let riveFile = try await withCheckedThrowingContinuation { continuation in DispatchQueue.global(qos: .userInitiated).async { do { - let riveFile = try RiveFile(data: data, loadCdn: loadCdn) + var referencedAssetCache = Ref(ReferencedAssetCache()) + let riveFile = + if let customLoader = self.toCustomLoader(referencedAssets: referencedAssets, cache: referencedAssetCache) { + try RiveFile(data: data, loadCdn: loadCdn, customAssetLoader: customLoader) + } else { + try RiveFile(data: data, loadCdn: loadCdn) + } + DispatchQueue.main.async { continuation.resume(returning: riveFile) } @@ -128,7 +353,7 @@ class HybridRiveFileFactory: HybridRiveFileFactorySpec { } } } - + let hybridRiveFile = HybridRiveFile() hybridRiveFile.riveFile = riveFile return hybridRiveFile diff --git a/ios/RCTLog.swift b/ios/RCTLog.swift new file mode 100644 index 00000000..5065eb6d --- /dev/null +++ b/ios/RCTLog.swift @@ -0,0 +1,29 @@ +func RCTLogError(_ message: String, _ file: String=#file, _ line: UInt=#line) { + DispatchQueue.main.async { + RCTSwiftLog.error(message, file: file, line: line) + } +} + +func RCTLogWarn(_ message: String, _ file: String=#file, _ line: UInt=#line) { + DispatchQueue.main.async { + RCTSwiftLog.warn(message, file: file, line: line) + } +} + +func RCTLogInfo(_ message: String, _ file: String=#file, _ line: UInt=#line) { + DispatchQueue.main.async { + RCTSwiftLog.info(message, file: file, line: line) + } +} + +func RCTLog(_ message: String, _ file: String=#file, _ line: UInt=#line) { + DispatchQueue.main.async { + RCTSwiftLog.log(message, file: file, line: line) + } +} + +func RCTLogTrace(_ message: String, _ file: String=#file, _ line: UInt=#line) { + DispatchQueue.main.async { + RCTSwiftLog.trace(message, file: file, line: line) + } +} diff --git a/ios/RCTSwiftLog.h b/ios/RCTSwiftLog.h new file mode 100644 index 00000000..8f9deab7 --- /dev/null +++ b/ios/RCTSwiftLog.h @@ -0,0 +1,11 @@ +#import + +@interface RCTSwiftLog : NSObject + ++ (void)error:(NSString * _Nonnull)message file:(NSString * _Nonnull)file line:(NSUInteger)line; ++ (void)warn:(NSString * _Nonnull)message file:(NSString * _Nonnull)file line:(NSUInteger)line; ++ (void)info:(NSString * _Nonnull)message file:(NSString * _Nonnull)file line:(NSUInteger)line; ++ (void)log:(NSString * _Nonnull)message file:(NSString * _Nonnull)file line:(NSUInteger)line; ++ (void)trace:(NSString * _Nonnull)message file:(NSString * _Nonnull)file line:(NSUInteger)line; + +@end diff --git a/ios/RCTSwiftLog.m b/ios/RCTSwiftLog.m new file mode 100644 index 00000000..4f19b2e0 --- /dev/null +++ b/ios/RCTSwiftLog.m @@ -0,0 +1,38 @@ +// +// RCTSwiftLog.m +// +// +// + +#import + +#import "RCTSwiftLog.h" + +@implementation RCTSwiftLog + ++ (void)info:(NSString *)message file:(NSString *)file line:(NSUInteger)line +{ + _RCTLogNativeInternal(RCTLogLevelInfo, file.UTF8String, (int)line, @"%@", message); +} + ++ (void)warn:(NSString *)message file:(NSString *)file line:(NSUInteger)line +{ + _RCTLogNativeInternal(RCTLogLevelWarning, file.UTF8String, (int)line, @"%@", message); +} + ++ (void)error:(NSString *)message file:(NSString *)file line:(NSUInteger)line +{ + _RCTLogNativeInternal(RCTLogLevelError, file.UTF8String, (int)line, @"%@", message); +} + ++ (void)log:(NSString *)message file:(NSString *)file line:(NSUInteger)line +{ + _RCTLogNativeInternal(RCTLogLevelInfo, file.UTF8String, (int)line, @"%@", message); +} + ++ (void)trace:(NSString *)message file:(NSString *)file line:(NSUInteger)line +{ + _RCTLogNativeInternal(RCTLogLevelTrace, file.UTF8String, (int)line, @"%@", message); +} + +@end \ No newline at end of file diff --git a/ios/RiveReactNativeView.swift b/ios/RiveReactNativeView.swift index f6ee5340..6d7bf6b2 100644 --- a/ios/RiveReactNativeView.swift +++ b/ios/RiveReactNativeView.swift @@ -67,7 +67,7 @@ class RiveReactNativeView: UIView, RiveStateMachineDelegate { func pause() { baseViewModel?.pause() } - + func addEventListener(_ onEvent: @escaping (UnifiedRiveEvent) -> Void) { eventListeners.append(onEvent) } From 262908a320f3461c6ce38f974626189ef4a4661c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mikl=C3=B3s=20Fazekas?= Date: Thu, 6 Nov 2025 07:11:10 +0100 Subject: [PATCH 02/24] fix: referencedAssets (ios) - missing files --- ios/HybridRiveFileFactory.swift | 272 ++++---------------------------- src/core/RiveFile.ts | 38 ++++- 2 files changed, 57 insertions(+), 253 deletions(-) diff --git a/ios/HybridRiveFileFactory.swift b/ios/HybridRiveFileFactory.swift index a9b9d95c..aca5b36c 100644 --- a/ios/HybridRiveFileFactory.swift +++ b/ios/HybridRiveFileFactory.swift @@ -1,218 +1,9 @@ import NitroModules import RiveRuntime - -final class Ref { - var value: T - init(_ value: T) { - self.value = value - } -} - -struct FileAndCache { - var file: RiveFile - var cache: [String: RiveFileAsset] -} - -private func isValidUrl(_ url: String) -> Bool { - if let url = URL(string: url) { - return url.scheme == "file" || url.scheme == "http" || url.scheme == "https" - } else { - return false - } - } - -func createIncorrectRiveURL(_ url: String) -> NSError { - return NSError(domain: RiveErrorDomain, code: 900, userInfo: [NSLocalizedDescriptionKey: "Unable to download Rive file from: \(url)", "name": "IncorrectRiveFileURL"]) -} - - -func createAssetFileError(_ assetName: String) -> NSError { - return NSError(domain: RiveErrorDomain, code: 801, userInfo: [NSLocalizedDescriptionKey: "Could not load Rive asset: \(assetName)", "name": "FileNotFound"]) -} - - - -final class HybridRiveFileFactory: HybridRiveFileFactorySpec { - private func handleRiveError(error: NSError) { - /*if isUserHandlingErrors { - let rnRiveError = RNRiveError.mapToRNRiveError(riveError: error) - if let safeRnRiveError = rnRiveError { - onRNRiveError(safeRnRiveError) - } - } else { */ - RCTLogError(error.localizedDescription) - /* } */ - } - - private func handleInvalidUrlError(url: String) { - handleRiveError(error: createIncorrectRiveURL(url)) - } - - private func downloadUrlAsset(url: String, listener: @escaping (Data) -> Void) { - guard isValidUrl(url) else { - handleInvalidUrlError(url: url) - return - } - if let fileUrl = URL(string: url), fileUrl.scheme == "file" { - do { - let data = try Data(contentsOf: fileUrl) - listener(data) - } catch { - handleInvalidUrlError(url: url) - } - return - } - - let queue = URLSession.shared - guard let requestUrl = URL(string: url) else { - handleInvalidUrlError(url: url) - return - } - - let request = URLRequest(url: requestUrl) - let task = queue.dataTask(with: request) {[weak self] data, response, error in - if error != nil { - self?.handleInvalidUrlError(url: url) - } else if let data = data { - listener(data) - } - } - - task.resume() - } - - private func processAssetBytes(_ data: Data, asset: RiveFileAsset, factory: RiveFactory) { - if (data.isEmpty == true) { - return; - } - DispatchQueue.global(qos: .background).async { - switch asset { - case let imageAsset as RiveImageAsset: - let decodedImage = factory.decodeImage(data) - DispatchQueue.main.async { - imageAsset.renderImage(decodedImage) - } - case let fontAsset as RiveFontAsset: - let decodedFont = factory.decodeFont(data) - DispatchQueue.main.async { - fontAsset.font(decodedFont) - } - case let audioAsset as RiveAudioAsset: - guard let decodedAudio = factory.decodeAudio(data) else { return } - DispatchQueue.main.async { - audioAsset.audio(decodedAudio) - } - default: - break - } - } - } - - private func handleSourceAssetId(_ sourceAssetId: String, asset: RiveFileAsset, factory: RiveFactory) { - guard URL(string: sourceAssetId) != nil else { - return - } - - downloadUrlAsset(url: sourceAssetId) { [weak self] data in - self?.processAssetBytes(data, asset: asset, factory: factory) - } - } - - private func handleSourceUrl(_ sourceUrl: String, asset: RiveFileAsset, factory: RiveFactory) { - downloadUrlAsset(url: sourceUrl) { [weak self] data in - self?.processAssetBytes(data, asset: asset, factory: factory) - } - } - - private func splitFileNameAndExtension(fileName: String) -> (name: String?, ext: String?)? { - let components = fileName.split(separator: ".") - let name = (fileName as NSString).deletingPathExtension; - let fileExtension = (fileName as NSString).pathExtension; - guard components.count == 2 else { return nil } - return (name: name, ext: fileExtension) - } - - - private func loadResourceAsset(sourceAsset: String, path: String?, listener: @escaping (Data) -> Void) { - guard let splitSourceAssetName = splitFileNameAndExtension(fileName: sourceAsset), - let name = splitSourceAssetName.name, - let ext = splitSourceAssetName.ext else { - handleRiveError(error: createAssetFileError(sourceAsset)) - return - } - - guard let folderUrl = Bundle.main.url(forResource: name, withExtension: ext) else { - handleRiveError(error: createAssetFileError(sourceAsset)) - return - } - - DispatchQueue.global(qos: .background).async { [weak self] in - do { - let fileData = try Data(contentsOf: folderUrl) - DispatchQueue.main.async { - listener(fileData) - } - } catch { - DispatchQueue.main.async { - self?.handleRiveError(error: createAssetFileError(sourceAsset)) - } - } - } - } - - private func handleSourceAsset(_ sourceAsset: String, path: String?, asset: RiveFileAsset, factory: RiveFactory) { - loadResourceAsset(sourceAsset: sourceAsset, path: path) {[weak self] data in - self?.processAssetBytes(data, asset: asset, factory: factory) - } - } - - private func loadAsset(source: ResolvedReferencedAsset, asset: RiveFileAsset, factory: RiveFactory) { - let sourceAssetId = source.sourceAssetId - let sourceUrl = source.sourceUrl - let sourceAsset = source.sourceAsset - - if let sourceAssetId = sourceAssetId { - handleSourceAssetId(sourceAssetId, asset: asset, factory: factory) - } else if let sourceUrl = sourceUrl { - handleSourceUrl(sourceUrl, asset: asset, factory: factory) - } else if let sourceAsset = sourceAsset { - handleSourceAsset(sourceAsset, path: source.path, asset: asset, factory: factory) - } - } - - func toCustomLoader(referencedAssets: ReferencedAssetsType?, cache: Ref) -> LoadAsset? { - guard let referencedAssets = referencedAssets, let referencedAssets = referencedAssets.data else { - return nil - } - return { (asset: RiveFileAsset, data: Data, factory: RiveFactory) -> Bool in - let assetByUniqueName = referencedAssets[asset.uniqueName()] - guard let assetData = assetByUniqueName ?? referencedAssets[asset.name()] else { - return false - } - let usedKey = assetByUniqueName != nil ? asset.uniqueName() : asset.name() - - cache.value[asset.uniqueName()] = asset - - self.loadAsset(source: assetData, asset: asset, factory: factory) - - return false - } - } - - private func buildRiveFile(data: Data, loadCdn: Bool,referencedAssets: ReferencedAssetsType?) throws -> FileAndCache { - var referencedAssetCache = Ref(ReferencedAssetCache()) - let riveFile = - if let customLoader = toCustomLoader(referencedAssets: referencedAssets, cache: referencedAssetCache) { - try RiveFile(data: data, loadCdn: loadCdn, customAssetLoader: customLoader) - } else { - try RiveFile(data: data, loadCdn: loadCdn) - } - return FileAndCache(file: riveFile, cache: referencedAssetCache.value) - } - +class HybridRiveFileFactory: HybridRiveFileFactorySpec { // MARK: Public Methods - func fromURL(url: String, loadCdn: Bool,referencedAssets: ReferencedAssetsType?) throws -> Promise<(any HybridRiveFileSpec)> { + func fromURL(url: String, loadCdn: Bool) throws -> Promise<(any HybridRiveFileSpec)> { // TODO: should we make use of the underlying Rive iOS URL asset loading instead return Promise.async { do { @@ -223,9 +14,8 @@ final class HybridRiveFileFactory: HybridRiveFileFactorySpec { let riveFile = try await withCheckedThrowingContinuation { continuation in DispatchQueue.global(qos: .userInitiated).async { do { - let data = try Data(contentsOf: url) - let riveFile = try self.buildRiveFile(data: data, loadCdn: loadCdn, referencedAssets: referencedAssets) - + let riveData = try Data(contentsOf: url) + let riveFile = try RiveFile(data: riveData, loadCdn: true) DispatchQueue.main.async { continuation.resume(returning: riveFile) } @@ -238,19 +28,19 @@ final class HybridRiveFileFactory: HybridRiveFileFactorySpec { } let hybridRiveFile = HybridRiveFile() - hybridRiveFile.riveFile = riveFile.file - hybridRiveFile.referencedAssetCache = riveFile.cache + hybridRiveFile.riveFile = riveFile return hybridRiveFile } catch let error as NSError { - throw RuntimeError.error(withMessage: "Failed to download Rive file: \(error.localizedDescription)") + throw RuntimeError.error( + withMessage: "Failed to download Rive file: \(error.localizedDescription)") } catch { throw RuntimeError.error(withMessage: "Unknown error occurred while downloading Rive file") } } } - func fromFileURL(fileURL: String, loadCdn: Bool, referencedAssets: ReferencedAssetsType?) throws -> Promise<(any HybridRiveFileSpec)> { - guard let url = URL(string:fileURL) else { + func fromFileURL(fileURL: String, loadCdn: Bool) throws -> Promise<(any HybridRiveFileSpec)> { + guard let url = URL(string: fileURL) else { throw RuntimeError.error(withMessage: "fromFileURL: Invalid URL: \(fileURL)") } @@ -264,7 +54,8 @@ final class HybridRiveFileFactory: HybridRiveFileFactorySpec { DispatchQueue.global(qos: .userInitiated).async { do { let data = try Data(contentsOf: url) - let riveFile = try self.buildRiveFile(data: data, loadCdn: loadCdn, referencedAssets: referencedAssets) + + let riveFile = try RiveFile(data: data, loadCdn: loadCdn) DispatchQueue.main.async { continuation.resume(returning: riveFile) } @@ -277,35 +68,28 @@ final class HybridRiveFileFactory: HybridRiveFileFactorySpec { } let hybridRiveFile = HybridRiveFile() - hybridRiveFile.riveFile = riveFile.file - hybridRiveFile.referencedAssetCache = riveFile.cache + hybridRiveFile.riveFile = riveFile return hybridRiveFile } catch let error as NSError { - throw RuntimeError.error(withMessage: "Failed to load Rive file: \(error.localizedDescription)") + throw RuntimeError.error( + withMessage: "Failed to load Rive file: \(error.localizedDescription)") } catch { throw RuntimeError.error(withMessage: "Unknown error occurred while loading Rive file") } } } - func fromResource(resource: String, loadCdn: Bool, referencedAssets: ReferencedAssetsType?) throws -> Promise<(any HybridRiveFileSpec)> { - guard let _ = Bundle.main.path(forResource: resource, ofType: "riv") else { + func fromResource(resource: String, loadCdn: Bool) throws -> Promise<(any HybridRiveFileSpec)> { + guard Bundle.main.path(forResource: resource, ofType: "riv") != nil else { throw RuntimeError.error(withMessage: "Could not find Rive file: \(resource).riv") } return Promise.async { do { - let riveFile = try await withCheckedThrowingContinuation { continuation in DispatchQueue.global(qos: .userInitiated).async { do { - var referencedAssetCache = Ref(ReferencedAssetCache()) - let riveFile = - if let customLoader = self.toCustomLoader(referencedAssets: referencedAssets, cache: referencedAssetCache) { - try RiveFile(resource: resource, loadCdn: loadCdn, customAssetLoader: customLoader) - } else { - try RiveFile(resource: resource, loadCdn: loadCdn) - } + let riveFile = try RiveFile(resource: resource, loadCdn: loadCdn) DispatchQueue.main.async { continuation.resume(returning: riveFile) } @@ -321,28 +105,24 @@ final class HybridRiveFileFactory: HybridRiveFileFactorySpec { hybridRiveFile.riveFile = riveFile return hybridRiveFile } catch let error as NSError { - throw RuntimeError.error(withMessage: "Failed to load Rive file: \(error.localizedDescription)") + throw RuntimeError.error( + withMessage: "Failed to load Rive file: \(error.localizedDescription)") } catch { throw RuntimeError.error(withMessage: "Unknown error occurred while loading Rive file") } } } - func fromBytes(bytes: ArrayBufferHolder, loadCdn: Bool, referencedAssets: ReferencedAssetsType?) throws -> Promise<(any HybridRiveFileSpec)> { + func fromBytes(bytes: ArrayBufferHolder, loadCdn: Bool) throws -> Promise< + (any HybridRiveFileSpec) + > { let data = bytes.toData(copyIfNeeded: false) return Promise.async { do { let riveFile = try await withCheckedThrowingContinuation { continuation in DispatchQueue.global(qos: .userInitiated).async { do { - var referencedAssetCache = Ref(ReferencedAssetCache()) - let riveFile = - if let customLoader = self.toCustomLoader(referencedAssets: referencedAssets, cache: referencedAssetCache) { - try RiveFile(data: data, loadCdn: loadCdn, customAssetLoader: customLoader) - } else { - try RiveFile(data: data, loadCdn: loadCdn) - } - + let riveFile = try RiveFile(data: data, loadCdn: loadCdn) DispatchQueue.main.async { continuation.resume(returning: riveFile) } @@ -358,9 +138,11 @@ final class HybridRiveFileFactory: HybridRiveFileFactorySpec { hybridRiveFile.riveFile = riveFile return hybridRiveFile } catch let error as NSError { - throw RuntimeError.error(withMessage: "Failed to load Rive file from bytes: \(error.localizedDescription)") + throw RuntimeError.error( + withMessage: "Failed to load Rive file from bytes: \(error.localizedDescription)") } catch { - throw RuntimeError.error(withMessage: "Unknown error occurred while loading Rive file from bytes") + throw RuntimeError.error( + withMessage: "Unknown error occurred while loading Rive file from bytes") } } } diff --git a/src/core/RiveFile.ts b/src/core/RiveFile.ts index cdebe93a..8be1ccfe 100644 --- a/src/core/RiveFile.ts +++ b/src/core/RiveFile.ts @@ -7,6 +7,7 @@ import type { // This import path isn't handled by @types/react-native // @ts-ignore import resolveAssetSource from 'react-native/Libraries/Image/resolveAssetSource'; +import type { ResolvedReferencedAssets } from '../hooks/useRiveFile'; const RiveFileInternal = NitroModules.createHybridObject('RiveFileFactory'); @@ -24,22 +25,32 @@ export namespace RiveFileFactory { */ export async function fromURL( url: string, + referencedAssets: ResolvedReferencedAssets | undefined, loadCdn: boolean = true ): Promise { - return RiveFileInternal.fromURL(url, loadCdn); + return RiveFileInternal.fromURL( + url, + loadCdn, + referencedAssets ? { data: referencedAssets } : undefined + ); } /** * Creates a RiveFile instance from a local file path URL. - * @param pathURL - The local file path of the Rive graphic file + * @param pathURL - The local file path of the Rive animation file * @param loadCdn - Whether to load from CDN (default: true) * @returns Promise that resolves to a RiveFile instance */ export async function fromFileURL( fileURL: string, + referencedAssets: ResolvedReferencedAssets | undefined = undefined, loadCdn: boolean = true ): Promise { - return RiveFileInternal.fromFileURL(fileURL, loadCdn); + return RiveFileInternal.fromFileURL( + fileURL, + loadCdn, + referencedAssets ? { data: referencedAssets } : undefined + ); } /** @@ -50,9 +61,14 @@ export namespace RiveFileFactory { */ export async function fromResource( resource: string, + referencedAssets: ResolvedReferencedAssets | undefined, loadCdn: boolean = true ): Promise { - return RiveFileInternal.fromResource(resource, loadCdn); + return RiveFileInternal.fromResource( + resource, + loadCdn, + referencedAssets ? { data: referencedAssets } : undefined + ); } /** @@ -63,9 +79,14 @@ export namespace RiveFileFactory { */ export async function fromBytes( bytes: ArrayBuffer, + referencedAssets: ResolvedReferencedAssets | undefined, loadCdn: boolean = true ): Promise { - return RiveFileInternal.fromBytes(bytes, loadCdn); + return RiveFileInternal.fromBytes( + bytes, + loadCdn, + referencedAssets ? { data: referencedAssets } : undefined + ); } /** @@ -92,6 +113,7 @@ export namespace RiveFileFactory { */ export async function fromSource( source: number | { uri: string }, + referencedAssets: ResolvedReferencedAssets | undefined, loadCdn: boolean = true ): Promise { const assetID = typeof source === 'number' ? source : null; @@ -108,16 +130,16 @@ export namespace RiveFileFactory { try { // handle http address and dev server if (assetURI.match(/https?:\/\//)) { - return RiveFileFactory.fromURL(assetURI, loadCdn); + return RiveFileFactory.fromURL(assetURI, referencedAssets, loadCdn); } // handle iOS bundled asset if (assetURI.match(/file:\/\//)) { - return RiveFileFactory.fromFileURL(assetURI, loadCdn); + return RiveFileFactory.fromFileURL(assetURI, referencedAssets, loadCdn); } // handle Android bundled asset or resource name uri - return RiveFileFactory.fromResource(assetURI, loadCdn); + return RiveFileFactory.fromResource(assetURI, referencedAssets, loadCdn); } catch (error: unknown) { const errorMessage = error instanceof Error ? error.message : String(error); From 15b4300e569d73b901a9942f42fcfc541f7d3ce7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mikl=C3=B3s=20Fazekas?= Date: Thu, 6 Nov 2025 08:38:51 +0100 Subject: [PATCH 03/24] feat: referencedAssets (ios) --- Rive.podspec | 1 + ios/HybridRiveFileFactory.swift | 55 ++++++++- ios/ReferencedAssetLoader.swift | 212 ++++++++++++++++++++++++++++++++ src/hooks/useRiveFile.ts | 152 +++++++++++++++++++---- src/index.tsx | 7 +- src/specs/RiveFile.nitro.ts | 38 +++++- 6 files changed, 433 insertions(+), 32 deletions(-) create mode 100644 ios/ReferencedAssetLoader.swift diff --git a/Rive.podspec b/Rive.podspec index 78392d41..9c4ddd9f 100644 --- a/Rive.podspec +++ b/Rive.podspec @@ -43,6 +43,7 @@ Pod::Spec.new do |s| s.source_files = "ios/**/*.{h,m,mm,swift}" + s.public_header_files = ['ios/RCTSwiftLog.h'] load 'nitrogen/generated/ios/Rive+autolinking.rb' add_nitrogen_files(s) diff --git a/ios/HybridRiveFileFactory.swift b/ios/HybridRiveFileFactory.swift index aca5b36c..10940620 100644 --- a/ios/HybridRiveFileFactory.swift +++ b/ios/HybridRiveFileFactory.swift @@ -1,7 +1,20 @@ import NitroModules import RiveRuntime -class HybridRiveFileFactory: HybridRiveFileFactorySpec { +final class HybridRiveFileFactory: HybridRiveFileFactorySpec { + private let assetLoader = ReferencedAssetLoader() + + private func buildRiveFile(data: Data, loadCdn: Bool,referencedAssets: ReferencedAssetsType?) throws -> FileAndCache { + var referencedAssetCache = Ref(ReferencedAssetCache()) + let riveFile = + if let customLoader = assetLoader.createCustomLoader(referencedAssets: referencedAssets, cache: referencedAssetCache) { + try RiveFile(data: data, loadCdn: loadCdn, customAssetLoader: customLoader) + } else { + try RiveFile(data: data, loadCdn: loadCdn) + } + return FileAndCache(file: riveFile, cache: referencedAssetCache.value) + } + // MARK: Public Methods func fromURL(url: String, loadCdn: Bool) throws -> Promise<(any HybridRiveFileSpec)> { // TODO: should we make use of the underlying Rive iOS URL asset loading instead @@ -55,7 +68,36 @@ class HybridRiveFileFactory: HybridRiveFileFactorySpec { do { let data = try Data(contentsOf: url) - let riveFile = try RiveFile(data: data, loadCdn: loadCdn) + let hybridRiveFile = HybridRiveFile() + hybridRiveFile.riveFile = riveFile.file + hybridRiveFile.referencedAssetCache = riveFile.cache + return hybridRiveFile + } catch let error as NSError { + throw RuntimeError.error(withMessage: "Failed to load Rive file: \(error.localizedDescription)") + } catch { + throw RuntimeError.error(withMessage: "Unknown error occurred while loading Rive file") + } + } + } + + func fromResource(resource: String, loadCdn: Bool, referencedAssets: ReferencedAssetsType?) throws -> Promise<(any HybridRiveFileSpec)> { + guard let _ = Bundle.main.path(forResource: resource, ofType: "riv") else { + throw RuntimeError.error(withMessage: "Could not find Rive file: \(resource).riv") + } + + return Promise.async { + do { + + let riveFile = try await withCheckedThrowingContinuation { continuation in + DispatchQueue.global(qos: .userInitiated).async { + do { + var referencedAssetCache = Ref(ReferencedAssetCache()) + let riveFile = + if let customLoader = self.assetLoader.createCustomLoader(referencedAssets: referencedAssets, cache: referencedAssetCache) { + try RiveFile(resource: resource, loadCdn: loadCdn, customAssetLoader: customLoader) + } else { + try RiveFile(resource: resource, loadCdn: loadCdn) + } DispatchQueue.main.async { continuation.resume(returning: riveFile) } @@ -122,7 +164,14 @@ class HybridRiveFileFactory: HybridRiveFileFactorySpec { let riveFile = try await withCheckedThrowingContinuation { continuation in DispatchQueue.global(qos: .userInitiated).async { do { - let riveFile = try RiveFile(data: data, loadCdn: loadCdn) + var referencedAssetCache = Ref(ReferencedAssetCache()) + let riveFile = + if let customLoader = self.assetLoader.createCustomLoader(referencedAssets: referencedAssets, cache: referencedAssetCache) { + try RiveFile(data: data, loadCdn: loadCdn, customAssetLoader: customLoader) + } else { + try RiveFile(data: data, loadCdn: loadCdn) + } + DispatchQueue.main.async { continuation.resume(returning: riveFile) } diff --git a/ios/ReferencedAssetLoader.swift b/ios/ReferencedAssetLoader.swift new file mode 100644 index 00000000..fd4be059 --- /dev/null +++ b/ios/ReferencedAssetLoader.swift @@ -0,0 +1,212 @@ +import NitroModules +import RiveRuntime + +final class Ref { + var value: T + init(_ value: T) { + self.value = value + } +} + +struct FileAndCache { + var file: RiveFile + var cache: [String: RiveFileAsset] +} + +private func isValidUrl(_ url: String) -> Bool { + if let url = URL(string: url) { + return url.scheme == "file" || url.scheme == "http" || url.scheme == "https" + } else { + return false + } +} + +func createIncorrectRiveURL(_ url: String) -> NSError { + return NSError( + domain: RiveErrorDomain, code: 900, + userInfo: [ + NSLocalizedDescriptionKey: "Unable to download Rive file from: \(url)", + "name": "IncorrectRiveFileURL", + ]) +} + +func createAssetFileError(_ assetName: String) -> NSError { + return NSError( + domain: RiveErrorDomain, code: 801, + userInfo: [ + NSLocalizedDescriptionKey: "Could not load Rive asset: \(assetName)", "name": "FileNotFound", + ]) +} + +final class ReferencedAssetLoader { + private func handleRiveError(error: NSError) { + // TODO allow user to specify onError callback + RCTLogError(error.localizedDescription) + } + + private func handleInvalidUrlError(url: String) { + handleRiveError(error: createIncorrectRiveURL(url)) + } + + private func downloadUrlAsset(url: String, listener: @escaping (Data) -> Void) { + guard isValidUrl(url) else { + handleInvalidUrlError(url: url) + return + } + if let fileUrl = URL(string: url), fileUrl.scheme == "file" { + do { + let data = try Data(contentsOf: fileUrl) + listener(data) + } catch { + handleInvalidUrlError(url: url) + } + return + } + + let queue = URLSession.shared + guard let requestUrl = URL(string: url) else { + handleInvalidUrlError(url: url) + return + } + + let request = URLRequest(url: requestUrl) + let task = queue.dataTask(with: request) { [weak self] data, response, error in + if error != nil { + self?.handleInvalidUrlError(url: url) + } else if let data = data { + listener(data) + } + } + + task.resume() + } + + private func processAssetBytes(_ data: Data, asset: RiveFileAsset, factory: RiveFactory) { + if data.isEmpty == true { + return + } + DispatchQueue.global(qos: .background).async { + switch asset { + case let imageAsset as RiveImageAsset: + let decodedImage = factory.decodeImage(data) + DispatchQueue.main.async { + imageAsset.renderImage(decodedImage) + } + case let fontAsset as RiveFontAsset: + let decodedFont = factory.decodeFont(data) + DispatchQueue.main.async { + fontAsset.font(decodedFont) + } + case let audioAsset as RiveAudioAsset: + guard let decodedAudio = factory.decodeAudio(data) else { return } + DispatchQueue.main.async { + audioAsset.audio(decodedAudio) + } + default: + break + } + } + } + + private func handleSourceAssetId( + _ sourceAssetId: String, asset: RiveFileAsset, factory: RiveFactory + ) { + guard URL(string: sourceAssetId) != nil else { + return + } + + downloadUrlAsset(url: sourceAssetId) { [weak self] data in + self?.processAssetBytes(data, asset: asset, factory: factory) + } + } + + private func handleSourceUrl(_ sourceUrl: String, asset: RiveFileAsset, factory: RiveFactory) { + downloadUrlAsset(url: sourceUrl) { [weak self] data in + self?.processAssetBytes(data, asset: asset, factory: factory) + } + } + + private func splitFileNameAndExtension(fileName: String) -> (name: String?, ext: String?)? { + let components = fileName.split(separator: ".") + let name = (fileName as NSString).deletingPathExtension + let fileExtension = (fileName as NSString).pathExtension + guard components.count == 2 else { return nil } + return (name: name, ext: fileExtension) + } + + private func loadResourceAsset( + sourceAsset: String, path: String?, listener: @escaping (Data) -> Void + ) { + guard let splitSourceAssetName = splitFileNameAndExtension(fileName: sourceAsset), + let name = splitSourceAssetName.name, + let ext = splitSourceAssetName.ext + else { + handleRiveError(error: createAssetFileError(sourceAsset)) + return + } + + guard let folderUrl = Bundle.main.url(forResource: name, withExtension: ext) else { + handleRiveError(error: createAssetFileError(sourceAsset)) + return + } + + DispatchQueue.global(qos: .background).async { [weak self] in + do { + let fileData = try Data(contentsOf: folderUrl) + DispatchQueue.main.async { + listener(fileData) + } + } catch { + DispatchQueue.main.async { + self?.handleRiveError(error: createAssetFileError(sourceAsset)) + } + } + } + } + + private func handleSourceAsset( + _ sourceAsset: String, path: String?, asset: RiveFileAsset, factory: RiveFactory + ) { + loadResourceAsset(sourceAsset: sourceAsset, path: path) { [weak self] data in + self?.processAssetBytes(data, asset: asset, factory: factory) + } + } + + private func loadAsset( + source: ResolvedReferencedAsset, asset: RiveFileAsset, factory: RiveFactory + ) { + let sourceAssetId = source.sourceAssetId + let sourceUrl = source.sourceUrl + let sourceAsset = source.sourceAsset + + if let sourceAssetId = sourceAssetId { + handleSourceAssetId(sourceAssetId, asset: asset, factory: factory) + } else if let sourceUrl = sourceUrl { + handleSourceUrl(sourceUrl, asset: asset, factory: factory) + } else if let sourceAsset = sourceAsset { + handleSourceAsset(sourceAsset, path: source.path, asset: asset, factory: factory) + } + } + + func createCustomLoader(referencedAssets: ReferencedAssetsType?, cache: Ref) + -> LoadAsset? + { + guard let referencedAssets = referencedAssets, let referencedAssets = referencedAssets.data + else { + return nil + } + return { (asset: RiveFileAsset, data: Data, factory: RiveFactory) -> Bool in + let assetByUniqueName = referencedAssets[asset.uniqueName()] + guard let assetData = assetByUniqueName ?? referencedAssets[asset.name()] else { + return false + } + let usedKey = assetByUniqueName != nil ? asset.uniqueName() : asset.name() + + cache.value[asset.uniqueName()] = asset + + self.loadAsset(source: assetData, asset: asset, factory: factory) + + return false + } + } +} diff --git a/src/hooks/useRiveFile.ts b/src/hooks/useRiveFile.ts index 51fe9253..2aa3f697 100644 --- a/src/hooks/useRiveFile.ts +++ b/src/hooks/useRiveFile.ts @@ -1,20 +1,94 @@ -import { useState, useEffect } from 'react'; +import { useState, useEffect, useMemo, useRef } from 'react'; +import { Image } from 'react-native'; import { RiveFileFactory, type RiveFile } from 'react-native-rive'; +import type { ResolvedReferencedAsset } from '../specs/RiveFile.nitro'; -export type RiveFileInput = number | { uri: string } | string | ArrayBuffer; +type RiveFileInput = number | { uri: string } | string | ArrayBuffer; -export function useRiveFile(input?: RiveFileInput) { - const [riveFile, setRiveFile] = useState(null); - const [isLoading, setIsLoading] = useState(true); - const [error, setError] = useState(null); +type ReferencedAsset = { source: number | { uri: string } }; - useEffect(() => { - if (!input) { - setRiveFile(null); - setIsLoading(false); - return; +export interface ReferencedAssets { + [assetName: string]: ReferencedAsset; +} + +export type ResolvedReferencedAssets = { + [assetName: string]: ResolvedReferencedAsset; +}; + +export type UseRiveFileOptions = { + referencedAssets?: ReferencedAssets; +}; + +function parsePossibleSources( + source: ReferencedAsset['source'] +): ResolvedReferencedAsset { + if (typeof source === 'number') { + const resolvedAsset = Image.resolveAssetSource(source); + if (resolvedAsset && resolvedAsset.uri) { + return { sourceAssetId: resolvedAsset.uri }; + } else { + throw new Error('Invalid asset source provided.'); + } + } + + const uri = (source as any).uri; + if (typeof source === 'object' && uri) { + return { sourceUrl: uri }; + } + + const asset = (source as any).fileName; + const path = (source as any).path; + + if (typeof source === 'object' && asset) { + const result: ResolvedReferencedAsset = { sourceAsset: asset }; + + if (path) { + result.path = path; } + return result; + } + + throw new Error('Invalid source provided.'); +} + +function transformFilesHandledMapping( + mapping?: ReferencedAssets +): ResolvedReferencedAssets | undefined { + const transformedMapping: ResolvedReferencedAssets = {}; + if (mapping === undefined) { + return undefined; + } + + Object.entries(mapping).forEach(([key, option]) => { + transformedMapping[key] = parsePossibleSources(option.source); + }); + + return transformedMapping; +} + +type RiveFileHookResult = + | { riveFile: RiveFile; isLoading: false; error: null } + | { riveFile: null; isLoading: true; error: null } + | { riveFile: null; isLoading: false; error: string }; + +export function useRiveFile( + input: RiveFileInput, + options: UseRiveFileOptions = {} +): RiveFileHookResult { + const [result, setResult] = useState({ + riveFile: null, + isLoading: true, + error: null, + }); + const referencedAssets = useMemo( + () => transformFilesHandledMapping(options.referencedAssets), + [options.referencedAssets] + ); + const initialReferencedAssets = useRef(referencedAssets); + const initialInput = useRef(input); + + useEffect(() => { let currentFile: RiveFile | null = null; const loadRiveFile = async () => { @@ -26,25 +100,39 @@ export function useRiveFile(input?: RiveFileInput) { currentInput.startsWith('http://') || currentInput.startsWith('https://') ) { - currentFile = await RiveFileFactory.fromURL(currentInput); + currentFile = await RiveFileFactory.fromURL( + currentInput, + initialReferencedAssets.current + ); } else { - currentFile = await RiveFileFactory.fromResource(currentInput); + currentFile = await RiveFileFactory.fromResource( + currentInput, + initialReferencedAssets.current + ); } } else if (typeof currentInput === 'number' || 'uri' in currentInput) { - currentFile = await RiveFileFactory.fromSource(currentInput); + currentFile = await RiveFileFactory.fromSource( + currentInput, + initialReferencedAssets.current + ); } else if (currentInput instanceof ArrayBuffer) { - currentFile = await RiveFileFactory.fromBytes(currentInput); + currentFile = await RiveFileFactory.fromBytes( + currentInput, + initialReferencedAssets.current + ); } - setRiveFile(currentFile); - setIsLoading(false); - setError(null); + setResult({ riveFile: currentFile!, isLoading: false, error: null }); } catch (err) { console.error(err); - setError( - err instanceof Error ? err.message : 'Failed to load Rive file' - ); - setIsLoading(false); + setResult({ + riveFile: null, + isLoading: false, + error: + err instanceof Error + ? err.message || 'Unknown error' + : 'Failed to load Rive file', + }); } }; @@ -57,5 +145,23 @@ export function useRiveFile(input?: RiveFileInput) { }; }, [input]); - return { riveFile, isLoading, error }; + if (initialReferencedAssets.current !== referencedAssets) { + // TODO: if riveFile not yet loaded?! + const { riveFile } = result; + if (riveFile && referencedAssets) { + riveFile.updateReferencedAssets(referencedAssets); + } + } + + if (initialInput.current !== input) { + console.warn( + 'useRiveFile: Changing input after initial render is not supported.' + ); + } + + return { + riveFile: result.riveFile, + isLoading: result.isLoading, + error: result.error, + } as RiveFileHookResult; } diff --git a/src/index.tsx b/src/index.tsx index 659e1301..76bd3d78 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -46,7 +46,7 @@ export function multiply(a: number, b: number): number { * - play(): Starts playing the animation * - pause(): Pauses the animation */ -export const RiveView = getHostComponent( +export const NitroRiveView = getHostComponent( 'RiveView', () => RiveViewConfig ) as ReactNativeView; @@ -78,3 +78,8 @@ export { useRiveColor } from './hooks/useRiveColor'; export { useRiveTrigger } from './hooks/useRiveTrigger'; export { useRiveFile } from './hooks/useRiveFile'; export { type RiveFileInput } from './hooks/useRiveFile'; +export { RiveConfigurator } from './core/RiveConfigurator'; +export { type RiveConfiguratorConfig } from './core/RiveConfigurator'; +export { type ArtboardSpec } from './specs/ArtboardSpec'; +export { type StateMachineSpec } from './specs/StateMachineSpec'; +export { RiveView } from './core/RiveView'; diff --git a/src/specs/RiveFile.nitro.ts b/src/specs/RiveFile.nitro.ts index 9db60746..f014bc89 100644 --- a/src/specs/RiveFile.nitro.ts +++ b/src/specs/RiveFile.nitro.ts @@ -2,6 +2,17 @@ import type { HybridObject } from 'react-native-nitro-modules'; import type { ViewModel } from './ViewModel.nitro'; import type { ArtboardBy } from './ArtboardBy'; +export type ResolvedReferencedAsset = { + sourceUrl?: string; + sourceAsset?: string; + sourceAssetId?: string; + path?: string; +}; + +export type ReferencedAssetsType = { + data?: Record; +}; + /** * A Rive file (.riv) as created in the Rive editor. */ @@ -16,13 +27,30 @@ export interface RiveFile /** Returns the default view model for the provided artboard */ defaultArtboardViewModel(artboardBy?: ArtboardBy): ViewModel | null; /** Release the Rive file. Important to call when done with the file to free resources. */ - release(): void; // TODO: Switch to `dispose`: https://github.com/mrousavy/nitro/issues/668 + release(): void; // TODO: Switch to `dispose`: https://github.com/mrousavy/nio + updateReferencedAssets(referencedAssets: ReferencedAssetsType): void; } export interface RiveFileFactory extends HybridObject<{ ios: 'swift'; android: 'kotlin' }> { - fromURL(url: string, loadCdn: boolean): Promise; - fromFileURL(fileURL: string, loadCdn: boolean): Promise; - fromResource(resource: string, loadCdn: boolean): Promise; - fromBytes(bytes: ArrayBuffer, loadCdn: boolean): Promise; + fromURL( + url: string, + loadCdn: boolean, + referencedAssets?: ReferencedAssetsType + ): Promise; + fromFileURL( + fileURL: string, + loadCdn: boolean, + referencedAssets?: ReferencedAssetsType + ): Promise; + fromResource( + resource: string, + loadCdn: boolean, + referencedAssets?: ReferencedAssetsType + ): Promise; + fromBytes( + bytes: ArrayBuffer, + loadCdn: boolean, + referencedAssets?: ReferencedAssetsType + ): Promise; } From f21f3ac81f12f238c32851daee979b3d9939372a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mikl=C3=B3s=20Fazekas?= Date: Thu, 6 Nov 2025 08:54:03 +0100 Subject: [PATCH 04/24] nitrogen files --- .../c++/JHybridRiveFileFactorySpec.cpp | 34 +++-- .../c++/JHybridRiveFileFactorySpec.hpp | 8 +- .../android/c++/JHybridRiveFileSpec.cpp | 13 ++ .../android/c++/JHybridRiveFileSpec.hpp | 1 + .../android/c++/JReferencedAssetsType.hpp | 74 +++++++++ .../android/c++/JResolvedReferencedAsset.hpp | 70 +++++++++ .../nitro/rive/HybridRiveFileFactorySpec.kt | 8 +- .../margelo/nitro/rive/HybridRiveFileSpec.kt | 4 + .../nitro/rive/ReferencedAssetsType.kt | 38 +++++ .../nitro/rive/ResolvedReferencedAsset.kt | 47 ++++++ .../generated/ios/Rive-Swift-Cxx-Bridge.hpp | 61 ++++++++ .../generated/ios/Rive-Swift-Cxx-Umbrella.hpp | 6 + .../c++/HybridRiveFileFactorySpecSwift.hpp | 24 ++- .../ios/c++/HybridRiveFileSpecSwift.hpp | 13 ++ .../ios/swift/HybridRiveFileFactorySpec.swift | 8 +- .../swift/HybridRiveFileFactorySpec_cxx.swift | 16 +- .../ios/swift/HybridRiveFileSpec.swift | 1 + .../ios/swift/HybridRiveFileSpec_cxx.swift | 11 ++ .../ios/swift/ReferencedAssetsType.swift | 74 +++++++++ .../ios/swift/ResolvedReferencedAsset.swift | 144 ++++++++++++++++++ .../shared/c++/HybridRiveFileFactorySpec.hpp | 12 +- .../shared/c++/HybridRiveFileSpec.cpp | 1 + .../shared/c++/HybridRiveFileSpec.hpp | 4 + .../shared/c++/ReferencedAssetsType.hpp | 79 ++++++++++ .../shared/c++/ResolvedReferencedAsset.hpp | 88 +++++++++++ 25 files changed, 795 insertions(+), 44 deletions(-) create mode 100644 nitrogen/generated/android/c++/JReferencedAssetsType.hpp create mode 100644 nitrogen/generated/android/c++/JResolvedReferencedAsset.hpp create mode 100644 nitrogen/generated/android/kotlin/com/margelo/nitro/rive/ReferencedAssetsType.kt create mode 100644 nitrogen/generated/android/kotlin/com/margelo/nitro/rive/ResolvedReferencedAsset.kt create mode 100644 nitrogen/generated/ios/swift/ReferencedAssetsType.swift create mode 100644 nitrogen/generated/ios/swift/ResolvedReferencedAsset.swift create mode 100644 nitrogen/generated/shared/c++/ReferencedAssetsType.hpp create mode 100644 nitrogen/generated/shared/c++/ResolvedReferencedAsset.hpp diff --git a/nitrogen/generated/android/c++/JHybridRiveFileFactorySpec.cpp b/nitrogen/generated/android/c++/JHybridRiveFileFactorySpec.cpp index 2e214051..b77851e2 100644 --- a/nitrogen/generated/android/c++/JHybridRiveFileFactorySpec.cpp +++ b/nitrogen/generated/android/c++/JHybridRiveFileFactorySpec.cpp @@ -9,6 +9,10 @@ // Forward declaration of `HybridRiveFileSpec` to properly resolve imports. namespace margelo::nitro::rive { class HybridRiveFileSpec; } +// Forward declaration of `ReferencedAssetsType` to properly resolve imports. +namespace margelo::nitro::rive { struct ReferencedAssetsType; } +// Forward declaration of `ResolvedReferencedAsset` to properly resolve imports. +namespace margelo::nitro::rive { struct ResolvedReferencedAsset; } #include #include "HybridRiveFileSpec.hpp" @@ -16,6 +20,12 @@ namespace margelo::nitro::rive { class HybridRiveFileSpec; } #include #include "JHybridRiveFileSpec.hpp" #include +#include "ReferencedAssetsType.hpp" +#include +#include "JReferencedAssetsType.hpp" +#include "ResolvedReferencedAsset.hpp" +#include +#include "JResolvedReferencedAsset.hpp" #include #include #include @@ -52,9 +62,9 @@ namespace margelo::nitro::rive { // Methods - std::shared_ptr>> JHybridRiveFileFactorySpec::fromURL(const std::string& url, bool loadCdn) { - static const auto method = javaClassStatic()->getMethod(jni::alias_ref /* url */, jboolean /* loadCdn */)>("fromURL"); - auto __result = method(_javaPart, jni::make_jstring(url), loadCdn); + std::shared_ptr>> JHybridRiveFileFactorySpec::fromURL(const std::string& url, bool loadCdn, const std::optional& referencedAssets) { + static const auto method = javaClassStatic()->getMethod(jni::alias_ref /* url */, jboolean /* loadCdn */, jni::alias_ref /* referencedAssets */)>("fromURL"); + auto __result = method(_javaPart, jni::make_jstring(url), loadCdn, referencedAssets.has_value() ? JReferencedAssetsType::fromCpp(referencedAssets.value()) : nullptr); return [&]() { auto __promise = Promise>::create(); __result->cthis()->addOnResolvedListener([=](const jni::alias_ref& __boxedResult) { @@ -68,9 +78,9 @@ namespace margelo::nitro::rive { return __promise; }(); } - std::shared_ptr>> JHybridRiveFileFactorySpec::fromFileURL(const std::string& fileURL, bool loadCdn) { - static const auto method = javaClassStatic()->getMethod(jni::alias_ref /* fileURL */, jboolean /* loadCdn */)>("fromFileURL"); - auto __result = method(_javaPart, jni::make_jstring(fileURL), loadCdn); + std::shared_ptr>> JHybridRiveFileFactorySpec::fromFileURL(const std::string& fileURL, bool loadCdn, const std::optional& referencedAssets) { + static const auto method = javaClassStatic()->getMethod(jni::alias_ref /* fileURL */, jboolean /* loadCdn */, jni::alias_ref /* referencedAssets */)>("fromFileURL"); + auto __result = method(_javaPart, jni::make_jstring(fileURL), loadCdn, referencedAssets.has_value() ? JReferencedAssetsType::fromCpp(referencedAssets.value()) : nullptr); return [&]() { auto __promise = Promise>::create(); __result->cthis()->addOnResolvedListener([=](const jni::alias_ref& __boxedResult) { @@ -84,9 +94,9 @@ namespace margelo::nitro::rive { return __promise; }(); } - std::shared_ptr>> JHybridRiveFileFactorySpec::fromResource(const std::string& resource, bool loadCdn) { - static const auto method = javaClassStatic()->getMethod(jni::alias_ref /* resource */, jboolean /* loadCdn */)>("fromResource"); - auto __result = method(_javaPart, jni::make_jstring(resource), loadCdn); + std::shared_ptr>> JHybridRiveFileFactorySpec::fromResource(const std::string& resource, bool loadCdn, const std::optional& referencedAssets) { + static const auto method = javaClassStatic()->getMethod(jni::alias_ref /* resource */, jboolean /* loadCdn */, jni::alias_ref /* referencedAssets */)>("fromResource"); + auto __result = method(_javaPart, jni::make_jstring(resource), loadCdn, referencedAssets.has_value() ? JReferencedAssetsType::fromCpp(referencedAssets.value()) : nullptr); return [&]() { auto __promise = Promise>::create(); __result->cthis()->addOnResolvedListener([=](const jni::alias_ref& __boxedResult) { @@ -100,9 +110,9 @@ namespace margelo::nitro::rive { return __promise; }(); } - std::shared_ptr>> JHybridRiveFileFactorySpec::fromBytes(const std::shared_ptr& bytes, bool loadCdn) { - static const auto method = javaClassStatic()->getMethod(jni::alias_ref /* bytes */, jboolean /* loadCdn */)>("fromBytes"); - auto __result = method(_javaPart, JArrayBuffer::wrap(bytes), loadCdn); + std::shared_ptr>> JHybridRiveFileFactorySpec::fromBytes(const std::shared_ptr& bytes, bool loadCdn, const std::optional& referencedAssets) { + static const auto method = javaClassStatic()->getMethod(jni::alias_ref /* bytes */, jboolean /* loadCdn */, jni::alias_ref /* referencedAssets */)>("fromBytes"); + auto __result = method(_javaPart, JArrayBuffer::wrap(bytes), loadCdn, referencedAssets.has_value() ? JReferencedAssetsType::fromCpp(referencedAssets.value()) : nullptr); return [&]() { auto __promise = Promise>::create(); __result->cthis()->addOnResolvedListener([=](const jni::alias_ref& __boxedResult) { diff --git a/nitrogen/generated/android/c++/JHybridRiveFileFactorySpec.hpp b/nitrogen/generated/android/c++/JHybridRiveFileFactorySpec.hpp index 63f95a3e..1e71e1a0 100644 --- a/nitrogen/generated/android/c++/JHybridRiveFileFactorySpec.hpp +++ b/nitrogen/generated/android/c++/JHybridRiveFileFactorySpec.hpp @@ -54,10 +54,10 @@ namespace margelo::nitro::rive { public: // Methods - std::shared_ptr>> fromURL(const std::string& url, bool loadCdn) override; - std::shared_ptr>> fromFileURL(const std::string& fileURL, bool loadCdn) override; - std::shared_ptr>> fromResource(const std::string& resource, bool loadCdn) override; - std::shared_ptr>> fromBytes(const std::shared_ptr& bytes, bool loadCdn) override; + std::shared_ptr>> fromURL(const std::string& url, bool loadCdn, const std::optional& referencedAssets) override; + std::shared_ptr>> fromFileURL(const std::string& fileURL, bool loadCdn, const std::optional& referencedAssets) override; + std::shared_ptr>> fromResource(const std::string& resource, bool loadCdn, const std::optional& referencedAssets) override; + std::shared_ptr>> fromBytes(const std::shared_ptr& bytes, bool loadCdn, const std::optional& referencedAssets) override; private: friend HybridBase; diff --git a/nitrogen/generated/android/c++/JHybridRiveFileSpec.cpp b/nitrogen/generated/android/c++/JHybridRiveFileSpec.cpp index dc839e84..c9470562 100644 --- a/nitrogen/generated/android/c++/JHybridRiveFileSpec.cpp +++ b/nitrogen/generated/android/c++/JHybridRiveFileSpec.cpp @@ -13,6 +13,10 @@ namespace margelo::nitro::rive { class HybridViewModelSpec; } namespace margelo::nitro::rive { struct ArtboardBy; } // Forward declaration of `ArtboardByTypes` to properly resolve imports. namespace margelo::nitro::rive { enum class ArtboardByTypes; } +// Forward declaration of `ReferencedAssetsType` to properly resolve imports. +namespace margelo::nitro::rive { struct ReferencedAssetsType; } +// Forward declaration of `ResolvedReferencedAsset` to properly resolve imports. +namespace margelo::nitro::rive { struct ResolvedReferencedAsset; } #include #include @@ -23,6 +27,11 @@ namespace margelo::nitro::rive { enum class ArtboardByTypes; } #include "JArtboardBy.hpp" #include "ArtboardByTypes.hpp" #include "JArtboardByTypes.hpp" +#include "ReferencedAssetsType.hpp" +#include "JReferencedAssetsType.hpp" +#include "ResolvedReferencedAsset.hpp" +#include +#include "JResolvedReferencedAsset.hpp" namespace margelo::nitro::rive { @@ -79,5 +88,9 @@ namespace margelo::nitro::rive { static const auto method = javaClassStatic()->getMethod("release"); method(_javaPart); } + void JHybridRiveFileSpec::updateReferencedAssets(const ReferencedAssetsType& referencedAssets) { + static const auto method = javaClassStatic()->getMethod /* referencedAssets */)>("updateReferencedAssets"); + method(_javaPart, JReferencedAssetsType::fromCpp(referencedAssets)); + } } // namespace margelo::nitro::rive diff --git a/nitrogen/generated/android/c++/JHybridRiveFileSpec.hpp b/nitrogen/generated/android/c++/JHybridRiveFileSpec.hpp index 16d211f0..a64a62d7 100644 --- a/nitrogen/generated/android/c++/JHybridRiveFileSpec.hpp +++ b/nitrogen/generated/android/c++/JHybridRiveFileSpec.hpp @@ -58,6 +58,7 @@ namespace margelo::nitro::rive { std::optional> viewModelByName(const std::string& name) override; std::optional> defaultArtboardViewModel(const std::optional& artboardBy) override; void release() override; + void updateReferencedAssets(const ReferencedAssetsType& referencedAssets) override; private: friend HybridBase; diff --git a/nitrogen/generated/android/c++/JReferencedAssetsType.hpp b/nitrogen/generated/android/c++/JReferencedAssetsType.hpp new file mode 100644 index 00000000..560c496b --- /dev/null +++ b/nitrogen/generated/android/c++/JReferencedAssetsType.hpp @@ -0,0 +1,74 @@ +/// +/// JReferencedAssetsType.hpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +#pragma once + +#include +#include "ReferencedAssetsType.hpp" + +#include "JResolvedReferencedAsset.hpp" +#include "ResolvedReferencedAsset.hpp" +#include +#include +#include + +namespace margelo::nitro::rive { + + using namespace facebook; + + /** + * The C++ JNI bridge between the C++ struct "ReferencedAssetsType" and the the Kotlin data class "ReferencedAssetsType". + */ + struct JReferencedAssetsType final: public jni::JavaClass { + public: + static auto constexpr kJavaDescriptor = "Lcom/margelo/nitro/rive/ReferencedAssetsType;"; + + public: + /** + * Convert this Java/Kotlin-based struct to the C++ struct ReferencedAssetsType by copying all values to C++. + */ + [[maybe_unused]] + [[nodiscard]] + ReferencedAssetsType toCpp() const { + static const auto clazz = javaClassStatic(); + static const auto fieldData = clazz->getField>("data"); + jni::local_ref> data = this->getFieldValue(fieldData); + return ReferencedAssetsType( + data != nullptr ? std::make_optional([&]() { + std::unordered_map __map; + __map.reserve(data->size()); + for (const auto& __entry : *data) { + __map.emplace(__entry.first->toStdString(), __entry.second->toCpp()); + } + return __map; + }()) : std::nullopt + ); + } + + public: + /** + * Create a Java/Kotlin-based struct by copying all values from the given C++ struct to Java. + */ + [[maybe_unused]] + static jni::local_ref fromCpp(const ReferencedAssetsType& value) { + using JSignature = JReferencedAssetsType(jni::alias_ref>); + static const auto clazz = javaClassStatic(); + static const auto create = clazz->getStaticMethod("fromCpp"); + return create( + clazz, + value.data.has_value() ? [&]() -> jni::local_ref> { + auto __map = jni::JHashMap::create(value.data.value().size()); + for (const auto& __entry : value.data.value()) { + __map->put(jni::make_jstring(__entry.first), JResolvedReferencedAsset::fromCpp(__entry.second)); + } + return __map; + }() : nullptr + ); + } + }; + +} // namespace margelo::nitro::rive diff --git a/nitrogen/generated/android/c++/JResolvedReferencedAsset.hpp b/nitrogen/generated/android/c++/JResolvedReferencedAsset.hpp new file mode 100644 index 00000000..181a27ba --- /dev/null +++ b/nitrogen/generated/android/c++/JResolvedReferencedAsset.hpp @@ -0,0 +1,70 @@ +/// +/// JResolvedReferencedAsset.hpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +#pragma once + +#include +#include "ResolvedReferencedAsset.hpp" + +#include +#include + +namespace margelo::nitro::rive { + + using namespace facebook; + + /** + * The C++ JNI bridge between the C++ struct "ResolvedReferencedAsset" and the the Kotlin data class "ResolvedReferencedAsset". + */ + struct JResolvedReferencedAsset final: public jni::JavaClass { + public: + static auto constexpr kJavaDescriptor = "Lcom/margelo/nitro/rive/ResolvedReferencedAsset;"; + + public: + /** + * Convert this Java/Kotlin-based struct to the C++ struct ResolvedReferencedAsset by copying all values to C++. + */ + [[maybe_unused]] + [[nodiscard]] + ResolvedReferencedAsset toCpp() const { + static const auto clazz = javaClassStatic(); + static const auto fieldSourceUrl = clazz->getField("sourceUrl"); + jni::local_ref sourceUrl = this->getFieldValue(fieldSourceUrl); + static const auto fieldSourceAsset = clazz->getField("sourceAsset"); + jni::local_ref sourceAsset = this->getFieldValue(fieldSourceAsset); + static const auto fieldSourceAssetId = clazz->getField("sourceAssetId"); + jni::local_ref sourceAssetId = this->getFieldValue(fieldSourceAssetId); + static const auto fieldPath = clazz->getField("path"); + jni::local_ref path = this->getFieldValue(fieldPath); + return ResolvedReferencedAsset( + sourceUrl != nullptr ? std::make_optional(sourceUrl->toStdString()) : std::nullopt, + sourceAsset != nullptr ? std::make_optional(sourceAsset->toStdString()) : std::nullopt, + sourceAssetId != nullptr ? std::make_optional(sourceAssetId->toStdString()) : std::nullopt, + path != nullptr ? std::make_optional(path->toStdString()) : std::nullopt + ); + } + + public: + /** + * Create a Java/Kotlin-based struct by copying all values from the given C++ struct to Java. + */ + [[maybe_unused]] + static jni::local_ref fromCpp(const ResolvedReferencedAsset& value) { + using JSignature = JResolvedReferencedAsset(jni::alias_ref, jni::alias_ref, jni::alias_ref, jni::alias_ref); + static const auto clazz = javaClassStatic(); + static const auto create = clazz->getStaticMethod("fromCpp"); + return create( + clazz, + value.sourceUrl.has_value() ? jni::make_jstring(value.sourceUrl.value()) : nullptr, + value.sourceAsset.has_value() ? jni::make_jstring(value.sourceAsset.value()) : nullptr, + value.sourceAssetId.has_value() ? jni::make_jstring(value.sourceAssetId.value()) : nullptr, + value.path.has_value() ? jni::make_jstring(value.path.value()) : nullptr + ); + } + }; + +} // namespace margelo::nitro::rive diff --git a/nitrogen/generated/android/kotlin/com/margelo/nitro/rive/HybridRiveFileFactorySpec.kt b/nitrogen/generated/android/kotlin/com/margelo/nitro/rive/HybridRiveFileFactorySpec.kt index a8c24d52..36568914 100644 --- a/nitrogen/generated/android/kotlin/com/margelo/nitro/rive/HybridRiveFileFactorySpec.kt +++ b/nitrogen/generated/android/kotlin/com/margelo/nitro/rive/HybridRiveFileFactorySpec.kt @@ -49,19 +49,19 @@ abstract class HybridRiveFileFactorySpec: HybridObject() { // Methods @DoNotStrip @Keep - abstract fun fromURL(url: String, loadCdn: Boolean): Promise + abstract fun fromURL(url: String, loadCdn: Boolean, referencedAssets: ReferencedAssetsType?): Promise @DoNotStrip @Keep - abstract fun fromFileURL(fileURL: String, loadCdn: Boolean): Promise + abstract fun fromFileURL(fileURL: String, loadCdn: Boolean, referencedAssets: ReferencedAssetsType?): Promise @DoNotStrip @Keep - abstract fun fromResource(resource: String, loadCdn: Boolean): Promise + abstract fun fromResource(resource: String, loadCdn: Boolean, referencedAssets: ReferencedAssetsType?): Promise @DoNotStrip @Keep - abstract fun fromBytes(bytes: ArrayBuffer, loadCdn: Boolean): Promise + abstract fun fromBytes(bytes: ArrayBuffer, loadCdn: Boolean, referencedAssets: ReferencedAssetsType?): Promise private external fun initHybrid(): HybridData diff --git a/nitrogen/generated/android/kotlin/com/margelo/nitro/rive/HybridRiveFileSpec.kt b/nitrogen/generated/android/kotlin/com/margelo/nitro/rive/HybridRiveFileSpec.kt index c87729ec..03f89d8d 100644 --- a/nitrogen/generated/android/kotlin/com/margelo/nitro/rive/HybridRiveFileSpec.kt +++ b/nitrogen/generated/android/kotlin/com/margelo/nitro/rive/HybridRiveFileSpec.kt @@ -62,6 +62,10 @@ abstract class HybridRiveFileSpec: HybridObject() { @DoNotStrip @Keep abstract fun release(): Unit + + @DoNotStrip + @Keep + abstract fun updateReferencedAssets(referencedAssets: ReferencedAssetsType): Unit private external fun initHybrid(): HybridData diff --git a/nitrogen/generated/android/kotlin/com/margelo/nitro/rive/ReferencedAssetsType.kt b/nitrogen/generated/android/kotlin/com/margelo/nitro/rive/ReferencedAssetsType.kt new file mode 100644 index 00000000..651c7692 --- /dev/null +++ b/nitrogen/generated/android/kotlin/com/margelo/nitro/rive/ReferencedAssetsType.kt @@ -0,0 +1,38 @@ +/// +/// ReferencedAssetsType.kt +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +package com.margelo.nitro.rive + +import androidx.annotation.Keep +import com.facebook.proguard.annotations.DoNotStrip + + +/** + * Represents the JavaScript object/struct "ReferencedAssetsType". + */ +@DoNotStrip +@Keep +data class ReferencedAssetsType( + @DoNotStrip + @Keep + val data: Map? +) { + /* primary constructor */ + + private companion object { + /** + * Constructor called from C++ + */ + @DoNotStrip + @Keep + @Suppress("unused") + @JvmStatic + private fun fromCpp(data: Map?): ReferencedAssetsType { + return ReferencedAssetsType(data) + } + } +} diff --git a/nitrogen/generated/android/kotlin/com/margelo/nitro/rive/ResolvedReferencedAsset.kt b/nitrogen/generated/android/kotlin/com/margelo/nitro/rive/ResolvedReferencedAsset.kt new file mode 100644 index 00000000..1ac8fa33 --- /dev/null +++ b/nitrogen/generated/android/kotlin/com/margelo/nitro/rive/ResolvedReferencedAsset.kt @@ -0,0 +1,47 @@ +/// +/// ResolvedReferencedAsset.kt +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +package com.margelo.nitro.rive + +import androidx.annotation.Keep +import com.facebook.proguard.annotations.DoNotStrip + + +/** + * Represents the JavaScript object/struct "ResolvedReferencedAsset". + */ +@DoNotStrip +@Keep +data class ResolvedReferencedAsset( + @DoNotStrip + @Keep + val sourceUrl: String?, + @DoNotStrip + @Keep + val sourceAsset: String?, + @DoNotStrip + @Keep + val sourceAssetId: String?, + @DoNotStrip + @Keep + val path: String? +) { + /* primary constructor */ + + private companion object { + /** + * Constructor called from C++ + */ + @DoNotStrip + @Keep + @Suppress("unused") + @JvmStatic + private fun fromCpp(sourceUrl: String?, sourceAsset: String?, sourceAssetId: String?, path: String?): ResolvedReferencedAsset { + return ResolvedReferencedAsset(sourceUrl, sourceAsset, sourceAssetId, path) + } + } +} diff --git a/nitrogen/generated/ios/Rive-Swift-Cxx-Bridge.hpp b/nitrogen/generated/ios/Rive-Swift-Cxx-Bridge.hpp index 0491a7a5..fbda282f 100644 --- a/nitrogen/generated/ios/Rive-Swift-Cxx-Bridge.hpp +++ b/nitrogen/generated/ios/Rive-Swift-Cxx-Bridge.hpp @@ -42,6 +42,10 @@ namespace margelo::nitro::rive { class HybridViewModelSpec; } namespace margelo::nitro::rive { class HybridViewModelStringPropertySpec; } // Forward declaration of `HybridViewModelTriggerPropertySpec` to properly resolve imports. namespace margelo::nitro::rive { class HybridViewModelTriggerPropertySpec; } +// Forward declaration of `ReferencedAssetsType` to properly resolve imports. +namespace margelo::nitro::rive { struct ReferencedAssetsType; } +// Forward declaration of `ResolvedReferencedAsset` to properly resolve imports. +namespace margelo::nitro::rive { struct ResolvedReferencedAsset; } // Forward declaration of `RiveEventType` to properly resolve imports. namespace margelo::nitro::rive { enum class RiveEventType; } // Forward declaration of `UnifiedRiveEvent` to properly resolve imports. @@ -93,6 +97,8 @@ namespace Rive { class HybridViewModelTriggerPropertySpec_cxx; } #include "HybridViewModelSpec.hpp" #include "HybridViewModelStringPropertySpec.hpp" #include "HybridViewModelTriggerPropertySpec.hpp" +#include "ReferencedAssetsType.hpp" +#include "ResolvedReferencedAsset.hpp" #include "RiveEventType.hpp" #include "UnifiedRiveEvent.hpp" #include @@ -205,6 +211,46 @@ namespace margelo::nitro::rive::bridge::swift { return *optional; } + // pragma MARK: std::unordered_map + /** + * Specialized version of `std::unordered_map`. + */ + using std__unordered_map_std__string__ResolvedReferencedAsset_ = std::unordered_map; + inline std::unordered_map create_std__unordered_map_std__string__ResolvedReferencedAsset_(size_t size) noexcept { + std::unordered_map map; + map.reserve(size); + return map; + } + inline std::vector get_std__unordered_map_std__string__ResolvedReferencedAsset__keys(const std__unordered_map_std__string__ResolvedReferencedAsset_& map) noexcept { + std::vector keys; + keys.reserve(map.size()); + for (const auto& entry : map) { + keys.push_back(entry.first); + } + return keys; + } + inline ResolvedReferencedAsset get_std__unordered_map_std__string__ResolvedReferencedAsset__value(const std__unordered_map_std__string__ResolvedReferencedAsset_& map, const std::string& key) noexcept { + return map.find(key)->second; + } + inline void emplace_std__unordered_map_std__string__ResolvedReferencedAsset_(std__unordered_map_std__string__ResolvedReferencedAsset_& map, const std::string& key, const ResolvedReferencedAsset& value) noexcept { + map.emplace(key, value); + } + + // pragma MARK: std::optional> + /** + * Specialized version of `std::optional>`. + */ + using std__optional_std__unordered_map_std__string__ResolvedReferencedAsset__ = std::optional>; + inline std::optional> create_std__optional_std__unordered_map_std__string__ResolvedReferencedAsset__(const std::unordered_map& value) noexcept { + return std::optional>(value); + } + inline bool has_value_std__optional_std__unordered_map_std__string__ResolvedReferencedAsset__(const std::optional>& optional) noexcept { + return optional.has_value(); + } + inline std::unordered_map get_std__optional_std__unordered_map_std__string__ResolvedReferencedAsset__(const std::optional>& optional) noexcept { + return *optional; + } + // pragma MARK: std::shared_ptr /** * Specialized version of `std::shared_ptr`. @@ -291,6 +337,21 @@ namespace margelo::nitro::rive::bridge::swift { return Func_void_std__exception_ptr_Wrapper(std::move(value)); } + // pragma MARK: std::optional + /** + * Specialized version of `std::optional`. + */ + using std__optional_ReferencedAssetsType_ = std::optional; + inline std::optional create_std__optional_ReferencedAssetsType_(const ReferencedAssetsType& value) noexcept { + return std::optional(value); + } + inline bool has_value_std__optional_ReferencedAssetsType_(const std::optional& optional) noexcept { + return optional.has_value(); + } + inline ReferencedAssetsType get_std__optional_ReferencedAssetsType_(const std::optional& optional) noexcept { + return *optional; + } + // pragma MARK: std::shared_ptr /** * Specialized version of `std::shared_ptr`. diff --git a/nitrogen/generated/ios/Rive-Swift-Cxx-Umbrella.hpp b/nitrogen/generated/ios/Rive-Swift-Cxx-Umbrella.hpp index 92fc9cb3..b56d547e 100644 --- a/nitrogen/generated/ios/Rive-Swift-Cxx-Umbrella.hpp +++ b/nitrogen/generated/ios/Rive-Swift-Cxx-Umbrella.hpp @@ -42,6 +42,10 @@ namespace margelo::nitro::rive { class HybridViewModelSpec; } namespace margelo::nitro::rive { class HybridViewModelStringPropertySpec; } // Forward declaration of `HybridViewModelTriggerPropertySpec` to properly resolve imports. namespace margelo::nitro::rive { class HybridViewModelTriggerPropertySpec; } +// Forward declaration of `ReferencedAssetsType` to properly resolve imports. +namespace margelo::nitro::rive { struct ReferencedAssetsType; } +// Forward declaration of `ResolvedReferencedAsset` to properly resolve imports. +namespace margelo::nitro::rive { struct ResolvedReferencedAsset; } // Forward declaration of `RiveEventType` to properly resolve imports. namespace margelo::nitro::rive { enum class RiveEventType; } // Forward declaration of `UnifiedRiveEvent` to properly resolve imports. @@ -65,6 +69,8 @@ namespace margelo::nitro::rive { struct UnifiedRiveEvent; } #include "HybridViewModelSpec.hpp" #include "HybridViewModelStringPropertySpec.hpp" #include "HybridViewModelTriggerPropertySpec.hpp" +#include "ReferencedAssetsType.hpp" +#include "ResolvedReferencedAsset.hpp" #include "RiveEventType.hpp" #include "UnifiedRiveEvent.hpp" #include diff --git a/nitrogen/generated/ios/c++/HybridRiveFileFactorySpecSwift.hpp b/nitrogen/generated/ios/c++/HybridRiveFileFactorySpecSwift.hpp index ea715f39..098ab3ea 100644 --- a/nitrogen/generated/ios/c++/HybridRiveFileFactorySpecSwift.hpp +++ b/nitrogen/generated/ios/c++/HybridRiveFileFactorySpecSwift.hpp @@ -14,6 +14,10 @@ namespace Rive { class HybridRiveFileFactorySpec_cxx; } // Forward declaration of `HybridRiveFileSpec` to properly resolve imports. namespace margelo::nitro::rive { class HybridRiveFileSpec; } +// Forward declaration of `ReferencedAssetsType` to properly resolve imports. +namespace margelo::nitro::rive { struct ReferencedAssetsType; } +// Forward declaration of `ResolvedReferencedAsset` to properly resolve imports. +namespace margelo::nitro::rive { struct ResolvedReferencedAsset; } // Forward declaration of `ArrayBufferHolder` to properly resolve imports. namespace NitroModules { class ArrayBufferHolder; } @@ -21,6 +25,10 @@ namespace NitroModules { class ArrayBufferHolder; } #include "HybridRiveFileSpec.hpp" #include #include +#include "ReferencedAssetsType.hpp" +#include +#include "ResolvedReferencedAsset.hpp" +#include #include #include @@ -68,32 +76,32 @@ namespace margelo::nitro::rive { public: // Methods - inline std::shared_ptr>> fromURL(const std::string& url, bool loadCdn) override { - auto __result = _swiftPart.fromURL(url, std::forward(loadCdn)); + inline std::shared_ptr>> fromURL(const std::string& url, bool loadCdn, const std::optional& referencedAssets) override { + auto __result = _swiftPart.fromURL(url, std::forward(loadCdn), referencedAssets); if (__result.hasError()) [[unlikely]] { std::rethrow_exception(__result.error()); } auto __value = std::move(__result.value()); return __value; } - inline std::shared_ptr>> fromFileURL(const std::string& fileURL, bool loadCdn) override { - auto __result = _swiftPart.fromFileURL(fileURL, std::forward(loadCdn)); + inline std::shared_ptr>> fromFileURL(const std::string& fileURL, bool loadCdn, const std::optional& referencedAssets) override { + auto __result = _swiftPart.fromFileURL(fileURL, std::forward(loadCdn), referencedAssets); if (__result.hasError()) [[unlikely]] { std::rethrow_exception(__result.error()); } auto __value = std::move(__result.value()); return __value; } - inline std::shared_ptr>> fromResource(const std::string& resource, bool loadCdn) override { - auto __result = _swiftPart.fromResource(resource, std::forward(loadCdn)); + inline std::shared_ptr>> fromResource(const std::string& resource, bool loadCdn, const std::optional& referencedAssets) override { + auto __result = _swiftPart.fromResource(resource, std::forward(loadCdn), referencedAssets); if (__result.hasError()) [[unlikely]] { std::rethrow_exception(__result.error()); } auto __value = std::move(__result.value()); return __value; } - inline std::shared_ptr>> fromBytes(const std::shared_ptr& bytes, bool loadCdn) override { - auto __result = _swiftPart.fromBytes(ArrayBufferHolder(bytes), std::forward(loadCdn)); + inline std::shared_ptr>> fromBytes(const std::shared_ptr& bytes, bool loadCdn, const std::optional& referencedAssets) override { + auto __result = _swiftPart.fromBytes(ArrayBufferHolder(bytes), std::forward(loadCdn), referencedAssets); if (__result.hasError()) [[unlikely]] { std::rethrow_exception(__result.error()); } diff --git a/nitrogen/generated/ios/c++/HybridRiveFileSpecSwift.hpp b/nitrogen/generated/ios/c++/HybridRiveFileSpecSwift.hpp index 48d1b295..e2dae7ae 100644 --- a/nitrogen/generated/ios/c++/HybridRiveFileSpecSwift.hpp +++ b/nitrogen/generated/ios/c++/HybridRiveFileSpecSwift.hpp @@ -18,6 +18,10 @@ namespace margelo::nitro::rive { class HybridViewModelSpec; } namespace margelo::nitro::rive { struct ArtboardBy; } // Forward declaration of `ArtboardByTypes` to properly resolve imports. namespace margelo::nitro::rive { enum class ArtboardByTypes; } +// Forward declaration of `ReferencedAssetsType` to properly resolve imports. +namespace margelo::nitro::rive { struct ReferencedAssetsType; } +// Forward declaration of `ResolvedReferencedAsset` to properly resolve imports. +namespace margelo::nitro::rive { struct ResolvedReferencedAsset; } #include #include @@ -25,6 +29,9 @@ namespace margelo::nitro::rive { enum class ArtboardByTypes; } #include #include "ArtboardBy.hpp" #include "ArtboardByTypes.hpp" +#include "ReferencedAssetsType.hpp" +#include "ResolvedReferencedAsset.hpp" +#include #include "Rive-Swift-Cxx-Umbrella.hpp" @@ -103,6 +110,12 @@ namespace margelo::nitro::rive { std::rethrow_exception(__result.error()); } } + inline void updateReferencedAssets(const ReferencedAssetsType& referencedAssets) override { + auto __result = _swiftPart.updateReferencedAssets(std::forward(referencedAssets)); + if (__result.hasError()) [[unlikely]] { + std::rethrow_exception(__result.error()); + } + } private: Rive::HybridRiveFileSpec_cxx _swiftPart; diff --git a/nitrogen/generated/ios/swift/HybridRiveFileFactorySpec.swift b/nitrogen/generated/ios/swift/HybridRiveFileFactorySpec.swift index c944d7c8..0364fea8 100644 --- a/nitrogen/generated/ios/swift/HybridRiveFileFactorySpec.swift +++ b/nitrogen/generated/ios/swift/HybridRiveFileFactorySpec.swift @@ -15,10 +15,10 @@ public protocol HybridRiveFileFactorySpec_protocol: HybridObject { // Methods - func fromURL(url: String, loadCdn: Bool) throws -> Promise<(any HybridRiveFileSpec)> - func fromFileURL(fileURL: String, loadCdn: Bool) throws -> Promise<(any HybridRiveFileSpec)> - func fromResource(resource: String, loadCdn: Bool) throws -> Promise<(any HybridRiveFileSpec)> - func fromBytes(bytes: ArrayBuffer, loadCdn: Bool) throws -> Promise<(any HybridRiveFileSpec)> + func fromURL(url: String, loadCdn: Bool, referencedAssets: ReferencedAssetsType?) throws -> Promise<(any HybridRiveFileSpec)> + func fromFileURL(fileURL: String, loadCdn: Bool, referencedAssets: ReferencedAssetsType?) throws -> Promise<(any HybridRiveFileSpec)> + func fromResource(resource: String, loadCdn: Bool, referencedAssets: ReferencedAssetsType?) throws -> Promise<(any HybridRiveFileSpec)> + func fromBytes(bytes: ArrayBuffer, loadCdn: Bool, referencedAssets: ReferencedAssetsType?) throws -> Promise<(any HybridRiveFileSpec)> } public extension HybridRiveFileFactorySpec_protocol { diff --git a/nitrogen/generated/ios/swift/HybridRiveFileFactorySpec_cxx.swift b/nitrogen/generated/ios/swift/HybridRiveFileFactorySpec_cxx.swift index f08a5d25..7a1fd7df 100644 --- a/nitrogen/generated/ios/swift/HybridRiveFileFactorySpec_cxx.swift +++ b/nitrogen/generated/ios/swift/HybridRiveFileFactorySpec_cxx.swift @@ -119,9 +119,9 @@ open class HybridRiveFileFactorySpec_cxx { // Methods @inline(__always) - public final func fromURL(url: std.string, loadCdn: Bool) -> bridge.Result_std__shared_ptr_Promise_std__shared_ptr_HybridRiveFileSpec____ { + public final func fromURL(url: std.string, loadCdn: Bool, referencedAssets: bridge.std__optional_ReferencedAssetsType_) -> bridge.Result_std__shared_ptr_Promise_std__shared_ptr_HybridRiveFileSpec____ { do { - let __result = try self.__implementation.fromURL(url: String(url), loadCdn: loadCdn) + let __result = try self.__implementation.fromURL(url: String(url), loadCdn: loadCdn, referencedAssets: referencedAssets.value) let __resultCpp = { () -> bridge.std__shared_ptr_Promise_std__shared_ptr_HybridRiveFileSpec___ in let __promise = bridge.create_std__shared_ptr_Promise_std__shared_ptr_HybridRiveFileSpec___() let __promiseHolder = bridge.wrap_std__shared_ptr_Promise_std__shared_ptr_HybridRiveFileSpec___(__promise) @@ -141,9 +141,9 @@ open class HybridRiveFileFactorySpec_cxx { } @inline(__always) - public final func fromFileURL(fileURL: std.string, loadCdn: Bool) -> bridge.Result_std__shared_ptr_Promise_std__shared_ptr_HybridRiveFileSpec____ { + public final func fromFileURL(fileURL: std.string, loadCdn: Bool, referencedAssets: bridge.std__optional_ReferencedAssetsType_) -> bridge.Result_std__shared_ptr_Promise_std__shared_ptr_HybridRiveFileSpec____ { do { - let __result = try self.__implementation.fromFileURL(fileURL: String(fileURL), loadCdn: loadCdn) + let __result = try self.__implementation.fromFileURL(fileURL: String(fileURL), loadCdn: loadCdn, referencedAssets: referencedAssets.value) let __resultCpp = { () -> bridge.std__shared_ptr_Promise_std__shared_ptr_HybridRiveFileSpec___ in let __promise = bridge.create_std__shared_ptr_Promise_std__shared_ptr_HybridRiveFileSpec___() let __promiseHolder = bridge.wrap_std__shared_ptr_Promise_std__shared_ptr_HybridRiveFileSpec___(__promise) @@ -163,9 +163,9 @@ open class HybridRiveFileFactorySpec_cxx { } @inline(__always) - public final func fromResource(resource: std.string, loadCdn: Bool) -> bridge.Result_std__shared_ptr_Promise_std__shared_ptr_HybridRiveFileSpec____ { + public final func fromResource(resource: std.string, loadCdn: Bool, referencedAssets: bridge.std__optional_ReferencedAssetsType_) -> bridge.Result_std__shared_ptr_Promise_std__shared_ptr_HybridRiveFileSpec____ { do { - let __result = try self.__implementation.fromResource(resource: String(resource), loadCdn: loadCdn) + let __result = try self.__implementation.fromResource(resource: String(resource), loadCdn: loadCdn, referencedAssets: referencedAssets.value) let __resultCpp = { () -> bridge.std__shared_ptr_Promise_std__shared_ptr_HybridRiveFileSpec___ in let __promise = bridge.create_std__shared_ptr_Promise_std__shared_ptr_HybridRiveFileSpec___() let __promiseHolder = bridge.wrap_std__shared_ptr_Promise_std__shared_ptr_HybridRiveFileSpec___(__promise) @@ -185,9 +185,9 @@ open class HybridRiveFileFactorySpec_cxx { } @inline(__always) - public final func fromBytes(bytes: ArrayBuffer, loadCdn: Bool) -> bridge.Result_std__shared_ptr_Promise_std__shared_ptr_HybridRiveFileSpec____ { + public final func fromBytes(bytes: ArrayBuffer, loadCdn: Bool, referencedAssets: bridge.std__optional_ReferencedAssetsType_) -> bridge.Result_std__shared_ptr_Promise_std__shared_ptr_HybridRiveFileSpec____ { do { - let __result = try self.__implementation.fromBytes(bytes: bytes, loadCdn: loadCdn) + let __result = try self.__implementation.fromBytes(bytes: bytes, loadCdn: loadCdn, referencedAssets: referencedAssets.value) let __resultCpp = { () -> bridge.std__shared_ptr_Promise_std__shared_ptr_HybridRiveFileSpec___ in let __promise = bridge.create_std__shared_ptr_Promise_std__shared_ptr_HybridRiveFileSpec___() let __promiseHolder = bridge.wrap_std__shared_ptr_Promise_std__shared_ptr_HybridRiveFileSpec___(__promise) diff --git a/nitrogen/generated/ios/swift/HybridRiveFileSpec.swift b/nitrogen/generated/ios/swift/HybridRiveFileSpec.swift index d6b3f16e..d5f652ca 100644 --- a/nitrogen/generated/ios/swift/HybridRiveFileSpec.swift +++ b/nitrogen/generated/ios/swift/HybridRiveFileSpec.swift @@ -18,6 +18,7 @@ public protocol HybridRiveFileSpec_protocol: HybridObject { func viewModelByName(name: String) throws -> (any HybridViewModelSpec)? func defaultArtboardViewModel(artboardBy: ArtboardBy?) throws -> (any HybridViewModelSpec)? func release() throws -> Void + func updateReferencedAssets(referencedAssets: ReferencedAssetsType) throws -> Void } public extension HybridRiveFileSpec_protocol { diff --git a/nitrogen/generated/ios/swift/HybridRiveFileSpec_cxx.swift b/nitrogen/generated/ios/swift/HybridRiveFileSpec_cxx.swift index 456ee101..210149f4 100644 --- a/nitrogen/generated/ios/swift/HybridRiveFileSpec_cxx.swift +++ b/nitrogen/generated/ios/swift/HybridRiveFileSpec_cxx.swift @@ -201,4 +201,15 @@ open class HybridRiveFileSpec_cxx { return bridge.create_Result_void_(__exceptionPtr) } } + + @inline(__always) + public final func updateReferencedAssets(referencedAssets: ReferencedAssetsType) -> bridge.Result_void_ { + do { + try self.__implementation.updateReferencedAssets(referencedAssets: referencedAssets) + return bridge.create_Result_void_() + } catch (let __error) { + let __exceptionPtr = __error.toCpp() + return bridge.create_Result_void_(__exceptionPtr) + } + } } diff --git a/nitrogen/generated/ios/swift/ReferencedAssetsType.swift b/nitrogen/generated/ios/swift/ReferencedAssetsType.swift new file mode 100644 index 00000000..658e8e81 --- /dev/null +++ b/nitrogen/generated/ios/swift/ReferencedAssetsType.swift @@ -0,0 +1,74 @@ +/// +/// ReferencedAssetsType.swift +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +import NitroModules + +/** + * Represents an instance of `ReferencedAssetsType`, backed by a C++ struct. + */ +public typealias ReferencedAssetsType = margelo.nitro.rive.ReferencedAssetsType + +public extension ReferencedAssetsType { + private typealias bridge = margelo.nitro.rive.bridge.swift + + /** + * Create a new instance of `ReferencedAssetsType`. + */ + init(data: Dictionary?) { + self.init({ () -> bridge.std__optional_std__unordered_map_std__string__ResolvedReferencedAsset__ in + if let __unwrappedValue = data { + return bridge.create_std__optional_std__unordered_map_std__string__ResolvedReferencedAsset__({ () -> bridge.std__unordered_map_std__string__ResolvedReferencedAsset_ in + var __map = bridge.create_std__unordered_map_std__string__ResolvedReferencedAsset_(__unwrappedValue.count) + for (__k, __v) in __unwrappedValue { + bridge.emplace_std__unordered_map_std__string__ResolvedReferencedAsset_(&__map, std.string(__k), __v) + } + return __map + }()) + } else { + return .init() + } + }()) + } + + var data: Dictionary? { + @inline(__always) + get { + return { () -> Dictionary? in + if bridge.has_value_std__optional_std__unordered_map_std__string__ResolvedReferencedAsset__(self.__data) { + let __unwrapped = bridge.get_std__optional_std__unordered_map_std__string__ResolvedReferencedAsset__(self.__data) + return { () -> Dictionary in + var __dictionary = Dictionary(minimumCapacity: __unwrapped.size()) + let __keys = bridge.get_std__unordered_map_std__string__ResolvedReferencedAsset__keys(__unwrapped) + for __key in __keys { + let __value = bridge.get_std__unordered_map_std__string__ResolvedReferencedAsset__value(__unwrapped, __key) + __dictionary[String(__key)] = __value + } + return __dictionary + }() + } else { + return nil + } + }() + } + @inline(__always) + set { + self.__data = { () -> bridge.std__optional_std__unordered_map_std__string__ResolvedReferencedAsset__ in + if let __unwrappedValue = newValue { + return bridge.create_std__optional_std__unordered_map_std__string__ResolvedReferencedAsset__({ () -> bridge.std__unordered_map_std__string__ResolvedReferencedAsset_ in + var __map = bridge.create_std__unordered_map_std__string__ResolvedReferencedAsset_(__unwrappedValue.count) + for (__k, __v) in __unwrappedValue { + bridge.emplace_std__unordered_map_std__string__ResolvedReferencedAsset_(&__map, std.string(__k), __v) + } + return __map + }()) + } else { + return .init() + } + }() + } + } +} diff --git a/nitrogen/generated/ios/swift/ResolvedReferencedAsset.swift b/nitrogen/generated/ios/swift/ResolvedReferencedAsset.swift new file mode 100644 index 00000000..bc80cb35 --- /dev/null +++ b/nitrogen/generated/ios/swift/ResolvedReferencedAsset.swift @@ -0,0 +1,144 @@ +/// +/// ResolvedReferencedAsset.swift +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +import NitroModules + +/** + * Represents an instance of `ResolvedReferencedAsset`, backed by a C++ struct. + */ +public typealias ResolvedReferencedAsset = margelo.nitro.rive.ResolvedReferencedAsset + +public extension ResolvedReferencedAsset { + private typealias bridge = margelo.nitro.rive.bridge.swift + + /** + * Create a new instance of `ResolvedReferencedAsset`. + */ + init(sourceUrl: String?, sourceAsset: String?, sourceAssetId: String?, path: String?) { + self.init({ () -> bridge.std__optional_std__string_ in + if let __unwrappedValue = sourceUrl { + return bridge.create_std__optional_std__string_(std.string(__unwrappedValue)) + } else { + return .init() + } + }(), { () -> bridge.std__optional_std__string_ in + if let __unwrappedValue = sourceAsset { + return bridge.create_std__optional_std__string_(std.string(__unwrappedValue)) + } else { + return .init() + } + }(), { () -> bridge.std__optional_std__string_ in + if let __unwrappedValue = sourceAssetId { + return bridge.create_std__optional_std__string_(std.string(__unwrappedValue)) + } else { + return .init() + } + }(), { () -> bridge.std__optional_std__string_ in + if let __unwrappedValue = path { + return bridge.create_std__optional_std__string_(std.string(__unwrappedValue)) + } else { + return .init() + } + }()) + } + + var sourceUrl: String? { + @inline(__always) + get { + return { () -> String? in + if bridge.has_value_std__optional_std__string_(self.__sourceUrl) { + let __unwrapped = bridge.get_std__optional_std__string_(self.__sourceUrl) + return String(__unwrapped) + } else { + return nil + } + }() + } + @inline(__always) + set { + self.__sourceUrl = { () -> bridge.std__optional_std__string_ in + if let __unwrappedValue = newValue { + return bridge.create_std__optional_std__string_(std.string(__unwrappedValue)) + } else { + return .init() + } + }() + } + } + + var sourceAsset: String? { + @inline(__always) + get { + return { () -> String? in + if bridge.has_value_std__optional_std__string_(self.__sourceAsset) { + let __unwrapped = bridge.get_std__optional_std__string_(self.__sourceAsset) + return String(__unwrapped) + } else { + return nil + } + }() + } + @inline(__always) + set { + self.__sourceAsset = { () -> bridge.std__optional_std__string_ in + if let __unwrappedValue = newValue { + return bridge.create_std__optional_std__string_(std.string(__unwrappedValue)) + } else { + return .init() + } + }() + } + } + + var sourceAssetId: String? { + @inline(__always) + get { + return { () -> String? in + if bridge.has_value_std__optional_std__string_(self.__sourceAssetId) { + let __unwrapped = bridge.get_std__optional_std__string_(self.__sourceAssetId) + return String(__unwrapped) + } else { + return nil + } + }() + } + @inline(__always) + set { + self.__sourceAssetId = { () -> bridge.std__optional_std__string_ in + if let __unwrappedValue = newValue { + return bridge.create_std__optional_std__string_(std.string(__unwrappedValue)) + } else { + return .init() + } + }() + } + } + + var path: String? { + @inline(__always) + get { + return { () -> String? in + if bridge.has_value_std__optional_std__string_(self.__path) { + let __unwrapped = bridge.get_std__optional_std__string_(self.__path) + return String(__unwrapped) + } else { + return nil + } + }() + } + @inline(__always) + set { + self.__path = { () -> bridge.std__optional_std__string_ in + if let __unwrappedValue = newValue { + return bridge.create_std__optional_std__string_(std.string(__unwrappedValue)) + } else { + return .init() + } + }() + } + } +} diff --git a/nitrogen/generated/shared/c++/HybridRiveFileFactorySpec.hpp b/nitrogen/generated/shared/c++/HybridRiveFileFactorySpec.hpp index b84d85d7..c8367768 100644 --- a/nitrogen/generated/shared/c++/HybridRiveFileFactorySpec.hpp +++ b/nitrogen/generated/shared/c++/HybridRiveFileFactorySpec.hpp @@ -15,11 +15,15 @@ // Forward declaration of `HybridRiveFileSpec` to properly resolve imports. namespace margelo::nitro::rive { class HybridRiveFileSpec; } +// Forward declaration of `ReferencedAssetsType` to properly resolve imports. +namespace margelo::nitro::rive { struct ReferencedAssetsType; } #include #include "HybridRiveFileSpec.hpp" #include #include +#include "ReferencedAssetsType.hpp" +#include #include namespace margelo::nitro::rive { @@ -53,10 +57,10 @@ namespace margelo::nitro::rive { public: // Methods - virtual std::shared_ptr>> fromURL(const std::string& url, bool loadCdn) = 0; - virtual std::shared_ptr>> fromFileURL(const std::string& fileURL, bool loadCdn) = 0; - virtual std::shared_ptr>> fromResource(const std::string& resource, bool loadCdn) = 0; - virtual std::shared_ptr>> fromBytes(const std::shared_ptr& bytes, bool loadCdn) = 0; + virtual std::shared_ptr>> fromURL(const std::string& url, bool loadCdn, const std::optional& referencedAssets) = 0; + virtual std::shared_ptr>> fromFileURL(const std::string& fileURL, bool loadCdn, const std::optional& referencedAssets) = 0; + virtual std::shared_ptr>> fromResource(const std::string& resource, bool loadCdn, const std::optional& referencedAssets) = 0; + virtual std::shared_ptr>> fromBytes(const std::shared_ptr& bytes, bool loadCdn, const std::optional& referencedAssets) = 0; protected: // Hybrid Setup diff --git a/nitrogen/generated/shared/c++/HybridRiveFileSpec.cpp b/nitrogen/generated/shared/c++/HybridRiveFileSpec.cpp index dbfb192e..7f69b5b2 100644 --- a/nitrogen/generated/shared/c++/HybridRiveFileSpec.cpp +++ b/nitrogen/generated/shared/c++/HybridRiveFileSpec.cpp @@ -19,6 +19,7 @@ namespace margelo::nitro::rive { prototype.registerHybridMethod("viewModelByName", &HybridRiveFileSpec::viewModelByName); prototype.registerHybridMethod("defaultArtboardViewModel", &HybridRiveFileSpec::defaultArtboardViewModel); prototype.registerHybridMethod("release", &HybridRiveFileSpec::release); + prototype.registerHybridMethod("updateReferencedAssets", &HybridRiveFileSpec::updateReferencedAssets); }); } diff --git a/nitrogen/generated/shared/c++/HybridRiveFileSpec.hpp b/nitrogen/generated/shared/c++/HybridRiveFileSpec.hpp index 63d4ac9c..fc91d675 100644 --- a/nitrogen/generated/shared/c++/HybridRiveFileSpec.hpp +++ b/nitrogen/generated/shared/c++/HybridRiveFileSpec.hpp @@ -17,12 +17,15 @@ namespace margelo::nitro::rive { class HybridViewModelSpec; } // Forward declaration of `ArtboardBy` to properly resolve imports. namespace margelo::nitro::rive { struct ArtboardBy; } +// Forward declaration of `ReferencedAssetsType` to properly resolve imports. +namespace margelo::nitro::rive { struct ReferencedAssetsType; } #include #include #include "HybridViewModelSpec.hpp" #include #include "ArtboardBy.hpp" +#include "ReferencedAssetsType.hpp" namespace margelo::nitro::rive { @@ -59,6 +62,7 @@ namespace margelo::nitro::rive { virtual std::optional> viewModelByName(const std::string& name) = 0; virtual std::optional> defaultArtboardViewModel(const std::optional& artboardBy) = 0; virtual void release() = 0; + virtual void updateReferencedAssets(const ReferencedAssetsType& referencedAssets) = 0; protected: // Hybrid Setup diff --git a/nitrogen/generated/shared/c++/ReferencedAssetsType.hpp b/nitrogen/generated/shared/c++/ReferencedAssetsType.hpp new file mode 100644 index 00000000..1e4f4b5f --- /dev/null +++ b/nitrogen/generated/shared/c++/ReferencedAssetsType.hpp @@ -0,0 +1,79 @@ +/// +/// ReferencedAssetsType.hpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +#pragma once + +#if __has_include() +#include +#else +#error NitroModules cannot be found! Are you sure you installed NitroModules properly? +#endif +#if __has_include() +#include +#else +#error NitroModules cannot be found! Are you sure you installed NitroModules properly? +#endif +#if __has_include() +#include +#else +#error NitroModules cannot be found! Are you sure you installed NitroModules properly? +#endif + +// Forward declaration of `ResolvedReferencedAsset` to properly resolve imports. +namespace margelo::nitro::rive { struct ResolvedReferencedAsset; } + +#include +#include "ResolvedReferencedAsset.hpp" +#include +#include + +namespace margelo::nitro::rive { + + /** + * A struct which can be represented as a JavaScript object (ReferencedAssetsType). + */ + struct ReferencedAssetsType { + public: + std::optional> data SWIFT_PRIVATE; + + public: + ReferencedAssetsType() = default; + explicit ReferencedAssetsType(std::optional> data): data(data) {} + }; + +} // namespace margelo::nitro::rive + +namespace margelo::nitro { + + // C++ ReferencedAssetsType <> JS ReferencedAssetsType (object) + template <> + struct JSIConverter final { + static inline margelo::nitro::rive::ReferencedAssetsType fromJSI(jsi::Runtime& runtime, const jsi::Value& arg) { + jsi::Object obj = arg.asObject(runtime); + return margelo::nitro::rive::ReferencedAssetsType( + JSIConverter>>::fromJSI(runtime, obj.getProperty(runtime, "data")) + ); + } + static inline jsi::Value toJSI(jsi::Runtime& runtime, const margelo::nitro::rive::ReferencedAssetsType& arg) { + jsi::Object obj(runtime); + obj.setProperty(runtime, "data", JSIConverter>>::toJSI(runtime, arg.data)); + return obj; + } + static inline bool canConvert(jsi::Runtime& runtime, const jsi::Value& value) { + if (!value.isObject()) { + return false; + } + jsi::Object obj = value.getObject(runtime); + if (!nitro::isPlainObject(runtime, obj)) { + return false; + } + if (!JSIConverter>>::canConvert(runtime, obj.getProperty(runtime, "data"))) return false; + return true; + } + }; + +} // namespace margelo::nitro diff --git a/nitrogen/generated/shared/c++/ResolvedReferencedAsset.hpp b/nitrogen/generated/shared/c++/ResolvedReferencedAsset.hpp new file mode 100644 index 00000000..99815eee --- /dev/null +++ b/nitrogen/generated/shared/c++/ResolvedReferencedAsset.hpp @@ -0,0 +1,88 @@ +/// +/// ResolvedReferencedAsset.hpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +#pragma once + +#if __has_include() +#include +#else +#error NitroModules cannot be found! Are you sure you installed NitroModules properly? +#endif +#if __has_include() +#include +#else +#error NitroModules cannot be found! Are you sure you installed NitroModules properly? +#endif +#if __has_include() +#include +#else +#error NitroModules cannot be found! Are you sure you installed NitroModules properly? +#endif + + + +#include +#include + +namespace margelo::nitro::rive { + + /** + * A struct which can be represented as a JavaScript object (ResolvedReferencedAsset). + */ + struct ResolvedReferencedAsset { + public: + std::optional sourceUrl SWIFT_PRIVATE; + std::optional sourceAsset SWIFT_PRIVATE; + std::optional sourceAssetId SWIFT_PRIVATE; + std::optional path SWIFT_PRIVATE; + + public: + ResolvedReferencedAsset() = default; + explicit ResolvedReferencedAsset(std::optional sourceUrl, std::optional sourceAsset, std::optional sourceAssetId, std::optional path): sourceUrl(sourceUrl), sourceAsset(sourceAsset), sourceAssetId(sourceAssetId), path(path) {} + }; + +} // namespace margelo::nitro::rive + +namespace margelo::nitro { + + // C++ ResolvedReferencedAsset <> JS ResolvedReferencedAsset (object) + template <> + struct JSIConverter final { + static inline margelo::nitro::rive::ResolvedReferencedAsset fromJSI(jsi::Runtime& runtime, const jsi::Value& arg) { + jsi::Object obj = arg.asObject(runtime); + return margelo::nitro::rive::ResolvedReferencedAsset( + JSIConverter>::fromJSI(runtime, obj.getProperty(runtime, "sourceUrl")), + JSIConverter>::fromJSI(runtime, obj.getProperty(runtime, "sourceAsset")), + JSIConverter>::fromJSI(runtime, obj.getProperty(runtime, "sourceAssetId")), + JSIConverter>::fromJSI(runtime, obj.getProperty(runtime, "path")) + ); + } + static inline jsi::Value toJSI(jsi::Runtime& runtime, const margelo::nitro::rive::ResolvedReferencedAsset& arg) { + jsi::Object obj(runtime); + obj.setProperty(runtime, "sourceUrl", JSIConverter>::toJSI(runtime, arg.sourceUrl)); + obj.setProperty(runtime, "sourceAsset", JSIConverter>::toJSI(runtime, arg.sourceAsset)); + obj.setProperty(runtime, "sourceAssetId", JSIConverter>::toJSI(runtime, arg.sourceAssetId)); + obj.setProperty(runtime, "path", JSIConverter>::toJSI(runtime, arg.path)); + return obj; + } + static inline bool canConvert(jsi::Runtime& runtime, const jsi::Value& value) { + if (!value.isObject()) { + return false; + } + jsi::Object obj = value.getObject(runtime); + if (!nitro::isPlainObject(runtime, obj)) { + return false; + } + if (!JSIConverter>::canConvert(runtime, obj.getProperty(runtime, "sourceUrl"))) return false; + if (!JSIConverter>::canConvert(runtime, obj.getProperty(runtime, "sourceAsset"))) return false; + if (!JSIConverter>::canConvert(runtime, obj.getProperty(runtime, "sourceAssetId"))) return false; + if (!JSIConverter>::canConvert(runtime, obj.getProperty(runtime, "path"))) return false; + return true; + } + }; + +} // namespace margelo::nitro From 12310e3738bd63adb5ee0141f12d4890bbf92e65 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mikl=C3=B3s=20Fazekas?= Date: Thu, 6 Nov 2025 08:57:00 +0100 Subject: [PATCH 05/24] fix typecheck --- src/hooks/useRiveFile.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hooks/useRiveFile.ts b/src/hooks/useRiveFile.ts index 2aa3f697..6122526d 100644 --- a/src/hooks/useRiveFile.ts +++ b/src/hooks/useRiveFile.ts @@ -3,7 +3,7 @@ import { Image } from 'react-native'; import { RiveFileFactory, type RiveFile } from 'react-native-rive'; import type { ResolvedReferencedAsset } from '../specs/RiveFile.nitro'; -type RiveFileInput = number | { uri: string } | string | ArrayBuffer; +export type RiveFileInput = number | { uri: string } | string | ArrayBuffer; type ReferencedAsset = { source: number | { uri: string } }; From 24ce2424b9de06eedfbe2c689d904b57814db8ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mikl=C3=B3s=20Fazekas?= Date: Thu, 6 Nov 2025 09:00:43 +0100 Subject: [PATCH 06/24] fix typecheck --- src/index.tsx | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/index.tsx b/src/index.tsx index 76bd3d78..659e1301 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -46,7 +46,7 @@ export function multiply(a: number, b: number): number { * - play(): Starts playing the animation * - pause(): Pauses the animation */ -export const NitroRiveView = getHostComponent( +export const RiveView = getHostComponent( 'RiveView', () => RiveViewConfig ) as ReactNativeView; @@ -78,8 +78,3 @@ export { useRiveColor } from './hooks/useRiveColor'; export { useRiveTrigger } from './hooks/useRiveTrigger'; export { useRiveFile } from './hooks/useRiveFile'; export { type RiveFileInput } from './hooks/useRiveFile'; -export { RiveConfigurator } from './core/RiveConfigurator'; -export { type RiveConfiguratorConfig } from './core/RiveConfigurator'; -export { type ArtboardSpec } from './specs/ArtboardSpec'; -export { type StateMachineSpec } from './specs/StateMachineSpec'; -export { RiveView } from './core/RiveView'; From 2d35e2533ff38b360922c20513a6f64e0ee88c0b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mikl=C3=B3s=20Fazekas?= Date: Thu, 6 Nov 2025 09:07:39 +0100 Subject: [PATCH 07/24] fix: allow useRiveFile to work with undefined input --- src/hooks/useRiveFile.ts | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/hooks/useRiveFile.ts b/src/hooks/useRiveFile.ts index 6122526d..cb799680 100644 --- a/src/hooks/useRiveFile.ts +++ b/src/hooks/useRiveFile.ts @@ -73,7 +73,7 @@ type RiveFileHookResult = | { riveFile: null; isLoading: false; error: string }; export function useRiveFile( - input: RiveFileInput, + input: RiveFileInput | undefined, options: UseRiveFileOptions = {} ): RiveFileHookResult { const [result, setResult] = useState({ @@ -95,6 +95,14 @@ export function useRiveFile( try { const currentInput = input; + if (currentInput == null) { + setResult({ + riveFile: null, + isLoading: false, + error: 'No Rive file input provided.', + }); + return; + } if (typeof currentInput === 'string') { if ( currentInput.startsWith('http://') || From 628a6a4441b6ea64b7a9bf1a57be139f40670b20 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mikl=C3=B3s=20Fazekas?= Date: Thu, 6 Nov 2025 13:34:25 +0100 Subject: [PATCH 08/24] feat(andorid): implement referencedAssets --- .../com/margelo/nitro/rive/HybridRiveFile.kt | 7 + .../nitro/rive/HybridRiveFileFactory.kt | 62 +++-- .../nitro/rive/ReferencedAssetLoader.kt | 219 ++++++++++++++++++ 3 files changed, 271 insertions(+), 17 deletions(-) create mode 100644 android/src/main/java/com/margelo/nitro/rive/ReferencedAssetLoader.kt diff --git a/android/src/main/java/com/margelo/nitro/rive/HybridRiveFile.kt b/android/src/main/java/com/margelo/nitro/rive/HybridRiveFile.kt index a56d7776..54f16202 100644 --- a/android/src/main/java/com/margelo/nitro/rive/HybridRiveFile.kt +++ b/android/src/main/java/com/margelo/nitro/rive/HybridRiveFile.kt @@ -8,6 +8,7 @@ import com.facebook.proguard.annotations.DoNotStrip @DoNotStrip class HybridRiveFile : HybridRiveFileSpec() { var riveFile: File? = null + var referencedAssetCache: ReferencedAssetCache? = null override val viewModelCount: Double? get() = riveFile?.viewModelCount?.toDouble() @@ -37,8 +38,14 @@ class HybridRiveFile : HybridRiveFileSpec() { } } + override fun updateReferencedAssets(referencedAssets: ReferencedAssetsType) { + // TODO: Implement dynamic asset updates + } + override fun release() { riveFile?.release() riveFile = null + referencedAssetCache?.clear() + referencedAssetCache = null } } diff --git a/android/src/main/java/com/margelo/nitro/rive/HybridRiveFileFactory.kt b/android/src/main/java/com/margelo/nitro/rive/HybridRiveFileFactory.kt index 6e390af2..5294f6c6 100644 --- a/android/src/main/java/com/margelo/nitro/rive/HybridRiveFileFactory.kt +++ b/android/src/main/java/com/margelo/nitro/rive/HybridRiveFileFactory.kt @@ -3,6 +3,7 @@ package com.margelo.nitro.rive import android.annotation.SuppressLint import androidx.annotation.Keep import app.rive.runtime.kotlin.core.File +import app.rive.runtime.kotlin.core.Rive import com.facebook.proguard.annotations.DoNotStrip import com.margelo.nitro.core.ArrayBuffer import com.margelo.nitro.core.Promise @@ -13,21 +14,45 @@ import java.io.File as JavaFile import java.net.URI import java.net.URL +data class FileAndCache( + val file: File, + val cache: ReferencedAssetCache +) + @Keep @DoNotStrip class HybridRiveFileFactory : HybridRiveFileFactorySpec() { - override fun fromURL(url: String, loadCdn: Boolean): Promise { + private val assetLoader = ReferencedAssetLoader() + + private fun buildRiveFile( + data: ByteArray, + referencedAssets: ReferencedAssetsType? + ): FileAndCache { + val cache = mutableMapOf() + val customLoader = assetLoader.createCustomLoader(referencedAssets, cache) + + // TODO: The File object in Android does not have the concept of loading CDN assets + val riveFile = if (customLoader != null) { + File(data, Rive.defaultRendererType, customLoader) + } else { + File(data) + } + + return FileAndCache(riveFile, cache) + } + + override fun fromURL(url: String, loadCdn: Boolean, referencedAssets: ReferencedAssetsType?): Promise { return Promise.async { try { - val riveFile = withContext(Dispatchers.IO) { + val fileAndCache = withContext(Dispatchers.IO) { val urlObj = URL(url) val riveData = urlObj.readBytes() - // TODO: The File object in Android does not have the concept of loading CDN assets - File(riveData) + buildRiveFile(riveData, referencedAssets) } val hybridRiveFile = HybridRiveFile() - hybridRiveFile.riveFile = riveFile + hybridRiveFile.riveFile = fileAndCache.file + hybridRiveFile.referencedAssetCache = fileAndCache.cache hybridRiveFile } catch (e: Exception) { throw Error("Failed to download Rive file: ${e.message}") @@ -35,7 +60,7 @@ class HybridRiveFileFactory : HybridRiveFileFactorySpec() { } } - override fun fromFileURL(fileURL: String, loadCdn: Boolean): Promise { + override fun fromFileURL(fileURL: String, loadCdn: Boolean, referencedAssets: ReferencedAssetsType?): Promise { if (!fileURL.startsWith("file://")) { throw Error("fromFileURL: URL must be a file URL: $fileURL") } @@ -45,14 +70,15 @@ class HybridRiveFileFactory : HybridRiveFileFactorySpec() { val uri = URI(fileURL) val path = uri.path ?: throw Error("fromFileURL: Invalid URL: $fileURL") - val riveFile = withContext(Dispatchers.IO) { + val fileAndCache = withContext(Dispatchers.IO) { val file = JavaFile(path) val riveData = file.readBytes() - File(riveData) + buildRiveFile(riveData, referencedAssets) } val hybridRiveFile = HybridRiveFile() - hybridRiveFile.riveFile = riveFile + hybridRiveFile.riveFile = fileAndCache.file + hybridRiveFile.referencedAssetCache = fileAndCache.cache hybridRiveFile } catch (e: Exception) { throw Error("Failed to load Rive file: ${e.message}") @@ -61,23 +87,24 @@ class HybridRiveFileFactory : HybridRiveFileFactorySpec() { } @SuppressLint("DiscouragedApi") - override fun fromResource(resource: String, loadCdn: Boolean): Promise { + override fun fromResource(resource: String, loadCdn: Boolean, referencedAssets: ReferencedAssetsType?): Promise { return Promise.async { try { val context = NitroModules.applicationContext ?: throw Error("Could not load Rive file ($resource) from resource. No application context.") - val riveFile = withContext(Dispatchers.IO) { + val fileAndCache = withContext(Dispatchers.IO) { val resourceId = context.resources.getIdentifier(resource, "raw", context.packageName) if (resourceId == 0) { throw Error("Could not find Rive file: $resource.riv") } val inputStream = context.resources.openRawResource(resourceId) val riveData = inputStream.readBytes() - File(riveData) + buildRiveFile(riveData, referencedAssets) } val hybridRiveFile = HybridRiveFile() - hybridRiveFile.riveFile = riveFile + hybridRiveFile.riveFile = fileAndCache.file + hybridRiveFile.referencedAssetCache = fileAndCache.cache hybridRiveFile } catch (e: Exception) { throw Error("Failed to load Rive file: ${e.message}") @@ -85,15 +112,16 @@ class HybridRiveFileFactory : HybridRiveFileFactorySpec() { } } - override fun fromBytes(bytes: ArrayBuffer, loadCdn: Boolean): Promise { - val buffer = bytes.getBuffer(false) // Use false to avoid creating a read-only buffer + override fun fromBytes(bytes: ArrayBuffer, loadCdn: Boolean, referencedAssets: ReferencedAssetsType?): Promise { + val buffer = bytes.getBuffer(false) return Promise.async { try { val byteArray = ByteArray(buffer.remaining()) buffer.get(byteArray) - val riveFile = File(byteArray) + val fileAndCache = buildRiveFile(byteArray, referencedAssets) val hybridRiveFile = HybridRiveFile() - hybridRiveFile.riveFile = riveFile + hybridRiveFile.riveFile = fileAndCache.file + hybridRiveFile.referencedAssetCache = fileAndCache.cache hybridRiveFile } catch (e: Exception) { throw Error("Failed to load Rive file from bytes: ${e.message}") diff --git a/android/src/main/java/com/margelo/nitro/rive/ReferencedAssetLoader.kt b/android/src/main/java/com/margelo/nitro/rive/ReferencedAssetLoader.kt new file mode 100644 index 00000000..a13f5528 --- /dev/null +++ b/android/src/main/java/com/margelo/nitro/rive/ReferencedAssetLoader.kt @@ -0,0 +1,219 @@ +package com.margelo.nitro.rive + +import android.annotation.SuppressLint +import android.content.Context +import android.content.res.Resources +import android.net.Uri +import android.util.Log +import app.rive.runtime.kotlin.core.* +import com.margelo.nitro.NitroModules +import kotlinx.coroutines.* +import java.io.File as JavaFile +import java.io.IOException +import java.net.URI +import java.net.URL + +typealias ReferencedAssetCache = MutableMap + +class ReferencedAssetLoader { + private val scope = CoroutineScope(Dispatchers.IO + SupervisorJob()) + + private fun logError(message: String) { + Log.e("ReferencedAssetLoader", message) + } + + private fun isValidUrl(url: String): Boolean { + return try { + URL(url) + true + } catch (e: Exception) { + false + } + } + + private fun constructFilePath(filename: String, path: String): String { + return if (path.endsWith("/")) "$path$filename" else "$path/$filename" + } + + @SuppressLint("DiscouragedApi") + private fun getResourceId(source: String, context: Context): Int { + val resourceTypes = listOf("raw", "drawable") + + for (type in resourceTypes) { + val resourceId = context.resources.getIdentifier(source, type, context.packageName) + if (resourceId != 0) { + return resourceId + } + } + + return 0 + } + + private fun readAssetBytes(context: Context, fileName: String): ByteArray? { + val assetManager = context.assets + return try { + assetManager.open(fileName).use { inputStream -> + inputStream.readBytes() + } + } catch (e: IOException) { + logError("Unable to read file from assets: $fileName - ${e.message}") + null + } + } + + private fun downloadUrlAsset(url: String, listener: (ByteArray) -> Unit) { + if (!isValidUrl(url)) { + logError("Invalid URL: $url") + return + } + + scope.launch { + try { + val uri = URI(url) + val bytes = when (uri.scheme) { + "file" -> { + val file = JavaFile(uri.path) + if (!file.exists()) { + throw IOException("File not found: ${uri.path}") + } + if (!file.canRead()) { + throw IOException("Permission denied: ${uri.path}") + } + file.readBytes() + } + "http", "https" -> { + URL(url).readBytes() + } + else -> { + logError("Unsupported URL scheme: ${uri.scheme}") + return@launch + } + } + + withContext(Dispatchers.Main) { + listener(bytes) + } + } catch (e: Exception) { + logError("Unable to download asset from URL: $url - ${e.message}") + } + } + } + + private fun loadResourceAsset( + sourceAssetId: String, + context: Context, + listener: (ByteArray) -> Unit + ) { + scope.launch { + try { + val scheme = runCatching { Uri.parse(sourceAssetId).scheme }.getOrNull() + + if (scheme != null) { + downloadUrlAsset(sourceAssetId, listener) + return@launch + } + + val resourceId = getResourceId(sourceAssetId, context) + + if (resourceId != 0) { + val bytes = context.resources.openRawResource(resourceId).use { inputStream -> + inputStream.readBytes() + } + withContext(Dispatchers.Main) { + listener(bytes) + } + } else { + logError("Resource not found: $sourceAssetId") + } + } catch (e: IOException) { + logError("IO Exception while reading resource: $sourceAssetId - ${e.message}") + } catch (e: Resources.NotFoundException) { + logError("Resource not found: $sourceAssetId - ${e.message}") + } catch (e: Exception) { + logError("Unexpected error while processing resource: $sourceAssetId - ${e.message}") + } + } + } + + private fun loadBundledAsset( + sourceAsset: String, + path: String?, + context: Context, + listener: (ByteArray) -> Unit + ) { + scope.launch { + try { + val fullPath = if (path == null) sourceAsset else constructFilePath(sourceAsset, path) + val bytes = readAssetBytes(context, fullPath) + + if (bytes != null) { + withContext(Dispatchers.Main) { + listener(bytes) + } + } + } catch (e: Exception) { + logError("Error loading bundled asset: $sourceAsset - ${e.message}") + } + } + } + + private fun processAssetBytes(bytes: ByteArray, asset: FileAsset) { + when (asset) { + is ImageAsset -> asset.image = RiveRenderImage.make(bytes) + is FontAsset -> asset.font = RiveFont.make(bytes) + is AudioAsset -> asset.audio = RiveAudio.make(bytes) + } + } + + private fun loadAsset(assetData: ResolvedReferencedAsset, asset: FileAsset, context: Context) { + val listener: (ByteArray) -> Unit = { bytes -> + processAssetBytes(bytes, asset) + } + + when { + assetData.sourceAssetId != null -> { + loadResourceAsset(assetData.sourceAssetId, context, listener) + } + assetData.sourceUrl != null -> { + downloadUrlAsset(assetData.sourceUrl, listener) + } + assetData.sourceAsset != null -> { + loadBundledAsset(assetData.sourceAsset, assetData.path, context, listener) + } + } + } + + fun createCustomLoader( + referencedAssets: ReferencedAssetsType?, + cache: ReferencedAssetCache + ): FileAssetLoader? { + val assetsData = referencedAssets?.data ?: return null + val context = NitroModules.applicationContext ?: return null + + return object : FileAssetLoader() { + override fun loadContents(asset: FileAsset, inBandBytes: ByteArray): Boolean { + var key = asset.uniqueFilename.substringBeforeLast(".") + var assetData = assetsData[key] + + if (assetData == null) { + key = asset.name + assetData = assetsData[asset.name] + } + + if (assetData == null) { + return false + } + + cache[key] = asset + + loadAsset(assetData, asset, context) + + return true + } + } + } + + fun dispose() { + scope.cancel() + } +} From c26985abfea0afd3cc721f545212a047a7110083 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mikl=C3=B3s=20Fazekas?= Date: Thu, 6 Nov 2025 16:39:56 +0100 Subject: [PATCH 09/24] feat(ios): referencedAssetLoader - update on native side --- .../com/margelo/nitro/rive/HybridRiveFile.kt | 14 +++++++++++- .../nitro/rive/HybridRiveFileFactory.kt | 14 +++++++----- .../nitro/rive/ReferencedAssetLoader.kt | 4 ++++ ios/HybridRiveFile.swift | 17 ++++++++++++-- ios/HybridRiveFileFactory.swift | 22 ++++++++++--------- ios/ReferencedAssetLoader.swift | 10 +++++++-- 6 files changed, 61 insertions(+), 20 deletions(-) diff --git a/android/src/main/java/com/margelo/nitro/rive/HybridRiveFile.kt b/android/src/main/java/com/margelo/nitro/rive/HybridRiveFile.kt index 54f16202..f25bd959 100644 --- a/android/src/main/java/com/margelo/nitro/rive/HybridRiveFile.kt +++ b/android/src/main/java/com/margelo/nitro/rive/HybridRiveFile.kt @@ -3,12 +3,14 @@ package com.margelo.nitro.rive import androidx.annotation.Keep import app.rive.runtime.kotlin.core.File import com.facebook.proguard.annotations.DoNotStrip +import com.margelo.nitro.NitroModules @Keep @DoNotStrip class HybridRiveFile : HybridRiveFileSpec() { var riveFile: File? = null var referencedAssetCache: ReferencedAssetCache? = null + var assetLoader: ReferencedAssetLoader? = null override val viewModelCount: Double? get() = riveFile?.viewModelCount?.toDouble() @@ -39,10 +41,20 @@ class HybridRiveFile : HybridRiveFileSpec() { } override fun updateReferencedAssets(referencedAssets: ReferencedAssetsType) { - // TODO: Implement dynamic asset updates + val assetsData = referencedAssets.data ?: return + val cache = referencedAssetCache ?: return + val loader = assetLoader ?: return + val context = NitroModules.applicationContext ?: return + + for ((key, assetData) in assetsData) { + val asset = cache[key] ?: continue + loader.updateAsset(assetData, asset, context) + } } override fun release() { + assetLoader?.dispose() + assetLoader = null riveFile?.release() riveFile = null referencedAssetCache?.clear() diff --git a/android/src/main/java/com/margelo/nitro/rive/HybridRiveFileFactory.kt b/android/src/main/java/com/margelo/nitro/rive/HybridRiveFileFactory.kt index 5294f6c6..bee73739 100644 --- a/android/src/main/java/com/margelo/nitro/rive/HybridRiveFileFactory.kt +++ b/android/src/main/java/com/margelo/nitro/rive/HybridRiveFileFactory.kt @@ -16,20 +16,20 @@ import java.net.URL data class FileAndCache( val file: File, - val cache: ReferencedAssetCache + val cache: ReferencedAssetCache, + val loader: ReferencedAssetLoader? ) @Keep @DoNotStrip class HybridRiveFileFactory : HybridRiveFileFactorySpec() { - private val assetLoader = ReferencedAssetLoader() - private fun buildRiveFile( data: ByteArray, referencedAssets: ReferencedAssetsType? ): FileAndCache { val cache = mutableMapOf() - val customLoader = assetLoader.createCustomLoader(referencedAssets, cache) + val loader = ReferencedAssetLoader() + val customLoader = loader.createCustomLoader(referencedAssets, cache) // TODO: The File object in Android does not have the concept of loading CDN assets val riveFile = if (customLoader != null) { @@ -38,7 +38,7 @@ class HybridRiveFileFactory : HybridRiveFileFactorySpec() { File(data) } - return FileAndCache(riveFile, cache) + return FileAndCache(riveFile, cache, if (customLoader != null) loader else null) } override fun fromURL(url: String, loadCdn: Boolean, referencedAssets: ReferencedAssetsType?): Promise { @@ -53,6 +53,7 @@ class HybridRiveFileFactory : HybridRiveFileFactorySpec() { val hybridRiveFile = HybridRiveFile() hybridRiveFile.riveFile = fileAndCache.file hybridRiveFile.referencedAssetCache = fileAndCache.cache + hybridRiveFile.assetLoader = fileAndCache.loader hybridRiveFile } catch (e: Exception) { throw Error("Failed to download Rive file: ${e.message}") @@ -79,6 +80,7 @@ class HybridRiveFileFactory : HybridRiveFileFactorySpec() { val hybridRiveFile = HybridRiveFile() hybridRiveFile.riveFile = fileAndCache.file hybridRiveFile.referencedAssetCache = fileAndCache.cache + hybridRiveFile.assetLoader = fileAndCache.loader hybridRiveFile } catch (e: Exception) { throw Error("Failed to load Rive file: ${e.message}") @@ -105,6 +107,7 @@ class HybridRiveFileFactory : HybridRiveFileFactorySpec() { val hybridRiveFile = HybridRiveFile() hybridRiveFile.riveFile = fileAndCache.file hybridRiveFile.referencedAssetCache = fileAndCache.cache + hybridRiveFile.assetLoader = fileAndCache.loader hybridRiveFile } catch (e: Exception) { throw Error("Failed to load Rive file: ${e.message}") @@ -122,6 +125,7 @@ class HybridRiveFileFactory : HybridRiveFileFactorySpec() { val hybridRiveFile = HybridRiveFile() hybridRiveFile.riveFile = fileAndCache.file hybridRiveFile.referencedAssetCache = fileAndCache.cache + hybridRiveFile.assetLoader = fileAndCache.loader hybridRiveFile } catch (e: Exception) { throw Error("Failed to load Rive file from bytes: ${e.message}") diff --git a/android/src/main/java/com/margelo/nitro/rive/ReferencedAssetLoader.kt b/android/src/main/java/com/margelo/nitro/rive/ReferencedAssetLoader.kt index a13f5528..f2efd9fc 100644 --- a/android/src/main/java/com/margelo/nitro/rive/ReferencedAssetLoader.kt +++ b/android/src/main/java/com/margelo/nitro/rive/ReferencedAssetLoader.kt @@ -183,6 +183,10 @@ class ReferencedAssetLoader { } } + fun updateAsset(assetData: ResolvedReferencedAsset, asset: FileAsset, context: Context) { + loadAsset(assetData, asset, context) + } + fun createCustomLoader( referencedAssets: ReferencedAssetsType?, cache: ReferencedAssetCache diff --git a/ios/HybridRiveFile.swift b/ios/HybridRiveFile.swift index 1aeaffb0..8715f173 100644 --- a/ios/HybridRiveFile.swift +++ b/ios/HybridRiveFile.swift @@ -5,7 +5,8 @@ typealias ReferencedAssetCache = [String: RiveFileAsset] class HybridRiveFile: HybridRiveFileSpec { var riveFile: RiveFile? var referencedAssetCache: ReferencedAssetCache? - + var assetLoader: ReferencedAssetLoader? + public func setRiveFile(_ riveFile: RiveFile) { self.riveFile = riveFile } @@ -49,7 +50,19 @@ class HybridRiveFile: HybridRiveFileSpec { } func updateReferencedAssets(referencedAssets: ReferencedAssetsType) { - + guard let assetsData = referencedAssets.data, + let cache = referencedAssetCache, + let loader = assetLoader, + let riveFile = riveFile else { + return + } + + let factory = RiveFactory() + + for (key, assetData) in assetsData { + guard let asset = cache[key] else { continue } + loader.loadAsset(source: assetData, asset: asset, factory: factory) + } } func release() throws { diff --git a/ios/HybridRiveFileFactory.swift b/ios/HybridRiveFileFactory.swift index 10940620..b3f87a00 100644 --- a/ios/HybridRiveFileFactory.swift +++ b/ios/HybridRiveFileFactory.swift @@ -2,17 +2,18 @@ import NitroModules import RiveRuntime final class HybridRiveFileFactory: HybridRiveFileFactorySpec { - private let assetLoader = ReferencedAssetLoader() - - private func buildRiveFile(data: Data, loadCdn: Bool,referencedAssets: ReferencedAssetsType?) throws -> FileAndCache { + private func buildRiveFile(data: Data, loadCdn: Bool, referencedAssets: ReferencedAssetsType?) throws -> (file: RiveFile, cache: ReferencedAssetCache, loader: ReferencedAssetLoader?) { var referencedAssetCache = Ref(ReferencedAssetCache()) - let riveFile = - if let customLoader = assetLoader.createCustomLoader(referencedAssets: referencedAssets, cache: referencedAssetCache) { - try RiveFile(data: data, loadCdn: loadCdn, customAssetLoader: customLoader) - } else { - try RiveFile(data: data, loadCdn: loadCdn) - } - return FileAndCache(file: riveFile, cache: referencedAssetCache.value) + let assetLoader = ReferencedAssetLoader() + let customLoader = assetLoader.createCustomLoader(referencedAssets: referencedAssets, cache: referencedAssetCache) + + let riveFile = if let customLoader = customLoader { + try RiveFile(data: data, loadCdn: loadCdn, customAssetLoader: customLoader) + } else { + try RiveFile(data: data, loadCdn: loadCdn) + } + + return (file: riveFile, cache: referencedAssetCache.value, loader: customLoader != nil ? assetLoader : nil) } // MARK: Public Methods @@ -71,6 +72,7 @@ final class HybridRiveFileFactory: HybridRiveFileFactorySpec { let hybridRiveFile = HybridRiveFile() hybridRiveFile.riveFile = riveFile.file hybridRiveFile.referencedAssetCache = riveFile.cache + hybridRiveFile.assetLoader = riveFile.loader return hybridRiveFile } catch let error as NSError { throw RuntimeError.error(withMessage: "Failed to load Rive file: \(error.localizedDescription)") diff --git a/ios/ReferencedAssetLoader.swift b/ios/ReferencedAssetLoader.swift index fd4be059..5e921276 100644 --- a/ios/ReferencedAssetLoader.swift +++ b/ios/ReferencedAssetLoader.swift @@ -172,7 +172,7 @@ final class ReferencedAssetLoader { } } - private func loadAsset( + private func loadAssetInternal( source: ResolvedReferencedAsset, asset: RiveFileAsset, factory: RiveFactory ) { let sourceAssetId = source.sourceAssetId @@ -188,6 +188,12 @@ final class ReferencedAssetLoader { } } + func loadAsset( + source: ResolvedReferencedAsset, asset: RiveFileAsset, factory: RiveFactory + ) { + loadAssetInternal(source: source, asset: asset, factory: factory) + } + func createCustomLoader(referencedAssets: ReferencedAssetsType?, cache: Ref) -> LoadAsset? { @@ -204,7 +210,7 @@ final class ReferencedAssetLoader { cache.value[asset.uniqueName()] = asset - self.loadAsset(source: assetData, asset: asset, factory: factory) + self.loadAssetInternal(source: assetData, asset: asset, factory: factory) return false } From 47e3abced50f6875b3f54f816c7708a5aa06cefa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mikl=C3=B3s=20Fazekas?= Date: Fri, 7 Nov 2025 07:57:54 +0100 Subject: [PATCH 10/24] chore: added test for useRiveFile --- example/package.json | 1 + jest-setup.js | 20 + package.json | 13 +- src/hooks/__tests__/useRiveFile.test.ts | 119 ++ src/hooks/useRiveFile.ts | 14 +- yarn.lock | 2455 +++++++++++------------ 6 files changed, 1314 insertions(+), 1308 deletions(-) create mode 100644 jest-setup.js create mode 100644 src/hooks/__tests__/useRiveFile.test.ts diff --git a/example/package.json b/example/package.json index c474acf9..4b18e335 100644 --- a/example/package.json +++ b/example/package.json @@ -10,6 +10,7 @@ "build:ios": "react-native build-ios --mode Debug" }, "dependencies": { + "@react-native-picker/picker": "^2.11.4", "@react-navigation/native": "^7.1.9", "@react-navigation/stack": "^7.3.2", "react": "19.0.0", diff --git a/jest-setup.js b/jest-setup.js new file mode 100644 index 00000000..9883d1cd --- /dev/null +++ b/jest-setup.js @@ -0,0 +1,20 @@ +/* global jest */ +const mockRiveFileFactory = { + fromURL: jest.fn(), + fromResource: jest.fn(), + fromSource: jest.fn(), + fromBytes: jest.fn(), +}; + +jest.mock('react-native-nitro-modules', () => ({ + NitroModules: { + createHybridObject: jest.fn(() => mockRiveFileFactory), + }, + getHostComponent: jest.fn(() => 'RiveView'), +})); + +jest.mock('./nitrogen/generated/shared/json/RiveViewConfig.json', () => ({}), { + virtual: true, +}); + +global.mockRiveFileFactory = mockRiveFileFactory; diff --git a/package.json b/package.json index 221f1c60..c5229f05 100644 --- a/package.json +++ b/package.json @@ -75,6 +75,8 @@ "@react-native/babel-preset": "0.79.2", "@react-native/eslint-config": "^0.78.0", "@release-it/conventional-changelog": "^9.0.2", + "@testing-library/react-hooks": "^8.0.1", + "@testing-library/react-native": "^13.3.3", "@types/jest": "^29.5.5", "@types/react": "^19.0.0", "commitlint": "^19.6.1", @@ -89,6 +91,7 @@ "react-native": "0.79.2", "react-native-builder-bob": "^0.40.10", "react-native-nitro-modules": "^0.31.3", + "react-test-renderer": "19.0.0", "release-it": "^17.10.0", "turbo": "^1.10.7", "typescript": "^5.2.2" @@ -104,10 +107,18 @@ "packageManager": "yarn@3.6.1", "jest": { "preset": "react-native", + "setupFilesAfterEnv": ["/jest-setup.js"], + "testMatch": [ + "/src/**/__tests__/**/*.{js,jsx,ts,tsx}", + "/src/**/*.{spec,test}.{js,jsx,ts,tsx}" + ], "modulePathIgnorePatterns": [ "/example/node_modules", "/lib/" - ] + ], + "moduleNameMapper": { + "^../nitrogen/generated/shared/json/RiveViewConfig\\.json$": "/jest-setup.js" + } }, "commitlint": { "extends": [ diff --git a/src/hooks/__tests__/useRiveFile.test.ts b/src/hooks/__tests__/useRiveFile.test.ts new file mode 100644 index 00000000..cf69cbb4 --- /dev/null +++ b/src/hooks/__tests__/useRiveFile.test.ts @@ -0,0 +1,119 @@ +import { renderHook, waitFor } from '@testing-library/react-native'; +import { useRiveFile } from '../useRiveFile'; +import type { RiveFile } from '../../specs/RiveFile.nitro'; + +jest.mock('react-native/Libraries/Image/Image', () => ({ + resolveAssetSource: jest.fn((source: number) => ({ + uri: `asset://resolved/${source}`, + })), +})); + +describe('useRiveFile - updateReferencedAssets', () => { + const mockRiveFile: RiveFile = { + release: jest.fn(), + updateReferencedAssets: jest.fn(), + viewModelCount: 0, + viewModelByIndex: jest.fn(), + viewModelByName: jest.fn(), + defaultArtboardViewModel: jest.fn(), + } as any; + + beforeEach(() => { + jest.clearAllMocks(); + (global as any).mockRiveFileFactory.fromURL.mockResolvedValue(mockRiveFile); + (global as any).mockRiveFileFactory.fromResource.mockResolvedValue( + mockRiveFile + ); + }); + + it('should call updateReferencedAssets when referencedAssets change', async () => { + const initialAssets = { + 'asset-1': { source: { uri: 'https://example.com/image1.png' } }, + }; + + const { result, rerender } = renderHook( + (props: { referencedAssets: any }) => + useRiveFile('https://example.com/animation.riv', { + referencedAssets: props.referencedAssets, + }), + { initialProps: { referencedAssets: initialAssets } } + ); + + await waitFor(() => { + expect((result.current as any).isLoading).toBe(false); + }); + + expect(mockRiveFile.updateReferencedAssets).not.toHaveBeenCalled(); + + const updatedAssets = { + 'asset-1': { source: { uri: 'https://example.com/image2.png' } }, + }; + + rerender({ referencedAssets: updatedAssets }); + + await waitFor(() => { + expect(mockRiveFile.updateReferencedAssets).toHaveBeenCalledWith({ + data: { + 'asset-1': { sourceUrl: 'https://example.com/image2.png' }, + }, + }); + }); + }); + + it('should handle multiple asset changes', async () => { + const initialAssets = { + 'asset-1': { source: { uri: 'https://example.com/image1.png' } }, + 'asset-2': { source: { uri: 'https://example.com/image2.png' } }, + }; + + const { result, rerender } = renderHook( + (props: { referencedAssets: any }) => + useRiveFile('https://example.com/animation.riv', { + referencedAssets: props.referencedAssets, + }), + { initialProps: { referencedAssets: initialAssets } } + ); + + await waitFor(() => { + expect((result.current as any).isLoading).toBe(false); + }); + + const updatedAssets = { + 'asset-1': { source: { uri: 'https://example.com/image1-new.png' } }, + 'asset-2': { source: { uri: 'https://example.com/image2-new.png' } }, + }; + + rerender({ referencedAssets: updatedAssets }); + + await waitFor(() => { + expect(mockRiveFile.updateReferencedAssets).toHaveBeenCalledWith({ + data: { + 'asset-1': { sourceUrl: 'https://example.com/image1-new.png' }, + 'asset-2': { sourceUrl: 'https://example.com/image2-new.png' }, + }, + }); + }); + }); + + it('should not call updateReferencedAssets if assets have not changed', async () => { + const assets = { + 'asset-1': { source: { uri: 'https://example.com/image1.png' } }, + }; + + const { result, rerender } = renderHook( + (props: { referencedAssets: any }) => + useRiveFile('https://example.com/animation.riv', { + referencedAssets: props.referencedAssets, + }), + { initialProps: { referencedAssets: assets } } + ); + + await waitFor(() => { + expect((result.current as any).isLoading).toBe(false); + }); + + rerender({ referencedAssets: assets }); + + expect(mockRiveFile.updateReferencedAssets).not.toHaveBeenCalled(); + }); +}); diff --git a/src/hooks/useRiveFile.ts b/src/hooks/useRiveFile.ts index cb799680..1d7f4961 100644 --- a/src/hooks/useRiveFile.ts +++ b/src/hooks/useRiveFile.ts @@ -153,13 +153,15 @@ export function useRiveFile( }; }, [input]); - if (initialReferencedAssets.current !== referencedAssets) { - // TODO: if riveFile not yet loaded?! - const { riveFile } = result; - if (riveFile && referencedAssets) { - riveFile.updateReferencedAssets(referencedAssets); + const { riveFile } = result; + useEffect(() => { + if (initialReferencedAssets.current !== referencedAssets) { + if (riveFile && referencedAssets) { + riveFile.updateReferencedAssets({ data: referencedAssets }); + initialReferencedAssets.current = referencedAssets; + } } - } + }, [referencedAssets, riveFile]); if (initialInput.current !== input) { console.warn( diff --git a/yarn.lock b/yarn.lock index 2a825f9d..027877cf 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5,29 +5,19 @@ __metadata: version: 6 cacheKey: 8 -"@ampproject/remapping@npm:^2.2.0": - version: 2.3.0 - resolution: "@ampproject/remapping@npm:2.3.0" - dependencies: - "@jridgewell/gen-mapping": ^0.3.5 - "@jridgewell/trace-mapping": ^0.3.24 - checksum: d3ad7b89d973df059c4e8e6d7c972cbeb1bb2f18f002a3bd04ae0707da214cb06cc06929b65aa2313b9347463df2914772298bae8b1d7973f246bb3f2ab3e8f0 - languageName: node - linkType: hard - -"@ark/schema@npm:0.46.0": - version: 0.46.0 - resolution: "@ark/schema@npm:0.46.0" +"@ark/schema@npm:0.53.0": + version: 0.53.0 + resolution: "@ark/schema@npm:0.53.0" dependencies: - "@ark/util": 0.46.0 - checksum: a4e7bc0e1c23009c7702ada7cfcbb1638af76f9721c43f96432844ec8616da6fc8121057fb87b0b80142558cf5c3e6141f40443cf43dd026ada8fd4acd635565 + "@ark/util": 0.53.0 + checksum: bea15e638bf63f56dee9a2bdeaf746232dd2c4b25663e47538376aa14d25a45b519f84271af9155b2618529cb4ad6701399e1f01153e3386cd3c38629ffc4c88 languageName: node linkType: hard -"@ark/util@npm:0.46.0": - version: 0.46.0 - resolution: "@ark/util@npm:0.46.0" - checksum: 0c0ceeb10aa0806860f7a7922586a05cda2945f7f598b414b4ebf268a6b45b00f9a854d6afd6b59df58c733e90d00b230194dd6a180a3a23d0eb64612be1b0e0 +"@ark/util@npm:0.53.0": + version: 0.53.0 + resolution: "@ark/util@npm:0.53.0" + checksum: 16d1a7393d310078083b333022dacfe2575cce8133b7348b566f20021605710aa93ffadc2d8c1a499f0e5ac533e610f204e77564db3bf82b1b5799f29988b27d languageName: node linkType: hard @@ -42,39 +32,39 @@ __metadata: languageName: node linkType: hard -"@babel/compat-data@npm:^7.22.6, @babel/compat-data@npm:^7.27.2": - version: 7.27.2 - resolution: "@babel/compat-data@npm:7.27.2" - checksum: 8d4066324e5f1275adc43f2e22110cac29ee09fe926260c43f0eaa432c148859367df4152574a28ee02dbb3e3d11dd57145eed345d49cc07f9b6e11fee06535f +"@babel/compat-data@npm:^7.27.2, @babel/compat-data@npm:^7.27.7, @babel/compat-data@npm:^7.28.5": + 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.27.1 - resolution: "@babel/core@npm:7.27.1" +"@babel/core@npm:^7.11.6, @babel/core@npm:^7.12.3, @babel/core@npm:^7.23.9, @babel/core@npm:^7.25.2": + version: 7.28.5 + resolution: "@babel/core@npm:7.28.5" dependencies: - "@ampproject/remapping": ^2.2.0 "@babel/code-frame": ^7.27.1 - "@babel/generator": ^7.27.1 - "@babel/helper-compilation-targets": ^7.27.1 - "@babel/helper-module-transforms": ^7.27.1 - "@babel/helpers": ^7.27.1 - "@babel/parser": ^7.27.1 - "@babel/template": ^7.27.1 - "@babel/traverse": ^7.27.1 - "@babel/types": ^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: fce205f9eea387ed8a9c6de64e5a8f50256359bfc8f1352c576c843b4c148a6c2ef187cfe8d729453e520fdcc997f65920aca6cb8911fb25dfd2286966b9b914 + checksum: 1ee35b20448f73e9d531091ad4f9e8198dc8f0cebb783263fbff1807342209882ddcaf419be04111326b6f0e494222f7055d71da316c437a6a784d230c11ab9f languageName: node linkType: hard "@babel/eslint-parser@npm:^7.25.1": - version: 7.27.1 - resolution: "@babel/eslint-parser@npm:7.27.1" + version: 7.28.5 + resolution: "@babel/eslint-parser@npm:7.28.5" dependencies: "@nicolo-ribaudo/eslint-scope-5-internals": 5.1.1-v1 eslint-visitor-keys: ^2.1.0 @@ -82,33 +72,33 @@ __metadata: peerDependencies: "@babel/core": ^7.11.0 eslint: ^7.5.0 || ^8.0.0 || ^9.0.0 - checksum: 0e8aa37fe03e5e5f2db35e1e628c02012a9ea9aa14429495eacdb0418e8ebeaf7b6308f9f8931ee3fe64a61fd6ac7637c8ffcc2c0d85eee246b6115198418bc2 + checksum: 8daaf6f24d3f78c18bc4cf2bf1bedda3d829f330f385b85acf630adde3de7a703abf0d2615afea09244caa713dded01aa3c00f3637ea70568b2e8c547067fb99 languageName: node linkType: hard -"@babel/generator@npm:^7.20.0, @babel/generator@npm:^7.25.0, @babel/generator@npm:^7.27.1, @babel/generator@npm:^7.7.2": - version: 7.27.1 - resolution: "@babel/generator@npm:7.27.1" +"@babel/generator@npm:^7.25.0, @babel/generator@npm:^7.28.5, @babel/generator@npm:^7.7.2": + version: 7.28.5 + resolution: "@babel/generator@npm:7.28.5" dependencies: - "@babel/parser": ^7.27.1 - "@babel/types": ^7.27.1 - "@jridgewell/gen-mapping": ^0.3.5 - "@jridgewell/trace-mapping": ^0.3.25 + "@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: d5e220eb20aca1d93aef85c4c716237f84c5aab7d3ed8dfeb7060dcd73d20c593a687fe74cfb6d3dc1604ef9faff2ca24e6cfdb1af18e03e3a5f9f63a04c0bdc + checksum: 3e86fa0197bb33394a85a73dbbca92bb1b3f250a30294c7e327359c0978ad90f36f3d71c7f2965a3fc349cfa82becc8f87e7421c75796c8bc48dd9010dd866d1 languageName: node linkType: hard -"@babel/helper-annotate-as-pure@npm:^7.27.1": - version: 7.27.1 - resolution: "@babel/helper-annotate-as-pure@npm:7.27.1" +"@babel/helper-annotate-as-pure@npm:^7.27.1, @babel/helper-annotate-as-pure@npm:^7.27.3": + version: 7.27.3 + resolution: "@babel/helper-annotate-as-pure@npm:7.27.3" dependencies: - "@babel/types": ^7.27.1 - checksum: 3f8e4d591458d6c0621a3d670f8798b8895580214287390126e3e621ddf3df0bd07cbcc9500c2671b9ec10162c2f9feb1194da5cf039d40df8cb69d181fc0cd8 + "@babel/types": ^7.27.3 + checksum: 63863a5c936ef82b546ca289c9d1b18fabfc24da5c4ee382830b124e2e79b68d626207febc8d4bffc720f50b2ee65691d7d12cc0308679dee2cd6bdc926b7190 languageName: node linkType: hard -"@babel/helper-compilation-targets@npm:^7.22.6, @babel/helper-compilation-targets@npm:^7.27.1, @babel/helper-compilation-targets@npm:^7.27.2": +"@babel/helper-compilation-targets@npm:^7.27.1, @babel/helper-compilation-targets@npm:^7.27.2": version: 7.27.2 resolution: "@babel/helper-compilation-targets@npm:7.27.2" dependencies: @@ -121,58 +111,65 @@ __metadata: languageName: node linkType: hard -"@babel/helper-create-class-features-plugin@npm:^7.27.1": - version: 7.27.1 - resolution: "@babel/helper-create-class-features-plugin@npm:7.27.1" +"@babel/helper-create-class-features-plugin@npm:^7.27.1, @babel/helper-create-class-features-plugin@npm:^7.28.3, @babel/helper-create-class-features-plugin@npm:^7.28.5": + version: 7.28.5 + resolution: "@babel/helper-create-class-features-plugin@npm:7.28.5" dependencies: - "@babel/helper-annotate-as-pure": ^7.27.1 - "@babel/helper-member-expression-to-functions": ^7.27.1 + "@babel/helper-annotate-as-pure": ^7.27.3 + "@babel/helper-member-expression-to-functions": ^7.28.5 "@babel/helper-optimise-call-expression": ^7.27.1 "@babel/helper-replace-supers": ^7.27.1 "@babel/helper-skip-transparent-expression-wrappers": ^7.27.1 - "@babel/traverse": ^7.27.1 + "@babel/traverse": ^7.28.5 semver: ^6.3.1 peerDependencies: "@babel/core": ^7.0.0 - checksum: 406954b455e5b20924e7d1b41cf932e6e98e95c3a5224c7a70c3ad96a84e8fbde915ceff7ddbf9c7d121397c4e9274f061241648475122cf6fe54e0a95caae15 + checksum: 98f94a27bcde0cf0b847c41e1307057a1caddd131fb5fa0b1566e0c15ccc20b0ebab9667d782bffcd3eac9262226b18e86dcf30ab0f4dc5d14b1e1bf243aba49 languageName: node linkType: hard "@babel/helper-create-regexp-features-plugin@npm:^7.18.6, @babel/helper-create-regexp-features-plugin@npm:^7.27.1": - version: 7.27.1 - resolution: "@babel/helper-create-regexp-features-plugin@npm:7.27.1" + version: 7.28.5 + resolution: "@babel/helper-create-regexp-features-plugin@npm:7.28.5" dependencies: - "@babel/helper-annotate-as-pure": ^7.27.1 - regexpu-core: ^6.2.0 + "@babel/helper-annotate-as-pure": ^7.27.3 + regexpu-core: ^6.3.1 semver: ^6.3.1 peerDependencies: "@babel/core": ^7.0.0 - checksum: 2ede6bbad0016a9262fd281ce8f1a5d69e6179dcec4ea282830e924c29a29b66b0544ecb92e4ef4acdaf2c4c990931d7dc442dbcd6a8bcec4bad73923ef70934 + checksum: de202103e6ff8cd8da0d62eb269fcceb29857f3fa16173f0ff38188fd514e9ad4901aef1d590ff8ba25381644b42eaf70ad9ba91fda59fe7aa6a5e694cdde267 languageName: node linkType: hard -"@babel/helper-define-polyfill-provider@npm:^0.6.3, @babel/helper-define-polyfill-provider@npm:^0.6.4": - version: 0.6.4 - resolution: "@babel/helper-define-polyfill-provider@npm:0.6.4" +"@babel/helper-define-polyfill-provider@npm:^0.6.5": + version: 0.6.5 + resolution: "@babel/helper-define-polyfill-provider@npm:0.6.5" dependencies: - "@babel/helper-compilation-targets": ^7.22.6 - "@babel/helper-plugin-utils": ^7.22.5 - debug: ^4.1.1 + "@babel/helper-compilation-targets": ^7.27.2 + "@babel/helper-plugin-utils": ^7.27.1 + debug: ^4.4.1 lodash.debounce: ^4.0.8 - resolve: ^1.14.2 + resolve: ^1.22.10 peerDependencies: "@babel/core": ^7.4.0 || ^8.0.0-0 <8.0.0 - checksum: bfbcb41f005ba11497b459cf801650af558b533f383b2f57034e9ccce592a0af699b585898deef93598ed3d9bd14502327e18dfc8a92a3db48b2a49ae2886f86 + checksum: 9fd3b09b209c8ed0d3d8bc1f494f1368b9e1f6e46195af4ce948630fe97d7dafde4882eedace270b319bf6555ddf35e220c77505f6d634f621766cdccbba0aae languageName: node linkType: hard -"@babel/helper-member-expression-to-functions@npm:^7.27.1": - version: 7.27.1 - resolution: "@babel/helper-member-expression-to-functions@npm:7.27.1" +"@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.27.1, @babel/helper-member-expression-to-functions@npm:^7.28.5": + version: 7.28.5 + resolution: "@babel/helper-member-expression-to-functions@npm:7.28.5" dependencies: - "@babel/traverse": ^7.27.1 - "@babel/types": ^7.27.1 - checksum: b13a3d120015a6fd2f6e6c2ff789cd12498745ef028710cba612cfb751b91ace700c3f96c1689228d1dcb41e9d4cf83d6dff8627dcb0c8da12d79440e783c6b8 + "@babel/traverse": ^7.28.5 + "@babel/types": ^7.28.5 + checksum: 447d385233bae2eea713df1785f819b5a5ca272950740da123c42d23f491045120f0fbbb5609c091f7a9bbd40f289a442846dde0cb1bf0c59440fa093690cf7c languageName: node linkType: hard @@ -186,16 +183,16 @@ __metadata: languageName: node linkType: hard -"@babel/helper-module-transforms@npm:^7.27.1": - version: 7.27.1 - resolution: "@babel/helper-module-transforms@npm:7.27.1" +"@babel/helper-module-transforms@npm:^7.27.1, @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.27.1 + "@babel/traverse": ^7.28.3 peerDependencies: "@babel/core": ^7.0.0 - checksum: 816dd166f0a850616d01ca198715d78fef052a834dc155dd57e4405d702f288071077be3ed58e13c86ac9e63ca560e876cc6d70cf5ef0f1f62bd9321084d4c06 + checksum: 7cf7b79da0fa626d6c84bfc7b35c079a2559caecaa2ff645b0f1db0d741507aa4df6b5b98a3283e8ac4e89094af271d805bf5701e5c4f916e622797b7c8cbb18 languageName: node linkType: hard @@ -208,7 +205,7 @@ __metadata: languageName: node linkType: hard -"@babel/helper-plugin-utils@npm:^7.0.0, @babel/helper-plugin-utils@npm:^7.10.4, @babel/helper-plugin-utils@npm:^7.12.13, @babel/helper-plugin-utils@npm:^7.14.5, @babel/helper-plugin-utils@npm:^7.18.6, @babel/helper-plugin-utils@npm:^7.22.5, @babel/helper-plugin-utils@npm:^7.27.1, @babel/helper-plugin-utils@npm:^7.8.0": +"@babel/helper-plugin-utils@npm:^7.0.0, @babel/helper-plugin-utils@npm:^7.10.4, @babel/helper-plugin-utils@npm:^7.12.13, @babel/helper-plugin-utils@npm:^7.14.5, @babel/helper-plugin-utils@npm:^7.18.6, @babel/helper-plugin-utils@npm:^7.27.1, @babel/helper-plugin-utils@npm:^7.8.0": version: 7.27.1 resolution: "@babel/helper-plugin-utils@npm:7.27.1" checksum: 5d715055301badab62bdb2336075a77f8dc8bd290cad2bc1b37ea3bf1b3efc40594d308082229f239deb4d6b5b80b0a73bce000e595ea74416e0339c11037047 @@ -258,10 +255,10 @@ __metadata: languageName: node linkType: hard -"@babel/helper-validator-identifier@npm:^7.27.1": - version: 7.27.1 - resolution: "@babel/helper-validator-identifier@npm:7.27.1" - checksum: 3c7e8391e59d6c85baeefe9afb86432f2ab821c6232b00ea9082a51d3e7e95a2f3fb083d74dc1f49ac82cf238e1d2295dafcb001f7b0fab479f3f56af5eaaa47 +"@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 @@ -273,46 +270,46 @@ __metadata: linkType: hard "@babel/helper-wrap-function@npm:^7.27.1": - version: 7.27.1 - resolution: "@babel/helper-wrap-function@npm:7.27.1" + version: 7.28.3 + resolution: "@babel/helper-wrap-function@npm:7.28.3" dependencies: - "@babel/template": ^7.27.1 - "@babel/traverse": ^7.27.1 - "@babel/types": ^7.27.1 - checksum: b0427765766494cb5455a188d4cdef5e6167f2835a8ed76f3c25fa3bbe2ec2a716588fa326c52fab0d184a9537200d76e48656e516580a914129d74528322821 + "@babel/template": ^7.27.2 + "@babel/traverse": ^7.28.3 + "@babel/types": ^7.28.2 + checksum: 0ebdfdc918fdd0c1cf6ff15ba4c664974d0cdf21a017af560d58b00c379df3bf2e55f13a44fe3225668bca169da174f6cb97a96c4e987fb728fdb8f9a39db302 languageName: node linkType: hard -"@babel/helpers@npm:^7.27.1": - version: 7.27.1 - resolution: "@babel/helpers@npm:7.27.1" +"@babel/helpers@npm:^7.28.4": + version: 7.28.4 + resolution: "@babel/helpers@npm:7.28.4" dependencies: - "@babel/template": ^7.27.1 - "@babel/types": ^7.27.1 - checksum: 19ede1e996cbd295fb3a881ff70bc0f91c5133ebac256441e9ecd69dfba89456e75cf7ecf06cd276c638a4de7bd6eff21151961c78038d0b23d94b4d23415ee4 + "@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.27.1, @babel/parser@npm:^7.27.2": - version: 7.27.2 - resolution: "@babel/parser@npm:7.27.2" +"@babel/parser@npm:^7.1.0, @babel/parser@npm:^7.14.7, @babel/parser@npm:^7.20.7, @babel/parser@npm:^7.23.9, @babel/parser@npm:^7.25.3, @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.27.1 + "@babel/types": ^7.28.5 bin: parser: ./bin/babel-parser.js - checksum: 1ac70a75028f1cc10eefb10ed2d83cf700ca3e1ddb4cf556a003fc5c4ca53ae83350bbb8065020fcc70d476fcf7bf1c17191b72384f719614ae18397142289cf + checksum: 5c2456e3f26c70d4a3ce1a220b529a91a2df26c54a2894fd0dea2342699ea1067ffdda9f0715eeab61da46ff546fd5661bc70be6d8d11977cbe21f5f0478819a languageName: node linkType: hard -"@babel/plugin-bugfix-firefox-class-in-computed-class-key@npm:^7.27.1": - version: 7.27.1 - resolution: "@babel/plugin-bugfix-firefox-class-in-computed-class-key@npm:7.27.1" +"@babel/plugin-bugfix-firefox-class-in-computed-class-key@npm:^7.28.5": + version: 7.28.5 + resolution: "@babel/plugin-bugfix-firefox-class-in-computed-class-key@npm:7.28.5" dependencies: "@babel/helper-plugin-utils": ^7.27.1 - "@babel/traverse": ^7.27.1 + "@babel/traverse": ^7.28.5 peerDependencies: "@babel/core": ^7.0.0 - checksum: 72f24b9487e445fa61cf8be552aad394a648c2bb445c38d39d1df003186d9685b87dd8d388c950f438ea0ca44c82099d9c49252fb681c719cc72edf02bbe0304 + checksum: 749b40a963d5633f554cad0336245cb6c1c1393c70a3fddcf302d86a1a42b35efdd2ed62056b88db66f3900887ae1cee9a3eeec89799c22e0cf65059f0dfd142 languageName: node linkType: hard @@ -351,15 +348,15 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@npm:^7.27.1": - version: 7.27.1 - resolution: "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@npm:7.27.1" +"@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@npm:^7.28.3": + version: 7.28.3 + resolution: "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@npm:7.28.3" dependencies: "@babel/helper-plugin-utils": ^7.27.1 - "@babel/traverse": ^7.27.1 + "@babel/traverse": ^7.28.3 peerDependencies: "@babel/core": ^7.0.0 - checksum: 4d6792ccade2d6b9d5577b0a879ab22d05ac8a1206b1a636b6ffdb53a0c0bacaf0f7947e46de254f228ffd75456f4b95ccd82fdeaefc0b92d88af3c5991863ad + checksum: c810e5d36030df6861ced35f0adbda7b4b41ac3e984422b32bee906564fd49374435f0a7a1a42eb0a9e6a5170c255f0ab31c163d5fc51fa5a816aa0420311029 languageName: node linkType: hard @@ -637,16 +634,16 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-transform-async-generator-functions@npm:^7.25.4, @babel/plugin-transform-async-generator-functions@npm:^7.27.1": - version: 7.27.1 - resolution: "@babel/plugin-transform-async-generator-functions@npm:7.27.1" +"@babel/plugin-transform-async-generator-functions@npm:^7.25.4, @babel/plugin-transform-async-generator-functions@npm:^7.28.0": + version: 7.28.0 + resolution: "@babel/plugin-transform-async-generator-functions@npm:7.28.0" dependencies: "@babel/helper-plugin-utils": ^7.27.1 "@babel/helper-remap-async-to-generator": ^7.27.1 - "@babel/traverse": ^7.27.1 + "@babel/traverse": ^7.28.0 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 37e8b76c992066f81cc24af11a25f296add6ae39f51f2c37da565fc004dbf3ef9733b42808acbfb86792d73f73bfbb4396338abbd364b9103146b119508b49c7 + checksum: 174aaccd7a8386fd7f32240c3f65a93cf60dcc5f6a2123cfbff44c0d22b424cd41de3a0c6d136b6a2fa60a8ca01550c261677284cb18a0daeab70730b2265f1d languageName: node linkType: hard @@ -674,14 +671,14 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-transform-block-scoping@npm:^7.25.0, @babel/plugin-transform-block-scoping@npm:^7.27.1": - version: 7.27.1 - resolution: "@babel/plugin-transform-block-scoping@npm:7.27.1" +"@babel/plugin-transform-block-scoping@npm:^7.25.0, @babel/plugin-transform-block-scoping@npm:^7.28.5": + version: 7.28.5 + resolution: "@babel/plugin-transform-block-scoping@npm:7.28.5" dependencies: "@babel/helper-plugin-utils": ^7.27.1 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 490773ee111fd298d74bd0ba454c941ae23a39db5cd08bf4258997f44f7584399fc4214a7c3816ee70f0273c263fe2ea4e11bb07939e57845702ba05258a9cb0 + checksum: 2cbc11c9b61097b61806c279211a4c4f5e85a5ca7fd52228efbf3a729178d330142a00a93695dbacc2898477e5fa9e34e7637f18323247ebebb84f43005560f3 languageName: node linkType: hard @@ -697,31 +694,31 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-transform-class-static-block@npm:^7.27.1": - version: 7.27.1 - resolution: "@babel/plugin-transform-class-static-block@npm:7.27.1" +"@babel/plugin-transform-class-static-block@npm:^7.28.3": + version: 7.28.3 + resolution: "@babel/plugin-transform-class-static-block@npm:7.28.3" dependencies: - "@babel/helper-create-class-features-plugin": ^7.27.1 + "@babel/helper-create-class-features-plugin": ^7.28.3 "@babel/helper-plugin-utils": ^7.27.1 peerDependencies: "@babel/core": ^7.12.0 - checksum: 69688fe1641ae0ea025b916b8c2336e8b5643a5ec292e8f546ecd35d9d9d4bb301d738910822a79d867098cf687d550d92cd906ae4cda03c0f69b1ece2149a58 + checksum: 9b2feaacbf29637ab35a3aae1df35a1129adec5400a1767443739557fb0d3bf8278bf0ec90aacf43dec9a7dd91428d01375020b70528713e1bc36a72776a104c languageName: node linkType: hard -"@babel/plugin-transform-classes@npm:^7.25.4, @babel/plugin-transform-classes@npm:^7.27.1": - version: 7.27.1 - resolution: "@babel/plugin-transform-classes@npm:7.27.1" +"@babel/plugin-transform-classes@npm:^7.25.4, @babel/plugin-transform-classes@npm:^7.28.4": + version: 7.28.4 + resolution: "@babel/plugin-transform-classes@npm:7.28.4" dependencies: - "@babel/helper-annotate-as-pure": ^7.27.1 - "@babel/helper-compilation-targets": ^7.27.1 + "@babel/helper-annotate-as-pure": ^7.27.3 + "@babel/helper-compilation-targets": ^7.27.2 + "@babel/helper-globals": ^7.28.0 "@babel/helper-plugin-utils": ^7.27.1 "@babel/helper-replace-supers": ^7.27.1 - "@babel/traverse": ^7.27.1 - globals: ^11.1.0 + "@babel/traverse": ^7.28.4 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: a4275d3a9e2e4144c421baa49958191e4b33957fca6e87686ed8da0eb3240270d4f91a2a4b9491c87feb6c33f459d8aec013cec8d5f5099c794b740703802dc7 + checksum: f412e00c86584a9094cc0a2f3dd181b8108a4dced477d609c5406beddd5bf79d05a7ea74db508dc4dcb37172f042d5ef98d3d6311ade61c7ea6fbbbb70f5ec29 languageName: node linkType: hard @@ -737,14 +734,15 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-transform-destructuring@npm:^7.24.8, @babel/plugin-transform-destructuring@npm:^7.27.1": - version: 7.27.1 - resolution: "@babel/plugin-transform-destructuring@npm:7.27.1" +"@babel/plugin-transform-destructuring@npm:^7.24.8, @babel/plugin-transform-destructuring@npm:^7.28.0, @babel/plugin-transform-destructuring@npm:^7.28.5": + version: 7.28.5 + resolution: "@babel/plugin-transform-destructuring@npm:7.28.5" dependencies: "@babel/helper-plugin-utils": ^7.27.1 + "@babel/traverse": ^7.28.5 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 492013fc4befd5f3554853f983b82cfa748dd2004a525f1f16a37f841ac402a51e891cac2084b03e2b89553f0e1e685cf5bf8bf9df8fed82114c580b3c567bb6 + checksum: 74a06e55e715cfda0fdd8be53d2655d64dfdc28dffaede329d42548fd5b1449ad26a4ce43a24c3fd277b96f8b2010c7b3915afa8297911cda740cc5cc3a81f38 languageName: node linkType: hard @@ -794,14 +792,26 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-transform-exponentiation-operator@npm:^7.27.1": - version: 7.27.1 - resolution: "@babel/plugin-transform-exponentiation-operator@npm:7.27.1" +"@babel/plugin-transform-explicit-resource-management@npm:^7.28.0": + version: 7.28.0 + resolution: "@babel/plugin-transform-explicit-resource-management@npm:7.28.0" + dependencies: + "@babel/helper-plugin-utils": ^7.27.1 + "@babel/plugin-transform-destructuring": ^7.28.0 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: a44140097ed4854883c426613f4e8763237cd0fdab1c780514f4315f6c148d6b528d7a57fe6fdec4dbce28a21b70393ef3507b72dfec2e30bfc8d7db1ff19474 + languageName: node + linkType: hard + +"@babel/plugin-transform-exponentiation-operator@npm:^7.28.5": + version: 7.28.5 + resolution: "@babel/plugin-transform-exponentiation-operator@npm:7.28.5" dependencies: "@babel/helper-plugin-utils": ^7.27.1 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 4ff4a0f30babc457a5ae8564deda209599627c2ce647284a0e8e66f65b44f6d968cf77761a4cc31b45b61693f0810479248c79e681681d8ccb39d0c52944c1fd + checksum: da9bb5acd35c9fba92b802641f9462b82334158a149c78a739a04576a1e62be41057a201a41c022dda263bb73ac1a26521bbc997c7fc067f54d487af297995f4 languageName: node linkType: hard @@ -875,14 +885,14 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-transform-logical-assignment-operators@npm:^7.24.7, @babel/plugin-transform-logical-assignment-operators@npm:^7.27.1": - version: 7.27.1 - resolution: "@babel/plugin-transform-logical-assignment-operators@npm:7.27.1" +"@babel/plugin-transform-logical-assignment-operators@npm:^7.24.7, @babel/plugin-transform-logical-assignment-operators@npm:^7.28.5": + version: 7.28.5 + resolution: "@babel/plugin-transform-logical-assignment-operators@npm:7.28.5" dependencies: "@babel/helper-plugin-utils": ^7.27.1 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 2757955d81d65cc4701c17b83720745f6858f7a1d1d58117e379c204f47adbeb066b778596b6168bdbf4a22c229aab595d79a9abc261d0c6bfd62d4419466e73 + checksum: c76778f4b186cc4f0b7e3658d91c690678bdb2b9d032f189213016d6177f2564709b79b386523b022b7d52e52331fd91f280f7c7bf85d835e0758b4b0d371447 languageName: node linkType: hard @@ -921,17 +931,17 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-transform-modules-systemjs@npm:^7.27.1": - version: 7.27.1 - resolution: "@babel/plugin-transform-modules-systemjs@npm:7.27.1" +"@babel/plugin-transform-modules-systemjs@npm:^7.28.5": + version: 7.28.5 + resolution: "@babel/plugin-transform-modules-systemjs@npm:7.28.5" dependencies: - "@babel/helper-module-transforms": ^7.27.1 + "@babel/helper-module-transforms": ^7.28.3 "@babel/helper-plugin-utils": ^7.27.1 - "@babel/helper-validator-identifier": ^7.27.1 - "@babel/traverse": ^7.27.1 + "@babel/helper-validator-identifier": ^7.28.5 + "@babel/traverse": ^7.28.5 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 7c17a8973676c18525d87f277944616596f1b154cc2b9263bfd78ecdbf5f4288ec46c7f58017321ca3e3d6dfeb96875467b95311a39719b475d42a157525d87f + checksum: 646748dcf968c107fedfbff38aa37f7a9ebf2ccdf51fd9f578c6cd323371db36bbc5fe0d995544db168f39be9bca32a85fbf3bfff4742d2bed22e21c2847fa46 languageName: node linkType: hard @@ -992,17 +1002,18 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-transform-object-rest-spread@npm:^7.24.7, @babel/plugin-transform-object-rest-spread@npm:^7.27.2": - version: 7.27.2 - resolution: "@babel/plugin-transform-object-rest-spread@npm:7.27.2" +"@babel/plugin-transform-object-rest-spread@npm:^7.24.7, @babel/plugin-transform-object-rest-spread@npm:^7.28.4": + version: 7.28.4 + resolution: "@babel/plugin-transform-object-rest-spread@npm:7.28.4" dependencies: "@babel/helper-compilation-targets": ^7.27.2 "@babel/helper-plugin-utils": ^7.27.1 - "@babel/plugin-transform-destructuring": ^7.27.1 - "@babel/plugin-transform-parameters": ^7.27.1 + "@babel/plugin-transform-destructuring": ^7.28.0 + "@babel/plugin-transform-parameters": ^7.27.7 + "@babel/traverse": ^7.28.4 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 6d518c21cddfa436029d72409aac8f680d3ba3a10eb94477112869132226498474a61218893ac9958f8bc079109af0f684d1347d5036fee8e9b477daecf2d8f3 + checksum: 2063672ba4ac457a64b5c0c982439c7b08b4c70f0e743792b98240db5a05f1c063918d8366c92d4d6b2572e2e3452b300a23980b6668e4f54ff349f60d47ec48 languageName: node linkType: hard @@ -1029,26 +1040,26 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-transform-optional-chaining@npm:^7.24.8, @babel/plugin-transform-optional-chaining@npm:^7.27.1": - version: 7.27.1 - resolution: "@babel/plugin-transform-optional-chaining@npm:7.27.1" +"@babel/plugin-transform-optional-chaining@npm:^7.24.8, @babel/plugin-transform-optional-chaining@npm:^7.27.1, @babel/plugin-transform-optional-chaining@npm:^7.28.5": + version: 7.28.5 + resolution: "@babel/plugin-transform-optional-chaining@npm:7.28.5" dependencies: "@babel/helper-plugin-utils": ^7.27.1 "@babel/helper-skip-transparent-expression-wrappers": ^7.27.1 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: c4428d31f182d724db6f10575669aad3dbccceb0dea26aa9071fa89f11b3456278da3097fcc78937639a13c105a82cd452dc0218ce51abdbcf7626a013b928a5 + checksum: 78c2be52b32e893c992aca52ef84130b3540e2ca0e1ff0e45f8d2ccc213b3c6e2b43f8dd2c86a0976acf3cdff97d4488c23b86d7a3e67daa517013089f44af1d languageName: node linkType: hard -"@babel/plugin-transform-parameters@npm:^7.24.7, @babel/plugin-transform-parameters@npm:^7.27.1": - version: 7.27.1 - resolution: "@babel/plugin-transform-parameters@npm:7.27.1" +"@babel/plugin-transform-parameters@npm:^7.24.7, @babel/plugin-transform-parameters@npm:^7.27.7": + version: 7.27.7 + resolution: "@babel/plugin-transform-parameters@npm:7.27.7" dependencies: "@babel/helper-plugin-utils": ^7.27.1 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 52dd9db2be63ca954dbf86bba3f1dedce5f8bcf0cbc2b9ab26981b6f9c3ad5ea3a1b7ba286d18ae05d7487763f2bd086533826ee82f7b8d76873265569e45125 + checksum: d51f195e1d6ac5d9fce583e9a70a5bfe403e62386e5eb06db9fbc6533f895a98ff7e7c3dcaa311a8e6fa7a9794466e81cdabcba6af9f59d787fb767bfe7868b4 languageName: node linkType: hard @@ -1088,14 +1099,14 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-transform-react-display-name@npm:^7.24.7, @babel/plugin-transform-react-display-name@npm:^7.27.1": - version: 7.27.1 - resolution: "@babel/plugin-transform-react-display-name@npm:7.27.1" +"@babel/plugin-transform-react-display-name@npm:^7.24.7, @babel/plugin-transform-react-display-name@npm:^7.28.0": + version: 7.28.0 + resolution: "@babel/plugin-transform-react-display-name@npm:7.28.0" dependencies: "@babel/helper-plugin-utils": ^7.27.1 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 9fb5fae6283f612983dac4df51a6cd41e085e698008146e046357fe324e6e8264cedf8426ea5a188326f6d3cd1e7a3d3174e15d510851e93e9ef7ceeba380dc2 + checksum: 268b1a9192974439d17949e170b01cac2a2aa003c844e2fe3b8361146f42f66487178cffdfa8ce862aa9e6c814bc37f879a70300cb3f067815d15fa6aad04e6d languageName: node linkType: hard @@ -1159,14 +1170,14 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-transform-regenerator@npm:^7.24.7, @babel/plugin-transform-regenerator@npm:^7.27.1": - version: 7.27.1 - resolution: "@babel/plugin-transform-regenerator@npm:7.27.1" +"@babel/plugin-transform-regenerator@npm:^7.24.7, @babel/plugin-transform-regenerator@npm:^7.28.4": + version: 7.28.4 + resolution: "@babel/plugin-transform-regenerator@npm:7.28.4" dependencies: "@babel/helper-plugin-utils": ^7.27.1 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: e1e28e08abf1c8fcdeaa8af5ab44cfda83bebc0ba6ebc155afdae243c51a2e941dd8ff6c51affb0447deb07a6bc66424fbf04482b050c061e272bc75c15853bf + checksum: 2aa99b3a7b254a109e913fabbe1fb320ff40723988fde0e225212b7ef20f523a399a6e45077258b176c29715493b2a853cf7c130811692215adf33e5af99782b languageName: node linkType: hard @@ -1194,18 +1205,18 @@ __metadata: linkType: hard "@babel/plugin-transform-runtime@npm:^7.24.7": - version: 7.27.1 - resolution: "@babel/plugin-transform-runtime@npm:7.27.1" + version: 7.28.5 + resolution: "@babel/plugin-transform-runtime@npm:7.28.5" dependencies: "@babel/helper-module-imports": ^7.27.1 "@babel/helper-plugin-utils": ^7.27.1 - babel-plugin-polyfill-corejs2: ^0.4.10 - babel-plugin-polyfill-corejs3: ^0.11.0 - babel-plugin-polyfill-regenerator: ^0.6.1 + babel-plugin-polyfill-corejs2: ^0.4.14 + babel-plugin-polyfill-corejs3: ^0.13.0 + babel-plugin-polyfill-regenerator: ^0.6.5 semver: ^6.3.1 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 9328060b54e430732883cac672cfd4c952c2bf2d9fb5268c675ae01f74ccb224ecdf105f5ad52b6277ad8b34b6df1e7cec6d1c02a0d17be54414265414e8ac88 + checksum: 5bb66f366c5bb22d0c890667ecd0f1fde9db86ac04df62b21fc2bbf58531eb84068bb0bf38fb1c496c8f78a917c59a884f6c1f8b205b8689d155e72fcf1d442d languageName: node linkType: hard @@ -1276,18 +1287,18 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-transform-typescript@npm:^7.25.2, @babel/plugin-transform-typescript@npm:^7.27.1": - version: 7.27.1 - resolution: "@babel/plugin-transform-typescript@npm:7.27.1" +"@babel/plugin-transform-typescript@npm:^7.25.2, @babel/plugin-transform-typescript@npm:^7.28.5": + version: 7.28.5 + resolution: "@babel/plugin-transform-typescript@npm:7.28.5" dependencies: - "@babel/helper-annotate-as-pure": ^7.27.1 - "@babel/helper-create-class-features-plugin": ^7.27.1 + "@babel/helper-annotate-as-pure": ^7.27.3 + "@babel/helper-create-class-features-plugin": ^7.28.5 "@babel/helper-plugin-utils": ^7.27.1 "@babel/helper-skip-transparent-expression-wrappers": ^7.27.1 "@babel/plugin-syntax-typescript": ^7.27.1 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 0037db32fedaacf42b5b3df774263bb7176d455859f77322f57135f7e50e457e5c95151280fc83bb9942fc1839e785489b098d73c9539d0f3c7dc9d42b3a8e86 + checksum: 202785e9cc6fb04efba091b3d5560cc8089cdc54df12fafa3d32ed7089e8d7a95b92b2fb1b53ec3e4db3bbafe56e8b32a3530cac004b3e493e902def8666001d languageName: node linkType: hard @@ -1339,61 +1350,62 @@ __metadata: linkType: hard "@babel/preset-env@npm:^7.25.2, @babel/preset-env@npm:^7.25.3": - version: 7.27.2 - resolution: "@babel/preset-env@npm:7.27.2" + version: 7.28.5 + resolution: "@babel/preset-env@npm:7.28.5" dependencies: - "@babel/compat-data": ^7.27.2 + "@babel/compat-data": ^7.28.5 "@babel/helper-compilation-targets": ^7.27.2 "@babel/helper-plugin-utils": ^7.27.1 "@babel/helper-validator-option": ^7.27.1 - "@babel/plugin-bugfix-firefox-class-in-computed-class-key": ^7.27.1 + "@babel/plugin-bugfix-firefox-class-in-computed-class-key": ^7.28.5 "@babel/plugin-bugfix-safari-class-field-initializer-scope": ^7.27.1 "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": ^7.27.1 "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": ^7.27.1 - "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": ^7.27.1 + "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": ^7.28.3 "@babel/plugin-proposal-private-property-in-object": 7.21.0-placeholder-for-preset-env.2 "@babel/plugin-syntax-import-assertions": ^7.27.1 "@babel/plugin-syntax-import-attributes": ^7.27.1 "@babel/plugin-syntax-unicode-sets-regex": ^7.18.6 "@babel/plugin-transform-arrow-functions": ^7.27.1 - "@babel/plugin-transform-async-generator-functions": ^7.27.1 + "@babel/plugin-transform-async-generator-functions": ^7.28.0 "@babel/plugin-transform-async-to-generator": ^7.27.1 "@babel/plugin-transform-block-scoped-functions": ^7.27.1 - "@babel/plugin-transform-block-scoping": ^7.27.1 + "@babel/plugin-transform-block-scoping": ^7.28.5 "@babel/plugin-transform-class-properties": ^7.27.1 - "@babel/plugin-transform-class-static-block": ^7.27.1 - "@babel/plugin-transform-classes": ^7.27.1 + "@babel/plugin-transform-class-static-block": ^7.28.3 + "@babel/plugin-transform-classes": ^7.28.4 "@babel/plugin-transform-computed-properties": ^7.27.1 - "@babel/plugin-transform-destructuring": ^7.27.1 + "@babel/plugin-transform-destructuring": ^7.28.5 "@babel/plugin-transform-dotall-regex": ^7.27.1 "@babel/plugin-transform-duplicate-keys": ^7.27.1 "@babel/plugin-transform-duplicate-named-capturing-groups-regex": ^7.27.1 "@babel/plugin-transform-dynamic-import": ^7.27.1 - "@babel/plugin-transform-exponentiation-operator": ^7.27.1 + "@babel/plugin-transform-explicit-resource-management": ^7.28.0 + "@babel/plugin-transform-exponentiation-operator": ^7.28.5 "@babel/plugin-transform-export-namespace-from": ^7.27.1 "@babel/plugin-transform-for-of": ^7.27.1 "@babel/plugin-transform-function-name": ^7.27.1 "@babel/plugin-transform-json-strings": ^7.27.1 "@babel/plugin-transform-literals": ^7.27.1 - "@babel/plugin-transform-logical-assignment-operators": ^7.27.1 + "@babel/plugin-transform-logical-assignment-operators": ^7.28.5 "@babel/plugin-transform-member-expression-literals": ^7.27.1 "@babel/plugin-transform-modules-amd": ^7.27.1 "@babel/plugin-transform-modules-commonjs": ^7.27.1 - "@babel/plugin-transform-modules-systemjs": ^7.27.1 + "@babel/plugin-transform-modules-systemjs": ^7.28.5 "@babel/plugin-transform-modules-umd": ^7.27.1 "@babel/plugin-transform-named-capturing-groups-regex": ^7.27.1 "@babel/plugin-transform-new-target": ^7.27.1 "@babel/plugin-transform-nullish-coalescing-operator": ^7.27.1 "@babel/plugin-transform-numeric-separator": ^7.27.1 - "@babel/plugin-transform-object-rest-spread": ^7.27.2 + "@babel/plugin-transform-object-rest-spread": ^7.28.4 "@babel/plugin-transform-object-super": ^7.27.1 "@babel/plugin-transform-optional-catch-binding": ^7.27.1 - "@babel/plugin-transform-optional-chaining": ^7.27.1 - "@babel/plugin-transform-parameters": ^7.27.1 + "@babel/plugin-transform-optional-chaining": ^7.28.5 + "@babel/plugin-transform-parameters": ^7.27.7 "@babel/plugin-transform-private-methods": ^7.27.1 "@babel/plugin-transform-private-property-in-object": ^7.27.1 "@babel/plugin-transform-property-literals": ^7.27.1 - "@babel/plugin-transform-regenerator": ^7.27.1 + "@babel/plugin-transform-regenerator": ^7.28.4 "@babel/plugin-transform-regexp-modifiers": ^7.27.1 "@babel/plugin-transform-reserved-words": ^7.27.1 "@babel/plugin-transform-shorthand-properties": ^7.27.1 @@ -1406,14 +1418,14 @@ __metadata: "@babel/plugin-transform-unicode-regex": ^7.27.1 "@babel/plugin-transform-unicode-sets-regex": ^7.27.1 "@babel/preset-modules": 0.1.6-no-external-plugins - babel-plugin-polyfill-corejs2: ^0.4.10 - babel-plugin-polyfill-corejs3: ^0.11.0 - babel-plugin-polyfill-regenerator: ^0.6.1 - core-js-compat: ^3.40.0 + babel-plugin-polyfill-corejs2: ^0.4.14 + babel-plugin-polyfill-corejs3: ^0.13.0 + babel-plugin-polyfill-regenerator: ^0.6.5 + core-js-compat: ^3.43.0 semver: ^6.3.1 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 318b123c8783ac3833bde5a5ff315970967ccd4c1e5c97e0843c0199fe9eab48a8cb40b367b784ae19a33667bee63eb8533eb924dab05bfc92ff9ef436109001 + checksum: 9e17ba89c5d8cbea0fde564ea29e6dc17ad43f6ebf1c11347af69a04cf69dbc62c3124d2afe46412bfa41dddde3aaabfeffc0d68bed96f6ea0c4d8fbf652e761 languageName: node linkType: hard @@ -1431,44 +1443,44 @@ __metadata: linkType: hard "@babel/preset-react@npm:^7.24.7": - version: 7.27.1 - resolution: "@babel/preset-react@npm:7.27.1" + version: 7.28.5 + resolution: "@babel/preset-react@npm:7.28.5" dependencies: "@babel/helper-plugin-utils": ^7.27.1 "@babel/helper-validator-option": ^7.27.1 - "@babel/plugin-transform-react-display-name": ^7.27.1 + "@babel/plugin-transform-react-display-name": ^7.28.0 "@babel/plugin-transform-react-jsx": ^7.27.1 "@babel/plugin-transform-react-jsx-development": ^7.27.1 "@babel/plugin-transform-react-pure-annotations": ^7.27.1 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 00bc146f9c742eed804c598d3f31b7d889c1baf8c768989b7f84a93ca527dd1518d3b86781e89ca45cae6dbee136510d3a121658e01416c5578aecf751517bb5 + checksum: 13bc1fe4dde0a29d00323e46749e5beb457844507cb3afa2fefbd85d283c2d4836f9e4a780be735de58a44c505870476dc2838f1f8faf9d6f056481e65f1a0fb languageName: node linkType: hard "@babel/preset-typescript@npm:^7.24.7": - version: 7.27.1 - resolution: "@babel/preset-typescript@npm:7.27.1" + version: 7.28.5 + resolution: "@babel/preset-typescript@npm:7.28.5" dependencies: "@babel/helper-plugin-utils": ^7.27.1 "@babel/helper-validator-option": ^7.27.1 "@babel/plugin-syntax-jsx": ^7.27.1 "@babel/plugin-transform-modules-commonjs": ^7.27.1 - "@babel/plugin-transform-typescript": ^7.27.1 + "@babel/plugin-transform-typescript": ^7.28.5 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 38020f1b23e88ec4fbffd5737da455d8939244bddfb48a2516aef93fb5947bd9163fb807ce6eff3e43fa5ffe9113aa131305fef0fb5053998410bbfcfe6ce0ec + checksum: 22f889835d9db1e627846e71ca2f02e2d24e2eb9ebcf9845b3b1d37bd3a53787967bafabbbcb342f06aaf7627399a7102ba6ca18f9a0e17066c865d680d2ceb9 languageName: node linkType: hard -"@babel/runtime@npm:^7.25.0": - version: 7.27.1 - resolution: "@babel/runtime@npm:7.27.1" - checksum: 11339838a54783e5b14e04d94d7a4d032e9965c5823f3f687e41556fa40344ae7aeb57c535720b7a74ab3e8217def7834a6f1a665ee55bbb3befede141419913 +"@babel/runtime@npm:^7.12.5, @babel/runtime@npm:^7.25.0": + version: 7.28.4 + resolution: "@babel/runtime@npm:7.28.4" + checksum: 934b0a0460f7d06637d93fcd1a44ac49adc33518d17253b5a0b55ff4cb90a45d8fe78bf034b448911dbec7aff2a90b918697559f78d21c99ff8dbadae9565b55 languageName: node linkType: hard -"@babel/template@npm:^7.0.0, @babel/template@npm:^7.25.0, @babel/template@npm:^7.27.1, @babel/template@npm:^7.3.3": +"@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" dependencies: @@ -1479,28 +1491,28 @@ __metadata: 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.27.1": - version: 7.27.1 - resolution: "@babel/traverse@npm:7.27.1" +"@babel/traverse--for-generate-function-map@npm:@babel/traverse@^7.25.3, @babel/traverse@npm:^7.25.3, @babel/traverse@npm:^7.27.1, @babel/traverse@npm:^7.28.0, @babel/traverse@npm:^7.28.3, @babel/traverse@npm:^7.28.4, @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.27.1 - "@babel/parser": ^7.27.1 - "@babel/template": ^7.27.1 - "@babel/types": ^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 - globals: ^11.1.0 - checksum: 7ea3ec36a65e734f2921f5dba6f417f5dd0c90eb44a60f6addbacbbedb44e8c82eba415a74feb7d6df58e351519b81b11b6ca3c0c7c41a3f73ebeaf6895a826c + 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.27.1, @babel/types@npm:^7.3.3, @babel/types@npm:^7.4.4": - version: 7.27.1 - resolution: "@babel/types@npm:7.27.1" +"@babel/types@npm:^7.0.0, @babel/types@npm:^7.20.7, @babel/types@npm:^7.25.2, @babel/types@npm:^7.27.1, @babel/types@npm:^7.27.3, @babel/types@npm:^7.28.2, @babel/types@npm:^7.28.4, @babel/types@npm:^7.28.5, @babel/types@npm:^7.3.3, @babel/types@npm:^7.4.4": + version: 7.28.5 + resolution: "@babel/types@npm:7.28.5" dependencies: "@babel/helper-string-parser": ^7.27.1 - "@babel/helper-validator-identifier": ^7.27.1 - checksum: 357c13f37aaa2f2e2cfcdb63f986d5f7abc9f38df20182b620ace34387d2460620415770fe5856eb54d70c9f0ba2f71230d29465e789188635a948476b830ae4 + "@babel/helper-validator-identifier": ^7.28.5 + checksum: 5bc266af9e55ff92f9ddf33d83a42c9de1a87f9579d0ed62ef94a741a081692dd410a4fbbab18d514b83e135083ff05bc0e37003834801c9514b9d8ad748070d languageName: node linkType: hard @@ -1729,60 +1741,64 @@ __metadata: languageName: node linkType: hard -"@eslint-community/eslint-utils@npm:^4.2.0, @eslint-community/eslint-utils@npm:^4.4.0": - version: 4.7.0 - resolution: "@eslint-community/eslint-utils@npm:4.7.0" +"@eslint-community/eslint-utils@npm:^4.2.0, @eslint-community/eslint-utils@npm:^4.4.0, @eslint-community/eslint-utils@npm:^4.8.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: b177e3b75c0b8d0e5d71f1c532edb7e40b31313db61f0c879f9bf19c3abb2783c6c372b5deb2396dab4432f2946b9972122ac682e77010376c029dfd0149c681 + 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" - checksum: 0d628680e204bc316d545b4993d3658427ca404ae646ce541fcc65306b8c712c340e5e573e30fb9f85f4855c0c5f6dca9868931f2fcced06417fbe1a0c6cd2d6 + version: 4.12.2 + resolution: "@eslint-community/regexpp@npm:4.12.2" + checksum: 1770bc81f676a72f65c7200b5675ff7a349786521f30e66125faaf767fde1ba1c19c3790e16ba8508a62a3933afcfc806a893858b3b5906faf693d862b9e4120 languageName: node linkType: hard "@eslint/compat@npm:^1.2.7": - version: 1.2.9 - resolution: "@eslint/compat@npm:1.2.9" + version: 1.4.1 + resolution: "@eslint/compat@npm:1.4.1" + dependencies: + "@eslint/core": ^0.17.0 peerDependencies: - eslint: ^9.10.0 + eslint: ^8.40 || 9 peerDependenciesMeta: eslint: optional: true - checksum: 5c1b792cba07caa274987517ed69461b9c91728021f65a49248bec41d3f715090c6d6266479d20b0aa646f269d5e58c9f7f4d9eeb086ec45caebc80e704d2378 + checksum: 2389344cf1fe6b34f14977cb449ab24214e3342cdf99fc045896bb1063343e6009765ee3ca0bf7b893e94b476bb569ddf4d5e79a957054a246d610355acbbb75 languageName: node linkType: hard -"@eslint/config-array@npm:^0.20.0": - version: 0.20.0 - resolution: "@eslint/config-array@npm:0.20.0" +"@eslint/config-array@npm:^0.21.1": + version: 0.21.1 + resolution: "@eslint/config-array@npm:0.21.1" dependencies: - "@eslint/object-schema": ^2.1.6 + "@eslint/object-schema": ^2.1.7 debug: ^4.3.1 minimatch: ^3.1.2 - checksum: 55824ea31f0502166a6fea97176c9c25089a0354474cdc72a5f739b1cf6925f44f667bf8f4f3a9dabf1112ab0fa671778ca3f96f1499f31ec42caf84cae55005 + checksum: fc5b57803b059f7c1f62950ef83baf045a01887fc00551f9e87ac119246fcc6d71c854a7f678accc79cbf829ed010e8135c755a154b0f54b129c538950cd7e6a languageName: node linkType: hard -"@eslint/config-helpers@npm:^0.2.1": - version: 0.2.2 - resolution: "@eslint/config-helpers@npm:0.2.2" - checksum: 8a4091a2c8af5366513647ccad720f184c1b723f04c086755797a3a5cac69dc9013bc8a75453d9fc188fc4364460f0eae9f1584b77b28082e0d26bf48356ae8f +"@eslint/config-helpers@npm:^0.4.2": + version: 0.4.2 + resolution: "@eslint/config-helpers@npm:0.4.2" + dependencies: + "@eslint/core": ^0.17.0 + checksum: 63ff6a0730c9fff2edb80c89b39b15b28d6a635a1c3f32cf0d7eb3e2625f2efbc373c5531ae84e420ae36d6e37016dd40c365b6e5dee6938478e9907aaadae0b languageName: node linkType: hard -"@eslint/core@npm:^0.14.0": - version: 0.14.0 - resolution: "@eslint/core@npm:0.14.0" +"@eslint/core@npm:^0.17.0": + version: 0.17.0 + resolution: "@eslint/core@npm:0.17.0" dependencies: "@types/json-schema": ^7.0.15 - checksum: d68b8282b6f38c5145234f812f18f491d12d716240875591bd54bf5ac32858d979bdf6d38e521997a6e01f2c4223a3e66049714151da7278d0a95ff15b5d46c8 + checksum: ff9b5b4987f0bae4f2a4cfcdc7ae584ad3b0cb58526ca562fb281d6837700a04c7f3c86862e95126462318f33f60bf38e1cb07ed0e2449532d4b91cd5f4ab1f2 languageName: node linkType: hard @@ -1803,36 +1819,36 @@ __metadata: languageName: node linkType: hard -"@eslint/js@npm:9.27.0, @eslint/js@npm:^9.22.0": - version: 9.27.0 - resolution: "@eslint/js@npm:9.27.0" - checksum: b31cfd61bb64e187f8758d13c893bf710f0500c29ced5dd6958c4fda254059489f1cee69567c20ba21608ce51224019b1fd10975b09d41adf16616d875da6ea4 +"@eslint/js@npm:9.39.1, @eslint/js@npm:^9.22.0": + version: 9.39.1 + resolution: "@eslint/js@npm:9.39.1" + checksum: b651930aec03a5aef97bc144627aebb05070afec5364cd3c5fd7c5dbb97f4fd82faf1b200b3be17572d5ebb7f8805211b655f463be96f2b02202ec7250868048 languageName: node linkType: hard -"@eslint/object-schema@npm:^2.1.6": - version: 2.1.6 - resolution: "@eslint/object-schema@npm:2.1.6" - checksum: e32e565319f6544d36d3fa69a3e163120722d12d666d1a4525c9a6f02e9b54c29d9b1f03139e25d7e759e08dda8da433590bc23c09db8d511162157ef1b86a4c +"@eslint/object-schema@npm:^2.1.7": + version: 2.1.7 + resolution: "@eslint/object-schema@npm:2.1.7" + checksum: fc5708f192476956544def13455d60fd1bafbf8f062d1e05ec5c06dd470b02078eaf721e696a8b31c1c45d2056723a514b941ae5eea1398cc7e38eba6711a775 languageName: node linkType: hard -"@eslint/plugin-kit@npm:^0.3.1": - version: 0.3.1 - resolution: "@eslint/plugin-kit@npm:0.3.1" +"@eslint/plugin-kit@npm:^0.4.1": + version: 0.4.1 + resolution: "@eslint/plugin-kit@npm:0.4.1" dependencies: - "@eslint/core": ^0.14.0 + "@eslint/core": ^0.17.0 levn: ^0.4.1 - checksum: 8de2438456d9a741c909dd22a60454793c0147e1a13833717e4109c46f5a6b090780e8d9e940a3b3b9bf3643d01a0e726cc74f28ccd7caac95053bb39c2e6c04 + checksum: 3f4492e02a3620e05d46126c5cfeff5f651ecf33466c8f88efb4812ae69db5f005e8c13373afabc070ecca7becd319b656d6670ad5093f05ca63c2a8841d99ba languageName: node linkType: hard "@evilmartians/lefthook@npm:^1.5.0": - version: 1.11.13 - resolution: "@evilmartians/lefthook@npm:1.11.13" + version: 1.13.6 + resolution: "@evilmartians/lefthook@npm:1.13.6" bin: lefthook: bin/index.js - checksum: 94d85f52e85c80094f0128e76ae18785e7d7b4950a11de1203f33d9deea14964c86db04d4d6f673ff96cd36d9376d4f231758e8afcce4caf06efdb5552c20a03 + checksum: 6cceca3e874015678f50818ae14a74d959816cfaba6638f8852d007332404d6819b15c71538985a3650a1ef057aa6975c17fadfe43ece7a0da1aeb9faaf02946 conditions: (os=darwin | os=linux | os=win32) & (cpu=x64 | cpu=arm64 | cpu=ia32) languageName: node linkType: hard @@ -1861,12 +1877,12 @@ __metadata: linkType: hard "@humanfs/node@npm:^0.16.6": - version: 0.16.6 - resolution: "@humanfs/node@npm:0.16.6" + version: 0.16.7 + resolution: "@humanfs/node@npm:0.16.7" dependencies: "@humanfs/core": ^0.19.1 - "@humanwhocodes/retry": ^0.3.0 - checksum: f9cb52bb235f8b9c6fcff43a7e500669a38f8d6ce26593404a9b56365a1644e0ed60c720dc65ff6a696b1f85f3563ab055bb554ec8674f2559085ba840e47710 + "@humanwhocodes/retry": ^0.4.0 + checksum: 7d2a396a94d80158ce320c0fd7df9aebb82edb8b667e5aaf8f87f4ca50518d0941ca494e0cd68e06b061e777ce5f7d26c45f93ac3fa9f7b11fd1ff26e3cd1440 languageName: node linkType: hard @@ -1877,14 +1893,7 @@ __metadata: languageName: node linkType: hard -"@humanwhocodes/retry@npm:^0.3.0": - version: 0.3.1 - resolution: "@humanwhocodes/retry@npm:0.3.1" - checksum: 7e5517bb51dbea3e02ab6cacef59a8f4b0ca023fc4b0b8cbc40de0ad29f46edd50b897c6e7fba79366a0217e3f48e2da8975056f6c35cfe19d9cc48f1d03c1dd - languageName: node - linkType: hard - -"@humanwhocodes/retry@npm:^0.4.2": +"@humanwhocodes/retry@npm:^0.4.0, @humanwhocodes/retry@npm:^0.4.2": version: 0.4.3 resolution: "@humanwhocodes/retry@npm:0.4.3" checksum: d423455b9d53cf01f778603404512a4246fb19b83e74fe3e28c70d9a80e9d4ae147d2411628907ca983e91a855a52535859a8bb218050bc3f6dbd7a553b7b442 @@ -1906,9 +1915,9 @@ __metadata: linkType: hard "@inquirer/figures@npm:^1.0.3": - version: 1.0.11 - resolution: "@inquirer/figures@npm:1.0.11" - checksum: 6be2867050f5c179d9fcc389a4a3e9aca6ac45fd02106918eba2d6c27a7251a48693ac13fcf9f084e25bf963eb51045c23ca9e87c523e318b0e286d4173449a9 + version: 1.0.14 + resolution: "@inquirer/figures@npm:1.0.14" + checksum: 37eec986f119eabb6c231c8c1481c6a48ab2347e9f57b2d6442161f7b83936678221fccb7ead60582026c2ae20d457467d0727c485ff53aee2cf965077b0f51b languageName: node linkType: hard @@ -2042,6 +2051,13 @@ __metadata: languageName: node linkType: hard +"@jest/diff-sequences@npm:30.0.1": + version: 30.0.1 + resolution: "@jest/diff-sequences@npm:30.0.1" + checksum: e5f931ca69c15a9b3a9b23b723f51ffc97f031b2f3ca37f901333dab99bd4dfa1ad4192a5cd893cd1272f7602eb09b9cfb5fc6bb62a0232c96fb8b5e96094970 + languageName: node + linkType: hard + "@jest/environment@npm:^29.7.0": version: 29.7.0 resolution: "@jest/environment@npm:29.7.0" @@ -2087,6 +2103,13 @@ __metadata: languageName: node linkType: hard +"@jest/get-type@npm:30.1.0": + version: 30.1.0 + resolution: "@jest/get-type@npm:30.1.0" + checksum: e2a95fbb49ce2d15547db8af5602626caf9b05f62a5e583b4a2de9bd93a2bfe7175f9bbb2b8a5c3909ce261d467b6991d7265bb1d547cb60e7e97f571f361a70 + languageName: node + linkType: hard + "@jest/globals@npm:^29.7.0": version: 29.7.0 resolution: "@jest/globals@npm:29.7.0" @@ -2136,6 +2159,15 @@ __metadata: languageName: node linkType: hard +"@jest/schemas@npm:30.0.5": + version: 30.0.5 + resolution: "@jest/schemas@npm:30.0.5" + dependencies: + "@sinclair/typebox": ^0.34.0 + checksum: 7a4fc4166f688947c22d81e61aaf2cb22f178dbf6ee806b0931b75136899d426a72a8330762f27f0cf6f79da0d2a56f49a22fe09f5f80df95a683ed237a0f3b0 + languageName: node + linkType: hard + "@jest/schemas@npm:^29.6.3": version: 29.6.3 resolution: "@jest/schemas@npm:29.6.3" @@ -2230,14 +2262,23 @@ __metadata: languageName: node linkType: hard -"@jridgewell/gen-mapping@npm:^0.3.5": - version: 0.3.8 - resolution: "@jridgewell/gen-mapping@npm:0.3.8" +"@jridgewell/gen-mapping@npm:^0.3.12, @jridgewell/gen-mapping@npm:^0.3.5": + version: 0.3.13 + resolution: "@jridgewell/gen-mapping@npm:0.3.13" dependencies: - "@jridgewell/set-array": ^1.2.1 - "@jridgewell/sourcemap-codec": ^1.4.10 + "@jridgewell/sourcemap-codec": ^1.5.0 "@jridgewell/trace-mapping": ^0.3.24 - checksum: c0687b5227461717aa537fe71a42e356bcd1c43293b3353796a148bf3b0d6f59109def46c22f05b60e29a46f19b2e4676d027959a7c53a6c92b9d5b0d87d0420 + checksum: f2105acefc433337145caa3c84bba286de954f61c0bc46279bbd85a9e6a02871089717fa060413cfb6a9d44189fe8313b2d1cabf3a2eb3284d208fd5f75c54ff + 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 @@ -2248,37 +2289,30 @@ __metadata: languageName: node linkType: hard -"@jridgewell/set-array@npm:^1.2.1": - version: 1.2.1 - resolution: "@jridgewell/set-array@npm:1.2.1" - checksum: 832e513a85a588f8ed4f27d1279420d8547743cc37fcad5a5a76fc74bb895b013dfe614d0eed9cb860048e6546b798f8f2652020b4b2ba0561b05caa8c654b10 - languageName: node - linkType: hard - "@jridgewell/source-map@npm:^0.3.3": - version: 0.3.6 - resolution: "@jridgewell/source-map@npm:0.3.6" + version: 0.3.11 + resolution: "@jridgewell/source-map@npm:0.3.11" dependencies: "@jridgewell/gen-mapping": ^0.3.5 "@jridgewell/trace-mapping": ^0.3.25 - checksum: c9dc7d899397df95e3c9ec287b93c0b56f8e4453cd20743e2b9c8e779b1949bc3cccf6c01bb302779e46560eb45f62ea38d19fedd25370d814734268450a9f30 + checksum: c8a0011cc67e701f270fa042e32b312f382c413bcc70ca9c03684687cbf5b64d5eed87d4afa36dddaabe60ab3da6db4935f878febd9cfc7f82724ea1a114d344 languageName: node linkType: hard -"@jridgewell/sourcemap-codec@npm:^1.4.10, @jridgewell/sourcemap-codec@npm:^1.4.14": - version: 1.5.0 - resolution: "@jridgewell/sourcemap-codec@npm:1.5.0" - checksum: 05df4f2538b3b0f998ea4c1cd34574d0feba216fa5d4ccaef0187d12abf82eafe6021cec8b49f9bb4d90f2ba4582ccc581e72986a5fcf4176ae0cfeb04cf52ec +"@jridgewell/sourcemap-codec@npm:^1.4.14, @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" +"@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, @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: 9d3c40d225e139987b50c48988f8717a54a8c994d8a948ee42e1412e08988761d0754d7d10b803061cc3aebf35f92a5dbbab493bd0e1a9ef9e89a2130e83ba34 + checksum: af8fda2431348ad507fbddf8e25f5d08c79ecc94594061ce402cf41bc5aba1a7b3e59bf0fd70a619b35f33983a3f488ceeba8faf56bff784f98bb5394a8b7d47 languageName: node linkType: hard @@ -2348,8 +2382,8 @@ __metadata: linkType: hard "@octokit/core@npm:^5.0.2": - version: 5.2.1 - resolution: "@octokit/core@npm:5.2.1" + version: 5.2.2 + resolution: "@octokit/core@npm:5.2.2" dependencies: "@octokit/auth-token": ^4.0.0 "@octokit/graphql": ^7.1.0 @@ -2358,7 +2392,7 @@ __metadata: "@octokit/types": ^13.0.0 before-after-hook: ^2.2.0 universal-user-agent: ^6.0.0 - checksum: a7076095ec1109bb9273764a2b561b323368e96ea2c1257cef1d48107fe6493f363cfa84539da2d182b065831667c1baa85b00e99712079e299e06b46ba8693b + checksum: d4303d808c6b8eca32ce03381db5f6230440c1c6cfd9d73376ed583973094abd8ca56d9a64d490e6b0045f827a8f913b619bd90eae99c2cba682487720dc8002 languageName: node linkType: hard @@ -2472,10 +2506,10 @@ __metadata: languageName: node linkType: hard -"@pkgr/core@npm:^0.2.4": - version: 0.2.4 - resolution: "@pkgr/core@npm:0.2.4" - checksum: 8544f0346c3f7035b9e2fdf60179c68b12d3c76b3fba9533844099af67cf5c0ce5257538f5faa05953d48cc1536d046f003231f321b2f75b3fb449db8410a2b7 +"@pkgr/core@npm:^0.2.9": + version: 0.2.9 + resolution: "@pkgr/core@npm:0.2.9" + checksum: bb2fb86977d63f836f8f5b09015d74e6af6488f7a411dcd2bfdca79d76b5a681a9112f41c45bdf88a9069f049718efc6f3900d7f1de66a2ec966068308ae517f languageName: node linkType: hard @@ -2684,6 +2718,16 @@ __metadata: languageName: node linkType: hard +"@react-native-picker/picker@npm:^2.11.4": + version: 2.11.4 + resolution: "@react-native-picker/picker@npm:2.11.4" + peerDependencies: + react: "*" + react-native: "*" + checksum: 03c34770ce137a149f2aea54cef38fa871df2d5207089d7041c12beff20d1ca4340eb3fa8aed09e1a7d5899c813187cf5c217571789482061fee5e4e4a0e4e34 + languageName: node + linkType: hard + "@react-native/assets-registry@npm:0.79.2": version: 0.79.2 resolution: "@react-native/assets-registry@npm:0.79.2" @@ -2819,12 +2863,12 @@ __metadata: linkType: hard "@react-native/eslint-config@npm:^0.78.0": - version: 0.78.2 - resolution: "@react-native/eslint-config@npm:0.78.2" + version: 0.78.3 + resolution: "@react-native/eslint-config@npm:0.78.3" dependencies: "@babel/core": ^7.25.2 "@babel/eslint-parser": ^7.25.1 - "@react-native/eslint-plugin": 0.78.2 + "@react-native/eslint-plugin": 0.78.3 "@typescript-eslint/eslint-plugin": ^7.1.1 "@typescript-eslint/parser": ^7.1.1 eslint-config-prettier: ^8.5.0 @@ -2837,14 +2881,14 @@ __metadata: peerDependencies: eslint: ">=8" prettier: ">=2" - checksum: 4cbdf40717a3f51432f685364ad81a2fd8bf7746d9dcb1e285900ddafdea777b058c931daf2a23916f909498ae756f0f1baab4636596a90653cd9a0e59ac9b84 + checksum: 92aaa23067b99ed6783f28ff51d7e39b8e7363b173d5a449ecb101b84913ea6224649a76729eb805ab9003843d2ce674acf61db14dc95475b9070748a382386f languageName: node linkType: hard -"@react-native/eslint-plugin@npm:0.78.2": - version: 0.78.2 - resolution: "@react-native/eslint-plugin@npm:0.78.2" - checksum: d79285f702e25e467525cb55ae824c50c7333138cce1295b4a1c046f11c68e7bd43ffa0c78fb0e5b1a59be92a5cf44e59c2bfc16e6c2e5b2550ea251f3cb65c6 +"@react-native/eslint-plugin@npm:0.78.3": + version: 0.78.3 + resolution: "@react-native/eslint-plugin@npm:0.78.3" + checksum: b14a613641a2f79db83268661aa2bf82ab97cf13c6a00e30745d7c689d4b3551b05109d1fe833b58659b728b411b37255f221d9a91d9cd58f2badbc68c4bdcec languageName: node linkType: hard @@ -2919,80 +2963,83 @@ __metadata: languageName: node linkType: hard -"@react-navigation/core@npm:^7.9.2": - version: 7.9.2 - resolution: "@react-navigation/core@npm:7.9.2" +"@react-navigation/core@npm:^7.13.0": + version: 7.13.0 + resolution: "@react-navigation/core@npm:7.13.0" dependencies: - "@react-navigation/routers": ^7.3.7 + "@react-navigation/routers": ^7.5.1 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.3 + use-latest-callback: ^0.2.4 use-sync-external-store: ^1.5.0 peerDependencies: react: ">= 18.2.0" - checksum: 346040b232b8e9dae6930cc8dd306020d3c6779d0aaf704947ca7279b7862aa0fc2e91abdcd8cc25b373d98435d787149539ca86e314317e7a5465df1e640239 + checksum: e6c99df003b274aacd9c39121ad5497574efb316af6b584b739ff134fc39726b59825245a6afdea62100fa51622af78c431907112d07f62e6e3a9c8d16332023 languageName: node linkType: hard -"@react-navigation/elements@npm:^2.4.2": - version: 2.4.2 - resolution: "@react-navigation/elements@npm:2.4.2" +"@react-navigation/elements@npm:^2.8.1": + version: 2.8.1 + resolution: "@react-navigation/elements@npm:2.8.1" 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.9 + "@react-navigation/native": ^7.1.19 react: ">= 18.2.0" react-native: "*" react-native-safe-area-context: ">= 4.0.0" peerDependenciesMeta: "@react-native-masked-view/masked-view": optional: true - checksum: 5fee0e6601d50512256028c5de9da924ab17e5edbdfbf84963c1e95b0a3da05eb09aa753111453f3a9701b7d123dbb14c2ce2bff888ec9488fcc893872e2e079 + checksum: 82e2d4ae99ef0dad3f8a8a70fe8678d7ee41e4e216859ec78e720a0816efdb370940ccbfc7f75874fcd98207336b09cbc44e6a4d38192f7474ef330052bb9195 languageName: node linkType: hard "@react-navigation/native@npm:^7.1.9": - version: 7.1.9 - resolution: "@react-navigation/native@npm:7.1.9" + version: 7.1.19 + resolution: "@react-navigation/native@npm:7.1.19" dependencies: - "@react-navigation/core": ^7.9.2 + "@react-navigation/core": ^7.13.0 escape-string-regexp: ^4.0.0 fast-deep-equal: ^3.1.3 nanoid: ^3.3.11 - use-latest-callback: ^0.2.3 + use-latest-callback: ^0.2.4 peerDependencies: react: ">= 18.2.0" react-native: "*" - checksum: 3dd504d6d7c4482612c48909754d051a68b36d5d7cdf1ae610333da99c1309e194b65cd4e79ed343dd12cbbb55a3fb856453830d6cb45b54f6f3fe88464667cd + checksum: 3215388017fef5ec6ecca19a128ef11d8b535f7534bfff15f931773b6849b2ee4ed0914c69eb264132e597700368df97d8991cf19d84f7d18ef1a0abd3ec6db6 languageName: node linkType: hard -"@react-navigation/routers@npm:^7.3.7": - version: 7.3.7 - resolution: "@react-navigation/routers@npm:7.3.7" +"@react-navigation/routers@npm:^7.5.1": + version: 7.5.1 + resolution: "@react-navigation/routers@npm:7.5.1" dependencies: nanoid: ^3.3.11 - checksum: cc3fb52957220adb8486c5546c78e4a9a92863f44368e5aeec74e6d3a31a9930d24e0cf022d91a7074a8e7d779690e11994f8f1254aaf0035d0d55b1656d8a3f + checksum: 49f04894f7e8b8e2c16abb96bbc1a9775a02341bb00fb9c0d9ce97f8d82613c27570921f2b854f8fd1639c29309df05345aa734124d48bdbcb5a934055b8af12 languageName: node linkType: hard "@react-navigation/stack@npm:^7.3.2": - version: 7.3.2 - resolution: "@react-navigation/stack@npm:7.3.2" + version: 7.6.2 + resolution: "@react-navigation/stack@npm:7.6.2" dependencies: - "@react-navigation/elements": ^2.4.2 + "@react-navigation/elements": ^2.8.1 color: ^4.2.3 peerDependencies: - "@react-navigation/native": ^7.1.9 + "@react-navigation/native": ^7.1.19 react: ">= 18.2.0" react-native: "*" react-native-gesture-handler: ">= 2.0.0" react-native-safe-area-context: ">= 4.0.0" react-native-screens: ">= 4.0.0" - checksum: 418c86f5b24915a834e9fbf9bb3603967058ae70d3cfcc9f8be17770e0a56fe78518e3ff421f224014608f2d272c04fe45b7b4532c998cb6fac0f1c9bb1c08c9 + checksum: 4b9fa85d3c6f34aa645af1e497ff9005142998fbad2a0891ed4bb8f266148581235ac172081d38729ab2b7ba3138706d7df165ae0f6da2c2be0a6be83ef2e2ec languageName: node linkType: hard @@ -3041,6 +3088,13 @@ __metadata: languageName: node linkType: hard +"@sinclair/typebox@npm:^0.34.0": + version: 0.34.41 + resolution: "@sinclair/typebox@npm:0.34.41" + checksum: dbcfdc55caef47ef5b728c2bc6979e50d00ee943b63eaaf604551be9a039187cdd256d810b790e61fdf63131df54b236149aef739d83bfe9a594a9863ac28115 + languageName: node + linkType: hard + "@sindresorhus/merge-streams@npm:^2.1.0": version: 2.3.0 resolution: "@sindresorhus/merge-streams@npm:2.3.0" @@ -3066,6 +3120,48 @@ __metadata: languageName: node linkType: hard +"@testing-library/react-hooks@npm:^8.0.1": + version: 8.0.1 + resolution: "@testing-library/react-hooks@npm:8.0.1" + dependencies: + "@babel/runtime": ^7.12.5 + react-error-boundary: ^3.1.0 + peerDependencies: + "@types/react": ^16.9.0 || ^17.0.0 + react: ^16.9.0 || ^17.0.0 + react-dom: ^16.9.0 || ^17.0.0 + react-test-renderer: ^16.9.0 || ^17.0.0 + peerDependenciesMeta: + "@types/react": + optional: true + react-dom: + optional: true + react-test-renderer: + optional: true + checksum: 7fe44352e920deb5cb1876f80d64e48615232072c9d5382f1e0284b3aab46bb1c659a040b774c45cdf084a5257b8fe463f7e08695ad8480d8a15635d4d3d1f6d + languageName: node + linkType: hard + +"@testing-library/react-native@npm:^13.3.3": + version: 13.3.3 + resolution: "@testing-library/react-native@npm:13.3.3" + dependencies: + jest-matcher-utils: ^30.0.5 + picocolors: ^1.1.1 + pretty-format: ^30.0.5 + redent: ^3.0.0 + peerDependencies: + jest: ">=29.0.0" + react: ">=18.2.0" + react-native: ">=0.71" + react-test-renderer: ">=18.2.0" + peerDependenciesMeta: + jest: + optional: true + checksum: 5688918384ce834e3667a56b72c8b776a2f9a5afae0a2738e7d0077f342b3ade7eca628cbe122943201caee75f3718379ef7b3ca00cd50c4ee607b4131d09505 + languageName: node + linkType: hard + "@tootallnate/quickjs-emscripten@npm:^0.23.0": version: 0.23.0 resolution: "@tootallnate/quickjs-emscripten@npm:0.23.0" @@ -3117,27 +3213,27 @@ __metadata: linkType: hard "@types/babel__traverse@npm:*, @types/babel__traverse@npm:^7.0.6": - version: 7.20.7 - resolution: "@types/babel__traverse@npm:7.20.7" + version: 7.28.0 + resolution: "@types/babel__traverse@npm:7.28.0" dependencies: - "@babel/types": ^7.20.7 - checksum: 2a2e5ad29c34a8b776162b0fe81c9ccb6459b2b46bf230f756ba0276a0258fcae1cbcfdccbb93a1e8b1df44f4939784ee8a1a269f95afe0c78b24b9cb6d50dd1 + "@babel/types": ^7.28.2 + checksum: e3124e6575b2f70de338eab8a9c704d315a86c46a8e395b6ec78a0157ab7b5fd877289556a57dcf28e4ff3543714e359cc1182d4afc4bcb4f3575a0bbafa0dad languageName: node linkType: hard "@types/conventional-commits-parser@npm:^5.0.0": - version: 5.0.1 - resolution: "@types/conventional-commits-parser@npm:5.0.1" + version: 5.0.2 + resolution: "@types/conventional-commits-parser@npm:5.0.2" dependencies: "@types/node": "*" - checksum: b4eb4f22051d42e7ed9fd3bffe6ea0cf62ae493a3c6c775a16babbad977c934f4c09ec3fa93020894de2073d63cfcd3a27dd5f00984966161da6797dd88a0f0d + checksum: bd05e0f0619737c6bb7e663e6274adf41f7c7d5742ec297b4b6095b3dcf328f81dab60668ba38cf51aff83c6e8135666b418e533ce4a2724053f40b82a5d4ca9 languageName: node linkType: hard "@types/estree@npm:^1.0.6": - version: 1.0.7 - resolution: "@types/estree@npm:1.0.7" - checksum: d9312b7075bdd08f3c9e1bb477102f5458aaa42a8eec31a169481ce314ca99ac716645cff4fca81ea65a2294b0276a0de63159d1baca0f8e7b5050a92de950ad + version: 1.0.8 + resolution: "@types/estree@npm:1.0.8" + checksum: bd93e2e415b6f182ec4da1074e1f36c480f1d26add3e696d54fb30c09bc470897e41361c8fd957bf0985024f8fbf1e6e2aff977d79352ef7eb93a5c6dcff6c11 languageName: node linkType: hard @@ -3207,11 +3303,11 @@ __metadata: linkType: hard "@types/node@npm:*": - version: 22.15.20 - resolution: "@types/node@npm:22.15.20" + version: 24.10.0 + resolution: "@types/node@npm:24.10.0" dependencies: - undici-types: ~6.21.0 - checksum: e672d7c630c3ade5988e7933dabe06b7a98648764e84023a345aecf6f810adb049637b392bdfe00b3773ef2cc905da87e9e43b5fceddd064a4a93c0da2ad3b64 + undici-types: ~7.16.0 + checksum: 268c843faae02ba88be2441759c26e73038583a7e221fa3000f2c1d7fdc1d06b28cb514fc5367f7cb147c3519cd25ddafdfa1f8566829b91fb096262ebe3f7bb languageName: node linkType: hard @@ -3223,18 +3319,18 @@ __metadata: linkType: hard "@types/react@npm:^19.0.0": - version: 19.1.4 - resolution: "@types/react@npm:19.1.4" + version: 19.2.2 + resolution: "@types/react@npm:19.2.2" dependencies: csstype: ^3.0.2 - checksum: 36dcbd7a2e78b011e61cddc3e97b5e8556d789a404a2e4847f9b88aaf46189a35d1c5becf93baa1bab89258a1cc1102ef295ffe3c1d008cfa95c4d4e1036606f + checksum: 7eb2d316dd5a6c02acb416524b50bae932c38d055d26e0f561ca23c009c686d16a2b22fcbb941eecbe2ecb167f119e29b9d0142d9d056dd381352c43413b60da languageName: node linkType: hard "@types/semver@npm:^7.3.12, @types/semver@npm:^7.5.5": - version: 7.7.0 - resolution: "@types/semver@npm:7.7.0" - checksum: d488eaeddb23879a0a8a759bed667e1a76cb0dd4d23e3255538e24c189db387357953ca9e7a3bda2bb7f95e84cac8fe0db4fbe6b3456e893043337732d1d23cc + version: 7.7.1 + resolution: "@types/semver@npm:7.7.1" + checksum: 76d218e414482a398148d5c28f2bfa017108869f3fc18cda379c9d8d062348f8b9653ae2fa8642d3b5b52e211928fe8be34f22da4e1f08245c84e0e51e040673 languageName: node linkType: hard @@ -3262,11 +3358,11 @@ __metadata: linkType: hard "@types/yargs@npm:^17.0.8": - version: 17.0.33 - resolution: "@types/yargs@npm:17.0.33" + version: 17.0.34 + resolution: "@types/yargs@npm:17.0.34" dependencies: "@types/yargs-parser": "*" - checksum: ee013f257472ab643cb0584cf3e1ff9b0c44bca1c9ba662395300a7f1a6c55fa9d41bd40ddff42d99f5d95febb3907c9ff600fbcb92dadbec22c6a76de7e1236 + checksum: 8f39dad7e345236b1c92ddc20dcee74b01d5322639054fe0c494b3d870ce0d784f8fd6ed81f5d010671625ae95b216ac9df13662c079afd112503b0ffd949e5e languageName: node linkType: hard @@ -3505,12 +3601,12 @@ __metadata: languageName: node linkType: hard -"acorn@npm:^8.14.0": - version: 8.14.1 - resolution: "acorn@npm:8.14.1" +"acorn@npm:^8.15.0": + version: 8.15.0 + resolution: "acorn@npm:8.15.0" bin: acorn: bin/acorn - checksum: 260d9bb6017a1b6e42d31364687f0258f78eb20210b36ef2baad38fd619d78d4e95ff7dde9b3dbe0d81f137f79a8d651a845363a26e6985997f7b71145dc5e94 + checksum: 309c6b49aedf1a2e34aaf266de06de04aab6eb097c02375c66fdeb0f64556a6a823540409914fb364d9a11bc30d79d485a2eba29af47992d3490e9886c4391c3 languageName: node linkType: hard @@ -3522,9 +3618,9 @@ __metadata: 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" - checksum: 87bb7ee54f5ecf0ccbfcba0b07473885c43ecd76cb29a8db17d6137a19d9f9cd443a2a7c5fd8a3f24d58ad8145f9eb49116344a66b107e1aeab82cf2383f4753 + version: 7.1.4 + resolution: "agent-base@npm:7.1.4" + checksum: 86a7f542af277cfbd77dd61e7df8422f90bac512953709003a1c530171a9d019d072e2400eab2b59f84b49ab9dd237be44315ca663ac73e82b3922d10ea5eafa languageName: node linkType: hard @@ -3623,9 +3719,9 @@ __metadata: linkType: hard "ansi-regex@npm:^6.0.1": - version: 6.1.0 - resolution: "ansi-regex@npm:6.1.0" - checksum: 495834a53b0856c02acd40446f7130cb0f8284f4a39afdab20d5dc42b2e198b1196119fe887beed8f9055c4ff2055e3b2f6d4641d0be018cdfb64fedf6fc1aac + version: 6.2.2 + resolution: "ansi-regex@npm:6.2.2" + checksum: 9b17ce2c6daecc75bcd5966b9ad672c23b184dc3ed9bf3c98a0702f0d2f736c15c10d461913568f2cf527a5e64291c7473358885dd493305c84a1cfed66ba94f languageName: node linkType: hard @@ -3647,7 +3743,7 @@ __metadata: languageName: node linkType: hard -"ansi-styles@npm:^5.0.0": +"ansi-styles@npm:^5.0.0, ansi-styles@npm:^5.2.0": version: 5.2.0 resolution: "ansi-styles@npm:5.2.0" checksum: d7f4e97ce0623aea6bc0d90dcd28881ee04cba06c570b97fd3391bd7a268eedfd9d5e2dd4fdcbdd82b8105df5faf6f24aaedc08eaf3da898e702db5948f63469 @@ -3655,9 +3751,9 @@ __metadata: linkType: hard "ansi-styles@npm:^6.1.0, ansi-styles@npm:^6.2.1": - version: 6.2.1 - resolution: "ansi-styles@npm:6.2.1" - checksum: ef940f2f0ced1a6347398da88a91da7930c33ecac3c77b72c5905f8b8fe402c52e6fde304ff5347f616e27a742da3f1dc76de98f6866c69251ad0b07a66776d9 + version: 6.2.3 + resolution: "ansi-styles@npm:6.2.3" + checksum: f1b0829cf048cce870a305819f65ce2adcebc097b6d6479e12e955fd6225df9b9eb8b497083b764df796d94383ff20016cc4dbbae5b40f36138fb65a9d33c2e2 languageName: node linkType: hard @@ -3694,13 +3790,23 @@ __metadata: languageName: node linkType: hard +"arkregex@npm:0.0.2": + version: 0.0.2 + resolution: "arkregex@npm:0.0.2" + dependencies: + "@ark/util": 0.53.0 + checksum: 5b6780b885398a89352f4278a6afb7d4d93820839fb00bfe5eb92a90fd282810750a4f00b025a1924b56654357e70ca5c5ec2ced01302d0e76c011704c4bb596 + languageName: node + linkType: hard + "arktype@npm:^2.1.15": - version: 2.1.20 - resolution: "arktype@npm:2.1.20" + version: 2.1.25 + resolution: "arktype@npm:2.1.25" dependencies: - "@ark/schema": 0.46.0 - "@ark/util": 0.46.0 - checksum: 5c02dda98606b83b35bbc66934259e3f30c4b4486c32e470e199da533c0af568951502173d7d7a5e64a2e53667eb36d10d772ce46c0bff204fab759430614c9b + "@ark/schema": 0.53.0 + "@ark/util": 0.53.0 + arkregex: 0.0.2 + checksum: f06ee4792cfb7eb991b523e4e88d4fbfb4329b36311cc761337dab46c59392dececd8584905327290cd6926ec748313b8479ccadd435fa5b70966e316b4e6c05 languageName: node linkType: hard @@ -3722,16 +3828,18 @@ __metadata: linkType: hard "array-includes@npm:^3.1.6, array-includes@npm:^3.1.8": - version: 3.1.8 - resolution: "array-includes@npm:3.1.8" + version: 3.1.9 + resolution: "array-includes@npm:3.1.9" dependencies: - call-bind: ^1.0.7 + call-bind: ^1.0.8 + call-bound: ^1.0.4 define-properties: ^1.2.1 - es-abstract: ^1.23.2 - es-object-atoms: ^1.0.0 - get-intrinsic: ^1.2.4 - is-string: ^1.0.7 - checksum: eb39ba5530f64e4d8acab39297c11c1c5be2a4ea188ab2b34aba5fb7224d918f77717a9d57a3e2900caaa8440e59431bdaf5c974d5212ef65d97f132e38e2d91 + es-abstract: ^1.24.0 + es-object-atoms: ^1.1.1 + get-intrinsic: ^1.3.0 + is-string: ^1.1.1 + math-intrinsics: ^1.1.0 + checksum: b58dc526fe415252e50319eaf88336e06e75aa673e3b58d252414739a4612dbe56e7b613fdcc7c90561dc9cf9202bbe5ca029ccd8c08362746459475ae5a8f3e languageName: node linkType: hard @@ -3845,6 +3953,13 @@ __metadata: languageName: node linkType: hard +"async-generator-function@npm:^1.0.0": + version: 1.0.0 + resolution: "async-generator-function@npm:1.0.0" + checksum: 74a71a4a2dd7afd06ebb612f6d612c7f4766a351bedffde466023bf6dae629e46b0d2cd38786239e0fbf245de0c7df76035465e16d1213774a0efb22fec0d713 + languageName: node + linkType: hard + "async-limiter@npm:~1.0.0": version: 1.0.1 resolution: "async-limiter@npm:1.0.1" @@ -3862,12 +3977,12 @@ __metadata: linkType: hard "atomically@npm:^2.0.3": - version: 2.0.3 - resolution: "atomically@npm:2.0.3" + version: 2.1.0 + resolution: "atomically@npm:2.1.0" dependencies: - stubborn-fs: ^1.2.5 - when-exit: ^2.1.1 - checksum: 4ee528fe35b4bc84cd626f6414cd2b51f04f94c2f6e8ab5c97d056779ef507bdd1e2671056957a031e6b487571fcc0a8627e8660645e6d61c84e561ae71cc8b6 + stubborn-fs: ^2.0.0 + when-exit: ^2.1.4 + checksum: 5ee3f88b6096c045e545a6ce8f9c9ec7d88ae1e547ab6c6f1b9d95fb85ff5faf49a8f1fe9197f8e439b253e49602db802fc40f8529816887707e457a43898f0e languageName: node linkType: hard @@ -3922,39 +4037,39 @@ __metadata: languageName: node linkType: hard -"babel-plugin-polyfill-corejs2@npm:^0.4.10": - version: 0.4.13 - resolution: "babel-plugin-polyfill-corejs2@npm:0.4.13" +"babel-plugin-polyfill-corejs2@npm:^0.4.14": + version: 0.4.14 + resolution: "babel-plugin-polyfill-corejs2@npm:0.4.14" dependencies: - "@babel/compat-data": ^7.22.6 - "@babel/helper-define-polyfill-provider": ^0.6.4 + "@babel/compat-data": ^7.27.7 + "@babel/helper-define-polyfill-provider": ^0.6.5 semver: ^6.3.1 peerDependencies: "@babel/core": ^7.4.0 || ^8.0.0-0 <8.0.0 - checksum: 553b64eb11bad2cfc220e94f1fb2449755b5c7d54886dca6d8053b13b6e910f349a38bbc75aafd610f88217699db499548919bb5df653d635b9cdeb39d34a68d + checksum: d654334c1b4390d08282416144b7b6f3d74d2cab44b2bfa2b6405c828882c82907b8b67698dce1be046c218d2d4fe5bf7fb6d01879938f3129dad969e8cfc44d languageName: node linkType: hard -"babel-plugin-polyfill-corejs3@npm:^0.11.0": - version: 0.11.1 - resolution: "babel-plugin-polyfill-corejs3@npm:0.11.1" +"babel-plugin-polyfill-corejs3@npm:^0.13.0": + version: 0.13.0 + resolution: "babel-plugin-polyfill-corejs3@npm:0.13.0" dependencies: - "@babel/helper-define-polyfill-provider": ^0.6.3 - core-js-compat: ^3.40.0 + "@babel/helper-define-polyfill-provider": ^0.6.5 + core-js-compat: ^3.43.0 peerDependencies: "@babel/core": ^7.4.0 || ^8.0.0-0 <8.0.0 - checksum: ee39440475ef377a1570ccbc06b1a1d274cbfbbe2e7c3d4c60f38781a47f00a28bd10d8e23430828b965820c41beb2c93c84596baf72583a2c9c3fdfa4397994 + checksum: cf526031acd97ff2124e7c10e15047e6eeb0620d029c687f1dca99916a8fe6cac0e634b84c913db6cb68b7a024f82492ba8fdcc2a6266e7b05bdac2cba0c2434 languageName: node linkType: hard -"babel-plugin-polyfill-regenerator@npm:^0.6.1": - version: 0.6.4 - resolution: "babel-plugin-polyfill-regenerator@npm:0.6.4" +"babel-plugin-polyfill-regenerator@npm:^0.6.5": + version: 0.6.5 + resolution: "babel-plugin-polyfill-regenerator@npm:0.6.5" dependencies: - "@babel/helper-define-polyfill-provider": ^0.6.4 + "@babel/helper-define-polyfill-provider": ^0.6.5 peerDependencies: "@babel/core": ^7.4.0 || ^8.0.0-0 <8.0.0 - checksum: f4d4a803834ffa72713579d696586d8cc654c0025cbd5ec775fc5d37faa00381dcb80e5b97d4b16059443352653585596d87848b5590b1d8670c235408e73fb3 + checksum: ed1932fa9a31e0752fd10ebf48ab9513a654987cab1182890839523cb898559d24ae0578fdc475d9f995390420e64eeaa4b0427045b56949dace3c725bc66dbb languageName: node linkType: hard @@ -3986,8 +4101,8 @@ __metadata: linkType: hard "babel-preset-current-node-syntax@npm:^1.0.0": - version: 1.1.0 - resolution: "babel-preset-current-node-syntax@npm:1.1.0" + version: 1.2.0 + resolution: "babel-preset-current-node-syntax@npm:1.2.0" dependencies: "@babel/plugin-syntax-async-generators": ^7.8.4 "@babel/plugin-syntax-bigint": ^7.8.3 @@ -4005,8 +4120,8 @@ __metadata: "@babel/plugin-syntax-private-property-in-object": ^7.14.5 "@babel/plugin-syntax-top-level-await": ^7.14.5 peerDependencies: - "@babel/core": ^7.0.0 - checksum: 9f93fac975eaba296c436feeca1031ca0539143c4066eaf5d1ba23525a31850f03b651a1049caea7287df837a409588c8252c15627ad3903f17864c8e25ed64b + "@babel/core": ^7.0.0 || ^8.0.0-0 + checksum: 3608fa671cfa46364ea6ec704b8fcdd7514b7b70e6ec09b1199e13ae73ed346c51d5ce2cb6d4d5b295f6a3f2cad1fdeec2308aa9e037002dd7c929194cc838ea languageName: node linkType: hard @@ -4036,6 +4151,15 @@ __metadata: languageName: node linkType: hard +"baseline-browser-mapping@npm:^2.8.19": + version: 2.8.24 + resolution: "baseline-browser-mapping@npm:2.8.24" + bin: + baseline-browser-mapping: dist/cli.js + checksum: 426df57ec914b3934e8d5ee294e84a8dfc0430acfda075cc2f6e321018ed9f8ebc4d416457c434da41c15d36ab2077fadad32f8b92a3266f1d59daa4278e8874 + languageName: node + linkType: hard + "basic-ftp@npm:^5.0.2": version: 5.0.5 resolution: "basic-ftp@npm:5.0.5" @@ -4098,21 +4222,21 @@ __metadata: linkType: hard "brace-expansion@npm:^1.1.7": - version: 1.1.11 - resolution: "brace-expansion@npm:1.1.11" + version: 1.1.12 + resolution: "brace-expansion@npm:1.1.12" dependencies: balanced-match: ^1.0.0 concat-map: 0.0.1 - checksum: faf34a7bb0c3fcf4b59c7808bc5d2a96a40988addf2e7e09dfbb67a2251800e0d14cd2bfc1aa79174f2f5095c54ff27f46fb1289fe2d77dac755b5eb3434cc07 + checksum: 12cb6d6310629e3048cadb003e1aca4d8c9bb5c67c3c321bafdd7e7a50155de081f78ea3e0ed92ecc75a9015e784f301efc8132383132f4f7904ad1ac529c562 languageName: node linkType: hard "brace-expansion@npm:^2.0.1": - version: 2.0.1 - resolution: "brace-expansion@npm:2.0.1" + version: 2.0.2 + resolution: "brace-expansion@npm:2.0.2" dependencies: balanced-match: ^1.0.0 - checksum: a61e7cd2e8a8505e9f0036b3b6108ba5e926b4b55089eeb5550cd04a471fe216c96d4fe7e4c7f995c728c554ae20ddfc4244cad10aef255e72b62930afd233d1 + checksum: 01dff195e3646bc4b0d27b63d9bab84d2ebc06121ff5013ad6e5356daa5a9d6b60fa26cf73c74797f2dc3fbec112af13578d51f75228c1112b26c790a87b0488 languageName: node linkType: hard @@ -4125,17 +4249,18 @@ __metadata: languageName: node linkType: hard -"browserslist@npm:^4.20.4, browserslist@npm:^4.24.0, browserslist@npm:^4.24.4": - version: 4.24.5 - resolution: "browserslist@npm:4.24.5" +"browserslist@npm:^4.20.4, browserslist@npm:^4.24.0, browserslist@npm:^4.26.3": + version: 4.27.0 + resolution: "browserslist@npm:4.27.0" dependencies: - caniuse-lite: ^1.0.30001716 - electron-to-chromium: ^1.5.149 - node-releases: ^2.0.19 - update-browserslist-db: ^1.1.3 + baseline-browser-mapping: ^2.8.19 + caniuse-lite: ^1.0.30001751 + electron-to-chromium: ^1.5.238 + node-releases: ^2.0.26 + update-browserslist-db: ^1.1.4 bin: browserslist: cli.js - checksum: 69310ade58b0cb2b2871022fdaba8388902f9a2d17a6fa05f383d046d6da87fd9f83018a66fe1c6296648ca7d52e3208c3fc68c82f17a0fd4bf12a452c036247 + checksum: 01dc8428f5deb018bf99d3d8da1dd41bb0ca8a65af0b371e3b5386f5eef11f0c15ec741fc0686ca0d85aafc8f20036c4330e37bcc6b448a7424012128ded8c96 languageName: node linkType: hard @@ -4298,14 +4423,14 @@ __metadata: languageName: node linkType: hard -"caniuse-lite@npm:^1.0.30001716": - version: 1.0.30001718 - resolution: "caniuse-lite@npm:1.0.30001718" - checksum: c6598b6eb2c4358fc9f8ead8982bf5f9efdc1f29bb74948b9481d314ced10675bd0beb99771094ac52d56c2cec121049d1f18e9405cab7d81807816d1836b38a +"caniuse-lite@npm:^1.0.30001751": + version: 1.0.30001753 + resolution: "caniuse-lite@npm:1.0.30001753" + checksum: d38b17895a99bf1ba9f1a8076233e3d4a606cd0121ccdb381ea94c651aaea0e1587ba3922b11dde4eb153b6741ac3e129fc670df0a7251987ed8619f09059b8a languageName: node linkType: hard -"chalk@npm:5.4.1, chalk@npm:^5.3.0": +"chalk@npm:5.4.1": version: 5.4.1 resolution: "chalk@npm:5.4.1" checksum: 0c656f30b782fed4d99198825c0860158901f449a6b12b818b0aabad27ec970389e7e8767d0e00762175b23620c812e70c4fd92c0210e55fc2d993638b74e86e @@ -4322,6 +4447,13 @@ __metadata: languageName: node linkType: hard +"chalk@npm:^5.3.0": + version: 5.6.2 + resolution: "chalk@npm:5.6.2" + checksum: 4ee2d47a626d79ca27cb5299ecdcce840ef5755e287412536522344db0fc51ca0f6d6433202332c29e2288c6a90a2b31f3bd626bc8c14743b6b6ee28abd3b796 + languageName: node + linkType: hard + "char-regex@npm:^1.0.2": version: 1.0.2 resolution: "char-regex@npm:1.0.2" @@ -4386,9 +4518,9 @@ __metadata: linkType: hard "ci-info@npm:^4.1.0": - version: 4.2.0 - resolution: "ci-info@npm:4.2.0" - checksum: 0e3726721526f54c5b17cf44ab2ed69b842c756bcb4d2b26ce279e595a80a856aec9fb38a2986a2baca3de73d15895f3a01d2771c4aad93c898aae7e3ca0ceb1 + version: 4.3.1 + resolution: "ci-info@npm:4.3.1" + checksum: 66c159d92648e8a07acab0a3a0681bff6ccc39aa44916263208c4d97bbbeedbbc886d7611fd30c21df1aa624ce3c6fcdfde982e74689e3e014e064e1d0805f94 languageName: node linkType: hard @@ -4509,9 +4641,9 @@ __metadata: linkType: hard "collect-v8-coverage@npm:^1.0.0": - version: 1.0.2 - resolution: "collect-v8-coverage@npm:1.0.2" - checksum: c10f41c39ab84629d16f9f6137bc8a63d332244383fc368caf2d2052b5e04c20cd1fd70f66fcf4e2422b84c8226598b776d39d5f2d2a51867cc1ed5d1982b4da + version: 1.0.3 + resolution: "collect-v8-coverage@npm:1.0.3" + checksum: ed1d1ebc9c05e7263fffa3ad6440031db6a1fdd9f574435aa689effcdfe9f2b93aba8ec600f9c7b99124cd6ff5d9415c17961d84ae829a72251a4fe668a49b63 languageName: node linkType: hard @@ -4634,17 +4766,17 @@ __metadata: linkType: hard "compression@npm:^1.7.1": - version: 1.8.0 - resolution: "compression@npm:1.8.0" + version: 1.8.1 + resolution: "compression@npm:1.8.1" dependencies: bytes: 3.1.2 compressible: ~2.0.18 debug: 2.6.9 negotiator: ~0.6.4 - on-headers: ~1.0.2 + on-headers: ~1.1.0 safe-buffer: 5.2.1 vary: ~1.1.2 - checksum: 12ca3e326b4ccb6b6e51e1d14d96fafd058ddb3be08fe888487d367d42fb4f81f25d4bf77acc517ba724370e7d74469280688baf2da8cad61062bdf62eb9fd45 + checksum: 906325935180cd3507d30ed898fb129deccab03689383d55536245a94610f5003923bb14c95ee6adc8d658ee13be549407eb4346ef55169045f3e41e9969808e languageName: node linkType: hard @@ -4678,14 +4810,14 @@ __metadata: linkType: hard "configstore@npm:^7.0.0": - version: 7.0.0 - resolution: "configstore@npm:7.0.0" + version: 7.1.0 + resolution: "configstore@npm:7.1.0" dependencies: atomically: ^2.0.3 dot-prop: ^9.0.0 graceful-fs: ^4.2.11 xdg-basedir: ^5.1.0 - checksum: 1f8f1ca51d10d5ef54a346e12dd82c81918d28144ff5f41af0a6eb65c394c0e3a37d0f91931516d8964efff8fd8802c6478d13a35a6c7924e7a6c83f11d19c16 + checksum: 0b5958a3e7a9eebddfea64564e49bb60d3948c9a6b4d160bddf00862316e16b4566fe1f23962cdd28cd5c05ee93776324667dfa6530d74fb92dd7e8c54719eae languageName: node linkType: hard @@ -4718,11 +4850,11 @@ __metadata: linkType: hard "conventional-changelog-angular@npm:^8.0.0": - version: 8.0.0 - resolution: "conventional-changelog-angular@npm:8.0.0" + version: 8.1.0 + resolution: "conventional-changelog-angular@npm:8.1.0" dependencies: compare-func: ^2.0.0 - checksum: 71f492cb4dccd46174430517177054be2e2097f1264c55419a79aa94fe4d163f98aeab7da6836473470fbfc920051a9554f46498989bdd6438648c2d7e32b42c + checksum: 1f14b235ab09b74e658353aa8ce559ec99de34f6c3e54923fee327291373baa720143a3172d12ae17cc3d9634b34a7bee57559c211354c9557d33743e5245f75 languageName: node linkType: hard @@ -4821,8 +4953,8 @@ __metadata: linkType: hard "conventional-changelog-writer@npm:^8.0.0": - version: 8.1.0 - resolution: "conventional-changelog-writer@npm:8.1.0" + version: 8.2.0 + resolution: "conventional-changelog-writer@npm:8.2.0" dependencies: conventional-commits-filter: ^5.0.0 handlebars: ^4.7.7 @@ -4830,7 +4962,7 @@ __metadata: semver: ^7.5.2 bin: conventional-changelog-writer: dist/cli/index.js - checksum: cf3122058186f1e0ceaaa321fdad22c4ff2cbd830115747a695be153184692800e4bf51e54487884c3809c87b52f7933a968b53f44e2a25ad56993ffc2034cf1 + checksum: 0a7b62fdc06dbe3e8f0feff2c51295ebc03d8046db73111b3c6a595472885551adf9ef2eeb741c43794466e58c1f23a055160c8aef08cacfe769b86ea2b7c611 languageName: node linkType: hard @@ -4875,13 +5007,13 @@ __metadata: linkType: hard "conventional-commits-parser@npm:^6.0.0": - version: 6.1.0 - resolution: "conventional-commits-parser@npm:6.1.0" + version: 6.2.1 + resolution: "conventional-commits-parser@npm:6.2.1" dependencies: meow: ^13.0.0 bin: conventional-commits-parser: dist/cli/index.js - checksum: c9b660b3aaa48576ee3a1fdf21f4c236d7f19991e8a8a121e24105b3470b15440310e5b3cbf4dd51fb4a0185e66bee7ee875354d29f47c234719629ecf40ac77 + checksum: 9d0fe3a7800bb3c6f2f7582724841990b44a21e944de584ef811591330d3c0fe9a19ba488234dde896b7d1331fbf63b18f43dc64579bf0805aad28bed4ce879a languageName: node linkType: hard @@ -4907,32 +5039,25 @@ __metadata: languageName: node linkType: hard -"core-js-compat@npm:^3.40.0": - version: 3.42.0 - resolution: "core-js-compat@npm:3.42.0" +"core-js-compat@npm:^3.43.0": + version: 3.46.0 + resolution: "core-js-compat@npm:3.46.0" dependencies: - browserslist: ^4.24.4 - checksum: 4f0a7db9ed9a95c4edae0749fe9a4d4d4f8f51a53c7c3e06049887500e98763732e8afef9628d2145f875b6e262567e951a77e4d06273f9eac273f5241259fd3 - languageName: node - linkType: hard - -"core-util-is@npm:~1.0.0": - version: 1.0.3 - resolution: "core-util-is@npm:1.0.3" - checksum: 9de8597363a8e9b9952491ebe18167e3b36e7707569eed0ebf14f8bba773611376466ae34575bca8cfe3c767890c859c74056084738f09d4e4a6f902b2ad7d99 + browserslist: ^4.26.3 + checksum: 16d381c51e34d38ecc65d429d5a5c1dbd198f70b5a0a6256a3a41dcb8523e07f0a8682f6349298a55ff6e9d039e131d67b07fe863047a28672ae5f10373c57cf languageName: node linkType: hard "cosmiconfig-typescript-loader@npm:^6.1.0": - version: 6.1.0 - resolution: "cosmiconfig-typescript-loader@npm:6.1.0" + version: 6.2.0 + resolution: "cosmiconfig-typescript-loader@npm:6.2.0" dependencies: - jiti: ^2.4.1 + jiti: ^2.6.1 peerDependencies: "@types/node": "*" cosmiconfig: ">=9" typescript: ">=5" - checksum: 45114854faaa97178abd2ccad511363faa57c03321c7e39ad16619c63842b3f6147dd20118f9f07c9530a242a39c3107c791708bb0b987dad374e71f23f9468b + checksum: 2680bb585de1185aa23ba678cb0426cba1be8fa0a9d286f71c2ce5bd63f23e5b8f726161673a16babb2aa0e7d033fda8774268a025fb63f548d1c75977292212 languageName: node linkType: hard @@ -5048,9 +5173,9 @@ __metadata: linkType: hard "dayjs@npm:^1.8.15": - version: 1.11.13 - resolution: "dayjs@npm:1.11.13" - checksum: f388db88a6aa93956c1f6121644e783391c7b738b73dbc54485578736565c8931bdfba4bb94e9b1535c6e509c97d5deb918bbe1ae6b34358d994de735055cca9 + version: 1.11.19 + resolution: "dayjs@npm:1.11.19" + checksum: dfafcca2c67cc6e542fd880d77f1d91667efd323edc28f0487b470b184a11cc97696163ed5be1142ea2a031045b27a0d0555e72f60a63275e0e0401ac24bea5d languageName: node linkType: hard @@ -5063,15 +5188,15 @@ __metadata: languageName: node linkType: hard -"debug@npm:4, debug@npm:^4.1.0, debug@npm:^4.1.1, debug@npm:^4.3.1, debug@npm:^4.3.2, debug@npm:^4.3.4, debug@npm:^4.4.0": - version: 4.4.1 - resolution: "debug@npm:4.4.1" +"debug@npm:4, debug@npm:^4.1.0, debug@npm:^4.1.1, debug@npm:^4.3.1, debug@npm:^4.3.2, debug@npm:^4.3.4, debug@npm:^4.4.0, debug@npm:^4.4.1": + version: 4.4.3 + resolution: "debug@npm:4.4.3" dependencies: ms: ^2.1.3 peerDependenciesMeta: supports-color: optional: true - checksum: a43826a01cda685ee4cec00fb2d3322eaa90ccadbef60d9287debc2a886be3e835d9199c80070ede75a409ee57828c4c6cd80e4b154f2843f0dc95a570dc0729 + checksum: 4805abd570e601acdca85b6aa3757186084a45cff9b2fa6eee1f3b173caa776b45f478b2a71a572d616d2010cea9211d0ac4a02a610e4c18ac4324bde3760834 languageName: node linkType: hard @@ -5114,14 +5239,14 @@ __metadata: linkType: hard "dedent@npm:^1.0.0": - version: 1.6.0 - resolution: "dedent@npm:1.6.0" + version: 1.7.0 + resolution: "dedent@npm:1.7.0" peerDependencies: babel-plugin-macros: ^3.1.0 peerDependenciesMeta: babel-plugin-macros: optional: true - checksum: ecaa83968b3db4ffeadf8f679c01280f8679ec79993d7e203c0281d7926e883bb79f42b263ba0df1f78e146e4b0be1b9a5b922b1fe040cb89b09977bc9c25b38 + checksum: e07a21b7ae078f2c6502b46e6e9fb3f5592dc48ad8c6142d501d1a85ee04cd3add5d62260a9b20f87674a80edada2032918ca0718597752c5cb90b36ab5066ec languageName: node linkType: hard @@ -5257,13 +5382,6 @@ __metadata: languageName: node linkType: hard -"denodeify@npm:^1.2.1": - version: 1.2.1 - resolution: "denodeify@npm:1.2.1" - checksum: a85c8f7fce5626e311edd897c27ad571b29393c4a739dc29baee48328e09edd82364ff697272dd612462c67e48b4766389642b5bdfaea0dc114b7c6a276c0eae - languageName: node - linkType: hard - "depd@npm:2.0.0": version: 2.0.0 resolution: "depd@npm:2.0.0" @@ -5360,10 +5478,10 @@ __metadata: languageName: node linkType: hard -"electron-to-chromium@npm:^1.5.149": - version: 1.5.155 - resolution: "electron-to-chromium@npm:1.5.155" - checksum: 6e8f666d4ea0b70e1dd94e2ae588a4e38545beab1d9de7875e19a771f333549cf304fe6cbf19d773d7ac79dffae1c479b9d4291cf6f1523e5d24109ae79f610c +"electron-to-chromium@npm:^1.5.238": + version: 1.5.245 + resolution: "electron-to-chromium@npm:1.5.245" + checksum: 6262655d0dec8663df58056559a8f1f47648657debf0c868e49d8e3b5f866318c4a9105261272a5aaa529fc6140f4401e0e2c5fadbd24ed50cf9b5cd7e961bfc languageName: node linkType: hard @@ -5375,9 +5493,9 @@ __metadata: linkType: hard "emoji-regex@npm:^10.3.0": - version: 10.4.0 - resolution: "emoji-regex@npm:10.4.0" - checksum: a6d9a0e454829a52e664e049847776ee1fff5646617b06cd87de7c03ce1dfcce4102a3b154d5e9c8e90f8125bc120fc1fe114d523dddf60a8a161f26c72658d2 + version: 10.6.0 + resolution: "emoji-regex@npm:10.6.0" + checksum: 8785f6a7ec4559c931bd6640f748fe23791f5af4c743b131d458c5551b4aa7da2a9cd882518723cb3859e8b0b59b0cc08f2ce0f8e65c61a026eed71c2dc407d5 languageName: node linkType: hard @@ -5419,11 +5537,11 @@ __metadata: linkType: hard "end-of-stream@npm:^1.1.0": - version: 1.4.4 - resolution: "end-of-stream@npm:1.4.4" + version: 1.4.5 + resolution: "end-of-stream@npm:1.4.5" dependencies: once: ^1.4.0 - checksum: 530a5a5a1e517e962854a31693dbb5c0b2fc40b46dad2a56a2deec656ca040631124f4795823acc68238147805f8b021abbe221f4afed5ef3c8e8efc2024908b + checksum: 1e0cfa6e7f49887544e03314f9dfc56a8cb6dde910cbb445983ecc2ff426fc05946df9d75d8a21a3a64f2cecfe1bf88f773952029f46756b2ed64a24e95b1fb8 languageName: node linkType: hard @@ -5435,11 +5553,11 @@ __metadata: linkType: hard "envinfo@npm:^7.13.0": - version: 7.14.0 - resolution: "envinfo@npm:7.14.0" + version: 7.20.0 + resolution: "envinfo@npm:7.20.0" bin: envinfo: dist/cli.js - checksum: 137c1dd9a4d5781c4a6cdc6b695454ba3c4ba1829f73927198aa4122f11b35b59d7b2cb7e1ceea1364925a30278897548511d22f860c14253a33797d0bebd551 + checksum: 5e7e7a4ec5b445939efd2634a8f2d7f926d6f79ae872acf5d7ebd46387f74b7c700667b2ffa795c109e53e70389e46c38726f24a834448dbddfc53f63376f5cb languageName: node linkType: hard @@ -5451,11 +5569,11 @@ __metadata: linkType: hard "error-ex@npm:^1.3.1": - version: 1.3.2 - resolution: "error-ex@npm:1.3.2" + version: 1.3.4 + resolution: "error-ex@npm:1.3.4" dependencies: is-arrayish: ^0.2.1 - checksum: c1c2b8b65f9c91b0f9d75f0debaa7ec5b35c266c2cac5de412c1a6de86d4cbae04ae44e510378cb14d032d0645a36925d0186f8bb7367bcc629db256b743a001 + checksum: 25136c0984569c8d68417036a9a1624804314296f24675199a391e5d20b2e26fe6d9304d40901293fa86900603a229983c9a8921ea7f1d16f814c2db946ff4ef languageName: node linkType: hard @@ -5478,26 +5596,26 @@ __metadata: languageName: node linkType: hard -"es-abstract@npm:^1.17.5, es-abstract@npm:^1.23.2, es-abstract@npm:^1.23.3, es-abstract@npm:^1.23.5, es-abstract@npm:^1.23.6, es-abstract@npm:^1.23.9": - version: 1.23.9 - resolution: "es-abstract@npm:1.23.9" +"es-abstract@npm:^1.17.5, es-abstract@npm:^1.23.2, es-abstract@npm:^1.23.3, es-abstract@npm:^1.23.5, es-abstract@npm:^1.23.6, es-abstract@npm:^1.23.9, es-abstract@npm:^1.24.0": + version: 1.24.0 + resolution: "es-abstract@npm:1.24.0" dependencies: array-buffer-byte-length: ^1.0.2 arraybuffer.prototype.slice: ^1.0.4 available-typed-arrays: ^1.0.7 call-bind: ^1.0.8 - call-bound: ^1.0.3 + call-bound: ^1.0.4 data-view-buffer: ^1.0.2 data-view-byte-length: ^1.0.2 data-view-byte-offset: ^1.0.1 es-define-property: ^1.0.1 es-errors: ^1.3.0 - es-object-atoms: ^1.0.0 + es-object-atoms: ^1.1.1 es-set-tostringtag: ^2.1.0 es-to-primitive: ^1.3.0 function.prototype.name: ^1.1.8 - get-intrinsic: ^1.2.7 - get-proto: ^1.0.0 + get-intrinsic: ^1.3.0 + get-proto: ^1.0.1 get-symbol-description: ^1.1.0 globalthis: ^1.0.4 gopd: ^1.2.0 @@ -5509,21 +5627,24 @@ __metadata: is-array-buffer: ^3.0.5 is-callable: ^1.2.7 is-data-view: ^1.0.2 + is-negative-zero: ^2.0.3 is-regex: ^1.2.1 + is-set: ^2.0.3 is-shared-array-buffer: ^1.0.4 is-string: ^1.1.1 is-typed-array: ^1.1.15 - is-weakref: ^1.1.0 + is-weakref: ^1.1.1 math-intrinsics: ^1.1.0 - object-inspect: ^1.13.3 + object-inspect: ^1.13.4 object-keys: ^1.1.1 object.assign: ^4.1.7 own-keys: ^1.0.1 - regexp.prototype.flags: ^1.5.3 + regexp.prototype.flags: ^1.5.4 safe-array-concat: ^1.1.3 safe-push-apply: ^1.0.0 safe-regex-test: ^1.1.0 set-proto: ^1.0.0 + stop-iteration-iterator: ^1.1.0 string.prototype.trim: ^1.2.10 string.prototype.trimend: ^1.0.9 string.prototype.trimstart: ^1.0.8 @@ -5532,8 +5653,8 @@ __metadata: typed-array-byte-offset: ^1.0.4 typed-array-length: ^1.0.7 unbox-primitive: ^1.1.0 - which-typed-array: ^1.1.18 - checksum: f3ee2614159ca197f97414ab36e3f406ee748ce2f97ffbf09e420726db5a442ce13f1e574601468bff6e6eb81588e6c9ce1ac6c03868a37c7cd48ac679f8485a + which-typed-array: ^1.1.19 + checksum: 06b3d605e56e3da9d16d4db2629a42dac1ca31f2961a41d15c860422a266115e865b43e82d6b9da81a0fabbbb65ebc12fb68b0b755bc9dbddacb6bf7450e96df languageName: node linkType: hard @@ -5684,24 +5805,24 @@ __metadata: linkType: hard "eslint-config-prettier@npm:^10.1.1": - version: 10.1.5 - resolution: "eslint-config-prettier@npm:10.1.5" + version: 10.1.8 + resolution: "eslint-config-prettier@npm:10.1.8" peerDependencies: eslint: ">=7.0.0" bin: eslint-config-prettier: bin/cli.js - checksum: 6d8eb41c716fc2b073bfd9daede0c87c4c2b29055f15c94618eec00a19c5499024ddb89902d6793b5ac9102075e4739d7cc2d4d58c7e7ed4cc2dcf79e3fbcacc + checksum: 9140e19f78f0dbc888b160bb72b85f8043bada7b12a548faa56cea0ba74f8ef16653250ffd014d85d9a376a88c4941c96a3cdc9d39a07eb3def6967166635bd8 languageName: node linkType: hard "eslint-config-prettier@npm:^8.5.0": - version: 8.10.0 - resolution: "eslint-config-prettier@npm:8.10.0" + version: 8.10.2 + resolution: "eslint-config-prettier@npm:8.10.2" peerDependencies: eslint: ">=7.0.0" bin: eslint-config-prettier: bin/cli.js - checksum: 153266badd477e49b0759816246b2132f1dbdb6c7f313ca60a9af5822fd1071c2bc5684a3720d78b725452bbac04bb130878b2513aea5e72b1b792de5a69fec8 + checksum: a92b7e8a996e65adf79de1579524235687e9d3552d088cfab4f170da60d23762addb4276169c8ca3a9551329dda8408c59f7e414101b238a6385379ac1bc3b16 languageName: node linkType: hard @@ -5749,11 +5870,11 @@ __metadata: linkType: hard "eslint-plugin-prettier@npm:^5.2.3": - version: 5.4.0 - resolution: "eslint-plugin-prettier@npm:5.4.0" + version: 5.5.4 + resolution: "eslint-plugin-prettier@npm:5.5.4" dependencies: prettier-linter-helpers: ^1.0.0 - synckit: ^0.11.0 + synckit: ^0.11.7 peerDependencies: "@types/eslint": ">=8.0.0" eslint: ">=8.0.0" @@ -5764,7 +5885,7 @@ __metadata: optional: true eslint-config-prettier: optional: true - checksum: 1d71d4fb42b8f9654232c6f9c6805549f7e9da6ee3207069dac122ab1c55eae90a0840f5c109e821e3a5145ec223dbbdfa7cfd3c3a28267316d08d55d5812e21 + checksum: 0dd05ed85018ab0e98da80325b7bd4c4ab6dd684398f1270a7c8cf4261df714dd4502ba4c7f85f651aade9989da0a7d2adda03af8873b73b52014141abf385de languageName: node linkType: hard @@ -5833,13 +5954,13 @@ __metadata: languageName: node linkType: hard -"eslint-scope@npm:^8.3.0": - version: 8.3.0 - resolution: "eslint-scope@npm:8.3.0" +"eslint-scope@npm:^8.4.0": + version: 8.4.0 + resolution: "eslint-scope@npm:8.4.0" dependencies: esrecurse: ^4.3.0 estraverse: ^5.2.0 - checksum: 57a58b6716533e25d527089826c4add89a047aecf75e4a88fee05f113ef5a72b85392b304a69bf670646cc3e068354aec70361b9718c2453949a05fc4d9bfe73 + checksum: cf88f42cd5e81490d549dc6d350fe01e6fe420f9d9ea34f134bb359b030e3c4ef888d36667632e448937fe52449f7181501df48c08200e3d3b0fee250d05364e languageName: node linkType: hard @@ -5857,38 +5978,37 @@ __metadata: languageName: node linkType: hard -"eslint-visitor-keys@npm:^4.2.0": - version: 4.2.0 - resolution: "eslint-visitor-keys@npm:4.2.0" - checksum: 779c604672b570bb4da84cef32f6abb085ac78379779c1122d7879eade8bb38ae715645324597cf23232d03cef06032c9844d25c73625bc282a5bfd30247e5b5 +"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.27.0 - resolution: "eslint@npm:9.27.0" + version: 9.39.1 + resolution: "eslint@npm:9.39.1" dependencies: - "@eslint-community/eslint-utils": ^4.2.0 + "@eslint-community/eslint-utils": ^4.8.0 "@eslint-community/regexpp": ^4.12.1 - "@eslint/config-array": ^0.20.0 - "@eslint/config-helpers": ^0.2.1 - "@eslint/core": ^0.14.0 + "@eslint/config-array": ^0.21.1 + "@eslint/config-helpers": ^0.4.2 + "@eslint/core": ^0.17.0 "@eslint/eslintrc": ^3.3.1 - "@eslint/js": 9.27.0 - "@eslint/plugin-kit": ^0.3.1 + "@eslint/js": 9.39.1 + "@eslint/plugin-kit": ^0.4.1 "@humanfs/node": ^0.16.6 "@humanwhocodes/module-importer": ^1.0.1 "@humanwhocodes/retry": ^0.4.2 "@types/estree": ^1.0.6 - "@types/json-schema": ^7.0.15 ajv: ^6.12.4 chalk: ^4.0.0 cross-spawn: ^7.0.6 debug: ^4.3.2 escape-string-regexp: ^4.0.0 - eslint-scope: ^8.3.0 - eslint-visitor-keys: ^4.2.0 - espree: ^10.3.0 + eslint-scope: ^8.4.0 + eslint-visitor-keys: ^4.2.1 + espree: ^10.4.0 esquery: ^1.5.0 esutils: ^2.0.2 fast-deep-equal: ^3.1.3 @@ -5910,18 +6030,18 @@ __metadata: optional: true bin: eslint: bin/eslint.js - checksum: 7e2f220574466a6dcd4ebbec19d47a39c3d964bad5bb96706dee7e814d2000d6da78b4515a368515979e1addd59546e24841090101585e5d816c9819077f753c + checksum: 35583d4d93f431ea2716e18c912e0b10980e27377a89d2c644a3a755921e42a2665dfd7367b8e9b54c7e4e9f193dea4126ce503c866f5795b170934ffd3f1dd9 languageName: node linkType: hard -"espree@npm:^10.0.1, espree@npm:^10.3.0": - version: 10.3.0 - resolution: "espree@npm:10.3.0" +"espree@npm:^10.0.1, espree@npm:^10.4.0": + version: 10.4.0 + resolution: "espree@npm:10.4.0" dependencies: - acorn: ^8.14.0 + acorn: ^8.15.0 acorn-jsx: ^5.3.2 - eslint-visitor-keys: ^4.2.0 - checksum: 63e8030ff5a98cea7f8b3e3a1487c998665e28d674af08b9b3100ed991670eb3cbb0e308c4548c79e03762753838fbe530c783f17309450d6b47a889fee72bef + eslint-visitor-keys: ^4.2.1 + checksum: 5f9d0d7c81c1bca4bfd29a55270067ff9d575adb8c729a5d7f779c2c7b910bfc68ccf8ec19b29844b707440fc159a83868f22c8e87bbf7cbcb225ed067df6c85 languageName: node linkType: hard @@ -6060,9 +6180,9 @@ __metadata: linkType: hard "exponential-backoff@npm:^3.1.1": - version: 3.1.2 - resolution: "exponential-backoff@npm:3.1.2" - checksum: 7e191e3dd6edd8c56c88f2c8037c98fbb8034fe48778be53ed8cb30ccef371a061a4e999a469aab939b92f8f12698f3b426d52f4f76b7a20da5f9f98c3cbc862 + version: 3.1.3 + resolution: "exponential-backoff@npm:3.1.3" + checksum: 471fdb70fd3d2c08a74a026973bdd4105b7832911f610ca67bbb74e39279411c1eed2f2a110c9d41c2edd89459ba58fdaba1c174beed73e7a42d773882dcff82 languageName: node linkType: hard @@ -6119,9 +6239,9 @@ __metadata: linkType: hard "fast-uri@npm:^3.0.1": - version: 3.0.6 - resolution: "fast-uri@npm:3.0.6" - checksum: 7161ba2a7944778d679ba8e5f00d6a2bb479a2142df0982f541d67be6c979b17808f7edbb0ce78161c85035974bde3fa52b5137df31da46c0828cb629ba67c4e + version: 3.1.0 + resolution: "fast-uri@npm:3.1.0" + checksum: daab0efd3548cc53d0db38ecc764d125773f8bd70c34552ff21abdc6530f26fa4cb1771f944222ca5e61a0a1a85d01a104848ff88c61736de445d97bd616ea7e languageName: node linkType: hard @@ -6154,18 +6274,6 @@ __metadata: languageName: node linkType: hard -"fdir@npm:^6.4.4": - version: 6.4.4 - resolution: "fdir@npm:6.4.4" - peerDependencies: - picomatch: ^3 || ^4 - peerDependenciesMeta: - picomatch: - optional: true - checksum: 79043610236579ffbd0647c508b43bd030a2d034a17c43cf96813a00e8e92e51acdb115c6ddecef3b5812cc2692b976155b4f6413e51e3761f1e772fa019a321 - languageName: node - linkType: hard - "fdir@npm:^6.5.0": version: 6.5.0 resolution: "fdir@npm:6.5.0" @@ -6391,6 +6499,13 @@ __metadata: languageName: node linkType: hard +"generator-function@npm:^2.0.0": + version: 2.0.1 + resolution: "generator-function@npm:2.0.1" + checksum: 3bf87f7b0230de5d74529677e6c3ceb3b7b5d9618b5a22d92b45ce3876defbaf5a77791b25a61b0fa7d13f95675b5ff67a7769f3b9af33f096e34653519e873d + languageName: node + linkType: hard + "gensync@npm:^1.0.0-beta.2": version: 1.0.0-beta.2 resolution: "gensync@npm:1.0.0-beta.2" @@ -6406,27 +6521,30 @@ __metadata: linkType: hard "get-east-asian-width@npm:^1.0.0": - version: 1.3.0 - resolution: "get-east-asian-width@npm:1.3.0" - checksum: 757a34c7a46ff385e2775f96f9d3e553f6b6666a8898fb89040d36a1010fba692332772945606a7d4b0f0c6afb84cd394e75d5477c56e1f00f1eb79603b0aecc + version: 1.4.0 + resolution: "get-east-asian-width@npm:1.4.0" + checksum: 1d9a81a8004f4217ebef5d461875047d269e4b57e039558fd65130877cd4da8e3f61e1c4eada0c8b10e2816c7baf7d5fddb7006f561da13bc6f6dd19c1e964a4 languageName: node linkType: hard "get-intrinsic@npm:^1.2.4, get-intrinsic@npm:^1.2.5, get-intrinsic@npm:^1.2.6, get-intrinsic@npm:^1.2.7, get-intrinsic@npm:^1.3.0": - version: 1.3.0 - resolution: "get-intrinsic@npm:1.3.0" + version: 1.3.1 + resolution: "get-intrinsic@npm:1.3.1" dependencies: + async-function: ^1.0.0 + async-generator-function: ^1.0.0 call-bind-apply-helpers: ^1.0.2 es-define-property: ^1.0.1 es-errors: ^1.3.0 es-object-atoms: ^1.1.1 function-bind: ^1.1.2 + generator-function: ^2.0.0 get-proto: ^1.0.1 gopd: ^1.2.0 has-symbols: ^1.1.0 hasown: ^2.0.2 math-intrinsics: ^1.1.0 - checksum: 301008e4482bb9a9cb49e132b88fee093bff373b4e6def8ba219b1e96b60158a6084f273ef5cafe832e42cd93462f4accb46a618d35fe59a2b507f2388c5b79d + checksum: c02b3b6a445f9cd53e14896303794ac60f9751f58a69099127248abdb0251957174c6524245fc68579dc8e6a35161d3d94c93e665f808274716f4248b269436a languageName: node linkType: hard @@ -6482,13 +6600,13 @@ __metadata: linkType: hard "get-uri@npm:^6.0.1": - version: 6.0.4 - resolution: "get-uri@npm:6.0.4" + version: 6.0.5 + resolution: "get-uri@npm:6.0.5" dependencies: basic-ftp: ^5.0.2 data-uri-to-buffer: ^6.0.2 debug: ^4.3.4 - checksum: 7eae81655e0c8cee250d29c189e09030f37a2d37987298325709affb9408de448bf2dc43ee9a59acd21c1f100c3ca711d0446b4e689e9590c25774ecc59f0442 + checksum: aef94dbecde44bc9cd23f5c1b6af5bf772a3d16612c0fc37d3a4056ffd202f2cdd329746d4fdc2124813ea6c8b1c5279f3749d27226a2b161df43dbcb70082e3 languageName: node linkType: hard @@ -6618,13 +6736,6 @@ __metadata: languageName: node linkType: hard -"globals@npm:^11.1.0": - version: 11.12.0 - resolution: "globals@npm:11.12.0" - checksum: 67051a45eca3db904aee189dfc7cd53c20c7d881679c93f6146ddd4c9f4ab2268e68a919df740d39c71f4445d2b38ee360fc234428baea1dbdfe68bbcb46979e - languageName: node - linkType: hard - "globals@npm:^14.0.0": version: 14.0.0 resolution: "globals@npm:14.0.0" @@ -6793,13 +6904,6 @@ __metadata: languageName: node linkType: hard -"hermes-estree@npm:0.23.1": - version: 0.23.1 - resolution: "hermes-estree@npm:0.23.1" - checksum: 0f63edc365099304f4cd8e91a3666a4fb5a2a47baee751dc120df9201640112865944cae93617f554af71be9827e96547f9989f4972d6964ecc121527295fec6 - languageName: node - linkType: hard - "hermes-estree@npm:0.25.1": version: 0.25.1 resolution: "hermes-estree@npm:0.25.1" @@ -6814,12 +6918,10 @@ __metadata: languageName: node linkType: hard -"hermes-parser@npm:0.23.1": - version: 0.23.1 - resolution: "hermes-parser@npm:0.23.1" - dependencies: - hermes-estree: 0.23.1 - checksum: a08008928aea9ea9a2cab2c0fac3cffa21f7869ab3fabb68e5add0fe057737a0c352d7a446426f7956172ccc8f2d4a215b4fc20d1d08354fc8dc16772c248fce +"hermes-estree@npm:0.29.1": + version: 0.29.1 + resolution: "hermes-estree@npm:0.29.1" + checksum: a72fe490d99ba2f56b3e22f3d050ca7757cc8dc9ebcb9d907104e46aaabdea9d32b445f73cca724a2537090fad3dde3cce0dc733bad6d7b3930c6bcde484d45c languageName: node linkType: hard @@ -6841,6 +6943,15 @@ __metadata: languageName: node linkType: hard +"hermes-parser@npm:0.29.1": + version: 0.29.1 + resolution: "hermes-parser@npm:0.29.1" + dependencies: + hermes-estree: 0.29.1 + checksum: 3a7cd5cbdb191579f521dcb17edf199e24631314b9f69d043007e91762b53cd1f38eeb7688571f5be378b1c118e99af42040139e5f00e74a7cfd5c52c9d262e0 + 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" @@ -7012,9 +7123,9 @@ __metadata: linkType: hard "import-meta-resolve@npm:^4.0.0": - version: 4.1.0 - resolution: "import-meta-resolve@npm:4.1.0" - checksum: 6497af27bf3ee384ad4efd4e0ec3facf9a114863f35a7b35f248659f32faa5e1ae07baa74d603069f35734ae3718a78b3f66926f98dc9a62e261e7df37854a62 + version: 4.2.0 + resolution: "import-meta-resolve@npm:4.2.0" + checksum: fe5ca3258f22dc3dd4e2f2e8f6b54324c1cf0261216c7d9aae801b2eadf664bbd61e26cfb907a1238761285a3e9c8c23403321d52ca0e579c341b8d90c97fa52 languageName: node linkType: hard @@ -7040,9 +7151,9 @@ __metadata: linkType: hard "index-to-position@npm:^1.1.0": - version: 1.1.0 - resolution: "index-to-position@npm:1.1.0" - checksum: 078b05777ba4ccc2af13328cbdef8ac945c885aed7c28bf55b17b7e7722507dfb3afbdeb30b59ff224374857147d16043da1bcb2a4dc533c7924d81873ef4363 + version: 1.2.0 + resolution: "index-to-position@npm:1.2.0" + checksum: 2026188af74d4f4c19de44ca29116f093daf072ff4f4b8dda61668463bd28b097164d43f819684cb2f65ff749bc0dec14fb3956da0299a36faa68255c4eb6858 languageName: node linkType: hard @@ -7124,13 +7235,10 @@ __metadata: languageName: node linkType: hard -"ip-address@npm:^9.0.5": - version: 9.0.5 - resolution: "ip-address@npm:9.0.5" - dependencies: - jsbn: 1.1.0 - sprintf-js: ^1.1.3 - checksum: aa15f12cfd0ef5e38349744e3654bae649a34c3b10c77a674a167e99925d1549486c5b14730eebce9fea26f6db9d5e42097b00aa4f9f612e68c79121c71652dc +"ip-address@npm:^10.0.1": + version: 10.0.1 + resolution: "ip-address@npm:10.0.1" + checksum: 525d5391cfd31a91f80f5857e98487aeaa8474e860a6725a0b6461ac8e436c7f8c869774dece391c8f8e7486306a34a4d1c094778c4c583a3f1f2cd905e5ed50 languageName: node linkType: hard @@ -7163,9 +7271,9 @@ __metadata: linkType: hard "is-arrayish@npm:^0.3.1": - version: 0.3.2 - resolution: "is-arrayish@npm:0.3.2" - checksum: 977e64f54d91c8f169b59afcd80ff19227e9f5c791fa28fa2e5bce355cbaf6c2c356711b734656e80c9dd4a854dd7efcf7894402f1031dfc5de5d620775b4d5f + version: 0.3.4 + resolution: "is-arrayish@npm:0.3.4" + checksum: 09816634eb7b6e357067f6b49c7656b4aff6d8b25486553d086bab53ce0f929c0293906539503b2a317f3137b5a5cd7e9ea01305f6090c0037c4340d9121420d languageName: node linkType: hard @@ -7208,7 +7316,7 @@ __metadata: languageName: node linkType: hard -"is-core-module@npm:^2.13.0, is-core-module@npm:^2.16.0, is-core-module@npm:^2.5.0": +"is-core-module@npm:^2.13.0, is-core-module@npm:^2.16.1, is-core-module@npm:^2.5.0": version: 2.16.1 resolution: "is-core-module@npm:2.16.1" dependencies: @@ -7301,14 +7409,15 @@ __metadata: linkType: hard "is-generator-function@npm:^1.0.10": - version: 1.1.0 - resolution: "is-generator-function@npm:1.1.0" + version: 1.1.2 + resolution: "is-generator-function@npm:1.1.2" dependencies: - call-bound: ^1.0.3 - get-proto: ^1.0.0 + call-bound: ^1.0.4 + generator-function: ^2.0.0 + get-proto: ^1.0.1 has-tostringtag: ^1.0.2 safe-regex-test: ^1.1.0 - checksum: f7f7276131bdf7e28169b86ac55a5b080012a597f9d85a0cbef6fe202a7133fa450a3b453e394870e3cb3685c5a764c64a9f12f614684b46969b1e6f297bed6b + checksum: 0b81c613752a5e534939e5b3835ff722446837a5b94c3a3934af5ded36a651d9aa31c3f11f8a3453884b9658bf26dbfb7eb855e744d920b07f084bd890a43414 languageName: node linkType: hard @@ -7392,10 +7501,17 @@ __metadata: languageName: node linkType: hard +"is-negative-zero@npm:^2.0.3": + version: 2.0.3 + resolution: "is-negative-zero@npm:2.0.3" + checksum: c1e6b23d2070c0539d7b36022d5a94407132411d01aba39ec549af824231f3804b1aea90b5e4e58e807a65d23ceb538ed6e355ce76b267bdd86edb757ffcbdcd + languageName: node + linkType: hard + "is-npm@npm:^6.0.0": - version: 6.0.0 - resolution: "is-npm@npm:6.0.0" - checksum: fafe1ddc772345f5460514891bb8014376904ccdbddd59eee7525c9adcc08d426933f28b087bef3e17524da7ebf35c03ef484ff3b6ba9d5fecd8c6e6a7d4bf11 + version: 6.1.0 + resolution: "is-npm@npm:6.1.0" + checksum: 54779c55419da537da77f0f41a409516148d09f1c6db9063ee6598783b309abab109ce4f540ef68c45f4dc1fec8600ed251e393029da31691fa93ce18e72243a languageName: node linkType: hard @@ -7518,7 +7634,7 @@ __metadata: languageName: node linkType: hard -"is-string@npm:^1.0.7, is-string@npm:^1.1.1": +"is-string@npm:^1.1.1": version: 1.1.1 resolution: "is-string@npm:1.1.1" dependencies: @@ -7594,7 +7710,7 @@ __metadata: languageName: node linkType: hard -"is-weakref@npm:^1.0.2, is-weakref@npm:^1.1.0": +"is-weakref@npm:^1.0.2, is-weakref@npm:^1.1.1": version: 1.1.1 resolution: "is-weakref@npm:1.1.1" dependencies: @@ -7652,13 +7768,6 @@ __metadata: languageName: node linkType: hard -"isarray@npm:~1.0.0": - version: 1.0.0 - resolution: "isarray@npm:1.0.0" - checksum: f032df8e02dce8ec565cf2eb605ea939bdccea528dbcf565cdf92bfa2da9110461159d86a537388ef1acef8815a330642d7885b29010e8f7eac967c9993b65ab - languageName: node - linkType: hard - "isexe@npm:^2.0.0": version: 2.0.0 resolution: "isexe@npm:2.0.0" @@ -7742,12 +7851,12 @@ __metadata: linkType: hard "istanbul-reports@npm:^3.1.3": - version: 3.1.7 - resolution: "istanbul-reports@npm:3.1.7" + version: 3.2.0 + resolution: "istanbul-reports@npm:3.2.0" dependencies: html-escaper: ^2.0.0 istanbul-lib-report: ^3.0.0 - checksum: 2072db6e07bfbb4d0eb30e2700250636182398c1af811aea5032acb219d2080f7586923c09fa194029efd6b92361afb3dcbe1ebcc3ee6651d13340f7c6c4ed95 + checksum: 72b4c8525276147908d28b0917bc675b1019836b638e50875521ca3b8ec63672681aa98dbab88a6f49ef798c08fe041d428abdcf84f4f3fcff5844eee54af65a languageName: node linkType: hard @@ -7881,6 +7990,18 @@ __metadata: languageName: node linkType: hard +"jest-diff@npm:30.2.0": + version: 30.2.0 + resolution: "jest-diff@npm:30.2.0" + dependencies: + "@jest/diff-sequences": 30.0.1 + "@jest/get-type": 30.1.0 + chalk: ^4.1.2 + pretty-format: 30.2.0 + checksum: 62fd17d3174316bf0140c2d342ac5ad84574763fa78fc4dd4e5ee605f121699033c9bfb7507ba8f1c5cc7fa95539a19abab13d3909a5aec1b447ab14d03c5386 + languageName: node + linkType: hard + "jest-diff@npm:^29.7.0": version: 29.7.0 resolution: "jest-diff@npm:29.7.0" @@ -7981,6 +8102,18 @@ __metadata: languageName: node linkType: hard +"jest-matcher-utils@npm:^30.0.5": + version: 30.2.0 + resolution: "jest-matcher-utils@npm:30.2.0" + dependencies: + "@jest/get-type": 30.1.0 + chalk: ^4.1.2 + jest-diff: 30.2.0 + pretty-format: 30.2.0 + checksum: 33154f3fc10b19608af7f8bc91eec129f9aba0a3d89f74ffbae659159c8e2dea69c85ef1d742b1d5dd6a8be57503d77d37351edc86ce9ef3f57ecc8585e0b154 + languageName: node + linkType: hard + "jest-message-util@npm:^29.7.0": version: 29.7.0 resolution: "jest-message-util@npm:29.7.0" @@ -8156,7 +8289,7 @@ __metadata: languageName: node linkType: hard -"jest-validate@npm:^29.6.3, jest-validate@npm:^29.7.0": +"jest-validate@npm:^29.7.0": version: 29.7.0 resolution: "jest-validate@npm:29.7.0" dependencies: @@ -8186,7 +8319,7 @@ __metadata: languageName: node linkType: hard -"jest-worker@npm:^29.6.3, jest-worker@npm:^29.7.0": +"jest-worker@npm:^29.7.0": version: 29.7.0 resolution: "jest-worker@npm:29.7.0" dependencies: @@ -8217,12 +8350,12 @@ __metadata: languageName: node linkType: hard -"jiti@npm:^2.4.1": - version: 2.4.2 - resolution: "jiti@npm:2.4.2" +"jiti@npm:^2.6.1": + version: 2.6.1 + resolution: "jiti@npm:2.6.1" bin: jiti: lib/jiti-cli.mjs - checksum: c6c30c7b6b293e9f26addfb332b63d964a9f143cdd2cf5e946dbe5143db89f7c1b50ad9223b77fb1f6ddb0b9c5ecef995fea024ecf7d2861d285d779cde66e1e + checksum: 9394e29c5e40d1ca8267923160d8d86706173c9ff30c901097883434b0c4866de2c060427b6a9a5843bb3e42fa3a3c8b5b2228531d3dd4f4f10c5c6af355bb86 languageName: node linkType: hard @@ -8269,13 +8402,6 @@ __metadata: languageName: node linkType: hard -"jsbn@npm:1.1.0": - version: 1.1.0 - resolution: "jsbn@npm:1.1.0" - checksum: 944f924f2bd67ad533b3850eee47603eed0f6ae425fd1ee8c760f477e8c34a05f144c1bd4f5a5dd1963141dc79a2c55f89ccc5ab77d039e7077f3ad196b64965 - languageName: node - linkType: hard - "jsc-safe-url@npm:^0.2.2": version: 0.2.4 resolution: "jsc-safe-url@npm:0.2.4" @@ -8283,7 +8409,7 @@ __metadata: languageName: node linkType: hard -"jsesc@npm:^3.0.2": +"jsesc@npm:^3.0.2, jsesc@npm:~3.1.0": version: 3.1.0 resolution: "jsesc@npm:3.1.0" bin: @@ -8292,15 +8418,6 @@ __metadata: languageName: node linkType: hard -"jsesc@npm:~3.0.2": - version: 3.0.2 - resolution: "jsesc@npm:3.0.2" - bin: - jsesc: bin/jsesc - checksum: a36d3ca40574a974d9c2063bf68c2b6141c20da8f2a36bd3279fc802563f35f0527a6c828801295bdfb2803952cf2cf387786c2c90ed564f88d5782475abfe3c - languageName: node - linkType: hard - "json-buffer@npm:3.0.1": version: 3.0.1 resolution: "json-buffer@npm:3.0.1" @@ -8365,15 +8482,15 @@ __metadata: linkType: hard "jsonfile@npm:^6.0.1": - version: 6.1.0 - resolution: "jsonfile@npm:6.1.0" + version: 6.2.0 + resolution: "jsonfile@npm:6.2.0" dependencies: graceful-fs: ^4.1.6 universalify: ^2.0.0 dependenciesMeta: graceful-fs: optional: true - checksum: 7af3b8e1ac8fe7f1eccc6263c6ca14e1966fcbc74b618d3c78a0a2075579487547b94f72b7a1114e844a1e15bb00d440e5d1720bfc4612d790a6f285d5ea8354 + checksum: c3028ec5c770bb41290c9bb9ca04bdd0a1b698ddbdf6517c9453d3f90fc9e000c9675959fb46891d317690a93c62de03ff1735d8dbe02be83e51168ce85815d3 languageName: node linkType: hard @@ -8427,9 +8544,9 @@ __metadata: linkType: hard "ky@npm:^1.2.0": - version: 1.8.1 - resolution: "ky@npm:1.8.1" - checksum: 802f3023ae1060b1d8c11376b9866fb5be82fa5174473d82c16a25d2905b3b41bc0121a134be87d8e3b40b24d56d34920a376e653785310803cbb8ea7cd43f85 + version: 1.14.0 + resolution: "ky@npm:1.14.0" + checksum: e4a3d7651953d823dc17021277349d0b61deb300d0cd77bbb495491e1d76cb3322a4aa6bc78d08146b696ba797d7367f7dcd4a42505399380f333ff74db38916 languageName: node linkType: hard @@ -8443,12 +8560,12 @@ __metadata: linkType: hard "launch-editor@npm:^2.9.1": - version: 2.10.0 - resolution: "launch-editor@npm:2.10.0" + version: 2.12.0 + resolution: "launch-editor@npm:2.12.0" dependencies: - picocolors: ^1.0.0 - shell-quote: ^1.8.1 - checksum: 0cd219f98a8be1cedc73119c1a18ff232eb1386dcc0f4e710b21234e62bf55513342a3e0939cd67c3d920fc7d714457876bc782a5b17e03f59acbbafd23c5f50 + picocolors: ^1.1.1 + shell-quote: ^1.8.3 + checksum: b1aa1b92ef4e720d1edd7f80affb90b2fa1cc2c41641cf80158940698c18a4b6a67e2a7cb060547712e858f0ec1a7c8c39f605e0eb299f516a6184f4e680ffc8 languageName: node linkType: hard @@ -8702,9 +8819,9 @@ __metadata: linkType: hard "macos-release@npm:^3.1.0": - version: 3.3.0 - resolution: "macos-release@npm:3.3.0" - checksum: 78a8ba70033a6a546537a04ba4a8a7e6daf00378d0a6cbdb7e8d09abdfab79f61a0da52fe6875d833c090e1d42a80964c349c96a735117b3a2bb1d278a86e563 + version: 3.4.0 + resolution: "macos-release@npm:3.4.0" + checksum: f4c0cb8b3f93b05d73c502b4bbe2b811c44facfc9bd072c13a30ff2a8ba1cad5d9de517d10be8b31e2b917643245a81587a2eec8300e66a7364419d11402ab02 languageName: node linkType: hard @@ -8835,151 +8952,69 @@ __metadata: languageName: node linkType: hard -"metro-babel-transformer@npm:0.80.12": - version: 0.80.12 - resolution: "metro-babel-transformer@npm:0.80.12" - dependencies: - "@babel/core": ^7.20.0 - flow-enums-runtime: ^0.0.6 - hermes-parser: 0.23.1 - nullthrows: ^1.1.1 - checksum: 1ea8bce0c169f3d8bf46f56da126ca52f4c8ba5ca9ffeaca987c34d269b0a3e2a54d0544bd44bfa5d0322e37f0171a52d2a2160defcbcd91ec1fd96f62b0eece - languageName: node - linkType: hard - -"metro-babel-transformer@npm:0.82.3": - version: 0.82.3 - resolution: "metro-babel-transformer@npm:0.82.3" +"metro-babel-transformer@npm:0.82.5": + version: 0.82.5 + resolution: "metro-babel-transformer@npm:0.82.5" dependencies: "@babel/core": ^7.25.2 flow-enums-runtime: ^0.0.6 - hermes-parser: 0.28.1 + hermes-parser: 0.29.1 nullthrows: ^1.1.1 - checksum: 0285de63ac0324297d0909241f8a9b793da1540287b15793157605a1d1d4ff62cd8b73caee50e8b0994083b961431c89cd7cd4c0ad8a0e6e1ae58d306c6602d1 - languageName: node - linkType: hard - -"metro-cache-key@npm:0.80.12": - version: 0.80.12 - resolution: "metro-cache-key@npm:0.80.12" - dependencies: - flow-enums-runtime: ^0.0.6 - checksum: 7a06601180604361339d19eb833d61b79cc188a4e6ebe73188cc10fbf3a33e711d74c81d1d19a14b6581bd9dfeebe1b253684360682d033ab55909c9995b6a18 - languageName: node - linkType: hard - -"metro-cache-key@npm:0.82.3": - version: 0.82.3 - resolution: "metro-cache-key@npm:0.82.3" - dependencies: - flow-enums-runtime: ^0.0.6 - checksum: fdb3c4e4b8c665cc5b74227b714201abff55dcff3039a83010088744362444bc6ae7cf16b6673125914120c0af91f6767de36569c202ca2539fafbc403bea082 + checksum: 3a3a8a9404c74290b5687290236e242f7b4edb3bc25cad6afe2424ddab8632a657b55ccbbd49dfa9b26078b5f3184f00930b8aa8b50d7c922247fd7d63ada395 languageName: node linkType: hard -"metro-cache@npm:0.80.12": - version: 0.80.12 - resolution: "metro-cache@npm:0.80.12" +"metro-cache-key@npm:0.82.5": + version: 0.82.5 + resolution: "metro-cache-key@npm:0.82.5" dependencies: - exponential-backoff: ^3.1.1 flow-enums-runtime: ^0.0.6 - metro-core: 0.80.12 - checksum: 724e33fdda6a3568572c36a3f2d3465ad1b5f3e8ded5ec116b98e0038826187ebdadd05f77e91ddc17fa71ff4dd91281793a940e7b619cac36044ed868abc01d + checksum: d5dcd86249905c7adad0375111a4bef395a5021df251a463f840eb21bf7b34f4e581ae919a88fb612a63c48a5f379ce50f104a576bd71e052693d89ae6a0d9f0 languageName: node linkType: hard -"metro-cache@npm:0.82.3": - version: 0.82.3 - resolution: "metro-cache@npm:0.82.3" +"metro-cache@npm:0.82.5": + version: 0.82.5 + resolution: "metro-cache@npm:0.82.5" dependencies: exponential-backoff: ^3.1.1 flow-enums-runtime: ^0.0.6 https-proxy-agent: ^7.0.5 - metro-core: 0.82.3 - checksum: 4d54317d65d95f5d6fae7c6403a8e1ca4c472e4b165f73cf462e883aa0bb754c3a38fbe6167283d6b57f0e3453cdb99ac0a286df3ed57a69cea6692adabb0b4b + metro-core: 0.82.5 + checksum: d0d193845063b1e1241a770d928630c68418b6bff2a25d7d14e71b88e905c640b65817ac069abf807b6e7c6db5470b8c52fe6236b3850ae55ce68e910747eb63 languageName: node linkType: hard -"metro-config@npm:0.80.12, metro-config@npm:^0.80.9": - version: 0.80.12 - resolution: "metro-config@npm:0.80.12" - dependencies: - connect: ^3.6.5 - cosmiconfig: ^5.0.5 - flow-enums-runtime: ^0.0.6 - jest-validate: ^29.6.3 - metro: 0.80.12 - metro-cache: 0.80.12 - metro-core: 0.80.12 - metro-runtime: 0.80.12 - checksum: 49496d2bc875fbb8c89639979753377888f5ce779742a4ef487d812e7c5f3f6c87dd6ae129727f614d2fe3210f7fde08041055d29772b8c86c018e2ef08e7785 - languageName: node - linkType: hard - -"metro-config@npm:0.82.3, metro-config@npm:^0.82.0": - version: 0.82.3 - resolution: "metro-config@npm:0.82.3" +"metro-config@npm:0.82.5, metro-config@npm:^0.82.0": + version: 0.82.5 + resolution: "metro-config@npm:0.82.5" dependencies: connect: ^3.6.5 cosmiconfig: ^5.0.5 flow-enums-runtime: ^0.0.6 jest-validate: ^29.7.0 - metro: 0.82.3 - metro-cache: 0.82.3 - metro-core: 0.82.3 - metro-runtime: 0.82.3 - checksum: 6dfafbc3de630e17799d742c672303e57dea7a2ee3eaf3404ce3692c50afd943d27e887ac02eeef3e733efddad7b594b2c644c2078f51afa95f611301021895a + metro: 0.82.5 + metro-cache: 0.82.5 + metro-core: 0.82.5 + metro-runtime: 0.82.5 + checksum: 641c88d795394e551fffe238670ad09f3c8637b45da767ee95c5b401e11b65d5a4e86694fb68bd13fde1fc148d9c4f738439a0a427fe5325bd36aa19ea7a5fc9 languageName: node linkType: hard -"metro-core@npm:0.80.12": - version: 0.80.12 - resolution: "metro-core@npm:0.80.12" +"metro-core@npm:0.82.5, metro-core@npm:^0.82.0": + version: 0.82.5 + resolution: "metro-core@npm:0.82.5" dependencies: flow-enums-runtime: ^0.0.6 lodash.throttle: ^4.1.1 - metro-resolver: 0.80.12 - checksum: 319f3965fa76fc08987cbd0228024bdbb0eaad7406e384e48929674188f1066cbc7a233053615ebd84b3ce1bbae28f59c114885fd0a0c179a580319ed69f717e - languageName: node - linkType: hard - -"metro-core@npm:0.82.3, metro-core@npm:^0.82.0": - version: 0.82.3 - resolution: "metro-core@npm:0.82.3" - dependencies: - flow-enums-runtime: ^0.0.6 - lodash.throttle: ^4.1.1 - metro-resolver: 0.82.3 - checksum: e61d316b6ff511d1524f923addbf8fb1bc8f0999ae3be7518a1cbdf39b0905d36e47d13cbebe029b5a1f0e88e8bd77bf75142af876e270af9de42d4dc1fe72e4 - languageName: node - linkType: hard - -"metro-file-map@npm:0.80.12": - version: 0.80.12 - resolution: "metro-file-map@npm:0.80.12" - dependencies: - anymatch: ^3.0.3 - debug: ^2.2.0 - fb-watchman: ^2.0.0 - flow-enums-runtime: ^0.0.6 - fsevents: ^2.3.2 - graceful-fs: ^4.2.4 - invariant: ^2.2.4 - jest-worker: ^29.6.3 - micromatch: ^4.0.4 - node-abort-controller: ^3.1.1 - nullthrows: ^1.1.1 - walker: ^1.0.7 - dependenciesMeta: - fsevents: - optional: true - checksum: 5e6eafcfafe55fd8a9a6e5613394a20ed2a0ad433a394dcb830f017b8fc9d82ddcd715391e36abe5e98c651c074b99a806d3b04d76f2cadb225f9f5b1c92daef + metro-resolver: 0.82.5 + checksum: f6f0c91240ad4ff2ebd61e5cb23f433309fc82e8042e240da1347f8edf61cc6b893bd176cabecad0dc91d214dd315d501af21cb518459aeb0ed613881619b583 languageName: node linkType: hard -"metro-file-map@npm:0.82.3": - version: 0.82.3 - resolution: "metro-file-map@npm:0.82.3" +"metro-file-map@npm:0.82.5": + version: 0.82.5 + resolution: "metro-file-map@npm:0.82.5" dependencies: debug: ^4.4.0 fb-watchman: ^2.0.0 @@ -8990,153 +9025,76 @@ __metadata: micromatch: ^4.0.4 nullthrows: ^1.1.1 walker: ^1.0.7 - checksum: 3a8f3022f1d8245ca1da5102134566c9096f1e3e320b50b73166f399bc19a811e86a6399c23e6515fbd90f37dc6ff2d3132ad5b3a017afa4b2c0966a1d4517fa + checksum: 46bda99f0ae892071c1b48b09f884f017f48d564c30b2a1f858f6fae1c6c1848bbbce20f66a5be086d7e0acfec3d8c1ddbf69699aaf2829f10954ae39d8a27d7 languageName: node linkType: hard -"metro-minify-terser@npm:0.80.12": - version: 0.80.12 - resolution: "metro-minify-terser@npm:0.80.12" +"metro-minify-terser@npm:0.82.5": + version: 0.82.5 + resolution: "metro-minify-terser@npm:0.82.5" dependencies: flow-enums-runtime: ^0.0.6 terser: ^5.15.0 - checksum: ff527b3f04c5814db139e55ceb7689aaaf0af5c7fbb0eb5d4a6f22044932dfb10bd385d388fa7b352acd03a2d078edaf43a6b5cd11cbc87a7c5502a34fc12735 + checksum: 754c150f0928460e1254e90e4e11bd87e069a0b286d21906758cb71fb8b4ec50dc8f78337bf8a9f8a28ddbd34230f5c66dad0fecf18dbe49715bf1300e5318c2 languageName: node linkType: hard -"metro-minify-terser@npm:0.82.3": - version: 0.82.3 - resolution: "metro-minify-terser@npm:0.82.3" +"metro-resolver@npm:0.82.5": + version: 0.82.5 + resolution: "metro-resolver@npm:0.82.5" dependencies: flow-enums-runtime: ^0.0.6 - terser: ^5.15.0 - checksum: 4f425549e5617e3dc39923c6e8ebb792da59bf9274934adaf8be90ea4fc9575780879fe4dc2802a5b2b75c2eb08761d8baf08d006384eb304e680e8e283d1a9e - languageName: node - linkType: hard - -"metro-resolver@npm:0.80.12": - version: 0.80.12 - resolution: "metro-resolver@npm:0.80.12" - dependencies: - flow-enums-runtime: ^0.0.6 - checksum: a520030a65afab2f3282604ef6dec802051899a356910606b8ffbc5b82a722008d9d416c8ba3d9ef9527912206586b713733b776803a6b76adac72bcb31870cd - languageName: node - linkType: hard - -"metro-resolver@npm:0.82.3": - version: 0.82.3 - resolution: "metro-resolver@npm:0.82.3" - dependencies: - flow-enums-runtime: ^0.0.6 - checksum: 910827413c331a7074a6d8530b5c976c1680a7c53c82c414b517832892977488f651b68dc08bd998de50cc41fb9dd416a17287926e5d78dd0e4739c3b4a247b1 + checksum: d1f7b57687c9cbb100114474689fee2fcfb86428a1228499b28391d16378573ac0f07c750874a2d75eabe237d67eb32a5c947bbbd70cd851885f1f6b13992472 languageName: node linkType: hard -"metro-runtime@npm:0.80.12": - version: 0.80.12 - resolution: "metro-runtime@npm:0.80.12" +"metro-runtime@npm:0.82.5, metro-runtime@npm:^0.82.0": + version: 0.82.5 + resolution: "metro-runtime@npm:0.82.5" dependencies: "@babel/runtime": ^7.25.0 flow-enums-runtime: ^0.0.6 - checksum: 11a6d36c7dcf9d221f7de6989556f45d4d64cd1cdd225ec96273b584138b4aa77b7afdc9e9a9488d1dc9a3d90f8e94bb68ab149079cc6ebdb8f8f8b03462cb4f - languageName: node - linkType: hard - -"metro-runtime@npm:0.82.3, metro-runtime@npm:^0.82.0": - version: 0.82.3 - resolution: "metro-runtime@npm:0.82.3" - dependencies: - "@babel/runtime": ^7.25.0 - flow-enums-runtime: ^0.0.6 - checksum: 6f7d9cd0cc5656dd22d6fa4409e278babf96937253045a0aa51fdb7f1c5d7259325583e27b81cc398bc847e1fe4ff6784e07df98633fd0368e07c2e289a088a7 - languageName: node - linkType: hard - -"metro-source-map@npm:0.80.12": - version: 0.80.12 - resolution: "metro-source-map@npm:0.80.12" - dependencies: - "@babel/traverse": ^7.20.0 - "@babel/types": ^7.20.0 - flow-enums-runtime: ^0.0.6 - invariant: ^2.2.4 - metro-symbolicate: 0.80.12 - nullthrows: ^1.1.1 - ob1: 0.80.12 - source-map: ^0.5.6 - vlq: ^1.0.0 - checksum: 39575bff8666abd0944ec71e01a0c0eacbeab48277528608e894ffa6691c4267c389ee51ad86d5cd8e96f13782b66e1f693a3c60786bb201268678232dce6130 + checksum: 931c2b581ac1527899cfec6b9c4bbbac75545c78bf192abd8efddd4dbff481b052513857c8544507e7900e7c06f08a8da75e16c864cd86ec3a8c3d6c05738dae languageName: node linkType: hard -"metro-source-map@npm:0.82.3, metro-source-map@npm:^0.82.0": - version: 0.82.3 - resolution: "metro-source-map@npm:0.82.3" +"metro-source-map@npm:0.82.5, metro-source-map@npm:^0.82.0": + version: 0.82.5 + resolution: "metro-source-map@npm:0.82.5" dependencies: "@babel/traverse": ^7.25.3 "@babel/traverse--for-generate-function-map": "npm:@babel/traverse@^7.25.3" "@babel/types": ^7.25.2 flow-enums-runtime: ^0.0.6 invariant: ^2.2.4 - metro-symbolicate: 0.82.3 + metro-symbolicate: 0.82.5 nullthrows: ^1.1.1 - ob1: 0.82.3 + ob1: 0.82.5 source-map: ^0.5.6 vlq: ^1.0.0 - checksum: 2222c9f970a48e8c8d4c001ef035c42d92bdadb10baeee3112774db4598fed4c861ae57f586b1d96508534f1c79dfd842f3c8493146088d10f224e549c48271a + checksum: 1bb53abe636524593207c578bfd0e15f47f4e15db919793a49b89359726d043cd69107244b6e1c2c8194983b8df7faa8b56ffa73a5f81c0fefc0cc1727907177 languageName: node linkType: hard -"metro-symbolicate@npm:0.80.12": - version: 0.80.12 - resolution: "metro-symbolicate@npm:0.80.12" +"metro-symbolicate@npm:0.82.5": + version: 0.82.5 + resolution: "metro-symbolicate@npm:0.82.5" dependencies: flow-enums-runtime: ^0.0.6 invariant: ^2.2.4 - metro-source-map: 0.80.12 + metro-source-map: 0.82.5 nullthrows: ^1.1.1 source-map: ^0.5.6 - through2: ^2.0.1 vlq: ^1.0.0 bin: metro-symbolicate: src/index.js - checksum: b775e4613deec421f6287918d0055c50bb2a38fe3f72581eb70b9441e4497c9c7413c2929c579b24fb76893737b6d5af83a5f6cd8c032e2a83957091f82ec5de - languageName: node - linkType: hard - -"metro-symbolicate@npm:0.82.3": - version: 0.82.3 - resolution: "metro-symbolicate@npm:0.82.3" - dependencies: - flow-enums-runtime: ^0.0.6 - invariant: ^2.2.4 - metro-source-map: 0.82.3 - nullthrows: ^1.1.1 - source-map: ^0.5.6 - vlq: ^1.0.0 - bin: - metro-symbolicate: src/index.js - checksum: a9563f71ca944ead08a1bdfa9e64778990ee9107af8dcb2ac5788cbcb78ac6478ef86da00db8e389b2253976d9b7ae4eae79d9c8a06a99d08b4e0ab1d7da2ffd - languageName: node - linkType: hard - -"metro-transform-plugins@npm:0.80.12": - version: 0.80.12 - resolution: "metro-transform-plugins@npm:0.80.12" - dependencies: - "@babel/core": ^7.20.0 - "@babel/generator": ^7.20.0 - "@babel/template": ^7.0.0 - "@babel/traverse": ^7.20.0 - flow-enums-runtime: ^0.0.6 - nullthrows: ^1.1.1 - checksum: 85c99c367d6c0b9721af744fc980372329c6d37711177660e2d5e2dbe5e92e2cd853604eb8a513ad824eafbed84663472fa304cbbe2036957ee8688b72c2324c + checksum: ae91be09cca42567ea3c2bee695e0db42512fc8bf28cf2aa281ae8043edc3bbddcadd0793b401b6bcb7e0cc1df1428647662462a8f515ab6c47420421b1e96f8 languageName: node linkType: hard -"metro-transform-plugins@npm:0.82.3": - version: 0.82.3 - resolution: "metro-transform-plugins@npm:0.82.3" +"metro-transform-plugins@npm:0.82.5": + version: 0.82.5 + resolution: "metro-transform-plugins@npm:0.82.5" dependencies: "@babel/core": ^7.25.2 "@babel/generator": ^7.25.0 @@ -9144,107 +9102,34 @@ __metadata: "@babel/traverse": ^7.25.3 flow-enums-runtime: ^0.0.6 nullthrows: ^1.1.1 - checksum: 66761639b7ceb6a6130332b3cd7ab124dac661e060f8f676c4abc1c132f35ce27f0a17ea993d7f053702833d61619e091418974fafaa3a130a707eb722268e1f + checksum: 891838d529df2c3170614de9e55025d37fb799a8d444d9e898fc203496ec33620ad8066e0ab06244b7abb806ffdae4728b84047d0d01bceee877ea5d69240d04 languageName: node linkType: hard -"metro-transform-worker@npm:0.80.12": - version: 0.80.12 - resolution: "metro-transform-worker@npm:0.80.12" - dependencies: - "@babel/core": ^7.20.0 - "@babel/generator": ^7.20.0 - "@babel/parser": ^7.20.0 - "@babel/types": ^7.20.0 - flow-enums-runtime: ^0.0.6 - metro: 0.80.12 - metro-babel-transformer: 0.80.12 - metro-cache: 0.80.12 - metro-cache-key: 0.80.12 - metro-minify-terser: 0.80.12 - metro-source-map: 0.80.12 - metro-transform-plugins: 0.80.12 - nullthrows: ^1.1.1 - checksum: 90684b1f1163bfc84b11bfc01082a38de2a5dd9f7bcabc524bc84f1faff32222954f686a60bc0f464d3e46e86c4c01435111e2ed0e9767a5efbfaf205f55245e - languageName: node - linkType: hard - -"metro-transform-worker@npm:0.82.3": - version: 0.82.3 - resolution: "metro-transform-worker@npm:0.82.3" +"metro-transform-worker@npm:0.82.5": + version: 0.82.5 + resolution: "metro-transform-worker@npm:0.82.5" dependencies: "@babel/core": ^7.25.2 "@babel/generator": ^7.25.0 "@babel/parser": ^7.25.3 "@babel/types": ^7.25.2 flow-enums-runtime: ^0.0.6 - metro: 0.82.3 - metro-babel-transformer: 0.82.3 - metro-cache: 0.82.3 - metro-cache-key: 0.82.3 - metro-minify-terser: 0.82.3 - metro-source-map: 0.82.3 - metro-transform-plugins: 0.82.3 + metro: 0.82.5 + metro-babel-transformer: 0.82.5 + metro-cache: 0.82.5 + metro-cache-key: 0.82.5 + metro-minify-terser: 0.82.5 + metro-source-map: 0.82.5 + metro-transform-plugins: 0.82.5 nullthrows: ^1.1.1 - checksum: 51ef31541c69caa07f90a2bc261326af7b88cfc54f4d238d71bf392a954dabad895d5f0125fa8d62d75041c09a20d0db15e4f76938b3750a7e2c293617080f21 + checksum: 653868f5fc525ad5b36181e7d1b3bb893c49ce6647791c21b585dd29cccc2f00e68d66b16e00eeb385fcb0c5f205a713aba0fe57971b1ab2bf150938cb820aaa languageName: node linkType: hard -"metro@npm:0.80.12": - version: 0.80.12 - resolution: "metro@npm:0.80.12" - dependencies: - "@babel/code-frame": ^7.0.0 - "@babel/core": ^7.20.0 - "@babel/generator": ^7.20.0 - "@babel/parser": ^7.20.0 - "@babel/template": ^7.0.0 - "@babel/traverse": ^7.20.0 - "@babel/types": ^7.20.0 - accepts: ^1.3.7 - chalk: ^4.0.0 - ci-info: ^2.0.0 - connect: ^3.6.5 - debug: ^2.2.0 - denodeify: ^1.2.1 - error-stack-parser: ^2.0.6 - flow-enums-runtime: ^0.0.6 - graceful-fs: ^4.2.4 - hermes-parser: 0.23.1 - image-size: ^1.0.2 - invariant: ^2.2.4 - jest-worker: ^29.6.3 - jsc-safe-url: ^0.2.2 - lodash.throttle: ^4.1.1 - metro-babel-transformer: 0.80.12 - metro-cache: 0.80.12 - metro-cache-key: 0.80.12 - metro-config: 0.80.12 - metro-core: 0.80.12 - metro-file-map: 0.80.12 - metro-resolver: 0.80.12 - metro-runtime: 0.80.12 - metro-source-map: 0.80.12 - metro-symbolicate: 0.80.12 - metro-transform-plugins: 0.80.12 - metro-transform-worker: 0.80.12 - mime-types: ^2.1.27 - nullthrows: ^1.1.1 - serialize-error: ^2.1.0 - source-map: ^0.5.6 - strip-ansi: ^6.0.0 - throat: ^5.0.0 - ws: ^7.5.10 - yargs: ^17.6.2 - bin: - metro: src/cli.js - checksum: 8016f7448e6e0947bd38633c01c3daad47b5a29d4a7294ebe922fa3c505430f78861d85965ecfc6f41d9b209e2663cac0f23c99a80a3f941a19de564203fcdb8 - languageName: node - linkType: hard - -"metro@npm:0.82.3, metro@npm:^0.82.0": - version: 0.82.3 - resolution: "metro@npm:0.82.3" +"metro@npm:0.82.5, metro@npm:^0.82.0": + version: 0.82.5 + resolution: "metro@npm:0.82.5" dependencies: "@babel/code-frame": ^7.24.7 "@babel/core": ^7.25.2 @@ -9261,24 +9146,24 @@ __metadata: error-stack-parser: ^2.0.6 flow-enums-runtime: ^0.0.6 graceful-fs: ^4.2.4 - hermes-parser: 0.28.1 + hermes-parser: 0.29.1 image-size: ^1.0.2 invariant: ^2.2.4 jest-worker: ^29.7.0 jsc-safe-url: ^0.2.2 lodash.throttle: ^4.1.1 - metro-babel-transformer: 0.82.3 - metro-cache: 0.82.3 - metro-cache-key: 0.82.3 - metro-config: 0.82.3 - metro-core: 0.82.3 - metro-file-map: 0.82.3 - metro-resolver: 0.82.3 - metro-runtime: 0.82.3 - metro-source-map: 0.82.3 - metro-symbolicate: 0.82.3 - metro-transform-plugins: 0.82.3 - metro-transform-worker: 0.82.3 + metro-babel-transformer: 0.82.5 + metro-cache: 0.82.5 + metro-cache-key: 0.82.5 + metro-config: 0.82.5 + metro-core: 0.82.5 + metro-file-map: 0.82.5 + metro-resolver: 0.82.5 + metro-runtime: 0.82.5 + metro-source-map: 0.82.5 + metro-symbolicate: 0.82.5 + metro-transform-plugins: 0.82.5 + metro-transform-worker: 0.82.5 mime-types: ^2.1.27 nullthrows: ^1.1.1 serialize-error: ^2.1.0 @@ -9288,7 +9173,7 @@ __metadata: yargs: ^17.6.2 bin: metro: src/cli.js - checksum: edd6647b20cfd0b9ca4b71a913acc76e0b11d93d960fdace97e1af550bfbcb3cbbcb77c6c2cbf0d5ee4072c3d566919ba33d22d29e0e2f35c4668848a8db4766 + checksum: 391411e1be9463f4d52e804f0a9680e59be1cfc5c76ca890f3a9e9c014561da65bbf6e3ccc44f7f52601add064b3b70862b3813c963384a0df2218a345a304e5 languageName: node linkType: hard @@ -9364,7 +9249,7 @@ __metadata: languageName: node linkType: hard -"min-indent@npm:^1.0.1": +"min-indent@npm:^1.0.0": version: 1.0.1 resolution: "min-indent@npm:1.0.1" checksum: bfc6dd03c5eaf623a4963ebd94d087f6f4bbbfd8c41329a7f09706b0cb66969c4ddd336abeb587bc44bc6f08e13bf90f0b374f9d71f9f01e04adc2cd6f083ef1 @@ -9372,11 +9257,11 @@ __metadata: linkType: hard "minimatch@npm:^10.0.1": - version: 10.0.3 - resolution: "minimatch@npm:10.0.3" + version: 10.1.1 + resolution: "minimatch@npm:10.1.1" dependencies: "@isaacs/brace-expansion": ^5.0.0 - checksum: 20bfb708095a321cb43c20b78254e484cb7d23aad992e15ca3234a3331a70fa9cd7a50bc1a7c7b2b9c9890c37ff0685f8380028fcc28ea5e6de75b1d4f9374aa + checksum: 8820c0be92994f57281f0a7a2cc4268dcc4b610f9a1ab666685716b4efe4b5898b43c835a8f22298875b31c7a278a5e3b7e253eee7c886546bb0b61fb94bca6b languageName: node linkType: hard @@ -9492,12 +9377,12 @@ __metadata: languageName: node linkType: hard -"minizlib@npm:^3.0.1": - version: 3.0.2 - resolution: "minizlib@npm:3.0.2" +"minizlib@npm:^3.0.1, minizlib@npm:^3.1.0": + version: 3.1.0 + resolution: "minizlib@npm:3.1.0" dependencies: minipass: ^7.1.2 - checksum: 493bed14dcb6118da7f8af356a8947cf1473289c09658e5aabd69a737800a8c3b1736fb7d7931b722268a9c9bc038a6d53c049b6a6af24b34a121823bb709996 + checksum: a15e6f0128f514b7d41a1c68ce531155447f4669e32d279bba1c1c071ef6c2abd7e4d4579bb59ccc2ed1531346749665968fdd7be8d83eb6b6ae2fe1f3d370a7 languageName: node linkType: hard @@ -9510,15 +9395,6 @@ __metadata: languageName: node linkType: hard -"mkdirp@npm:^3.0.1": - version: 3.0.1 - resolution: "mkdirp@npm:3.0.1" - bin: - mkdirp: dist/cjs/src/bin.js - checksum: 972deb188e8fb55547f1e58d66bd6b4a3623bf0c7137802582602d73e6480c1c2268dcbafbfb1be466e00cc7e56ac514d7fd9334b7cf33e3e2ab547c16f83a8d - languageName: node - linkType: hard - "ms@npm:2.0.0": version: 2.0.0 resolution: "ms@npm:2.0.0" @@ -9601,17 +9477,17 @@ __metadata: linkType: hard "nitrogen@npm:^0.31.3": - version: 0.31.3 - resolution: "nitrogen@npm:0.31.3" + version: 0.31.4 + resolution: "nitrogen@npm:0.31.4" dependencies: chalk: ^5.3.0 - react-native-nitro-modules: ^0.31.3 + react-native-nitro-modules: ^0.31.4 ts-morph: ^27.0.0 yargs: ^18.0.0 zod: ^4.0.5 bin: nitrogen: lib/index.js - checksum: 502be866220912eefbfc87108ae917c5325a37731b821d3da3c8de20d364395b570efa5c1fb89780853d866800a5c7b3ef05a3b17a477c54201622ba83c28b0b + checksum: 566abe01767d03860834b7b95093f1de5d7d7e010a556508e727afafc7476765d146452047adeee3aeaa5b0d361c504762695d8d3d6386e77f0091ff53e00d9c languageName: node linkType: hard @@ -9622,16 +9498,9 @@ __metadata: languageName: node linkType: hard -"node-abort-controller@npm:^3.1.1": - version: 3.1.1 - resolution: "node-abort-controller@npm:3.1.1" - checksum: 2c340916af9710328b11c0828223fc65ba320e0d082214a211311bf64c2891028e42ef276b9799188c4ada9e6e1c54cf7a0b7c05dd9d59fcdc8cd633304c8047 - languageName: node - linkType: hard - "node-gyp@npm:latest": - version: 11.2.0 - resolution: "node-gyp@npm:11.2.0" + version: 11.5.0 + resolution: "node-gyp@npm:11.5.0" dependencies: env-paths: ^2.2.0 exponential-backoff: ^3.1.1 @@ -9645,7 +9514,7 @@ __metadata: which: ^5.0.0 bin: node-gyp: bin/node-gyp.js - checksum: 2536282ba81f8a94b29482d3622b6ab298611440619e46de4512a6f32396a68b5530357c474b859787069d84a4c537d99e0c71078cce5b9f808bf84eeb78e8fb + checksum: 6cc29b9d454d9a684c8fe299668db618875bb4282e37717ca5b79689cc5ce99cd553c70944bb367979f2eba40ad6a50afaf7b12a6b214172edc7377384efa051 languageName: node linkType: hard @@ -9656,10 +9525,10 @@ __metadata: languageName: node linkType: hard -"node-releases@npm:^2.0.19": - version: 2.0.19 - resolution: "node-releases@npm:2.0.19" - checksum: 917dbced519f48c6289a44830a0ca6dc944c3ee9243c468ebd8515a41c97c8b2c256edb7f3f750416bc37952cc9608684e6483c7b6c6f39f6bd8d86c52cfe658 +"node-releases@npm:^2.0.26": + version: 2.0.27 + resolution: "node-releases@npm:2.0.27" + checksum: a9a54079d894704c2ec728a690b41fbc779a710f5d47b46fa3e460acff08a3e7dfa7108e5599b2db390aa31dac062c47c5118317201f12784188dc5b415f692d languageName: node linkType: hard @@ -9736,21 +9605,12 @@ __metadata: languageName: node linkType: hard -"ob1@npm:0.80.12": - version: 0.80.12 - resolution: "ob1@npm:0.80.12" +"ob1@npm:0.82.5": + version: 0.82.5 + resolution: "ob1@npm:0.82.5" dependencies: flow-enums-runtime: ^0.0.6 - checksum: c78af51d6ecf47ba5198bc7eb27d0456a287589533f1445e6d595e2d067f6f8038da02a98e5faa4a6c3d0c04f77c570bc9b29c652fec55518884c40c73212f17 - languageName: node - linkType: hard - -"ob1@npm:0.82.3": - version: 0.82.3 - resolution: "ob1@npm:0.82.3" - dependencies: - flow-enums-runtime: ^0.0.6 - checksum: 353bf489624f90c5029128ecd3ca5f8fbb68d334bcb27de06611e4a5b09b90473b860514aaa54eba2238b37b5fd53d51032a24d80494cd0b77e4d9b7f7a86553 + checksum: 3faa161e5b5307188b6bbbf7e21727b1e434b8f6c31c51386808b2efd5e7238cf85a7ce71416d9a3f073625afb5a2212f80ec267996dc88fe086944adbb525d9 languageName: node linkType: hard @@ -9761,7 +9621,7 @@ __metadata: languageName: node linkType: hard -"object-inspect@npm:^1.13.3": +"object-inspect@npm:^1.13.3, object-inspect@npm:^1.13.4": version: 1.13.4 resolution: "object-inspect@npm:1.13.4" checksum: 582810c6a8d2ef988ea0a39e69e115a138dad8f42dd445383b394877e5816eb4268489f316a6f74ee9c4e0a984b3eab1028e3e79d62b1ed67c726661d55c7a8b @@ -9843,10 +9703,10 @@ __metadata: languageName: node linkType: hard -"on-headers@npm:~1.0.2": - version: 1.0.2 - resolution: "on-headers@npm:1.0.2" - checksum: 2bf13467215d1e540a62a75021e8b318a6cfc5d4fc53af8e8f84ad98dbcea02d506c6d24180cd62e1d769c44721ba542f3154effc1f7579a8288c9f7873ed8e5 +"on-headers@npm:~1.1.0": + version: 1.1.0 + resolution: "on-headers@npm:1.1.0" + checksum: 98aa64629f986fb8cc4517dd8bede73c980e31208cba97f4442c330959f60ced3dc6214b83420491f5111fc7c4f4343abe2ea62c85f505cf041d67850f238776 languageName: node linkType: hard @@ -10264,7 +10124,7 @@ __metadata: languageName: node linkType: hard -"picocolors@npm:^1.0.0, picocolors@npm:^1.1.1": +"picocolors@npm:^1.1.1": version: 1.1.1 resolution: "picocolors@npm:1.1.1" checksum: e1cf46bf84886c79055fdfa9dcb3e4711ad259949e3565154b004b260cd356c5d54b31a1437ce9782624bf766272fe6b0154f5f0c744fb7af5d454d2b60db045 @@ -10278,13 +10138,6 @@ __metadata: languageName: node linkType: hard -"picomatch@npm:^4.0.2": - version: 4.0.2 - resolution: "picomatch@npm:4.0.2" - checksum: a7a5188c954f82c6585720e9143297ccd0e35ad8072231608086ca950bee672d51b0ef676254af0788205e59bd4e4deb4e7708769226bed725bf13370a7d1464 - languageName: node - linkType: hard - "picomatch@npm:^4.0.3": version: 4.0.3 resolution: "picomatch@npm:4.0.3" @@ -10332,11 +10185,22 @@ __metadata: linkType: hard "prettier@npm:^3.0.3": - version: 3.5.3 - resolution: "prettier@npm:3.5.3" + version: 3.6.2 + resolution: "prettier@npm:3.6.2" bin: prettier: bin/prettier.cjs - checksum: 61e97bb8e71a95d8f9c71f1fd5229c9aaa9d1e184dedb12399f76aa802fb6fdc8954ecac9df25a7f82ee7311cf8ddbd06baf5507388fc98e5b44036cc6a88a1b + checksum: 0206f5f437892e8858f298af8850bf9d0ef1c22e21107a213ba56bfb9c2387a2020bfda244a20161d8e3dad40c6b04101609a55d370dece53d0a31893b64f861 + languageName: node + linkType: hard + +"pretty-format@npm:30.2.0, pretty-format@npm:^30.0.5": + version: 30.2.0 + resolution: "pretty-format@npm:30.2.0" + dependencies: + "@jest/schemas": 30.0.5 + ansi-styles: ^5.2.0 + react-is: ^18.3.1 + checksum: 4c54f5ed8bcf450df9d5d70726c3373f26896845a9704f5a4a835913dacea794fabb5de4ab19fabb0d867de496f9fc8bf854ccdb661c45af334026308557d622 languageName: node linkType: hard @@ -10370,13 +10234,6 @@ __metadata: languageName: node linkType: hard -"process-nextick-args@npm:~2.0.0": - version: 2.0.1 - resolution: "process-nextick-args@npm:2.0.1" - checksum: 1d38588e520dab7cea67cbbe2efdd86a10cc7a074c09657635e34f035277b59fbb57d09d8638346bf7090f8e8ebc070c96fa5fd183b777fff4f5edff5e9466cf - languageName: node - linkType: hard - "promise-retry@npm:^2.0.1": version: 2.0.1 resolution: "promise-retry@npm:2.0.1" @@ -10455,12 +10312,12 @@ __metadata: linkType: hard "pump@npm:^3.0.0": - version: 3.0.2 - resolution: "pump@npm:3.0.2" + version: 3.0.3 + resolution: "pump@npm:3.0.3" dependencies: end-of-stream: ^1.1.0 once: ^1.3.1 - checksum: e0c4216874b96bd25ddf31a0b61a5613e26cc7afa32379217cf39d3915b0509def3565f5f6968fafdad2894c8bbdbd67d340e84f3634b2a29b950cffb6442d9f + checksum: 52843fc933b838c0330f588388115a1b28ef2a5ffa7774709b142e35431e8ab0c2edec90de3fa34ebb72d59fef854f151eea7dfc211b6dcf586b384556bd2f39 languageName: node linkType: hard @@ -10472,11 +10329,11 @@ __metadata: linkType: hard "pupa@npm:^3.1.0": - version: 3.1.0 - resolution: "pupa@npm:3.1.0" + version: 3.3.0 + resolution: "pupa@npm:3.3.0" dependencies: escape-goat: ^4.0.0 - checksum: 0e4f4ab6bbdce600fa6d23b1833f1af57b2641246ff4cbe10f9d66e4e5479b0de2864a88d5bd629eef59524eda3c6680726acd7f3f873d9ed46b7f095d0bb5f6 + checksum: a26b57cb4ff761495628b3630ab65fd97229d19314dbd9a08133d34f3f85fdb368da478f7b4a57647660c6d2973f0dae740668f8809c5861e3ede99e938ded05 languageName: node linkType: hard @@ -10565,12 +10422,23 @@ __metadata: linkType: hard "react-devtools-core@npm:^6.1.1": - version: 6.1.2 - resolution: "react-devtools-core@npm:6.1.2" + version: 6.1.5 + resolution: "react-devtools-core@npm:6.1.5" dependencies: shell-quote: ^1.6.1 ws: ^7 - checksum: aa72d4ad993af861088ead93bcce789dbf084a530a7723d94d3a040dad6cdb3fa46e14ff0d6e1c1c8f22713f30cf52505c6083f3c91b5114c1d90f7a3c2c1e43 + checksum: b54f2d2416f5f5ca61b1741367865eab18b0040d7e4b3236693595803dfdf82ae02adbcb480acc5b9767748b615a2d5ce3af286cde3a7f8c193123c62c777428 + languageName: node + linkType: hard + +"react-error-boundary@npm:^3.1.0": + version: 3.1.4 + resolution: "react-error-boundary@npm:3.1.4" + dependencies: + "@babel/runtime": ^7.12.5 + peerDependencies: + react: ">=16.13.1" + checksum: f36270a5d775a25c8920f854c0d91649ceea417b15b5bc51e270a959b0476647bb79abb4da3be7dd9a4597b029214e8fe43ea914a7f16fa7543c91f784977f1b languageName: node linkType: hard @@ -10588,23 +10456,23 @@ __metadata: languageName: node linkType: hard -"react-is@npm:^18.0.0": +"react-is@npm:^18.0.0, react-is@npm:^18.3.1": version: 18.3.1 resolution: "react-is@npm:18.3.1" checksum: e20fe84c86ff172fc8d898251b7cc2c43645d108bf96d0b8edf39b98f9a2cae97b40520ee7ed8ee0085ccc94736c4886294456033304151c3f94978cec03df21 languageName: node linkType: hard -"react-is@npm:^19.1.0": - version: 19.1.0 - resolution: "react-is@npm:19.1.0" - checksum: 3eb4eac7f09bf178bdc6fa98d384f5f243b85de7c99679a88b0154ead4d818ad94386ccb00ea31ec52409ffd13299057f5ec6ca2eaec06f9f7eddc1ad4832332 +"react-is@npm:^19.0.0, react-is@npm:^19.1.0": + version: 19.2.0 + resolution: "react-is@npm:19.2.0" + checksum: 9a23e1c2d0bbc13b383bc59a05f54e6eb95dd87e01aec8aa92a88618364b7b0ee8a5b057ad813cf61e2f7ae7d24503b624706acb609d07c54754e5ad2c522568 languageName: node linkType: hard "react-native-builder-bob@npm:^0.40.10": - version: 0.40.11 - resolution: "react-native-builder-bob@npm:0.40.11" + version: 0.40.14 + resolution: "react-native-builder-bob@npm:0.40.14" dependencies: "@babel/core": ^7.25.2 "@babel/plugin-transform-flow-strip-types": ^7.26.5 @@ -10624,20 +10492,19 @@ __metadata: is-git-dirty: ^2.0.1 json5: ^2.2.1 kleur: ^4.1.4 - metro-config: ^0.80.9 prompts: ^2.4.2 react-native-monorepo-config: ^0.1.8 which: ^2.0.2 yargs: ^17.5.1 bin: bob: bin/bob - checksum: a165c284bb9a938238c7fee526399b06d831dc6ce01762db466f79f768708536f34f0c01e01f49fae732bc160d6198a5499200fdb254b317ce04b69e1c814fdc + checksum: f7a95477535ccf749affb79f539faf925ff23a3864b0ad4fd4eb0e729f246e1c6357b392857156695d22005a60aa9f9f7bb773e2582f0e06b5c3f77e5258f00d languageName: node linkType: hard "react-native-gesture-handler@npm:^2.25.0": - version: 2.25.0 - resolution: "react-native-gesture-handler@npm:2.25.0" + 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 @@ -10645,27 +10512,27 @@ __metadata: peerDependencies: react: "*" react-native: "*" - checksum: 51b155bcc56043b9e06bf8ded089c44348e8da297b38e73f203f2d6ce8bd51698f85a38dca8eeab3d2ab721aeddefc270acd99e16cf493b20f1f429ad02214b8 + checksum: dddabdb12ce31d68ef71796e8fcaa57acd4608cca14412f36ce36fee14911fb629f325f0ced86bea1336a64673a434e34cde32a63be8d33f29d9a7bed292c5b2 languageName: node linkType: hard "react-native-monorepo-config@npm:^0.1.8": - version: 0.1.9 - resolution: "react-native-monorepo-config@npm:0.1.9" + version: 0.1.10 + resolution: "react-native-monorepo-config@npm:0.1.10" dependencies: escape-string-regexp: ^5.0.0 fast-glob: ^3.3.3 - checksum: 6356c362c517c49e17d54ee764c3566ba71491fa0d755618ecf2ca548348668e84fe448c24066645983acbc2bd4c0ed47594f9b3ec9dcc0558c0fd9594d2391e + checksum: 9b1c6fefb4d67e4a9f3f11554d33072c2112f56d578b8e9b68becc3457383e4f487f31af00d9e85cd43f0b23996c1b22e10cbec57e80c3fb2e4557a0e3db176d languageName: node linkType: hard -"react-native-nitro-modules@npm:^0.31.3": - version: 0.31.3 - resolution: "react-native-nitro-modules@npm:0.31.3" +"react-native-nitro-modules@npm:^0.31.3, react-native-nitro-modules@npm:^0.31.4": + version: 0.31.4 + resolution: "react-native-nitro-modules@npm:0.31.4" peerDependencies: react: "*" react-native: "*" - checksum: e7d87edc84a664d0aeb80fa1b01e53befc2ec86bd694ecd5f35bc9c97bdb050029b3396dc411fdd5ce7639e5d8c8c31bc3d7bd0804c640a7c44c963ceea5086a + checksum: 9d251ec788eafb5c66033a1f376e2a8f9dfc8962a22e8511f6451bc50bf324549fd4e5113ee5bed59a993c0afc3288e8722d854239a33c00faae26848a211fde languageName: node linkType: hard @@ -10679,6 +10546,7 @@ __metadata: "@react-native-community/cli": 18.0.0 "@react-native-community/cli-platform-android": 18.0.0 "@react-native-community/cli-platform-ios": 18.0.0 + "@react-native-picker/picker": ^2.11.4 "@react-native/babel-preset": 0.79.2 "@react-native/metro-config": 0.79.2 "@react-native/typescript-config": 0.79.2 @@ -10706,6 +10574,8 @@ __metadata: "@react-native/babel-preset": 0.79.2 "@react-native/eslint-config": ^0.78.0 "@release-it/conventional-changelog": ^9.0.2 + "@testing-library/react-hooks": ^8.0.1 + "@testing-library/react-native": ^13.3.3 "@types/jest": ^29.5.5 "@types/react": ^19.0.0 commitlint: ^19.6.1 @@ -10720,6 +10590,7 @@ __metadata: react-native: 0.79.2 react-native-builder-bob: ^0.40.10 react-native-nitro-modules: ^0.31.3 + react-test-renderer: 19.0.0 release-it: ^17.10.0 turbo: ^1.10.7 typescript: ^5.2.2 @@ -10731,12 +10602,12 @@ __metadata: linkType: soft "react-native-safe-area-context@npm:^5.4.0": - version: 5.4.0 - resolution: "react-native-safe-area-context@npm:5.4.0" + version: 5.6.2 + resolution: "react-native-safe-area-context@npm:5.6.2" peerDependencies: react: "*" react-native: "*" - checksum: 7d7f9a8278048650fd207d436798bd062d6f78d771cb0665b92aef69dba870251339e6812e1d669fd1958345288bd0f9ac98fbfe353c13958d18b58dc946c341 + checksum: 7b15cdd07df4f3650cf443fb322ee2d51b3ab45c652789cbea4cb48a8e6fd2b66e2be01e9f63e614ceaf28d9d228af681ca8857b2ed8dabe48f23964076d40c3 languageName: node linkType: hard @@ -10799,6 +10670,18 @@ __metadata: languageName: node linkType: hard +"react-test-renderer@npm:19.0.0": + version: 19.0.0 + resolution: "react-test-renderer@npm:19.0.0" + dependencies: + react-is: ^19.0.0 + scheduler: ^0.25.0 + peerDependencies: + react: ^19.0.0 + checksum: 2e1e527588c69e822b7aa25262c9f4a48161ede9cee5109b88228ecafbd91ce82f7afed176645efcba903ba5a43d05842a8229cdde220049e42a0cf679715dbc + languageName: node + linkType: hard + "react@npm:19.0.0": version: 19.0.0 resolution: "react@npm:19.0.0" @@ -10864,21 +10747,6 @@ __metadata: languageName: node linkType: hard -"readable-stream@npm:~2.3.6": - version: 2.3.8 - resolution: "readable-stream@npm:2.3.8" - dependencies: - core-util-is: ~1.0.0 - inherits: ~2.0.3 - isarray: ~1.0.0 - process-nextick-args: ~2.0.0 - safe-buffer: ~5.1.1 - string_decoder: ~1.1.1 - util-deprecate: ~1.0.1 - checksum: 65645467038704f0c8aaf026a72fbb588a9e2ef7a75cd57a01702ee9db1c4a1e4b03aaad36861a6a0926546a74d174149c8c207527963e0c2d3eee2f37678a42 - languageName: node - linkType: hard - "rechoir@npm:^0.6.2": version: 0.6.2 resolution: "rechoir@npm:0.6.2" @@ -10888,6 +10756,16 @@ __metadata: languageName: node linkType: hard +"redent@npm:^3.0.0": + version: 3.0.0 + resolution: "redent@npm:3.0.0" + dependencies: + indent-string: ^4.0.0 + strip-indent: ^3.0.0 + checksum: fa1ef20404a2d399235e83cc80bd55a956642e37dd197b4b612ba7327bf87fa32745aeb4a1634b2bab25467164ab4ed9c15be2c307923dd08b0fe7c52431ae6b + languageName: node + linkType: hard + "redent@npm:^4.0.0": version: 4.0.0 resolution: "redent@npm:4.0.0" @@ -10914,12 +10792,12 @@ __metadata: languageName: node linkType: hard -"regenerate-unicode-properties@npm:^10.2.0": - version: 10.2.0 - resolution: "regenerate-unicode-properties@npm:10.2.0" +"regenerate-unicode-properties@npm:^10.2.2": + version: 10.2.2 + resolution: "regenerate-unicode-properties@npm:10.2.2" dependencies: regenerate: ^1.4.2 - checksum: d5c5fc13f8b8d7e16e791637a4bfef741f8d70e267d51845ee7d5404a32fa14c75b181c4efba33e4bff8b0000a2f13e9773593713dfe5b66597df4259275ce63 + checksum: 7ae4c1c32460c4360e3118c45eec0621424908f430fdd6f162c9172067786bf2b1682fbc885a33b26bc85e76e06f4d3f398b52425e801b0bb0cbae147dafb0b2 languageName: node linkType: hard @@ -10937,7 +10815,7 @@ __metadata: languageName: node linkType: hard -"regexp.prototype.flags@npm:^1.5.3": +"regexp.prototype.flags@npm:^1.5.3, regexp.prototype.flags@npm:^1.5.4": version: 1.5.4 resolution: "regexp.prototype.flags@npm:1.5.4" dependencies: @@ -10951,17 +10829,17 @@ __metadata: languageName: node linkType: hard -"regexpu-core@npm:^6.2.0": - version: 6.2.0 - resolution: "regexpu-core@npm:6.2.0" +"regexpu-core@npm:^6.3.1": + version: 6.4.0 + resolution: "regexpu-core@npm:6.4.0" dependencies: regenerate: ^1.4.2 - regenerate-unicode-properties: ^10.2.0 + regenerate-unicode-properties: ^10.2.2 regjsgen: ^0.8.0 - regjsparser: ^0.12.0 + regjsparser: ^0.13.0 unicode-match-property-ecmascript: ^2.0.0 - unicode-match-property-value-ecmascript: ^2.1.0 - checksum: 67d3c4a3f6c99bc80b5d690074a27e6f675be1c1739f8a9acf028fbc36f1a468472574ea65e331e217995198ba4404d7878f3cb3739a73552dd3c70d3fb7f8e6 + unicode-match-property-value-ecmascript: ^2.2.1 + checksum: a316eb988599b7fb9d77f4adb937c41c022504dc91ddd18175c11771addc7f1d9dce550f34e36038395e459a2cf9ffc0d663bfe8d3c6c186317ca000ba79a8cf languageName: node linkType: hard @@ -10990,14 +10868,14 @@ __metadata: languageName: node linkType: hard -"regjsparser@npm:^0.12.0": - version: 0.12.0 - resolution: "regjsparser@npm:0.12.0" +"regjsparser@npm:^0.13.0": + version: 0.13.0 + resolution: "regjsparser@npm:0.13.0" dependencies: - jsesc: ~3.0.2 + jsesc: ~3.1.0 bin: regjsparser: bin/parser - checksum: 094b55b0ab3e1fd58f8ce5132a1d44dab08d91f7b0eea4132b0157b303ebb8ded20a9cbd893d25402d2aeddb23fac1f428ab4947b295d6fa51dd1c334a9e76f0 + checksum: 1cf09f6afde2b2d1c1e89e1ce3034e3ee8d9433912728dbaa48e123f5f43ce34e263b2a8ab228817dce85d676ee0c801a512101b015ac9ab80ed449cf7329d3a languageName: node linkType: hard @@ -11093,16 +10971,16 @@ __metadata: languageName: node linkType: hard -"resolve@npm:^1.1.6, resolve@npm:^1.14.2, resolve@npm:^1.20.0": - version: 1.22.10 - resolution: "resolve@npm:1.22.10" +"resolve@npm:^1.1.6, resolve@npm:^1.20.0, resolve@npm:^1.22.10": + version: 1.22.11 + resolution: "resolve@npm:1.22.11" dependencies: - is-core-module: ^2.16.0 + is-core-module: ^2.16.1 path-parse: ^1.0.7 supports-preserve-symlinks-flag: ^1.0.0 bin: resolve: bin/resolve - checksum: ab7a32ff4046fcd7c6fdd525b24a7527847d03c3650c733b909b01b757f92eb23510afa9cc3e9bf3f26a3e073b48c88c706dfd4c1d2fb4a16a96b73b6328ddcf + checksum: 6d5baa2156b95a65ac431e7642e21106584e9f4194da50871cae8bc1bbd2b53bb7cee573c92543d83bb999620b224a087f62379d800ed1ccb189da6df5d78d50 languageName: node linkType: hard @@ -11119,16 +10997,16 @@ __metadata: languageName: node linkType: hard -"resolve@patch:resolve@^1.1.6#~builtin, resolve@patch:resolve@^1.14.2#~builtin, resolve@patch:resolve@^1.20.0#~builtin": - version: 1.22.10 - resolution: "resolve@patch:resolve@npm%3A1.22.10#~builtin::version=1.22.10&hash=c3c19d" +"resolve@patch:resolve@^1.1.6#~builtin, resolve@patch:resolve@^1.20.0#~builtin, resolve@patch:resolve@^1.22.10#~builtin": + version: 1.22.11 + resolution: "resolve@patch:resolve@npm%3A1.22.11#~builtin::version=1.22.11&hash=c3c19d" dependencies: - is-core-module: ^2.16.0 + is-core-module: ^2.16.1 path-parse: ^1.0.7 supports-preserve-symlinks-flag: ^1.0.0 bin: resolve: bin/resolve - checksum: 8aac1e4e4628bd00bf4b94b23de137dd3fe44097a8d528fd66db74484be929936e20c696e1a3edf4488f37e14180b73df6f600992baea3e089e8674291f16c9d + checksum: 1462da84ac3410d7c2e12e4f5f25c1423d8a174c3b4245c43eafea85e7bbe6af3eb7ec10a4850b5e518e8531608604742b8cbd761e1acd7ad1035108b7c98013 languageName: node linkType: hard @@ -11198,9 +11076,9 @@ __metadata: linkType: hard "run-applescript@npm:^7.0.0": - version: 7.0.0 - resolution: "run-applescript@npm:7.0.0" - checksum: b02462454d8b182ad4117e5d4626e9e6782eb2072925c9fac582170b0627ae3c1ea92ee9b2df7daf84b5e9ffe14eb1cf5fb70bc44b15c8a0bfcdb47987e2410c + version: 7.1.0 + resolution: "run-applescript@npm:7.1.0" + checksum: 8659fb5f2717b2b37a68cbfe5f678254cf24b5a82a6df3372b180c80c7c137dcd757a4166c3887e459f59a090ca414e8ea7ca97cf3ee5123db54b3b4006d7b7a languageName: node linkType: hard @@ -11249,13 +11127,6 @@ __metadata: languageName: node linkType: hard -"safe-buffer@npm:~5.1.0, safe-buffer@npm:~5.1.1": - version: 5.1.2 - resolution: "safe-buffer@npm:5.1.2" - checksum: f2f1f7943ca44a594893a852894055cf619c1fbcb611237fc39e461ae751187e7baf4dc391a72125e0ac4fb2d8c5c0b3c71529622e6a58f46b960211e704903c - languageName: node - linkType: hard - "safe-push-apply@npm:^1.0.0": version: 1.0.0 resolution: "safe-push-apply@npm:1.0.0" @@ -11284,7 +11155,7 @@ __metadata: languageName: node linkType: hard -"scheduler@npm:0.25.0": +"scheduler@npm:0.25.0, scheduler@npm:^0.25.0": version: 0.25.0 resolution: "scheduler@npm:0.25.0" checksum: b7bb9fddbf743e521e9aaa5198a03ae823f5e104ebee0cb9ec625392bb7da0baa1c28ab29cee4b1e407a94e76acc6eee91eeb749614f91f853efda2613531566 @@ -11310,11 +11181,11 @@ __metadata: linkType: hard "semver@npm:^7.1.3, semver@npm:^7.3.4, semver@npm:^7.3.5, semver@npm:^7.3.7, semver@npm:^7.5.2, semver@npm:^7.5.3, semver@npm:^7.5.4, semver@npm:^7.6.0, semver@npm:^7.6.3": - version: 7.7.2 - resolution: "semver@npm:7.7.2" + version: 7.7.3 + resolution: "semver@npm:7.7.3" bin: semver: bin/semver.js - checksum: dd94ba8f1cbc903d8eeb4dd8bf19f46b3deb14262b6717d0de3c804b594058ae785ef2e4b46c5c3b58733c99c83339068203002f9e37cfe44f7e2cc5e3d2f621 + checksum: f013a3ee4607857bcd3503b6ac1d80165f7f8ea94f5d55e2d3e33df82fce487aa3313b987abf9b39e0793c83c9fc67b76c36c067625141a9f6f704ae0ea18db2 languageName: node linkType: hard @@ -11425,10 +11296,10 @@ __metadata: languageName: node linkType: hard -"shell-quote@npm:^1.6.1, shell-quote@npm:^1.8.1": - version: 1.8.2 - resolution: "shell-quote@npm:1.8.2" - checksum: 1e97b62ced1c4c5135015978ebf273bed1f425a68cf84163e83fbb0f34b3ff9471e656720dab2b7cbb4ae0f58998e686d17d166c28dfb3662acd009e8bd7faed +"shell-quote@npm:^1.6.1, shell-quote@npm:^1.8.3": + version: 1.8.3 + resolution: "shell-quote@npm:1.8.3" + checksum: 550dd84e677f8915eb013d43689c80bb114860649ec5298eb978f40b8f3d4bc4ccb072b82c094eb3548dc587144bb3965a8676f0d685c1cf4c40b5dc27166242 languageName: node linkType: hard @@ -11508,11 +11379,11 @@ __metadata: linkType: hard "simple-swizzle@npm:^0.2.2": - version: 0.2.2 - resolution: "simple-swizzle@npm:0.2.2" + version: 0.2.4 + resolution: "simple-swizzle@npm:0.2.4" dependencies: is-arrayish: ^0.3.1 - checksum: a7f3f2ab5c76c4472d5c578df892e857323e452d9f392e1b5cf74b74db66e6294a1e1b8b390b519fa1b96b5b613f2a37db6cffef52c3f1f8f3c5ea64eb2d54c0 + checksum: 9a2f6f39a6b9fab68f96903523bf19953ec21e5e843108154cf47a9cc0f78955dd44f64499ffb71a849ac10c758d9fab7533627c7ca3ab40b5c177117acfdc1b languageName: node linkType: hard @@ -11574,12 +11445,12 @@ __metadata: linkType: hard "socks@npm:^2.8.3": - version: 2.8.4 - resolution: "socks@npm:2.8.4" + version: 2.8.7 + resolution: "socks@npm:2.8.7" dependencies: - ip-address: ^9.0.5 + ip-address: ^10.0.1 smart-buffer: ^4.2.0 - checksum: cd1edc924475d5dfde534adf66038df7e62c7343e6b8c0113e52dc9bb6a0a10e25b2f136197f379d695f18e8f0f2b7f6e42977bf720ddbee912a851201c396ad + checksum: 4bbe2c88cf0eeaf49f94b7f11564a99b2571bde6fd1e714ff95b38f89e1f97858c19e0ab0e6d39eb7f6a984fa67366825895383ed563fe59962a1d57a1d55318 languageName: node linkType: hard @@ -11645,9 +11516,9 @@ __metadata: linkType: hard "spdx-license-ids@npm:^3.0.0": - version: 3.0.21 - resolution: "spdx-license-ids@npm:3.0.21" - checksum: 681dfe26d250f48cc725c9118adf1eb0a175e3c298cd8553c039bfae37ed21bea30a27bc02dbb99b4a0d3a25c644c5dda952090e11ef4b3093f6ec7db4b93b58 + version: 3.0.22 + resolution: "spdx-license-ids@npm:3.0.22" + checksum: 3810ce1ddd8c67d7cfa76a0af05157090a2d93e5bb93bd85bf9735f1fd8062c5b510423a4669dc7d8c34b0892b27a924b1c6f8965f85d852aa25062cceff5e29 languageName: node linkType: hard @@ -11665,13 +11536,6 @@ __metadata: languageName: node linkType: hard -"sprintf-js@npm:^1.1.3": - version: 1.1.3 - resolution: "sprintf-js@npm:1.1.3" - checksum: a3fdac7b49643875b70864a9d9b469d87a40dfeaf5d34d9d0c5b1cda5fd7d065531fcb43c76357d62254c57184a7b151954156563a4d6a747015cfb41021cad0 - languageName: node - linkType: hard - "sprintf-js@npm:~1.0.2": version: 1.0.3 resolution: "sprintf-js@npm:1.0.3" @@ -11734,6 +11598,16 @@ __metadata: languageName: node linkType: hard +"stop-iteration-iterator@npm:^1.1.0": + version: 1.1.0 + resolution: "stop-iteration-iterator@npm:1.1.0" + dependencies: + es-errors: ^1.3.0 + internal-slot: ^1.1.0 + checksum: be944489d8829fb3bdec1a1cc4a2142c6b6eb317305eeace1ece978d286d6997778afa1ae8cb3bd70e2b274b9aa8c69f93febb1e15b94b1359b11058f9d3c3a1 + languageName: node + linkType: hard + "strict-uri-encode@npm:^2.0.0": version: 2.0.0 resolution: "strict-uri-encode@npm:2.0.0" @@ -11869,15 +11743,6 @@ __metadata: languageName: node linkType: hard -"string_decoder@npm:~1.1.1": - version: 1.1.1 - resolution: "string_decoder@npm:1.1.1" - dependencies: - safe-buffer: ~5.1.0 - checksum: 9ab7e56f9d60a28f2be697419917c50cac19f3e8e6c28ef26ed5f4852289fe0de5d6997d29becf59028556f2c62983790c1d9ba1e2a3cc401768ca12d5183a5b - languageName: node - linkType: hard - "strip-ansi-cjs@npm:strip-ansi@^6.0.1, strip-ansi@npm:^6.0.0, strip-ansi@npm:^6.0.1": version: 6.0.1 resolution: "strip-ansi@npm:6.0.1" @@ -11897,11 +11762,11 @@ __metadata: linkType: hard "strip-ansi@npm:^7.0.1, strip-ansi@npm:^7.1.0": - version: 7.1.0 - resolution: "strip-ansi@npm:7.1.0" + version: 7.1.2 + resolution: "strip-ansi@npm:7.1.2" dependencies: ansi-regex: ^6.0.1 - checksum: 859c73fcf27869c22a4e4d8c6acfe690064659e84bef9458aa6d13719d09ca88dcfd40cbf31fd0be63518ea1a643fe070b4827d353e09533a5b0b9fd4553d64d + checksum: db0e3f9654e519c8a33c50fc9304d07df5649388e7da06d3aabf66d29e5ad65d5e6315d8519d409c15b32fa82c1df7e11ed6f8cd50b0e4404463f0c9d77c8d0b languageName: node linkType: hard @@ -11926,12 +11791,19 @@ __metadata: languageName: node linkType: hard -"strip-indent@npm:^4.0.0": - version: 4.0.0 - resolution: "strip-indent@npm:4.0.0" +"strip-indent@npm:^3.0.0": + version: 3.0.0 + resolution: "strip-indent@npm:3.0.0" dependencies: - min-indent: ^1.0.1 - checksum: 06cbcd93da721c46bc13caeb1c00af93a9b18146a1c95927672d2decab6a25ad83662772417cea9317a2507fb143253ecc23c4415b64f5828cef9b638a744598 + min-indent: ^1.0.0 + checksum: 18f045d57d9d0d90cd16f72b2313d6364fd2cb4bf85b9f593523ad431c8720011a4d5f08b6591c9d580f446e78855c5334a30fb91aa1560f5d9f95ed1b4a0530 + languageName: node + linkType: hard + +"strip-indent@npm:^4.0.0": + version: 4.1.1 + resolution: "strip-indent@npm:4.1.1" + checksum: d322bfdc59855006791a4aebe2a66e0892eab7004a5c064d74b86a0c6ecff2818974c9a5eda54b16d8af6aadbc90a6c02635ffcbec11ab33dd8979b1a6346fc0 languageName: node linkType: hard @@ -11956,10 +11828,19 @@ __metadata: languageName: node linkType: hard -"stubborn-fs@npm:^1.2.5": - version: 1.2.5 - resolution: "stubborn-fs@npm:1.2.5" - checksum: 28d197afec1ec21ce7ffb06a42f01db19beecdf491694c53393ff5d92ec8a300df9c357e09a16d5cf55747ee2a70bc3c788b9e5577696061ffb9ae279655a600 +"stubborn-fs@npm:^2.0.0": + version: 2.0.0 + resolution: "stubborn-fs@npm:2.0.0" + dependencies: + stubborn-utils: ^1.0.1 + checksum: ead3401b9487d6fba35625e7349b36bda0c1850bf3c14cac96bd61e520dc4bc326e3e45f4ec1a4fa74f6c5688ba1690b8bae25baeedd1c3f4803bd39f7fbd935 + languageName: node + linkType: hard + +"stubborn-utils@npm:^1.0.1": + version: 1.0.2 + resolution: "stubborn-utils@npm:1.0.2" + checksum: 49f6b5b0f7c5565b0946905c4200f6b58dc614f9c52d7e246fac43f061b4e68e0ba274366a6d6d080e796c014da0de2ceb04b0046e5aea9cfe26365a9dac4190 languageName: node linkType: hard @@ -11988,40 +11869,39 @@ __metadata: languageName: node linkType: hard -"synckit@npm:^0.11.0": - version: 0.11.6 - resolution: "synckit@npm:0.11.6" +"synckit@npm:^0.11.7": + version: 0.11.11 + resolution: "synckit@npm:0.11.11" dependencies: - "@pkgr/core": ^0.2.4 - checksum: ce910d27ee1b30ff961905e5d63d60e2cede4f33cd3dc7b46988989f83ac33b3020a193ec8121af9c999b68aa90c01ec42121ebf9fe4356cc6406b9ff037f180 + "@pkgr/core": ^0.2.9 + checksum: bc896d4320525501495654766e6b0aa394e522476ea0547af603bdd9fd7e9b65dcd6e3a237bc7eb3ab7e196376712f228bf1bf6ed1e1809f4b32dc9baf7ad413 languageName: node linkType: hard "tar@npm:^7.4.3": - version: 7.4.3 - resolution: "tar@npm:7.4.3" + version: 7.5.2 + resolution: "tar@npm:7.5.2" dependencies: "@isaacs/fs-minipass": ^4.0.0 chownr: ^3.0.0 minipass: ^7.1.2 - minizlib: ^3.0.1 - mkdirp: ^3.0.1 + minizlib: ^3.1.0 yallist: ^5.0.0 - checksum: 8485350c0688331c94493031f417df069b778aadb25598abdad51862e007c39d1dd5310702c7be4a6784731a174799d8885d2fde0484269aea205b724d7b2ffa + checksum: 192559b0e7af17d57c7747592ef22c14d5eba2d9c35996320ccd20c3e2038160fe8d928fc5c08b2aa1b170c4d0a18c119441e81eae8f227ca2028d5bcaa6bf23 languageName: node linkType: hard "terser@npm:^5.15.0": - version: 5.39.2 - resolution: "terser@npm:5.39.2" + version: 5.44.0 + resolution: "terser@npm:5.44.0" dependencies: "@jridgewell/source-map": ^0.3.3 - acorn: ^8.14.0 + acorn: ^8.15.0 commander: ^2.20.0 source-map-support: ~0.5.20 bin: terser: bin/terser - checksum: 986a47896503c5bc6475c751d9445d4326de2e6f8b0be2c943b7726426ad0fe2385aacb9dce1dbc3aee13171595a0234411479bc855e6c730a51f23175132c84 + checksum: 4e1868d9662ea280dad7b49cfe61b7693187be2b529b31b1f86782db00833c03ba05f2b82fc513d928e937260f2a5fbf42a93724e86eaf55f069288f934ccdb3 languageName: node linkType: hard @@ -12050,16 +11930,6 @@ __metadata: languageName: node linkType: hard -"through2@npm:^2.0.1": - version: 2.0.5 - resolution: "through2@npm:2.0.5" - dependencies: - readable-stream: ~2.3.6 - xtend: ~4.0.1 - checksum: beb0f338aa2931e5660ec7bf3ad949e6d2e068c31f4737b9525e5201b824ac40cac6a337224856b56bd1ddd866334bbfb92a9f57cd6f66bc3f18d3d86fc0fe50 - languageName: node - linkType: hard - "through@npm:>=2.2.7 <3": version: 2.3.8 resolution: "through@npm:2.3.8" @@ -12068,23 +11938,13 @@ __metadata: linkType: hard "tinyexec@npm:^1.0.0": - version: 1.0.1 - resolution: "tinyexec@npm:1.0.1" - checksum: 40f5219abf891884863b085ebe5e8c8bf95bde802f6480f279588b355835ad1604fa01eada2afe90063b48b53cd4b0be5c37393980e23f06fd10689d92fb9586 - languageName: node - linkType: hard - -"tinyglobby@npm:^0.2.12": - version: 0.2.13 - resolution: "tinyglobby@npm:0.2.13" - dependencies: - fdir: ^6.4.4 - picomatch: ^4.0.2 - checksum: 3a2e87a2518cb3616057b0aa58be4f17771ae78c6890556516ae1e631f8ce4cfee1ba1dcb62fcc54a64e2bdd6c3104f4f3d021e1a3e3f8fb0875bca380b913e5 + version: 1.0.2 + resolution: "tinyexec@npm:1.0.2" + checksum: af22de2191cc70bb782eef29bbba7cf6ac16664e550b547b0db68804f988eeb2c70e12fbb7d2d688ee994b28ba831d746e9eded98c3d10042fd3a9b8de208514 languageName: node linkType: hard -"tinyglobby@npm:^0.2.14": +"tinyglobby@npm:^0.2.12, tinyglobby@npm:^0.2.14": version: 0.2.15 resolution: "tinyglobby@npm:0.2.15" dependencies: @@ -12370,22 +12230,22 @@ __metadata: linkType: hard "typescript@npm:^5.2.2": - version: 5.8.3 - resolution: "typescript@npm:5.8.3" + version: 5.9.3 + resolution: "typescript@npm:5.9.3" bin: tsc: bin/tsc tsserver: bin/tsserver - checksum: cb1d081c889a288b962d3c8ae18d337ad6ee88a8e81ae0103fa1fecbe923737f3ba1dbdb3e6d8b776c72bc73bfa6d8d850c0306eed1a51377d2fccdfd75d92c4 + checksum: 0d0ffb84f2cd072c3e164c79a2e5a1a1f4f168e84cb2882ff8967b92afe1def6c2a91f6838fb58b168428f9458c57a2ba06a6737711fdd87a256bbe83e9a217f languageName: node linkType: hard "typescript@patch:typescript@^5.2.2#~builtin": - version: 5.8.3 - resolution: "typescript@patch:typescript@npm%3A5.8.3#~builtin::version=5.8.3&hash=14eedb" + version: 5.9.3 + resolution: "typescript@patch:typescript@npm%3A5.9.3#~builtin::version=5.9.3&hash=14eedb" bin: tsc: bin/tsc tsserver: bin/tsserver - checksum: 1b503525a88ff0ff5952e95870971c4fb2118c17364d60302c21935dedcd6c37e6a0a692f350892bafcef6f4a16d09073fe461158547978d2f16fbe4cb18581c + checksum: 8bb8d86819ac86a498eada254cad7fb69c5f74778506c700c2a712daeaff21d3a6f51fd0d534fe16903cb010d1b74f89437a3d02d4d0ff5ca2ba9a4660de8497 languageName: node linkType: hard @@ -12417,10 +12277,10 @@ __metadata: languageName: node linkType: hard -"undici-types@npm:~6.21.0": - version: 6.21.0 - resolution: "undici-types@npm:6.21.0" - checksum: 46331c7d6016bf85b3e8f20c159d62f5ae471aba1eb3dc52fff35a0259d58dcc7d592d4cc4f00c5f9243fa738a11cfa48bd20203040d4a9e6bc25e807fab7ab3 +"undici-types@npm:~7.16.0": + version: 7.16.0 + resolution: "undici-types@npm:7.16.0" + checksum: 1ef68fc6c5bad200c8b6f17de8e5bc5cfdcadc164ba8d7208cd087cfa8583d922d8316a7fd76c9a658c22b4123d3ff847429185094484fbc65377d695c905857 languageName: node linkType: hard @@ -12441,17 +12301,17 @@ __metadata: languageName: node linkType: hard -"unicode-match-property-value-ecmascript@npm:^2.1.0": - version: 2.2.0 - resolution: "unicode-match-property-value-ecmascript@npm:2.2.0" - checksum: 9e3151e1d0bc6be35c4cef105e317c04090364173e8462005b5cde08a1e7c858b6586486cfebac39dc2c6c8c9ee24afb245de6d527604866edfa454fe2a35fae +"unicode-match-property-value-ecmascript@npm:^2.2.1": + version: 2.2.1 + resolution: "unicode-match-property-value-ecmascript@npm:2.2.1" + checksum: e6c73e07bb4dc4aa399797a14b170e84a30ed290bcf97cc4305cf67dde8744119721ce17cef03f4f9d4ff48654bfa26eadc7fe1e8dd4b71b8f3b2e9a9742f013 languageName: node linkType: hard "unicode-property-aliases-ecmascript@npm:^2.0.0": - version: 2.1.0 - resolution: "unicode-property-aliases-ecmascript@npm:2.1.0" - checksum: 243524431893649b62cc674d877bd64ef292d6071dd2fd01ab4d5ad26efbc104ffcd064f93f8a06b7e4ec54c172bf03f6417921a0d8c3a9994161fe1f88f815b + version: 2.2.0 + resolution: "unicode-property-aliases-ecmascript@npm:2.2.0" + checksum: 0dd0f6e70130c59b4a841bac206758f70227b113145e4afe238161e3e8540e8eb79963e7a228cd90ad13d499e96f7ef4ee8940835404b2181ad9bf9c174818e3 languageName: node linkType: hard @@ -12508,9 +12368,9 @@ __metadata: languageName: node linkType: hard -"update-browserslist-db@npm:^1.1.3": - version: 1.1.3 - resolution: "update-browserslist-db@npm:1.1.3" +"update-browserslist-db@npm:^1.1.4": + version: 1.1.4 + resolution: "update-browserslist-db@npm:1.1.4" dependencies: escalade: ^3.2.0 picocolors: ^1.1.1 @@ -12518,7 +12378,7 @@ __metadata: browserslist: ">= 4.21.0" bin: update-browserslist-db: cli.js - checksum: 7b6d8d08c34af25ee435bccac542bedcb9e57c710f3c42421615631a80aa6dd28b0a81c9d2afbef53799d482fb41453f714b8a7a0a8003e3b4ec8fb1abb819af + checksum: b757805a63d7954985753c97a48e313abd2d35f2bb10d2bffa65d73a4b81ec9e1305a7b06296819bac8a6b4db8e7be88582487fae2ad7e24731e4ee372b919a6 languageName: node linkType: hard @@ -12556,25 +12416,25 @@ __metadata: languageName: node linkType: hard -"use-latest-callback@npm:^0.2.3": - version: 0.2.3 - resolution: "use-latest-callback@npm:0.2.3" +"use-latest-callback@npm:^0.2.4": + version: 0.2.6 + resolution: "use-latest-callback@npm:0.2.6" peerDependencies: react: ">=16.8" - checksum: 5db2dc0d414508c768ba4d1a337bd73dd0fb2a77eccc9dd7051517b28cd71c849c5e9230b5c97fc76a3811c1500f210cb4e4ebb95fe20347e5f910509a8e533c + checksum: 67a245bf91b23ef0d2d2c8a52845da62e006867bd9d93a99ca4d2f859101fcd54c7afd4f5a3b8bb5d24283f516e7e41bd8226250ee39affc33bd1cfd622a5cfb languageName: node linkType: hard "use-sync-external-store@npm:^1.5.0": - version: 1.5.0 - resolution: "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: 5e639c9273200adb6985b512c96a3a02c458bc8ca1a72e91da9cdc6426144fc6538dca434b0f99b28fb1baabc82e1c383ba7900b25ccdcb43758fb058dc66c34 + checksum: 61a62e910713adfaf91bdb72ff2cd30e5ba83687accaf3b6e75a903b45bf635f5722e3694af30d83a03e92cb533c0a5c699298d2fef639a03ffc86b469f4eee2 languageName: node linkType: hard -"util-deprecate@npm:^1.0.1, util-deprecate@npm:~1.0.1": +"util-deprecate@npm:^1.0.1": version: 1.0.2 resolution: "util-deprecate@npm:1.0.2" checksum: 474acf1146cb2701fe3b074892217553dfcf9a031280919ba1b8d651a068c9b15d863b7303cb15bd00a862b498e6cf4ad7b4a08fb134edd5a6f7641681cb54a2 @@ -12648,10 +12508,10 @@ __metadata: languageName: node linkType: hard -"when-exit@npm:^2.1.1": - version: 2.1.4 - resolution: "when-exit@npm:2.1.4" - checksum: d77635a0ed43bb63b3b41930637db16fb1e4e8630f5c6efd4aa669322c32b36ba750b7484991f806d3ac56f4e21cdf3925f82fff289b90706cc21e6745038a26 +"when-exit@npm:^2.1.4": + version: 2.1.5 + resolution: "when-exit@npm:2.1.5" + checksum: 94f0ca73dcbaac51e61bcf178268e82bd5b29c3ed45fc154807893d803b220bb15e234cf18b5f392c88e87acf33f0b72dc27c265f8cfdf371121c30d49686966 languageName: node linkType: hard @@ -12708,7 +12568,7 @@ __metadata: languageName: node linkType: hard -"which-typed-array@npm:^1.1.16, which-typed-array@npm:^1.1.18": +"which-typed-array@npm:^1.1.16, which-typed-array@npm:^1.1.19": version: 1.1.19 resolution: "which-typed-array@npm:1.1.19" dependencies: @@ -12818,13 +12678,13 @@ __metadata: linkType: hard "wrap-ansi@npm:^9.0.0": - version: 9.0.0 - resolution: "wrap-ansi@npm:9.0.0" + version: 9.0.2 + resolution: "wrap-ansi@npm:9.0.2" dependencies: ansi-styles: ^6.2.1 string-width: ^7.0.0 strip-ansi: ^7.1.0 - checksum: b2d43b76b3d8dcbdd64768165e548aad3e54e1cae4ecd31bac9966faaa7cf0b0345677ad6879db10ba58eb446ba8fa44fb82b4951872fd397f096712467a809f + checksum: 9827bf8bbb341d2d15f26d8507d98ca2695279359073422fe089d374b30e233d24ab95beca55cf9ab8dcb89face00e919be4158af50d4b6d8eab5ef4ee399e0c languageName: node linkType: hard @@ -12876,13 +12736,6 @@ __metadata: languageName: node linkType: hard -"xtend@npm:~4.0.1": - version: 4.0.2 - resolution: "xtend@npm:4.0.2" - checksum: ac5dfa738b21f6e7f0dd6e65e1b3155036d68104e67e5d5d1bde74892e327d7e5636a076f625599dc394330a731861e87343ff184b0047fef1360a7ec0a5a36a - languageName: node - linkType: hard - "y18n@npm:^4.0.0": version: 4.0.3 resolution: "y18n@npm:4.0.3" @@ -12919,11 +12772,11 @@ __metadata: linkType: hard "yaml@npm:^2.2.1": - version: 2.8.0 - resolution: "yaml@npm:2.8.0" + version: 2.8.1 + resolution: "yaml@npm:2.8.1" bin: yaml: bin.mjs - checksum: 66f103ca5a2f02dac0526895cc7ae7626d91aa8c43aad6fdcff15edf68b1199be4012140b390063877913441aaa5288fdf57eca30e06268a8282dd741525e626 + checksum: 35b46150d48bc1da2fd5b1521a48a4fa36d68deaabe496f3c3fa9646d5796b6b974f3930a02c4b5aee6c85c860d7d7f79009416724465e835f40b87898c36de4 languageName: node linkType: hard @@ -13021,9 +12874,9 @@ __metadata: linkType: hard "yoctocolors-cjs@npm:^2.1.1": - version: 2.1.2 - resolution: "yoctocolors-cjs@npm:2.1.2" - checksum: 1c474d4b30a8c130e679279c5c2c33a0d48eba9684ffa0252cc64846c121fb56c3f25457fef902edbe1e2d7a7872130073a9fc8e795299d75e13fa3f5f548f1b + version: 2.1.3 + resolution: "yoctocolors-cjs@npm:2.1.3" + checksum: 207df586996c3b604fa85903f81cc54676f1f372613a0c7247f0d24b1ca781905685075d06955211c4d5d4f629d7d5628464f8af0a42d286b7a8ff88e9dadcb8 languageName: node linkType: hard From 3bde6bd29c32d4ec422b386d652ca7a2e3eda7a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mikl=C3=B3s=20Fazekas?= Date: Fri, 7 Nov 2025 17:18:02 +0100 Subject: [PATCH 11/24] fix(ios): refresh after updating the asset --- example/ios/Podfile.lock | 50 +++++++++++++++++----- ios/HybridRiveFile.swift | 30 +++++++++++-- ios/HybridRiveFileFactory.swift | 71 ++++++++++++++++++------------- ios/HybridRiveView.swift | 8 ++-- ios/RiveReactNativeView.swift | 23 ++++++++-- src/core/RiveView.tsx | 75 +++++++++++++++++++++++++++++++++ 6 files changed, 207 insertions(+), 50 deletions(-) create mode 100644 src/core/RiveView.tsx diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock index 5dd96353..77139433 100644 --- a/example/ios/Podfile.lock +++ b/example/ios/Podfile.lock @@ -8,7 +8,7 @@ PODS: - hermes-engine (0.79.2): - hermes-engine/Pre-built (= 0.79.2) - hermes-engine/Pre-built (0.79.2) - - NitroModules (0.31.3): + - NitroModules (0.31.4): - DoubleConversion - glog - hermes-engine @@ -1357,7 +1357,7 @@ PODS: - React-jsiexecutor - React-RCTFBReactNativeSpec - ReactCommon/turbomodule/core - - react-native-safe-area-context (5.4.0): + - react-native-safe-area-context (5.6.2): - DoubleConversion - glog - hermes-engine @@ -1372,8 +1372,8 @@ PODS: - React-hermes - React-ImageManager - React-jsi - - react-native-safe-area-context/common (= 5.4.0) - - react-native-safe-area-context/fabric (= 5.4.0) + - react-native-safe-area-context/common (= 5.6.2) + - react-native-safe-area-context/fabric (= 5.6.2) - React-NativeModulesApple - React-RCTFabric - React-renderercss @@ -1383,7 +1383,7 @@ PODS: - ReactCommon/turbomodule/bridging - ReactCommon/turbomodule/core - Yoga - - react-native-safe-area-context/common (5.4.0): + - react-native-safe-area-context/common (5.6.2): - DoubleConversion - glog - hermes-engine @@ -1407,7 +1407,7 @@ PODS: - ReactCommon/turbomodule/bridging - ReactCommon/turbomodule/core - Yoga - - react-native-safe-area-context/fabric (5.4.0): + - react-native-safe-area-context/fabric (5.6.2): - DoubleConversion - glog - hermes-engine @@ -1781,7 +1781,31 @@ PODS: - RiveRuntime (= 6.12.0) - Yoga - RiveRuntime (6.12.0) - - RNGestureHandler (2.25.0): + - RNCPicker (2.11.4): + - DoubleConversion + - glog + - hermes-engine + - RCT-Folly (= 2024.11.18.00) + - RCTRequired + - RCTTypeSafety + - React-Core + - React-debug + - React-Fabric + - React-featureflags + - React-graphics + - React-hermes + - React-ImageManager + - React-jsi + - React-NativeModulesApple + - React-RCTFabric + - React-renderercss + - React-rendererdebug + - React-utils + - ReactCodegen + - ReactCommon/turbomodule/bridging + - ReactCommon/turbomodule/core + - Yoga + - RNGestureHandler (2.29.1): - DoubleConversion - glog - hermes-engine @@ -1883,6 +1907,7 @@ DEPENDENCIES: - ReactCodegen (from `build/generated/ios`) - ReactCommon/turbomodule/core (from `../node_modules/react-native/ReactCommon`) - Rive (from `../..`) + - "RNCPicker (from `../node_modules/@react-native-picker/picker`)" - RNGestureHandler (from `../node_modules/react-native-gesture-handler`) - Yoga (from `../node_modules/react-native/ReactCommon/yoga`) @@ -2037,6 +2062,8 @@ EXTERNAL SOURCES: :path: "../node_modules/react-native/ReactCommon" Rive: :path: "../.." + RNCPicker: + :path: "../node_modules/@react-native-picker/picker" RNGestureHandler: :path: "../node_modules/react-native-gesture-handler" Yoga: @@ -2050,7 +2077,7 @@ SPEC CHECKSUMS: fmt: a40bb5bd0294ea969aaaba240a927bd33d878cdd glog: 5683914934d5b6e4240e497e0f4a3b42d1854183 hermes-engine: 314be5250afa5692b57b4dd1705959e1973a8ebe - NitroModules: bb52372447b073b536ecc728f79fbd1242547738 + NitroModules: 8229091083785ae690dc9071f07fc412e0cb8243 RCT-Folly: 36fe2295e44b10d831836cc0d1daec5f8abcf809 RCTDeprecation: 83ffb90c23ee5cea353bd32008a7bca100908f8c RCTRequired: eb7c0aba998009f47a540bec9e9d69a54f68136e @@ -2082,7 +2109,7 @@ SPEC CHECKSUMS: React-logger: 368570a253f00879a1e4fea24ed4047e72e7bbf3 React-Mapbuffer: c04fcda1c6281fc0a6824c7dcc1633dd217ac1ec React-microtasksnativemodule: ca2804a25fdcefffa0aa942aa23ab53b99614a34 - react-native-safe-area-context: 00d03dc688ba86664be66f9e3f203fc7d747d899 + react-native-safe-area-context: bc59472155ffb889a1ffe16c19a04c0cd451562b React-NativeModulesApple: 452b86b29fae99ed0a4015dca3ad9cd222f88abf React-oscompat: ef5df1c734f19b8003e149317d041b8ce1f7d29c React-perflogger: 6fd2f6811533e9c19a61e855c3033eecbf4ad2a0 @@ -2114,9 +2141,10 @@ SPEC CHECKSUMS: ReactAppDependencyProvider: d5dcc564f129632276bd3184e60f053fcd574d6b ReactCodegen: fda99a79c866370190e162083a35602fdc314e5d ReactCommon: 4d0da92a5eb8da86c08e3ec34bd23ab439fb2461 - Rive: 3bd6bb2febc263defec083afd3a4fb29b82efeb9 + Rive: b83a5c913ae79218b9e33f22bbe77d860de54eec RiveRuntime: 8d819993126145fbf5a73089e7634b14b9aa577f - RNGestureHandler: 5d8431415d4b8518e86e289e9ad5bb9be78f6dba + RNCPicker: 83c74db2de8274d8a8f3e18d91dea174a708f8c4 + RNGestureHandler: bff91bb5ab5688265c70f74180ef718b94f33fe3 SocketRocket: d4aabe649be1e368d1318fdf28a022d714d65748 Yoga: 9f110fc4b7aa538663cba3c14cbb1c335f43c13f diff --git a/ios/HybridRiveFile.swift b/ios/HybridRiveFile.swift index 8715f173..6c7a6d8f 100644 --- a/ios/HybridRiveFile.swift +++ b/ios/HybridRiveFile.swift @@ -6,10 +6,28 @@ class HybridRiveFile: HybridRiveFileSpec { var riveFile: RiveFile? var referencedAssetCache: ReferencedAssetCache? var assetLoader: ReferencedAssetLoader? + private var weakViews: [Weak] = [] public func setRiveFile(_ riveFile: RiveFile) { self.riveFile = riveFile } + + func registerView(_ view: RiveReactNativeView) { + weakViews.append(Weak(value: view)) + } + + func unregisterView(_ view: RiveReactNativeView) { + weakViews.removeAll { $0.value === view } + } + + private func refreshAfterAssetChange() { + weakViews = weakViews.filter { $0.value != nil } + + for weakView in weakViews { + guard let view = weakView.value else { continue } + view.refreshAfterAssetChange() + } + } var viewModelCount: Double? { guard let count = riveFile?.viewModelCount else { return nil } @@ -53,15 +71,19 @@ class HybridRiveFile: HybridRiveFileSpec { guard let assetsData = referencedAssets.data, let cache = referencedAssetCache, let loader = assetLoader, - let riveFile = riveFile else { + let _ = riveFile else { return } - let factory = RiveFactory() - + var hasChanged = false for (key, assetData) in assetsData { guard let asset = cache[key] else { continue } - loader.loadAsset(source: assetData, asset: asset, factory: factory) + loader.loadAsset(source: assetData, asset: asset) + hasChanged = true + } + + if hasChanged { + refreshAfterAssetChange() } } diff --git a/ios/HybridRiveFileFactory.swift b/ios/HybridRiveFileFactory.swift index b3f87a00..6002afd3 100644 --- a/ios/HybridRiveFileFactory.swift +++ b/ios/HybridRiveFileFactory.swift @@ -2,9 +2,10 @@ import NitroModules import RiveRuntime final class HybridRiveFileFactory: HybridRiveFileFactorySpec { + let assetLoader = ReferencedAssetLoader() + private func buildRiveFile(data: Data, loadCdn: Bool, referencedAssets: ReferencedAssetsType?) throws -> (file: RiveFile, cache: ReferencedAssetCache, loader: ReferencedAssetLoader?) { - var referencedAssetCache = Ref(ReferencedAssetCache()) - let assetLoader = ReferencedAssetLoader() + var referencedAssetCache = SendableRef(ReferencedAssetCache()) let customLoader = assetLoader.createCustomLoader(referencedAssets: referencedAssets, cache: referencedAssetCache) let riveFile = if let customLoader = customLoader { @@ -17,21 +18,20 @@ final class HybridRiveFileFactory: HybridRiveFileFactorySpec { } // MARK: Public Methods - func fromURL(url: String, loadCdn: Bool) throws -> Promise<(any HybridRiveFileSpec)> { - // TODO: should we make use of the underlying Rive iOS URL asset loading instead + func fromURL(url: String, loadCdn: Bool, referencedAssets: ReferencedAssetsType?) throws -> Promise<(any HybridRiveFileSpec)> { return Promise.async { do { guard let url = URL(string: url) else { throw RuntimeError.error(withMessage: "Invalid URL: \(url)") } - let riveFile = try await withCheckedThrowingContinuation { continuation in + let result = try await withCheckedThrowingContinuation { continuation in DispatchQueue.global(qos: .userInitiated).async { do { let riveData = try Data(contentsOf: url) - let riveFile = try RiveFile(data: riveData, loadCdn: true) + let result = try self.buildRiveFile(data: riveData, loadCdn: loadCdn, referencedAssets: referencedAssets) DispatchQueue.main.async { - continuation.resume(returning: riveFile) + continuation.resume(returning: result) } } catch { DispatchQueue.main.async { @@ -42,7 +42,9 @@ final class HybridRiveFileFactory: HybridRiveFileFactorySpec { } let hybridRiveFile = HybridRiveFile() - hybridRiveFile.riveFile = riveFile + hybridRiveFile.riveFile = result.file + hybridRiveFile.referencedAssetCache = result.cache + hybridRiveFile.assetLoader = result.loader return hybridRiveFile } catch let error as NSError { throw RuntimeError.error( @@ -53,7 +55,7 @@ final class HybridRiveFileFactory: HybridRiveFileFactorySpec { } } - func fromFileURL(fileURL: String, loadCdn: Bool) throws -> Promise<(any HybridRiveFileSpec)> { + func fromFileURL(fileURL: String, loadCdn: Bool, referencedAssets: ReferencedAssetsType?) throws -> Promise<(any HybridRiveFileSpec)> { guard let url = URL(string: fileURL) else { throw RuntimeError.error(withMessage: "fromFileURL: Invalid URL: \(fileURL)") } @@ -64,18 +66,30 @@ final class HybridRiveFileFactory: HybridRiveFileFactorySpec { return Promise.async { do { - let riveFile = try await withCheckedThrowingContinuation { continuation in + let result = try await withCheckedThrowingContinuation { continuation in DispatchQueue.global(qos: .userInitiated).async { do { let data = try Data(contentsOf: url) + let result = try self.buildRiveFile(data: data, loadCdn: loadCdn, referencedAssets: referencedAssets) + DispatchQueue.main.async { + continuation.resume(returning: result) + } + } catch { + DispatchQueue.main.async { + continuation.resume(throwing: error) + } + } + } + } let hybridRiveFile = HybridRiveFile() - hybridRiveFile.riveFile = riveFile.file - hybridRiveFile.referencedAssetCache = riveFile.cache - hybridRiveFile.assetLoader = riveFile.loader + hybridRiveFile.riveFile = result.file + hybridRiveFile.referencedAssetCache = result.cache + hybridRiveFile.assetLoader = result.loader return hybridRiveFile } catch let error as NSError { - throw RuntimeError.error(withMessage: "Failed to load Rive file: \(error.localizedDescription)") + throw RuntimeError.error( + withMessage: "Failed to load Rive file: \(error.localizedDescription)") } catch { throw RuntimeError.error(withMessage: "Unknown error occurred while loading Rive file") } @@ -89,13 +103,13 @@ final class HybridRiveFileFactory: HybridRiveFileFactorySpec { return Promise.async { do { - + let assetLoader = self.assetLoader + let referencedAssetCache = SendableRef(ReferencedAssetCache()) let riveFile = try await withCheckedThrowingContinuation { continuation in DispatchQueue.global(qos: .userInitiated).async { do { - var referencedAssetCache = Ref(ReferencedAssetCache()) let riveFile = - if let customLoader = self.assetLoader.createCustomLoader(referencedAssets: referencedAssets, cache: referencedAssetCache) { + if let customLoader = assetLoader.createCustomLoader(referencedAssets: referencedAssets, cache: referencedAssetCache) { try RiveFile(resource: resource, loadCdn: loadCdn, customAssetLoader: customLoader) } else { try RiveFile(resource: resource, loadCdn: loadCdn) @@ -113,6 +127,10 @@ final class HybridRiveFileFactory: HybridRiveFileFactorySpec { let hybridRiveFile = HybridRiveFile() hybridRiveFile.riveFile = riveFile + if referencedAssets != nil { + hybridRiveFile.referencedAssetCache = referencedAssetCache.value + hybridRiveFile.assetLoader = assetLoader + } return hybridRiveFile } catch let error as NSError { throw RuntimeError.error( @@ -157,25 +175,18 @@ final class HybridRiveFileFactory: HybridRiveFileFactorySpec { } } - func fromBytes(bytes: ArrayBufferHolder, loadCdn: Bool) throws -> Promise< + func fromBytes(bytes: ArrayBufferHolder, loadCdn: Bool, referencedAssets: ReferencedAssetsType?) throws -> Promise< (any HybridRiveFileSpec) > { let data = bytes.toData(copyIfNeeded: false) return Promise.async { do { - let riveFile = try await withCheckedThrowingContinuation { continuation in + let result = try await withCheckedThrowingContinuation { continuation in DispatchQueue.global(qos: .userInitiated).async { do { - var referencedAssetCache = Ref(ReferencedAssetCache()) - let riveFile = - if let customLoader = self.assetLoader.createCustomLoader(referencedAssets: referencedAssets, cache: referencedAssetCache) { - try RiveFile(data: data, loadCdn: loadCdn, customAssetLoader: customLoader) - } else { - try RiveFile(data: data, loadCdn: loadCdn) - } - + let result = try self.buildRiveFile(data: data, loadCdn: loadCdn, referencedAssets: referencedAssets) DispatchQueue.main.async { - continuation.resume(returning: riveFile) + continuation.resume(returning: result) } } catch { DispatchQueue.main.async { @@ -186,7 +197,9 @@ final class HybridRiveFileFactory: HybridRiveFileFactorySpec { } let hybridRiveFile = HybridRiveFile() - hybridRiveFile.riveFile = riveFile + hybridRiveFile.riveFile = result.file + hybridRiveFile.referencedAssetCache = result.cache + hybridRiveFile.assetLoader = result.loader return hybridRiveFile } catch let error as NSError { throw RuntimeError.error( diff --git a/ios/HybridRiveView.swift b/ios/HybridRiveView.swift index c3cabc05..2d813788 100644 --- a/ios/HybridRiveView.swift +++ b/ios/HybridRiveView.swift @@ -83,19 +83,21 @@ class HybridRiveView : HybridRiveViewSpec { // MARK: Update func afterUpdate() { - guard let file = (file as? HybridRiveFile)?.riveFile else { return } - + guard let hybridFile = file as? HybridRiveFile, + let file = hybridFile.riveFile else { return } + let config = ViewConfiguration( artboardName: artboardName, stateMachineName: stateMachineName, autoBind: autoBind ?? DefaultConfiguration.autoBind, autoPlay: autoPlay ?? DefaultConfiguration.autoPlay, riveFile: file, + hybridRiveFile: hybridFile, alignment: convertAlignment(alignment) ?? DefaultConfiguration.alignment, fit: convertFit(fit) ?? DefaultConfiguration.fit, layoutScaleFactor: layoutScaleFactor ?? DefaultConfiguration.layoutScaleFactor ) - + try? getRiveView().configure(config, reload: needsReload) needsReload = false } diff --git a/ios/RiveReactNativeView.swift b/ios/RiveReactNativeView.swift index 6d7bf6b2..1dddddbe 100644 --- a/ios/RiveReactNativeView.swift +++ b/ios/RiveReactNativeView.swift @@ -8,6 +8,7 @@ struct ViewConfiguration { let autoBind: Bool let autoPlay: Bool let riveFile: RiveFile + let hybridRiveFile: HybridRiveFile? let alignment: RiveRuntime.RiveAlignment let fit: RiveRuntime.RiveFit let layoutScaleFactor: Double @@ -20,7 +21,8 @@ class RiveReactNativeView: UIView, RiveStateMachineDelegate { private var eventListeners: [(UnifiedRiveEvent) -> Void] = [] private var viewReadyContinuation: CheckedContinuation? private var isViewReady = false - + private weak var riveFile: HybridRiveFile? + // MARK: Public Config Properties var autoPlay: Bool = true @@ -42,13 +44,18 @@ class RiveReactNativeView: UIView, RiveStateMachineDelegate { let model = RiveModel(riveFile: config.riveFile) baseViewModel = RiveViewModel(model, autoPlay: config.autoPlay) createViewFromViewModel() + + if let hybridRiveFile = config.hybridRiveFile { + self.riveFile = hybridRiveFile + hybridRiveFile.registerView(self) + } } - + baseViewModel?.alignment = config.alignment baseViewModel?.fit = config.fit baseViewModel?.autoPlay = config.autoPlay baseViewModel?.layoutScaleFactor = config.layoutScaleFactor - + if !isViewReady { isViewReady = true viewReadyContinuation?.resume() @@ -68,6 +75,12 @@ class RiveReactNativeView: UIView, RiveStateMachineDelegate { baseViewModel?.pause() } + func refreshAfterAssetChange() { + if baseViewModel?.isPlaying == false { + baseViewModel?.play() + } + } + func addEventListener(_ onEvent: @escaping (UnifiedRiveEvent) -> Void) { eventListeners.append(onEvent) } @@ -157,6 +170,10 @@ class RiveReactNativeView: UIView, RiveStateMachineDelegate { riveView?.stateMachineDelegate = nil riveView = nil baseViewModel = nil + if let riveFile = riveFile { + riveFile.unregisterView(self) + self.riveFile = nil + } } @objc func onRiveEventReceived(onRiveEvent riveEvent: RiveRuntime.RiveEvent) { diff --git a/src/core/RiveView.tsx b/src/core/RiveView.tsx new file mode 100644 index 00000000..21527922 --- /dev/null +++ b/src/core/RiveView.tsx @@ -0,0 +1,75 @@ +import type { HybridViewProps } from 'react-native-nitro-modules'; +import type { RiveFile } from '../specs/RiveFile.nitro'; +import '../specs/RiveView.nitro'; +import type { Alignment } from './Alignment'; +import type { Fit } from './Fit'; +import { NitroRiveView } from 'react-native-rive'; +import type { ReferencedAssets } from '../hooks/useRiveFile'; +import type { RiveFileInput } from '../../lib/typescript/src'; +import { useRiveFile } from '../hooks/useRiveFile'; +import { ActivityIndicator, Text } from 'react-native'; +import type { ComponentProps } from 'react'; + +export interface RiveViewProps + extends Omit, 'file'> { + /** Name of the artboard to display from the Rive file */ + artboardName?: string; + /** Name of the state machine to play */ + stateMachineName?: string; + /** Whether to automatically bind the state machine and artboard */ + autoBind?: boolean; + /** Whether to automatically start playing the state machine */ + autoPlay?: boolean; + /** The Rive file to be displayed */ + file: RiveFile | RiveFileInput; + /** How the Rive graphic should be aligned within its container */ + alignment?: Alignment; + /** How the Rive graphic should fit within its container */ + fit?: Fit; + /** The scale factor to apply to the Rive graphic when using Fit.Layout */ + layoutScaleFactor?: number; + /** Referenced assets for out-of-band asset loading */ + referencedAssets?: ReferencedAssets; +} + +function isNitroFile(file: RiveFile | RiveFileInput): file is RiveFile { + return ( + typeof file === 'object' && + '__type' in file && + file.__type === 'HybridObject' + ); +} + +function RiveViewWithFileInput( + props: Omit & { + file: RiveFileInput; + referencedAssets?: ReferencedAssets; + } +) { + const { file, referencedAssets, ...rest } = props; + const { riveFile, isLoading, error } = useRiveFile(file, referencedAssets); + + if (isLoading) { + return ; + } else if (error != null) { + return {error}; + } else { + return ; + } +} + +export function RiveView(props: RiveViewProps) { + const { file, referencedAssets, ...rest } = props; + + if (isNitroFile(file)) { + return ; + } else { + return ( + + ); + } +} From c5adec25e3be32f274c274471e7e94ad0ffca297 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mikl=C3=B3s=20Fazekas?= Date: Mon, 10 Nov 2025 14:05:30 +0100 Subject: [PATCH 12/24] fix: adderss race condition on doanlowd finished -> refresh --- .../com/margelo/nitro/rive/HybridRiveFile.kt | 37 ++++++++++++- .../com/margelo/nitro/rive/HybridRiveView.kt | 18 +++++- .../nitro/rive/ReferencedAssetLoader.kt | 55 +++++++++++++++---- rn82-example | 1 + 4 files changed, 97 insertions(+), 14 deletions(-) create mode 160000 rn82-example diff --git a/android/src/main/java/com/margelo/nitro/rive/HybridRiveFile.kt b/android/src/main/java/com/margelo/nitro/rive/HybridRiveFile.kt index f25bd959..e636013a 100644 --- a/android/src/main/java/com/margelo/nitro/rive/HybridRiveFile.kt +++ b/android/src/main/java/com/margelo/nitro/rive/HybridRiveFile.kt @@ -4,6 +4,13 @@ import androidx.annotation.Keep import app.rive.runtime.kotlin.core.File import com.facebook.proguard.annotations.DoNotStrip import com.margelo.nitro.NitroModules +import java.lang.ref.WeakReference +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.SupervisorJob +import kotlinx.coroutines.awaitAll +import kotlinx.coroutines.cancel +import kotlinx.coroutines.launch @Keep @DoNotStrip @@ -11,6 +18,8 @@ class HybridRiveFile : HybridRiveFileSpec() { var riveFile: File? = null var referencedAssetCache: ReferencedAssetCache? = null var assetLoader: ReferencedAssetLoader? = null + private val weakViews = mutableListOf>() + private val scope = CoroutineScope(Dispatchers.Main + SupervisorJob()) override val viewModelCount: Double? get() = riveFile?.viewModelCount?.toDouble() @@ -40,19 +49,45 @@ class HybridRiveFile : HybridRiveFileSpec() { } } + fun registerView(view: HybridRiveView) { + weakViews.add(WeakReference(view)) + } + + fun unregisterView(view: HybridRiveView) { + weakViews.removeAll { it.get() == view } + } + + private fun refreshAfterAssetChange() { + weakViews.removeAll { it.get() == null } + + for (weakView in weakViews) { + weakView.get()?.refreshAfterAssetChange() + } + } + override fun updateReferencedAssets(referencedAssets: ReferencedAssetsType) { val assetsData = referencedAssets.data ?: return val cache = referencedAssetCache ?: return val loader = assetLoader ?: return val context = NitroModules.applicationContext ?: return + val loadJobs = mutableListOf>() + for ((key, assetData) in assetsData) { val asset = cache[key] ?: continue - loader.updateAsset(assetData, asset, context) + loadJobs.add(loader.updateAsset(assetData, asset, context)) + } + + if (loadJobs.isNotEmpty()) { + scope.launch { + loadJobs.awaitAll() + refreshAfterAssetChange() + } } } override fun release() { + scope.cancel() assetLoader?.dispose() assetLoader = null riveFile?.release() diff --git a/android/src/main/java/com/margelo/nitro/rive/HybridRiveView.kt b/android/src/main/java/com/margelo/nitro/rive/HybridRiveView.kt index 2f72c0b6..f18d8a04 100644 --- a/android/src/main/java/com/margelo/nitro/rive/HybridRiveView.kt +++ b/android/src/main/java/com/margelo/nitro/rive/HybridRiveView.kt @@ -25,6 +25,7 @@ class HybridRiveView(val context: ThemedReactContext) : HybridRiveViewSpec() { //region State override val view: RiveReactNativeView = RiveReactNativeView(context) private var needsReload = false + private var registeredFile: HybridRiveFile? = null //endregion //region View Props @@ -46,6 +47,10 @@ class HybridRiveView(val context: ThemedReactContext) : HybridRiveViewSpec() { } override var file: HybridRiveFileSpec = HybridRiveFile() set(value) { + if (field != value) { + registeredFile?.unregisterView(this) + registeredFile = null + } changed(field, value) { field = it } } override var alignment: Alignment? = null @@ -99,8 +104,13 @@ class HybridRiveView(val context: ThemedReactContext) : HybridRiveViewSpec() { //endregion //region Update + fun refreshAfterAssetChange() { + afterUpdate() + } + override fun afterUpdate() { - val riveFile = (file as? HybridRiveFile)?.riveFile ?: return + val hybridFile = file as? HybridRiveFile + val riveFile = hybridFile?.riveFile ?: return val config = ViewConfiguration( artboardName = artboardName, @@ -113,6 +123,12 @@ class HybridRiveView(val context: ThemedReactContext) : HybridRiveViewSpec() { layoutScaleFactor = layoutScaleFactor?.toFloat() ?: DefaultConfiguration.LAYOUTSCALEFACTOR, ) view.configure(config, needsReload) + + if (needsReload && hybridFile != null) { + hybridFile.registerView(this) + registeredFile = hybridFile + } + needsReload = false super.afterUpdate() } diff --git a/android/src/main/java/com/margelo/nitro/rive/ReferencedAssetLoader.kt b/android/src/main/java/com/margelo/nitro/rive/ReferencedAssetLoader.kt index f2efd9fc..339c39ac 100644 --- a/android/src/main/java/com/margelo/nitro/rive/ReferencedAssetLoader.kt +++ b/android/src/main/java/com/margelo/nitro/rive/ReferencedAssetLoader.kt @@ -8,6 +8,8 @@ import android.util.Log import app.rive.runtime.kotlin.core.* import com.margelo.nitro.NitroModules import kotlinx.coroutines.* +import kotlinx.coroutines.CompletableDeferred +import kotlinx.coroutines.Deferred import java.io.File as JavaFile import java.io.IOException import java.net.URI @@ -61,9 +63,10 @@ class ReferencedAssetLoader { } } - private fun downloadUrlAsset(url: String, listener: (ByteArray) -> Unit) { + private fun downloadUrlAsset(url: String, listener: (ByteArray?) -> Unit) { if (!isValidUrl(url)) { logError("Invalid URL: $url") + listener(null) return } @@ -86,6 +89,9 @@ class ReferencedAssetLoader { } else -> { logError("Unsupported URL scheme: ${uri.scheme}") + withContext(Dispatchers.Main) { + listener(null) + } return@launch } } @@ -95,6 +101,9 @@ class ReferencedAssetLoader { } } catch (e: Exception) { logError("Unable to download asset from URL: $url - ${e.message}") + withContext(Dispatchers.Main) { + listener(null) + } } } } @@ -102,7 +111,7 @@ class ReferencedAssetLoader { private fun loadResourceAsset( sourceAssetId: String, context: Context, - listener: (ByteArray) -> Unit + listener: (ByteArray?) -> Unit ) { scope.launch { try { @@ -124,13 +133,25 @@ class ReferencedAssetLoader { } } else { logError("Resource not found: $sourceAssetId") + withContext(Dispatchers.Main) { + listener(null) + } } } catch (e: IOException) { logError("IO Exception while reading resource: $sourceAssetId - ${e.message}") + withContext(Dispatchers.Main) { + listener(null) + } } catch (e: Resources.NotFoundException) { logError("Resource not found: $sourceAssetId - ${e.message}") + withContext(Dispatchers.Main) { + listener(null) + } } catch (e: Exception) { logError("Unexpected error while processing resource: $sourceAssetId - ${e.message}") + withContext(Dispatchers.Main) { + listener(null) + } } } } @@ -139,20 +160,21 @@ class ReferencedAssetLoader { sourceAsset: String, path: String?, context: Context, - listener: (ByteArray) -> Unit + listener: (ByteArray?) -> Unit ) { scope.launch { try { val fullPath = if (path == null) sourceAsset else constructFilePath(sourceAsset, path) val bytes = readAssetBytes(context, fullPath) - if (bytes != null) { - withContext(Dispatchers.Main) { - listener(bytes) - } + withContext(Dispatchers.Main) { + listener(bytes) } } catch (e: Exception) { logError("Error loading bundled asset: $sourceAsset - ${e.message}") + withContext(Dispatchers.Main) { + listener(null) + } } } } @@ -165,9 +187,13 @@ class ReferencedAssetLoader { } } - private fun loadAsset(assetData: ResolvedReferencedAsset, asset: FileAsset, context: Context) { - val listener: (ByteArray) -> Unit = { bytes -> - processAssetBytes(bytes, asset) + private fun loadAsset(assetData: ResolvedReferencedAsset, asset: FileAsset, context: Context): Deferred { + val deferred = CompletableDeferred() + val listener: (ByteArray?) -> Unit = { bytes -> + if (bytes != null) { + processAssetBytes(bytes, asset) + } + deferred.complete(Unit) } when { @@ -180,11 +206,16 @@ class ReferencedAssetLoader { assetData.sourceAsset != null -> { loadBundledAsset(assetData.sourceAsset, assetData.path, context, listener) } + else -> { + deferred.complete(Unit) + } } + + return deferred } - fun updateAsset(assetData: ResolvedReferencedAsset, asset: FileAsset, context: Context) { - loadAsset(assetData, asset, context) + fun updateAsset(assetData: ResolvedReferencedAsset, asset: FileAsset, context: Context): Deferred { + return loadAsset(assetData, asset, context) } fun createCustomLoader( diff --git a/rn82-example b/rn82-example new file mode 160000 index 00000000..032eeda5 --- /dev/null +++ b/rn82-example @@ -0,0 +1 @@ +Subproject commit 032eeda50ad5a29c0c723babb906d9e0339487a8 From 1171783cc13a65fb0e9a82f67003f86b2fec2b84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mikl=C3=B3s=20Fazekas?= Date: Mon, 10 Nov 2025 14:17:34 +0100 Subject: [PATCH 13/24] fix: js lint/test --- src/core/RiveView.tsx | 3 +-- src/hooks/useRiveFile.ts | 2 +- src/index.tsx | 1 + 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/core/RiveView.tsx b/src/core/RiveView.tsx index 21527922..92d39034 100644 --- a/src/core/RiveView.tsx +++ b/src/core/RiveView.tsx @@ -1,11 +1,10 @@ -import type { HybridViewProps } from 'react-native-nitro-modules'; import type { RiveFile } from '../specs/RiveFile.nitro'; import '../specs/RiveView.nitro'; import type { Alignment } from './Alignment'; import type { Fit } from './Fit'; import { NitroRiveView } from 'react-native-rive'; import type { ReferencedAssets } from '../hooks/useRiveFile'; -import type { RiveFileInput } from '../../lib/typescript/src'; +import type { RiveFileInput } from '../hooks/useRiveFile'; import { useRiveFile } from '../hooks/useRiveFile'; import { ActivityIndicator, Text } from 'react-native'; import type { ComponentProps } from 'react'; diff --git a/src/hooks/useRiveFile.ts b/src/hooks/useRiveFile.ts index 1d7f4961..5eea5525 100644 --- a/src/hooks/useRiveFile.ts +++ b/src/hooks/useRiveFile.ts @@ -1,6 +1,6 @@ import { useState, useEffect, useMemo, useRef } from 'react'; import { Image } from 'react-native'; -import { RiveFileFactory, type RiveFile } from 'react-native-rive'; +import { RiveFileFactory, type RiveFile } from '../index'; import type { ResolvedReferencedAsset } from '../specs/RiveFile.nitro'; export type RiveFileInput = number | { uri: string } | string | ArrayBuffer; diff --git a/src/index.tsx b/src/index.tsx index 659e1301..83122ebd 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -50,6 +50,7 @@ export const RiveView = getHostComponent( 'RiveView', () => RiveViewConfig ) as ReactNativeView; +export { RiveView as NitroRiveView }; export type { RiveViewProps, RiveViewMethods }; export type { RiveFile } from './specs/RiveFile.nitro'; From f6bcf87e721fe95052a6c6f62c7004db6957fc89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mikl=C3=B3s=20Fazekas?= Date: Mon, 10 Nov 2025 14:49:12 +0100 Subject: [PATCH 14/24] remove rive view --- src/core/RiveView.tsx | 74 ------------------------------------------- 1 file changed, 74 deletions(-) delete mode 100644 src/core/RiveView.tsx diff --git a/src/core/RiveView.tsx b/src/core/RiveView.tsx deleted file mode 100644 index 92d39034..00000000 --- a/src/core/RiveView.tsx +++ /dev/null @@ -1,74 +0,0 @@ -import type { RiveFile } from '../specs/RiveFile.nitro'; -import '../specs/RiveView.nitro'; -import type { Alignment } from './Alignment'; -import type { Fit } from './Fit'; -import { NitroRiveView } from 'react-native-rive'; -import type { ReferencedAssets } from '../hooks/useRiveFile'; -import type { RiveFileInput } from '../hooks/useRiveFile'; -import { useRiveFile } from '../hooks/useRiveFile'; -import { ActivityIndicator, Text } from 'react-native'; -import type { ComponentProps } from 'react'; - -export interface RiveViewProps - extends Omit, 'file'> { - /** Name of the artboard to display from the Rive file */ - artboardName?: string; - /** Name of the state machine to play */ - stateMachineName?: string; - /** Whether to automatically bind the state machine and artboard */ - autoBind?: boolean; - /** Whether to automatically start playing the state machine */ - autoPlay?: boolean; - /** The Rive file to be displayed */ - file: RiveFile | RiveFileInput; - /** How the Rive graphic should be aligned within its container */ - alignment?: Alignment; - /** How the Rive graphic should fit within its container */ - fit?: Fit; - /** The scale factor to apply to the Rive graphic when using Fit.Layout */ - layoutScaleFactor?: number; - /** Referenced assets for out-of-band asset loading */ - referencedAssets?: ReferencedAssets; -} - -function isNitroFile(file: RiveFile | RiveFileInput): file is RiveFile { - return ( - typeof file === 'object' && - '__type' in file && - file.__type === 'HybridObject' - ); -} - -function RiveViewWithFileInput( - props: Omit & { - file: RiveFileInput; - referencedAssets?: ReferencedAssets; - } -) { - const { file, referencedAssets, ...rest } = props; - const { riveFile, isLoading, error } = useRiveFile(file, referencedAssets); - - if (isLoading) { - return ; - } else if (error != null) { - return {error}; - } else { - return ; - } -} - -export function RiveView(props: RiveViewProps) { - const { file, referencedAssets, ...rest } = props; - - if (isNitroFile(file)) { - return ; - } else { - return ( - - ); - } -} From b54117ec8601abb2be7aee0c4f117be8d720aa16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mikl=C3=B3s=20Fazekas?= Date: Mon, 10 Nov 2025 16:22:52 +0100 Subject: [PATCH 15/24] added exmpla --- .../assets/audio/referenced_audio-2929340.wav | Bin 0 -> 56996 bytes example/assets/fonts/Inter-594377.ttf | Bin 0 -> 19024 bytes example/assets/rive/out_of_band.riv | Bin 0 -> 311977 bytes example/src/pages/OutOfBandAssets.tsx | 144 ++++++++++++++++++ ios/Utils.swift | 15 ++ 5 files changed, 159 insertions(+) create mode 100644 example/assets/audio/referenced_audio-2929340.wav create mode 100644 example/assets/fonts/Inter-594377.ttf create mode 100644 example/assets/rive/out_of_band.riv create mode 100644 example/src/pages/OutOfBandAssets.tsx create mode 100644 ios/Utils.swift diff --git a/example/assets/audio/referenced_audio-2929340.wav b/example/assets/audio/referenced_audio-2929340.wav new file mode 100644 index 0000000000000000000000000000000000000000..4bfcc159dd7273c1785142cd372968f7ab58f842 GIT binary patch literal 56996 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 S=X>D!9(cY7p6>zgf&T~B0bG3m literal 0 HcmV?d00001 diff --git a/example/assets/fonts/Inter-594377.ttf b/example/assets/fonts/Inter-594377.ttf new file mode 100644 index 0000000000000000000000000000000000000000..f5a2ed31c088344883bbc09f66ccf20592fc512d GIT binary patch literal 19024 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 hZ95bpJOC6s;5HY>oqvoz7L0L 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 z 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 b>8lT{-DNdg#>>Xaz@OfNV`Sq3>DByS?#|9? literal 0 HcmV?d00001 diff --git a/example/src/pages/OutOfBandAssets.tsx b/example/src/pages/OutOfBandAssets.tsx new file mode 100644 index 00000000..6e94c66a --- /dev/null +++ b/example/src/pages/OutOfBandAssets.tsx @@ -0,0 +1,144 @@ +import * as React from 'react'; +import { + ActivityIndicator, + SafeAreaView, + ScrollView, + StyleSheet, + Text, + View, +} from 'react-native'; +import { + /*Rive, */ Fit, + /*RNRiveError,*/ useRiveFile, + RiveView, +} from 'react-native-rive'; +import { Picker } from '@react-native-picker/picker'; + +export default function StateMachine() { + const [uri, setUri] = React.useState('https://picsum.photos/id/372/500/500'); + const { riveFile, isLoading, error } = useRiveFile( + require('../../assets/rive/out_of_band.riv'), + { + referencedAssets: { + 'Inter-594377': { + source: require('../../assets/fonts/Inter-594377.ttf'), + // source: { + // fileName: 'Inter-594377.ttf', + // path: 'fonts', // only needed for Android assets + // }, + }, + 'referenced-image-2929282': { + source: { + uri: uri, + }, + // source: { + // fileName: 'referenced-image-2929282.png', + // path: 'images', // only needed for Android assets + // }, + }, + 'referenced_audio-2929340': { + source: require('../../assets/audio/referenced_audio-2929340.wav'), + // source: { + // fileName: 'referenced_audio-2929340.wav', + // path: 'audio', // only needed for Android assets + // }, + }, + }, + } + ); + + if (isLoading) { + return ; + } else if (error != null) { + return ( + + Error loading Rive file + + ); + } + + return ( + + { + console.log(riveError); + }} + /> + {/* + Load in an external asset from a URL, or bundled asset on the native + platform, or as a source loaded directly from JavaScript. + */} + + + + setUri(value)} + mode={'dropdown'} + style={styles.picker} + > + {[ + 'https://picsum.photos/id/372/500/500', + 'https://picsum.photos/id/373/500/500', + ].map((key) => ( + + ))} + + + + + + ); +} + +const styles = StyleSheet.create({ + safeAreaViewContainer: { + flex: 1, + }, + container: { + flexGrow: 1, + alignItems: 'center', + justifyContent: 'flex-start', + }, + animation: { + width: '100%', + height: 400, + }, + picker: { + flex: 1, + width: '100%', + }, + pickerWrapper: { + borderWidth: 1, + borderColor: 'black', + borderRadius: 5, + alignItems: 'center', + margin: 16, + }, + pickersWrapper: { + flex: 1, + padding: 16, + alignSelf: 'stretch', + }, +}); diff --git a/ios/Utils.swift b/ios/Utils.swift new file mode 100644 index 00000000..ad8ed6a8 --- /dev/null +++ b/ios/Utils.swift @@ -0,0 +1,15 @@ +final class Weak { + weak var value: T? + + init(_ value: T) { + self.value = value + } +} + +final class SendableRef: @unchecked Sendable { + var value: T + + init(_ value: T) { + self.value = value + } +} From f823eb22ddb8a6045521281e1d819383b1089410 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mikl=C3=B3s=20Fazekas?= Date: Mon, 10 Nov 2025 16:24:17 +0100 Subject: [PATCH 16/24] update --- example/src/App.tsx | 13 +++++++++++++ ios/HybridRiveFile.swift | 9 +++++++-- ios/HybridRiveFileFactory.swift | 13 +++++++++---- ios/ReferencedAssetLoader.swift | 10 ++-------- 4 files changed, 31 insertions(+), 14 deletions(-) diff --git a/example/src/App.tsx b/example/src/App.tsx index b38f1dee..d326dd55 100644 --- a/example/src/App.tsx +++ b/example/src/App.tsx @@ -13,6 +13,7 @@ import TemplatePage from './pages/TemplatePage'; import EventsExample from './pages/RiveEventsExample'; import StateMachineInputsExample from './pages/RiveStateMachineInputsExample'; import TextRunExample from './pages/RiveTextRunExample'; +import OutOfBandAssets from './pages/OutOfBandAssets'; type RootStackParamList = { Home: undefined; @@ -22,6 +23,7 @@ type RootStackParamList = { RiveStateMachineInputs: undefined; RiveTextRun: undefined; Template: undefined; + OutOfBandAssets: undefined; }; const Stack = createStackNavigator(); @@ -63,6 +65,12 @@ function HomeScreen({ navigation }: { navigation: any }) { > Rive Text Run Example + navigation.navigate('OutOfBandAssets')} + > + Out of band assets + navigation.navigate('Template')} @@ -118,6 +126,11 @@ export default function App() { component={TextRunExample} options={{ title: 'Rive Text Runs' }} /> + ] = [] public func setRiveFile(_ riveFile: RiveFile) { @@ -13,7 +14,7 @@ class HybridRiveFile: HybridRiveFileSpec { } func registerView(_ view: RiveReactNativeView) { - weakViews.append(Weak(value: view)) + weakViews.append(Weak(view)) } func unregisterView(_ view: RiveReactNativeView) { @@ -78,7 +79,11 @@ class HybridRiveFile: HybridRiveFileSpec { var hasChanged = false for (key, assetData) in assetsData { guard let asset = cache[key] else { continue } - loader.loadAsset(source: assetData, asset: asset) + if let riveFactory = cachedFactory { + loader.loadAsset(source: assetData, asset: asset, factory: riveFactory) + } else { + RCTLogError("[RiveFile] no factory available for update") + } hasChanged = true } diff --git a/ios/HybridRiveFileFactory.swift b/ios/HybridRiveFileFactory.swift index 6002afd3..988ff825 100644 --- a/ios/HybridRiveFileFactory.swift +++ b/ios/HybridRiveFileFactory.swift @@ -4,9 +4,10 @@ import RiveRuntime final class HybridRiveFileFactory: HybridRiveFileFactorySpec { let assetLoader = ReferencedAssetLoader() - private func buildRiveFile(data: Data, loadCdn: Bool, referencedAssets: ReferencedAssetsType?) throws -> (file: RiveFile, cache: ReferencedAssetCache, loader: ReferencedAssetLoader?) { + private func buildRiveFile(data: Data, loadCdn: Bool, referencedAssets: ReferencedAssetsType?) throws -> (file: RiveFile, cache: ReferencedAssetCache, factory: RiveFactory?, loader: ReferencedAssetLoader?) { var referencedAssetCache = SendableRef(ReferencedAssetCache()) - let customLoader = assetLoader.createCustomLoader(referencedAssets: referencedAssets, cache: referencedAssetCache) + var factoryCache: SendableRef = .init(nil) + let customLoader = assetLoader.createCustomLoader(referencedAssets: referencedAssets, cache: referencedAssetCache, factory: factoryCache) let riveFile = if let customLoader = customLoader { try RiveFile(data: data, loadCdn: loadCdn, customAssetLoader: customLoader) @@ -14,7 +15,7 @@ final class HybridRiveFileFactory: HybridRiveFileFactorySpec { try RiveFile(data: data, loadCdn: loadCdn) } - return (file: riveFile, cache: referencedAssetCache.value, loader: customLoader != nil ? assetLoader : nil) + return (file: riveFile, cache: referencedAssetCache.value, factory: factoryCache.value, loader: customLoader != nil ? assetLoader : nil) } // MARK: Public Methods @@ -44,6 +45,9 @@ final class HybridRiveFileFactory: HybridRiveFileFactorySpec { let hybridRiveFile = HybridRiveFile() hybridRiveFile.riveFile = result.file hybridRiveFile.referencedAssetCache = result.cache + if let factory = result.factory { + hybridRiveFile.cachedFactory = factory + } hybridRiveFile.assetLoader = result.loader return hybridRiveFile } catch let error as NSError { @@ -105,11 +109,12 @@ final class HybridRiveFileFactory: HybridRiveFileFactorySpec { do { let assetLoader = self.assetLoader let referencedAssetCache = SendableRef(ReferencedAssetCache()) + let factoryCache = SendableRef(nil) let riveFile = try await withCheckedThrowingContinuation { continuation in DispatchQueue.global(qos: .userInitiated).async { do { let riveFile = - if let customLoader = assetLoader.createCustomLoader(referencedAssets: referencedAssets, cache: referencedAssetCache) { + if let customLoader = assetLoader.createCustomLoader(referencedAssets: referencedAssets, cache: referencedAssetCache, factory: factoryCache) { try RiveFile(resource: resource, loadCdn: loadCdn, customAssetLoader: customLoader) } else { try RiveFile(resource: resource, loadCdn: loadCdn) diff --git a/ios/ReferencedAssetLoader.swift b/ios/ReferencedAssetLoader.swift index 5e921276..ba692390 100644 --- a/ios/ReferencedAssetLoader.swift +++ b/ios/ReferencedAssetLoader.swift @@ -1,13 +1,6 @@ import NitroModules import RiveRuntime -final class Ref { - var value: T - init(_ value: T) { - self.value = value - } -} - struct FileAndCache { var file: RiveFile var cache: [String: RiveFileAsset] @@ -194,7 +187,7 @@ final class ReferencedAssetLoader { loadAssetInternal(source: source, asset: asset, factory: factory) } - func createCustomLoader(referencedAssets: ReferencedAssetsType?, cache: Ref) + func createCustomLoader(referencedAssets: ReferencedAssetsType?, cache: SendableRef, factory factoryOut: SendableRef) -> LoadAsset? { guard let referencedAssets = referencedAssets, let referencedAssets = referencedAssets.data @@ -209,6 +202,7 @@ final class ReferencedAssetLoader { let usedKey = assetByUniqueName != nil ? asset.uniqueName() : asset.name() cache.value[asset.uniqueName()] = asset + factoryOut.value = factory self.loadAssetInternal(source: assetData, asset: asset, factory: factory) From 253249ae910a42f6cbb6dbd6bb8baca1e1960f2b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mikl=C3=B3s=20Fazekas?= Date: Mon, 10 Nov 2025 20:21:35 +0100 Subject: [PATCH 17/24] fix: typecheck --- example/src/pages/OutOfBandAssets.tsx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/example/src/pages/OutOfBandAssets.tsx b/example/src/pages/OutOfBandAssets.tsx index 6e94c66a..49849183 100644 --- a/example/src/pages/OutOfBandAssets.tsx +++ b/example/src/pages/OutOfBandAssets.tsx @@ -61,7 +61,6 @@ export default function StateMachine() { + {/* onError={(riveError: RNRiveError) => { console.log(riveError); }} - /> - {/* + */ + /* Load in an external asset from a URL, or bundled asset on the native platform, or as a source loaded directly from JavaScript. */} From cf9a8bbe464f909681b51a9c37d0a9e65fd967eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mikl=C3=B3s=20Fazekas?= Date: Tue, 11 Nov 2025 07:56:04 +0100 Subject: [PATCH 18/24] fix(ios): prevent race condition in referenced asset loading MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixed race condition where views would refresh before asset downloads completed. This mirrors the Android fix in commit c5adec2. Changes: - ReferencedAssetLoader: Added completion handlers to entire async chain - Completion fires in both success and failure cases - HybridRiveFile: Use DispatchGroup to wait for all asset loads - refreshAfterAssetChange() only called after all downloads finish This ensures views display updated assets even with slow network. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- ios/HybridRiveFile.swift | 11 ++++- ios/ReferencedAssetLoader.swift | 71 ++++++++++++++++++++++----------- 2 files changed, 56 insertions(+), 26 deletions(-) diff --git a/ios/HybridRiveFile.swift b/ios/HybridRiveFile.swift index 01e52442..1b4d7d1f 100644 --- a/ios/HybridRiveFile.swift +++ b/ios/HybridRiveFile.swift @@ -76,11 +76,16 @@ class HybridRiveFile: HybridRiveFileSpec { return } + let dispatchGroup = DispatchGroup() var hasChanged = false + for (key, assetData) in assetsData { guard let asset = cache[key] else { continue } if let riveFactory = cachedFactory { - loader.loadAsset(source: assetData, asset: asset, factory: riveFactory) + dispatchGroup.enter() + loader.loadAsset(source: assetData, asset: asset, factory: riveFactory) { + dispatchGroup.leave() + } } else { RCTLogError("[RiveFile] no factory available for update") } @@ -88,7 +93,9 @@ class HybridRiveFile: HybridRiveFileSpec { } if hasChanged { - refreshAfterAssetChange() + dispatchGroup.notify(queue: .main) { [weak self] in + self?.refreshAfterAssetChange() + } } } diff --git a/ios/ReferencedAssetLoader.swift b/ios/ReferencedAssetLoader.swift index ba692390..2bdff84a 100644 --- a/ios/ReferencedAssetLoader.swift +++ b/ios/ReferencedAssetLoader.swift @@ -41,9 +41,10 @@ final class ReferencedAssetLoader { handleRiveError(error: createIncorrectRiveURL(url)) } - private func downloadUrlAsset(url: String, listener: @escaping (Data) -> Void) { + private func downloadUrlAsset(url: String, listener: @escaping (Data) -> Void, onError: @escaping () -> Void) { guard isValidUrl(url) else { handleInvalidUrlError(url: url) + onError() return } if let fileUrl = URL(string: url), fileUrl.scheme == "file" { @@ -52,6 +53,7 @@ final class ReferencedAssetLoader { listener(data) } catch { handleInvalidUrlError(url: url) + onError() } return } @@ -59,6 +61,7 @@ final class ReferencedAssetLoader { let queue = URLSession.shared guard let requestUrl = URL(string: url) else { handleInvalidUrlError(url: url) + onError() return } @@ -66,16 +69,20 @@ final class ReferencedAssetLoader { let task = queue.dataTask(with: request) { [weak self] data, response, error in if error != nil { self?.handleInvalidUrlError(url: url) + onError() } else if let data = data { listener(data) + } else { + onError() } } task.resume() } - private func processAssetBytes(_ data: Data, asset: RiveFileAsset, factory: RiveFactory) { + private func processAssetBytes(_ data: Data, asset: RiveFileAsset, factory: RiveFactory, completion: @escaping () -> Void) { if data.isEmpty == true { + completion() return } DispatchQueue.global(qos: .background).async { @@ -84,39 +91,50 @@ final class ReferencedAssetLoader { let decodedImage = factory.decodeImage(data) DispatchQueue.main.async { imageAsset.renderImage(decodedImage) + completion() } case let fontAsset as RiveFontAsset: let decodedFont = factory.decodeFont(data) DispatchQueue.main.async { fontAsset.font(decodedFont) + completion() } case let audioAsset as RiveAudioAsset: - guard let decodedAudio = factory.decodeAudio(data) else { return } + guard let decodedAudio = factory.decodeAudio(data) else { + DispatchQueue.main.async { + completion() + } + return + } DispatchQueue.main.async { audioAsset.audio(decodedAudio) + completion() } default: - break + DispatchQueue.main.async { + completion() + } } } } private func handleSourceAssetId( - _ sourceAssetId: String, asset: RiveFileAsset, factory: RiveFactory + _ sourceAssetId: String, asset: RiveFileAsset, factory: RiveFactory, completion: @escaping () -> Void ) { guard URL(string: sourceAssetId) != nil else { + completion() return } - downloadUrlAsset(url: sourceAssetId) { [weak self] data in - self?.processAssetBytes(data, asset: asset, factory: factory) - } + downloadUrlAsset(url: sourceAssetId, listener: { [weak self] data in + self?.processAssetBytes(data, asset: asset, factory: factory, completion: completion) + }, onError: completion) } - private func handleSourceUrl(_ sourceUrl: String, asset: RiveFileAsset, factory: RiveFactory) { - downloadUrlAsset(url: sourceUrl) { [weak self] data in - self?.processAssetBytes(data, asset: asset, factory: factory) - } + private func handleSourceUrl(_ sourceUrl: String, asset: RiveFileAsset, factory: RiveFactory, completion: @escaping () -> Void) { + downloadUrlAsset(url: sourceUrl, listener: { [weak self] data in + self?.processAssetBytes(data, asset: asset, factory: factory, completion: completion) + }, onError: completion) } private func splitFileNameAndExtension(fileName: String) -> (name: String?, ext: String?)? { @@ -128,18 +146,20 @@ final class ReferencedAssetLoader { } private func loadResourceAsset( - sourceAsset: String, path: String?, listener: @escaping (Data) -> Void + sourceAsset: String, path: String?, listener: @escaping (Data) -> Void, onError: @escaping () -> Void ) { guard let splitSourceAssetName = splitFileNameAndExtension(fileName: sourceAsset), let name = splitSourceAssetName.name, let ext = splitSourceAssetName.ext else { handleRiveError(error: createAssetFileError(sourceAsset)) + onError() return } guard let folderUrl = Bundle.main.url(forResource: name, withExtension: ext) else { handleRiveError(error: createAssetFileError(sourceAsset)) + onError() return } @@ -152,39 +172,42 @@ final class ReferencedAssetLoader { } catch { DispatchQueue.main.async { self?.handleRiveError(error: createAssetFileError(sourceAsset)) + onError() } } } } private func handleSourceAsset( - _ sourceAsset: String, path: String?, asset: RiveFileAsset, factory: RiveFactory + _ sourceAsset: String, path: String?, asset: RiveFileAsset, factory: RiveFactory, completion: @escaping () -> Void ) { - loadResourceAsset(sourceAsset: sourceAsset, path: path) { [weak self] data in - self?.processAssetBytes(data, asset: asset, factory: factory) - } + loadResourceAsset(sourceAsset: sourceAsset, path: path, listener: { [weak self] data in + self?.processAssetBytes(data, asset: asset, factory: factory, completion: completion) + }, onError: completion) } private func loadAssetInternal( - source: ResolvedReferencedAsset, asset: RiveFileAsset, factory: RiveFactory + source: ResolvedReferencedAsset, asset: RiveFileAsset, factory: RiveFactory, completion: @escaping () -> Void ) { let sourceAssetId = source.sourceAssetId let sourceUrl = source.sourceUrl let sourceAsset = source.sourceAsset if let sourceAssetId = sourceAssetId { - handleSourceAssetId(sourceAssetId, asset: asset, factory: factory) + handleSourceAssetId(sourceAssetId, asset: asset, factory: factory, completion: completion) } else if let sourceUrl = sourceUrl { - handleSourceUrl(sourceUrl, asset: asset, factory: factory) + handleSourceUrl(sourceUrl, asset: asset, factory: factory, completion: completion) } else if let sourceAsset = sourceAsset { - handleSourceAsset(sourceAsset, path: source.path, asset: asset, factory: factory) + handleSourceAsset(sourceAsset, path: source.path, asset: asset, factory: factory, completion: completion) + } else { + completion() } } func loadAsset( - source: ResolvedReferencedAsset, asset: RiveFileAsset, factory: RiveFactory + source: ResolvedReferencedAsset, asset: RiveFileAsset, factory: RiveFactory, completion: @escaping () -> Void ) { - loadAssetInternal(source: source, asset: asset, factory: factory) + loadAssetInternal(source: source, asset: asset, factory: factory, completion: completion) } func createCustomLoader(referencedAssets: ReferencedAssetsType?, cache: SendableRef, factory factoryOut: SendableRef) @@ -204,7 +227,7 @@ final class ReferencedAssetLoader { cache.value[asset.uniqueName()] = asset factoryOut.value = factory - self.loadAssetInternal(source: assetData, asset: asset, factory: factory) + self.loadAssetInternal(source: assetData, asset: asset, factory: factory, completion: {}) return false } From 5b4958fa2de50114dc95c697e78ddb0dd1bb1247 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mikl=C3=B3s=20Fazekas?= Date: Tue, 11 Nov 2025 10:30:04 +0100 Subject: [PATCH 19/24] chore: remove rn82-example submodule MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- rn82-example | 1 - 1 file changed, 1 deletion(-) delete mode 160000 rn82-example diff --git a/rn82-example b/rn82-example deleted file mode 160000 index 032eeda5..00000000 --- a/rn82-example +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 032eeda50ad5a29c0c723babb906d9e0339487a8 From 4bbe09860f3b5a13022259bfc270bc7cb6ab1475 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mikl=C3=B3s=20Fazekas?= Date: Wed, 12 Nov 2025 13:41:04 +0100 Subject: [PATCH 20/24] reactor: streamline rivefile factory --- ios/HybridRiveFileFactory.swift | 308 +++++++++++++++----------------- 1 file changed, 146 insertions(+), 162 deletions(-) diff --git a/ios/HybridRiveFileFactory.swift b/ios/HybridRiveFileFactory.swift index 988ff825..295a8a09 100644 --- a/ios/HybridRiveFileFactory.swift +++ b/ios/HybridRiveFileFactory.swift @@ -1,36 +1,96 @@ import NitroModules import RiveRuntime -final class HybridRiveFileFactory: HybridRiveFileFactorySpec { +final class HybridRiveFileFactory: HybridRiveFileFactorySpec, @unchecked Sendable { let assetLoader = ReferencedAssetLoader() - private func buildRiveFile(data: Data, loadCdn: Bool, referencedAssets: ReferencedAssetsType?) throws -> (file: RiveFile, cache: ReferencedAssetCache, factory: RiveFactory?, loader: ReferencedAssetLoader?) { - var referencedAssetCache = SendableRef(ReferencedAssetCache()) - var factoryCache: SendableRef = .init(nil) - let customLoader = assetLoader.createCustomLoader(referencedAssets: referencedAssets, cache: referencedAssetCache, factory: factoryCache) + private final func buildRiveFile( + fileWithCustomAssetLoader: (@escaping LoadAsset) throws -> RiveFile, + file: () throws -> RiveFile, + referencedAssets: ReferencedAssetsType? + ) throws -> ( + file: RiveFile, cache: ReferencedAssetCache, factory: RiveFactory?, + loader: ReferencedAssetLoader? + ) { + let referencedAssetCache = SendableRef(ReferencedAssetCache()) + let factoryCache: SendableRef = .init(nil) + let customLoader = assetLoader.createCustomLoader( + referencedAssets: referencedAssets, cache: referencedAssetCache, factory: factoryCache) + + let riveFile = + if let customLoader = customLoader { + try fileWithCustomAssetLoader(customLoader) + } else { + try file() + } - let riveFile = if let customLoader = customLoader { - try RiveFile(data: data, loadCdn: loadCdn, customAssetLoader: customLoader) - } else { - try RiveFile(data: data, loadCdn: loadCdn) - } + return ( + file: riveFile, cache: referencedAssetCache.value, factory: factoryCache.value, + loader: customLoader != nil ? assetLoader : nil + ) + } - return (file: riveFile, cache: referencedAssetCache.value, factory: factoryCache.value, loader: customLoader != nil ? assetLoader : nil) + private func buildRiveFile(data: Data, loadCdn: Bool, referencedAssets: ReferencedAssetsType?) + throws -> ( + file: RiveFile, cache: ReferencedAssetCache, factory: RiveFactory?, + loader: ReferencedAssetLoader? + ) + { + return try buildRiveFile( + fileWithCustomAssetLoader: { (loader) in + try RiveFile(data: data, loadCdn: loadCdn, customAssetLoader: loader) + }, + file: { try RiveFile(data: data, loadCdn: loadCdn) }, + referencedAssets: referencedAssets) } - // MARK: Public Methods - func fromURL(url: String, loadCdn: Bool, referencedAssets: ReferencedAssetsType?) throws -> Promise<(any HybridRiveFileSpec)> { + /// Asynchronously creates a `HybridRiveFileSpec` by performing the following steps: + /// 1. Executes `check()` to validate or fetch initial data. + /// 2. Processes the result with `prepare()`. + /// 3. If a custom asset loader is available, loads the file using `fileWithCustomAssetLoader(prepared, assetLoader)`. + /// Otherwise, loads the file using `file(prepared)`. + /// 4. Handles referenced assets and caches as needed. + /// - Parameters: + /// - check: Closure to validate or fetch initial data. + /// - prepare: Closure to process the checked result. + /// - fileWithCustomAssetLoader: Closure to load the file with a custom asset loader. + /// - file: Closure to load the file without a custom asset loader. + /// - referencedAssets: Optional referenced assets. + /// - Returns: A promise resolving to a `HybridRiveFileSpec`. + /// - Throws: Runtime errors if any step fails. + func genericFrom( + check: @escaping () throws -> CheckResult, + prepare: @escaping (CheckResult) throws -> Prepared, + fileWithCustomAssetLoader: @escaping (Prepared, @escaping LoadAsset) throws -> RiveFile, + file: @escaping (Prepared) throws -> RiveFile, + referencedAssets: ReferencedAssetsType? + ) throws -> Promise<(any HybridRiveFileSpec)> { return Promise.async { do { - guard let url = URL(string: url) else { - throw RuntimeError.error(withMessage: "Invalid URL: \(url)") - } + let checked = try check() let result = try await withCheckedThrowingContinuation { continuation in DispatchQueue.global(qos: .userInitiated).async { do { - let riveData = try Data(contentsOf: url) - let result = try self.buildRiveFile(data: riveData, loadCdn: loadCdn, referencedAssets: referencedAssets) + let prepared = try prepare(checked) + + let referencedAssetCache = SendableRef(ReferencedAssetCache()) + let factoryCache: SendableRef = .init(nil) + let customLoader = self.assetLoader.createCustomLoader( + referencedAssets: referencedAssets, cache: referencedAssetCache, + factory: factoryCache) + + let riveFile = + if let customLoader = customLoader { + try fileWithCustomAssetLoader(prepared, customLoader) + } else { + try file(prepared) + } + + let result = ( + file: riveFile, cache: referencedAssetCache.value, factory: factoryCache.value, + loader: customLoader != nil ? self.assetLoader : nil + ) DispatchQueue.main.async { continuation.resume(returning: result) } @@ -59,160 +119,84 @@ final class HybridRiveFileFactory: HybridRiveFileFactorySpec { } } - func fromFileURL(fileURL: String, loadCdn: Bool, referencedAssets: ReferencedAssetsType?) throws -> Promise<(any HybridRiveFileSpec)> { - guard let url = URL(string: fileURL) else { - throw RuntimeError.error(withMessage: "fromFileURL: Invalid URL: \(fileURL)") - } - - guard url.isFileURL else { - throw RuntimeError.error(withMessage: "fromFileURL: URL must be a file URL: \(fileURL)") - } - - return Promise.async { - do { - let result = try await withCheckedThrowingContinuation { continuation in - DispatchQueue.global(qos: .userInitiated).async { - do { - let data = try Data(contentsOf: url) - let result = try self.buildRiveFile(data: data, loadCdn: loadCdn, referencedAssets: referencedAssets) - DispatchQueue.main.async { - continuation.resume(returning: result) - } - } catch { - DispatchQueue.main.async { - continuation.resume(throwing: error) - } - } - } + // MARK: Public Methods + func fromURL(url: String, loadCdn: Bool, referencedAssets: ReferencedAssetsType?) throws + -> Promise<(any HybridRiveFileSpec)> + { + return try genericFrom( + check: { + guard let url = URL(string: url) else { + throw RuntimeError.error(withMessage: "Invalid URL: \(url)") } - - let hybridRiveFile = HybridRiveFile() - hybridRiveFile.riveFile = result.file - hybridRiveFile.referencedAssetCache = result.cache - hybridRiveFile.assetLoader = result.loader - return hybridRiveFile - } catch let error as NSError { - throw RuntimeError.error( - withMessage: "Failed to load Rive file: \(error.localizedDescription)") - } catch { - throw RuntimeError.error(withMessage: "Unknown error occurred while loading Rive file") - } - } + return url + }, + prepare: { url in try Data(contentsOf: url) }, + fileWithCustomAssetLoader: { (data, loader) in + try RiveFile(data: data, loadCdn: loadCdn, customAssetLoader: loader) + }, + file: { (data) in try RiveFile(data: data, loadCdn: loadCdn) }, + referencedAssets: referencedAssets + ) } - func fromResource(resource: String, loadCdn: Bool, referencedAssets: ReferencedAssetsType?) throws -> Promise<(any HybridRiveFileSpec)> { - guard let _ = Bundle.main.path(forResource: resource, ofType: "riv") else { - throw RuntimeError.error(withMessage: "Could not find Rive file: \(resource).riv") - } - - return Promise.async { - do { - let assetLoader = self.assetLoader - let referencedAssetCache = SendableRef(ReferencedAssetCache()) - let factoryCache = SendableRef(nil) - let riveFile = try await withCheckedThrowingContinuation { continuation in - DispatchQueue.global(qos: .userInitiated).async { - do { - let riveFile = - if let customLoader = assetLoader.createCustomLoader(referencedAssets: referencedAssets, cache: referencedAssetCache, factory: factoryCache) { - try RiveFile(resource: resource, loadCdn: loadCdn, customAssetLoader: customLoader) - } else { - try RiveFile(resource: resource, loadCdn: loadCdn) - } - DispatchQueue.main.async { - continuation.resume(returning: riveFile) - } - } catch { - DispatchQueue.main.async { - continuation.resume(throwing: error) - } - } - } + func fromFileURL(fileURL: String, loadCdn: Bool, referencedAssets: ReferencedAssetsType?) throws + -> Promise<(any HybridRiveFileSpec)> + { + return try genericFrom( + check: { + guard let url = URL(string: fileURL) else { + throw RuntimeError.error(withMessage: "Invalid URL: \(fileURL)") } - - let hybridRiveFile = HybridRiveFile() - hybridRiveFile.riveFile = riveFile - if referencedAssets != nil { - hybridRiveFile.referencedAssetCache = referencedAssetCache.value - hybridRiveFile.assetLoader = assetLoader + guard url.isFileURL else { + throw RuntimeError.error(withMessage: "fromFileURL: URL must be a file URL: \(fileURL)") } - return hybridRiveFile - } catch let error as NSError { - throw RuntimeError.error( - withMessage: "Failed to load Rive file: \(error.localizedDescription)") - } catch { - throw RuntimeError.error(withMessage: "Unknown error occurred while loading Rive file") - } - } + return url + }, + prepare: { url in try Data(contentsOf: url) }, + fileWithCustomAssetLoader: { (data, loader) in + try RiveFile(data: data, loadCdn: loadCdn, customAssetLoader: loader) + }, + file: { (data) in try RiveFile(data: data, loadCdn: loadCdn) }, + referencedAssets: referencedAssets + ) } - func fromResource(resource: String, loadCdn: Bool) throws -> Promise<(any HybridRiveFileSpec)> { - guard Bundle.main.path(forResource: resource, ofType: "riv") != nil else { - throw RuntimeError.error(withMessage: "Could not find Rive file: \(resource).riv") - } - - return Promise.async { - do { - let riveFile = try await withCheckedThrowingContinuation { continuation in - DispatchQueue.global(qos: .userInitiated).async { - do { - let riveFile = try RiveFile(resource: resource, loadCdn: loadCdn) - DispatchQueue.main.async { - continuation.resume(returning: riveFile) - } - } catch { - DispatchQueue.main.async { - continuation.resume(throwing: error) - } - } - } + func fromResource(resource: String, loadCdn: Bool, referencedAssets: ReferencedAssetsType?) throws + -> Promise<(any HybridRiveFileSpec)> + { + return try genericFrom( + check: { + guard Bundle.main.path(forResource: resource, ofType: "riv") != nil else { + throw RuntimeError.error(withMessage: "Could not find Rive file: \(resource).riv") } - - let hybridRiveFile = HybridRiveFile() - hybridRiveFile.riveFile = riveFile - return hybridRiveFile - } catch let error as NSError { - throw RuntimeError.error( - withMessage: "Failed to load Rive file: \(error.localizedDescription)") - } catch { - throw RuntimeError.error(withMessage: "Unknown error occurred while loading Rive file") - } - } + return resource + }, + prepare: { $0 }, + fileWithCustomAssetLoader: { (resource, loader) in + try RiveFile(resource: resource, loadCdn: loadCdn, customAssetLoader: loader) + }, + file: { (resource) in try RiveFile(resource: resource, loadCdn: loadCdn) }, + referencedAssets: referencedAssets + ) } - func fromBytes(bytes: ArrayBufferHolder, loadCdn: Bool, referencedAssets: ReferencedAssetsType?) throws -> Promise< - (any HybridRiveFileSpec) - > { - let data = bytes.toData(copyIfNeeded: false) - return Promise.async { - do { - let result = try await withCheckedThrowingContinuation { continuation in - DispatchQueue.global(qos: .userInitiated).async { - do { - let result = try self.buildRiveFile(data: data, loadCdn: loadCdn, referencedAssets: referencedAssets) - DispatchQueue.main.async { - continuation.resume(returning: result) - } - } catch { - DispatchQueue.main.async { - continuation.resume(throwing: error) - } - } - } - } + func fromResource(resource: String, loadCdn: Bool) throws -> Promise<(any HybridRiveFileSpec)> { + return try fromResource(resource: resource, loadCdn: loadCdn, referencedAssets: nil) + } - let hybridRiveFile = HybridRiveFile() - hybridRiveFile.riveFile = result.file - hybridRiveFile.referencedAssetCache = result.cache - hybridRiveFile.assetLoader = result.loader - return hybridRiveFile - } catch let error as NSError { - throw RuntimeError.error( - withMessage: "Failed to load Rive file from bytes: \(error.localizedDescription)") - } catch { - throw RuntimeError.error( - withMessage: "Unknown error occurred while loading Rive file from bytes") - } - } + func fromBytes(bytes: ArrayBufferHolder, loadCdn: Bool, referencedAssets: ReferencedAssetsType?) + throws -> Promise< + (any HybridRiveFileSpec) + > + { + return try genericFrom( + check: { bytes.toData(copyIfNeeded: false) }, + prepare: { $0 }, + fileWithCustomAssetLoader: { (data, loader) in + try RiveFile(data: data, loadCdn: loadCdn, customAssetLoader: loader) + }, + file: { (data) in try RiveFile(data: data, loadCdn: loadCdn) }, + referencedAssets: referencedAssets + ) } } From c96265c2ef6080f8437eb10751c9fc866e3a9247 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mikl=C3=B3s=20Fazekas?= Date: Wed, 12 Nov 2025 14:20:37 +0100 Subject: [PATCH 21/24] refactor: decouple riveFile and riveView --- ios/HybridRiveFile.swift | 2 +- ios/HybridRiveView.swift | 2 +- ios/RiveReactNativeView.swift | 21 +++++++++++++-------- 3 files changed, 15 insertions(+), 10 deletions(-) diff --git a/ios/HybridRiveFile.swift b/ios/HybridRiveFile.swift index 1b4d7d1f..b3109e8b 100644 --- a/ios/HybridRiveFile.swift +++ b/ios/HybridRiveFile.swift @@ -2,7 +2,7 @@ import RiveRuntime typealias ReferencedAssetCache = [String: RiveFileAsset] -class HybridRiveFile: HybridRiveFileSpec { +class HybridRiveFile: HybridRiveFileSpec, RiveViewSource { var riveFile: RiveFile? var referencedAssetCache: ReferencedAssetCache? var assetLoader: ReferencedAssetLoader? diff --git a/ios/HybridRiveView.swift b/ios/HybridRiveView.swift index 2d813788..c4abac0e 100644 --- a/ios/HybridRiveView.swift +++ b/ios/HybridRiveView.swift @@ -92,7 +92,7 @@ class HybridRiveView : HybridRiveViewSpec { autoBind: autoBind ?? DefaultConfiguration.autoBind, autoPlay: autoPlay ?? DefaultConfiguration.autoPlay, riveFile: file, - hybridRiveFile: hybridFile, + viewSource: hybridFile, alignment: convertAlignment(alignment) ?? DefaultConfiguration.alignment, fit: convertFit(fit) ?? DefaultConfiguration.fit, layoutScaleFactor: layoutScaleFactor ?? DefaultConfiguration.layoutScaleFactor diff --git a/ios/RiveReactNativeView.swift b/ios/RiveReactNativeView.swift index 1dddddbe..18a04acb 100644 --- a/ios/RiveReactNativeView.swift +++ b/ios/RiveReactNativeView.swift @@ -2,13 +2,18 @@ import UIKit import RiveRuntime import NitroModules +protocol RiveViewSource: AnyObject { + func registerView(_ view: RiveReactNativeView) + func unregisterView(_ view: RiveReactNativeView) +} + struct ViewConfiguration { let artboardName: String? let stateMachineName: String? let autoBind: Bool let autoPlay: Bool let riveFile: RiveFile - let hybridRiveFile: HybridRiveFile? + let viewSource: RiveViewSource? let alignment: RiveRuntime.RiveAlignment let fit: RiveRuntime.RiveFit let layoutScaleFactor: Double @@ -21,7 +26,7 @@ class RiveReactNativeView: UIView, RiveStateMachineDelegate { private var eventListeners: [(UnifiedRiveEvent) -> Void] = [] private var viewReadyContinuation: CheckedContinuation? private var isViewReady = false - private weak var riveFile: HybridRiveFile? + private weak var viewSource: RiveViewSource? // MARK: Public Config Properties var autoPlay: Bool = true @@ -45,9 +50,9 @@ class RiveReactNativeView: UIView, RiveStateMachineDelegate { baseViewModel = RiveViewModel(model, autoPlay: config.autoPlay) createViewFromViewModel() - if let hybridRiveFile = config.hybridRiveFile { - self.riveFile = hybridRiveFile - hybridRiveFile.registerView(self) + if let viewSource = config.viewSource { + self.viewSource = viewSource + viewSource.registerView(self) } } @@ -170,9 +175,9 @@ class RiveReactNativeView: UIView, RiveStateMachineDelegate { riveView?.stateMachineDelegate = nil riveView = nil baseViewModel = nil - if let riveFile = riveFile { - riveFile.unregisterView(self) - self.riveFile = nil + if let viewSource = viewSource { + viewSource.unregisterView(self) + self.viewSource = nil } } From fb0acffeb77b5d02b7d9dec202c9458b086beef8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mikl=C3=B3s=20Fazekas?= Date: Wed, 12 Nov 2025 14:21:56 +0100 Subject: [PATCH 22/24] refactor: remove unused export --- src/index.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/index.tsx b/src/index.tsx index 83122ebd..659e1301 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -50,7 +50,6 @@ export const RiveView = getHostComponent( 'RiveView', () => RiveViewConfig ) as ReactNativeView; -export { RiveView as NitroRiveView }; export type { RiveViewProps, RiveViewMethods }; export type { RiveFile } from './specs/RiveFile.nitro'; From 80b2196834b9de084f6bccee5f0d0c2a72c4f0c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mikl=C3=B3s=20Fazekas?= Date: Wed, 12 Nov 2025 14:25:50 +0100 Subject: [PATCH 23/24] chore: refresh --- ios/ReferencedAssetLoader.swift | 63 ++++++++++++++++++++++----------- 1 file changed, 42 insertions(+), 21 deletions(-) diff --git a/ios/ReferencedAssetLoader.swift b/ios/ReferencedAssetLoader.swift index 2bdff84a..0939a524 100644 --- a/ios/ReferencedAssetLoader.swift +++ b/ios/ReferencedAssetLoader.swift @@ -41,7 +41,9 @@ final class ReferencedAssetLoader { handleRiveError(error: createIncorrectRiveURL(url)) } - private func downloadUrlAsset(url: String, listener: @escaping (Data) -> Void, onError: @escaping () -> Void) { + private func downloadUrlAsset( + url: String, listener: @escaping (Data) -> Void, onError: @escaping () -> Void + ) { guard isValidUrl(url) else { handleInvalidUrlError(url: url) onError() @@ -80,7 +82,9 @@ final class ReferencedAssetLoader { task.resume() } - private func processAssetBytes(_ data: Data, asset: RiveFileAsset, factory: RiveFactory, completion: @escaping () -> Void) { + private func processAssetBytes( + _ data: Data, asset: RiveFileAsset, factory: RiveFactory, completion: @escaping () -> Void + ) { if data.isEmpty == true { completion() return @@ -119,22 +123,30 @@ final class ReferencedAssetLoader { } private func handleSourceAssetId( - _ sourceAssetId: String, asset: RiveFileAsset, factory: RiveFactory, completion: @escaping () -> Void + _ sourceAssetId: String, asset: RiveFileAsset, factory: RiveFactory, + completion: @escaping () -> Void ) { guard URL(string: sourceAssetId) != nil else { completion() return } - downloadUrlAsset(url: sourceAssetId, listener: { [weak self] data in - self?.processAssetBytes(data, asset: asset, factory: factory, completion: completion) - }, onError: completion) + downloadUrlAsset( + url: sourceAssetId, + listener: { [weak self] data in + self?.processAssetBytes(data, asset: asset, factory: factory, completion: completion) + }, onError: completion) } - private func handleSourceUrl(_ sourceUrl: String, asset: RiveFileAsset, factory: RiveFactory, completion: @escaping () -> Void) { - downloadUrlAsset(url: sourceUrl, listener: { [weak self] data in - self?.processAssetBytes(data, asset: asset, factory: factory, completion: completion) - }, onError: completion) + private func handleSourceUrl( + _ sourceUrl: String, asset: RiveFileAsset, factory: RiveFactory, + completion: @escaping () -> Void + ) { + downloadUrlAsset( + url: sourceUrl, + listener: { [weak self] data in + self?.processAssetBytes(data, asset: asset, factory: factory, completion: completion) + }, onError: completion) } private func splitFileNameAndExtension(fileName: String) -> (name: String?, ext: String?)? { @@ -146,7 +158,8 @@ final class ReferencedAssetLoader { } private func loadResourceAsset( - sourceAsset: String, path: String?, listener: @escaping (Data) -> Void, onError: @escaping () -> Void + sourceAsset: String, path: String?, listener: @escaping (Data) -> Void, + onError: @escaping () -> Void ) { guard let splitSourceAssetName = splitFileNameAndExtension(fileName: sourceAsset), let name = splitSourceAssetName.name, @@ -179,15 +192,19 @@ final class ReferencedAssetLoader { } private func handleSourceAsset( - _ sourceAsset: String, path: String?, asset: RiveFileAsset, factory: RiveFactory, completion: @escaping () -> Void + _ sourceAsset: String, path: String?, asset: RiveFileAsset, factory: RiveFactory, + completion: @escaping () -> Void ) { - loadResourceAsset(sourceAsset: sourceAsset, path: path, listener: { [weak self] data in - self?.processAssetBytes(data, asset: asset, factory: factory, completion: completion) - }, onError: completion) + loadResourceAsset( + sourceAsset: sourceAsset, path: path, + listener: { [weak self] data in + self?.processAssetBytes(data, asset: asset, factory: factory, completion: completion) + }, onError: completion) } private func loadAssetInternal( - source: ResolvedReferencedAsset, asset: RiveFileAsset, factory: RiveFactory, completion: @escaping () -> Void + source: ResolvedReferencedAsset, asset: RiveFileAsset, factory: RiveFactory, + completion: @escaping () -> Void ) { let sourceAssetId = source.sourceAssetId let sourceUrl = source.sourceUrl @@ -198,19 +215,24 @@ final class ReferencedAssetLoader { } else if let sourceUrl = sourceUrl { handleSourceUrl(sourceUrl, asset: asset, factory: factory, completion: completion) } else if let sourceAsset = sourceAsset { - handleSourceAsset(sourceAsset, path: source.path, asset: asset, factory: factory, completion: completion) + handleSourceAsset( + sourceAsset, path: source.path, asset: asset, factory: factory, completion: completion) } else { completion() } } func loadAsset( - source: ResolvedReferencedAsset, asset: RiveFileAsset, factory: RiveFactory, completion: @escaping () -> Void + source: ResolvedReferencedAsset, asset: RiveFileAsset, factory: RiveFactory, + completion: @escaping () -> Void ) { loadAssetInternal(source: source, asset: asset, factory: factory, completion: completion) } - func createCustomLoader(referencedAssets: ReferencedAssetsType?, cache: SendableRef, factory factoryOut: SendableRef) + func createCustomLoader( + referencedAssets: ReferencedAssetsType?, cache: SendableRef, + factory factoryOut: SendableRef + ) -> LoadAsset? { guard let referencedAssets = referencedAssets, let referencedAssets = referencedAssets.data @@ -222,14 +244,13 @@ final class ReferencedAssetLoader { guard let assetData = assetByUniqueName ?? referencedAssets[asset.name()] else { return false } - let usedKey = assetByUniqueName != nil ? asset.uniqueName() : asset.name() cache.value[asset.uniqueName()] = asset factoryOut.value = factory self.loadAssetInternal(source: assetData, asset: asset, factory: factory, completion: {}) - return false + return true } } } From f9b917f53aa8b605b41d0c3cdf73baec1d5a8cf2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mikl=C3=B3s=20Fazekas?= Date: Wed, 12 Nov 2025 15:09:10 +0100 Subject: [PATCH 24/24] removed unused buildFile --- ios/HybridRiveFileFactory.swift | 40 --------------------------------- 1 file changed, 40 deletions(-) diff --git a/ios/HybridRiveFileFactory.swift b/ios/HybridRiveFileFactory.swift index 295a8a09..9030d93d 100644 --- a/ios/HybridRiveFileFactory.swift +++ b/ios/HybridRiveFileFactory.swift @@ -4,46 +4,6 @@ import RiveRuntime final class HybridRiveFileFactory: HybridRiveFileFactorySpec, @unchecked Sendable { let assetLoader = ReferencedAssetLoader() - private final func buildRiveFile( - fileWithCustomAssetLoader: (@escaping LoadAsset) throws -> RiveFile, - file: () throws -> RiveFile, - referencedAssets: ReferencedAssetsType? - ) throws -> ( - file: RiveFile, cache: ReferencedAssetCache, factory: RiveFactory?, - loader: ReferencedAssetLoader? - ) { - let referencedAssetCache = SendableRef(ReferencedAssetCache()) - let factoryCache: SendableRef = .init(nil) - let customLoader = assetLoader.createCustomLoader( - referencedAssets: referencedAssets, cache: referencedAssetCache, factory: factoryCache) - - let riveFile = - if let customLoader = customLoader { - try fileWithCustomAssetLoader(customLoader) - } else { - try file() - } - - return ( - file: riveFile, cache: referencedAssetCache.value, factory: factoryCache.value, - loader: customLoader != nil ? assetLoader : nil - ) - } - - private func buildRiveFile(data: Data, loadCdn: Bool, referencedAssets: ReferencedAssetsType?) - throws -> ( - file: RiveFile, cache: ReferencedAssetCache, factory: RiveFactory?, - loader: ReferencedAssetLoader? - ) - { - return try buildRiveFile( - fileWithCustomAssetLoader: { (loader) in - try RiveFile(data: data, loadCdn: loadCdn, customAssetLoader: loader) - }, - file: { try RiveFile(data: data, loadCdn: loadCdn) }, - referencedAssets: referencedAssets) - } - /// Asynchronously creates a `HybridRiveFileSpec` by performing the following steps: /// 1. Executes `check()` to validate or fetch initial data. /// 2. Processes the result with `prepare()`.