Started tasks to migrate runtime to React 19. Added phase 3 projects

This commit is contained in:
Richard Osborne
2025-12-13 22:37:44 +01:00
parent 8dd4f395c0
commit 1477a29ff7
55 changed files with 49205 additions and 281 deletions

View File

@@ -73,18 +73,18 @@ export class Drag extends React.Component<DragProps, State> {
setDragValues({ x, y, deltaX: 0, deltaY: 0 }, this.props);
}
UNSAFE_componentWillReceiveProps(nextProps: DragProps) {
componentDidUpdate(prevProps: DragProps) {
const props = this.props;
if (props.inputPositionX !== nextProps.inputPositionX) {
this.setState({ x: nextProps.inputPositionX });
props.positionX && props.positionX(nextProps.inputPositionX);
props.deltaX && props.deltaX(nextProps.inputPositionX - props.inputPositionX);
if (prevProps.inputPositionX !== props.inputPositionX) {
this.setState({ x: props.inputPositionX });
props.positionX && props.positionX(props.inputPositionX);
props.deltaX && props.deltaX(props.inputPositionX - prevProps.inputPositionX);
}
if (props.inputPositionY !== nextProps.inputPositionY) {
this.setState({ y: nextProps.inputPositionY });
props.positionY && props.positionY(nextProps.inputPositionY);
props.deltaY && props.deltaY(nextProps.inputPositionY - props.inputPositionY);
if (prevProps.inputPositionY !== props.inputPositionY) {
this.setState({ y: props.inputPositionY });
props.positionY && props.positionY(props.inputPositionY);
props.deltaY && props.deltaY(props.inputPositionY - prevProps.inputPositionY);
}
}

View File

@@ -68,19 +68,6 @@ export class Group extends React.Component<GroupProps> {
this.props.noodlNode.context.setNodeFocused(this.props.noodlNode, false);
}
componentDidUpdate() {
if (this.scrollNeedsToInit) {
this.setupIScroll();
this.scrollNeedsToInit = false;
}
if (this.iScroll) {
setTimeout(() => {
this.iScroll && this.iScroll.refresh();
}, 0);
}
}
scrollToIndex(index, duration) {
if (this.iScroll) {
const child = this.scrollRef.current.children[0].children[index] as HTMLElement;
@@ -171,19 +158,19 @@ export class Group extends React.Component<GroupProps> {
}
}
UNSAFE_componentWillReceiveProps(nextProps: GroupProps) {
componentDidUpdate(prevProps: GroupProps) {
const scrollHasUpdated =
this.props.scrollSnapEnabled !== nextProps.scrollSnapEnabled ||
this.props.onScrollPositionChanged !== nextProps.onScrollPositionChanged ||
this.props.onScrollStart !== nextProps.onScrollStart ||
this.props.onScrollEnd !== nextProps.onScrollEnd ||
this.props.showScrollbar !== nextProps.showScrollbar ||
this.props.scrollEnabled !== nextProps.scrollEnabled ||
this.props.nativeScroll !== nextProps.nativeScroll ||
this.props.scrollSnapToEveryItem !== nextProps.scrollSnapToEveryItem ||
this.props.layout !== nextProps.layout ||
this.props.flexWrap !== nextProps.flexWrap ||
this.props.scrollBounceEnabled !== nextProps.scrollBounceEnabled;
prevProps.scrollSnapEnabled !== this.props.scrollSnapEnabled ||
prevProps.onScrollPositionChanged !== this.props.onScrollPositionChanged ||
prevProps.onScrollStart !== this.props.onScrollStart ||
prevProps.onScrollEnd !== this.props.onScrollEnd ||
prevProps.showScrollbar !== this.props.showScrollbar ||
prevProps.scrollEnabled !== this.props.scrollEnabled ||
prevProps.nativeScroll !== this.props.nativeScroll ||
prevProps.scrollSnapToEveryItem !== this.props.scrollSnapToEveryItem ||
prevProps.layout !== this.props.layout ||
prevProps.flexWrap !== this.props.flexWrap ||
prevProps.scrollBounceEnabled !== this.props.scrollBounceEnabled;
if (scrollHasUpdated) {
if (this.iScroll) {
@@ -191,7 +178,19 @@ export class Group extends React.Component<GroupProps> {
this.iScroll = undefined;
}
this.scrollNeedsToInit = nextProps.scrollEnabled && !nextProps.nativeScroll;
this.scrollNeedsToInit = this.props.scrollEnabled && !this.props.nativeScroll;
}
// Handle scroll initialization (moved from the old componentDidUpdate)
if (this.scrollNeedsToInit) {
this.setupIScroll();
this.scrollNeedsToInit = false;
}
if (this.iScroll) {
setTimeout(() => {
this.iScroll && this.iScroll.refresh();
}, 0);
}
}

View File

@@ -1,7 +1,6 @@
'use strict';
import React from 'react';
import ReactDOM from 'react-dom';
import DOMBoundingBoxObserver from './dom-boundingbox-oberver';
import Layout from './layout';
@@ -127,6 +126,14 @@ class NoodlReactComponent extends React.Component {
const props = {
ref: (ref) => {
noodlNode.innerReactComponentRef = ref;
// React 19: Store DOM element reference directly for getDOMElement()
// This avoids using the deprecated findDOMNode
if (ref && ref instanceof Element) {
noodlNode._domElement = ref;
} else if (ref && typeof ref === 'object' && ref.nodeType === 1) {
// ref is already a DOM element
noodlNode._domElement = ref;
}
},
style: finalStyle,
//the noodl props coming from the node
@@ -659,7 +666,15 @@ function createNodeFromReactComponent(def) {
noodlNode: this,
ref: (ref) => {
this.reactComponentRef = ref;
this.boundingBoxObserver.setTarget(ReactDOM.findDOMNode(ref));
// React 19: Use stored DOM element instead of findDOMNode
// The _domElement is set by the ref callback in NoodlReactComponent
// We need to wait a frame for the inner ref to be set
if (ref) {
requestAnimationFrame(() => {
const domElement = this._domElement || this.getDOMElement();
this.boundingBoxObserver.setTarget(domElement);
});
}
}
});
},
@@ -800,10 +815,28 @@ function createNodeFromReactComponent(def) {
return this.reactComponentRef;
},
getDOMElement() {
// React 19: Use stored DOM element reference instead of findDOMNode
// The _domElement is set by the ref callback in NoodlReactComponent
if (this._domElement) {
return this._domElement;
}
// Fallback: try to get DOM element from innerReactComponentRef
const innerRef = this.innerReactComponentRef;
if (innerRef && innerRef instanceof Element) {
return innerRef;
}
// Legacy fallback for backwards compatibility (will be removed)
const ref = this.getRef();
if (!ref) return;
return ReactDOM.findDOMNode(ref);
if (!ref) return null;
// If ref is a DOM element, return it directly
if (ref instanceof Element) {
return ref;
}
return null;
},
getVisualParentNode() {
if (this.parent) return this.parent;