@plurid/plurid-react
Version:
React implementation of Plurid to explore the web in three dimensions
1,320 lines (1,197 loc) • 252 kB
JavaScript
import { defaultConfiguration, TRANSFORM_MODES, LAYOUT_TYPES, FOCUS_ANCHOR_SUFFIX, TRANSLATION_STEP, ROTATION_STEP, SCALE_STEP, SCALE_UPPER_LIMIT, SCALE_LOWER_LIMIT, PLURID_DEFAULT_ANIMATED_TRANSFORM_TIMEOUT, PLURID_PUBSUB_TOPIC, directions, PLURID_ENTITY_PLANE_BRIDGE, PLURID_ENTITY_PLANE_CONTROLS, PLURID_ENTITY_PLANE_CONTENT, PLURID_ENTITY_PLANE, PLURID_ENTITY_ROOT, PLURID_ENTITY_ROOTS, PLURID_ENTITY_SPACE, SIZES, PLURID_ENTITY_TRANSFORM_ORIGIN, internationalization, TRANSFORM_TOUCHES, layoutNames, defaultShortcuts, shortcutsNames, TOOLBAR_DRAWERS, PLURID_ENTITY_TOOLBAR, PLURID_ENTITY_VIEWCUBE, PLURID_DEFAULT_RESIZE_DEBOUNCE_TIME, PLURID_ENTITY_VIEW, PLURID_DEFAULT_PREVENT_OVERSCROLL_TIMEOUT, PLURID_ROUTE_DEFAULT_PATH_VALUE, PLURID_ROUTE_DEFAULT_PATH, PLURID_ROUTE_DEFAULT_SPACE_VALUE, PLURID_ROUTE_DEFAULT_SPACE, PLURID_ROUTE_DEFAULT_UNIVERSE_VALUE, PLURID_ROUTE_DEFAULT_UNIVERSE, PLURID_ROUTE_DEFAULT_CLUSTER_VALUE, PLURID_ROUTE_DEFAULT_CLUSTER, PLURID_ROUTE_SEPARATOR, PLURID_ENTITY_MULTISPACE, PLURID_ROUTER_LOCATION_CHANGED, PLURID_ROUTER_STORAGE, PLURID_ROUTER_LOCATION_STORED, PLURID_ENTITY_LINK, PLURID_DEFAULT_CONFIGURATION_LINK_PREVIEW_FADE_IN, PLURID_DEFAULT_CONFIGURATION_LINK_PREVIEW_FADE_OUT, PLURID_DEFAULT_CONFIGURATION_LINK_SUFFIX, PLURID_ENTITY_APPLICATION_CONFIGURATOR, PLURID_ENTITY_PLANE_CONFIGURATOR } from "@plurid/plurid-data";
export { PLURID_PUBSUB_TOPIC, PLURID_ROUTER_LOCATION_CHANGED, PLURID_ROUTER_LOCATION_STORED, SIZES, LAYOUT_TYPES as SPACE_LAYOUT, TRANSFORM_MODES, TRANSFORM_TOUCHES } from "@plurid/plurid-data";
import { planes, routing, interaction, general as general$2, space as space$2, cleanTemplate, internatiolate, state, utilities, pluridRouterNavigate } from "@plurid/plurid-engine";
export { pluridRouterNavigate } from "@plurid/plurid-engine";
import PluridPubSub from "@plurid/plurid-pubsub";
export { default as PluridPubSub } from "@plurid/plurid-pubsub";
import React, { useState, useRef, useContext, useEffect, useMemo, useCallback, Component } from "react";
import { connect, Provider } from "react-redux";
import { createSlice, combineReducers, configureStore } from "@reduxjs/toolkit";
import { mathematics, objects, dom, meta, uuid, storage } from "@plurid/plurid-functions";
import themes$2, { plurid, decomposeColor } from "@plurid/plurid-themes";
import styled, { createGlobalStyle, css, keyframes } from "styled-components";
import { useDebouncedCallback, useMounted, usePortal } from "@plurid/plurid-functions-react";
import { PluridIconReset, PluridIconRectangle, PluridIconArrowLeft, PluridIconFrame, PluridIconDelete, PluridIconRotate, PluridIconScale, PluridIconTranslate, PluridIconFirstPerson, PluridIconMore, PluridIconGlobal } from "@plurid/plurid-icons-react";
import { universal } from "@plurid/plurid-ui-components-react";
import { createPortal } from "react-dom";
import fetch from "cross-fetch";
import { ElementQLClient } from "@plurid/elementql-client-react";
const initialState$5 = Object.assign({}, defaultConfiguration);
const configuration = createSlice({
name: "configuration",
initialState: initialState$5,
reducers: {
setConfiguration: (_state, action) => Object.assign({}, action.payload),
setConfigurationMicro: state => {
state.elements.toolbar.show = false;
state.elements.plane.controls.show = false;
state.elements.viewcube.show = false;
},
setConfigurationPlaneControls: (state, action) => {
state.elements.plane.controls.show = action.payload;
},
setConfigurationPlaneOpacity: (state, action) => {
state.elements.plane.opacity = action.payload;
},
setConfigurationThemeGeneral: (state, action) => {
const updatedTheme = {
general: action.payload,
interaction: typeof state.global.theme === "object" ? state.global.theme.interaction : "plurid"
};
state.global.theme = updatedTheme;
},
setConfigurationThemeInteraction: (state, action) => {
const updatedTheme = {
general: typeof state.global.theme === "object" ? state.global.theme.general : "plurid",
interaction: action.payload
};
state.global.theme = updatedTheme;
},
setConfigurationLanguage: (state, action) => {
state.global.language = action.payload;
},
toggleConfigurationViewcubeHide: (state, action) => {
state.elements.viewcube.show = action.payload;
},
toggleConfigurationViewcubeButtons: (state, action) => {
state.elements.viewcube.buttons = action.payload;
},
toggleConfigurationViewcubeOpaque: (state, action) => {
state.elements.viewcube.opaque = action.payload;
},
toggleConfigurationViewcubeConceal: state => {
const {conceal: conceal} = state.elements.viewcube;
state.elements.viewcube.conceal = !conceal;
},
toggleConfigurationToolbarConceal: state => {
const {conceal: conceal} = state.elements.toolbar;
state.elements.toolbar.conceal = !conceal;
},
toggleConfigurationToolbarTransformIcons: state => {
const {transformIcons: transformIcons} = state.elements.toolbar;
state.elements.toolbar.transformIcons = !transformIcons;
},
toggleConfigurationToolbarTransformButtons: state => {
const {transformButtons: transformButtons} = state.elements.toolbar;
state.elements.toolbar.transformButtons = !transformButtons;
},
toggleConfigurationShowTransformOrigin: state => {
const {show: show} = state.space.transformOrigin;
state.space.transformOrigin.show = !show;
},
toggleConfigurationToolbarOpaque: state => {
const {opaque: opaque} = state.elements.toolbar;
state.elements.toolbar.opaque = !opaque;
},
toggleConfigurationSpaceTransparentUI: state => {
state.global.transparentUI = !state.global.transparentUI;
},
setConfigurationSpaceTransformOriginSize: (state, action) => {
state.space.transformOrigin.size = action.payload;
},
setConfigurationSpaceTransformMode: (state, action) => {
if (state.space.transformMode !== action.payload) {
state.space.transformMode = action.payload;
} else {
state.space.transformMode = TRANSFORM_MODES.ALL;
}
},
toggleConfigurationSpaceTransformMultimode: (state, action) => {
state.space.transformMultimode = action.payload;
},
setConfigurationSpaceTransformTouch: (state, action) => {
state.space.transformTouch = action.payload;
},
toggleConfigurationSpaceFirstPerson: state => {
const {firstPerson: firstPerson} = state.space;
state.space.firstPerson = !firstPerson;
},
toggleConfigurationToolbarToggleDrawer: (state, action) => {
const {toggledDrawers: toggledDrawers} = state.elements.toolbar;
if (toggledDrawers.includes(action.payload)) {
const updatedDrawers = toggledDrawers.filter((el => el !== action.payload));
state.elements.toolbar.toggledDrawers = [ ...updatedDrawers ];
} else {
state.elements.toolbar.toggledDrawers = [ ...toggledDrawers, action.payload ];
}
},
setConfigurationSpaceTransformLocks: (state, action) => {
const {transformLocks: transformLocks} = state.space;
const updatedTransformLocks = Object.assign({}, transformLocks);
updatedTransformLocks[action.payload] = !transformLocks[action.payload];
state.space.transformLocks = Object.assign({}, updatedTransformLocks);
},
setConfigurationSpaceLayout: (state, action) => {
const layout = {
type: LAYOUT_TYPES[action.payload]
};
state.space.layout = Object.assign({}, layout);
},
setConfigurationSpaceCullingDistance: (state, action) => {
state.space.cullingDistance = action.payload;
}
}
});
const actions$6 = configuration.actions;
const getConfiguration = state => state.configuration;
const selectors$6 = {
getConfiguration: getConfiguration
};
const reducer$6 = configuration.reducer;
var configuration$1 = Object.freeze({
__proto__: null,
actions: actions$6,
configuration: configuration,
getConfiguration: getConfiguration,
reducer: reducer$6,
selectors: selectors$6
});
const initialState$4 = {};
const general = createSlice({
name: "general",
initialState: initialState$4,
reducers: {}
});
const actions$5 = general.actions;
const getGeneral = state => state.general;
const selectors$5 = {
getGeneral: getGeneral
};
const reducer$5 = general.reducer;
var general$1 = Object.freeze({
__proto__: null,
actions: actions$5,
general: general,
getGeneral: getGeneral,
reducer: reducer$5,
selectors: selectors$5
});
const initialState$3 = {
global: true
};
const shortcuts = createSlice({
name: "shortcuts",
initialState: initialState$3,
reducers: {
setGlobalShortcuts: (state, action) => {
state.global = action.payload;
}
}
});
const actions$4 = shortcuts.actions;
const getGlobal = state => state.shortcuts.global;
const selectors$4 = {
getGlobal: getGlobal
};
const reducer$4 = shortcuts.reducer;
var shortcuts$1 = Object.freeze({
__proto__: null,
actions: actions$4,
getGlobal: getGlobal,
reducer: reducer$4,
selectors: selectors$4,
shortcuts: shortcuts
});
const {registerPlanes: registerPlanes, getRegisteredPlanes: getRegisteredPlanes, getPlanesRegistrar: getPlanesRegistrar, getPluridPlaneIDByData: getPluridPlaneIDByData$1, getRegisteredPlane: getRegisteredPlane, resolvePluridRoutePlaneData: resolvePluridRoutePlaneData, resolvePluridPlaneData: resolvePluridPlaneData, Registrar: PluridPlanesRegistrar} = planes;
const {IsoMatcher: PluridIsoMatcher$1, resolveRoute: resolveRoute, computePlaneAddress: computePlaneAddress} = routing;
const {quaternion: quaternion$1, matrix: matrix$1} = interaction;
const {degToRad: degToRad$2} = quaternion$1;
const {matrixArrayToCSSMatrix: matrixArrayToCSSMatrix$1, rotateMatrix: rotateMatrix$2, multiplyArrayOfMatrices: multiplyArrayOfMatrices$2, scaleMatrix: scaleMatrix$2, translateMatrix: translateMatrix$2} = matrix$1;
const computeMatrix = spaceState => {
const {translationX: translationX, translationY: translationY, translationZ: translationZ, rotationX: rotationX, rotationY: rotationY, scale: scale} = spaceState;
const innerWidth = typeof window === "undefined" ? 720 : window.innerWidth / 2;
const innerHeight = typeof window === "undefined" ? 400 : window.innerHeight / 2;
const transformOriginX = translationX * -1 + innerWidth;
const transformOriginY = translationY * -1 + innerHeight;
const transformOriginZ = translationZ * -1;
const rotationMatrix = rotateMatrix$2(degToRad$2(-rotationX), degToRad$2(-rotationY));
const translationMatrix = translateMatrix$2(translationX, translationY, translationZ);
const scalationMatrix = scaleMatrix$2(scale);
const transformMatrix = multiplyArrayOfMatrices$2([ translationMatrix, translateMatrix$2(transformOriginX, transformOriginY, transformOriginZ), rotationMatrix, translateMatrix$2(-transformOriginX, -transformOriginY, -transformOriginZ), scalationMatrix ]);
const transform = matrixArrayToCSSMatrix$1(transformMatrix);
return transform;
};
const focusPluridPlaneAnchor = planeID => {
const selector = `[id='${planeID + FOCUS_ANCHOR_SUFFIX}']`;
const focusAnchor = document.querySelector(selector);
if (focusAnchor) {
focusAnchor.focus();
}
};
const getSpace = state => state.space;
const getLoading = state => state.space.loading;
const getResolvedLayout = state => state.space.resolvedLayout;
const getTransformMatrix = state => state.space.transform;
const getAnimatedTransform = state => state.space.animatedTransform;
const getTransformTime = state => state.space.transformTime;
const getRotationX = state => state.space.rotationX;
const getRotationY = state => state.space.rotationY;
const getTranslationX = state => state.space.translationX;
const getTranslationY = state => state.space.translationY;
const getTranslationZ = state => state.space.translationZ;
const getScale = state => state.space.scale;
const getTree = state => state.space.tree;
const getTransform = state => ({
rotationX: state.space.rotationX,
rotationY: state.space.rotationY,
translationX: state.space.translationX,
translationY: state.space.translationY,
translationZ: state.space.translationZ,
scale: state.space.scale
});
const getActiveUniverseID = state => state.space.activeUniverseID;
const getView = state => state.space.view;
const getViewSize = state => state.space.viewSize;
const getCulledView = state => state.space.culledView;
const getActivePlaneID = state => state.space.activePlaneID;
const getIsolatePlane = state => state.space.isolatePlane;
const getLastClosedPlane = state => state.space.lastClosedPlane;
var selectors$3 = Object.freeze({
__proto__: null,
getActivePlaneID: getActivePlaneID,
getActiveUniverseID: getActiveUniverseID,
getAnimatedTransform: getAnimatedTransform,
getCulledView: getCulledView,
getIsolatePlane: getIsolatePlane,
getLastClosedPlane: getLastClosedPlane,
getLoading: getLoading,
getResolvedLayout: getResolvedLayout,
getRotationX: getRotationX,
getRotationY: getRotationY,
getScale: getScale,
getSpace: getSpace,
getTransform: getTransform,
getTransformMatrix: getTransformMatrix,
getTransformTime: getTransformTime,
getTranslationX: getTranslationX,
getTranslationY: getTranslationY,
getTranslationZ: getTranslationZ,
getTree: getTree,
getView: getView,
getViewSize: getViewSize
});
const {toRadians: toRadians} = mathematics.geometry;
const initialState$2 = {
loading: true,
resolvedLayout: false,
transform: "matrix3d(1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1)",
animatedTransform: false,
transformTime: 450,
scale: 1,
rotationX: 0,
rotationY: 0,
translationX: 0,
translationY: 0,
translationZ: 0,
tree: [],
activeUniverseID: "",
camera: {
x: 0,
y: 0,
z: 0
},
viewSize: {
width: typeof window === "undefined" ? 1440 : window.innerWidth,
height: typeof window === "undefined" ? 821 : window.innerHeight
},
spaceSize: {
width: typeof window === "undefined" ? 1440 : window.innerWidth,
height: typeof window === "undefined" ? 821 : window.innerHeight,
depth: 0,
topCorner: {
x: 0,
y: 0,
z: 0
}
},
view: [],
culledView: [],
activePlaneID: "",
isolatePlane: "",
lastClosedPlane: ""
};
const name = "space";
const space = createSlice({
name: name,
initialState: initialState$2,
reducers: {
setSpaceField: (state, action) => {
const {field: field, value: value} = action.payload;
state[field] = value;
},
setSpaceLoading: (state, action) => {
state.loading = action.payload;
},
changeTransform: (state, action) => {},
setTransform: (state, action) => {
const {translationX: translationX, translationY: translationY, translationZ: translationZ, rotationX: rotationX, rotationY: rotationY, scale: scale} = action.payload;
const resolvedTranslationX = translationX !== null && translationX !== void 0 ? translationX : state.translationX;
const resolvedTranslationY = translationY !== null && translationY !== void 0 ? translationY : state.translationY;
const resolvedTranslationZ = translationZ !== null && translationZ !== void 0 ? translationZ : state.translationZ;
const resolvedRotationX = rotationX !== null && rotationX !== void 0 ? rotationX : state.rotationX;
const resolvedRotationY = rotationY !== null && rotationY !== void 0 ? rotationY : state.rotationY;
const resolvedScale = scale !== null && scale !== void 0 ? scale : state.scale;
state.translationX = resolvedTranslationX;
state.translationY = resolvedTranslationY;
state.translationZ = resolvedTranslationZ;
state.rotationX = resolvedRotationX;
state.rotationY = resolvedRotationY;
state.scale = resolvedScale;
},
setAnimatedTransform: (state, action) => {
state.animatedTransform = action.payload;
},
setTransformTime: (state, action) => {
state.transformTime = action.payload;
},
setSpaceLocation: (state, action) => {
const newState = Object.assign(Object.assign({}, state), action.payload);
const transform = computeMatrix(newState);
return Object.assign(Object.assign({}, newState), {
transform: transform
});
},
viewCameraMoveForward: state => {
state.translationZ = state.translationZ + TRANSLATION_STEP * 6 * Math.cos(toRadians(-state.rotationY));
state.translationX = state.translationX + TRANSLATION_STEP * 6 * Math.sin(toRadians(-state.rotationY));
state.transform = computeMatrix(state);
},
viewCameraMoveBackward: state => {
state.translationZ = state.translationZ - TRANSLATION_STEP * 6 * Math.cos(toRadians(-state.rotationY));
state.translationX = state.translationX - TRANSLATION_STEP * 6 * Math.sin(toRadians(-state.rotationY));
state.transform = computeMatrix(state);
},
viewCameraMoveLeft: state => {
state.translationX = state.translationX + TRANSLATION_STEP * 3 * Math.cos(toRadians(state.rotationY));
state.translationZ = state.translationZ + TRANSLATION_STEP * 3 * Math.sin(toRadians(state.rotationY));
state.transform = computeMatrix(state);
},
viewCameraMoveRight: state => {
state.translationX = state.translationX - TRANSLATION_STEP * 3 * Math.cos(toRadians(state.rotationY));
state.translationZ = state.translationZ - TRANSLATION_STEP * 3 * Math.sin(toRadians(state.rotationY));
state.transform = computeMatrix(state);
},
viewCameraMoveUp: state => {
state.translationY = state.translationY + TRANSLATION_STEP * 3;
state.transform = computeMatrix(state);
},
viewCameraMoveDown: state => {
state.translationY = state.translationY - TRANSLATION_STEP * 3;
state.transform = computeMatrix(state);
},
viewCameraTurnUp: state => {
state.rotationX = (state.rotationX + ROTATION_STEP) % 360;
state.transform = computeMatrix(state);
},
viewCameraTurnDown: state => {
state.rotationX = (state.rotationX - ROTATION_STEP) % 360;
state.transform = computeMatrix(state);
},
viewCameraTurnLeft: state => {
state.rotationY = (state.rotationY - ROTATION_STEP) % 360;
state.transform = computeMatrix(state);
},
viewCameraTurnRight: state => {
state.rotationY = (state.rotationY + ROTATION_STEP) % 360;
state.transform = computeMatrix(state);
},
rotateUp: state => {
state.rotationX = (state.rotationX + ROTATION_STEP) % 360;
state.transform = computeMatrix(state);
},
rotateDown: state => {
state.rotationX = (state.rotationX - ROTATION_STEP) % 360;
state.transform = computeMatrix(state);
},
rotateX: (state, action) => {
state.rotationX = action.payload;
state.transform = computeMatrix(state);
},
rotateXWith: (state, action) => {
state.rotationX = state.rotationX + action.payload;
state.transform = computeMatrix(state);
},
rotateLeft: state => {
state.rotationY = (state.rotationY + ROTATION_STEP) % 360;
state.transform = computeMatrix(state);
},
rotateRight: state => {
state.rotationY = (state.rotationY - ROTATION_STEP) % 360;
state.transform = computeMatrix(state);
},
rotateY: (state, action) => {
state.rotationY = action.payload;
state.transform = computeMatrix(state);
},
rotateYWith: (state, action) => {
state.rotationY = state.rotationY + action.payload;
state.transform = computeMatrix(state);
},
translateUp: state => {
state.translationY = state.translationY - TRANSLATION_STEP;
state.transform = computeMatrix(state);
},
translateDown: state => {
state.translationY = state.translationY + TRANSLATION_STEP;
state.transform = computeMatrix(state);
},
translateLeft: state => {
state.translationX = state.translationX - TRANSLATION_STEP * Math.cos(toRadians(state.rotationY));
state.translationZ = state.translationZ - TRANSLATION_STEP * Math.sin(toRadians(state.rotationY));
state.transform = computeMatrix(state);
},
translateRight: state => {
state.translationX = state.translationX + TRANSLATION_STEP * Math.cos(toRadians(state.rotationY));
state.translationZ = state.translationZ + TRANSLATION_STEP * Math.sin(toRadians(state.rotationY));
state.transform = computeMatrix(state);
},
translateIn: state => {
state.translationZ = state.translationZ - TRANSLATION_STEP * 3 * Math.cos(toRadians(-state.rotationY));
state.translationX = state.translationX - TRANSLATION_STEP * 3 * Math.sin(toRadians(-state.rotationY));
state.transform = computeMatrix(state);
},
translateOut: state => {
state.translationZ = state.translationZ + TRANSLATION_STEP * 3 * Math.cos(toRadians(-state.rotationY));
state.translationX = state.translationX + TRANSLATION_STEP * 3 * Math.sin(toRadians(-state.rotationY));
state.transform = computeMatrix(state);
},
translateXWith: (state, action) => {
state.translationX = state.translationX + action.payload * Math.cos(toRadians(state.rotationY));
state.translationZ = state.translationZ + action.payload * Math.sin(toRadians(state.rotationY));
state.transform = computeMatrix(state);
},
translateYWith: (state, action) => {
state.translationY = state.translationY + action.payload;
state.transform = computeMatrix(state);
},
translateZWith: (state, action) => {
state.translationZ = state.translationZ + action.payload;
state.transform = computeMatrix(state);
},
scaleUp: state => {
const computedScale = state.scale + SCALE_STEP;
const scale = computedScale < SCALE_UPPER_LIMIT ? computedScale : SCALE_UPPER_LIMIT;
state.scale = scale;
state.transform = computeMatrix(state);
},
scaleDown: state => {
const computedScale = state.scale - SCALE_STEP;
const scale = computedScale > SCALE_LOWER_LIMIT ? computedScale : SCALE_LOWER_LIMIT;
state.scale = scale;
state.transform = computeMatrix(state);
},
scaleUpWith: (state, action) => {
const computedScale = state.scale + Math.abs(action.payload);
const scale = computedScale < SCALE_UPPER_LIMIT ? computedScale : SCALE_UPPER_LIMIT;
state.scale = scale;
state.transform = computeMatrix(state);
},
scaleDownWith: (state, action) => {
const computedScale = state.scale - Math.abs(action.payload);
const scale = computedScale > SCALE_LOWER_LIMIT ? computedScale : SCALE_LOWER_LIMIT;
state.scale = scale;
state.transform = computeMatrix(state);
},
setTree: (state, action) => {
state.tree = [ ...action.payload ];
},
setActiveUniverse: (state, action) => {
state.activeUniverseID = action.payload;
},
spaceResetTransform: state => {
state.scale = 1;
state.rotationX = 0;
state.rotationY = 0;
state.translationX = 0;
state.translationY = 0;
state.translationZ = 0;
state.transform = computeMatrix(state);
},
setViewSize: (state, action) => {
state.viewSize = action.payload;
},
setSpaceSize: (state, action) => {
state.spaceSize = action.payload;
},
updateSpaceTreePlane: (state, action) => {
const updatedTree = general$2.tree.updateTreePlane(state.tree, action.payload);
state.tree = updatedTree;
},
updateSpaceLinkCoordinates: (state, action) => {
const {planeID: planeID, linkCoordinates: linkCoordinates} = action.payload;
const updatedTree = general$2.tree.updateTreeByPlaneIDWithLinkCoordinates(state.tree, planeID, linkCoordinates);
state.tree = updatedTree;
},
spaceSetView: (state, action) => {
state.view = action.payload;
},
spaceSetCulledView: (state, action) => {
state.culledView = action.payload;
},
removePlane: (state, action) => {
const updatedTree = space$2.tree.logic.removePlaneFromTree(objects.clone(state.tree), action.payload);
state.tree = updatedTree;
}
}
});
const actions$3 = space.actions;
const reducer$3 = space.reducer;
var space$1 = Object.freeze({
__proto__: null,
actions: actions$3,
name: name,
reducer: reducer$3,
selectors: selectors$3,
space: space
});
const initialState$1 = {
general: plurid,
interaction: plurid
};
const themes = createSlice({
name: "themes",
initialState: initialState$1,
reducers: {
setGeneralTheme: (state, action) => {
state.general = action.payload;
},
setInteractionTheme: (state, action) => {
state.interaction = action.payload;
}
}
});
const actions$2 = themes.actions;
const getGeneralTheme = state => state.themes.general;
const getInteractionTheme = state => state.themes.general;
const selectors$2 = {
getGeneralTheme: getGeneralTheme,
getInteractionTheme: getInteractionTheme
};
const reducer$2 = themes.reducer;
var themes$1 = Object.freeze({
__proto__: null,
actions: actions$2,
getGeneralTheme: getGeneralTheme,
getInteractionTheme: getInteractionTheme,
reducer: reducer$2,
selectors: selectors$2,
themes: themes
});
const initialState = {
toolbarScrollPosition: 0
};
const ui = createSlice({
name: "ui",
initialState: initialState,
reducers: {
setUIToolbarScrollPosition: (state, action) => {
state.toolbarScrollPosition = action.payload;
}
}
});
const actions$1 = ui.actions;
const getToolbarScrollPosition = state => state.ui.toolbarScrollPosition;
const selectors$1 = {
getToolbarScrollPosition: getToolbarScrollPosition
};
const reducer$1 = ui.reducer;
var ui$1 = Object.freeze({
__proto__: null,
actions: actions$1,
getToolbarScrollPosition: getToolbarScrollPosition,
reducer: reducer$1,
selectors: selectors$1,
ui: ui
});
var modules = {
configuration: configuration$1,
general: general$1,
shortcuts: shortcuts$1,
space: space$1,
themes: themes$1,
ui: ui$1
};
const reducer = combineReducers({
configuration: modules.configuration.reducer,
general: modules.general.reducer,
shortcuts: modules.shortcuts.reducer,
space: modules.space.reducer,
themes: modules.themes.reducer,
ui: modules.ui.reducer
});
const store$1 = preloadedState => configureStore({
preloadedState: preloadedState,
reducer: reducer,
devTools: false
});
const store = store$1;
const StateContext = React.createContext({});
function __awaiter(thisArg, _arguments, P, generator) {
function adopt(value) {
return value instanceof P ? value : new P((function(resolve) {
resolve(value);
}));
}
return new (P || (P = Promise))((function(resolve, reject) {
function fulfilled(value) {
try {
step(generator.next(value));
} catch (e) {
reject(e);
}
}
function rejected(value) {
try {
step(generator["throw"](value));
} catch (e) {
reject(e);
}
}
function step(result) {
result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected);
}
step((generator = generator.apply(thisArg, _arguments || [])).next());
}));
}
const Context = React.createContext(null);
var actions = {
configuration: modules.configuration.actions,
general: modules.general.actions,
shortcuts: modules.shortcuts.actions,
space: modules.space.actions,
themes: modules.themes.actions,
ui: modules.ui.actions
};
const {quaternion: quaternion, transform: transform, matrix: matrix} = interaction;
const {degToRad: degToRad$1, radToDeg: radToDeg} = quaternion;
const {multiplyMatricesArray: multiplyMatricesArray, translateMatrix: translateMatrix$1, rotateYMatrix: rotateYMatrix, matrixToCSSMatrix: matrixToCSSMatrix, arrayToMatrix: arrayToMatrix, inverseMatrix: inverseMatrix} = transform.general;
const {getTransformRotate: getTransformRotate, getTransformTranslate: getTransformTranslate, getTransformScale: getTransformScale} = transform.matrix3d;
const {rotateMatrix: rotateMatrix$1, translateMatrix: translateMatrixArray, scaleMatrix: scaleMatrix$1, multiplyArrayOfMatrices: multiplyArrayOfMatrices$1} = matrix;
const computeApplication = (planes, configuration, view, origin = "origin") => {
const appConfiguration = general$2.configuration.merge(configuration);
const currentView = view || [];
const absoluteView = [];
for (const viewItem of currentView) {
if (typeof viewItem === "string") {
const viewPath = routing.resolveRoute(viewItem);
if (!viewPath) {
continue;
}
absoluteView.push(viewPath.route);
}
}
const registrar = new PluridPlanesRegistrar(planes, origin);
const registrarPlanes = registrar.getAll();
const spaceTree = new space$2.tree.Tree({
planes: registrarPlanes,
configuration: appConfiguration,
view: absoluteView
}, origin);
const computedTree = spaceTree.compute();
const data = {
computedTree: computedTree,
appConfiguration: appConfiguration
};
return data;
};
const computePlaneLocation = plane => {
const {location: location} = plane;
const {translateX: translateX, translateY: translateY, translateZ: translateZ, rotateY: rotateY} = location;
const getTransform = () => {
const innerWidth = typeof window === "undefined" ? 720 : window.innerWidth / 2;
const innerHeight = typeof window === "undefined" ? 400 : window.innerHeight / 2;
const transformOriginX = translateX * -1 + innerWidth;
const transformOriginY = translateY * -1 + innerHeight;
const transformOriginZ = translateZ * -1;
const rotationMatrix = rotateMatrix$1(0, degToRad$1(rotateY));
const translationMatrix = translateMatrixArray(translateX, translateY, translateZ);
const scalationMatrix = scaleMatrix$1(1);
const transformMatrix = multiplyArrayOfMatrices$1([ translationMatrix, translateMatrixArray(transformOriginX, transformOriginY, transformOriginZ), rotationMatrix, translateMatrixArray(-transformOriginX, -transformOriginY, -transformOriginZ), scalationMatrix ]);
const inverseTransformMatrix = inverseMatrix(arrayToMatrix(transformMatrix));
const matrix3dTransformMatrix = matrixToCSSMatrix(inverseTransformMatrix);
const rotate = getTransformRotate(matrix3dTransformMatrix);
const translate = getTransformTranslate(matrix3dTransformMatrix);
const scale = getTransformScale(matrix3dTransformMatrix);
const transform = {
translationX: translate.translateX,
translationY: translate.translateY,
translationZ: translate.translateZ,
rotationX: radToDeg(rotate.rotateX),
rotationY: radToDeg(rotate.rotateY),
scale: scale.scale
};
return transform;
};
const transform = getTransform();
const getMatrix3d = () => {
const zSign1 = rotateY < 100 ? 1 : -1;
const zSign2 = rotateY < 100 ? -1 : 1;
const xOffset = rotateY < 100 ? plane.parentPlaneID ? 200 : 0 : 0;
const newMatrix = multiplyMatricesArray([ translateMatrix$1(-translateX, -translateY, zSign1 * translateZ), rotateYMatrix(degToRad$1(rotateY)), translateMatrix$1(translateX, translateY, zSign2 * translateZ), translateMatrix$1(-(translateX + xOffset), -translateY, zSign1 * translateZ) ]);
const matrix3d = matrixToCSSMatrix(newMatrix);
return matrix3d;
};
const matrix3d = getMatrix3d();
return {
transform: transform,
matrix3d: matrix3d
};
};
const factoryUseAnimatedTransform = () => {
let timeout;
return dispatch => {
const dispatchSetAnimatedTransform = payload => dispatch(actions.space.setAnimatedTransform(payload));
dispatchSetAnimatedTransform(true);
if (timeout) {
clearTimeout(timeout);
}
timeout = setTimeout((() => {
dispatchSetAnimatedTransform(false);
}), PLURID_DEFAULT_ANIMATED_TRANSFORM_TIMEOUT);
};
};
const useAnimatedTransform = factoryUseAnimatedTransform();
const navigateToPluridPlane = (dispatch, plane, event, deisolate = true) => {
if (event && (event.ctrlKey || event.metaKey)) {
return;
}
if (!plane) {
return;
}
const dispatchSetTransform = payload => dispatch(actions.space.setTransform(payload));
const dispatchSetSpaceField = payload => dispatch(actions.space.setSpaceField(payload));
const {matrix3d: matrix3d, transform: transform} = computePlaneLocation(plane);
useAnimatedTransform(dispatch);
dispatchSetSpaceField({
field: "transform",
value: matrix3d
});
dispatchSetTransform(Object.assign({}, transform));
if (deisolate) {
dispatchSetSpaceField({
field: "isolatePlane",
value: ""
});
}
setTimeout((() => {
focusPluridPlaneAnchor(plane.planeID);
dispatchSetSpaceField({
field: "activePlaneID",
value: plane.planeID
});
}), PLURID_DEFAULT_ANIMATED_TRANSFORM_TIMEOUT);
};
const getActivePlane = state => {
const {activePlaneID: activePlaneID, tree: tree} = state.space;
if (!activePlaneID) {
return;
}
const treePlane = space$2.tree.logic.getTreePlaneByID(tree, activePlaneID);
return treePlane;
};
const focusActivePlane = (dispatch, state) => {
const activePlane = getActivePlane(state);
if (!activePlane) {
return;
}
const event = undefined;
const deisolate = false;
navigateToPluridPlane(dispatch, activePlane, event, deisolate);
};
const focusParentActivePlane = (dispatch, state) => {
const activePlane = getActivePlane(state);
if (!activePlane || !activePlane.parentPlaneID) {
return;
}
const parentPlane = space$2.tree.logic.getTreePlaneByID(state.space.tree, activePlane.parentPlaneID);
if (!parentPlane) {
return;
}
navigateToPluridPlane(dispatch, parentPlane);
};
const findRootIndex = (tree, activePlaneID, currentRootIndex) => {
for (const [index, plane] of tree.entries()) {
if (plane.planeID === activePlaneID) {
return currentRootIndex !== null && currentRootIndex !== void 0 ? currentRootIndex : index;
}
if (plane.children) {
const rootIndex = findRootIndex(plane.children, activePlaneID, index);
if (typeof rootIndex === "number") {
return rootIndex;
}
}
}
return;
};
const navigateToRoot = (dispatch, state, type) => {
const {activePlaneID: activePlaneID, tree: tree} = state.space;
const rootIndex = findRootIndex(tree, activePlaneID);
if (typeof rootIndex !== "number") {
return;
}
const treeIndex = type === "previous" ? rootIndex - 1 || 0 : rootIndex + 1;
let root = tree[treeIndex];
if (!root) {
if (type === "previous") {
root = tree[tree.length - 1];
} else {
root = tree[0];
}
if (!root) {
return;
}
}
navigateToPluridPlane(dispatch, root, undefined, true);
};
const focusPreviousRoot = (dispatch, state) => {
navigateToRoot(dispatch, state, "previous");
};
const focusNextRoot = (dispatch, state) => {
navigateToRoot(dispatch, state, "next");
};
const focusRootIndex = (dispatch, state, index) => {
const {tree: tree} = state.space;
const root = tree[index];
if (!root) {
return;
}
navigateToPluridPlane(dispatch, root, undefined, true);
};
const focusRootID = (dispatch, state, id) => {
const {tree: tree} = state.space;
const root = tree.find((plane => plane.planeID === id));
if (!root) {
return;
}
navigateToPluridPlane(dispatch, root, undefined, true);
};
const refreshActivePlane = (state, pubsub) => {
const {activePlaneID: id} = state.space;
if (!id) {
return;
}
pubsub.publish({
topic: PLURID_PUBSUB_TOPIC.REFRESH_PLANE,
data: {
id: id
}
});
};
const isolateActivePlane = (state, pubsub) => {
const {activePlaneID: id, isolatePlane: isolatePlane} = state.space;
if (isolatePlane) {
pubsub.publish({
topic: PLURID_PUBSUB_TOPIC.ISOLATE_PLANE,
data: {
id: ""
}
});
return;
}
if (!id) {
return;
}
pubsub.publish({
topic: PLURID_PUBSUB_TOPIC.ISOLATE_PLANE,
data: {
id: id
}
});
};
const openClosedPlane = pubsub => {
pubsub.publish({
topic: PLURID_PUBSUB_TOPIC.OPEN_CLOSED_PLANE
});
};
const closeActivePlane = (state, pubsub) => {
const {activePlaneID: id} = state.space;
if (!id) {
return;
}
pubsub.publish({
topic: PLURID_PUBSUB_TOPIC.CLOSE_PLANE,
data: {
id: id
}
});
};
const handleGlobalShortcuts = (dispatch, state, pubsub, event, firstPerson, locks) => {
if (event.defaultPrevented) {
return;
}
const inputOnPath = dom.verifyPathInputElement(dom.getEventPath(event));
if (inputOnPath) {
return;
}
const noModifiers = !event.shiftKey && !event.altKey && !event.ctrlKey && !event.metaKey;
const handleEvent = () => {
event.preventDefault();
};
if (event.code === "KeyF" && noModifiers) {
handleEvent();
return dispatch(actions.configuration.toggleConfigurationSpaceFirstPerson());
}
if (firstPerson) {
if (event.code === "KeyW" && noModifiers && locks.translationZ) {
handleEvent();
return dispatch(actions.space.viewCameraMoveForward());
}
if (event.code === "KeyS" && noModifiers && locks.translationZ) {
handleEvent();
return dispatch(actions.space.viewCameraMoveBackward());
}
if (event.code === "KeyA" && noModifiers && locks.translationX) {
handleEvent();
return dispatch(actions.space.viewCameraMoveLeft());
}
if (event.code === "KeyA" && event.shiftKey && locks.rotationY) {
handleEvent();
return dispatch(actions.space.viewCameraTurnLeft());
}
if (event.code === "KeyD" && noModifiers && locks.translationX) {
handleEvent();
return dispatch(actions.space.viewCameraMoveRight());
}
if (event.code === "KeyD" && event.shiftKey && locks.rotationY) {
handleEvent();
return dispatch(actions.space.viewCameraTurnRight());
}
if (event.code === "KeyQ" && noModifiers && locks.rotationX) {
handleEvent();
return dispatch(actions.space.viewCameraTurnUp());
}
if (event.code === "KeyZ" && noModifiers && locks.rotationX) {
handleEvent();
return dispatch(actions.space.viewCameraTurnDown());
}
if (event.code === "KeyE" && noModifiers && locks.translationY) {
handleEvent();
return dispatch(actions.space.viewCameraMoveUp());
}
if (event.code === "KeyC" && noModifiers && locks.translationY) {
handleEvent();
return dispatch(actions.space.viewCameraMoveDown());
}
}
if (event.code === "KeyR" && noModifiers) {
handleEvent();
return dispatch(actions.configuration.setConfigurationSpaceTransformMode(TRANSFORM_MODES.ROTATION));
}
if (event.code === "KeyT" && noModifiers) {
handleEvent();
return dispatch(actions.configuration.setConfigurationSpaceTransformMode(TRANSFORM_MODES.TRANSLATION));
}
if (event.code === "KeyS" && noModifiers && !firstPerson) {
handleEvent();
return dispatch(actions.configuration.setConfigurationSpaceTransformMode(TRANSFORM_MODES.SCALE));
}
if (event.key === "ArrowRight") {
if (event.shiftKey && locks.rotationY) {
handleEvent();
return dispatch(actions.space.rotateLeft());
}
if (event.altKey && locks.translationX) {
handleEvent();
return dispatch(actions.space.translateRight());
}
}
if (event.key === "ArrowLeft") {
if (event.shiftKey && locks.rotationY) {
handleEvent();
return dispatch(actions.space.rotateRight());
}
if (event.altKey && locks.translationX) {
handleEvent();
return dispatch(actions.space.translateLeft());
}
}
if (event.key === "ArrowUp") {
if (event.shiftKey && event.altKey && locks.translationZ) {
handleEvent();
return dispatch(actions.space.translateIn());
}
if (event.shiftKey && !event.altKey && locks.rotationX) {
handleEvent();
return dispatch(actions.space.rotateUp());
}
if (event.altKey && !event.shiftKey && locks.translationY) {
handleEvent();
return dispatch(actions.space.translateUp());
}
if (event.metaKey || event.ctrlKey && locks.scale) {
handleEvent();
return dispatch(actions.space.scaleUp());
}
}
if (event.key === "ArrowDown") {
if (event.shiftKey && event.altKey && locks.translationZ) {
handleEvent();
return dispatch(actions.space.translateOut());
}
if (event.shiftKey && !event.altKey && locks.rotationX) {
handleEvent();
return dispatch(actions.space.rotateDown());
}
if (event.altKey && !event.shiftKey && locks.translationY) {
handleEvent();
return dispatch(actions.space.translateDown());
}
if (event.metaKey || event.ctrlKey && locks.scale) {
handleEvent();
return dispatch(actions.space.scaleDown());
}
}
if (event.altKey && event.code === "KeyF") {
handleEvent();
focusActivePlane(dispatch, state);
return;
}
if (event.altKey && event.code === "KeyB") {
handleEvent();
focusParentActivePlane(dispatch, state);
return;
}
if (event.altKey && event.code === "KeyR") {
handleEvent();
refreshActivePlane(state, pubsub);
return;
}
if (event.altKey && event.code === "KeyE") {
handleEvent();
isolateActivePlane(state, pubsub);
return;
}
if (event.altKey && event.shiftKey && event.code === "KeyT") {
handleEvent();
openClosedPlane(pubsub);
return;
}
if (event.altKey && event.code === "KeyW") {
handleEvent();
closeActivePlane(state, pubsub);
return;
}
if (event.altKey && event.code === "KeyA") {
handleEvent();
focusPreviousRoot(dispatch, state);
return;
}
if (event.altKey && event.code === "KeyD") {
handleEvent();
focusNextRoot(dispatch, state);
return;
}
if (event.altKey && event.code === "Tab") {
handleEvent();
if (event.shiftKey) {
focusPreviousRoot(dispatch, state);
} else {
focusNextRoot(dispatch, state);
}
return;
}
if (event.altKey && event.code.startsWith("Digit")) {
handleEvent();
const index = parseInt(event.code.replace("Digit", "")) - 1;
focusRootIndex(dispatch, state, index);
return;
}
return;
};
const handleGlobalWheel = (dispatch, event, modes, locks) => {
if (event.shiftKey || event.metaKey || event.altKey || event.ctrlKey || modes.rotation || modes.translation || modes.scale) {
event.preventDefault();
}
const deltas = {
deltaX: event.deltaX,
deltaY: event.deltaY
};
const absoluteThreshold = 100;
const direction = interaction.direction.getWheelDirection(deltas, absoluteThreshold);
if (modes.rotation) {
if (direction === directions.left && locks.rotationY) {
return dispatch(actions.space.rotateLeft());
}
if (direction === directions.right && locks.rotationY) {
return dispatch(actions.space.rotateRight());
}
if (direction === directions.up && locks.rotationX) {
return dispatch(actions.space.rotateUp());
}
if (direction === directions.down && locks.rotationX) {
return dispatch(actions.space.rotateDown());
}
}
if (event.shiftKey && !event.altKey) {
if (direction === directions.up && locks.rotationX) {
return dispatch(actions.space.rotateUp());
}
if (direction === directions.down && locks.rotationX) {
return dispatch(actions.space.rotateDown());
}
if (direction === directions.left && locks.rotationY) {
return dispatch(actions.space.rotateLeft());
}
if (direction === directions.right && locks.rotationY) {
return dispatch(actions.space.rotateRight());
}
}
if (modes.translation) {
if (event.metaKey || event.ctrlKey) {
if (direction === directions.up) {
return dispatch(actions.space.translateDown());
}
if (direction === directions.down) {
return dispatch(actions.space.translateUp());
}
return;
}
if (event.altKey) {
if (direction === directions.up && locks.translationZ) {
return dispatch(actions.space.translateIn());
}
if (direction === directions.down && locks.translationZ) {
return dispatch(actions.space.translateOut());
}
}
if (direction === directions.up && locks.translationY) {
return dispatch(actions.space.translateDown());
}
if (direction === directions.down && locks.translationY) {
return dispatch(actions.space.translateUp());
}
if (direction === directions.left && locks.translationX) {
return dispatch(actions.space.translateRight());
}
if (direction === directions.right && locks.translationX) {
return dispatch(actions.space.translateLeft());
}
}
if (event.altKey && event.shiftKey) {
if (direction === directions.up && locks.translationZ) {
return dispatch(actions.space.translateIn());
}
if (direction === directions.down && locks.translationZ) {
return dispatch(actions.space.translateOut());
}
}
if (event.altKey && !event.shiftKey) {
if (event.metaKey || event.ctrlKey) {
if (direction === directions.up) {
return dispatch(actions.space.translateDown());
}
if (direction === directions.down) {
return dispatch(actions.space.translateUp());
}
return;
}
if (direction === directions.up && locks.translationY) {
return dispatch(actions.space.translateDown());
}
if (direction === directions.down && locks.translationY) {
return dispatch(actions.space.translateUp());
}
if (direction === directions.left && locks.translationX) {
return dispatch(actions.space.translateRight());
}
if (direction === directions.right && locks.translationX) {