UNPKG

@plurid/plurid-engine

Version:
1,559 lines (1,450 loc) 93.5 kB
import { defaultConfiguration, protocols, HTTPS_PROTOCOL, HTTP_PROTOCOL, compareTypes, internationalization, ROOTS_GAP, LAYOUT_TYPES, PLANE_DEFAULT_ANGLE, PLURID_ROUTER_LOCATION_CHANGED } from "@plurid/plurid-data"; import { objects, mathematics, uuid } from "@plurid/plurid-functions"; import themes, { THEME_NAMES } from "@plurid/plurid-themes"; const resolveTheme = (theme, type) => { if (!theme) { return "plurid"; } if (typeof theme === "string") { return theme; } if (typeof theme !== "object") { return "plurid"; } const {general: general, interaction: interaction} = theme; if (type === "general" && general) { return general; } if (type === "interaction" && interaction) { return interaction; } return "plurid"; }; const merge = (configuration, target) => { const targetConfiguration = Object.assign(Object.assign({}, objects.clone(defaultConfiguration)), objects.clone(target || {})); if (!configuration) { return targetConfiguration; } const mergedConfiguration = objects.merge(targetConfiguration, configuration, { "global.theme": () => { var _a, _b; return { general: resolveTheme((_a = configuration.global) === null || _a === void 0 ? void 0 : _a.theme, "general"), interaction: resolveTheme((_b = configuration.global) === null || _b === void 0 ? void 0 : _b.theme, "interaction") }; } }); return mergedConfiguration; }; var index$k = Object.freeze({ __proto__: null, merge: merge }); const extractPathname = location => { const queryIndex = location.indexOf("?"); const noQueryPath = queryIndex === -1 ? location : location.substring(0, queryIndex); const fragmentIndex = noQueryPath.indexOf("#:~:"); const noFragmentPath = fragmentIndex === -1 ? noQueryPath : noQueryPath.substring(0, fragmentIndex); return noFragmentPath; }; const extractParametersAndMatch = (location, route) => { const routeElements = splitPath(route); const parameters = []; routeElements.forEach((routeElement => { if (routeElement[0] === ":") { parameters.push(routeElement); } else { parameters.push(""); } })); const {locationElements: locationElements, comparingPath: comparingPath} = computeComparingPath(location, parameters); if (comparingPath !== route) { return { match: false, parameters: {}, elements: locationElements }; } const parametersValues = extractParametersValues(parameters, locationElements); return { match: true, parameters: parametersValues, elements: locationElements }; }; const extractParametersValues = (parameters, pathElements) => { const parametersValues = {}; parameters.forEach(((parameter, index) => { if (parameter) { const parameterKey = parameter.slice(1); parametersValues[parameterKey] = pathElements[index]; } })); return parametersValues; }; const computeComparingPath = (path, parameters) => { const pathname = extractPathname(path); const locationElements = splitPath(pathname); const comparingPathElements = [ ...locationElements ]; for (const index of locationElements.keys()) { if (parameters[index]) { comparingPathElements[index] = parameters[index]; } } const comparingPath = comparingPathElements.join("/"); return { locationElements: locationElements, comparingPath: comparingPath }; }; const splitPath = path => path.split("/").filter((i => i !== "")); const extractQuery = path => { const fragmentIndex = path.indexOf("#:~:"); const noFragmentPath = fragmentIndex === -1 ? path : path.substring(0, fragmentIndex); const querySplit = noFragmentPath.split("?"); if (querySplit.length === 2) { const queryValues = {}; const query = querySplit[1]; const queryItems = query.split("&"); for (const item of queryItems) { const queryValue = item.split("="); const id = queryValue[0]; const value = decodeURIComponent(queryValue[1]); queryValues[id] = value; } return queryValues; } else { return {}; } }; const extractFragments = location => { if (!location) { return { texts: [], elements: [] }; } const split = location.split("#:~:"); const fragmentsValues = split[1]; if (!fragmentsValues) { return { texts: [], elements: [] }; } const fragmentItems = fragmentsValues.split("&"); const textFragments = []; const elementFragments = []; for (const item of fragmentItems) { const parsedFragment = parseFragment(item); if (parsedFragment) { switch (parsedFragment.type) { case "text": textFragments.push(parsedFragment); break; case "element": elementFragments.push(parsedFragment); break; } } } return { texts: textFragments, elements: elementFragments }; }; const parseFragment = fragment => { const fragmentData = fragment.split("="); const fragmentType = fragmentData[0]; const fragmentValues = fragmentData[1]; switch (fragmentType.toLowerCase()) { case "text": { const textValues = fragmentValues.split(","); const textStart = textValues[0]; const textEnd = textValues[1]; const textOccurence = extractOccurence(textValues[2]); if (!textStart) { return; } return { type: "text", start: textStart, end: textEnd || "", occurence: textOccurence }; } case "element": { const elementValues = fragmentValues.split(","); const elementID = elementValues[0]; const elementOccurence = extractOccurence(elementValues[1]); if (!elementID) { return; } return { type: "element", id: elementID, occurence: elementOccurence }; } } return undefined; }; const extractOccurence = occurence => { if (!occurence) { return 0; } const occurenceMatch = occurence.match(/\[(\d*)\]/); const occurenceValue = occurenceMatch ? parseInt(occurenceMatch[1]) : 0; return occurenceValue; }; const stringInsertInitial = (value, insert) => { if (!value.startsWith(insert)) { value = insert + value; } return value; }; const stringRemoveTrailing = (value, trail) => { if (value.endsWith(trail)) { value = value.slice(0, value.length - trail.length); } return value; }; const PATH_SEPARATOR = "/"; const cleanupPath = value => { value = stringInsertInitial(value, PATH_SEPARATOR); value = stringRemoveTrailing(value, PATH_SEPARATOR); return value; }; const computePlaneAddress = (plane, route, origin = "origin") => { if (origin === "origin" && typeof location !== "undefined" && location.host) { origin = location.host; } const cleanPlane = extractPathname(plane); const planeAddressType = checkPlaneAddressType(cleanPlane); switch (planeAddressType) { case "http": case "https": case "pttp": return cleanPlane; } origin = stringRemoveTrailing(origin, "/"); const absolutePlane = isAbsolutePlane(plane); const path = route && route !== "/" ? absolutePlane ? cleanupPath(cleanPlane) : cleanupPath(route) + cleanupPath(cleanPlane) : cleanupPath(cleanPlane); const planeAddress = protocols.plurid + origin + path; return planeAddress; }; const isAbsolutePlane = value => value[0] === "/"; const checkPlaneAddressType = value => { value = value.toLowerCase().trim(); if (value.startsWith(protocols.plurid)) { return "pttp"; } if (value.startsWith(protocols.https)) { return HTTPS_PROTOCOL; } if (value.startsWith(protocols.http)) { return HTTP_PROTOCOL; } return "relative"; }; const removeTrailingSlash = value => { if (value.endsWith("/") && value.length > 1) { return value.slice(0, value.length - 1); } return value; }; const cleanPathValue = value => { const queryStart = value.indexOf("?"); if (queryStart < 0) { return removeTrailingSlash(value); } return removeTrailingSlash(value.substring(0, queryStart)); }; const checkParameterLength = (parameter, length, compareType) => { const parameterLength = parameter.length; switch (compareType) { case compareTypes.equal: return parameterLength === length; case compareTypes.equalLessThan: return parameterLength <= length; case compareTypes.lessThan: return parameterLength < length; case compareTypes.equalGreaterThan: return parameterLength >= length; case compareTypes.greaterThan: return parameterLength > length; default: return parameterLength <= length; } }; const checkValidPath = (validationParameters, parameters) => { if (validationParameters) { for (const [parameterKey, parameterData] of Object.entries(validationParameters)) { const {length: length, lengthType: lengthType, startsWith: startsWith, endsWith: endsWith, includes: includes} = parameterData; const paramaterValue = parameters[parameterKey]; if (!paramaterValue) { return false; } if (startsWith && !paramaterValue.startsWith(startsWith)) { return false; } if (endsWith && !paramaterValue.endsWith(endsWith)) { return false; } if (includes && !includes.includes(paramaterValue)) { return false; } if (length) { const validLength = checkParameterLength(paramaterValue, length, lengthType); return validLength; } } } return true; }; const cleanPathElement = path => { if (path[0] === "/") { return path.slice(1); } return path; }; var index$j = Object.freeze({ __proto__: null, cleanPathElement: cleanPathElement }); const mapPathsToRoutes = (paths, view) => { const routes = []; for (const [key, path] of Object.entries(paths)) { const pathView = view[key]; if (pathView) { const route = { value: "" }; routes.push(route); } } return routes; }; const pluridLinkPathDivider = route => { const windowProtocol = typeof window === "undefined" ? "http" : window.location.protocol.replace(":", ""); const windowHost = typeof window === "undefined" ? "localhost:63000" : window.location.host; const split = route.split("://").filter((value => value !== "")).map((value => cleanPathElement(value))); let protocol = windowProtocol; const host = { value: windowHost, controlled: false }; const path = { value: "", parameters: {}, query: {} }; const space = { value: "", parameters: {}, query: {} }; const universe = { value: "", parameters: {}, query: {} }; const cluster = { value: "", parameters: {}, query: {} }; const plane = { value: "", parameters: {}, query: {}, fragments: { texts: [], elements: [] } }; const valid = false; if (split.length === 0 || split.length > 7) { const url = { protocol: { value: protocol, secure: true }, host: host, path: path, space: space, universe: universe, cluster: cluster, plane: plane, valid: valid }; return url; } if (route.startsWith("/://")) { const routeSplit = split.slice(1); switch (routeSplit.length) { case 1: path.value = routeSplit[0]; break; case 5: path.value = routeSplit[0]; space.value = routeSplit[1]; universe.value = routeSplit[2]; cluster.value = routeSplit[3]; plane.value = routeSplit[4]; break; } const url = { protocol: { value: protocol, secure: true }, host: host, path: path, space: space, universe: universe, cluster: cluster, plane: plane, valid: true }; return url; } if (split[0] !== "http" && split[0] !== "https" && split[0] !== "chrome-extension") { switch (split.length) { case 1: plane.value = split[0]; break; case 2: cluster.value = split[0]; plane.value = split[1]; break; case 3: universe.value = split[0]; cluster.value = split[1]; plane.value = split[2]; break; case 4: space.value = split[0]; universe.value = split[1]; cluster.value = split[2]; plane.value = split[3]; break; case 5: path.value = split[0]; space.value = split[1]; universe.value = split[2]; cluster.value = split[3]; plane.value = split[4]; break; case 6: host.value = split[0]; path.value = split[1]; space.value = split[2]; universe.value = split[3]; cluster.value = split[4]; plane.value = split[5]; break; default: const url = { protocol: { value: protocol, secure: true }, host: host, path: path, space: space, universe: universe, cluster: cluster, plane: plane, valid: valid }; return url; } } else { switch (split.length) { case 3: protocol = split[0]; host.value = split[1]; path.value = split[2]; break; case 7: protocol = split[0]; host.value = split[1]; path.value = split[2]; space.value = split[3]; universe.value = split[4]; cluster.value = split[5]; plane.value = split[6]; break; default: const url = { protocol: { value: protocol, secure: true }, host: host, path: path, space: space, universe: universe, cluster: cluster, plane: plane, valid: valid }; return url; } } const url = { protocol: { value: protocol, secure: true }, host: host, path: path, space: space, universe: universe, cluster: cluster, plane: plane, valid: true }; return url; }; const resolveRoute = (route, protocol, host) => { const windowProtocol = typeof window === "undefined" ? protocol || "http" : window.location.protocol.replace(":", ""); const windowHost = typeof window === "undefined" ? host || "localhost:63000" : window.location.host; const divisions = pluridLinkPathDivider(route); const defaultPathname = typeof window !== "undefined" ? window.location.pathname === "/" ? "p" : window.location.pathname.slice(1) : divisions.path.value ? divisions.path.value : "p"; const protocolDivision = divisions.protocol.value || windowProtocol; const hostDivision = divisions.host.value ? divisions.host : { value: windowHost, controlled: true }; const path = divisions.path.value ? divisions.path : { value: defaultPathname, parameters: {}, query: {} }; const space = divisions.space.value ? divisions.space : { value: "s", parameters: {}, query: {} }; const universe = divisions.universe.value ? divisions.universe : { value: "u", parameters: {}, query: {} }; const cluster = divisions.cluster.value ? divisions.cluster : { value: "c", parameters: {}, query: {} }; const plane = divisions.plane; const separator = "://"; if (!plane.value && route !== "/") { const resolvers = [ protocolDivision, hostDivision.value, path.value ]; const absoluteRoute = resolvers.join(separator); return { protocol: protocolDivision, host: hostDivision, path: path, space: space, universe: universe, cluster: cluster, plane: plane, route: absoluteRoute }; } [ protocolDivision, hostDivision.value, path.value, space.value, universe.value, cluster.value, cleanPathElement(plane.value) ]; return { protocol: "", host: "", path: path, space: "", universe: "", cluster: "", plane: "", route: route }; }; const updateTreePlane$1 = (tree, page) => { const updatedTree = tree.map((treePlane => { if (treePlane.planeID === page.planeID) { return Object.assign({}, page); } if (treePlane.children) { return Object.assign(Object.assign({}, treePlane), { children: updateTreePlane$1(treePlane.children, page) }); } return treePlane; })); return updatedTree; }; const updateTreeByPlaneIDWithLinkCoordinates = (tree, planeID, linkCoordinates) => { const updatedTree = tree.map((treePlane => { if (treePlane.planeID === planeID) { const updatedPlane = Object.assign(Object.assign({}, treePlane), { linkCoordinates: linkCoordinates }); return updatedPlane; } if (treePlane.children) { const updatedChildren = updateTreeByPlaneIDWithLinkCoordinates(treePlane.children, planeID, linkCoordinates); const updatedPlane = Object.assign(Object.assign({}, treePlane), { children: updatedChildren }); return updatedPlane; } return treePlane; })); return updatedTree; }; var index$i = Object.freeze({ __proto__: null, updateTreePlane: updateTreePlane$1, updateTreeByPlaneIDWithLinkCoordinates: updateTreeByPlaneIDWithLinkCoordinates }); var index$h = Object.freeze({ __proto__: null, configuration: index$k, tree: index$i }); const getWheelDirection = (deltas, ABSTHRESHOLD = 10, THRESHOLD = 0) => { let direction = "left"; const wheelDeltaX = deltas.deltaX; const wheelDeltaY = deltas.deltaY; const absWheelDeltaX = Math.abs(wheelDeltaX); const absWheelDeltaY = Math.abs(wheelDeltaY); if (wheelDeltaX > THRESHOLD && absWheelDeltaY < ABSTHRESHOLD && absWheelDeltaX > absWheelDeltaY) { direction = "left"; } if (wheelDeltaX < THRESHOLD && absWheelDeltaY < ABSTHRESHOLD && absWheelDeltaX > absWheelDeltaY) { direction = "right"; } if (wheelDeltaY > THRESHOLD && absWheelDeltaX < ABSTHRESHOLD && absWheelDeltaY > absWheelDeltaX) { direction = "up"; } if (wheelDeltaY < THRESHOLD && absWheelDeltaX < ABSTHRESHOLD && absWheelDeltaY > absWheelDeltaX) { direction = "down"; } return direction; }; var index$g = Object.freeze({ __proto__: null, getWheelDirection: getWheelDirection }); const degToRad = deg => deg * .01745329252; const radToDeg = rad => rad * 57.2957795131; const makeQuaternion = (x, y, z, w) => ({ x: x, y: y, z: z, w: w }); const zeroQuaternion = () => makeQuaternion(0, 0, 0, 0); function inverseQuaternion(quaternion) { return makeQuaternion(quaternion.x, quaternion.y, quaternion.z, -quaternion.w); } function conjugateQuaternion(quaternion) { return makeQuaternion(-quaternion.x, -quaternion.y, -quaternion.z, quaternion.w); } function computeQuaternionFromEulers(alpha, beta, gamma, radians = true) { const x = radians ? beta : degToRad(beta); const y = radians ? gamma : degToRad(gamma); const z = radians ? alpha : degToRad(alpha); const cX = Math.cos(x / 2); const cY = Math.cos(y / 2); const cZ = Math.cos(z / 2); const sX = Math.sin(x / 2); const sY = Math.sin(y / 2); const sZ = Math.sin(z / 2); const xQ = sX * cY * cZ - cX * sY * sZ; const yQ = cX * sY * cZ + sX * cY * sZ; const zQ = cX * cY * sZ + sX * sY * cZ; const wQ = cX * cY * cZ - sX * sY * sZ; return makeQuaternion(xQ, yQ, zQ, wQ); } function quaternionFromAxisAngle(x, y, z, angle) { const q = zeroQuaternion(); const halfAngle = angle / 2; const sine = Math.sin(halfAngle); q.x = x * sine; q.y = y * sine; q.z = z * sine; q.w = Math.cos(halfAngle); return q; } function quaternionMultiply(quaternionArray) { const firstQuaternion = quaternionArray[0]; const valueQuaternion = Object.assign({}, firstQuaternion); for (let i = 1; i < quaternionArray.length; i++) { const nextQuaternion = quaternionArray[i]; const w = valueQuaternion.w * nextQuaternion.w - valueQuaternion.x * nextQuaternion.x - valueQuaternion.y * nextQuaternion.y - valueQuaternion.z * nextQuaternion.z; const x = valueQuaternion.x * nextQuaternion.w + valueQuaternion.w * nextQuaternion.x + valueQuaternion.y * nextQuaternion.z - valueQuaternion.z * nextQuaternion.y; const y = valueQuaternion.y * nextQuaternion.w + valueQuaternion.w * nextQuaternion.y + valueQuaternion.z * nextQuaternion.x - valueQuaternion.x * nextQuaternion.z; const z = valueQuaternion.z * nextQuaternion.w + valueQuaternion.w * nextQuaternion.z + valueQuaternion.x * nextQuaternion.y - valueQuaternion.y * nextQuaternion.x; valueQuaternion.x = x; valueQuaternion.y = y; valueQuaternion.z = z; valueQuaternion.w = w; } return valueQuaternion; } function rotatePointViaQuaternion(pointRotate, quaternion) { const temporaryQuaternion = { x: pointRotate[0], y: pointRotate[1], z: pointRotate[2], w: 0 }; const rotatedPointQuaternion = quaternionMultiply([ quaternion, temporaryQuaternion, conjugateQuaternion(quaternion) ]); return rotatedPointQuaternion; } function makeRotationMatrixFromQuaternion(quaternion) { const num = quaternion.x * 2; const num2 = quaternion.y * 2; const num3 = quaternion.z * 2; const num4 = quaternion.x * num; const num5 = quaternion.y * num2; const num6 = quaternion.z * num3; const num7 = quaternion.x * num2; const num8 = quaternion.x * num3; const num9 = quaternion.y * num3; const num10 = quaternion.w * num; const num11 = quaternion.w * num2; const num12 = quaternion.w * num3; return [ 1 - (num5 + num6), num7 - num12, num8 + num11, 0, num7 + num12, 1 - (num4 + num6), num9 - num10, 0, num8 - num11, num9 + num10, 1 - (num4 + num5), 0, 0, 0, 0, 1 ]; } var index$f = Object.freeze({ __proto__: null, degToRad: degToRad, radToDeg: radToDeg, makeQuaternion: makeQuaternion, zeroQuaternion: zeroQuaternion, inverseQuaternion: inverseQuaternion, conjugateQuaternion: conjugateQuaternion, computeQuaternionFromEulers: computeQuaternionFromEulers, quaternionFromAxisAngle: quaternionFromAxisAngle, quaternionMultiply: quaternionMultiply, rotatePointViaQuaternion: rotatePointViaQuaternion, makeRotationMatrixFromQuaternion: makeRotationMatrixFromQuaternion }); function rotateMatrix(xAngle, yAngle, zAngle = 0) { const xQuaternion = computeQuaternionFromEulers(0, xAngle, 0); const yQuaternion = computeQuaternionFromEulers(0, 0, yAngle); const zQuaternion = computeQuaternionFromEulers(zAngle, 0, 0); const quartenionMultiplication = quaternionMultiply([ yQuaternion, xQuaternion, zQuaternion ]); const rotationMatrix = makeRotationMatrixFromQuaternion(quartenionMultiplication); return rotationMatrix; } function translateMatrix$1(x, y, z) { return [ 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, x, y, z, 1 ]; } function scaleMatrix$1(s) { return [ s, 0, 0, 0, 0, s, 0, 0, 0, 0, s, 0, 0, 0, 0, 1 ]; } function multiplyMatrices$1(matrixA, matrixB) { const result = []; const a00 = matrixA[0]; const a01 = matrixA[1]; const a02 = matrixA[2]; const a03 = matrixA[3]; const a10 = matrixA[4]; const a11 = matrixA[5]; const a12 = matrixA[6]; const a13 = matrixA[7]; const a20 = matrixA[8]; const a21 = matrixA[9]; const a22 = matrixA[10]; const a23 = matrixA[11]; const a30 = matrixA[12]; const a31 = matrixA[13]; const a32 = matrixA[14]; const a33 = matrixA[15]; let b0 = matrixB[0]; let b1 = matrixB[1]; let b2 = matrixB[2]; let b3 = matrixB[3]; result[0] = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30; result[1] = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31; result[2] = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32; result[3] = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33; b0 = matrixB[4]; b1 = matrixB[5]; b2 = matrixB[6]; b3 = matrixB[7]; result[4] = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30; result[5] = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31; result[6] = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32; result[7] = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33; b0 = matrixB[8]; b1 = matrixB[9]; b2 = matrixB[10]; b3 = matrixB[11]; result[8] = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30; result[9] = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31; result[10] = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32; result[11] = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33; b0 = matrixB[12]; b1 = matrixB[13]; b2 = matrixB[14]; b3 = matrixB[15]; result[12] = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30; result[13] = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31; result[14] = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32; result[15] = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33; return result; } function multiplyArrayOfMatrices(matrices) { let inputMatrix = matrices[0]; for (let i = 1; i < matrices.length; i++) { inputMatrix = multiplyMatrices$1(inputMatrix, matrices[i]); } return inputMatrix; } function matrixArrayToCSSMatrix(array) { return "matrix3d(" + array.join(",") + ")"; } var index$e = Object.freeze({ __proto__: null, rotateMatrix: rotateMatrix, translateMatrix: translateMatrix$1, scaleMatrix: scaleMatrix$1, multiplyMatrices: multiplyMatrices$1, multiplyArrayOfMatrices: multiplyArrayOfMatrices, matrixArrayToCSSMatrix: matrixArrayToCSSMatrix }); const getInitialMatrix = () => { const matrix = [ [ 1, 0, 0, 0 ], [ 0, 1, 0, 0 ], [ 0, 0, 1, 0 ], [ 0, 0, 0, 1 ] ]; return matrix; }; const multiplyMatrices = (m1, m2) => { const result = []; for (let i = 0; i < m1.length; i++) { result[i] = []; for (let j = 0; j < m2[0].length; j++) { let sum = 0; for (let k = 0; k < m1[0].length; k++) { sum += m1[i][k] * m2[k][j]; } result[i][j] = sum; } } return result; }; const multiplyMatricesArray = matrices => { if (matrices.length < 2) { throw new Error("invalid number of matrices"); } const first = matrices[0]; let result = first; for (const [index, matrix] of matrices.entries()) { if (index === 0) { continue; } result = multiplyMatrices(result, matrix); } return result; }; const arrayToMatrix = array => { const matrix = []; for (let i = 0; i < array.length; i += 4) { const row = []; row.push(array[i]); row.push(array[i + 1]); row.push(array[i + 2]); row.push(array[i + 3]); matrix.push(row); } return matrix; }; const matrixToArray = matrix => matrix.flat(); const matrix3DToMatrix = value => { const values = value.replace("matrix3d(", "").replace(")", "").split(",").map((val => parseFloat(val))); return arrayToMatrix(values); }; const printMatrix = (matrix, name) => { const normalize = value => { if (value === 1 || value === 0) { return value + " "; } if (value > 0) { return value.toFixed(2) + " "; } return value.toFixed(2) + " "; }; console.log("matrix", name + ":"); for (const row of matrix) { console.log(normalize(row[0]), normalize(row[1]), normalize(row[2]), normalize(row[3])); } console.log(`matrix3d(${matrix.flat().join(",")})`); console.log(); }; const rotateXMatrix = angle => { const x = Math.cos(angle); const y = -1 * Math.sin(angle); const z = Math.sin(angle); const m = [ [ 1, 0, 0, 0 ], [ 0, x, y, 0 ], [ 0, z, x, 0 ], [ 0, 0, 0, 1 ] ]; return m; }; const rotateYMatrix = angle => { const x = Math.cos(angle); const y = -1 * Math.sin(angle); const z = Math.sin(angle); const m = [ [ x, 0, z, 0 ], [ 0, 1, 0, 0 ], [ y, 0, x, 0 ], [ 0, 0, 0, 1 ] ]; return m; }; const rotateZMatrix = angle => { const x = Math.cos(angle); const y = -1 * Math.sin(angle); const z = Math.sin(angle); const m = [ [ x, y, 0, 0 ], [ z, x, 0, 0 ], [ 0, 0, 1, 0 ], [ 0, 0, 0, 1 ] ]; return m; }; const translateMatrix = (x = 0, y = 0, z = 0) => { const m = [ [ 1, 0, 0, 0 ], [ 0, 1, 0, 0 ], [ 0, 0, 1, 0 ], [ x, y, z, 1 ] ]; return m; }; const scaleMatrix = s => [ [ s, 0, 0, 0 ], [ 0, s, 0, 0 ], [ 0, 0, s, 0 ], [ 0, 0, 0, 1 ] ]; function rotationMatrixFromQuaternion(quaternion) { const num = quaternion.x * 2; const num2 = quaternion.y * 2; const num3 = quaternion.z * 2; const num4 = quaternion.x * num; const num5 = quaternion.y * num2; const num6 = quaternion.z * num3; const num7 = quaternion.x * num2; const num8 = quaternion.x * num3; const num9 = quaternion.y * num3; const num10 = quaternion.w * num; const num11 = quaternion.w * num2; const num12 = quaternion.w * num3; return [ [ 1 - (num5 + num6), num7 - num12, num8 + num11, 0 ], [ num7 + num12, 1 - (num4 + num6), num9 - num10, 0 ], [ num8 - num11, num9 + num10, 1 - (num4 + num5), 0 ], [ 0, 0, 0, 1 ] ]; } const matrixToCSSMatrix = matrix => { const value = matrix.flat().join(","); return `matrix3d(${value})`; }; const identityMatrix = () => { const matrix = [ [ 1, 0, 0, 0 ], [ 0, 1, 0, 0 ], [ 0, 0, 1, 0 ], [ 0, 0, 0, 1 ] ]; return matrix; }; const inverseMatrix = matrix => { const cols = 4; const rows = 4; const A = [ ...matrix ]; const B = identityMatrix(); let r; let s; let f; let temp; for (let c = 0; c < cols; c++) { let ABig = Math.abs(A[c][c]); let rBig = c; r = c + 1; while (r < rows) { if (Math.abs(A[r][c]) > ABig) { ABig = Math.abs(A[r][c]); rBig = r; } r++; } if (ABig === 0) { throw Error("Cannot calculate inverse, determinant is zero"); } r = rBig; if (r !== c) { temp = A[c]; A[c] = A[r]; A[r] = temp; temp = B[c]; B[c] = B[r]; B[r] = temp; } const Ac = A[c]; const Bc = B[c]; for (r = 0; r < rows; r++) { const Ar = A[r]; const Br = B[r]; if (r !== c) { if (Ar[c] !== 0) { f = -Ar[c] / Ac[c]; for (s = c; s < cols; s++) { Ar[s] = Ar[s] + f * Ac[s]; } for (s = 0; s < cols; s++) { Br[s] = Br[s] + f * Bc[s]; } } } else { f = Ac[c]; for (s = c; s < cols; s++) { Ar[s] = Ar[s] / f; } for (s = 0; s < cols; s++) { Br[s] = Br[s] / f; } } } } return B; }; var index$d = Object.freeze({ __proto__: null, getInitialMatrix: getInitialMatrix, multiplyMatrices: multiplyMatrices, multiplyMatricesArray: multiplyMatricesArray, arrayToMatrix: arrayToMatrix, matrixToArray: matrixToArray, matrix3DToMatrix: matrix3DToMatrix, printMatrix: printMatrix, rotateXMatrix: rotateXMatrix, rotateYMatrix: rotateYMatrix, rotateZMatrix: rotateZMatrix, translateMatrix: translateMatrix, scaleMatrix: scaleMatrix, rotationMatrixFromQuaternion: rotationMatrixFromQuaternion, matrixToCSSMatrix: matrixToCSSMatrix, identityMatrix: identityMatrix, inverseMatrix: inverseMatrix }); function getMatrixValues(matrix3d) { const matrixValues = matrix3d.split("(")[1].split(")")[0].split(","); const matrixValuesInt = []; for (let i = 0; i < matrixValues.length; i++) { matrixValuesInt[i] = parseFloat(matrixValues[i]); } return matrixValuesInt; } function getRotationMatrix(matrix3d) { const valuesMatrix = getMatrixValues(matrix3d); const scale = getScalationValue(matrix3d); if (valuesMatrix.length === 16) { for (let i = 0; i < 11; i++) { valuesMatrix[i] /= scale; } } else if (valuesMatrix.length === 6) { for (let i = 0; i < 4; i++) { valuesMatrix[i] /= scale; } } const rotationMatrix = valuesMatrix; return rotationMatrix; } function getTranslationMatrix(matrix3d) { const valuesMatrix = getMatrixValues(matrix3d); let translationMatrix; if (valuesMatrix.length === 16) { translationMatrix = getMatrixValues(matrix3d).slice(12, 15); } else if (valuesMatrix.length === 6) { translationMatrix = getMatrixValues(matrix3d).slice(4); } return translationMatrix; } function getScalationValue(matrix3d) { const valuesMatrix = getMatrixValues(matrix3d); let temp = 0; let scale; if (valuesMatrix.length === 16) { const scaleMatrix = getMatrixValues(matrix3d).slice(0, 4); scale = 0; for (const el of scaleMatrix) { scale += parseFloat(el) * parseFloat(el); } scale = parseFloat(Math.sqrt(scale).toPrecision(4)); } else if (valuesMatrix.length === 6) { temp = valuesMatrix[0] * valuesMatrix[0] + valuesMatrix[1] * valuesMatrix[1]; scale = parseFloat(Math.sqrt(temp).toPrecision(4)); } return scale; } function setTransform(rotationMatrix, translationMatrix, scalationMatrix) { const transformMatrix = multiplyArrayOfMatrices([ translationMatrix, rotationMatrix, scalationMatrix ]); return matrixArrayToCSSMatrix(transformMatrix); } function getTransformRotate(matrix3d) { const pi = Math.PI; const values = getRotationMatrix(matrix3d); let rotateX = 0; let rotateY = 0; if (values.length === 6) { const cosa = values[0]; const sina = values[1]; if (cosa === 1 && sina === 0) { rotateX = Math.asin(sina); rotateY = Math.acos(cosa); } } if (values.length === 16) { const cosaX1 = values[5]; const sinaX3 = values[9]; if (sinaX3 <= 0) { rotateX = Math.acos(cosaX1); } if (sinaX3 > 0) { rotateX = 2 * pi - Math.acos(cosaX1); } const cosaY1 = values[0]; const sinaY2 = values[2]; if (sinaY2 <= 0) { rotateY = Math.acos(cosaY1); } if (sinaY2 > 0) { rotateY = 2 * pi - Math.acos(cosaY1); } rotateX = Math.atan2(values[9], values[5]); rotateY = Math.atan2(values[2], values[0]); } return { rotateX: rotateX, rotateY: rotateY, rotateZ: 0 }; } function getTransformTranslate(matrix3d) { const values = getTranslationMatrix(matrix3d); const translateX = values[0]; const translateY = values[1]; const translateZ = values[2]; return { translateX: translateX, translateY: translateY, translateZ: translateZ }; } function getTransformScale(matrix3d) { const scale = getScalationValue(matrix3d); return { scale: scale }; } function rotatePlurid(matrix3d, direction = "", angleIncrement = .07) { const transformRotate = getTransformRotate(matrix3d); const rotateX = transformRotate.rotateX; let rotateY = transformRotate.rotateY; const rotateZ = transformRotate.rotateZ; const transformTranslate = getTransformTranslate(matrix3d); const translateX = transformTranslate.translateX; const translateY = transformTranslate.translateY; const translateZ = transformTranslate.translateZ; const scale = getTransformScale(matrix3d).scale; let valRotationMatrix = rotateMatrix(rotateX, rotateY, rotateZ); const valTranslationMatrix = translateMatrix$1(translateX, translateY, translateZ); const valScalationMatrix = scaleMatrix$1(scale); if (direction === "left") { rotateY -= angleIncrement; valRotationMatrix = rotateMatrix(rotateX, rotateY); } if (direction === "right") { rotateY += angleIncrement; valRotationMatrix = rotateMatrix(rotateX, rotateY); } if (direction === "up") { rotateY -= angleIncrement; valRotationMatrix = rotateMatrix(rotateX, rotateY); } if (direction === "down") { rotateY += angleIncrement; valRotationMatrix = rotateMatrix(rotateX, rotateY); } const transformedMatrix3d = setTransform(valRotationMatrix, valTranslationMatrix, valScalationMatrix); return transformedMatrix3d; } function translatePlurid(matrix3d, direction = "", linearIncrement = 50) { const transformRotate = getTransformRotate(matrix3d); const rotateX = transformRotate.rotateX; const rotateY = transformRotate.rotateY; const rotateZ = transformRotate.rotateZ; const transformTranslate = getTransformTranslate(matrix3d); let translateX = transformTranslate.translateX; let translateY = transformTranslate.translateY; const translateZ = transformTranslate.translateZ; const scale = getTransformScale(matrix3d).scale; const valRotationMatrix = rotateMatrix(rotateX, rotateY, rotateZ); let valTranslationMatrix = translateMatrix$1(translateX, translateY, translateZ); const valScalationMatrix = scaleMatrix$1(scale); scale < .5 ? linearIncrement = 50 : linearIncrement = 30; if (direction === "left") { translateX += linearIncrement; valTranslationMatrix = translateMatrix$1(translateX, translateY, translateZ); } if (direction === "right") { translateX -= linearIncrement; valTranslationMatrix = translateMatrix$1(translateX, translateY, translateZ); } if (direction === "up") { translateY += linearIncrement; valTranslationMatrix = translateMatrix$1(translateX, translateY, translateZ); } if (direction === "down") { translateY -= linearIncrement; valTranslationMatrix = translateMatrix$1(translateX, translateY, translateZ); } const transformedMatrix3d = setTransform(valRotationMatrix, valTranslationMatrix, valScalationMatrix); return transformedMatrix3d; } function scalePlurid(matrix3d, direction = "", scaleIncrement = .05) { const transformRotate = getTransformRotate(matrix3d); const rotateX = transformRotate.rotateX; const rotateY = transformRotate.rotateY; const rotateZ = transformRotate.rotateZ; const transformTranslate = getTransformTranslate(matrix3d); const translateX = transformTranslate.translateX; const translateY = transformTranslate.translateY; const translateZ = transformTranslate.translateZ; let scale = getTransformScale(matrix3d).scale; const valRotationMatrix = rotateMatrix(rotateX, rotateY, rotateZ); const valTranslationMatrix = translateMatrix$1(translateX, translateY, translateZ); let valScalationMatrix = scaleMatrix$1(scale); if (direction === "up") { scale -= scaleIncrement; if (scale < .1) { scale = .1; } valScalationMatrix = scaleMatrix$1(scale); } if (direction === "down") { scale += scaleIncrement; if (scale > 4) { scale = 4; } valScalationMatrix = scaleMatrix$1(scale); } const transformedMatrix3d = setTransform(valRotationMatrix, valTranslationMatrix, valScalationMatrix); return transformedMatrix3d; } var index$c = Object.freeze({ __proto__: null, getMatrixValues: getMatrixValues, getRotationMatrix: getRotationMatrix, getTranslationMatrix: getTranslationMatrix, getScalationValue: getScalationValue, setTransform: setTransform, getTransformRotate: getTransformRotate, getTransformTranslate: getTransformTranslate, getTransformScale: getTransformScale, rotatePlurid: rotatePlurid, translatePlurid: translatePlurid, scalePlurid: scalePlurid }); var index$b = Object.freeze({ __proto__: null, general: index$d, matrix3d: index$c }); var index$a = Object.freeze({ __proto__: null, direction: index$g, matrix: index$e, quaternion: index$f, transform: index$b }); const internatiolate = (lamguage, field) => internationalization[lamguage][field]; const resolvePluridPlaneData = plane => { if (Array.isArray(plane)) { const [route, component, options] = plane; return Object.assign({ route: route, component: component }, options); } return plane; }; const resolvePluridRoutePlaneData = plane => { if (Array.isArray(plane)) { const [value, component, options] = plane; return Object.assign({ value: value, component: component }, options); } return plane; }; const getPluridPlaneIDByData = element => { if (!element) { return ""; } const parent = element.parentElement; if (parent && parent.dataset.pluridPlane) { return parent.dataset.pluridPlane; } return getPluridPlaneIDByData(parent); }; class IsoMatcher { constructor(data, origin = "origin") { this.routesIndex = new Map; this.planesIndex = new Map; this.routesKeys = []; this.planesKeys = []; if (origin === "origin" && typeof location !== "undefined" && location.host) { this.origin = location.host; } else { this.origin = origin; } this.updateIndexes(data.routes || [], data.routePlanes || [], data.planes || []); } match(path, context = "plane") { switch (context) { case "plane": return this.matchPlane(path); case "route": return this.matchRoute(path); } } index(data) { this.updateIndexes(data.routes || [], data.routePlanes || [], data.planes || []); } clear() { this.routesIndex = new Map; this.planesIndex = new Map; this.routesKeys = []; this.planesKeys = []; } getPlanesIndex() { return this.planesIndex; } updateIndexes(routes, routePlanes, planes) { this.indexPlanes(planes, "Plane"); this.indexPlanes(routePlanes, "RoutePlane"); for (const route of routes) { if (route.planes) { this.indexPlanes(route.planes, "RoutePlane", route.value); } this.routesIndex.set(route.value, { data: Object.assign({}, route) }); } this.routesKeys = Array.from(this.routesIndex.keys()); this.planesKeys = Array.from(this.planesIndex.keys()); } indexPlanes(planes, kind, parent) { for (const plane of planes) { const planeData = kind === "Plane" ? resolvePluridPlaneData(plane) : resolvePluridRoutePlaneData(plane); const address = computePlaneAddress(kind === "Plane" ? planeData.route : planeData.value, parent, this.origin); const indexedPlane = { kind: kind, data: Object.assign({}, planeData) }; if (parent) { indexedPlane["parent"] = parent; } this.planesIndex.set(address, indexedPlane); } } matchPlane(value) { const planeAddress = computePlaneAddress(value, undefined, this.origin); const plane = this.planesIndex.get(planeAddress); if (plane) { const query = extractQuery(value); const fragments = extractFragments(value); const match = { value: planeAddress, fragments: fragments, query: query, parameters: {} }; if (plane.kind === "Plane") { const {kind: kind, data: data, parent: parent} = plane; const result = { kind: kind, data: data, parent: parent, match: match }; return result; } if (plane.kind === "RoutePlane") { const {kind: kind, data: data, parent: parent} = plane; const result = { kind: kind, data: data, parent: parent, match: match }; return result; } } for (const planePath of this.planesKeys) { const normalizedPlanePath = planePath.replace(protocols.plurid, ""); const normalizedPlaneAddress = planeAddress.replace(protocols.plurid, ""); const planePathSplit = normalizedPlanePath.split("/"); const planeAddressSplit = normalizedPlaneAddress.split("/"); if (planePathSplit[0] !== planeAddressSplit[0]) { continue; } if (planePathSplit.length !== planeAddressSplit.length) { continue; } const parametersAndMatch = extractParametersAndMatch(normalizedPlaneAddress, normalizedPlanePath); if (parametersAndMatch.match) { const plane = this.planesIndex.get(planePath); if (!plane) { return; } const {parameters: parameters} = parametersAndMatch; const validPath = checkValidPath(plane.data.parameters, parameters); if (!validPath) { return; } const query = extractQuery(value); const fragments = extractFragments(value); const match = { value: planeAddress, fragments: fragments, query: query, parameters: parameters }; if (plane.kind === "Plane") { const {kind: kind, data: data, parent: parent} = plane; const result = { kind: kind, data: data, parent: parent, match: match }; return result; } if (plane.kind === "RoutePlane") { const {kind: kind, data: data, parent: parent} = plane; const result = { kind: kind, data: data, parent: parent, match: match }; return result; } } } return; } matchRoute(value) { const routeValue = cleanPathValue(value); const route = this.routesIndex.get(routeValue); if (route) { const query = extractQuery(value); const result = { kind: "Route", data: route.data, match: { value: routeValue, query: query, parameters: {} } }; return result; } for (const routePath of this.routesKeys) { const routeSplit = routePath.split("/"); const valueSplit = routeValue.split("/"); if (routeSplit.length !== valueSplit.length) { continue; } const parametersAndMatch = extractParametersAndMatch(routeValue.slice(1), routePath.slice(1)); if (parametersAndMatch.match) { const route = this.routesIndex.get(routePath); if (!route) { return; }