react-native-enriched-markdown-scaffold 0.7.4-scaffold.3 → 0.7.4-scaffold.4

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.
@@ -57,6 +57,13 @@ class EnrichedMarkdownTextInputManager :
57
57
  stateWrapper: StateWrapper?,
58
58
  ): Any? {
59
59
  view.stateWrapper = stateWrapper
60
+ // Fabric applies props before it hands over the state wrapper, so every layout
61
+ // invalidation raised during the mount transaction was dropped. Replay it now that we can
62
+ // actually push state — otherwise the shadow node keeps the initialMeasure() estimate,
63
+ // which ignores math chips, until the first keystroke.
64
+ if (stateWrapper != null) {
65
+ view.layoutManager.flushPendingInvalidation()
66
+ }
60
67
  return super.updateState(view, props, stateWrapper)
61
68
  }
62
69
 
@@ -69,6 +76,11 @@ class EnrichedMarkdownTextInputManager :
69
76
  view.dismissActiveMention()
70
77
  super.onDropViewInstance(view)
71
78
  view.layoutManager.release()
79
+ // Unreachable while view recycling is off — it needs a `setupViewRecycling()` call from this
80
+ // constructor *and* ReactNativeFeatureFlags.enableViewRecycling(). Kept because the flush
81
+ // above turns a recycled view into a view that pushes state at mount: without this, it would
82
+ // push into the shadow node it was dropped from.
83
+ view.stateWrapper = null
72
84
  }
73
85
 
74
86
  override fun measure(
@@ -708,8 +708,16 @@ class EnrichedMarkdownTextInputView(
708
708
  }
709
709
  invalidate()
710
710
  requestLayout()
711
+ // Chips only reach the text here when `defaultValue` landed before `markdownStyle`
712
+ // (@ReactProp order is undefined). requestLayout() cannot change a height Fabric owns —
713
+ // the shadow tree has to re-measure text that now carries the spans.
714
+ layoutManager.invalidateLayout()
711
715
  } else if (mathStyleChanged) {
712
716
  refreshAllMathChips()
717
+ // A math font size / padding change resizes every chip, so the measured height moves.
718
+ // Colour-only changes end up here too; store() then measures the same size and skips
719
+ // the state update.
720
+ layoutManager.invalidateLayout()
713
721
  }
714
722
  return changed
715
723
  }
@@ -8,21 +8,49 @@ class InputLayoutManager(
8
8
  ) {
9
9
  private var forceHeightRecalculationCounter = 0
10
10
 
11
+ /**
12
+ * An invalidation that arrived before `stateWrapper` existed. Fabric applies every prop
13
+ * (and runs `onAfterUpdateTransaction`) inside `ViewManager.updateProperties`, which runs
14
+ * *before* `updateState` assigns the wrapper — so the whole mount transaction invalidates
15
+ * into the void. Without this flag the measurement store stays empty and Yoga keeps the
16
+ * `initialMeasure()` approximation until the next text/prop change.
17
+ */
18
+ private var pending = false
19
+
11
20
  fun invalidateLayout() {
12
- if (view.stateWrapper == null) return
21
+ val stateWrapper = view.stateWrapper
22
+ if (stateWrapper == null) {
23
+ pending = true
24
+ return
25
+ }
26
+ pending = false
13
27
 
14
28
  val text = view.text
15
29
  val paint = view.paint
16
30
 
31
+ // First call for this view measures against cachedWidth = 0 and stores a throwaway size;
32
+ // Yoga immediately re-measures through getMeasureById() with the real width and overwrites
33
+ // it. The state update below is what makes that second pass happen.
17
34
  val needUpdate = InputMeasurementStore.store(view.id, text, paint)
18
35
  if (!needUpdate) return
19
36
 
20
37
  val state = Arguments.createMap()
21
38
  state.putInt("forceHeightRecalculationCounter", forceHeightRecalculationCounter++)
22
- view.stateWrapper?.updateState(state)
39
+ stateWrapper.updateState(state)
40
+ }
41
+
42
+ /**
43
+ * Replays an invalidation that was dropped while `stateWrapper` was null. Called once the
44
+ * wrapper is assigned, i.e. after every prop of the mount transaction has been applied — so
45
+ * the text carries its math chips and the paint carries the resolved typeface/size.
46
+ */
47
+ fun flushPendingInvalidation() {
48
+ if (!pending) return
49
+ invalidateLayout()
23
50
  }
24
51
 
25
52
  fun release() {
53
+ pending = false
26
54
  InputMeasurementStore.release(view.id)
27
55
  }
28
56
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-enriched-markdown-scaffold",
3
- "version": "0.7.4-scaffold.3",
3
+ "version": "0.7.4-scaffold.4",
4
4
  "description": "Markdown Text component for React Native",
5
5
  "main": "./lib/module/index",
6
6
  "module": "./lib/module/index",