diff --git a/.babelrc b/.babelrc index 723ea646..fcbe5857 100644 --- a/.babelrc +++ b/.babelrc @@ -1,9 +1,13 @@ { "presets": [ - ["env", { - "modules": false - }], - "stage-0", - "react" - ] -} + [ + "@babel/preset-env", + { + "modules": false + } + ], + "@babel/preset-typescript", + "@babel/preset-react" + ], + "plugins": ["@babel/plugin-transform-runtime"] +} \ No newline at end of file diff --git a/.eslintrc b/.eslintrc index 31211a37..6a067032 100644 --- a/.eslintrc +++ b/.eslintrc @@ -3,5 +3,9 @@ "globals": { "cy": true, "Cypress": true + }, + "plugins": ["eslint-plugin-tsdoc"], + "rules": { + "tsdoc/syntax": "warn" } } diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 00000000..cac0e10e --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "editor.formatOnSave": true +} \ No newline at end of file diff --git a/docs/docs/saving-nodes.mdx b/docs/docs/saving-nodes.mdx index a7fbc5d1..6817e034 100644 --- a/docs/docs/saving-nodes.mdx +++ b/docs/docs/saving-nodes.mdx @@ -15,6 +15,12 @@ import config from './config' const App = () => { const [nodes, setNodes] = React.useState({}) + + React.useCallback((nodes) => { + // Do whatever you want with the nodes + setNodes(nodes) + }, []) + return (
{ The `onChange` handler will be called any time any of the nodes change? This includes any time their position or control values change. +:::warning +It's critical to note that the `onChange` handler **MUST** be memoized. If you don't memoize the handler you will get an infinite loop. +::: + + ## `getNodes` Because the `onChange` handler may be called quite often, there are times you may want to only get out the nodes when the user is done editing. For these times the node editor provides an imperative handler for extracting the nodes. diff --git a/example/package.json b/example/package.json index 945bbaff..6cbc3d3d 100644 --- a/example/package.json +++ b/example/package.json @@ -6,6 +6,10 @@ "dependencies": { "@emotion/core": "^10.0.28", "@emotion/styled": "^10.0.27", + "@types/jest": "^29.5.0", + "@types/node": "^18.15.3", + "@types/react": "^18.0.28", + "@types/react-dom": "^18.0.11", "axios": "^0.19.2", "decode-query-string": "^0.1.2", "docz": "^2.3.1", @@ -17,8 +21,9 @@ "react": "link:../node_modules/react", "react-dom": "link:../node_modules/react-dom", "react-router": "^5.1.2", - "react-router-dom": "^5.1.2", - "react-scripts": "5.0.1" + "react-router-dom": "5.3.3", + "react-scripts": "^5.0.1", + "typescript": "^5.0.2" }, "scripts": { "start": "react-scripts start", @@ -29,6 +34,12 @@ "docz:build": "DOCZ_SOURCE=./src docz build", "docz:serve": "DOCZ_SOURCE=./src docz build && docz serve" }, + "eslintConfig": { + "extends": [ + "react-app", + "react-app/jest" + ] + }, "browserslist": { "production": [ ">0.2%", @@ -40,5 +51,6 @@ "last 1 firefox version", "last 1 safari version" ] - } + }, + "devDependencies": {} } diff --git a/example/src/App.js b/example/src/App.tsx similarity index 96% rename from example/src/App.js rename to example/src/App.tsx index 1c19e013..bad82684 100644 --- a/example/src/App.js +++ b/example/src/App.tsx @@ -6,7 +6,8 @@ import { Controls, Colors, RootEngine, - useRootEngine + useRootEngine, + NodeMap } from "node-editor"; const colors = [ @@ -212,7 +213,7 @@ flumeConfig type: "multiColor", name: "multiColor", label: "Multicolor", - multiColor: Colors.grey, + // multiColor: Colors.grey, controls: [ Controls.multiselect({ name: "multiColor", @@ -635,7 +636,7 @@ const App = () => { border: "none", padding: 0, fontSize: 14, - color: '#222' + color: "#222" }} onClick={actions.openMenu} > @@ -645,7 +646,7 @@ const App = () => { ); }} - // debug + debug />
@@ -656,25 +657,38 @@ const App = () => { export default App; -const useInfiniteEngine = (nodes, engine, context, options = {}) => - Object.keys(nodes).length ? engine.resolveRootNode(nodes, { context, ...options }) : {}; +const useInfiniteEngine = ( + nodes: NodeMap, + engine: RootEngine, + context: any, + options = {} +): T => + Object.keys(nodes).length + ? engine.resolveRootNode(nodes, { context, ...options }) + : ({} as T); -const Website = ({ nodes }) => { +const Website = ({ nodes }: { nodes: NodeMap }) => { const { title, description, showDashboard, - showContactForm, - showLoginButton - } = useInfiniteEngine(nodes, engine, { someContext: true }, { maxLoops: 10 }); + showBody, + showLogin + } = useInfiniteEngine<{ + title: string; + description: string; + showDashboard: boolean; + showBody: boolean; + showLogin: boolean; + }>(nodes, engine, { someContext: true }, { maxLoops: 10 }); return (

{title}

{description}

{showDashboard &&
Dashboard
} - {showContactForm &&
Contact Form
} - {showLoginButton && } + {showBody &&
Contact Form
} + {showLogin && }
); }; diff --git a/example/src/TestRoutes/TestEditor.js b/example/src/TestRoutes/TestEditor.js deleted file mode 100644 index 21e7e0fb..00000000 --- a/example/src/TestRoutes/TestEditor.js +++ /dev/null @@ -1,79 +0,0 @@ -import React from "react"; -import "normalize.css"; - -import { NodeEditor } from "node-editor"; - -const Log = console.log; - -const TestEditor = () => { - const [output, setOutput] = React.useState(); - - React.useEffect(() => { - console.log = log => { - Log(log); - if(typeof log === 'object'){ - setOutput(JSON.stringify(log)) - } - } - return () => { - console.log = Log - } - }) - return ( -
- -
{output}
-
- ); -}; - -export default TestEditor; diff --git a/example/src/TestRoutes/TestEditor.tsx b/example/src/TestRoutes/TestEditor.tsx new file mode 100644 index 00000000..7a7914a6 --- /dev/null +++ b/example/src/TestRoutes/TestEditor.tsx @@ -0,0 +1,74 @@ +import React from "react"; +import "normalize.css"; + +import { Controls, FlumeConfig, NodeEditor } from "node-editor"; + +const Log = console.log; + +const config = new FlumeConfig() + .addPortType({ + type: "number", + name: "number", + label: "Number", + controls: [ + Controls.number({ + name: "number" + }) + ] + }) + .addNodeType({ + type: "number", + label: "Number", + initialWidth: 150, + inputs: ports => [ports.number()], + outputs: ports => [ports.number()] + }) + .addNodeType({ + type: "addNumbers", + label: "Add Numbers", + initialWidth: 150, + inputs: ports => [ + ports.number({ + name: "num1" + }), + ports.number({ + name: "num2" + }) + ], + outputs: ports => [ + ports.number({ + name: "result" + }) + ] + }); + +const TestEditor = () => { + const [output, setOutput] = React.useState(); + + React.useEffect(() => { + console.log = log => { + Log(log); + if (typeof log === "object") { + setOutput(JSON.stringify(log)); + } + }; + return () => { + console.log = Log; + }; + }); + return ( +
+ +
+ {output} +
+
+ ); +}; + +export default TestEditor; diff --git a/example/src/TestRoutes/nodes.js b/example/src/TestRoutes/nodes.tsx similarity index 100% rename from example/src/TestRoutes/nodes.js rename to example/src/TestRoutes/nodes.tsx diff --git a/example/src/components/Checkbox.js b/example/src/components/Checkbox.js deleted file mode 100644 index 6686b816..00000000 --- a/example/src/components/Checkbox.js +++ /dev/null @@ -1,22 +0,0 @@ -import React from "react"; -import { nanoid }from "nanoid"; - -const Checkbox = ({ label, value, onChange }) => { - const id = React.useRef(nanoid(10)); - - return ( -
- onChange(e.target.checked)} - /> - - -
- ); -}; - -export default Checkbox; \ No newline at end of file diff --git a/example/src/components/FloatingNavigation.js b/example/src/components/FloatingNavigation.js deleted file mode 100644 index 459c116e..00000000 --- a/example/src/components/FloatingNavigation.js +++ /dev/null @@ -1,73 +0,0 @@ -import React from "react"; -import { Link } from "react-router-dom"; -import BoxIcon from "../icons/BoxIcon"; -import FormIcon from "../icons/FormIcon"; -import GearIcon from "../icons/GearIcon"; -import { Portal } from "react-portal"; - -const FloatingNavigation = () => { - const [menuOpen, setMenuOpen] = React.useState(); - - const openMenu = () => { - setMenuOpen(true); - }; - - const closeMenu = () => { - setMenuOpen(false); - }; - - return ( - -
-
- - - - - - - - - -
- -
-
- - ); -}; - -export default FloatingNavigation; - -const HoverLink = ({ to, children, label, style }) => { - const [showLabel, setShowLabel] = React.useState(false); - - return ( - - -
- {label} -
-
- setShowLabel(true)} - onMouseLeave={() => setShowLabel(false)} - > - {children} - -
- ); -}; - -const NavIcon = ({ menuOpen }) => ( -
-
-
-
-
-); diff --git a/example/src/components/Header.js b/example/src/components/Header.js deleted file mode 100644 index 01d1b4b9..00000000 --- a/example/src/components/Header.js +++ /dev/null @@ -1,16 +0,0 @@ -import React from 'react' - -export default () => { - - return ( -
-
-
- - - -
-
-
- ) -} diff --git a/example/src/components/LogicEditor.js b/example/src/components/LogicEditor.js deleted file mode 100644 index 1dfc13ce..00000000 --- a/example/src/components/LogicEditor.js +++ /dev/null @@ -1,52 +0,0 @@ -import React from "react"; -import Modal from "./Modal"; -import { NodeEditor } from "node-editor"; - -const LogicEditor = ({ - isOpen, - onCloseRequested, - nodeTypes, - inputTypes, - defaultNodes, - nodes, - onChange, - context = {} -}) => { - const nodeEditor = React.useRef(); - - const saveNodes = () => { - const nodes = nodeEditor.current.getNodes(); - onChange(nodes); - onCloseRequested() - }; - - return isOpen ? ( - -
-
-

Logic Editor

- -
-
- -
-
-
- ) : ( - false - ); -}; - -export default LogicEditor; \ No newline at end of file diff --git a/example/src/components/Modal.js b/example/src/components/Modal.js deleted file mode 100644 index f60c8d8e..00000000 --- a/example/src/components/Modal.js +++ /dev/null @@ -1,18 +0,0 @@ -import React from 'react' -import { Portal } from 'react-portal' - -const Modal = ({ children, onCloseRequested }) => { - - return ( - -
-
- {children} -
-
-
-
- ) -}; - -export default Modal; \ No newline at end of file diff --git a/example/src/components/OptionsEditor.js b/example/src/components/OptionsEditor.js deleted file mode 100644 index 92fc2239..00000000 --- a/example/src/components/OptionsEditor.js +++ /dev/null @@ -1,82 +0,0 @@ -import React from "react"; -import Modal from "./Modal"; - -const OptionsEditor = ({ - options: initialOptions, - onChange, - isOpen, - onCloseRequested -}) => { - const [options, setOptions] = React.useState(initialOptions); - - React.useEffect(() => { - if (isOpen === true) { - setOptions(initialOptions); - } - }, [isOpen, initialOptions]); - - const save = () => { - onChange(options) - onCloseRequested() - } - - const setOption = (opt, i) => { - setOptions(opts => [...opts.slice(0, i), opt, ...opts.slice(i + 1)]); - }; - - const addOption = () => { - setOptions(opts => ([ - ...opts, - {value: "", label: ""} - ])) - } - - return isOpen ? ( - -
-
- -
-
-
- -
-
- -
-
- {options.map((option, i) => ( - setOption(opt, i)} key={i} /> - ))} -
- -
-
-
- ) : null; -}; - -export default OptionsEditor; - -const OptionRow = ({ value, label, onChange }) => { - const handleChange = (key, val) => { - onChange({ value, label, [key]: val }); - }; - - return ( -
- handleChange("value", e.target.value)} - /> - handleChange("label", e.target.value)} - /> -
- ); -}; diff --git a/example/src/config.tsx b/example/src/config.tsx new file mode 100644 index 00000000..e69de29b diff --git a/example/src/icons/BoxIcon.js b/example/src/icons/BoxIcon.js deleted file mode 100644 index d85e5f56..00000000 --- a/example/src/icons/BoxIcon.js +++ /dev/null @@ -1,12 +0,0 @@ -import * as React from "react" - -function BoxIcon(props) { - return ( - - - - - ) -} - -export default BoxIcon diff --git a/example/src/icons/FormIcon.js b/example/src/icons/FormIcon.js deleted file mode 100644 index 159d0d82..00000000 --- a/example/src/icons/FormIcon.js +++ /dev/null @@ -1,11 +0,0 @@ -import * as React from "react" - -function FormIcon(props) { - return ( - - - - ) -} - -export default FormIcon diff --git a/example/src/icons/GearIcon.js b/example/src/icons/GearIcon.js deleted file mode 100644 index 5cd1954d..00000000 --- a/example/src/icons/GearIcon.js +++ /dev/null @@ -1,12 +0,0 @@ -import * as React from "react" - -function GearIcon(props) { - return ( - - - - - ) -} - -export default GearIcon diff --git a/example/src/index.js b/example/src/index.js deleted file mode 100644 index 2bdc216a..00000000 --- a/example/src/index.js +++ /dev/null @@ -1,65 +0,0 @@ -import React from "react"; -import ReactDOM from "react-dom/client"; -import { BrowserRouter as Router, Route, Switch } from "react-router-dom"; -import App from "./App"; -import TestEditor from './TestRoutes/TestEditor' -import Form from "./pages/Form/Form"; -import Forms from "./pages/Forms/Forms"; -import Records from "./pages/Records/Records"; -import "./index.css"; - -const FormStyles = () => ( - -); - -const root = ReactDOM.createRoot(document.getElementById("root")); - - -root.render( - - } /> - - ( - - - - - )} - /> - ( - - - - - )} - /> - ( - - -
- - )} - /> - ( - - - - - )} - /> - } /> - - -); \ No newline at end of file diff --git a/example/src/index.tsx b/example/src/index.tsx new file mode 100644 index 00000000..59dc4d6d --- /dev/null +++ b/example/src/index.tsx @@ -0,0 +1,21 @@ +import ReactDOM from "react-dom/client"; +//@ts-ignore next-line +import { BrowserRouter as Router, Route, Switch } from "react-router-dom"; +import App from "./App"; +import TestEditor from "./TestRoutes/TestEditor"; +import "./index.css"; + +const rootElement = document.getElementById("root"); + +if (rootElement) { + const root = ReactDOM.createRoot(rootElement); + + root.render( + + } /> + + } /> + + + ); +} diff --git a/example/src/pages/Form/Attributes.js b/example/src/pages/Form/Attributes.js deleted file mode 100644 index a4071ce7..00000000 --- a/example/src/pages/Form/Attributes.js +++ /dev/null @@ -1,225 +0,0 @@ -import React from "react"; -import { - DesignerStateContext, - DesignerDispatchContext, - FieldsContext, - FieldsDispatchContext -} from "./Form"; -import fieldTypes from "./fieldTypes"; -import Checkbox from "../../components/Checkbox"; -import OptionsEditor from "../../components/OptionsEditor"; -import LogicEditor from "../../components/LogicEditor"; -import NodeTypes from "./NodeTypes"; -import { getInputTypes } from "./InputTypes"; -import { NodeTypes as WizardNodeTypes, InputTypes as WizardInputTypes } from './wizardLogic/logicTypes' - -const AttributesWrapper = ({ previewing, editingWizard }) => { - const designerState = React.useContext(DesignerStateContext); - const designerDispatch = React.useContext(DesignerDispatchContext); - const fields = React.useContext(FieldsContext); - const fieldsDispatch = React.useContext(FieldsDispatchContext); - - const currentField = fields[designerState.selectedFieldId]; - const currentFieldType = currentField ? fieldTypes[currentField.type] : {}; - - const deleteField = () => { - const fieldId = designerState.selectedFieldId - - designerDispatch({ - type: "SET_SELECTED_FIELD_ID", - fieldId: null - }) - - fieldsDispatch({ - type: "REMOVE_FIELD", - fieldId - }) - } - - const setWizardTitle = title => { - designerDispatch({ - type: "SET_TITLE", - title - }) - } - - const setWizardLogic = logic => { - console.log(logic); - designerDispatch({ - type: "SET_LOGIC", - logic - }) - } - - return ( -
-
-

Attributes

- { - !editingWizard ? - - {currentField && currentFieldType ? ( - - ) : ( - No field selected - )} - {currentField && currentFieldType ? ( - - Delete Field - - ) : null} - - : - - - setWizardTitle(e.target.value)} - /> - - - - - - } -
-
- ); -}; - -export default AttributesWrapper - -const Attributes = ({ attributes = [], currentField }) => { - return attributes.map(attr => ( - - )); -}; - -const hiddenLabelTypes = ["checkbox", "options", "logic"]; - -const WizardLogic = ({logic, fields, onChange}) => { - const [modalOpen, setModalOpen] = React.useState(false); - - const closeModal = () => setModalOpen(false); - - return ( - - setModalOpen(true)}> - Edit Logic - - - - ) -} - -const Attribute = ({ field, label, name, type, value }) => { - const [modalOpen, setModalOpen] = React.useState(false); - const fieldsDispatch = React.useContext(FieldsDispatchContext); - const fields = React.useContext(FieldsContext); - - const setAttribute = value => { - fieldsDispatch({ - type: "SET_ATTRIBUTE_VALUE", - fieldId: field.id, - name, - value - }); - }; - - const closeModal = () => setModalOpen(false); - - const getAttributeField = () => { - switch (type) { - case "checkbox": - return ; - case "options": - return ( - - setModalOpen(true)}> - Edit Options - - - - ); - case "logic": - return ( - - setModalOpen(true)}> - Edit Logic - - - - ); - case "text": - default: - return ( - setAttribute(e.target.value)} - /> - ); - } - }; - - return ( - - {getAttributeField()} - - ); -}; - -const AttributeWrapper = ({ label, children, hideLabel }) => ( -
- {!hideLabel && label ? : null} - {children} -
-); - -const AttributeButton = ({ children, onClick, danger }) => ( - -); diff --git a/example/src/pages/Form/Body.js b/example/src/pages/Form/Body.js deleted file mode 100644 index 28e44e83..00000000 --- a/example/src/pages/Form/Body.js +++ /dev/null @@ -1,104 +0,0 @@ -import React from "react"; -import axios from 'axios' -import { useHistory } from 'react-router' -import Field from "./Field"; -import PreviewField from './PreviewField'; -import { DesignerDispatchContext, DesignerStateContext, BASE_URL } from './Form' -import { getFieldValues } from './formHandler' - -const Body = ({ - previewFields, - fields, - fieldsOrder, - clearForm, - saveForm, - togglePreview, - previewing, - filing, - editingWizard, - wizardLoading -}) => { - const designerDispatch = React.useContext(DesignerDispatchContext) - const designerState = React.useContext(DesignerStateContext) - const history = useHistory() - - const startWizardEdit = () => { - designerDispatch({ - type: "START_WIZARD_EDIT" - }) - } - - const handleSubmit = e => { - e.preventDefault() - const values = getFieldValues(previewFields, fieldsOrder) - axios.post(`${BASE_URL}/records`, { - wizardId: designerState.wizardId, - values - }) - .then(res => { - history.push('/records') - }) - } - - return ( - -
-

{filing ? designerState.title : "Form Preview"}

-
- { - !filing && - - } - {!previewing && !filing && ( - - )} - {!previewing && !filing && ( - - )} -
-
- { - !wizardLoading && - - {!previewing && !filing ? - fieldsOrder.map(fieldId => ( - - )) - : - fieldsOrder.map(fieldId => ( - - )) - } - - } - { - filing && -
- -
- } - - ); -}; - -export default Body; \ No newline at end of file diff --git a/example/src/pages/Form/Field.js b/example/src/pages/Form/Field.js deleted file mode 100644 index 46812b0d..00000000 --- a/example/src/pages/Form/Field.js +++ /dev/null @@ -1,90 +0,0 @@ -import React from "react"; -import fieldTypes from "./fieldTypes"; -import { DesignerStateContext, DesignerDispatchContext } from "./Form"; - -const Field = ({ field }) => { - const designerState = React.useContext(DesignerStateContext); - const { ownsLabel } = fieldTypes[field.type]; - - const getFieldByType = () => { - switch (field.type) { - case "text": - return ; - case "select": - return handleChange(e.target.value)} - /> - ); - case "checkbox": - return ( - - ); - case "select": - return ( - onChange(e.target.checked)} - /> - - -
- ); -}; - -const Select = ({ value, disabled, onChange, options, required }) => ( - -); - -export default PreviewField; \ No newline at end of file diff --git a/example/src/pages/Form/Sidebar.js b/example/src/pages/Form/Sidebar.js deleted file mode 100644 index 9a098951..00000000 --- a/example/src/pages/Form/Sidebar.js +++ /dev/null @@ -1,37 +0,0 @@ -import React from 'react' -import fieldTypes from './fieldTypes' -import { FieldsDispatchContext } from './Form' - -const Sidebar = ({ previewing }) => { - - return ( -
-
-

Fields

- { - Object.values(fieldTypes).map(fieldType => ( - - )) - } -
-
- ) -} - -const FieldButton = ({ label, type }) => { - const fieldsDispatch = React.useContext(FieldsDispatchContext) - - const addField = () => { - fieldsDispatch({ - type: 'ADD_FIELD', - fieldType: fieldTypes[type] - }) - } - - return ( - - ) -} - - -export default Sidebar; \ No newline at end of file diff --git a/example/src/pages/Form/defaultNodes.js b/example/src/pages/Form/defaultNodes.js deleted file mode 100644 index ad18322e..00000000 --- a/example/src/pages/Form/defaultNodes.js +++ /dev/null @@ -1,13 +0,0 @@ -const defaultNodes = { - "L9y4-xxI2Q": { - id: "L9y4-xxI2Q", - x: 912, - y: 345.5, - type: "output", - width: 200, - connections: { inputs: {}, outputs: {} }, - inputData: { label: { text: "" }, visible: {}, disabled: {}, required: {} } - } -}; - -export default defaultNodes \ No newline at end of file diff --git a/example/src/pages/Form/designerReducer.js b/example/src/pages/Form/designerReducer.js deleted file mode 100644 index 7bce4ac9..00000000 --- a/example/src/pages/Form/designerReducer.js +++ /dev/null @@ -1,44 +0,0 @@ -const designerReducer = (state, action) => { - switch (action.type) { - case 'POPULATE_STATE': - return { - ...state, - wizardId: action.wizardId, - wizardLogic: action.wizardLogic, - title: action.title - } - - case 'SET_SELECTED_FIELD_ID': { - const { fieldId } = action - return { - ...state, - selectedFieldId: fieldId, - editingWizard: false - } - } - - case 'START_WIZARD_EDIT': - return { - ...state, - selectedFieldId: null, - editingWizard: true - } - - case 'SET_TITLE': - return { - ...state, - title: action.title - } - - case 'SET_LOGIC': - return { - ...state, - wizardLogic: action.logic - } - - default: - return state; - } -} - -export default designerReducer diff --git a/example/src/pages/Form/fieldTypes.js b/example/src/pages/Form/fieldTypes.js deleted file mode 100644 index 9cb948a3..00000000 --- a/example/src/pages/Form/fieldTypes.js +++ /dev/null @@ -1,71 +0,0 @@ -import defaultNodes from './defaultNodes' - -const commonAttributes = [ - { - name: "label", - label: "Label", - defaultValue: "New Field", - type: "text" - }, - { - name: "name", - label: "Name", - defaultValue: "FIELD_NAME", - type: "text" - }, - { - name: "visible", - label: "Visible", - defaultValue: true, - type: "checkbox" - }, - { - name: "disabled", - label: "Disabled", - defaultValue: false, - type: "checkbox" - }, - { - name: "required", - label: "Required", - defaultValue: false, - type: "checkbox" - }, - { - name: "logic", - label: "Logic", - defaultValue: defaultNodes, - type: "logic" - } -]; - -const optionsAttribute = { - name: "options", - label: "Options", - defaultValue: [{ value: "", label: "[Pick an Option]" }], - type: "options" -}; - -const fieldTypes = { - text: { - type: "text", - label: "Text Input", - defaultValue: "", - attributes: [...commonAttributes] - }, - checkbox: { - type: "checkbox", - label: "Checkbox", - defaultValue: false, - ownsLabel: true, - attributes: [...commonAttributes] - }, - select: { - type: "select", - label: "Dropdown", - defaultValue: "", - attributes: [...commonAttributes, optionsAttribute] - } -}; - -export default fieldTypes; \ No newline at end of file diff --git a/example/src/pages/Form/fieldsReducer.js b/example/src/pages/Form/fieldsReducer.js deleted file mode 100644 index 8fdf9b61..00000000 --- a/example/src/pages/Form/fieldsReducer.js +++ /dev/null @@ -1,72 +0,0 @@ -import { nanoid }from "nanoid/non-secure/index"; - -const getAttributes = attributes => - attributes.reduce((obj, attr) => { - obj[attr.name] = attr.defaultValue; - return obj; - }, {}); - -const removeFieldByFieldId = (state, fieldId) => { - const { [fieldId]: deletedField, ...fields } = state.fields; - - return { - fields, - fieldsOrder: state.fieldsOrder.filter(f => f !== fieldId) - } -} - -const fieldsReducer = (state, action) => { - switch (action.type) { - case "POPULATE_FIELDS": { - const { fields, fieldsOrder } = action; - return {...state, fields, fieldsOrder} - } - - case "ADD_FIELD": { - const { fieldType } = action; - const id = nanoid(10); - return { - ...state, - fields: { - ...state.fields, - [id]: { - id, - type: fieldType.type, - value: fieldType.defaultValue, - ...getAttributes(fieldType.attributes) - } - }, - fieldsOrder: [...state.fieldsOrder, id] - }; - } - - case "REMOVE_FIELD": { - const { fieldId } = action; - return removeFieldByFieldId(state, fieldId) - } - - case "SET_ATTRIBUTE_VALUE": { - const { fieldId, name, value } = action; - - return { - ...state, - fields: { - ...state.fields, - [fieldId]: { - ...state.fields[fieldId], - [name]: value - } - } - }; - } - - case "CLEAR_FORM": { - return { fields: {}, fieldsOrder: [] } - } - - default: - return state; - } -}; - -export default fieldsReducer; diff --git a/example/src/pages/Form/formHandler.js b/example/src/pages/Form/formHandler.js deleted file mode 100644 index 9c5743bb..00000000 --- a/example/src/pages/Form/formHandler.js +++ /dev/null @@ -1,14 +0,0 @@ -import resolveLogic from './resolveLogic' - -export const getFieldValues = (fields, fieldsOrder) => ( - fieldsOrder.reduce((values, fieldId) => { - const field = fields[fieldId] - const { name, value, visible } = resolveLogic(field, fields) || {}; - values[name] = { - value, - name, - visible - } - return values - }, {}) -) diff --git a/example/src/pages/Form/previewFieldsReducer.js b/example/src/pages/Form/previewFieldsReducer.js deleted file mode 100644 index b3ce9c41..00000000 --- a/example/src/pages/Form/previewFieldsReducer.js +++ /dev/null @@ -1,33 +0,0 @@ -const previewFieldsReducer = (state, action) => { - - switch (action.type) { - - case 'POPULATE_FIELDS': { - const { fields } = action; - - return { - ...state, - previewFields: fields - } - } - - case 'SET_FIELD_VALUE': { - const { fieldId, value } = action; - return { - ...state, - previewFields: { - ...state.previewFields, - [fieldId]: { - ...state.previewFields[fieldId], - value - } - } - } - } - - default: - return state - } -} - -export default previewFieldsReducer diff --git a/example/src/pages/Form/resolveLogic.js b/example/src/pages/Form/resolveLogic.js deleted file mode 100644 index 2f231a20..00000000 --- a/example/src/pages/Form/resolveLogic.js +++ /dev/null @@ -1,109 +0,0 @@ -import NodeTypes from './NodeTypes' -import { previewState } from './Form' - -const getRootNode = nodes => - nodes[Object.values(nodes).find(n => n.type === "output").id]; - -// const loopTransputs = (transputs, callback) => { -// Object.entries(transputs).forEach(([inputName, connection]) => { -// callback(inputName, connection); -// }); -// }; - -const mapTransputs = (transputs, callback) => ( - Object.entries(transputs).map(([inputName, connection]) => { - return callback(inputName, connection); - }) -); - -const fireNodeFunction = (node, inputValues, nodeType) => { - switch (node.type) { - case "number": return { number: inputValues.number }; - case "boolean": return { boolean: inputValues.boolean }; - case "string": return { string: inputValues.string }; - case "and": return { output: inputValues.val1 && inputValues.val2 }; - case "or": return { output: inputValues.val1 || inputValues.val2 }; - case "valueEqualsBoolean": return { output: inputValues.val1 === inputValues.boolean }; - case "valueEqualsValue": return { output: inputValues.val1 === inputValues.val2 }; - case "textSwitch": return { output: inputValues.test ? inputValues.textIfTrue : inputValues.textIfFalse} - case "field": { - const fields = previewState.getFields() - const field = fields[inputValues.fieldId] - return field ? resolveLogic(field, fields) : {} - } - case "valueEqualsOneOfOptions": { - let value = inputValues.value - if(value === undefined){ - const fields = previewState.getFields() - const field = fields[inputValues.fieldId] || {} - value = field.value - } - return { output: inputValues.selectedOptions.includes(value) } - } - default: - return undefined - } -} - -const resolveInputControls = (type, data) => { - switch (type) { - case "number": - return data.number; - case "boolean": - return data.boolean; - case "string": - return data.text; - case "fieldId": - return data.selectedFieldId; - case "textSwitch": - return { - textIfTrue: data.textIfTrue.text, - textIfFalse: data.textIfFalse.text - }; - case "stringArray": - return data.values - case "value": - return Object.keys(data).length ? data : undefined - default: - return data; - } -}; - -const resolveInputValues = (node, nodeType, nodes) => { - return nodeType.inputs.reduce((obj, input) => { - const inputConnections = node.connections.inputs[input.name] || [] - if(inputConnections.length > 0){ - obj[input.name] = getValueOfConnection(inputConnections[0], nodes) - }else{ - obj[input.name] = resolveInputControls(input.type, node.inputData[input.name]) - } - return obj - }, {}) -} - -const getValueOfConnection = (connection, nodes) => { - const outputNode = nodes[connection.nodeId] - const outputNodeType = NodeTypes[outputNode.type] - const inputValues = resolveInputValues(outputNode, outputNodeType, nodes) - const outputResult = fireNodeFunction(outputNode, inputValues, outputNodeType)[connection.portName] - return outputResult -} - -const resolveLogic = (field, fields) => { - const rootNode = getRootNode(field.logic); - const attributes = mapTransputs( - rootNode.connections.inputs, - (inputName, connection) => { - return { - name: inputName, - value: getValueOfConnection(connection[0], field.logic) - } - } - ).reduce((obj, attr) => { - obj[attr.name] = attr.value !== undefined ? attr.value : field[attr.name] - return obj - }, {}) - return {...field, ...attributes} -}; - -export default resolveLogic; diff --git a/example/src/pages/Form/wizardLogic/logicTypes.js b/example/src/pages/Form/wizardLogic/logicTypes.js deleted file mode 100644 index 19ebf50d..00000000 --- a/example/src/pages/Form/wizardLogic/logicTypes.js +++ /dev/null @@ -1,464 +0,0 @@ -import orderBy from "lodash/orderBy"; - -export const statusOptions = [ - { value: "review", label: "Pending Review" }, - { value: "approved", label: "Approved" }, - { value: "correction", label: "Needs Correction" } -]; - -export const NodeTypes = { - output: { - type: "output", - label: "Record Attributes", - addable: false, - deletable: false, - inputs: [ - { - type: "string", - label: "Title", - name: "title", - noControls: true - }, - { - type: "status", - label: "Status", - name: "status", - noControls: true - }, - { - type: "number", - label: "Fee", - name: "fee", - noControls: true - } - ] - }, - number: { - label: "Number", - description: "Outputs a number.", - type: "number", - initialWidth: 130, - inputs: [ - { - type: "number", - name: "number" - } - ], - outputs: [ - { - type: "number", - name: "number" - } - ] - }, - string: { - label: "Text", - description: "Outputs a string of text.", - type: "string", - inputs: [ - { - type: "string", - name: "string" - } - ], - outputs: [ - { - type: "string", - name: "string" - } - ] - }, - status: { - type: "status", - label: "Status", - description: "Outputs a selected status", - initialWidth: 150, - inputs: [ - { - type: "status", - label: "Selected Status", - name: "statusValue", - hidePort: true, - controls: [ - { - type: "select", - placeholder: "[Select a Status]", - name: "selectedStatus", - options: statusOptions - } - ] - } - ], - outputs: [ - { - type: "status", - label: "Status", - name: "selectedStatus" - } - ] - }, - and: { - label: "And", - description: "Outputs true if both values are true.", - type: "and", - initialWidth: 150, - inputs: [ - { - type: "boolean", - name: "val1" - }, - { - type: "boolean", - name: "val2" - } - ], - outputs: [ - { - type: "boolean", - name: "output", - label: "True/False" - } - ] - }, - or: { - label: "Or", - description: "Outputs true if either value is true.", - initialWidth: 150, - type: "or", - inputs: [ - { - type: "boolean", - name: "val1" - }, - { - type: "boolean", - name: "val2" - } - ], - outputs: [ - { - type: "boolean", - name: "output", - label: "True/False" - } - ] - }, - booleanReverse: { - label: "Reverse Boolean", - description: "Outputs the opposite of a true/false", - initialWidth: 150, - type: "booleanReverse", - inputs: [ - { - type: "boolean", - name: "boolean" - } - ], - outputs: [ - { - type: "boolean", - name: "output" - } - ] - }, - statusSwitch: { - label: "Status Switch", - description: "Outputs a status based on a given true/false input.", - type: "statusSwitch", - inputs: [ - { - type: "boolean", - name: "test" - }, - { - type: "status", - name: "statusIfTrue", - label: "Status if true", - controls: [ - { - type: "select", - name: "statusIfTrue", - placeholder: "Status if True", - options: statusOptions - } - ] - }, - { - type: "status", - name: "statusIfFalse", - label: "Status if false", - controls: [ - { - type: "select", - name: "statusIfFalse", - placeholder: "Status if False", - options: statusOptions - } - ] - } - ], - outputs: [ - { - type: "status", - name: "output" - } - ] - }, - numberSwitch: { - label: "Number Switch", - description: "Outputs a number based on a given true/false input.", - type: "numberSwitch", - initialWidth: 140, - inputs: [ - { - type: "boolean", - name: "test" - }, - { - type: "number", - name: "numberIfTrue", - label: "Number if true" - }, - { - type: "number", - name: "numberIfFalse", - label: "Number if false" - } - ], - outputs: [ - { - type: "number", - name: "output" - } - ] - }, - valueToString: { - type: "valueToString", - label: "Value to Text", - description: "Converts a value to text", - initialWidth: 160, - inputs: [ - { - type: "value", - name: "value" - } - ], - outputs: [ - { - type: "string", - name: "string", - label: "Text" - } - ] - }, - addText: { - type: "addText", - label: "Join Text", - description: "Joins together two strings of text.", - initialWidth: 160, - inputs: [ - { - type: "string", - name: "string1" - }, - { - type: "string", - name: "string2" - } - ], - outputs: [ - { - type: "string", - name: "output" - } - ] - }, - user: { - label: "User", - description: "Outputs attributes of the current user.", - type: "user", - inputs: [], - outputs: [ - { - type: "string", - name: "firstName", - label: "First Name" - }, - { - type: "string", - name: "lastName", - label: "Last Name" - }, - { - type: "boolean", - name: "isAdmin", - label: "Is Administrator" - } - ] - }, - filingValue: { - label: "Filing Value", - description: "Outputs a value from the current filing", - type: "filingValue", - initialWidth: 170, - inputs: [ - { - type: "fieldName", - name: "fieldName", - label: "Field Name" - } - ], - outputs: [ - { - type: "value", - name: "value", - label: "Field Value" - } - ] - }, - valueEqualsValue: { - label: "Values Equal", - description: "Outputs whether two values equal each other.", - type: "valueEqualsValue", - inputs: [ - { - type: "value", - name: "val1" - }, - { - type: "value", - name: "val2" - } - ], - outputs: [ - { - type: "boolean", - name: "output" - } - ] - }, - valueEqualsText: { - label: "Value Equals Text", - description: "Outputs whether a value equals some given text.", - type: "valueEqualsText", - inputs: [ - { - type: "value", - name: "val1" - }, - { - type: "string", - name: "val2" - } - ], - outputs: [ - { - type: "boolean", - name: "output" - } - ] - }, - valueEqualsBoolean: { - label: "Value Equals Boolean", - description: "Outputs whether a value equals a given boolean.", - type: "valueEqualsBoolean", - inputs: [ - { - type: "value", - name: "val1" - }, - { - type: "boolean", - name: "val2" - } - ], - outputs: [ - { - type: "boolean", - name: "output" - } - ] - } -}; - -export const InputTypes = { - string: { - type: "string", - label: "Text", - acceptTypes: ["string"], - color: "green", - controls: [ - { - type: "text", - name: "text", - label: "Text", - defaultValue: "" - } - ] - }, - boolean: { - type: "boolean", - label: "True/False", - acceptTypes: ["boolean"], - controls: [ - { - type: "checkbox", - name: "boolean", - label: "True/False", - defaultValue: false - } - ] - }, - number: { - type: "number", - label: "Number", - acceptTypes: ["number"], - color: "red", - controls: [ - { - type: "number", - name: "number", - label: "Number", - defaultValue: 0 - } - ] - }, - value: { - type: "value", - label: "Field Value", - acceptTypes: ["value", "number", "string", "boolean"], - color: "yellow" - }, - status: { - type: "status", - label: "Status", - acceptTypes: ["status"], - color: "purple", - hidePort: true - }, - fieldName: { - type: "fieldName", - label: "Field Name", - acceptTypes: ["fieldName"], - color: "pink", - hidePort: true, - controls: [ - { - type: "select", - name: "name", - placeholder: "[Pick a Field]", - getOptions: (data, context) => { - const fields = orderBy( - Object.values(context.fields).map(f => ({ - label: f.label, - value: f.name, - description: f.name - })), - "label" - ); - return fields; - } - } - ] - } -}; diff --git a/example/src/pages/Forms/Forms.css b/example/src/pages/Forms/Forms.css deleted file mode 100644 index d3f77b72..00000000 --- a/example/src/pages/Forms/Forms.css +++ /dev/null @@ -1,100 +0,0 @@ -.forms-page-wrapper{ - width: 100%; - display: flex; - justify-content: center; - font-family: "Roboto", sans-serif; -} -.forms-wrapper{ - width: 100%; - max-width: 1200px; - display: flex; - flex-direction: column; -} -.forms-wrapper h1{ - margin: 0px; -} -.form-blocks{ - display: grid; - grid-template-columns: repeat(4, 1fr); - grid-gap: 30px 30px; - padding-top: 30px; -} -.form-block{ - display: flex; - flex-direction: column; - background: #fff; - box-shadow: 0px 15px 32px -4px rgba(0, 0, 0, 0.3); - border-radius: 5px; - padding: 15px; -} -.form-block h2{ - margin: 0px; - margin-bottom: 5px; - font-size: 20px; - font-weight: 500; - color: rgb(45, 53, 60); -} -.form-block p{ - margin: 0px; - font-style: italic; - color: rgb(84, 103, 119); - font-size: 13px; -} -.form-block-button{ - background: rgba(7, 104, 194, 0.12); - border: none; - border-radius: 4px; - margin: 0px 5px; - text-transform: uppercase; - font-weight: 500; - font-size: 14px; - padding: 5px 10px; - text-decoration: none; - color: rgb(45, 53, 60); - user-select: none; -} -.form-block-button:hover{ - background: rgba(7, 104, 194, 0.22); -} -.form-block-button:last-child{ - margin-right: 0px; -} -.form-block-controls{ - margin-top: 10px; - margin-bottom: 5px; -} -.new-form-button{ - border-radius: 40px; - padding: 9px 20px; - padding-left: 15px; - background: rgba(27, 71, 130, 0.15); - border: none; - color: rgb(37, 59, 88); - text-decoration: none; - display: flex; - align-items: center; - font-weight: 500; - text-transform: uppercase; -} -.new-form-button:hover{ - background: rgba(52, 108, 184, 0.22); -} -.plus-icon{ - width: 18px; - height: 18px; - position: relative; - margin-right: 10px; -} -.plus-icon::before, .plus-icon::after{ - content: ""; - position: absolute; - left: 0px; - top: calc(50% - 1px); - width: 100%; - height: 2px; - border-radius: 6px; - background: rgb(37, 59, 88); -} -.plus-icon::after{ - transform: rotate(90deg); -} diff --git a/example/src/pages/Forms/Forms.js b/example/src/pages/Forms/Forms.js deleted file mode 100644 index 4f45d4a2..00000000 --- a/example/src/pages/Forms/Forms.js +++ /dev/null @@ -1,66 +0,0 @@ -import React from "react"; -import axios from "axios"; -import FloatingNavigation from "../../components/FloatingNavigation"; -import { BASE_URL } from "../Form/Form"; -import orderBy from "lodash/orderBy"; -import { Link } from "react-router-dom"; -import "./Forms.css"; - -const placeholderDescription = - "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt."; - -const Forms = () => { - const [forms, setForms] = React.useState([]); - - React.useEffect(() => { - axios.get(`${BASE_URL}/forms`).then(res => { - setForms(orderBy(res.data, "dateCreated")); - }); - }, []); - - return ( -
-
-
-

Forms

- -
New Form - -
-
- {forms.map(form => ( -
- -
- ))} -
-
- -
- ); -}; - -export default Forms; - -const FormBlock = ({ title, description, id }) => { - return ( -
-

{title}

-

{description}

-
-
- - Edit - - - File - -
-
-
- ); -}; diff --git a/example/src/pages/Records/Records.css b/example/src/pages/Records/Records.css deleted file mode 100644 index cb918b1a..00000000 --- a/example/src/pages/Records/Records.css +++ /dev/null @@ -1,40 +0,0 @@ -.record-blocks { - width: 100%; - display: grid; - grid-template-columns: repeat(4, 1fr); - grid-gap: 30px 30px; - padding-top: 30px; -} -.record-block { - display: flex; - flex-direction: column; - background: #fff; - box-shadow: 0px 15px 32px -4px rgba(0, 0, 0, 0.3); - border-radius: 5px; - padding: 15px; -} -.record-block h2{ - margin: 0px; - margin-bottom: 5px; - font-size: 20px; - font-weight: 500; - color: rgb(45, 53, 60); -} -.record-block p{ - margin: 0px; - font-style: italic; - color: rgb(84, 103, 119); - font-size: 13px; -} -.record-attributes{ - display: flex; - flex-direction: column; -} -.record-attribute-wrapper{ - margin: 3px 0px; - color: rgb(56, 57, 59); - font-size: 15px; -} -.record-attribute-wrapper:last-child{ - margin-bottom: 0px; -} diff --git a/example/src/pages/Records/Records.js b/example/src/pages/Records/Records.js deleted file mode 100644 index 18084afa..00000000 --- a/example/src/pages/Records/Records.js +++ /dev/null @@ -1,61 +0,0 @@ -import React from "react"; -import axios from "axios"; -import { Link } from "react-router-dom"; -import { BASE_URL } from "../Form/Form"; -import { statusOptions } from '../Form/wizardLogic/logicTypes' -import FloatingNavigation from '../../components/FloatingNavigation' -import "./Records.css"; - -const Records = () => { - const [records, setRecords] = React.useState([]); - - React.useEffect(() => { - axios.get(`${BASE_URL}/records`).then(res => { - setRecords(res.data); - }); - }, []); - - console.log(records); - - return ( -
-
-
-

My Records

- -
New Record - -
-
- {records.map(record => ( - - ))} -
-
- -
- ); -}; - -export default Records; - -const RecordBlock = ({ title, status = "approved", fee = 0 }) => ( -
-

{title}

-
- opt.value === status).label} /> - -
-
-); - -const Attribute = ({ label, value }) => ( -
- {label}: {value} -
-) diff --git a/example/src/react-app-env.d.ts b/example/src/react-app-env.d.ts new file mode 100644 index 00000000..6431bc5f --- /dev/null +++ b/example/src/react-app-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/example/tsconfig.json b/example/tsconfig.json new file mode 100644 index 00000000..9d379a3c --- /dev/null +++ b/example/tsconfig.json @@ -0,0 +1,20 @@ +{ + "compilerOptions": { + "target": "es5", + "lib": ["dom", "dom.iterable", "esnext"], + "allowJs": true, + "skipLibCheck": true, + "esModuleInterop": true, + "allowSyntheticDefaultImports": true, + "strict": true, + "forceConsistentCasingInFileNames": true, + "noFallthroughCasesInSwitch": true, + "module": "esnext", + "moduleResolution": "node", + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": true, + "jsx": "react-jsx" + }, + "include": ["src"] +} diff --git a/example/yarn.lock b/example/yarn.lock index 86aeeb05..cf8eb3e3 100644 --- a/example/yarn.lock +++ b/example/yarn.lock @@ -1919,6 +1919,13 @@ dependencies: regenerator-runtime "^0.13.4" +"@babel/runtime@^7.12.1", "@babel/runtime@^7.12.13": + version "7.21.0" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.21.0.tgz#5b55c9d394e5fcf304909a8b00c07dc217b56673" + integrity sha512-xwII0//EObnq89Ji5AKYQaRYiW/nZ3llSv29d49IuxPhKbtJoLP+9QUUZ4nVragQVtaVGeZrpB+ZtG/Pdy/POw== + dependencies: + regenerator-runtime "^0.13.11" + "@babel/runtime@^7.5.5", "@babel/runtime@^7.6.3", "@babel/runtime@^7.7.2": version "7.8.7" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.8.7.tgz#8fefce9802db54881ba59f90bb28719b4996324d" @@ -2339,6 +2346,13 @@ "@types/node" "*" jest-mock "^27.5.1" +"@jest/expect-utils@^29.5.0": + version "29.5.0" + resolved "https://registry.yarnpkg.com/@jest/expect-utils/-/expect-utils-29.5.0.tgz#f74fad6b6e20f924582dc8ecbf2cb800fe43a036" + integrity sha512-fmKzsidoXQT2KwnrwE0SQq3uj8Z763vzR8LnLBwC2qYWEFpjX8daRsk6rHUM1QvNlEW/UJXNXm59ztmJJWs2Mg== + dependencies: + jest-get-type "^29.4.3" + "@jest/fake-timers@^27.5.1": version "27.5.1" resolved "https://registry.yarnpkg.com/@jest/fake-timers/-/fake-timers-27.5.1.tgz#76979745ce0579c8a94a4678af7a748eda8ada74" @@ -2391,6 +2405,13 @@ terminal-link "^2.0.0" v8-to-istanbul "^8.1.0" +"@jest/schemas@^29.4.3": + version "29.4.3" + resolved "https://registry.yarnpkg.com/@jest/schemas/-/schemas-29.4.3.tgz#39cf1b8469afc40b6f5a2baaa146e332c4151788" + integrity sha512-VLYKXQmtmuEz6IxJsrZwzG9NvtkQsWNnWMsKxqWNu3+CnfzJQhp0WDDKWLVV9hLKr0l3SLLFRqcYHjhtyuDVxg== + dependencies: + "@sinclair/typebox" "^0.25.16" + "@jest/source-map@^27.5.1": version "27.5.1" resolved "https://registry.yarnpkg.com/@jest/source-map/-/source-map-27.5.1.tgz#6608391e465add4205eae073b55e7f279e04e8cf" @@ -2462,6 +2483,18 @@ "@types/yargs" "^16.0.0" chalk "^4.0.0" +"@jest/types@^29.5.0": + version "29.5.0" + resolved "https://registry.yarnpkg.com/@jest/types/-/types-29.5.0.tgz#f59ef9b031ced83047c67032700d8c807d6e1593" + integrity sha512-qbu7kN6czmVRc3xWFQcAN03RAUamgppVUdXrvl1Wr3jlNF93o9mJbGcDWrwGB6ht44u7efB1qCFgVQmca24Uog== + dependencies: + "@jest/schemas" "^29.4.3" + "@types/istanbul-lib-coverage" "^2.0.0" + "@types/istanbul-reports" "^3.0.0" + "@types/node" "*" + "@types/yargs" "^17.0.8" + chalk "^4.0.0" + "@jridgewell/resolve-uri@^3.0.3": version "3.0.5" resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.0.5.tgz#68eb521368db76d040a6315cdb24bf2483037b9c" @@ -2671,11 +2704,24 @@ estree-walker "^1.0.1" picomatch "^2.2.2" +"@rollup/pluginutils@^4.1.2": + version "4.2.1" + resolved "https://registry.yarnpkg.com/@rollup/pluginutils/-/pluginutils-4.2.1.tgz#e6c6c3aba0744edce3fb2074922d3776c0af2a6d" + integrity sha512-iKnFXr7NkdZAIHiIWE+BX5ULi/ucVFYWD6TbAV+rZctiRTY2PL6tsIKhoIOaoskiWAkgu+VsbXgUVDNLHf+InQ== + dependencies: + estree-walker "^2.0.1" + picomatch "^2.2.2" + "@rushstack/eslint-patch@^1.1.0": version "1.1.1" resolved "https://registry.yarnpkg.com/@rushstack/eslint-patch/-/eslint-patch-1.1.1.tgz#782fa5da44c4f38ae9fd38e9184b54e451936118" integrity sha512-BUyKJGdDWqvWC5GEhyOiUrGNi9iJUr4CU0O2WxJL6QJhHeeA/NVBalH+FeK0r/x/W0rPymXt5s78TDS7d6lCwg== +"@sinclair/typebox@^0.25.16": + version "0.25.24" + resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.25.24.tgz#8c7688559979f7079aacaf31aa881c3aa410b718" + integrity sha512-XJfwUVUKDHF5ugKwIcxEgc9k8b7HbznCp6eUfWgu710hMPNIO4aw4/zB5RogDQz8nd6gyCDpU9O/m6qYEWY6yQ== + "@sindresorhus/is@^0.14.0": version "0.14.0" resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-0.14.0.tgz#9fb3a3cf3132328151f353de4632e01e52102bea" @@ -3072,6 +3118,14 @@ dependencies: "@types/istanbul-lib-report" "*" +"@types/jest@^29.5.0": + version "29.5.0" + resolved "https://registry.yarnpkg.com/@types/jest/-/jest-29.5.0.tgz#337b90bbcfe42158f39c2fb5619ad044bbb518ac" + integrity sha512-3Emr5VOl/aoBwnWcH/EFQvlSAmjV+XtV9GGu5mwdYew5vhQh0IUZx/60x0TzHDu09Bi7HMx10t/namdJw5QIcg== + dependencies: + expect "^29.0.0" + pretty-format "^29.0.0" + "@types/json-schema@*", "@types/json-schema@^7.0.4", "@types/json-schema@^7.0.5", "@types/json-schema@^7.0.8", "@types/json-schema@^7.0.9": version "7.0.10" resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.10.tgz#9b05b7896166cd00e9cbd59864853abf65d9ac23" @@ -3114,6 +3168,11 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-13.13.4.tgz#1581d6c16e3d4803eb079c87d4ac893ee7501c2c" integrity sha512-x26ur3dSXgv5AwKS0lNfbjpCakGIduWU1DU91Zz58ONRWrIKGunmZBNv4P7N+e27sJkiGDsw/3fT4AtsqQBrBA== +"@types/node@^18.15.3": + version "18.15.3" + resolved "https://registry.yarnpkg.com/@types/node/-/node-18.15.3.tgz#f0b991c32cfc6a4e7f3399d6cb4b8cf9a0315014" + integrity sha512-p6ua9zBxz5otCmbpb5D3U4B5Nanw6Pk3PPyX05xnxbB/fRv71N7CPmORg7uAD5P70T0xmx1pzAx/FUfa5X+3cw== + "@types/node@^8.5.7": version "8.10.60" resolved "https://registry.yarnpkg.com/@types/node/-/node-8.10.60.tgz#73eb4d1e1c8aa5dc724363b57db019cf28863ef7" @@ -3157,6 +3216,13 @@ "@types/history" "*" "@types/react" "*" +"@types/react-dom@^18.0.11": + version "18.0.11" + resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-18.0.11.tgz#321351c1459bc9ca3d216aefc8a167beec334e33" + integrity sha512-O38bPbI2CWtgw/OoQoY+BRelw7uysmXbWvw3nLWO21H1HSh+GOlqPuXshJfjmpNlKiiSDG9cc1JZAaMmVdcTlw== + dependencies: + "@types/react" "*" + "@types/react@*": version "16.9.34" resolved "https://registry.yarnpkg.com/@types/react/-/react-16.9.34.tgz#f7d5e331c468f53affed17a8a4d488cd44ea9349" @@ -3165,6 +3231,15 @@ "@types/prop-types" "*" csstype "^2.2.0" +"@types/react@^18.0.28": + version "18.0.28" + resolved "https://registry.yarnpkg.com/@types/react/-/react-18.0.28.tgz#accaeb8b86f4908057ad629a26635fe641480065" + integrity sha512-RD0ivG1kEztNBdoAK7lekI9M+azSnitIn85h4iOiaLjaTrMjzslhaqCGaI4IyCJ1RljWiLCEu4jyrLLgqxBTew== + dependencies: + "@types/prop-types" "*" + "@types/scheduler" "*" + csstype "^3.0.2" + "@types/resolve@1.17.1": version "1.17.1" resolved "https://registry.yarnpkg.com/@types/resolve/-/resolve-1.17.1.tgz#3afd6ad8967c77e4376c598a82ddd58f46ec45d6" @@ -3185,6 +3260,11 @@ "@types/glob" "*" "@types/node" "*" +"@types/scheduler@*": + version "0.16.2" + resolved "https://registry.yarnpkg.com/@types/scheduler/-/scheduler-0.16.2.tgz#1a62f89525723dde24ba1b01b092bf5df8ad4d39" + integrity sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew== + "@types/serve-index@^1.9.1": version "1.9.1" resolved "https://registry.yarnpkg.com/@types/serve-index/-/serve-index-1.9.1.tgz#1b5e85370a192c01ec6cec4735cf2917337a6278" @@ -3274,6 +3354,13 @@ dependencies: "@types/yargs-parser" "*" +"@types/yargs@^17.0.8": + version "17.0.22" + resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-17.0.22.tgz#7dd37697691b5f17d020f3c63e7a45971ff71e9a" + integrity sha512-pet5WJ9U8yPVRhkwuEIp5ktAeAqRZOq4UdAyWLWzxbtpyXnzbtLdKiXAjJzi/KLmPGS9wk86lUFWZFN6sISo4g== + dependencies: + "@types/yargs-parser" "*" + "@types/yoga-layout@1.9.1": version "1.9.1" resolved "https://registry.yarnpkg.com/@types/yoga-layout/-/yoga-layout-1.9.1.tgz#6c00e4a151a9a529397d580e2cf6f3947a42a928" @@ -3692,6 +3779,15 @@ resolved "https://registry.yarnpkg.com/@xtuc/long/-/long-4.2.2.tgz#d291c6a4e97989b5c61d9acf396ae4fe133a718d" integrity sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ== +"@yarn-tool/resolve-package@^1.0.40": + version "1.0.47" + resolved "https://registry.yarnpkg.com/@yarn-tool/resolve-package/-/resolve-package-1.0.47.tgz#8ec25f291a316280a281632331e88926a66fdf19" + integrity sha512-Zaw58gQxjQceJqhqybJi1oUDaORT8i2GTgwICPs8v/X/Pkx35FXQba69ldHVg5pQZ6YLKpROXgyHvBaCJOFXiA== + dependencies: + pkg-dir "< 6 >= 5" + tslib "^2" + upath2 "^3.1.13" + abab@^2.0.3, abab@^2.0.5: version "2.0.5" resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.5.tgz#c0b678fb32d60fc1219c784d6a826fe385aeb79a" @@ -6583,6 +6679,11 @@ csstype@^2.5.7: resolved "https://registry.yarnpkg.com/csstype/-/csstype-2.6.9.tgz#05141d0cd557a56b8891394c1911c40c8a98d098" integrity sha512-xz39Sb4+OaTsULgUERcCk+TJj8ylkL4aSVDQiX/ksxbELSqwkgt4d4RD7fovIdgJGSuNYqwZEiVjYY5l0ask+Q== +csstype@^3.0.2: + version "3.1.1" + resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.1.tgz#841b532c45c758ee546a11d5bd7b7b473c8c30b9" + integrity sha512-DJR/VvkAvSZW9bTouZue2sSxDwdTN92uHjqeKVm+0dAqdfNykRzQ95tay8aXMBAAPpUiq4Qcug2L7neoRh2Egw== + currently-unhandled@^0.4.1: version "0.4.1" resolved "https://registry.yarnpkg.com/currently-unhandled/-/currently-unhandled-0.4.1.tgz#988df33feab191ef799a61369dd76c17adf957ea" @@ -7013,6 +7114,11 @@ diff-sequences@^27.5.1: resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-27.5.1.tgz#eaecc0d327fd68c8d9672a1e64ab8dccb2ef5327" integrity sha512-k1gCAXAsNgLwEL+Y8Wvl+M6oEFj5bgazfZULpS5CneoPPXRaCCW7dm+q21Ky2VEE5X+VeRDBVg1Pcvvsr4TtNQ== +diff-sequences@^29.4.3: + version "29.4.3" + resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-29.4.3.tgz#9314bc1fabe09267ffeca9cbafc457d8499a13f2" + integrity sha512-ofrBgwpPhCD85kMKtE9RYFFq6OC1A89oW2vvgWZNCwxrUpRUILopY7lsYyMDSjc8g6U6aiO0Qubg6r4Wgt5ZnA== + diffie-hellman@^5.0.0: version "5.0.3" resolved "https://registry.yarnpkg.com/diffie-hellman/-/diffie-hellman-5.0.3.tgz#40e8ee98f55a2149607146921c63e1ae5f3d2875" @@ -8159,6 +8265,11 @@ estree-walker@^1.0.1: resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-1.0.1.tgz#31bc5d612c96b704106b477e6dd5d8aa138cb700" integrity sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg== +estree-walker@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-2.0.2.tgz#52f010178c2a4c117a7757cfe942adb7d2da4cac" + integrity sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w== + esutils@^2.0.2: version "2.0.3" resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" @@ -8330,6 +8441,17 @@ expect@^27.5.1: jest-matcher-utils "^27.5.1" jest-message-util "^27.5.1" +expect@^29.0.0: + version "29.5.0" + resolved "https://registry.yarnpkg.com/expect/-/expect-29.5.0.tgz#68c0509156cb2a0adb8865d413b137eeaae682f7" + integrity sha512-yM7xqUrCO2JdpFo4XpM82t+PJBFybdqoQuJLDGeDX2ij8NZzqRHyu3Hp188/JX7SWqud+7t4MUdvcgGBICMHZg== + dependencies: + "@jest/expect-utils" "^29.5.0" + jest-get-type "^29.4.3" + jest-matcher-utils "^29.5.0" + jest-message-util "^29.5.0" + jest-util "^29.5.0" + express-graphql@^0.9.0: version "0.9.0" resolved "https://registry.yarnpkg.com/express-graphql/-/express-graphql-0.9.0.tgz#00fd8552f866bac5c9a4612b2c4c82076107b3c2" @@ -8701,7 +8823,7 @@ find-cache-dir@^3.2.0: make-dir "^3.0.2" pkg-dir "^4.1.0" -find-cache-dir@^3.3.1: +find-cache-dir@^3.3.1, find-cache-dir@^3.3.2: version "3.3.2" resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-3.3.2.tgz#b30c5b6eff0730731aea9bbd9dbecbd80256d64b" integrity sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig== @@ -11761,6 +11883,16 @@ jest-diff@^27.5.1: jest-get-type "^27.5.1" pretty-format "^27.5.1" +jest-diff@^29.5.0: + version "29.5.0" + resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-29.5.0.tgz#e0d83a58eb5451dcc1fa61b1c3ee4e8f5a290d63" + integrity sha512-LtxijLLZBduXnHSniy0WMdaHjmQnt3g5sa16W4p0HqukYTTsyTW3GD1q41TyGl5YFXj/5B2U6dlh5FM1LIMgxw== + dependencies: + chalk "^4.0.0" + diff-sequences "^29.4.3" + jest-get-type "^29.4.3" + pretty-format "^29.5.0" + jest-docblock@^27.5.1: version "27.5.1" resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-27.5.1.tgz#14092f364a42c6108d42c33c8cf30e058e25f6c0" @@ -11814,6 +11946,11 @@ jest-get-type@^27.5.1: resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-27.5.1.tgz#3cd613c507b0f7ace013df407a1c1cd578bcb4f1" integrity sha512-2KY95ksYSaK7DMBWQn6dQz3kqAf3BB64y2udeG+hv4KfSOb9qwcYQstTJc1KCbsix+wLZWZYN8t7nwX3GOBLRw== +jest-get-type@^29.4.3: + version "29.4.3" + resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-29.4.3.tgz#1ab7a5207c995161100b5187159ca82dd48b3dd5" + integrity sha512-J5Xez4nRRMjk8emnTpWrlkyb9pfRQQanDrvWHhsR1+VUfbwxi30eVcZFlcdGInRibU4G5LwHXpI7IRHU0CY+gg== + jest-haste-map@^27.5.1: version "27.5.1" resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-27.5.1.tgz#9fd8bd7e7b4fa502d9c6164c5640512b4e811e7f" @@ -11875,6 +12012,16 @@ jest-matcher-utils@^27.5.1: jest-get-type "^27.5.1" pretty-format "^27.5.1" +jest-matcher-utils@^29.5.0: + version "29.5.0" + resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-29.5.0.tgz#d957af7f8c0692c5453666705621ad4abc2c59c5" + integrity sha512-lecRtgm/rjIK0CQ7LPQwzCs2VwW6WAahA55YBuI+xqmhm7LAaxokSB8C97yJeYyT+HvQkH741StzpU41wohhWw== + dependencies: + chalk "^4.0.0" + jest-diff "^29.5.0" + jest-get-type "^29.4.3" + pretty-format "^29.5.0" + jest-message-util@^27.5.1: version "27.5.1" resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-27.5.1.tgz#bdda72806da10d9ed6425e12afff38cd1458b6cf" @@ -11890,6 +12037,21 @@ jest-message-util@^27.5.1: slash "^3.0.0" stack-utils "^2.0.3" +jest-message-util@^29.5.0: + version "29.5.0" + resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-29.5.0.tgz#1f776cac3aca332ab8dd2e3b41625435085c900e" + integrity sha512-Kijeg9Dag6CKtIDA7O21zNTACqD5MD/8HfIV8pdD94vFyFuer52SigdC3IQMhab3vACxXMiFk+yMHNdbqtyTGA== + dependencies: + "@babel/code-frame" "^7.12.13" + "@jest/types" "^29.5.0" + "@types/stack-utils" "^2.0.0" + chalk "^4.0.0" + graceful-fs "^4.2.9" + micromatch "^4.0.4" + pretty-format "^29.5.0" + slash "^3.0.0" + stack-utils "^2.0.3" + jest-mock@^27.5.1: version "27.5.1" resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-27.5.1.tgz#19948336d49ef4d9c52021d34ac7b5f36ff967d6" @@ -12036,6 +12198,18 @@ jest-util@^27.5.1: graceful-fs "^4.2.9" picomatch "^2.2.3" +jest-util@^29.5.0: + version "29.5.0" + resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-29.5.0.tgz#24a4d3d92fc39ce90425311b23c27a6e0ef16b8f" + integrity sha512-RYMgG/MTadOr5t8KdhejfvUU82MxsCu5MF6KuDUHl+NuwzUt+Sm6jJWxTJVrDR1j5M/gJVCPKQEpWXY+yIQ6lQ== + dependencies: + "@jest/types" "^29.5.0" + "@types/node" "*" + chalk "^4.0.0" + ci-info "^3.2.0" + graceful-fs "^4.2.9" + picomatch "^2.2.3" + jest-validate@^27.5.1: version "27.5.1" resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-27.5.1.tgz#9197d54dc0bdb52260b8db40b46ae668e04df067" @@ -13284,6 +13458,14 @@ mini-create-react-context@^0.3.0: gud "^1.0.0" tiny-warning "^1.0.2" +mini-create-react-context@^0.4.0: + version "0.4.1" + resolved "https://registry.yarnpkg.com/mini-create-react-context/-/mini-create-react-context-0.4.1.tgz#072171561bfdc922da08a60c2197a497cc2d1d5e" + integrity sha512-YWCYEmd5CQeHGSAKrYvXgmzzkrvssZcuuQDDeqkT+PziKGMgE+0MCCtcKbROzocGBG1meBLl2FotlRwf4gAzbQ== + dependencies: + "@babel/runtime" "^7.12.1" + tiny-warning "^1.0.3" + mini-css-extract-plugin@^0.8.2: version "0.8.2" resolved "https://registry.yarnpkg.com/mini-css-extract-plugin/-/mini-css-extract-plugin-0.8.2.tgz#a875e169beb27c88af77dd962771c9eedc3da161" @@ -13475,16 +13657,16 @@ nanoid@^2.1.11: resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-2.1.11.tgz#ec24b8a758d591561531b4176a01e3ab4f0f0280" integrity sha512-s/snB+WGm6uwi0WjsZdaVcuf3KJXlfGl2LcxgwkEwJF0D/BWzVWAZW/XY4bFaiR7s0Jk3FPvlnepg1H1b1UwlA== -nanoid@^3.1.30: - version "3.1.30" - resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.1.30.tgz#63f93cc548d2a113dc5dfbc63bfa09e2b9b64362" - integrity sha512-zJpuPDwOv8D2zq2WRoMe1HsfZthVewpel9CAvTfc/2mBD1uUT/agc5f7GHGWXlYkFvi1mVxe4IjvP2HNrop7nQ== - nanoid@^3.3.1: version "3.3.1" resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.1.tgz#6347a18cac88af88f58af0b3594b723d5e99bb35" integrity sha512-n6Vs/3KGyxPQd6uO0eH4Bv0ojGSUvuLlIHtC3Y0kEO23YRge8H9x1GCzLn28YX0H66pMkxuaeESFq4tKISKwdw== +nanoid@^3.3.2: + version "3.3.4" + resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.4.tgz#730b67e3cd09e2deacf03c027c81c9d9dbc5e8ab" + integrity sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw== + nanomatch@^1.2.9: version "1.2.13" resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119" @@ -14532,6 +14714,13 @@ path-is-inside@^1.0.1, path-is-inside@^1.0.2: resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53" integrity sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM= +path-is-network-drive@^1.0.20: + version "1.0.20" + resolved "https://registry.yarnpkg.com/path-is-network-drive/-/path-is-network-drive-1.0.20.tgz#9c264db2e0fce5e9bc2ef9177fcab3f996d1a1b5" + integrity sha512-p5wCWlRB4+ggzxWshqHH9aF3kAuVu295NaENXmVhThbZPJQBeJdxZTP6CIoUR+kWHDUW56S9YcaO1gXnc/BOxw== + dependencies: + tslib "^2" + path-key@^2.0.0, path-key@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" @@ -14552,6 +14741,13 @@ path-parse@^1.0.7: resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== +path-strip-sep@^1.0.17: + version "1.0.17" + resolved "https://registry.yarnpkg.com/path-strip-sep/-/path-strip-sep-1.0.17.tgz#3b7dd4f461cf73a9277333f50289ce9b00cffba3" + integrity sha512-+2zIC2fNgdilgV7pTrktY6oOxxZUo9x5zJYfTzxsGze5kSGDDwhA5/0WlBn+sUyv/WuuyYn3OfM+Ue5nhdQUgA== + dependencies: + tslib "^2" + path-to-regexp@0.1.7: version "0.1.7" resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" @@ -14671,6 +14867,13 @@ pkg-conf@^2.1.0: find-up "^2.0.0" load-json-file "^4.0.0" +"pkg-dir@< 6 >= 5": + version "5.0.0" + resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-5.0.0.tgz#a02d6aebe6ba133a928f74aec20bafdfe6b8e760" + integrity sha512-NPE8TDbzl/3YQYY7CSS228s3g2ollTFnc+Qi3tqmqJp9Vg2ovUpixcJEo2HJScN2Ez+kEaal6y70c0ehqJBJeA== + dependencies: + find-up "^5.0.0" + pkg-dir@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-1.0.0.tgz#7a4b508a8d5bb2d629d447056ff4e9c9314cf3d4" @@ -15690,6 +15893,15 @@ pretty-format@^27.5.1: ansi-styles "^5.0.0" react-is "^17.0.1" +pretty-format@^29.0.0, pretty-format@^29.5.0: + version "29.5.0" + resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-29.5.0.tgz#283134e74f70e2e3e7229336de0e4fce94ccde5a" + integrity sha512-V2mGkI31qdttvTFX7Mt4efOqHXqJWMu4/r66Xh3Z3BwZaPfPJgp6/gbwoujRpPUtfEF6AUUWx3Jim3GCw5g/Qw== + dependencies: + "@jest/schemas" "^29.4.3" + ansi-styles "^5.0.0" + react-is "^18.0.0" + prism-react-renderer@^1.0.1, prism-react-renderer@^1.0.2: version "1.1.0" resolved "https://registry.yarnpkg.com/prism-react-renderer/-/prism-react-renderer-1.1.0.tgz#6fe1b33f1de1b23afbdb07663d135f9026eef4ad" @@ -16211,6 +16423,11 @@ react-is@^17.0.1: resolved "https://registry.yarnpkg.com/react-is/-/react-is-17.0.2.tgz#e691d4a8e9c789365655539ab372762b0efb54f0" integrity sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w== +react-is@^18.0.0: + version "18.2.0" + resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.2.0.tgz#199431eeaaa2e09f86427efbb4f1473edb47609b" + integrity sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w== + react-lifecycles-compat@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz#4f1a273afdfc8f3488a8c516bfda78f872352362" @@ -16268,20 +16485,36 @@ react-resize-detector@^4.2.1: raf-schd "^4.0.2" resize-observer-polyfill "^1.5.1" -react-router-dom@^5.1.2: - version "5.1.2" - resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-5.1.2.tgz#06701b834352f44d37fbb6311f870f84c76b9c18" - integrity sha512-7BPHAaIwWpZS074UKaw1FjVdZBSVWEk8IuDXdB+OkLb8vd/WRQIpA4ag9WQk61aEfQs47wHyjWUoUGGZxpQXew== +react-router-dom@5.3.3: + version "5.3.3" + resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-5.3.3.tgz#8779fc28e6691d07afcaf98406d3812fe6f11199" + integrity sha512-Ov0tGPMBgqmbu5CDmN++tv2HQ9HlWDuWIIqn4b88gjlAN5IHI+4ZUZRcpz9Hl0azFIwihbLDYw1OiHGRo7ZIng== dependencies: - "@babel/runtime" "^7.1.2" + "@babel/runtime" "^7.12.13" history "^4.9.0" loose-envify "^1.3.1" prop-types "^15.6.2" - react-router "5.1.2" + react-router "5.3.3" + tiny-invariant "^1.0.2" + tiny-warning "^1.0.0" + +react-router@5.3.3: + version "5.3.3" + resolved "https://registry.yarnpkg.com/react-router/-/react-router-5.3.3.tgz#8e3841f4089e728cf82a429d92cdcaa5e4a3a288" + integrity sha512-mzQGUvS3bM84TnbtMYR8ZjKnuPJ71IjSzR+DE6UkUqvN4czWIqEs17yLL8xkAycv4ev0AiN+IGrWu88vJs/p2w== + dependencies: + "@babel/runtime" "^7.12.13" + history "^4.9.0" + hoist-non-react-statics "^3.1.0" + loose-envify "^1.3.1" + mini-create-react-context "^0.4.0" + path-to-regexp "^1.7.0" + prop-types "^15.6.2" + react-is "^16.6.0" tiny-invariant "^1.0.2" tiny-warning "^1.0.0" -react-router@5.1.2, react-router@^5.1.2: +react-router@^5.1.2: version "5.1.2" resolved "https://registry.yarnpkg.com/react-router/-/react-router-5.1.2.tgz#6ea51d789cb36a6be1ba5f7c0d48dd9e817d3418" integrity sha512-yjEuMFy1ONK246B+rsa0cUam5OeAQ8pyclRDgpxuSCrAlJ1qN9uZ5IgyKC7gQg0w8OM50NXHEegPh/ks9YuR2A== @@ -16297,7 +16530,7 @@ react-router@5.1.2, react-router@^5.1.2: tiny-invariant "^1.0.2" tiny-warning "^1.0.0" -react-scripts@5.0.1: +react-scripts@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/react-scripts/-/react-scripts-5.0.1.tgz#6285dbd65a8ba6e49ca8d651ce30645a6d980003" integrity sha512-8VAmEm/ZAwQzJ+GOMLbBsTdDKOpuZh7RPs0UymvBR2vRk4iZWCskjbFnxqjrzoIvlNNRZ3QJFx6/qDSi6zSnaQ== @@ -16565,6 +16798,11 @@ regenerator-runtime@^0.11.0: resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9" integrity sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg== +regenerator-runtime@^0.13.11: + version "0.13.11" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz#f6dca3e7ceec20590d07ada785636a90cdca17f9" + integrity sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg== + regenerator-runtime@^0.13.2: version "0.13.3" resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.3.tgz#7cf6a77d8f5c6f60eb73c5fc1955b2ceb01e6bf5" @@ -17249,6 +17487,18 @@ rollup-plugin-terser@^7.0.0: serialize-javascript "^4.0.0" terser "^5.0.0" +rollup-plugin-typescript2@^0.31.2: + version "0.31.2" + resolved "https://registry.yarnpkg.com/rollup-plugin-typescript2/-/rollup-plugin-typescript2-0.31.2.tgz#463aa713a7e2bf85b92860094b9f7fb274c5a4d8" + integrity sha512-hRwEYR1C8xDGVVMFJQdEVnNAeWRvpaY97g5mp3IeLnzhNXzSVq78Ye/BJ9PAaUfN4DXa/uDnqerifMOaMFY54Q== + dependencies: + "@rollup/pluginutils" "^4.1.2" + "@yarn-tool/resolve-package" "^1.0.40" + find-cache-dir "^3.3.2" + fs-extra "^10.0.0" + resolve "^1.20.0" + tslib "^2.3.1" + rollup@^2.43.1: version "2.70.1" resolved "https://registry.yarnpkg.com/rollup/-/rollup-2.70.1.tgz#824b1f1f879ea396db30b0fc3ae8d2fead93523e" @@ -18833,7 +19083,7 @@ tiny-invariant@^1.0.2: resolved "https://registry.yarnpkg.com/tiny-invariant/-/tiny-invariant-1.1.0.tgz#634c5f8efdc27714b7f386c35e6760991d230875" integrity sha512-ytxQvrb1cPc9WBEI/HSeYYoGD0kWnGEOR8RY6KomWLBVhqz0RgTwVO9dLrGz7dC+nN9llyI7OKAgRq8Vq4ZBSw== -tiny-warning@^1.0.0, tiny-warning@^1.0.2: +tiny-warning@^1.0.0, tiny-warning@^1.0.2, tiny-warning@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/tiny-warning/-/tiny-warning-1.0.3.tgz#94a30db453df4c643d0fd566060d60a875d84754" integrity sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA== @@ -19014,6 +19264,11 @@ tslib@^1.10.0, tslib@^1.8.1, tslib@^1.9.0: resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.11.1.tgz#eb15d128827fbee2841549e171f45ed338ac7e35" integrity sha512-aZW88SY8kQbU7gpV19lN24LtXh/yD4ZZg6qieAJDDg+YBsJcSmLGK9QpnUjAKVG/xefmvJGd1WUmfpT/g6AJGA== +tslib@^2, tslib@^2.3.1: + version "2.5.0" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.5.0.tgz#42bfed86f5787aeb41d031866c8f402429e0fddf" + integrity sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg== + tslib@^2.0.0, tslib@^2.0.3: version "2.3.1" resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.3.1.tgz#e8a335add5ceae51aa261d32a490158ef042ef01" @@ -19129,6 +19384,11 @@ typescript@3.5.3: resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.5.3.tgz#c830f657f93f1ea846819e929092f5fe5983e977" integrity sha512-ACzBtm/PhXBDId6a6sDJfroT2pOWt/oOnk4/dElG5G33ZL776N3Y6/6bKZJBFpd+b05F3Ct9qDjMeJmRWtE2/g== +typescript@^5.0.2: + version "5.0.2" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.0.2.tgz#891e1a90c5189d8506af64b9ef929fca99ba1ee5" + integrity sha512-wVORMBGO/FAs/++blGNeAVdbNKtIh1rbBL2EyQ1+J9lClJ93KiiKe8PmFIVdXhHcyv44SL9oglmfeSsndo0jRw== + typography-breakpoint-constants@^0.16.19: version "0.16.19" resolved "https://registry.yarnpkg.com/typography-breakpoint-constants/-/typography-breakpoint-constants-0.16.19.tgz#e0e89147749562cbb46ce76c47ff0f73372765e7" @@ -19506,6 +19766,16 @@ unset-value@^1.0.0: has-value "^0.3.1" isobject "^3.0.0" +upath2@^3.1.13: + version "3.1.19" + resolved "https://registry.yarnpkg.com/upath2/-/upath2-3.1.19.tgz#d987d34a62b2daad1c54a692fd5a720a30c9a786" + integrity sha512-d23dQLi8nDWSRTIQwXtaYqMrHuca0As53fNiTLLFDmsGBbepsZepISaB2H1x45bDFN/n3Qw9bydvyZEacTrEWQ== + dependencies: + "@types/node" "*" + path-is-network-drive "^1.0.20" + path-strip-sep "^1.0.17" + tslib "^2" + upath@^1.1.1, upath@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/upath/-/upath-1.2.0.tgz#8f66dbcd55a883acdae4408af8b035a5044c1894" diff --git a/package.json b/package.json index 8f8ca889..9dfd499b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "flume", - "version": "0.8.2", + "version": "1.0.2-4", "description": "A node editor for React", "author": "chrisjpatty", "license": "MIT", @@ -32,15 +32,28 @@ "react-dom": "^18.2.0" }, "devDependencies": { + "@babel/core": "^7.17.5", + "@babel/plugin-external-helpers": "^7.16.7", "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-transform-runtime": "^7.17.0", + "@babel/preset-env": "^7.16.11", + "@babel/preset-react": "^7.16.7", + "@babel/preset-typescript": "^7.16.7", + "@rollup/plugin-babel": "^5.3.1", + "@rollup/plugin-commonjs": "^21.0.2", + "@rollup/plugin-node-resolve": "^13.1.3", + "@rollup/plugin-replace": "^4.0.0", + "@rollup/plugin-typescript": "^8.3.2", "@svgr/rollup": "^2.4.1", "@testing-library/dom": "^7.20.0", "@testing-library/react": "^14.0.0", + "@types/d3-shape": "^3.0.2", + "@types/lodash": "^4.14.182", + "@types/react": "^18.0.5", + "@types/react-portal": "^4.0.4", "@typescript-eslint/eslint-plugin": "2.x", "@typescript-eslint/parser": "2.x", - "babel-core": "^6.26.3", "babel-eslint": "10.x", - "babel-plugin-external-helpers": "^6.22.0", "babel-preset-env": "^1.7.0", "babel-preset-react": "^6.24.1", "babel-preset-stage-0": "^6.24.1", @@ -54,9 +67,10 @@ "eslint-plugin-jsx-a11y": "6.x", "eslint-plugin-node": "^7.0.1", "eslint-plugin-promise": "^4.0.0", - "eslint-plugin-react": "7.x", + "eslint-plugin-react": "^7.32.2", "eslint-plugin-react-hooks": "1.x", "eslint-plugin-standard": "^3.1.0", + "eslint-plugin-tsdoc": "^0.2.16", "gh-pages": "^1.2.0", "jest-puppeteer": "^4.4.0", "np": "^7.2.0", @@ -64,13 +78,12 @@ "react": "^18.2.0", "react-dom": "^18.2.0", "react-scripts": "^5.0.0", - "rollup": "^0.64.1", - "rollup-plugin-babel": "^3.0.7", - "rollup-plugin-commonjs": "^9.1.3", - "rollup-plugin-node-resolve": "^3.3.0", + "rollup": "^2.70.2", "rollup-plugin-peer-deps-external": "^2.2.0", "rollup-plugin-postcss": "^1.6.2", "rollup-plugin-url": "^1.4.0", + "tslib": "^2.3.1", + "typescript": "^4.6.3", "wait-on": "^5.2.1", "y18n": "^5.0.8" }, @@ -81,8 +94,9 @@ "@reach/auto-id": "^0.10.5", "d3-shape": "^1.3.7", "lodash": "^4.17.15", - "nanoid": "^3.1.30", - "react-portal": "^4.2.1" + "nanoid": "^3.3.2", + "react-portal": "^4.2.1", + "rollup-plugin-typescript2": "^0.31.2" }, "jest": { "transformIgnorePatterns": [ diff --git a/rollup.config.js b/rollup.config.js index 4fe30004..7016c7a4 100644 --- a/rollup.config.js +++ b/rollup.config.js @@ -1,15 +1,16 @@ -import babel from 'rollup-plugin-babel' -import commonjs from 'rollup-plugin-commonjs' +import babel from '@rollup/plugin-babel' +import commonjs from '@rollup/plugin-commonjs' import external from 'rollup-plugin-peer-deps-external' import postcss from 'rollup-plugin-postcss' -import resolve from 'rollup-plugin-node-resolve' +import resolve from '@rollup/plugin-node-resolve' import url from 'rollup-plugin-url' import svgr from '@svgr/rollup' +import typescript from '@rollup/plugin-typescript'; import pkg from './package.json' export default { - input: 'src/index.js', + input: 'src/index.ts', output: [ { file: pkg.main, @@ -25,17 +26,19 @@ export default { external: [ 'react', 'react-dom' ], plugins: [ external(), - postcss({ - modules: true, - plugins: [require('postcss-nested')] - }), url(), svgr(), + resolve(), babel({ + extensions: ['.js', '.ts', '.tsx'], exclude: 'node_modules/**', - plugins: [ 'external-helpers' ] + babelHelpers: 'runtime', + }), + typescript({tsconfig: './tsconfig.json'}), + commonjs(), + postcss({ + modules: true, + plugins: [require('postcss-nested')] }), - resolve(), - commonjs() ] } diff --git a/src/Cache.js b/src/Cache.js deleted file mode 100644 index 87c6641a..00000000 --- a/src/Cache.js +++ /dev/null @@ -1,7 +0,0 @@ -class Cache{ - constructor(){ - this.ports = {}; - this.connections = {}; - } -} -export default Cache diff --git a/src/Cache.ts b/src/Cache.ts new file mode 100644 index 00000000..7d5d2d03 --- /dev/null +++ b/src/Cache.ts @@ -0,0 +1,12 @@ +import { Connections, PortType } from "./types"; + +class FlumeCache{ + ports: { [portType: string]: Element }; + connections: {[id: string]: SVGPathElement}; + + constructor(){ + this.ports = {}; + this.connections = {}; + } +} +export default FlumeCache diff --git a/src/Globals.d.ts b/src/Globals.d.ts new file mode 100644 index 00000000..ae621ece --- /dev/null +++ b/src/Globals.d.ts @@ -0,0 +1,7 @@ +declare module '*.css' { + interface IClassNames { + [className: string]: string + } + const classNames: IClassNames; + export = classNames; +} \ No newline at end of file diff --git a/src/NodeEditor.tsx b/src/NodeEditor.tsx new file mode 100644 index 00000000..0a135016 --- /dev/null +++ b/src/NodeEditor.tsx @@ -0,0 +1,282 @@ +import React from "react"; +import { useId } from "@reach/auto-id"; +import Stage from "./components/Stage/Stage"; +import Node from "./components/Node/Node"; +import Comment from "./components/Comment/Comment"; +import Toaster from "./components/Toaster/Toaster"; +import Connections from "./components/Connections/Connections"; +import { + NodeTypesContext, + PortTypesContext, + NodeDispatchContext, + ConnectionRecalculateContext, + RecalculateStageRectContext, + ContextContext, + StageContext, + CacheContext, + EditorIdContext +} from "./context"; +import { createConnections } from "./connectionCalculator"; +import nodesReducer, { + connectNodesReducer, + getInitialNodes, + NodesActionType +} from "./nodesReducer"; +import commentsReducer from "./commentsReducer"; +import toastsReducer, { ToastAction } from "./toastsReducer"; +import stageReducer from "./stageReducer"; +import usePrevious from "./hooks/usePrevious"; +import clamp from "lodash/clamp"; +import Cache from "./Cache"; +import { STAGE_ID, DRAG_CONNECTION_ID } from "./constants"; +import styles from "./styles.css"; +import { + CircularBehavior, + DefaultNode, + FlumeCommentMap, + NodeHeaderRenderCallback, + NodeMap, + NodeTypeMap, + PortTypeMap, + Toast +} from "./types"; + +const defaultContext = {}; + +interface NodeEditorProps { + comments?: FlumeCommentMap; + nodes?: NodeMap; + nodeTypes: NodeTypeMap; + portTypes: PortTypeMap; + defaultNodes?: DefaultNode[]; + context?: any; + onChange?: (nodes: NodeMap) => void; + onCommentsChange?: (comments: FlumeCommentMap) => void; + initialScale?: number; + spaceToPan?: boolean; + hideComments?: boolean; + disableComments?: boolean; + disableZoom?: boolean; + disablePan?: boolean; + circularBehavior?: CircularBehavior; + renderNodeHeader?: NodeHeaderRenderCallback; + debug?: boolean; +} + +export let NodeEditor = React.forwardRef( + ( + { + comments: initialComments, + nodes: initialNodes, + nodeTypes = {}, + portTypes = {}, + defaultNodes = [], + context = defaultContext, + onChange, + onCommentsChange, + initialScale, + spaceToPan = false, + hideComments = false, + disableComments = false, + disableZoom = false, + disablePan = false, + circularBehavior, + renderNodeHeader, + debug + }: NodeEditorProps, + ref + ) => { + const editorId = useId() ?? ""; + const cache = React.useRef(new Cache()); + const stage = React.useRef(); + const [sideEffectToasts, setSideEffectToasts] = React.useState< + ToastAction + >(); + const [toasts, dispatchToasts] = React.useReducer(toastsReducer, []); + const [nodes, dispatchNodes] = React.useReducer( + connectNodesReducer( + nodesReducer, + { nodeTypes, portTypes, cache, circularBehavior, context }, + setSideEffectToasts + ), + {}, + () => + getInitialNodes( + initialNodes, + defaultNodes, + nodeTypes, + portTypes, + context + ) + ); + + const [comments, dispatchComments] = React.useReducer( + commentsReducer, + initialComments || {} + ); + + React.useEffect(() => { + dispatchNodes({ type: NodesActionType.HYDRATE_DEFAULT_NODES }); + }, []); + + const [ + shouldRecalculateConnections, + setShouldRecalculateConnections + ] = React.useState(true); + + const [stageState, dispatchStageState] = React.useReducer(stageReducer, { + scale: typeof initialScale === "number" ? clamp(initialScale, 0.1, 7) : 1, + translate: { x: 0, y: 0 } + }); + + const recalculateConnections = React.useCallback(() => { + createConnections(nodes, stageState, editorId); + }, [nodes, editorId, stageState]); + + const recalculateStageRect = React.useCallback(() => { + stage.current = document + .getElementById(`${STAGE_ID}${editorId}`) + ?.getBoundingClientRect(); + }, [editorId]); + + React.useLayoutEffect(() => { + if (shouldRecalculateConnections) { + recalculateConnections(); + setShouldRecalculateConnections(false); + } + }, [shouldRecalculateConnections, recalculateConnections]); + + const triggerRecalculation = React.useCallback(() => { + setShouldRecalculateConnections(true); + }, []); + + React.useImperativeHandle(ref, () => ({ + getNodes: () => { + return nodes; + }, + getComments: () => { + return comments; + } + })); + + const previousNodes = usePrevious(nodes); + + React.useEffect(() => { + if (previousNodes && onChange && nodes !== previousNodes) { + onChange(nodes); + } + }, [nodes, previousNodes, onChange]); + + const previousComments = usePrevious(comments); + + React.useEffect(() => { + if ( + previousComments && + onCommentsChange && + comments !== previousComments + ) { + onCommentsChange(comments); + } + }, [comments, previousComments, onCommentsChange]); + + React.useEffect(() => { + if (sideEffectToasts) { + dispatchToasts(sideEffectToasts); + setSideEffectToasts(undefined); + } + }, [sideEffectToasts]); + + return ( + + + + + + + + + + + {debug && ( +
+ + + +
+ )} + + + } + > + {!hideComments && + Object.values(comments).map(comment => ( + + ))} + {Object.values(nodes).map(node => ( + + ))} + +
+
+
+
+
+
+
+
+
+
+
+ ); + } +); diff --git a/src/RootEngine.js b/src/RootEngine.ts similarity index 52% rename from src/RootEngine.js rename to src/RootEngine.ts index 7e12e83b..95f47c85 100644 --- a/src/RootEngine.js +++ b/src/RootEngine.ts @@ -1,24 +1,52 @@ +import { + PortResolver, + NodeResolver, + NodeMap, + ConnectionMap, + Connection, + FlumeNode, + NodeType, + NodeTypeMap, + Connections, + RootEngineOptions +} from "./types"; +import { FlumeConfig } from "./typeBuilders"; + class LoopError extends Error { - constructor(message, code) { + public code: number; + static maxLoopsExceeded = 1; + + constructor(message: string, code: number) { super(message); this.code = code; } - static maxLoopsExceeded = 1; } export class RootEngine { - constructor(config, resolveInputControls, fireNodeFunction) { + public config: FlumeConfig; + private resolveInputControls: PortResolver; + private fireNodeFunction: NodeResolver; + private loops: number; + private maxLoops: number; + + constructor( + config: FlumeConfig, + resolveInputControls: PortResolver, + fireNodeFunction: NodeResolver + ) { this.config = config; this.fireNodeFunction = fireNodeFunction; this.resolveInputControls = resolveInputControls; this.loops = 0; this.maxLoops = 1000; } - resetLoops = maxLoops => { + + private resetLoops = (maxLoops?: number) => { this.maxLoops = maxLoops !== undefined ? maxLoops : 1000; this.loops = 0; }; - checkLoops = () => { + + private checkLoops = () => { if (this.maxLoops >= 0 && this.loops > this.maxLoops) { throw new LoopError( "Max loop count exceeded.", @@ -28,7 +56,8 @@ export class RootEngine { this.loops++; } }; - getRootNode = nodes => { + + private getRootNode = (nodes: NodeMap) => { const roots = Object.values(nodes).filter(n => n.root); if (roots.length > 1) { throw new Error( @@ -37,16 +66,32 @@ export class RootEngine { } return roots[0]; }; - reduceRootInputs = (inputs, callback) => - Object.entries(inputs).reduce((obj, [inputName, connection]) => { - const input = callback(inputName, connection); - obj[input.name] = input.value; - return obj; - }, {}); - resolveInputValues = (node, nodeType, nodes, context) => { - let inputs = nodeType.inputs - if (typeof inputs === 'function') { - inputs = inputs(node.inputData, node.connections, context) + + private reduceRootInputs = ( + inputs: ConnectionMap, + callback: ( + inputName: string, + connection: Connection[] + ) => { name: string; value: any } + ) => + Object.entries(inputs).reduce<{ [inputName: string]: any }>( + (obj, [inputName, connections]) => { + const input = callback(inputName, connections); + obj[input.name] = input.value; + return obj; + }, + {} + ); + + private resolveInputValues = ( + node: FlumeNode, + nodeType: NodeType, + nodes: NodeMap, + context: any + ) => { + let inputs = nodeType.inputs; + if (typeof inputs === "function") { + inputs = inputs(node.inputData, node.connections, context); } return inputs.reduce((obj, input) => { const inputConnections = node.connections.inputs[input.name] || []; @@ -66,7 +111,12 @@ export class RootEngine { return obj; }, {}); }; - getValueOfConnection = (connection, nodes, context) => { + + private getValueOfConnection = ( + connection: Connection, + nodes: NodeMap, + context: any + ) => { this.checkLoops(); const outputNode = nodes[connection.nodeId]; const outputNodeType = this.config.nodeTypes[outputNode.type]; @@ -84,42 +134,53 @@ export class RootEngine { )[connection.portName]; return outputResult; }; - resolveRootNode(nodes, options = {}) { + + public resolveRootNode( + nodes: NodeMap, + rawOptions?: RootEngineOptions + ): T { + const options = rawOptions ?? {}; const rootNode = options.rootNodeId ? nodes[options.rootNodeId] : this.getRootNode(nodes); if (rootNode) { let inputs = this.config.nodeTypes[rootNode.type].inputs; - if (typeof inputs === 'function') { - inputs = inputs(rootNode.inputData, rootNode.connections, options.context); + if (typeof inputs === "function") { + inputs = inputs( + rootNode.inputData, + rootNode.connections, + options.context + ); } - const controlValues = inputs.reduce( - (obj, input) => { - obj[input.name] = this.resolveInputControls( - input.type, - rootNode.inputData[input.name] || {}, - options.context - ); - return obj; - }, - {} - ); + const controlValues = inputs.reduce<{ + [controlName: string]: any; + }>((obj, input) => { + obj[input.name] = this.resolveInputControls( + input.type, + rootNode.inputData[input.name] || {}, + options.context + ); + return obj; + }, {}); const inputValues = this.reduceRootInputs( rootNode.connections.inputs, - (inputName, connection) => { + (inputName, connections) => { this.resetLoops(options.maxLoops); let value; try { value = this.getValueOfConnection( - connection[0], + connections[0], nodes, options.context ); } catch (e) { - if (e.code === LoopError.maxLoopsExceeded) { - console.error(`${e.message} Circular nodes detected in ${inputName} port.`); + const err = e as LoopError; + if (err.code === LoopError.maxLoopsExceeded) { + console.error( + `${err.message} Circular nodes detected in ${inputName} port.` + ); } else { - console.error(e) + console.error(e); } } finally { return { @@ -130,15 +191,15 @@ export class RootEngine { } ); if (options.onlyResolveConnected) { - return inputValues; + return inputValues as T; } else { - return { ...controlValues, ...inputValues }; + return { ...controlValues, ...inputValues } as T; } } else { console.error( "A root node was not found. The Root Engine requires that exactly one node be marked as the root node." ); - return {}; + return {} as T; } } } diff --git a/src/commentsReducer.js b/src/commentsReducer.js deleted file mode 100644 index 06f37ce5..00000000 --- a/src/commentsReducer.js +++ /dev/null @@ -1,57 +0,0 @@ -import { nanoid }from "nanoid/non-secure/index"; - -const setComment = (comments, id, merge) => ({ - ...comments, - [id]: { - ...comments[id], - ...merge - } -}); - -export default (comments = {}, action) => { - switch (action.type) { - case "ADD_COMMENT": { - const comment = { - id: nanoid(10), - text: "", - x: action.x, - y: action.y, - width: 200, - height: 30, - color: "blue", - isNew: true - }; - return { - ...comments, - [comment.id]: comment - }; - } - case "REMOVE_COMMENT_NEW": - const { isNew: toDelete, ...comment } = comments[action.id]; - return { - ...comments, - [action.id]: comment - }; - case "SET_COMMENT_COORDINATES": { - return setComment(comments, action.id, { x: action.x, y: action.y }); - } - case "SET_COMMENT_DIMENSIONS": { - return setComment(comments, action.id, { - width: action.width, - height: action.height - }); - } - case "SET_COMMENT_TEXT": { - return setComment(comments, action.id, { text: action.text }); - } - case "SET_COMMENT_COLOR": { - return setComment(comments, action.id, { color: action.color }); - } - case "DELETE_COMMENT": { - const { [action.id]: toDelete, ...newComments } = comments; - return newComments; - } - default: - return comments; - } -}; diff --git a/src/commentsReducer.ts b/src/commentsReducer.ts new file mode 100644 index 00000000..b8114f7e --- /dev/null +++ b/src/commentsReducer.ts @@ -0,0 +1,116 @@ +import { nanoid } from "nanoid/non-secure"; +import { Colors, FlumeComment } from "./types"; + +type CommentMap = { [commentId: string]: FlumeComment }; + +export enum CommentActionTypes { + ADD_COMMENT = "ADD_COMMENT", + REMOVE_COMMENT_NEW = "REMOVE_COMMENT_NEW", + SET_COMMENT_COORDINATES = "SET_COMMENT_COORDINATES", + SET_COMMENT_DIMENSIONS = "SET_COMMENT_DIMENSIONS", + SET_COMMENT_TEXT = "SET_COMMENT_TEXT", + SET_COMMENT_COLOR = "SET_COMMENT_COLOR", + DELETE_COMMENT = "DELETE_COMMENT" +} + +export type CommentAction = + | { + type: CommentActionTypes.ADD_COMMENT; + x: number; + y: number; + } + | { + type: CommentActionTypes.REMOVE_COMMENT_NEW; + id: string; + } + | { + type: CommentActionTypes.SET_COMMENT_COORDINATES; + id: string; + x: number; + y: number; + } + | { + type: CommentActionTypes.SET_COMMENT_DIMENSIONS; + id: string; + width: number; + height: number; + } + | { + type: CommentActionTypes.SET_COMMENT_TEXT; + id: string; + text: string; + } + | { + type: CommentActionTypes.SET_COMMENT_COLOR; + id: string; + color: Colors; + } + | { + type: CommentActionTypes.DELETE_COMMENT; + id: string; + }; + +const setComment = ( + comments: CommentMap, + id: string, + merge: Partial +): CommentMap => ({ + ...comments, + [id]: { + ...comments[id], + ...merge + } +}); + +const commentsReducer: React.Reducer = ( + comments = {}, + action +) => { + switch (action.type) { + case CommentActionTypes.ADD_COMMENT: { + const comment = { + id: nanoid(10), + text: "", + x: action.x, + y: action.y, + width: 200, + height: 30, + color: "blue", + isNew: true + }; + return { + ...comments, + [comment.id]: comment + } as CommentMap; + } + case CommentActionTypes.REMOVE_COMMENT_NEW: + const { isNew: toDelete, ...comment } = comments[action.id]; + return { + ...comments, + [action.id]: comment + } as CommentMap; + case CommentActionTypes.SET_COMMENT_COORDINATES: { + return setComment(comments, action.id, { x: action.x, y: action.y }); + } + case CommentActionTypes.SET_COMMENT_DIMENSIONS: { + return setComment(comments, action.id, { + width: action.width, + height: action.height + }); + } + case CommentActionTypes.SET_COMMENT_TEXT: { + return setComment(comments, action.id, { text: action.text }); + } + case CommentActionTypes.SET_COMMENT_COLOR: { + return setComment(comments, action.id, { color: action.color }); + } + case CommentActionTypes.DELETE_COMMENT: { + const { [action.id]: toDelete, ...newComments } = comments; + return newComments as CommentMap; + } + default: + return comments; + } +}; + +export default commentsReducer; diff --git a/src/components/Checkbox/Checkbox.js b/src/components/Checkbox/Checkbox.tsx similarity index 54% rename from src/components/Checkbox/Checkbox.js rename to src/components/Checkbox/Checkbox.tsx index b4295505..36b93847 100644 --- a/src/components/Checkbox/Checkbox.js +++ b/src/components/Checkbox/Checkbox.tsx @@ -1,8 +1,14 @@ import React from "react"; import styles from "./Checkbox.css"; -import { nanoid }from "nanoid/non-secure/index"; +import { nanoid } from "nanoid/non-secure"; -const Checkbox = ({ label, data, onChange }) => { +interface CheckboxProps { + label: string; + data: boolean; + onChange: (data: boolean) => void; +} + +const Checkbox = ({ label, data, onChange }: CheckboxProps) => { const id = React.useRef(nanoid(10)); return ( @@ -11,12 +17,15 @@ const Checkbox = ({ label, data, onChange }) => { data-flume-component="checkbox" className={styles.checkbox} type="checkbox" - id={id} - value={data} + id={id.current} checked={data} onChange={e => onChange(e.target.checked)} /> -
diff --git a/src/components/ColorPicker/ColorPicker.js b/src/components/ColorPicker/ColorPicker.tsx similarity index 51% rename from src/components/ColorPicker/ColorPicker.js rename to src/components/ColorPicker/ColorPicker.tsx index c3face08..34b6d349 100644 --- a/src/components/ColorPicker/ColorPicker.js +++ b/src/components/ColorPicker/ColorPicker.tsx @@ -1,13 +1,22 @@ import React from "react"; import styles from "./ColorPicker.css"; import { Colors } from "../../typeBuilders"; +import { Colors as ColorsType } from "../../types"; -export default ({ x, y, onColorPicked, onRequestClose }) => { - const wrapper = React.useRef(); +interface ColorPickerProps { + x: number; + y: number; + onColorPicked: (color: ColorsType) => void; + onRequestClose: () => void; +} + +export default ({ x, y, onColorPicked, onRequestClose }: ColorPickerProps) => { + const wrapper = React.useRef(null); const testClickOutside = React.useCallback( - e => { - if (wrapper.current && !wrapper.current.contains(e.target)) { + (e: MouseEvent) => { + console.log("testClickOutside", e.type); + if (wrapper.current && !wrapper.current.contains(e.target as Node)) { onRequestClose(); document.removeEventListener("click", testClickOutside); document.removeEventListener("contextmenu", testClickOutside); @@ -17,8 +26,8 @@ export default ({ x, y, onColorPicked, onRequestClose }) => { ); const testEscape = React.useCallback( - e => { - if (e.keyCode === 27) { + (e: KeyboardEvent) => { + if (e.key === "Escape") { onRequestClose(); document.removeEventListener("keydown", testEscape); } @@ -27,9 +36,11 @@ export default ({ x, y, onColorPicked, onRequestClose }) => { ); React.useEffect(() => { - document.addEventListener("keydown", testEscape); - document.addEventListener("click", testClickOutside); - document.addEventListener("contextmenu", testClickOutside); + setTimeout(() => { + document.addEventListener("keydown", testEscape); + document.addEventListener("click", testClickOutside); + document.addEventListener("contextmenu", testClickOutside); + }); return () => { document.removeEventListener("click", testClickOutside); document.removeEventListener("contextmenu", testClickOutside); @@ -47,21 +58,30 @@ export default ({ x, y, onColorPicked, onRequestClose }) => { top: y }} > - {Object.values(Colors).map(color => ( - { - onColorPicked(color); - onRequestClose(); - }} - color={color} - key={color} - /> - ))} + {Object.values(Colors).map(colorString => { + const color = colorString as ColorsType; + return ( + { + onColorPicked(color); + onRequestClose(); + }} + color={color} + key={color} + /> + ); + })}
); }; -const ColorButton = ({ color, onSelected }) => ( +const ColorButton = ({ + color, + onSelected +}: { + color: ColorsType; + onSelected: () => void; +}) => (
+
); }; + +export default Toaster; \ No newline at end of file diff --git a/src/connectionCalculator.js b/src/connectionCalculator.ts similarity index 52% rename from src/connectionCalculator.js rename to src/connectionCalculator.ts index 6ec52288..640d3157 100644 --- a/src/connectionCalculator.js +++ b/src/connectionCalculator.ts @@ -1,30 +1,49 @@ import styles from "./components/Connection/Connection.css"; -import { CONNECTIONS_ID } from './constants' -import { line, curveBasis } from 'd3-shape' +import { CONNECTIONS_ID } from "./constants"; +import { line, curveBasis } from "d3-shape"; +import { Coordinate, FlumeNode, StageState, TransputType } from "./types"; +import FlumeCache from "./Cache"; +import { RefObject } from "react"; -const getPort = (nodeId, portName, transputType = "input") => document - .querySelector( +const getPort = ( + nodeId: string, + portName: string, + transputType: TransputType = "input" +) => + document.querySelector( `[data-node-id="${nodeId}"] [data-port-name="${portName}"][data-port-transput-type="${transputType}"]` - ) + ); + +export const getPortRect = ( + nodeId: string, + portName: string, + transputType?: TransputType, + cache?: RefObject +) => { + let calculatedTransputType = transputType ?? "input"; -export const getPortRect = (nodeId, portName, transputType = "input", cache) => { - if(cache){ - const portCacheName = nodeId + portName + transputType; + if (cache && cache.current) { + const portCacheName = nodeId + portName + calculatedTransputType; const cachedPort = cache.current.ports[portCacheName]; - if(cachedPort){ + if (cachedPort) { return cachedPort.getBoundingClientRect(); - }else{ - const port = getPort(nodeId, portName, transputType) - cache.current.ports[portCacheName] = port; + } else { + const port = getPort(nodeId, portName, calculatedTransputType); + if (port) { + cache.current.ports[portCacheName] = port; + } return port && port.getBoundingClientRect(); } - }else{ - const port = getPort(nodeId, portName, transputType); + } else { + const port = getPort(nodeId, portName, calculatedTransputType); return port && port.getBoundingClientRect(); } -} +}; -export const getPortRectsByNodes = (nodes, forEachConnection) => +export const getPortRectsByNodes = ( + nodes: { [nodeId: string]: FlumeNode }, + forEachConnection +) => Object.values(nodes).reduce((obj, node) => { if (node.connections && node.connections.inputs) { Object.entries(node.connections.inputs).forEach( @@ -52,33 +71,44 @@ export const getPortRectsByNodes = (nodes, forEachConnection) => return obj; }, {}); -export const calculateCurve = (from, to) => { +export const calculateCurve = (from: Coordinate, to: Coordinate) => { const length = to.x - from.x; const thirdLength = length / 3; - const curve = line().curve(curveBasis)([ - [from.x, from.y], - [from.x + thirdLength, from.y], - [from.x + thirdLength * 2, to.y], - [to.x, to.y] - ]); + const curve = + line().curve(curveBasis)([ + [from.x, from.y], + [from.x + thirdLength, from.y], + [from.x + thirdLength * 2, to.y], + [to.x, to.y] + ]) ?? ""; return curve; }; -export const deleteConnection = ({ id }) => { +export const deleteConnection = ({ id }: { id: string }) => { const line = document.querySelector(`[data-connection-id="${id}"]`); - if (line) line.parentNode.remove(); + line?.parentElement?.remove(); }; -export const deleteConnectionsByNodeId = nodeId => { - const lines = document.querySelectorAll( - `[data-output-node-id="${nodeId}"], [data-input-node-id="${nodeId}"]` +export const deleteConnectionsByNodeId = (nodeId: string) => { + const lines = Array.from( + document.querySelectorAll( + `[data-output-node-id="${nodeId}"], [data-input-node-id="${nodeId}"]` + ) ); for (const line of lines) { - line.parentNode.remove(); + line?.parentElement?.remove(); } }; -export const updateConnection = ({ line, from, to }) => { +export const updateConnection = ({ + line, + from, + to +}: { + line: SVGPathElement; + from: Coordinate; + to: Coordinate; +}) => { line.setAttribute("d", calculateCurve(from, to)); }; @@ -91,12 +121,21 @@ export const createSVG = ({ outputPortName, inputNodeId, inputPortName +}: { + from: Coordinate; + to: Coordinate; + stage: HTMLDivElement; + id: string; + outputNodeId: string; + outputPortName: string; + inputNodeId: string; + inputPortName: string; }) => { const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg"); svg.setAttribute("class", styles.svg); const path = document.createElementNS("http://www.w3.org/2000/svg", "path"); - const curve = calculateCurve(from, to) - path.setAttribute("d", curve) + const curve = calculateCurve(from, to); + path.setAttribute("d", curve); path.setAttribute("stroke", "rgb(185, 186, 189)"); path.setAttribute("stroke-width", "3"); path.setAttribute("stroke-linecap", "round"); @@ -111,17 +150,23 @@ export const createSVG = ({ return svg; }; -export const getStageRef = editorId => - document.getElementById(`${CONNECTIONS_ID}${editorId}`); +export const getStageRef = (editorId: string) => + document.getElementById( + `${CONNECTIONS_ID}${editorId}` + ) as HTMLDivElement | null; -export const createConnections = (nodes, {scale, stageId}, editorId) => { +export const createConnections = ( + nodes: { [nodeId: string]: FlumeNode }, + { scale }: StageState, + editorId: string +) => { const stageRef = getStageRef(editorId); - if(stageRef){ + if (stageRef) { const stage = stageRef.getBoundingClientRect(); const stageHalfWidth = stage.width / 2; const stageHalfHeight = stage.height / 2; - const byScale = value => (1 / scale) * value; + const byScale = (value: number) => (1 / scale) * value; Object.values(nodes).forEach(node => { if (node.connections && node.connections.inputs) { @@ -136,20 +181,29 @@ export const createConnections = (nodes, {scale, stageId}, editorId) => { const toPort = getPortRect(node.id, inputName, "input"); const portHalf = fromPort ? fromPort.width / 2 : 0; if (fromPort && toPort) { - const id = output.nodeId + output.portName + node.id + inputName; - const existingLine = document.querySelector( + const id = + output.nodeId + output.portName + node.id + inputName; + const existingLine: SVGPathElement | null = document.querySelector( `[data-connection-id="${id}"]` ); if (existingLine) { updateConnection({ line: existingLine, from: { - x: byScale(fromPort.x - stage.x + portHalf - stageHalfWidth), - y: byScale(fromPort.y - stage.y + portHalf - stageHalfHeight) + x: byScale( + fromPort.x - stage.x + portHalf - stageHalfWidth + ), + y: byScale( + fromPort.y - stage.y + portHalf - stageHalfHeight + ) }, to: { - x: byScale(toPort.x - stage.x + portHalf - stageHalfWidth), - y: byScale(toPort.y - stage.y + portHalf - stageHalfHeight) + x: byScale( + toPort.x - stage.x + portHalf - stageHalfWidth + ), + y: byScale( + toPort.y - stage.y + portHalf - stageHalfHeight + ) } }); } else { @@ -160,12 +214,20 @@ export const createConnections = (nodes, {scale, stageId}, editorId) => { inputNodeId: node.id, inputPortName: inputName, from: { - x: byScale(fromPort.x - stage.x + portHalf - stageHalfWidth), - y: byScale(fromPort.y - stage.y + portHalf - stageHalfHeight) + x: byScale( + fromPort.x - stage.x + portHalf - stageHalfWidth + ), + y: byScale( + fromPort.y - stage.y + portHalf - stageHalfHeight + ) }, to: { - x: byScale(toPort.x - stage.x + portHalf - stageHalfWidth), - y: byScale(toPort.y - stage.y + portHalf - stageHalfHeight) + x: byScale( + toPort.x - stage.x + portHalf - stageHalfWidth + ), + y: byScale( + toPort.y - stage.y + portHalf - stageHalfHeight + ) }, stage: stageRef }); diff --git a/src/constants.js b/src/constants.ts similarity index 100% rename from src/constants.js rename to src/constants.ts diff --git a/src/context.js b/src/context.js deleted file mode 100644 index dbb1d16f..00000000 --- a/src/context.js +++ /dev/null @@ -1,11 +0,0 @@ -import React from 'react' - -export const NodeTypesContext = React.createContext() -export const PortTypesContext = React.createContext() -export const NodeDispatchContext = React.createContext() -export const ConnectionRecalculateContext = React.createContext() -export const ContextContext = React.createContext() -export const StageContext = React.createContext() -export const CacheContext = React.createContext() -export const RecalculateStageRectContext = React.createContext() -export const EditorIdContext = React.createContext() diff --git a/src/context.ts b/src/context.ts new file mode 100644 index 00000000..986a9953 --- /dev/null +++ b/src/context.ts @@ -0,0 +1,22 @@ +import { NodeTypeMap, StageState, PortTypeMap } from "./types"; +import { NodesAction } from "./nodesReducer"; +import React, { RefObject } from "react"; +import FlumeCache from "./Cache"; + +export const NodeTypesContext = React.createContext(null); +export const PortTypesContext = React.createContext(null); +export const NodeDispatchContext = React.createContext | null>(null); +export const ConnectionRecalculateContext = React.createContext< + (() => void) | null +>(null); +export const ContextContext = React.createContext(null); +export const StageContext = React.createContext(null); +export const CacheContext = React.createContext | null>( + null +); +export const RecalculateStageRectContext = React.createContext< + null | (() => void) +>(null); +export const EditorIdContext = React.createContext(""); diff --git a/src/hooks/usePrevious.js b/src/hooks/usePrevious.ts similarity index 67% rename from src/hooks/usePrevious.js rename to src/hooks/usePrevious.ts index 390e787a..65b53926 100644 --- a/src/hooks/usePrevious.js +++ b/src/hooks/usePrevious.ts @@ -1,7 +1,7 @@ import React from 'react' -const usePrevious = value => { - const ref = React.useRef(); +const usePrevious = (value: T) => { + const ref = React.useRef(); React.useEffect(() => { ref.current = value; }, [ref.current]); diff --git a/src/index.js b/src/index.js deleted file mode 100644 index 1f103364..00000000 --- a/src/index.js +++ /dev/null @@ -1,238 +0,0 @@ -import React from "react"; -import { useId } from "@reach/auto-id"; -import Stage from "./components/Stage/Stage"; -import Node from "./components/Node/Node"; -import Comment from "./components/Comment/Comment"; -import Toaster from "./components/Toaster/Toaster"; -import Connections from "./components/Connections/Connections"; -import { - NodeTypesContext, - PortTypesContext, - NodeDispatchContext, - ConnectionRecalculateContext, - RecalculateStageRectContext, - ContextContext, - StageContext, - CacheContext, - EditorIdContext -} from "./context"; -import { createConnections } from "./connectionCalculator"; -import nodesReducer, { - connectNodesReducer, - getInitialNodes -} from "./nodesReducer"; -import commentsReducer from "./commentsReducer"; -import toastsReducer from "./toastsReducer"; -import stageReducer from "./stageReducer"; -import usePrevious from "./hooks/usePrevious"; -import clamp from "lodash/clamp"; -import Cache from "./Cache"; -import { STAGE_ID, DRAG_CONNECTION_ID } from "./constants"; -import styles from "./styles.css"; - -const defaultContext = {}; - -export let NodeEditor = ( - { - comments: initialComments, - nodes: initialNodes, - nodeTypes = {}, - portTypes = {}, - defaultNodes = [], - context = defaultContext, - onChange, - onCommentsChange, - initialScale, - spaceToPan = false, - hideComments = false, - disableComments = false, - disableZoom = false, - disablePan = false, - circularBehavior, - renderNodeHeader, - debug - }, - ref -) => { - const editorId = useId(); - const cache = React.useRef(new Cache()); - const stage = React.useRef(); - const [sideEffectToasts, setSideEffectToasts] = React.useState() - const [toasts, dispatchToasts] = React.useReducer(toastsReducer, []); - const [nodes, dispatchNodes] = React.useReducer( - connectNodesReducer( - nodesReducer, - { nodeTypes, portTypes, cache, circularBehavior, context }, - setSideEffectToasts - ), - {}, - () => getInitialNodes(initialNodes, defaultNodes, nodeTypes, portTypes, context) - ); - const [comments, dispatchComments] = React.useReducer( - commentsReducer, - initialComments || {} - ); - React.useEffect(() => { - dispatchNodes({ type: "HYDRATE_DEFAULT_NODES" }); - }, []); - const [ - shouldRecalculateConnections, - setShouldRecalculateConnections - ] = React.useState(true); - const [stageState, dispatchStageState] = React.useReducer(stageReducer, { - scale: typeof initialScale === "number" ? clamp(initialScale, 0.1, 7) : 1, - translate: { x: 0, y: 0 } - }); - - const recalculateConnections = React.useCallback(() => { - createConnections(nodes, stageState, editorId); - }, [nodes, editorId, stageState]); - - const recalculateStageRect = React.useCallback(() => { - stage.current = document - .getElementById(`${STAGE_ID}${editorId}`) - .getBoundingClientRect(); - }, [editorId]); - - React.useLayoutEffect(() => { - if (shouldRecalculateConnections) { - recalculateConnections(); - setShouldRecalculateConnections(false); - } - }, [shouldRecalculateConnections, recalculateConnections]); - - const triggerRecalculation = React.useCallback(() => { - setShouldRecalculateConnections(true); - }, []); - - React.useImperativeHandle(ref, () => ({ - getNodes: () => { - return nodes; - }, - getComments: () => { - return comments; - } - })); - - const previousNodes = usePrevious(nodes); - - React.useEffect(() => { - if (previousNodes && onChange && nodes !== previousNodes) { - onChange(nodes); - } - }, [nodes, previousNodes, onChange]); - - const previousComments = usePrevious(comments); - - React.useEffect(() => { - if (previousComments && onCommentsChange && comments !== previousComments) { - onCommentsChange(comments); - } - }, [comments, previousComments, onCommentsChange]); - - React.useEffect(() => { - if(sideEffectToasts){ - dispatchToasts(sideEffectToasts) - setSideEffectToasts(null) - } - }, [sideEffectToasts]) - - return ( - - - - - - - - - - - {debug && ( -
- - - -
- )} - - - } - > - {!hideComments && - Object.values(comments).map(comment => ( - - ))} - {Object.values(nodes).map(node => ( - - ))} - -
-
-
-
-
-
-
-
-
-
-
- ); -}; -NodeEditor = React.forwardRef(NodeEditor); -export { FlumeConfig, Controls, Colors } from "./typeBuilders"; -export { RootEngine } from "./RootEngine"; -export const useRootEngine = (nodes, engine, context, options = {}) => - Object.keys(nodes).length ? engine.resolveRootNode(nodes, {...options, context }) : {}; diff --git a/src/index.ts b/src/index.ts new file mode 100644 index 00000000..1317ad53 --- /dev/null +++ b/src/index.ts @@ -0,0 +1,5 @@ +export { NodeEditor } from "./NodeEditor"; +export { FlumeConfig, Controls, Colors } from "./typeBuilders"; +export { RootEngine } from "./RootEngine"; +export { useRootEngine } from "./useRootEngine"; +export * from "./types"; diff --git a/src/nodesReducer.js b/src/nodesReducer.ts similarity index 60% rename from src/nodesReducer.js rename to src/nodesReducer.ts index adac3518..c3360eed 100644 --- a/src/nodesReducer.js +++ b/src/nodesReducer.ts @@ -1,11 +1,28 @@ +import { RefObject } from "react"; import { deleteConnection, deleteConnectionsByNodeId } from "./connectionCalculator"; import { checkForCircularNodes } from "./utilities"; -import {nanoid} from "nanoid/non-secure/index"; +import { nanoid } from "nanoid/non-secure"; +import { + CircularBehavior, + ConnectionMap, + Connections, + DefaultNode, + FlumeNode, + NodeMap, + NodeType, + NodeTypeMap, + PortTypeMap, + Toast, + TransputType, + ValueSetter +} from "./types"; +import FlumeCache from "./Cache"; +import { ToastAction, ToastActionTypes } from "./toastsReducer"; -const addConnection = (nodes, input, output, portTypes) => { +const addConnection = (nodes: NodeMap, input, output, portTypes) => { const newNodes = { ...nodes, [input.nodeId]: { @@ -45,7 +62,7 @@ const addConnection = (nodes, input, output, portTypes) => { return newNodes; }; -const removeConnection = (nodes, input, output) => { +const removeConnection = (nodes: NodeMap, input, output) => { const inputNode = nodes[input.nodeId]; const { [input.portName]: removedInputPort, @@ -83,7 +100,7 @@ const removeConnection = (nodes, input, output) => { }; }; -const getFilteredTransputs = (transputs, nodeId) => +const getFilteredTransputs = (transputs: ConnectionMap, nodeId: string) => Object.entries(transputs).reduce((obj, [portName, transput]) => { const newTransputs = transput.filter(t => t.nodeId !== nodeId); if (newTransputs.length) { @@ -92,12 +109,12 @@ const getFilteredTransputs = (transputs, nodeId) => return obj; }, {}); -const removeConnections = (connections, nodeId) => ({ +const removeConnections = (connections: Connections, nodeId: string) => ({ inputs: getFilteredTransputs(connections.inputs, nodeId), outputs: getFilteredTransputs(connections.outputs, nodeId) }); -const removeNode = (startNodes, nodeId) => { +const removeNode = (startNodes: NodeMap, nodeId: string) => { let { [nodeId]: deletedNode, ...nodes } = startNodes; nodes = Object.values(nodes).reduce((obj, node) => { obj[node.id] = { @@ -111,19 +128,24 @@ const removeNode = (startNodes, nodeId) => { return nodes; }; -const reconcileNodes = (initialNodes, nodeTypes, portTypes, context) => { +const reconcileNodes = ( + initialNodes: NodeMap, + nodeTypes: NodeTypeMap, + portTypes: PortTypeMap, + context +) => { let nodes = { ...initialNodes }; // Delete extraneous nodes let nodesToDelete = Object.values(nodes) .map(node => (!nodeTypes[node.type] ? node.id : undefined)) - .filter(x => x); + .filter((x): x is string => !!x); nodesToDelete.forEach(nodeId => { nodes = nodesReducer( nodes, { - type: "REMOVE_NODE", + type: NodesActionType.REMOVE_NODE, nodeId }, { nodeTypes, portTypes, context } @@ -131,28 +153,36 @@ const reconcileNodes = (initialNodes, nodeTypes, portTypes, context) => { }); // Reconcile input data for each node - let reconciledNodes = Object.values(nodes).reduce((nodesObj, node) => { - const nodeType = nodeTypes[node.type]; - const defaultInputData = getDefaultData({ node, nodeType, portTypes, context }); - const currentInputData = Object.entries(node.inputData).reduce( - (dataObj, [key, data]) => { - if (defaultInputData[key] !== undefined) { - dataObj[key] = data; - } - return dataObj; - }, - {} - ); - const newInputData = { - ...defaultInputData, - ...currentInputData - }; - nodesObj[node.id] = { - ...node, - inputData: newInputData - }; - return nodesObj; - }, {}); + let reconciledNodes: NodeTypeMap = Object.values(nodes).reduce( + (nodesObj, node) => { + const nodeType = nodeTypes[node.type]; + const defaultInputData = getDefaultData({ + node, + nodeType, + portTypes, + context + }); + const currentInputData = Object.entries(node.inputData).reduce( + (dataObj, [key, data]) => { + if (defaultInputData[key] !== undefined) { + dataObj[key] = data; + } + return dataObj; + }, + {} + ); + const newInputData = { + ...defaultInputData, + ...currentInputData + }; + nodesObj[node.id] = { + ...node, + inputData: newInputData + }; + return nodesObj; + }, + {} + ); // Reconcile node attributes for each node reconciledNodes = Object.values(reconciledNodes).reduce((nodesObj, node) => { @@ -173,13 +203,18 @@ const reconcileNodes = (initialNodes, nodeTypes, portTypes, context) => { }; export const getInitialNodes = ( - initialNodes = {}, - defaultNodes = [], + initialNodes: NodeMap = {}, + defaultNodes: DefaultNode[] = [], nodeTypes, portTypes, context -) => { - const reconciledNodes = reconcileNodes(initialNodes, nodeTypes, portTypes, context); +): NodeMap => { + const reconciledNodes = reconcileNodes( + initialNodes, + nodeTypes, + portTypes, + context + ); return { ...reconciledNodes, @@ -191,7 +226,7 @@ export const getInitialNodes = ( nodes = nodesReducer( nodes, { - type: "ADD_NODE", + type: NodesActionType.ADD_NODE, id: `default-${i}`, defaultNode: true, x: dNode.x || 0, @@ -206,10 +241,21 @@ export const getInitialNodes = ( }; }; -const getDefaultData = ({ node, nodeType, portTypes, context }) => { +const getDefaultData = ({ + node, + nodeType, + portTypes, + context +}: { + node: FlumeNode; + nodeType: NodeType; + portTypes: PortTypeMap; + context: any; +}) => { const inputs = Array.isArray(nodeType.inputs) ? nodeType.inputs : nodeType.inputs(node.inputData, node.connections, context); + return inputs.reduce((obj, input) => { const inputType = portTypes[input.type]; obj[input.name || inputType.name] = ( @@ -224,25 +270,88 @@ const getDefaultData = ({ node, nodeType, portTypes, context }) => { }, {}); }; +export enum NodesActionType { + ADD_CONNECTION = "ADD_CONNECTION", + REMOVE_CONNECTION = "REMOVE_CONNECTION", + DESTROY_TRANSPUT = "DESTROY_TRANSPUT", + ADD_NODE = "ADD_NODE", + REMOVE_NODE = "REMOVE_NODE", + HYDRATE_DEFAULT_NODES = "HYDRATE_DEFAULT_NODES", + SET_PORT_DATA = "SET_PORT_DATA", + SET_NODE_COORDINATES = "SET_NODE_COORDINATES" +} + +type ProposedConnection = { nodeId: string; portName: string }; + +export type NodesAction = + | { + type: NodesActionType.ADD_CONNECTION | NodesActionType.REMOVE_CONNECTION; + input: ProposedConnection; + output: ProposedConnection; + } + | { + type: NodesActionType.DESTROY_TRANSPUT; + transput: ProposedConnection; + transputType: TransputType; + } + | { + type: NodesActionType.ADD_NODE; + nodeType: string; + x: number; + y: number; + id?: string; + defaultNode?: boolean; + } + | { + type: NodesActionType.REMOVE_NODE; + nodeId: string; + } + | { + type: NodesActionType.HYDRATE_DEFAULT_NODES; + } + | { + type: NodesActionType.SET_PORT_DATA; + nodeId: string; + portName: string; + controlName: string; + data: any; + setValue?: ValueSetter; + } + | { + type: NodesActionType.SET_NODE_COORDINATES; + x: number; + y: number; + nodeId: string; + }; + +interface FlumeEnvironment { + nodeTypes: NodeTypeMap; + portTypes: PortTypeMap; + cache?: RefObject; + circularBehavior?: CircularBehavior; + context: any; +} + const nodesReducer = ( - nodes, - action = {}, - { nodeTypes, portTypes, cache, circularBehavior, context }, - dispatchToasts + nodes: NodeMap, + action: NodesAction, + { nodeTypes, portTypes, cache, circularBehavior, context }: FlumeEnvironment, + dispatchToasts?: React.Dispatch> ) => { switch (action.type) { - case "ADD_CONNECTION": { + case NodesActionType.ADD_CONNECTION: { const { input, output } = action; const inputIsNotConnected = !nodes[input.nodeId].connections.inputs[ input.portName ]; if (inputIsNotConnected) { - const allowCircular = circularBehavior === "warn" || circularBehavior === "allow" + const allowCircular = + circularBehavior === "warn" || circularBehavior === "allow"; const newNodes = addConnection(nodes, input, output, portTypes); const isCircular = checkForCircularNodes(newNodes, output.nodeId); if (isCircular && !allowCircular) { - dispatchToasts({ - type: "ADD_TOAST", + dispatchToasts?.({ + type: ToastActionTypes.ADD_TOAST, title: "Unable to connect", message: "Connecting these nodes would result in an infinite loop.", toastType: "warning", @@ -250,9 +359,9 @@ const nodesReducer = ( }); return nodes; } else { - if(isCircular && circularBehavior === "warn"){ - dispatchToasts({ - type: "ADD_TOAST", + if (isCircular && circularBehavior === "warn") { + dispatchToasts?.({ + type: ToastActionTypes.ADD_TOAST, title: "Circular Connection Detected", message: "Connecting these nodes has created an infinite loop.", toastType: "warning", @@ -264,37 +373,40 @@ const nodesReducer = ( } else return nodes; } - case "REMOVE_CONNECTION": { + case NodesActionType.REMOVE_CONNECTION: { const { input, output } = action; const id = output.nodeId + output.portName + input.nodeId + input.portName; - delete cache.current.connections[id]; + delete cache?.current?.connections[id]; deleteConnection({ id }); return removeConnection(nodes, input, output); } - case "DESTROY_TRANSPUT": { + case NodesActionType.DESTROY_TRANSPUT: { const { transput, transputType } = action; const portId = transput.nodeId + transput.portName + transputType; - delete cache.current.ports[portId]; + delete cache?.current?.ports[portId]; - const cnxType = transputType === 'input' ? 'inputs' : 'outputs'; - const connections = nodes[transput.nodeId].connections[cnxType][transput.portName]; + const cnxType = transputType === "input" ? "inputs" : "outputs"; + const connections = + nodes[transput.nodeId].connections[cnxType][transput.portName]; if (!connections || !connections.length) return nodes; return connections.reduce((nodes, cnx) => { - const [input, output] = transputType === 'input' ? [transput, cnx] : [cnx, transput]; - const id = output.nodeId + output.portName + input.nodeId + input.portName; - delete cache.current.connections[id]; + const [input, output] = + transputType === "input" ? [transput, cnx] : [cnx, transput]; + const id = + output.nodeId + output.portName + input.nodeId + input.portName; + delete cache?.current?.connections[id]; deleteConnection({ id }); return removeConnection(nodes, input, output); }, nodes); } - case "ADD_NODE": { + case NodesActionType.ADD_NODE: { const { x, y, nodeType, id, defaultNode } = action; const newNodeId = id || nanoid(10); - const newNode = { + const newNode: FlumeNode = { id: newNodeId, x, y, @@ -324,25 +436,25 @@ const nodesReducer = ( }; } - case "REMOVE_NODE": { + case NodesActionType.REMOVE_NODE: { const { nodeId } = action; return removeNode(nodes, nodeId); } - case "HYDRATE_DEFAULT_NODES": { + case NodesActionType.HYDRATE_DEFAULT_NODES: { const newNodes = { ...nodes }; for (const key in newNodes) { if (newNodes[key].defaultNode) { const newNodeId = nanoid(10); const { id, defaultNode, ...node } = newNodes[key]; - newNodes[newNodeId] = {...node, id: newNodeId }; + newNodes[newNodeId] = { ...node, id: newNodeId }; delete newNodes[key]; } } return newNodes; } - case "SET_PORT_DATA": { + case NodesActionType.SET_PORT_DATA: { const { nodeId, portName, controlName, data, setValue } = action; let newData = { ...nodes[nodeId].inputData, @@ -363,7 +475,7 @@ const nodesReducer = ( }; } - case "SET_NODE_COORDINATES": { + case NodesActionType.SET_NODE_COORDINATES: { const { x, y, nodeId } = action; return { ...nodes, @@ -380,9 +492,11 @@ const nodesReducer = ( } }; -export const connectNodesReducer = (reducer, environment, dispatchToasts) => ( - state, - action -) => reducer(state, action, environment, dispatchToasts); +export const connectNodesReducer = ( + reducer: typeof nodesReducer, + environment: FlumeEnvironment, + dispatchToasts: React.Dispatch> +) => (state: NodeMap, action: NodesAction) => + reducer(state, action, environment, dispatchToasts); export default nodesReducer; diff --git a/src/stageReducer.js b/src/stageReducer.js deleted file mode 100644 index e1246542..00000000 --- a/src/stageReducer.js +++ /dev/null @@ -1,13 +0,0 @@ -export default (state, incomingAction) => { - let action = typeof incomingAction === 'function' ? incomingAction(state) : incomingAction; - switch (action.type) { - case 'SET_SCALE': - return { ...state, scale: action.scale } - case 'SET_TRANSLATE': - return { ...state, translate: action.translate } - case 'SET_TRANSLATE_SCALE': - return { ...state, translate: action.translate, scale: action.scale } - default: - return state; - } -} diff --git a/src/stageReducer.ts b/src/stageReducer.ts new file mode 100644 index 00000000..9475b067 --- /dev/null +++ b/src/stageReducer.ts @@ -0,0 +1,47 @@ +import { StageTranslate } from "./types"; + +export interface StageState { + translate: StageTranslate; + scale: number; +} + +export enum StageActionType { + SET_SCALE = "SET_SCALE", + SET_TRANSLATE = "SET_TRANSLATE", + SET_TRANSLATE_SCALE = "SET_TRANSLATE_SCALE" +} + +export type StageAction = + | { + type: StageActionType.SET_SCALE; + scale: number; + } + | { + type: StageActionType.SET_TRANSLATE; + translate: StageTranslate; + } + | { + type: StageActionType.SET_TRANSLATE_SCALE; + translate: StageTranslate; + scale: number; + }; + +export type StageActionSetter = StageAction | ((state: StageState) => StageAction); + +export default (state: StageState, incomingAction: StageActionSetter) => { + let action = + typeof incomingAction === "function" + ? incomingAction(state) + : incomingAction; + + switch (action.type) { + case StageActionType.SET_SCALE: + return { ...state, scale: action.scale }; + case StageActionType.SET_TRANSLATE: + return { ...state, translate: action.translate }; + case StageActionType.SET_TRANSLATE_SCALE: + return { ...state, translate: action.translate, scale: action.scale }; + default: + return state; + } +}; diff --git a/src/tests/test.js b/src/tests/general.test.js similarity index 100% rename from src/tests/test.js rename to src/tests/general.test.js diff --git a/src/toastsReducer.js b/src/toastsReducer.ts similarity index 55% rename from src/toastsReducer.js rename to src/toastsReducer.ts index 15772d2d..353f4b06 100644 --- a/src/toastsReducer.js +++ b/src/toastsReducer.ts @@ -1,8 +1,34 @@ -import { nanoid }from "nanoid/non-secure/index"; +import { nanoid }from "nanoid/non-secure"; +import { Toast, ToastTypes } from "./types"; -export default (toasts = [], action) => { +export enum ToastActionTypes { + ADD_TOAST = "ADD_TOAST", + REMOVE_TOAST = "REMOVE_TOAST", + SET_HEIGHT = "SET_HEIGHT", + SET_EXITING = "SET_EXITING", +} + +export type ToastAction = { + type: ToastActionTypes.ADD_TOAST; + title: string; + message: string; + toastType?: ToastTypes; + duration?: number; +} | { + type: ToastActionTypes.REMOVE_TOAST; + id: string; +} | { + type: ToastActionTypes.SET_HEIGHT; + id: string; + height: number; +} | { + type: ToastActionTypes.SET_EXITING; + id: string; +} + +export default (toasts: Toast[] = [], action: ToastAction) => { switch (action.type) { - case "ADD_TOAST": + case ToastActionTypes.ADD_TOAST: return [ { id: nanoid(5), @@ -15,7 +41,7 @@ export default (toasts = [], action) => { }, ...toasts ]; - case "SET_HEIGHT": { + case ToastActionTypes.SET_HEIGHT: { const index = toasts.findIndex(t => t.id === action.id); return [ ...toasts.slice(0, index), @@ -26,7 +52,7 @@ export default (toasts = [], action) => { ...toasts.slice(index + 1) ]; } - case "SET_EXITING": { + case ToastActionTypes.SET_EXITING: { const index = toasts.findIndex(t => t.id === action.id); return [ ...toasts.slice(0, index), @@ -37,7 +63,7 @@ export default (toasts = [], action) => { ...toasts.slice(index + 1) ]; } - case "REMOVE_TOAST": { + case ToastActionTypes.REMOVE_TOAST: { const index = toasts.findIndex(t => t.id === action.id); return [ ...toasts.slice(0, index), diff --git a/src/typeBuilders.js b/src/typeBuilders.ts similarity index 64% rename from src/typeBuilders.js rename to src/typeBuilders.ts index 3aefb263..d8987279 100644 --- a/src/typeBuilders.js +++ b/src/typeBuilders.ts @@ -1,84 +1,144 @@ -const define = (value, defaultValue) => +import { CheckboxControl } from "./../dist/types.d"; +import { + Colors as ColorsType, + Control, + CustomControl, + GenericControl, + MultiselectControl, + NodeType, + NodeTypeConfig, + NumberControl, + PortType, + PortTypeBuilder, + PortTypeConfig, + SelectControl, + TextControl +} from "./types"; +const define = (value: T, defaultValue: T): T => value !== undefined ? value : defaultValue; -const buildControlType = ( - defaultConfig, - validate = () => {}, - setup = () => ({}) -) => config => { - validate(config); +const buildDefaultConfig = ( + defaultConfig: Partial, + config: Partial +): Omit => { return { - type: defaultConfig.type, - label: define(config.label, defaultConfig.label || ""), - name: define(config.name, defaultConfig.name || ""), - defaultValue: define(config.defaultValue, defaultConfig.defaultValue), - setValue: define(config.setValue, undefined), - ...setup(config) + label: config.label ?? defaultConfig.label ?? "", + name: config.name ?? defaultConfig.name ?? "", + defaultValue: config.defaultValue ?? defaultConfig.defaultValue }; }; -export const Controls = { - text: buildControlType({ - type: "text", - name: "text", - defaultValue: "" - }), - select: buildControlType( +const buildTextControl = ( + config: Omit, "type"> +): TextControl => { + const defaultConfig = buildDefaultConfig( + { + name: "text", + defaultValue: "" + }, + config + ); + return { + ...defaultConfig, + type: "text" + }; +}; + +const buildSelectControl = ( + config: Omit, "type"> +): SelectControl => { + const defaultConfig = buildDefaultConfig( { - type: "select", name: "select", - options: [], defaultValue: "" }, - () => {}, - config => ({ - options: define(config.options, []), - getOptions: define(config.getOptions, undefined), - placeholder: define(config.placeholder, undefined) - }) - ), - number: buildControlType( + config + ); + return { + ...defaultConfig, + type: "select", + options: config.options ?? [], + getOptions: config.getOptions, + placeholder: config.placeholder + }; +}; + +const buildNumberControl = ( + config: Omit, "type"> +): NumberControl => { + const defaultConfig = buildDefaultConfig( { - type: "number", name: "number", defaultValue: 0 }, - () => {}, - config => ({ - step: define(config.step, undefined) - }) - ), - checkbox: buildControlType({ - type: "checkbox", - name: "checkbox", - defaultValue: false - }), - multiselect: buildControlType( + config + ); + return { + ...defaultConfig, + type: "number", + step: config.step + }; +}; + +const buildCheckboxControl = ( + config: Omit, "type"> +): CheckboxControl => { + const defaultConfig = buildDefaultConfig( + { + name: "checkbox", + defaultValue: false + }, + config + ); + return { + ...defaultConfig, + type: "checkbox" + }; +}; + +const buildMultiselectControl = ( + config: Omit, "type"> +): MultiselectControl => { + const defaultConfig = buildDefaultConfig( { - type: "multiselect", name: "multiselect", - options: [], defaultValue: [] }, - () => {}, - config => ({ - options: define(config.options, []), - getOptions: define(config.getOptions, undefined), - placeholder: define(config.placeholder, undefined) - }) - ), - custom: buildControlType( + config + ); + return { + ...defaultConfig, + type: "multiselect", + options: config.options ?? [], + getOptions: config.getOptions, + placeholder: config.placeholder + }; +}; + +const buildCustomControl = ( + config: Omit, "type"> +): CustomControl => { + const defaultConfig = buildDefaultConfig( { - type: "custom", name: "custom", - render: () => {}, defaultValue: undefined }, - () => {}, - config => ({ - render: define(config.render, () => {}) - }) - ) + config + ); + return { + ...defaultConfig, + type: "custom", + render: config.render ?? (() => null) + }; +}; + +export const Controls = { + text: buildTextControl, + select: buildSelectControl, + number: buildNumberControl, + checkbox: buildCheckboxControl, + multiselect: buildMultiselectControl, + custom: buildCustomControl }; export const Colors = { @@ -90,11 +150,13 @@ export const Colors = { blue: "blue", green: "green", grey: "grey" -}; +} as const; -export const getPortBuilders = ports => +export const getPortBuilders = (ports: { + [portType: string]: PortType; +}): { [portType: string]: PortTypeBuilder } => Object.values(ports).reduce((obj, port) => { - obj[port.type] = (config = {}) => { + obj[port.type] = (config: Partial = {}) => { return { type: port.type, name: config.name || port.name, @@ -109,7 +171,13 @@ export const getPortBuilders = ports => }, {}); export class FlumeConfig { - constructor(config) { + nodeTypes: { [nodeType: string]: NodeType }; + portTypes: { [portType: string]: PortType }; + + constructor(config?: { + nodeTypes: { [nodeType: string]: NodeType }; + portTypes: { [portType: string]: PortType }; + }) { if (config) { this.nodeTypes = { ...config.nodeTypes }; this.portTypes = { ...config.portTypes }; @@ -118,16 +186,16 @@ export class FlumeConfig { this.portTypes = {}; } } - addRootNodeType(config) { + public addRootNodeType(config: NodeTypeConfig) { this.addNodeType({ ...config, root: true, addable: false, deletable: false - }) + }); return this; } - addNodeType(config) { + public addNodeType(config: NodeTypeConfig) { if (typeof config !== "object" && config !== null) { throw new Error( "You must provide a configuration object when calling addNodeType." @@ -151,7 +219,7 @@ export class FlumeConfig { `A node with type "${config.type}" has already been declared.` ); } - const node = { + const node: Partial = { type: config.type, label: define(config.label, ""), description: define(config.description, ""), @@ -166,7 +234,7 @@ export class FlumeConfig { } if (typeof config.inputs === "function") { const inputs = config.inputs(getPortBuilders(this.portTypes)); - if (!Array.isArray(inputs) && typeof config.inputs !== 'function') { + if (!Array.isArray(inputs) && typeof config.inputs !== "function") { throw new Error( `When providing a function to the "inputs" key, you must return either an array or a function.` ); @@ -182,7 +250,7 @@ export class FlumeConfig { if (typeof config.outputs === "function") { const outputs = config.outputs(getPortBuilders(this.portTypes)); - if (!Array.isArray(outputs) && typeof config.outputs !== 'function') { + if (!Array.isArray(outputs) && typeof config.outputs !== "function") { throw new Error( `When providing a function to the "outputs" key, you must return either an array or a function.` ); @@ -204,10 +272,10 @@ export class FlumeConfig { } } - this.nodeTypes[config.type] = node; + this.nodeTypes[config.type] = node as NodeType; return this; } - removeNodeType(type) { + public removeNodeType(type: string) { if (!this.nodeTypes[type]) { console.error(`Non-existent node type "${type}" cannot be removed.`); } else { @@ -216,7 +284,7 @@ export class FlumeConfig { } return this; } - addPortType(config) { + public addPortType(config: PortTypeConfig) { if (typeof config !== "object" && config !== null) { throw new Error( "You must provide a configuration object when calling addPortType" @@ -238,7 +306,7 @@ export class FlumeConfig { ); } - const port = { + const port: Partial = { type: config.type, name: config.name, label: define(config.label, ""), @@ -262,24 +330,24 @@ export class FlumeConfig { port.controls = config.controls; } - this.portTypes[config.type] = port; + this.portTypes[config.type] = port as PortType; return this; } - removePortType(type, { skipDynamicNodesCheck = false } = {}) { + public removePortType(type: string, { skipDynamicNodesCheck = false } = {}) { if (!this.portTypes[type]) { console.error(`Non-existent port type "${type}" cannot be removed.`); } else { if (!skipDynamicNodesCheck) { const dynamicNodes = Object.values(this.nodeTypes).filter( node => - typeof node.inputs === 'function' || - typeof node.outputs === 'function' + typeof node.inputs === "function" || + typeof node.outputs === "function" ); if (dynamicNodes.length) { console.warn( `We've detected that one or more of your nodes is using dynamic inputs/outputs. This is a potentially dangerous operation as we are unable to detect if this portType is being used in one of those nodes. You can quiet this message by passing { skipDynamicNodesCheck: true } in as the second argument.` ); - } + } } const affectedNodes = Object.values(this.nodeTypes).filter( node => diff --git a/src/types.ts b/src/types.ts new file mode 100644 index 00000000..594e8b27 --- /dev/null +++ b/src/types.ts @@ -0,0 +1,377 @@ +import { HTMLProps, ReactNode } from "react"; + +export type ControlData = { [controlName: string]: any }; +export type InputData = { [portName: string]: ControlData }; + +export type ControlTypes = + | "text" + | "number" + | "select" + | "checkbox" + | "multiselect" + | "custom"; + +export type ValueSetter = (newData: any, oldData: any) => any; + +export interface GenericControl { + type: ControlTypes; + label: string; + name: string; + defaultValue: any; + setValue?: ValueSetter; +} + +export interface TextControl extends GenericControl { + type: "text"; + defaultValue: string; +} + +export interface SelectOption { + label: string; + value: string; + description?: string; + sortIndex?: number; + node?: NodeType; + internalType?: "comment"; +} + +export interface SelectControl extends GenericControl { + type: "select"; + options: SelectOption[]; + defaultValue: string; + getOptions?: (inputData: InputData, context: any) => SelectOption[]; + placeholder?: string; +} + +export interface NumberControl extends GenericControl { + type: "number"; + defaultValue: number; + step?: number; +} + +export interface CheckboxControl extends GenericControl { + type: "checkbox"; + defaultValue: boolean; +} + +export interface MultiselectControl extends GenericControl { + type: "multiselect"; + options: SelectOption[]; + defaultValue: string[]; + getOptions?: (inputData: InputData, context: any) => SelectOption[]; + placeholder?: string; +} + +export type ControlRenderCallback = ( + data: any, + onChange: (newData: any) => void, + context: any, + redraw: () => void, + portProps: { + label: string; + name: string; + portName: string; + inputLabel: string; + defaultValue: any; + }, + controlData: ControlData +) => ReactNode; + +export interface CustomControl extends GenericControl { + type: "custom"; + defaultValue: any; + render: ControlRenderCallback; +} + +export type Control = + | TextControl + | SelectControl + | NumberControl + | CheckboxControl + | MultiselectControl + | CustomControl; + +export type Colors = + | "yellow" + | "orange" + | "red" + | "pink" + | "purple" + | "blue" + | "green" + | "grey"; + +export interface PortType { + /** + * A unique string identifier for the port. Preferred to be camelCased. + */ + type: string; + /** + * A default string identifier used when the port is constructed. + */ + name: string; + /** + * A default human-readable label for the port. + */ + label: string; + /** + * When true the port will not render its controls. + * + * @defaultValue false + */ + noControls: boolean; + /** + * The color of the port. Should be one of the colors defined by the Colors type. + */ + color: Colors; + /** + * If true the ports controls will render but the actual port will not. This disallows connections. + * + * @defaultValue false + */ + hidePort: boolean; + /** + * An array of controls to render on the port. + */ + controls: Control[]; + /** + * An array of port type strings. Only port types included in this array will be allowed to connect to this port. By default ports always accept their own type. + */ + acceptTypes: string[]; +} + +export type PortTypeMap = { [portType: string]: PortType }; + +export type PortTypeBuilder = (config?: Partial) => PortType; + +export interface PortTypeConfig extends Partial { + type: string; + name: string; +} + +export type TransputType = "input" | "output"; + +export type TransputBuilder = ( + inputData: InputData, + connections: Connections, + context: any +) => PortType[]; + +export interface NodeType { + /** + * A unique randomly-generated string identifier for the node. + */ + id: string; + /** + * A unique string identifier for the node. Preferred to be camelCased. + */ + type: string; + /** + * A human-readable label for the node. + */ + label: string; + /** + * A human-readable description for the node. Renders in the "Add Node" context menu. + */ + description: string; + /** + * If false the node may not be added to the canvas. + * + * @defaultValue true + */ + addable: boolean; + /** + * If false the node may not be removed from the canvas. + * + * @defaultValue true + */ + deletable: boolean; + inputs: PortType[] | TransputBuilder; + outputs: PortType[] | TransputBuilder; + initialWidth?: number; + sortIndex?: number; + root?: boolean; +} + +export type NodeTypeMap = { [nodeType: string]: NodeType }; + +export type DynamicPortTypeBuilder = ( + inputData: InputData, + connections: Connections, + context: any +) => PortType[]; + +export interface NodeTypeConfig + extends Omit, "inputs" | "outputs"> { + type: string; + /** + * Represents the ports available to be connected as inputs to the node. Must be one of the following types: + * - An array of ports + * - A function that returns an array of ports at definition time + * - A function that returns a function that returns an array of ports at runtime + * + * @example + * ### Static ports + * ``` + * inputs: ports => [ + * ports.string({name: "stringPortName", label: "String Port Label"}), + * ports.number({name: "numberPortName", label: "Number Port Label"}), + * ] + * ``` + * + * ### Dynamic ports + * ``` + * inputs: ports => (inputData, connections, context) => { + * if(inputData.isAdmin.boolean) { + * return [ports.string({label: "Admin Name"})] + * }else{ + * return [] + * } + * } + * ``` + */ + inputs?: + | PortType[] + | ((ports: { [portType: string]: PortTypeBuilder }) => PortType[]) + | ((ports: { + [portType: string]: PortTypeBuilder; + }) => DynamicPortTypeBuilder); + /** + * Represents the ports available to be connected as outputs from the node. Must be one of the following types: + * - An array of ports + * - A function that returns an array of ports at definition time + * - A function that returns a function that returns an array of ports at runtime + * + * @example + * ### Static ports + * ``` + * inputs: ports => [ + * ports.string({name: "stringPortName", label: "String Port Label"}), + * ports.number({name: "numberPortName", label: "Number Port Label"}), + * ] + * ``` + * + * ### Dynamic ports + * ``` + * inputs: ports => (inputData, connections, context) => { + * if(inputData.isAdmin.boolean) { + * return [ports.string({label: "Admin Name"})] + * }else{ + * return [] + * } + * } + * ``` + */ + outputs?: + | PortType[] + | ((ports: { [portType: string]: PortTypeBuilder }) => PortType[]) + | ((ports: { + [portType: string]: PortTypeBuilder; + }) => DynamicPortTypeBuilder); +} + +export type Connection = { + nodeId: string; + portName: string; +}; + +export type ConnectionMap = { [portName: string]: Connection[] }; + +export type Connections = { + inputs: ConnectionMap; + outputs: ConnectionMap; +}; + +export type FlumeNode = { + id: string; + type: string; + width: number; + x: number; + y: number; + inputData: InputData; + connections: Connections; + defaultNode?: boolean; + root?: boolean; +}; + +export type DefaultNode = { + type: string; + x?: number; + y?: number; +}; + +export type NodeMap = { [nodeId: string]: FlumeNode }; + +export type ToastTypes = "danger" | "info" | "success" | "warning"; + +export type Toast = { + id: string; + title: string; + message: string; + type: ToastTypes; + duration: number; + height: number; + exiting: boolean; +}; + +export type FlumeComment = { + id: string; + text: string; + x: number; + y: number; + width: number; + height: number; + color: Colors; + isNew: boolean; +}; + +export type FlumeCommentMap = { [commentId: string]: FlumeComment }; + +export type StageTranslate = { + x: number; + y: number; +}; + +export type Coordinate = { + x: number; + y: number; +}; + +export type StageState = { + scale: number; + translate: StageTranslate; +}; + +export type CircularBehavior = "prevent" | "warn" | "allow"; + +export type NodeHeaderActions = { + openMenu: (event: MouseEvent | React.MouseEvent) => void | any; + closeMenu: () => void | any; + deleteNode: () => void | any; +}; + +export type NodeHeaderRenderCallback = ( + Wrapper: React.FC>, + nodeType: NodeType, + actions: NodeHeaderActions +) => ReactNode; + +export type PortResolver = ( + portType: string, + data: InputData, + context: any +) => any; + +export type NodeResolver = ( + node: FlumeNode, + inputValues: InputData, + nodeType: NodeType, + context: any +) => { [outputPortName: string]: any }; + +export interface RootEngineOptions { + rootNodeId?: string; + context?: any; + maxLoops?: number; + onlyResolveConnected?: boolean; +} diff --git a/src/useRootEngine.ts b/src/useRootEngine.ts new file mode 100644 index 00000000..23aeef58 --- /dev/null +++ b/src/useRootEngine.ts @@ -0,0 +1,12 @@ +import { RootEngine } from "./RootEngine"; +import { NodeMap, RootEngineOptions } from "./types"; + +export const useRootEngine = ( + nodes: NodeMap, + engine: RootEngine, + context?: any, + options?: RootEngineOptions +): T => + Object.keys(nodes).length + ? engine.resolveRootNode(nodes, { ...options, context }) + : ({} as T); diff --git a/src/utilities.js b/src/utilities.js deleted file mode 100644 index 0c2caf70..00000000 --- a/src/utilities.js +++ /dev/null @@ -1,23 +0,0 @@ -export const checkForCircularNodes = (nodes, startNodeId) => { - let isCircular = false; - const walk = nodeId => { - const outputs = Object.values(nodes[nodeId].connections.outputs); - for (var i = 0; i < outputs.length; i++) { - if(isCircular){ - break; - } - const outputConnections = outputs[i]; - for (var k = 0; k < outputConnections.length; k++) { - const connectedTo = outputConnections[k] - if(connectedTo.nodeId === startNodeId){ - isCircular = true; - break; - }else{ - walk(connectedTo.nodeId) - } - } - } - } - walk(startNodeId) - return isCircular; -} diff --git a/src/utilities.ts b/src/utilities.ts new file mode 100644 index 00000000..21e62e37 --- /dev/null +++ b/src/utilities.ts @@ -0,0 +1,28 @@ +import { FlumeNode } from "./types"; + +export const checkForCircularNodes = ( + nodes: { [nodeId: string]: FlumeNode }, + startNodeId: string +) => { + let isCircular = false; + const walk = (nodeId: string) => { + const outputs = Object.values(nodes[nodeId].connections.outputs); + for (var i = 0; i < outputs.length; i++) { + if (isCircular) { + break; + } + const outputConnections = outputs[i]; + for (var k = 0; k < outputConnections.length; k++) { + const connectedTo = outputConnections[k]; + if (connectedTo.nodeId === startNodeId) { + isCircular = true; + break; + } else { + walk(connectedTo.nodeId); + } + } + } + }; + walk(startNodeId); + return isCircular; +}; diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 00000000..67149446 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,21 @@ +{ + "compilerOptions": { + "outDir": "dist", + "module": "esnext", + "target": "esnext", + "lib": ["dom", "esnext"], + "jsx": "react", + "declaration": true, + "declarationDir": ".", + "moduleResolution": "node", + "sourceMap": true, + "esModuleInterop": true, + "forceConsistentCasingInFileNames": true, + "strict": true, + "noImplicitAny": false, + "skipLibCheck": true, + "allowSyntheticDefaultImports": true + }, + "exclude": ["dist"], + "include": ["./src/**/*.ts", "./src/**/*.tsx", "src/*.d.ts"] +} diff --git a/yarn.lock b/yarn.lock index 5cc2e826..56bec9ac 100644 --- a/yarn.lock +++ b/yarn.lock @@ -91,6 +91,27 @@ json5 "^2.1.2" semver "^6.3.0" +"@babel/core@^7.17.5": + version "7.17.9" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.17.9.tgz#6bae81a06d95f4d0dec5bb9d74bbc1f58babdcfe" + integrity sha512-5ug+SfZCpDAkVp9SFIZAzlW18rlzsOcJGaetCjkySnrXXDUw9AR8cDUm1iByTmdWM6yxX6/zycaV76w3YTF2gw== + dependencies: + "@ampproject/remapping" "^2.1.0" + "@babel/code-frame" "^7.16.7" + "@babel/generator" "^7.17.9" + "@babel/helper-compilation-targets" "^7.17.7" + "@babel/helper-module-transforms" "^7.17.7" + "@babel/helpers" "^7.17.9" + "@babel/parser" "^7.17.9" + "@babel/template" "^7.16.7" + "@babel/traverse" "^7.17.9" + "@babel/types" "^7.17.0" + convert-source-map "^1.7.0" + debug "^4.1.0" + gensync "^1.0.0-beta.2" + json5 "^2.2.1" + semver "^6.3.0" + "@babel/eslint-parser@^7.16.3": version "7.17.0" resolved "https://registry.yarnpkg.com/@babel/eslint-parser/-/eslint-parser-7.17.0.tgz#eabb24ad9f0afa80e5849f8240d0e5facc2d90d6" @@ -118,6 +139,15 @@ jsesc "^2.5.1" source-map "^0.5.0" +"@babel/generator@^7.17.9": + version "7.17.9" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.17.9.tgz#f4af9fd38fa8de143c29fce3f71852406fc1e2fc" + integrity sha512-rAdDousTwxbIxbz5I7GEQ3lUip+xVCXooZNbsydCWs3xA7ZsYOv+CFRdzGxRX78BmQHu9B1Eso59AOZQOJDEdQ== + dependencies: + "@babel/types" "^7.17.0" + jsesc "^2.5.1" + source-map "^0.5.0" + "@babel/helper-annotate-as-pure@^7.16.0": version "7.16.0" resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.16.0.tgz#9a1f0ebcda53d9a2d00108c4ceace6a5d5f1f08d" @@ -276,6 +306,14 @@ "@babel/template" "^7.16.7" "@babel/types" "^7.16.7" +"@babel/helper-function-name@^7.17.9": + version "7.17.9" + resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.17.9.tgz#136fcd54bc1da82fcb47565cf16fd8e444b1ff12" + integrity sha512-7cRisGlVtiVqZ0MW0/yFB4atgpGLWEHUVYnb448hZK4x+vih0YO5UoS11XIYtZYqHd0dIPMdUSv8q5K4LdMnIg== + dependencies: + "@babel/template" "^7.16.7" + "@babel/types" "^7.17.0" + "@babel/helper-get-function-arity@^7.16.0": version "7.16.0" resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.16.0.tgz#0088c7486b29a9cb5d948b1a1de46db66e089cfa" @@ -516,6 +554,15 @@ "@babel/traverse" "^7.17.3" "@babel/types" "^7.17.0" +"@babel/helpers@^7.17.9": + version "7.17.9" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.17.9.tgz#b2af120821bfbe44f9907b1826e168e819375a1a" + integrity sha512-cPCt915ShDWUEzEp3+UNRktO2n6v49l5RSnG9M5pS24hA+2FAc5si+Pn1i4VVbQQ+jh+bIZhPFQOJOzbrOYY1Q== + dependencies: + "@babel/template" "^7.16.7" + "@babel/traverse" "^7.17.9" + "@babel/types" "^7.17.0" + "@babel/highlight@^7.10.4", "@babel/highlight@^7.16.7": version "7.16.10" resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.16.10.tgz#744f2eb81579d6eea753c227b0f570ad785aba88" @@ -544,6 +591,11 @@ resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.16.4.tgz#d5f92f57cf2c74ffe9b37981c0e72fee7311372e" integrity sha512-6V0qdPUaiVHH3RtZeLIsc+6pDhbYzHR8ogA8w+f+Wc77DuXto19g2QUwveINoS34Uw+W8/hQDGJCx+i4n7xcng== +"@babel/parser@^7.17.9": + version "7.17.9" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.17.9.tgz#9c94189a6062f0291418ca021077983058e171ef" + integrity sha512-vqUSBLP8dQHFPdPi9bc5GK9vRkYHJ49fsZdtoJ8EQ8ibpwk5rPKfvNIwChB0KVXcIjcepEBBd2VHC5r9Gy8ueg== + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@^7.16.2": version "7.16.2" resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.16.2.tgz#2977fca9b212db153c195674e57cfab807733183" @@ -576,6 +628,13 @@ "@babel/helper-skip-transparent-expression-wrappers" "^7.16.0" "@babel/plugin-proposal-optional-chaining" "^7.16.7" +"@babel/plugin-external-helpers@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-external-helpers/-/plugin-external-helpers-7.16.7.tgz#dd91e9b22d52f606461e7fcb4dc99a8b3392dd84" + integrity sha512-3MvRbPgl957CR3ZMeW/ukGrKDM3+m5vtTkgrBAKKbUgrAkb1molwjRqUvAYsCnwboN1vXgHStotdhAvTgQS/Gw== + dependencies: + "@babel/helper-plugin-utils" "^7.16.7" + "@babel/plugin-proposal-async-generator-functions@^7.16.4": version "7.16.4" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.16.4.tgz#e606eb6015fec6fa5978c940f315eae4e300b081" @@ -1474,7 +1533,7 @@ dependencies: "@babel/helper-plugin-utils" "^7.16.7" -"@babel/plugin-transform-runtime@^7.16.4": +"@babel/plugin-transform-runtime@^7.16.4", "@babel/plugin-transform-runtime@^7.17.0": version "7.17.0" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.17.0.tgz#0a2e08b5e2b2d95c4b1d3b3371a2180617455b70" integrity sha512-fr7zPWnKXNc1xoHfrIU9mN/4XKX4VLZ45Q+oMhfsYIaHvg7mHgmhfOy/ckRWqDK7XF3QDigRpkh5DKq6+clE8A== @@ -1677,7 +1736,7 @@ core-js-compat "^3.19.1" semver "^6.3.0" -"@babel/preset-env@^7.11.0", "@babel/preset-env@^7.12.1", "@babel/preset-env@^7.16.4": +"@babel/preset-env@^7.11.0", "@babel/preset-env@^7.12.1", "@babel/preset-env@^7.16.11", "@babel/preset-env@^7.16.4": version "7.16.11" resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.16.11.tgz#5dd88fd885fae36f88fd7c8342475c9f0abe2982" integrity sha512-qcmWG8R7ZW6WBRPZK//y+E3Cli151B20W1Rv7ln27vuPaXU/8TKms6jFdiJtF7UDTxcrb7mZd88tAeK9LjdT8g== @@ -1780,7 +1839,7 @@ "@babel/plugin-transform-react-jsx-development" "^7.16.0" "@babel/plugin-transform-react-pure-annotations" "^7.16.0" -"@babel/preset-react@^7.12.5", "@babel/preset-react@^7.16.0": +"@babel/preset-react@^7.12.5", "@babel/preset-react@^7.16.0", "@babel/preset-react@^7.16.7": version "7.16.7" resolved "https://registry.yarnpkg.com/@babel/preset-react/-/preset-react-7.16.7.tgz#4c18150491edc69c183ff818f9f2aecbe5d93852" integrity sha512-fWpyI8UM/HE6DfPBzD8LnhQ/OcH8AgTaqcqP2nGOXEUV+VKBR5JRN9hCk9ai+zQQ57vtm9oWeXguBCPNUjytgA== @@ -1792,7 +1851,7 @@ "@babel/plugin-transform-react-jsx-development" "^7.16.7" "@babel/plugin-transform-react-pure-annotations" "^7.16.7" -"@babel/preset-typescript@^7.16.0": +"@babel/preset-typescript@^7.16.0", "@babel/preset-typescript@^7.16.7": version "7.16.7" resolved "https://registry.yarnpkg.com/@babel/preset-typescript/-/preset-typescript-7.16.7.tgz#ab114d68bb2020afc069cd51b37ff98a046a70b9" integrity sha512-WbVEmgXdIyvzB77AQjGBEyYPZx+8tTsO50XtfozQrkW8QB2rLJpH2lgx0TRw5EJrBxOZQ+wCcyPVQvS8tjEHpQ== @@ -1872,6 +1931,22 @@ debug "^4.1.0" globals "^11.1.0" +"@babel/traverse@^7.17.9": + version "7.17.9" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.17.9.tgz#1f9b207435d9ae4a8ed6998b2b82300d83c37a0d" + integrity sha512-PQO8sDIJ8SIwipTPiR71kJQCKQYB5NGImbOviK8K+kg5xkNSYXLBupuX9QhatFowrsvo9Hj8WgArg3W7ijNAQw== + dependencies: + "@babel/code-frame" "^7.16.7" + "@babel/generator" "^7.17.9" + "@babel/helper-environment-visitor" "^7.16.7" + "@babel/helper-function-name" "^7.17.9" + "@babel/helper-hoist-variables" "^7.16.7" + "@babel/helper-split-export-declaration" "^7.16.7" + "@babel/parser" "^7.17.9" + "@babel/types" "^7.17.0" + debug "^4.1.0" + globals "^11.1.0" + "@babel/types@^7.0.0", "@babel/types@^7.12.6", "@babel/types@^7.16.7", "@babel/types@^7.16.8", "@babel/types@^7.17.0", "@babel/types@^7.3.0", "@babel/types@^7.3.3": version "7.17.0" resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.17.0.tgz#a826e368bccb6b3d84acd76acad5c0d87342390b" @@ -2310,6 +2385,21 @@ "@jridgewell/resolve-uri" "^3.0.3" "@jridgewell/sourcemap-codec" "^1.4.10" +"@microsoft/tsdoc-config@0.16.1": + version "0.16.1" + resolved "https://registry.yarnpkg.com/@microsoft/tsdoc-config/-/tsdoc-config-0.16.1.tgz#4de11976c1202854c4618f364bf499b4be33e657" + integrity sha512-2RqkwiD4uN6MLnHFljqBlZIXlt/SaUT6cuogU1w2ARw4nKuuppSmR0+s+NC+7kXBQykd9zzu0P4HtBpZT5zBpQ== + dependencies: + "@microsoft/tsdoc" "0.14.1" + ajv "~6.12.6" + jju "~1.4.0" + resolve "~1.19.0" + +"@microsoft/tsdoc@0.14.1": + version "0.14.1" + resolved "https://registry.yarnpkg.com/@microsoft/tsdoc/-/tsdoc-0.14.1.tgz#155ef21065427901994e765da8a0ba0eaae8b8bd" + integrity sha512-6Wci+Tp3CgPt/B9B0a3J4s3yMgLNSku6w5TV6mN+61C71UqsRBv2FUibBf3tPGlNxebgPHMEUzKpb1ggE8KCKw== + "@nodelib/fs.scandir@2.1.5": version "2.1.5" resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" @@ -2363,7 +2453,7 @@ tslib "^2.0.0" warning "^4.0.3" -"@rollup/plugin-babel@^5.2.0": +"@rollup/plugin-babel@^5.2.0", "@rollup/plugin-babel@^5.3.1": version "5.3.1" resolved "https://registry.yarnpkg.com/@rollup/plugin-babel/-/plugin-babel-5.3.1.tgz#04bc0608f4aa4b2e4b1aebf284344d0f68fda283" integrity sha512-WFfdLWU/xVWKeRQnKmIAQULUI7Il0gZnBIH/ZFO069wYIfPu+8zrfp/KMW0atmELoRDq8FbiP3VCss9MhCut7Q== @@ -2371,6 +2461,19 @@ "@babel/helper-module-imports" "^7.10.4" "@rollup/pluginutils" "^3.1.0" +"@rollup/plugin-commonjs@^21.0.2": + version "21.1.0" + resolved "https://registry.yarnpkg.com/@rollup/plugin-commonjs/-/plugin-commonjs-21.1.0.tgz#45576d7b47609af2db87f55a6d4b46e44fc3a553" + integrity sha512-6ZtHx3VHIp2ReNNDxHjuUml6ur+WcQ28N1yHgCQwsbNkQg2suhxGMDQGJOn/KuDxKtd1xuZP5xSTwBA4GQ8hbA== + dependencies: + "@rollup/pluginutils" "^3.1.0" + commondir "^1.0.1" + estree-walker "^2.0.1" + glob "^7.1.6" + is-reference "^1.2.1" + magic-string "^0.25.7" + resolve "^1.17.0" + "@rollup/plugin-node-resolve@^11.2.1": version "11.2.1" resolved "https://registry.yarnpkg.com/@rollup/plugin-node-resolve/-/plugin-node-resolve-11.2.1.tgz#82aa59397a29cd4e13248b106e6a4a1880362a60" @@ -2383,6 +2486,18 @@ is-module "^1.0.0" resolve "^1.19.0" +"@rollup/plugin-node-resolve@^13.1.3": + version "13.2.1" + resolved "https://registry.yarnpkg.com/@rollup/plugin-node-resolve/-/plugin-node-resolve-13.2.1.tgz#cdee815cf02c180ff0a42536ca67a8f67e299f84" + integrity sha512-btX7kzGvp1JwShQI9V6IM841YKNPYjKCvUbNrQ2EcVYbULtUd/GH6wZ/qdqH13j9pOHBER+EZXNN2L8RSJhVRA== + dependencies: + "@rollup/pluginutils" "^3.1.0" + "@types/resolve" "1.17.1" + builtin-modules "^3.1.0" + deepmerge "^4.2.2" + is-module "^1.0.0" + resolve "^1.19.0" + "@rollup/plugin-replace@^2.4.1": version "2.4.2" resolved "https://registry.yarnpkg.com/@rollup/plugin-replace/-/plugin-replace-2.4.2.tgz#a2d539314fbc77c244858faa523012825068510a" @@ -2391,6 +2506,22 @@ "@rollup/pluginutils" "^3.1.0" magic-string "^0.25.7" +"@rollup/plugin-replace@^4.0.0": + version "4.0.0" + resolved "https://registry.yarnpkg.com/@rollup/plugin-replace/-/plugin-replace-4.0.0.tgz#e34c457d6a285f0213359740b43f39d969b38a67" + integrity sha512-+rumQFiaNac9y64OHtkHGmdjm7us9bo1PlbgQfdihQtuNxzjpaB064HbRnewUOggLQxVCCyINfStkgmBeQpv1g== + dependencies: + "@rollup/pluginutils" "^3.1.0" + magic-string "^0.25.7" + +"@rollup/plugin-typescript@^8.3.2": + version "8.3.2" + resolved "https://registry.yarnpkg.com/@rollup/plugin-typescript/-/plugin-typescript-8.3.2.tgz#e1b719e2ed3e752bbc092001656c48378f2d15f0" + integrity sha512-MtgyR5LNHZr3GyN0tM7gNO9D0CS+Y+vflS4v/PHmrX17JCkHUYKvQ5jN5o3cz1YKllM3duXUqu3yOHwMPUxhDg== + dependencies: + "@rollup/pluginutils" "^3.1.0" + resolve "^1.17.0" + "@rollup/pluginutils@^3.1.0": version "3.1.0" resolved "https://registry.yarnpkg.com/@rollup/pluginutils/-/pluginutils-3.1.0.tgz#706b4524ee6dc8b103b3c995533e5ad680c02b9b" @@ -2400,6 +2531,14 @@ estree-walker "^1.0.1" picomatch "^2.2.2" +"@rollup/pluginutils@^4.1.2": + version "4.2.1" + resolved "https://registry.yarnpkg.com/@rollup/pluginutils/-/pluginutils-4.2.1.tgz#e6c6c3aba0744edce3fb2074922d3776c0af2a6d" + integrity sha512-iKnFXr7NkdZAIHiIWE+BX5ULi/ucVFYWD6TbAV+rZctiRTY2PL6tsIKhoIOaoskiWAkgu+VsbXgUVDNLHf+InQ== + dependencies: + estree-walker "^2.0.1" + picomatch "^2.2.2" + "@rushstack/eslint-patch@^1.1.0": version "1.1.1" resolved "https://registry.yarnpkg.com/@rushstack/eslint-patch/-/eslint-patch-1.1.1.tgz#782fa5da44c4f38ae9fd38e9184b54e451936118" @@ -2745,6 +2884,18 @@ dependencies: "@types/node" "*" +"@types/d3-path@*": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@types/d3-path/-/d3-path-3.0.0.tgz#939e3a784ae4f80b1fde8098b91af1776ff1312b" + integrity sha512-0g/A+mZXgFkQxN3HniRDbXMN79K3CdTpLsevj+PXiTcb2hVyvkZUBg37StmgCQkaD84cUJ4uaDAWq7UJOQy2Tg== + +"@types/d3-shape@^3.0.2": + version "3.0.2" + resolved "https://registry.yarnpkg.com/@types/d3-shape/-/d3-shape-3.0.2.tgz#4b1ca4ddaac294e76b712429726d40365cd1e8ca" + integrity sha512-5+ButCmIfNX8id5seZ7jKj3igdcxx+S9IDBiT35fQGTLZUfkFgTv+oBH34xgeoWDKpWcMITSzBILWQtBoN5Piw== + dependencies: + "@types/d3-path" "*" + "@types/eslint-scope@^3.7.3": version "3.7.3" resolved "https://registry.yarnpkg.com/@types/eslint-scope/-/eslint-scope-3.7.3.tgz#125b88504b61e3c8bc6f870882003253005c3224" @@ -2873,6 +3024,11 @@ dependencies: "@types/node" "*" +"@types/lodash@^4.14.182": + version "4.14.182" + resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.182.tgz#05301a4d5e62963227eaafe0ce04dd77c54ea5c2" + integrity sha512-/THyiqyQAP9AfARo4pF+aCGcyiQ94tX/Is2I7HofNRqoYLgN1PBoOWu2/zTA5zMxzP5EFutMtWtGAFRKUe961Q== + "@types/mime@^1": version "1.3.2" resolved "https://registry.yarnpkg.com/@types/mime/-/mime-1.3.2.tgz#93e25bf9ee75fe0fd80b594bc4feb0e862111b5a" @@ -2930,6 +3086,13 @@ dependencies: "@types/react" "*" +"@types/react-portal@^4.0.4": + version "4.0.4" + resolved "https://registry.yarnpkg.com/@types/react-portal/-/react-portal-4.0.4.tgz#1c0e5a248f6e18a66f981139c13b6e796f4a92b6" + integrity sha512-ecVWngYHeSymq5XdrQOXRpIb9ay5SM4Stm/ur6+wc0Z+r05gafZ5SuMRbXKYsj4exNJa+4CTKK6J7qcTKm9K5g== + dependencies: + "@types/react" "*" + "@types/react@*": version "18.0.28" resolved "https://registry.yarnpkg.com/@types/react/-/react-18.0.28.tgz#accaeb8b86f4908057ad629a26635fe641480065" @@ -2939,6 +3102,15 @@ "@types/scheduler" "*" csstype "^3.0.2" +"@types/react@^18.0.5": + version "18.0.5" + resolved "https://registry.yarnpkg.com/@types/react/-/react-18.0.5.tgz#1a4d4b705ae6af5aed369dec22800b20f89f5301" + integrity sha512-UPxNGInDCIKlfqBrm8LDXYWNfLHwIdisWcsH5GpMyGjhEDLFgTtlRBaoWuCua9HcyuE0rMkmAeZ3FXV1pYLIYQ== + dependencies: + "@types/prop-types" "*" + "@types/scheduler" "*" + csstype "^3.0.2" + "@types/resolve@1.17.1": version "1.17.1" resolved "https://registry.yarnpkg.com/@types/resolve/-/resolve-1.17.1.tgz#3afd6ad8967c77e4376c598a82ddd58f46ec45d6" @@ -3297,6 +3469,15 @@ resolved "https://registry.yarnpkg.com/@xtuc/long/-/long-4.2.2.tgz#d291c6a4e97989b5c61d9acf396ae4fe133a718d" integrity sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ== +"@yarn-tool/resolve-package@^1.0.40": + version "1.0.46" + resolved "https://registry.yarnpkg.com/@yarn-tool/resolve-package/-/resolve-package-1.0.46.tgz#db7354380e5ca7682294af59e5ab0f7fce640ac1" + integrity sha512-RJcBGTVywUqYGRtGkPSgJC/ozf0wK/xjUy66tXkbpL35U0o1oef4S0v23euxA/CiukqBWr2fRGtGY6FidESdTg== + dependencies: + pkg-dir "< 6 >= 5" + tslib "^2.3.1" + upath2 "^3.1.12" + abab@^2.0.3, abab@^2.0.5: version "2.0.5" resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.5.tgz#c0b678fb32d60fc1219c784d6a826fe385aeb79a" @@ -3412,7 +3593,7 @@ ajv-keywords@^5.0.0: dependencies: fast-deep-equal "^3.1.3" -ajv@^6.10.0, ajv@^6.12.2, ajv@^6.12.3, ajv@^6.12.4, ajv@^6.12.5: +ajv@^6.10.0, ajv@^6.12.2, ajv@^6.12.3, ajv@^6.12.4, ajv@^6.12.5, ajv@~6.12.6: version "6.12.6" resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== @@ -3575,6 +3756,14 @@ arr-union@^3.1.0: resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-3.1.0.tgz#e39b09aea9def866a8f206e288af63919bae39c4" integrity sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ= +array-buffer-byte-length@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz#fabe8bc193fea865f317fe7807085ee0dee5aead" + integrity sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A== + dependencies: + call-bind "^1.0.2" + is-array-buffer "^3.0.1" + array-flatten@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" @@ -3596,6 +3785,17 @@ array-includes@^3.1.3, array-includes@^3.1.4: get-intrinsic "^1.1.1" is-string "^1.0.7" +array-includes@^3.1.6: + version "3.1.6" + resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.1.6.tgz#9e9e720e194f198266ba9e18c29e6a9b0e4b225f" + integrity sha512-sgTbLvL6cNnw24FnbaDyjmvddQ2ML8arZsgaJhoABMoplz/4QRhtrYS+alr1BUM1Bwp6dhx8vVCBSLG+StwOFw== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.4" + es-abstract "^1.20.4" + get-intrinsic "^1.1.3" + is-string "^1.0.7" + array-union@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/array-union/-/array-union-1.0.2.tgz#9a34410e4f4e3da23dea375be5be70f24778ec39" @@ -3631,6 +3831,27 @@ array.prototype.flatmap@^1.2.5: define-properties "^1.1.3" es-abstract "^1.19.0" +array.prototype.flatmap@^1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/array.prototype.flatmap/-/array.prototype.flatmap-1.3.1.tgz#1aae7903c2100433cb8261cd4ed310aab5c4a183" + integrity sha512-8UGn9O1FDVvMNB0UlLv4voxRMze7+FpHyF5mSMRjWHUMlpoDViniy05870VlxhfgTnLbpuwTzvD76MTtWxB/mQ== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.4" + es-abstract "^1.20.4" + es-shim-unscopables "^1.0.0" + +array.prototype.tosorted@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/array.prototype.tosorted/-/array.prototype.tosorted-1.1.1.tgz#ccf44738aa2b5ac56578ffda97c03fd3e23dd532" + integrity sha512-pZYPXPRl2PqWcsUs6LOMn+1f1532nEoPTYowBtqLwAW+W8vSVhkIGnmOX1t/UQjD6YGI0vcD2B1U7ZFGQH9jnQ== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.4" + es-abstract "^1.20.4" + es-shim-unscopables "^1.0.0" + get-intrinsic "^1.1.3" + arrify@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" @@ -3767,31 +3988,6 @@ babel-code-frame@^6.26.0: esutils "^2.0.2" js-tokens "^3.0.2" -babel-core@^6.26.0, babel-core@^6.26.3: - version "6.26.3" - resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-6.26.3.tgz#b2e2f09e342d0f0c88e2f02e067794125e75c207" - integrity sha512-6jyFLuDmeidKmUEb3NM+/yawG0M2bDZ9Z1qbZP59cyHLz8kYGKYwpJP0UwUKKUiTRNvxfLesJnTedqczP7cTDA== - dependencies: - babel-code-frame "^6.26.0" - babel-generator "^6.26.0" - babel-helpers "^6.24.1" - babel-messages "^6.23.0" - babel-register "^6.26.0" - babel-runtime "^6.26.0" - babel-template "^6.26.0" - babel-traverse "^6.26.0" - babel-types "^6.26.0" - babylon "^6.18.0" - convert-source-map "^1.5.1" - debug "^2.6.9" - json5 "^0.5.1" - lodash "^4.17.4" - minimatch "^3.0.4" - path-is-absolute "^1.0.1" - private "^0.1.8" - slash "^1.0.0" - source-map "^0.5.7" - babel-eslint@10.x: version "10.1.0" resolved "https://registry.yarnpkg.com/babel-eslint/-/babel-eslint-10.1.0.tgz#6968e568a910b78fb3779cdd8b6ac2f479943232" @@ -3804,20 +4000,6 @@ babel-eslint@10.x: eslint-visitor-keys "^1.0.0" resolve "^1.12.0" -babel-generator@^6.26.0: - version "6.26.1" - resolved "https://registry.yarnpkg.com/babel-generator/-/babel-generator-6.26.1.tgz#1844408d3b8f0d35a404ea7ac180f087a601bd90" - integrity sha512-HyfwY6ApZj7BYTcJURpM5tznulaBvyio7/0d4zFOeMPUmfxkCjHocCuoLa2SAGzBI8AREcH3eP3758F672DppA== - dependencies: - babel-messages "^6.23.0" - babel-runtime "^6.26.0" - babel-types "^6.26.0" - detect-indent "^4.0.0" - jsesc "^1.3.0" - lodash "^4.17.4" - source-map "^0.5.7" - trim-right "^1.0.1" - babel-helper-bindify-decorators@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-helper-bindify-decorators/-/babel-helper-bindify-decorators-6.24.1.tgz#14c19e5f142d7b47f19a52431e52b1ccbc40a330" @@ -3951,14 +4133,6 @@ babel-helper-replace-supers@^6.24.1: babel-traverse "^6.24.1" babel-types "^6.24.1" -babel-helpers@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helpers/-/babel-helpers-6.24.1.tgz#3471de9caec388e5c850e597e58a26ddf37602b2" - integrity sha1-NHHenK7DiOXIUOWX5Yom3fN2ArI= - dependencies: - babel-runtime "^6.22.0" - babel-template "^6.24.1" - babel-jest@^27.4.2, babel-jest@^27.5.1: version "27.5.1" resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-27.5.1.tgz#a1bf8d61928edfefd21da27eb86a695bfd691444" @@ -4004,13 +4178,6 @@ babel-plugin-dynamic-import-node@^2.3.3: dependencies: object.assign "^4.1.0" -babel-plugin-external-helpers@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-external-helpers/-/babel-plugin-external-helpers-6.22.0.tgz#2285f48b02bd5dede85175caf8c62e86adccefa1" - integrity sha1-IoX0iwK9Xe3oUXXK+MYuhq3M76E= - dependencies: - babel-runtime "^6.22.0" - babel-plugin-istanbul@^6.1.1: version "6.1.1" resolved "https://registry.yarnpkg.com/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz#fa88ec59232fd9b4e36dbbc540a8ec9a9b47da73" @@ -4629,19 +4796,6 @@ babel-preset-stage-3@^6.24.1: babel-plugin-transform-exponentiation-operator "^6.24.1" babel-plugin-transform-object-rest-spread "^6.22.0" -babel-register@^6.26.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-register/-/babel-register-6.26.0.tgz#6ed021173e2fcb486d7acb45c6009a856f647071" - integrity sha1-btAhFz4vy0htestFxgCahW9kcHE= - dependencies: - babel-core "^6.26.0" - babel-runtime "^6.26.0" - core-js "^2.5.0" - home-or-tmp "^2.0.0" - lodash "^4.17.4" - mkdirp "^0.5.1" - source-map-support "^0.4.15" - babel-runtime@^6.18.0, babel-runtime@^6.22.0, babel-runtime@^6.26.0: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.26.0.tgz#965c7058668e82b55d7bfe04ff2337bc8b5647fe" @@ -4865,11 +5019,6 @@ buffer-indexof@^1.0.0: resolved "https://registry.yarnpkg.com/buffer-indexof/-/buffer-indexof-1.1.1.tgz#52fabcc6a606d1a00302802648ef68f639da268c" integrity sha512-4/rOEg86jivtPTeOUUT61jJO1Ya1TrR/OkqCSZDyq84WJh3LuuiphBYJN+fm5xufIk4XAFcEwte/8WzC8If/1g== -builtin-modules@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-2.0.0.tgz#60b7ef5ae6546bd7deefa74b08b62a43a232648e" - integrity sha512-3U5kUA5VPsRUA3nofm/BXX7GVHKfxz0hOBAPxXrIvHzlDRkQVqEn6yi8QJegxl4LzOHLdvb7XF5dVawa/VVYBg== - builtin-modules@^3.1.0: version "3.2.0" resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-3.2.0.tgz#45d5db99e7ee5e6bc4f362e008bf917ab5049887" @@ -5482,7 +5631,7 @@ content-type@~1.0.4: resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b" integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA== -convert-source-map@^1.4.0, convert-source-map@^1.5.1, convert-source-map@^1.6.0, convert-source-map@^1.7.0: +convert-source-map@^1.4.0, convert-source-map@^1.6.0, convert-source-map@^1.7.0: version "1.8.0" resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.8.0.tgz#f3373c32d21b4d780dd8004514684fb791ca4369" integrity sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA== @@ -5525,7 +5674,7 @@ core-js-pure@^3.8.1: resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.21.1.tgz#8c4d1e78839f5f46208de7230cebfb72bc3bdb51" integrity sha512-12VZfFIu+wyVbBebyHmRTuEE/tZrB4tJToWcwAMcsp3h4+sHR+fMJWbKpYiCRWlhFBq+KNyO8rIV9rTkeVmznQ== -core-js@^2.4.0, core-js@^2.5.0, core-js@^2.6.5: +core-js@^2.4.0, core-js@^2.6.5: version "2.6.12" resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.12.tgz#d9333dfa7b065e347cc5682219d6f690859cc2ec" integrity sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ== @@ -6174,13 +6323,6 @@ destroy@~1.0.4: resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80" integrity sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA= -detect-indent@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-4.0.0.tgz#f76d064352cdf43a1cb6ce619c4ee3a9475de208" - integrity sha1-920GQ1LN9Docts5hnE7jqUdd4gg= - dependencies: - repeating "^2.0.0" - detect-newline@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-3.1.0.tgz#576f5dfc63ae1a192ff192d8ad3af6308991b651" @@ -6515,6 +6657,46 @@ es-abstract@^1.17.2, es-abstract@^1.19.0, es-abstract@^1.19.1: string.prototype.trimstart "^1.0.4" unbox-primitive "^1.0.1" +es-abstract@^1.20.4: + version "1.21.2" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.21.2.tgz#a56b9695322c8a185dc25975aa3b8ec31d0e7eff" + integrity sha512-y/B5POM2iBnIxCiernH1G7rC9qQoM77lLIMQLuob0zhp8C56Po81+2Nj0WFKnd0pNReDTnkYryc+zhOzpEIROg== + dependencies: + array-buffer-byte-length "^1.0.0" + available-typed-arrays "^1.0.5" + call-bind "^1.0.2" + es-set-tostringtag "^2.0.1" + es-to-primitive "^1.2.1" + function.prototype.name "^1.1.5" + get-intrinsic "^1.2.0" + get-symbol-description "^1.0.0" + globalthis "^1.0.3" + gopd "^1.0.1" + has "^1.0.3" + has-property-descriptors "^1.0.0" + has-proto "^1.0.1" + has-symbols "^1.0.3" + internal-slot "^1.0.5" + is-array-buffer "^3.0.2" + is-callable "^1.2.7" + is-negative-zero "^2.0.2" + is-regex "^1.1.4" + is-shared-array-buffer "^1.0.2" + is-string "^1.0.7" + is-typed-array "^1.1.10" + is-weakref "^1.0.2" + object-inspect "^1.12.3" + object-keys "^1.1.1" + object.assign "^4.1.4" + regexp.prototype.flags "^1.4.3" + safe-regex-test "^1.0.0" + string.prototype.trim "^1.2.7" + string.prototype.trimend "^1.0.6" + string.prototype.trimstart "^1.0.6" + typed-array-length "^1.0.4" + unbox-primitive "^1.0.2" + which-typed-array "^1.1.9" + es-get-iterator@^1.1.2: version "1.1.3" resolved "https://registry.yarnpkg.com/es-get-iterator/-/es-get-iterator-1.1.3.tgz#3ef87523c5d464d41084b2c3c9c214f1199763d6" @@ -6535,6 +6717,22 @@ es-module-lexer@^0.9.0: resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-0.9.3.tgz#6f13db00cc38417137daf74366f535c8eb438f19" integrity sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ== +es-set-tostringtag@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz#338d502f6f674301d710b80c8592de8a15f09cd8" + integrity sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg== + dependencies: + get-intrinsic "^1.1.3" + has "^1.0.3" + has-tostringtag "^1.0.0" + +es-shim-unscopables@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz#702e632193201e3edf8713635d083d378e510241" + integrity sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w== + dependencies: + has "^1.0.3" + es-to-primitive@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a" @@ -6766,45 +6964,46 @@ eslint-plugin-react-hooks@^4.3.0: resolved "https://registry.yarnpkg.com/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.3.0.tgz#318dbf312e06fab1c835a4abef00121751ac1172" integrity sha512-XslZy0LnMn+84NEG9jSGR6eGqaZB3133L8xewQo3fQagbQuGt7a63gf+P1NGKZavEYEC3UXaWEAA/AqDkuN6xA== -eslint-plugin-react@7.x: - version "7.27.1" - resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.27.1.tgz#469202442506616f77a854d91babaae1ec174b45" - integrity sha512-meyunDjMMYeWr/4EBLTV1op3iSG3mjT/pz5gti38UzfM4OPpNc2m0t2xvKCOMU5D6FSdd34BIMFOvQbW+i8GAA== +eslint-plugin-react@^7.27.1: + version "7.29.4" + resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.29.4.tgz#4717de5227f55f3801a5fd51a16a4fa22b5914d2" + integrity sha512-CVCXajliVh509PcZYRFyu/BoUEz452+jtQJq2b3Bae4v3xBUWPLCmtmBM+ZinG4MzwmxJgJ2M5rMqhqLVn7MtQ== dependencies: array-includes "^3.1.4" array.prototype.flatmap "^1.2.5" doctrine "^2.1.0" estraverse "^5.3.0" jsx-ast-utils "^2.4.1 || ^3.0.0" - minimatch "^3.0.4" + minimatch "^3.1.2" object.entries "^1.1.5" object.fromentries "^2.0.5" object.hasown "^1.1.0" object.values "^1.1.5" - prop-types "^15.7.2" + prop-types "^15.8.1" resolve "^2.0.0-next.3" semver "^6.3.0" string.prototype.matchall "^4.0.6" -eslint-plugin-react@^7.27.1: - version "7.29.4" - resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.29.4.tgz#4717de5227f55f3801a5fd51a16a4fa22b5914d2" - integrity sha512-CVCXajliVh509PcZYRFyu/BoUEz452+jtQJq2b3Bae4v3xBUWPLCmtmBM+ZinG4MzwmxJgJ2M5rMqhqLVn7MtQ== +eslint-plugin-react@^7.32.2: + version "7.32.2" + resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.32.2.tgz#e71f21c7c265ebce01bcbc9d0955170c55571f10" + integrity sha512-t2fBMa+XzonrrNkyVirzKlvn5RXzzPwRHtMvLAtVZrt8oxgnTQaYbU6SXTOO1mwQgp1y5+toMSKInnzGr0Knqg== dependencies: - array-includes "^3.1.4" - array.prototype.flatmap "^1.2.5" + array-includes "^3.1.6" + array.prototype.flatmap "^1.3.1" + array.prototype.tosorted "^1.1.1" doctrine "^2.1.0" estraverse "^5.3.0" jsx-ast-utils "^2.4.1 || ^3.0.0" minimatch "^3.1.2" - object.entries "^1.1.5" - object.fromentries "^2.0.5" - object.hasown "^1.1.0" - object.values "^1.1.5" + object.entries "^1.1.6" + object.fromentries "^2.0.6" + object.hasown "^1.1.2" + object.values "^1.1.6" prop-types "^15.8.1" - resolve "^2.0.0-next.3" + resolve "^2.0.0-next.4" semver "^6.3.0" - string.prototype.matchall "^4.0.6" + string.prototype.matchall "^4.0.8" eslint-plugin-standard@^3.1.0: version "3.1.0" @@ -6818,6 +7017,14 @@ eslint-plugin-testing-library@^5.0.1: dependencies: "@typescript-eslint/utils" "^5.13.0" +eslint-plugin-tsdoc@^0.2.16: + version "0.2.16" + resolved "https://registry.yarnpkg.com/eslint-plugin-tsdoc/-/eslint-plugin-tsdoc-0.2.16.tgz#a3d31fb9c7955faa3c66a43dd43da7635f1c5e0d" + integrity sha512-F/RWMnyDQuGlg82vQEFHQtGyWi7++XJKdYNn0ulIbyMOFqYIjoJOUdE6olORxgwgLkpJxsCJpJbTHgxJ/ggfXw== + dependencies: + "@microsoft/tsdoc" "0.14.1" + "@microsoft/tsdoc-config" "0.16.1" + eslint-scope@5.1.1, eslint-scope@^5.0.0, eslint-scope@^5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c" @@ -7020,12 +7227,7 @@ estraverse@^5.1.0, estraverse@^5.2.0, estraverse@^5.3.0: resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123" integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== -estree-walker@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-0.2.1.tgz#bdafe8095383d8414d5dc2ecf4c9173b6db9412e" - integrity sha1-va/oCVOD2EFNXcLs9MkXO225QS4= - -estree-walker@^0.6.0, estree-walker@^0.6.1: +estree-walker@^0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-0.6.1.tgz#53049143f40c6eb918b23671d1fe3219f3a1b362" integrity sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w== @@ -7035,6 +7237,11 @@ estree-walker@^1.0.1: resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-1.0.1.tgz#31bc5d612c96b704106b477e6dd5d8aa138cb700" integrity sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg== +estree-walker@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-2.0.2.tgz#52f010178c2a4c117a7757cfe942adb7d2da4cac" + integrity sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w== + esutils@^2.0.2: version "2.0.3" resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" @@ -7358,7 +7565,7 @@ finalhandler@~1.1.2: statuses "~1.5.0" unpipe "~1.0.0" -find-cache-dir@^3.3.1: +find-cache-dir@^3.3.1, find-cache-dir@^3.3.2: version "3.3.2" resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-3.3.2.tgz#b30c5b6eff0730731aea9bbd9dbecbd80256d64b" integrity sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig== @@ -7596,6 +7803,16 @@ function-bind@^1.1.1: resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== +function.prototype.name@^1.1.5: + version "1.1.5" + resolved "https://registry.yarnpkg.com/function.prototype.name/-/function.prototype.name-1.1.5.tgz#cce0505fe1ffb80503e6f9e46cc64e46a12a9621" + integrity sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + es-abstract "^1.19.0" + functions-have-names "^1.2.2" + functional-red-black-tree@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" @@ -7806,6 +8023,13 @@ globals@^9.18.0: resolved "https://registry.yarnpkg.com/globals/-/globals-9.18.0.tgz#aa3896b3e69b487f17e31ed2143d69a8e30c2d8a" integrity sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ== +globalthis@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/globalthis/-/globalthis-1.0.3.tgz#5852882a52b80dc301b0660273e1ed082f0b6ccf" + integrity sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA== + dependencies: + define-properties "^1.1.3" + globby@^11.0.1: version "11.0.4" resolved "https://registry.yarnpkg.com/globby/-/globby-11.0.4.tgz#2cbaff77c2f2a62e71e9b2813a67b97a3a3001a5" @@ -7991,6 +8215,11 @@ has-bigints@^1.0.1: resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.1.tgz#64fe6acb020673e3b78db035a5af69aa9d07b113" integrity sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA== +has-bigints@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.2.tgz#0871bd3e3d51626f6ca0966668ba35d5602d6eaa" + integrity sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ== + has-flag@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa" @@ -8013,6 +8242,11 @@ has-property-descriptors@^1.0.0: dependencies: get-intrinsic "^1.1.1" +has-proto@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/has-proto/-/has-proto-1.0.1.tgz#1885c1305538958aff469fef37937c22795408e0" + integrity sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg== + has-symbols@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.2.tgz#165d3070c00309752a1236a479331e3ac56f1423" @@ -8047,14 +8281,6 @@ he@^1.2.0: resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== -home-or-tmp@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/home-or-tmp/-/home-or-tmp-2.0.0.tgz#e36c3f2d2cae7d746a857e38d18d5f32a7882db8" - integrity sha1-42w/LSyufXRqhX440Y1fMqeILbg= - dependencies: - os-homedir "^1.0.0" - os-tmpdir "^1.0.1" - homedir-polyfill@^1.0.0: version "1.0.3" resolved "https://registry.yarnpkg.com/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz#743298cef4e5af3e194161fbadcc2151d3a058e8" @@ -8487,7 +8713,7 @@ internal-slot@^1.0.3: has "^1.0.3" side-channel "^1.0.4" -internal-slot@^1.0.4: +internal-slot@^1.0.4, internal-slot@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.5.tgz#f2a2ee21f668f8627a4667f309dc0f4fb6674986" integrity sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ== @@ -8531,7 +8757,7 @@ is-arguments@^1.0.4, is-arguments@^1.1.1: call-bind "^1.0.2" has-tostringtag "^1.0.0" -is-array-buffer@^3.0.1: +is-array-buffer@^3.0.1, is-array-buffer@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/is-array-buffer/-/is-array-buffer-3.0.2.tgz#f2653ced8412081638ecb0ebbd0c41c6e0aecbbe" integrity sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w== @@ -8572,7 +8798,7 @@ is-buffer@^1.0.2, is-buffer@^1.1.5: resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== -is-callable@^1.1.3: +is-callable@^1.1.3, is-callable@^1.2.7: version "1.2.7" resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.7.tgz#3bc2a85ea742d9e36205dcacdd72ca1fdc51b055" integrity sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA== @@ -8589,6 +8815,13 @@ is-ci@^2.0.0: dependencies: ci-info "^2.0.0" +is-core-module@^2.1.0: + version "2.9.0" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.9.0.tgz#e1c34429cd51c6dd9e09e0799e396e27b19a9c69" + integrity sha512-+5FPy5PnwmO3lvfMb0AsoPaBG+5KHUI0wYFXOtYPnVVVspTFUuMZNfNaNVRt3FZadstu2c8x23vykRW/NBoU6A== + dependencies: + has "^1.0.3" + is-core-module@^2.2.0, is-core-module@^2.8.1: version "2.8.1" resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.8.1.tgz#f59fdfca701d5879d0a6b100a40aa1560ce27211" @@ -8603,6 +8836,13 @@ is-core-module@^2.5.0, is-core-module@^2.8.0: dependencies: has "^1.0.3" +is-core-module@^2.9.0: + version "2.11.0" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.11.0.tgz#ad4cb3e3863e814523c96f3f58d26cc570ff0144" + integrity sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw== + dependencies: + has "^1.0.3" + is-date-object@^1.0.1, is-date-object@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.5.tgz#0841d5536e724c25597bf6ea62e1bd38298df31f" @@ -8630,11 +8870,6 @@ is-extglob@^2.1.1: resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= -is-finite@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-finite/-/is-finite-1.1.0.tgz#904135c77fb42c0641d6aa1bcdbc4daa8da082f3" - integrity sha512-cdyMtqX/BOqqNBBiKlIVkytNHm49MtMlYyn1zxzvJKWmFMlGzm+ry5BBfYyeY9YmNKbRSo/o7OX9w9ale0wg3w== - is-fullwidth-code-point@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb" @@ -8700,6 +8935,11 @@ is-negative-zero@^2.0.1: resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.1.tgz#3de746c18dda2319241a53675908d8f766f11c24" integrity sha512-2z6JzQvZRa9A2Y7xC6dQQm4FSTSTNWjKIYYTt4246eMTJmIo0Q+ZyOsU66X8lxK1AbB92dFeglPLrhwpeRKO6w== +is-negative-zero@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.2.tgz#7bf6f03a28003b8b3965de3ac26f664d765f3150" + integrity sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA== + is-npm@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/is-npm/-/is-npm-5.0.0.tgz#43e8d65cc56e1b67f8d47262cf667099193f45a8" @@ -8771,6 +9011,13 @@ is-promise@^2.1.0: resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.2.2.tgz#39ab959ccbf9a774cf079f7b40c7a26f763135f1" integrity sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ== +is-reference@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/is-reference/-/is-reference-1.2.1.tgz#8b2dac0b371f4bc994fdeaba9eb542d03002d0b7" + integrity sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ== + dependencies: + "@types/estree" "*" + is-regex@^1.0.4, is-regex@^1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.4.tgz#eef5663cd59fa4c0ae339505323df6854bb15958" @@ -8844,7 +9091,7 @@ is-symbol@^1.0.2, is-symbol@^1.0.3: dependencies: has-symbols "^1.0.2" -is-typed-array@^1.1.10: +is-typed-array@^1.1.10, is-typed-array@^1.1.9: version "1.1.10" resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.10.tgz#36a5b5cb4189b575d1a3e4b08536bfb485801e3f" integrity sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A== @@ -8882,6 +9129,13 @@ is-weakref@^1.0.1: dependencies: call-bind "^1.0.0" +is-weakref@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-weakref/-/is-weakref-1.0.2.tgz#9529f383a9338205e89765e0392efc2f100f06f2" + integrity sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ== + dependencies: + call-bind "^1.0.2" + is-weakset@^2.0.1: version "2.0.2" resolved "https://registry.yarnpkg.com/is-weakset/-/is-weakset-2.0.2.tgz#4569d67a747a1ce5a994dfd4ef6dcea76e7c0a1d" @@ -9447,6 +9701,11 @@ jest@^27.4.3: import-local "^3.0.2" jest-cli "^27.5.1" +jju@~1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/jju/-/jju-1.4.0.tgz#a3abe2718af241a2b2904f84a625970f389ae32a" + integrity sha1-o6vicYryQaKykE+EpiWXDzia4yo= + joi@^17.3.0: version "17.5.0" resolved "https://registry.yarnpkg.com/joi/-/joi-17.5.0.tgz#7e66d0004b5045d971cf416a55fb61d33ac6e011" @@ -9567,11 +9826,6 @@ jsdom@^16.6.0: ws "^7.4.6" xml-name-validator "^3.0.0" -jsesc@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-1.3.0.tgz#46c3fec8c1892b12b0833db9bc7622176dbab34b" - integrity sha1-RsP+yMGJKxKwgz25vHYiF226s0s= - jsesc@^2.5.1: version "2.5.2" resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" @@ -9627,11 +9881,6 @@ json-stringify-safe@~5.0.1: resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus= -json5@^0.5.1: - version "0.5.1" - resolved "https://registry.yarnpkg.com/json5/-/json5-0.5.1.tgz#1eade7acc012034ad84e2396767ead9fa5495821" - integrity sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE= - json5@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.1.tgz#779fb0018604fa854eacbf6252180d83543e3dbe" @@ -9646,6 +9895,11 @@ json5@^2.1.2, json5@^2.2.0: dependencies: minimist "^1.2.5" +json5@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.1.tgz#655d50ed1e6f95ad1a3caababd2b0efda10b395c" + integrity sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA== + jsonfile@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb" @@ -10044,13 +10298,6 @@ magic-string@^0.25.0, magic-string@^0.25.7: dependencies: sourcemap-codec "^1.4.8" -magic-string@^0.25.2: - version "0.25.7" - resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.25.7.tgz#3f497d6fd34c669c6798dcb821f2ef31f5445051" - integrity sha512-4CrMT5DOHTDk4HYDlzmwu4FVCcIYI8gauveasrdCu2IKIFOJ3f0v/8MDGJCDL9oD2ppz/Av1b0Nj345H9M+XIA== - dependencies: - sourcemap-codec "^1.4.4" - make-dir@^3.0.0, make-dir@^3.0.2, make-dir@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f" @@ -10239,7 +10486,7 @@ minimalistic-assert@^1.0.0: resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A== -minimatch@3.0.4, minimatch@^3.0.2, minimatch@^3.0.4: +minimatch@3.0.4, minimatch@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== @@ -10275,7 +10522,7 @@ mixin-object@^2.0.1: for-in "^0.1.3" is-extendable "^0.1.1" -mkdirp@^0.5.1, mkdirp@^0.5.4, mkdirp@^0.5.5, mkdirp@~0.5.1: +mkdirp@^0.5.4, mkdirp@^0.5.5, mkdirp@~0.5.1: version "0.5.5" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def" integrity sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ== @@ -10325,16 +10572,16 @@ mute-stream@0.0.8: resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.8.tgz#1630c42b2251ff81e2a283de96a5497ea92e5e0d" integrity sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA== -nanoid@^3.1.30: - version "3.1.30" - resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.1.30.tgz#63f93cc548d2a113dc5dfbc63bfa09e2b9b64362" - integrity sha512-zJpuPDwOv8D2zq2WRoMe1HsfZthVewpel9CAvTfc/2mBD1uUT/agc5f7GHGWXlYkFvi1mVxe4IjvP2HNrop7nQ== - nanoid@^3.3.1: version "3.3.1" resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.1.tgz#6347a18cac88af88f58af0b3594b723d5e99bb35" integrity sha512-n6Vs/3KGyxPQd6uO0eH4Bv0ojGSUvuLlIHtC3Y0kEO23YRge8H9x1GCzLn28YX0H66pMkxuaeESFq4tKISKwdw== +nanoid@^3.3.2: + version "3.3.2" + resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.2.tgz#c89622fafb4381cd221421c69ec58547a1eec557" + integrity sha512-CuHBogktKwpm5g2sRgv83jEy2ijFzBwMoYA60orPDR7ynsLijJDqgsi4RDGj3OJpy3Ieb+LYwiRmIOGyytgITA== + natural-compare@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" @@ -10568,6 +10815,11 @@ object-inspect@^1.11.0, object-inspect@^1.9.0: resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.11.1.tgz#d4bd7d7de54b9a75599f59a00bd698c1f1c6549b" integrity sha512-If7BjFlpkzzBeV1cqgT3OSWT3azyoxDGajR+iGnFBfVV2EWyDyWaZZW2ERDjUaY2QM8i5jI3Sj7mhsM4DDAqWA== +object-inspect@^1.12.3: + version "1.12.3" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.3.tgz#ba62dffd67ee256c8c086dfae69e016cd1f198b9" + integrity sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g== + object-is@^1.0.1, object-is@^1.1.5: version "1.1.5" resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.1.5.tgz#b9deeaa5fc7f1846a0faecdceec138e5778f53ac" @@ -10610,6 +10862,15 @@ object.entries@^1.1.5: define-properties "^1.1.3" es-abstract "^1.19.1" +object.entries@^1.1.6: + version "1.1.6" + resolved "https://registry.yarnpkg.com/object.entries/-/object.entries-1.1.6.tgz#9737d0e5b8291edd340a3e3264bb8a3b00d5fa23" + integrity sha512-leTPzo4Zvg3pmbQ3rDK69Rl8GQvIqMWubrkxONG9/ojtFE2rD9fjMKfSI5BxW3osRH1m6VdzmqK8oAY9aT4x5w== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.4" + es-abstract "^1.20.4" + object.fromentries@^2.0.5: version "2.0.5" resolved "https://registry.yarnpkg.com/object.fromentries/-/object.fromentries-2.0.5.tgz#7b37b205109c21e741e605727fe8b0ad5fa08251" @@ -10619,6 +10880,15 @@ object.fromentries@^2.0.5: define-properties "^1.1.3" es-abstract "^1.19.1" +object.fromentries@^2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/object.fromentries/-/object.fromentries-2.0.6.tgz#cdb04da08c539cffa912dcd368b886e0904bfa73" + integrity sha512-VciD13dswC4j1Xt5394WR4MzmAQmlgN72phd/riNp9vtD7tp4QQWJ0R4wvclXcafgcYK8veHRed2W6XeGBvcfg== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.4" + es-abstract "^1.20.4" + object.getownpropertydescriptors@^2.1.0: version "2.1.3" resolved "https://registry.yarnpkg.com/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.3.tgz#b223cf38e17fefb97a63c10c91df72ccb386df9e" @@ -10636,6 +10906,14 @@ object.hasown@^1.1.0: define-properties "^1.1.3" es-abstract "^1.19.1" +object.hasown@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/object.hasown/-/object.hasown-1.1.2.tgz#f919e21fad4eb38a57bc6345b3afd496515c3f92" + integrity sha512-B5UIT3J1W+WuWIU55h0mjlwaqxiE5vYENJXIXZ4VFe05pNYrkKuK0U/6aFcb0pKywYJh7IhfoqUfKVmrJJHZHw== + dependencies: + define-properties "^1.1.4" + es-abstract "^1.20.4" + object.values@^1.1.0, object.values@^1.1.5: version "1.1.5" resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.1.5.tgz#959f63e3ce9ef108720333082131e4a459b716ac" @@ -10645,6 +10923,15 @@ object.values@^1.1.0, object.values@^1.1.5: define-properties "^1.1.3" es-abstract "^1.19.1" +object.values@^1.1.6: + version "1.1.6" + resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.1.6.tgz#4abbaa71eba47d63589d402856f908243eea9b1d" + integrity sha512-FVVTkD1vENCsAcwNs9k6jea2uHC/X0+JcjG8YA60FN5CMaJmG95wT9jek/xX9nornqGRrBkKtzuAu2wuHpKqvw== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.4" + es-abstract "^1.20.4" + obuf@^1.0.0, obuf@^1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/obuf/-/obuf-1.1.2.tgz#09bea3343d41859ebd446292d11c9d4db619084e" @@ -10734,12 +11021,12 @@ org-regex@^1.0.0: resolved "https://registry.yarnpkg.com/org-regex/-/org-regex-1.0.0.tgz#67ebb9ab3cb124fea5841289d60b59434f041a59" integrity sha512-7bqkxkEJwzJQUAlyYniqEZ3Ilzjh0yoa62c7gL6Ijxj5bEpPL+8IE1Z0PFj0ywjjXQcdrwR51g9MIcLezR0hKQ== -os-homedir@^1.0.0, os-homedir@^1.0.1: +os-homedir@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" integrity sha1-/7xJiDNuDoM94MFox+8VISGqf7M= -os-tmpdir@^1.0.1, os-tmpdir@~1.0.2: +os-tmpdir@~1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ= @@ -10996,11 +11283,18 @@ path-exists@^4.0.0: resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== -path-is-absolute@^1.0.0, path-is-absolute@^1.0.1: +path-is-absolute@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= +path-is-network-drive@^1.0.13: + version "1.0.13" + resolved "https://registry.yarnpkg.com/path-is-network-drive/-/path-is-network-drive-1.0.13.tgz#c9aa0183eb72c328aa83f43def93ddcb9d7ec4d4" + integrity sha512-Hg74mRN6mmXV+gTm3INjFK40ncAmC/Lo4qoQaSZ+GT3hZzlKdWQSqAjqyPeW0SvObP2W073WyYEBWY9d3wOm3A== + dependencies: + tslib "^2.3.1" + path-key@^2.0.0, path-key@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" @@ -11016,6 +11310,13 @@ path-parse@^1.0.6, path-parse@^1.0.7: resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== +path-strip-sep@^1.0.10: + version "1.0.10" + resolved "https://registry.yarnpkg.com/path-strip-sep/-/path-strip-sep-1.0.10.tgz#2be4e789406b298af8709ff79af716134b733b98" + integrity sha512-JpCy+8LAJQQTO1bQsb/84s1g+/Stm3h39aOpPRBQ/paMUGVPPZChLTOTKHoaCkc/6sKuF7yVsnq5Pe1S6xQGcA== + dependencies: + tslib "^2.3.1" + path-to-regexp@0.1.7: version "0.1.7" resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" @@ -11083,6 +11384,13 @@ pirates@^4.0.4: resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.5.tgz#feec352ea5c3268fb23a37c702ab1699f35a5f3b" integrity sha512-8V9+HQPupnaXMA23c5hvl69zXvTwTzyAYasnkb0Tts4XvO4CliqONMOnvlq26rkhLC3nWDFBJf73LU1e1VZLaQ== +"pkg-dir@< 6 >= 5", pkg-dir@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-5.0.0.tgz#a02d6aebe6ba133a928f74aec20bafdfe6b8e760" + integrity sha512-NPE8TDbzl/3YQYY7CSS228s3g2ollTFnc+Qi3tqmqJp9Vg2ovUpixcJEo2HJScN2Ez+kEaal6y70c0ehqJBJeA== + dependencies: + find-up "^5.0.0" + pkg-dir@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-2.0.0.tgz#f6d5d1109e19d63edf428e0bd57e12777615334b" @@ -11097,13 +11405,6 @@ pkg-dir@^4.1.0, pkg-dir@^4.2.0: dependencies: find-up "^4.0.0" -pkg-dir@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-5.0.0.tgz#a02d6aebe6ba133a928f74aec20bafdfe6b8e760" - integrity sha512-NPE8TDbzl/3YQYY7CSS228s3g2ollTFnc+Qi3tqmqJp9Vg2ovUpixcJEo2HJScN2Ez+kEaal6y70c0ehqJBJeA== - dependencies: - find-up "^5.0.0" - pkg-up@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/pkg-up/-/pkg-up-3.1.0.tgz#100ec235cc150e4fd42519412596a28512a0def5" @@ -12041,7 +12342,7 @@ pretty-format@^27.0.2, pretty-format@^27.5.1: ansi-styles "^5.0.0" react-is "^17.0.1" -private@^0.1.6, private@^0.1.8: +private@^0.1.6: version "0.1.8" resolved "https://registry.yarnpkg.com/private/-/private-0.1.8.tgz#2381edb3689f7a53d653190060fcf822d2f368ff" integrity sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg== @@ -12076,7 +12377,7 @@ prompts@^2.0.1, prompts@^2.3.0, prompts@^2.4.2: kleur "^3.0.3" sisteransi "^1.0.5" -prop-types@^15.5.8, prop-types@^15.7.2: +prop-types@^15.5.8: version "15.7.2" resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.7.2.tgz#52c41e75b8c87e72b9d9360e0206b99dcbffa6c5" integrity sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ== @@ -12621,13 +12922,6 @@ renderkid@^3.0.0: lodash "^4.17.21" strip-ansi "^6.0.1" -repeating@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/repeating/-/repeating-2.0.1.tgz#5214c53a926d3552707527fbab415dbc08d06dda" - integrity sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo= - dependencies: - is-finite "^1.0.0" - request-progress@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/request-progress/-/request-progress-3.0.0.tgz#4ca754081c7fec63f505e4faa825aa06cd669dbe" @@ -12732,7 +13026,7 @@ resolve.exports@^1.1.0: resolved "https://registry.yarnpkg.com/resolve.exports/-/resolve.exports-1.1.0.tgz#5ce842b94b05146c0e03076985d1d0e7e48c90c9" integrity sha512-J1l+Zxxp4XK3LUDZ9m60LRJF/mAe4z6a4xyabPHk7pvK5t35dACV32iIjJDFeWZFfZlO29w6SZ67knR0tHzJtQ== -resolve@^1.1.6, resolve@^1.10.0, resolve@^1.12.0, resolve@^1.14.2, resolve@^1.20.0, resolve@^1.5.0, resolve@^1.8.1: +resolve@^1.10.0, resolve@^1.12.0, resolve@^1.14.2, resolve@^1.20.0, resolve@^1.5.0, resolve@^1.8.1: version "1.20.0" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.20.0.tgz#629a013fb3f70755d6f0b7935cc1c2c5378b1975" integrity sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A== @@ -12740,7 +13034,7 @@ resolve@^1.1.6, resolve@^1.10.0, resolve@^1.12.0, resolve@^1.14.2, resolve@^1.20 is-core-module "^2.2.0" path-parse "^1.0.6" -resolve@^1.19.0, resolve@^1.22.0: +resolve@^1.17.0, resolve@^1.19.0, resolve@^1.22.0: version "1.22.0" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.0.tgz#5e0b8c67c15df57a89bdbabe603a002f21731198" integrity sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw== @@ -12757,6 +13051,23 @@ resolve@^2.0.0-next.3: is-core-module "^2.2.0" path-parse "^1.0.6" +resolve@^2.0.0-next.4: + version "2.0.0-next.4" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-2.0.0-next.4.tgz#3d37a113d6429f496ec4752d2a2e58efb1fd4660" + integrity sha512-iMDbmAWtfU+MHpxt/I5iWI7cY6YVEZUQ3MBgPQ++XD1PELuJHIl82xBmObyP2KyQmkNB2dsqF7seoQQiAn5yDQ== + dependencies: + is-core-module "^2.9.0" + path-parse "^1.0.7" + supports-preserve-symlinks-flag "^1.0.0" + +resolve@~1.19.0: + version "1.19.0" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.19.0.tgz#1af5bf630409734a067cae29318aac7fa29a267c" + integrity sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg== + dependencies: + is-core-module "^2.1.0" + path-parse "^1.0.6" + responselike@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/responselike/-/responselike-1.0.2.tgz#918720ef3b631c5642be068f15ade5a46f4ba1e7" @@ -12819,32 +13130,6 @@ rimraf@^3.0.0, rimraf@^3.0.2: dependencies: glob "^7.1.3" -rollup-plugin-babel@^3.0.7: - version "3.0.7" - resolved "https://registry.yarnpkg.com/rollup-plugin-babel/-/rollup-plugin-babel-3.0.7.tgz#5b13611f1ab8922497e9d15197ae5d8a23fe3b1e" - integrity sha512-bVe2y0z/V5Ax1qU8NX/0idmzIwJPdUGu8Xx3vXH73h0yGjxfv2gkFI82MBVg49SlsFlLTBadBHb67zy4TWM3hA== - dependencies: - rollup-pluginutils "^1.5.0" - -rollup-plugin-commonjs@^9.1.3: - version "9.3.4" - resolved "https://registry.yarnpkg.com/rollup-plugin-commonjs/-/rollup-plugin-commonjs-9.3.4.tgz#2b3dddbbbded83d45c36ff101cdd29e924fd23bc" - integrity sha512-DTZOvRoiVIHHLFBCL4pFxOaJt8pagxsVldEXBOn6wl3/V21wVaj17HFfyzTsQUuou3sZL3lEJZVWKPFblJfI6w== - dependencies: - estree-walker "^0.6.0" - magic-string "^0.25.2" - resolve "^1.10.0" - rollup-pluginutils "^2.6.0" - -rollup-plugin-node-resolve@^3.3.0: - version "3.4.0" - resolved "https://registry.yarnpkg.com/rollup-plugin-node-resolve/-/rollup-plugin-node-resolve-3.4.0.tgz#908585eda12e393caac7498715a01e08606abc89" - integrity sha512-PJcd85dxfSBWih84ozRtBkB731OjXk0KnzN0oGp7WOWcarAFkVa71cV5hTJg2qpVsV2U8EUwrzHP3tvy9vS3qg== - dependencies: - builtin-modules "^2.0.0" - is-module "^1.0.0" - resolve "^1.1.6" - rollup-plugin-peer-deps-external@^2.2.0: version "2.2.4" resolved "https://registry.yarnpkg.com/rollup-plugin-peer-deps-external/-/rollup-plugin-peer-deps-external-2.2.4.tgz#8a420bbfd6dccc30aeb68c9bf57011f2f109570d" @@ -12881,6 +13166,18 @@ rollup-plugin-terser@^7.0.0: serialize-javascript "^4.0.0" terser "^5.0.0" +rollup-plugin-typescript2@^0.31.2: + version "0.31.2" + resolved "https://registry.yarnpkg.com/rollup-plugin-typescript2/-/rollup-plugin-typescript2-0.31.2.tgz#463aa713a7e2bf85b92860094b9f7fb274c5a4d8" + integrity sha512-hRwEYR1C8xDGVVMFJQdEVnNAeWRvpaY97g5mp3IeLnzhNXzSVq78Ye/BJ9PAaUfN4DXa/uDnqerifMOaMFY54Q== + dependencies: + "@rollup/pluginutils" "^4.1.2" + "@yarn-tool/resolve-package" "^1.0.40" + find-cache-dir "^3.3.2" + fs-extra "^10.0.0" + resolve "^1.20.0" + tslib "^2.3.1" + rollup-plugin-url@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/rollup-plugin-url/-/rollup-plugin-url-1.4.0.tgz#346124cad853267b324cba0991f10bfd4be60c65" @@ -12889,29 +13186,13 @@ rollup-plugin-url@^1.4.0: mime "^2.3.1" rollup-pluginutils "^2.0.1" -rollup-pluginutils@^1.5.0: - version "1.5.2" - resolved "https://registry.yarnpkg.com/rollup-pluginutils/-/rollup-pluginutils-1.5.2.tgz#1e156e778f94b7255bfa1b3d0178be8f5c552408" - integrity sha1-HhVud4+UtyVb+hs9AXi+j1xVJAg= - dependencies: - estree-walker "^0.2.1" - minimatch "^3.0.2" - -rollup-pluginutils@^2.0.1, rollup-pluginutils@^2.3.1, rollup-pluginutils@^2.6.0: +rollup-pluginutils@^2.0.1, rollup-pluginutils@^2.3.1: version "2.8.2" resolved "https://registry.yarnpkg.com/rollup-pluginutils/-/rollup-pluginutils-2.8.2.tgz#72f2af0748b592364dbd3389e600e5a9444a351e" integrity sha512-EEp9NhnUkwY8aif6bxgovPHMoMoNr2FulJziTndpt5H9RdwC47GSGuII9XxpSdzVGM0GWrNPHV6ie1LTNJPaLQ== dependencies: estree-walker "^0.6.1" -rollup@^0.64.1: - version "0.64.1" - resolved "https://registry.yarnpkg.com/rollup/-/rollup-0.64.1.tgz#9188ee368e5fcd43ffbc00ec414e72eeb5de87ba" - integrity sha512-+ThdVXrvonJdOTzyybMBipP0uz605Z8AnzWVY3rf+cSGnLO7uNkJBlN+9jXqWOomkvumXfm/esmBpA5d53qm7g== - dependencies: - "@types/estree" "0.0.39" - "@types/node" "*" - rollup@^2.43.1: version "2.70.1" resolved "https://registry.yarnpkg.com/rollup/-/rollup-2.70.1.tgz#824b1f1f879ea396db30b0fc3ae8d2fead93523e" @@ -12919,6 +13200,13 @@ rollup@^2.43.1: optionalDependencies: fsevents "~2.3.2" +rollup@^2.70.2: + version "2.70.2" + resolved "https://registry.yarnpkg.com/rollup/-/rollup-2.70.2.tgz#808d206a8851628a065097b7ba2053bd83ba0c0d" + integrity sha512-EitogNZnfku65I1DD5Mxe8JYRUCy0hkK5X84IlDtUs+O6JRMpRciXTzyCUuX11b5L5pvjH+OmFXiQ3XjabcXgg== + optionalDependencies: + fsevents "~2.3.2" + run-async@^2.2.0, run-async@^2.4.0: version "2.4.1" resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.4.1.tgz#8440eccf99ea3e70bd409d49aab88e10c189a455" @@ -12953,6 +13241,15 @@ safe-buffer@5.2.1, safe-buffer@>=5.1.0, safe-buffer@^5.0.1, safe-buffer@^5.1.0, resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== +safe-regex-test@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/safe-regex-test/-/safe-regex-test-1.0.0.tgz#793b874d524eb3640d1873aad03596db2d4f2295" + integrity sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA== + dependencies: + call-bind "^1.0.2" + get-intrinsic "^1.1.3" + is-regex "^1.1.4" + "safer-buffer@>= 2.1.2 < 3", "safer-buffer@>= 2.1.2 < 3.0.0", safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: version "2.1.2" resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" @@ -13197,11 +13494,6 @@ sisteransi@^1.0.5: resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.5.tgz#134d681297756437cc05ca01370d3a7a571075ed" integrity sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg== -slash@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/slash/-/slash-1.0.0.tgz#c41f2f6c39fc16d1cd17ad4b5d896114ae470d55" - integrity sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU= - slash@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" @@ -13261,13 +13553,6 @@ source-map-loader@^3.0.0: iconv-lite "^0.6.3" source-map-js "^1.0.1" -source-map-support@^0.4.15: - version "0.4.18" - resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.4.18.tgz#0286a6de8be42641338594e97ccea75f0a2c585f" - integrity sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA== - dependencies: - source-map "^0.5.6" - source-map-support@^0.5.6, source-map-support@~0.5.20: version "0.5.21" resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f" @@ -13281,7 +13566,7 @@ source-map@0.6.1, source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.0, sourc resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== -source-map@^0.5.0, source-map@^0.5.3, source-map@^0.5.6, source-map@^0.5.7: +source-map@^0.5.0, source-map@^0.5.3, source-map@^0.5.6: version "0.5.7" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w= @@ -13298,7 +13583,7 @@ source-map@^0.8.0-beta.0: dependencies: whatwg-url "^7.0.0" -sourcemap-codec@^1.4.4, sourcemap-codec@^1.4.8: +sourcemap-codec@^1.4.8: version "1.4.8" resolved "https://registry.yarnpkg.com/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz#ea804bd94857402e6992d05a38ef1ae35a9ab4c4" integrity sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA== @@ -13489,6 +13774,29 @@ string.prototype.matchall@^4.0.6: regexp.prototype.flags "^1.3.1" side-channel "^1.0.4" +string.prototype.matchall@^4.0.8: + version "4.0.8" + resolved "https://registry.yarnpkg.com/string.prototype.matchall/-/string.prototype.matchall-4.0.8.tgz#3bf85722021816dcd1bf38bb714915887ca79fd3" + integrity sha512-6zOCOcJ+RJAQshcTvXPHoxoQGONa3e/Lqx90wUA+wEzX78sg5Bo+1tQo4N0pohS0erG9qtCqJDjNCQBjeWVxyg== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.4" + es-abstract "^1.20.4" + get-intrinsic "^1.1.3" + has-symbols "^1.0.3" + internal-slot "^1.0.3" + regexp.prototype.flags "^1.4.3" + side-channel "^1.0.4" + +string.prototype.trim@^1.2.7: + version "1.2.7" + resolved "https://registry.yarnpkg.com/string.prototype.trim/-/string.prototype.trim-1.2.7.tgz#a68352740859f6893f14ce3ef1bb3037f7a90533" + integrity sha512-p6TmeT1T3411M8Cgg9wBTMRtY2q9+PNy9EV1i2lIXUN/btt763oIfxwN3RR8VU6wHX8j/1CFy0L+YuThm6bgOg== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.4" + es-abstract "^1.20.4" + string.prototype.trimend@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz#e75ae90c2942c63504686c18b287b4a0b1a45f80" @@ -13497,6 +13805,15 @@ string.prototype.trimend@^1.0.4: call-bind "^1.0.2" define-properties "^1.1.3" +string.prototype.trimend@^1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.6.tgz#c4a27fa026d979d79c04f17397f250a462944533" + integrity sha512-JySq+4mrPf9EsDBEDYMOb/lM7XQLulwg5R/m1r0PXEFqrV0qHvl58sdTilSXtKOflCsK2E8jxf+GKC0T07RWwQ== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.4" + es-abstract "^1.20.4" + string.prototype.trimstart@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz#b36399af4ab2999b4c9c648bd7a3fb2bb26feeed" @@ -13505,6 +13822,15 @@ string.prototype.trimstart@^1.0.4: call-bind "^1.0.2" define-properties "^1.1.3" +string.prototype.trimstart@^1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.6.tgz#e90ab66aa8e4007d92ef591bbf3cd422c56bdcf4" + integrity sha512-omqjMDaY92pbn5HOX7f9IccLA+U1tA9GvtU4JrodiXFfYB7jPzzHpRzpglLAjtUV6bB557zwClJezTqnAiYnQA== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.4" + es-abstract "^1.20.4" + string_decoder@^1.1.1: version "1.3.0" resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" @@ -13990,11 +14316,6 @@ trim-repeated@^1.0.0: dependencies: escape-string-regexp "^1.0.2" -trim-right@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/trim-right/-/trim-right-1.0.1.tgz#cb2e1203067e0c8de1f614094b9fe45704ea6003" - integrity sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM= - tryer@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/tryer/-/tryer-1.0.1.tgz#f2c85406800b9b0f74c9f7465b81eaad241252f8" @@ -14030,7 +14351,7 @@ tslib@^2.0.0: resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.5.0.tgz#42bfed86f5787aeb41d031866c8f402429e0fddf" integrity sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg== -tslib@^2.0.3: +tslib@^2.0.3, tslib@^2.3.1: version "2.3.1" resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.3.1.tgz#e8a335add5ceae51aa261d32a490158ef042ef01" integrity sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw== @@ -14121,6 +14442,15 @@ type-is@~1.6.18: media-typer "0.3.0" mime-types "~2.1.24" +typed-array-length@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/typed-array-length/-/typed-array-length-1.0.4.tgz#89d83785e5c4098bec72e08b319651f0eac9c1bb" + integrity sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng== + dependencies: + call-bind "^1.0.2" + for-each "^0.3.3" + is-typed-array "^1.1.9" + typedarray-to-buffer@^3.1.5: version "3.1.5" resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz#a97ee7a9ff42691b9f783ff1bc5112fe3fca9080" @@ -14133,6 +14463,11 @@ typedarray@^0.0.6: resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= +typescript@^4.6.3: + version "4.6.3" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.6.3.tgz#eefeafa6afdd31d725584c67a0eaba80f6fc6c6c" + integrity sha512-yNIatDa5iaofVozS/uQJEl3JRWLKKGJKh6Yaiv0GLGSuhpFJe7P3SbHZ8/yjAHRQwKRoA6YZqlfjXWmVzoVSMw== + unbox-primitive@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.0.1.tgz#085e215625ec3162574dc8859abee78a59b14471" @@ -14143,6 +14478,16 @@ unbox-primitive@^1.0.1: has-symbols "^1.0.2" which-boxed-primitive "^1.0.2" +unbox-primitive@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.0.2.tgz#29032021057d5e6cdbd08c5129c226dff8ed6f9e" + integrity sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw== + dependencies: + call-bind "^1.0.2" + has-bigints "^1.0.2" + has-symbols "^1.0.3" + which-boxed-primitive "^1.0.2" + unicode-canonical-property-names-ecmascript@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz#301acdc525631670d39f6146e0e77ff6bbdebddc" @@ -14208,6 +14553,15 @@ untildify@^4.0.0: resolved "https://registry.yarnpkg.com/untildify/-/untildify-4.0.0.tgz#2bc947b953652487e4600949fb091e3ae8cd919b" integrity sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw== +upath2@^3.1.12: + version "3.1.12" + resolved "https://registry.yarnpkg.com/upath2/-/upath2-3.1.12.tgz#441b3dfbadde21731017bd1b7beb169498efd0a9" + integrity sha512-yC3eZeCyCXFWjy7Nu4pgjLhXNYjuzuUmJiRgSSw6TJp8Emc+E4951HGPJf+bldFC5SL7oBLeNbtm1fGzXn2gxw== + dependencies: + path-is-network-drive "^1.0.13" + path-strip-sep "^1.0.10" + tslib "^2.3.1" + upath@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/upath/-/upath-1.2.0.tgz#8f66dbcd55a883acdae4408af8b035a5044c1894"