@mathers101/react-native-render-rich-text 0.1.9 → 0.1.14
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/LICENSE +20 -20
- package/README.md +140 -140
- package/ReactNativeRenderRichText.podspec +23 -23
- package/android/build.gradle +86 -86
- package/android/consumer-rules.pro +3 -3
- package/android/src/main/AndroidManifest.xml +2 -2
- package/android/src/main/java/com/renderrichtext/EnrichedTiptapTextLayoutManager.kt +24 -24
- package/android/src/main/java/com/renderrichtext/EnrichedTiptapTextPackage.kt +13 -13
- package/android/src/main/java/com/renderrichtext/MeasurementStore.kt +644 -644
- package/android/src/main/java/com/renderrichtext/accessibility/AccessibilityLabels.kt +17 -17
- package/android/src/main/java/com/renderrichtext/accessibility/AccessibleTiptapTextView.kt +112 -112
- package/android/src/main/java/com/renderrichtext/accessibility/TiptapAccessibilityHelper.kt +576 -576
- package/android/src/main/java/com/renderrichtext/events/CodeBlockPressEvent.kt +24 -24
- package/android/src/main/java/com/renderrichtext/events/ContextMenuItemPressEvent.kt +28 -28
- package/android/src/main/java/com/renderrichtext/events/CopyPressEvent.kt +24 -24
- package/android/src/main/java/com/renderrichtext/events/ImagePressEvent.kt +25 -25
- package/android/src/main/java/com/renderrichtext/events/LatexErrorEvent.kt +29 -29
- package/android/src/main/java/com/renderrichtext/events/LinkLongPressEvent.kt +23 -23
- package/android/src/main/java/com/renderrichtext/events/LinkPressEvent.kt +23 -23
- package/android/src/main/java/com/renderrichtext/events/MentionLongPressEvent.kt +25 -25
- package/android/src/main/java/com/renderrichtext/events/MentionPressEvent.kt +25 -25
- package/android/src/main/java/com/renderrichtext/events/TaskListItemPressEvent.kt +26 -26
- package/android/src/main/java/com/renderrichtext/math/LatexErrorReporter.kt +9 -9
- package/android/src/main/java/com/renderrichtext/parser/Parser.kt +59 -59
- package/android/src/main/java/com/renderrichtext/parser/TextLinkMatching.kt +35 -35
- package/android/src/main/java/com/renderrichtext/renderer/BaselineShiftRenderer.kt +45 -45
- package/android/src/main/java/com/renderrichtext/renderer/BlankLineRenderer.kt +39 -39
- package/android/src/main/java/com/renderrichtext/renderer/BlockquoteRenderer.kt +243 -243
- package/android/src/main/java/com/renderrichtext/renderer/BlockquoteTextRenderer.kt +56 -56
- package/android/src/main/java/com/renderrichtext/renderer/CodeBlockRenderer.kt +135 -135
- package/android/src/main/java/com/renderrichtext/renderer/CodeRenderer.kt +37 -37
- package/android/src/main/java/com/renderrichtext/renderer/EmphasisRenderer.kt +28 -28
- package/android/src/main/java/com/renderrichtext/renderer/HeadingRenderer.kt +81 -81
- package/android/src/main/java/com/renderrichtext/renderer/HighlightRenderer.kt +26 -26
- package/android/src/main/java/com/renderrichtext/renderer/LineBreakRenderer.kt +17 -17
- package/android/src/main/java/com/renderrichtext/renderer/LinkRenderer.kt +90 -90
- package/android/src/main/java/com/renderrichtext/renderer/ListContextManager.kt +109 -109
- package/android/src/main/java/com/renderrichtext/renderer/ListItemRenderer.kt +211 -211
- package/android/src/main/java/com/renderrichtext/renderer/ListRenderer.kt +133 -133
- package/android/src/main/java/com/renderrichtext/renderer/MentionRenderer.kt +85 -85
- package/android/src/main/java/com/renderrichtext/renderer/ParagraphRenderer.kt +91 -91
- package/android/src/main/java/com/renderrichtext/renderer/Renderer.kt +148 -148
- package/android/src/main/java/com/renderrichtext/renderer/SoftBreakRenderer.kt +17 -17
- package/android/src/main/java/com/renderrichtext/renderer/SpanStyleCache.kt +143 -143
- package/android/src/main/java/com/renderrichtext/renderer/StrikethroughRenderer.kt +28 -28
- package/android/src/main/java/com/renderrichtext/renderer/StrongRenderer.kt +28 -28
- package/android/src/main/java/com/renderrichtext/renderer/TextRenderer.kt +31 -31
- package/android/src/main/java/com/renderrichtext/renderer/ThematicBreakRenderer.kt +46 -46
- package/android/src/main/java/com/renderrichtext/renderer/UnderlineRenderer.kt +28 -28
- package/android/src/main/java/com/renderrichtext/spans/BaseListSpan.kt +164 -164
- package/android/src/main/java/com/renderrichtext/spans/BaselineShiftSpan.kt +27 -27
- package/android/src/main/java/com/renderrichtext/spans/BlockquoteSpan.kt +302 -302
- package/android/src/main/java/com/renderrichtext/spans/CodeBackgroundSpan.kt +205 -205
- package/android/src/main/java/com/renderrichtext/spans/CodeBlockSpan.kt +216 -216
- package/android/src/main/java/com/renderrichtext/spans/CodeSpan.kt +32 -32
- package/android/src/main/java/com/renderrichtext/spans/EmphasisSpan.kt +42 -42
- package/android/src/main/java/com/renderrichtext/spans/FadeInSpan.kt +29 -29
- package/android/src/main/java/com/renderrichtext/spans/HeadingSpan.kt +38 -38
- package/android/src/main/java/com/renderrichtext/spans/HighlightSpan.kt +80 -80
- package/android/src/main/java/com/renderrichtext/spans/ImageSpan.kt +481 -481
- package/android/src/main/java/com/renderrichtext/spans/InlineBackgroundGeometry.kt +42 -42
- package/android/src/main/java/com/renderrichtext/spans/LineHeightSpan.kt +39 -39
- package/android/src/main/java/com/renderrichtext/spans/LinkPillIconCache.kt +154 -154
- package/android/src/main/java/com/renderrichtext/spans/LinkPillSpan.kt +381 -381
- package/android/src/main/java/com/renderrichtext/spans/LinkSpan.kt +68 -68
- package/android/src/main/java/com/renderrichtext/spans/ListItemSpacingSpan.kt +33 -33
- package/android/src/main/java/com/renderrichtext/spans/ListMarkerAnchorSpan.kt +38 -38
- package/android/src/main/java/com/renderrichtext/spans/MarginBottomSpan.kt +76 -76
- package/android/src/main/java/com/renderrichtext/spans/MentionChipSpan.kt +132 -132
- package/android/src/main/java/com/renderrichtext/spans/MentionSpan.kt +46 -46
- package/android/src/main/java/com/renderrichtext/spans/OrderedListSpan.kt +127 -127
- package/android/src/main/java/com/renderrichtext/spans/SpoilerSpan.kt +33 -33
- package/android/src/main/java/com/renderrichtext/spans/StrikethroughSpan.kt +12 -12
- package/android/src/main/java/com/renderrichtext/spans/StrongSpan.kt +39 -39
- package/android/src/main/java/com/renderrichtext/spans/TaskListSpan.kt +143 -143
- package/android/src/main/java/com/renderrichtext/spans/TextSpan.kt +26 -26
- package/android/src/main/java/com/renderrichtext/spans/ThematicBreakSpan.kt +69 -69
- package/android/src/main/java/com/renderrichtext/spans/UnorderedListSpan.kt +96 -96
- package/android/src/main/java/com/renderrichtext/spoiler/SpoilerStubs.kt +46 -46
- package/android/src/main/java/com/renderrichtext/styles/BaseBlockStyle.kt +11 -11
- package/android/src/main/java/com/renderrichtext/styles/BlockquoteStyle.kt +83 -83
- package/android/src/main/java/com/renderrichtext/styles/CodeBlockStyle.kt +80 -80
- package/android/src/main/java/com/renderrichtext/styles/CodeStyle.kt +26 -26
- package/android/src/main/java/com/renderrichtext/styles/EmphasisStyle.kt +21 -21
- package/android/src/main/java/com/renderrichtext/styles/FactoidStyle.kt +21 -21
- package/android/src/main/java/com/renderrichtext/styles/HeadingStyle.kt +33 -33
- package/android/src/main/java/com/renderrichtext/styles/HighlightStyle.kt +19 -19
- package/android/src/main/java/com/renderrichtext/styles/ImageStyle.kt +29 -29
- package/android/src/main/java/com/renderrichtext/styles/InlineImageStyle.kt +17 -17
- package/android/src/main/java/com/renderrichtext/styles/InlineMathStyle.kt +17 -17
- package/android/src/main/java/com/renderrichtext/styles/LinkPillContent.kt +36 -36
- package/android/src/main/java/com/renderrichtext/styles/LinkPillStyle.kt +44 -44
- package/android/src/main/java/com/renderrichtext/styles/LinkStyle.kt +23 -23
- package/android/src/main/java/com/renderrichtext/styles/LinkVariantEntry.kt +34 -34
- package/android/src/main/java/com/renderrichtext/styles/ListStyle.kt +65 -65
- package/android/src/main/java/com/renderrichtext/styles/MathStyle.kt +29 -29
- package/android/src/main/java/com/renderrichtext/styles/MentionStyle.kt +19 -19
- package/android/src/main/java/com/renderrichtext/styles/ParagraphStyle.kt +33 -33
- package/android/src/main/java/com/renderrichtext/styles/SpoilerStyle.kt +27 -27
- package/android/src/main/java/com/renderrichtext/styles/StrikethroughStyle.kt +17 -17
- package/android/src/main/java/com/renderrichtext/styles/StrongStyle.kt +21 -21
- package/android/src/main/java/com/renderrichtext/styles/StyleConfig.kt +411 -411
- package/android/src/main/java/com/renderrichtext/styles/StyleParser.kt +92 -92
- package/android/src/main/java/com/renderrichtext/styles/SubscriptStyle.kt +16 -16
- package/android/src/main/java/com/renderrichtext/styles/SuperscriptStyle.kt +16 -16
- package/android/src/main/java/com/renderrichtext/styles/TableStyle.kt +75 -75
- package/android/src/main/java/com/renderrichtext/styles/TaskListStyle.kt +29 -29
- package/android/src/main/java/com/renderrichtext/styles/TextAlignment.kt +32 -32
- package/android/src/main/java/com/renderrichtext/styles/ThematicBreakStyle.kt +23 -23
- package/android/src/main/java/com/renderrichtext/styles/UnderlineStyle.kt +17 -17
- package/android/src/main/java/com/renderrichtext/styles/VideoStyle.kt +31 -31
- package/android/src/main/java/com/renderrichtext/utils/common/BorderStyleUtils.kt +86 -86
- package/android/src/main/java/com/renderrichtext/utils/common/BreakStrategyUtils.kt +32 -32
- package/android/src/main/java/com/renderrichtext/utils/common/CodeBlockHighlighter.kt +36 -36
- package/android/src/main/java/com/renderrichtext/utils/common/CodeBlockNode.kt +42 -42
- package/android/src/main/java/com/renderrichtext/utils/common/EllipsizeUtils.kt +27 -27
- package/android/src/main/java/com/renderrichtext/utils/common/EnrichedTiptapAncestorUtils.kt +10 -10
- package/android/src/main/java/com/renderrichtext/utils/common/FeatureFlags.kt +9 -9
- package/android/src/main/java/com/renderrichtext/utils/common/LinkRecognitionProps.kt +31 -31
- package/android/src/main/java/com/renderrichtext/utils/common/LinkRegexConfig.kt +56 -56
- package/android/src/main/java/com/renderrichtext/utils/common/MotionPreferences.kt +18 -18
- package/android/src/main/java/com/renderrichtext/utils/common/ReadableMapExtensions.kt +28 -28
- package/android/src/main/java/com/renderrichtext/utils/common/layout/RTLUtils.kt +6 -6
- package/android/src/main/java/com/renderrichtext/utils/common/serialization/TiptapASTSerializer.kt +368 -368
- package/android/src/main/java/com/renderrichtext/utils/text/ImageCache.kt +88 -88
- package/android/src/main/java/com/renderrichtext/utils/text/ImageDownloader.kt +203 -203
- package/android/src/main/java/com/renderrichtext/utils/text/LocalImageLoader.kt +167 -167
- package/android/src/main/java/com/renderrichtext/utils/text/TailFadeInAnimator.kt +84 -84
- package/android/src/main/java/com/renderrichtext/utils/text/conversion/HTMLGenerator.kt +1105 -1105
- package/android/src/main/java/com/renderrichtext/utils/text/conversion/TiptapExtractor.kt +423 -423
- package/android/src/main/java/com/renderrichtext/utils/text/extensions/ParagraphUtils.kt +9 -9
- package/android/src/main/java/com/renderrichtext/utils/text/extensions/SpannableExtensions.kt +9 -9
- package/android/src/main/java/com/renderrichtext/utils/text/extensions/TextPaintExtensions.kt +76 -76
- package/android/src/main/java/com/renderrichtext/utils/text/interaction/CheckboxTouchHelper.kt +61 -61
- package/android/src/main/java/com/renderrichtext/utils/text/interaction/TaskListTapUtils.kt +286 -286
- package/android/src/main/java/com/renderrichtext/utils/text/span/ApplyLineHeight.kt +39 -39
- package/android/src/main/java/com/renderrichtext/utils/text/span/BlockSpacing.kt +142 -142
- package/android/src/main/java/com/renderrichtext/utils/text/span/SpanFlags.kt +43 -43
- package/android/src/main/java/com/renderrichtext/utils/text/span/WidthAwareSpans.kt +30 -30
- package/android/src/main/java/com/renderrichtext/utils/text/view/CodeBlockPressHost.kt +15 -15
- package/android/src/main/java/com/renderrichtext/utils/text/view/ImagePressHost.kt +19 -19
- package/android/src/main/java/com/renderrichtext/utils/text/view/SelectionActionMode.kt +235 -235
- package/android/src/main/java/com/renderrichtext/utils/text/view/TextSelectionColors.kt +48 -48
- package/android/src/main/java/com/renderrichtext/utils/text/view/TextViewSetup.kt +119 -119
- package/android/src/main/java/com/renderrichtext/views/ContextMenuPopup.kt +217 -217
- package/android/src/main/java/com/renderrichtext/views/CopyGlyph.kt +101 -101
- package/android/src/main/java/com/renderrichtext/views/WrapGlyph.kt +40 -40
- package/android/src/main/jni/CMakeLists.txt +52 -52
- package/android/src/main/jni/react/renderer/components/RichTextSpec/ComponentDescriptors.h +30 -30
- package/android/src/main/jni/react/renderer/components/RichTextSpec/TiptapTextComponentDescriptor.h +29 -29
- package/android/src/main/jni/react/renderer/components/RichTextSpec/TiptapTextMeasurementManager.cpp +45 -45
- package/android/src/main/jni/react/renderer/components/RichTextSpec/TiptapTextMeasurementManager.h +21 -21
- package/android/src/main/jni/react/renderer/components/RichTextSpec/TiptapTextShadowNode.cpp +38 -38
- package/android/src/main/jni/react/renderer/components/RichTextSpec/TiptapTextShadowNode.h +53 -53
- package/android/src/main/jni/react/renderer/components/RichTextSpec/TiptapTextState.cpp +9 -9
- package/android/src/main/jni/react/renderer/components/RichTextSpec/TiptapTextState.h +24 -24
- package/android/src/main/jni/react/renderer/components/RichTextSpec/conversions.h +40 -40
- package/cpp/parser/TiptapParser.hpp +13 -13
- package/cpp/vendor/nlohmann/json.hpp +24765 -24765
- package/ios/EnrichedTiptapText.h +27 -27
- package/ios/attachments/ENRMImageAttachment.h +51 -51
- package/ios/attachments/ENRMImageAttachment.m +398 -398
- package/ios/attachments/ENRMLinkPillAttachment.h +47 -47
- package/ios/attachments/ENRMLinkPillAttachment.m +324 -324
- package/ios/attachments/ENRMLinkPillIconCache.h +28 -28
- package/ios/attachments/ENRMLinkPillIconCache.m +181 -181
- package/ios/attachments/ENRMLinkPillText.h +27 -27
- package/ios/attachments/ENRMLinkPillText.m +118 -118
- package/ios/attachments/ENRMMathInlineAttachment.h +7 -7
- package/ios/attachments/ENRMMathInlineAttachment.m +4 -4
- package/ios/attachments/ThematicBreakAttachment.h +15 -15
- package/ios/attachments/ThematicBreakAttachment.m +33 -33
- package/ios/internals/ENRMViewFreeMeasurement.h +208 -208
- package/ios/internals/EnrichedTiptapTextComponentDescriptor.h +19 -19
- package/ios/internals/EnrichedTiptapTextShadowNode.h +43 -43
- package/ios/internals/EnrichedTiptapTextShadowNode.mm +69 -69
- package/ios/internals/EnrichedTiptapTextState.h +24 -24
- package/ios/internals/MeasurementCache.h +308 -308
- package/ios/internals/ShadowMeasurementUtils.h +145 -145
- package/ios/parser/ENRMTextLinkAttributes.h +7 -7
- package/ios/parser/ENRMTiptapParser.h +33 -33
- package/ios/parser/ENRMTiptapParser.mm +73 -73
- package/ios/parser/TiptapASTNode.m +52 -52
- package/ios/renderer/AttributedRenderer.h +23 -23
- package/ios/renderer/AttributedRenderer.m +229 -229
- package/ios/renderer/BaseRenderer.h +33 -33
- package/ios/renderer/BaseRenderer.m +46 -46
- package/ios/renderer/BaselineShiftTextAttributes.h +10 -10
- package/ios/renderer/BaselineShiftTextAttributes.m +26 -26
- package/ios/renderer/BlankLineRenderer.h +4 -4
- package/ios/renderer/BlankLineRenderer.m +51 -51
- package/ios/renderer/BlockquoteRenderer.h +6 -6
- package/ios/renderer/BlockquoteRenderer.m +258 -258
- package/ios/renderer/CodeBlockRenderer.h +9 -9
- package/ios/renderer/CodeBlockRenderer.m +99 -99
- package/ios/renderer/CodeRenderer.h +9 -9
- package/ios/renderer/CodeRenderer.m +69 -69
- package/ios/renderer/ENRMBlockquoteTextRenderer.h +25 -25
- package/ios/renderer/ENRMBlockquoteTextRenderer.m +48 -48
- package/ios/renderer/EmphasisRenderer.h +5 -5
- package/ios/renderer/EmphasisRenderer.m +99 -99
- package/ios/renderer/HeadingRenderer.h +6 -6
- package/ios/renderer/HeadingRenderer.m +102 -102
- package/ios/renderer/HighlightRenderer.h +7 -7
- package/ios/renderer/HighlightRenderer.m +33 -33
- package/ios/renderer/LinkRenderer.h +6 -6
- package/ios/renderer/LinkRenderer.m +157 -157
- package/ios/renderer/ListItemRenderer.h +24 -24
- package/ios/renderer/ListItemRenderer.m +283 -283
- package/ios/renderer/ListRenderer.h +13 -13
- package/ios/renderer/ListRenderer.m +126 -126
- package/ios/renderer/MentionRenderer.h +9 -9
- package/ios/renderer/MentionRenderer.m +96 -96
- package/ios/renderer/NodeRenderer.h +8 -8
- package/ios/renderer/ParagraphRenderer.h +6 -6
- package/ios/renderer/ParagraphRenderer.m +85 -85
- package/ios/renderer/RenderContext.h +145 -145
- package/ios/renderer/RenderContext.m +402 -402
- package/ios/renderer/RendererFactory.h +12 -12
- package/ios/renderer/StrikethroughRenderer.h +5 -5
- package/ios/renderer/StrikethroughRenderer.m +30 -30
- package/ios/renderer/StrongRenderer.h +5 -5
- package/ios/renderer/StrongRenderer.m +87 -87
- package/ios/renderer/TextRenderer.h +6 -6
- package/ios/renderer/TextRenderer.m +18 -18
- package/ios/renderer/ThematicBreakRenderer.h +4 -4
- package/ios/renderer/ThematicBreakRenderer.m +41 -41
- package/ios/renderer/UnderlineRenderer.h +4 -4
- package/ios/renderer/UnderlineRenderer.m +41 -41
- package/ios/styles/ENRMFontSlot.h +12 -12
- package/ios/styles/ENRMFontSlot.m +24 -24
- package/ios/styles/StyleConfig.h +488 -488
- package/ios/styles/StyleConfig.mm +2820 -2820
- package/ios/utils/AccessibilityInfo.h +35 -35
- package/ios/utils/AccessibilityInfo.m +24 -24
- package/ios/utils/BlockquoteBorder.h +26 -26
- package/ios/utils/BlockquoteBorder.m +294 -294
- package/ios/utils/CodeBackground.h +19 -19
- package/ios/utils/CodeBackground.m +196 -196
- package/ios/utils/CodeBlockBackground.h +17 -17
- package/ios/utils/CodeBlockBackground.m +102 -102
- package/ios/utils/ContextMenuUtils.h +76 -76
- package/ios/utils/ContextMenuUtils.mm +75 -75
- package/ios/utils/ENRMAccessibilityLabels.h +40 -40
- package/ios/utils/ENRMAccessibilityLabels.m +5 -5
- package/ios/utils/ENRMAsyncRenderCoordinator.h +24 -24
- package/ios/utils/ENRMAsyncRenderCoordinator.m +37 -37
- package/ios/utils/ENRMAtomicSize.h +65 -65
- package/ios/utils/ENRMCodeBlockContent.h +37 -37
- package/ios/utils/ENRMCodeBlockContent.mm +89 -89
- package/ios/utils/ENRMFeatureFlags.h +25 -25
- package/ios/utils/ENRMImageDownloader.h +30 -30
- package/ios/utils/ENRMImageDownloader.m +168 -168
- package/ios/utils/ENRMLatexErrorCoordinator.h +27 -27
- package/ios/utils/ENRMLatexErrorCoordinator.mm +75 -75
- package/ios/utils/ENRMLatexErrorReporting.h +13 -13
- package/ios/utils/ENRMLinkContextMenus.h +93 -93
- package/ios/utils/ENRMLinkContextMenus.m +178 -178
- package/ios/utils/ENRMLinkRegexConfig.h +30 -30
- package/ios/utils/ENRMLinkRegexConfig.mm +104 -104
- package/ios/utils/ENRMLinkRegexProps.h +23 -23
- package/ios/utils/ENRMLocalImageLoader.h +35 -35
- package/ios/utils/ENRMLocalImageLoader.m +111 -111
- package/ios/utils/ENRMMenuAction.h +27 -27
- package/ios/utils/ENRMMenuAction.m +33 -33
- package/ios/utils/ENRMSpoilerOverlayManager.h +15 -15
- package/ios/utils/ENRMSpoilerOverlayManager.m +19 -19
- package/ios/utils/ENRMSpoilerTapUtils.h +6 -6
- package/ios/utils/ENRMSpoilerTapUtils.m +11 -11
- package/ios/utils/ENRMTailFadeInAnimator.h +16 -16
- package/ios/utils/ENRMTailFadeInAnimator.m +161 -161
- package/ios/utils/ENRMTextHitTest.h +23 -23
- package/ios/utils/ENRMTextHitTest.m +20 -20
- package/ios/utils/ENRMTextInteractionUtils.h +20 -20
- package/ios/utils/ENRMTextInteractionUtils.m +15 -15
- package/ios/utils/ENRMTextRenderer.h +38 -38
- package/ios/utils/ENRMTextRenderer.m +54 -54
- package/ios/utils/ENRMTextViewSetup.h +132 -132
- package/ios/utils/ENRMUIKit.h +429 -429
- package/ios/utils/EditMenuUtils.h +105 -105
- package/ios/utils/EditMenuUtils.m +143 -143
- package/ios/utils/FontScaleObserver.h +10 -10
- package/ios/utils/FontScaleObserver.m +55 -55
- package/ios/utils/FontUtils.h +31 -31
- package/ios/utils/FontUtils.m +63 -63
- package/ios/utils/HTMLGenerator.h +25 -25
- package/ios/utils/HTMLGenerator.m +1041 -1041
- package/ios/utils/HeightUpdateUtils.h +25 -25
- package/ios/utils/ImageRequestHeaderUtils.h +35 -35
- package/ios/utils/LastElementUtils.h +97 -97
- package/ios/utils/LinkContextMenuUtils.h +55 -55
- package/ios/utils/LinkPillContentUtils.h +46 -46
- package/ios/utils/ListMarkerDrawer.h +15 -15
- package/ios/utils/ListMarkerDrawer.m +239 -239
- package/ios/utils/MentionBackground.h +26 -26
- package/ios/utils/MentionBackground.m +86 -86
- package/ios/utils/ParagraphStyleUtils.h +87 -87
- package/ios/utils/ParagraphStyleUtils.m +484 -484
- package/ios/utils/PasteboardUtils.h +48 -48
- package/ios/utils/PasteboardUtils.m +166 -166
- package/ios/utils/RTFExportUtils.h +24 -24
- package/ios/utils/RTFExportUtils.m +299 -299
- package/ios/utils/SelectionColorUtils.h +14 -14
- package/ios/utils/StylePropsUtils.h +1340 -1340
- package/ios/utils/TaskListTapUtils.h +6 -6
- package/ios/utils/TaskListTapUtils.m +14 -14
- package/ios/utils/TextViewLayoutManager.h +14 -14
- package/ios/utils/TiptapAccessibilityElementBuilder.h +43 -43
- package/ios/utils/TiptapAccessibilityElementBuilder.m +432 -432
- package/ios/utils/TiptapExtractor.h +17 -17
- package/ios/utils/TiptapExtractor.m +367 -367
- package/ios/views/ENRMTiptapTextView.h +25 -25
- package/ios/views/ENRMTiptapTextView.m +247 -247
- package/package.json +65 -70
- package/react-native.config.js +10 -10
- package/src/admonitionDefaults.ts +58 -58
- package/src/darkModeTextStyle.ts +99 -99
- package/src/headingDefaults.ts +21 -21
- package/src/index.tsx +4 -4
- package/src/linkVariantUtils.ts +120 -120
- package/src/normalizeTiptapStyle.ts +397 -397
- package/src/rn-globals.d.ts +1 -1
- package/src/styleUtils.ts +107 -107
- package/src/types/TiptapStyle.ts +532 -532
- package/src/types/TiptapStyleInternal.ts +299 -299
- package/src/types/linkPill.ts +9 -9
- package/src/utils/isDev.ts +4 -4
package/ios/utils/ENRMUIKit.h
CHANGED
|
@@ -1,429 +1,429 @@
|
|
|
1
|
-
#pragma once
|
|
2
|
-
|
|
3
|
-
#include <TargetConditionals.h>
|
|
4
|
-
|
|
5
|
-
// RCTUIKit.h is react-native-macos only. On iOS we import UIKit and define the aliases ourselves.
|
|
6
|
-
#if !TARGET_OS_OSX
|
|
7
|
-
#import <UIKit/UIKit.h>
|
|
8
|
-
#define RCTUIColor UIColor
|
|
9
|
-
#define RCTUIImage UIImage
|
|
10
|
-
#define RCTUIView UIView
|
|
11
|
-
#define RCTUIScrollView UIScrollView
|
|
12
|
-
#define RCTUIGraphicsImageRenderer UIGraphicsImageRenderer
|
|
13
|
-
#define RCTUIGraphicsImageRendererContext UIGraphicsImageRendererContext
|
|
14
|
-
#define RCTUIGraphicsImageRendererFormat UIGraphicsImageRendererFormat
|
|
15
|
-
#define ENRMPlatformTextView UITextView
|
|
16
|
-
#define ENRMTapRecognizer UITapGestureRecognizer
|
|
17
|
-
|
|
18
|
-
// Inline helpers that RCTUIKit.h normally provides on iOS.
|
|
19
|
-
static inline UIBezierPath *UIBezierPathWithRoundedRect(CGRect rect, CGFloat cornerRadius)
|
|
20
|
-
{
|
|
21
|
-
return [UIBezierPath bezierPathWithRoundedRect:rect cornerRadius:cornerRadius];
|
|
22
|
-
}
|
|
23
|
-
static inline void UIBezierPathAppendPath(UIBezierPath *path, UIBezierPath *appendPath)
|
|
24
|
-
{
|
|
25
|
-
[path appendPath:appendPath];
|
|
26
|
-
}
|
|
27
|
-
static inline CGFloat UIFontLineHeight(UIFont *font)
|
|
28
|
-
{
|
|
29
|
-
return font.lineHeight;
|
|
30
|
-
}
|
|
31
|
-
#else
|
|
32
|
-
#import <React/RCTTextUIKit.h>
|
|
33
|
-
#import <React/RCTUIKit.h>
|
|
34
|
-
#import <React/RCTUITextView.h>
|
|
35
|
-
#define ENRMPlatformTextView RCTUITextView
|
|
36
|
-
#define ENRMTapRecognizer NSClickGestureRecognizer
|
|
37
|
-
#endif
|
|
38
|
-
|
|
39
|
-
/// Value for `usesFontLeading` on every NSLayoutManager that draws or
|
|
40
|
-
/// measures tiptap. NSLayoutManager defaults to YES, which adds each font's
|
|
41
|
-
/// built-in leading on top of the paragraph line height. React Native turns it
|
|
42
|
-
/// off for Text layout, and drawing and measuring must agree, or the reported
|
|
43
|
-
/// height and the on-screen layout drift apart. Fonts pulled in by glyph
|
|
44
|
-
/// fallback make this visible: Geeza Pro (Arabic) has nonzero leading, so with
|
|
45
|
-
/// YES every Arabic line measures taller than it renders.
|
|
46
|
-
/// https://github.com/react/react-native/blob/v0.86.2/packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/RCTTextLayoutManager.mm#L237
|
|
47
|
-
static const BOOL ENRMLayoutManagerUsesFontLeading = NO;
|
|
48
|
-
|
|
49
|
-
/// On iOS, explicitly sets opaque=NO — without it the renderer produces an opaque backing,
|
|
50
|
-
/// breaking transparent backgrounds. macOS handles transparency by default.
|
|
51
|
-
static inline RCTUIGraphicsImageRenderer *ImageRendererForSize(CGSize size)
|
|
52
|
-
{
|
|
53
|
-
#if !TARGET_OS_OSX
|
|
54
|
-
RCTUIGraphicsImageRendererFormat *format = [RCTUIGraphicsImageRendererFormat preferredFormat];
|
|
55
|
-
format.opaque = NO;
|
|
56
|
-
return [[RCTUIGraphicsImageRenderer alloc] initWithSize:size format:format];
|
|
57
|
-
#else
|
|
58
|
-
return [[RCTUIGraphicsImageRenderer alloc] initWithSize:size];
|
|
59
|
-
#endif
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
/// NSBezierPath uses NS-prefixed enum values; UIBezierPath uses kCG-prefixed constants.
|
|
63
|
-
static inline void BezierPathSetRoundStyle(UIBezierPath *path)
|
|
64
|
-
{
|
|
65
|
-
#if !TARGET_OS_OSX
|
|
66
|
-
path.lineCapStyle = kCGLineCapRound;
|
|
67
|
-
path.lineJoinStyle = kCGLineJoinRound;
|
|
68
|
-
#else
|
|
69
|
-
path.lineCapStyle = NSLineCapStyleRound;
|
|
70
|
-
path.lineJoinStyle = NSLineJoinStyleRound;
|
|
71
|
-
#endif
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
/// Cross-platform line segment: NSBezierPath uses lineToPoint: instead of addLineToPoint:.
|
|
75
|
-
static inline void BezierPathAddLine(UIBezierPath *path, CGPoint point)
|
|
76
|
-
{
|
|
77
|
-
#if !TARGET_OS_OSX
|
|
78
|
-
[path addLineToPoint:point];
|
|
79
|
-
#else
|
|
80
|
-
[path lineToPoint:point];
|
|
81
|
-
#endif
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
/// Cross-platform quad-curve: NSBezierPath lacks addQuadCurveToPoint:, so we approximate
|
|
85
|
-
/// with a cubic Bezier using the standard quadratic-to-cubic conversion.
|
|
86
|
-
static inline void BezierPathAddQuadCurve(UIBezierPath *path, CGPoint end, CGPoint control)
|
|
87
|
-
{
|
|
88
|
-
#if !TARGET_OS_OSX
|
|
89
|
-
[path addQuadCurveToPoint:end controlPoint:control];
|
|
90
|
-
#else
|
|
91
|
-
CGPoint start = [path currentPoint];
|
|
92
|
-
[path curveToPoint:end
|
|
93
|
-
controlPoint1:CGPointMake(start.x + 2.0 / 3.0 * (control.x - start.x),
|
|
94
|
-
start.y + 2.0 / 3.0 * (control.y - start.y))
|
|
95
|
-
controlPoint2:CGPointMake(end.x + 2.0 / 3.0 * (control.x - end.x), end.y + 2.0 / 3.0 * (control.y - end.y))];
|
|
96
|
-
#endif
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
/// Cross-platform IME composition check: UITextView uses markedTextRange (nullable UITextRange);
|
|
100
|
-
/// NSTextView uses hasMarkedText (BOOL).
|
|
101
|
-
static inline BOOL ENRMHasMarkedText(ENRMPlatformTextView *textView)
|
|
102
|
-
{
|
|
103
|
-
#if !TARGET_OS_OSX
|
|
104
|
-
return textView.markedTextRange != nil;
|
|
105
|
-
#else
|
|
106
|
-
return textView.hasMarkedText;
|
|
107
|
-
#endif
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
/// Cross-platform plain text read: UITextView uses .text; NSTextView uses .string.
|
|
111
|
-
static inline NSString *ENRMGetPlainText(ENRMPlatformTextView *textView)
|
|
112
|
-
{
|
|
113
|
-
#if !TARGET_OS_OSX
|
|
114
|
-
return textView.text;
|
|
115
|
-
#else
|
|
116
|
-
return textView.string;
|
|
117
|
-
#endif
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
/// Cross-platform plain text write: UITextView uses .text setter; NSTextView uses setString:.
|
|
121
|
-
static inline void ENRMSetPlainText(ENRMPlatformTextView *textView, NSString *text)
|
|
122
|
-
{
|
|
123
|
-
#if !TARGET_OS_OSX
|
|
124
|
-
textView.text = text;
|
|
125
|
-
#else
|
|
126
|
-
[textView setString:text];
|
|
127
|
-
#endif
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
/// Cross-platform attributed text read: NSTextView exposes content via textStorage;
|
|
131
|
-
/// UITextView exposes it via attributedText.
|
|
132
|
-
static inline NSAttributedString *ENRMGetAttributedText(ENRMPlatformTextView *textView)
|
|
133
|
-
{
|
|
134
|
-
#if !TARGET_OS_OSX
|
|
135
|
-
return textView.attributedText;
|
|
136
|
-
#else
|
|
137
|
-
return textView.textStorage;
|
|
138
|
-
#endif
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
/// Cross-platform attributed text write: NSTextView uses textStorage setAttributedString:;
|
|
142
|
-
/// UITextView uses the attributedText property setter.
|
|
143
|
-
static inline void ENRMSetAttributedText(ENRMPlatformTextView *textView, NSAttributedString *text)
|
|
144
|
-
{
|
|
145
|
-
#if !TARGET_OS_OSX
|
|
146
|
-
textView.attributedText = text;
|
|
147
|
-
#else
|
|
148
|
-
[textView.textStorage setAttributedString:text];
|
|
149
|
-
#endif
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
/// Cross-platform text replacement at a given range.
|
|
153
|
-
/// iOS uses UITextInput protocol methods; macOS uses NSTextView's insertText:replacementRange:.
|
|
154
|
-
static inline void ENRMReplaceTextInRange(ENRMPlatformTextView *textView, NSString *text, NSRange range)
|
|
155
|
-
{
|
|
156
|
-
#if !TARGET_OS_OSX
|
|
157
|
-
UITextPosition *start = [textView positionFromPosition:textView.beginningOfDocument offset:(NSInteger)range.location];
|
|
158
|
-
UITextPosition *end = [textView positionFromPosition:textView.beginningOfDocument
|
|
159
|
-
offset:(NSInteger)NSMaxRange(range)];
|
|
160
|
-
[textView replaceRange:[textView textRangeFromPosition:start toPosition:end] withText:text];
|
|
161
|
-
#else
|
|
162
|
-
[textView insertText:text replacementRange:range];
|
|
163
|
-
#endif
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
/// Cross-platform content size update after measurement.
|
|
167
|
-
/// iOS UITextView has a settable contentSize; macOS NSTextView does not.
|
|
168
|
-
static inline void ENRMSetContentSize(ENRMPlatformTextView *textView, CGSize size)
|
|
169
|
-
{
|
|
170
|
-
#if !TARGET_OS_OSX
|
|
171
|
-
textView.contentSize = size;
|
|
172
|
-
#endif
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
/// Returns YES when the user has asked the system to minimise motion.
|
|
176
|
-
/// iOS: UIAccessibilityIsReduceMotionEnabled.
|
|
177
|
-
/// macOS: NSWorkspace.shared.accessibilityDisplayShouldReduceMotion.
|
|
178
|
-
/// Always NO on platforms where the API is unavailable.
|
|
179
|
-
static inline BOOL ENRMShouldReduceMotion(void)
|
|
180
|
-
{
|
|
181
|
-
#if !TARGET_OS_OSX
|
|
182
|
-
return UIAccessibilityIsReduceMotionEnabled();
|
|
183
|
-
#else
|
|
184
|
-
if (@available(macOS 10.12, *)) {
|
|
185
|
-
return NSWorkspace.sharedWorkspace.accessibilityDisplayShouldReduceMotion;
|
|
186
|
-
}
|
|
187
|
-
return NO;
|
|
188
|
-
#endif
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
/// Sets default typing attributes on the text view.
|
|
192
|
-
/// On macOS, RCTUITextView overrides setTypingAttributes: to use defaultTextAttributes,
|
|
193
|
-
/// so we must set that property as well.
|
|
194
|
-
static inline void ENRMSetDefaultTypingAttributes(ENRMPlatformTextView *textView, NSDictionary *attrs)
|
|
195
|
-
{
|
|
196
|
-
#if TARGET_OS_OSX
|
|
197
|
-
textView.defaultTextAttributes = attrs;
|
|
198
|
-
#endif
|
|
199
|
-
textView.typingAttributes = attrs;
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
/// Applies shared configuration to a text view used for tiptap input editing.
|
|
203
|
-
/// Handles platform differences: scroll indicators, text container insets,
|
|
204
|
-
/// drawsBackground (macOS). Sets editable=YES, scrollEnabled=YES.
|
|
205
|
-
static inline void ENRMConfigureTiptapTextInputTextView(ENRMPlatformTextView *textView)
|
|
206
|
-
{
|
|
207
|
-
textView.font = [UIFont systemFontOfSize:16.0];
|
|
208
|
-
textView.backgroundColor = [RCTUIColor clearColor];
|
|
209
|
-
textView.editable = YES;
|
|
210
|
-
#if !TARGET_OS_OSX
|
|
211
|
-
textView.scrollEnabled = YES;
|
|
212
|
-
textView.showsVerticalScrollIndicator = NO;
|
|
213
|
-
textView.showsHorizontalScrollIndicator = NO;
|
|
214
|
-
textView.textContainerInset = UIEdgeInsetsZero;
|
|
215
|
-
#else
|
|
216
|
-
textView.textContainerInsets = UIEdgeInsetsZero;
|
|
217
|
-
textView.drawsBackground = NO;
|
|
218
|
-
#endif
|
|
219
|
-
textView.textContainer.lineFragmentPadding = 0;
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
/// Cross-platform cursor color: iOS uses tintColor; macOS uses insertionPointColor.
|
|
223
|
-
static inline void ENRMSetCursorColor(ENRMPlatformTextView *textView, RCTUIColor *color)
|
|
224
|
-
{
|
|
225
|
-
#if !TARGET_OS_OSX
|
|
226
|
-
textView.tintColor = color;
|
|
227
|
-
#else
|
|
228
|
-
textView.insertionPointColor = color;
|
|
229
|
-
#endif
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
/// Cross-platform selection color: iOS uses tintColor (also affects the caret
|
|
233
|
-
/// and selection handles); macOS sets the selection background via
|
|
234
|
-
/// `selectedTextAttributes`. Pass `nil` to restore the system default.
|
|
235
|
-
static inline void ENRMSetSelectionColor(ENRMPlatformTextView *textView, RCTUIColor *color)
|
|
236
|
-
{
|
|
237
|
-
#if !TARGET_OS_OSX
|
|
238
|
-
textView.tintColor = color;
|
|
239
|
-
#else
|
|
240
|
-
RCTUIColor *resolved = color ?: [NSColor selectedTextBackgroundColor];
|
|
241
|
-
textView.selectedTextAttributes = @{NSBackgroundColorAttributeName : resolved};
|
|
242
|
-
#endif
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
/// Cross-platform focus: iOS uses becomeFirstResponder;
|
|
246
|
-
/// macOS uses makeFirstResponder: on the window.
|
|
247
|
-
static inline void ENRMFocusTextView(ENRMPlatformTextView *textView)
|
|
248
|
-
{
|
|
249
|
-
#if !TARGET_OS_OSX
|
|
250
|
-
[textView becomeFirstResponder];
|
|
251
|
-
#else
|
|
252
|
-
[textView.window makeFirstResponder:textView];
|
|
253
|
-
#endif
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
/// Cross-platform blur: iOS uses resignFirstResponder;
|
|
257
|
-
/// macOS clears first responder via the window.
|
|
258
|
-
static inline void ENRMBlurTextView(ENRMPlatformTextView *textView)
|
|
259
|
-
{
|
|
260
|
-
#if !TARGET_OS_OSX
|
|
261
|
-
[textView resignFirstResponder];
|
|
262
|
-
#else
|
|
263
|
-
[textView.window makeFirstResponder:nil];
|
|
264
|
-
#endif
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
/// Applies shared configuration to a text view used for tiptap rendering.
|
|
268
|
-
/// Handles platform differences: scroll indicators, text container insets,
|
|
269
|
-
/// drawsBackground (macOS), accessibilityElementsHidden (iOS).
|
|
270
|
-
static inline void ENRMConfigureTiptapTextView(ENRMPlatformTextView *textView)
|
|
271
|
-
{
|
|
272
|
-
textView.font = [UIFont systemFontOfSize:16.0];
|
|
273
|
-
textView.backgroundColor = [RCTUIColor clearColor];
|
|
274
|
-
textView.textColor = [RCTUIColor blackColor];
|
|
275
|
-
textView.editable = NO;
|
|
276
|
-
textView.scrollEnabled = NO;
|
|
277
|
-
#if !TARGET_OS_OSX
|
|
278
|
-
textView.showsVerticalScrollIndicator = NO;
|
|
279
|
-
textView.showsHorizontalScrollIndicator = NO;
|
|
280
|
-
textView.textContainerInset = UIEdgeInsetsZero;
|
|
281
|
-
#else
|
|
282
|
-
textView.textContainerInsets = UIEdgeInsetsZero;
|
|
283
|
-
textView.drawsBackground = NO;
|
|
284
|
-
#endif
|
|
285
|
-
textView.textContainer.lineFragmentPadding = 0;
|
|
286
|
-
textView.layoutManager.usesFontLeading = ENRMLayoutManagerUsesFontLeading;
|
|
287
|
-
textView.linkTextAttributes = @{};
|
|
288
|
-
textView.selectable = YES;
|
|
289
|
-
#if !TARGET_OS_OSX
|
|
290
|
-
textView.accessibilityElementsHidden = YES;
|
|
291
|
-
#endif
|
|
292
|
-
}
|
|
293
|
-
|
|
294
|
-
/// Result of a text layout measurement pass.
|
|
295
|
-
typedef struct {
|
|
296
|
-
CGRect usedRect;
|
|
297
|
-
CGRect extraLineFragmentRect;
|
|
298
|
-
} ENRMTextLayoutResult;
|
|
299
|
-
|
|
300
|
-
/// Measures text layout in a text view for a given width.
|
|
301
|
-
/// On macOS, temporarily disables widthTracksTextView so the container width
|
|
302
|
-
/// can be set directly without being overridden by the view's frame.
|
|
303
|
-
static inline ENRMTextLayoutResult ENRMMeasureTextLayout(ENRMPlatformTextView *textView, CGFloat maxWidth)
|
|
304
|
-
{
|
|
305
|
-
#if TARGET_OS_OSX
|
|
306
|
-
textView.textContainer.widthTracksTextView = NO;
|
|
307
|
-
#endif
|
|
308
|
-
textView.textContainer.size = CGSizeMake(maxWidth, CGFLOAT_MAX);
|
|
309
|
-
[textView.layoutManager ensureLayoutForTextContainer:textView.textContainer];
|
|
310
|
-
ENRMTextLayoutResult result;
|
|
311
|
-
result.usedRect = [textView.layoutManager usedRectForTextContainer:textView.textContainer];
|
|
312
|
-
result.extraLineFragmentRect = textView.layoutManager.extraLineFragmentRect;
|
|
313
|
-
#if TARGET_OS_OSX
|
|
314
|
-
textView.textContainer.widthTracksTextView = YES;
|
|
315
|
-
#endif
|
|
316
|
-
return result;
|
|
317
|
-
}
|
|
318
|
-
|
|
319
|
-
/// Cross-platform display refresh: UIView requires layoutIfNeeded before setNeedsDisplay
|
|
320
|
-
/// to flush pending layout before the redraw; NSView takes a BOOL argument.
|
|
321
|
-
/// Implemented as a macro to avoid Objective-C++ implicit pointer conversion issues in .mm files.
|
|
322
|
-
#if !TARGET_OS_OSX
|
|
323
|
-
#define ENRMSetNeedsDisplay(view) \
|
|
324
|
-
do { \
|
|
325
|
-
[(view) layoutIfNeeded]; \
|
|
326
|
-
[(view) setNeedsDisplay]; \
|
|
327
|
-
} while (0)
|
|
328
|
-
#else
|
|
329
|
-
#define ENRMSetNeedsDisplay(view) [(view) setNeedsDisplay:YES]
|
|
330
|
-
#endif
|
|
331
|
-
|
|
332
|
-
/// Invalidates the text container, re-lays out any existing content, and
|
|
333
|
-
/// triggers a redraw. On iOS also resets contentOffset to zero.
|
|
334
|
-
/// Does NOT touch the text view's frame — callers that need to reposition
|
|
335
|
-
/// the view should set the frame themselves before calling this.
|
|
336
|
-
static inline void ENRMRefreshTextViewLayout(ENRMPlatformTextView *textView)
|
|
337
|
-
{
|
|
338
|
-
#if !TARGET_OS_OSX
|
|
339
|
-
textView.contentOffset = CGPointZero;
|
|
340
|
-
#endif
|
|
341
|
-
textView.textContainer.size = CGSizeMake(textView.bounds.size.width, CGFLOAT_MAX);
|
|
342
|
-
NSUInteger textLength = ENRMGetAttributedText(textView).length;
|
|
343
|
-
if (textLength > 0) {
|
|
344
|
-
[textView.layoutManager invalidateLayoutForCharacterRange:NSMakeRange(0, textLength) actualCharacterRange:NULL];
|
|
345
|
-
[textView.layoutManager ensureLayoutForTextContainer:textView.textContainer];
|
|
346
|
-
}
|
|
347
|
-
ENRMSetNeedsDisplay(textView);
|
|
348
|
-
}
|
|
349
|
-
|
|
350
|
-
/// Refreshes a text view's layout and display after it is attached to a window.
|
|
351
|
-
/// Sets the frame and text container to the given bounds, invalidates layout for
|
|
352
|
-
/// any existing content, then triggers a redraw.
|
|
353
|
-
static inline void ENRMRefreshTextViewAfterWindowAttach(ENRMPlatformTextView *textView, CGRect bounds)
|
|
354
|
-
{
|
|
355
|
-
textView.frame = bounds;
|
|
356
|
-
ENRMRefreshTextViewLayout(textView);
|
|
357
|
-
}
|
|
358
|
-
|
|
359
|
-
/// Cross-platform text deselection: UITextView uses selectedTextRange (nullable);
|
|
360
|
-
/// NSTextView uses selectedRange (length-based).
|
|
361
|
-
static inline void ENRMClearSelection(ENRMPlatformTextView *textView)
|
|
362
|
-
{
|
|
363
|
-
#if !TARGET_OS_OSX
|
|
364
|
-
if (textView.selectedTextRange != nil) {
|
|
365
|
-
textView.selectedTextRange = nil;
|
|
366
|
-
}
|
|
367
|
-
#else
|
|
368
|
-
if (textView.selectedRange.length > 0) {
|
|
369
|
-
textView.selectedRange = NSMakeRange(0, 0);
|
|
370
|
-
}
|
|
371
|
-
#endif
|
|
372
|
-
}
|
|
373
|
-
|
|
374
|
-
// ── Placeholder label abstraction ──────────────────────────────────────────────
|
|
375
|
-
|
|
376
|
-
#if !TARGET_OS_OSX
|
|
377
|
-
typedef UILabel ENRMPlaceholderLabel;
|
|
378
|
-
#else
|
|
379
|
-
typedef NSTextField ENRMPlaceholderLabel;
|
|
380
|
-
#endif
|
|
381
|
-
|
|
382
|
-
/// Creates a placeholder label configured for use inside an ENRMPlatformTextView.
|
|
383
|
-
/// On iOS: UILabel with multiline, placeholderTextColor, auto-layout pinned to
|
|
384
|
-
/// textContainerInset and lineFragmentPadding.
|
|
385
|
-
/// On macOS: borderless, non-editable NSTextField pinned to the text view origin.
|
|
386
|
-
static inline ENRMPlaceholderLabel *ENRMCreatePlaceholderLabel(ENRMPlatformTextView *textView, UIFont *font)
|
|
387
|
-
{
|
|
388
|
-
#if !TARGET_OS_OSX
|
|
389
|
-
UILabel *label = [[UILabel alloc] init];
|
|
390
|
-
label.numberOfLines = 0;
|
|
391
|
-
label.textColor = [UIColor placeholderTextColor];
|
|
392
|
-
label.font = font;
|
|
393
|
-
label.translatesAutoresizingMaskIntoConstraints = NO;
|
|
394
|
-
[textView addSubview:label];
|
|
395
|
-
[NSLayoutConstraint activateConstraints:@[
|
|
396
|
-
[label.topAnchor constraintEqualToAnchor:textView.topAnchor constant:textView.textContainerInset.top],
|
|
397
|
-
[label.leadingAnchor constraintEqualToAnchor:textView.leadingAnchor
|
|
398
|
-
constant:textView.textContainer.lineFragmentPadding],
|
|
399
|
-
[label.trailingAnchor constraintEqualToAnchor:textView.trailingAnchor
|
|
400
|
-
constant:-textView.textContainer.lineFragmentPadding],
|
|
401
|
-
]];
|
|
402
|
-
return label;
|
|
403
|
-
#else
|
|
404
|
-
NSTextField *label = [[NSTextField alloc] initWithFrame:CGRectZero];
|
|
405
|
-
label.bordered = NO;
|
|
406
|
-
label.editable = NO;
|
|
407
|
-
label.selectable = NO;
|
|
408
|
-
label.drawsBackground = NO;
|
|
409
|
-
label.textColor = [NSColor placeholderTextColor];
|
|
410
|
-
label.font = font;
|
|
411
|
-
label.translatesAutoresizingMaskIntoConstraints = NO;
|
|
412
|
-
[textView addSubview:label];
|
|
413
|
-
[NSLayoutConstraint activateConstraints:@[
|
|
414
|
-
[label.topAnchor constraintEqualToAnchor:textView.topAnchor],
|
|
415
|
-
[label.leadingAnchor constraintEqualToAnchor:textView.leadingAnchor],
|
|
416
|
-
]];
|
|
417
|
-
return label;
|
|
418
|
-
#endif
|
|
419
|
-
}
|
|
420
|
-
|
|
421
|
-
/// Cross-platform placeholder attributed text setter.
|
|
422
|
-
static inline void ENRMSetPlaceholderAttributedText(ENRMPlaceholderLabel *label, NSAttributedString *text)
|
|
423
|
-
{
|
|
424
|
-
#if !TARGET_OS_OSX
|
|
425
|
-
label.attributedText = text;
|
|
426
|
-
#else
|
|
427
|
-
label.attributedStringValue = text;
|
|
428
|
-
#endif
|
|
429
|
-
}
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#include <TargetConditionals.h>
|
|
4
|
+
|
|
5
|
+
// RCTUIKit.h is react-native-macos only. On iOS we import UIKit and define the aliases ourselves.
|
|
6
|
+
#if !TARGET_OS_OSX
|
|
7
|
+
#import <UIKit/UIKit.h>
|
|
8
|
+
#define RCTUIColor UIColor
|
|
9
|
+
#define RCTUIImage UIImage
|
|
10
|
+
#define RCTUIView UIView
|
|
11
|
+
#define RCTUIScrollView UIScrollView
|
|
12
|
+
#define RCTUIGraphicsImageRenderer UIGraphicsImageRenderer
|
|
13
|
+
#define RCTUIGraphicsImageRendererContext UIGraphicsImageRendererContext
|
|
14
|
+
#define RCTUIGraphicsImageRendererFormat UIGraphicsImageRendererFormat
|
|
15
|
+
#define ENRMPlatformTextView UITextView
|
|
16
|
+
#define ENRMTapRecognizer UITapGestureRecognizer
|
|
17
|
+
|
|
18
|
+
// Inline helpers that RCTUIKit.h normally provides on iOS.
|
|
19
|
+
static inline UIBezierPath *UIBezierPathWithRoundedRect(CGRect rect, CGFloat cornerRadius)
|
|
20
|
+
{
|
|
21
|
+
return [UIBezierPath bezierPathWithRoundedRect:rect cornerRadius:cornerRadius];
|
|
22
|
+
}
|
|
23
|
+
static inline void UIBezierPathAppendPath(UIBezierPath *path, UIBezierPath *appendPath)
|
|
24
|
+
{
|
|
25
|
+
[path appendPath:appendPath];
|
|
26
|
+
}
|
|
27
|
+
static inline CGFloat UIFontLineHeight(UIFont *font)
|
|
28
|
+
{
|
|
29
|
+
return font.lineHeight;
|
|
30
|
+
}
|
|
31
|
+
#else
|
|
32
|
+
#import <React/RCTTextUIKit.h>
|
|
33
|
+
#import <React/RCTUIKit.h>
|
|
34
|
+
#import <React/RCTUITextView.h>
|
|
35
|
+
#define ENRMPlatformTextView RCTUITextView
|
|
36
|
+
#define ENRMTapRecognizer NSClickGestureRecognizer
|
|
37
|
+
#endif
|
|
38
|
+
|
|
39
|
+
/// Value for `usesFontLeading` on every NSLayoutManager that draws or
|
|
40
|
+
/// measures tiptap. NSLayoutManager defaults to YES, which adds each font's
|
|
41
|
+
/// built-in leading on top of the paragraph line height. React Native turns it
|
|
42
|
+
/// off for Text layout, and drawing and measuring must agree, or the reported
|
|
43
|
+
/// height and the on-screen layout drift apart. Fonts pulled in by glyph
|
|
44
|
+
/// fallback make this visible: Geeza Pro (Arabic) has nonzero leading, so with
|
|
45
|
+
/// YES every Arabic line measures taller than it renders.
|
|
46
|
+
/// https://github.com/react/react-native/blob/v0.86.2/packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/RCTTextLayoutManager.mm#L237
|
|
47
|
+
static const BOOL ENRMLayoutManagerUsesFontLeading = NO;
|
|
48
|
+
|
|
49
|
+
/// On iOS, explicitly sets opaque=NO — without it the renderer produces an opaque backing,
|
|
50
|
+
/// breaking transparent backgrounds. macOS handles transparency by default.
|
|
51
|
+
static inline RCTUIGraphicsImageRenderer *ImageRendererForSize(CGSize size)
|
|
52
|
+
{
|
|
53
|
+
#if !TARGET_OS_OSX
|
|
54
|
+
RCTUIGraphicsImageRendererFormat *format = [RCTUIGraphicsImageRendererFormat preferredFormat];
|
|
55
|
+
format.opaque = NO;
|
|
56
|
+
return [[RCTUIGraphicsImageRenderer alloc] initWithSize:size format:format];
|
|
57
|
+
#else
|
|
58
|
+
return [[RCTUIGraphicsImageRenderer alloc] initWithSize:size];
|
|
59
|
+
#endif
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/// NSBezierPath uses NS-prefixed enum values; UIBezierPath uses kCG-prefixed constants.
|
|
63
|
+
static inline void BezierPathSetRoundStyle(UIBezierPath *path)
|
|
64
|
+
{
|
|
65
|
+
#if !TARGET_OS_OSX
|
|
66
|
+
path.lineCapStyle = kCGLineCapRound;
|
|
67
|
+
path.lineJoinStyle = kCGLineJoinRound;
|
|
68
|
+
#else
|
|
69
|
+
path.lineCapStyle = NSLineCapStyleRound;
|
|
70
|
+
path.lineJoinStyle = NSLineJoinStyleRound;
|
|
71
|
+
#endif
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/// Cross-platform line segment: NSBezierPath uses lineToPoint: instead of addLineToPoint:.
|
|
75
|
+
static inline void BezierPathAddLine(UIBezierPath *path, CGPoint point)
|
|
76
|
+
{
|
|
77
|
+
#if !TARGET_OS_OSX
|
|
78
|
+
[path addLineToPoint:point];
|
|
79
|
+
#else
|
|
80
|
+
[path lineToPoint:point];
|
|
81
|
+
#endif
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/// Cross-platform quad-curve: NSBezierPath lacks addQuadCurveToPoint:, so we approximate
|
|
85
|
+
/// with a cubic Bezier using the standard quadratic-to-cubic conversion.
|
|
86
|
+
static inline void BezierPathAddQuadCurve(UIBezierPath *path, CGPoint end, CGPoint control)
|
|
87
|
+
{
|
|
88
|
+
#if !TARGET_OS_OSX
|
|
89
|
+
[path addQuadCurveToPoint:end controlPoint:control];
|
|
90
|
+
#else
|
|
91
|
+
CGPoint start = [path currentPoint];
|
|
92
|
+
[path curveToPoint:end
|
|
93
|
+
controlPoint1:CGPointMake(start.x + 2.0 / 3.0 * (control.x - start.x),
|
|
94
|
+
start.y + 2.0 / 3.0 * (control.y - start.y))
|
|
95
|
+
controlPoint2:CGPointMake(end.x + 2.0 / 3.0 * (control.x - end.x), end.y + 2.0 / 3.0 * (control.y - end.y))];
|
|
96
|
+
#endif
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/// Cross-platform IME composition check: UITextView uses markedTextRange (nullable UITextRange);
|
|
100
|
+
/// NSTextView uses hasMarkedText (BOOL).
|
|
101
|
+
static inline BOOL ENRMHasMarkedText(ENRMPlatformTextView *textView)
|
|
102
|
+
{
|
|
103
|
+
#if !TARGET_OS_OSX
|
|
104
|
+
return textView.markedTextRange != nil;
|
|
105
|
+
#else
|
|
106
|
+
return textView.hasMarkedText;
|
|
107
|
+
#endif
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/// Cross-platform plain text read: UITextView uses .text; NSTextView uses .string.
|
|
111
|
+
static inline NSString *ENRMGetPlainText(ENRMPlatformTextView *textView)
|
|
112
|
+
{
|
|
113
|
+
#if !TARGET_OS_OSX
|
|
114
|
+
return textView.text;
|
|
115
|
+
#else
|
|
116
|
+
return textView.string;
|
|
117
|
+
#endif
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/// Cross-platform plain text write: UITextView uses .text setter; NSTextView uses setString:.
|
|
121
|
+
static inline void ENRMSetPlainText(ENRMPlatformTextView *textView, NSString *text)
|
|
122
|
+
{
|
|
123
|
+
#if !TARGET_OS_OSX
|
|
124
|
+
textView.text = text;
|
|
125
|
+
#else
|
|
126
|
+
[textView setString:text];
|
|
127
|
+
#endif
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/// Cross-platform attributed text read: NSTextView exposes content via textStorage;
|
|
131
|
+
/// UITextView exposes it via attributedText.
|
|
132
|
+
static inline NSAttributedString *ENRMGetAttributedText(ENRMPlatformTextView *textView)
|
|
133
|
+
{
|
|
134
|
+
#if !TARGET_OS_OSX
|
|
135
|
+
return textView.attributedText;
|
|
136
|
+
#else
|
|
137
|
+
return textView.textStorage;
|
|
138
|
+
#endif
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/// Cross-platform attributed text write: NSTextView uses textStorage setAttributedString:;
|
|
142
|
+
/// UITextView uses the attributedText property setter.
|
|
143
|
+
static inline void ENRMSetAttributedText(ENRMPlatformTextView *textView, NSAttributedString *text)
|
|
144
|
+
{
|
|
145
|
+
#if !TARGET_OS_OSX
|
|
146
|
+
textView.attributedText = text;
|
|
147
|
+
#else
|
|
148
|
+
[textView.textStorage setAttributedString:text];
|
|
149
|
+
#endif
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/// Cross-platform text replacement at a given range.
|
|
153
|
+
/// iOS uses UITextInput protocol methods; macOS uses NSTextView's insertText:replacementRange:.
|
|
154
|
+
static inline void ENRMReplaceTextInRange(ENRMPlatformTextView *textView, NSString *text, NSRange range)
|
|
155
|
+
{
|
|
156
|
+
#if !TARGET_OS_OSX
|
|
157
|
+
UITextPosition *start = [textView positionFromPosition:textView.beginningOfDocument offset:(NSInteger)range.location];
|
|
158
|
+
UITextPosition *end = [textView positionFromPosition:textView.beginningOfDocument
|
|
159
|
+
offset:(NSInteger)NSMaxRange(range)];
|
|
160
|
+
[textView replaceRange:[textView textRangeFromPosition:start toPosition:end] withText:text];
|
|
161
|
+
#else
|
|
162
|
+
[textView insertText:text replacementRange:range];
|
|
163
|
+
#endif
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/// Cross-platform content size update after measurement.
|
|
167
|
+
/// iOS UITextView has a settable contentSize; macOS NSTextView does not.
|
|
168
|
+
static inline void ENRMSetContentSize(ENRMPlatformTextView *textView, CGSize size)
|
|
169
|
+
{
|
|
170
|
+
#if !TARGET_OS_OSX
|
|
171
|
+
textView.contentSize = size;
|
|
172
|
+
#endif
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/// Returns YES when the user has asked the system to minimise motion.
|
|
176
|
+
/// iOS: UIAccessibilityIsReduceMotionEnabled.
|
|
177
|
+
/// macOS: NSWorkspace.shared.accessibilityDisplayShouldReduceMotion.
|
|
178
|
+
/// Always NO on platforms where the API is unavailable.
|
|
179
|
+
static inline BOOL ENRMShouldReduceMotion(void)
|
|
180
|
+
{
|
|
181
|
+
#if !TARGET_OS_OSX
|
|
182
|
+
return UIAccessibilityIsReduceMotionEnabled();
|
|
183
|
+
#else
|
|
184
|
+
if (@available(macOS 10.12, *)) {
|
|
185
|
+
return NSWorkspace.sharedWorkspace.accessibilityDisplayShouldReduceMotion;
|
|
186
|
+
}
|
|
187
|
+
return NO;
|
|
188
|
+
#endif
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
/// Sets default typing attributes on the text view.
|
|
192
|
+
/// On macOS, RCTUITextView overrides setTypingAttributes: to use defaultTextAttributes,
|
|
193
|
+
/// so we must set that property as well.
|
|
194
|
+
static inline void ENRMSetDefaultTypingAttributes(ENRMPlatformTextView *textView, NSDictionary *attrs)
|
|
195
|
+
{
|
|
196
|
+
#if TARGET_OS_OSX
|
|
197
|
+
textView.defaultTextAttributes = attrs;
|
|
198
|
+
#endif
|
|
199
|
+
textView.typingAttributes = attrs;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
/// Applies shared configuration to a text view used for tiptap input editing.
|
|
203
|
+
/// Handles platform differences: scroll indicators, text container insets,
|
|
204
|
+
/// drawsBackground (macOS). Sets editable=YES, scrollEnabled=YES.
|
|
205
|
+
static inline void ENRMConfigureTiptapTextInputTextView(ENRMPlatformTextView *textView)
|
|
206
|
+
{
|
|
207
|
+
textView.font = [UIFont systemFontOfSize:16.0];
|
|
208
|
+
textView.backgroundColor = [RCTUIColor clearColor];
|
|
209
|
+
textView.editable = YES;
|
|
210
|
+
#if !TARGET_OS_OSX
|
|
211
|
+
textView.scrollEnabled = YES;
|
|
212
|
+
textView.showsVerticalScrollIndicator = NO;
|
|
213
|
+
textView.showsHorizontalScrollIndicator = NO;
|
|
214
|
+
textView.textContainerInset = UIEdgeInsetsZero;
|
|
215
|
+
#else
|
|
216
|
+
textView.textContainerInsets = UIEdgeInsetsZero;
|
|
217
|
+
textView.drawsBackground = NO;
|
|
218
|
+
#endif
|
|
219
|
+
textView.textContainer.lineFragmentPadding = 0;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
/// Cross-platform cursor color: iOS uses tintColor; macOS uses insertionPointColor.
|
|
223
|
+
static inline void ENRMSetCursorColor(ENRMPlatformTextView *textView, RCTUIColor *color)
|
|
224
|
+
{
|
|
225
|
+
#if !TARGET_OS_OSX
|
|
226
|
+
textView.tintColor = color;
|
|
227
|
+
#else
|
|
228
|
+
textView.insertionPointColor = color;
|
|
229
|
+
#endif
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
/// Cross-platform selection color: iOS uses tintColor (also affects the caret
|
|
233
|
+
/// and selection handles); macOS sets the selection background via
|
|
234
|
+
/// `selectedTextAttributes`. Pass `nil` to restore the system default.
|
|
235
|
+
static inline void ENRMSetSelectionColor(ENRMPlatformTextView *textView, RCTUIColor *color)
|
|
236
|
+
{
|
|
237
|
+
#if !TARGET_OS_OSX
|
|
238
|
+
textView.tintColor = color;
|
|
239
|
+
#else
|
|
240
|
+
RCTUIColor *resolved = color ?: [NSColor selectedTextBackgroundColor];
|
|
241
|
+
textView.selectedTextAttributes = @{NSBackgroundColorAttributeName : resolved};
|
|
242
|
+
#endif
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
/// Cross-platform focus: iOS uses becomeFirstResponder;
|
|
246
|
+
/// macOS uses makeFirstResponder: on the window.
|
|
247
|
+
static inline void ENRMFocusTextView(ENRMPlatformTextView *textView)
|
|
248
|
+
{
|
|
249
|
+
#if !TARGET_OS_OSX
|
|
250
|
+
[textView becomeFirstResponder];
|
|
251
|
+
#else
|
|
252
|
+
[textView.window makeFirstResponder:textView];
|
|
253
|
+
#endif
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
/// Cross-platform blur: iOS uses resignFirstResponder;
|
|
257
|
+
/// macOS clears first responder via the window.
|
|
258
|
+
static inline void ENRMBlurTextView(ENRMPlatformTextView *textView)
|
|
259
|
+
{
|
|
260
|
+
#if !TARGET_OS_OSX
|
|
261
|
+
[textView resignFirstResponder];
|
|
262
|
+
#else
|
|
263
|
+
[textView.window makeFirstResponder:nil];
|
|
264
|
+
#endif
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
/// Applies shared configuration to a text view used for tiptap rendering.
|
|
268
|
+
/// Handles platform differences: scroll indicators, text container insets,
|
|
269
|
+
/// drawsBackground (macOS), accessibilityElementsHidden (iOS).
|
|
270
|
+
static inline void ENRMConfigureTiptapTextView(ENRMPlatformTextView *textView)
|
|
271
|
+
{
|
|
272
|
+
textView.font = [UIFont systemFontOfSize:16.0];
|
|
273
|
+
textView.backgroundColor = [RCTUIColor clearColor];
|
|
274
|
+
textView.textColor = [RCTUIColor blackColor];
|
|
275
|
+
textView.editable = NO;
|
|
276
|
+
textView.scrollEnabled = NO;
|
|
277
|
+
#if !TARGET_OS_OSX
|
|
278
|
+
textView.showsVerticalScrollIndicator = NO;
|
|
279
|
+
textView.showsHorizontalScrollIndicator = NO;
|
|
280
|
+
textView.textContainerInset = UIEdgeInsetsZero;
|
|
281
|
+
#else
|
|
282
|
+
textView.textContainerInsets = UIEdgeInsetsZero;
|
|
283
|
+
textView.drawsBackground = NO;
|
|
284
|
+
#endif
|
|
285
|
+
textView.textContainer.lineFragmentPadding = 0;
|
|
286
|
+
textView.layoutManager.usesFontLeading = ENRMLayoutManagerUsesFontLeading;
|
|
287
|
+
textView.linkTextAttributes = @{};
|
|
288
|
+
textView.selectable = YES;
|
|
289
|
+
#if !TARGET_OS_OSX
|
|
290
|
+
textView.accessibilityElementsHidden = YES;
|
|
291
|
+
#endif
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
/// Result of a text layout measurement pass.
|
|
295
|
+
typedef struct {
|
|
296
|
+
CGRect usedRect;
|
|
297
|
+
CGRect extraLineFragmentRect;
|
|
298
|
+
} ENRMTextLayoutResult;
|
|
299
|
+
|
|
300
|
+
/// Measures text layout in a text view for a given width.
|
|
301
|
+
/// On macOS, temporarily disables widthTracksTextView so the container width
|
|
302
|
+
/// can be set directly without being overridden by the view's frame.
|
|
303
|
+
static inline ENRMTextLayoutResult ENRMMeasureTextLayout(ENRMPlatformTextView *textView, CGFloat maxWidth)
|
|
304
|
+
{
|
|
305
|
+
#if TARGET_OS_OSX
|
|
306
|
+
textView.textContainer.widthTracksTextView = NO;
|
|
307
|
+
#endif
|
|
308
|
+
textView.textContainer.size = CGSizeMake(maxWidth, CGFLOAT_MAX);
|
|
309
|
+
[textView.layoutManager ensureLayoutForTextContainer:textView.textContainer];
|
|
310
|
+
ENRMTextLayoutResult result;
|
|
311
|
+
result.usedRect = [textView.layoutManager usedRectForTextContainer:textView.textContainer];
|
|
312
|
+
result.extraLineFragmentRect = textView.layoutManager.extraLineFragmentRect;
|
|
313
|
+
#if TARGET_OS_OSX
|
|
314
|
+
textView.textContainer.widthTracksTextView = YES;
|
|
315
|
+
#endif
|
|
316
|
+
return result;
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
/// Cross-platform display refresh: UIView requires layoutIfNeeded before setNeedsDisplay
|
|
320
|
+
/// to flush pending layout before the redraw; NSView takes a BOOL argument.
|
|
321
|
+
/// Implemented as a macro to avoid Objective-C++ implicit pointer conversion issues in .mm files.
|
|
322
|
+
#if !TARGET_OS_OSX
|
|
323
|
+
#define ENRMSetNeedsDisplay(view) \
|
|
324
|
+
do { \
|
|
325
|
+
[(view) layoutIfNeeded]; \
|
|
326
|
+
[(view) setNeedsDisplay]; \
|
|
327
|
+
} while (0)
|
|
328
|
+
#else
|
|
329
|
+
#define ENRMSetNeedsDisplay(view) [(view) setNeedsDisplay:YES]
|
|
330
|
+
#endif
|
|
331
|
+
|
|
332
|
+
/// Invalidates the text container, re-lays out any existing content, and
|
|
333
|
+
/// triggers a redraw. On iOS also resets contentOffset to zero.
|
|
334
|
+
/// Does NOT touch the text view's frame — callers that need to reposition
|
|
335
|
+
/// the view should set the frame themselves before calling this.
|
|
336
|
+
static inline void ENRMRefreshTextViewLayout(ENRMPlatformTextView *textView)
|
|
337
|
+
{
|
|
338
|
+
#if !TARGET_OS_OSX
|
|
339
|
+
textView.contentOffset = CGPointZero;
|
|
340
|
+
#endif
|
|
341
|
+
textView.textContainer.size = CGSizeMake(textView.bounds.size.width, CGFLOAT_MAX);
|
|
342
|
+
NSUInteger textLength = ENRMGetAttributedText(textView).length;
|
|
343
|
+
if (textLength > 0) {
|
|
344
|
+
[textView.layoutManager invalidateLayoutForCharacterRange:NSMakeRange(0, textLength) actualCharacterRange:NULL];
|
|
345
|
+
[textView.layoutManager ensureLayoutForTextContainer:textView.textContainer];
|
|
346
|
+
}
|
|
347
|
+
ENRMSetNeedsDisplay(textView);
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
/// Refreshes a text view's layout and display after it is attached to a window.
|
|
351
|
+
/// Sets the frame and text container to the given bounds, invalidates layout for
|
|
352
|
+
/// any existing content, then triggers a redraw.
|
|
353
|
+
static inline void ENRMRefreshTextViewAfterWindowAttach(ENRMPlatformTextView *textView, CGRect bounds)
|
|
354
|
+
{
|
|
355
|
+
textView.frame = bounds;
|
|
356
|
+
ENRMRefreshTextViewLayout(textView);
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
/// Cross-platform text deselection: UITextView uses selectedTextRange (nullable);
|
|
360
|
+
/// NSTextView uses selectedRange (length-based).
|
|
361
|
+
static inline void ENRMClearSelection(ENRMPlatformTextView *textView)
|
|
362
|
+
{
|
|
363
|
+
#if !TARGET_OS_OSX
|
|
364
|
+
if (textView.selectedTextRange != nil) {
|
|
365
|
+
textView.selectedTextRange = nil;
|
|
366
|
+
}
|
|
367
|
+
#else
|
|
368
|
+
if (textView.selectedRange.length > 0) {
|
|
369
|
+
textView.selectedRange = NSMakeRange(0, 0);
|
|
370
|
+
}
|
|
371
|
+
#endif
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
// ── Placeholder label abstraction ──────────────────────────────────────────────
|
|
375
|
+
|
|
376
|
+
#if !TARGET_OS_OSX
|
|
377
|
+
typedef UILabel ENRMPlaceholderLabel;
|
|
378
|
+
#else
|
|
379
|
+
typedef NSTextField ENRMPlaceholderLabel;
|
|
380
|
+
#endif
|
|
381
|
+
|
|
382
|
+
/// Creates a placeholder label configured for use inside an ENRMPlatformTextView.
|
|
383
|
+
/// On iOS: UILabel with multiline, placeholderTextColor, auto-layout pinned to
|
|
384
|
+
/// textContainerInset and lineFragmentPadding.
|
|
385
|
+
/// On macOS: borderless, non-editable NSTextField pinned to the text view origin.
|
|
386
|
+
static inline ENRMPlaceholderLabel *ENRMCreatePlaceholderLabel(ENRMPlatformTextView *textView, UIFont *font)
|
|
387
|
+
{
|
|
388
|
+
#if !TARGET_OS_OSX
|
|
389
|
+
UILabel *label = [[UILabel alloc] init];
|
|
390
|
+
label.numberOfLines = 0;
|
|
391
|
+
label.textColor = [UIColor placeholderTextColor];
|
|
392
|
+
label.font = font;
|
|
393
|
+
label.translatesAutoresizingMaskIntoConstraints = NO;
|
|
394
|
+
[textView addSubview:label];
|
|
395
|
+
[NSLayoutConstraint activateConstraints:@[
|
|
396
|
+
[label.topAnchor constraintEqualToAnchor:textView.topAnchor constant:textView.textContainerInset.top],
|
|
397
|
+
[label.leadingAnchor constraintEqualToAnchor:textView.leadingAnchor
|
|
398
|
+
constant:textView.textContainer.lineFragmentPadding],
|
|
399
|
+
[label.trailingAnchor constraintEqualToAnchor:textView.trailingAnchor
|
|
400
|
+
constant:-textView.textContainer.lineFragmentPadding],
|
|
401
|
+
]];
|
|
402
|
+
return label;
|
|
403
|
+
#else
|
|
404
|
+
NSTextField *label = [[NSTextField alloc] initWithFrame:CGRectZero];
|
|
405
|
+
label.bordered = NO;
|
|
406
|
+
label.editable = NO;
|
|
407
|
+
label.selectable = NO;
|
|
408
|
+
label.drawsBackground = NO;
|
|
409
|
+
label.textColor = [NSColor placeholderTextColor];
|
|
410
|
+
label.font = font;
|
|
411
|
+
label.translatesAutoresizingMaskIntoConstraints = NO;
|
|
412
|
+
[textView addSubview:label];
|
|
413
|
+
[NSLayoutConstraint activateConstraints:@[
|
|
414
|
+
[label.topAnchor constraintEqualToAnchor:textView.topAnchor],
|
|
415
|
+
[label.leadingAnchor constraintEqualToAnchor:textView.leadingAnchor],
|
|
416
|
+
]];
|
|
417
|
+
return label;
|
|
418
|
+
#endif
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
/// Cross-platform placeholder attributed text setter.
|
|
422
|
+
static inline void ENRMSetPlaceholderAttributedText(ENRMPlaceholderLabel *label, NSAttributedString *text)
|
|
423
|
+
{
|
|
424
|
+
#if !TARGET_OS_OSX
|
|
425
|
+
label.attributedText = text;
|
|
426
|
+
#else
|
|
427
|
+
label.attributedStringValue = text;
|
|
428
|
+
#endif
|
|
429
|
+
}
|