react-native-enriched-html 1.0.0 → 1.0.1
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/android/src/main/java/com/swmansion/enriched/common/EnrichedSpanFlags.kt +39 -0
- package/android/src/main/java/com/swmansion/enriched/common/parser/EnrichedParser.java +43 -20
- package/android/src/main/java/com/swmansion/enriched/common/parser/EnrichedSpanFactory.kt +1 -0
- package/android/src/main/java/com/swmansion/enriched/text/EnrichedTextSpanFactory.kt +1 -0
- package/android/src/main/java/com/swmansion/enriched/text/EnrichedTextView.kt +2 -1
- package/android/src/main/java/com/swmansion/enriched/textinput/EnrichedTextInputSpannableFactory.kt +2 -1
- package/android/src/main/java/com/swmansion/enriched/textinput/EnrichedTextInputView.kt +8 -5
- package/android/src/main/java/com/swmansion/enriched/textinput/events/MentionHandler.kt +12 -2
- package/android/src/main/java/com/swmansion/enriched/textinput/events/OnMentionEvent.kt +6 -0
- package/android/src/main/java/com/swmansion/enriched/textinput/styles/AlignmentStyles.kt +6 -7
- package/android/src/main/java/com/swmansion/enriched/textinput/styles/InlineStyles.kt +13 -1
- package/android/src/main/java/com/swmansion/enriched/textinput/styles/ListStyles.kt +4 -3
- package/android/src/main/java/com/swmansion/enriched/textinput/styles/ParagraphStyles.kt +4 -3
- package/android/src/main/java/com/swmansion/enriched/textinput/styles/ParametrizedStyles.kt +38 -11
- package/android/src/main/java/com/swmansion/enriched/textinput/utils/EnrichedSelection.kt +2 -0
- package/android/src/main/java/com/swmansion/enriched/textinput/utils/EnrichedSpannable.kt +2 -1
- package/android/src/main/java/com/swmansion/enriched/textinput/utils/Utils.kt +2 -1
- package/cpp/parser/GumboNormalizer.c +61 -3
- package/cpp/tests/GumboParserTest.cpp +54 -0
- package/ios/EnrichedTextInputView.mm +37 -25
- package/ios/extensions/LayoutManagerExtension.mm +73 -62
- package/ios/extensions/StringExtension.mm +75 -0
- package/ios/htmlParser/HtmlParser.h +4 -1
- package/ios/htmlParser/HtmlParser.mm +23 -5
- package/ios/inputHtmlParser/InputHtmlParser.mm +6 -3
- package/ios/interfaces/StyleHeaders.h +4 -0
- package/ios/styles/LinkStyle.mm +20 -34
- package/ios/styles/MentionStyle.mm +55 -4
- package/ios/textHtmlParser/TextHtmlParser.mm +2 -1
- package/ios/utils/ParagraphAttributesUtils.mm +7 -0
- package/lib/module/index.js +1 -0
- package/lib/module/index.js.map +1 -1
- package/lib/module/utils/expandMentionStylesForIndicators.js +2 -3
- package/lib/module/utils/expandMentionStylesForIndicators.js.map +1 -1
- package/lib/module/utils/normalizeHtmlStyle.js +1 -1
- package/lib/module/utils/normalizeHtmlStyle.js.map +1 -1
- package/lib/module/web/EnrichedText.css +343 -0
- package/lib/module/web/EnrichedText.js +55 -0
- package/lib/module/web/EnrichedText.js.map +1 -0
- package/lib/module/web/EnrichedTextInput.js +54 -52
- package/lib/module/web/EnrichedTextInput.js.map +1 -1
- package/lib/module/web/constants/brokenImageGlyph.js +9 -0
- package/lib/module/web/constants/brokenImageGlyph.js.map +1 -0
- package/lib/module/web/constants/classNames.js +5 -0
- package/lib/module/web/constants/classNames.js.map +1 -0
- package/lib/module/web/emitLinkDetected.js +12 -0
- package/lib/module/web/emitLinkDetected.js.map +1 -0
- package/lib/module/web/formats/EnrichedBlockquote.js +1 -1
- package/lib/module/web/formats/EnrichedBlockquote.js.map +1 -1
- package/lib/module/web/formats/EnrichedCheckboxList.js +2 -2
- package/lib/module/web/formats/EnrichedCheckboxList.js.map +1 -1
- package/lib/module/web/formats/EnrichedCodeBlock.js +1 -1
- package/lib/module/web/formats/EnrichedCodeBlock.js.map +1 -1
- package/lib/module/web/formats/EnrichedHeading.js +1 -1
- package/lib/module/web/formats/EnrichedHeading.js.map +1 -1
- package/lib/module/web/formats/EnrichedImageNodeView.js +1 -1
- package/lib/module/web/formats/EnrichedImageNodeView.js.map +1 -1
- package/lib/module/web/formats/EnrichedLink.js +43 -3
- package/lib/module/web/formats/EnrichedLink.js.map +1 -1
- package/lib/module/web/formats/EnrichedOrderedList.js +2 -2
- package/lib/module/web/formats/EnrichedOrderedList.js.map +1 -1
- package/lib/module/web/formats/EnrichedTextAlign.js +82 -0
- package/lib/module/web/formats/EnrichedTextAlign.js.map +1 -0
- package/lib/module/web/formats/EnrichedUnorderedList.js +2 -2
- package/lib/module/web/formats/EnrichedUnorderedList.js.map +1 -1
- package/lib/module/web/formats/applyWrappingListToSelection.js +3 -2
- package/lib/module/web/formats/applyWrappingListToSelection.js.map +1 -1
- package/lib/module/web/formats/formatRules.js +39 -3
- package/lib/module/web/formats/formatRules.js.map +1 -1
- package/lib/module/web/formats/listKeyboard.js +4 -1
- package/lib/module/web/formats/listKeyboard.js.map +1 -1
- package/lib/module/web/normalization/checkboxHtmlNormalizer.js.map +1 -0
- package/lib/module/web/normalization/htmlNormalizer.js +514 -0
- package/lib/module/web/normalization/htmlNormalizer.js.map +1 -0
- package/lib/module/web/normalization/prepareHtmlForWeb.js +78 -0
- package/lib/module/web/normalization/prepareHtmlForWeb.js.map +1 -0
- package/lib/module/web/{tiptapHtmlNormalizer.js → normalization/tiptapHtmlNormalizer.js} +6 -2
- package/lib/module/web/normalization/tiptapHtmlNormalizer.js.map +1 -0
- package/lib/module/web/pmPlugins/AutolinkPlugin/autolinkRegex.js +27 -0
- package/lib/module/web/pmPlugins/AutolinkPlugin/autolinkRegex.js.map +1 -0
- package/lib/module/web/pmPlugins/AutolinkPlugin/index.js +178 -0
- package/lib/module/web/pmPlugins/AutolinkPlugin/index.js.map +1 -0
- package/lib/module/web/pmPlugins/MentionPlugin/index.js +1 -1
- package/lib/module/web/pmPlugins/MentionPlugin/index.js.map +1 -1
- package/lib/module/web/pmPlugins/MentionPlugin/makeMentionPluginState.js +23 -4
- package/lib/module/web/pmPlugins/MentionPlugin/makeMentionPluginState.js.map +1 -1
- package/lib/module/web/pmPlugins/MentionPlugin/setMention.js +17 -18
- package/lib/module/web/pmPlugins/MentionPlugin/setMention.js.map +1 -1
- package/lib/module/web/pmPlugins/MentionPlugin/useMentionEvents.js +105 -0
- package/lib/module/web/pmPlugins/MentionPlugin/useMentionEvents.js.map +1 -0
- package/lib/module/web/pmPlugins/ShortcutPlugin.js +11 -0
- package/lib/module/web/pmPlugins/ShortcutPlugin.js.map +1 -1
- package/lib/module/web/pmPlugins/StrictMarksPlugin.js +2 -0
- package/lib/module/web/pmPlugins/StrictMarksPlugin.js.map +1 -1
- package/lib/module/web/pmPlugins/StripBoldInStyledHeadingsPlugin.js.map +1 -1
- package/lib/module/web/sanitization/htmlSanitizer.js +10 -0
- package/lib/module/web/sanitization/htmlSanitizer.js.map +1 -0
- package/lib/module/web/styleConversion/buildMentionRulesCSS.js +12 -6
- package/lib/module/web/styleConversion/buildMentionRulesCSS.js.map +1 -1
- package/lib/module/web/styleConversion/enrichedBaseStyleToCSSProperties.js +159 -0
- package/lib/module/web/styleConversion/enrichedBaseStyleToCSSProperties.js.map +1 -0
- package/lib/module/web/styleConversion/enrichedInputStyleToCSSProperties.js +3 -155
- package/lib/module/web/styleConversion/enrichedInputStyleToCSSProperties.js.map +1 -1
- package/lib/module/web/styleConversion/enrichedTextStyleToCSSProperties.js +44 -0
- package/lib/module/web/styleConversion/enrichedTextStyleToCSSProperties.js.map +1 -0
- package/lib/module/web/styleConversion/{enrichedInputThemingToCSSProperties.js → enrichedThemingToCSSProperties.js} +3 -3
- package/lib/module/web/styleConversion/enrichedThemingToCSSProperties.js.map +1 -0
- package/lib/module/web/styleConversion/htmlStyleToCSSVariables.js +87 -64
- package/lib/module/web/styleConversion/htmlStyleToCSSVariables.js.map +1 -1
- package/lib/module/web/styleConversion/inlineImageCSSVariables.js +7 -0
- package/lib/module/web/styleConversion/inlineImageCSSVariables.js.map +1 -0
- package/lib/module/web/useImageErrorFallback.js +33 -0
- package/lib/module/web/useImageErrorFallback.js.map +1 -0
- package/lib/module/web/useOnChangeHtml.js +1 -1
- package/lib/module/web/useOnChangeHtml.js.map +1 -1
- package/lib/module/web/useOnChangeState.js +6 -3
- package/lib/module/web/useOnChangeState.js.map +1 -1
- package/lib/module/web/useOnLinkDetected.js +32 -45
- package/lib/module/web/useOnLinkDetected.js.map +1 -1
- package/lib/module/web/usePressInteractions.js +19 -0
- package/lib/module/web/usePressInteractions.js.map +1 -0
- package/lib/module/web/useStableRef.js +13 -0
- package/lib/module/web/useStableRef.js.map +1 -0
- package/lib/typescript/src/index.d.ts +1 -0
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/lib/typescript/src/native/EnrichedText.d.ts +1 -1
- package/lib/typescript/src/native/EnrichedText.d.ts.map +1 -1
- package/lib/typescript/src/native/EnrichedTextInput.d.ts +1 -1
- package/lib/typescript/src/native/EnrichedTextInput.d.ts.map +1 -1
- package/lib/typescript/src/types.d.ts +1 -1
- package/lib/typescript/src/types.d.ts.map +1 -1
- package/lib/typescript/src/utils/expandMentionStylesForIndicators.d.ts +1 -1
- package/lib/typescript/src/utils/expandMentionStylesForIndicators.d.ts.map +1 -1
- package/lib/typescript/src/utils/normalizeHtmlStyle.d.ts.map +1 -1
- package/lib/typescript/src/web/EnrichedText.d.ts +4 -0
- package/lib/typescript/src/web/EnrichedText.d.ts.map +1 -0
- package/lib/typescript/src/web/EnrichedTextInput.d.ts +2 -2
- package/lib/typescript/src/web/EnrichedTextInput.d.ts.map +1 -1
- package/lib/typescript/src/web/constants/brokenImageGlyph.d.ts +3 -0
- package/lib/typescript/src/web/constants/brokenImageGlyph.d.ts.map +1 -0
- package/lib/typescript/src/web/constants/classNames.d.ts +3 -0
- package/lib/typescript/src/web/constants/classNames.d.ts.map +1 -0
- package/lib/typescript/src/web/emitLinkDetected.d.ts +10 -0
- package/lib/typescript/src/web/emitLinkDetected.d.ts.map +1 -0
- package/lib/typescript/src/web/formats/EnrichedBlockquote.d.ts.map +1 -1
- package/lib/typescript/src/web/formats/EnrichedCheckboxList.d.ts.map +1 -1
- package/lib/typescript/src/web/formats/EnrichedCodeBlock.d.ts.map +1 -1
- package/lib/typescript/src/web/formats/EnrichedHeading.d.ts.map +1 -1
- package/lib/typescript/src/web/formats/EnrichedImageNodeView.d.ts +1 -1
- package/lib/typescript/src/web/formats/EnrichedImageNodeView.d.ts.map +1 -1
- package/lib/typescript/src/web/formats/EnrichedLink.d.ts +4 -1
- package/lib/typescript/src/web/formats/EnrichedLink.d.ts.map +1 -1
- package/lib/typescript/src/web/formats/EnrichedOrderedList.d.ts.map +1 -1
- package/lib/typescript/src/web/formats/EnrichedTextAlign.d.ts +2 -0
- package/lib/typescript/src/web/formats/EnrichedTextAlign.d.ts.map +1 -0
- package/lib/typescript/src/web/formats/EnrichedUnorderedList.d.ts.map +1 -1
- package/lib/typescript/src/web/formats/applyWrappingListToSelection.d.ts.map +1 -1
- package/lib/typescript/src/web/formats/formatRules.d.ts +3 -1
- package/lib/typescript/src/web/formats/formatRules.d.ts.map +1 -1
- package/lib/typescript/src/web/formats/listKeyboard.d.ts.map +1 -1
- package/lib/typescript/src/web/normalization/checkboxHtmlNormalizer.d.ts.map +1 -0
- package/lib/typescript/src/web/normalization/htmlNormalizer.d.ts +2 -0
- package/lib/typescript/src/web/normalization/htmlNormalizer.d.ts.map +1 -0
- package/lib/typescript/src/web/normalization/prepareHtmlForWeb.d.ts +2 -0
- package/lib/typescript/src/web/normalization/prepareHtmlForWeb.d.ts.map +1 -0
- package/lib/typescript/src/web/normalization/tiptapHtmlNormalizer.d.ts +3 -0
- package/lib/typescript/src/web/normalization/tiptapHtmlNormalizer.d.ts.map +1 -0
- package/lib/typescript/src/web/pmPlugins/AutolinkPlugin/autolinkRegex.d.ts +7 -0
- package/lib/typescript/src/web/pmPlugins/AutolinkPlugin/autolinkRegex.d.ts.map +1 -0
- package/lib/typescript/src/web/pmPlugins/AutolinkPlugin/index.d.ts +8 -0
- package/lib/typescript/src/web/pmPlugins/AutolinkPlugin/index.d.ts.map +1 -0
- package/lib/typescript/src/web/pmPlugins/MentionPlugin/index.d.ts +1 -1
- package/lib/typescript/src/web/pmPlugins/MentionPlugin/index.d.ts.map +1 -1
- package/lib/typescript/src/web/pmPlugins/MentionPlugin/makeMentionPluginState.d.ts.map +1 -1
- package/lib/typescript/src/web/pmPlugins/MentionPlugin/setMention.d.ts.map +1 -1
- package/lib/typescript/src/web/pmPlugins/MentionPlugin/useMentionEvents.d.ts +4 -0
- package/lib/typescript/src/web/pmPlugins/MentionPlugin/useMentionEvents.d.ts.map +1 -0
- package/lib/typescript/src/web/pmPlugins/ShortcutPlugin.d.ts.map +1 -1
- package/lib/typescript/src/web/pmPlugins/StrictMarksPlugin.d.ts.map +1 -1
- package/lib/typescript/src/web/pmPlugins/StripBoldInStyledHeadingsPlugin.d.ts +6 -1
- package/lib/typescript/src/web/pmPlugins/StripBoldInStyledHeadingsPlugin.d.ts.map +1 -1
- package/lib/typescript/src/web/sanitization/htmlSanitizer.d.ts +2 -0
- package/lib/typescript/src/web/sanitization/htmlSanitizer.d.ts.map +1 -0
- package/lib/typescript/src/web/styleConversion/buildMentionRulesCSS.d.ts +2 -2
- package/lib/typescript/src/web/styleConversion/buildMentionRulesCSS.d.ts.map +1 -1
- package/lib/typescript/src/web/styleConversion/enrichedBaseStyleToCSSProperties.d.ts +8 -0
- package/lib/typescript/src/web/styleConversion/enrichedBaseStyleToCSSProperties.d.ts.map +1 -0
- package/lib/typescript/src/web/styleConversion/enrichedInputStyleToCSSProperties.d.ts +2 -5
- package/lib/typescript/src/web/styleConversion/enrichedInputStyleToCSSProperties.d.ts.map +1 -1
- package/lib/typescript/src/web/styleConversion/enrichedTextStyleToCSSProperties.d.ts +4 -0
- package/lib/typescript/src/web/styleConversion/enrichedTextStyleToCSSProperties.d.ts.map +1 -0
- package/lib/typescript/src/web/styleConversion/{enrichedInputThemingToCSSProperties.d.ts → enrichedThemingToCSSProperties.d.ts} +1 -1
- package/lib/typescript/src/web/styleConversion/enrichedThemingToCSSProperties.d.ts.map +1 -0
- package/lib/typescript/src/web/styleConversion/htmlStyleToCSSVariables.d.ts +5 -4
- package/lib/typescript/src/web/styleConversion/htmlStyleToCSSVariables.d.ts.map +1 -1
- package/lib/typescript/src/web/styleConversion/inlineImageCSSVariables.d.ts +3 -0
- package/lib/typescript/src/web/styleConversion/inlineImageCSSVariables.d.ts.map +1 -0
- package/lib/typescript/src/web/useImageErrorFallback.d.ts +3 -0
- package/lib/typescript/src/web/useImageErrorFallback.d.ts.map +1 -0
- package/lib/typescript/src/web/useOnChangeState.d.ts.map +1 -1
- package/lib/typescript/src/web/useOnLinkDetected.d.ts +2 -2
- package/lib/typescript/src/web/useOnLinkDetected.d.ts.map +1 -1
- package/lib/typescript/src/web/usePressInteractions.d.ts +2 -0
- package/lib/typescript/src/web/usePressInteractions.d.ts.map +1 -0
- package/lib/typescript/src/web/useStableRef.d.ts +3 -0
- package/lib/typescript/src/web/useStableRef.d.ts.map +1 -0
- package/package.json +54 -28
- package/src/index.tsx +1 -0
- package/src/types.ts +5 -3
- package/src/utils/expandMentionStylesForIndicators.ts +3 -3
- package/src/utils/normalizeHtmlStyle.ts +2 -1
- package/src/web/EnrichedText.css +343 -0
- package/src/web/EnrichedText.tsx +82 -0
- package/src/web/EnrichedTextInput.tsx +69 -55
- package/src/web/constants/brokenImageGlyph.ts +7 -0
- package/src/web/constants/classNames.ts +2 -0
- package/src/web/emitLinkDetected.ts +29 -0
- package/src/web/formats/EnrichedBlockquote.ts +2 -1
- package/src/web/formats/EnrichedCheckboxList.ts +5 -2
- package/src/web/formats/EnrichedCodeBlock.ts +2 -1
- package/src/web/formats/EnrichedHeading.ts +2 -1
- package/src/web/formats/EnrichedImageNodeView.tsx +1 -3
- package/src/web/formats/EnrichedLink.ts +59 -4
- package/src/web/formats/EnrichedOrderedList.ts +5 -2
- package/src/web/formats/EnrichedTextAlign.ts +88 -0
- package/src/web/formats/EnrichedUnorderedList.ts +5 -2
- package/src/web/formats/applyWrappingListToSelection.ts +4 -4
- package/src/web/formats/formatRules.ts +48 -4
- package/src/web/formats/listKeyboard.ts +6 -1
- package/src/web/normalization/htmlNormalizer.ts +656 -0
- package/src/web/normalization/prepareHtmlForWeb.ts +93 -0
- package/src/web/{tiptapHtmlNormalizer.ts → normalization/tiptapHtmlNormalizer.ts} +12 -2
- package/src/web/pmPlugins/AutolinkPlugin/autolinkRegex.ts +43 -0
- package/src/web/pmPlugins/AutolinkPlugin/index.ts +274 -0
- package/src/web/pmPlugins/MentionPlugin/index.ts +1 -1
- package/src/web/pmPlugins/MentionPlugin/makeMentionPluginState.ts +32 -5
- package/src/web/pmPlugins/MentionPlugin/setMention.ts +19 -29
- package/src/web/pmPlugins/MentionPlugin/useMentionEvents.ts +114 -0
- package/src/web/pmPlugins/ShortcutPlugin.ts +7 -0
- package/src/web/pmPlugins/StrictMarksPlugin.ts +3 -0
- package/src/web/pmPlugins/StripBoldInStyledHeadingsPlugin.ts +41 -36
- package/src/web/sanitization/htmlSanitizer.ts +8 -0
- package/src/web/styleConversion/buildMentionRulesCSS.ts +30 -11
- package/src/web/styleConversion/enrichedBaseStyleToCSSProperties.ts +228 -0
- package/src/web/styleConversion/enrichedInputStyleToCSSProperties.ts +6 -217
- package/src/web/styleConversion/enrichedTextStyleToCSSProperties.ts +53 -0
- package/src/web/styleConversion/{enrichedInputThemingToCSSProperties.ts → enrichedThemingToCSSProperties.ts} +4 -4
- package/src/web/styleConversion/htmlStyleToCSSVariables.ts +121 -70
- package/src/web/styleConversion/inlineImageCSSVariables.ts +6 -0
- package/src/web/useImageErrorFallback.ts +37 -0
- package/src/web/useOnChangeHtml.ts +1 -1
- package/src/web/useOnChangeState.ts +7 -5
- package/src/web/useOnLinkDetected.ts +38 -50
- package/src/web/usePressInteractions.tsx +22 -0
- package/src/web/useStableRef.ts +12 -0
- package/lib/module/web/EnrichedTextInput.css +0 -201
- package/lib/module/web/checkboxHtmlNormalizer.js.map +0 -1
- package/lib/module/web/pmPlugins/MentionPlugin/subscribeMentionEvents.js +0 -100
- package/lib/module/web/pmPlugins/MentionPlugin/subscribeMentionEvents.js.map +0 -1
- package/lib/module/web/styleConversion/enrichedInputThemingToCSSProperties.js.map +0 -1
- package/lib/module/web/tiptapHtmlNormalizer.js.map +0 -1
- package/lib/typescript/src/web/checkboxHtmlNormalizer.d.ts.map +0 -1
- package/lib/typescript/src/web/pmPlugins/MentionPlugin/subscribeMentionEvents.d.ts +0 -4
- package/lib/typescript/src/web/pmPlugins/MentionPlugin/subscribeMentionEvents.d.ts.map +0 -1
- package/lib/typescript/src/web/styleConversion/enrichedInputThemingToCSSProperties.d.ts.map +0 -1
- package/lib/typescript/src/web/tiptapHtmlNormalizer.d.ts +0 -3
- package/lib/typescript/src/web/tiptapHtmlNormalizer.d.ts.map +0 -1
- package/src/web/EnrichedTextInput.css +0 -201
- package/src/web/pmPlugins/MentionPlugin/subscribeMentionEvents.ts +0 -105
- /package/lib/module/web/{checkboxHtmlNormalizer.js → normalization/checkboxHtmlNormalizer.js} +0 -0
- /package/lib/typescript/src/web/{checkboxHtmlNormalizer.d.ts → normalization/checkboxHtmlNormalizer.d.ts} +0 -0
- /package/src/web/{checkboxHtmlNormalizer.ts → normalization/checkboxHtmlNormalizer.ts} +0 -0
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import type { CSSProperties } from 'react';
|
|
2
|
+
import type { TextStyle } from 'react-native';
|
|
3
|
+
import { enrichedBaseStyleToCSSProperties } from './enrichedBaseStyleToCSSProperties';
|
|
4
|
+
import { toColor } from './toColor';
|
|
5
|
+
|
|
6
|
+
export function enrichedTextStyleToCSSProperties(
|
|
7
|
+
style: TextStyle
|
|
8
|
+
): CSSProperties {
|
|
9
|
+
const css: CSSProperties = {
|
|
10
|
+
...enrichedBaseStyleToCSSProperties(style, { scrollEnabled: false }),
|
|
11
|
+
|
|
12
|
+
// Text-only properties
|
|
13
|
+
// textAlign: RN 'auto' has no CSS equivalent
|
|
14
|
+
textAlign: style.textAlign !== 'auto' ? style.textAlign : undefined,
|
|
15
|
+
textTransform: style.textTransform,
|
|
16
|
+
textDecorationLine: style.textDecorationLine,
|
|
17
|
+
textDecorationStyle: style.textDecorationStyle,
|
|
18
|
+
textDecorationColor: toColor(style.textDecorationColor),
|
|
19
|
+
textShadow: resolveTextShadow(style),
|
|
20
|
+
// userSelect: RN 'contain' has no CSS equivalent
|
|
21
|
+
userSelect: style.userSelect !== 'contain' ? style.userSelect : undefined,
|
|
22
|
+
fontVariant: Array.isArray(style.fontVariant)
|
|
23
|
+
? style.fontVariant.join(' ')
|
|
24
|
+
: undefined,
|
|
25
|
+
// writingDirection: RN 'auto' has no CSS equivalent
|
|
26
|
+
direction:
|
|
27
|
+
style.writingDirection !== 'auto' ? style.writingDirection : undefined,
|
|
28
|
+
// verticalAlign: RN 'auto' has no CSS equivalent
|
|
29
|
+
verticalAlign:
|
|
30
|
+
style.verticalAlign !== 'auto' ? style.verticalAlign : undefined,
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
return Object.fromEntries(
|
|
34
|
+
Object.entries(css).filter(([, v]) => v !== undefined)
|
|
35
|
+
);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function resolveTextShadow(style: TextStyle): string | undefined {
|
|
39
|
+
const { textShadowColor, textShadowOffset, textShadowRadius } = style;
|
|
40
|
+
if (
|
|
41
|
+
textShadowColor == null &&
|
|
42
|
+
textShadowOffset == null &&
|
|
43
|
+
textShadowRadius == null
|
|
44
|
+
) {
|
|
45
|
+
return undefined;
|
|
46
|
+
}
|
|
47
|
+
const x = textShadowOffset?.width ?? 0;
|
|
48
|
+
const y = textShadowOffset?.height ?? 0;
|
|
49
|
+
const blur = textShadowRadius ?? 0;
|
|
50
|
+
const color = toColor(textShadowColor);
|
|
51
|
+
const offset = `${x}px ${y}px ${blur}px`;
|
|
52
|
+
return color ? `${offset} ${color}` : offset;
|
|
53
|
+
}
|
|
@@ -4,8 +4,8 @@ import { toColor } from './toColor';
|
|
|
4
4
|
|
|
5
5
|
type EnrichedInputThemingStyle = Partial<
|
|
6
6
|
Pick<CSSProperties, 'caretColor'> & {
|
|
7
|
-
'--
|
|
8
|
-
'--
|
|
7
|
+
'--et-placeholder-text-color': string;
|
|
8
|
+
'--et-selection-color': string;
|
|
9
9
|
}
|
|
10
10
|
>;
|
|
11
11
|
|
|
@@ -25,10 +25,10 @@ export function enrichedInputThemingToCSSProperties({
|
|
|
25
25
|
if (caret) extra.caretColor = caret;
|
|
26
26
|
|
|
27
27
|
const placeholderCss = toColor(placeholderTextColor);
|
|
28
|
-
if (placeholderCss) extra['--
|
|
28
|
+
if (placeholderCss) extra['--et-placeholder-text-color'] = placeholderCss;
|
|
29
29
|
|
|
30
30
|
const selectionCss = toColor(selectionColor);
|
|
31
|
-
if (selectionCss) extra['--
|
|
31
|
+
if (selectionCss) extra['--et-selection-color'] = selectionCss;
|
|
32
32
|
|
|
33
33
|
return extra;
|
|
34
34
|
}
|
|
@@ -1,7 +1,15 @@
|
|
|
1
1
|
import type { CSSProperties } from 'react';
|
|
2
2
|
import type { ColorValue } from 'react-native';
|
|
3
|
-
import type {
|
|
4
|
-
|
|
3
|
+
import type {
|
|
4
|
+
EnrichedTextHtmlStyle,
|
|
5
|
+
EnrichedTextMentionStyleProperties,
|
|
6
|
+
HtmlStyle,
|
|
7
|
+
MentionStyleProperties,
|
|
8
|
+
} from '../../types';
|
|
9
|
+
import {
|
|
10
|
+
DEFAULT_ENRICHED_TEXT_STYLE,
|
|
11
|
+
DEFAULT_HTML_STYLE,
|
|
12
|
+
} from '../../utils/defaultHtmlStyle';
|
|
5
13
|
import { expandMentionStylesForIndicators } from '../../utils/expandMentionStylesForIndicators';
|
|
6
14
|
import { HEADING_TAGS } from '../formats/EnrichedHeading';
|
|
7
15
|
import {
|
|
@@ -12,17 +20,21 @@ import { toColor } from './toColor';
|
|
|
12
20
|
import { isMentionStyleRecord } from '../../utils/isMentionStyleRecord';
|
|
13
21
|
|
|
14
22
|
export function mergeWithDefaultHtmlStyle(
|
|
15
|
-
htmlStyle?: HtmlStyle
|
|
23
|
+
htmlStyle?: HtmlStyle,
|
|
24
|
+
htmlStyleToMergeWith: HtmlStyle = DEFAULT_HTML_STYLE
|
|
16
25
|
): Required<HtmlStyle> {
|
|
17
26
|
const style = htmlStyle ?? {};
|
|
18
27
|
|
|
19
|
-
const mentionMap = expandMentionStylesForIndicatorsIncludeDefault(
|
|
28
|
+
const mentionMap = expandMentionStylesForIndicatorsIncludeDefault(
|
|
29
|
+
style,
|
|
30
|
+
htmlStyleToMergeWith
|
|
31
|
+
);
|
|
20
32
|
const converted: HtmlStyle = {
|
|
21
33
|
...style,
|
|
22
34
|
mention: mentionMap,
|
|
23
35
|
};
|
|
24
36
|
|
|
25
|
-
const merged: Record<string, unknown> = { ...
|
|
37
|
+
const merged: Record<string, unknown> = { ...htmlStyleToMergeWith };
|
|
26
38
|
|
|
27
39
|
for (const key in converted) {
|
|
28
40
|
if (key === 'mention') {
|
|
@@ -30,7 +42,7 @@ export function mergeWithDefaultHtmlStyle(
|
|
|
30
42
|
continue;
|
|
31
43
|
}
|
|
32
44
|
merged[key] = {
|
|
33
|
-
...
|
|
45
|
+
...htmlStyleToMergeWith[key as keyof HtmlStyle],
|
|
34
46
|
...(converted[key as keyof HtmlStyle] as object),
|
|
35
47
|
};
|
|
36
48
|
}
|
|
@@ -38,39 +50,76 @@ export function mergeWithDefaultHtmlStyle(
|
|
|
38
50
|
return merged as Required<HtmlStyle>;
|
|
39
51
|
}
|
|
40
52
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
53
|
+
export function mergeWithDefaultEnrichedTextHtmlStyle(
|
|
54
|
+
htmlStyle?: EnrichedTextHtmlStyle
|
|
55
|
+
): Required<EnrichedTextHtmlStyle> {
|
|
56
|
+
const merged = mergeWithDefaultHtmlStyle(
|
|
57
|
+
htmlStyle as HtmlStyle,
|
|
58
|
+
DEFAULT_ENRICHED_TEXT_STYLE
|
|
59
|
+
);
|
|
60
|
+
|
|
61
|
+
const a = {
|
|
62
|
+
...DEFAULT_ENRICHED_TEXT_STYLE.a,
|
|
63
|
+
...htmlStyle?.a,
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
const mentionDefaults = DEFAULT_ENRICHED_TEXT_STYLE.mention;
|
|
67
|
+
const passedMentionMap = htmlStyle?.mention;
|
|
68
|
+
const mergedMentionMap = merged.mention as Record<
|
|
69
|
+
string,
|
|
70
|
+
EnrichedTextMentionStyleProperties
|
|
71
|
+
>;
|
|
72
|
+
const mention: Record<string, EnrichedTextMentionStyleProperties> = {};
|
|
73
|
+
for (const indicator in mergedMentionMap) {
|
|
74
|
+
mention[indicator] = {
|
|
75
|
+
...mentionDefaults,
|
|
76
|
+
...(isMentionStyleRecord(passedMentionMap)
|
|
77
|
+
? (passedMentionMap[indicator] ??
|
|
78
|
+
passedMentionMap[MENTION_STYLE_DEFAULT_KEY])
|
|
79
|
+
: passedMentionMap),
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
return {
|
|
84
|
+
...merged,
|
|
85
|
+
a,
|
|
86
|
+
mention,
|
|
87
|
+
} as Required<EnrichedTextHtmlStyle>;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
const ET_CSS_VARS = {
|
|
91
|
+
codeColor: '--et-code-color',
|
|
92
|
+
codeBgColor: '--et-code-bg-color',
|
|
93
|
+
blockquoteBorderColor: '--et-blockquote-border-color',
|
|
94
|
+
blockquoteBorderWidth: '--et-blockquote-border-width',
|
|
95
|
+
blockquoteGapWidth: '--et-blockquote-gap-width',
|
|
96
|
+
blockquoteColor: '--et-blockquote-color',
|
|
97
|
+
codeblockBgColor: '--et-codeblock-bg-color',
|
|
98
|
+
codeblockColor: '--et-codeblock-color',
|
|
99
|
+
codeblockBorderRadius: '--et-codeblock-border-radius',
|
|
100
|
+
linkColor: '--et-link-color',
|
|
101
|
+
linkTextDecorationLine: '--et-link-text-decoration-line',
|
|
102
|
+
ulBulletColor: '--et-ul-bullet-color',
|
|
103
|
+
ulBulletSize: '--et-ul-bullet-size',
|
|
104
|
+
ulMarginLeft: '--et-ul-margin-left',
|
|
105
|
+
ulGapWidth: '--et-ul-gap-width',
|
|
106
|
+
olMarginLeft: '--et-ol-margin-left',
|
|
107
|
+
olGapWidth: '--et-ol-gap-width',
|
|
108
|
+
olMarkerColor: '--et-ol-marker-color',
|
|
109
|
+
olMarkerFontWeight: '--et-ol-marker-font-weight',
|
|
110
|
+
checkboxBoxSize: '--et-checkbox-box-size',
|
|
111
|
+
checkboxGapWidth: '--et-checkbox-gap-width',
|
|
112
|
+
checkboxMarginLeft: '--et-checkbox-margin-left',
|
|
113
|
+
checkboxBoxColor: '--et-checkbox-box-color',
|
|
65
114
|
} as const;
|
|
66
115
|
|
|
67
|
-
export const
|
|
116
|
+
export const ET_MENTION_CSS_VARS = {
|
|
68
117
|
color: (indicator: string) =>
|
|
69
|
-
`--
|
|
118
|
+
`--et-mention-${indicatorToMentionCssKey(indicator)}-color`,
|
|
70
119
|
backgroundColor: (indicator: string) =>
|
|
71
|
-
`--
|
|
120
|
+
`--et-mention-${indicatorToMentionCssKey(indicator)}-background-color`,
|
|
72
121
|
textDecorationLine: (indicator: string) =>
|
|
73
|
-
`--
|
|
122
|
+
`--et-mention-${indicatorToMentionCssKey(indicator)}-text-decoration-line`,
|
|
74
123
|
} as const;
|
|
75
124
|
|
|
76
125
|
function setColorVar(
|
|
@@ -94,8 +143,8 @@ function applyCodeVars(
|
|
|
94
143
|
vars: Record<string, string>,
|
|
95
144
|
code?: HtmlStyle['code']
|
|
96
145
|
): void {
|
|
97
|
-
setColorVar(vars,
|
|
98
|
-
setColorVar(vars,
|
|
146
|
+
setColorVar(vars, ET_CSS_VARS.codeColor, code?.color);
|
|
147
|
+
setColorVar(vars, ET_CSS_VARS.codeBgColor, code?.backgroundColor);
|
|
99
148
|
}
|
|
100
149
|
|
|
101
150
|
function applyHeadingVars(
|
|
@@ -105,9 +154,9 @@ function applyHeadingVars(
|
|
|
105
154
|
for (const level of HEADING_TAGS) {
|
|
106
155
|
const h = htmlStyle?.[level];
|
|
107
156
|
if (h?.fontSize != null)
|
|
108
|
-
vars[`--
|
|
157
|
+
vars[`--et-${level}-font-size`] = `${h.fontSize}px`;
|
|
109
158
|
if (h?.bold != null)
|
|
110
|
-
vars[`--
|
|
159
|
+
vars[`--et-${level}-font-weight`] = h.bold ? 'bold' : 'normal';
|
|
111
160
|
}
|
|
112
161
|
}
|
|
113
162
|
|
|
@@ -115,28 +164,28 @@ function applyBlockquoteVars(
|
|
|
115
164
|
vars: Record<string, string>,
|
|
116
165
|
bq?: HtmlStyle['blockquote']
|
|
117
166
|
): void {
|
|
118
|
-
setColorVar(vars,
|
|
119
|
-
setPxVar(vars,
|
|
120
|
-
setPxVar(vars,
|
|
121
|
-
setColorVar(vars,
|
|
167
|
+
setColorVar(vars, ET_CSS_VARS.blockquoteBorderColor, bq?.borderColor);
|
|
168
|
+
setPxVar(vars, ET_CSS_VARS.blockquoteBorderWidth, bq?.borderWidth);
|
|
169
|
+
setPxVar(vars, ET_CSS_VARS.blockquoteGapWidth, bq?.gapWidth);
|
|
170
|
+
setColorVar(vars, ET_CSS_VARS.blockquoteColor, bq?.color);
|
|
122
171
|
}
|
|
123
172
|
|
|
124
173
|
function applyCodeblockVars(
|
|
125
174
|
vars: Record<string, string>,
|
|
126
175
|
cb?: HtmlStyle['codeblock']
|
|
127
176
|
): void {
|
|
128
|
-
setColorVar(vars,
|
|
129
|
-
setColorVar(vars,
|
|
130
|
-
setPxVar(vars,
|
|
177
|
+
setColorVar(vars, ET_CSS_VARS.codeblockBgColor, cb?.backgroundColor);
|
|
178
|
+
setColorVar(vars, ET_CSS_VARS.codeblockColor, cb?.color);
|
|
179
|
+
setPxVar(vars, ET_CSS_VARS.codeblockBorderRadius, cb?.borderRadius);
|
|
131
180
|
}
|
|
132
181
|
|
|
133
182
|
function applyLinkVars(
|
|
134
183
|
vars: Record<string, string>,
|
|
135
184
|
anchor?: HtmlStyle['a']
|
|
136
185
|
): void {
|
|
137
|
-
setColorVar(vars,
|
|
186
|
+
setColorVar(vars, ET_CSS_VARS.linkColor, anchor?.color);
|
|
138
187
|
if (anchor?.textDecorationLine != null) {
|
|
139
|
-
vars[
|
|
188
|
+
vars[ET_CSS_VARS.linkTextDecorationLine] = anchor.textDecorationLine;
|
|
140
189
|
}
|
|
141
190
|
}
|
|
142
191
|
|
|
@@ -144,21 +193,21 @@ function applyUnorderedListVars(
|
|
|
144
193
|
vars: Record<string, string>,
|
|
145
194
|
ul?: HtmlStyle['ul']
|
|
146
195
|
): void {
|
|
147
|
-
setColorVar(vars,
|
|
148
|
-
setPxVar(vars,
|
|
149
|
-
setPxVar(vars,
|
|
150
|
-
setPxVar(vars,
|
|
196
|
+
setColorVar(vars, ET_CSS_VARS.ulBulletColor, ul?.bulletColor);
|
|
197
|
+
setPxVar(vars, ET_CSS_VARS.ulBulletSize, ul?.bulletSize);
|
|
198
|
+
setPxVar(vars, ET_CSS_VARS.ulMarginLeft, ul?.marginLeft);
|
|
199
|
+
setPxVar(vars, ET_CSS_VARS.ulGapWidth, ul?.gapWidth);
|
|
151
200
|
}
|
|
152
201
|
|
|
153
202
|
function applyOrderedListVars(
|
|
154
203
|
vars: Record<string, string>,
|
|
155
204
|
ol?: HtmlStyle['ol']
|
|
156
205
|
): void {
|
|
157
|
-
setPxVar(vars,
|
|
158
|
-
setPxVar(vars,
|
|
159
|
-
setColorVar(vars,
|
|
206
|
+
setPxVar(vars, ET_CSS_VARS.olMarginLeft, ol?.marginLeft);
|
|
207
|
+
setPxVar(vars, ET_CSS_VARS.olGapWidth, ol?.gapWidth);
|
|
208
|
+
setColorVar(vars, ET_CSS_VARS.olMarkerColor, ol?.markerColor);
|
|
160
209
|
if (ol?.markerFontWeight != null) {
|
|
161
|
-
vars[
|
|
210
|
+
vars[ET_CSS_VARS.olMarkerFontWeight] = String(ol.markerFontWeight);
|
|
162
211
|
}
|
|
163
212
|
}
|
|
164
213
|
|
|
@@ -166,35 +215,36 @@ function applyCheckboxListVars(
|
|
|
166
215
|
vars: Record<string, string>,
|
|
167
216
|
ulCheckbox?: HtmlStyle['ulCheckbox']
|
|
168
217
|
): void {
|
|
169
|
-
setPxVar(vars,
|
|
170
|
-
setPxVar(vars,
|
|
171
|
-
setPxVar(vars,
|
|
172
|
-
setColorVar(vars,
|
|
218
|
+
setPxVar(vars, ET_CSS_VARS.checkboxBoxSize, ulCheckbox?.boxSize);
|
|
219
|
+
setPxVar(vars, ET_CSS_VARS.checkboxGapWidth, ulCheckbox?.gapWidth);
|
|
220
|
+
setPxVar(vars, ET_CSS_VARS.checkboxMarginLeft, ulCheckbox?.marginLeft);
|
|
221
|
+
setColorVar(vars, ET_CSS_VARS.checkboxBoxColor, ulCheckbox?.boxColor);
|
|
173
222
|
}
|
|
174
223
|
|
|
175
224
|
function applyMentionVars(
|
|
176
225
|
vars: Record<string, string>,
|
|
177
226
|
mention: Record<string, MentionStyleProperties>
|
|
178
227
|
): void {
|
|
228
|
+
if (!mention) return;
|
|
229
|
+
|
|
179
230
|
for (const [indicator, mentionStyle] of Object.entries(mention)) {
|
|
231
|
+
setColorVar(vars, ET_MENTION_CSS_VARS.color(indicator), mentionStyle.color);
|
|
180
232
|
setColorVar(
|
|
181
233
|
vars,
|
|
182
|
-
|
|
183
|
-
mentionStyle.color
|
|
184
|
-
);
|
|
185
|
-
setColorVar(
|
|
186
|
-
vars,
|
|
187
|
-
ETI_MENTION_CSS_VARS.backgroundColor(indicator),
|
|
234
|
+
ET_MENTION_CSS_VARS.backgroundColor(indicator),
|
|
188
235
|
mentionStyle.backgroundColor
|
|
189
236
|
);
|
|
190
237
|
if (mentionStyle.textDecorationLine != null) {
|
|
191
|
-
vars[
|
|
238
|
+
vars[ET_MENTION_CSS_VARS.textDecorationLine(indicator)] =
|
|
192
239
|
mentionStyle.textDecorationLine;
|
|
193
240
|
}
|
|
194
241
|
}
|
|
195
242
|
}
|
|
196
243
|
|
|
197
|
-
function expandMentionStylesForIndicatorsIncludeDefault(
|
|
244
|
+
function expandMentionStylesForIndicatorsIncludeDefault(
|
|
245
|
+
htmlStyle: HtmlStyle,
|
|
246
|
+
htmlStyleToMergeWith: HtmlStyle
|
|
247
|
+
) {
|
|
198
248
|
const mentionIndicators = isMentionStyleRecord(htmlStyle?.mention)
|
|
199
249
|
? Object.keys(htmlStyle?.mention)
|
|
200
250
|
: [];
|
|
@@ -204,11 +254,12 @@ function expandMentionStylesForIndicatorsIncludeDefault(htmlStyle?: HtmlStyle) {
|
|
|
204
254
|
|
|
205
255
|
return expandMentionStylesForIndicators(
|
|
206
256
|
htmlStyle?.mention,
|
|
207
|
-
mentionIndicators
|
|
257
|
+
mentionIndicators,
|
|
258
|
+
htmlStyleToMergeWith
|
|
208
259
|
);
|
|
209
260
|
}
|
|
210
261
|
|
|
211
|
-
export function htmlStyleToCSSVariables(htmlStyle
|
|
262
|
+
export function htmlStyleToCSSVariables(htmlStyle: HtmlStyle): CSSProperties {
|
|
212
263
|
const vars: Record<string, string> = {};
|
|
213
264
|
applyCodeVars(vars, htmlStyle?.code);
|
|
214
265
|
applyHeadingVars(vars, htmlStyle);
|
|
@@ -220,7 +271,7 @@ export function htmlStyleToCSSVariables(htmlStyle?: HtmlStyle): CSSProperties {
|
|
|
220
271
|
applyCheckboxListVars(vars, htmlStyle?.ulCheckbox);
|
|
221
272
|
applyMentionVars(
|
|
222
273
|
vars,
|
|
223
|
-
|
|
274
|
+
htmlStyle.mention as Record<string, MentionStyleProperties>
|
|
224
275
|
);
|
|
225
276
|
return vars as CSSProperties;
|
|
226
277
|
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { useEffect, type RefObject } from 'react';
|
|
2
|
+
|
|
3
|
+
/*
|
|
4
|
+
* Flag images that fail to load so CSS can swap in a broken-image placeholder.
|
|
5
|
+
*/
|
|
6
|
+
export const useImageErrorFallback = (
|
|
7
|
+
containerRef: RefObject<HTMLElement | null>
|
|
8
|
+
) => {
|
|
9
|
+
// listen for errors
|
|
10
|
+
useEffect(() => {
|
|
11
|
+
const container = containerRef.current;
|
|
12
|
+
if (!container) return;
|
|
13
|
+
|
|
14
|
+
const handleImageError = (e: Event) => {
|
|
15
|
+
const target = e.target as HTMLElement;
|
|
16
|
+
if (target && target.tagName && target.tagName.toLowerCase() === 'img') {
|
|
17
|
+
target.classList.add('error');
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
container.addEventListener('error', handleImageError, true);
|
|
22
|
+
|
|
23
|
+
// handle <img> elements that emitted an error event before we could set up a listener
|
|
24
|
+
const images =
|
|
25
|
+
container.querySelectorAll<HTMLImageElement>('img:not(.error)');
|
|
26
|
+
|
|
27
|
+
images.forEach((img) => {
|
|
28
|
+
if (img.complete && img.naturalHeight === 0) {
|
|
29
|
+
img.classList.add('error');
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
return () => {
|
|
34
|
+
container.removeEventListener('error', handleImageError, true);
|
|
35
|
+
};
|
|
36
|
+
}, [containerRef]);
|
|
37
|
+
};
|
|
@@ -2,7 +2,7 @@ import { type Editor } from '@tiptap/react';
|
|
|
2
2
|
import type { OnChangeHtmlEvent } from '../types';
|
|
3
3
|
import type { NativeSyntheticEvent } from 'react-native';
|
|
4
4
|
import { useOnEditorChange } from './useOnEditorChange';
|
|
5
|
-
import { normalizeHtmlFromTiptap } from './tiptapHtmlNormalizer';
|
|
5
|
+
import { normalizeHtmlFromTiptap } from './normalization/tiptapHtmlNormalizer';
|
|
6
6
|
|
|
7
7
|
export const useOnChangeHtml = (
|
|
8
8
|
editor: Editor,
|
|
@@ -4,6 +4,7 @@ import type { OnChangeStateEvent } from '../types';
|
|
|
4
4
|
import type { NativeSyntheticEvent } from 'react-native';
|
|
5
5
|
import { adaptWebToNativeEvent } from './adaptWebToNativeEvent';
|
|
6
6
|
import {
|
|
7
|
+
getCurrentAlignment,
|
|
7
8
|
isAnyParagraphFormatActive,
|
|
8
9
|
isFormatBlocked,
|
|
9
10
|
} from './formats/formatRules';
|
|
@@ -97,21 +98,22 @@ function buildState(
|
|
|
97
98
|
isConflicting: editor.isActive('link'),
|
|
98
99
|
isBlocking: isFormatBlocked('image', editor, htmlStyle),
|
|
99
100
|
},
|
|
100
|
-
alignment: '
|
|
101
|
+
alignment: getCurrentAlignment(editor) ?? 'auto',
|
|
101
102
|
};
|
|
102
103
|
}
|
|
103
104
|
|
|
104
105
|
function hashState(state: OnChangeStateEvent): string {
|
|
105
106
|
return Object.values(state)
|
|
106
|
-
.map((formatState) =>
|
|
107
|
-
|
|
107
|
+
.map((formatState) => {
|
|
108
|
+
if (typeof formatState === 'string') return formatState;
|
|
109
|
+
return String(
|
|
108
110
|
getFormatHash(
|
|
109
111
|
formatState.isActive,
|
|
110
112
|
formatState.isConflicting,
|
|
111
113
|
formatState.isBlocking
|
|
112
114
|
)
|
|
113
|
-
)
|
|
114
|
-
)
|
|
115
|
+
);
|
|
116
|
+
})
|
|
115
117
|
.join('');
|
|
116
118
|
}
|
|
117
119
|
|
|
@@ -1,82 +1,70 @@
|
|
|
1
|
-
import { useEffect
|
|
1
|
+
import { useEffect } from 'react';
|
|
2
2
|
import { type Editor } from '@tiptap/react';
|
|
3
3
|
import { getMarkRange, getMarksBetween } from '@tiptap/core';
|
|
4
|
-
import type {
|
|
4
|
+
import type { EditorState } from '@tiptap/pm/state';
|
|
5
|
+
import type { MarkType } from '@tiptap/pm/model';
|
|
6
|
+
import { emitLinkDetected, type LinkEmitterRef } from './emitLinkDetected';
|
|
5
7
|
import { tiptapPosToNativePos } from './positionMapping';
|
|
6
8
|
|
|
9
|
+
function findLinkRangeAt(
|
|
10
|
+
state: EditorState,
|
|
11
|
+
linkType: MarkType
|
|
12
|
+
): { from: number; to: number } | null {
|
|
13
|
+
const $pos = state.selection.$from;
|
|
14
|
+
const direct = getMarkRange($pos, linkType);
|
|
15
|
+
if (direct) return direct;
|
|
16
|
+
if ($pos.pos > 0) {
|
|
17
|
+
const $before = state.doc.resolve($pos.pos - 1);
|
|
18
|
+
const before = getMarkRange($before, linkType);
|
|
19
|
+
if (before && before.to === $pos.pos) return before;
|
|
20
|
+
}
|
|
21
|
+
return null;
|
|
22
|
+
}
|
|
23
|
+
|
|
7
24
|
export const useOnLinkDetected = (
|
|
8
25
|
editor: Editor | null,
|
|
9
|
-
|
|
26
|
+
ref: LinkEmitterRef
|
|
10
27
|
) => {
|
|
11
|
-
const lastEmittedRef = useRef<OnLinkDetected | null>(null);
|
|
12
|
-
const wasInLinkRef = useRef(false);
|
|
13
|
-
|
|
14
28
|
useEffect(() => {
|
|
15
|
-
if (!editor
|
|
29
|
+
if (!editor) return;
|
|
16
30
|
|
|
17
31
|
const handleUpdate = () => {
|
|
18
32
|
const { state } = editor;
|
|
19
33
|
const linkType = state.schema.marks.link;
|
|
20
34
|
if (!linkType) return;
|
|
21
35
|
|
|
22
|
-
const
|
|
23
|
-
const range = getMarkRange($pos, linkType);
|
|
36
|
+
const range = findLinkRangeAt(state, linkType);
|
|
24
37
|
|
|
25
38
|
if (!range) {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
}
|
|
35
|
-
lastEmittedRef.current = null;
|
|
39
|
+
const last = ref.current.lastEmitted;
|
|
40
|
+
if (!last || last.url === '') return;
|
|
41
|
+
emitLinkDetected(ref.current, {
|
|
42
|
+
text: '',
|
|
43
|
+
url: '',
|
|
44
|
+
start: 0,
|
|
45
|
+
end: 0,
|
|
46
|
+
});
|
|
36
47
|
return;
|
|
37
48
|
}
|
|
38
49
|
|
|
39
50
|
const linkMark = getMarksBetween(range.from, range.to, state.doc).find(
|
|
40
51
|
(entry) => entry.mark.type === linkType
|
|
41
52
|
)?.mark;
|
|
53
|
+
if (!linkMark) return;
|
|
42
54
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
wasInLinkRef.current = true;
|
|
50
|
-
|
|
51
|
-
const { from, to } = range;
|
|
52
|
-
const url = (linkMark.attrs.href as string | undefined) ?? '';
|
|
53
|
-
const text = state.doc.textBetween(from, to, '\n');
|
|
54
|
-
const start = tiptapPosToNativePos(state.doc, from);
|
|
55
|
-
const end = tiptapPosToNativePos(state.doc, to);
|
|
56
|
-
|
|
57
|
-
const next: OnLinkDetected = { text, url, start, end };
|
|
58
|
-
const prev = lastEmittedRef.current;
|
|
59
|
-
|
|
60
|
-
if (
|
|
61
|
-
prev !== null &&
|
|
62
|
-
prev.text === next.text &&
|
|
63
|
-
prev.url === next.url &&
|
|
64
|
-
prev.start === next.start &&
|
|
65
|
-
prev.end === next.end
|
|
66
|
-
) {
|
|
67
|
-
return;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
lastEmittedRef.current = next;
|
|
71
|
-
onLinkDetected(next);
|
|
55
|
+
emitLinkDetected(ref.current, {
|
|
56
|
+
text: state.doc.textBetween(range.from, range.to, '\n'),
|
|
57
|
+
url: (linkMark.attrs.href as string | undefined) ?? '',
|
|
58
|
+
start: tiptapPosToNativePos(state.doc, range.from),
|
|
59
|
+
end: tiptapPosToNativePos(state.doc, range.to),
|
|
60
|
+
});
|
|
72
61
|
};
|
|
73
62
|
|
|
74
63
|
handleUpdate();
|
|
75
64
|
editor.on('transaction', handleUpdate);
|
|
76
65
|
|
|
77
66
|
return () => {
|
|
78
|
-
wasInLinkRef.current = false;
|
|
79
67
|
editor.off('transaction', handleUpdate);
|
|
80
68
|
};
|
|
81
|
-
}, [editor,
|
|
69
|
+
}, [editor, ref]);
|
|
82
70
|
};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { useEffect } from 'react';
|
|
2
|
+
|
|
3
|
+
export function usePressInteractions(
|
|
4
|
+
containerRef: React.RefObject<HTMLDivElement | null>
|
|
5
|
+
) {
|
|
6
|
+
useEffect(() => {
|
|
7
|
+
const container = containerRef.current;
|
|
8
|
+
if (!container) return;
|
|
9
|
+
|
|
10
|
+
const handleClick = (e: MouseEvent) => {
|
|
11
|
+
const target = e.target as HTMLElement;
|
|
12
|
+
|
|
13
|
+
const anchor = target.closest('a');
|
|
14
|
+
if (anchor && container.contains(anchor)) {
|
|
15
|
+
e.preventDefault();
|
|
16
|
+
}
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
container.addEventListener('click', handleClick);
|
|
20
|
+
return () => container.removeEventListener('click', handleClick);
|
|
21
|
+
}, [containerRef]);
|
|
22
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { useEffect, useRef, type RefObject } from 'react';
|
|
2
|
+
|
|
3
|
+
//TODO: When upgrading to React 19.2 migrate to useEffectEvent instead
|
|
4
|
+
export const useStableRef = <T>(value: T): RefObject<T> => {
|
|
5
|
+
const ref = useRef<T>(value);
|
|
6
|
+
|
|
7
|
+
useEffect(() => {
|
|
8
|
+
ref.current = value;
|
|
9
|
+
}, [value]);
|
|
10
|
+
|
|
11
|
+
return ref;
|
|
12
|
+
};
|