248 lines
9.2 KiB
JavaScript
248 lines
9.2 KiB
JavaScript
import React from 'react';
|
|
import Konva from 'konva/lib/Core.js';
|
|
import { applyNodeProps, updatePicture, EVENTS_NAMESPACE, } from './makeUpdates.js';
|
|
export { unstable_now as now, unstable_IdlePriority as idlePriority, unstable_runWithPriority as run, } from 'scheduler';
|
|
import {
|
|
// NoEventPriority,
|
|
DefaultEventPriority, DiscreteEventPriority, } from 'react-reconciler/constants.js';
|
|
const NO_CONTEXT = {};
|
|
// for react-spring capability
|
|
Konva.Node.prototype._applyProps = applyNodeProps;
|
|
// let currentUpdatePriority: number = NoEventPriority;
|
|
let currentUpdatePriority = DefaultEventPriority;
|
|
export function appendInitialChild(parentInstance, child) {
|
|
if (typeof child === 'string') {
|
|
// Noop for string children of Text (eg <Text>foo</Text>)
|
|
console.error(`Do not use plain text as child of Konva.Node. You are using text: ${child}`);
|
|
return;
|
|
}
|
|
parentInstance.add(child);
|
|
updatePicture(parentInstance);
|
|
}
|
|
export function createInstance(type, props, internalInstanceHandle) {
|
|
let NodeClass = Konva[type];
|
|
if (!NodeClass) {
|
|
console.error(`Konva has no node with the type ${type}. Group will be used instead. If you use minimal version of react-konva, just import required nodes into Konva: "import "konva/lib/shapes/${type}" If you want to render DOM elements as part of canvas tree take a look into this demo: https://konvajs.github.io/docs/react/DOM_Portal.html`);
|
|
NodeClass = Konva.Group;
|
|
}
|
|
// we need to split props into events and non events
|
|
// we we can pass non events into constructor directly
|
|
// that way the performance should be better
|
|
// we we apply change "applyNodeProps"
|
|
// then it will trigger change events on first run
|
|
// but we don't need them!
|
|
const propsWithoutEvents = {};
|
|
const propsWithOnlyEvents = {};
|
|
for (var key in props) {
|
|
// ignore ref
|
|
if (key === 'ref') {
|
|
continue;
|
|
}
|
|
var isEvent = key.slice(0, 2) === 'on';
|
|
if (isEvent) {
|
|
propsWithOnlyEvents[key] = props[key];
|
|
}
|
|
else {
|
|
propsWithoutEvents[key] = props[key];
|
|
}
|
|
}
|
|
const instance = new NodeClass(propsWithoutEvents);
|
|
applyNodeProps(instance, propsWithOnlyEvents);
|
|
return instance;
|
|
}
|
|
export function createTextInstance(text, rootContainerInstance, internalInstanceHandle) {
|
|
console.error(`Text components are not supported for now in ReactKonva. Your text is: "${text}"`);
|
|
}
|
|
export function finalizeInitialChildren(domElement, type, props) {
|
|
return false;
|
|
}
|
|
export function getPublicInstance(instance) {
|
|
return instance;
|
|
}
|
|
// Fragments group Konva children but have no DOM instance or Fragment methods.
|
|
// This matches React's noop renderer.
|
|
export function createFragmentInstance() {
|
|
return null;
|
|
}
|
|
export function updateFragmentInstanceFiber() { }
|
|
export function commitNewChildToFragmentInstance() { }
|
|
export function deleteChildFromFragmentInstance() { }
|
|
let finishUpdateBatch;
|
|
export function prepareForCommit() {
|
|
// Older supported Konva versions do not expose commit batching.
|
|
finishUpdateBatch = Konva.beginUpdateBatch?.();
|
|
return null;
|
|
}
|
|
export function preparePortalMount() {
|
|
return null;
|
|
}
|
|
export function resetAfterCommit() {
|
|
const finish = finishUpdateBatch;
|
|
finishUpdateBatch = undefined;
|
|
// React layout effects must see the final Transformer geometry.
|
|
finish?.();
|
|
}
|
|
export function resetTextContent(domElement) {
|
|
// Noop
|
|
}
|
|
export function getRootHostContext() {
|
|
return NO_CONTEXT;
|
|
}
|
|
export function getChildHostContext() {
|
|
return NO_CONTEXT;
|
|
}
|
|
export const scheduleTimeout = setTimeout;
|
|
export const cancelTimeout = clearTimeout;
|
|
export const supportsMicrotasks = true;
|
|
// Async — fixes the mobx-react-lite snapshot race. Stage's useLayoutEffect
|
|
// then explicitly calls `flushSyncWork()` to keep parent useLayoutEffect able
|
|
// to read Konva nodes added by subscribing children (see ReactKonvaCore.tsx).
|
|
export { scheduleMicrotask } from './EventBatch.js';
|
|
export const noTimeout = -1;
|
|
// export const schedulePassiveEffects = scheduleDeferredCallback;
|
|
// export const cancelPassiveEffects = cancelDeferredCallback;
|
|
export function shouldSetTextContent(type, props) {
|
|
return false;
|
|
}
|
|
// The Konva renderer is secondary to the React DOM renderer.
|
|
export const isPrimaryRenderer = false;
|
|
export const warnsIfNotActing = false;
|
|
export const supportsMutation = true;
|
|
export const supportsPersistence = false;
|
|
export const supportsHydration = false;
|
|
export function appendChild(parentInstance, child) {
|
|
if (child.parent === parentInstance) {
|
|
child.moveToTop();
|
|
}
|
|
else {
|
|
parentInstance.add(child);
|
|
}
|
|
updatePicture(parentInstance);
|
|
}
|
|
export const appendChildToContainer = appendChild;
|
|
export function insertBefore(parentInstance, child, beforeChild) {
|
|
// child._remove() will not stop dragging
|
|
// but child.remove() will stop it, but we don't need it
|
|
// removing will reset zIndexes
|
|
child._remove();
|
|
parentInstance.add(child);
|
|
child.setZIndex(beforeChild.getZIndex());
|
|
updatePicture(parentInstance);
|
|
}
|
|
export const insertInContainerBefore = insertBefore;
|
|
export function removeChild(parentInstance, child) {
|
|
child.destroy();
|
|
child.off(EVENTS_NAMESPACE);
|
|
updatePicture(parentInstance);
|
|
}
|
|
export const removeChildFromContainer = removeChild;
|
|
export function commitTextUpdate(textInstance, oldText, newText) {
|
|
console.error(`Text components are not yet supported in ReactKonva. You text is: "${newText}"`);
|
|
}
|
|
export function commitMount(instance, type, newProps) {
|
|
// Noop
|
|
}
|
|
export function commitUpdate(instance, type, oldProps, newProps) {
|
|
applyNodeProps(instance, newProps, oldProps);
|
|
}
|
|
export function hideInstance(instance) {
|
|
instance.hide();
|
|
updatePicture(instance);
|
|
}
|
|
export function hideTextInstance(textInstance) {
|
|
// Noop
|
|
}
|
|
export function unhideInstance(instance, props) {
|
|
if (props.visible == null || props.visible) {
|
|
instance.show();
|
|
updatePicture(instance);
|
|
}
|
|
}
|
|
export function unhideTextInstance(textInstance, text) {
|
|
// Noop
|
|
}
|
|
export function clearContainer(container) {
|
|
// Noop
|
|
}
|
|
export function detachDeletedInstance(instance) {
|
|
// React visits every deleted host node here, including descendants of a
|
|
// removed container. Konva.destroy() alone does not release their listeners.
|
|
instance.off(EVENTS_NAMESPACE);
|
|
}
|
|
export function getInstanceFromNode() {
|
|
return null;
|
|
}
|
|
export function bindToConsole(methodName, args) {
|
|
return console[methodName].bind(console, ...args);
|
|
}
|
|
export function beforeActiveInstanceBlur() { }
|
|
export function afterActiveInstanceBlur() { }
|
|
export function prepareScopeUpdate() { }
|
|
export function getInstanceFromScope() {
|
|
return null;
|
|
}
|
|
export function setCurrentUpdatePriority(newPriority) {
|
|
currentUpdatePriority = newPriority;
|
|
}
|
|
export function getCurrentUpdatePriority() {
|
|
return currentUpdatePriority;
|
|
}
|
|
// Load-bearing: pins secondary commits to React's sync lane so they land
|
|
// before the scheduler yields. Required for parent useLayoutEffect to read
|
|
// Konva nodes added by subscribing children. Changing to Default/Continuous/
|
|
// Idle breaks ~18 tests in test/01-mounting and test/16-scheduling-invariants.
|
|
export function resolveUpdatePriority() {
|
|
return DiscreteEventPriority;
|
|
}
|
|
export function shouldAttemptEagerTransition() {
|
|
return false;
|
|
}
|
|
export function trackSchedulerEvent() { }
|
|
export function resolveEventType() {
|
|
return null;
|
|
}
|
|
export function resolveEventTimeStamp() {
|
|
return -1.1;
|
|
}
|
|
export function requestPostPaintCallback() { }
|
|
export function maySuspendCommit() {
|
|
// React 19.3 calls this during render only for nodes inside ViewTransition.
|
|
// Reject before commit, where a view-transition error can escape boundaries.
|
|
throw new Error('ViewTransition is not supported inside a Stage. ' +
|
|
'Place ViewTransition around Stage to animate its DOM container.');
|
|
}
|
|
export const createViewTransitionInstance = maySuspendCommit;
|
|
export const maySuspendCommitOnUpdate = maySuspendCommit;
|
|
export const maySuspendCommitInSyncRender = maySuspendCommit;
|
|
// Empty ViewTransition boundaries can reach commit without any Konva nodes.
|
|
// Finish those commits without animation so ref errors can reach a boundary.
|
|
export function startViewTransition(suspendedState, rootContainer, transitionTypes, mutationCallback, layoutCallback, afterMutationCallback, spawnedWorkCallback, passiveCallback, errorCallback, blockedCallback, finishedAnimation) {
|
|
mutationCallback();
|
|
layoutCallback();
|
|
finishedAnimation?.();
|
|
spawnedWorkCallback();
|
|
return null;
|
|
}
|
|
export function preloadInstance() {
|
|
return true;
|
|
}
|
|
export function startSuspendingCommit() { }
|
|
export function suspendInstance() { }
|
|
// React also calls this for Suspense retries without a ViewTransition component.
|
|
export function suspendOnActiveViewTransition() { }
|
|
export function waitForCommitToBeReady() {
|
|
return null;
|
|
}
|
|
export function getSuspendedCommitReason() {
|
|
return null;
|
|
}
|
|
// Stage provides the surrounding DOM form status. Standalone roots stay idle.
|
|
export const NotPendingTransition = Object.freeze({
|
|
pending: false,
|
|
data: null,
|
|
method: null,
|
|
action: null,
|
|
});
|
|
export const HostTransitionContext = /* @__PURE__ */ React.createContext(NotPendingTransition);
|
|
export function resetFormInstance() { }
|