@thelacanians/vue-native-cli 0.4.15 → 0.6.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +329 -15
- package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Bridge/NativeBridge.kt +118 -0
- package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Components/Factories/VViewFactory.kt +178 -1
- package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Modules/GeneratedModuleRegistry.kt +28 -0
- package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Modules/NativeModuleRegistry.kt +3 -0
- package/native/android/VueNativeCore/src/test/kotlin/com/vuenative/core/ComponentFactoryTest.kt +674 -0
- package/native/android/VueNativeCore/src/test/kotlin/com/vuenative/core/ErrorOverlayViewTest.kt +183 -0
- package/native/android/VueNativeCore/src/test/kotlin/com/vuenative/core/EventThrottleTest.kt +203 -0
- package/native/android/VueNativeCore/src/test/kotlin/com/vuenative/core/HotReloadManagerTest.kt +162 -0
- package/native/android/VueNativeCore/src/test/kotlin/com/vuenative/core/JSPolyfillsTest.kt +153 -0
- package/native/android/VueNativeCore/src/test/kotlin/com/vuenative/core/NativeBridgeTest.kt +6 -3
- package/native/android/VueNativeCore/src/test/kotlin/com/vuenative/core/NativeModuleTest.kt +475 -0
- package/native/android/gradle.properties +1 -0
- package/native/android/gradlew +1 -1
- package/native/ios/VueNativeCore/Package.swift +1 -1
- package/native/ios/VueNativeCore/Sources/VueNativeCore/Bridge/EventThrottle.swift +1 -0
- package/native/ios/VueNativeCore/Sources/VueNativeCore/Bridge/NativeBridge.swift +143 -5
- package/native/ios/VueNativeCore/Sources/VueNativeCore/Components/Factories/VTextFactory.swift +43 -0
- package/native/ios/VueNativeCore/Sources/VueNativeCore/Components/Factories/VViewFactory.swift +116 -4
- package/native/ios/VueNativeCore/Sources/VueNativeCore/Helpers/GestureWrapper.swift +100 -0
- package/native/ios/VueNativeCore/Sources/VueNativeCore/Modules/GeneratedModuleRegistry.swift +28 -0
- package/native/ios/VueNativeCore/Sources/VueNativeCore/Modules/NativeModuleRegistry.swift +3 -0
- package/native/ios/VueNativeCore/Tests/VueNativeCoreTests/CertificatePinningTests.swift +190 -0
- package/native/ios/VueNativeCore/Tests/VueNativeCoreTests/ComponentFactoryTests.swift +585 -0
- package/native/ios/VueNativeCore/Tests/VueNativeCoreTests/EventThrottleTests.swift +161 -0
- package/native/ios/VueNativeCore/Tests/VueNativeCoreTests/HotReloadManagerTests.swift +88 -0
- package/native/ios/VueNativeCore/Tests/VueNativeCoreTests/JSPolyfillsTests.swift +319 -0
- package/native/ios/VueNativeCore/Tests/VueNativeCoreTests/NativeModuleTests.swift +400 -0
- package/native/macos/VueNativeMacOS/Package.swift +34 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Bridge/ErrorOverlayView.swift +112 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Bridge/EventThrottle.swift +58 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Bridge/HotReloadManager.swift +153 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Bridge/JSPolyfills.swift +696 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Bridge/JSRuntime.swift +347 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Bridge/NativeBridge.swift +877 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Bridge/VueNativeWindowController.swift +125 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/ComponentRegistry.swift +209 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VActionSheetFactory.swift +155 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VActivityIndicatorFactory.swift +85 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VAlertDialogFactory.swift +132 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VButtonFactory.swift +83 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VCheckboxFactory.swift +108 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VDropdownFactory.swift +155 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VImageFactory.swift +270 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VInputFactory.swift +257 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VKeyboardAvoidingFactory.swift +22 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VListFactory.swift +324 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VModalFactory.swift +231 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VOutlineViewFactory.swift +276 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VPickerFactory.swift +134 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VPressableFactory.swift +120 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VProgressBarFactory.swift +71 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VRadioFactory.swift +193 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VRefreshControlFactory.swift +25 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VSafeAreaFactory.swift +46 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VScrollViewFactory.swift +190 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VSectionListFactory.swift +374 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VSegmentedControlFactory.swift +125 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VSliderFactory.swift +131 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VSplitViewFactory.swift +215 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VStatusBarFactory.swift +25 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VSwitchFactory.swift +92 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VTextFactory.swift +336 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VToolbarFactory.swift +212 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VVideoFactory.swift +245 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VViewFactory.swift +314 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VWebViewFactory.swift +162 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/NativeComponentFactory.swift +54 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Helpers/ClickableView.swift +100 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Helpers/Extensions.swift +23 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Helpers/GestureWrapper.swift +183 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Helpers/NSColor+Hex.swift +78 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Layout/FlippedView.swift +19 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Layout/LayoutNode.swift +493 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Modules/AnimationModule.swift +354 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Modules/AppStateModule.swift +62 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Modules/BiometryModule.swift +60 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Modules/CameraModule.swift +167 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Modules/ClipboardModule.swift +34 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Modules/DeviceInfoModule.swift +49 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Modules/DragDropModule.swift +50 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Modules/FileDialogModule.swift +86 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Modules/HapticsModule.swift +42 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Modules/KeyboardModule.swift +28 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Modules/LinkingModule.swift +49 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Modules/MenuModule.swift +95 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Modules/NativeModuleRegistry.swift +63 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Modules/NotificationsModule.swift +112 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Modules/PermissionsModule.swift +149 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Modules/ShareModule.swift +37 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Modules/WindowModule.swift +71 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Resources/vue-native-placeholder.js +2 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Styling/StyleEngine.swift +885 -0
- package/native/macos/VueNativeMacOS/Tests/VueNativeMacOSTests/ComponentFactoryTests.swift +80 -0
- package/native/macos/VueNativeMacOS/Tests/VueNativeMacOSTests/VueNativeMacOSTests.swift +149 -0
- package/native/shared/VueNativeShared/AGENTS.md +129 -0
- package/native/shared/VueNativeShared/Package.swift +14 -0
- package/native/shared/VueNativeShared/Sources/VueNativeShared/CertificatePinning.swift +134 -0
- package/native/shared/VueNativeShared/Sources/VueNativeShared/EventThrottle.swift +78 -0
- package/native/shared/VueNativeShared/Sources/VueNativeShared/HotReloadManager.swift +162 -0
- package/native/shared/VueNativeShared/Sources/VueNativeShared/JSRuntime.swift +412 -0
- package/native/shared/VueNativeShared/Sources/VueNativeShared/Modules/AsyncStorageModule.swift +68 -0
- package/native/shared/VueNativeShared/Sources/VueNativeShared/Modules/AudioModule.swift +359 -0
- package/native/shared/VueNativeShared/Sources/VueNativeShared/Modules/DatabaseModule.swift +259 -0
- package/native/shared/VueNativeShared/Sources/VueNativeShared/Modules/FileSystemModule.swift +233 -0
- package/native/shared/VueNativeShared/Sources/VueNativeShared/Modules/GeolocationModule.swift +156 -0
- package/native/shared/VueNativeShared/Sources/VueNativeShared/Modules/NetworkModule.swift +59 -0
- package/native/shared/VueNativeShared/Sources/VueNativeShared/Modules/PerformanceModule.swift +113 -0
- package/native/shared/VueNativeShared/Sources/VueNativeShared/Modules/SecureStorageModule.swift +119 -0
- package/native/shared/VueNativeShared/Sources/VueNativeShared/Modules/WebSocketModule.swift +212 -0
- package/native/shared/VueNativeShared/Sources/VueNativeShared/NativeEventDispatcher.swift +6 -0
- package/native/shared/VueNativeShared/Sources/VueNativeShared/NativeModule.swift +26 -0
- package/native/shared/VueNativeShared/Sources/VueNativeShared/NativeModuleRegistry.swift +37 -0
- package/native/shared/VueNativeShared/Sources/VueNativeShared/SharedJSPolyfills.swift +673 -0
- package/native/shared/VueNativeShared/Tests/VueNativeSharedTests/VueNativeSharedTests.swift +44 -0
- package/package.json +8 -2
|
@@ -61,6 +61,23 @@ public final class NativeBridge {
|
|
|
61
61
|
/// Reference to the JS runtime.
|
|
62
62
|
private let runtime = JSRuntime.shared
|
|
63
63
|
|
|
64
|
+
// MARK: - Teleport Support
|
|
65
|
+
|
|
66
|
+
/// Maps teleport marker IDs (start, end) for cleanup
|
|
67
|
+
private var teleportMarkers: [Int: (start: Int, end: Int)] = [:]
|
|
68
|
+
|
|
69
|
+
/// Maps parent node IDs to their teleport containers
|
|
70
|
+
private var teleportContainers: [Int: UIView] = [:]
|
|
71
|
+
|
|
72
|
+
/// Modal container for teleporting modals
|
|
73
|
+
private lazy var modalContainer: UIView = {
|
|
74
|
+
let container = UIView()
|
|
75
|
+
container.backgroundColor = .clear
|
|
76
|
+
container.isUserInteractionEnabled = true
|
|
77
|
+
container.translatesAutoresizingMaskIntoConstraints = false
|
|
78
|
+
return container
|
|
79
|
+
}()
|
|
80
|
+
|
|
64
81
|
// MARK: - Initialization
|
|
65
82
|
|
|
66
83
|
private init() {}
|
|
@@ -239,6 +256,12 @@ public final class NativeBridge {
|
|
|
239
256
|
handleRemoveEventListener(args: args)
|
|
240
257
|
case "setRootView":
|
|
241
258
|
handleSetRootView(args: args)
|
|
259
|
+
case "createTeleport":
|
|
260
|
+
handleCreateTeleport(args: args)
|
|
261
|
+
case "removeTeleport":
|
|
262
|
+
handleRemoveTeleport(args: args)
|
|
263
|
+
case "teleportTo":
|
|
264
|
+
handleTeleportTo(args: args)
|
|
242
265
|
case "invokeNativeModule":
|
|
243
266
|
handleInvokeNativeModule(args: args)
|
|
244
267
|
case "invokeNativeModuleSync":
|
|
@@ -425,11 +448,8 @@ public final class NativeBridge {
|
|
|
425
448
|
factory.insertChild(childView, into: container, before: beforeView)
|
|
426
449
|
} else if let index = container.subviews.firstIndex(of: beforeView) {
|
|
427
450
|
container.insertSubview(childView, at: index)
|
|
428
|
-
|
|
429
|
-
container.
|
|
430
|
-
for subview in container.subviews {
|
|
431
|
-
container.flex.addItem(subview)
|
|
432
|
-
}
|
|
451
|
+
container.flex.markDirty()
|
|
452
|
+
container.setNeedsLayout()
|
|
433
453
|
} else {
|
|
434
454
|
container.flex.addItem(childView)
|
|
435
455
|
}
|
|
@@ -599,6 +619,124 @@ public final class NativeBridge {
|
|
|
599
619
|
vc.view.addSubview(traitObserver)
|
|
600
620
|
// Retain the observer for the lifetime of the root view controller's view
|
|
601
621
|
objc_setAssociatedObject(vc.view as UIView, &NativeBridge.traitObserverKey, traitObserver as AnyObject, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
|
|
622
|
+
|
|
623
|
+
// Add modal container to root view for teleport
|
|
624
|
+
if rootView != nil {
|
|
625
|
+
rootView?.addSubview(modalContainer)
|
|
626
|
+
modalContainer.topAnchor.constraint(equalTo: rootView!.topAnchor).isActive = true
|
|
627
|
+
modalContainer.leadingAnchor.constraint(equalTo: rootView!.leadingAnchor).isActive = true
|
|
628
|
+
modalContainer.trailingAnchor.constraint(equalTo: rootView!.trailingAnchor).isActive = true
|
|
629
|
+
modalContainer.bottomAnchor.constraint(equalTo: rootView!.bottomAnchor).isActive = true
|
|
630
|
+
}
|
|
631
|
+
}
|
|
632
|
+
|
|
633
|
+
// MARK: - Teleport Handlers
|
|
634
|
+
|
|
635
|
+
/// createTeleport: [parentId: Int, startId: Int, endId: Int]
|
|
636
|
+
private func handleCreateTeleport(args: [Any]) {
|
|
637
|
+
guard args.count >= 3,
|
|
638
|
+
let parentId = asInt(args[0]),
|
|
639
|
+
let startId = asInt(args[1]),
|
|
640
|
+
let endId = asInt(args[2]) else {
|
|
641
|
+
NSLog("[VueNative Bridge] Error: Invalid createTeleport args: \(args)")
|
|
642
|
+
return
|
|
643
|
+
}
|
|
644
|
+
|
|
645
|
+
guard let parentView = viewRegistry[parentId] else {
|
|
646
|
+
NSLog("[VueNative Bridge] Error: Parent view not found for teleport (id: \(parentId))")
|
|
647
|
+
return
|
|
648
|
+
}
|
|
649
|
+
|
|
650
|
+
// Store teleport marker IDs
|
|
651
|
+
teleportMarkers[parentId] = (start: startId, end: endId)
|
|
652
|
+
|
|
653
|
+
// Create container for teleported content
|
|
654
|
+
let container = UIView()
|
|
655
|
+
container.tag = -parentId // Negative tag to identify as teleport container
|
|
656
|
+
container.backgroundColor = .clear
|
|
657
|
+
container.isUserInteractionEnabled = true
|
|
658
|
+
container.translatesAutoresizingMaskIntoConstraints = false
|
|
659
|
+
|
|
660
|
+
parentView.addSubview(container)
|
|
661
|
+
teleportContainers[parentId] = container
|
|
662
|
+
|
|
663
|
+
#if DEBUG
|
|
664
|
+
NSLog("[VueNative Bridge] Created teleport container for parent \(parentId)")
|
|
665
|
+
#endif
|
|
666
|
+
}
|
|
667
|
+
|
|
668
|
+
/// removeTeleport: [parentId: Int, startId: Int, endId: Int]
|
|
669
|
+
private func handleRemoveTeleport(args: [Any]) {
|
|
670
|
+
guard args.count >= 1,
|
|
671
|
+
let parentId = asInt(args[0]) else {
|
|
672
|
+
NSLog("[VueNative Bridge] Error: Invalid removeTeleport args: \(args)")
|
|
673
|
+
return
|
|
674
|
+
}
|
|
675
|
+
|
|
676
|
+
// Remove teleport container
|
|
677
|
+
if let container = teleportContainers.removeValue(forKey: parentId) {
|
|
678
|
+
container.removeFromSuperview()
|
|
679
|
+
}
|
|
680
|
+
|
|
681
|
+
// Clean up markers
|
|
682
|
+
teleportMarkers.removeValue(forKey: parentId)
|
|
683
|
+
|
|
684
|
+
#if DEBUG
|
|
685
|
+
NSLog("[VueNative Bridge] Removed teleport container for parent \(parentId)")
|
|
686
|
+
#endif
|
|
687
|
+
}
|
|
688
|
+
|
|
689
|
+
/// teleportTo: [target: String, nodeId: Int]
|
|
690
|
+
private func handleTeleportTo(args: [Any]) {
|
|
691
|
+
guard args.count >= 2,
|
|
692
|
+
let target = args[0] as? String,
|
|
693
|
+
let nodeId = asInt(args[1]) else {
|
|
694
|
+
NSLog("[VueNative Bridge] Error: Invalid teleportTo args: \(args)")
|
|
695
|
+
return
|
|
696
|
+
}
|
|
697
|
+
|
|
698
|
+
guard let targetView = getTeleportTarget(target) else {
|
|
699
|
+
NSLog("[VueNative Bridge] Warning: Teleport target '\(target)' not found")
|
|
700
|
+
return
|
|
701
|
+
}
|
|
702
|
+
|
|
703
|
+
guard let childView = viewRegistry[nodeId] else {
|
|
704
|
+
NSLog("[VueNative Bridge] Warning: Node view not found for teleport (id: \(nodeId))")
|
|
705
|
+
return
|
|
706
|
+
}
|
|
707
|
+
|
|
708
|
+
// Move view to teleport target
|
|
709
|
+
childView.removeFromSuperview()
|
|
710
|
+
targetView.addSubview(childView)
|
|
711
|
+
|
|
712
|
+
// Set up full-size constraints
|
|
713
|
+
childView.translatesAutoresizingMaskIntoConstraints = false
|
|
714
|
+
NSLayoutConstraint.activate([
|
|
715
|
+
childView.topAnchor.constraint(equalTo: targetView.topAnchor),
|
|
716
|
+
childView.leadingAnchor.constraint(equalTo: targetView.leadingAnchor),
|
|
717
|
+
childView.trailingAnchor.constraint(equalTo: targetView.trailingAnchor),
|
|
718
|
+
childView.bottomAnchor.constraint(equalTo: targetView.bottomAnchor),
|
|
719
|
+
])
|
|
720
|
+
|
|
721
|
+
#if DEBUG
|
|
722
|
+
NSLog("[VueNative Bridge] Teleported node \(nodeId) to target '\(target)'")
|
|
723
|
+
#endif
|
|
724
|
+
}
|
|
725
|
+
|
|
726
|
+
/// Get teleport target view by name
|
|
727
|
+
private func getTeleportTarget(_ target: String) -> UIView? {
|
|
728
|
+
switch target {
|
|
729
|
+
case "root":
|
|
730
|
+
return rootView
|
|
731
|
+
case "modal":
|
|
732
|
+
// Ensure modal container is added to root if not already
|
|
733
|
+
if modalContainer.superview == nil && rootView != nil {
|
|
734
|
+
rootView?.addSubview(modalContainer)
|
|
735
|
+
}
|
|
736
|
+
return modalContainer
|
|
737
|
+
default:
|
|
738
|
+
return nil
|
|
739
|
+
}
|
|
602
740
|
}
|
|
603
741
|
|
|
604
742
|
// MARK: - Native Module Handlers
|
package/native/ios/VueNativeCore/Sources/VueNativeCore/Components/Factories/VTextFactory.swift
CHANGED
|
@@ -40,6 +40,7 @@ final class VTextFactory: NativeComponentFactory {
|
|
|
40
40
|
private static var fontSizeKey: UInt8 = 0
|
|
41
41
|
private static var fontWeightKey: UInt8 = 0
|
|
42
42
|
private static var fontFamilyKey: UInt8 = 0
|
|
43
|
+
private static var textChildrenKey: UInt8 = 0
|
|
43
44
|
|
|
44
45
|
// MARK: - NativeComponentFactory
|
|
45
46
|
|
|
@@ -57,6 +58,7 @@ final class VTextFactory: NativeComponentFactory {
|
|
|
57
58
|
|
|
58
59
|
switch key {
|
|
59
60
|
case "text":
|
|
61
|
+
storeTextChildren([], on: label)
|
|
60
62
|
if let text = value as? String {
|
|
61
63
|
label.text = text
|
|
62
64
|
} else {
|
|
@@ -235,6 +237,31 @@ final class VTextFactory: NativeComponentFactory {
|
|
|
235
237
|
}
|
|
236
238
|
}
|
|
237
239
|
|
|
240
|
+
func insertChild(_ child: UIView, into parent: UIView, before anchor: UIView?) {
|
|
241
|
+
guard let label = parent as? UILabel else {
|
|
242
|
+
child.removeFromSuperview()
|
|
243
|
+
return
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
var children = storedTextChildren(on: label)
|
|
247
|
+
if let anchor = anchor, let index = children.firstIndex(where: { $0 === anchor }) {
|
|
248
|
+
children.insert(child, at: index)
|
|
249
|
+
} else {
|
|
250
|
+
children.append(child)
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
storeTextChildren(children, on: label)
|
|
254
|
+
rebuildText(from: children, on: label)
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
func removeChild(_ child: UIView, from parent: UIView) {
|
|
258
|
+
guard let label = parent as? UILabel else { return }
|
|
259
|
+
var children = storedTextChildren(on: label)
|
|
260
|
+
children.removeAll { $0 === child }
|
|
261
|
+
storeTextChildren(children, on: label)
|
|
262
|
+
rebuildText(from: children, on: label)
|
|
263
|
+
}
|
|
264
|
+
|
|
238
265
|
// MARK: - Font rebuilding
|
|
239
266
|
|
|
240
267
|
/// Rebuild the UIFont from stored fontSize, fontWeight, and fontFamily.
|
|
@@ -286,5 +313,21 @@ final class VTextFactory: NativeComponentFactory {
|
|
|
286
313
|
private func storedFontFamily(on view: UIView) -> String? {
|
|
287
314
|
return objc_getAssociatedObject(view, &VTextFactory.fontFamilyKey) as? String
|
|
288
315
|
}
|
|
316
|
+
|
|
317
|
+
private func storeTextChildren(_ children: [UIView], on view: UIView) {
|
|
318
|
+
objc_setAssociatedObject(view, &VTextFactory.textChildrenKey, children, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
private func storedTextChildren(on view: UIView) -> [UIView] {
|
|
322
|
+
return objc_getAssociatedObject(view, &VTextFactory.textChildrenKey) as? [UIView] ?? []
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
private func rebuildText(from children: [UIView], on label: UILabel) {
|
|
326
|
+
let text = children.compactMap { child -> String? in
|
|
327
|
+
(child as? UILabel)?.text
|
|
328
|
+
}.joined()
|
|
329
|
+
label.text = text.isEmpty ? nil : text
|
|
330
|
+
label.flex.markDirty()
|
|
331
|
+
}
|
|
289
332
|
}
|
|
290
333
|
#endif
|
package/native/ios/VueNativeCore/Sources/VueNativeCore/Components/Factories/VViewFactory.swift
CHANGED
|
@@ -87,6 +87,51 @@ final class VViewFactory: NativeComponentFactory {
|
|
|
87
87
|
view.isUserInteractionEnabled = true
|
|
88
88
|
GestureStorage.storeObject(pinchWrapper, for: view, event: event)
|
|
89
89
|
|
|
90
|
+
// MARK: Rotation
|
|
91
|
+
case "rotate":
|
|
92
|
+
let rotationWrapper = RotationWrapper(handler: handler)
|
|
93
|
+
let rotation = UIRotationGestureRecognizer(
|
|
94
|
+
target: rotationWrapper,
|
|
95
|
+
action: #selector(RotationWrapper.handle(_:))
|
|
96
|
+
)
|
|
97
|
+
view.addGestureRecognizer(rotation)
|
|
98
|
+
view.isUserInteractionEnabled = true
|
|
99
|
+
GestureStorage.storeObject(rotationWrapper, for: view, event: event)
|
|
100
|
+
|
|
101
|
+
// MARK: Double Tap
|
|
102
|
+
case "doubleTap":
|
|
103
|
+
let wrapper = DoubleTapWrapper(handler: handler)
|
|
104
|
+
let tapRecognizer = UITapGestureRecognizer(
|
|
105
|
+
target: wrapper,
|
|
106
|
+
action: #selector(DoubleTapWrapper.handleGesture(_:))
|
|
107
|
+
)
|
|
108
|
+
tapRecognizer.numberOfTapsRequired = 2
|
|
109
|
+
view.addGestureRecognizer(tapRecognizer)
|
|
110
|
+
view.isUserInteractionEnabled = true
|
|
111
|
+
GestureStorage.storeObject(wrapper, for: view, event: event)
|
|
112
|
+
|
|
113
|
+
// MARK: Force Touch (3D Touch)
|
|
114
|
+
case "forceTouch":
|
|
115
|
+
let wrapper = ForceTouchWrapper(handler: handler)
|
|
116
|
+
// Force touch is handled via touch events, not gesture recognizers
|
|
117
|
+
// We store the wrapper and will handle it in a custom touch handler
|
|
118
|
+
GestureStorage.storeObject(wrapper, for: view, event: event)
|
|
119
|
+
// Enable force touch on the view
|
|
120
|
+
view.isUserInteractionEnabled = true
|
|
121
|
+
attachForceTouchHandler(to: view, wrapper: wrapper)
|
|
122
|
+
|
|
123
|
+
// MARK: Hover (iOS 13+)
|
|
124
|
+
case "hover":
|
|
125
|
+
if #available(iOS 13.0, *) {
|
|
126
|
+
let hoverWrapper = HoverWrapper(handler: handler)
|
|
127
|
+
let hover = UIHoverGestureRecognizer(
|
|
128
|
+
target: hoverWrapper,
|
|
129
|
+
action: #selector(HoverWrapper.handleGesture(_:))
|
|
130
|
+
)
|
|
131
|
+
view.addGestureRecognizer(hover)
|
|
132
|
+
GestureStorage.storeObject(hoverWrapper, for: view, event: event)
|
|
133
|
+
}
|
|
134
|
+
|
|
90
135
|
default:
|
|
91
136
|
break
|
|
92
137
|
}
|
|
@@ -97,24 +142,91 @@ final class VViewFactory: NativeComponentFactory {
|
|
|
97
142
|
// Remove matching gesture recognizers
|
|
98
143
|
view.gestureRecognizers?.forEach { recognizer in
|
|
99
144
|
switch event {
|
|
100
|
-
case "press"
|
|
101
|
-
|
|
145
|
+
case "press":
|
|
146
|
+
if let tap = recognizer as? UITapGestureRecognizer, tap.numberOfTapsRequired == 1 {
|
|
147
|
+
view.removeGestureRecognizer(recognizer)
|
|
148
|
+
}
|
|
102
149
|
case "longpress" where recognizer is UILongPressGestureRecognizer:
|
|
103
150
|
view.removeGestureRecognizer(recognizer)
|
|
104
151
|
case "pan" where recognizer is UIPanGestureRecognizer:
|
|
105
152
|
view.removeGestureRecognizer(recognizer)
|
|
106
|
-
case "swipeLeft"
|
|
107
|
-
|
|
153
|
+
case "swipeLeft" where recognizer is UISwipeGestureRecognizer:
|
|
154
|
+
view.removeGestureRecognizer(recognizer)
|
|
155
|
+
case "swipeRight" where recognizer is UISwipeGestureRecognizer:
|
|
156
|
+
view.removeGestureRecognizer(recognizer)
|
|
157
|
+
case "swipeUp" where recognizer is UISwipeGestureRecognizer:
|
|
158
|
+
view.removeGestureRecognizer(recognizer)
|
|
159
|
+
case "swipeDown" where recognizer is UISwipeGestureRecognizer:
|
|
108
160
|
view.removeGestureRecognizer(recognizer)
|
|
109
161
|
case "pinch" where recognizer is UIPinchGestureRecognizer:
|
|
110
162
|
view.removeGestureRecognizer(recognizer)
|
|
163
|
+
case "rotate" where recognizer is UIRotationGestureRecognizer:
|
|
164
|
+
view.removeGestureRecognizer(recognizer)
|
|
165
|
+
case "doubleTap":
|
|
166
|
+
if let tap = recognizer as? UITapGestureRecognizer, tap.numberOfTapsRequired == 2 {
|
|
167
|
+
view.removeGestureRecognizer(recognizer)
|
|
168
|
+
}
|
|
169
|
+
case "hover":
|
|
170
|
+
if #available(iOS 13.0, *) {
|
|
171
|
+
if recognizer is UIHoverGestureRecognizer {
|
|
172
|
+
view.removeGestureRecognizer(recognizer)
|
|
173
|
+
}
|
|
174
|
+
}
|
|
111
175
|
default:
|
|
112
176
|
break
|
|
113
177
|
}
|
|
114
178
|
}
|
|
115
179
|
}
|
|
180
|
+
|
|
181
|
+
// MARK: - Force Touch Helper
|
|
182
|
+
|
|
183
|
+
private func attachForceTouchHandler(to view: UIView, wrapper: ForceTouchWrapper) {
|
|
184
|
+
// ForceTouchHandler is attached via associated object
|
|
185
|
+
let handler = ForceTouchHandlerView(wrapper: wrapper)
|
|
186
|
+
objc_setAssociatedObject(view, &forceTouchHandlerKey, handler, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
|
|
187
|
+
handler.attach(to: view)
|
|
188
|
+
}
|
|
116
189
|
}
|
|
117
190
|
|
|
191
|
+
// MARK: - ForceTouchHandlerView
|
|
192
|
+
|
|
193
|
+
/// Custom UIView subclass that monitors force touch events
|
|
194
|
+
private class ForceTouchHandlerView: UIView {
|
|
195
|
+
private let wrapper: ForceTouchWrapper
|
|
196
|
+
private weak var targetView: UIView?
|
|
197
|
+
|
|
198
|
+
init(wrapper: ForceTouchWrapper) {
|
|
199
|
+
self.wrapper = wrapper
|
|
200
|
+
super.init(frame: .zero)
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
required init?(coder: NSCoder) {
|
|
204
|
+
fatalError("init(coder:) has not been implemented")
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
func attach(to view: UIView) {
|
|
208
|
+
targetView = view
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
|
|
212
|
+
super.touchesMoved(touches, with: event)
|
|
213
|
+
guard let touch = touches.first else { return }
|
|
214
|
+
let force = touch.force
|
|
215
|
+
let location = touch.location(in: targetView)
|
|
216
|
+
wrapper.handleTouch(force: force, location: location)
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
|
|
220
|
+
super.touchesBegan(touches, with: event)
|
|
221
|
+
guard let touch = touches.first else { return }
|
|
222
|
+
let force = touch.force
|
|
223
|
+
let location = touch.location(in: targetView)
|
|
224
|
+
wrapper.handleTouch(force: force, location: location)
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
private var forceTouchHandlerKey: UInt8 = 0
|
|
229
|
+
|
|
118
230
|
// MARK: - GestureStorage
|
|
119
231
|
|
|
120
232
|
/// Stores gesture wrapper references as associated objects on views to prevent deallocation.
|
|
@@ -104,4 +104,104 @@ import UIKit
|
|
|
104
104
|
] as [String: Any])
|
|
105
105
|
}
|
|
106
106
|
}
|
|
107
|
+
|
|
108
|
+
// MARK: - RotationWrapper
|
|
109
|
+
|
|
110
|
+
/// ObjC-compatible wrapper for UIRotationGestureRecognizer action handlers.
|
|
111
|
+
@objc final class RotationWrapper: NSObject {
|
|
112
|
+
private let handler: (Any?) -> Void
|
|
113
|
+
|
|
114
|
+
init(handler: @escaping (Any?) -> Void) {
|
|
115
|
+
self.handler = handler
|
|
116
|
+
super.init()
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
@objc func handle(_ recognizer: UIRotationGestureRecognizer) {
|
|
120
|
+
let stateStr: String
|
|
121
|
+
switch recognizer.state {
|
|
122
|
+
case .began: stateStr = "began"
|
|
123
|
+
case .changed: stateStr = "changed"
|
|
124
|
+
case .ended: stateStr = "ended"
|
|
125
|
+
default: stateStr = "cancelled"
|
|
126
|
+
}
|
|
127
|
+
handler([
|
|
128
|
+
"rotation": recognizer.rotation,
|
|
129
|
+
"velocity": recognizer.velocity,
|
|
130
|
+
"state": stateStr
|
|
131
|
+
] as [String: Any])
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// MARK: - ForceTouchWrapper
|
|
136
|
+
|
|
137
|
+
/// Wrapper for 3D Touch / Force Touch gesture handlers.
|
|
138
|
+
@objc final class ForceTouchWrapper: NSObject {
|
|
139
|
+
private let handler: (Any?) -> Void
|
|
140
|
+
private var lastForce: CGFloat = 0
|
|
141
|
+
|
|
142
|
+
init(handler: @escaping (Any?) -> Void) {
|
|
143
|
+
self.handler = handler
|
|
144
|
+
super.init()
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
func handleTouch(force: CGFloat, location: CGPoint) {
|
|
148
|
+
let payload: [String: Any] = [
|
|
149
|
+
"force": force,
|
|
150
|
+
"locationX": location.x,
|
|
151
|
+
"locationY": location.y
|
|
152
|
+
]
|
|
153
|
+
handler(payload)
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// MARK: - DoubleTapWrapper
|
|
158
|
+
|
|
159
|
+
/// ObjC-compatible wrapper for double-tap gesture handlers.
|
|
160
|
+
@objc final class DoubleTapWrapper: NSObject {
|
|
161
|
+
private let handler: (Any?) -> Void
|
|
162
|
+
|
|
163
|
+
init(handler: @escaping (Any?) -> Void) {
|
|
164
|
+
self.handler = handler
|
|
165
|
+
super.init()
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
@objc func handleGesture(_ gesture: UITapGestureRecognizer) {
|
|
169
|
+
let location = gesture.location(in: gesture.view)
|
|
170
|
+
let payload: [String: Any] = [
|
|
171
|
+
"locationX": location.x,
|
|
172
|
+
"locationY": location.y
|
|
173
|
+
]
|
|
174
|
+
handler(payload)
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
// MARK: - HoverWrapper
|
|
179
|
+
|
|
180
|
+
/// Wrapper for hover gesture handlers (iOS 13+).
|
|
181
|
+
@objc final class HoverWrapper: NSObject {
|
|
182
|
+
private let handler: (Any?) -> Void
|
|
183
|
+
|
|
184
|
+
init(handler: @escaping (Any?) -> Void) {
|
|
185
|
+
self.handler = handler
|
|
186
|
+
super.init()
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
@objc func handleGesture(_ gesture: UIHoverGestureRecognizer) {
|
|
190
|
+
guard let view = gesture.view else { return }
|
|
191
|
+
let location = gesture.location(in: view)
|
|
192
|
+
let stateStr: String
|
|
193
|
+
switch gesture.state {
|
|
194
|
+
case .began: stateStr = "began"
|
|
195
|
+
case .changed: stateStr = "changed"
|
|
196
|
+
case .ended: stateStr = "ended"
|
|
197
|
+
default: stateStr = "cancelled"
|
|
198
|
+
}
|
|
199
|
+
let payload: [String: Any] = [
|
|
200
|
+
"locationX": location.x,
|
|
201
|
+
"locationY": location.y,
|
|
202
|
+
"state": stateStr
|
|
203
|
+
]
|
|
204
|
+
handler(payload)
|
|
205
|
+
}
|
|
206
|
+
}
|
|
107
207
|
#endif
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
// ────────────────────────────────────────────────────────────────────────────────
|
|
2
|
+
// Auto-Generated Module Registration
|
|
3
|
+
// ────────────────────────────────────────────────────────────────────────────────
|
|
4
|
+
//
|
|
5
|
+
// ⚠️ WARNING: This file is auto-generated. DO NOT EDIT MANUALLY.
|
|
6
|
+
// Changes will be overwritten by the vue-native-codegen tool.
|
|
7
|
+
//
|
|
8
|
+
// Generated: {{GENERATED_DATE}}
|
|
9
|
+
//
|
|
10
|
+
// This file registers all native modules generated from <native> blocks
|
|
11
|
+
// in Vue SFC files.
|
|
12
|
+
//
|
|
13
|
+
// ────────────────────────────────────────────────────────────────────────────────
|
|
14
|
+
|
|
15
|
+
import Foundation
|
|
16
|
+
|
|
17
|
+
@MainActor
|
|
18
|
+
extension NativeModuleRegistry {
|
|
19
|
+
/// Register all generated native modules from <native> blocks
|
|
20
|
+
func registerGeneratedModules() {
|
|
21
|
+
// Generated modules will be registered here
|
|
22
|
+
// Example:
|
|
23
|
+
// register(HapticsModule())
|
|
24
|
+
// register(CameraModule())
|
|
25
|
+
|
|
26
|
+
// This function is called automatically after registerDefaults()
|
|
27
|
+
}
|
|
28
|
+
}
|
|
@@ -55,6 +55,9 @@ final class NativeModuleRegistry {
|
|
|
55
55
|
register(BluetoothModule(bridge: bridge))
|
|
56
56
|
register(CalendarModule())
|
|
57
57
|
register(ContactsModule())
|
|
58
|
+
|
|
59
|
+
// Register generated modules from <native> blocks
|
|
60
|
+
registerGeneratedModules()
|
|
58
61
|
}
|
|
59
62
|
|
|
60
63
|
// MARK: - Invocation
|