diff --git a/.github/workflows/azure-static-web-app.yml b/.github/workflows/azure-static-web-app.yml index 7f40552..5b6f144 100644 --- a/.github/workflows/azure-static-web-app.yml +++ b/.github/workflows/azure-static-web-app.yml @@ -35,16 +35,14 @@ jobs: with: azure_static_web_apps_api_token: ${{ secrets.AZURE_STATIC_WEB_APPS_API_TOKEN_WITTY_GROUND_00482BD00 }} repo_token: ${{ secrets.GITHUB_TOKEN }} # Used for Github integrations (i.e. PR comments) - action: "upload" - ###### Repository/Build Configurations - These values can be configured to match your app requirements. ###### + action: upload # For more information regarding Static Web App workflow configurations, please visit: https://aka.ms/swaworkflowconfig - app_location: "packages/northstar" # App source code path - output_location: "dist" # Built app content directory - optional + app_location: packages/northstar # App source code path + output_location: dist # Built app content directory - optional skip_api_build: true env: PRE_BUILD_COMMAND: echo "do nothing" CUSTOM_BUILD_COMMAND: echo "do nothing" - ###### End of Repository/Build Configurations ###### close_pull_request_job: if: github.event_name == 'pull_request' && github.event.action == 'closed' @@ -56,4 +54,4 @@ jobs: uses: Azure/static-web-apps-deploy@v1 with: azure_static_web_apps_api_token: ${{ secrets.AZURE_STATIC_WEB_APPS_API_TOKEN_WITTY_GROUND_00482BD00 }} - action: "close" + action: close diff --git a/.vscode/settings.json b/.vscode/settings.json index 461b2ad..8e43c92 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -17,5 +17,47 @@ "[*.r.js][*.r.ts]": { "editor.guides.bracketPairs": "active" }, - "editor.guides.bracketPairs": "active" + "editor.guides.bracketPairs": "active", + + // Enable the ESlint flat config support + "eslint.experimental.useFlatConfig": true, + + // Disable the default formatter, use eslint instead + "prettier.enable": false, + "editor.formatOnSave": false, + + // Auto fix + "editor.codeActionsOnSave": { + "source.fixAll.eslint": "explicit", + "source.organizeImports": "never" + }, + + // Silent the stylistic rules in you IDE, but still auto fix them + "eslint.rules.customizations": [ + { "rule": "style/*", "severity": "off" }, + { "rule": "format/*", "severity": "off" }, + { "rule": "*-indent", "severity": "off" }, + { "rule": "*-spacing", "severity": "off" }, + { "rule": "*-spaces", "severity": "off" }, + { "rule": "*-order", "severity": "off" }, + { "rule": "*-dangle", "severity": "off" }, + { "rule": "*-newline", "severity": "off" }, + { "rule": "*quotes", "severity": "off" }, + { "rule": "*semi", "severity": "off" } + ], + + // Enable eslint for all supported languages + "eslint.validate": [ + "javascript", + "javascriptreact", + "typescript", + "typescriptreact", + "vue", + "html", + "markdown", + "json", + "jsonc", + "yaml", + "toml" + ] } diff --git a/eslint.config.js b/eslint.config.js new file mode 100644 index 0000000..998af1b --- /dev/null +++ b/eslint.config.js @@ -0,0 +1,14 @@ +import antfu from '@antfu/eslint-config' + +export default antfu( + { + typescript: true, + ignores: ['packages/browser-tailwind/src/polyfill/*'], + }, + { + rules: { + 'ts/no-this-alias': ['off'], + 'style/arrow-parens': ['error', 'as-needed'], + }, + }, +) diff --git a/package.json b/package.json index bba548b..3b4c2b2 100644 --- a/package.json +++ b/package.json @@ -1,22 +1,28 @@ { "name": "@quasi-dev/monorepo", - "version": "0.0.0", "type": "module", + "version": "0.0.0", "private": true, "scripts": { "build": "pnpm -r run build", "dev": "pnpm dev:northstar", "dev:northstar": "pnpm -r --parallel --filter \"@quasi-dev/northstar...\" run dev", "check": "pnpm -r --parallel run check", - "prettier": "prettier --write .", - "prepare": "husky install" + "prepare": "husky install", + "lint": "eslint .", + "lint:fix": "eslint . --fix" }, "devDependencies": { + "@antfu/eslint-config": "^2.8.1", + "eslint": "^8.57.0", "husky": "^8.0.3", "lint-staged": "^14.0.1", - "prettier": "3.0.0" + "simple-git-hooks": "^2.10.0" + }, + "simple-git-hooks": { + "pre-commit": "pnpm lint-staged" }, "lint-staged": { - "**/*": "prettier --write --ignore-unknown" + "*": "eslint --fix" } } diff --git a/packages/browser-tailwind/package.json b/packages/browser-tailwind/package.json index 5df8bc2..946d6da 100644 --- a/packages/browser-tailwind/package.json +++ b/packages/browser-tailwind/package.json @@ -1,30 +1,30 @@ { "name": "@quasi-dev/browser-tailwind", - "version": "0.0.0", - "description": "Compile Tailwind CSS in the browser", "type": "module", + "version": "0.0.0", "private": true, - "scripts": { - "check": "tsc --noEmit", - "build": "vite build" - }, - "main": "./dist/browser-tailwind.js", - "types": "./src/index.ts", + "description": "Compile Tailwind CSS in the browser", "exports": { ".": { - "default": "./dist/browser-tailwind.js", + "types": "./src/index.ts", "import": "./dist/browser-tailwind.js", - "types": "./src/index.ts" + "default": "./dist/browser-tailwind.js" } }, + "main": "./dist/browser-tailwind.js", + "types": "./src/index.ts", + "scripts": { + "check": "tsc --noEmit", + "build": "vite build" + }, + "dependencies": { + "postcss": "^8.4.31", + "tailwindcss": "^3.3.5" + }, "devDependencies": { "@rollup/plugin-commonjs": "^25.0.7", "@rollup/plugin-node-resolve": "^15.2.3", "typescript": "^5.4.2", "vite": "^4.4.8" - }, - "dependencies": { - "postcss": "^8.4.31", - "tailwindcss": "^3.3.5" } } diff --git a/packages/browser-tailwind/src/index.ts b/packages/browser-tailwind/src/index.ts index a3e9ca4..3468243 100644 --- a/packages/browser-tailwind/src/index.ts +++ b/packages/browser-tailwind/src/index.ts @@ -1,29 +1,33 @@ -//@ts-nocheck -import postcss, { Plugin } from "postcss"; -import tailwindcss, { Config } from "tailwindcss"; +/* eslint-disable node/prefer-global/process */ +/* eslint-disable no-restricted-globals */ + +import type { Plugin } from 'postcss' +import postcss from 'postcss' +import type { Config } from 'tailwindcss' +import tailwindcss from 'tailwindcss' import { VIRTUAL_CONTENT_EXTNAME, VIRTUAL_CONTENT_FILENAME, VIRTUAL_SOURCE_PATH, -} from "./polyfill/constants"; +} from './polyfill/constants' -//@ts-ignore +// @ts-expect-error missing type self.process = { env: {}, -}; +} export async function compileTailwindCSS( cssInput: string, contentInput: string, extname: string, - config: Config | {} = {}, + config: Config = {} as any, plugins: Plugin[] = [], ) { - self[VIRTUAL_CONTENT_EXTNAME] = extname; + self[VIRTUAL_CONTENT_EXTNAME] = extname // Tailwind scans the config.content for files to parse classNames -> set a virtual file here - if (!("content" in config)) { + if (!('content' in config)) { self[VIRTUAL_CONTENT_FILENAME] = contentInput; - (config as Config).content = [VIRTUAL_CONTENT_FILENAME]; + (config as Config).content = [VIRTUAL_CONTENT_FILENAME] } return await postcss([ tailwindcss(config as Config), @@ -31,30 +35,29 @@ export async function compileTailwindCSS( ...plugins, ]).process(cssInput, { from: VIRTUAL_SOURCE_PATH, - }); + }) } // https://github.com/tailwindlabs/tailwindcss/blob/315e3a2445d682b2da9ca93fda77252fe32879ff/src/cli.js#L26-L42 function formatNodes(root) { - indentRecursive(root); - if (root.first) { - root.first.raws.before = ""; - } + indentRecursive(root) + if (root.first) + root.first.raws.before = '' } function indentRecursive(node, indent = 0) { - node.each && - node.each((child, i) => { - if ( - !child.raws.before || - !child.raws.before.trim() || - child.raws.before.includes("\n") - ) { - child.raws.before = `\n${ - node.type !== "rule" && i > 0 ? "\n" : "" - }${" ".repeat(indent)}`; - } - child.raws.after = `\n${" ".repeat(indent)}`; - indentRecursive(child, indent + 1); - }); + node.each + && node.each((child, i) => { + if ( + !child.raws.before + || !child.raws.before.trim() + || child.raws.before.includes('\n') + ) { + child.raws.before = `\n${ + node.type !== 'rule' && i > 0 ? '\n' : '' + }${' '.repeat(indent)}` + } + child.raws.after = `\n${' '.repeat(indent)}` + indentRecursive(child, indent + 1) + }) } diff --git a/packages/browser-tailwind/src/polyfill/colorette.ts b/packages/browser-tailwind/src/polyfill/colorette.ts index 72f7afc..1e540bb 100644 --- a/packages/browser-tailwind/src/polyfill/colorette.ts +++ b/packages/browser-tailwind/src/polyfill/colorette.ts @@ -1,2 +1,2 @@ -//@ts-nocheck -export const options = { enabled: false }; +// @ts-nocheck +export const options = { enabled: false } diff --git a/packages/browser-tailwind/src/polyfill/constants.ts b/packages/browser-tailwind/src/polyfill/constants.ts index 84ca1f4..4b8f72f 100644 --- a/packages/browser-tailwind/src/polyfill/constants.ts +++ b/packages/browser-tailwind/src/polyfill/constants.ts @@ -1,9 +1,9 @@ -//@ts-nocheck +// @ts-nocheck /** * Dummy constant for Node like environment in Browser for lib depending on fs module, like PostCSS */ -export const VIRTUAL_SOURCE_PATH = "BROWSER_TAILWIND_VIRTUAL_SOURCE_PATH"; -export const VIRTUAL_CONTENT_FILENAME = - "BROWSER_TAILWIND_VIRTUAL_CONTENT_FILENAME"; -export const VIRTUAL_CONTENT_EXTNAME = - "BROWSER_TAILWIND_VIRTUAL_CONTENT_EXTNAME"; +export const VIRTUAL_SOURCE_PATH = 'BROWSER_TAILWIND_VIRTUAL_SOURCE_PATH' +export const VIRTUAL_CONTENT_FILENAME + = 'BROWSER_TAILWIND_VIRTUAL_CONTENT_FILENAME' +export const VIRTUAL_CONTENT_EXTNAME + = 'BROWSER_TAILWIND_VIRTUAL_CONTENT_EXTNAME' diff --git a/packages/browser-tailwind/src/polyfill/fast-glob.ts b/packages/browser-tailwind/src/polyfill/fast-glob.ts index 12fcd32..a7bd9fb 100644 --- a/packages/browser-tailwind/src/polyfill/fast-glob.ts +++ b/packages/browser-tailwind/src/polyfill/fast-glob.ts @@ -1,14 +1,14 @@ -//@ts-nocheck +// @ts-nocheck export default { - sync: (patterns) => [].concat(patterns), - escapePath: (path) => path, - generateTasks: (patterns) => [ + sync: patterns => [].concat(patterns), + escapePath: path => path, + generateTasks: patterns => [ { dynamic: false, - base: ".", + base: '.', negative: [], positive: [].concat(patterns), patterns: [].concat(patterns), }, ], -}; +} diff --git a/packages/browser-tailwind/src/polyfill/fs.ts b/packages/browser-tailwind/src/polyfill/fs.ts index 77e7756..bfe58b0 100644 --- a/packages/browser-tailwind/src/polyfill/fs.ts +++ b/packages/browser-tailwind/src/polyfill/fs.ts @@ -1,20 +1,20 @@ -//@ts-nocheck -import { VIRTUAL_SOURCE_PATH } from "./constants"; +// @ts-nocheck +import { VIRTUAL_SOURCE_PATH } from './constants' -let i = 0; -self.BUILD_ID = 0; +let i = 0 +self.BUILD_ID = 0 export default { - statSync: (id) => { - if (id === VIRTUAL_SOURCE_PATH) { - return { mtimeMs: self.BUILD_ID }; - } - return { mtimeMs: ++i }; + statSync: id => { + if (id === VIRTUAL_SOURCE_PATH) + return { mtimeMs: self.BUILD_ID } + + return { mtimeMs: ++i } }, - readFileSync: (id) => self[id] ?? "", + readFileSync: id => self[id] ?? '', promises: { readFile(id) { - return self[id] ?? ""; + return self[id] ?? '' }, }, -}; +} diff --git a/packages/browser-tailwind/src/polyfill/glob-parent.ts b/packages/browser-tailwind/src/polyfill/glob-parent.ts index ce085c7..a34a611 100644 --- a/packages/browser-tailwind/src/polyfill/glob-parent.ts +++ b/packages/browser-tailwind/src/polyfill/glob-parent.ts @@ -1,2 +1,2 @@ -//@ts-nocheck -export default () => ""; +// @ts-nocheck +export default () => '' diff --git a/packages/browser-tailwind/src/polyfill/is-glob.ts b/packages/browser-tailwind/src/polyfill/is-glob.ts index 3326eed..ceff997 100644 --- a/packages/browser-tailwind/src/polyfill/is-glob.ts +++ b/packages/browser-tailwind/src/polyfill/is-glob.ts @@ -1,2 +1,2 @@ -//@ts-nocheck -export default () => false; +// @ts-nocheck +export default () => false diff --git a/packages/browser-tailwind/src/polyfill/path.ts b/packages/browser-tailwind/src/polyfill/path.ts index 111fe41..57c46c3 100644 --- a/packages/browser-tailwind/src/polyfill/path.ts +++ b/packages/browser-tailwind/src/polyfill/path.ts @@ -1,15 +1,15 @@ -//@ts-nocheck -import { VIRTUAL_CONTENT_EXTNAME } from "./constants"; +// @ts-nocheck +import { VIRTUAL_CONTENT_EXTNAME } from './constants' -self.__dirname = ""; +self.__dirname = '' export default { join: () => { - return ""; + return '' }, - resolve: (id) => id, - extname: (id) => self[VIRTUAL_CONTENT_EXTNAME], -}; + resolve: id => id, + extname: _id => self[VIRTUAL_CONTENT_EXTNAME], +} -export const join = () => { - return ""; -}; +export function join() { + return '' +} diff --git a/packages/browser-tailwind/src/polyfill/url.ts b/packages/browser-tailwind/src/polyfill/url.ts index f7f01a5..3b44322 100644 --- a/packages/browser-tailwind/src/polyfill/url.ts +++ b/packages/browser-tailwind/src/polyfill/url.ts @@ -1,6 +1,6 @@ -//@ts-nocheck +// @ts-nocheck export default { parse() { - return new URL(location.href); + return new URL(location.href) }, -}; +} diff --git a/packages/browser-tailwind/tsconfig.json b/packages/browser-tailwind/tsconfig.json index 20fb158..d65b771 100644 --- a/packages/browser-tailwind/tsconfig.json +++ b/packages/browser-tailwind/tsconfig.json @@ -1,8 +1,8 @@ { - "include": ["src"], "compilerOptions": { + "lib": ["ESNext", "DOM"], "module": "ESNext", - "moduleResolution": "Bundler", - "lib": ["ESNext", "DOM"] - } + "moduleResolution": "Bundler" + }, + "include": ["src"] } diff --git a/packages/browser-tailwind/vite.config.ts b/packages/browser-tailwind/vite.config.ts index 6c5df17..3af4f04 100644 --- a/packages/browser-tailwind/vite.config.ts +++ b/packages/browser-tailwind/vite.config.ts @@ -1,28 +1,29 @@ -import { defineConfig } from "vite"; -import commonjs from "@rollup/plugin-commonjs"; -import resolve from "@rollup/plugin-node-resolve"; +import { defineConfig } from 'vite' +import commonjs from '@rollup/plugin-commonjs' +import resolve from '@rollup/plugin-node-resolve' export default defineConfig({ plugins: [ commonjs(), resolve(), { - name: "helper", - enforce: "pre", - transform(code, id, options) { + name: 'helper', + enforce: 'pre', + transform(code, id) { const names = [ - ["declaration", "Declaration"], - ["comment", "Comment"], - ["container", "Container"], - ["document", "Document"], - ["at-rule", "AtRule"], - ["root", "Root"], - ["rule", "Rule"], - ]; + ['declaration', 'Declaration'], + ['comment', 'Comment'], + ['container', 'Container'], + ['document', 'Document'], + ['at-rule', 'AtRule'], + ['root', 'Root'], + ['rule', 'Rule'], + ] for (const name of names) { if (id.endsWith(`postcss/lib/${name[0]}.js`)) { - console.log(`Removing ${name[1]} from ${id}`); - return code.replace(`${name[1]}.default = ${name[1]}`, ""); + // eslint-disable-next-line no-console + console.log(`Removing ${name[1]} from ${id}`) + return code.replace(`${name[1]}.default = ${name[1]}`, '') } } }, @@ -30,21 +31,21 @@ export default defineConfig({ ], resolve: { alias: { - colorette: "./src/polyfill/colorette.ts", - fs: "./src/polyfill/fs.ts", - path: "./src/polyfill/path.ts", - url: "./src/polyfill/url.ts", - "is-glob": "./src/polyfill/is-glob.ts", - "glob-parent": "./src/polyfill/glob-parent.ts", - "fast-glob": "./src/polyfill/fast-glob.ts", + 'colorette': './src/polyfill/colorette.ts', + 'fs': './src/polyfill/fs.ts', + 'path': './src/polyfill/path.ts', + 'url': './src/polyfill/url.ts', + 'is-glob': './src/polyfill/is-glob.ts', + 'glob-parent': './src/polyfill/glob-parent.ts', + 'fast-glob': './src/polyfill/fast-glob.ts', }, }, build: { lib: { - entry: "src/index.ts", - name: "BrowserTailwind", - formats: ["es"], + entry: 'src/index.ts', + name: 'BrowserTailwind', + formats: ['es'], }, minify: false, }, -}); +}) diff --git a/packages/compiler/package.json b/packages/compiler/package.json index 05fbf30..114b66e 100644 --- a/packages/compiler/package.json +++ b/packages/compiler/package.json @@ -1,20 +1,20 @@ { "name": "@quasi-dev/compiler", - "version": "0.0.0", "type": "module", + "version": "0.0.0", "private": true, - "main": "./src/index.ts", - "types": "./src/index.ts", "exports": { ".": "./src/index.ts" }, + "main": "./src/index.ts", + "types": "./src/index.ts", "scripts": { "check": "tsc --noEmit" }, - "devDependencies": { - "typescript": "^5.4.2" - }, "dependencies": { "prettier": "3.0.0" + }, + "devDependencies": { + "typescript": "^5.4.2" } } diff --git a/packages/compiler/src/compiler.ts b/packages/compiler/src/compiler.ts index 29acdd9..38961d0 100644 --- a/packages/compiler/src/compiler.ts +++ b/packages/compiler/src/compiler.ts @@ -1,14 +1,15 @@ -import { QuasiOutput } from "./types"; -import { ViewCompiler } from "./viewCompiler"; -import * as prettier from "prettier"; -import BabelPlugin from "prettier/plugins/babel"; -//@ts-ignore -import EsTreePlugin from "prettier/plugins/estree"; +import * as prettier from 'prettier' +import BabelPlugin from 'prettier/plugins/babel' + +// @ts-expect-error missing type +import EsTreePlugin from 'prettier/plugins/estree' +import { ViewCompiler } from './viewCompiler' +import type { QuasiOutput } from './types' export class Compiler { constructor(public input: QuasiOutput) {} - runtimeModuleURL = "@quasi-dev/runtime"; + runtimeModuleURL = '@quasi-dev/runtime' async compile() { const code = ` @@ -17,16 +18,16 @@ import QuasiRuntime, * as $quasi from "${this.runtimeModuleURL}"; const { $app, $view } = $quasi.refina; ${this.input.views - .map((v) => { - const viewCompiler = new ViewCompiler(this, v); - return viewCompiler.compile(); + .map(v => { + const viewCompiler = new ViewCompiler(this, v) + return viewCompiler.compile() }) - .join("\n\n")} -`; + .join('\n\n')} +` return await prettier.format(code, { - parser: "babel", + parser: 'babel', plugins: [BabelPlugin, EsTreePlugin], - arrowParens: "avoid", - }); + arrowParens: 'avoid', + }) } } diff --git a/packages/compiler/src/index.ts b/packages/compiler/src/index.ts index 80a22ff..ce1e50f 100644 --- a/packages/compiler/src/index.ts +++ b/packages/compiler/src/index.ts @@ -1,2 +1,2 @@ -export * from "./types"; -export * from "./compiler"; +export * from './types' +export * from './compiler' diff --git a/packages/compiler/src/types/base.ts b/packages/compiler/src/types/base.ts index defc450..ede67db 100644 --- a/packages/compiler/src/types/base.ts +++ b/packages/compiler/src/types/base.ts @@ -2,9 +2,9 @@ export interface ConnectTo { /** * if this socket is not connected, `blockId` will be `NaN` */ - blockId: number; + blockId: number /** * if this socket is not connected, `blockId` will be `""` */ - socketName: string; + socketName: string } diff --git a/packages/compiler/src/types/componentBlock.ts b/packages/compiler/src/types/componentBlock.ts index 9bc6778..bd982fd 100644 --- a/packages/compiler/src/types/componentBlock.ts +++ b/packages/compiler/src/types/componentBlock.ts @@ -1,59 +1,59 @@ -import { ConnectTo } from "./base"; +import type { ConnectTo } from './base' -export type ComponentBlockCallbacks = Record; +export type ComponentBlockCallbacks = Record export type ComponentBlockProps = Record< string, string | number | boolean | ConnectTo ->; +> -export type ComponentBlockPlugins = Record; +export type ComponentBlockPlugins = Record /** * Content text or child block id */ -export type ComponentBlockChildren = Record; +export type ComponentBlockChildren = Record export type ComponentBlockPrimaryInput = { - name: string; - value: string; - slots: Record; -} | null; + name: string + value: string + slots: Record +} | null export interface ComponentBlockOutput { - type: "component"; - id: number; + type: 'component' + id: number /** * `_.` + componentType,组件被调用的时候的名字 */ - func: string; + func: string /** * 显示的名称,感觉编译的时候用不到 */ - name: string; + name: string /** * Model构造器 * e.g. `DialogModel` */ - model: string | null; + model: string | null /** * 事件回调,生成成函数后作为属性传入 */ - callbacks: ComponentBlockCallbacks; + callbacks: ComponentBlockCallbacks /** * 属性,直接作为属性传入 */ - props: ComponentBlockProps; + props: ComponentBlockProps /** * 插件,键为插件名,值直接作为代码输出 */ - plugins: ComponentBlockPlugins; + plugins: ComponentBlockPlugins /** * 子元素的block的id */ - children: ComponentBlockChildren; + children: ComponentBlockChildren /** * Primary input的信息 */ - primaryInput: ComponentBlockPrimaryInput; + primaryInput: ComponentBlockPrimaryInput } diff --git a/packages/compiler/src/types/index.ts b/packages/compiler/src/types/index.ts index 9baa4ad..ba3b040 100644 --- a/packages/compiler/src/types/index.ts +++ b/packages/compiler/src/types/index.ts @@ -1,16 +1,16 @@ -import { ComponentBlockOutput } from "./componentBlock"; -import { SpecialBlockOutput } from "./specialBlock"; +import type { ComponentBlockOutput } from './componentBlock' +import type { SpecialBlockOutput } from './specialBlock' -export * from "./base"; -export * from "./componentBlock"; -export * from "./specialBlock"; +export * from './base' +export * from './componentBlock' +export * from './specialBlock' export interface ViewOutput { - name: string; - componentBlocks: ComponentBlockOutput[]; - specialBlocks: SpecialBlockOutput[]; + name: string + componentBlocks: ComponentBlockOutput[] + specialBlocks: SpecialBlockOutput[] } export interface QuasiOutput { - views: ViewOutput[]; + views: ViewOutput[] } diff --git a/packages/compiler/src/types/specialBlock.ts b/packages/compiler/src/types/specialBlock.ts index f6a7635..7d93678 100644 --- a/packages/compiler/src/types/specialBlock.ts +++ b/packages/compiler/src/types/specialBlock.ts @@ -1,74 +1,74 @@ -import { ConnectTo } from "./base"; +import type { ConnectTo } from './base' export interface RootBlockOutput { - type: "root"; - id: number; + type: 'root' + id: number /** * block id of children */ - children: number[]; + children: number[] } export interface IfBlockOutput { - type: "if"; - id: number; - condition: ConnectTo; - when: ConnectTo[]; - then: ConnectTo; - else: ConnectTo; + type: 'if' + id: number + condition: ConnectTo + when: ConnectTo[] + then: ConnectTo + else: ConnectTo } export interface ViewBlockOutput { - type: "view"; - id: number; - viewName: string; - parent: ConnectTo; + type: 'view' + id: number + viewName: string + parent: ConnectTo } -export interface ImpBlockOutput extends Omit { - type: "imp"; - when: ConnectTo[]; - then: ConnectTo; +export interface ImpBlockOutput extends Omit { + type: 'imp' + when: ConnectTo[] + then: ConnectTo } export type FuncBlockTypes = - | "expr" - | "imp" - | "string" - | "validator" - | "state" - | "state-setter"; + | 'expr' + | 'imp' + | 'string' + | 'validator' + | 'state' + | 'state-setter' export interface FuncBlockOutput { - type: Exclude; - id: number; - value: string; - slots: Record; - output: ConnectTo[]; + type: Exclude + id: number + value: string + slots: Record + output: ConnectTo[] } export interface ValidatorBlockOutput { - type: "validator"; - id: number; - expr: string; + type: 'validator' + id: number + expr: string } -export interface StateBlockOutput extends Omit { - type: "state"; - setters: number[]; +export interface StateBlockOutput extends Omit { + type: 'state' + setters: number[] } -export interface StateSetterBlockOutput extends Omit { - type: "state-setter"; - onset: ConnectTo[]; - state: number; +export interface StateSetterBlockOutput extends Omit { + type: 'state-setter' + onset: ConnectTo[] + state: number } export interface DoBlockOutput { - type: "do"; - id: number; - when: ConnectTo[]; - then: ConnectTo[]; + type: 'do' + id: number + when: ConnectTo[] + then: ConnectTo[] } export type SpecialBlockOutput = @@ -80,4 +80,4 @@ export type SpecialBlockOutput = | ViewBlockOutput | StateBlockOutput | StateSetterBlockOutput - | DoBlockOutput; + | DoBlockOutput diff --git a/packages/compiler/src/viewCompiler.ts b/packages/compiler/src/viewCompiler.ts index bdd4487..2c716dd 100644 --- a/packages/compiler/src/viewCompiler.ts +++ b/packages/compiler/src/viewCompiler.ts @@ -1,5 +1,5 @@ -import { Compiler } from "./compiler"; -import { +import type { Compiler } from './compiler' +import type { ComponentBlockCallbacks, ComponentBlockChildren, ComponentBlockOutput, @@ -14,8 +14,8 @@ import { StateSetterBlockOutput, ViewBlockOutput, ViewOutput, -} from "./types"; -import { ConnectTo } from "./types/base"; +} from './types' +import type { ConnectTo } from './types/base' export class ViewCompiler { constructor( @@ -23,67 +23,65 @@ export class ViewCompiler { public view: ViewOutput, ) {} - dataLines: {}[] = []; - getViewRoot() { - const first = this.view.specialBlocks.findIndex((b) => b.type === "root"); - if (first === -1) { - throw new Error("No root block found"); - } - const last = this.view.specialBlocks.findIndex((b) => b.type === "root"); - if (first !== last) { - throw new Error("Cannot have multiple root blocks in one view"); - } - return this.view.specialBlocks[first] as RootBlockOutput; + const first = this.view.specialBlocks.findIndex(b => b.type === 'root') + if (first === -1) + throw new Error('No root block found') + + const last = this.view.specialBlocks.findIndex(b => b.type === 'root') + if (first !== last) + throw new Error('Cannot have multiple root blocks in one view') + + return this.view.specialBlocks[first] as RootBlockOutput } getComponentOrViewBlockById(id: number) { return ( - this.view.componentBlocks.find((b) => b.id === id) ?? - (this.view.specialBlocks.find((b) => b.id === id) as ViewBlockOutput) - ); + this.view.componentBlocks.find(b => b.id === id) + ?? (this.view.specialBlocks.find(b => b.id === id) as ViewBlockOutput) + ) } getBlockById(id: number) { - const block = - this.view.componentBlocks.find((b) => b.id === id) ?? - this.view.specialBlocks.find((b) => b.id === id); - if (!block) { - throw new Error(`Block ${id} not found`); - } - return block; + const block + = this.view.componentBlocks.find(b => b.id === id) + ?? this.view.specialBlocks.find(b => b.id === id) + if (!block) + throw new Error(`Block ${id} not found`) + + return block } compile() { - const root = this.getViewRoot(); + const root = this.getViewRoot() const mainFunc = root.children - .map((c) => + .map(c => this.compileComponentOrViewBlock(this.getComponentOrViewBlockById(c)), ) - .join("\n"); + .join('\n') const stateInitExprsDef = [...this.stateInitExprs.entries()] .map(([k, v]) => { - return `let ${k} = ${v};`; + return `let ${k} = ${v};` }) - .join("\n"); + .join('\n') - const stateInputsDef = this.stateUpdators.join("\n"); + const stateInputsDef = this.stateUpdators.join('\n') const modelsDef = [...this.modelAllocators.entries()] .map(([k, v]) => { - return `const ${k} = new $quasi.${v}();`; + return `const ${k} = new $quasi.${v}();` }) - .join("\n"); + .join('\n') - const linesDef = this.lineDefs.join("\n"); + const linesDef = this.lineDefs.join('\n') const impsDef = [...this.impDefs.entries()] .map(([k, v]) => { - return `const ${k} = ${v};`; + return `const ${k} = ${v};` }) - .join("\n"); + .join('\n') return ` ${stateInitExprsDef} @@ -97,103 +95,104 @@ ${linesDef} ${impsDef} const ${this.view.name}_view = ${ - this.view.name === "app" ? "$app({plugins:[QuasiRuntime]}," : "$view(" + this.view.name === 'app' ? '$app({plugins:[QuasiRuntime]},' : '$view(' }_ => { ${mainFunc} }); -`; +` } compileStringBlock( block: FuncBlockOutput | Exclude, ): string { return `\`${block.value.replace(/\{([a-zA-Z0-9]+)\}/g, (_, name) => { - const slot = Object.entries(block.slots).find(([k]) => k === name); - if (!slot) { - throw new Error(`Cannot find input ${name}`); - } - return `\${${this.compileDataLineEnd(slot[1])}}`; - })}\``; + const slot = Object.entries(block.slots).find(([k]) => k === name) + if (!slot) + throw new Error(`Cannot find input ${name}`) + + return `\${${this.compileDataLineEnd(slot[1])}}` + })}\`` } compileExprBlock( block: FuncBlockOutput | StateBlockOutput | StateSetterBlockOutput, ): string { return block.value.replace(/\$([a-zA-Z0-9]+)/g, (_, name) => { - const slot = Object.entries(block.slots).find(([k]) => k === name); - if (!slot) { - throw new Error(`Cannot find input ${name} in block ${block.id}`); - } - return `(${this.compileDataLineEnd(slot[1])})`; - }); + const slot = Object.entries(block.slots).find(([k]) => k === name) + if (!slot) + throw new Error(`Cannot find input ${name} in block ${block.id}`) + + return `(${this.compileDataLineEnd(slot[1])})` + }) } - lineDefs: string[] = []; - currentLineId = 0; + lineDefs: string[] = [] + currentLineId = 0 compileDataLineEnd({ blockId, socketName }: ConnectTo): string { - if (Number.isNaN(blockId)) return "null"; + if (Number.isNaN(blockId)) + return 'null' - const lineId = `${this.view.name}_line${this.currentLineId++}`; + const lineId = `${this.view.name}_line${this.currentLineId++}` - const block = this.getBlockById(blockId); + const block = this.getBlockById(blockId) switch (block.type) { - case "string": - if (socketName !== "output") { + case 'string': + if (socketName !== 'output') { throw new Error( `Cannot find socket ${socketName} in block ${blockId}`, - ); + ) } this.lineDefs.push( `const ${lineId} = () => ${this.compileStringBlock(block)};`, - ); - break; - case "root": - throw new Error("Not implemented"); - case "component": - if (!block.model) { - throw new Error("This component block has no data output"); - } + ) + break + case 'root': + throw new Error('Not implemented') + case 'component': + if (!block.model) + throw new Error('This component block has no data output') + this.lineDefs.push( `const ${lineId} = () => ${this.compileModel( blockId, block.model, )}["${socketName}"];`, - ); - break; - case "expr": - if (socketName !== "value") { + ) + break + case 'expr': + if (socketName !== 'value') { throw new Error( `Cannot find socket ${socketName} in block ${blockId}`, - ); + ) } this.lineDefs.push( `const ${lineId} = () => (${this.compileExprBlock(block)});`, - ); - break; - case "imp": - throw new Error("Not implemented"); - case "if": - throw new Error("If-else block has no data output"); - case "view": - throw new Error("view block has no data output"); - case "state": - if (socketName !== "current") { + ) + break + case 'imp': + throw new Error('Not implemented') + case 'if': + throw new Error('If-else block has no data output') + case 'view': + throw new Error('view block has no data output') + case 'state': + if (socketName !== 'current') { throw new Error( `Cannot find socket ${socketName} in block ${blockId}`, - ); + ) } this.lineDefs.push( `const ${lineId} = () => ${this.compileStateBlock( block as StateBlockOutput, )};`, - ); - break; - case "state-setter": - throw new Error("State setter block has no data output"); - case "do": - throw new Error("State setter block has no data output"); + ) + break + case 'state-setter': + throw new Error('State setter block has no data output') + case 'do': + throw new Error('State setter block has no data output') } - return `${lineId}()`; + return `${lineId}()` } compileImpBlock(block: ImpBlockOutput): string { @@ -201,16 +200,16 @@ const ${this.view.name}_view = ${ const result = (() => {${block.value.replace( /\$([a-zA-Z0-9]+)/g, (_, name) => { - const slot = Object.entries(block.slots).find(([k]) => k === name); - if (!slot) { - throw new Error(`Cannot find input ${name} in block ${block.id}`); - } - return `(${this.compileDataLineEnd(slot[1])})`; + const slot = Object.entries(block.slots).find(([k]) => k === name) + if (!slot) + throw new Error(`Cannot find input ${name} in block ${block.id}`) + + return `(${this.compileDataLineEnd(slot[1])})` }, )}})(); ${this.compileEventLineStart(block.then)}; return result; - }`; + }` } compileIfElseBlock(block: IfBlockOutput): string { @@ -218,17 +217,18 @@ const ${this.view.name}_view = ${ ${this.compileEventLineStart(block.then)} } else { ${this.compileEventLineStart(block.else)} - }`; + }` } - stateIdMap = new Map(); - stateInitExprs = new Map(); - stateUpdators: string[] = []; + stateIdMap = new Map() + stateInitExprs = new Map() + stateUpdators: string[] = [] compileStateBlock(block: StateBlockOutput): string { - if (this.stateIdMap.has(block.id)) return this.stateIdMap.get(block.id)!; - const stateId = `${this.view.name}_state${this.stateIdMap.size}`; - this.stateIdMap.set(block.id, stateId); - this.stateInitExprs.set(stateId, this.compileExprBlock(block)); + if (this.stateIdMap.has(block.id)) + return this.stateIdMap.get(block.id)! + const stateId = `${this.view.name}_state${this.stateIdMap.size}` + this.stateIdMap.set(block.id, stateId) + this.stateInitExprs.set(stateId, this.compileExprBlock(block)) for (const setterId of block.setters) { this.stateUpdators.push( `const ${stateId}_update_${setterId} = () => { @@ -236,122 +236,123 @@ const ${this.view.name}_view = ${ ${stateId} = ${this.compileExprBlock( this.getBlockById(setterId) as StateSetterBlockOutput, )}; };`, - ); + ) } - return stateId; + return stateId } - impIdMap = new Map(); - impDefs = new Map(); + impIdMap = new Map() + impDefs = new Map() compileEventLineStart({ blockId, socketName }: ConnectTo): string { - if (Number.isNaN(blockId)) return ""; + if (Number.isNaN(blockId)) + return '' - const serializedInfo = `${blockId}|${socketName}`; + const serializedInfo = `${blockId}|${socketName}` if (!this.impIdMap.has(serializedInfo)) { this.impIdMap.set( serializedInfo, `${this.view.name}_imp${this.impIdMap.size}`, - ); + ) } - const impId = this.impIdMap.get(serializedInfo)!; - const block = this.getBlockById(blockId); + const impId = this.impIdMap.get(serializedInfo)! + const block = this.getBlockById(blockId) switch (block.type) { - case "string": - throw new Error("String block is not callable"); - case "root": - throw new Error("Root block is not callable"); - case "component": + case 'string': + throw new Error('String block is not callable') + case 'root': + throw new Error('Root block is not callable') + case 'component': if (!block.model) - throw new Error("This component block has no event input"); + throw new Error('This component block has no event input') this.impDefs.set( impId, `() => ${this.compileModel(blockId, block.model)}["${socketName}"]()`, - ); - break; - case "expr": - throw new Error("Expr block is not callable"); - case "imp": - if (socketName !== "when") { + ) + break + case 'expr': + throw new Error('Expr block is not callable') + case 'imp': + if (socketName !== 'when') { throw new Error( `Cannot find socket ${socketName} in block ${blockId}`, - ); + ) } - this.impDefs.set(impId, this.compileImpBlock(block as ImpBlockOutput)); - break; - case "if": - if (socketName !== "when") { + this.impDefs.set(impId, this.compileImpBlock(block as ImpBlockOutput)) + break + case 'if': + if (socketName !== 'when') { throw new Error( `Cannot find socket ${socketName} in block ${blockId}`, - ); + ) } - this.impDefs.set(impId, `() => {${this.compileIfElseBlock(block)}}`); - break; - case "view": - throw new Error("Expr block is not callable"); - case "state": - throw new Error("State block is not callable"); - case "state-setter": - if (socketName !== "set") { + this.impDefs.set(impId, `() => {${this.compileIfElseBlock(block)}}`) + break + case 'view': + throw new Error('Expr block is not callable') + case 'state': + throw new Error('State block is not callable') + case 'state-setter': + if (socketName !== 'set') { throw new Error( `Cannot find socket ${socketName} in block ${blockId}`, - ); + ) } this.impDefs.set( impId, `${this.compileStateBlock( this.getBlockById(block.state) as StateBlockOutput, )}_update_${blockId}`, - ); - break; - case "do": - if (socketName !== "when") { + ) + break + case 'do': + if (socketName !== 'when') { throw new Error( `Cannot find socket ${socketName} in block ${blockId}`, - ); + ) } this.impDefs.set( impId, `() => {${block.then - .map((v) => this.compileEventLineStart(v)) - .join(";\n")}}`, - ); - break; + .map(v => this.compileEventLineStart(v)) + .join(';\n')}}`, + ) + break } - return `${impId}()`; + return `${impId}()` } - blockModelMap = new Map(); - modelAllocators = new Map(); + blockModelMap = new Map() + modelAllocators = new Map() compileModel(blockId: number, allocator: string): string { if (this.blockModelMap.has(blockId)) - return this.blockModelMap.get(blockId)!; - const modelId = `${this.view.name}_model${this.modelAllocators.size}`; - this.blockModelMap.set(blockId, modelId); - this.modelAllocators.set(modelId, allocator); - return modelId; + return this.blockModelMap.get(blockId)! + const modelId = `${this.view.name}_model${this.modelAllocators.size}` + this.blockModelMap.set(blockId, modelId) + this.modelAllocators.set(modelId, allocator) + return modelId } compileComponentPrimaryInput( primaryInput: ComponentBlockPrimaryInput, ): Record { - if (!primaryInput) return {}; - return { [primaryInput.name]: this.compileStringBlock(primaryInput) }; + if (!primaryInput) + return {} + return { [primaryInput.name]: this.compileStringBlock(primaryInput) } } compileComponentProps(props: ComponentBlockProps): Record { return Object.fromEntries( Object.entries(props).map(([k, v]) => { - if (typeof v === "string") { - return [k, `"${v}"`]; - } else if (typeof v === "number") { - return [k, `${v}`]; - } else if (typeof v === "boolean") { - return [k, v ? "true" : "false"]; - } else { - return [k, this.compileDataLineEnd(v)]; - } + if (typeof v === 'string') + return [k, `"${v}"`] + else if (typeof v === 'number') + return [k, `${v}`] + else if (typeof v === 'boolean') + return [k, v ? 'true' : 'false'] + else + return [k, this.compileDataLineEnd(v)] }), - ); + ) } compileComponentCallbacks( @@ -362,43 +363,47 @@ const ${this.view.name}_view = ${ k, `()=>{${this.compileEventLineStart(v)}}`, ]), - ); + ) } + compileComponentPlugins( plugins: ComponentBlockPlugins, ): Record { - return plugins; + return plugins } + compileComponentChildren(children: ComponentBlockChildren) { return Object.fromEntries( Object.entries(children).map(([k, v]) => { - if (typeof v === "string") { - return [k, `"${v}"`]; - } else { + if (typeof v === 'string') { + return [k, `"${v}"`] + } + else { return [ k, `_ => { ${v - .map((c) => + .map(c => this.compileComponentOrViewBlock( this.getComponentOrViewBlockById(c), ), ) - .join("\n")} + .join('\n')} }`, - ]; + ] } }), - ); + ) } compileComponentOrViewBlock( block: ComponentBlockOutput | ViewBlockOutput, ): string { - if (block.type === "view") return `_.embed(${block.viewName}_view);`; + if (block.type === 'view') + return `_.embed(${block.viewName}_view);` return `_.${block.func}( - ${block.model ? `${this.compileModel(block.id, block.model)},\n` : ""}{ + ${block.model ? `${this.compileModel(block.id, block.model)},\n` : ''}{ ${Object.entries({ ...this.compileComponentPrimaryInput(block.primaryInput), ...this.compileComponentProps(block.props), @@ -407,7 +412,7 @@ const ${this.view.name}_view = ${ ...this.compileComponentChildren(block.children), }) .map(([k, v]) => `"${k}":${v}`) - .join(",\n")} - });`; + .join(',\n')} + });` } } diff --git a/packages/compiler/tsconfig.json b/packages/compiler/tsconfig.json index 2e5b947..f14bf3e 100644 --- a/packages/compiler/tsconfig.json +++ b/packages/compiler/tsconfig.json @@ -1,10 +1,10 @@ { - "include": ["src"], "compilerOptions": { "target": "ESNext", + "lib": ["ESNext"], "module": "ESNext", "moduleResolution": "Bundler", - "lib": ["ESNext"], "strict": true - } + }, + "include": ["src"] } diff --git a/packages/mdui2-dts/entrypoint.d.ts b/packages/mdui2-dts/entrypoint.d.ts index 37be71d..806b884 100644 --- a/packages/mdui2-dts/entrypoint.d.ts +++ b/packages/mdui2-dts/entrypoint.d.ts @@ -1,5 +1,5 @@ -export * from "mdui/functions/alert"; -export * from "mdui/functions/confirm"; -export * from "mdui/functions/dialog"; -export * from "mdui/functions/prompt"; -export * from "mdui/functions/snackbar"; +export * from 'mdui/functions/alert' +export * from 'mdui/functions/confirm' +export * from 'mdui/functions/dialog' +export * from 'mdui/functions/prompt' +export * from 'mdui/functions/snackbar' diff --git a/packages/mdui2-dts/index.ts b/packages/mdui2-dts/index.ts index 7d5d327..3bf4ccb 100644 --- a/packages/mdui2-dts/index.ts +++ b/packages/mdui2-dts/index.ts @@ -1,9 +1,10 @@ /// -import raw from "./dist/mdui2-dts.d.ts?raw"; +// eslint-disable-next-line antfu/no-import-dist +import raw from './dist/mdui2-dts.d.ts?raw' const dts = raw - .replace('/// ', "") - .replaceAll(/\bexport\b/g, "") - .replace("export { }", ""); + .replace('/// ', '') + .replaceAll(/\bexport\b/g, '') + .replace('export { }', '') -export default dts; +export default dts diff --git a/packages/mdui2-dts/package.json b/packages/mdui2-dts/package.json index b0f340d..7ce329e 100644 --- a/packages/mdui2-dts/package.json +++ b/packages/mdui2-dts/package.json @@ -1,19 +1,19 @@ { "name": "@quasi-dev/mdui2-dts", - "version": "0.0.1", "type": "module", - "license": "MIT", + "version": "0.0.1", "description": "Bundle MdUI2 to a single d.ts file", + "license": "MIT", "repository": "https://github.com/Quasi-Studio/quasi", - "scripts": { - "build": "api-extractor run --local --verbose" + "exports": { + ".": "./index.ts" }, "files": [ - "index.d.ts", - "dist" + "dist", + "index.d.ts" ], - "exports": { - ".": "./index.ts" + "scripts": { + "build": "api-extractor run --local --verbose" }, "devDependencies": { "@microsoft/api-extractor": "^7.38.3", diff --git a/packages/mdui2-dts/tsconfig.json b/packages/mdui2-dts/tsconfig.json index 91d74a6..8f8b60d 100644 --- a/packages/mdui2-dts/tsconfig.json +++ b/packages/mdui2-dts/tsconfig.json @@ -1,13 +1,13 @@ { - "include": ["entrypoint.d.ts", "index.ts"], "compilerOptions": { "target": "ESNext", + "lib": ["ESNext", "DOM"], "module": "ESNext", - "declaration": true, "moduleResolution": "Bundler", "types": [], - "lib": ["ESNext", "DOM"], - "outDir": "dist", - "allowJs": true - } + "allowJs": true, + "declaration": true, + "outDir": "dist" + }, + "include": ["entrypoint.d.ts", "index.ts"] } diff --git a/packages/monaco-editor/package.json b/packages/monaco-editor/package.json index 49fec8b..951891a 100644 --- a/packages/monaco-editor/package.json +++ b/packages/monaco-editor/package.json @@ -1,27 +1,27 @@ { "name": "@quasi-dev/monaco-editor", - "version": "0.0.1", "type": "module", - "license": "MIT", + "version": "0.0.1", "description": "Monaco Editor for Quasi", + "license": "MIT", "repository": "https://github.com/Quasi-Studio/quasi", - "scripts": { - "check": "tsc --noEmit" - }, - "devDependencies": { - "@refina/tsconfig": "^0.6.0", - "typescript": "^5.4.2" + "exports": { + ".": "./src/index.ts" }, "main": "./src/index.ts", "types": "./src/index.ts", "files": [ "src" ], - "exports": { - ".": "./src/index.ts" + "scripts": { + "check": "tsc --noEmit" }, "dependencies": { "monaco-editor": "^0.44.0", "refina": "^0.6.1" + }, + "devDependencies": { + "@refina/tsconfig": "^0.6.0", + "typescript": "^5.4.2" } } diff --git a/packages/monaco-editor/src/component.r.ts b/packages/monaco-editor/src/component.r.ts index 28d5fba..32bed2f 100644 --- a/packages/monaco-editor/src/component.r.ts +++ b/packages/monaco-editor/src/component.r.ts @@ -1,60 +1,62 @@ -import * as monaco from "monaco-editor"; -import { HTMLElementComponent, TriggerComponent, _, ref } from "refina"; +import * as monaco from 'monaco-editor' +import type { HTMLElementComponent } from 'refina' +import { TriggerComponent, _, ref } from 'refina' export class MonacoEditor extends TriggerComponent { - containerRef = ref>(); - editor: monaco.editor.IStandaloneCodeEditor | null = null; + containerRef = ref>() + editor: monaco.editor.IStandaloneCodeEditor | null = null $main( initialValue: string, language: string, options?: Omit< monaco.editor.IStandaloneEditorConstructionOptions, - "value" | "language" + 'value' | 'language' >, ): this is { - $ev: string; + $ev: string } { - _.$css`height:100%`; - _.$ref(this.containerRef) && _._div(); + _.$css`height:100%` + _.$ref(this.containerRef) && _._div() if (_.$updateContext) { - _.$app.pushOnetimeHook("afterModifyDOM", () => { + _.$app.pushOnetimeHook('afterModifyDOM', () => { setTimeout(() => { if (!this.editor) { - const node = this.containerRef.current!.node; + const node = this.containerRef.current!.node this.editor = monaco.editor.create(node, { ...options, value: initialValue, language, - }); + }) - this.editor.getModel()?.onDidChangeContent(ev => { - const newValue = this.editor!.getValue(); - this.$fire(newValue); - }); + this.editor.getModel()?.onDidChangeContent(() => { + const newValue = this.editor!.getValue() + this.$fire(newValue) + }) - const parent = node.parentElement!; + const parent = node.parentElement! - if (_.$updateContext) - window.addEventListener("resize", () => { - // make editor as small as possible - this.editor!.layout({ width: 0, height: 0 }); + if (_.$updateContext) { + window.addEventListener('resize', () => { + // make editor as small as possible + this.editor!.layout({ width: 0, height: 0 }) // wait for next frame to ensure last layout finished window.requestAnimationFrame(() => { - // get the parent dimensions and re-layout the editor - const rect = parent.getBoundingClientRect(); + // get the parent dimensions and re-layout the editor + const rect = parent.getBoundingClientRect() this.editor!.layout({ width: rect.width, height: rect.height, - }); - }); - }); + }) + }) + }) + } } - }); - }); + }) + }) } - return this.$fired; + return this.$fired } } diff --git a/packages/monaco-editor/src/index.ts b/packages/monaco-editor/src/index.ts index 8646b09..49fe01f 100644 --- a/packages/monaco-editor/src/index.ts +++ b/packages/monaco-editor/src/index.ts @@ -1,13 +1,13 @@ -import * as monaco from "monaco-editor"; -import { Plugin } from "refina"; -import { MonacoEditor } from "./component.r"; +import * as monaco from 'monaco-editor' +import type { Plugin } from 'refina' +import { MonacoEditor } from './component.r' export default { - name: "monaco-editor", + name: 'monaco-editor', components: { monacoEditor: MonacoEditor, }, -} satisfies Plugin; +} satisfies Plugin -export * from "./component.r"; -export { monaco }; +export * from './component.r' +export { monaco } diff --git a/packages/monaco-editor/tsconfig.json b/packages/monaco-editor/tsconfig.json index 55a854a..610bec2 100644 --- a/packages/monaco-editor/tsconfig.json +++ b/packages/monaco-editor/tsconfig.json @@ -1,7 +1,7 @@ { "extends": "@refina/tsconfig", - "include": ["src"], "compilerOptions": { "lib": ["ESNext", "DOM"] - } + }, + "include": ["src"] } diff --git a/packages/northstar/package.json b/packages/northstar/package.json index 2127a2b..209b95d 100644 --- a/packages/northstar/package.json +++ b/packages/northstar/package.json @@ -1,29 +1,15 @@ { "name": "@quasi-dev/northstar", - "version": "0.0.0", "type": "module", + "version": "0.0.0", "private": true, + "packageManager": "pnpm@8.10.2", "scripts": { "dev": "vite --open", "build": "vite build", "preview": "vite preview", "check": "tsc --noEmit" }, - "packageManager": "pnpm@8.10.2", - "devDependencies": { - "@refina/transformer": "^0.6.0", - "@refina/tsconfig": "^0.6.0", - "@types/wicg-file-system-access": "^2023.10.5", - "autoprefixer": "^10.4.18", - "postcss": "^8.4.35", - "tailwindcss": "^3.4.1", - "typescript": "^5.4.2", - "vite": "^4.5.2", - "vite-plugin-inspect": "^0.8.3", - "vite-plugin-monaco-editor": "^1.1.0", - "vite-plugin-refina": "^0.6.0", - "vite-plugin-static-copy": "^0.17.1" - }, "dependencies": { "@quasi-dev/browser-tailwind": "workspace:^", "@quasi-dev/compiler": "workspace:^", @@ -38,5 +24,19 @@ "modern-screenshot": "^4.4.38", "prettier": "3.0.0", "refina": "^0.6.1" + }, + "devDependencies": { + "@refina/transformer": "^0.6.0", + "@refina/tsconfig": "^0.6.0", + "@types/wicg-file-system-access": "^2023.10.5", + "autoprefixer": "^10.4.18", + "postcss": "^8.4.35", + "tailwindcss": "^3.4.1", + "typescript": "^5.4.2", + "vite": "^4.5.2", + "vite-plugin-inspect": "^0.8.3", + "vite-plugin-monaco-editor": "^1.1.0", + "vite-plugin-refina": "^0.6.0", + "vite-plugin-static-copy": "^0.17.1" } } diff --git a/packages/northstar/postcss.config.js b/packages/northstar/postcss.config.js index 2aa7205..2e7af2b 100644 --- a/packages/northstar/postcss.config.js +++ b/packages/northstar/postcss.config.js @@ -3,4 +3,4 @@ export default { tailwindcss: {}, autoprefixer: {}, }, -}; +} diff --git a/packages/northstar/src/app.r.ts b/packages/northstar/src/app.r.ts index 3b3a433..02fa3aa 100644 --- a/packages/northstar/src/app.r.ts +++ b/packages/northstar/src/app.r.ts @@ -1,38 +1,38 @@ -import Monaco from "@quasi-dev/monaco-editor"; -import Vf from "@quasi-dev/visual-flow"; -import Basics from "@refina/basic-components"; -import FluentUI from "@refina/fluentui"; -import { $app } from "refina"; +import Monaco from '@quasi-dev/monaco-editor' +import Vf from '@quasi-dev/visual-flow' +import Basics from '@refina/basic-components' +import FluentUI from '@refina/fluentui' +import { $app } from 'refina' import { currentProject, loadAutoSaved, saveAs, setAutoSaveInterval, -} from "./project"; +} from './project' import { duplicateBlocks, hasBlocksToDuplicate, hasBlocksToRemove, initMonaco, removeBlocks, -} from "./utils"; -import blocksView from "./views/blocks.r"; -import previewView from "./views/preview.r"; -import propertiesView from "./views/properties.r"; -import toolbarView, { graphElRef, previewMode } from "./views/toolbar.r"; +} from './utils' +import blocksView from './views/blocks.r' +import previewView from './views/preview.r' +import propertiesView from './views/properties.r' +import toolbarView, { graphElRef, previewMode } from './views/toolbar.r' -document.body.spellcheck = false; +document.body.spellcheck = false -loadAutoSaved(); -setAutoSaveInterval(); -initMonaco(); +loadAutoSaved() +setAutoSaveInterval() +initMonaco() -declare module "refina" { +declare module 'refina' { interface Plugins { - VisualFlow: typeof Vf; - Basics: typeof Basics; - FluentUI: ReturnType; - Monaco: typeof Monaco; + VisualFlow: typeof Vf + Basics: typeof Basics + FluentUI: ReturnType + Monaco: typeof Monaco } } @@ -41,91 +41,96 @@ export const app = $app( plugins: [FluentUI(), Vf, Basics, Monaco], }, _ => { - if (_.$updateContext) { - _.$root.addCls(`fixed top-0 left-0 right-0 bottom-0`); - } + if (_.$updateContext) + _.$root.addCls(`fixed top-0 left-0 right-0 bottom-0`) - _.documentTitle("Quasi Studio"); + _.documentTitle('Quasi Studio') // toolbar - _.$cls`absolute left-0 top-0 w-full h-8 bg-gray-100 flex select-none z-[1000] border-gray-400 border-b`; - _.div(toolbarView); + _.$cls`absolute left-0 top-0 w-full h-8 bg-gray-100 flex select-none z-[1000] border-gray-400 border-b` + _.div(toolbarView) if (previewMode.value) { _.$cls`absolute left-0 bottom-0 right-0 top-8 ${ - previewMode.value ? "" : "hidden" - }`; - _.div(previewView); + previewMode.value ? '' : 'hidden' + }` + _.div(previewView) } - if (!previewMode.value) + if (!previewMode.value) { _.div(_ => { - const hasSelectedBlock = - currentProject.activeGraph.selectedBlocks.size > 0; + const hasSelectedBlock + = currentProject.activeGraph.selectedBlocks.size > 0 _.$cls`absolute left-0 top-8 w-80 bottom-0 - bg-gray-200 select-none z-[1000] border-r border-gray-400 flex flex-col`; + bg-gray-200 select-none z-[1000] border-r border-gray-400 flex flex-col` _.div(_ => { - _.$cls`flex items-center w-full bg-gray-300 pl-2 leading-7 font-bold`; - _.div("BLOCKS"); + _.$cls`flex items-center w-full bg-gray-300 pl-2 leading-7 font-bold` + _.div('BLOCKS') - _.$cls`overflow-y-scroll flex-grow w-full pb-16`; - _.div(blocksView); + _.$cls`overflow-y-scroll flex-grow w-full pb-16` + _.div(blocksView) if (hasSelectedBlock) { - // _.$cls`absolute left-0 bottom-0 w-80 h-2/5 border-t-4 border-gray-400 border-r border-gray-400 z-[1000]`; - // _.div(_ => { - _.$cls`flex items-center w-full bg-gray-300 pl-2 leading-7`; + // _.$cls`absolute left-0 bottom-0 w-80 h-2/5 border-t-4 border-gray-400 border-r border-gray-400 z-[1000]`; + // _.div(_ => { + _.$cls`flex items-center w-full bg-gray-300 pl-2 leading-7` _.div(_ => { - _.$cls`font-bold`; - _.span("PROPERTIES"); - - // _.$cls`text-xs pl-3`; - // _.span( - // [...currentProject.activeGraph.selectedBlocks] - // .filter(isComponentBlock) - // .map(b => b.info.name) - // .join(" "), - // ); - }); - - _.$cls`overflow-y-scroll h-min min-h-[60px] bg-gray-200 grid grid-cols-3 pb-8`; - _.div(propertiesView); - // }); + _.$cls`font-bold` + _.span('PROPERTIES') + + // _.$cls`text-xs pl-3`; + // _.span( + // [...currentProject.activeGraph.selectedBlocks] + // .filter(isComponentBlock) + // .map(b => b.info.name) + // .join(" "), + // ); + }) + + _.$cls`overflow-y-scroll h-min min-h-[60px] bg-gray-200 grid grid-cols-3 pb-8` + _.div(propertiesView) + // }); } - }); + }) - _.$cls`absolute left-80 top-8 right-0 bottom-0`; - _.$ref(graphElRef) && - _._div({}, _ => _.vfGraph(currentProject.activeGraph)); + _.$cls`absolute left-80 top-8 right-0 bottom-0` + _.$ref(graphElRef) + && _._div({}, _ => _.vfGraph(currentProject.activeGraph)) - if (_.$updateContext) - _.$window.addEventListener("keydown", (ev: KeyboardEvent) => { + if (_.$updateContext) { + _.$window.addEventListener('keydown', (ev: KeyboardEvent) => { if (ev.ctrlKey) { - if (ev.key === "z" && currentProject.activeGraph.canUndo) { - currentProject.activeGraph.undo(); - app.update(); - } else if (ev.key === "y" && currentProject.activeGraph.canRedo) { - currentProject.activeGraph.redo(); - app.update(); - } else if (ev.key === "s") { - saveAs(); - } else if (ev.key === "d" && hasBlocksToDuplicate()) { - duplicateBlocks(); - app.update(); + if (ev.key === 'z' && currentProject.activeGraph.canUndo) { + currentProject.activeGraph.undo() + app.update() + } + else if (ev.key === 'y' && currentProject.activeGraph.canRedo) { + currentProject.activeGraph.redo() + app.update() + } + else if (ev.key === 's') { + saveAs() } - ev.preventDefault(); - } else if (ev.key === "Delete") { + else if (ev.key === 'd' && hasBlocksToDuplicate()) { + duplicateBlocks() + app.update() + } + ev.preventDefault() + } + else if (ev.key === 'Delete') { if (hasBlocksToRemove()) { - removeBlocks(); - app.update(); + removeBlocks() + app.update() } - ev.preventDefault(); + ev.preventDefault() } - }); + }) + } // a workaround to update the position of the graph - setTimeout(() => currentProject.activeGraph.updatePosition()); - }); + setTimeout(() => currentProject.activeGraph.updatePosition()) + }) + } }, -); +) diff --git a/packages/northstar/src/blocks/component/block.ts b/packages/northstar/src/blocks/component/block.ts index b453069..d343a5c 100644 --- a/packages/northstar/src/blocks/component/block.ts +++ b/packages/northstar/src/blocks/component/block.ts @@ -1,4 +1,9 @@ -import { ComponentInfo, componentInfoObj } from "@quasi-dev/runtime"; +import type { ComponentInfo } from '@quasi-dev/runtime' +import { componentInfoObj } from '@quasi-dev/runtime' +import type { + Socket, + UseSocket, +} from '@quasi-dev/visual-flow' import { Direction, MultiInSocket, @@ -12,177 +17,181 @@ import { RectBlock, SingleInSocket, SingleOutSocket, - Socket, - UseSocket, blockCtors, -} from "@quasi-dev/visual-flow"; -import { model } from "refina"; -import { PropsData } from "../../utils/props"; -import { getContent } from "./getContent.r"; -import { getProps } from "./getProps"; -import { updatePlugins } from "./updatePlugins"; +} from '@quasi-dev/visual-flow' +import { model } from 'refina' +import type { PropsData } from '../../utils/props' +import { getContent } from './getContent.r' +import { getProps } from './getProps' +import { updatePlugins } from './updatePlugins' export class ComponentBlock extends RectBlock { - ctorName: string = "ComponentBlock"; + ctorName: string = 'ComponentBlock' cloneTo(target: this): this { - super.cloneTo(target); - target.setComponentType(this.componentType, this.info); - target.props = { ...this.props }; - target.primaryValue.value = this.primaryValue.value; - return target; + super.cloneTo(target) + target.setComponentType(this.componentType, this.info) + target.props = { ...this.props } + target.primaryValue.value = this.primaryValue.value + return target } setComponentType(componentType: string, info: ComponentInfo) { - this.componentType = componentType; - this.info = info; - this.boardWidth = info.blockWidth; - this.boardHeight = info.blockHeight; - this.content = getContent(this); - updatePlugins(this); + this.componentType = componentType + this.info = info + this.boardWidth = info.blockWidth + this.boardHeight = info.blockHeight + this.content = getContent(this) + updatePlugins(this) } - isComponentBlock = true; + isComponentBlock = true - removable = true; - duplicateable = true; + removable = true + duplicateable = true - componentType: string; - info: ComponentInfo; - props: Record = {}; + componentType: string + info: ComponentInfo + props: Record = {} get primaryInputInfo() { return [ ...Object.entries(this.info.inputs), ...Object.entries(this.info.contents), ].find( - ([_, v]) => v.mode === "as-primary" || v.mode === "as-primary-and-socket", - ); + ([_, v]) => v.mode === 'as-primary' || v.mode === 'as-primary-and-socket', + ) } - primaryValue = model(""); + primaryValue = model('') get primaryFilled() { - return this.primaryValue.value !== ""; + return this.primaryValue.value !== '' } - getPrimaryDisabled = () => false; - slotsDirection = Direction.TOP; + getPrimaryDisabled = () => false + + slotsDirection = Direction.TOP get slots() { - const template = this.primaryValue.value; - const matches = template.matchAll(/\{[a-zA-Z0-9_]+\}/g); - return [...matches].map((match) => match[0].slice(1, -1)); + const template = this.primaryValue.value + const matches = template.matchAll(/\{[a-zA-Z0-9_]+\}/g) + return [...matches].map(match => match[0].slice(1, -1)) } get slotSockets() { - return this.getSocketsByPrefix("slot") as SingleInSocket[]; + return this.getSocketsByPrefix('slot') as SingleInSocket[] } socketUpdater(useSocket: UseSocket): void { - const contents = Object.entries(this.info.contents); - const events = Object.entries(this.info.events); - const inputs = Object.entries(this.info.inputs); - const outputs = Object.entries(this.info.outputs); - const methods = Object.entries(this.info.methods); - - useSocket("parent", SingleInSocket, { - type: "L", + const contents = Object.entries(this.info.contents) + const events = Object.entries(this.info.events) + const inputs = Object.entries(this.info.inputs) + const outputs = Object.entries(this.info.outputs) + const methods = Object.entries(this.info.methods) + + useSocket('parent', SingleInSocket, { + type: 'L', path: PATH_IN_RECT, hideLabel: true, direction: Direction.LEFT, - }); + }) if (this.primaryInputInfo) { for (const slot of this.slots) { useSocket(`slot-${slot}`, SingleInSocket, { label: slot, - type: "D", + type: 'D', path: PATH_IN_ELIPSE, direction: this.slotsDirection, - }); + }) } } const shouldHideSocket = ( k: string, socketInfo: { - mode: string; - displayName: string; + mode: string + displayName: string }, ) => { - const prop = this.props[`[${k}]`]; + const prop = this.props[`[${k}]`] return ( - (socketInfo.mode === "as-hidden-socket" && prop !== true) || - (socketInfo.mode === "as-hidable-socket" && prop === false) || - (socketInfo.mode === "as-primary-and-socket" && this.primaryFilled) - ); - }; + (socketInfo.mode === 'as-hidden-socket' && prop !== true) + || (socketInfo.mode === 'as-hidable-socket' && prop === false) + || (socketInfo.mode === 'as-primary-and-socket' && this.primaryFilled) + ) + } for (const [k, v] of contents) { - if (v.mode === "as-primary" || shouldHideSocket(k, v)) continue; + if (v.mode === 'as-primary' || shouldHideSocket(k, v)) + continue const socket = useSocket(k, MultiOutSocket, { label: v.displayName, - type: "L", + type: 'L', path: PATH_OUT_RECT, hideLabel: contents.length === 1, direction: v.position ?? Direction.RIGHT, - }); + }) - if (v.mode === "as-primary-and-socket") { + if (v.mode === 'as-primary-and-socket') { this.getPrimaryDisabled = () => { - return socket.allConnectedLines.length > 0; - }; + return socket.allConnectedLines.length > 0 + } } } for (const [k, v] of events) { - if (shouldHideSocket(k, v)) continue; + if (shouldHideSocket(k, v)) + continue useSocket(k, SingleOutSocket, { label: v.displayName, - type: "E", + type: 'E', path: PATH_OUT_TRIANGLE, direction: v.position ?? Direction.BOTTOM, - }); + }) } for (const [k, v] of inputs) { - if (v.mode === "as-primary" || shouldHideSocket(k, v)) continue; + if (v.mode === 'as-primary' || shouldHideSocket(k, v)) + continue const socket = useSocket(k, SingleInSocket, { label: v.displayName, - type: "D", + type: 'D', path: PATH_IN_ELIPSE, direction: v.position ?? Direction.UP, - }); + }) - if (v.mode === "as-primary-and-socket") { + if (v.mode === 'as-primary-and-socket') { this.getPrimaryDisabled = () => { - return socket.allConnectedLines.length > 0; - }; + return socket.allConnectedLines.length > 0 + } } } for (const [k, v] of outputs) { - if (shouldHideSocket(k, v)) continue; + if (shouldHideSocket(k, v)) + continue useSocket(k, MultiOutSocket, { label: v.displayName, - type: "D", + type: 'D', path: PATH_OUT_ELIPSE, direction: v.position ?? Direction.BOTTOM, - }); + }) } for (const [k, v] of methods) { - if (shouldHideSocket(k, v)) continue; + if (shouldHideSocket(k, v)) + continue useSocket(k, MultiInSocket, { label: v.displayName, - type: "E", + type: 'E', path: PATH_IN_TRIANGLE, direction: v.position ?? Direction.TOP, - }); + }) } } getProps(): PropsData { - return getProps(this); + return getProps(this) } protected exportData() { @@ -192,22 +201,23 @@ export class ComponentBlock extends RectBlock { props: this.props, primaryValue: this.primaryValue.value, slotsDirection: this.slotsDirection, - }; + } } + protected importData(data: any, sockets: Record): void { - super.importData(data, sockets); + super.importData(data, sockets) this.setComponentType( data.componentType, componentInfoObj[data.componentType as keyof typeof componentInfoObj], - ); - this.props = data.props; - this.primaryValue.value = data.primaryValue; - this.slotsDirection = data.slotsDirection; + ) + this.props = data.props + this.primaryValue.value = data.primaryValue + this.slotsDirection = data.slotsDirection } } -blockCtors["ComponentBlock"] = ComponentBlock; +blockCtors.ComponentBlock = ComponentBlock export function isComponentBlock(block: any): block is ComponentBlock { - return Boolean(block.isComponentBlock); + return Boolean(block.isComponentBlock) } diff --git a/packages/northstar/src/blocks/component/getContent.r.ts b/packages/northstar/src/blocks/component/getContent.r.ts index 0e1694a..ecd3bdc 100644 --- a/packages/northstar/src/blocks/component/getContent.r.ts +++ b/packages/northstar/src/blocks/component/getContent.r.ts @@ -1,22 +1,24 @@ -import { Context, PrimaryElRef, ref } from "refina"; -import { currentProject } from "../../project"; -import { ComponentBlock } from "./block"; -import { app } from "../../app.r"; +import type { Context, PrimaryElRef } from 'refina' +import { ref } from 'refina' +import { currentProject } from '../../project' +import { app } from '../../app.r' +import type { ComponentBlock } from './block' export function getContent(block: ComponentBlock) { const title = (_: Context) => { - _.$cls`mx-2 text-sm`; - _.span(block.info.displayName(block.props)); - }; - const primaryInputInfo = block.primaryInputInfo?.[1]; + _.$cls`mx-2 text-sm` + _.span(block.info.displayName(block.props)) + } + const primaryInputInfo = block.primaryInputInfo?.[1] - if (!primaryInputInfo) return title; + if (!primaryInputInfo) + return title return (_: Context) => { - _.$cls`text-gray-600`; - title(_); + _.$cls`text-gray-600` + title(_) - const propagationStopper = (ev: Event) => ev.stopPropagation(); - block.getPrimaryDisabled() && _.$cls`invisible`; + const propagationStopper = (ev: Event) => ev.stopPropagation() + block.getPrimaryDisabled() && _.$cls`invisible` _._span( { onmousedown: propagationStopper, @@ -25,30 +27,31 @@ export function getContent(block: ComponentBlock) { onkeydown: propagationStopper, }, _ => { - const inputRef: PrimaryElRef = ref(); - _.$css`font-family: Consolas; max-width: 108px; padding-left:4px`; - _.$ref(inputRef) && - _.fUnderlineInput( - block.primaryValue, - false, - primaryInputInfo.displayName, - ); + const inputRef: PrimaryElRef = ref() + _.$css`font-family: Consolas; max-width: 108px; padding-left:4px` + _.$ref(inputRef) + && _.fUnderlineInput( + block.primaryValue, + false, + primaryInputInfo.displayName, + ) if (_.$updateContext) { setTimeout(() => { const inputEl = inputRef.current!.$primaryEl!.node.firstChild as | HTMLInputElement - | undefined; - if (!inputEl) return; + | undefined + if (!inputEl) + return inputEl.onchange = () => { - currentProject.activeGraph.pushRecord(); - }; + currentProject.activeGraph.pushRecord() + } inputEl.onfocus = () => { - currentProject.activeGraph.addSelectedBlock(block, false); - app.update(); - }; - }, 5); + currentProject.activeGraph.addSelectedBlock(block, false) + app.update() + } + }, 5) } }, - ); - }; + ) + } } diff --git a/packages/northstar/src/blocks/component/getProps.ts b/packages/northstar/src/blocks/component/getProps.ts index 9f589ec..a354f6a 100644 --- a/packages/northstar/src/blocks/component/getProps.ts +++ b/packages/northstar/src/blocks/component/getProps.ts @@ -1,46 +1,46 @@ -import { directionNameMap, directionMap } from "@quasi-dev/visual-flow"; -import { PropData, PropsData } from "../../utils/props"; -import { ComponentBlock } from "./block"; +import { directionMap, directionNameMap } from '@quasi-dev/visual-flow' +import type { PropData, PropsData } from '../../utils/props' +import type { ComponentBlock } from './block' export function getProps(block: ComponentBlock): PropsData { - const { info } = block; + const { info } = block - const slotPos: PropData[] = []; - const primaryInputInfo = block.primaryInputInfo; + const slotPos: PropData[] = [] + const primaryInputInfo = block.primaryInputInfo if (primaryInputInfo) { slotPos.push({ - key: "slots-pos", - displayName: "slots pos", - type: "dropdown", - options: ["TOP", "BOTTOM"], + key: 'slots-pos', + displayName: 'slots pos', + type: 'dropdown', + options: ['TOP', 'BOTTOM'], getVal: () => { - return directionNameMap[block.slotsDirection]; + return directionNameMap[block.slotsDirection] }, - setVal: (val) => { - block.slotsDirection = directionMap[val]; + setVal: val => { + block.slotsDirection = directionMap[val] }, - }); + }) } return [ ...slotPos, ...Object.entries(info.props).map(([k, v]) => { - if (v.type !== "readonly") { - block.props[k] ??= v.defaultVal; - } + if (v.type !== 'readonly') + block.props[k] ??= v.defaultVal + return { ...v, key: k, getVal: - v.type === "readonly" + v.type === 'readonly' ? () => v.value : () => { - return block.props[k]; + return block.props[k] }, setVal: (val: any) => { - block.props[k] = val; + block.props[k] = val }, - } as PropData; + } as PropData }), ...Object.entries({ ...info.contents, @@ -50,22 +50,22 @@ export function getProps(block: ComponentBlock): PropsData { ...info.methods, }) .filter( - ([k, v]) => - v.mode === "as-hidable-socket" || v.mode === "as-hidden-socket", + ([_k, v]) => + v.mode === 'as-hidable-socket' || v.mode === 'as-hidden-socket', ) .map(([k, v]) => { - block.props[`[${k}]`] ??= v.mode === "as-hidable-socket"; + block.props[`[${k}]`] ??= v.mode === 'as-hidable-socket' return { key: `[${k}]`, displayName: `[${v.displayName}]`, - type: "switch", + type: 'switch', getVal: () => { - return block.props[`[${k}]`]; + return block.props[`[${k}]`] }, setVal: (val: any) => { - block.props[`[${k}]`] = val; + block.props[`[${k}]`] = val }, - } as PropData; + } as PropData }), - ]; + ] } diff --git a/packages/northstar/src/blocks/component/index.ts b/packages/northstar/src/blocks/component/index.ts index aabc41a..a6cec03 100644 --- a/packages/northstar/src/blocks/component/index.ts +++ b/packages/northstar/src/blocks/component/index.ts @@ -1,3 +1,3 @@ -export * from "./block"; -export * from "./getProps"; -export * from "./toBlockOutput"; +export * from './block' +export * from './getProps' +export * from './toBlockOutput' diff --git a/packages/northstar/src/blocks/component/toBlockOutput.ts b/packages/northstar/src/blocks/component/toBlockOutput.ts index b864d58..8fbe266 100644 --- a/packages/northstar/src/blocks/component/toBlockOutput.ts +++ b/packages/northstar/src/blocks/component/toBlockOutput.ts @@ -6,111 +6,110 @@ import type { ComponentBlockPrimaryInput, ComponentBlockProps, ConnectTo, -} from "@quasi-dev/compiler"; -import { Block, SingleOutSocket, Socket } from "@quasi-dev/visual-flow"; +} from '@quasi-dev/compiler' +import type { Block, SingleOutSocket, Socket } from '@quasi-dev/visual-flow' import { singleInSocketToOutput, singleOutSocketToOutput, -} from "../../utils/toOutput"; -import { ValidatorBlock } from "../special/validator"; -import { ComponentBlock } from "./block"; +} from '../../utils/toOutput' +import type { ValidatorBlock } from '../special/validator' +import type { ComponentBlock } from './block' export function toBlockOutput(block: ComponentBlock) { - const blockContents = Object.entries(block.info.contents); - const blockEvents = Object.entries(block.info.events); - const blockInputs = Object.entries(block.info.inputs); - const blockProps = Object.entries(block.info.props); - const blockPlugins = Object.entries(block.info.plugins); + const blockContents = Object.entries(block.info.contents) + const blockEvents = Object.entries(block.info.events) + const blockInputs = Object.entries(block.info.inputs) + const blockProps = Object.entries(block.info.props) + const blockPlugins = Object.entries(block.info.plugins) - const callbacks = {} as ComponentBlockCallbacks; - for (const [k, v] of blockEvents) { + const callbacks = {} as ComponentBlockCallbacks + for (const [k] of blockEvents) { callbacks[k] = singleOutSocketToOutput( block.getSocketByName(k) as SingleOutSocket, - ); + ) } - const props = {} as ComponentBlockProps; + const props = {} as ComponentBlockProps for (const [k, v] of blockProps) { - if (v.type !== "readonly") { - props[k] = block.props[k]; - } + if (v.type !== 'readonly') + props[k] = block.props[k] } for (const [k, v] of blockInputs) { if ( - v.mode === "as-primary" || - (v.mode === "as-primary-and-socket" && block.primaryFilled) + v.mode === 'as-primary' + || (v.mode === 'as-primary-and-socket' && block.primaryFilled) ) - continue; - const socket = block.getSocketByName(k)?.allConnectedLines[0]?.a; + continue + const socket = block.getSocketByName(k)?.allConnectedLines[0]?.a props[k] = { - blockId: socket?.block.id ?? NaN, - socketName: socket?.label ?? "", - }; + blockId: socket?.block.id ?? Number.NaN, + socketName: socket?.label ?? '', + } } - let children = {} as ComponentBlockChildren; + const children = {} as ComponentBlockChildren for (const [k, v] of blockContents) { if ( - v.mode === "as-primary" || - (v.mode === "as-primary-and-socket" && block.primaryFilled) + v.mode === 'as-primary' + || (v.mode === 'as-primary-and-socket' && block.primaryFilled) ) - continue; - children[k] = - block + continue + children[k] + = block .getSocketByName(k) - ?.allConnectedLines.map((l) => (l.b as Socket).block) + ?.allConnectedLines.map(l => (l.b as Socket).block) .sort((a, b) => a.boardY - b.boardY) - .map((b) => b.id) ?? []; + .map(b => b.id) ?? [] } - let plugins = {} as ComponentBlockPlugins; + const plugins = {} as ComponentBlockPlugins for (const [k, v] of blockPlugins) { - if (v.kind !== "input-plugin") continue; + if (v.kind !== 'input-plugin') + continue - const validators: ValidatorBlock[] = []; - let currentPluginBlock: Block | undefined = block; + const validators: ValidatorBlock[] = [] + let currentPluginBlock: Block | undefined = block while (true) { currentPluginBlock = currentPluginBlock.dockedByBlocks.find( - ([d, b]) => d === v.direction, - )?.[1]; - if (!currentPluginBlock) { - break; - } - if ((currentPluginBlock as ValidatorBlock).type === "validator") { - validators.push(currentPluginBlock as ValidatorBlock); - } else { - throw new Error(`Invalid plugin block ${currentPluginBlock.id}`); - } + ([d]) => d === v.direction, + )?.[1] + if (!currentPluginBlock) + break + + if ((currentPluginBlock as ValidatorBlock).type === 'validator') + validators.push(currentPluginBlock as ValidatorBlock) + else + throw new Error(`Invalid plugin block ${currentPluginBlock.id}`) } plugins[k] = `$ => { ${validators - .map((v) => { + .map(v => { if (v.inputValue.value.length === 0) - throw new Error("Validator expression is empty"); - return `if(!(${v.inputValue})) return "${v.errorMessages}";`; + throw new Error('Validator expression is empty') + return `if(!(${v.inputValue})) return "${v.errorMessages}";` }) - .join("\n")} + .join('\n')} return true; - }`; + }` } - let primaryInput: ComponentBlockPrimaryInput = null; - const primaryInputInfo = block.primaryInputInfo; + let primaryInput: ComponentBlockPrimaryInput = null + const primaryInputInfo = block.primaryInputInfo if (primaryInputInfo) { - const slots: Record = {}; - for (const socket of block.slotSockets) { - slots[socket.label] = singleInSocketToOutput(socket); - } + const slots: Record = {} + for (const socket of block.slotSockets) + slots[socket.label] = singleInSocketToOutput(socket) + primaryInput = { name: primaryInputInfo[1].displayName, value: block.primaryValue.value, slots, - }; + } } return { - type: "component", + type: 'component', func: block.componentType, id: block.id, name: block.info.displayName(block.props), @@ -120,5 +119,5 @@ export function toBlockOutput(block: ComponentBlock) { plugins, children, primaryInput, - } satisfies ComponentBlockOutput; + } satisfies ComponentBlockOutput } diff --git a/packages/northstar/src/blocks/component/updatePlugins.ts b/packages/northstar/src/blocks/component/updatePlugins.ts index d9a92e7..095c65f 100644 --- a/packages/northstar/src/blocks/component/updatePlugins.ts +++ b/packages/northstar/src/blocks/component/updatePlugins.ts @@ -1,11 +1,10 @@ -import { ComponentBlock } from "./block"; +import type { ComponentBlock } from './block' export function updatePlugins(block: ComponentBlock) { - const { info } = block; + const { info } = block - const plugins = Object.values(info.plugins); + const plugins = Object.values(info.plugins) - for (const plugin of plugins) { - block.dockableDirections.push([plugin.direction, plugin.kind]); - } + for (const plugin of plugins) + block.dockableDirections.push([plugin.direction, plugin.kind]) } diff --git a/packages/northstar/src/blocks/special/FuncBlockBase.r.ts b/packages/northstar/src/blocks/special/FuncBlockBase.r.ts index 9b71ff5..b1ee61d 100644 --- a/packages/northstar/src/blocks/special/FuncBlockBase.r.ts +++ b/packages/northstar/src/blocks/special/FuncBlockBase.r.ts @@ -6,7 +6,11 @@ import type { StateBlockOutput, StateSetterBlockOutput, ValidatorBlockOutput, -} from "@quasi-dev/compiler"; +} from '@quasi-dev/compiler' +import type { + UseSocket, + UsedSockets, +} from '@quasi-dev/visual-flow' import { Direction, MultiOutSocket, @@ -14,48 +18,47 @@ import { PATH_OUT_ELIPSE, RectBlock, SingleInSocket, - UseSocket, - UsedSockets, directionMap, directionNameMap, -} from "@quasi-dev/visual-flow"; -import { FiExpandUpLeft20Regular } from "@refina/fluentui-icons/expandUpLeft"; -import { Context, PrimaryElRef, bySelf, model, ref } from "refina"; -import { setExtraLib } from "../../utils"; -import { PropData, PropsData } from "../../utils/props"; -import { multiOutSocketToOutput } from "../../utils/toOutput"; -import { SpecialBlock } from "./base"; -import { currentProject } from "../../project"; +} from '@quasi-dev/visual-flow' +import { FiExpandUpLeft20Regular } from '@refina/fluentui-icons/expandUpLeft' +import type { Context, PrimaryElRef } from 'refina' +import { bySelf, model, ref } from 'refina' +import { setExtraLib } from '../../utils' +import type { PropData, PropsData } from '../../utils/props' +import { multiOutSocketToOutput } from '../../utils/toOutput' +import { currentProject } from '../../project' +import type { SpecialBlock } from './base' export abstract class FuncBlockBase extends RectBlock implements SpecialBlock { cloneTo(target: this): this { - super.cloneTo(target); - target.inputValue.value = this.inputValue.value; - target.outputDirection = this.outputDirection; - target.slotsDirection = this.slotsDirection; - return target; + super.cloneTo(target) + target.inputValue.value = this.inputValue.value + target.outputDirection = this.outputDirection + target.slotsDirection = this.slotsDirection + return target } - abstract type: FuncBlockTypes; + abstract type: FuncBlockTypes - removable = true; - duplicateable = true; + removable = true + duplicateable = true - boardWidth: number = 200; - boardHeight: number = 50; + boardWidth: number = 200 + boardHeight: number = 50 - useTextarea: boolean = false; - outputLabel: string = "output"; - abstract label: string; - placeholder = ""; + useTextarea: boolean = false + outputLabel: string = 'output' + abstract label: string + placeholder = '' - inputValue = model(""); - slotsDirection = Direction.TOP; - outputDirection = Direction.BOTTOM; + inputValue = model('') + slotsDirection = Direction.TOP + outputDirection = Direction.BOTTOM content = (_: Context) => { - _.$cls`text-xs ml-1 mt-[5px] leading-3 text-gray-600`; - _.div(this.label); + _.$cls`text-xs ml-1 mt-[5px] leading-3 text-gray-600` + _.div(this.label) _._div( { @@ -65,62 +68,63 @@ export abstract class FuncBlockBase extends RectBlock implements SpecialBlock { onkeydown: ev => ev.stopPropagation(), }, _ => { - const inputRef: PrimaryElRef = ref(); - _.$css`--fontFamilyBase: Consolas,'Segoe UI', 'Segoe UI Web (West European)', -apple-system, BlinkMacSystemFont, Roboto, 'Helvetica Neue', sans-serif`; - _.$ref(inputRef) && - (this.useTextarea - ? _.$css`margin-top:4px;max-width:180px` && - _.fTextarea(this.inputValue, false, this.placeholder, "none") - : _.$css`min-height:24px;margin-left:-4px` && - _.fUnderlineInput(this.inputValue, false, this.placeholder)); + const inputRef: PrimaryElRef = ref() + _.$css`--fontFamilyBase: Consolas,'Segoe UI', 'Segoe UI Web (West European)', -apple-system, BlinkMacSystemFont, Roboto, 'Helvetica Neue', sans-serif` + _.$ref(inputRef) + && (this.useTextarea + ? _.$css`margin-top:4px;max-width:180px` + && _.fTextarea(this.inputValue, false, this.placeholder, 'none') + : _.$css`min-height:24px;margin-left:-4px` + && _.fUnderlineInput(this.inputValue, false, this.placeholder)) if (_.$updateContext) { setTimeout(() => { const inputEl = inputRef.current!.$primaryEl!.node.firstChild as | HTMLElement - | undefined; - if (!inputEl) return; + | undefined + if (!inputEl) + return inputEl.onchange = () => { - currentProject.activeGraph.pushRecord(); - }; - }, 5); + currentProject.activeGraph.pushRecord() + } + }, 5) } if (this.useTextarea) { - const slots = this.slots; + const slots = this.slots - _.$cls`monaco-dialog`; + _.$cls`monaco-dialog` _.fDialog( open => { - _.$cls`absolute right-0 top-0 text-gray-600`; - _.button(_ => _(FiExpandUpLeft20Regular)()) && open(); + _.$cls`absolute right-0 top-0 text-gray-600` + _.button(_ => _(FiExpandUpLeft20Regular)()) && open() }, _ => { - _.span(this.label); + _.span(this.label) - _.$cls`ml-10 inline-block text-base text-gray-500`; + _.$cls`ml-10 inline-block text-base text-gray-500` _.div(_ => { - _.span("Params:"); + _.span('Params:') if (slots.length === 0) { - _.$cls`ml-2`; - _.span("none"); + _.$cls`ml-2` + _.span('none') } - _.$cls`font-[Consolas]`; + _.$cls`font-[Consolas]` _.span(_ => _.for(this.slots, bySelf, (slot, i) => { - if (i !== 0) { - _.span(", "); - } - _.$cls`text-black`; - _.span(slot); + if (i !== 0) + _.span(', ') + + _.$cls`text-black` + _.span(slot) }), - ); - }); + ) + }) }, () => { - const propagationStopper = (ev: Event) => ev.stopPropagation(); - _.$cls`h-[80vh] overflow-visible`; + const propagationStopper = (ev: Event) => ev.stopPropagation() + _.$cls`h-[80vh] overflow-visible` _._div( { onclick: propagationStopper, @@ -131,59 +135,61 @@ export abstract class FuncBlockBase extends RectBlock implements SpecialBlock { }, _ => { if ( - _.monacoEditor(this.inputValue.value, "javascript", { + _.monacoEditor(this.inputValue.value, 'javascript', { tabSize: 2, }) ) { - this.inputValue.value = _.$ev; + this.inputValue.value = _.$ev setExtraLib( this.slots .map( slot => `/** param */ declare const $${slot}: any;`, ) - .join("\n"), - ); + .join('\n'), + ) } }, - ); + ) }, - ); + ) } }, - ); - }; + ) + } - abstract get slotsUsage(): string[]; + abstract get slotsUsage(): string[] get slots() { - return [...new Set(this.slotsUsage)]; + return [...new Set(this.slotsUsage)] } + get noOutput() { - return false; + return false } get inputSockets() { - return this.getSocketsByPrefix("input") as SingleInSocket[]; + return this.getSocketsByPrefix('input') as SingleInSocket[] } + get outputSocket() { - return this.getSocketByName("output") as MultiOutSocket; + return this.getSocketByName('output') as MultiOutSocket } socketUpdater(useSocket: UseSocket, _usedSockets: UsedSockets): void { for (const slot of this.slots) { useSocket(`input-${slot}`, SingleInSocket, { label: slot, - type: "D", + type: 'D', path: PATH_IN_ELIPSE, direction: this.slotsDirection, - }); + }) } if (!this.noOutput) { - useSocket("output", MultiOutSocket, { + useSocket('output', MultiOutSocket, { label: this.outputLabel, - type: "D", + type: 'D', path: PATH_OUT_ELIPSE, direction: this.outputDirection, - }); + }) } } @@ -193,42 +199,43 @@ export abstract class FuncBlockBase extends RectBlock implements SpecialBlock { inputValue: this.inputValue.value, outputDirection: this.outputDirection, slotsDirection: this.slotsDirection, - }; + } } + protected importData(data: any, sockets: any): void { - super.importData(data, sockets); - this.inputValue.value = data.inputValue; - this.outputDirection = data.outputDirection; - this.slotsDirection = data.slotsDirection; + super.importData(data, sockets) + this.inputValue.value = data.inputValue + this.outputDirection = data.outputDirection + this.slotsDirection = data.slotsDirection } getProps(): PropsData { return [ { - key: "slots-pos", - displayName: "slots pos", - type: "dropdown", - options: ["TOP", "BOTTOM"], + key: 'slots-pos', + displayName: 'slots pos', + type: 'dropdown', + options: ['TOP', 'BOTTOM'], getVal: () => { - return directionNameMap[this.slotsDirection]; + return directionNameMap[this.slotsDirection] }, setVal: val => { - this.slotsDirection = directionMap[val]; + this.slotsDirection = directionMap[val] }, } satisfies PropData, { - key: "output-pos", - displayName: "output pos", - type: "dropdown", - options: ["BOTTOM", "TOP"], + key: 'output-pos', + displayName: 'output pos', + type: 'dropdown', + options: ['BOTTOM', 'TOP'], getVal: () => { - return directionNameMap[this.outputDirection]; + return directionNameMap[this.outputDirection] }, setVal: val => { - this.outputDirection = directionMap[val]; + this.outputDirection = directionMap[val] }, } satisfies PropData, - ].slice(0, this.noOutput ? 1 : 2); + ].slice(0, this.noOutput ? 1 : 2) } toOutput(): @@ -237,12 +244,12 @@ export abstract class FuncBlockBase extends RectBlock implements SpecialBlock { | ImpBlockOutput | StateBlockOutput | StateSetterBlockOutput { - const slots: Record = {}; + const slots: Record = {} for (const socket of this.inputSockets) { slots[socket.label] = { - blockId: socket.connectedLine?.a.block.id ?? NaN, - socketName: socket.connectedLine?.a.label ?? "", - }; + blockId: socket.connectedLine?.a.block.id ?? Number.NaN, + socketName: socket.connectedLine?.a.label ?? '', + } } return { @@ -251,6 +258,6 @@ export abstract class FuncBlockBase extends RectBlock implements SpecialBlock { value: this.inputValue.value, slots, output: multiOutSocketToOutput(this.outputSocket), - }; + } } } diff --git a/packages/northstar/src/blocks/special/base.ts b/packages/northstar/src/blocks/special/base.ts index 55191d6..ff21c4c 100644 --- a/packages/northstar/src/blocks/special/base.ts +++ b/packages/northstar/src/blocks/special/base.ts @@ -1,6 +1,6 @@ -import { PropsData } from "../../utils/props"; +import type { PropsData } from '../../utils/props' export interface SpecialBlock { - getProps(): PropsData; - toOutput(): any; + getProps: () => PropsData + toOutput: () => any } diff --git a/packages/northstar/src/blocks/special/do.r.ts b/packages/northstar/src/blocks/special/do.r.ts index 83c5213..9493605 100644 --- a/packages/northstar/src/blocks/special/do.r.ts +++ b/packages/northstar/src/blocks/special/do.r.ts @@ -1,142 +1,147 @@ -import { DoBlockOutput } from "@quasi-dev/compiler"; -import { +import type { DoBlockOutput } from '@quasi-dev/compiler' +import type { Block, + Socket, + UseSocket, +} from '@quasi-dev/visual-flow' +import { Direction, MultiInSocket, PATH_IN_TRIANGLE, PATH_OUT_TRIANGLE, RectBlock, SingleOutSocket, - Socket, - UseSocket, blockCtors, -} from "@quasi-dev/visual-flow"; -import { Context } from "refina"; -import { PropsData } from "../../utils/props"; +} from '@quasi-dev/visual-flow' +import type { Context } from 'refina' +import type { PropsData } from '../../utils/props' import { multiInSocketToOutput, singleOutSocketToOutput, -} from "../../utils/toOutput"; +} from '../../utils/toOutput' -const WIDTH = 70; -const HEIGHT = 30; +const WIDTH = 70 +const HEIGHT = 30 export class DoBlock extends RectBlock { - ctorName: string = "DoBlock"; + ctorName: string = 'DoBlock' cloneTo(target: this): this { - super.cloneTo(target); - target.thenNum = this.thenNum; - target.rotate = this.rotate; - return target; + super.cloneTo(target) + target.thenNum = this.thenNum + target.rotate = this.rotate + return target } - type = "state-setter"; + type = 'state-setter' - boardWidth = WIDTH; - boardHeight = HEIGHT; + boardWidth = WIDTH + boardHeight = HEIGHT - removable = true; - duplicateable = true; + removable = true + duplicateable = true get whenSocket() { - return this.getSocketByName("when") as MultiInSocket; + return this.getSocketByName('when') as MultiInSocket } + get thenSockets() { - return this.getSocketsByPrefix("then") as SingleOutSocket[]; + return this.getSocketsByPrefix('then') as SingleOutSocket[] } - thenNum: number = 2; - rotate: boolean = false; + thenNum: number = 2 + rotate: boolean = false socketUpdater(useSocket: UseSocket): void { - useSocket("when", MultiInSocket, { + useSocket('when', MultiInSocket, { hideLabel: true, - type: "E", + type: 'E', path: PATH_IN_TRIANGLE, direction: this.rotate ? Direction.LEFT : Direction.TOP, - }); + }) for (let i = 0; i < this.thenNum; i++) { useSocket(`then-${i}`, SingleOutSocket, { label: `${i + 1}`, - type: "E", + type: 'E', path: PATH_OUT_TRIANGLE, direction: this.rotate ? Direction.RIGHT : Direction.BOTTOM, - }); + }) } } getProps(): PropsData { return [ { - key: "number", - displayName: "number", - type: "number", + key: 'number', + displayName: 'number', + type: 'number', min: 2, max: 5, getVal: () => { - return this.thenNum; + return this.thenNum }, setVal: val => { - this.thenNum = val; + this.thenNum = val }, }, { - key: "rotate", - displayName: "rotate", - type: "switch", + key: 'rotate', + displayName: 'rotate', + type: 'switch', getVal: () => { - return this.rotate; + return this.rotate }, setVal: val => { - this.rotate = val; + this.rotate = val if (val) { - this.boardWidth = HEIGHT; - this.boardHeight = WIDTH; - } else { - this.boardWidth = WIDTH; - this.boardHeight = HEIGHT; + this.boardWidth = HEIGHT + this.boardHeight = WIDTH + } + else { + this.boardWidth = WIDTH + this.boardHeight = HEIGHT } }, }, - ]; + ] } contentMain = (_: Context) => { - _.$cls`absolute flex items-center left-0 top-0 justify-around text-gray-600`; - _.$css`width:${this.pageWidth}px;height:${this.pageHeight}px;`; - _.$css`transform:scale(${this.graph.boardScale})`; + _.$cls`absolute flex items-center left-0 top-0 justify-around text-gray-600` + _.$css`width:${this.pageWidth}px;height:${this.pageHeight}px;` + _.$css`transform:scale(${this.graph.boardScale})` _.div(_ => { - _.span("do"); - }); - }; + _.span('do') + }) + } protected exportData() { return { ...super.exportData(), thenNum: this.thenNum, rotate: this.rotate, - }; + } } + protected importData(data: any, sockets: Record): void { - super.importData(data, sockets); - this.thenNum = data.thenNum; - this.rotate = data.rotate; + super.importData(data, sockets) + this.thenNum = data.thenNum + this.rotate = data.rotate } toOutput(): DoBlockOutput { - let stateBlock: Block = this; - while (stateBlock.dockedToBlock) { - stateBlock = stateBlock.dockedToBlock; - } + let stateBlock: Block = this + while (stateBlock.dockedToBlock) + stateBlock = stateBlock.dockedToBlock + return { - type: "do", + type: 'do', id: this.id, when: multiInSocketToOutput(this.whenSocket), then: this.thenSockets.map(singleOutSocketToOutput), - }; + } } } -blockCtors["DoBlock"] = DoBlock; +blockCtors.DoBlock = DoBlock diff --git a/packages/northstar/src/blocks/special/expr.ts b/packages/northstar/src/blocks/special/expr.ts index 985cd3d..c45b786 100644 --- a/packages/northstar/src/blocks/special/expr.ts +++ b/packages/northstar/src/blocks/special/expr.ts @@ -1,19 +1,19 @@ -import type { FuncBlockTypes } from "@quasi-dev/compiler"; -import { blockCtors } from "@quasi-dev/visual-flow"; -import { FuncBlockBase } from "./FuncBlockBase.r"; +import type { FuncBlockTypes } from '@quasi-dev/compiler' +import { blockCtors } from '@quasi-dev/visual-flow' +import { FuncBlockBase } from './FuncBlockBase.r' export class ExprBlock extends FuncBlockBase { - ctorName: string = "ExprBlock"; + ctorName: string = 'ExprBlock' - type: FuncBlockTypes = "expr"; - label = "expression"; - outputLabel = "value"; + type: FuncBlockTypes = 'expr' + label = 'expression' + outputLabel = 'value' get slotsUsage() { - const template = this.inputValue.value; - const matches = template.matchAll(/\$[a-zA-Z0-9]+/g); - return [...matches].map((match) => match[0].slice(1)); + const template = this.inputValue.value + const matches = template.matchAll(/\$[a-zA-Z0-9]+/g) + return [...matches].map(match => match[0].slice(1)) } } -blockCtors["ExprBlock"] = ExprBlock; +blockCtors.ExprBlock = ExprBlock diff --git a/packages/northstar/src/blocks/special/if.r.ts b/packages/northstar/src/blocks/special/if.r.ts index cb854e0..d8586a7 100644 --- a/packages/northstar/src/blocks/special/if.r.ts +++ b/packages/northstar/src/blocks/special/if.r.ts @@ -1,4 +1,7 @@ -import type { IfBlockOutput } from "@quasi-dev/compiler"; +import type { IfBlockOutput } from '@quasi-dev/compiler' +import type { + UseSocket, +} from '@quasi-dev/visual-flow' import { Direction, MultiInSocket, @@ -8,106 +11,108 @@ import { RectBlock, SingleInSocket, SingleOutSocket, - UseSocket, blockCtors, -} from "@quasi-dev/visual-flow"; -import { Context } from "refina"; -import { PropsData } from "../../utils/props"; +} from '@quasi-dev/visual-flow' +import type { Context } from 'refina' +import type { PropsData } from '../../utils/props' import { multiInSocketToOutput, singleInSocketToOutput, singleOutSocketToOutput, -} from "../../utils/toOutput"; -import { SpecialBlock } from "./base"; +} from '../../utils/toOutput' +import type { SpecialBlock } from './base' export class IfElseBlock extends RectBlock implements SpecialBlock { - ctorName: string = "IfElseBlock"; + ctorName: string = 'IfElseBlock' cloneTo(target: this): this { - super.cloneTo(target); - target.hasElse = this.hasElse; - return target; + super.cloneTo(target) + target.hasElse = this.hasElse + return target } - removable = true; - duplicateable = true; + removable = true + duplicateable = true - boardWidth: number = 200; - boardHeight: number = 50; + boardWidth: number = 200 + boardHeight: number = 50 - hasElse: boolean = false; + hasElse: boolean = false get condSocket() { - return this.getSocketByName("cond") as SingleInSocket; + return this.getSocketByName('cond') as SingleInSocket } + get whenSocket() { - return this.getSocketByName("when") as MultiInSocket; + return this.getSocketByName('when') as MultiInSocket } + get thenSocket() { - return this.getSocketByName("then") as SingleOutSocket; + return this.getSocketByName('then') as SingleOutSocket } + get elseSocket() { - return this.getSocketByName("else") as SingleOutSocket; + return this.getSocketByName('else') as SingleOutSocket } socketUpdater(useSocket: UseSocket): void { - useSocket("cond", SingleInSocket, { - type: "D", + useSocket('cond', SingleInSocket, { + type: 'D', path: PATH_IN_ELIPSE, direction: Direction.TOP, - }); - useSocket("when", MultiInSocket, { - type: "E", + }) + useSocket('when', MultiInSocket, { + type: 'E', path: PATH_IN_TRIANGLE, direction: Direction.LEFT, - }); - useSocket("then", SingleOutSocket, { - type: "E", + }) + useSocket('then', SingleOutSocket, { + type: 'E', path: PATH_OUT_TRIANGLE, direction: Direction.BOTTOM, - }); + }) if (this.hasElse) { - useSocket("else", SingleOutSocket, { - type: "E", + useSocket('else', SingleOutSocket, { + type: 'E', path: PATH_OUT_TRIANGLE, direction: Direction.BOTTOM, - }); + }) } } contentMain = (_: Context) => { - _.$cls`absolute flex items-center left-0 top-0 justify-around text-gray-600`; - _.$css`width:${this.pageWidth}px;height:${this.pageHeight}px;`; - _.$css`transform:scale(${this.graph.boardScale})`; - _.div(this.hasElse ? "if-else" : "if"); - }; + _.$cls`absolute flex items-center left-0 top-0 justify-around text-gray-600` + _.$css`width:${this.pageWidth}px;height:${this.pageHeight}px;` + _.$css`transform:scale(${this.graph.boardScale})` + _.div(this.hasElse ? 'if-else' : 'if') + } getProps(): PropsData { return [ { - key: "[else]", - displayName: "[else]", - type: "switch", + key: '[else]', + displayName: '[else]', + type: 'switch', getVal: () => { - return this.hasElse; + return this.hasElse }, setVal: val => { - this.hasElse = val; + this.hasElse = val }, }, - ]; + ] } toOutput(): IfBlockOutput { return { - type: "if", + type: 'if', id: this.id, condition: singleInSocketToOutput(this.condSocket), when: multiInSocketToOutput(this.whenSocket), then: singleOutSocketToOutput(this.thenSocket), else: singleOutSocketToOutput(this.elseSocket), - }; + } } } -blockCtors["IfElseBlock"] = IfElseBlock; +blockCtors.IfElseBlock = IfElseBlock diff --git a/packages/northstar/src/blocks/special/imp.ts b/packages/northstar/src/blocks/special/imp.ts index 13174e9..f28ed92 100644 --- a/packages/northstar/src/blocks/special/imp.ts +++ b/packages/northstar/src/blocks/special/imp.ts @@ -2,97 +2,101 @@ import type { FuncBlockOutput, FuncBlockTypes, ImpBlockOutput, -} from "@quasi-dev/compiler"; +} from '@quasi-dev/compiler' +import type { + UseSocket, + UsedSockets, +} from '@quasi-dev/visual-flow' import { Direction, MultiInSocket, PATH_IN_TRIANGLE, PATH_OUT_TRIANGLE, SingleOutSocket, - UseSocket, - UsedSockets, blockCtors, -} from "@quasi-dev/visual-flow"; -import { PropsData } from "../../utils/props"; +} from '@quasi-dev/visual-flow' +import type { PropsData } from '../../utils/props' import { multiInSocketToOutput, singleOutSocketToOutput, -} from "../../utils/toOutput"; -import { FuncBlockBase } from "./FuncBlockBase.r"; +} from '../../utils/toOutput' +import { FuncBlockBase } from './FuncBlockBase.r' export class ImpBlock extends FuncBlockBase { - ctorName: string = "ImpBlock"; + ctorName: string = 'ImpBlock' cloneTo(target: this): this { - super.cloneTo(target); - target.hasThen = this.hasThen; - return target; + super.cloneTo(target) + target.hasThen = this.hasThen + return target } - type: FuncBlockTypes = "imp"; - boardHeight = 80; + type: FuncBlockTypes = 'imp' + + boardHeight = 80 - label = "imperative code"; - outputLabel = "retVal"; - useTextarea = true; + label = 'imperative code' + outputLabel = 'retVal' + useTextarea = true - hasThen = false; + hasThen = false get whenSocket() { - return this.getSocketByName("when") as MultiInSocket; + return this.getSocketByName('when') as MultiInSocket } + get thenSocket() { - return this.getSocketByName("then") as SingleOutSocket | undefined; + return this.getSocketByName('then') as SingleOutSocket | undefined } socketUpdater(useSocket: UseSocket, usedSockets: UsedSockets): void { - super.socketUpdater(useSocket, usedSockets); - useSocket("when", MultiInSocket, { - type: "E", + super.socketUpdater(useSocket, usedSockets) + useSocket('when', MultiInSocket, { + type: 'E', path: PATH_IN_TRIANGLE, direction: Direction.LEFT, - }); + }) if (this.hasThen) { - useSocket("then", SingleOutSocket, { - type: "E", + useSocket('then', SingleOutSocket, { + type: 'E', path: PATH_OUT_TRIANGLE, direction: Direction.RIGHT, - }); + }) } - usedSockets.find(([n]) => n === "output")![1].disabled = - this.inputValue.value.match(/\breturn\b/g) === null; + usedSockets.find(([n]) => n === 'output')![1].disabled + = this.inputValue.value.match(/\breturn\b/g) === null } get slotsUsage() { - const template = this.inputValue.value; - const matches = template.matchAll(/\$[a-zA-Z0-9]+/g); - return [...matches].map((match) => match[0].slice(1)); + const template = this.inputValue.value + const matches = template.matchAll(/\$[a-zA-Z0-9]+/g) + return [...matches].map(match => match[0].slice(1)) } getProps(): PropsData { return [ { - key: "[then]", - displayName: "[then]", - type: "switch", + key: '[then]', + displayName: '[then]', + type: 'switch', getVal: () => { - return this.hasThen; + return this.hasThen }, - setVal: (val) => { - this.hasThen = val; + setVal: val => { + this.hasThen = val }, }, - ]; + ] } toOutput(): ImpBlockOutput { return { ...(super.toOutput() as FuncBlockOutput), - type: "imp", + type: 'imp', when: multiInSocketToOutput(this.whenSocket), then: singleOutSocketToOutput(this.thenSocket), - }; + } } } -blockCtors["ImpBlock"] = ImpBlock; +blockCtors.ImpBlock = ImpBlock diff --git a/packages/northstar/src/blocks/special/index.ts b/packages/northstar/src/blocks/special/index.ts index 203aaa6..c99ac22 100644 --- a/packages/northstar/src/blocks/special/index.ts +++ b/packages/northstar/src/blocks/special/index.ts @@ -1,20 +1,20 @@ -import { DoBlock } from "./do.r"; -import { ExprBlock } from "./expr"; -import { IfElseBlock } from "./if.r"; -import { ImpBlock } from "./imp"; -import { StateBlock } from "./state"; -import { StateSetterBlock } from "./stateSetter.r"; -import { StringBlock } from "./string"; -import { ValidatorBlock } from "./validator"; +import { DoBlock } from './do.r' +import { ExprBlock } from './expr' +import { IfElseBlock } from './if.r' +import { ImpBlock } from './imp' +import { StateBlock } from './state' +import { StateSetterBlock } from './stateSetter.r' +import { StringBlock } from './string' +import { ValidatorBlock } from './validator' export default Object.entries({ // root: RootBlock, - string: StringBlock, - expr: ExprBlock, - "if-else": IfElseBlock, - imperative: ImpBlock, - validator: ValidatorBlock, - state: StateBlock, - stateSetter: StateSetterBlock, - do: DoBlock, -}); + 'string': StringBlock, + 'expr': ExprBlock, + 'if-else': IfElseBlock, + 'imperative': ImpBlock, + 'validator': ValidatorBlock, + 'state': StateBlock, + 'stateSetter': StateSetterBlock, + 'do': DoBlock, +}) diff --git a/packages/northstar/src/blocks/special/root.r.ts b/packages/northstar/src/blocks/special/root.r.ts index d91234c..4b7cb47 100644 --- a/packages/northstar/src/blocks/special/root.r.ts +++ b/packages/northstar/src/blocks/special/root.r.ts @@ -1,64 +1,67 @@ -import type { RootBlockOutput } from "@quasi-dev/compiler"; +import type { RootBlockOutput } from '@quasi-dev/compiler' +import type { + Socket, + UseSocket, +} from '@quasi-dev/visual-flow' import { Direction, MultiOutSocket, PATH_OUT_RECT, RectBlock, - Socket, - UseSocket, blockCtors, -} from "@quasi-dev/visual-flow"; -import { Context } from "refina"; -import { PropsData } from "../../utils/props"; -import { SpecialBlock } from "./base"; -import { currentProject } from "../../project"; +} from '@quasi-dev/visual-flow' +import type { Context } from 'refina' +import type { PropsData } from '../../utils/props' +import { currentProject } from '../../project' +import type { SpecialBlock } from './base' export class RootBlock extends RectBlock implements SpecialBlock { - ctorName: string = "RootBlock"; + ctorName: string = 'RootBlock' - boardWidth = 200; - boardHeight = 50; + boardWidth = 200 + boardHeight = 50 get outSocket() { - return this.getSocketByName("out") as MultiOutSocket; + return this.getSocketByName('out') as MultiOutSocket } + socketUpdater(useSocket: UseSocket): void { - useSocket("out", MultiOutSocket, { + useSocket('out', MultiOutSocket, { hideLabel: true, - type: "L", + type: 'L', path: PATH_OUT_RECT, direction: Direction.RIGHT, - }); + }) } contentMain = (_: Context) => { - _.$cls`absolute flex items-center left-0 top-0 justify-around text-gray-600 text-lg`; - _.$css`width:${this.pageWidth}px;height:${this.pageHeight}px;`; - _.$css`transform:scale(${this.graph.boardScale})`; + _.$cls`absolute flex items-center left-0 top-0 justify-around text-gray-600 text-lg` + _.$css`width:${this.pageWidth}px;height:${this.pageHeight}px;` + _.$css`transform:scale(${this.graph.boardScale})` _.div(_ => { _.div(_ => { - _.$css`font-family:Consolas;transform:translateY(-2px);font-size:20px`; - _.$cls`mr-1 font-semibold`; - _.span(currentProject.activeView.name); - _.span("root"); - }); - }); - }; + _.$css`font-family:Consolas;transform:translateY(-2px);font-size:20px` + _.$cls`mr-1 font-semibold` + _.span(currentProject.activeView.name) + _.span('root') + }) + }) + } getProps(): PropsData { - return []; + return [] } toOutput(): RootBlockOutput { return { - type: "root", + type: 'root', id: this.id, children: this.outSocket.connectedLines .map(line => (line.b as Socket).block) .sort((a, b) => a.boardY - b.boardY) .map(b => b.id), - }; + } } } -blockCtors["RootBlock"] = RootBlock; +blockCtors.RootBlock = RootBlock diff --git a/packages/northstar/src/blocks/special/state.ts b/packages/northstar/src/blocks/special/state.ts index f04e87b..4aac3aa 100644 --- a/packages/northstar/src/blocks/special/state.ts +++ b/packages/northstar/src/blocks/special/state.ts @@ -1,41 +1,41 @@ -import { FuncBlockTypes, StateBlockOutput } from "@quasi-dev/compiler"; -import { Block, Direction, blockCtors } from "@quasi-dev/visual-flow"; -import { ExprBlock } from "./expr"; -import { StateSetterBlock } from "./stateSetter.r"; +import type { FuncBlockTypes, StateBlockOutput } from '@quasi-dev/compiler' +import type { Block } from '@quasi-dev/visual-flow' +import { Direction, blockCtors } from '@quasi-dev/visual-flow' +import { ExprBlock } from './expr' +import type { StateSetterBlock } from './stateSetter.r' export class StateBlock extends ExprBlock { - ctorName: string = "StateBlock"; + ctorName: string = 'StateBlock' - label = "state"; - type: FuncBlockTypes = "state"; - placeholder = "initial value"; - outputLabel = "current"; + label = 'state' + type: FuncBlockTypes = 'state' + placeholder = 'initial value' + outputLabel = 'current' dockableDirections: [Direction, string][] = [ - [Direction.LEFT, "state-plugin"], - ]; + [Direction.LEFT, 'state-plugin'], + ] toOutput(): StateBlockOutput { - const setters: number[] = []; - let currentPluginBlock: Block | undefined = this; + const setters: number[] = [] + let currentPluginBlock: Block | undefined = this while (true) { - currentPluginBlock = currentPluginBlock.dockedByBlocks[0]?.[1]; - if (!currentPluginBlock) { - break; - } - if ((currentPluginBlock as StateSetterBlock).type === "state-setter") { - setters.push(currentPluginBlock.id); - } else { - throw new Error(`Invalid plugin block ${currentPluginBlock.id}`); - } + currentPluginBlock = currentPluginBlock.dockedByBlocks[0]?.[1] + if (!currentPluginBlock) + break + + if ((currentPluginBlock as StateSetterBlock).type === 'state-setter') + setters.push(currentPluginBlock.id) + else + throw new Error(`Invalid plugin block ${currentPluginBlock.id}`) } return { ...(super.toOutput() as StateBlockOutput), - type: "state", + type: 'state', setters, - }; + } } } -blockCtors["StateBlock"] = StateBlock; +blockCtors.StateBlock = StateBlock diff --git a/packages/northstar/src/blocks/special/stateSetter.r.ts b/packages/northstar/src/blocks/special/stateSetter.r.ts index 2560df4..e185df2 100644 --- a/packages/northstar/src/blocks/special/stateSetter.r.ts +++ b/packages/northstar/src/blocks/special/stateSetter.r.ts @@ -1,64 +1,67 @@ -import { +import type { FuncBlockTypes, StateBlockOutput, StateSetterBlockOutput, -} from "@quasi-dev/compiler"; -import { +} from '@quasi-dev/compiler' +import type { Block, + UseSocket, + UsedSockets, +} from '@quasi-dev/visual-flow' +import { Direction, MultiInSocket, PATH_IN_TRIANGLE, - UseSocket, - UsedSockets, blockCtors, -} from "@quasi-dev/visual-flow"; -import { multiInSocketToOutput } from "../../utils/toOutput"; -import { ExprBlock } from "./expr"; +} from '@quasi-dev/visual-flow' +import { multiInSocketToOutput } from '../../utils/toOutput' +import { ExprBlock } from './expr' export class StateSetterBlock extends ExprBlock { - ctorName: string = "StateSetterBlock"; + ctorName: string = 'StateSetterBlock' - type: FuncBlockTypes = "state-setter"; - label = "state setter"; - placeholder = "expr"; + type: FuncBlockTypes = 'state-setter' + label = 'state setter' + placeholder = 'expr' - removable = true; - duplicateable = true; + removable = true + duplicateable = true - dockingDirections: [Direction, string][] = [[Direction.LEFT, "state-plugin"]]; + dockingDirections: [Direction, string][] = [[Direction.LEFT, 'state-plugin']] dockableDirections: [Direction, string][] = [ - [Direction.LEFT, "state-plugin"], - ]; + [Direction.LEFT, 'state-plugin'], + ] get onsetSocket() { - return this.getSocketByName("set") as MultiInSocket; + return this.getSocketByName('set') as MultiInSocket } + socketUpdater(useSocket: UseSocket, usedSockets: UsedSockets): void { - super.socketUpdater(useSocket, usedSockets); - useSocket("set", MultiInSocket, { + super.socketUpdater(useSocket, usedSockets) + useSocket('set', MultiInSocket, { hideLabel: true, - type: "E", + type: 'E', path: PATH_IN_TRIANGLE, direction: Direction.TOP, - }); + }) } get noOutput(): boolean { - return true; + return true } toOutput(): StateSetterBlockOutput { - let stateBlock: Block = this; - while (stateBlock.dockedToBlock) { - stateBlock = stateBlock.dockedToBlock; - } + let stateBlock: Block = this + while (stateBlock.dockedToBlock) + stateBlock = stateBlock.dockedToBlock + return { ...(super.toOutput() as StateBlockOutput), - type: "state-setter", + type: 'state-setter', onset: multiInSocketToOutput(this.onsetSocket), state: stateBlock.id, - }; + } } } -blockCtors["StateSetterBlock"] = StateSetterBlock; +blockCtors.StateSetterBlock = StateSetterBlock diff --git a/packages/northstar/src/blocks/special/string.ts b/packages/northstar/src/blocks/special/string.ts index 06d98d6..e40b26a 100644 --- a/packages/northstar/src/blocks/special/string.ts +++ b/packages/northstar/src/blocks/special/string.ts @@ -1,19 +1,19 @@ -import type { FuncBlockTypes } from "@quasi-dev/compiler"; -import { blockCtors } from "@quasi-dev/visual-flow"; -import { FuncBlockBase } from "./FuncBlockBase.r"; +import type { FuncBlockTypes } from '@quasi-dev/compiler' +import { blockCtors } from '@quasi-dev/visual-flow' +import { FuncBlockBase } from './FuncBlockBase.r' export class StringBlock extends FuncBlockBase { - ctorName: string = "StringBlock"; + ctorName: string = 'StringBlock' - type: FuncBlockTypes = "string"; + type: FuncBlockTypes = 'string' - label = "string template"; + label = 'string template' get slotsUsage() { - const template = this.inputValue.value; - const matches = template.matchAll(/\{[a-zA-Z0-9_]+\}/g); - return [...matches].map((match) => match[0].slice(1, -1)); + const template = this.inputValue.value + const matches = template.matchAll(/\{[a-zA-Z0-9_]+\}/g) + return [...matches].map(match => match[0].slice(1, -1)) } } -blockCtors["StringBlock"] = StringBlock; +blockCtors.StringBlock = StringBlock diff --git a/packages/northstar/src/blocks/special/validator.ts b/packages/northstar/src/blocks/special/validator.ts index 8c3370c..e5a5c51 100644 --- a/packages/northstar/src/blocks/special/validator.ts +++ b/packages/northstar/src/blocks/special/validator.ts @@ -1,35 +1,36 @@ -import { FuncBlockTypes, ValidatorBlockOutput } from "@quasi-dev/compiler"; -import { Direction, blockCtors } from "@quasi-dev/visual-flow"; -import { FuncBlockBase } from "./FuncBlockBase.r"; +import type { FuncBlockTypes, ValidatorBlockOutput } from '@quasi-dev/compiler' +import { Direction, blockCtors } from '@quasi-dev/visual-flow' +import { FuncBlockBase } from './FuncBlockBase.r' export class ValidatorBlock extends FuncBlockBase { - ctorName: string = "ValidatorBlock"; + ctorName: string = 'ValidatorBlock' - label = "validator"; - type: FuncBlockTypes = "validator"; - placeholder = "expression"; + label = 'validator' + type: FuncBlockTypes = 'validator' + placeholder = 'expression' - errorMessages: string = "Invalid input"; + errorMessages: string = 'Invalid input' - dockingDirections: [Direction, string][] = [[Direction.LEFT, "input-plugin"]]; + dockingDirections: [Direction, string][] = [[Direction.LEFT, 'input-plugin']] dockableDirections: [Direction, string][] = [ - [Direction.LEFT, "input-plugin"], - ]; + [Direction.LEFT, 'input-plugin'], + ] get slotsUsage(): string[] { - return []; + return [] } + get noOutput() { - return true; + return true } toOutput(): ValidatorBlockOutput { return { - type: "validator", + type: 'validator', id: this.id, expr: this.inputValue.value, - }; + } } } -blockCtors["ValidatorBlock"] = ValidatorBlock; +blockCtors.ValidatorBlock = ValidatorBlock diff --git a/packages/northstar/src/blocks/special/view.r.ts b/packages/northstar/src/blocks/special/view.r.ts index 8c00d88..8c7e698 100644 --- a/packages/northstar/src/blocks/special/view.r.ts +++ b/packages/northstar/src/blocks/special/view.r.ts @@ -1,76 +1,80 @@ -import type { ViewBlockOutput } from "@quasi-dev/compiler"; +import type { ViewBlockOutput } from '@quasi-dev/compiler' +import type { + UseSocket, +} from '@quasi-dev/visual-flow' import { Direction, PATH_IN_RECT, RectBlock, SingleInSocket, - UseSocket, blockCtors, -} from "@quasi-dev/visual-flow"; -import { Context } from "refina"; -import { PropsData } from "../../utils/props"; -import { singleInSocketToOutput } from "../../utils/toOutput"; -import { SpecialBlock } from "./base"; +} from '@quasi-dev/visual-flow' +import type { Context } from 'refina' +import type { PropsData } from '../../utils/props' +import { singleInSocketToOutput } from '../../utils/toOutput' +import type { SpecialBlock } from './base' export class ViewBlock extends RectBlock implements SpecialBlock { - ctorName: string = "ViewBlock"; + ctorName: string = 'ViewBlock' cloneTo(target: this): this { - super.cloneTo(target); - target.viewName = this.viewName; - return target; + super.cloneTo(target) + target.viewName = this.viewName + return target } - removable = true; - duplicateable = true; + removable = true + duplicateable = true - boardWidth = 200; - boardHeight = 50; + boardWidth = 200 + boardHeight = 50 - viewName: string; + viewName: string get parentSocket() { - return this.getSocketByName("parent") as SingleInSocket; + return this.getSocketByName('parent') as SingleInSocket } + socketUpdater(useSocket: UseSocket): void { - useSocket("parent", SingleInSocket, { + useSocket('parent', SingleInSocket, { hideLabel: true, - type: "L", + type: 'L', path: PATH_IN_RECT, direction: Direction.LEFT, - }); + }) } contentMain = (_: Context) => { - _.$cls`absolute flex items-center left-0 top-0 justify-around text-gray-600`; - _.$css`width:${this.pageWidth}px;height:${this.pageHeight}px;`; - _.$css`transform:scale(${this.graph.boardScale})`; - _.div(this.viewName); - }; + _.$cls`absolute flex items-center left-0 top-0 justify-around text-gray-600` + _.$css`width:${this.pageWidth}px;height:${this.pageHeight}px;` + _.$css`transform:scale(${this.graph.boardScale})` + _.div(this.viewName) + } getProps(): PropsData { - return []; + return [] } protected exportData(): any { return { ...super.exportData(), viewName: this.viewName, - }; + } } + protected importData(data: any, sockets: any): void { - super.importData(data, sockets); - this.viewName = data.viewName; + super.importData(data, sockets) + this.viewName = data.viewName } toOutput(): ViewBlockOutput { return { - type: "view", + type: 'view', id: this.id, viewName: this.viewName, parent: singleInSocketToOutput(this.parentSocket), - }; + } } } -blockCtors["ViewBlock"] = ViewBlock; +blockCtors.ViewBlock = ViewBlock diff --git a/packages/northstar/src/project/autoSave.ts b/packages/northstar/src/project/autoSave.ts index b1f3751..df4bb0c 100644 --- a/packages/northstar/src/project/autoSave.ts +++ b/packages/northstar/src/project/autoSave.ts @@ -1,26 +1,29 @@ -import { Project, currentProject, setCurrentProject } from "./project"; +import { Project, currentProject, setCurrentProject } from './project' -export const STORAGE = localStorage; -export const STORAGE_KEY = "northstar"; -export const AUTOSAVE_INTERVAL = 1000; +export const STORAGE = localStorage +export const STORAGE_KEY = 'northstar' +export const AUTOSAVE_INTERVAL = 1000 export function loadAutoSaved() { - const initialStorage = STORAGE.getItem(STORAGE_KEY); + const initialStorage = STORAGE.getItem(STORAGE_KEY) if (initialStorage) { try { - setCurrentProject(Project.load(initialStorage)); - } catch (e) { - console.error(e); - alert(`Failed to load project from storage due to ${e}`); - setCurrentProject(Project.new()); + setCurrentProject(Project.load(initialStorage)) } - } else { - setCurrentProject(Project.new()); + catch (e) { + console.error(e) + // eslint-disable-next-line no-alert + alert(`Failed to load project from storage due to ${e}`) + setCurrentProject(Project.new()) + } + } + else { + setCurrentProject(Project.new()) } } export function setAutoSaveInterval() { setInterval(() => { - STORAGE.setItem(STORAGE_KEY, currentProject.dump()); - }, AUTOSAVE_INTERVAL); + STORAGE.setItem(STORAGE_KEY, currentProject.dump()) + }, AUTOSAVE_INTERVAL) } diff --git a/packages/northstar/src/project/file.ts b/packages/northstar/src/project/file.ts index 57b7055..2e9eade 100644 --- a/packages/northstar/src/project/file.ts +++ b/packages/northstar/src/project/file.ts @@ -1,34 +1,34 @@ -import { setCurrentProject, Project, currentProject } from "./project"; +import { Project, currentProject, setCurrentProject } from './project' export async function openFile() { const [handle] = await window.showOpenFilePicker({ types: [ { - description: "Quasi Studio Project", + description: 'Quasi Studio Project', accept: { - "application/json": [".q.json"], + 'application/json': ['.q.json'], }, }, ], - }); - const file = await handle.getFile(); - const json = await file.text(); - setCurrentProject(Project.load(json)); + }) + const file = await handle.getFile() + const json = await file.text() + setCurrentProject(Project.load(json)) } export async function saveAs() { const handle = await window.showSaveFilePicker({ - suggestedName: "Untitled.q.json", + suggestedName: 'Untitled.q.json', types: [ { - description: "Quasi Studio Project", + description: 'Quasi Studio Project', accept: { - "application/json": [".q.json"], + 'application/json': ['.q.json'], }, }, ], - }); - const writable = await handle.createWritable(); - await writable.write(currentProject.dump()); - await writable.close(); + }) + const writable = await handle.createWritable() + await writable.write(currentProject.dump()) + await writable.close() } diff --git a/packages/northstar/src/project/index.ts b/packages/northstar/src/project/index.ts index 1921294..9c6eb89 100644 --- a/packages/northstar/src/project/index.ts +++ b/packages/northstar/src/project/index.ts @@ -1,3 +1,3 @@ -export * from "./autoSave"; -export * from "./file"; -export * from "./project"; +export * from './autoSave' +export * from './file' +export * from './project' diff --git a/packages/northstar/src/project/project.ts b/packages/northstar/src/project/project.ts index a06537b..5a728bc 100644 --- a/packages/northstar/src/project/project.ts +++ b/packages/northstar/src/project/project.ts @@ -1,105 +1,114 @@ -import { ViewOutput } from "@quasi-dev/compiler"; -import { Graph, exportVf, importVf } from "@quasi-dev/visual-flow"; -import { isComponentBlock, toBlockOutput } from "../blocks/component"; -import { SpecialBlock } from "../blocks/special/base"; -import { RootBlock } from "../blocks/special/root.r"; +import type { ViewOutput } from '@quasi-dev/compiler' +import { Graph, exportVf, importVf } from '@quasi-dev/visual-flow' +import { isComponentBlock, toBlockOutput } from '../blocks/component' +import type { SpecialBlock } from '../blocks/special/base' +import { RootBlock } from '../blocks/special/root.r' export class Project { - name: string; + name: string views: (null | { - name: string; - graph: Graph; - })[]; - activeViewId: number; + name: string + graph: Graph + })[] + + activeViewId: number get activeView() { - return this.views[this.activeViewId]!; + return this.views[this.activeViewId]! } + get activeGraph() { - return this.views[this.activeViewId]!.graph; + return this.views[this.activeViewId]!.graph } addView() { - const graph = new Graph(); - const rootBlock = new RootBlock(); - rootBlock.boardX = 120; - rootBlock.boardY = 300; - rootBlock.attached = true; - graph.addBlock(rootBlock); - graph.captureInitialRecord(); + const graph = new Graph() + const rootBlock = new RootBlock() + rootBlock.boardX = 120 + rootBlock.boardY = 300 + rootBlock.attached = true + graph.addBlock(rootBlock) + graph.captureInitialRecord() this.views.push({ name: `view${this.views.length}`, graph, - }); + }) - return this.views.length - 1; + return this.views.length - 1 } + removeView(id: number) { - this.views.splice(id, 1); + this.views.splice(id, 1) } + setActiveView(id: number) { - this.activeGraph.clearSelectedBlocks(); - this.activeViewId = id; + this.activeGraph.clearSelectedBlocks() + this.activeViewId = id } dump(): string { const data = { name: this.name, views: this.views - .filter((view) => view !== null) - .map((view) => ({ + .filter(view => view !== null) + .map(view => ({ name: view!.name, graph: exportVf(view!.graph), })), activeViewId: this.activeViewId, - }; + } return import.meta.env.DEV ? JSON.stringify(data, null, 2) - : JSON.stringify(data); + : JSON.stringify(data) } + static load(json: string): Project { - const data = JSON.parse(json); - const project = new Project(); - project.name = data.name; + const data = JSON.parse(json) + const project = new Project() + project.name = data.name project.views = data.views.map((view: any) => ({ name: view.name, graph: importVf(view.graph), - })); - project.activeViewId = data.activeViewId; - return project; + })) + project.activeViewId = data.activeViewId + return project } + static new(): Project { - const project = new Project(); - project.name = "Untitled"; - project.views = []; - project.activeViewId = 0; - project.addView(); - project.views[0]!.name = "app"; - return project; + const project = new Project() + project.name = 'Untitled' + project.views = [] + project.activeViewId = 0 + project.addView() + project.views[0]!.name = 'app' + return project } toOutput() { - const viewsOutput: ViewOutput[] = []; - currentProject.views.forEach((view, id) => { - if (view === null) return; + const viewsOutput: ViewOutput[] = [] + // eslint-disable-next-line ts/no-use-before-define + currentProject.views.forEach(view => { + if (view === null) + return viewsOutput.push({ name: view.name, componentBlocks: view.graph.blocks .filter(isComponentBlock) .map(toBlockOutput), specialBlocks: view.graph.blocks - .filter((b) => !isComponentBlock(b)) - .map((b) => (b as unknown as SpecialBlock).toOutput()), - }); - }); + .filter(b => !isComponentBlock(b)) + .map(b => (b as unknown as SpecialBlock).toOutput()), + }) + }) return { views: viewsOutput, - }; + } } } -export let currentProject: Project; +// eslint-disable-next-line import/no-mutable-exports +export let currentProject: Project export function setCurrentProject(project: Project) { - currentProject = project; + currentProject = project } diff --git a/packages/northstar/src/utils/align.ts b/packages/northstar/src/utils/align.ts index 56f9026..aa56e3f 100644 --- a/packages/northstar/src/utils/align.ts +++ b/packages/northstar/src/utils/align.ts @@ -1,19 +1,19 @@ -import { currentProject } from "../project"; +import { currentProject } from '../project' export function hasBlocksToAlign() { - return currentProject.activeGraph.selectedBlocks.size > 1; + return currentProject.activeGraph.selectedBlocks.size > 1 } export function alignBlocksToLeft() { - const blocks = [...currentProject.activeGraph.selectedBlocks]; - const left = Math.min(...blocks.map((b) => b.boardX)); - blocks.forEach((b) => (b.boardX = left)); - currentProject.activeGraph.pushRecord(); + const blocks = [...currentProject.activeGraph.selectedBlocks] + const left = Math.min(...blocks.map(b => b.boardX)) + blocks.forEach(b => (b.boardX = left)) + currentProject.activeGraph.pushRecord() } export function alignBlocksToTop() { - const blocks = [...currentProject.activeGraph.selectedBlocks]; - const top = Math.min(...blocks.map((b) => b.boardY)); - blocks.forEach((b) => (b.boardY = top)); - currentProject.activeGraph.pushRecord(); + const blocks = [...currentProject.activeGraph.selectedBlocks] + const top = Math.min(...blocks.map(b => b.boardY)) + blocks.forEach(b => (b.boardY = top)) + currentProject.activeGraph.pushRecord() } diff --git a/packages/northstar/src/utils/duplicateBlocks.ts b/packages/northstar/src/utils/duplicateBlocks.ts index 626c56f..8ee8419 100644 --- a/packages/northstar/src/utils/duplicateBlocks.ts +++ b/packages/northstar/src/utils/duplicateBlocks.ts @@ -1,33 +1,33 @@ -import { GraphStateType } from "@quasi-dev/visual-flow"; -import { currentProject } from "../project"; +import { GraphStateType } from '@quasi-dev/visual-flow' +import { currentProject } from '../project' function isDuplicateable(block: any) { - return block.duplicateable; + return block.duplicateable } export function hasBlocksToDuplicate() { if (currentProject.activeGraph.state.type === GraphStateType.DRAGGING_BLOCK) - return false; + return false return ( [...currentProject.activeGraph.selectedBlocks].filter(isDuplicateable) .length > 0 - ); + ) } export function duplicateBlocks() { const blocks = [...currentProject.activeGraph.selectedBlocks].filter( isDuplicateable, - ); - currentProject.activeGraph.clearSelectedBlocks(); - blocks.forEach((block) => { - const newBlock = block.clone(); - newBlock.boardX = block.boardX + 90; - newBlock.boardY = block.boardY + 90; - newBlock.attached = true; - currentProject.activeGraph.addBlock(newBlock); - currentProject.activeGraph.moveBlockToTop(newBlock); - currentProject.activeGraph.updateBlockZIndex(); - currentProject.activeGraph.addSelectedBlock(newBlock, true); - }); - currentProject.activeGraph.pushRecord(); + ) + currentProject.activeGraph.clearSelectedBlocks() + blocks.forEach(block => { + const newBlock = block.clone() + newBlock.boardX = block.boardX + 90 + newBlock.boardY = block.boardY + 90 + newBlock.attached = true + currentProject.activeGraph.addBlock(newBlock) + currentProject.activeGraph.moveBlockToTop(newBlock) + currentProject.activeGraph.updateBlockZIndex() + currentProject.activeGraph.addSelectedBlock(newBlock, true) + }) + currentProject.activeGraph.pushRecord() } diff --git a/packages/northstar/src/utils/index.ts b/packages/northstar/src/utils/index.ts index ca3f876..1306732 100644 --- a/packages/northstar/src/utils/index.ts +++ b/packages/northstar/src/utils/index.ts @@ -1,6 +1,6 @@ -export * from "./align"; -export * from "./duplicateBlocks"; -export * from "./monaco"; -export * from "./removeBlocks"; -export * from "./props"; -export * from "./toOutput"; +export * from './align' +export * from './duplicateBlocks' +export * from './monaco' +export * from './removeBlocks' +export * from './props' +export * from './toOutput' diff --git a/packages/northstar/src/utils/monaco.ts b/packages/northstar/src/utils/monaco.ts index 903d1c2..e7d7690 100644 --- a/packages/northstar/src/utils/monaco.ts +++ b/packages/northstar/src/utils/monaco.ts @@ -1,42 +1,44 @@ -import { monaco } from "@quasi-dev/monaco-editor"; -import * as prettier from "prettier"; -import BabelPlugin from "prettier/plugins/babel"; -import mdui2Dts from "@quasi-dev/mdui2-dts"; -//@ts-ignore -import EsTreePlugin from "prettier/plugins/estree"; +import { monaco } from '@quasi-dev/monaco-editor' +import * as prettier from 'prettier' +import BabelPlugin from 'prettier/plugins/babel' +import mdui2Dts from '@quasi-dev/mdui2-dts' + +// @ts-expect-error missing type +import EsTreePlugin from 'prettier/plugins/estree' export function initMonaco() { const formatProvider = { provideDocumentFormattingEdits: async (model, options, _token) => [ { text: await prettier.format(model.getValue(), { - parser: "babel", + parser: 'babel', plugins: [BabelPlugin, EsTreePlugin], - arrowParens: "avoid", + arrowParens: 'avoid', tabWidth: options.tabSize, }), range: model.getFullModelRange() as monaco.IRange, }, ], - } as monaco.languages.DocumentFormattingEditProvider; + } as monaco.languages.DocumentFormattingEditProvider monaco.languages.registerDocumentFormattingEditProvider( - "javascript", + 'javascript', formatProvider, - ); + ) monaco.languages.typescript.javascriptDefaults.addExtraLib( mdui2Dts, - "mdui.d.ts", - ); + 'mdui.d.ts', + ) } -let currentExtraLib = ""; +let currentExtraLib = '' export function setExtraLib(code: string) { - if (currentExtraLib === code) return; + if (currentExtraLib === code) + return monaco.languages.typescript.javascriptDefaults.addExtraLib( code, - "context.d.ts", - ); - currentExtraLib = code; + 'context.d.ts', + ) + currentExtraLib = code } diff --git a/packages/northstar/src/utils/props.ts b/packages/northstar/src/utils/props.ts index 456c79e..75b307c 100644 --- a/packages/northstar/src/utils/props.ts +++ b/packages/northstar/src/utils/props.ts @@ -1,40 +1,40 @@ -import { currentProject } from "../project"; +import { currentProject } from '../project' export interface PropDataBase { - key: string; - displayName: string; + key: string + displayName: string } export interface TextPropData extends PropDataBase { - type: "text"; - getVal(): string; - setVal(val: string): void; + type: 'text' + getVal: () => string + setVal: (val: string) => void } export interface SwitchPropData extends PropDataBase { - type: "switch"; - getVal(): boolean; - setVal(val: boolean): void; + type: 'switch' + getVal: () => boolean + setVal: (val: boolean) => void } export interface DropdownPropData extends PropDataBase { - type: "dropdown"; - options: string[]; - getVal(): string; - setVal(val: string): void; + type: 'dropdown' + options: string[] + getVal: () => string + setVal: (val: string) => void } export interface ReadonlyPropData extends PropDataBase { - type: "readonly"; - getVal(): string; + type: 'readonly' + getVal: () => string /** * @deprecated */ - setVal(val: string): void; + setVal: (val: string) => void } export interface NumberPropData extends PropDataBase { - type: "number"; - min: number; - max: number; - getVal(): number; - setVal(val: number): void; + type: 'number' + min: number + max: number + getVal: () => number + setVal: (val: number) => void } export type PropData = @@ -42,27 +42,26 @@ export type PropData = | SwitchPropData | DropdownPropData | ReadonlyPropData - | NumberPropData; -export type PropsData = PropData[]; + | NumberPropData +export type PropsData = PropData[] export function mergeProps([props0, ...propsRest]: PropsData[]) { - const mergedProps: PropsData = []; + const mergedProps: PropsData = [] for (const v of props0) { if ( - propsRest.every((ps) => - ps.some((p) => p.displayName === v.displayName && p.type === v.type), + propsRest.every(ps => + ps.some(p => p.displayName === v.displayName && p.type === v.type), ) - ) { - mergedProps.push(v); - } + ) + mergedProps.push(v) } - return mergedProps; + return mergedProps } export function getSelectedProps(): PropsData { return mergeProps( [...currentProject.activeGraph.selectedBlocks].map( - (b) => (b as any).getProps?.() ?? [], + b => (b as any).getProps?.() ?? [], ), - ); + ) } diff --git a/packages/northstar/src/utils/removeBlocks.ts b/packages/northstar/src/utils/removeBlocks.ts index ce580e3..bcd7805 100644 --- a/packages/northstar/src/utils/removeBlocks.ts +++ b/packages/northstar/src/utils/removeBlocks.ts @@ -1,31 +1,32 @@ -import { GraphStateType, Socket } from "@quasi-dev/visual-flow"; -import { currentProject } from "../project"; +import type { Socket } from '@quasi-dev/visual-flow' +import { GraphStateType } from '@quasi-dev/visual-flow' +import { currentProject } from '../project' function isRemovable(block: any) { - return block.removable; + return block.removable } export function hasBlocksToRemove() { if (currentProject.activeGraph.state.type === GraphStateType.DRAGGING_BLOCK) - return false; + return false return ( - [...currentProject.activeGraph.selectedBlocks].filter(isRemovable).length > - 0 - ); + [...currentProject.activeGraph.selectedBlocks].filter(isRemovable).length + > 0 + ) } export function removeBlocks() { [...currentProject.activeGraph.selectedBlocks] .filter(isRemovable) - .forEach((block) => { - block.allSockets.forEach((socket) => { - socket.allConnectedLines.forEach((line) => { + .forEach(block => { + block.allSockets.forEach(socket => { + socket.allConnectedLines.forEach(line => { line.a.disconnectTo(line); - (line.b as Socket).disconnectTo(line); - currentProject.activeGraph.removeLine(line); - }); - }); - currentProject.activeGraph.removeBlock(block); - currentProject.activeGraph.pushRecord(); - }); + (line.b as Socket).disconnectTo(line) + currentProject.activeGraph.removeLine(line) + }) + }) + currentProject.activeGraph.removeBlock(block) + currentProject.activeGraph.pushRecord() + }) } diff --git a/packages/northstar/src/utils/toOutput.ts b/packages/northstar/src/utils/toOutput.ts index 331d22c..ac44b34 100644 --- a/packages/northstar/src/utils/toOutput.ts +++ b/packages/northstar/src/utils/toOutput.ts @@ -1,48 +1,48 @@ -import type { ConnectTo } from "@quasi-dev/compiler"; +import type { ConnectTo } from '@quasi-dev/compiler' import type { MultiInSocket, MultiOutSocket, SingleInSocket, SingleOutSocket, Socket, -} from "@quasi-dev/visual-flow"; +} from '@quasi-dev/visual-flow' export function multiInSocketToOutput( socket: MultiInSocket | undefined, ): ConnectTo[] { return ( - socket?.allConnectedLines.map((l) => ({ + socket?.allConnectedLines.map(l => ({ blockId: l.a.block.id, socketName: l.a.label, })) ?? [] - ); + ) } export function multiOutSocketToOutput( socket: MultiOutSocket | undefined, ): ConnectTo[] { return ( - socket?.allConnectedLines.map((l) => ({ + socket?.allConnectedLines.map(l => ({ blockId: (l.b as Socket).block.id, socketName: (l.b as Socket).label, })) ?? [] - ); + ) } export function singleInSocketToOutput( socket: SingleInSocket | undefined, ): ConnectTo { return { - blockId: socket?.connectedLine?.a.block.id ?? NaN, - socketName: socket?.connectedLine?.a.label ?? "", - }; + blockId: socket?.connectedLine?.a.block.id ?? Number.NaN, + socketName: socket?.connectedLine?.a.label ?? '', + } } export function singleOutSocketToOutput( socket: SingleOutSocket | undefined, ): ConnectTo { return { - blockId: (socket?.connectedLine?.b as Socket | undefined)?.block.id ?? NaN, - socketName: (socket?.connectedLine?.b as Socket | undefined)?.label ?? "", - }; + blockId: (socket?.connectedLine?.b as Socket | undefined)?.block.id ?? Number.NaN, + socketName: (socket?.connectedLine?.b as Socket | undefined)?.label ?? '', + } } diff --git a/packages/northstar/src/views/blocks.r.ts b/packages/northstar/src/views/blocks.r.ts index 6e0d48a..816960c 100644 --- a/packages/northstar/src/views/blocks.r.ts +++ b/packages/northstar/src/views/blocks.r.ts @@ -1,125 +1,127 @@ -import { componentInfoArray } from "@quasi-dev/runtime"; -import { FiEdit20Filled, FiEdit20Regular } from "@refina/fluentui-icons/edit"; -import { byIndex, $view } from "refina"; -import { ComponentBlock } from "../blocks/component/block"; -import special from "../blocks/special"; -import { ViewBlock } from "../blocks/special/view.r"; -import { currentProject } from "../project"; -import { app } from "../app.r"; +import { componentInfoArray } from '@quasi-dev/runtime' +import { FiEdit20Filled, FiEdit20Regular } from '@refina/fluentui-icons/edit' +import { $view, byIndex } from 'refina' +import { ComponentBlock } from '../blocks/component/block' +import special from '../blocks/special' +import { ViewBlock } from '../blocks/special/view.r' +import { currentProject } from '../project' +import { app } from '../app.r' export default $view(_ => { - if (_.fAccordion("Special", false, true)) { - _.$cls`grid grid-cols-3 justify-items-center`; + if (_.fAccordion('Special', false, true)) { + _.$cls`grid grid-cols-3 justify-items-center` _.div(_ => { _.for( special, ([k]: any) => k, - ([k, v]) => { - _.$cls`cursor-pointer`; + ([k, Ctor]) => { + _.$cls`cursor-pointer` _.vfCreator( currentProject.activeGraph, _ => { - _.$cls`my-1`; + _.$cls`my-1` _.div(_ => { - _.img("https://via.placeholder.com/80x80?text=" + k); - _.$cls`text-center text-sm overflow-hidden`; - _.div(k); - }); + _.img(`https://via.placeholder.com/80x80?text=${k}`) + _.$cls`text-center text-sm overflow-hidden` + _.div(k) + }) }, () => { - const block = new v(); - return block; + const block = new Ctor() + return block }, - ); + ) }, - ); - }); + ) + }) } - if (_.fAccordion("Components", false, true)) { - _.$cls`grid grid-cols-3 justify-items-center`; + if (_.fAccordion('Components', false, true)) { + _.$cls`grid grid-cols-3 justify-items-center` _.div(_ => { _.for( componentInfoArray, ([k]: any) => k, ([k, v]) => { - _.$cls`cursor-pointer`; + _.$cls`cursor-pointer` _.vfCreator( currentProject.activeGraph, _ => { - _.$cls`my-1`; + _.$cls`my-1` _.div(_ => { - _.img("https://via.placeholder.com/80x80?text=" + k); - _.$cls`text-center text-sm overflow-hidden`; - _.div(v.displayName({})); - }); + _.img(`https://via.placeholder.com/80x80?text=${k}`) + _.$cls`text-center text-sm overflow-hidden` + _.div(v.displayName({})) + }) }, () => { - const block = new ComponentBlock(); - block.setComponentType(k, v); - return block; + const block = new ComponentBlock() + block.setComponentType(k, v) + return block }, - ); + ) }, - ); - }); + ) + }) } - if (_.fAccordion("Views", false, true)) { - _.$cls`grid grid-cols-3 justify-items-center`; + if (_.fAccordion('Views', false, true)) { + _.$cls`grid grid-cols-3 justify-items-center` _.div(_ => { _.for(currentProject.views, byIndex, (view, id) => { - if (view === null) return; + if (view === null) + return - const editingThis = id === currentProject.activeViewId; + const editingThis = id === currentProject.activeViewId - _.$cls`my-1 cursor-pointer`; + _.$cls`my-1 cursor-pointer` _.vfCreator( currentProject.activeGraph, _ => { - _.img("https://via.placeholder.com/80x80?text=" + view.name); - _.$cls`text-center text-sm flex-nowrap`; + _.img(`https://via.placeholder.com/80x80?text=${view.name}`) + _.$cls`text-center text-sm flex-nowrap` _.div(_ => { - _.span(view.name); + _.span(view.name) if (editingThis) { - _.$cls`float-right mr-1 text-gray-500`; - _.div(_ => _(FiEdit20Filled)()); - } else { - _.$cls`float-right mr-1 hover:bg-gray-300`; + _.$cls`float-right mr-1 text-gray-500` + _.div(_ => _(FiEdit20Filled)()) + } + else { + _.$cls`float-right mr-1 hover:bg-gray-300` _._div( { onmousedown: ev => ev.stopPropagation(), onclick: () => { - currentProject.setActiveView(id); - app.update(); + currentProject.setActiveView(id) + app.update() }, }, _ => _(FiEdit20Regular)(), - ); + ) } - }); + }) }, () => { - const block = new ViewBlock(); - block.viewName = view.name; - return block; + const block = new ViewBlock() + block.viewName = view.name + return block }, id === 0 || editingThis, - ); - }); - _.$cls`my-1 hover:border-2 hover:border-gray-400 cursor-pointer`; + ) + }) + _.$cls`my-1 hover:border-2 hover:border-gray-400 cursor-pointer` _._div( { onclick: () => { - const id = currentProject.addView(); - currentProject.setActiveView(id); - app.update(); + const id = currentProject.addView() + currentProject.setActiveView(id) + app.update() }, }, _ => { - _.img("https://via.placeholder.com/80x80?text=%2B"); - _.$cls`w-full text-center text-sm flex-nowrap`; - _.div("New View"); + _.img('https://via.placeholder.com/80x80?text=%2B') + _.$cls`w-full text-center text-sm flex-nowrap` + _.div('New View') }, - ); - }); + ) + }) } -}); +}) diff --git a/packages/northstar/src/views/preview.r.ts b/packages/northstar/src/views/preview.r.ts index 4bb3824..5ee447f 100644 --- a/packages/northstar/src/views/preview.r.ts +++ b/packages/northstar/src/views/preview.r.ts @@ -1,120 +1,129 @@ /// -import { compileTailwindCSS } from "@quasi-dev/browser-tailwind"; -import { Compiler } from "@quasi-dev/compiler"; -import { transformFragment } from "@refina/transformer"; -import { $view, HTMLElementComponent, ref } from "refina"; -import { app } from "../app.r"; -import { currentProject } from "../project"; - -import runtimeURL from "@quasi-dev/runtime/src/index.ts?url"; -import mduiStyleContent from "@quasi-dev/runtime/styles.css?inline"; // Used in production -import mduiStyleUrl from "@quasi-dev/runtime/styles.css?url"; // Used in development -import iframeURL from "./iframe/index.html?url"; - -let code = { - js: "", - css: "", -}; -let codeModified = true; -let errorReported = false; -const iframe = ref>(); -let errorMsg = ""; +import { compileTailwindCSS } from '@quasi-dev/browser-tailwind' +import { Compiler } from '@quasi-dev/compiler' +import { transformFragment } from '@refina/transformer' +import type { HTMLElementComponent } from 'refina' +import { $view, ref } from 'refina' + +import runtimeURL from '@quasi-dev/runtime/src/index.ts?url' + +import mduiStyleContent from '@quasi-dev/runtime/styles.css?inline' + +// Used in production +import mduiStyleUrl from '@quasi-dev/runtime/styles.css?url' +import { currentProject } from '../project' + +// Used in development +import { app } from '../app.r' +import iframeURL from './iframe/index.html?url' + +const code = { + js: '', + css: '', +} +let codeModified = true +let errorReported = false +const iframe = ref>() +let errorMsg = '' export async function startPreview() { - const compiler = new Compiler(currentProject.toOutput()); - compiler.runtimeModuleURL = runtimeURL; - code.js = - "window.__QUASI_PREVIEW__ = true; \n\n" + - transformFragment(await compiler.compile(), idx => idx.toString(36)); + const compiler = new Compiler(currentProject.toOutput()) + compiler.runtimeModuleURL = runtimeURL + code.js + = `window.__QUASI_PREVIEW__ = true; \n\n${ + transformFragment(await compiler.compile(), idx => idx.toString(36))}` code.css = ( await compileTailwindCSS( `@tailwind base; @tailwind components; @tailwind utilities;`, code.js, - "js", + 'js', ) - ).css; - codeModified = true; - errorReported = false; - errorMsg = ""; + ).css + codeModified = true + errorReported = false + errorMsg = '' } export default $view(_ => { if (errorMsg.length > 0) { - _.$cls`text-red-900 border border-red-500`; - _._pre({}, errorMsg); + _.$cls`text-red-900 border border-red-500` + _._pre({}, errorMsg) } - _.$ref(iframe) && - _._iframe({ - // src: iframeURL, - frameBorder: "0", - width: "100%", - height: "100%", - }); - - _.$updateContext && - _.$app.pushOnetimeHook("afterModifyDOM", () => { - if (!_.$updateContext || !codeModified) return; - codeModified = false; - const iframeNode = iframe.current!.node; - - iframeNode.src = iframeURL; - iframeNode.onload = () => { - if (errorMsg !== "") { - errorMsg = ""; - app.update(); - } - - iframeNode.contentWindow!.onerror = ( - event: Event | string, - source?: string, - lineno?: number, - colno?: number, - error?: Error, - ) => { - if (errorReported) return; - - errorMsg = `ERROR: ${event} + _.$ref(iframe) + && _._iframe({ + // src: iframeURL, + frameBorder: '0', + width: '100%', + height: '100%', + }) + + _.$updateContext + && _.$app.pushOnetimeHook('afterModifyDOM', () => { + if (!_.$updateContext || !codeModified) + return + codeModified = false + const iframeNode = iframe.current!.node + + iframeNode.src = iframeURL + iframeNode.onload = () => { + if (errorMsg !== '') { + errorMsg = '' + app.update() + } + + iframeNode.contentWindow!.onerror = ( + event: Event | string, + source?: string, + lineno?: number, + colno?: number, + error?: Error, + ) => { + if (errorReported) + return + + errorMsg = `ERROR: ${event} source: ${source} lineno: ${lineno} colno: ${colno} -error: ${error}`; - - app.update(); - errorReported = true; - }; - //@ts-ignore - iframeNode.contentWindow!.console.error = (...args: any[]) => { - errorMsg += "\nCONSOLE ERROR: \n" + args.join(" "); - console.error(...args); - app.update(); - }; - - const scriptNode = iframeNode.contentDocument!.getElementById( - "app-script", - ) as HTMLScriptElement; - scriptNode.innerHTML = code.js; +error: ${error}` + + app.update() + errorReported = true + } + // @ts-expect-error missing type + iframeNode.contentWindow!.console.error = (...args: any[]) => { + errorMsg += `\nCONSOLE ERROR: \n${args.join(' ')}` + console.error(...args) + app.update() + } + const scriptNode = iframeNode.contentDocument!.getElementById( + 'app-script', + ) as HTMLScriptElement + scriptNode.innerHTML = code.js + + const styleNode = iframeNode.contentDocument!.getElementById( + 'app-style', + ) as HTMLStyleElement + styleNode.innerHTML = code.css + + if (import.meta.env.DEV) { + const styleNode = iframeNode.contentDocument!.getElementById( + 'mdui-style-dev', + ) as HTMLLinkElement + styleNode.href = mduiStyleUrl + } + else { const styleNode = iframeNode.contentDocument!.getElementById( - "app-style", - ) as HTMLStyleElement; - styleNode.innerHTML = code.css; - - if (import.meta.env.DEV) { - const styleNode = iframeNode.contentDocument!.getElementById( - "mdui-style-dev", - ) as HTMLLinkElement; - styleNode.href = mduiStyleUrl; - } else { - const styleNode = iframeNode.contentDocument!.getElementById( - "mdui-style", - ) as HTMLStyleElement; - styleNode.innerHTML = mduiStyleContent; - } - }; - }); -}); + 'mdui-style', + ) as HTMLStyleElement + styleNode.innerHTML = mduiStyleContent + } + } + }) +}) diff --git a/packages/northstar/src/views/properties.r.ts b/packages/northstar/src/views/properties.r.ts index 53f61ae..dcb77b6 100644 --- a/packages/northstar/src/views/properties.r.ts +++ b/packages/northstar/src/views/properties.r.ts @@ -1,66 +1,70 @@ -import { FiAdd20Filled } from "@refina/fluentui-icons/add"; -import { FiSubtract20Filled } from "@refina/fluentui-icons/subtract"; -import { $view, PrimaryElRef, ref } from "refina"; -import { getSelectedProps } from "../utils/props"; +import { FiAdd20Filled } from '@refina/fluentui-icons/add' +import { FiSubtract20Filled } from '@refina/fluentui-icons/subtract' +import type { PrimaryElRef } from 'refina' +import { $view, ref } from 'refina' +import { getSelectedProps } from '../utils/props' export default $view(_ => { - const props = getSelectedProps(); - _.for(props, "key", p => { - const r = ref() as PrimaryElRef; - _.$cls`col-span-1 flex justify-center items-center border-b border-gray-500 h-8`; + const props = getSelectedProps() + _.for(props, 'key', p => { + const r = ref() as PrimaryElRef + _.$cls`col-span-1 flex justify-center items-center border-b border-gray-500 h-8` _._div( { onclick: () => { ( r.current?.$primaryEl?.node.firstChild as - | HTMLElement - | null - | undefined - )?.focus(); + | HTMLElement + | null + | undefined + )?.focus() }, }, p.displayName, - ); - _.$cls`col-span-2 h-8`; - if (p.type === "text") { - _.$ref(r); - _.fUnderlineInput(p.getVal(), false, "unset") && p.setVal(_.$ev); - } else if (p.type === "switch") { - _.$cls`ml-4`; - _.fSwitch("", p.getVal()) && p.setVal(_.$ev); - } else if (p.type === "dropdown") { - _.$ref(r); - if (_.fDropdown(p.getVal(), p.options)) { - p.setVal(_.$ev); - } - } else if (p.type === "readonly") { - _.$cls`w-full border-b border-gray-500 flex items-center pl-2`; - _.div(p.getVal()); - } else if (p.type === "number") { - const value = p.getVal(); - _.$cls`w-full grid grid-cols-4 items-center px-2`; + ) + _.$cls`col-span-2 h-8` + if (p.type === 'text') { + _.$ref(r) + _.fUnderlineInput(p.getVal(), false, 'unset') && p.setVal(_.$ev) + } + else if (p.type === 'switch') { + _.$cls`ml-4` + _.fSwitch('', p.getVal()) && p.setVal(_.$ev) + } + else if (p.type === 'dropdown') { + _.$ref(r) + if (_.fDropdown(p.getVal(), p.options)) + p.setVal(_.$ev) + } + else if (p.type === 'readonly') { + _.$cls`w-full border-b border-gray-500 flex items-center pl-2` + _.div(p.getVal()) + } + else if (p.type === 'number') { + const value = p.getVal() + _.$cls`w-full grid grid-cols-4 items-center px-2` _.div(() => { const btnStyle = () => - _.$cls`w-5 h-5 p-[2px] box-content font-bold border-2 border-gray-500 rounded hover:border-gray-800 disabled:opacity-50`; + _.$cls`w-5 h-5 p-[2px] box-content font-bold border-2 border-gray-500 rounded hover:border-gray-800 disabled:opacity-50` - btnStyle(); - _.$cls`justify-self-end`; - _.button(_ => _(FiSubtract20Filled)(), value === p.min) && - p.setVal(value - 1); + btnStyle() + _.$cls`justify-self-end` + _.button(_ => _(FiSubtract20Filled)(), value === p.min) + && p.setVal(value - 1) - _.$cls`col-span-2 justify-self-center`; - _.span(value.toString()); + _.$cls`col-span-2 justify-self-center` + _.span(value.toString()) - btnStyle(); - _.$cls`justify-self-start`; - _.button(_ => _(FiAdd20Filled)(), value === p.max) && - p.setVal(value + 1); - }); + btnStyle() + _.$cls`justify-self-start` + _.button(_ => _(FiAdd20Filled)(), value === p.max) + && p.setVal(value + 1) + }) } - }); + }) if (props.length === 0) { - _.$cls`italic ml-4 mt-1 whitespace-nowrap`; - _.span("No properties"); + _.$cls`italic ml-4 mt-1 whitespace-nowrap` + _.span('No properties') } -}); +}) diff --git a/packages/northstar/src/views/toolbar.r.ts b/packages/northstar/src/views/toolbar.r.ts index 5e41fc1..0fab281 100644 --- a/packages/northstar/src/views/toolbar.r.ts +++ b/packages/northstar/src/views/toolbar.r.ts @@ -1,39 +1,41 @@ -import { Compiler } from "@quasi-dev/compiler"; -import { +import { Compiler } from '@quasi-dev/compiler' +import type { FFieldValidationState, FProgressBarColor, FProgressBarValue, -} from "@refina/fluentui"; -import { FiAddSquareMultiple20Regular } from "@refina/fluentui-icons/addSquareMultiple"; -import { FiAlignLeft20Regular } from "@refina/fluentui-icons/alignLeft"; -import { FiAlignTop20Regular } from "@refina/fluentui-icons/alignTop"; -import { FiArrowRedo20Filled } from "@refina/fluentui-icons/arrowRedo"; -import { FiArrowUndo20Filled } from "@refina/fluentui-icons/arrowUndo"; -import { FiDelete20Regular } from "@refina/fluentui-icons/delete"; -import { FiDocumentBulletList20Regular } from "@refina/fluentui-icons/documentBulletList"; -import { FiDrawerArrowDownload20Regular } from "@refina/fluentui-icons/drawerArrowDownload"; -import { FiImageBorder20Regular } from "@refina/fluentui-icons/imageBorder"; -import { FiResizeLarge20Regular } from "@refina/fluentui-icons/resizeLarge"; -import { FiResizeSmall20Regular } from "@refina/fluentui-icons/resizeSmall"; -import { domToBlob } from "modern-screenshot"; +} from '@refina/fluentui' +import { FiAddSquareMultiple20Regular } from '@refina/fluentui-icons/addSquareMultiple' +import { FiAlignLeft20Regular } from '@refina/fluentui-icons/alignLeft' +import { FiAlignTop20Regular } from '@refina/fluentui-icons/alignTop' +import { FiArrowRedo20Filled } from '@refina/fluentui-icons/arrowRedo' +import { FiArrowUndo20Filled } from '@refina/fluentui-icons/arrowUndo' +import { FiDelete20Regular } from '@refina/fluentui-icons/delete' +import { FiDocumentBulletList20Regular } from '@refina/fluentui-icons/documentBulletList' +import { FiDrawerArrowDownload20Regular } from '@refina/fluentui-icons/drawerArrowDownload' +import { FiImageBorder20Regular } from '@refina/fluentui-icons/imageBorder' +import { FiResizeLarge20Regular } from '@refina/fluentui-icons/resizeLarge' +import { FiResizeSmall20Regular } from '@refina/fluentui-icons/resizeSmall' +import { domToBlob } from 'modern-screenshot' +import type { + Content, + HTMLElementComponent, +} from 'refina' import { $view, Component, - Content, - HTMLElementComponent, _, model, propModel, ref, -} from "refina"; -import { app } from "../app.r"; +} from 'refina' +import { app } from '../app.r' import { Project, currentProject, openFile, saveAs, setCurrentProject, -} from "../project"; +} from '../project' import { alignBlocksToLeft, alignBlocksToTop, @@ -42,11 +44,11 @@ import { hasBlocksToDuplicate, hasBlocksToRemove, removeBlocks, -} from "../utils"; -import { startPreview } from "./preview.r"; -import iconURL from "/favicon.ico?url"; +} from '../utils' +import { startPreview } from './preview.r' +import iconURL from '/favicon.ico?url' -export const previewMode = model(false); +export const previewMode = model(false) class ToolItem extends Component { $main( @@ -57,68 +59,71 @@ class ToolItem extends Component { ) { _.fTooltip( _ => - _.$cls`disabled:opacity-30 h-full flex items-center enabled:hover:bg-gray-300 px-2` && - _.button(buttonContent, disabled) && - callback(), + _.$cls`disabled:opacity-30 h-full flex items-center enabled:hover:bg-gray-300 px-2` + && _.button(buttonContent, disabled) + && callback(), tip, - ); + ) } } -let buildOutput = ""; +let buildOutput = '' -let exportToPNGProgess: FProgressBarValue = 0; -let exportToPNGColor: FProgressBarColor = "brand"; -let exportToPNGValidationState: FFieldValidationState = "none"; -let exportToPNGMessage = `Click the "Export" button above to start`; +let exportToPNGProgess: FProgressBarValue = 0 +let exportToPNGColor: FProgressBarColor = 'brand' +let exportToPNGValidationState: FFieldValidationState = 'none' +let exportToPNGMessage = `Click the "Export" button above to start` -export const graphElRef = ref>(); +export const graphElRef = ref>() export default $view(_ => { - _.$cls`flex items-center h-full`; + _.$cls`flex items-center h-full` _.div(_ => { - _.$cls`w-[2em] h-[2em] invert`; - _._img({ src: iconURL }); + _.$cls`w-[2em] h-[2em] invert` + _._img({ src: iconURL }) - _.$cls`font-bold text-lg pr-2`; - _.span("Quasi Studio"); + _.$cls`font-bold text-lg pr-2` + _.span('Quasi Studio') _.fDialog( open => { _.fTooltip( _ => - _.$cls`h-full flex items-center hover:bg-gray-300 px-2` && - _.button(_ => _(FiDocumentBulletList20Regular)()) && - open(), - "File", - ); + _.$cls`h-full flex items-center hover:bg-gray-300 px-2` + && _.button(_ => _(FiDocumentBulletList20Regular)()) + && open(), + 'File', + ) }, - "File", + 'File', close => { - _.$cls`flex flex-col gap-4`; + _.$cls`flex flex-col gap-4` _.div(_ => { - _.fButton("New") && (setCurrentProject(Project.new()), close()); - _.fButton("Open") && openFile().then(close); + if (_.fButton('New')) { + setCurrentProject(Project.new()) + close() + } + _.fButton('Open') && openFile().then(close) // _.fButton("Save"); - _.fButton("Save as") && saveAs().then(close); - }); + _.fButton('Save as') && saveAs().then(close) + }) }, - ); + ) if ( _.fDialog( open => { _.fTooltip( _ => - _.$cls`h-full flex items-center hover:bg-gray-300 px-2` && - _.button(_ => _(FiDrawerArrowDownload20Regular)()) && - open(), - "Build", - ); + _.$cls`h-full flex items-center hover:bg-gray-300 px-2` + && _.button(_ => _(FiDrawerArrowDownload20Regular)()) + && open(), + 'Build', + ) }, - "Build", - close => { - _.$cls`block h-56 w-full border-2 overflow-y-scroll rounded shadow-inner border-gray-400 p-3 font-[Consolas]`; + 'Build', + () => { + _.$cls`block h-56 w-full border-2 overflow-y-scroll rounded shadow-inner border-gray-400 p-3 font-[Consolas]` _._textarea( { onwheel: e => e.stopPropagation(), @@ -128,29 +133,31 @@ export default $view(_ => { onkeydown: e => e.stopPropagation(), }, buildOutput, - ); + ) }, ) ) { if (_.$ev) { try { - const compiler = new Compiler(currentProject.toOutput()); + const compiler = new Compiler(currentProject.toOutput()) compiler .compile() .then(v => { - buildOutput = v; - app.update(); + buildOutput = v + app.update() }) .catch(err => { - buildOutput = `Compile ${err}`; - app.update(); - }); - } catch (e) { - buildOutput = `${e}`; - console.error(e); + buildOutput = `Compile ${err}` + app.update() + }) + } + catch (e) { + buildOutput = `${e}` + console.error(e) } - } else { - buildOutput = "Building..."; + } + else { + buildOutput = 'Building...' } } @@ -158,199 +165,199 @@ export default $view(_ => { _.fDialog( open => _(ToolItem)( - "Export to PNG", + 'Export to PNG', _ => _(FiImageBorder20Regular)(), currentProject.activeGraph.blocks.length === 0, open, ), - "Export to PNG", + 'Export to PNG', close => { - _.$cls`mb-5`; - _._div(); + _.$cls`mb-5` + _._div() - if (_.fPrimaryButton("Export", exportToPNGProgess !== 0)) { - exportToPNGMessage = "Generating..."; + if (_.fPrimaryButton('Export', exportToPNGProgess !== 0)) { + exportToPNGMessage = 'Generating...' - const node = graphElRef.current!.node; + const node = graphElRef.current!.node - const { boardOffsetX, boardOffsetY, boardScale } = - currentProject.activeGraph; + const { boardOffsetX, boardOffsetY, boardScale } + = currentProject.activeGraph const restoreBoard = () => { - currentProject.activeGraph.boardOffsetX = boardOffsetX; - currentProject.activeGraph.boardOffsetY = boardOffsetY; - currentProject.activeGraph.boardScale = boardScale; - }; - const { width, height } = currentProject.activeGraph.fullView(); - currentProject.activeGraph.updatePosition(); + currentProject.activeGraph.boardOffsetX = boardOffsetX + currentProject.activeGraph.boardOffsetY = boardOffsetY + currentProject.activeGraph.boardScale = boardScale + } + const { width, height } = currentProject.activeGraph.fullView() + currentProject.activeGraph.updatePosition() setTimeout(() => { - const { x, y } = node.getBoundingClientRect(); + const { x, y } = node.getBoundingClientRect() domToBlob(node, { - backgroundColor: "white", + backgroundColor: 'white', scale: 4 / currentProject.activeGraph.boardScale, - width: width, - height: height, + width, + height, style: { transform: `translate(-${x}px, -${y}px)`, }, - filter: node => (node as Element).id !== "vf-thumbnail", + filter: node => (node as Element).id !== 'vf-thumbnail', timeout: 30000, }) .then(async blob => { - exportToPNGProgess = 0.7; - exportToPNGMessage = "Saving..."; - app.update(); + exportToPNGProgess = 0.7 + exportToPNGMessage = 'Saving...' + app.update() const handle = await window.showSaveFilePicker({ - suggestedName: "quasi-graph.png", + suggestedName: 'quasi-graph.png', types: [ { - description: "PNG", + description: 'PNG', accept: { - "image/png": [".png"], + 'image/png': ['.png'], }, }, ], - }); + }) - const writable = await handle.createWritable(); - exportToPNGProgess = 0.8; - app.update(); + const writable = await handle.createWritable() + exportToPNGProgess = 0.8 + app.update() - await writable.write(await blob.arrayBuffer()); - exportToPNGProgess = 0.9; - app.update(); + await writable.write(await blob.arrayBuffer()) + exportToPNGProgess = 0.9 + app.update() - await writable.close(); - exportToPNGProgess = 1; - exportToPNGMessage = "Done"; - exportToPNGValidationState = "success"; + await writable.close() + exportToPNGProgess = 1 + exportToPNGMessage = 'Done' + exportToPNGValidationState = 'success' - app.update(); + app.update() - await new Promise(resolve => setTimeout(resolve, 500)); - close(); + await new Promise(resolve => setTimeout(resolve, 500)) + close() }) .catch(err => { - if (err instanceof Error && err.name === "AbortError") { - close(); - return; + if (err instanceof Error && err.name === 'AbortError') { + close() + return } - exportToPNGProgess = 0; - exportToPNGColor = "success"; - exportToPNGColor = "error"; - exportToPNGMessage = `${err}`; - exportToPNGValidationState = "error"; - app.update(); + exportToPNGProgess = 0 + exportToPNGColor = 'success' + exportToPNGColor = 'error' + exportToPNGMessage = `${err}` + exportToPNGValidationState = 'error' + app.update() }) .finally(() => { - restoreBoard(); - exportToPNGProgess = 0; - exportToPNGColor = "brand"; - exportToPNGValidationState = "none"; - exportToPNGMessage = `Click the "Export" button above to start`; - }); - }, 100); + restoreBoard() + exportToPNGProgess = 0 + exportToPNGColor = 'brand' + exportToPNGValidationState = 'none' + exportToPNGMessage = `Click the "Export" button above to start` + }) + }, 100) } - _.$cls`mt-5`; + _.$cls`mt-5` _.fField( _ => _.fProgressBar(exportToPNGProgess, exportToPNGColor), - "Progess", + 'Progess', false, exportToPNGValidationState, exportToPNGMessage, - ); + ) }, - ); + ) _(ToolItem)( - "Undo", + 'Undo', _ => _(FiArrowUndo20Filled)(), !currentProject.activeGraph.canUndo, () => currentProject.activeGraph.undo(), - ); + ) _(ToolItem)( - "Redo", + 'Redo', _ => _(FiArrowRedo20Filled)(), !currentProject.activeGraph.canRedo, () => currentProject.activeGraph.redo(), - ); + ) _(ToolItem)( - "Reset viewport", + 'Reset viewport', _ => _(FiResizeLarge20Regular)(), false, () => { - currentProject.activeGraph.resetViewport(); - currentProject.activeGraph.pushRecord(); + currentProject.activeGraph.resetViewport() + currentProject.activeGraph.pushRecord() }, - ); + ) _(ToolItem)( - "Full view", + 'Full view', _ => _(FiResizeSmall20Regular)(), false, () => { - currentProject.activeGraph.fullView(); - currentProject.activeGraph.pushRecord(); + currentProject.activeGraph.fullView() + currentProject.activeGraph.pushRecord() }, - ); + ) _(ToolItem)( - "Duplicate", + 'Duplicate', _ => _(FiAddSquareMultiple20Regular)(), !hasBlocksToDuplicate(), duplicateBlocks, - ); + ) _(ToolItem)( - "Remove", + 'Remove', _ => _(FiDelete20Regular)(), !hasBlocksToRemove(), removeBlocks, - ); + ) _(ToolItem)( - "Align left", + 'Align left', _ => _(FiAlignLeft20Regular)(), !hasBlocksToAlign(), alignBlocksToLeft, - ); + ) _(ToolItem)( - "Align top", + 'Align top', _ => _(FiAlignTop20Regular)(), !hasBlocksToAlign(), alignBlocksToTop, - ); + ) } - }); + }) - _.$cls`flex font-[Consolas] absolute left-1/2 h-full items-center`; + _.$cls`flex font-[Consolas] absolute left-1/2 h-full items-center` _.div( previewMode.value - ? "Preview App" + ? 'Preview App' : _ => { - _.span("Graph:"); - if (currentProject.activeViewId === 0) { - _.$cls`ml-1`; - _.span("app"); - } else { - _._span( - { - onkeydown: ev => ev.stopPropagation(), - }, - _ => - _.fUnderlineInput(propModel(currentProject.activeView, "name")), - ); - } - }, - ); + _.span('Graph:') + if (currentProject.activeViewId === 0) { + _.$cls`ml-1` + _.span('app') + } + else { + _._span( + { + onkeydown: ev => ev.stopPropagation(), + }, + _ => + _.fUnderlineInput(propModel(currentProject.activeView, 'name')), + ) + } + }, + ) - _.$cls`absolute flex items-center h-full right-0`; + _.$cls`absolute flex items-center h-full right-0` _.div(_ => { - _.span("Preview"); - if (_.fSwitch("", previewMode)) { - if (_.$ev) { - startPreview(); - } + _.span('Preview') + if (_.fSwitch('', previewMode)) { + if (_.$ev) + startPreview() } - }); -}); + }) +}) diff --git a/packages/northstar/tailwind.config.ts b/packages/northstar/tailwind.config.ts index cea8c96..8d63144 100644 --- a/packages/northstar/tailwind.config.ts +++ b/packages/northstar/tailwind.config.ts @@ -1,8 +1,9 @@ -import type { Config } from "tailwindcss"; +import type { Config } from 'tailwindcss' + export default { - content: ["./index.html", "./src/**/*.{js,ts}"], + content: ['./index.html', './src/**/*.{js,ts}'], theme: { extend: {}, }, plugins: [], -} satisfies Config; +} satisfies Config diff --git a/packages/northstar/vite.config.ts b/packages/northstar/vite.config.ts index 2ea68c3..c398ec3 100644 --- a/packages/northstar/vite.config.ts +++ b/packages/northstar/vite.config.ts @@ -1,43 +1,44 @@ -import { +import type { PluginOption, UserConfig, +} from 'vite' +import { build, createLogger, defineConfig, -} from "vite"; -import Refina from "vite-plugin-refina"; -import { viteStaticCopy } from "vite-plugin-static-copy"; -import MonacoEditorPluginObj from "vite-plugin-monaco-editor"; -import Inspect from "vite-plugin-inspect"; +} from 'vite' +import Refina from 'vite-plugin-refina' +import { viteStaticCopy } from 'vite-plugin-static-copy' +import MonacoEditorPluginObj from 'vite-plugin-monaco-editor' +import Inspect from 'vite-plugin-inspect' const MonacoEditorPlugin = (MonacoEditorPluginObj as any) - .default as typeof MonacoEditorPluginObj; + .default as typeof MonacoEditorPluginObj // Base on https://github.com/vitejs/vite/issues/6757#issuecomment-1584823965 function TsBundleUrlPlugin(): PluginOption { - let viteConfig: UserConfig; - let command: string; + let viteConfig: UserConfig + let command: string return { - name: "vite-plugin-ts-bundle-url", - apply: "build", - enforce: "post", + name: 'vite-plugin-ts-bundle-url', + apply: 'build', + enforce: 'post', config(config) { - viteConfig = config; + viteConfig = config }, configResolved(config) { - command = config.command; + command = config.command }, async transform(_code, id) { - if (!(command === "build" && id.endsWith(".ts?url"))) { - return; - } + if (!(command === 'build' && id.endsWith('.ts?url'))) + return - const quietLogger = createLogger(); - quietLogger.info = () => undefined; + const quietLogger = createLogger() + quietLogger.info = () => undefined const output = await build({ ...viteConfig, @@ -48,28 +49,30 @@ function TsBundleUrlPlugin(): PluginOption { build: { ...viteConfig.build, lib: { - entry: id.replace("?url", ""), - name: "_", - formats: ["es"], + entry: id.replace('?url', ''), + name: '_', + formats: ['es'], }, write: false, }, - }); + }) + + if (!(Array.isArray(output))) + throw new Error('Expected output to be Array') - if (!(output instanceof Array)) { - throw new Error("Expected output to be Array"); - } - const code = output[0].output[0].code; - //@ts-ignore `@types/node` not installed. - const encoded = Buffer.from(code, "utf8").toString("base64"); - const transformed = `export default "data:text/javascript;base64,${encoded}";`; + const code = output[0].output[0].code + // @ts-expect-error `@types/node` not installed. + // eslint-disable-next-line node/prefer-global/buffer + const encoded = Buffer.from(code, 'utf8').toString('base64') + const transformed = `export default "data:text/javascript;base64,${encoded}";` // TODO: Fix this so emoji etc. get properly decoded from within audio worklet module added using this url - console.log(`TypeScript bundle url: ${id} (${transformed.length} bytes)`); + // eslint-disable-next-line no-console + console.log(`TypeScript bundle url: ${id} (${transformed.length} bytes)`) - return transformed; + return transformed }, - }; + } } export default defineConfig({ @@ -81,19 +84,19 @@ export default defineConfig({ viteStaticCopy({ targets: [ { - src: "node_modules/@quasi-dev/runtime/node_modules/@refina/mdui/node_modules/mdui/dist/icons/**/*", - dest: "icons", + src: 'node_modules/@quasi-dev/runtime/node_modules/@refina/mdui/node_modules/mdui/dist/icons/**/*', + dest: 'icons', }, { - src: "node_modules/@quasi-dev/runtime/node_modules/@refina/mdui/node_modules/mdui/dist/fonts/**/*", - dest: "fonts", + src: 'node_modules/@quasi-dev/runtime/node_modules/@refina/mdui/node_modules/mdui/dist/fonts/**/*', + dest: 'fonts', }, ], }), ], server: { fs: { - allow: ["../../.."], + allow: ['../../..'], }, }, -}); +}) diff --git a/packages/runtime/package.json b/packages/runtime/package.json index 687a590..4478852 100644 --- a/packages/runtime/package.json +++ b/packages/runtime/package.json @@ -1,21 +1,21 @@ { "name": "@quasi-dev/runtime", - "version": "0.0.1", "type": "module", - "license": "MIT", + "version": "0.0.1", "description": "The generated frontend runtime library for Quasi Studio", + "license": "MIT", "repository": "https://github.com/Quasi-Studio/quasi", - "scripts": { - "check": "tsc --noEmit" + "exports": { + ".": "./src/index.ts", + "./*": "./*" }, "main": "./src/index.ts", "types": "./src/index.ts", "files": [ "src" ], - "exports": { - ".": "./src/index.ts", - "./*": "./*" + "scripts": { + "check": "tsc --noEmit" }, "dependencies": { "@refina/mdui": "^0.6.1", diff --git a/packages/runtime/src/components/appLayout.r.ts b/packages/runtime/src/components/appLayout.r.ts index edec0c4..ccc29f5 100644 --- a/packages/runtime/src/components/appLayout.r.ts +++ b/packages/runtime/src/components/appLayout.r.ts @@ -5,76 +5,76 @@ import { MdNavRail, MdTopAppBar, MdTopAppBarTitle, -} from "@refina/mdui"; -import { Component, Content, HTMLElementComponent, _, ref } from "refina"; -import { Direction, component, content, textProp } from "../types"; +} from '@refina/mdui' +import type { Content, HTMLElementComponent } from 'refina' +import { Component, _, ref } from 'refina' +import { Direction, component, content, textProp } from '../types' export default component({ - displayName: () => "App layout", - model: "AppLayoutModel", + displayName: () => 'App layout', + model: 'AppLayoutModel', contents: { - title: content("title", "as-primary"), - topBar: content("top bar", "as-socket"), - content: content("content", "as-socket", Direction.BOTTOM), + title: content('title', 'as-primary'), + topBar: content('top bar', 'as-socket'), + content: content('content', 'as-socket', Direction.BOTTOM), }, props: { - class: textProp("class"), + class: textProp('class'), }, -}); +}) -export const currentNavSymbol = Symbol("currentNav"); +export const currentNavSymbol = Symbol('currentNav') export interface AppLayoutProps { - class: string; - title: string; - topBar: Content; - content: Content; + class: string + title: string + topBar: Content + content: Content } export class AppLayoutModel { - renderingState: "nav" | "main"; - items: [value: string, iconName?: string][]; - current: string; + renderingState: 'nav' | 'main' + items: [value: string, iconName?: string][] + current: string } export class QAppLayout extends Component { - navRailRef = ref>(); + navRailRef = ref>() $main(model: AppLayoutModel, props: AppLayoutProps) { - _.$cls(props.class); - _.$css`position:fixed;width:100%;height:100%`; + _.$cls(props.class) + _.$css`position:fixed;width:100%;height:100%` _(MdLayout)(_ => { _(MdTopAppBar)(_ => { _(MdTopAppBarTitle)( _ => - _.$css`user-select:none;text-decoration:none;color:inherit` && - _._a( + _.$css`user-select:none;text-decoration:none;color:inherit` + && _._a( { - href: window.__QUASI_PREVIEW__ ? "" : import.meta.env.BASE_URL, + href: window.__QUASI_PREVIEW__ ? '' : import.meta.env.BASE_URL, }, props.title, ), - ); - _.embed(props.topBar); - }); + ) + _.embed(props.topBar) + }) _.provide(currentNavSymbol, model, _ => { - model.renderingState = "nav"; - model.items = []; - _.embed(props.content); - }); + model.renderingState = 'nav' + model.items = [] + _.embed(props.content) + }) - _.$css`height:100%`; - model.current = _(MdNavRail)(model.items); + _.$css`height:100%` + model.current = _(MdNavRail)(model.items) _(MdLayoutMain)(_ => { - _.$css`padding:18px;padding-right:64px`; + _.$css`padding:18px;padding-right:64px` _._div({}, _ => _.provide(currentNavSymbol, model, _ => { - model.renderingState = "main"; - _.embed(props.content); - }), - ); - }); - }); + model.renderingState = 'main' + _.embed(props.content) + })) + }) + }) } } diff --git a/packages/runtime/src/components/button.r.ts b/packages/runtime/src/components/button.r.ts index 6730982..66e8984 100644 --- a/packages/runtime/src/components/button.r.ts +++ b/packages/runtime/src/components/button.r.ts @@ -1,35 +1,35 @@ -import { Component, Content, _ } from "refina"; -import { component, content, event, input, textProp } from "../types"; -import { MdButton } from "@refina/mdui"; +import type { Content } from 'refina' +import { Component, _ } from 'refina' +import { MdButton } from '@refina/mdui' +import { component, content, event, input, textProp } from '../types' export default component({ - displayName: () => "Button", + displayName: () => 'Button', contents: { - inner: content("inner", "as-primary"), + inner: content('inner', 'as-primary'), }, inputs: { - disabled: input("disabled", "as-hidden-socket"), + disabled: input('disabled', 'as-hidden-socket'), }, events: { - onClick: event("onClick"), + onClick: event('onClick'), }, props: { - class: textProp("class"), + class: textProp('class'), }, -}); +}) export interface ButtonProps { - inner: Content; - class: string; - disabled: boolean; - onClick: () => void; + inner: Content + class: string + disabled: boolean + onClick: () => void } export class QButton extends Component { $main(props: ButtonProps) { - _.$cls(props.class); - if (_(MdButton)(props.inner, props.disabled)) { - props.onClick(); - } + _.$cls(props.class) + if (_(MdButton)(props.inner, props.disabled)) + props.onClick() } } diff --git a/packages/runtime/src/components/card.r.ts b/packages/runtime/src/components/card.r.ts index f8093c5..5b15993 100644 --- a/packages/runtime/src/components/card.r.ts +++ b/packages/runtime/src/components/card.r.ts @@ -1,36 +1,37 @@ -import { Component, Content, _ } from "refina"; +import type { Content } from 'refina' +import { Component, _ } from 'refina' -import { Direction, component, content, textProp } from "../types"; +import { Direction, component, content, textProp } from '../types' export default component({ - displayName: () => "Card", + displayName: () => 'Card', contents: { - title: content("title", "as-primary"), - inner: content("inner", "as-socket", Direction.BOTTOM), + title: content('title', 'as-primary'), + inner: content('inner', 'as-socket', Direction.BOTTOM), }, props: { - class: textProp("class"), + class: textProp('class'), }, -}); +}) export interface CardProps { - title: Content; - inner: Content; - class: string; + title: Content + inner: Content + class: string } export class QCard extends Component { $main(props: CardProps) { - _.$css`width:100%;padding:18px;padding-top:0`; - _.$cls(props.class); + _.$css`width:100%;padding:18px;padding-top:0` + _.$cls(props.class) _._mdui_card( { - variant: "filled", + variant: 'filled', }, _ => { - _._h2({}, props.title); - _.embed(props.inner); + _._h2({}, props.title) + _.embed(props.inner) }, - ); + ) } } diff --git a/packages/runtime/src/components/div.r.ts b/packages/runtime/src/components/div.r.ts index 0d0e905..2d81f25 100644 --- a/packages/runtime/src/components/div.r.ts +++ b/packages/runtime/src/components/div.r.ts @@ -1,25 +1,26 @@ -import { Component, Content, _ } from "refina"; +import type { Content } from 'refina' +import { Component, _ } from 'refina' -import { component, content, textProp } from "../types"; +import { component, content, textProp } from '../types' export default component({ - displayName: () => "Div", + displayName: () => 'Div', contents: { - inner: content("inner"), + inner: content('inner'), }, props: { - class: textProp("class"), + class: textProp('class'), }, -}); +}) export interface DivProps { - inner: Content; - class: string; + inner: Content + class: string } export class QDiv extends Component { $main(props: DivProps) { - _.$cls(props.class); - _._div({}, props.inner); + _.$cls(props.class) + _._div({}, props.inner) } } diff --git a/packages/runtime/src/components/forEach.r.ts b/packages/runtime/src/components/forEach.r.ts index c88da95..fe83e9f 100644 --- a/packages/runtime/src/components/forEach.r.ts +++ b/packages/runtime/src/components/forEach.r.ts @@ -1,49 +1,50 @@ -import { Component, Content, RefTreeNode, _ } from "refina"; +import type { Content, RefTreeNode } from 'refina' +import { Component, _ } from 'refina' -import { Direction, component, content, input, output } from "../types"; +import { Direction, component, content, input, output } from '../types' export default component({ - displayName: () => "For each", - model: "ForEachModel", + displayName: () => 'For each', + model: 'ForEachModel', contents: { - inner: content("inner", "as-socket", Direction.BOTTOM), + inner: content('inner', 'as-socket', Direction.BOTTOM), }, inputs: { - iterable: input("iterable"), + iterable: input('iterable'), }, outputs: { - current: output("current", "as-socket", Direction.RIGHT), + current: output('current', 'as-socket', Direction.RIGHT), }, -}); +}) export interface ForEachProps { - inner: Content; - iterable: Iterable; + inner: Content + iterable: Iterable } export class ForEachModel { - current: unknown; + current: unknown } export class QForEach extends Component { - refNodes: Record = {}; + refNodes: Record = {} $main(model: ForEachModel, props: ForEachProps) { - const parentRefTreeNode = _.$lowlevel.$$currentRefNode; + const parentRefTreeNode = _.$lowlevel.$$currentRefNode - let index = 0; + let index = 0 for (const v of props.iterable) { - model.current = v; + model.current = v - const key = index.toString(); + const key = index.toString() - this.refNodes[key] ??= {}; - _.$lowlevel.$$currentRefNode = this.refNodes[key]; + this.refNodes[key] ??= {} + _.$lowlevel.$$currentRefNode = this.refNodes[key] - _.embed(props.inner); + _.embed(props.inner) - index++; + index++ } - _.$lowlevel.$$currentRefNode = parentRefTreeNode; + _.$lowlevel.$$currentRefNode = parentRefTreeNode } } diff --git a/packages/runtime/src/components/ifElse.r.ts b/packages/runtime/src/components/ifElse.r.ts index b77704d..ea8fa13 100644 --- a/packages/runtime/src/components/ifElse.r.ts +++ b/packages/runtime/src/components/ifElse.r.ts @@ -1,30 +1,30 @@ -import { Component, Content, _ } from "refina"; +import type { Content } from 'refina' +import { Component, _ } from 'refina' -import { Direction, component, content, input } from "../types"; +import { Direction, component, content, input } from '../types' export default component({ - displayName: props => (props["[else]"] ? "If else" : "If"), + displayName: props => (props['[else]'] ? 'If else' : 'If'), contents: { - then: content("then", "as-socket", Direction.RIGHT), - else: content("else", "as-hidden-socket", Direction.BOTTOM), + then: content('then', 'as-socket', Direction.RIGHT), + else: content('else', 'as-hidden-socket', Direction.BOTTOM), }, inputs: { - condition: input("condition"), + condition: input('condition'), }, -}); +}) export interface IfElseProps { - condition: boolean; - then: Content; - else: Content; + condition: boolean + then: Content + else: Content } export class QIfElse extends Component { $main(props: IfElseProps) { - if (props.condition) { - _.embed(props.then); - } else { - _.embed(props.else); - } + if (props.condition) + _.embed(props.then) + else + _.embed(props.else) } } diff --git a/packages/runtime/src/components/index.ts b/packages/runtime/src/components/index.ts index 5bdfe8d..d7f0cc1 100644 --- a/packages/runtime/src/components/index.ts +++ b/packages/runtime/src/components/index.ts @@ -1,32 +1,32 @@ -export * from "./appLayout.r"; -export * from "./button.r"; -export * from "./card.r"; -export * from "./div.r"; -export * from "./forEach.r"; -export * from "./ifElse.r"; -export * from "./input.r"; -export * from "./list.r"; -export * from "./paragraph.r"; -export * from "./span.r"; -export * from "./subPage.r"; -export * from "./table.r"; -export * from "./tableItem.r"; -export * from "./textNode.r"; +import qAppLayout from './appLayout.r' +import qButton from './button.r' +import qCard from './card.r' +import qDiv from './div.r' +import qForEach from './forEach.r' +import qIfElse from './ifElse.r' +import qInput from './input.r' +import qList from './list.r' +import qParagraph from './paragraph.r' +import qSpan from './span.r' +import qSubPage from './subPage.r' +import qTable from './table.r' +import qTableItem from './tableItem.r' +import qTextNode from './textNode.r' -import qAppLayout from "./appLayout.r"; -import qButton from "./button.r"; -import qCard from "./card.r"; -import qDiv from "./div.r"; -import qForEach from "./forEach.r"; -import qIfElse from "./ifElse.r"; -import qInput from "./input.r"; -import qList from "./list.r"; -import qParagraph from "./paragraph.r"; -import qSpan from "./span.r"; -import qSubPage from "./subPage.r"; -import qTable from "./table.r"; -import qTableItem from "./tableItem.r"; -import qTextNode from "./textNode.r"; +export * from './appLayout.r' +export * from './button.r' +export * from './card.r' +export * from './div.r' +export * from './forEach.r' +export * from './ifElse.r' +export * from './input.r' +export * from './list.r' +export * from './paragraph.r' +export * from './span.r' +export * from './subPage.r' +export * from './table.r' +export * from './tableItem.r' +export * from './textNode.r' export const componentInfoObj = { qAppLayout, @@ -43,6 +43,6 @@ export const componentInfoObj = { qTable, qTableItem, qTextNode, -}; +} -export const componentInfoArray = Object.entries(componentInfoObj); +export const componentInfoArray = Object.entries(componentInfoObj) diff --git a/packages/runtime/src/components/input.r.ts b/packages/runtime/src/components/input.r.ts index 8e78887..1897af2 100644 --- a/packages/runtime/src/components/input.r.ts +++ b/packages/runtime/src/components/input.r.ts @@ -1,5 +1,5 @@ -import { Component, _, propModel } from "refina"; -import { MdPasswordInput, MdTextField } from "@refina/mdui"; +import { Component, _, propModel } from 'refina' +import { MdPasswordInput, MdTextField } from '@refina/mdui' import { component, dropdownProp, @@ -9,87 +9,89 @@ import { output, plugin, textProp, -} from "../types"; +} from '../types' export default component({ displayName: props => ( ({ - text: "Text input", - password: "Pwd input", - number: "Num input", + text: 'Text input', + password: 'Pwd input', + number: 'Num input', }) as any - )[props.type] ?? "Input", - model: "InputModel", + )[props.type] ?? 'Input', + model: 'InputModel', inputs: { - label: input("label", "as-primary"), - disabled: input("disabled", "as-hidden-socket"), + label: input('label', 'as-primary'), + disabled: input('disabled', 'as-hidden-socket'), }, outputs: { - value: output("value"), + value: output('value'), }, events: { - onInput: event("onInput", "as-hidden-socket"), + onInput: event('onInput', 'as-hidden-socket'), }, methods: { - clear: method("clear", "as-hidden-socket"), + clear: method('clear', 'as-hidden-socket'), }, plugins: { - validator: plugin("validator", "input-plugin"), + validator: plugin('validator', 'input-plugin'), }, props: { - type: dropdownProp("type", ["text", "password", "number"], "text"), - class: textProp("class"), - initial: textProp("initial"), + type: dropdownProp('type', ['text', 'password', 'number'], 'text'), + class: textProp('class'), + initial: textProp('initial'), }, -}); +}) export interface InputProps { - type: string; - class: string; - label: string; - initial: string; - disabled: boolean; - onInput: (newVal: string | number) => void; - validator: (value: string) => string | true; + type: string + class: string + label: string + initial: string + disabled: boolean + onInput: (newVal: string | number) => void + validator: (value: string) => string | true } export class InputModel { - type: string; - _value: string; + type: string + _value: string clear() { - this._value = ""; + this._value = '' } + set value(value: string | number) { - this._value = String(value); + this._value = String(value) } + get value() { - return this.type === "number" ? +this._value : this._value; + return this.type === 'number' ? +this._value : this._value } } export class QInput extends Component { $main(model: InputModel, props: InputProps) { - model.type = props.type; - model.value ??= props.initial; - _.$cls(props.class); - _.$css`margin-bottom:18px;`; + model.type = props.type + model.value ??= props.initial + _.$cls(props.class) + _.$css`margin-bottom:18px;` if ( - props.type === "password" + props.type === 'password' ? _(MdPasswordInput)( - propModel(model, "_value"), - props.label, - props.disabled, - ) + propModel(model, '_value'), + props.label, + props.disabled, + ) : _(MdTextField)( - propModel(model, "_value"), - props.label, - props.disabled, - ) + propModel(model, '_value'), + props.label, + props.disabled, + ) ) { - //@ts-ignore - const newVal = _.$ev as string; - props.onInput?.(props.type === "number" ? +newVal : newVal); + // @ts-expect-error missing type + const newVal = _.$ev as string + props.onInput?.(props.type === 'number' ? +newVal : newVal) } } } diff --git a/packages/runtime/src/components/list.r.ts b/packages/runtime/src/components/list.r.ts index c542c77..ee5937e 100644 --- a/packages/runtime/src/components/list.r.ts +++ b/packages/runtime/src/components/list.r.ts @@ -1,5 +1,6 @@ -import { MdList } from "@refina/mdui"; -import { Component, Content, _, byIndex, bySelf } from "refina"; +import { MdList } from '@refina/mdui' +import type { Content } from 'refina' +import { Component, _, byIndex, bySelf } from 'refina' import { Direction, component, @@ -7,52 +8,52 @@ import { input, output, textProp, -} from "../types"; +} from '../types' export default component({ - displayName: () => "List", - model: "ListModel", + displayName: () => 'List', + model: 'ListModel', contents: { - inner: content("inner", undefined, Direction.BOTTOM), + inner: content('inner', undefined, Direction.BOTTOM), }, inputs: { - data: input("data"), + data: input('data'), }, outputs: { - current: output("current", undefined, Direction.RIGHT), + current: output('current', undefined, Direction.RIGHT), }, props: { - class: textProp("class"), - key: textProp("key", "$index"), + class: textProp('class'), + key: textProp('key', '$index'), }, -}); +}) export interface ListProps { - inner: Content; - class: string; - data: Iterable; - key: string; + inner: Content + class: string + data: Iterable + key: string } export class ListModel { - current: any; + current: any } export class QList extends Component { $main(model: ListModel, props: ListProps) { - _.$cls(props.class); + _.$cls(props.class) _(MdList)( props.data, - props.key === "$index" + props.key === '$index' ? byIndex - : props.key === "$self" - ? bySelf - : props.key, + : props.key === '$self' + ? bySelf + : props.key, v => { - model.current = v; - _.embed(props.inner); + model.current = v + _.embed(props.inner) }, - ); - model.current = null; + ) + model.current = null } } diff --git a/packages/runtime/src/components/paragraph.r.ts b/packages/runtime/src/components/paragraph.r.ts index c5110c5..3183207 100644 --- a/packages/runtime/src/components/paragraph.r.ts +++ b/packages/runtime/src/components/paragraph.r.ts @@ -1,25 +1,26 @@ -import { Component, Content, _ } from "refina"; +import type { Content } from 'refina' +import { Component, _ } from 'refina' -import { component, content, textProp } from "../types"; +import { component, content, textProp } from '../types' export default component({ - displayName: () => "Paragraph", + displayName: () => 'Paragraph', contents: { - inner: content("inner"), + inner: content('inner'), }, props: { - class: textProp("class"), + class: textProp('class'), }, -}); +}) export interface ParagraphProps { - inner: Content; - class: string; + inner: Content + class: string } export class QParagraph extends Component { $main(props: ParagraphProps) { - _.$cls(props.class); - _._p({}, props.inner); + _.$cls(props.class) + _._p({}, props.inner) } } diff --git a/packages/runtime/src/components/span.r.ts b/packages/runtime/src/components/span.r.ts index be10516..da1404f 100644 --- a/packages/runtime/src/components/span.r.ts +++ b/packages/runtime/src/components/span.r.ts @@ -1,25 +1,26 @@ -import { Component, Content, _ } from "refina"; +import type { Content } from 'refina' +import { Component, _ } from 'refina' -import { component, content, textProp } from "../types"; +import { component, content, textProp } from '../types' export default component({ - displayName: () => "Span", + displayName: () => 'Span', contents: { - inner: content("inner", "as-primary-and-socket"), + inner: content('inner', 'as-primary-and-socket'), }, props: { - class: textProp("class"), + class: textProp('class'), }, -}); +}) export interface SpanProps { - inner: Content; - class: string; + inner: Content + class: string } export class QSpan extends Component { $main(props: SpanProps) { - _.$cls(props.class); - _._span({}, props.inner); + _.$cls(props.class) + _._span({}, props.inner) } } diff --git a/packages/runtime/src/components/subPage.r.ts b/packages/runtime/src/components/subPage.r.ts index 9787837..2e60b05 100644 --- a/packages/runtime/src/components/subPage.r.ts +++ b/packages/runtime/src/components/subPage.r.ts @@ -1,37 +1,39 @@ -import { Component, Content, _ } from "refina"; +import type { Content } from 'refina' +import { Component, _ } from 'refina' -import { component, content, input, textProp } from "../types"; -import { AppLayoutModel, currentNavSymbol } from "./appLayout.r"; +import { component, content, input, textProp } from '../types' +import type { AppLayoutModel } from './appLayout.r' +import { currentNavSymbol } from './appLayout.r' export default component({ - displayName: () => "Sub page", + displayName: () => 'Sub page', contents: { - inner: content("inner"), + inner: content('inner'), }, inputs: { - title: input("title", "as-primary"), + title: input('title', 'as-primary'), }, props: { - icon: textProp("icon"), + icon: textProp('icon'), }, -}); +}) export interface SubPageProps { - title: string; - icon: string; - inner: Content; + title: string + icon: string + inner: Content } export class QSubPage extends Component { $main(props: SubPageProps) { - const model = _.$runtimeData[currentNavSymbol] as AppLayoutModel; + const model = _.$runtimeData[currentNavSymbol] as AppLayoutModel - if (model.renderingState === "nav") { - model.items.push([props.title, props.icon]); - } else { - if (model.current === props.title) { - _.embed(props.inner); - } + if (model.renderingState === 'nav') { + model.items.push([props.title, props.icon]) + } + else { + if (model.current === props.title) + _.embed(props.inner) } } } diff --git a/packages/runtime/src/components/table.r.ts b/packages/runtime/src/components/table.r.ts index 4b1bb9d..d896f8b 100644 --- a/packages/runtime/src/components/table.r.ts +++ b/packages/runtime/src/components/table.r.ts @@ -1,5 +1,6 @@ -import { MdTable } from "@refina/mdui"; -import { Component, Content, _, byIndex, bySelf } from "refina"; +import { MdTable } from '@refina/mdui' +import type { Content } from 'refina' +import { Component, _, byIndex, bySelf } from 'refina' import { Direction, component, @@ -7,64 +8,64 @@ import { input, output, textProp, -} from "../types"; +} from '../types' export default component({ - displayName: () => "Table", - contents: { inner: content("inner", "as-socket", Direction.BOTTOM) }, + displayName: () => 'Table', + contents: { inner: content('inner', 'as-socket', Direction.BOTTOM) }, inputs: { - data: input("data"), + data: input('data'), }, outputs: { - current: output("current", "as-hidable-socket", Direction.RIGHT), + current: output('current', 'as-hidable-socket', Direction.RIGHT), renderingState: output( - "renderingState", - "as-hidden-socket", + 'renderingState', + 'as-hidden-socket', Direction.RIGHT, ), }, props: { - class: textProp("class"), - key: textProp("key", "$index"), + class: textProp('class'), + key: textProp('key', '$index'), }, -}); +}) -export const currentTableSymbol = Symbol("currentTable"); +export const currentTableSymbol = Symbol('currentTable') export interface TableProps { - inner: Content; - class: string; - data: Iterable; - key: string; + inner: Content + class: string + data: Iterable + key: string } export class TableModel { - renderingState: "head" | "body"; - current: any; + renderingState: 'head' | 'body' + current: any } export class QTable extends Component { $main(model: TableModel, props: TableProps) { - _.$cls(props.class); + _.$cls(props.class) _.provide(currentTableSymbol, model, _ => { _(MdTable)( props.data, _ => { - model.renderingState = "head"; - _.embed(props.inner); + model.renderingState = 'head' + _.embed(props.inner) }, - props.key === "$index" + props.key === '$index' ? byIndex - : props.key === "$self" - ? bySelf - : props.key, + : props.key === '$self' + ? bySelf + : props.key, v => { - model.renderingState = "body"; - model.current = v; - _.embed(props.inner); + model.renderingState = 'body' + model.current = v + _.embed(props.inner) }, - ); - model.current = null; - }); + ) + model.current = null + }) } } diff --git a/packages/runtime/src/components/tableItem.r.ts b/packages/runtime/src/components/tableItem.r.ts index 2dd0ee6..bf5deba 100644 --- a/packages/runtime/src/components/tableItem.r.ts +++ b/packages/runtime/src/components/tableItem.r.ts @@ -1,5 +1,6 @@ -import { MdTableCell, MdTableHeader } from "@refina/mdui"; -import { Component, Content, _ } from "refina"; +import { MdTableCell, MdTableHeader } from '@refina/mdui' +import type { Content } from 'refina' +import { Component, _ } from 'refina' import { Direction, component, @@ -7,50 +8,52 @@ import { input, output, textProp, -} from "../types"; -import { TableModel, currentTableSymbol } from "./table.r"; +} from '../types' +import type { TableModel } from './table.r' +import { currentTableSymbol } from './table.r' export default component({ - displayName: () => "Table Col", - model: "TableColModel", + displayName: () => 'Table Col', + model: 'TableColModel', contents: { - inner: content("inner"), + inner: content('inner'), }, inputs: { - prop: input("prop", "as-primary"), + prop: input('prop', 'as-primary'), }, outputs: { - value: output("value", "as-hidable-socket", Direction.TOP), + value: output('value', 'as-hidable-socket', Direction.TOP), }, props: { - header: textProp("header", "$prop"), - headClass: textProp("head class"), - cellClass: textProp("cell class"), + header: textProp('header', '$prop'), + headClass: textProp('head class'), + cellClass: textProp('cell class'), }, -}); +}) export interface TableColProps { - inner: Content; - prop: string; - header: string; - headClass: string; - cellClass: string; + inner: Content + prop: string + header: string + headClass: string + cellClass: string } export class TableColModel { - value: any; + value: any } export class QTableCol extends Component { $main(model: TableColModel, props: TableColProps) { - const currentTable = _.$runtimeData[currentTableSymbol] as TableModel; - if (currentTable.renderingState === "head") { - _.$cls(props.headClass); - _(MdTableHeader)(props.header === "$prop" ? props.prop : props.header); - } else { - model.value = currentTable.current[props.prop]; - _.$cls(props.cellClass); - _(MdTableCell)(props.inner); + const currentTable = _.$runtimeData[currentTableSymbol] as TableModel + if (currentTable.renderingState === 'head') { + _.$cls(props.headClass) + _(MdTableHeader)(props.header === '$prop' ? props.prop : props.header) + } + else { + model.value = currentTable.current[props.prop] + _.$cls(props.cellClass) + _(MdTableCell)(props.inner) } } } diff --git a/packages/runtime/src/components/textNode.r.ts b/packages/runtime/src/components/textNode.r.ts index 5696a55..f82e125 100644 --- a/packages/runtime/src/components/textNode.r.ts +++ b/packages/runtime/src/components/textNode.r.ts @@ -1,19 +1,19 @@ -import { Component, _ } from "refina"; -import { component, input } from "../types"; +import { Component, _ } from 'refina' +import { component, input } from '../types' export default component({ - displayName: () => "Text", + displayName: () => 'Text', inputs: { - text: input("text", "as-primary-and-socket"), + text: input('text', 'as-primary-and-socket'), }, -}); +}) export interface TextNodeProps { - text: string | null; + text: string | null } export class QTextNode extends Component { $main(props: TextNodeProps) { - _.t(props.text ?? ""); + _.t(props.text ?? '') } } diff --git a/packages/runtime/src/index.ts b/packages/runtime/src/index.ts index 2e01408..0fdb98d 100644 --- a/packages/runtime/src/index.ts +++ b/packages/runtime/src/index.ts @@ -1,11 +1,11 @@ -import { Plugin } from "refina"; -import * as c from "./components"; -import MdUI from "@refina/mdui"; +import type { Plugin } from 'refina' +import MdUI from '@refina/mdui' +import * as c from './components' export default [ MdUI as Plugin, { - name: "quasi-runtime", + name: 'quasi-runtime', components: { qAppLayout: c.QAppLayout, qButton: c.QButton, @@ -23,8 +23,8 @@ export default [ qTextNode: c.QTextNode, }, } satisfies Plugin, -]; +] -export * as refina from "refina"; -export * from "./components"; -export * from "./types"; +export * as refina from 'refina' +export * from './components' +export * from './types' diff --git a/packages/runtime/src/types/base.ts b/packages/runtime/src/types/base.ts index caaa468..0e4ba3c 100644 --- a/packages/runtime/src/types/base.ts +++ b/packages/runtime/src/types/base.ts @@ -1,3 +1,4 @@ +/* eslint-disable ts/prefer-literal-enum-member */ /** * Copied from `@quasi-dev/visual-flow` */ @@ -10,4 +11,4 @@ export enum Direction { BOTTOM = Direction.DOWN, // alias } -export type PositionInfo = Direction | null; +export type PositionInfo = Direction | null diff --git a/packages/runtime/src/types/component.ts b/packages/runtime/src/types/component.ts index e8b53ac..042bb1d 100644 --- a/packages/runtime/src/types/component.ts +++ b/packages/runtime/src/types/component.ts @@ -1,31 +1,33 @@ -import { ContentInfo, content } from "./content"; -import { EventInfo } from "./event"; -import { InputInfo } from "./input"; -import { MethodInfo } from "./method"; -import { OutputInfo } from "./output"; -import { PluginInfo } from "./plugin"; -import { Prop, textProp } from "./prop"; +import type { ContentInfo } from './content' +import { content } from './content' +import type { EventInfo } from './event' +import type { InputInfo } from './input' +import type { MethodInfo } from './method' +import type { OutputInfo } from './output' +import type { PluginInfo } from './plugin' +import type { Prop } from './prop' +import { textProp } from './prop' export interface ComponentInfo { - displayName: (props: Record) => string; + displayName: (props: Record) => string - blockWidth: number; - blockHeight: number; + blockWidth: number + blockHeight: number - model: string | null; + model: string | null - contents: Record; - inputs: Record; - outputs: Record; - events: Record; - methods: Record; - plugins: Record; - props: Record; + contents: Record + inputs: Record + outputs: Record + events: Record + methods: Record + plugins: Record + props: Record } export function component( - info: Partial> & - Pick, + info: Partial> & + Pick, ): ComponentInfo { return { blockWidth: 200, @@ -39,29 +41,29 @@ export function component( plugins: {}, props: {}, ...info, - }; + } } export function contentWrapper(name: string) { return component({ displayName: () => name, contents: { - inner: content("inner", "as-primary"), + inner: content('inner', 'as-primary'), }, props: { - class: textProp("class"), + class: textProp('class'), }, - }); + }) } export function layer(name: string) { return component({ displayName: () => name, contents: { - inner: content("inner", "as-primary-and-socket"), + inner: content('inner', 'as-primary-and-socket'), }, props: { - class: textProp("class"), + class: textProp('class'), }, - }); + }) } diff --git a/packages/runtime/src/types/content.ts b/packages/runtime/src/types/content.ts index 2dcc331..43dcfd2 100644 --- a/packages/runtime/src/types/content.ts +++ b/packages/runtime/src/types/content.ts @@ -1,26 +1,26 @@ -import { PositionInfo } from "./base"; +import type { PositionInfo } from './base' export type ContentMode = - | "as-socket" - | "as-primary" - | "as-primary-and-socket" - | "as-hidden-socket" - | "as-hidable-socket"; + | 'as-socket' + | 'as-primary' + | 'as-primary-and-socket' + | 'as-hidden-socket' + | 'as-hidable-socket' export interface ContentInfo { - displayName: string; - mode: ContentMode; - position: PositionInfo; + displayName: string + mode: ContentMode + position: PositionInfo } export function content( - displayName: string = "inner", - mode: ContentMode = "as-socket", + displayName: string = 'inner', + mode: ContentMode = 'as-socket', position: PositionInfo = null, ): ContentInfo { return { displayName, mode, position, - }; + } } diff --git a/packages/runtime/src/types/env.ts b/packages/runtime/src/types/env.ts index 5385489..366bac9 100644 --- a/packages/runtime/src/types/env.ts +++ b/packages/runtime/src/types/env.ts @@ -1,6 +1,6 @@ declare global { interface Window { - __QUASI_PREVIEW__: boolean; + __QUASI_PREVIEW__: boolean } } -export {}; +export {} diff --git a/packages/runtime/src/types/event.ts b/packages/runtime/src/types/event.ts index aa09e87..fa09979 100644 --- a/packages/runtime/src/types/event.ts +++ b/packages/runtime/src/types/event.ts @@ -1,21 +1,21 @@ -import { PositionInfo } from "./base"; +import type { PositionInfo } from './base' -type EventMode = "as-socket" | "as-hidden-socket" | "as-hidable-socket"; +type EventMode = 'as-socket' | 'as-hidden-socket' | 'as-hidable-socket' export interface EventInfo { - displayName: string; - mode: EventMode; - position: PositionInfo; + displayName: string + mode: EventMode + position: PositionInfo } export function event( displayName: string, - mode: EventMode = "as-socket", + mode: EventMode = 'as-socket', position: PositionInfo = null, ): EventInfo { return { displayName, mode, position, - }; + } } diff --git a/packages/runtime/src/types/index.ts b/packages/runtime/src/types/index.ts index 939ada8..0954ecb 100644 --- a/packages/runtime/src/types/index.ts +++ b/packages/runtime/src/types/index.ts @@ -1,10 +1,10 @@ -export * from "./base"; -export * from "./component"; -export * from "./content"; -export * from "./env"; -export * from "./event"; -export * from "./input"; -export * from "./method"; -export * from "./output"; -export * from "./plugin"; -export * from "./prop"; +export * from './base' +export * from './component' +export * from './content' +export * from './env' +export * from './event' +export * from './input' +export * from './method' +export * from './output' +export * from './plugin' +export * from './prop' diff --git a/packages/runtime/src/types/input.ts b/packages/runtime/src/types/input.ts index 53f301c..8b9f1ef 100644 --- a/packages/runtime/src/types/input.ts +++ b/packages/runtime/src/types/input.ts @@ -1,26 +1,26 @@ -import { PositionInfo } from "./base"; +import type { PositionInfo } from './base' export type InputMode = - | "as-socket" - | "as-primary" - | "as-primary-and-socket" - | "as-hidden-socket" - | "as-hidable-socket"; + | 'as-socket' + | 'as-primary' + | 'as-primary-and-socket' + | 'as-hidden-socket' + | 'as-hidable-socket' export interface InputInfo { - displayName: string; - mode: InputMode; - position: PositionInfo; + displayName: string + mode: InputMode + position: PositionInfo } export function input( displayName: string, - mode: InputMode = "as-socket", + mode: InputMode = 'as-socket', position: PositionInfo = null, ): InputInfo { return { displayName, mode, position, - }; + } } diff --git a/packages/runtime/src/types/method.ts b/packages/runtime/src/types/method.ts index f40e2db..10e23dd 100644 --- a/packages/runtime/src/types/method.ts +++ b/packages/runtime/src/types/method.ts @@ -1,24 +1,24 @@ -import { PositionInfo } from "./base"; +import type { PositionInfo } from './base' export type MethodDisplay = - | "as-socket" - | "as-hidden-socket" - | "as-hidable-socket"; + | 'as-socket' + | 'as-hidden-socket' + | 'as-hidable-socket' export interface MethodInfo { - displayName: string; - mode: MethodDisplay; - position: PositionInfo; + displayName: string + mode: MethodDisplay + position: PositionInfo } export function method( displayName: string, - mode: MethodDisplay = "as-socket", + mode: MethodDisplay = 'as-socket', position: PositionInfo = null, ): MethodInfo { return { displayName, mode, position, - }; + } } diff --git a/packages/runtime/src/types/output.ts b/packages/runtime/src/types/output.ts index 76180a4..ffaf2d5 100644 --- a/packages/runtime/src/types/output.ts +++ b/packages/runtime/src/types/output.ts @@ -1,21 +1,21 @@ -import { PositionInfo } from "./base"; +import type { PositionInfo } from './base' -export type OutputMode = "as-socket" | "as-hidden-socket" | "as-hidable-socket"; +export type OutputMode = 'as-socket' | 'as-hidden-socket' | 'as-hidable-socket' export interface OutputInfo { - displayName: string; - mode: OutputMode; - position: PositionInfo; + displayName: string + mode: OutputMode + position: PositionInfo } export function output( displayName: string, - mode: OutputMode = "as-socket", + mode: OutputMode = 'as-socket', position: PositionInfo = null, ): OutputInfo { return { displayName, mode, position, - }; + } } diff --git a/packages/runtime/src/types/plugin.ts b/packages/runtime/src/types/plugin.ts index 47c7867..75d2e88 100644 --- a/packages/runtime/src/types/plugin.ts +++ b/packages/runtime/src/types/plugin.ts @@ -1,9 +1,9 @@ -import { Direction } from "./base"; +import { Direction } from './base' export interface PluginInfo { - displayName: string; - kind: string; - direction: Direction; + displayName: string + kind: string + direction: Direction } export function plugin( @@ -15,5 +15,5 @@ export function plugin( displayName, kind, direction, - }; + } } diff --git a/packages/runtime/src/types/prop.ts b/packages/runtime/src/types/prop.ts index 36ae6d2..21aa68b 100644 --- a/packages/runtime/src/types/prop.ts +++ b/packages/runtime/src/types/prop.ts @@ -1,25 +1,25 @@ export interface PropBase { - displayName: string; + displayName: string } export interface TextProp extends PropBase { - type: "text"; - defaultVal: string; + type: 'text' + defaultVal: string } export function textProp( displayName: string, - defaultVal: string = "", + defaultVal: string = '', ): TextProp { return { displayName, - type: "text", + type: 'text', defaultVal, - }; + } } export interface SwitchProp extends PropBase { - type: "switch"; - defaultVal: boolean; + type: 'switch' + defaultVal: boolean } export function switchProp( displayName: string, @@ -27,15 +27,15 @@ export function switchProp( ): SwitchProp { return { displayName, - type: "switch", + type: 'switch', defaultVal, - }; + } } export interface DropdownProp extends PropBase { - type: "dropdown"; - options: string[]; - defaultVal: string; + type: 'dropdown' + options: string[] + defaultVal: string } export function dropdownProp( displayName: string, @@ -44,43 +44,43 @@ export function dropdownProp( ): DropdownProp { return { displayName, - type: "dropdown", + type: 'dropdown', options, defaultVal, - }; + } } export interface ReadonlyProp extends PropBase { - type: "readonly"; - value: string; + type: 'readonly' + value: string } export function readonlyProp(displayName: string, value: string): ReadonlyProp { return { displayName, - type: "readonly", + type: 'readonly', value, - }; + } } export interface NumberProp extends PropBase { - type: "number"; - defaultVal: number; - min: number; - max: number; + type: 'number' + defaultVal: number + min: number + max: number } export function numberProp( displayName: string, defaultVal: number, - min: number = -Infinity, - max: number = Infinity, + min: number = Number.NEGATIVE_INFINITY, + max: number = Number.POSITIVE_INFINITY, ): NumberProp { return { displayName, - type: "number", + type: 'number', defaultVal, min, max, - }; + } } export type Prop = @@ -88,4 +88,4 @@ export type Prop = | SwitchProp | DropdownProp | ReadonlyProp - | NumberProp; + | NumberProp diff --git a/packages/visual-flow/package.json b/packages/visual-flow/package.json index cb4c46d..08a499d 100644 --- a/packages/visual-flow/package.json +++ b/packages/visual-flow/package.json @@ -1,21 +1,21 @@ { "name": "@quasi-dev/visual-flow", - "version": "0.0.1", "type": "module", - "license": "MIT", + "version": "0.0.1", "description": "A visualized functional programming framework.", + "license": "MIT", "repository": "https://github.com/Quasi-Studio/quasi", - "scripts": { - "check": "tsc --noEmit" + "exports": { + ".": "./src/index.ts" }, "main": "./src/index.ts", "types": "./src/index.ts", "files": [ - "src", - "README.md" + "README.md", + "src" ], - "exports": { - ".": "./src/index.ts" + "scripts": { + "check": "tsc --noEmit" }, "dependencies": { "@fluentui/tokens": "^1.0.0-alpha.11", diff --git a/packages/visual-flow/src/components/block/RectBlock.r.ts b/packages/visual-flow/src/components/block/RectBlock.r.ts index 504a14f..63dbcf7 100644 --- a/packages/visual-flow/src/components/block/RectBlock.r.ts +++ b/packages/visual-flow/src/components/block/RectBlock.r.ts @@ -1,120 +1,126 @@ -import { Context } from "refina"; -import { Block, Socket } from "../../model"; -import { Direction, Point } from "../../types"; -import { spreadItems } from "../../utils"; -import useStyles from "./RectBlock.styles"; +import type { Context } from 'refina' +import type { Socket } from '../../model' +import { Block } from '../../model' +import { Direction, Point } from '../../types' +import { spreadItems } from '../../utils' +import useStyles from './RectBlock.styles' -const SOCKET_PADDING_SCALE = -0.1; +const SOCKET_PADDING_SCALE = -0.1 export abstract class RectBlock extends Block { - ctorName: string = "RectBlock"; + ctorName: string = 'RectBlock' cloneTo(target: this): this { - target.boardWidth = this.boardWidth; - target.boardHeight = this.boardHeight; - target.boardBorderRadius = this.boardBorderRadius; - return target; + target.boardWidth = this.boardWidth + target.boardHeight = this.boardHeight + target.boardBorderRadius = this.boardBorderRadius + return target } - boardWidth: number; - boardHeight: number; - boardBorderRadius: number = 8; + boardWidth: number + boardHeight: number + boardBorderRadius: number = 8 get boundingRectBoardWidth() { - return this.boardWidth; + return this.boardWidth } + get boundingRectBoardHeight() { - return this.boardHeight; + return this.boardHeight } get graphWidth() { - return this.boardWidth * this.graph.boardScale; + return this.boardWidth * this.graph.boardScale } + get graphHeight() { - return this.boardHeight * this.graph.boardScale; + return this.boardHeight * this.graph.boardScale } + get graphBorderRadius() { - return this.boardBorderRadius * this.graph.boardScale; + return this.boardBorderRadius * this.graph.boardScale } get pageWidth() { - return this.graphWidth; + return this.graphWidth } + get pageHeight() { - return this.graphHeight; + return this.graphHeight } + get pageBorderRadius() { - return this.graphBorderRadius; + return this.graphBorderRadius } getDockingBenchmarkBlockPos(direction: Direction): Point { switch (direction) { case Direction.LEFT: - return new Point(0, 0); + return new Point(0, 0) case Direction.RIGHT: - return new Point(this.boardWidth, this.boardHeight); + return new Point(this.boardWidth, this.boardHeight) case Direction.TOP: - return new Point(this.boardWidth, 0); + return new Point(this.boardWidth, 0) case Direction.BOTTOM: - return new Point(0, this.boardHeight); + return new Point(0, this.boardHeight) } } updateSocketPosition() { const leftSockets = this.allSockets.filter( s => s.direction === Direction.LEFT, - ); + ) const rightSockets = this.allSockets.filter( s => s.direction === Direction.RIGHT, - ); + ) const topSockets = this.allSockets.filter( s => s.direction === Direction.TOP, - ); + ) const bottomSockets = this.allSockets.filter( s => s.direction === Direction.BOTTOM, - ); + ) spreadItems( this.boardHeight, leftSockets.length, SOCKET_PADDING_SCALE, ).forEach((offset, i) => { - leftSockets[i].blockX = 0; - leftSockets[i].blockY = offset; - }); + leftSockets[i].blockX = 0 + leftSockets[i].blockY = offset + }) spreadItems( this.boardHeight, rightSockets.length, SOCKET_PADDING_SCALE, ).forEach((offset, i) => { - rightSockets[i].blockX = this.boardWidth; - rightSockets[i].blockY = offset; - }); + rightSockets[i].blockX = this.boardWidth + rightSockets[i].blockY = offset + }) spreadItems( this.boardWidth, topSockets.length, SOCKET_PADDING_SCALE, ).forEach((offset, i) => { - topSockets[i].blockX = offset; - topSockets[i].blockY = 0; - }); + topSockets[i].blockX = offset + topSockets[i].blockY = 0 + }) spreadItems( this.boardWidth, bottomSockets.length, SOCKET_PADDING_SCALE, ).forEach((offset, i) => { - bottomSockets[i].blockX = offset; - bottomSockets[i].blockY = this.boardHeight; - }); + bottomSockets[i].blockX = offset + bottomSockets[i].blockY = this.boardHeight + }) } isBlockPosInside(blockPos: Point): boolean { return ( - blockPos.x >= 0 && - blockPos.x <= this.boardWidth && - blockPos.y >= 0 && - blockPos.y <= this.boardHeight - ); + blockPos.x >= 0 + && blockPos.x <= this.boardWidth + && blockPos.y >= 0 + && blockPos.y <= this.boardHeight + ) } get backgroudPath(): string { @@ -122,9 +128,9 @@ export abstract class RectBlock extends Block { pageHeight: height, pageWidth: width, pageBorderRadius: radius, - } = this; - const t1 = radius / 4; - const t2 = (radius * 3) / 4; + } = this + const t1 = radius / 4 + const t2 = (radius * 3) / 4 return `m 0 ${radius} v ${ height - radius * 2 @@ -135,31 +141,31 @@ export abstract class RectBlock extends Block { height - radius * 2 } c 0 -${t2} -${t1} -${radius} -${radius} -${radius} h -${ width - radius * 2 - } c -${t2} 0 -${radius} ${t1} -${radius} ${radius}`; + } c -${t2} 0 -${radius} ${t1} -${radius} ${radius}` } - content: (_: Context) => void; + content: (_: Context) => void contentMain = (_: Context) => { - const styles = useStyles(); + const styles = useStyles() - styles.contentOuterWrapper(); - _.$css`width:${this.pageWidth}px;height:${this.pageHeight}px;`; - _.$css`padding:${8 * this.graph.boardScale}px;`; + styles.contentOuterWrapper() + _.$css`width:${this.pageWidth}px;height:${this.pageHeight}px;` + _.$css`padding:${8 * this.graph.boardScale}px;` _._div({}, _ => { - styles.contentInnerWrapper(); - _.$css`transform:scale(${this.graph.boardScale})`; - _._div({}, this.content); - }); - }; + styles.contentInnerWrapper() + _.$css`transform:scale(${this.graph.boardScale})` + _._div({}, this.content) + }) + } createPredictor(): Block { - const predictor = super.createPredictor() as RectBlock; - predictor.boardWidth = this.boardWidth; - predictor.boardHeight = this.boardHeight; - predictor.boardBorderRadius = this.boardBorderRadius; - predictor.content = _ => {}; - return predictor; + const predictor = super.createPredictor() as RectBlock + predictor.boardWidth = this.boardWidth + predictor.boardHeight = this.boardHeight + predictor.boardBorderRadius = this.boardBorderRadius + predictor.content = _ => {} + return predictor } protected exportData(): any { @@ -167,20 +173,21 @@ export abstract class RectBlock extends Block { boardHeight: this.boardHeight, boardWidth: this.boardWidth, boardBorderRadius: this.boardBorderRadius, - } satisfies RectBlockRecordData; + } satisfies RectBlockRecordData } + protected importData( data: RectBlockRecordData, - sockets: Record, + _sockets: Record, ): void { - this.boardHeight = data.boardHeight; - this.boardWidth = data.boardWidth; - this.boardBorderRadius = data.boardBorderRadius; + this.boardHeight = data.boardHeight + this.boardWidth = data.boardWidth + this.boardBorderRadius = data.boardBorderRadius } } interface RectBlockRecordData { - boardHeight: number; - boardWidth: number; - boardBorderRadius: number; + boardHeight: number + boardWidth: number + boardBorderRadius: number } diff --git a/packages/visual-flow/src/components/block/RectBlock.styles.ts b/packages/visual-flow/src/components/block/RectBlock.styles.ts index 18c7c0c..9a63f73 100644 --- a/packages/visual-flow/src/components/block/RectBlock.styles.ts +++ b/packages/visual-flow/src/components/block/RectBlock.styles.ts @@ -1,24 +1,24 @@ -import { defineStyles, makeResetStyles, mergeClasses } from "@refina/griffel"; +import { defineStyles, makeResetStyles } from '@refina/griffel' const contentOuterWrapperClassName = makeResetStyles({ - position: "absolute", - display: "flex", - alignItems: "center", + position: 'absolute', + display: 'flex', + alignItems: 'center', left: 0, top: 0, - boxSizing: "border-box", -}); + boxSizing: 'border-box', +}) const contentInnerWrapperClassName = makeResetStyles({ flexGrow: 0, flexShrink: 0, - width: "max-content", - height: "max-content", - transformOrigin: "center left", -}); + width: 'max-content', + height: 'max-content', + transformOrigin: 'center left', +}) export default () => defineStyles({ contentOuterWrapper: [contentOuterWrapperClassName], contentInnerWrapper: [contentInnerWrapperClassName], - }); + }) diff --git a/packages/visual-flow/src/components/block/index.ts b/packages/visual-flow/src/components/block/index.ts index c2c7472..f8a1478 100644 --- a/packages/visual-flow/src/components/block/index.ts +++ b/packages/visual-flow/src/components/block/index.ts @@ -1 +1 @@ -export * from "./RectBlock.r"; +export * from './RectBlock.r' diff --git a/packages/visual-flow/src/components/index.ts b/packages/visual-flow/src/components/index.ts index 0b30de4..acce4d9 100644 --- a/packages/visual-flow/src/components/index.ts +++ b/packages/visual-flow/src/components/index.ts @@ -1,3 +1,3 @@ -export * from "./block"; -export * from "./line"; -export * from "./socket"; +export * from './block' +export * from './line' +export * from './socket' diff --git a/packages/visual-flow/src/components/line/BasicLine.ts b/packages/visual-flow/src/components/line/BasicLine.ts index 52f77f6..f241789 100644 --- a/packages/visual-flow/src/components/line/BasicLine.ts +++ b/packages/visual-flow/src/components/line/BasicLine.ts @@ -1,84 +1,85 @@ -import { Line, Socket } from "../../model"; -import { lineCtors } from "../../recorder"; -import { Point, rotate } from "../../types"; +import type { Socket } from '../../model' +import { Line } from '../../model' +import { lineCtors } from '../../recorder' +import { Point, rotate } from '../../types' -const CTRL_POINT_OFFSET_SCALE = 0.8; -const CTRL_POINT_OFFSET_MIN = 30; +const CTRL_POINT_OFFSET_SCALE = 0.8 +const CTRL_POINT_OFFSET_MIN = 30 -const ARROW_BOARD_LENGTH = 25; -const ARROW_BOARD_WIDTH = 7; -export const LINE_END_OFFSET = ARROW_BOARD_LENGTH * 0.99; +const ARROW_BOARD_LENGTH = 25 +const ARROW_BOARD_WIDTH = 7 +export const LINE_END_OFFSET = ARROW_BOARD_LENGTH * 0.99 function getCtrlPointOffset(delta: number) { return Math.max( Math.abs(delta * CTRL_POINT_OFFSET_SCALE), CTRL_POINT_OFFSET_MIN, - ); + ) } export class BasicLine extends Line { - ctorName: string = "BasicLine"; + ctorName: string = 'BasicLine' clone(): Line { - const line = new BasicLine(); - line.type = this.type; - return line; + const line = new BasicLine() + line.type = this.type + return line } calcCtrlPoint(point1: Point, point2: Point) { - const delta = Point.minus(point2, point1); + const delta = Point.minus(point2, point1) - const delta1 = Point.getComponentByDirection(delta, this.a.direction); - const offset1 = getCtrlPointOffset(delta1); - const controlPoint1 = Point.moveFarther(point1, this.a.direction, offset1); + const delta1 = Point.getComponentByDirection(delta, this.a.direction) + const offset1 = getCtrlPointOffset(delta1) + const controlPoint1 = Point.moveFarther(point1, this.a.direction, offset1) - const delta2 = Point.getComponentByDirection(delta, this.b.direction); - const offset2 = getCtrlPointOffset(delta2); - const controlPoint2 = Point.moveFarther(point2, this.b.direction, offset2); + const delta2 = Point.getComponentByDirection(delta, this.b.direction) + const offset2 = getCtrlPointOffset(delta2) + const controlPoint2 = Point.moveFarther(point2, this.b.direction, offset2) - return [controlPoint1, controlPoint2]; + return [controlPoint1, controlPoint2] } get linePath() { - let point1 = this.boardPosA; - let point2 = this.boardPosB; + const point1 = this.boardPosA + let point2 = this.boardPosB - point2 = Point.moveFarther(point2, this.b.direction, LINE_END_OFFSET); + point2 = Point.moveFarther(point2, this.b.direction, LINE_END_OFFSET) - const [controlPoint1, controlPoint2] = this.calcCtrlPoint(point1, point2); + const [controlPoint1, controlPoint2] = this.calcCtrlPoint(point1, point2) - const graphPos1 = this.graphPosA; - const graphPos2 = this.graph.boardPos2GraphPos(point2); - const graphCtrl1 = this.graph.boardPos2GraphPos(controlPoint1); - const graphCtrl2 = this.graph.boardPos2GraphPos(controlPoint2); + const graphPos1 = this.graphPosA + const graphPos2 = this.graph.boardPos2GraphPos(point2) + const graphCtrl1 = this.graph.boardPos2GraphPos(controlPoint1) + const graphCtrl2 = this.graph.boardPos2GraphPos(controlPoint2) - return `M${graphPos1.x} ${graphPos1.y} C${graphCtrl1.x} ${graphCtrl1.y}, ${graphCtrl2.x} ${graphCtrl2.y}, ${graphPos2.x} ${graphPos2.y}`; + return `M${graphPos1.x} ${graphPos1.y} C${graphCtrl1.x} ${graphCtrl1.y}, ${graphCtrl2.x} ${graphCtrl2.y}, ${graphPos2.x} ${graphPos2.y}` } calcArrowPoint() { - const p0 = this.boardPosB; - const p1 = Point.moveFarther(p0, this.b.direction, ARROW_BOARD_LENGTH); + const p0 = this.boardPosB + const p1 = Point.moveFarther(p0, this.b.direction, ARROW_BOARD_LENGTH) const p2 = Point.moveFarther( p1, rotate(this.b.direction), ARROW_BOARD_WIDTH, - ); + ) const p3 = Point.moveFarther( p1, rotate(this.b.direction), -ARROW_BOARD_WIDTH, - ); - return { p2, p3 }; + ) + return { p2, p3 } } get arrowPath() { - const { p2, p3 } = this.calcArrowPoint(); + const { p2, p3 } = this.calcArrowPoint() - const gp0 = this.graphPosB; - const gp2 = this.graph.boardPos2GraphPos(p2); - const gp3 = this.graph.boardPos2GraphPos(p3); + const gp0 = this.graphPosB + const gp2 = this.graph.boardPos2GraphPos(p2) + const gp3 = this.graph.boardPos2GraphPos(p3) - return `M${gp0.x} ${gp0.y} L${gp2.x} ${gp2.y} L${gp3.x} ${gp3.y} Z`; + return `M${gp0.x} ${gp0.y} L${gp2.x} ${gp2.y} L${gp3.x} ${gp3.y} Z` } drawThumbnail( @@ -87,21 +88,22 @@ export class BasicLine extends Line { top: number, scale: number, ): void { - if (this.predicting) return; + if (this.predicting) + return - ctx.lineWidth = Math.max(0.05, Math.min(2 * scale, 1)); - ctx.strokeStyle = this.dragging ? "rgb(15,84,140)" : "rgb(15,108,189)"; - ctx.fillStyle = ctx.strokeStyle; + ctx.lineWidth = Math.max(0.05, Math.min(2 * scale, 1)) + ctx.strokeStyle = this.dragging ? 'rgb(15,84,140)' : 'rgb(15,108,189)' + ctx.fillStyle = ctx.strokeStyle - let point1 = this.boardPosA; - let point2 = Point.moveFarther( + const point1 = this.boardPosA + const point2 = Point.moveFarther( this.boardPosB, this.b.direction, LINE_END_OFFSET, - ); - const [controlPoint1, controlPoint2] = this.calcCtrlPoint(point1, point2); - ctx.beginPath(); - ctx.moveTo((point1.x - left) * scale, (point1.y - top) * scale); + ) + const [controlPoint1, controlPoint2] = this.calcCtrlPoint(point1, point2) + ctx.beginPath() + ctx.moveTo((point1.x - left) * scale, (point1.y - top) * scale) ctx.bezierCurveTo( (controlPoint1.x - left) * scale, (controlPoint1.y - top) * scale, @@ -109,24 +111,25 @@ export class BasicLine extends Line { (controlPoint2.y - top) * scale, (point2.x - left) * scale, (point2.y - top) * scale, - ); - ctx.stroke(); - - const p0 = this.boardPosB; - const { p2, p3 } = this.calcArrowPoint(); - ctx.beginPath(); - ctx.moveTo((p0.x - left) * scale, (p0.y - top) * scale); - ctx.lineTo((p2.x - left) * scale, (p2.y - top) * scale); - ctx.lineTo((p3.x - left) * scale, (p3.y - top) * scale); - ctx.fill(); + ) + ctx.stroke() + + const p0 = this.boardPosB + const { p2, p3 } = this.calcArrowPoint() + ctx.beginPath() + ctx.moveTo((p0.x - left) * scale, (p0.y - top) * scale) + ctx.lineTo((p2.x - left) * scale, (p2.y - top) * scale) + ctx.lineTo((p3.x - left) * scale, (p3.y - top) * scale) + ctx.fill() } protected exportData(): any { - return {}; + return {} } + protected importData(_data: any, _sockets: Record): void { // do nothing } } -lineCtors["BasicLine"] = BasicLine; +lineCtors.BasicLine = BasicLine diff --git a/packages/visual-flow/src/components/line/index.ts b/packages/visual-flow/src/components/line/index.ts index c1eb90a..63e1b8b 100644 --- a/packages/visual-flow/src/components/line/index.ts +++ b/packages/visual-flow/src/components/line/index.ts @@ -1 +1 @@ -export * from "./BasicLine"; +export * from './BasicLine' diff --git a/packages/visual-flow/src/components/socket/MultiInSocket.ts b/packages/visual-flow/src/components/socket/MultiInSocket.ts index 74fb1d9..bc86f60 100644 --- a/packages/visual-flow/src/components/socket/MultiInSocket.ts +++ b/packages/visual-flow/src/components/socket/MultiInSocket.ts @@ -1,42 +1,46 @@ -import { Line, Socket } from "../../model"; -import { socketCtors } from "../../recorder"; -import { Direction, Point } from "../../types"; -import { LINE_END_OFFSET } from "../line"; +import type { Line } from '../../model' +import { Socket } from '../../model' +import { socketCtors } from '../../recorder' +import { Direction, Point } from '../../types' +import { LINE_END_OFFSET } from '../line' export class MultiInSocket extends Socket { - ctorName: string = "MultiInSocket"; + ctorName: string = 'MultiInSocket' - connectedLines: Line[] = []; + connectedLines: Line[] = [] get allConnectedLines(): Line[] { - return this.connectedLines; + return this.connectedLines } connectTo(line: Line): void { - this.connectedLines.push(line); - line.b = this; + this.connectedLines.push(line) + line.b = this } + disconnectTo(line: Line): void { - const index = this.connectedLines.indexOf(line); - if (index === -1) { - throw new Error("line not found"); - } - this.connectedLines.splice(index, 1); + const index = this.connectedLines.indexOf(line) + if (index === -1) + throw new Error('line not found') + + this.connectedLines.splice(index, 1) } canDragFrom(): boolean { - return false; + return false } + canDragRemove(): boolean { - return this.connectedLines.length > 0; + return this.connectedLines.length > 0 } + checkConnectable(line: Line): boolean { return ( - !this.disabled && - line.type === this.type && - this.block.id !== line.a.block.id && - this.connectedLines.every((l) => l.a.id !== line.a.id) - ); + !this.disabled + && line.type === this.type + && this.block.id !== line.a.block.id + && this.connectedLines.every(l => l.a.id !== line.a.id) + ) } getHoveredLine() { @@ -46,56 +50,59 @@ export class MultiInSocket extends Socket { [Direction.RIGHT]: (p: Point) => ({ x: Math.abs(p.x), y: p.y }), [Direction.TOP]: (p: Point) => ({ x: p.x, y: -Math.abs(p.y) }), [Direction.BOTTOM]: (p: Point) => ({ x: p.x, y: Math.abs(p.y) }), - }[this.direction]; + }[this.direction] const basePoint = Point.moveFarther( this.boardPos, this.direction, LINE_END_OFFSET, - ); + ) const { x: mouseDx, y: mouseDy } = normalizeDelta( Point.minus(this.graph.mouseBoardPos, basePoint), - ); - const theta0 = Math.atan2(mouseDy, mouseDx); + ) + const theta0 = Math.atan2(mouseDy, mouseDx) - let nearestLineDeltaTheta = Infinity; - let nearestLine = this.connectedLines[0]; + let nearestLineDeltaTheta = Number.POSITIVE_INFINITY + let nearestLine = this.connectedLines[0] for (const line of this.connectedLines) { const { x: lineDx, y: lineDy } = normalizeDelta( Point.minus(line.a.boardPos, basePoint), - ); + ) - const theta = Math.atan2(lineDy, lineDx); - const deltaTheta = Math.abs(theta - theta0); + const theta = Math.atan2(lineDy, lineDx) + const deltaTheta = Math.abs(theta - theta0) if (deltaTheta < nearestLineDeltaTheta) { - nearestLineDeltaTheta = deltaTheta; - nearestLine = line; + nearestLineDeltaTheta = deltaTheta + nearestLine = line } } - return nearestLine; - } else { - return this.connectedLines[0] ?? null; + return nearestLine + } + else { + return this.connectedLines[0] ?? null } } onMouseDown(): void { if (this.connectedLines.length > 0) { - const hoveredLine = this.getHoveredLine(); - this.disconnectTo(hoveredLine); - hoveredLine.neverLeaves = this; - this.graph.startDraggingLine(hoveredLine); - } else { + const hoveredLine = this.getHoveredLine() + this.disconnectTo(hoveredLine) + hoveredLine.neverLeaves = this + this.graph.startDraggingLine(hoveredLine) + } + else { // do nothing } } protected exportData(): any { - return {}; + return {} } + protected importData(_data: any): void { // do nothing } } -socketCtors["MultiInSocket"] = MultiInSocket; +socketCtors.MultiInSocket = MultiInSocket diff --git a/packages/visual-flow/src/components/socket/MultiOutSocket.ts b/packages/visual-flow/src/components/socket/MultiOutSocket.ts index 37dde04..6df63bf 100644 --- a/packages/visual-flow/src/components/socket/MultiOutSocket.ts +++ b/packages/visual-flow/src/components/socket/MultiOutSocket.ts @@ -1,52 +1,57 @@ -import { Line, Socket } from "../../model"; -import { socketCtors } from "../../recorder"; -import { BasicLine } from "../line"; +import type { Line } from '../../model' +import { Socket } from '../../model' +import { socketCtors } from '../../recorder' +import { BasicLine } from '../line' export class MultiOutSocket extends Socket { - ctorName: string = "MultiOutSocket"; + ctorName: string = 'MultiOutSocket' - connectedLines: Line[] = []; + connectedLines: Line[] = [] connectTo(line: Line): void { - this.connectedLines.push(line); + this.connectedLines.push(line) } + disconnectTo(line: Line) { - const index = this.connectedLines.indexOf(line); - if (index === -1) { - throw new Error("line not found"); - } - this.connectedLines.splice(index, 1); + const index = this.connectedLines.indexOf(line) + if (index === -1) + throw new Error('line not found') + + this.connectedLines.splice(index, 1) } canDragFrom(): boolean { - return !this.disabled; + return !this.disabled } + canDragRemove(): boolean { - return false; + return false } + checkConnectable(_line: Line): boolean { - return false; + return false } get allConnectedLines(): Line[] { - return this.connectedLines; + return this.connectedLines } getHoveredLine(): Line | null { - return null; + return null } onMouseDown(): void { - const line = this.connectToNewLine(new BasicLine()); - this.graph.startDraggingLine(line); + const line = this.connectToNewLine(new BasicLine()) + this.graph.startDraggingLine(line) } protected exportData(): any { - return {}; + return {} } + protected importData(_data: any): void { // do nothing } } -socketCtors["MultiOutSocket"] = MultiOutSocket; +socketCtors.MultiOutSocket = MultiOutSocket diff --git a/packages/visual-flow/src/components/socket/SingleInSocket.ts b/packages/visual-flow/src/components/socket/SingleInSocket.ts index fbcf5a6..f63513b 100644 --- a/packages/visual-flow/src/components/socket/SingleInSocket.ts +++ b/packages/visual-flow/src/components/socket/SingleInSocket.ts @@ -1,63 +1,69 @@ -import { Line, Socket } from "../../model"; -import { socketCtors } from "../../recorder"; +import type { Line } from '../../model' +import { Socket } from '../../model' +import { socketCtors } from '../../recorder' export class SingleInSocket extends Socket { - ctorName: string = "SingleInSocket"; + ctorName: string = 'SingleInSocket' - connectedLine: Line | null = null; + connectedLine: Line | null = null get allConnectedLines(): Line[] { - return this.connectedLine ? [this.connectedLine] : []; + return this.connectedLine ? [this.connectedLine] : [] } connectTo(line: Line): void { if (this.connectedLine) { - this.connectedLine.a.disconnectTo(this.connectedLine); - this.graph.removeLine(this.connectedLine); + this.connectedLine.a.disconnectTo(this.connectedLine) + this.graph.removeLine(this.connectedLine) } - this.connectedLine = line; - line.b = this; + this.connectedLine = line + line.b = this } + disconnectTo(_line: Line): void { - this.connectedLine = null; + this.connectedLine = null } canDragFrom(): boolean { - return false; + return false } + canDragRemove(): boolean { - return this.connectedLine !== null; + return this.connectedLine !== null } + checkConnectable(line: Line): boolean { return ( - !this.disabled && - line.type === this.type && - this.block.id !== line.a.block.id && - (!this.connectedLine || line.a.id !== this.connectedLine.a.id) - ); + !this.disabled + && line.type === this.type + && this.block.id !== line.a.block.id + && (!this.connectedLine || line.a.id !== this.connectedLine.a.id) + ) } onMouseDown(): void { if (this.connectedLine) { - const line = this.connectedLine; - this.connectedLine = null; - line.neverLeaves = this; - this.graph.startDraggingLine(line); - } else { + const line = this.connectedLine + this.connectedLine = null + line.neverLeaves = this + this.graph.startDraggingLine(line) + } + else { // do nothing } } getHoveredLine(): Line | null { - return this.connectedLine; + return this.connectedLine } protected exportData(): any { - return {}; + return {} } + protected importData(_data: any): void { // do nothing } } -socketCtors["SingleInSocket"] = SingleInSocket; +socketCtors.SingleInSocket = SingleInSocket diff --git a/packages/visual-flow/src/components/socket/SingleOutSocket.ts b/packages/visual-flow/src/components/socket/SingleOutSocket.ts index 9bc9637..6140ca6 100644 --- a/packages/visual-flow/src/components/socket/SingleOutSocket.ts +++ b/packages/visual-flow/src/components/socket/SingleOutSocket.ts @@ -1,57 +1,61 @@ -import { Line, Socket } from "../../model"; -import { socketCtors } from "../../recorder"; -import { BasicLine } from "../line"; -import { PATH_OUT_ELIPSE, PATH_OUT_RECT } from "./constants"; +import type { Line } from '../../model' +import { Socket } from '../../model' +import { socketCtors } from '../../recorder' +import { BasicLine } from '../line' export class SingleOutSocket extends Socket { - ctorName: string = "SingleOutSocket"; + ctorName: string = 'SingleOutSocket' - connectedLine: Line | null = null; + connectedLine: Line | null = null get allConnectedLines(): Line[] { - return this.connectedLine ? [this.connectedLine] : []; + return this.connectedLine ? [this.connectedLine] : [] } connectTo(line: Line): void { - this.connectedLine = line; + this.connectedLine = line } + disconnectTo(line: Line): void { - if (this.connectedLine === line) { - this.connectedLine = null; - } else { - throw new Error("line not found"); - } + if (this.connectedLine === line) + this.connectedLine = null + else + throw new Error('line not found') } canDragFrom(): boolean { - return !this.connectedLine && !this.disabled; + return !this.connectedLine && !this.disabled } + canDragRemove(): boolean { - return false; + return false } + checkConnectable(_line: Line): boolean { - return false; + return false } getHoveredLine(): Line | null { - return this.connectedLine; + return this.connectedLine } onMouseDown(): void { if (this.connectedLine) { // do nothing - } else { - const line = this.connectToNewLine(new BasicLine()); - this.graph.startDraggingLine(line); + } + else { + const line = this.connectToNewLine(new BasicLine()) + this.graph.startDraggingLine(line) } } protected exportData(): any { - return {}; + return {} } + protected importData(_data: any): void { // do nothing } } -socketCtors["SingleOutSocket"] = SingleOutSocket; +socketCtors.SingleOutSocket = SingleOutSocket diff --git a/packages/visual-flow/src/components/socket/constants.ts b/packages/visual-flow/src/components/socket/constants.ts index a8f8acd..6986692 100644 --- a/packages/visual-flow/src/components/socket/constants.ts +++ b/packages/visual-flow/src/components/socket/constants.ts @@ -1,23 +1,23 @@ -const LENGTH = 6; -const HEIGHT = 10; -const RADIUS = 5; +const LENGTH = 6 +const HEIGHT = 10 +const RADIUS = 5 export const PATH_OUT_TRIANGLE = `M 0 0 L 0 ${HEIGHT / 2} L ${LENGTH} 0 L 0 -${ HEIGHT / 2 -} Z`; +} Z` export const PATH_IN_TRIANGLE = `M 0 0 L 0 ${HEIGHT / 2} L ${-LENGTH} 0 L 0 -${ HEIGHT / 2 -} Z`; +} Z` export const PATH_OUT_RECT = `M 0 0 L 0 ${HEIGHT / 2} L ${LENGTH} ${ HEIGHT / 2 -} L ${LENGTH} ${-HEIGHT / 2} L 0 ${-HEIGHT / 2} Z`; +} L ${LENGTH} ${-HEIGHT / 2} L 0 ${-HEIGHT / 2} Z` export const PATH_IN_RECT = `M 0 0 L 0 ${HEIGHT / 2} L ${-LENGTH} ${ HEIGHT / 2 -} L ${-LENGTH} ${-HEIGHT / 2} L 0 ${-HEIGHT / 2} Z`; +} L ${-LENGTH} ${-HEIGHT / 2} L 0 ${-HEIGHT / 2} Z` -export const PATH_OUT_ELIPSE = `M 0 0 L 0 ${RADIUS} A ${RADIUS} ${RADIUS} 0 0 0 0 ${-RADIUS} Z`; +export const PATH_OUT_ELIPSE = `M 0 0 L 0 ${RADIUS} A ${RADIUS} ${RADIUS} 0 0 0 0 ${-RADIUS} Z` -export const PATH_IN_ELIPSE = `M 0 0 L 0 ${RADIUS} A ${RADIUS} ${RADIUS} 0 0 1 0 ${-RADIUS} Z`; +export const PATH_IN_ELIPSE = `M 0 0 L 0 ${RADIUS} A ${RADIUS} ${RADIUS} 0 0 1 0 ${-RADIUS} Z` diff --git a/packages/visual-flow/src/components/socket/index.ts b/packages/visual-flow/src/components/socket/index.ts index cbf400e..a49cc5d 100644 --- a/packages/visual-flow/src/components/socket/index.ts +++ b/packages/visual-flow/src/components/socket/index.ts @@ -1,5 +1,5 @@ -export * from "./MultiInSocket"; -export * from "./MultiOutSocket"; -export * from "./SingleInSocket"; -export * from "./SingleOutSocket"; -export * from "./constants"; +export * from './MultiInSocket' +export * from './MultiOutSocket' +export * from './SingleInSocket' +export * from './SingleOutSocket' +export * from './constants' diff --git a/packages/visual-flow/src/index.ts b/packages/visual-flow/src/index.ts index 7f37d37..5ca99f8 100644 --- a/packages/visual-flow/src/index.ts +++ b/packages/visual-flow/src/index.ts @@ -1,8 +1,8 @@ -import { Plugin } from "refina"; -import * as c from "./view"; +import type { Plugin } from 'refina' +import * as c from './view' export default { - name: "visual-flow", + name: 'visual-flow', components: { vfBlock: c.VfBlock, vfCreator: c.VfCreator, @@ -10,10 +10,10 @@ export default { vfLine: c.VfLine, vfSocket: c.VfSocket, }, -} satisfies Plugin; +} satisfies Plugin -export * from "./components"; -export * from "./model"; -export * from "./recorder"; -export * from "./types"; -export * from "./view"; +export * from './components' +export * from './model' +export * from './recorder' +export * from './types' +export * from './view' diff --git a/packages/visual-flow/src/model/base.ts b/packages/visual-flow/src/model/base.ts index 2cb65a8..273fb19 100644 --- a/packages/visual-flow/src/model/base.ts +++ b/packages/visual-flow/src/model/base.ts @@ -1,5 +1,5 @@ -import { allocateId } from "../utils"; +import { allocateId } from '../utils' export abstract class ModelBase { - id: number = allocateId(); + id: number = allocateId() } diff --git a/packages/visual-flow/src/model/block.ts b/packages/visual-flow/src/model/block.ts index 5a611c5..d320368 100644 --- a/packages/visual-flow/src/model/block.ts +++ b/packages/visual-flow/src/model/block.ts @@ -1,136 +1,149 @@ -import { +import type { Context, HTMLElementComponent, SVGElementComponent, +} from 'refina' +import { ref, -} from "refina"; -import { Direction, Point, rotate } from "../types"; -import { ModelBase } from "./base"; -import { Graph } from "./graph"; -import { Line } from "./line"; -import { Socket } from "./socket"; - -const MIN_INSIDE_DISTANCE_SQUARE = 25 * 25; -const MIN_OUTSIDE_DISTANCE_SQUARE = 40 * 40; -const MIN_DOCKING_DISTANCE_SQUARE = 40 * 40; +} from 'refina' +import type { Direction } from '../types' +import { Point, rotate } from '../types' +import { ModelBase } from './base' +import type { Graph } from './graph' +import type { Line } from './line' +import type { Socket } from './socket' + +const MIN_INSIDE_DISTANCE_SQUARE = 25 * 25 +const MIN_OUTSIDE_DISTANCE_SQUARE = 40 * 40 +const MIN_DOCKING_DISTANCE_SQUARE = 40 * 40 export type UseSocket = ( name: string, ctor: new () => T, data: Partial, -) => T; +) => T -export type UsedSockets = [string, Socket][]; +export type UsedSockets = [string, Socket][] export abstract class Block extends ModelBase { - abstract ctorName: string; + abstract ctorName: string - abstract cloneTo(target: this): this; + abstract cloneTo(target: this): this clone() { - return this.cloneTo(new (this.constructor as any)()); + return this.cloneTo(new (this.constructor as any)()) } - graph: Graph; + graph: Graph - ref = ref>(); + ref = ref>() get el() { - return this.ref.current?.node; + return this.ref.current?.node } - bgRef = ref>(); + bgRef = ref>() get bgEl() { - return this.bgRef.current?.node; + return this.bgRef.current?.node } - boardX: number; - boardY: number; + boardX: number + boardY: number get boardPos(): Point { - return { x: this.boardX, y: this.boardY }; + return { x: this.boardX, y: this.boardY } } + get graphPos(): Point { - return this.graph.boardPos2GraphPos(this.boardPos); + return this.graph.boardPos2GraphPos(this.boardPos) } + get pagePos(): Point { - return this.graph.boardPos2PagePos(this.boardPos); + return this.graph.boardPos2PagePos(this.boardPos) } - abstract get boundingRectBoardWidth(): number; - abstract get boundingRectBoardHeight(): number; + abstract get boundingRectBoardWidth(): number + abstract get boundingRectBoardHeight(): number boardPos2BlockPos(boardPos: Point): Point { - return Point.minus(boardPos, this.boardPos); + return Point.minus(boardPos, this.boardPos) } + graphPos2BlockPos(graphPos: Point): Point { - return this.boardPos2BlockPos(this.graph.graphPos2BoardPos(graphPos)); + return this.boardPos2BlockPos(this.graph.graphPos2BoardPos(graphPos)) } + pagePos2BlockPos(pagePos: Point): Point { - return this.boardPos2BlockPos(this.graph.pagePos2BoardPos(pagePos)); + return this.boardPos2BlockPos(this.graph.pagePos2BoardPos(pagePos)) } + blockPos2BoardPos(blockPos: Point): Point { - return Point.add(blockPos, this.boardPos); + return Point.add(blockPos, this.boardPos) } + blockPos2GraphPos(blockPos: Point): Point { - return this.graph.boardPos2GraphPos(this.blockPos2BoardPos(blockPos)); + return this.graph.boardPos2GraphPos(this.blockPos2BoardPos(blockPos)) } + blockPos2PagePos(blockPos: Point): Point { - return this.graph.boardPos2PagePos(this.blockPos2BoardPos(blockPos)); + return this.graph.boardPos2PagePos(this.blockPos2BoardPos(blockPos)) } - zIndex: number; + zIndex: number - protected _selected: boolean = false; + protected _selected: boolean = false get selected() { - return this._selected; + return this._selected } + set selected(selected: boolean) { - this._selected = selected; - for (const [_d, b] of this.dockedByBlocks) { - b.selected = selected; - } + this._selected = selected + for (const [_d, b] of this.dockedByBlocks) + b.selected = selected } - predicting: boolean = false; - pendingClick: boolean = false; + + predicting: boolean = false + pendingClick: boolean = false /** * Whether the block is attached to the graph. * When dragging from the panel, it is not attached until the mouse is released inside the graph. */ - attached = false; + attached = false - dockableDirections: [Direction, string][] = []; - dockingDirections: [Direction, string][] = []; - dockedToBlock: Block | null = null; - dockedByBlocks: [Direction, Block][] = []; + dockableDirections: [Direction, string][] = [] + dockingDirections: [Direction, string][] = [] + dockedToBlock: Block | null = null + dockedByBlocks: [Direction, Block][] = [] /** * @example `direction` is `LEFT`, then returns the top-left point of the block. */ - abstract getDockingBenchmarkBlockPos(direction: Direction): Point; + abstract getDockingBenchmarkBlockPos(direction: Direction): Point getDockingBenchmarkBoardPos(direction: Direction): Point { - return this.blockPos2BoardPos(this.getDockingBenchmarkBlockPos(direction)); + return this.blockPos2BoardPos(this.getDockingBenchmarkBlockPos(direction)) } + getDockedBenchmarkBlockPos(direction: Direction): Point { - return this.getDockingBenchmarkBlockPos(rotate(direction)); + return this.getDockingBenchmarkBlockPos(rotate(direction)) } + getDockedBenchmarkBoardPos(direction: Direction): Point { - return this.getDockingBenchmarkBoardPos(rotate(direction)); + return this.getDockingBenchmarkBoardPos(rotate(direction)) } setBoardPos(boardPos: Point) { - if (this.dockedToBlock) { - return; - } - this.boardX = boardPos.x; - this.boardY = boardPos.y; - this.setDockedBlocksPos(); + if (this.dockedToBlock) + return + + this.boardX = boardPos.x + this.boardY = boardPos.y + this.setDockedBlocksPos() } setDockPos(direction: Direction, benchmarkBoardPoint: Point) { - const benchmarkBlockPos = this.getDockingBenchmarkBlockPos(direction); - this.boardX = benchmarkBoardPoint.x - benchmarkBlockPos.x; - this.boardY = benchmarkBoardPoint.y - benchmarkBlockPos.y; - this.setDockedBlocksPos(); - this.updatePosition(); // TODO: why remove this will cause issue? + const benchmarkBlockPos = this.getDockingBenchmarkBlockPos(direction) + this.boardX = benchmarkBoardPoint.x - benchmarkBlockPos.x + this.boardY = benchmarkBoardPoint.y - benchmarkBlockPos.y + this.setDockedBlocksPos() + this.updatePosition() // TODO: why remove this will cause issue? } protected setDockedBlocksPos() { @@ -138,270 +151,281 @@ export abstract class Block extends ModelBase { dockedBlock.setDockPos( dockedDirection, this.getDockedBenchmarkBoardPos(dockedDirection), - ); + ) } } moveToTop() { - for (const [_d, b] of this.dockedByBlocks) { - this.graph.moveBlockToTop(b); - } - this.graph.moveBlockToTop(this); - this.graph.updateBlockZIndex(); + for (const [_d, b] of this.dockedByBlocks) + this.graph.moveBlockToTop(b) + + this.graph.moveBlockToTop(this) + this.graph.updateBlockZIndex() } attach() { - this.attached = true; + this.attached = true } dockTo(block: Block, direction: Direction) { - this.dockedToBlock = block; - block.dockBy(this, direction); + this.dockedToBlock = block + block.dockBy(this, direction) } + protected dockBy(block: Block, direction: Direction) { - this.dockedByBlocks.push([direction, block]); - this.moveToTop(); - block.setDockPos(direction, this.getDockedBenchmarkBoardPos(direction)); + this.dockedByBlocks.push([direction, block]) + this.moveToTop() + block.setDockPos(direction, this.getDockedBenchmarkBoardPos(direction)) } + undockFrom() { - this.dockedToBlock!.undockBy(this); - this.dockedToBlock = null; + this.dockedToBlock!.undockBy(this) + this.dockedToBlock = null } + protected undockBy(block: Block) { - this.dockedByBlocks = this.dockedByBlocks.filter(([_d, b]) => b !== block); + this.dockedByBlocks = this.dockedByBlocks.filter(([_d, b]) => b !== block) } - sockets: [string, Socket][] = []; + sockets: [string, Socket][] = [] get allSockets(): Socket[] { - return this.sockets.map(([_, socket]) => socket); + return this.sockets.map(([_, socket]) => socket) } getSocketByName(name: string) { - return this.sockets.find(([n, _]) => n === name)?.[1]; + return this.sockets.find(([n, _]) => n === name)?.[1] } + getSocketsByPrefix(prefix: string) { - prefix += "-"; + prefix += '-' return this.sockets .filter(([n, _]) => n.startsWith(prefix)) - .map(([_, s]) => s); + .map(([_, s]) => s) } abstract socketUpdater( useSocket: UseSocket, usedSockets: [string, Socket][], - ): void; + ): void updateSockets() { - const socketsToRemove = new Map(this.sockets); - const newSockets: [string, Socket][] = []; + const socketsToRemove = new Map(this.sockets) + const newSockets: [string, Socket][] = [] this.socketUpdater( - (name: string, ctor: new () => T, data: Partial) => { - let socket = socketsToRemove.get(name); + (name: string, Ctor: new () => T, data: Partial) => { + let socket = socketsToRemove.get(name) if (socket) { - socketsToRemove.delete(name); - } else { - socket = new ctor(); - socket.block = this; + socketsToRemove.delete(name) } - socket.label = name; + else { + socket = new Ctor() + socket.block = this + } + socket.label = name if (data.disabled) { - socket.allConnectedLines.forEach((l) => { + socket.allConnectedLines.forEach(l => { l.a.disconnectTo(l); - (l.b as Socket).disconnectTo(l); - this.graph.removeLine(l); - }); + (l.b as Socket).disconnectTo(l) + this.graph.removeLine(l) + }) } - Object.assign(socket, data); - newSockets.push([name, socket]); + Object.assign(socket, data) + newSockets.push([name, socket]) - return socket as T; + return socket as T }, newSockets, - ); + ) for (const socket of socketsToRemove.values()) { - socket.allConnectedLines.forEach((l) => { + socket.allConnectedLines.forEach(l => { l.a.disconnectTo(l); - (l.b as Socket).disconnectTo(l); - this.graph.removeLine(l); - }); + (l.b as Socket).disconnectTo(l) + this.graph.removeLine(l) + }) } - this.sockets = newSockets; + this.sockets = newSockets - this.updateSocketPosition(); + this.updateSocketPosition() } updatePosition() { - const { x, y } = this.attached ? this.graphPos : this.pagePos; - if (this.el) this.el.style.left = `${x}px`; - if (this.el) this.el.style.top = `${y}px`; - this.updateSocketPosition(); - this.updateLinkedLinesPosition(); - this.updateDockedBlocksPosition(); - } - abstract updateSocketPosition(): void; + const { x, y } = this.attached ? this.graphPos : this.pagePos + if (this.el) + this.el.style.left = `${x}px` + if (this.el) + this.el.style.top = `${y}px` + this.updateSocketPosition() + this.updateLinkedLinesPosition() + this.updateDockedBlocksPosition() + } + + abstract updateSocketPosition(): void protected updateLinkedLinesPosition() { - this.allSockets.forEach((s) => - s.allConnectedLines.forEach((l) => l.updatePosition()), - ); + this.allSockets.forEach(s => + s.allConnectedLines.forEach(l => l.updatePosition()), + ) } + protected updateDockedBlocksPosition() { this.dockedByBlocks.forEach(([_d, b]) => { - b.updatePosition(); - }); + b.updatePosition() + }) } - abstract isBlockPosInside(blockPos: Point): boolean; + abstract isBlockPosInside(blockPos: Point): boolean /** * @returns Whether the line is accepted. */ checkConnectable(line: Line): Socket | null { - const connectableSockets = this.allSockets.filter((s) => + const connectableSockets = this.allSockets.filter(s => s.checkConnectable(line), - ); + ) - const pagePos = this.graph.mousePagePos; - const blockPos = this.pagePos2BlockPos(pagePos); + const pagePos = this.graph.mousePagePos + const blockPos = this.pagePos2BlockPos(pagePos) - return getNearestSocket(connectableSockets, blockPos)?.[0] ?? null; + return getNearestSocket(connectableSockets, blockPos)?.[0] ?? null } getDraggingSource(blockOnly: boolean): null | Block | [Socket, number] { - if (!this.attached) { - return this; - } + if (!this.attached) + return this - const blockPos = this.pagePos2BlockPos(this.graph.mousePagePos); + const blockPos = this.pagePos2BlockPos(this.graph.mousePagePos) - const isInside = this.isBlockPosInside(blockPos); + const isInside = this.isBlockPosInside(blockPos) - if (blockOnly) return isInside ? this : null; + if (blockOnly) + return isInside ? this : null const draggableSockets = isInside - ? this.allSockets.filter((s) => s.canDragFrom()) - : this.allSockets.filter((s) => s.canDragRemove() || s.canDragFrom()); + ? this.allSockets.filter(s => s.canDragFrom()) + : this.allSockets.filter(s => s.canDragRemove() || s.canDragFrom()) const maxSocketDistanceSquare: number = isInside ? MIN_INSIDE_DISTANCE_SQUARE - : MIN_OUTSIDE_DISTANCE_SQUARE; + : MIN_OUTSIDE_DISTANCE_SQUARE const hoveredSocket = getNearestSocket( draggableSockets, blockPos, maxSocketDistanceSquare, - ); + ) - if (hoveredSocket) { - return isInside ? [hoveredSocket[0], -Infinity] : hoveredSocket; - } else { - return isInside ? this : null; - } + if (hoveredSocket) + return isInside ? [hoveredSocket[0], Number.NEGATIVE_INFINITY] : hoveredSocket + else + return isInside ? this : null } getDraggingLineTarget(line: Line): null | Socket | [Socket, number] { - const blockPos = this.pagePos2BlockPos(this.graph.mousePagePos); + const blockPos = this.pagePos2BlockPos(this.graph.mousePagePos) - const connectableSockets = this.allSockets.filter((s) => + const connectableSockets = this.allSockets.filter(s => s.checkConnectable(line), - ); + ) if (this.isBlockPosInside(blockPos)) { // if the mouse is inside the block, must connect to the nearest connectable socket. - return getNearestSocket(connectableSockets, blockPos)?.[0] ?? null; - } else { + return getNearestSocket(connectableSockets, blockPos)?.[0] ?? null + } + else { return getNearestSocket( connectableSockets, blockPos, MIN_OUTSIDE_DISTANCE_SQUARE, - ); + ) } } isDockableBy(block: Block): null | [number, Direction, Point] { - if (this === block || this.predicting) return null; - let minDockingDistanceSquare = MIN_DOCKING_DISTANCE_SQUARE; - let dockingInfo: [Direction, Point] | null = null; + if (this === block || this.predicting) + return null + let minDockingDistanceSquare = MIN_DOCKING_DISTANCE_SQUARE + let dockingInfo: [Direction, Point] | null = null for (const [direction, type] of this.dockableDirections) { if ( block.dockingDirections.some( - (d) => d[0] == direction && d[1] == type, - ) && - this.dockedByBlocks.every(([d, _b]) => d !== direction) + d => d[0] === direction && d[1] === type, + ) + && this.dockedByBlocks.every(([d, _b]) => d !== direction) ) { - const p1 = this.getDockedBenchmarkBoardPos(direction); - const p2 = block.getDockingBenchmarkBoardPos(direction); - const distanceSquare = Point.distanceSquare(p1, p2); + const p1 = this.getDockedBenchmarkBoardPos(direction) + const p2 = block.getDockingBenchmarkBoardPos(direction) + const distanceSquare = Point.distanceSquare(p1, p2) if (distanceSquare < minDockingDistanceSquare) { - minDockingDistanceSquare = distanceSquare; - dockingInfo = [direction, Point.minus(p1, p2)]; + minDockingDistanceSquare = distanceSquare + dockingInfo = [direction, Point.minus(p1, p2)] } } } return dockingInfo !== null ? [minDockingDistanceSquare, ...dockingInfo] - : null; + : null } onHover(): void { - this.el?.classList.add("hovered"); - this.bgEl?.classList.add("hovered"); - for (const [_d, b] of this.dockedByBlocks) { - b.onHover(); - } + this.el?.classList.add('hovered') + this.bgEl?.classList.add('hovered') + for (const [_d, b] of this.dockedByBlocks) + b.onHover() } + onUnhover(): void { - this.el?.classList.remove("hovered"); - this.bgEl?.classList.remove("hovered"); - for (const [_d, b] of this.dockedByBlocks) { - b.onUnhover(); - } + this.el?.classList.remove('hovered') + this.bgEl?.classList.remove('hovered') + for (const [_d, b] of this.dockedByBlocks) + b.onUnhover() } onMouseDown(targetSocket: Socket | null, preserveSelected: boolean): void { if (targetSocket) { - this.graph.clearSelectedBlocks(); - targetSocket.onMouseDown(); - } else { + this.graph.clearSelectedBlocks() + targetSocket.onMouseDown() + } + else { if (this.selected && this.graph.selectedBlocks.size > 1) { for (const block of this.graph.selectedBlocks) { - if (block.dockedToBlock) { - block.undockFrom(); - } - block.moveToTop(); - } - this.graph.startDraggingSelectedBlocks(); - } else { - if (this.dockedToBlock) { - this.undockFrom(); + if (block.dockedToBlock) + block.undockFrom() + + block.moveToTop() } - this.graph.addSelectedBlock(this, preserveSelected); - this.pendingClick = true; - this.moveToTop(); - this.graph.startDraggingBlock(this); + this.graph.startDraggingSelectedBlocks() + } + else { + if (this.dockedToBlock) + this.undockFrom() + + this.graph.addSelectedBlock(this, preserveSelected) + this.pendingClick = true + this.moveToTop() + this.graph.startDraggingBlock(this) } } } - abstract get backgroudPath(): string; + abstract get backgroudPath(): string - abstract contentMain: (_: Context) => void; + abstract contentMain: (_: Context) => void createPredictor(): Block { - const predictor = this.clone(); - predictor.graph = this.graph; - predictor.attached = this.attached; - predictor.selected = true; - predictor.predicting = true; - predictor.boardX = this.boardX; - predictor.boardY = this.boardY; - return predictor; + const predictor = this.clone() + predictor.graph = this.graph + predictor.attached = this.attached + predictor.selected = true + predictor.predicting = true + predictor.boardX = this.boardX + predictor.boardY = this.boardY + return predictor } - protected abstract exportData(): any; + protected abstract exportData(): any exportRecord(): BlockRecord { return { ctor: this.ctorName, @@ -414,65 +438,66 @@ export abstract class Block extends ModelBase { dockedByBlocks: this.dockedByBlocks.map(([d, b]) => [d, b.id]), sockets: this.sockets.map(([name, socket]) => [name, socket.id]), data: this.exportData(), - }; + } } + protected abstract importData( data: any, sockets: Record, - ): void; + ): void importRecord( record: BlockRecord, blocks: Record, sockets: Record, ) { - this.id = record.id; - this.attached = true; - this.boardX = record.boardX; - this.boardY = record.boardY; - this.dockableDirections = record.dockableDirections; - this.dockingDirections = record.dockingDirection; + this.id = record.id + this.attached = true + this.boardX = record.boardX + this.boardY = record.boardY + this.dockableDirections = record.dockableDirections + this.dockingDirections = record.dockingDirection this.dockedToBlock = record.dockedToBlock ? blocks[record.dockedToBlock] - : null; - this.dockedByBlocks = record.dockedByBlocks.map(([d, b]) => [d, blocks[b]]); + : null + this.dockedByBlocks = record.dockedByBlocks.map(([d, b]) => [d, blocks[b]]) for (const [name, socketId] of record.sockets) { - const socket = sockets[socketId]; - socket.block = this; - this.sockets.push([name, socket]); + const socket = sockets[socketId] + socket.block = this + this.sockets.push([name, socket]) } - this.updateSocketPosition(); + this.updateSocketPosition() - this.importData(record.data, sockets); + this.importData(record.data, sockets) } } function getNearestSocket( sockets: Socket[], blockPos: Point, - maxSocketDistanceSquare: number = Infinity, + maxSocketDistanceSquare: number = Number.POSITIVE_INFINITY, ): [Socket, number] | null { - let minSocketDistanceSquare = maxSocketDistanceSquare; - let nearestSocket: null | Socket = null; + let minSocketDistanceSquare = maxSocketDistanceSquare + let nearestSocket: null | Socket = null for (const socket of sockets) { - const distance = Point.distanceSquare(socket.blockPos, blockPos); + const distance = Point.distanceSquare(socket.blockPos, blockPos) if (distance < minSocketDistanceSquare) { - minSocketDistanceSquare = distance; - nearestSocket = socket; + minSocketDistanceSquare = distance + nearestSocket = socket } } - return nearestSocket ? [nearestSocket, minSocketDistanceSquare] : null; + return nearestSocket ? [nearestSocket, minSocketDistanceSquare] : null } export interface BlockRecord { - ctor: string; - id: number; - boardX: number; - boardY: number; - dockableDirections: [Direction, string][]; - dockingDirection: [Direction, string][]; - dockedToBlock: number | null; - dockedByBlocks: [Direction, number][]; - sockets: [string, number][]; - data: any; + ctor: string + id: number + boardX: number + boardY: number + dockableDirections: [Direction, string][] + dockingDirection: [Direction, string][] + dockedToBlock: number | null + dockedByBlocks: [Direction, number][] + sockets: [string, number][] + data: any } diff --git a/packages/visual-flow/src/model/graph.ts b/packages/visual-flow/src/model/graph.ts index bfb3006..c11ff37 100644 --- a/packages/visual-flow/src/model/graph.ts +++ b/packages/visual-flow/src/model/graph.ts @@ -1,20 +1,23 @@ -import deepEqual from "deep-equal"; -import { App, HTMLElementComponent, ref } from "refina"; -import { VfRecord, exportVf, importVf } from "../recorder"; -import { Direction, Point } from "../types"; -import { Block } from "./block"; -import { Line } from "./line"; -import { Socket } from "./socket"; - -const MIN_ZINDEX = 0; -const BOARD_SCALE_MIN = 0.2; -const BOARD_SCALE_MAX = 4; -const AUTO_MOVE_INTERVAL = 10; -const AUTO_MOVE_START_PADDING = 70; -const AUTO_MOVE_SPEED_SCALE = 0.07; -const AUTO_MOVE_SPEED_MAX = AUTO_MOVE_START_PADDING * AUTO_MOVE_SPEED_SCALE; -const GRID_SIZE = 30; -const FULL_VIEW_PADDING = 100; +import deepEqual from 'deep-equal' +import type { App, HTMLElementComponent } from 'refina' +import { ref } from 'refina' +import type { VfRecord } from '../recorder' +import { exportVf, importVf } from '../recorder' +import type { Direction } from '../types' +import { Point } from '../types' +import type { Block } from './block' +import type { Line } from './line' +import type { Socket } from './socket' + +const MIN_ZINDEX = 0 +const BOARD_SCALE_MIN = 0.2 +const BOARD_SCALE_MAX = 4 +const AUTO_MOVE_INTERVAL = 10 +const AUTO_MOVE_START_PADDING = 70 +const AUTO_MOVE_SPEED_SCALE = 0.07 +const AUTO_MOVE_SPEED_MAX = AUTO_MOVE_START_PADDING * AUTO_MOVE_SPEED_SCALE +const GRID_SIZE = 30 +const FULL_VIEW_PADDING = 100 export enum GraphStateType { IDLE, @@ -24,882 +27,927 @@ export enum GraphStateType { DRAGGING_BOARD, } -type IdelState = { - type: GraphStateType.IDLE; -}; -type DraggingLineState = { - type: GraphStateType.DRAGGING_LINE; - line: Line; - predictor: Line; -}; -type DraggingBlockState = { - type: GraphStateType.DRAGGING_BLOCK; - block: Block; - predictor: Block; - offsetBoardX0: number; - offsetBoardY0: number; -}; -type DraggingMultiBlockState = { - type: GraphStateType.DRAGGING_MULTI_BLOCK; +interface IdelState { + type: GraphStateType.IDLE +} +interface DraggingLineState { + type: GraphStateType.DRAGGING_LINE + line: Line + predictor: Line +} +interface DraggingBlockState { + type: GraphStateType.DRAGGING_BLOCK + block: Block + predictor: Block + offsetBoardX0: number + offsetBoardY0: number +} +interface DraggingMultiBlockState { + type: GraphStateType.DRAGGING_MULTI_BLOCK blocks: { - block: Block; - offsetBoardX0: number; - offsetBoardY0: number; - }[]; -}; -type DraggingBoardState = { - type: GraphStateType.DRAGGING_BOARD; - startPageX: number; - startPageY: number; - initialBoardOffsetX: number; - initialBoardOffsetY: number; -}; + block: Block + offsetBoardX0: number + offsetBoardY0: number + }[] +} +interface DraggingBoardState { + type: GraphStateType.DRAGGING_BOARD + startPageX: number + startPageY: number + initialBoardOffsetX: number + initialBoardOffsetY: number +} type State = | IdelState | DraggingLineState | DraggingBlockState | DraggingMultiBlockState - | DraggingBoardState; + | DraggingBoardState -const idelState = { type: GraphStateType.IDLE } as const; +const idelState = { type: GraphStateType.IDLE } as const export class Graph { - app: App; + app: App - ref = ref>(); + ref = ref>() get el() { - return this.ref.current?.node; + return this.ref.current?.node } - canvasRef = ref>(); + canvasRef = ref>() get canvasEl() { - return this.canvasRef.current?.node; + return this.canvasRef.current?.node } + getCanvasCtx() { - return this.canvasRef.current!.node.getContext("2d")!; + return this.canvasRef.current!.node.getContext('2d')! } - initialRecord: VfRecord; - recordStack: VfRecord[] = []; - recordIndex: number = -1; + initialRecord: VfRecord + recordStack: VfRecord[] = [] + recordIndex: number = -1 get canUndo() { - return this.recordIndex >= 0; + return this.recordIndex >= 0 } + get canRedo() { - return this.recordIndex < this.recordStack.length - 1; + return this.recordIndex < this.recordStack.length - 1 } reset() { - this.blocks = []; - this.blockZIndex = []; - this.boardMoveSpeed = { x: 0, y: 0 }; - this.lines = []; - this.boardOffsetX = 0; - this.boardOffsetY = 0; - this.boardScale = 1; + this.blocks = [] + this.blockZIndex = [] + this.boardMoveSpeed = { x: 0, y: 0 } + this.lines = [] + this.boardOffsetX = 0 + this.boardOffsetY = 0 + this.boardScale = 1 } + undo() { - this.selectedBlocks.clear(); + this.selectedBlocks.clear() if (this.recordIndex === 0) { - importVf(this.initialRecord, this); - --this.recordIndex; - } else { - importVf(this.recordStack[--this.recordIndex], this); + importVf(this.initialRecord, this) + --this.recordIndex + } + else { + importVf(this.recordStack[--this.recordIndex], this) } } + redo() { - this.selectedBlocks.clear(); - importVf(this.recordStack[++this.recordIndex], this); + this.selectedBlocks.clear() + importVf(this.recordStack[++this.recordIndex], this) } captureInitialRecord() { - this.initialRecord = exportVf(this); + this.initialRecord = exportVf(this) } + pushRecord() { - const record = exportVf(this); - const lastRecord = - this.recordIndex === -1 + const record = exportVf(this) + const lastRecord + = this.recordIndex === -1 ? this.initialRecord - : this.recordStack[this.recordIndex]; - if (deepEqual(record, lastRecord)) return; + : this.recordStack[this.recordIndex] + if (deepEqual(record, lastRecord)) + return - this.recordStack = this.recordStack.slice(0, this.recordIndex + 1); - this.recordStack.push(record); - this.recordIndex++; + this.recordStack = this.recordStack.slice(0, this.recordIndex + 1) + this.recordStack.push(record) + this.recordIndex++ } + overwriteRecord() { - if (this.recordIndex < 0) { - this.pushRecord(); - } else { - this.recordStack[this.recordIndex] = exportVf(this); - } + if (this.recordIndex < 0) + this.pushRecord() + else + this.recordStack[this.recordIndex] = exportVf(this) } /** * The position of the left-top corner of the graph in board coord. */ - boardOffsetX: number = 0; - boardOffsetY: number = 0; + boardOffsetX: number = 0 + boardOffsetY: number = 0 get originGraphPos(): Point { - return this.boardPos2GraphPos({ x: 0, y: 0 }); + return this.boardPos2GraphPos({ x: 0, y: 0 }) } /** * 1 in board coord equals `boardScale` px in screen. */ - boardScale: number = 1; + boardScale: number = 1 boardPos2GraphPos(boardPos: Point): Point { return { x: (boardPos.x - this.boardOffsetX) * this.boardScale, y: (boardPos.y - this.boardOffsetY) * this.boardScale, - }; + } } + graphPos2BoardPos(graphPos: Point): Point { return { x: graphPos.x / this.boardScale + this.boardOffsetX, y: graphPos.y / this.boardScale + this.boardOffsetY, - }; + } } graphPos2PagePos(graphPos: Point): Point { - const boundingRect = this.el!.getBoundingClientRect(); + const boundingRect = this.el!.getBoundingClientRect() return { x: graphPos.x + boundingRect.x, y: graphPos.y + boundingRect.y, - }; + } } + pagePos2GraphPos(pagePos: Point): Point { - const boundingRect = this.el!.getBoundingClientRect(); + const boundingRect = this.el!.getBoundingClientRect() return { x: pagePos.x - boundingRect.x, y: pagePos.y - boundingRect.y, - }; + } } boardPos2PagePos(boardPos: Point): Point { - return this.graphPos2PagePos(this.boardPos2GraphPos(boardPos)); + return this.graphPos2PagePos(this.boardPos2GraphPos(boardPos)) } + pagePos2BoardPos(pagePos: Point): Point { - return this.graphPos2BoardPos(this.pagePos2GraphPos(pagePos)); + return this.graphPos2BoardPos(this.pagePos2GraphPos(pagePos)) } get isMouseInsideGraph(): boolean { - const { left, top, right, bottom } = this.el!.getBoundingClientRect(); + const { left, top, right, bottom } = this.el!.getBoundingClientRect() return ( - this.mousePagePos.x >= left && - this.mousePagePos.x <= right && - this.mousePagePos.y >= top && - this.mousePagePos.y <= bottom - ); + this.mousePagePos.x >= left + && this.mousePagePos.x <= right + && this.mousePagePos.y >= top + && this.mousePagePos.y <= bottom + ) } - blocks: Block[] = []; + blocks: Block[] = [] getBlockById(id: number): Block { - const block = this.blocks.find((b) => b.id === id); - if (!block) throw new Error(`Block ${id} not found`); - return block; + const block = this.blocks.find(b => b.id === id) + if (!block) + throw new Error(`Block ${id} not found`) + return block } + get blocksIdMap(): Record { - return Object.fromEntries(this.blocks.map((b) => [b.id, b])); + return Object.fromEntries(this.blocks.map(b => [b.id, b])) } + get socketsIdMap(): Record { return Object.fromEntries( - this.blocks.flatMap((b) => b.allSockets).map((s) => [s.id, s]), - ); + this.blocks.flatMap(b => b.allSockets).map(s => [s.id, s]), + ) } - lines: Line[] = []; + lines: Line[] = [] getLineById(id: number): Line { - const line = this.lines.find((l) => l.id === id); - if (!line) throw new Error(`Line ${id} not found`); - return line; + const line = this.lines.find(l => l.id === id) + if (!line) + throw new Error(`Line ${id} not found`) + return line } + get linesIdMap(): Record { - return Object.fromEntries(this.lines.map((l) => [l.id, l])); + return Object.fromEntries(this.lines.map(l => [l.id, l])) } get displayLines(): { - bg: Line[]; - fg: Line[]; + bg: Line[] + fg: Line[] } { - const state = this.state; + const state = this.state if (state.type === GraphStateType.DRAGGING_LINE) { return { bg: this.lines.filter( - (line) => line !== state.line && line !== state.predictor, + line => line !== state.line && line !== state.predictor, ), fg: [state.predictor, state.line], - }; - } else if (state.type === GraphStateType.DRAGGING_BLOCK) { + } + } + else if (state.type === GraphStateType.DRAGGING_BLOCK) { const linkedLines = state.block.allSockets.flatMap( - (s) => s.allConnectedLines, - ); + s => s.allConnectedLines, + ) return { - bg: this.lines.filter((line) => !linkedLines.includes(line)), + bg: this.lines.filter(line => !linkedLines.includes(line)), fg: linkedLines, - }; - } else { + } + } + else { return { bg: this.lines, fg: [], - }; + } } } - state: State = idelState; - protected mouseDown: boolean = false; - protected scaleEndTimeout: number = NaN; - protected hoveredItem: Block | [Socket, Line | null] | null = null; - mousePagePos: Point; - mouseGraphPos: Point; - mouseBoardPos: Point; + state: State = idelState + protected mouseDown: boolean = false + protected scaleEndTimeout: number = Number.NaN + protected hoveredItem: Block | [Socket, Line | null] | null = null + mousePagePos: Point + mouseGraphPos: Point + mouseBoardPos: Point - selectedBlocks = new Set(); + selectedBlocks = new Set() clearSelectedBlocks() { - for (const block of this.selectedBlocks) { - block.selected = false; - } - this.selectedBlocks.clear(); + for (const block of this.selectedBlocks) + block.selected = false + + this.selectedBlocks.clear() } + addSelectedBlock(block: Block, shiftKey: boolean) { - if (!shiftKey) { - this.clearSelectedBlocks(); - } - this.selectedBlocks.add(block); - block.selected = true; + if (!shiftKey) + this.clearSelectedBlocks() + + this.selectedBlocks.add(block) + block.selected = true } setHoveredItem(hoveredItem: Block | [Socket, Line | null] | null) { if (this.hoveredItem !== hoveredItem) { if (Array.isArray(this.hoveredItem)) { - this.hoveredItem[0].onUnhover(); - this.hoveredItem[1]?.onUnhover(); - } else { - this.hoveredItem?.onUnhover(); + this.hoveredItem[0].onUnhover() + this.hoveredItem[1]?.onUnhover() + } + else { + this.hoveredItem?.onUnhover() } if (Array.isArray(hoveredItem)) { - hoveredItem[0].onHover(); - hoveredItem[1]?.onHover(); - } else { - hoveredItem?.onHover(); + hoveredItem[0].onHover() + hoveredItem[1]?.onHover() } - this.hoveredItem = hoveredItem; + else { + hoveredItem?.onHover() + } + this.hoveredItem = hoveredItem } } setMousePos(ev: MouseEvent) { - this.mousePagePos = { x: ev.pageX, y: ev.pageY }; - this.syncGraphAndBoardMousePos(); + this.mousePagePos = { x: ev.pageX, y: ev.pageY } + this.syncGraphAndBoardMousePos() } + protected syncGraphAndBoardMousePos() { - this.mouseGraphPos = this.pagePos2GraphPos(this.mousePagePos); - this.mouseBoardPos = this.graphPos2BoardPos(this.mouseGraphPos); + this.mouseGraphPos = this.pagePos2GraphPos(this.mousePagePos) + this.mouseBoardPos = this.graphPos2BoardPos(this.mouseGraphPos) } - protected blockZIndex: (Block | null)[] = []; + protected blockZIndex: (Block | null)[] = [] addBlock(block: Block) { - block.graph = this; - this.blocks.push(block); - this.blockZIndex.push(block); + block.graph = this + this.blocks.push(block) + this.blockZIndex.push(block) } + removeBlock(block: Block) { - this.blocks.splice(this.blocks.indexOf(block), 1); - const index = this.blockZIndex.indexOf(block); - if (index === -1) throw new Error("Block not found"); - this.blockZIndex.splice(index, 1); - this.selectedBlocks.delete(block); - this.updateBlockZIndex(); + this.blocks.splice(this.blocks.indexOf(block), 1) + const index = this.blockZIndex.indexOf(block) + if (index === -1) + throw new Error('Block not found') + this.blockZIndex.splice(index, 1) + this.selectedBlocks.delete(block) + this.updateBlockZIndex() } addLine(line: Line) { - line.graph = this; - this.lines.push(line); + line.graph = this + this.lines.push(line) } + removeLine(line: Line) { - this.lines.splice(this.lines.indexOf(line), 1); + this.lines.splice(this.lines.indexOf(line), 1) } updatePosition() { - this.blocks.forEach((b) => b.updatePosition()); - this.lines.forEach((l) => l.updatePosition()); - this.redrawCanvas(); + this.blocks.forEach(b => b.updatePosition()) + this.lines.forEach(l => l.updatePosition()) + this.redrawCanvas() } + protected updateDraggingBlockPosition({ block, predictor, offsetBoardX0, offsetBoardY0, }: DraggingBlockState) { - const { x: boardX0, y: boardY0 } = this.mouseBoardPos; + const { x: boardX0, y: boardY0 } = this.mouseBoardPos const newPagePos = { x: boardX0 - offsetBoardX0, y: boardY0 - offsetBoardY0, - }; - block.setBoardPos(newPagePos); - predictor.setBoardPos(newPagePos); - block.updatePosition(); - predictor.updatePosition(); + } + block.setBoardPos(newPagePos) + predictor.setBoardPos(newPagePos) + block.updatePosition() + predictor.updatePosition() } + protected updateDraggingMultiBlocksPosition({ blocks, }: DraggingMultiBlockState) { - const { x: boardX0, y: boardY0 } = this.mouseBoardPos; + const { x: boardX0, y: boardY0 } = this.mouseBoardPos for (const blockData of blocks) { - const { block, offsetBoardX0, offsetBoardY0 } = blockData; + const { block, offsetBoardX0, offsetBoardY0 } = blockData const newPagePos = { x: boardX0 - offsetBoardX0, y: boardY0 - offsetBoardY0, - }; - block.setBoardPos(newPagePos); - block.updatePosition(); + } + block.setBoardPos(newPagePos) + block.updatePosition() } } + protected updateDraggingLinePosition({ line, predictor }: DraggingLineState) { - line.setBoardPosB(this.mouseBoardPos); - line.updatePosition(); - predictor.setBoardPosB(this.mouseBoardPos); - predictor.updatePosition(); + line.setBoardPosB(this.mouseBoardPos) + line.updatePosition() + predictor.setBoardPosB(this.mouseBoardPos) + predictor.updatePosition() } protected redrawCanvas() { - const ctx = this.getCanvasCtx(); + const ctx = this.getCanvasCtx() const { left: fullviewLeft, top: fullviewTop, right: fullviewRight, bottom: fullviewBottom, - } = this.fullViewRect; - const { width: graphWidth, height: graphHeight } = - this.el!.getBoundingClientRect(); + } = this.fullViewRect + const { width: graphWidth, height: graphHeight } + = this.el!.getBoundingClientRect() - const left = Math.min(fullviewLeft, this.boardOffsetX); - const top = Math.min(fullviewTop, this.boardOffsetY); + const left = Math.min(fullviewLeft, this.boardOffsetX) + const top = Math.min(fullviewTop, this.boardOffsetY) const right = Math.max( fullviewRight, this.boardOffsetX + graphWidth / this.boardScale, - ); + ) const bottom = Math.max( fullviewBottom, this.boardOffsetY + graphHeight / this.boardScale, - ); + ) - const width = right - left; - const height = bottom - top; + const width = right - left + const height = bottom - top - const scale = Math.sqrt(30000 / (width * height)); + const scale = Math.sqrt(30000 / (width * height)) if (this.canvasEl) { - this.canvasEl.style.width = width * scale + "px"; - this.canvasEl.style.height = height * scale + "px"; - this.canvasEl.width = width * scale; - this.canvasEl.height = height * scale; + this.canvasEl.style.width = `${width * scale}px` + this.canvasEl.style.height = `${height * scale}px` + this.canvasEl.width = width * scale + this.canvasEl.height = height * scale } - const { fg: fgLines, bg: bgLines } = this.displayLines; + const { fg: fgLines, bg: bgLines } = this.displayLines - for (const line of bgLines) { - line.drawThumbnail(ctx, left, top, scale); - } + for (const line of bgLines) + line.drawThumbnail(ctx, left, top, scale) for (const block of this.blockZIndex) { if (block) { - ctx.fillStyle = block.selected ? "rgb(17,94,163)" : "rgb(71,158,245)"; + ctx.fillStyle = block.selected ? 'rgb(17,94,163)' : 'rgb(71,158,245)' ctx.fillRect( (block.boardPos.x - left) * scale, (block.boardPos.y - top) * scale, block.boundingRectBoardWidth * scale, block.boundingRectBoardHeight * scale, - ); + ) } } - for (const line of fgLines) { - line.drawThumbnail(ctx, left, top, scale); - } + for (const line of fgLines) + line.drawThumbnail(ctx, left, top, scale) - ctx.strokeStyle = "#555555"; - ctx.lineWidth = 2; + ctx.strokeStyle = '#555555' + ctx.lineWidth = 2 ctx.strokeRect( (this.boardOffsetX - left) * scale, (this.boardOffsetY - top) * scale, (graphWidth / this.boardScale) * scale - 1, (graphHeight / this.boardScale) * scale - 1, - ); + ) // ctx.fillStyle = "rgb(200,0,0)"; // ctx.fillRect(10, 10, 55, 50); } - protected boardMoveSpeed: Point = { x: 0, y: 0 }; + protected boardMoveSpeed: Point = { x: 0, y: 0 } protected boardMovingInterval = setInterval(() => { - this.updateBoardMoveSpeed(); - if (this.boardMoveSpeed.x === 0 && this.boardMoveSpeed.y === 0) return; - this.boardOffsetX += this.boardMoveSpeed.x / this.boardScale; - this.boardOffsetY += this.boardMoveSpeed.y / this.boardScale; - this.syncGraphAndBoardMousePos(); - this.updatePosition(); - if (this.state.type === GraphStateType.DRAGGING_BLOCK) { - this.updateDraggingBlockPosition(this.state); - } else if (this.state.type === GraphStateType.DRAGGING_MULTI_BLOCK) { - this.updateDraggingMultiBlocksPosition(this.state); - } else if (this.state.type === GraphStateType.DRAGGING_LINE) { - this.updateDraggingLinePosition(this.state); - } - }, AUTO_MOVE_INTERVAL); + this.updateBoardMoveSpeed() + if (this.boardMoveSpeed.x === 0 && this.boardMoveSpeed.y === 0) + return + this.boardOffsetX += this.boardMoveSpeed.x / this.boardScale + this.boardOffsetY += this.boardMoveSpeed.y / this.boardScale + this.syncGraphAndBoardMousePos() + this.updatePosition() + if (this.state.type === GraphStateType.DRAGGING_BLOCK) + this.updateDraggingBlockPosition(this.state) + else if (this.state.type === GraphStateType.DRAGGING_MULTI_BLOCK) + this.updateDraggingMultiBlocksPosition(this.state) + else if (this.state.type === GraphStateType.DRAGGING_LINE) + this.updateDraggingLinePosition(this.state) + }, AUTO_MOVE_INTERVAL) + protected updateBoardMoveSpeed() { if ( - this.mouseDown && - ((this.state.type === GraphStateType.DRAGGING_BLOCK && - this.state.block.attached) || - this.state.type === GraphStateType.DRAGGING_MULTI_BLOCK || - this.state.type === GraphStateType.DRAGGING_LINE) + this.mouseDown + && ((this.state.type === GraphStateType.DRAGGING_BLOCK + && this.state.block.attached) + || this.state.type === GraphStateType.DRAGGING_MULTI_BLOCK + || this.state.type === GraphStateType.DRAGGING_LINE) ) { this.boardMoveSpeed = { x: calcMoveSpeed(this.mouseGraphPos.x, this.el!.clientWidth), y: calcMoveSpeed(this.mouseGraphPos.y, this.el!.clientHeight), - }; - } else { - this.boardMoveSpeed = { x: 0, y: 0 }; + } + } + else { + this.boardMoveSpeed = { x: 0, y: 0 } } } protected getDraggingSource( blockOnly: boolean, ): null | readonly [Block, Socket | null] { - let socketTarget: Socket | null = null, - minSocketDistanceSquare: number = Infinity; + let socketTarget: Socket | null = null + let minSocketDistanceSquare: number = Number.POSITIVE_INFINITY for (let i = this.blockZIndex.length - 1; i >= 0; i--) { - const block = this.blockZIndex[i]; - if (!block) continue; - const result = block.getDraggingSource(blockOnly); + const block = this.blockZIndex[i] + if (!block) + continue + const result = block.getDraggingSource(blockOnly) if (result !== null) { if (Array.isArray(result)) { - if (result[1] === -Infinity) { - return [result[0].block, result[0]] as const; - } + if (result[1] === Number.NEGATIVE_INFINITY) + return [result[0].block, result[0]] as const + if (result[1] < minSocketDistanceSquare) { - socketTarget = result[0]; - minSocketDistanceSquare = result[1]; + socketTarget = result[0] + minSocketDistanceSquare = result[1] } - } else { - return [result, null] as const; + } + else { + return [result, null] as const } } } - return socketTarget ? [socketTarget.block, socketTarget] : null; + return socketTarget ? [socketTarget.block, socketTarget] : null } + protected getDraggingTarget(line: Line): null | Socket { - let socketTarget: Socket | null = null, - minSocketDistanceSquare: number = Infinity; + let socketTarget: Socket | null = null + let minSocketDistanceSquare: number = Number.POSITIVE_INFINITY for (let i = this.blockZIndex.length - 1; i >= 0; i--) { - const block = this.blockZIndex[i]; - if (!block) continue; - const result = block.getDraggingLineTarget(line); + const block = this.blockZIndex[i] + if (!block) + continue + const result = block.getDraggingLineTarget(line) if (result !== null) { if (Array.isArray(result)) { if (result[1] < minSocketDistanceSquare) { - socketTarget = result[0]; - minSocketDistanceSquare = result[1]; + socketTarget = result[0] + minSocketDistanceSquare = result[1] } - } else { - return result; + } + else { + return result } } } - return socketTarget; + return socketTarget } + protected getDockingTarget(block: Block): [Block, Direction, Point] | null { - let minDockingDistanceSquare = Infinity; - let dockingTarget: [Block, Direction, Point] | null = null; + let minDockingDistanceSquare = Number.POSITIVE_INFINITY + let dockingTarget: [Block, Direction, Point] | null = null for (let i = this.blockZIndex.length - 1; i >= 0; i--) { - const target = this.blockZIndex[i]; - if (!target) continue; - const result = target.isDockableBy(block); + const target = this.blockZIndex[i] + if (!target) + continue + const result = target.isDockableBy(block) if (result !== null) { - const [distanceSquare, ...dockingInfo] = result; + const [distanceSquare, ...dockingInfo] = result if (distanceSquare < minDockingDistanceSquare) { - minDockingDistanceSquare = distanceSquare; - dockingTarget = [target, ...dockingInfo]; + minDockingDistanceSquare = distanceSquare + dockingTarget = [target, ...dockingInfo] } } } - return dockingTarget; + return dockingTarget } moveBlockToTop(block: Block) { - const index = this.blockZIndex.indexOf(block); - if (index === -1) throw new Error("Block not found"); - this.blockZIndex[index] = null; - this.blockZIndex.push(block); + const index = this.blockZIndex.indexOf(block) + if (index === -1) + throw new Error('Block not found') + this.blockZIndex[index] = null + this.blockZIndex.push(block) } updateBlockZIndex() { - this.blockZIndex = this.blockZIndex.filter((b) => b !== null); + this.blockZIndex = this.blockZIndex.filter(b => b !== null) for (let i = 0; i < this.blockZIndex.length; i++) { - const block = this.blockZIndex[i]; - if (block) { - block.zIndex = i + MIN_ZINDEX; - } + const block = this.blockZIndex[i] + if (block) + block.zIndex = i + MIN_ZINDEX } } startDraggingBlock(block: Block) { - const predictor = block.createPredictor(); - this.addBlock(predictor); - predictor.moveToTop(); - const { x: blockBoardX, y: blockBoardY } = block.boardPos; + const predictor = block.createPredictor() + this.addBlock(predictor) + predictor.moveToTop() + const { x: blockBoardX, y: blockBoardY } = block.boardPos this.state = { type: GraphStateType.DRAGGING_BLOCK, block, - predictor: predictor, + predictor, offsetBoardX0: this.mouseBoardPos.x - blockBoardX, offsetBoardY0: this.mouseBoardPos.y - blockBoardY, - }; + } } startDraggingSelectedBlocks() { this.state = { type: GraphStateType.DRAGGING_MULTI_BLOCK, - blocks: [...this.selectedBlocks].map((block) => { - const { x: blockBoardX, y: blockBoardY } = block.boardPos; + blocks: [...this.selectedBlocks].map(block => { + const { x: blockBoardX, y: blockBoardY } = block.boardPos return { block, offsetBoardX0: this.mouseBoardPos.x - blockBoardX, offsetBoardY0: this.mouseBoardPos.y - blockBoardY, - }; + } }), - }; + } } startDraggingLine(line: Line) { - const predictor = line.createPredictor(); - this.addLine(predictor); + const predictor = line.createPredictor() + this.addLine(predictor) - line.dragging = true; + line.dragging = true this.state = { type: GraphStateType.DRAGGING_LINE, line, predictor, - }; + } } toGridPos(pos: Point) { return { x: Math.round(pos.x / GRID_SIZE) * GRID_SIZE, y: Math.round(pos.y / GRID_SIZE) * GRID_SIZE, - }; + } } onScaling(scaleDelta: number) { if ( - (this.boardScale <= BOARD_SCALE_MIN && scaleDelta < 0) || - (this.boardScale >= BOARD_SCALE_MAX && scaleDelta > 0) - ) { - return true; - } - if (!Number.isNaN(this.scaleEndTimeout)) clearTimeout(this.scaleEndTimeout); + (this.boardScale <= BOARD_SCALE_MIN && scaleDelta < 0) + || (this.boardScale >= BOARD_SCALE_MAX && scaleDelta > 0) + ) + return true + + if (!Number.isNaN(this.scaleEndTimeout)) + clearTimeout(this.scaleEndTimeout) this.scaleEndTimeout = setTimeout(() => { - this.pushRecord(); - this.scaleEndTimeout = NaN; - this.app.update(); - }, 500); + this.pushRecord() + this.scaleEndTimeout = Number.NaN + this.app.update() + }, 500) - const oldScale = this.boardScale; - let newScale = this.boardScale + scaleDelta; - if (newScale < BOARD_SCALE_MIN) newScale = BOARD_SCALE_MIN; - else if (newScale > BOARD_SCALE_MAX) newScale = BOARD_SCALE_MAX; + const oldScale = this.boardScale + let newScale = this.boardScale + scaleDelta + if (newScale < BOARD_SCALE_MIN) + newScale = BOARD_SCALE_MIN + else if (newScale > BOARD_SCALE_MAX) + newScale = BOARD_SCALE_MAX - const { x: mouseGraphX, y: mouseGraphY } = this.mouseGraphPos; + const { x: mouseGraphX, y: mouseGraphY } = this.mouseGraphPos - const k = 1 / oldScale - 1 / newScale; + const k = 1 / oldScale - 1 / newScale - this.boardOffsetX += mouseGraphX * k; - this.boardOffsetY += mouseGraphY * k; + this.boardOffsetX += mouseGraphX * k + this.boardOffsetY += mouseGraphY * k - this.boardScale = newScale; + this.boardScale = newScale - this.syncGraphAndBoardMousePos(); - this.onMouseMove(this.mouseDown, false); - this.updatePosition(); - return true; + this.syncGraphAndBoardMousePos() + this.onMouseMove(this.mouseDown, false) + this.updatePosition() + return true } onMouseMove(mouseDown: boolean, shiftKey: boolean): boolean { - if (mouseDown && !this.mouseDown) { - return this.onMouseDown(false); - } - if (!mouseDown && this.mouseDown) { - return this.onMouseUp(false); - } + if (mouseDown && !this.mouseDown) + return this.onMouseDown(false) + + if (!mouseDown && this.mouseDown) + return this.onMouseUp(false) if (this.state.type === GraphStateType.IDLE) { - const draggingSource = this.getDraggingSource(shiftKey); + const draggingSource = this.getDraggingSource(shiftKey) if (draggingSource) { if (draggingSource[1]) { this.setHoveredItem([ draggingSource[1], draggingSource[1].getHoveredLine(), - ]); - } else { - this.setHoveredItem(draggingSource[0]); + ]) } - } else { - this.setHoveredItem(null); + else { + this.setHoveredItem(draggingSource[0]) + } + } + else { + this.setHoveredItem(null) } - return false; + return false } if (this.state.type === GraphStateType.DRAGGING_LINE) { - if (!mouseDown) { - throw new Error("Not dragging line"); - } - const { line, predictor } = this.state; - const targetSocket = this.getDraggingTarget(line); + if (!mouseDown) + throw new Error('Not dragging line') + + const { line, predictor } = this.state + const targetSocket = this.getDraggingTarget(line) if (targetSocket) { - this.setHoveredItem([targetSocket, targetSocket.getHoveredLine()]); - line.setBoardPosB(this.mouseBoardPos, targetSocket.direction); + this.setHoveredItem([targetSocket, targetSocket.getHoveredLine()]) + line.setBoardPosB(this.mouseBoardPos, targetSocket.direction) predictor.setBoardPosB( line.neverLeaves ? this.mouseBoardPos : targetSocket.boardPos, targetSocket.direction, - ); - } else { - this.setHoveredItem(null); - line.setBoardPosB(this.mouseBoardPos); - predictor.setBoardPosB(this.mouseBoardPos); + ) + } + else { + this.setHoveredItem(null) + line.setBoardPosB(this.mouseBoardPos) + predictor.setBoardPosB(this.mouseBoardPos) } - line.updatePosition(); - predictor.updatePosition(); + line.updatePosition() + predictor.updatePosition() - this.redrawCanvas(); - return false; + this.redrawCanvas() + return false } if (this.state.type === GraphStateType.DRAGGING_BLOCK) { - if (!mouseDown) { - throw new Error("Not dragging block"); - } - const { x: boardX0, y: boardY0 } = this.mouseBoardPos; - const { block, predictor, offsetBoardX0, offsetBoardY0 } = this.state; + if (!mouseDown) + throw new Error('Not dragging block') + + const { x: boardX0, y: boardY0 } = this.mouseBoardPos + const { block, predictor, offsetBoardX0, offsetBoardY0 } = this.state const newBlockBoardPos = { x: boardX0 - offsetBoardX0, y: boardY0 - offsetBoardY0, - }; + } - block.pendingClick = false; - block.setBoardPos(newBlockBoardPos); - block.updatePosition(); + block.pendingClick = false + block.setBoardPos(newBlockBoardPos) + block.updatePosition() - const dockingTarget = this.getDockingTarget(block); + const dockingTarget = this.getDockingTarget(block) if (dockingTarget) { - const [blockToDock, _direction, movementBoardPos] = dockingTarget; - this.setHoveredItem(blockToDock); - predictor.setBoardPos(Point.add(newBlockBoardPos, movementBoardPos)); - } else { - this.setHoveredItem(null); - predictor.setBoardPos(newBlockBoardPos); + const [blockToDock, _direction, movementBoardPos] = dockingTarget + this.setHoveredItem(blockToDock) + predictor.setBoardPos(Point.add(newBlockBoardPos, movementBoardPos)) } - predictor.updatePosition(); + else { + this.setHoveredItem(null) + predictor.setBoardPos(newBlockBoardPos) + } + predictor.updatePosition() - this.redrawCanvas(); - return false; + this.redrawCanvas() + return false } if (this.state.type === GraphStateType.DRAGGING_MULTI_BLOCK) { - if (!mouseDown) { - throw new Error("Not dragging block"); - } - const { x: boardX0, y: boardY0 } = this.mouseBoardPos; - const { blocks } = this.state; + if (!mouseDown) + throw new Error('Not dragging block') + + const { x: boardX0, y: boardY0 } = this.mouseBoardPos + const { blocks } = this.state for (const blockData of blocks) { - const { block, offsetBoardX0, offsetBoardY0 } = blockData; + const { block, offsetBoardX0, offsetBoardY0 } = blockData const newBlockBoardPos = { x: boardX0 - offsetBoardX0, y: boardY0 - offsetBoardY0, - }; - block.pendingClick = false; - block.setBoardPos(newBlockBoardPos); - block.updatePosition(); + } + block.pendingClick = false + block.setBoardPos(newBlockBoardPos) + block.updatePosition() // this.setHoveredItem(null); } - this.redrawCanvas(); - return false; + this.redrawCanvas() + return false } if (this.state.type === GraphStateType.DRAGGING_BOARD) { - if (!mouseDown) { - throw new Error("Not dragging board"); - } + if (!mouseDown) + throw new Error('Not dragging board') + const { startPageX, startPageY, initialBoardOffsetX, initialBoardOffsetY, - } = this.state; - const { x: mousePageX, y: mousePageY } = this.mousePagePos; - this.boardOffsetX = - initialBoardOffsetX + (startPageX - mousePageX) / this.boardScale; - this.boardOffsetY = - initialBoardOffsetY + (startPageY - mousePageY) / this.boardScale; - this.updatePosition(); - return false; + } = this.state + const { x: mousePageX, y: mousePageY } = this.mousePagePos + this.boardOffsetX + = initialBoardOffsetX + (startPageX - mousePageX) / this.boardScale + this.boardOffsetY + = initialBoardOffsetY + (startPageY - mousePageY) / this.boardScale + this.updatePosition() + return false } - return false; + return false } onMouseDown(shiftKey: boolean) { - if (this.mouseDown) { - this.onMouseUp(shiftKey); - } - this.mouseDown = true; + if (this.mouseDown) + this.onMouseUp(shiftKey) - this.state = idelState; + this.mouseDown = true - const hoveredBlock = this.getDraggingSource(shiftKey); + this.state = idelState + + const hoveredBlock = this.getDraggingSource(shiftKey) if (hoveredBlock) { - hoveredBlock[0].onMouseDown(hoveredBlock[1], shiftKey); - return true; + hoveredBlock[0].onMouseDown(hoveredBlock[1], shiftKey) + return true } if (this.isMouseInsideGraph) { - if (!shiftKey) this.clearSelectedBlocks(); - const pagePos = this.mousePagePos; + if (!shiftKey) + this.clearSelectedBlocks() + const pagePos = this.mousePagePos this.state = { type: GraphStateType.DRAGGING_BOARD, startPageX: pagePos.x, startPageY: pagePos.y, initialBoardOffsetX: this.boardOffsetX, initialBoardOffsetY: this.boardOffsetY, - }; - return true; + } + return true } - return false; + return false } onMouseUp(shiftKey: boolean) { - if (!this.mouseDown) { - this.onMouseDown(false); - } - this.mouseDown = false; + if (!this.mouseDown) + this.onMouseDown(false) + + this.mouseDown = false + + if (this.state.type === GraphStateType.IDLE) + return false - if (this.state.type === GraphStateType.IDLE) { - return false; - } if (this.state.type === GraphStateType.DRAGGING_BOARD) { - this.state = idelState; - this.pushRecord(); - return true; + this.state = idelState + this.pushRecord() + return true } if (this.state.type === GraphStateType.DRAGGING_BLOCK) { - const { block, predictor, offsetBoardX0, offsetBoardY0 } = this.state; - this.removeBlock(predictor); + const { block, predictor, offsetBoardX0, offsetBoardY0 } = this.state + this.removeBlock(predictor) - const dockingTarget = this.getDockingTarget(block); + const dockingTarget = this.getDockingTarget(block) if (dockingTarget) { - const [blockToDock, dockingDirection, _movementBoardPos] = - dockingTarget; - block.dockTo(blockToDock, dockingDirection); + const [blockToDock, dockingDirection, _movementBoardPos] + = dockingTarget + block.dockTo(blockToDock, dockingDirection) } - const { x: boardX0, y: boardY0 } = this.mouseBoardPos; + const { x: boardX0, y: boardY0 } = this.mouseBoardPos const newBlockBoardPos = this.toGridPos({ x: boardX0 - offsetBoardX0, y: boardY0 - offsetBoardY0, - }); - block.setBoardPos(newBlockBoardPos); - block.updatePosition(); + }) + block.setBoardPos(newBlockBoardPos) + block.updatePosition() if (!block.attached) { if (this.isMouseInsideGraph) { - block.attach(); - this.pushRecord(); - } else { - this.removeBlock(block); + block.attach() + this.pushRecord() + } + else { + this.removeBlock(block) } - } else if (block.pendingClick) { - this.addSelectedBlock(block, shiftKey); - this.overwriteRecord(); - } else { - this.pushRecord(); } - block.pendingClick = false; - this.state = idelState; - return true; + else if (block.pendingClick) { + this.addSelectedBlock(block, shiftKey) + this.overwriteRecord() + } + else { + this.pushRecord() + } + block.pendingClick = false + this.state = idelState + return true } if (this.state.type === GraphStateType.DRAGGING_MULTI_BLOCK) { - const { blocks } = this.state; + const { blocks } = this.state for (const blockData of blocks) { - const { block, offsetBoardX0, offsetBoardY0 } = blockData; - const { x: boardX0, y: boardY0 } = this.mouseBoardPos; + const { block, offsetBoardX0, offsetBoardY0 } = blockData + const { x: boardX0, y: boardY0 } = this.mouseBoardPos const newBlockBoardPos = this.toGridPos({ x: boardX0 - offsetBoardX0, y: boardY0 - offsetBoardY0, - }); - block.setBoardPos(newBlockBoardPos); - block.updatePosition(); + }) + block.setBoardPos(newBlockBoardPos) + block.updatePosition() } - this.pushRecord(); - this.state = idelState; - return true; + this.pushRecord() + this.state = idelState + return true } if (this.state.type === GraphStateType.DRAGGING_LINE) { - const { line, predictor } = this.state; - const targetSocket = this.getDraggingTarget(line); + const { line, predictor } = this.state + const targetSocket = this.getDraggingTarget(line) if (!line.neverLeaves && targetSocket) { - targetSocket.connectTo(line); - line.dragging = false; - this.moveBlockToTop(targetSocket.block); - this.updateBlockZIndex(); - } else { - line.a.disconnectTo(line); - this.removeLine(line); + targetSocket.connectTo(line) + line.dragging = false + this.moveBlockToTop(targetSocket.block) + this.updateBlockZIndex() + } + else { + line.a.disconnectTo(line) + this.removeLine(line) } - this.removeLine(predictor); - this.state = idelState; - this.pushRecord(); - return true; + this.removeLine(predictor) + this.state = idelState + this.pushRecord() + return true } - return false; + return false } onHorizontalScroll(delta: number) { - this.boardOffsetX += delta / this.boardScale; - this.syncGraphAndBoardMousePos(); - this.onMouseMove(this.mouseDown, false); - this.updatePosition(); - return true; + this.boardOffsetX += delta / this.boardScale + this.syncGraphAndBoardMousePos() + this.onMouseMove(this.mouseDown, false) + this.updatePosition() + return true } onVerticalScroll(delta: number) { - this.boardOffsetY += delta / this.boardScale; - this.syncGraphAndBoardMousePos(); - this.onMouseMove(this.mouseDown, false); - this.updatePosition(); - return true; + this.boardOffsetY += delta / this.boardScale + this.syncGraphAndBoardMousePos() + this.onMouseMove(this.mouseDown, false) + this.updatePosition() + return true } onResize() { - this.updatePosition(); + this.updatePosition() } resetViewport() { - this.boardOffsetX = 0; - this.boardOffsetY = 0; - this.boardScale = 1; + this.boardOffsetX = 0 + this.boardOffsetY = 0 + this.boardScale = 1 } get fullViewRect() { - const blocks = this.blocks.filter((b) => b.attached); - const left = - Math.min(...blocks.map((b) => b.boardPos.x)) - FULL_VIEW_PADDING; - const top = - Math.min(...blocks.map((b) => b.boardPos.y)) - FULL_VIEW_PADDING; - const right = - Math.max(...blocks.map((b) => b.boardPos.x + b.boundingRectBoardWidth)) + - FULL_VIEW_PADDING; - const bottom = - Math.max(...blocks.map((b) => b.boardPos.y + b.boundingRectBoardHeight)) + - FULL_VIEW_PADDING; + const blocks = this.blocks.filter(b => b.attached) + const left + = Math.min(...blocks.map(b => b.boardPos.x)) - FULL_VIEW_PADDING + const top + = Math.min(...blocks.map(b => b.boardPos.y)) - FULL_VIEW_PADDING + const right + = Math.max(...blocks.map(b => b.boardPos.x + b.boundingRectBoardWidth)) + + FULL_VIEW_PADDING + const bottom + = Math.max(...blocks.map(b => b.boardPos.y + b.boundingRectBoardHeight)) + + FULL_VIEW_PADDING return { left, top, @@ -907,29 +955,30 @@ export class Graph { bottom, width: right - left, height: bottom - top, - }; + } } + fullView() { if (this.blocks.length === 0) { - this.resetViewport(); - return { width: NaN, height: NaN }; + this.resetViewport() + return { width: Number.NaN, height: Number.NaN } } - const { left, top, width, height } = this.fullViewRect; + const { left, top, width, height } = this.fullViewRect - const { width: graphWidth, height: graphHeight } = - this.el!.getBoundingClientRect(); + const { width: graphWidth, height: graphHeight } + = this.el!.getBoundingClientRect() - const scale = Math.min(graphWidth / width, graphHeight / height); + const scale = Math.min(graphWidth / width, graphHeight / height) - this.boardScale = scale; - this.boardOffsetX = left; - this.boardOffsetY = top; + this.boardScale = scale + this.boardOffsetX = left + this.boardOffsetY = top return { width: width * scale, height: height * scale, - }; + } } exportRecord(): GraphRecord { @@ -937,41 +986,42 @@ export class Graph { boardOffsetX: this.boardOffsetX, boardOffsetY: this.boardOffsetY, boardScale: this.boardScale, - blockZIndex: (this.blockZIndex.filter((b) => b !== null) as Block[]).map( - (b) => b.id, + blockZIndex: (this.blockZIndex.filter(b => b !== null) as Block[]).map( + b => b.id, ), - }; + } } + importRecord(record: GraphRecord, blocks: Record) { - this.boardOffsetX = record.boardOffsetX; - this.boardOffsetY = record.boardOffsetY; - this.boardScale = record.boardScale; - this.blockZIndex = record.blockZIndex.map((id) => blocks[id]); - this.updateBlockZIndex(); + this.boardOffsetX = record.boardOffsetX + this.boardOffsetY = record.boardOffsetY + this.boardScale = record.boardScale + this.blockZIndex = record.blockZIndex.map(id => blocks[id]) + this.updateBlockZIndex() } } function calcMoveSpeed(graphPos: number, sideLength: number) { - if (graphPos < 0) { - return -AUTO_MOVE_SPEED_MAX; - } - if (graphPos < AUTO_MOVE_START_PADDING) { - return AUTO_MOVE_SPEED_SCALE * (graphPos - AUTO_MOVE_START_PADDING); - } - if (graphPos > sideLength) { - return AUTO_MOVE_SPEED_MAX; - } + if (graphPos < 0) + return -AUTO_MOVE_SPEED_MAX + + if (graphPos < AUTO_MOVE_START_PADDING) + return AUTO_MOVE_SPEED_SCALE * (graphPos - AUTO_MOVE_START_PADDING) + + if (graphPos > sideLength) + return AUTO_MOVE_SPEED_MAX + if (graphPos > sideLength - AUTO_MOVE_START_PADDING) { return ( AUTO_MOVE_SPEED_SCALE * (graphPos - sideLength + AUTO_MOVE_START_PADDING) - ); + ) } - return 0; + return 0 } export interface GraphRecord { - boardOffsetX: number; - boardOffsetY: number; - boardScale: number; - blockZIndex: number[]; + boardOffsetX: number + boardOffsetY: number + boardScale: number + blockZIndex: number[] } diff --git a/packages/visual-flow/src/model/index.ts b/packages/visual-flow/src/model/index.ts index 66ea801..68dd6f6 100644 --- a/packages/visual-flow/src/model/index.ts +++ b/packages/visual-flow/src/model/index.ts @@ -1,5 +1,5 @@ -export * from "./base"; -export * from "./block"; -export * from "./graph"; -export * from "./line"; -export * from "./socket"; +export * from './base' +export * from './block' +export * from './graph' +export * from './line' +export * from './socket' diff --git a/packages/visual-flow/src/model/line.ts b/packages/visual-flow/src/model/line.ts index 964e4bd..1354b39 100644 --- a/packages/visual-flow/src/model/line.ts +++ b/packages/visual-flow/src/model/line.ts @@ -1,191 +1,204 @@ -import { SVGElementComponent, ref } from "refina"; -import { Direction, Point } from "../types"; -import { calcLineEndDirection } from "../utils"; -import { ModelBase } from "./base"; -import { Graph } from "./graph"; -import { Socket } from "./socket"; - -const NEVER_LEAVES_DISTANCE_SQUARE = 100; - -const pointWithDirectionSym = Symbol(); - -export type PointWithDirection = { - boardX: number; - boardY: number; - direction: Direction; - [pointWithDirectionSym]: true; -}; +import type { SVGElementComponent } from 'refina' +import { ref } from 'refina' +import type { Direction } from '../types' +import { Point } from '../types' +import { calcLineEndDirection } from '../utils' +import { ModelBase } from './base' +import type { Graph } from './graph' +import type { Socket } from './socket' + +const NEVER_LEAVES_DISTANCE_SQUARE = 100 + +const pointWithDirectionSym = Symbol('pointWithDirectionSym') + +export interface PointWithDirection { + boardX: number + boardY: number + direction: Direction + [pointWithDirectionSym]: true +} export interface LineColors { - default: string; - hovered: string; - dragging: string; + default: string + hovered: string + dragging: string } const defaultColors: Record = { L: { - default: "#CE9178", - hovered: "#AE7158", - dragging: "#8E5138", + default: '#CE9178', + hovered: '#AE7158', + dragging: '#8E5138', }, D: { - default: "#4FC1FF", - hovered: "#2EA0E5", - dragging: "#0E80CB", + default: '#4FC1FF', + hovered: '#2EA0E5', + dragging: '#0E80CB', }, E: { - default: "#DCDCAA", - hovered: "#BCBC8B", - dragging: "#9C9C6B", + default: '#DCDCAA', + hovered: '#BCBC8B', + dragging: '#9C9C6B', }, -}; +} export abstract class Line extends ModelBase { - abstract ctorName: string; + abstract ctorName: string - abstract clone(): Line; + abstract clone(): Line - graph: Graph; - type: string; + graph: Graph + type: string get colors(): LineColors { - return defaultColors[this.type]; + return defaultColors[this.type] } - hasArrow: boolean = true; + hasArrow: boolean = true - dragging: boolean = false; - hovered: boolean = false; - predicting: boolean = false; + dragging: boolean = false + hovered: boolean = false + predicting: boolean = false - neverLeaves: Socket | null = null; + neverLeaves: Socket | null = null - lineRef = ref(); + lineRef = ref() get lineEl() { - return this.lineRef.current?.node; + return this.lineRef.current?.node } - arrowRef = ref(); + arrowRef = ref() get arrowEl() { - return this.arrowRef.current?.node; + return this.arrowRef.current?.node } - a: Socket; - b: Socket | PointWithDirection; + a: Socket + b: Socket | PointWithDirection initialize(socketA: Socket, boardPosB: Point) { - this.a = socketA; - this.setBoardPosB(boardPosB); + this.a = socketA + this.setBoardPosB(boardPosB) } setBoardPosB(boardPosB: Point, direction?: Direction) { if ( - this.neverLeaves && - Point.distanceSquare(this.neverLeaves.boardPos, boardPosB) >= - NEVER_LEAVES_DISTANCE_SQUARE - ) { - this.neverLeaves = null; - } - const boardPosA = this.a.boardPos; + this.neverLeaves + && Point.distanceSquare(this.neverLeaves.boardPos, boardPosB) + >= NEVER_LEAVES_DISTANCE_SQUARE + ) + this.neverLeaves = null + + const boardPosA = this.a.boardPos this.b = { boardX: boardPosB.x, boardY: boardPosB.y, direction: - direction ?? - calcLineEndDirection( + direction + ?? calcLineEndDirection( this.a.direction, boardPosB.x - boardPosA.x, boardPosB.y - boardPosA.y, ), [pointWithDirectionSym]: true, - }; + } } get graphPosA() { - return this.a.graphPos; + return this.a.graphPos } + get graphPosB() { if (this.connected) { - return (this.b as Socket).graphPos; - } else { + return (this.b as Socket).graphPos + } + else { return this.graph.boardPos2GraphPos({ x: (this.b as PointWithDirection).boardX, y: (this.b as PointWithDirection).boardY, - }); + }) } } + get boardPosA() { - return this.a.boardPos; + return this.a.boardPos } + get boardPosB() { if (this.connected) { - return (this.b as Socket).boardPos; - } else { + return (this.b as Socket).boardPos + } + else { return { x: (this.b as PointWithDirection).boardX, y: (this.b as PointWithDirection).boardY, - }; + } } } get connected() { - //@ts-ignore - return this.b[pointWithDirectionSym] !== true; + // @ts-expect-error type guard + return this.b[pointWithDirectionSym] !== true } updatePosition() { - this.lineEl?.setAttribute("d", this.linePath); - this.arrowEl?.setAttribute("d", this.arrowPath); + this.lineEl?.setAttribute('d', this.linePath) + this.arrowEl?.setAttribute('d', this.arrowPath) } onHover() { - this.hovered = true; - if (this.lineEl) this.lineEl.style.stroke = this.colors.hovered; - if (this.arrowEl) this.arrowEl.style.fill = this.colors.hovered; + this.hovered = true + if (this.lineEl) + this.lineEl.style.stroke = this.colors.hovered + if (this.arrowEl) + this.arrowEl.style.fill = this.colors.hovered } onUnhover() { - this.hovered = false; - if (this.lineEl) this.lineEl.style.stroke = this.colors.default; - if (this.arrowEl) this.arrowEl.style.fill = this.colors.default; + this.hovered = false + if (this.lineEl) + this.lineEl.style.stroke = this.colors.default + if (this.arrowEl) + this.arrowEl.style.fill = this.colors.default } disconnect(s: Socket) { if (s === this.a) { if (!this.connected) { - this.graph.removeLine(this); - return; + this.graph.removeLine(this) + return } - this.a = this.b as Socket; - this.b = undefined as any; - } else if (s === this.b) { - this.b = undefined as any; - } else { - throw new Error("Socket not connected"); + this.a = this.b as Socket + this.b = undefined as any + } + else if (s === this.b) { + this.b = undefined as any + } + else { + throw new Error('Socket not connected') } } - abstract get linePath(): string; + abstract get linePath(): string - abstract get arrowPath(): string; + abstract get arrowPath(): string abstract drawThumbnail( ctx: CanvasRenderingContext2D, left: number, top: number, scale: number, - ): void; + ): void createPredictor(): Line { - const predictor = this.clone(); - predictor.graph = this.graph; - predictor.a = this.a; - predictor.b = this.b; - predictor.predicting = true; - return predictor; + const predictor = this.clone() + predictor.graph = this.graph + predictor.a = this.a + predictor.b = this.b + predictor.predicting = true + return predictor } - protected abstract exportData(): any; + protected abstract exportData(): any exportRecord(): LineRecord { return { ctor: this.ctorName, @@ -195,30 +208,31 @@ export abstract class Line extends ModelBase { socketBId: (this.b as Socket).id, hasArrow: this.hasArrow, data: this.exportData(), - }; + } } + protected abstract importData( data: any, sockets: Record, - ): void; + ): void importRecord(record: LineRecord, sockets: Record) { - this.id = record.id; - this.type = record.type; - this.a = sockets[record.socketAId]; - this.a.connectTo(this); - this.b = sockets[record.socketBId]; - this.b.connectTo(this); - this.hasArrow = record.hasArrow; - this.importData(record.data, sockets); + this.id = record.id + this.type = record.type + this.a = sockets[record.socketAId] + this.a.connectTo(this) + this.b = sockets[record.socketBId] + this.b.connectTo(this) + this.hasArrow = record.hasArrow + this.importData(record.data, sockets) } } export interface LineRecord { - ctor: string; - id: number; - type: string; - socketAId: number; - socketBId: number; - hasArrow: boolean; - data: any; + ctor: string + id: number + type: string + socketAId: number + socketBId: number + hasArrow: boolean + data: any } diff --git a/packages/visual-flow/src/model/socket.ts b/packages/visual-flow/src/model/socket.ts index c0de8fa..158ce76 100644 --- a/packages/visual-flow/src/model/socket.ts +++ b/packages/visual-flow/src/model/socket.ts @@ -1,91 +1,98 @@ -import { SVGElementComponent, ref } from "refina"; -import { Direction, Point } from "../types"; -import { ModelBase } from "./base"; -import { Block } from "./block"; -import { Graph } from "./graph"; -import { Line } from "./line"; +import type { SVGElementComponent } from 'refina' +import { ref } from 'refina' +import { Direction, Point } from '../types' +import { ModelBase } from './base' +import type { Block } from './block' +import type { Graph } from './graph' +import type { Line } from './line' export abstract class Socket extends ModelBase { - abstract ctorName: string; + abstract ctorName: string get graph(): Graph { - return this.block.graph; + return this.block.graph } - type: string; + + type: string /** * label to be displayed */ - label: string; - hideLabel = false; - disabled = false; + label: string + hideLabel = false + disabled = false - ref = ref>(); + ref = ref>() get el() { - return this.ref.current?.node; + return this.ref.current?.node } - block: Block; - direction: Direction; + block: Block + direction: Direction /** * position relative to the block. * unit: board coord */ - blockX: number; - blockY: number; + blockX: number + blockY: number get blockDisplayX() { - return this.blockX * this.graph.boardScale; + return this.blockX * this.graph.boardScale } + get blockDisplayY() { - return this.blockY * this.graph.boardScale; + return this.blockY * this.graph.boardScale } + get blockDisplayRadius() { - return Math.min(this.graph.boardScale * 3, 1) * 5; + return Math.min(this.graph.boardScale * 3, 1) * 5 } - abstract get allConnectedLines(): Line[]; + abstract get allConnectedLines(): Line[] - abstract connectTo(line: Line): void; - abstract disconnectTo(line: Line): void; + abstract connectTo(line: Line): void + abstract disconnectTo(line: Line): void get blockPos() { - return { x: this.blockX, y: this.blockY }; + return { x: this.blockX, y: this.blockY } } + get boardPos() { - return Point.add(this.block.boardPos, this.blockPos); + return Point.add(this.block.boardPos, this.blockPos) } + get graphPos() { - return this.graph.boardPos2GraphPos(this.boardPos); + return this.graph.boardPos2GraphPos(this.boardPos) } - abstract canDragFrom(): boolean; - abstract canDragRemove(): boolean; - abstract checkConnectable(line: Line): boolean; + abstract canDragFrom(): boolean + abstract canDragRemove(): boolean + abstract checkConnectable(line: Line): boolean onHover() { - this.el?.classList.add("hovered"); + this.el?.classList.add('hovered') } + onUnhover() { - this.el?.classList.remove("hovered"); + this.el?.classList.remove('hovered') } - abstract onMouseDown(): void; + abstract onMouseDown(): void protected connectToNewLine(line: Line) { - line.type = this.type; - line.initialize(this, this.graph.mouseBoardPos); + line.type = this.type + line.initialize(this, this.graph.mouseBoardPos) - this.graph.addLine(line); + this.graph.addLine(line) - this.connectTo(line); - return line; + this.connectTo(line) + return line } - abstract getHoveredLine(): Line | null; + abstract getHoveredLine(): Line | null - protected abstract exportData(): any; + protected abstract exportData(): any exportRecord(): SocketRecord { return { ctor: this.ctorName, @@ -98,45 +105,46 @@ export abstract class Socket extends ModelBase { blockId: this.block.id, path: this.path, data: this.exportData(), - }; + } } - protected abstract importData(data: any): void; + + protected abstract importData(data: any): void importRecord(record: SocketRecord) { - this.id = record.id; - this.type = record.type; - this.direction = record.direction; - this.label = record.label; - this.hideLabel = record.hideLabel; - this.disabled = record.disabled; - this.path = record.path; - this.importData(record.data); + this.id = record.id + this.type = record.type + this.direction = record.direction + this.label = record.label + this.hideLabel = record.hideLabel + this.disabled = record.disabled + this.path = record.path + this.importData(record.data) } - path: string; + path: string get labelBoardPos() { switch (this.direction) { case Direction.LEFT: - return { x: -4, y: -5, "text-anchor": "end" }; + return { 'x': -4, 'y': -5, 'text-anchor': 'end' } case Direction.TOP: - return { x: 5, y: 0 }; + return { x: 5, y: 0 } case Direction.RIGHT: - return { x: 5, y: -5 }; + return { x: 5, y: -5 } case Direction.BOTTOM: - return { x: 5, y: 15 }; + return { x: 5, y: 15 } } } } export interface SocketRecord { - ctor: string; - id: number; - type: string; - direction: Direction; - label: string; - hideLabel: boolean; - disabled: boolean; - blockId: number; - path: string; - data: any; + ctor: string + id: number + type: string + direction: Direction + label: string + hideLabel: boolean + disabled: boolean + blockId: number + path: string + data: any } diff --git a/packages/visual-flow/src/recorder/ctors.ts b/packages/visual-flow/src/recorder/ctors.ts index ff90784..9fe7cd1 100644 --- a/packages/visual-flow/src/recorder/ctors.ts +++ b/packages/visual-flow/src/recorder/ctors.ts @@ -1,6 +1,6 @@ -import type { CtorMap } from "./types"; -import type { Block, Line, Socket } from "../model"; +import type { Block, Line, Socket } from '../model' +import type { CtorMap } from './types' -export const blockCtors: CtorMap = {}; -export const socketCtors: CtorMap = {}; -export const lineCtors: CtorMap = {}; +export const blockCtors: CtorMap = {} +export const socketCtors: CtorMap = {} +export const lineCtors: CtorMap = {} diff --git a/packages/visual-flow/src/recorder/exporter.ts b/packages/visual-flow/src/recorder/exporter.ts index f058395..9a415ef 100644 --- a/packages/visual-flow/src/recorder/exporter.ts +++ b/packages/visual-flow/src/recorder/exporter.ts @@ -1,20 +1,20 @@ -import { Graph } from "../model"; -import { VfRecord } from "./types"; +import type { Graph } from '../model' +import type { VfRecord } from './types' export function exportVf(graph: Graph) { const record: VfRecord = { graph: graph.exportRecord(), blocks: graph.blocks - .filter((block) => block.attached) - .map((block) => block.exportRecord()), + .filter(block => block.attached) + .map(block => block.exportRecord()), sockets: graph.blocks - .filter((block) => block.attached) - .flatMap((block) => - block.allSockets.map((socket) => socket.exportRecord()), + .filter(block => block.attached) + .flatMap(block => + block.allSockets.map(socket => socket.exportRecord()), ), lines: graph.lines - .filter((line) => line.connected) - .map((line) => line.exportRecord()), - }; - return record; + .filter(line => line.connected) + .map(line => line.exportRecord()), + } + return record } diff --git a/packages/visual-flow/src/recorder/importer.ts b/packages/visual-flow/src/recorder/importer.ts index 85cba57..029107c 100644 --- a/packages/visual-flow/src/recorder/importer.ts +++ b/packages/visual-flow/src/recorder/importer.ts @@ -1,49 +1,50 @@ -import { Graph } from "../model"; -import { setCurrentId } from "../utils"; -import { blockCtors, lineCtors, socketCtors } from "./ctors"; -import { VfRecord } from "./types"; +import { Graph } from '../model' +import { setCurrentId } from '../utils' +import { blockCtors, lineCtors, socketCtors } from './ctors' +import type { VfRecord } from './types' export function importVf(record: VfRecord, graphRaw?: Graph) { if (graphRaw) { - graphRaw.reset(); - } else { - graphRaw = new Graph(); - graphRaw.recordStack = [record]; - graphRaw.recordIndex = 0; + graphRaw.reset() } - const graph = graphRaw; + else { + graphRaw = new Graph() + graphRaw.recordStack = [record] + graphRaw.recordIndex = 0 + } + const graph = graphRaw const sockets = Object.fromEntries( - record.sockets.map((socketRecord) => { - const socket = new socketCtors[socketRecord.ctor](); - socket.importRecord(socketRecord); - setCurrentId(socketRecord.id); - return [socketRecord.id, socket]; + record.sockets.map(socketRecord => { + const socket = new socketCtors[socketRecord.ctor]() + socket.importRecord(socketRecord) + setCurrentId(socketRecord.id) + return [socketRecord.id, socket] }), - ); + ) const blocks = Object.fromEntries( - record.blocks.map((blockRecord) => { - const block = new blockCtors[blockRecord.ctor](); - return [blockRecord.id, block]; + record.blocks.map(blockRecord => { + const block = new blockCtors[blockRecord.ctor]() + return [blockRecord.id, block] }), - ); + ) - record.blocks.forEach((blockRecord) => { - const block = blocks[blockRecord.id]; - block.importRecord(blockRecord, blocks, sockets); - graph.addBlock(block); - setCurrentId(blockRecord.id); - }); + record.blocks.forEach(blockRecord => { + const block = blocks[blockRecord.id] + block.importRecord(blockRecord, blocks, sockets) + graph.addBlock(block) + setCurrentId(blockRecord.id) + }) - record.lines.forEach((lineRecord) => { - const line = new lineCtors[lineRecord.ctor](); - line.importRecord(lineRecord, sockets); - graph.addLine(line); - setCurrentId(lineRecord.id); - }); + record.lines.forEach(lineRecord => { + const line = new lineCtors[lineRecord.ctor]() + line.importRecord(lineRecord, sockets) + graph.addLine(line) + setCurrentId(lineRecord.id) + }) - graph.importRecord(record.graph, blocks); + graph.importRecord(record.graph, blocks) - return graph; + return graph } diff --git a/packages/visual-flow/src/recorder/index.ts b/packages/visual-flow/src/recorder/index.ts index 9b0873d..5b2ca12 100644 --- a/packages/visual-flow/src/recorder/index.ts +++ b/packages/visual-flow/src/recorder/index.ts @@ -1,4 +1,4 @@ -export * from "./ctors"; -export * from "./exporter"; -export * from "./importer"; -export * from "./types"; +export * from './ctors' +export * from './exporter' +export * from './importer' +export * from './types' diff --git a/packages/visual-flow/src/recorder/types.ts b/packages/visual-flow/src/recorder/types.ts index 91ebbfc..c5d7d80 100644 --- a/packages/visual-flow/src/recorder/types.ts +++ b/packages/visual-flow/src/recorder/types.ts @@ -3,13 +3,13 @@ import type { GraphRecord, LineRecord, SocketRecord, -} from "../model"; +} from '../model' -export type CtorMap = Record T>; +export type CtorMap = Record T> export interface VfRecord { - graph: GraphRecord; - blocks: BlockRecord[]; - sockets: SocketRecord[]; - lines: LineRecord[]; + graph: GraphRecord + blocks: BlockRecord[] + sockets: SocketRecord[] + lines: LineRecord[] } diff --git a/packages/visual-flow/src/types/direction.ts b/packages/visual-flow/src/types/direction.ts index 6a210ee..5031340 100644 --- a/packages/visual-flow/src/types/direction.ts +++ b/packages/visual-flow/src/types/direction.ts @@ -1,4 +1,5 @@ -import { Point } from "./point"; +/* eslint-disable ts/prefer-literal-enum-member */ +import { Point } from './point' export enum Direction { LEFT, @@ -12,91 +13,93 @@ export enum Direction { export function toPoint(dire: Direction, dist: number) { switch (dire) { case Direction.LEFT: - return new Point(-dist, 0); + return new Point(-dist, 0) case Direction.RIGHT: - return new Point(dist, 0); + return new Point(dist, 0) case Direction.UP: - return new Point(0, -dist); + return new Point(0, -dist) case Direction.DOWN: - return new Point(0, dist); + return new Point(0, dist) } } export function opposite(dire: Direction): Direction { switch (dire) { case Direction.LEFT: - return Direction.RIGHT; + return Direction.RIGHT case Direction.RIGHT: - return Direction.LEFT; + return Direction.LEFT case Direction.UP: - return Direction.DOWN; + return Direction.DOWN case Direction.DOWN: - return Direction.UP; + return Direction.UP } } export function updatePoint(dire: Direction, p: Point, val: number): Point { if (dire === Direction.LEFT || dire === Direction.RIGHT) - return new Point(val, p.y); + return new Point(val, p.y) if (dire === Direction.UP || dire === Direction.DOWN) - return new Point(p.x, val); - return 1 as never; + return new Point(p.x, val) + return 1 as never } export function rotate(dire: Direction): Direction { switch (dire) { case Direction.LEFT: - return Direction.UP; + return Direction.UP case Direction.RIGHT: - return Direction.DOWN; + return Direction.DOWN case Direction.UP: - return Direction.RIGHT; + return Direction.RIGHT case Direction.DOWN: - return Direction.LEFT; + return Direction.LEFT } } export function getPoint(dire: Direction, p: Point): number { - if (dire === Direction.LEFT || dire === Direction.RIGHT) return p.x; - if (dire === Direction.UP || dire === Direction.DOWN) return p.y; - return 1 as never; + if (dire === Direction.LEFT || dire === Direction.RIGHT) + return p.x + if (dire === Direction.UP || dire === Direction.DOWN) + return p.y + return 1 as never } export function further(dire: Direction, p1: Point, p2: Point): boolean { switch (dire) { case Direction.LEFT: - return p1.x < p2.x; + return p1.x < p2.x case Direction.RIGHT: - return p1.x > p2.x; + return p1.x > p2.x case Direction.UP: - return p1.y < p2.y; + return p1.y < p2.y case Direction.DOWN: - return p1.y > p2.y; + return p1.y > p2.y } } export function futherDis(dire: Direction, p1: Point, p2: Point): number { switch (dire) { case Direction.LEFT: - return Math.min(p1.x, p2.x); + return Math.min(p1.x, p2.x) case Direction.RIGHT: - return Math.max(p1.x, p2.x); + return Math.max(p1.x, p2.x) case Direction.UP: - return Math.min(p1.y, p2.y); + return Math.min(p1.y, p2.y) case Direction.DOWN: - return Math.max(p1.y, p2.y); + return Math.max(p1.y, p2.y) } } export const directionNameMap = { - [Direction.LEFT]: "LEFT", - [Direction.RIGHT]: "RIGHT", - [Direction.TOP]: "TOP", - [Direction.BOTTOM]: "BOTTOM", -}; + [Direction.LEFT]: 'LEFT', + [Direction.RIGHT]: 'RIGHT', + [Direction.TOP]: 'TOP', + [Direction.BOTTOM]: 'BOTTOM', +} export const directionMap = { LEFT: Direction.LEFT, RIGHT: Direction.RIGHT, TOP: Direction.TOP, BOTTOM: Direction.BOTTOM, -} as Record; +} as Record diff --git a/packages/visual-flow/src/types/index.ts b/packages/visual-flow/src/types/index.ts index eace2ad..bd7a637 100644 --- a/packages/visual-flow/src/types/index.ts +++ b/packages/visual-flow/src/types/index.ts @@ -1,2 +1,2 @@ -export * from "./direction"; -export * from "./point"; +export * from './direction' +export * from './point' diff --git a/packages/visual-flow/src/types/point.ts b/packages/visual-flow/src/types/point.ts index 84106f5..10ada9d 100644 --- a/packages/visual-flow/src/types/point.ts +++ b/packages/visual-flow/src/types/point.ts @@ -1,4 +1,4 @@ -import { Direction } from "./direction"; +import { Direction } from './direction' export class Point { constructor( @@ -7,44 +7,44 @@ export class Point { ) {} static distanceSquare(a: Point, b: Point): number { - return (a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y); + return (a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y) } static eq(lhs: Point, rhs: Point): boolean { - return lhs.x == rhs.x && lhs.y == rhs.y; + return lhs.x === rhs.x && lhs.y === rhs.y } static add(a: Point, b: Point): Point { - return new Point(a.x + b.x, a.y + b.y); + return new Point(a.x + b.x, a.y + b.y) } static minus(a: Point, b: Point): Point { - return new Point(a.x - b.x, a.y - b.y); + return new Point(a.x - b.x, a.y - b.y) } static moveFarther(p: Point, direction: Direction, distance: number): Point { switch (direction) { case Direction.UP: - return new Point(p.x, p.y - distance); + return new Point(p.x, p.y - distance) case Direction.RIGHT: - return new Point(p.x + distance, p.y); + return new Point(p.x + distance, p.y) case Direction.DOWN: - return new Point(p.x, p.y + distance); + return new Point(p.x, p.y + distance) case Direction.LEFT: - return new Point(p.x - distance, p.y); + return new Point(p.x - distance, p.y) } } static getComponentByDirection(p: Point, direction: Direction): number { switch (direction) { case Direction.UP: - return -p.y; + return -p.y case Direction.DOWN: - return p.y; + return p.y case Direction.RIGHT: - return p.x; + return p.x case Direction.LEFT: - return -p.x; + return -p.x } } } diff --git a/packages/visual-flow/src/utils/allocateId.ts b/packages/visual-flow/src/utils/allocateId.ts index 99266ff..23e8595 100644 --- a/packages/visual-flow/src/utils/allocateId.ts +++ b/packages/visual-flow/src/utils/allocateId.ts @@ -1,9 +1,9 @@ -let currentId = 0; +let currentId = 0 export function setCurrentId(id: number) { - currentId = Math.max(currentId, id); + currentId = Math.max(currentId, id) } export function allocateId() { - return currentId++; + return currentId++ } diff --git a/packages/visual-flow/src/utils/calcLineEndDirection.ts b/packages/visual-flow/src/utils/calcLineEndDirection.ts index 7cf309f..2a1887c 100644 --- a/packages/visual-flow/src/utils/calcLineEndDirection.ts +++ b/packages/visual-flow/src/utils/calcLineEndDirection.ts @@ -1,6 +1,6 @@ -import { Direction } from "../types"; +import { Direction } from '../types' -const SAME_DIRECTION_MAX_SLOPE = 1; +const SAME_DIRECTION_MAX_SLOPE = 1 export function calcLineEndDirection( startDirection: Direction, @@ -10,38 +10,46 @@ export function calcLineEndDirection( switch (startDirection) { case Direction.LEFT: if (dx < 0) { - const maxDy = -dx * SAME_DIRECTION_MAX_SLOPE; - if (dy < -maxDy) return Direction.BOTTOM; - if (dy > maxDy) return Direction.TOP; - return Direction.RIGHT; + const maxDy = -dx * SAME_DIRECTION_MAX_SLOPE + if (dy < -maxDy) + return Direction.BOTTOM + if (dy > maxDy) + return Direction.TOP + return Direction.RIGHT } - return Direction.LEFT; + return Direction.LEFT case Direction.RIGHT: if (dx > 0) { - const maxDy = dx * SAME_DIRECTION_MAX_SLOPE; - if (dy < -maxDy) return Direction.BOTTOM; - if (dy > maxDy) return Direction.TOP; - return Direction.LEFT; + const maxDy = dx * SAME_DIRECTION_MAX_SLOPE + if (dy < -maxDy) + return Direction.BOTTOM + if (dy > maxDy) + return Direction.TOP + return Direction.LEFT } - return Direction.RIGHT; + return Direction.RIGHT case Direction.TOP: if (dy < 0) { - const maxDx = -dy * SAME_DIRECTION_MAX_SLOPE; - if (dx < -maxDx) return Direction.RIGHT; - if (dx > maxDx) return Direction.LEFT; - return Direction.BOTTOM; + const maxDx = -dy * SAME_DIRECTION_MAX_SLOPE + if (dx < -maxDx) + return Direction.RIGHT + if (dx > maxDx) + return Direction.LEFT + return Direction.BOTTOM } - return Direction.TOP; + return Direction.TOP case Direction.BOTTOM: if (dy > 0) { - const maxDx = dy * SAME_DIRECTION_MAX_SLOPE; - if (dx < -maxDx) return Direction.RIGHT; - if (dx > maxDx) return Direction.LEFT; - return Direction.TOP; + const maxDx = dy * SAME_DIRECTION_MAX_SLOPE + if (dx < -maxDx) + return Direction.RIGHT + if (dx > maxDx) + return Direction.LEFT + return Direction.TOP } - return Direction.BOTTOM; + return Direction.BOTTOM } } diff --git a/packages/visual-flow/src/utils/index.ts b/packages/visual-flow/src/utils/index.ts index 1ef379f..268239c 100644 --- a/packages/visual-flow/src/utils/index.ts +++ b/packages/visual-flow/src/utils/index.ts @@ -1,3 +1,3 @@ -export * from "./allocateId"; -export * from "./calcLineEndDirection"; -export * from "./spreadItems"; +export * from './allocateId' +export * from './calcLineEndDirection' +export * from './spreadItems' diff --git a/packages/visual-flow/src/utils/spreadItems.ts b/packages/visual-flow/src/utils/spreadItems.ts index 0265ae1..8627812 100644 --- a/packages/visual-flow/src/utils/spreadItems.ts +++ b/packages/visual-flow/src/utils/spreadItems.ts @@ -7,12 +7,12 @@ export function spreadItems( itemNum: number, paddingScale: number, ) { - const positions: number[] = []; - const offset = ((1 - 2 * paddingScale) * length) / (itemNum + 1); - let x = paddingScale * length; + const positions: number[] = [] + const offset = ((1 - 2 * paddingScale) * length) / (itemNum + 1) + let x = paddingScale * length for (let i = 0; i < itemNum; i++) { - x += offset; - positions.push(x); + x += offset + positions.push(x) } - return positions; + return positions } diff --git a/packages/visual-flow/src/view/block.r.ts b/packages/visual-flow/src/view/block.r.ts index 227f68d..8443427 100644 --- a/packages/visual-flow/src/view/block.r.ts +++ b/packages/visual-flow/src/view/block.r.ts @@ -1,66 +1,68 @@ -import { Component, _ } from "refina"; -import { Block } from "../model"; -import useStyles, { PADDING_FOR_SOCKETS } from "./block.styles"; -import { VfSocket } from "./socket.r"; +import { Component, _ } from 'refina' +import type { Block } from '../model' +import useStyles, { PADDING_FOR_SOCKETS } from './block.styles' +import { VfSocket } from './socket.r' export class VfBlock extends Component { $main(model: Block) { - const { x, y } = model.attached ? model.graphPos : model.pagePos; - const padding = PADDING_FOR_SOCKETS * model.graph.boardScale; + const { x, y } = model.attached ? model.graphPos : model.pagePos + const padding = PADDING_FOR_SOCKETS * model.graph.boardScale - const styles = useStyles(model.selected, model.attached, model.predicting); + const styles = useStyles(model.selected, model.attached, model.predicting) - styles.root(); + styles.root() _.$css`left:${x}px;top:${y}px;z-index:${ model.attached ? model.zIndex : 10000 - }`; - _.$ref(model.ref) && - _._div({}, _ => { - styles.svg(); - _.$css`left:${-padding}px; top:${-padding}px`; - _._svgSvg( - { - width: - model.boundingRectBoardWidth * model.graph.boardScale + - 2 * padding, - height: - model.boundingRectBoardHeight * model.graph.boardScale + - 2 * padding, - }, - _ => { - _._svgG( - { - transform: `translate(${padding}, ${padding})`, - }, - _ => { - styles.bg(); - _.$ref(model.bgRef) && - _._svgPath({ - d: model.backgroudPath, - }); - - _.for(model.allSockets, "id", socket => { - _(VfSocket)(socket); - }); - }, - ); - }, - ); - - _._div( - { - onmousedown: ev => { - if (ev.defaultPrevented) ev.stopPropagation(); + }` + _.$ref(model.ref) + && _._div({}, _ => { + styles.svg() + _.$css`left:${-padding}px; top:${-padding}px` + _._svgSvg( + { + width: + model.boundingRectBoardWidth * model.graph.boardScale + + 2 * padding, + height: + model.boundingRectBoardHeight * model.graph.boardScale + + 2 * padding, + }, + _ => { + _._svgG( + { + transform: `translate(${padding}, ${padding})`, }, - // onmousemove: (ev) => { - // if (!model.dragging) ev.stopPropagation(); - // }, - onmouseup: ev => { - if (!model.selected) ev.stopPropagation(); + _ => { + styles.bg() + _.$ref(model.bgRef) + && _._svgPath({ + d: model.backgroudPath, + }) + + _.for(model.allSockets, 'id', socket => { + _(VfSocket)(socket) + }) }, + ) + }, + ) + + _._div( + { + onmousedown: ev => { + if (ev.defaultPrevented) + ev.stopPropagation() + }, + // onmousemove: (ev) => { + // if (!model.dragging) ev.stopPropagation(); + // }, + onmouseup: ev => { + if (!model.selected) + ev.stopPropagation() }, - model.contentMain, - ); - }); + }, + model.contentMain, + ) + }) } } diff --git a/packages/visual-flow/src/view/block.styles.ts b/packages/visual-flow/src/view/block.styles.ts index 7b55243..7bcb97c 100644 --- a/packages/visual-flow/src/view/block.styles.ts +++ b/packages/visual-flow/src/view/block.styles.ts @@ -1,53 +1,52 @@ -import { tokens, typographyStyles } from "@fluentui/tokens"; +import { tokens, typographyStyles } from '@fluentui/tokens' import { defineStyles, makeResetStyles, makeStyles, - mergeClasses, shorthands, -} from "@refina/griffel"; +} from '@refina/griffel' -export const PADDING_FOR_SOCKETS = 100; +export const PADDING_FOR_SOCKETS = 100 const rootClassName = makeResetStyles({ - position: "absolute", - width: 0, - height: 0, - filter: `drop-shadow(0 4px 8px rgba(0,0,0,0.14))`, - cursor: "default", - ...shorthands.overflow("visible"), + 'position': 'absolute', + 'width': 0, + 'height': 0, + 'filter': `drop-shadow(0 4px 8px rgba(0,0,0,0.14))`, + 'cursor': 'default', + ...shorthands.overflow('visible'), - "&.animated": { - transitionProperty: "all", + '&.animated': { + transitionProperty: 'all', transitionDuration: tokens.durationNormal, transitionTimingFunction: tokens.curveEasyEase, }, -}); +}) const rootStyles = makeStyles({ selected: { filter: `drop-shadow(0 14px 28px rgba(0,0,0,0.14))`, }, unattached: { - position: "fixed", + position: 'fixed', opacity: 0.4, }, predicting: { opacity: 0.4, }, -}); +}) const svgClassName = makeResetStyles({ - position: "absolute", - pointerEvents: "none", - ...shorthands.overflow("visible"), -}); + position: 'absolute', + pointerEvents: 'none', + ...shorthands.overflow('visible'), +}) const bgClassName = makeResetStyles({ fill: tokens.colorNeutralBackground5Hover, stroke: tokens.colorBrandStroke2, strokeWidth: tokens.strokeWidthThick, -}); +}) const bgStyles = makeStyles({ selected: { @@ -56,16 +55,16 @@ const bgStyles = makeStyles({ strokeWidth: tokens.strokeWidthThicker, }, notSelected: { - "&.hovered": { + '&.hovered': { fill: tokens.colorNeutralBackground5, stroke: tokens.colorBrandStroke2Hover, }, }, -}); +}) const textStyles = makeResetStyles({ ...typographyStyles.caption1, -}); +}) export default (selected: boolean, attached: boolean, predicting: boolean) => defineStyles({ @@ -78,4 +77,4 @@ export default (selected: boolean, attached: boolean, predicting: boolean) => svg: [svgClassName], bg: [bgClassName, selected ? bgStyles.selected : bgStyles.notSelected], text: [textStyles], - }); + }) diff --git a/packages/visual-flow/src/view/creator.r.ts b/packages/visual-flow/src/view/creator.r.ts index 7d5a7ff..cb939d5 100644 --- a/packages/visual-flow/src/view/creator.r.ts +++ b/packages/visual-flow/src/view/creator.r.ts @@ -1,8 +1,9 @@ -import { Content, TriggerComponent, _, Model } from "refina"; -import { Block, Graph } from "../model"; -import useStyles from "./creator.styles"; +import type { Content, Model } from 'refina' +import { TriggerComponent, _ } from 'refina' +import type { Block, Graph } from '../model' +import useStyles from './creator.styles' -const DRAGGING_START_PADDING = 20; +const DRAGGING_START_PADDING = 20 export class VfCreator extends TriggerComponent { $main( @@ -11,34 +12,35 @@ export class VfCreator extends TriggerComponent { factory: () => Block, disabled?: Model, ): this is { - $ev: void; + $ev: void } { - const styles = useStyles(); + const styles = useStyles() - styles.root(); + styles.root() _._div( { onmousedown: ev => { - if (disabled) return; - ev.preventDefault(); - const block = factory(); + if (disabled) + return + ev.preventDefault() + const block = factory() - const padding = graph.boardScale * DRAGGING_START_PADDING; + const padding = graph.boardScale * DRAGGING_START_PADDING const { x: boardX, y: boardY } = graph.pagePos2BoardPos({ x: ev.pageX - padding, y: ev.pageY - padding, - }); - block.boardX = boardX; - block.boardY = boardY; + }) + block.boardX = boardX + block.boardY = boardY - graph.addBlock(block); + graph.addBlock(block) - this.$fire(); - this.$update(); + this.$fire() + this.$update() }, }, inner, - ); - return this.$fired; + ) + return this.$fired } } diff --git a/packages/visual-flow/src/view/creator.styles.ts b/packages/visual-flow/src/view/creator.styles.ts index 300af9a..b08f7d7 100644 --- a/packages/visual-flow/src/view/creator.styles.ts +++ b/packages/visual-flow/src/view/creator.styles.ts @@ -1,11 +1,11 @@ -import { defineStyles, makeResetStyles } from "@refina/griffel"; +import { defineStyles, makeResetStyles } from '@refina/griffel' const rootClassName = makeResetStyles({ - width: "max-content", - height: "max-content", -}); + width: 'max-content', + height: 'max-content', +}) export default () => defineStyles({ root: [rootClassName], - }); + }) diff --git a/packages/visual-flow/src/view/graph.r.ts b/packages/visual-flow/src/view/graph.r.ts index b206b78..515def0 100644 --- a/packages/visual-flow/src/view/graph.r.ts +++ b/packages/visual-flow/src/view/graph.r.ts @@ -1,123 +1,125 @@ -import { Component, _ } from "refina"; -import { Graph } from "../model"; -import { VfBlock } from "./block.r"; -import useStyles from "./graph.styles"; -import { VfLine } from "./line.r"; +import { Component, _ } from 'refina' +import type { Graph } from '../model' +import { VfBlock } from './block.r' +import useStyles from './graph.styles' +import { VfLine } from './line.r' export class VfGraph extends Component { $main(model: Graph) { - model.app = _.$app; + model.app = _.$app - const styles = useStyles(); + const styles = useStyles() if (_.$updateContext) { - const windowElement = _.$window as any; + const windowElement = _.$window as any windowElement.addEventListener( - "resize", + 'resize', () => { - model.onResize(); + model.onResize() // not update here, because it will cause performance issue }, { passive: true, }, - ); + ) windowElement.addEventListener( - "mousemove", + 'mousemove', (ev: MouseEvent) => { - model.setMousePos(ev); + model.setMousePos(ev) if (model.onMouseMove((ev.buttons & 1) !== 0, ev.shiftKey)) { - window.getSelection()?.removeAllRanges(); - this.$update(); + window.getSelection()?.removeAllRanges() + this.$update() } }, { passive: true, }, - ); - windowElement.addEventListener("mousedown", (ev: MouseEvent) => { - model.setMousePos(ev); + ) + windowElement.addEventListener('mousedown', (ev: MouseEvent) => { + model.setMousePos(ev) if (model.onMouseDown(ev.shiftKey)) { - window.getSelection()?.removeAllRanges(); - if (document.activeElement instanceof HTMLElement) { - document.activeElement?.blur(); - } - ev.preventDefault(); - this.$update(); - return false; + window.getSelection()?.removeAllRanges() + if (document.activeElement instanceof HTMLElement) + document.activeElement?.blur() + + ev.preventDefault() + this.$update() + return false } - return true; - }); - windowElement.addEventListener("mouseup", (ev: MouseEvent) => { - model.setMousePos(ev); + return true + }) + windowElement.addEventListener('mouseup', (ev: MouseEvent) => { + model.setMousePos(ev) if (model.onMouseUp(ev.shiftKey)) { - ev.preventDefault(); - this.$update(); - return false; + ev.preventDefault() + this.$update() + return false } - return true; - }); + return true + }) _.$root.addEventListener( - "wheel", + 'wheel', ev => { - model.setMousePos(ev); - if (!model.isMouseInsideGraph) { - return; - } + model.setMousePos(ev) + if (!model.isMouseInsideGraph) + return + if (ev.ctrlKey) { if (model.onScaling(-ev.deltaY / 1500)) { - ev.preventDefault(); - this.$update(); + ev.preventDefault() + this.$update() } - } else if (ev.shiftKey) { + } + else if (ev.shiftKey) { if (model.onHorizontalScroll(ev.deltaY / 2)) { - ev.preventDefault(); - this.$update(); + ev.preventDefault() + this.$update() } - } else { + } + else { if (model.onVerticalScroll(ev.deltaY / 2)) { - ev.preventDefault(); - this.$update(); + ev.preventDefault() + this.$update() } } - return true; + return true }, { passive: false, }, - ); + ) - model.blocks.forEach(block => block.updateSockets()); + model.blocks.forEach(block => block.updateSockets()) } - styles.root(); - _.$ref(model.ref) && - _._div({}, _ => { - const { bg, fg } = model.displayLines; + styles.root() + _.$ref(model.ref) + && _._div({}, _ => { + const { bg, fg } = model.displayLines - styles.bgSvg(); - _._svgSvg({}, _ => { - _.for(bg, "id", line => { - _(VfLine)(line); - }); - }); + styles.bgSvg() + _._svgSvg({}, _ => { + _.for(bg, 'id', line => { + _(VfLine)(line) + }) + }) - styles.fgSvg(); - _._svgSvg({}, _ => { - _.for(fg, "id", line => { - _(VfLine)(line); - }); - }); - }); + styles.fgSvg() + _._svgSvg({}, _ => { + _.for(fg, 'id', line => { + _(VfLine)(line) + }) + }) + }) - _.for(model.blocks, "id", block => { - _(VfBlock)(block); - }); + _.for(model.blocks, 'id', block => { + _(VfBlock)(block) + }) - styles.canvas(); - _.$ref(model.canvasRef) && - _._canvas({ - id: "vf-thumbnail", - }); + styles.canvas() + _.$ref(model.canvasRef) + && _._canvas({ + id: 'vf-thumbnail', + }) } } diff --git a/packages/visual-flow/src/view/graph.styles.ts b/packages/visual-flow/src/view/graph.styles.ts index 1e5c283..de27e53 100644 --- a/packages/visual-flow/src/view/graph.styles.ts +++ b/packages/visual-flow/src/view/graph.styles.ts @@ -1,32 +1,32 @@ -import { defineStyles, makeResetStyles, makeStyles } from "@refina/griffel"; +import { defineStyles, makeResetStyles, makeStyles } from '@refina/griffel' const rootClassName = makeResetStyles({ - width: "100%", - height: "100%", -}); + width: '100%', + height: '100%', +}) const svgClassName = makeResetStyles({ - position: "absolute", + position: 'absolute', top: 0, left: 0, - width: "100%", - height: "100%", -}); + width: '100%', + height: '100%', +}) const svgStyles = makeStyles({ fg: { zIndex: 1000, - pointerEvents: "none", + pointerEvents: 'none', }, -}); +}) const canvasClassName = makeResetStyles({ - position: "absolute", - right: "10px", - bottom: "10px", + position: 'absolute', + right: '10px', + bottom: '10px', zIndex: 1000, - backgroundColor: "#eeeeee", -}); + backgroundColor: '#eeeeee', +}) export default () => defineStyles({ @@ -34,4 +34,4 @@ export default () => bgSvg: [svgClassName], fgSvg: [svgClassName, svgStyles.fg], canvas: [canvasClassName], - }); + }) diff --git a/packages/visual-flow/src/view/index.ts b/packages/visual-flow/src/view/index.ts index fd73dc7..1297dba 100644 --- a/packages/visual-flow/src/view/index.ts +++ b/packages/visual-flow/src/view/index.ts @@ -1,5 +1,5 @@ -export * from "./block.r"; -export * from "./creator.r"; -export * from "./graph.r"; -export * from "./line.r"; -export * from "./socket.r"; +export * from './block.r' +export * from './creator.r' +export * from './graph.r' +export * from './line.r' +export * from './socket.r' diff --git a/packages/visual-flow/src/view/line.r.ts b/packages/visual-flow/src/view/line.r.ts index 40dab06..aa71cb9 100644 --- a/packages/visual-flow/src/view/line.r.ts +++ b/packages/visual-flow/src/view/line.r.ts @@ -1,28 +1,28 @@ -import { Component, _ } from "refina"; -import { Line } from "../model"; -import useStyles from "./line.styles"; +import { Component, _ } from 'refina' +import type { Line } from '../model' +import useStyles from './line.styles' export class VfLine extends Component { $main(model: Line) { - const color = - model.colors[ - model.dragging ? "dragging" : model.hovered ? "hovered" : "default" - ]; + const color + = model.colors[ + model.dragging ? 'dragging' : model.hovered ? 'hovered' : 'default' + ] - const styles = useStyles(model.dragging, model.predicting); + const styles = useStyles(model.dragging, model.predicting) - styles.curve(); - _.$css`stroke-width:${model.graph.boardScale * 3}px;stroke:${color}`; - _.$ref(model.lineRef) && - _._svgPath({ - d: model.linePath, - }); + styles.curve() + _.$css`stroke-width:${model.graph.boardScale * 3}px;stroke:${color}` + _.$ref(model.lineRef) + && _._svgPath({ + d: model.linePath, + }) - styles.arrow(); - _.$css`fill:${color}`; - _.$ref(model.arrowRef) && - _._svgPath({ - d: model.arrowPath, - }); + styles.arrow() + _.$css`fill:${color}` + _.$ref(model.arrowRef) + && _._svgPath({ + d: model.arrowPath, + }) } } diff --git a/packages/visual-flow/src/view/line.styles.ts b/packages/visual-flow/src/view/line.styles.ts index 3e28b61..ae15457 100644 --- a/packages/visual-flow/src/view/line.styles.ts +++ b/packages/visual-flow/src/view/line.styles.ts @@ -1,14 +1,13 @@ -import { tokens } from "@fluentui/tokens"; +import { tokens } from '@fluentui/tokens' import { defineStyles, makeResetStyles, makeStyles, - mergeClasses, -} from "@refina/griffel"; +} from '@refina/griffel' const curveClassName = makeResetStyles({ - fill: "none", -}); + fill: 'none', +}) const curveStyles = makeStyles({ dragging: { @@ -17,16 +16,16 @@ const curveStyles = makeStyles({ predicting: { opacity: 0.4, }, -}); +}) -const arrowClassName = makeResetStyles({}); +const arrowClassName = makeResetStyles({}) const arrowStyles = makeStyles({ dragging: {}, predicting: { opacity: 0.4, }, -}); +}) export default (dragging: boolean, predicting: boolean) => defineStyles({ @@ -40,4 +39,4 @@ export default (dragging: boolean, predicting: boolean) => dragging && arrowStyles.dragging, predicting && arrowStyles.predicting, ], - }); + }) diff --git a/packages/visual-flow/src/view/socket.r.ts b/packages/visual-flow/src/view/socket.r.ts index 5d39d6f..b381afc 100644 --- a/packages/visual-flow/src/view/socket.r.ts +++ b/packages/visual-flow/src/view/socket.r.ts @@ -1,32 +1,32 @@ -import { Component, _ } from "refina"; -import { Socket } from "../model"; -import { Direction } from "../types"; -import useStyles from "./socket.styles"; +import { Component, _ } from 'refina' +import type { Socket } from '../model' +import { Direction } from '../types' +import useStyles from './socket.styles' export class VfSocket extends Component { $main(model: Socket) { - const styles = useStyles(model.disabled); + const styles = useStyles(model.disabled) - styles.root(); - _.$css`transform: translate(${model.blockDisplayX}px, ${model.blockDisplayY}px) scale(${model.graph.boardScale})`; - _.$ref(model.ref) && - _._svgG({}, _ => { - _.$css`transform: rotate(${ + styles.root() + _.$css`transform: translate(${model.blockDisplayX}px, ${model.blockDisplayY}px) scale(${model.graph.boardScale})` + _.$ref(model.ref) + && _._svgG({}, _ => { + _.$css`transform: rotate(${ { [Direction.LEFT]: 180, [Direction.TOP]: 270, [Direction.RIGHT]: 0, [Direction.BOTTOM]: 90, }[model.direction] - }deg)`; - _._svgPath({ - d: model.path, - }); + }deg)` + _._svgPath({ + d: model.path, + }) - if (!model.hideLabel) { - styles.label(); - _._svgText(model.labelBoardPos, model.label); - } - }); + if (!model.hideLabel) { + styles.label() + _._svgText(model.labelBoardPos, model.label) + } + }) } } diff --git a/packages/visual-flow/src/view/socket.styles.ts b/packages/visual-flow/src/view/socket.styles.ts index 1198863..3a2dd2f 100644 --- a/packages/visual-flow/src/view/socket.styles.ts +++ b/packages/visual-flow/src/view/socket.styles.ts @@ -1,28 +1,28 @@ -import { tokens } from "@fluentui/tokens"; -import { defineStyles, makeResetStyles, makeStyles } from "@refina/griffel"; +import { tokens } from '@fluentui/tokens' +import { defineStyles, makeResetStyles, makeStyles } from '@refina/griffel' const rootClassName = makeResetStyles({ fill: tokens.colorBrandForegroundInverted, -}); +}) const rootStyles = makeStyles({ disabled: { fill: tokens.colorNeutralForegroundDisabled }, notDisabled: { - "&.hovered *": { + '&.hovered *': { fill: tokens.colorCompoundBrandBackgroundHover, }, }, -}); +}) const labelClassName = makeResetStyles({ fontSize: tokens.fontSizeBase200, fontWeight: tokens.fontWeightMedium, - alignmentBaseline: "text-after-edge", -}); + alignmentBaseline: 'text-after-edge', +}) const labelStyles = makeStyles({ disabled: { fill: tokens.colorNeutralForegroundDisabled }, -}); +}) export default (disabled: boolean) => defineStyles({ @@ -31,4 +31,4 @@ export default (disabled: boolean) => disabled ? rootStyles.disabled : rootStyles.notDisabled, ], label: [labelClassName, disabled && labelStyles.disabled], - }); + }) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index cd0ef7e..5b880e0 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -8,15 +8,21 @@ importers: .: devDependencies: + '@antfu/eslint-config': + specifier: ^2.8.1 + version: 2.8.1(@vue/compiler-sfc@3.4.21)(eslint@8.57.0)(typescript@5.4.2) + eslint: + specifier: ^8.57.0 + version: 8.57.0 husky: specifier: ^8.0.3 version: 8.0.3 lint-staged: specifier: ^14.0.1 version: 14.0.1 - prettier: - specifier: 3.0.0 - version: 3.0.0 + simple-git-hooks: + specifier: ^2.10.0 + version: 2.10.0 packages/browser-tailwind: dependencies: @@ -152,7 +158,7 @@ importers: version: 0.8.3(vite@4.5.2) vite-plugin-monaco-editor: specifier: ^1.1.0 - version: 1.1.0(monaco-editor@0.47.0) + version: 1.1.0(monaco-editor@0.44.0) vite-plugin-refina: specifier: ^0.6.0 version: 0.6.0(typescript@5.4.2)(vite@4.5.2) @@ -209,14 +215,125 @@ importers: packages: + /@aashutoshrathi/word-wrap@1.2.6: + resolution: {integrity: sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==} + engines: {node: '>=0.10.0'} + dev: true + /@alloc/quick-lru@5.2.0: resolution: {integrity: sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==} engines: {node: '>=10'} + /@antfu/eslint-config@2.8.1(@vue/compiler-sfc@3.4.21)(eslint@8.57.0)(typescript@5.4.2): + resolution: {integrity: sha512-9fgSdaycCj4odiejWrCMET/Ub+dktRUSxFr8rMJ9SfiOlimav86SHo0myEtj14422yTrw8J9XkVUW6Q9ASt2Og==} + hasBin: true + peerDependencies: + '@unocss/eslint-plugin': '>=0.50.0' + astro-eslint-parser: ^0.16.3 + eslint: '>=8.40.0' + eslint-plugin-astro: ^0.31.4 + eslint-plugin-format: '>=0.1.0' + eslint-plugin-react: ^7.33.2 + eslint-plugin-react-hooks: ^4.6.0 + eslint-plugin-react-refresh: ^0.4.4 + eslint-plugin-svelte: ^2.34.1 + prettier-plugin-astro: ^0.13.0 + prettier-plugin-slidev: ^1.0.5 + svelte-eslint-parser: ^0.33.1 + peerDependenciesMeta: + '@unocss/eslint-plugin': + optional: true + astro-eslint-parser: + optional: true + eslint-plugin-astro: + optional: true + eslint-plugin-format: + optional: true + eslint-plugin-react: + optional: true + eslint-plugin-react-hooks: + optional: true + eslint-plugin-react-refresh: + optional: true + eslint-plugin-svelte: + optional: true + prettier-plugin-astro: + optional: true + prettier-plugin-slidev: + optional: true + svelte-eslint-parser: + optional: true + dependencies: + '@antfu/eslint-define-config': 1.23.0-2 + '@antfu/install-pkg': 0.3.1 + '@eslint-types/jsdoc': 46.8.2-1 + '@eslint-types/typescript-eslint': 7.0.2 + '@eslint-types/unicorn': 51.0.1 + '@stylistic/eslint-plugin': 1.6.3(eslint@8.57.0)(typescript@5.4.2) + '@typescript-eslint/eslint-plugin': 7.2.0(@typescript-eslint/parser@7.2.0)(eslint@8.57.0)(typescript@5.4.2) + '@typescript-eslint/parser': 7.2.0(eslint@8.57.0)(typescript@5.4.2) + eslint: 8.57.0 + eslint-config-flat-gitignore: 0.1.3 + eslint-merge-processors: 0.1.0(eslint@8.57.0) + eslint-plugin-antfu: 2.1.2(eslint@8.57.0) + eslint-plugin-eslint-comments: 3.2.0(eslint@8.57.0) + eslint-plugin-i: 2.29.1(@typescript-eslint/parser@7.2.0)(eslint@8.57.0) + eslint-plugin-jsdoc: 48.2.1(eslint@8.57.0) + eslint-plugin-jsonc: 2.13.0(eslint@8.57.0) + eslint-plugin-markdown: 4.0.1(eslint@8.57.0) + eslint-plugin-n: 16.6.2(eslint@8.57.0) + eslint-plugin-no-only-tests: 3.1.0 + eslint-plugin-perfectionist: 2.6.0(eslint@8.57.0)(typescript@5.4.2)(vue-eslint-parser@9.4.2) + eslint-plugin-toml: 0.9.2(eslint@8.57.0) + eslint-plugin-unicorn: 51.0.1(eslint@8.57.0) + eslint-plugin-unused-imports: 3.1.0(@typescript-eslint/eslint-plugin@7.2.0)(eslint@8.57.0) + eslint-plugin-vitest: 0.3.26(@typescript-eslint/eslint-plugin@7.2.0)(eslint@8.57.0)(typescript@5.4.2) + eslint-plugin-vue: 9.23.0(eslint@8.57.0) + eslint-plugin-yml: 1.12.2(eslint@8.57.0) + eslint-processor-vue-blocks: 0.1.1(@vue/compiler-sfc@3.4.21)(eslint@8.57.0) + globals: 14.0.0 + jsonc-eslint-parser: 2.4.0 + local-pkg: 0.5.0 + parse-gitignore: 2.0.0 + picocolors: 1.0.0 + prompts: 2.4.2 + toml-eslint-parser: 0.9.3 + vue-eslint-parser: 9.4.2(eslint@8.57.0) + yaml-eslint-parser: 1.2.2 + yargs: 17.7.2 + transitivePeerDependencies: + - '@vue/compiler-sfc' + - eslint-import-resolver-typescript + - eslint-import-resolver-webpack + - supports-color + - svelte + - typescript + - vitest + dev: true + + /@antfu/eslint-define-config@1.23.0-2: + resolution: {integrity: sha512-LvxY21+ZhpuBf/aHeBUtGQhSEfad4PkNKXKvDOSvukaM3XVTfBhwmHX2EKwAsdq5DlfjbT3qqYyMiueBIO5iDQ==} + engines: {node: '>=18.0.0', npm: '>=9.0.0', pnpm: '>= 8.6.0'} + dev: true + + /@antfu/install-pkg@0.3.1: + resolution: {integrity: sha512-A3zWY9VeTPnxlMiZtsGHw2lSd3ghwvL8s9RiGOtqvDxhhFfZ781ynsGBa/iUnDJ5zBrmTFQrJDud3TGgRISaxw==} + dependencies: + execa: 8.0.1 + dev: true + /@antfu/utils@0.7.7: resolution: {integrity: sha512-gFPqTG7otEJ8uP6wrhDv6mqwGWYZKNvAcCq6u9hOj0c+IKCEsY4L1oC9trPq2SaWIzAfHvqfBDxF591JkMf+kg==} dev: true + /@babel/code-frame@7.23.5: + resolution: {integrity: sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/highlight': 7.23.4 + chalk: 2.4.2 + dev: true + /@babel/helper-string-parser@7.23.4: resolution: {integrity: sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ==} engines: {node: '>=6.9.0'} @@ -227,6 +344,15 @@ packages: engines: {node: '>=6.9.0'} dev: true + /@babel/highlight@7.23.4: + resolution: {integrity: sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/helper-validator-identifier': 7.22.20 + chalk: 2.4.2 + js-tokens: 4.0.0 + dev: true + /@babel/parser@7.24.0: resolution: {integrity: sha512-QuP/FxEAzMSjXygs8v4N9dvdXzEHN4W1oF3PxuWAtPo08UdM17u89RDMgjLn/mlc56iM0HlLmVkO/wgR+rDgHg==} engines: {node: '>=6.0.0'} @@ -255,6 +381,15 @@ packages: resolution: {integrity: sha512-gJB6HLm5rYwSLI6PQa+X1t5CFGrv1J1TWG+sOyMCeKz2ojaj6Fnl/rZEspogG+cvqbt4AE/2eIyD2QfLKTBNlQ==} dev: false + /@es-joy/jsdoccomment@0.42.0: + resolution: {integrity: sha512-R1w57YlVA6+YE01wch3GPYn6bCsrOV3YW/5oGGE2tmX6JcL9Nr+b5IikrjMPF+v9CV3ay+obImEdsDhovhJrzw==} + engines: {node: '>=16'} + dependencies: + comment-parser: 1.4.1 + esquery: 1.5.0 + jsdoc-type-pratt-parser: 4.0.0 + dev: true + /@esbuild/android-arm64@0.18.20: resolution: {integrity: sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ==} engines: {node: '>=12'} @@ -453,6 +588,55 @@ packages: dev: true optional: true + /@eslint-community/eslint-utils@4.4.0(eslint@8.57.0): + resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 + dependencies: + eslint: 8.57.0 + eslint-visitor-keys: 3.4.3 + dev: true + + /@eslint-community/regexpp@4.10.0: + resolution: {integrity: sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==} + engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} + dev: true + + /@eslint-types/jsdoc@46.8.2-1: + resolution: {integrity: sha512-FwD7V0xX0jyaqj8Ul5ZY+TAAPohDfVqtbuXJNHb+OIv1aTIqZi5+Zn3F2UwQ5O3BnQd2mTduyK0+HjGx3/AMFg==} + dev: true + + /@eslint-types/typescript-eslint@7.0.2: + resolution: {integrity: sha512-2F67MVKhkJ2rSwoYvNJzJULqZwR5rNYI/eWoIrKDQ14lMzfqzbpzCBvnHrivBYWTN+Az7MVX00TzDTrjOc+YNA==} + dev: true + + /@eslint-types/unicorn@51.0.1: + resolution: {integrity: sha512-RuuEK+dBISEikf7a8lrWOrDCUYv09sZfqLoG/kozH+5UqEvot1xMmGHXomGkTyB68rzjgJe0N4uESVyL62obJw==} + dev: true + + /@eslint/eslintrc@2.1.4: + resolution: {integrity: sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dependencies: + ajv: 6.12.6 + debug: 4.3.4 + espree: 9.6.1 + globals: 13.24.0 + ignore: 5.3.1 + import-fresh: 3.3.0 + js-yaml: 4.1.0 + minimatch: 3.1.2 + strip-json-comments: 3.1.1 + transitivePeerDependencies: + - supports-color + dev: true + + /@eslint/js@8.57.0: + resolution: {integrity: sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dev: true + /@floating-ui/core@1.6.0: resolution: {integrity: sha512-PcF++MykgmTj3CIyOQbKA/hDzOAiqI3mhuoN44WRCopIs1sgoDoU4oty4Jtqaj/y3oDU6fnVSm4QG0a3t5i0+g==} dependencies: @@ -509,6 +693,26 @@ packages: csstype: 3.1.3 dev: false + /@humanwhocodes/config-array@0.11.14: + resolution: {integrity: sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==} + engines: {node: '>=10.10.0'} + dependencies: + '@humanwhocodes/object-schema': 2.0.2 + debug: 4.3.4 + minimatch: 3.1.2 + transitivePeerDependencies: + - supports-color + dev: true + + /@humanwhocodes/module-importer@1.0.1: + resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} + engines: {node: '>=12.22'} + dev: true + + /@humanwhocodes/object-schema@2.0.2: + resolution: {integrity: sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw==} + dev: true + /@isaacs/cliui@8.0.2: resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} engines: {node: '>=12'} @@ -898,6 +1102,78 @@ packages: string-argv: 0.3.2 dev: true + /@stylistic/eslint-plugin-js@1.6.3(eslint@8.57.0): + resolution: {integrity: sha512-ckdz51oHxD2FaxgY2piJWJVJiwgp8Uu96s+as2yB3RMwavn3nHBrpliVukXY9S/DmMicPRB2+H8nBk23GDG+qA==} + engines: {node: ^16.0.0 || >=18.0.0} + peerDependencies: + eslint: '>=8.40.0' + dependencies: + '@types/eslint': 8.56.5 + acorn: 8.11.3 + escape-string-regexp: 4.0.0 + eslint: 8.57.0 + eslint-visitor-keys: 3.4.3 + espree: 9.6.1 + dev: true + + /@stylistic/eslint-plugin-jsx@1.6.3(eslint@8.57.0): + resolution: {integrity: sha512-SRysCIg59Zvn3dJPqHziiHwuni4NNj1et5stAmivmyQ3Cdp2ULCB7tGxCF1OxpkwRlZQue3ZgdiM7EXfJKaf9w==} + engines: {node: ^16.0.0 || >=18.0.0} + peerDependencies: + eslint: '>=8.40.0' + dependencies: + '@stylistic/eslint-plugin-js': 1.6.3(eslint@8.57.0) + '@types/eslint': 8.56.5 + eslint: 8.57.0 + estraverse: 5.3.0 + picomatch: 4.0.1 + dev: true + + /@stylistic/eslint-plugin-plus@1.6.3(eslint@8.57.0)(typescript@5.4.2): + resolution: {integrity: sha512-TuwQOdyVGycDPw5XeF7W4f3ZonAVzOAzORSaD2yGAJ0fRAbJ+l/v3CkKzIAqBBwWkc+c2aRMsWtLP2+viBnmlQ==} + peerDependencies: + eslint: '*' + dependencies: + '@types/eslint': 8.56.5 + '@typescript-eslint/utils': 6.21.0(eslint@8.57.0)(typescript@5.4.2) + eslint: 8.57.0 + transitivePeerDependencies: + - supports-color + - typescript + dev: true + + /@stylistic/eslint-plugin-ts@1.6.3(eslint@8.57.0)(typescript@5.4.2): + resolution: {integrity: sha512-v5GwZsPLblWM9uAIdaSi31Sed3XBWlTFQJ3b5upEmj6QsKYivA5nmIYutwqqL133QdVWjmC86pINlx2Muq3uNQ==} + engines: {node: ^16.0.0 || >=18.0.0} + peerDependencies: + eslint: '>=8.40.0' + dependencies: + '@stylistic/eslint-plugin-js': 1.6.3(eslint@8.57.0) + '@types/eslint': 8.56.5 + '@typescript-eslint/utils': 6.21.0(eslint@8.57.0)(typescript@5.4.2) + eslint: 8.57.0 + transitivePeerDependencies: + - supports-color + - typescript + dev: true + + /@stylistic/eslint-plugin@1.6.3(eslint@8.57.0)(typescript@5.4.2): + resolution: {integrity: sha512-WDa4FjhImp7YcztRaMG09svhKYYhi2Hc4p9ltQRSqyB4fsUUFm+GKzStqqH7xfjHnxacMJaOnaMGRTUqIIZDLA==} + engines: {node: ^16.0.0 || >=18.0.0} + peerDependencies: + eslint: '>=8.40.0' + dependencies: + '@stylistic/eslint-plugin-js': 1.6.3(eslint@8.57.0) + '@stylistic/eslint-plugin-jsx': 1.6.3(eslint@8.57.0) + '@stylistic/eslint-plugin-plus': 1.6.3(eslint@8.57.0)(typescript@5.4.2) + '@stylistic/eslint-plugin-ts': 1.6.3(eslint@8.57.0)(typescript@5.4.2) + '@types/eslint': 8.56.5 + eslint: 8.57.0 + transitivePeerDependencies: + - supports-color + - typescript + dev: true + /@swc/helpers@0.5.3: resolution: {integrity: sha512-FaruWX6KdudYloq1AHD/4nU+UsMTdNE8CKyrseXWEcgjDAbvkwJg2QGPAnfIJLIWsjZOSPLOAykK6fuYp4vp4A==} dependencies: @@ -918,21 +1194,248 @@ packages: resolution: {integrity: sha512-xP1pB67eLrRdMLKpXUXhYN/3uiJN1gNalcVOSY5kdJbxhGuZTTE8awSWOD9LCJDzQZVsuZZcnMMLRrbf+nOUSQ==} dev: true + /@types/eslint@8.56.5: + resolution: {integrity: sha512-u5/YPJHo1tvkSF2CE0USEkxon82Z5DBy2xR+qfyYNszpX9qcs4sT6uq2kBbj4BXY1+DBGDPnrhMZV3pKWGNukw==} + dependencies: + '@types/estree': 1.0.5 + '@types/json-schema': 7.0.15 + dev: true + /@types/estree@1.0.5: resolution: {integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==} dev: true + /@types/json-schema@7.0.15: + resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} + dev: true + + /@types/mdast@3.0.15: + resolution: {integrity: sha512-LnwD+mUEfxWMa1QpDraczIn6k0Ee3SMicuYSSzS6ZYl2gKS09EClnJYGd8Du6rfc5r/GZEk5o1mRb8TaTj03sQ==} + dependencies: + '@types/unist': 2.0.10 + dev: true + + /@types/normalize-package-data@2.4.4: + resolution: {integrity: sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==} + dev: true + /@types/resolve@1.20.2: resolution: {integrity: sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==} dev: true + /@types/semver@7.5.8: + resolution: {integrity: sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==} + dev: true + /@types/trusted-types@2.0.7: resolution: {integrity: sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==} + /@types/unist@2.0.10: + resolution: {integrity: sha512-IfYcSBWE3hLpBg8+X2SEa8LVkJdJEkT2Ese2aaLs3ptGdVtABxndrMaxuFlQ1qdFf9Q5rDvDpxI3WwgvKFAsQA==} + dev: true + /@types/wicg-file-system-access@2023.10.5: resolution: {integrity: sha512-e9kZO9kCdLqT2h9Tw38oGv9UNzBBWaR1MzuAavxPcsV/7FJ3tWbU6RI3uB+yKIDPGLkGVbplS52ub0AcRLvrhA==} dev: true + /@typescript-eslint/eslint-plugin@7.2.0(@typescript-eslint/parser@7.2.0)(eslint@8.57.0)(typescript@5.4.2): + resolution: {integrity: sha512-mdekAHOqS9UjlmyF/LSs6AIEvfceV749GFxoBAjwAv0nkevfKHWQFDMcBZWUiIC5ft6ePWivXoS36aKQ0Cy3sw==} + engines: {node: ^16.0.0 || >=18.0.0} + peerDependencies: + '@typescript-eslint/parser': ^7.0.0 + eslint: ^8.56.0 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@eslint-community/regexpp': 4.10.0 + '@typescript-eslint/parser': 7.2.0(eslint@8.57.0)(typescript@5.4.2) + '@typescript-eslint/scope-manager': 7.2.0 + '@typescript-eslint/type-utils': 7.2.0(eslint@8.57.0)(typescript@5.4.2) + '@typescript-eslint/utils': 7.2.0(eslint@8.57.0)(typescript@5.4.2) + '@typescript-eslint/visitor-keys': 7.2.0 + debug: 4.3.4 + eslint: 8.57.0 + graphemer: 1.4.0 + ignore: 5.3.1 + natural-compare: 1.4.0 + semver: 7.6.0 + ts-api-utils: 1.3.0(typescript@5.4.2) + typescript: 5.4.2 + transitivePeerDependencies: + - supports-color + dev: true + + /@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.4.2): + resolution: {integrity: sha512-5FKsVcHTk6TafQKQbuIVkXq58Fnbkd2wDL4LB7AURN7RUOu1utVP+G8+6u3ZhEroW3DF6hyo3ZEXxgKgp4KeCg==} + engines: {node: ^16.0.0 || >=18.0.0} + peerDependencies: + eslint: ^8.56.0 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@typescript-eslint/scope-manager': 7.2.0 + '@typescript-eslint/types': 7.2.0 + '@typescript-eslint/typescript-estree': 7.2.0(typescript@5.4.2) + '@typescript-eslint/visitor-keys': 7.2.0 + debug: 4.3.4 + eslint: 8.57.0 + typescript: 5.4.2 + transitivePeerDependencies: + - supports-color + dev: true + + /@typescript-eslint/scope-manager@6.21.0: + resolution: {integrity: sha512-OwLUIWZJry80O99zvqXVEioyniJMa+d2GrqpUTqi5/v5D5rOrppJVBPa0yKCblcigC0/aYAzxxqQ1B+DS2RYsg==} + engines: {node: ^16.0.0 || >=18.0.0} + dependencies: + '@typescript-eslint/types': 6.21.0 + '@typescript-eslint/visitor-keys': 6.21.0 + dev: true + + /@typescript-eslint/scope-manager@7.2.0: + resolution: {integrity: sha512-Qh976RbQM/fYtjx9hs4XkayYujB/aPwglw2choHmf3zBjB4qOywWSdt9+KLRdHubGcoSwBnXUH2sR3hkyaERRg==} + engines: {node: ^16.0.0 || >=18.0.0} + dependencies: + '@typescript-eslint/types': 7.2.0 + '@typescript-eslint/visitor-keys': 7.2.0 + dev: true + + /@typescript-eslint/type-utils@7.2.0(eslint@8.57.0)(typescript@5.4.2): + resolution: {integrity: sha512-xHi51adBHo9O9330J8GQYQwrKBqbIPJGZZVQTHHmy200hvkLZFWJIFtAG/7IYTWUyun6DE6w5InDReePJYJlJA==} + engines: {node: ^16.0.0 || >=18.0.0} + peerDependencies: + eslint: ^8.56.0 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@typescript-eslint/typescript-estree': 7.2.0(typescript@5.4.2) + '@typescript-eslint/utils': 7.2.0(eslint@8.57.0)(typescript@5.4.2) + debug: 4.3.4 + eslint: 8.57.0 + ts-api-utils: 1.3.0(typescript@5.4.2) + typescript: 5.4.2 + transitivePeerDependencies: + - supports-color + dev: true + + /@typescript-eslint/types@6.21.0: + resolution: {integrity: sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg==} + engines: {node: ^16.0.0 || >=18.0.0} + dev: true + + /@typescript-eslint/types@7.2.0: + resolution: {integrity: sha512-XFtUHPI/abFhm4cbCDc5Ykc8npOKBSJePY3a3s+lwumt7XWJuzP5cZcfZ610MIPHjQjNsOLlYK8ASPaNG8UiyA==} + engines: {node: ^16.0.0 || >=18.0.0} + dev: true + + /@typescript-eslint/typescript-estree@6.21.0(typescript@5.4.2): + resolution: {integrity: sha512-6npJTkZcO+y2/kr+z0hc4HwNfrrP4kNYh57ek7yCNlrBjWQ1Y0OS7jiZTkgumrvkX5HkEKXFZkkdFNkaW2wmUQ==} + engines: {node: ^16.0.0 || >=18.0.0} + peerDependencies: + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@typescript-eslint/types': 6.21.0 + '@typescript-eslint/visitor-keys': 6.21.0 + debug: 4.3.4 + globby: 11.1.0 + is-glob: 4.0.3 + minimatch: 9.0.3 + semver: 7.6.0 + ts-api-utils: 1.3.0(typescript@5.4.2) + typescript: 5.4.2 + transitivePeerDependencies: + - supports-color + dev: true + + /@typescript-eslint/typescript-estree@7.2.0(typescript@5.4.2): + resolution: {integrity: sha512-cyxS5WQQCoBwSakpMrvMXuMDEbhOo9bNHHrNcEWis6XHx6KF518tkF1wBvKIn/tpq5ZpUYK7Bdklu8qY0MsFIA==} + engines: {node: ^16.0.0 || >=18.0.0} + peerDependencies: + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@typescript-eslint/types': 7.2.0 + '@typescript-eslint/visitor-keys': 7.2.0 + debug: 4.3.4 + globby: 11.1.0 + is-glob: 4.0.3 + minimatch: 9.0.3 + semver: 7.6.0 + ts-api-utils: 1.3.0(typescript@5.4.2) + typescript: 5.4.2 + transitivePeerDependencies: + - supports-color + dev: true + + /@typescript-eslint/utils@6.21.0(eslint@8.57.0)(typescript@5.4.2): + resolution: {integrity: sha512-NfWVaC8HP9T8cbKQxHcsJBY5YE1O33+jpMwN45qzWWaPDZgLIbo12toGMWnmhvCpd3sIxkpDw3Wv1B3dYrbDQQ==} + engines: {node: ^16.0.0 || >=18.0.0} + peerDependencies: + eslint: ^7.0.0 || ^8.0.0 + dependencies: + '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) + '@types/json-schema': 7.0.15 + '@types/semver': 7.5.8 + '@typescript-eslint/scope-manager': 6.21.0 + '@typescript-eslint/types': 6.21.0 + '@typescript-eslint/typescript-estree': 6.21.0(typescript@5.4.2) + eslint: 8.57.0 + semver: 7.6.0 + transitivePeerDependencies: + - supports-color + - typescript + dev: true + + /@typescript-eslint/utils@7.2.0(eslint@8.57.0)(typescript@5.4.2): + resolution: {integrity: sha512-YfHpnMAGb1Eekpm3XRK8hcMwGLGsnT6L+7b2XyRv6ouDuJU1tZir1GS2i0+VXRatMwSI1/UfcyPe53ADkU+IuA==} + engines: {node: ^16.0.0 || >=18.0.0} + peerDependencies: + eslint: ^8.56.0 + dependencies: + '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) + '@types/json-schema': 7.0.15 + '@types/semver': 7.5.8 + '@typescript-eslint/scope-manager': 7.2.0 + '@typescript-eslint/types': 7.2.0 + '@typescript-eslint/typescript-estree': 7.2.0(typescript@5.4.2) + eslint: 8.57.0 + semver: 7.6.0 + transitivePeerDependencies: + - supports-color + - typescript + dev: true + + /@typescript-eslint/visitor-keys@6.21.0: + resolution: {integrity: sha512-JJtkDduxLi9bivAB+cYOVMtbkqdPOhZ+ZI5LC47MIRrDV4Yn2o+ZnW10Nkmr28xRpSpdJ6Sm42Hjf2+REYXm0A==} + engines: {node: ^16.0.0 || >=18.0.0} + dependencies: + '@typescript-eslint/types': 6.21.0 + eslint-visitor-keys: 3.4.3 + dev: true + + /@typescript-eslint/visitor-keys@7.2.0: + resolution: {integrity: sha512-c6EIQRHhcpl6+tO8EMR+kjkkV+ugUNXOmeASA1rlzkd8EPIriavpWoiEz1HR/VLhbVIdhqnV6E7JZm00cBDx2A==} + engines: {node: ^16.0.0 || >=18.0.0} + dependencies: + '@typescript-eslint/types': 7.2.0 + eslint-visitor-keys: 3.4.3 + dev: true + + /@ungap/structured-clone@1.2.0: + resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==} + dev: true + /@volar/language-core@1.11.1: resolution: {integrity: sha512-dOcNn3i9GgZAcJt43wuaEykSluAuOkQgzni1cuxLxTV0nJKanQztp7FxyswdRILaKH+P2XZMPRp2S4MV/pElCw==} dependencies: @@ -969,6 +1472,27 @@ packages: '@vue/shared': 3.4.21 dev: true + /@vue/compiler-sfc@3.4.21: + resolution: {integrity: sha512-me7epoTxYlY+2CUM7hy9PCDdpMPfIwrOvAXud2Upk10g4YLv9UBW7kL798TvMeDhPthkZ0CONNrK2GoeI1ODiQ==} + dependencies: + '@babel/parser': 7.24.0 + '@vue/compiler-core': 3.4.21 + '@vue/compiler-dom': 3.4.21 + '@vue/compiler-ssr': 3.4.21 + '@vue/shared': 3.4.21 + estree-walker: 2.0.2 + magic-string: 0.30.8 + postcss: 8.4.35 + source-map-js: 1.0.2 + dev: true + + /@vue/compiler-ssr@3.4.21: + resolution: {integrity: sha512-M5+9nI2lPpAsgXOGQobnIueVqc9sisBFexh5yMIMRAPYLa7+5wEJs8iqOZc1WAa9WQbx9GR2twgznU8LTIiZ4Q==} + dependencies: + '@vue/compiler-dom': 3.4.21 + '@vue/shared': 3.4.21 + dev: true + /@vue/language-core@1.8.27(typescript@5.4.2): resolution: {integrity: sha512-L8Kc27VdQserNaCUNiSFdDl9LWT24ly8Hpwf1ECy3aFb9m6bDhBGQYOujDm21N7EW3moKIOKEanQwe1q5BK+mA==} peerDependencies: @@ -993,6 +1517,20 @@ packages: resolution: {integrity: sha512-PuJe7vDIi6VYSinuEbUIQgMIRZGgM8e4R+G+/dQTk0X1NEdvgvvgv7m+rfmDH1gZzyA1OjjoWskvHlfRNfQf3g==} dev: true + /acorn-jsx@5.3.2(acorn@8.11.3): + resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} + peerDependencies: + acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 + dependencies: + acorn: 8.11.3 + dev: true + + /acorn@8.11.3: + resolution: {integrity: sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==} + engines: {node: '>=0.4.0'} + hasBin: true + dev: true + /ajv@6.12.6: resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} dependencies: @@ -1019,6 +1557,13 @@ packages: engines: {node: '>=12'} dev: true + /ansi-styles@3.2.1: + resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==} + engines: {node: '>=4'} + dependencies: + color-convert: 1.9.3 + dev: true + /ansi-styles@4.3.0: resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} engines: {node: '>=8'} @@ -1041,6 +1586,11 @@ packages: normalize-path: 3.0.0 picomatch: 2.3.1 + /are-docs-informative@0.0.2: + resolution: {integrity: sha512-ixiS0nLNNG5jNQzgZJNoUpBKdo9yTYZMGJ+QgT2jmjR7G7+QHRCc4v6LQ3NgE7EBJq+o0ams3waJwkrlBom8Ig==} + engines: {node: '>=14'} + dev: true + /arg@5.0.2: resolution: {integrity: sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==} @@ -1050,6 +1600,10 @@ packages: sprintf-js: 1.0.3 dev: true + /argparse@2.0.1: + resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} + dev: true + /array-buffer-byte-length@1.0.0: resolution: {integrity: sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==} dependencies: @@ -1057,6 +1611,11 @@ packages: is-array-buffer: 3.0.2 dev: false + /array-union@2.1.0: + resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} + engines: {node: '>=8'} + dev: true + /autoprefixer@10.4.18(postcss@8.4.35): resolution: {integrity: sha512-1DKbDfsr6KUElM6wg+0zRNkB/Q7WcKYAaK+pzXn+Xqmszm/5Xa9coeNdtP88Vi+dPzZnMjhge8GIV49ZQkDa+g==} engines: {node: ^10 || ^12 || >=14} @@ -1085,12 +1644,15 @@ packages: resolution: {integrity: sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==} engines: {node: '>=8'} + /boolbase@1.0.0: + resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==} + dev: true + /brace-expansion@1.1.11: resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} dependencies: balanced-match: 1.0.2 concat-map: 0.0.1 - dev: false /brace-expansion@2.0.1: resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} @@ -1120,6 +1682,12 @@ packages: engines: {node: '>=6'} dev: true + /builtins@5.0.1: + resolution: {integrity: sha512-qwVpFEHNfhYJIzNRBvd2C1kyo6jz3ZSMPyyuR47OPdiKWlbYnZNyDWuyR175qDnAJLiCo5fBBqPb3RiXgWlkOQ==} + dependencies: + semver: 7.6.0 + dev: true + /bundle-name@4.1.0: resolution: {integrity: sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==} engines: {node: '>=18'} @@ -1135,6 +1703,11 @@ packages: set-function-length: 1.1.1 dev: false + /callsites@3.1.0: + resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} + engines: {node: '>=6'} + dev: true + /camelcase-css@2.0.1: resolution: {integrity: sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==} engines: {node: '>= 6'} @@ -1143,11 +1716,40 @@ packages: resolution: {integrity: sha512-7LjJvmQU6Sj7bL0j5b5WY/3n7utXUJvAe1lxhsHDbLmwX9mdL86Yjtr+5SRCyf8qME4M7pU2hswj0FpyBVCv9w==} dev: true + /chalk@2.4.2: + resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} + engines: {node: '>=4'} + dependencies: + ansi-styles: 3.2.1 + escape-string-regexp: 1.0.5 + supports-color: 5.5.0 + dev: true + + /chalk@4.1.2: + resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} + engines: {node: '>=10'} + dependencies: + ansi-styles: 4.3.0 + supports-color: 7.2.0 + dev: true + /chalk@5.3.0: resolution: {integrity: sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==} engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} dev: true + /character-entities-legacy@1.1.4: + resolution: {integrity: sha512-3Xnr+7ZFS1uxeiUDvV02wQ+QDbc55o97tIV5zHScSPJpcLm/r0DFPcoY3tYRp+VZukxuMeKgXYmsXQHO05zQeA==} + dev: true + + /character-entities@1.2.4: + resolution: {integrity: sha512-iBMyeEHxfVnIakwOuDXpVkc54HijNgCyQB2w0VfGQThle6NXn50zU6V/u+LDhxHcDUPojn6Kpga3PTAD8W1bQw==} + dev: true + + /character-reference-invalid@1.1.4: + resolution: {integrity: sha512-mKKUkUbhPpQlCOfIuZkvSEgktjPFIsZKRRbC6KWVEMvlzblj3i3asQv5ODsrwt0N3pHAEvjP8KTQPHkp0+6jOg==} + dev: true + /chokidar@3.5.3: resolution: {integrity: sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==} engines: {node: '>= 8.10.0'} @@ -1178,9 +1780,21 @@ packages: fsevents: 2.3.3 dev: true + /ci-info@4.0.0: + resolution: {integrity: sha512-TdHqgGf9odd8SXNuxtUBVx8Nv+qZOejE6qyqiy5NtbYYQOeFa6zmHkxlPzmaLxWWHsU6nJmB7AETdVPi+2NBUg==} + engines: {node: '>=8'} + dev: true + /classcat@5.0.4: resolution: {integrity: sha512-sbpkOw6z413p+HDGcBENe498WM9woqWHiJxCq7nvmxe9WmrUmqfAcxpIwAiMtM5Q3AhYkzXcNQHqsWq0mND51g==} + /clean-regexp@1.0.0: + resolution: {integrity: sha512-GfisEZEJvzKrmGWkvfhgzcz/BllN1USeqD2V6tg14OAOgaCD2Z/PUEuxnAZ/nPvmaHRG7a8y77p1T/IRQ4D1Hw==} + engines: {node: '>=4'} + dependencies: + escape-string-regexp: 1.0.5 + dev: true + /cli-cursor@4.0.0: resolution: {integrity: sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} @@ -1196,6 +1810,21 @@ packages: string-width: 5.1.2 dev: true + /cliui@8.0.1: + resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} + engines: {node: '>=12'} + dependencies: + string-width: 4.2.3 + strip-ansi: 6.0.1 + wrap-ansi: 7.0.0 + dev: true + + /color-convert@1.9.3: + resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} + dependencies: + color-name: 1.1.3 + dev: true + /color-convert@2.0.1: resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} engines: {node: '>=7.0.0'} @@ -1203,6 +1832,10 @@ packages: color-name: 1.1.4 dev: true + /color-name@1.1.3: + resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==} + dev: true + /color-name@1.1.4: resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} dev: true @@ -1232,6 +1865,11 @@ packages: dev: true optional: true + /comment-parser@1.4.1: + resolution: {integrity: sha512-buhp5kePrmda3vhc5B9t7pUQXAb2Tnd0qgpkIhPhkHXxJpiPJ11H0ZEU0oBpJ2QztSbzG/ZxMj/CHsYJqRHmyg==} + engines: {node: '>= 12.0.0'} + dev: true + /commondir@1.0.1: resolution: {integrity: sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==} dev: true @@ -1242,7 +1880,12 @@ packages: /concat-map@0.0.1: resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} - dev: false + + /core-js-compat@3.36.0: + resolution: {integrity: sha512-iV9Pd/PsgjNWBXeq8XRtWVSgz2tKAfhfvBs7qxYty+RlRd+OCksaWmOnc4JKrTc1cToXL1N0s3l/vwlxPtdElw==} + dependencies: + browserslist: 4.23.0 + dev: true /cross-spawn@7.0.3: resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} @@ -1266,6 +1909,17 @@ packages: resolution: {integrity: sha512-e/1zu3xH5MQryN2zdVaF0OrdNLUbvWxzMbi+iNA6Bky7l1RoP8a2fIbRocyHclXt/arDrrR6lL3TqFD9pMQTsg==} dev: true + /debug@3.2.7: + resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + dependencies: + ms: 2.1.2 + dev: true + /debug@4.3.4: resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} engines: {node: '>=6.0'} @@ -1301,6 +1955,10 @@ packages: which-typed-array: 1.1.13 dev: false + /deep-is@0.1.4: + resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} + dev: true + /deepmerge@4.3.1: resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==} engines: {node: '>=0.10.0'} @@ -1345,9 +2003,23 @@ packages: /didyoumean@1.2.2: resolution: {integrity: sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==} + /dir-glob@3.0.1: + resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} + engines: {node: '>=8'} + dependencies: + path-type: 4.0.0 + dev: true + /dlv@1.1.3: resolution: {integrity: sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==} + /doctrine@3.0.0: + resolution: {integrity: sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==} + engines: {node: '>=6.0.0'} + dependencies: + esutils: 2.0.3 + dev: true + /eastasianwidth@0.2.0: resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} dev: true @@ -1369,6 +2041,12 @@ packages: engines: {node: '>=0.12'} dev: true + /error-ex@1.3.2: + resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} + dependencies: + is-arrayish: 0.2.1 + dev: true + /error-stack-parser-es@0.1.1: resolution: {integrity: sha512-g/9rfnvnagiNf+DRMHEVGuGuIBlCIMDFoTA616HaP2l9PlCjGjVhD98PNbVSJvmK4TttqT5mV5tInMhoFgi+aA==} dev: true @@ -1422,10 +2100,467 @@ packages: engines: {node: '>=6'} dev: true + /escape-string-regexp@1.0.5: + resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} + engines: {node: '>=0.8.0'} + dev: true + + /escape-string-regexp@4.0.0: + resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} + engines: {node: '>=10'} + dev: true + + /eslint-compat-utils@0.1.2(eslint@8.57.0): + resolution: {integrity: sha512-Jia4JDldWnFNIru1Ehx1H5s9/yxiRHY/TimCuUc0jNexew3cF1gI6CYZil1ociakfWO3rRqFjl1mskBblB3RYg==} + engines: {node: '>=12'} + peerDependencies: + eslint: '>=6.0.0' + dependencies: + eslint: 8.57.0 + dev: true + + /eslint-compat-utils@0.4.1(eslint@8.57.0): + resolution: {integrity: sha512-5N7ZaJG5pZxUeNNJfUchurLVrunD1xJvyg5kYOIVF8kg1f3ajTikmAu/5fZ9w100omNPOoMjngRszh/Q/uFGMg==} + engines: {node: '>=12'} + peerDependencies: + eslint: '>=6.0.0' + dependencies: + eslint: 8.57.0 + semver: 7.6.0 + dev: true + + /eslint-config-flat-gitignore@0.1.3: + resolution: {integrity: sha512-oQD+dEZv3RThN60tFqGFt+NJcO1DmssUcP+T/nlX+ZzEoEvVUYH0GU9X/VlmDXsbMsS9mONI1HrlxLgtKojw7w==} + dependencies: + find-up: 7.0.0 + parse-gitignore: 2.0.0 + dev: true + + /eslint-import-resolver-node@0.3.9: + resolution: {integrity: sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==} + dependencies: + debug: 3.2.7 + is-core-module: 2.13.0 + resolve: 1.22.8 + transitivePeerDependencies: + - supports-color + dev: true + + /eslint-merge-processors@0.1.0(eslint@8.57.0): + resolution: {integrity: sha512-IvRXXtEajLeyssvW4wJcZ2etxkR9mUf4zpNwgI+m/Uac9RfXHskuJefkHUcawVzePnd6xp24enp5jfgdHzjRdQ==} + peerDependencies: + eslint: '*' + dependencies: + eslint: 8.57.0 + dev: true + + /eslint-module-utils@2.8.1(@typescript-eslint/parser@7.2.0)(eslint-import-resolver-node@0.3.9)(eslint@8.57.0): + resolution: {integrity: sha512-rXDXR3h7cs7dy9RNpUlQf80nX31XWJEyGq1tRMo+6GsO5VmTe4UTwtmonAD4ZkAsrfMVDA2wlGJ3790Ys+D49Q==} + engines: {node: '>=4'} + peerDependencies: + '@typescript-eslint/parser': '*' + eslint: '*' + eslint-import-resolver-node: '*' + eslint-import-resolver-typescript: '*' + eslint-import-resolver-webpack: '*' + peerDependenciesMeta: + '@typescript-eslint/parser': + optional: true + eslint: + optional: true + eslint-import-resolver-node: + optional: true + eslint-import-resolver-typescript: + optional: true + eslint-import-resolver-webpack: + optional: true + dependencies: + '@typescript-eslint/parser': 7.2.0(eslint@8.57.0)(typescript@5.4.2) + debug: 3.2.7 + eslint: 8.57.0 + eslint-import-resolver-node: 0.3.9 + transitivePeerDependencies: + - supports-color + dev: true + + /eslint-plugin-antfu@2.1.2(eslint@8.57.0): + resolution: {integrity: sha512-s7ZTOM3uq0iqpp6gF0UEotnvup7f2PHBUftCytLZX0+6C9j9KadKZQh6bVVngAyFgsmeD9+gcBopOYLClb2oDg==} + peerDependencies: + eslint: '*' + dependencies: + eslint: 8.57.0 + dev: true + + /eslint-plugin-es-x@7.5.0(eslint@8.57.0): + resolution: {integrity: sha512-ODswlDSO0HJDzXU0XvgZ3lF3lS3XAZEossh15Q2UHjwrJggWeBoKqqEsLTZLXl+dh5eOAozG0zRcYtuE35oTuQ==} + engines: {node: ^14.18.0 || >=16.0.0} + peerDependencies: + eslint: '>=8' + dependencies: + '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) + '@eslint-community/regexpp': 4.10.0 + eslint: 8.57.0 + eslint-compat-utils: 0.1.2(eslint@8.57.0) + dev: true + + /eslint-plugin-eslint-comments@3.2.0(eslint@8.57.0): + resolution: {integrity: sha512-0jkOl0hfojIHHmEHgmNdqv4fmh7300NdpA9FFpF7zaoLvB/QeXOGNLIo86oAveJFrfB1p05kC8hpEMHM8DwWVQ==} + engines: {node: '>=6.5.0'} + peerDependencies: + eslint: '>=4.19.1' + dependencies: + escape-string-regexp: 1.0.5 + eslint: 8.57.0 + ignore: 5.3.1 + dev: true + + /eslint-plugin-i@2.29.1(@typescript-eslint/parser@7.2.0)(eslint@8.57.0): + resolution: {integrity: sha512-ORizX37MelIWLbMyqI7hi8VJMf7A0CskMmYkB+lkCX3aF4pkGV7kwx5bSEb4qx7Yce2rAf9s34HqDRPjGRZPNQ==} + engines: {node: '>=12'} + peerDependencies: + eslint: ^7.2.0 || ^8 + dependencies: + debug: 4.3.4 + doctrine: 3.0.0 + eslint: 8.57.0 + eslint-import-resolver-node: 0.3.9 + eslint-module-utils: 2.8.1(@typescript-eslint/parser@7.2.0)(eslint-import-resolver-node@0.3.9)(eslint@8.57.0) + get-tsconfig: 4.7.3 + is-glob: 4.0.3 + minimatch: 3.1.2 + semver: 7.6.0 + transitivePeerDependencies: + - '@typescript-eslint/parser' + - eslint-import-resolver-typescript + - eslint-import-resolver-webpack + - supports-color + dev: true + + /eslint-plugin-jsdoc@48.2.1(eslint@8.57.0): + resolution: {integrity: sha512-iUvbcyDZSO/9xSuRv2HQBw++8VkV/pt3UWtX9cpPH0l7GKPq78QC/6+PmyQHHvNZaTjAce6QVciEbnc6J/zH5g==} + engines: {node: '>=18'} + peerDependencies: + eslint: ^7.0.0 || ^8.0.0 || ^9.0.0 + dependencies: + '@es-joy/jsdoccomment': 0.42.0 + are-docs-informative: 0.0.2 + comment-parser: 1.4.1 + debug: 4.3.4 + escape-string-regexp: 4.0.0 + eslint: 8.57.0 + esquery: 1.5.0 + is-builtin-module: 3.2.1 + semver: 7.6.0 + spdx-expression-parse: 4.0.0 + transitivePeerDependencies: + - supports-color + dev: true + + /eslint-plugin-jsonc@2.13.0(eslint@8.57.0): + resolution: {integrity: sha512-2wWdJfpO/UbZzPDABuUVvlUQjfMJa2p2iQfYt/oWxOMpXCcjuiMUSaA02gtY/Dbu82vpaSqc+O7Xq6ECHwtIxA==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: '>=6.0.0' + dependencies: + '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) + eslint: 8.57.0 + eslint-compat-utils: 0.4.1(eslint@8.57.0) + espree: 9.6.1 + graphemer: 1.4.0 + jsonc-eslint-parser: 2.4.0 + natural-compare: 1.4.0 + synckit: 0.6.2 + dev: true + + /eslint-plugin-markdown@4.0.1(eslint@8.57.0): + resolution: {integrity: sha512-5/MnGvYU0i8MbHH5cg8S+Vl3DL+bqRNYshk1xUO86DilNBaxtTkhH+5FD0/yO03AmlI6+lfNFdk2yOw72EPzpA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: '>=8' + dependencies: + eslint: 8.57.0 + mdast-util-from-markdown: 0.8.5 + transitivePeerDependencies: + - supports-color + dev: true + + /eslint-plugin-n@16.6.2(eslint@8.57.0): + resolution: {integrity: sha512-6TyDmZ1HXoFQXnhCTUjVFULReoBPOAjpuiKELMkeP40yffI/1ZRO+d9ug/VC6fqISo2WkuIBk3cvuRPALaWlOQ==} + engines: {node: '>=16.0.0'} + peerDependencies: + eslint: '>=7.0.0' + dependencies: + '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) + builtins: 5.0.1 + eslint: 8.57.0 + eslint-plugin-es-x: 7.5.0(eslint@8.57.0) + get-tsconfig: 4.7.3 + globals: 13.24.0 + ignore: 5.3.1 + is-builtin-module: 3.2.1 + is-core-module: 2.13.0 + minimatch: 3.1.2 + resolve: 1.22.8 + semver: 7.6.0 + dev: true + + /eslint-plugin-no-only-tests@3.1.0: + resolution: {integrity: sha512-Lf4YW/bL6Un1R6A76pRZyE1dl1vr31G/ev8UzIc/geCgFWyrKil8hVjYqWVKGB/UIGmb6Slzs9T0wNezdSVegw==} + engines: {node: '>=5.0.0'} + dev: true + + /eslint-plugin-perfectionist@2.6.0(eslint@8.57.0)(typescript@5.4.2)(vue-eslint-parser@9.4.2): + resolution: {integrity: sha512-hee0Fu5825v+WTIhrRIJdWO8biUgm9O+c4Q1AEXIIGsXDHrLv5cdXfVUdnQcYgGtI/4X+tdFu69iVofHCIkvtw==} + peerDependencies: + astro-eslint-parser: ^0.16.0 + eslint: '>=8.0.0' + svelte: '>=3.0.0' + svelte-eslint-parser: ^0.33.0 + vue-eslint-parser: '>=9.0.0' + peerDependenciesMeta: + astro-eslint-parser: + optional: true + svelte: + optional: true + svelte-eslint-parser: + optional: true + vue-eslint-parser: + optional: true + dependencies: + '@typescript-eslint/utils': 6.21.0(eslint@8.57.0)(typescript@5.4.2) + eslint: 8.57.0 + minimatch: 9.0.3 + natural-compare-lite: 1.4.0 + vue-eslint-parser: 9.4.2(eslint@8.57.0) + transitivePeerDependencies: + - supports-color + - typescript + dev: true + + /eslint-plugin-toml@0.9.2(eslint@8.57.0): + resolution: {integrity: sha512-ri0xf63PYf3pIq/WY9BIwrqxZmGTIwSkAO0bHddI0ajUwN4KGz6W8vOvdXFHOpRdRfzxlmXze/vfsY/aTEXESg==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: '>=6.0.0' + dependencies: + debug: 4.3.4 + eslint: 8.57.0 + eslint-compat-utils: 0.4.1(eslint@8.57.0) + lodash: 4.17.21 + toml-eslint-parser: 0.9.3 + transitivePeerDependencies: + - supports-color + dev: true + + /eslint-plugin-unicorn@51.0.1(eslint@8.57.0): + resolution: {integrity: sha512-MuR/+9VuB0fydoI0nIn2RDA5WISRn4AsJyNSaNKLVwie9/ONvQhxOBbkfSICBPnzKrB77Fh6CZZXjgTt/4Latw==} + engines: {node: '>=16'} + peerDependencies: + eslint: '>=8.56.0' + dependencies: + '@babel/helper-validator-identifier': 7.22.20 + '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) + '@eslint/eslintrc': 2.1.4 + ci-info: 4.0.0 + clean-regexp: 1.0.0 + core-js-compat: 3.36.0 + eslint: 8.57.0 + esquery: 1.5.0 + indent-string: 4.0.0 + is-builtin-module: 3.2.1 + jsesc: 3.0.2 + pluralize: 8.0.0 + read-pkg-up: 7.0.1 + regexp-tree: 0.1.27 + regjsparser: 0.10.0 + semver: 7.6.0 + strip-indent: 3.0.0 + transitivePeerDependencies: + - supports-color + dev: true + + /eslint-plugin-unused-imports@3.1.0(@typescript-eslint/eslint-plugin@7.2.0)(eslint@8.57.0): + resolution: {integrity: sha512-9l1YFCzXKkw1qtAru1RWUtG2EVDZY0a0eChKXcL+EZ5jitG7qxdctu4RnvhOJHv4xfmUf7h+JJPINlVpGhZMrw==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + '@typescript-eslint/eslint-plugin': 6 - 7 + eslint: '8' + peerDependenciesMeta: + '@typescript-eslint/eslint-plugin': + optional: true + dependencies: + '@typescript-eslint/eslint-plugin': 7.2.0(@typescript-eslint/parser@7.2.0)(eslint@8.57.0)(typescript@5.4.2) + eslint: 8.57.0 + eslint-rule-composer: 0.3.0 + dev: true + + /eslint-plugin-vitest@0.3.26(@typescript-eslint/eslint-plugin@7.2.0)(eslint@8.57.0)(typescript@5.4.2): + resolution: {integrity: sha512-oxe5JSPgRjco8caVLTh7Ti8PxpwJdhSV0hTQAmkFcNcmy/9DnqLB/oNVRA11RmVRP//2+jIIT6JuBEcpW3obYg==} + engines: {node: ^18.0.0 || >= 20.0.0} + peerDependencies: + '@typescript-eslint/eslint-plugin': '*' + eslint: '>=8.0.0' + vitest: '*' + peerDependenciesMeta: + '@typescript-eslint/eslint-plugin': + optional: true + vitest: + optional: true + dependencies: + '@typescript-eslint/eslint-plugin': 7.2.0(@typescript-eslint/parser@7.2.0)(eslint@8.57.0)(typescript@5.4.2) + '@typescript-eslint/utils': 7.2.0(eslint@8.57.0)(typescript@5.4.2) + eslint: 8.57.0 + transitivePeerDependencies: + - supports-color + - typescript + dev: true + + /eslint-plugin-vue@9.23.0(eslint@8.57.0): + resolution: {integrity: sha512-Bqd/b7hGYGrlV+wP/g77tjyFmp81lh5TMw0be9093X02SyelxRRfCI6/IsGq/J7Um0YwB9s0Ry0wlFyjPdmtUw==} + engines: {node: ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^6.2.0 || ^7.0.0 || ^8.0.0 + dependencies: + '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) + eslint: 8.57.0 + natural-compare: 1.4.0 + nth-check: 2.1.1 + postcss-selector-parser: 6.0.15 + semver: 7.6.0 + vue-eslint-parser: 9.4.2(eslint@8.57.0) + xml-name-validator: 4.0.0 + transitivePeerDependencies: + - supports-color + dev: true + + /eslint-plugin-yml@1.12.2(eslint@8.57.0): + resolution: {integrity: sha512-hvS9p08FhPT7i/ynwl7/Wt7ke7Rf4P2D6fT8lZlL43peZDTsHtH2A0SIFQ7Kt7+mJ6if6P+FX3iJhMkdnxQwpg==} + engines: {node: ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: '>=6.0.0' + dependencies: + debug: 4.3.4 + eslint: 8.57.0 + eslint-compat-utils: 0.4.1(eslint@8.57.0) + lodash: 4.17.21 + natural-compare: 1.4.0 + yaml-eslint-parser: 1.2.2 + transitivePeerDependencies: + - supports-color + dev: true + + /eslint-processor-vue-blocks@0.1.1(@vue/compiler-sfc@3.4.21)(eslint@8.57.0): + resolution: {integrity: sha512-9+dU5lU881log570oBwpelaJmOfOzSniben7IWEDRYQPPWwlvaV7NhOtsTuUWDqpYT+dtKKWPsgz4OkOi+aZnA==} + peerDependencies: + '@vue/compiler-sfc': ^3.3.0 + eslint: ^8.50.0 + dependencies: + '@vue/compiler-sfc': 3.4.21 + eslint: 8.57.0 + dev: true + + /eslint-rule-composer@0.3.0: + resolution: {integrity: sha512-bt+Sh8CtDmn2OajxvNO+BX7Wn4CIWMpTRm3MaiKPCQcnnlm0CS2mhui6QaoeQugs+3Kj2ESKEEGJUdVafwhiCg==} + engines: {node: '>=4.0.0'} + dev: true + + /eslint-scope@7.2.2: + resolution: {integrity: sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dependencies: + esrecurse: 4.3.0 + estraverse: 5.3.0 + dev: true + + /eslint-visitor-keys@3.4.3: + resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dev: true + + /eslint@8.57.0: + resolution: {integrity: sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + hasBin: true + dependencies: + '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) + '@eslint-community/regexpp': 4.10.0 + '@eslint/eslintrc': 2.1.4 + '@eslint/js': 8.57.0 + '@humanwhocodes/config-array': 0.11.14 + '@humanwhocodes/module-importer': 1.0.1 + '@nodelib/fs.walk': 1.2.8 + '@ungap/structured-clone': 1.2.0 + ajv: 6.12.6 + chalk: 4.1.2 + cross-spawn: 7.0.3 + debug: 4.3.4 + doctrine: 3.0.0 + escape-string-regexp: 4.0.0 + eslint-scope: 7.2.2 + eslint-visitor-keys: 3.4.3 + espree: 9.6.1 + esquery: 1.5.0 + esutils: 2.0.3 + fast-deep-equal: 3.1.3 + file-entry-cache: 6.0.1 + find-up: 5.0.0 + glob-parent: 6.0.2 + globals: 13.24.0 + graphemer: 1.4.0 + ignore: 5.3.1 + imurmurhash: 0.1.4 + is-glob: 4.0.3 + is-path-inside: 3.0.3 + js-yaml: 4.1.0 + json-stable-stringify-without-jsonify: 1.0.1 + levn: 0.4.1 + lodash.merge: 4.6.2 + minimatch: 3.1.2 + natural-compare: 1.4.0 + optionator: 0.9.3 + strip-ansi: 6.0.1 + text-table: 0.2.0 + transitivePeerDependencies: + - supports-color + dev: true + + /espree@9.6.1: + resolution: {integrity: sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dependencies: + acorn: 8.11.3 + acorn-jsx: 5.3.2(acorn@8.11.3) + eslint-visitor-keys: 3.4.3 + dev: true + + /esquery@1.5.0: + resolution: {integrity: sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==} + engines: {node: '>=0.10'} + dependencies: + estraverse: 5.3.0 + dev: true + + /esrecurse@4.3.0: + resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} + engines: {node: '>=4.0'} + dependencies: + estraverse: 5.3.0 + dev: true + + /estraverse@5.3.0: + resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} + engines: {node: '>=4.0'} + dev: true + /estree-walker@2.0.2: resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} dev: true + /esutils@2.0.3: + resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} + engines: {node: '>=0.10.0'} + dev: true + /eventemitter3@5.0.1: resolution: {integrity: sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==} dev: true @@ -1445,6 +2580,21 @@ packages: strip-final-newline: 3.0.0 dev: true + /execa@8.0.1: + resolution: {integrity: sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==} + engines: {node: '>=16.17'} + dependencies: + cross-spawn: 7.0.3 + get-stream: 8.0.1 + human-signals: 5.0.0 + is-stream: 3.0.0 + merge-stream: 2.0.0 + npm-run-path: 5.3.0 + onetime: 6.0.0 + signal-exit: 4.1.0 + strip-final-newline: 3.0.0 + dev: true + /fast-deep-equal@3.1.3: resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} dev: true @@ -1475,17 +2625,66 @@ packages: resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} dev: true + /fast-levenshtein@2.0.6: + resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} + dev: true + /fastq@1.15.0: resolution: {integrity: sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==} dependencies: reusify: 1.0.4 + /file-entry-cache@6.0.1: + resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==} + engines: {node: ^10.12.0 || >=12.0.0} + dependencies: + flat-cache: 3.2.0 + dev: true + /fill-range@7.0.1: resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} engines: {node: '>=8'} dependencies: to-regex-range: 5.0.1 + /find-up@4.1.0: + resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==} + engines: {node: '>=8'} + dependencies: + locate-path: 5.0.0 + path-exists: 4.0.0 + dev: true + + /find-up@5.0.0: + resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} + engines: {node: '>=10'} + dependencies: + locate-path: 6.0.0 + path-exists: 4.0.0 + dev: true + + /find-up@7.0.0: + resolution: {integrity: sha512-YyZM99iHrqLKjmt4LJDj58KI+fYyufRLBSYcqycxf//KpBk9FoewoGX0450m9nB44qrZnovzC2oeP5hUibxc/g==} + engines: {node: '>=18'} + dependencies: + locate-path: 7.2.0 + path-exists: 5.0.0 + unicorn-magic: 0.1.0 + dev: true + + /flat-cache@3.2.0: + resolution: {integrity: sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==} + engines: {node: ^10.12.0 || >=12.0.0} + dependencies: + flatted: 3.3.1 + keyv: 4.5.4 + rimraf: 3.0.2 + dev: true + + /flatted@3.3.1: + resolution: {integrity: sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==} + dev: true + /for-each@0.3.3: resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==} dependencies: @@ -1540,6 +2739,11 @@ packages: resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==} dev: false + /get-caller-file@2.0.5: + resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} + engines: {node: 6.* || 8.* || >= 10.*} + dev: true + /get-intrinsic@1.2.2: resolution: {integrity: sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA==} dependencies: @@ -1554,6 +2758,17 @@ packages: engines: {node: '>=10'} dev: true + /get-stream@8.0.1: + resolution: {integrity: sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==} + engines: {node: '>=16'} + dev: true + + /get-tsconfig@4.7.3: + resolution: {integrity: sha512-ZvkrzoUA0PQZM6fy6+/Hce561s+faD1rsNwhnO5FelNjyy7EMGJ3Rz1AQ8GYDWjhRs/7dBLOEJvhK8MiEJOAFg==} + dependencies: + resolve-pkg-maps: 1.0.0 + dev: true + /glob-parent@5.1.2: resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} engines: {node: '>= 6'} @@ -1587,7 +2802,6 @@ packages: minimatch: 3.1.2 once: 1.4.0 path-is-absolute: 1.0.1 - dev: false /glob@8.1.0: resolution: {integrity: sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==} @@ -1600,6 +2814,30 @@ packages: once: 1.4.0 dev: true + /globals@13.24.0: + resolution: {integrity: sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==} + engines: {node: '>=8'} + dependencies: + type-fest: 0.20.2 + dev: true + + /globals@14.0.0: + resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==} + engines: {node: '>=18'} + dev: true + + /globby@11.1.0: + resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==} + engines: {node: '>=10'} + dependencies: + array-union: 2.1.0 + dir-glob: 3.0.1 + fast-glob: 3.3.2 + ignore: 5.3.1 + merge2: 1.4.1 + slash: 3.0.0 + dev: true + /gopd@1.0.1: resolution: {integrity: sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==} dependencies: @@ -1610,10 +2848,24 @@ packages: resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} dev: true + /graphemer@1.4.0: + resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} + dev: true + /has-bigints@1.0.2: resolution: {integrity: sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==} dev: false + /has-flag@3.0.0: + resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==} + engines: {node: '>=4'} + dev: true + + /has-flag@4.0.0: + resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} + engines: {node: '>=8'} + dev: true + /has-property-descriptors@1.0.1: resolution: {integrity: sha512-VsX8eaIewvas0xnvinAe9bw4WfIeODpGYikiWYLH+dma0Jw6KHYqWiWfhQlgOVK8D6PvjubK5Uc4P0iIhIcNVg==} dependencies: @@ -1653,22 +2905,54 @@ packages: hasBin: true dev: true + /hosted-git-info@2.8.9: + resolution: {integrity: sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==} + dev: true + /human-signals@4.3.1: resolution: {integrity: sha512-nZXjEF2nbo7lIw3mgYjItAfgQXog3OjJogSbKa2CQIIvSGWcKgeJnQlNXip6NglNzYH45nSRiEVimMvYL8DDqQ==} engines: {node: '>=14.18.0'} dev: true + /human-signals@5.0.0: + resolution: {integrity: sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==} + engines: {node: '>=16.17.0'} + dev: true + /husky@8.0.3: resolution: {integrity: sha512-+dQSyqPh4x1hlO1swXBiNb2HzTDN1I2IGLQx1GrBuiqFJfoMrnZWwVmatvSiO+Iz8fBUnf+lekwNo4c2LlXItg==} engines: {node: '>=14'} hasBin: true dev: true + /ignore@5.3.1: + resolution: {integrity: sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==} + engines: {node: '>= 4'} + dev: true + + /import-fresh@3.3.0: + resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==} + engines: {node: '>=6'} + dependencies: + parent-module: 1.0.1 + resolve-from: 4.0.0 + dev: true + /import-lazy@4.0.0: resolution: {integrity: sha512-rKtvo6a868b5Hu3heneU+L4yEQ4jYKLtjpnPeUdK7h0yzXGmyBTypknlkCvHFBqfX9YlorEiMM6Dnq/5atfHkw==} engines: {node: '>=8'} dev: true + /imurmurhash@0.1.4: + resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} + engines: {node: '>=0.8.19'} + dev: true + + /indent-string@4.0.0: + resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==} + engines: {node: '>=8'} + dev: true + /inflight@1.0.6: resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} dependencies: @@ -1687,6 +2971,17 @@ packages: side-channel: 1.0.4 dev: false + /is-alphabetical@1.0.4: + resolution: {integrity: sha512-DwzsA04LQ10FHTZuL0/grVDk4rFoVH1pjAToYwBrHSxcrBIGQuXrQMtD5U1b0U2XVgKZCTLLP8u2Qxqhy3l2Vg==} + dev: true + + /is-alphanumerical@1.0.4: + resolution: {integrity: sha512-UzoZUr+XfVz3t3v4KyGEniVL9BDRoQtY7tOyrRybkVNjDFWyo1yhXNGrrBTQxp3ib9BLAWs7k2YKBQsFRkZG9A==} + dependencies: + is-alphabetical: 1.0.4 + is-decimal: 1.0.4 + dev: true + /is-arguments@1.1.1: resolution: {integrity: sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==} engines: {node: '>= 0.4'} @@ -1703,6 +2998,10 @@ packages: is-typed-array: 1.1.12 dev: false + /is-arrayish@0.2.1: + resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} + dev: true + /is-bigint@1.0.4: resolution: {integrity: sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==} dependencies: @@ -1747,6 +3046,10 @@ packages: has-tostringtag: 1.0.0 dev: false + /is-decimal@1.0.4: + resolution: {integrity: sha512-RGdriMmQQvZ2aqaQq3awNA6dCGtKpiDFcOzrTWrDAT2MiWrKQVPmxLGHl7Y2nNu6led0kEyoX0enY0qXYsv9zw==} + dev: true + /is-docker@3.0.0: resolution: {integrity: sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} @@ -1773,6 +3076,10 @@ packages: dependencies: is-extglob: 2.1.1 + /is-hexadecimal@1.0.4: + resolution: {integrity: sha512-gyPJuv83bHMpocVYoqof5VDiZveEoGoFL8m3BXNb2VW8Xs+rz9kqO8LOQ5DH6EsuvilT1ApazU0pyl+ytbPtlw==} + dev: true + /is-inside-container@1.0.0: resolution: {integrity: sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==} engines: {node: '>=14.16'} @@ -1800,6 +3107,11 @@ packages: resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} engines: {node: '>=0.12.0'} + /is-path-inside@3.0.3: + resolution: {integrity: sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==} + engines: {node: '>=8'} + dev: true + /is-promise@4.0.0: resolution: {integrity: sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==} @@ -1902,10 +3214,63 @@ packages: resolution: {integrity: sha512-8wb9Yw966OSxApiCt0K3yNJL8pnNeIv+OEq2YMidz4FKP6nonSRoOXc80iXY4JaN2FC11B9qsNmDsm+ZOfMROA==} dev: true + /js-tokens@4.0.0: + resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} + dev: true + + /js-yaml@4.1.0: + resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} + hasBin: true + dependencies: + argparse: 2.0.1 + dev: true + + /jsdoc-type-pratt-parser@4.0.0: + resolution: {integrity: sha512-YtOli5Cmzy3q4dP26GraSOeAhqecewG04hoO8DY56CH4KJ9Fvv5qKWUCCo3HZob7esJQHCv6/+bnTy72xZZaVQ==} + engines: {node: '>=12.0.0'} + dev: true + + /jsesc@0.5.0: + resolution: {integrity: sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==} + hasBin: true + dev: true + + /jsesc@3.0.2: + resolution: {integrity: sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==} + engines: {node: '>=6'} + hasBin: true + dev: true + + /json-buffer@3.0.1: + resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} + dev: true + + /json-parse-even-better-errors@2.3.1: + resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} + dev: true + /json-schema-traverse@0.4.1: resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} dev: true + /json-stable-stringify-without-jsonify@1.0.1: + resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} + dev: true + + /jsonc-eslint-parser@2.4.0: + resolution: {integrity: sha512-WYDyuc/uFcGp6YtM2H0uKmUwieOuzeE/5YocFJLnLfclZ4inf3mRn8ZVy1s7Hxji7Jxm6Ss8gqpexD/GlKoGgg==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dependencies: + acorn: 8.11.3 + eslint-visitor-keys: 3.4.3 + espree: 9.6.1 + semver: 7.6.0 + dev: true + + /jsonc-parser@3.2.1: + resolution: {integrity: sha512-AilxAyFOAcK5wA1+LeaySVBrHsGQvUFCDWXKpZjzaL0PqW+xfBOttn8GNtWKFWqneyMZj41MWF9Kl6iPWLwgOA==} + dev: true + /jsonfile@4.0.0: resolution: {integrity: sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==} optionalDependencies: @@ -1924,10 +3289,29 @@ packages: resolution: {integrity: sha512-nb4Ji1suqWqj6VXb61Jrs4ab/UWgtGph4wDch2NIZDfLBUObmLcZE0aiDjZY49ghtu03fvwxDNvS9ZB0XMz6/g==} dev: false + /keyv@4.5.4: + resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} + dependencies: + json-buffer: 3.0.1 + dev: true + + /kleur@3.0.3: + resolution: {integrity: sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==} + engines: {node: '>=6'} + dev: true + /kolorist@1.8.0: resolution: {integrity: sha512-Y+60/zizpJ3HRH8DCss+q95yr6145JXZo46OTpFvDZWLfRCE4qChOyk1b26nMaNpfHHgxagk9dXT5OP0Tfe+dQ==} dev: true + /levn@0.4.1: + resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} + engines: {node: '>= 0.8.0'} + dependencies: + prelude-ls: 1.2.1 + type-check: 0.4.0 + dev: true + /lilconfig@2.1.0: resolution: {integrity: sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==} engines: {node: '>=10'} @@ -1989,12 +3373,41 @@ packages: dependencies: '@types/trusted-types': 2.0.7 - /lit@3.1.0: - resolution: {integrity: sha512-rzo/hmUqX8zmOdamDAeydfjsGXbbdtAFqMhmocnh2j9aDYqbu0fjXygjCa0T99Od9VQ/2itwaGrjZz/ZELVl7w==} + /lit@3.1.0: + resolution: {integrity: sha512-rzo/hmUqX8zmOdamDAeydfjsGXbbdtAFqMhmocnh2j9aDYqbu0fjXygjCa0T99Od9VQ/2itwaGrjZz/ZELVl7w==} + dependencies: + '@lit/reactive-element': 2.0.2 + lit-element: 4.0.2 + lit-html: 3.1.0 + + /local-pkg@0.5.0: + resolution: {integrity: sha512-ok6z3qlYyCDS4ZEU27HaU6x/xZa9Whf8jD4ptH5UZTQYZVYeb9bnZ3ojVhiJNLiXK1Hfc0GNbLXcmZ5plLDDBg==} + engines: {node: '>=14'} + dependencies: + mlly: 1.6.1 + pkg-types: 1.0.3 + dev: true + + /locate-path@5.0.0: + resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==} + engines: {node: '>=8'} + dependencies: + p-locate: 4.1.0 + dev: true + + /locate-path@6.0.0: + resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} + engines: {node: '>=10'} + dependencies: + p-locate: 5.0.0 + dev: true + + /locate-path@7.2.0: + resolution: {integrity: sha512-gvVijfZvn7R+2qyPX8mAuKcFGDf6Nc61GdvGafQsHL0sBIxfKzA+usWn4GFC/bk+QdwPUD4kWFJLhElipq+0VA==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} dependencies: - '@lit/reactive-element': 2.0.2 - lit-element: 4.0.2 - lit-html: 3.1.0 + p-locate: 6.0.0 + dev: true /lodash.get@4.4.2: resolution: {integrity: sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==} @@ -2004,6 +3417,10 @@ packages: resolution: {integrity: sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==} dev: true + /lodash.merge@4.6.2: + resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} + dev: true + /lodash@4.17.21: resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} dev: true @@ -2045,6 +3462,22 @@ packages: '@jridgewell/sourcemap-codec': 1.4.15 dev: true + /mdast-util-from-markdown@0.8.5: + resolution: {integrity: sha512-2hkTXtYYnr+NubD/g6KGBS/0mFmBcifAsI0yIWRiRo0PjVs6SSOSOdtzbp6kSGnShDN6G5aWZpKQ2lWRy27mWQ==} + dependencies: + '@types/mdast': 3.0.15 + mdast-util-to-string: 2.0.0 + micromark: 2.11.4 + parse-entities: 2.0.0 + unist-util-stringify-position: 2.0.3 + transitivePeerDependencies: + - supports-color + dev: true + + /mdast-util-to-string@2.0.0: + resolution: {integrity: sha512-AW4DRS3QbBayY/jJmD8437V1Gombjf8RSOUCMFBuo5iHi58AGEgVCKQ+ezHkZZDpAQS75hcBMpLqjpJTjtUL7w==} + dev: true + /mdui@2.0.2: resolution: {integrity: sha512-n824kl2/kSO38j3jNQG62WXUYymgssMcOyeX/GkUjsPla7ohqX+rjPrg6pJfExAMZUjcMA3M5O0tDLQBm9nldA==} dependencies: @@ -2084,6 +3517,15 @@ packages: resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} engines: {node: '>= 8'} + /micromark@2.11.4: + resolution: {integrity: sha512-+WoovN/ppKolQOFIAajxi7Lu9kInbPxFuTBVEavFcL8eAfVstoc5MocPmqBeAdBOJV00uaVjegzH4+MA0DN/uA==} + dependencies: + debug: 4.3.4 + parse-entities: 2.0.0 + transitivePeerDependencies: + - supports-color + dev: true + /micromatch@4.0.5: resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==} engines: {node: '>=8.6'} @@ -2101,11 +3543,15 @@ packages: engines: {node: '>=12'} dev: true + /min-indent@1.0.1: + resolution: {integrity: sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==} + engines: {node: '>=4'} + dev: true + /minimatch@3.1.2: resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} dependencies: brace-expansion: 1.1.11 - dev: false /minimatch@5.1.6: resolution: {integrity: sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==} @@ -2126,17 +3572,21 @@ packages: engines: {node: '>=16 || 14 >=14.17'} dev: true + /mlly@1.6.1: + resolution: {integrity: sha512-vLgaHvaeunuOXHSmEbZ9izxPx3USsk8KCQ8iC+aTlp5sKRSoZvwhHh5L9VbKSaVC6sJDqbyohIS76E2VmHIPAA==} + dependencies: + acorn: 8.11.3 + pathe: 1.1.2 + pkg-types: 1.0.3 + ufo: 1.4.0 + dev: true + /modern-screenshot@4.4.38: resolution: {integrity: sha512-WeC3BuaJYjKvtXPSvSZRV5uvoJ4A1yrdb4mu1w5eLWkrONwD2mxYecRIJx3scf6/IwNl4zRh1SBrMibeJHMrYQ==} dev: false /monaco-editor@0.44.0: resolution: {integrity: sha512-5SmjNStN6bSuSE5WPT2ZV+iYn1/yI9sd4Igtk23ChvqB7kDk9lZbB9F5frsuvpB+2njdIeGGFf2G4gbE6rCC9Q==} - dev: false - - /monaco-editor@0.47.0: - resolution: {integrity: sha512-VabVvHvQ9QmMwXu4du008ZDuyLnHs9j7ThVFsiJoXSOQk18+LF89N4ADzPbFenm0W4V2bGHnFBztIRQTgBfxzw==} - dev: true /mrmime@2.0.0: resolution: {integrity: sha512-eu38+hdgojoyq63s+yTpN4XMBdt5l8HhMhc4VKLO9KM5caLIBvUm4thi7fFaxyTmCKeNnXZ5pAlBwCUnhA09uw==} @@ -2169,10 +3619,27 @@ packages: hasBin: true dev: true + /natural-compare-lite@1.4.0: + resolution: {integrity: sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==} + dev: true + + /natural-compare@1.4.0: + resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} + dev: true + /node-releases@2.0.14: resolution: {integrity: sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==} dev: true + /normalize-package-data@2.5.0: + resolution: {integrity: sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==} + dependencies: + hosted-git-info: 2.8.9 + resolve: 1.22.8 + semver: 5.7.2 + validate-npm-package-license: 3.0.4 + dev: true + /normalize-path@3.0.0: resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} engines: {node: '>=0.10.0'} @@ -2189,6 +3656,12 @@ packages: path-key: 4.0.0 dev: true + /nth-check@2.1.1: + resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==} + dependencies: + boolbase: 1.0.0 + dev: true + /object-assign@4.1.1: resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} engines: {node: '>=0.10.0'} @@ -2253,14 +3726,115 @@ packages: is-wsl: 3.1.0 dev: true + /optionator@0.9.3: + resolution: {integrity: sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==} + engines: {node: '>= 0.8.0'} + dependencies: + '@aashutoshrathi/word-wrap': 1.2.6 + deep-is: 0.1.4 + fast-levenshtein: 2.0.6 + levn: 0.4.1 + prelude-ls: 1.2.1 + type-check: 0.4.0 + dev: true + + /p-limit@2.3.0: + resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==} + engines: {node: '>=6'} + dependencies: + p-try: 2.2.0 + dev: true + + /p-limit@3.1.0: + resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} + engines: {node: '>=10'} + dependencies: + yocto-queue: 0.1.0 + dev: true + + /p-limit@4.0.0: + resolution: {integrity: sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dependencies: + yocto-queue: 1.0.0 + dev: true + + /p-locate@4.1.0: + resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==} + engines: {node: '>=8'} + dependencies: + p-limit: 2.3.0 + dev: true + + /p-locate@5.0.0: + resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} + engines: {node: '>=10'} + dependencies: + p-limit: 3.1.0 + dev: true + + /p-locate@6.0.0: + resolution: {integrity: sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dependencies: + p-limit: 4.0.0 + dev: true + + /p-try@2.2.0: + resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} + engines: {node: '>=6'} + dev: true + + /parent-module@1.0.1: + resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} + engines: {node: '>=6'} + dependencies: + callsites: 3.1.0 + dev: true + + /parse-entities@2.0.0: + resolution: {integrity: sha512-kkywGpCcRYhqQIchaWqZ875wzpS/bMKhz5HnN3p7wveJTkTtyAB/AlnS0f8DFSqYW1T82t6yEAkEcB+A1I3MbQ==} + dependencies: + character-entities: 1.2.4 + character-entities-legacy: 1.1.4 + character-reference-invalid: 1.1.4 + is-alphanumerical: 1.0.4 + is-decimal: 1.0.4 + is-hexadecimal: 1.0.4 + dev: true + + /parse-gitignore@2.0.0: + resolution: {integrity: sha512-RmVuCHWsfu0QPNW+mraxh/xjQVw/lhUCUru8Zni3Ctq3AoMhpDTq0OVdKS6iesd6Kqb7viCV3isAL43dciOSog==} + engines: {node: '>=14'} + dev: true + + /parse-json@5.2.0: + resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} + engines: {node: '>=8'} + dependencies: + '@babel/code-frame': 7.23.5 + error-ex: 1.3.2 + json-parse-even-better-errors: 2.3.1 + lines-and-columns: 1.2.4 + dev: true + /path-browserify@1.0.1: resolution: {integrity: sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==} dev: true + /path-exists@4.0.0: + resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} + engines: {node: '>=8'} + dev: true + + /path-exists@5.0.0: + resolution: {integrity: sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dev: true + /path-is-absolute@1.0.1: resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} engines: {node: '>=0.10.0'} - dev: false /path-key@3.1.1: resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} @@ -2283,6 +3857,15 @@ packages: minipass: 7.0.4 dev: true + /path-type@4.0.0: + resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} + engines: {node: '>=8'} + dev: true + + /pathe@1.1.2: + resolution: {integrity: sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==} + dev: true + /perfect-debounce@1.0.0: resolution: {integrity: sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA==} dev: true @@ -2294,6 +3877,11 @@ packages: resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} engines: {node: '>=8.6'} + /picomatch@4.0.1: + resolution: {integrity: sha512-xUXwsxNjwTQ8K3GnT4pCJm+xq3RUPQbmkYJTP5aFIfNIvbcc/4MUxgBaaRSZJ6yGJZiGSyYlM6MzwTsRk8SYCg==} + engines: {node: '>=12'} + dev: true + /pidtree@0.6.0: resolution: {integrity: sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==} engines: {node: '>=0.10'} @@ -2308,6 +3896,19 @@ packages: resolution: {integrity: sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==} engines: {node: '>= 6'} + /pkg-types@1.0.3: + resolution: {integrity: sha512-nN7pYi0AQqJnoLPC9eHFQ8AcyaixBUOwvqc5TDnIKCMEE6I0y8P7OKA7fPexsXGCGxQDl/cmrLAp26LhcwxZ4A==} + dependencies: + jsonc-parser: 3.2.1 + mlly: 1.6.1 + pathe: 1.1.2 + dev: true + + /pluralize@8.0.0: + resolution: {integrity: sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==} + engines: {node: '>=4'} + dev: true + /postcss-import@15.1.0(postcss@8.4.31): resolution: {integrity: sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==} engines: {node: '>=14.0.0'} @@ -2441,10 +4042,24 @@ packages: source-map-js: 1.0.2 dev: true + /prelude-ls@1.2.1: + resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} + engines: {node: '>= 0.8.0'} + dev: true + /prettier@3.0.0: resolution: {integrity: sha512-zBf5eHpwHOGPC47h0zrPyNn+eAEIdEzfywMoYn2XPi0P44Zp0tSq64rq0xAREh4auw2cJZHo9QUob+NqCQky4g==} engines: {node: '>=14'} hasBin: true + dev: false + + /prompts@2.4.2: + resolution: {integrity: sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==} + engines: {node: '>= 6'} + dependencies: + kleur: 3.0.3 + sisteransi: 1.0.5 + dev: true /punycode@2.3.1: resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} @@ -2459,6 +4074,25 @@ packages: dependencies: pify: 2.3.0 + /read-pkg-up@7.0.1: + resolution: {integrity: sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==} + engines: {node: '>=8'} + dependencies: + find-up: 4.1.0 + read-pkg: 5.2.0 + type-fest: 0.8.1 + dev: true + + /read-pkg@5.2.0: + resolution: {integrity: sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==} + engines: {node: '>=8'} + dependencies: + '@types/normalize-package-data': 2.4.4 + normalize-package-data: 2.5.0 + parse-json: 5.2.0 + type-fest: 0.6.0 + dev: true + /readdirp@3.6.0: resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} engines: {node: '>=8.10.0'} @@ -2473,6 +4107,11 @@ packages: resolution: {integrity: sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==} dev: false + /regexp-tree@0.1.27: + resolution: {integrity: sha512-iETxpjK6YoRWJG5o6hXLwvjYAoW+FEZn9os0PD/b6AP6xQwsa/Y7lCVgIixBbUPMfhu+i2LtdeAqVTgGlQarfA==} + hasBin: true + dev: true + /regexp.prototype.flags@1.5.1: resolution: {integrity: sha512-sy6TXMN+hnP/wMy+ISxg3krXx7BAtWVO4UouuCN/ziM9UEne0euamVNafDfvC83bRNr95y0V5iijeDQFUNpvrg==} engines: {node: '>= 0.4'} @@ -2482,6 +4121,27 @@ packages: set-function-name: 2.0.1 dev: false + /regjsparser@0.10.0: + resolution: {integrity: sha512-qx+xQGZVsy55CH0a1hiVwHmqjLryfh7wQyF5HO07XJ9f7dQMY/gPQHhlyDkIzJKC+x2fUCpCcUODUUUFrm7SHA==} + hasBin: true + dependencies: + jsesc: 0.5.0 + dev: true + + /require-directory@2.1.1: + resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} + engines: {node: '>=0.10.0'} + dev: true + + /resolve-from@4.0.0: + resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} + engines: {node: '>=4'} + dev: true + + /resolve-pkg-maps@1.0.0: + resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==} + dev: true + /resolve@1.19.0: resolution: {integrity: sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg==} dependencies: @@ -2513,6 +4173,13 @@ packages: resolution: {integrity: sha512-r5a3l5HzYlIC68TpmYKlxWjmOP6wiPJ1vWv2HeLhNsRZMrCkxeqxiHlQ21oXmQ4F3SiryXBHhAD7JZqvOJjFmg==} dev: true + /rimraf@3.0.2: + resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} + hasBin: true + dependencies: + glob: 7.1.6 + dev: true + /rollup@3.29.4: resolution: {integrity: sha512-oWzmBZwvYrU0iJHtDmhsm662rC15FRXmcjCk1xD771dFDx5jJ02ufAQQTn0etB2emNk4J9EZg/yWKpsn9BWGRw==} engines: {node: '>=14.18.0', npm: '>=8.0.0'} @@ -2537,6 +4204,11 @@ packages: dependencies: queue-microtask: 1.2.3 + /semver@5.7.2: + resolution: {integrity: sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==} + hasBin: true + dev: true + /semver@7.5.4: resolution: {integrity: sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==} engines: {node: '>=10'} @@ -2601,6 +4273,12 @@ packages: engines: {node: '>=14'} dev: true + /simple-git-hooks@2.10.0: + resolution: {integrity: sha512-TtCytVYfV77pILCkzVxpOSgYKHQyaO7fBI/iwG5bLGb0dIo/v/K1Y1IZ5DN40RQu6WNNJiN0gkuRvSYjxOhFog==} + hasBin: true + requiresBuild: true + dev: true + /sirv@2.0.4: resolution: {integrity: sha512-94Bdh3cC2PKrbgSOUqTiGPWVZeSiXfKOVZNJniWoqrWrRkB1CJzBU3NEbiTsPcYy1lDsANA/THzS+9WBiy5nfQ==} engines: {node: '>= 10'} @@ -2610,6 +4288,15 @@ packages: totalist: 3.0.1 dev: true + /sisteransi@1.0.5: + resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==} + dev: true + + /slash@3.0.0: + resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} + engines: {node: '>=8'} + dev: true + /slice-ansi@5.0.0: resolution: {integrity: sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==} engines: {node: '>=12'} @@ -2627,6 +4314,35 @@ packages: engines: {node: '>=0.10.0'} dev: true + /spdx-correct@3.2.0: + resolution: {integrity: sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==} + dependencies: + spdx-expression-parse: 3.0.1 + spdx-license-ids: 3.0.17 + dev: true + + /spdx-exceptions@2.5.0: + resolution: {integrity: sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==} + dev: true + + /spdx-expression-parse@3.0.1: + resolution: {integrity: sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==} + dependencies: + spdx-exceptions: 2.5.0 + spdx-license-ids: 3.0.17 + dev: true + + /spdx-expression-parse@4.0.0: + resolution: {integrity: sha512-Clya5JIij/7C6bRR22+tnGXbc4VKlibKSVj2iHvVeX5iMW7s1SIQlqu699JkODJJIhh/pUu8L0/VLh8xflD+LQ==} + dependencies: + spdx-exceptions: 2.5.0 + spdx-license-ids: 3.0.17 + dev: true + + /spdx-license-ids@3.0.17: + resolution: {integrity: sha512-sh8PWc/ftMqAAdFiBu6Fy6JUOYjqDJBJvIhpfDMyHrr0Rbp5liZqd4TjtQ/RgfLjKFZb+LMx5hpml5qOWy0qvg==} + dev: true + /sprintf-js@1.0.3: resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} dev: true @@ -2683,6 +4399,13 @@ packages: engines: {node: '>=12'} dev: true + /strip-indent@3.0.0: + resolution: {integrity: sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==} + engines: {node: '>=8'} + dependencies: + min-indent: 1.0.1 + dev: true + /strip-json-comments@3.1.1: resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} engines: {node: '>=8'} @@ -2720,10 +4443,31 @@ packages: ts-interface-checker: 0.1.13 dev: true + /supports-color@5.5.0: + resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} + engines: {node: '>=4'} + dependencies: + has-flag: 3.0.0 + dev: true + + /supports-color@7.2.0: + resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} + engines: {node: '>=8'} + dependencies: + has-flag: 4.0.0 + dev: true + /supports-preserve-symlinks-flag@1.0.0: resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} engines: {node: '>= 0.4'} + /synckit@0.6.2: + resolution: {integrity: sha512-Vhf+bUa//YSTYKseDiiEuQmhGCoIF3CVBhunm3r/DQnYiGT4JssmnKQc44BIyOZRK2pKjXXAgbhfmbeoC9CJpA==} + engines: {node: '>=12.20'} + dependencies: + tslib: 2.6.2 + dev: true + /tailwindcss@3.3.5: resolution: {integrity: sha512-5SEZU4J7pxZgSkv7FP1zY8i2TIAOooNZ1e/OGtxIEv6GltpoiXUqWvLy89+a10qYTB1N5Ifkuw9lqQkN9sscvA==} engines: {node: '>=14.0.0'} @@ -2786,6 +4530,10 @@ packages: - ts-node dev: true + /text-table@0.2.0: + resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} + dev: true + /thenify-all@1.6.0: resolution: {integrity: sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==} engines: {node: '>=0.8'} @@ -2808,17 +4556,55 @@ packages: dependencies: is-number: 7.0.0 + /toml-eslint-parser@0.9.3: + resolution: {integrity: sha512-moYoCvkNUAPCxSW9jmHmRElhm4tVJpHL8ItC/+uYD0EpPSFXbck7yREz9tNdJVTSpHVod8+HoipcpbQ0oE6gsw==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dependencies: + eslint-visitor-keys: 3.4.3 + dev: true + /totalist@3.0.1: resolution: {integrity: sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==} engines: {node: '>=6'} dev: true + /ts-api-utils@1.3.0(typescript@5.4.2): + resolution: {integrity: sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==} + engines: {node: '>=16'} + peerDependencies: + typescript: '>=4.2.0' + dependencies: + typescript: 5.4.2 + dev: true + /ts-interface-checker@0.1.13: resolution: {integrity: sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==} /tslib@2.6.2: resolution: {integrity: sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==} + /type-check@0.4.0: + resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} + engines: {node: '>= 0.8.0'} + dependencies: + prelude-ls: 1.2.1 + dev: true + + /type-fest@0.20.2: + resolution: {integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==} + engines: {node: '>=10'} + dev: true + + /type-fest@0.6.0: + resolution: {integrity: sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==} + engines: {node: '>=8'} + dev: true + + /type-fest@0.8.1: + resolution: {integrity: sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==} + engines: {node: '>=8'} + dev: true + /type-fest@1.4.0: resolution: {integrity: sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==} engines: {node: '>=10'} @@ -2842,6 +4628,21 @@ packages: hasBin: true dev: true + /ufo@1.4.0: + resolution: {integrity: sha512-Hhy+BhRBleFjpJ2vchUNN40qgkh0366FWJGqVLYBHev0vpHTrXSA0ryT+74UiW6KWsldNurQMKGqCm1M2zBciQ==} + dev: true + + /unicorn-magic@0.1.0: + resolution: {integrity: sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ==} + engines: {node: '>=18'} + dev: true + + /unist-util-stringify-position@2.0.3: + resolution: {integrity: sha512-3faScn5I+hy9VleOq/qNbAd6pAx7iH5jYBMS9I1HgQVijz/4mv5Bvw5iw1sC/90CODiKo81G/ps8AJrISn687g==} + dependencies: + '@types/unist': 2.0.10 + dev: true + /universalify@0.1.2: resolution: {integrity: sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==} engines: {node: '>= 4.0.0'} @@ -2872,6 +4673,13 @@ packages: /util-deprecate@1.0.2: resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} + /validate-npm-package-license@3.0.4: + resolution: {integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==} + dependencies: + spdx-correct: 3.2.0 + spdx-expression-parse: 3.0.1 + dev: true + /validator@13.11.0: resolution: {integrity: sha512-Ii+sehpSfZy+At5nPdnyMhx78fEoPDkR2XW/zimHEL3MyGJQOCQ7WeP20jPYRz7ZCpcKLB21NxuXHF3bxjStBQ==} engines: {node: '>= 0.10'} @@ -2926,12 +4734,12 @@ packages: - supports-color dev: true - /vite-plugin-monaco-editor@1.1.0(monaco-editor@0.47.0): + /vite-plugin-monaco-editor@1.1.0(monaco-editor@0.44.0): resolution: {integrity: sha512-IvtUqZotrRoVqwT0PBBDIZPNraya3BxN/bfcNfnxZ5rkJiGcNtO5eAOWWSgT7zullIAEqQwxMU83yL9J5k7gww==} peerDependencies: monaco-editor: '>=0.33.0' dependencies: - monaco-editor: 0.47.0 + monaco-editor: 0.44.0 dev: true /vite-plugin-refina@0.6.0(typescript@5.4.2)(vite@4.5.2): @@ -3034,6 +4842,24 @@ packages: fsevents: 2.3.3 dev: true + /vue-eslint-parser@9.4.2(eslint@8.57.0): + resolution: {integrity: sha512-Ry9oiGmCAK91HrKMtCrKFWmSFWvYkpGglCeFAIqDdr9zdXmMMpJOmUJS7WWsW7fX81h6mwHmUZCQQ1E0PkSwYQ==} + engines: {node: ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: '>=6.0.0' + dependencies: + debug: 4.3.4 + eslint: 8.57.0 + eslint-scope: 7.2.2 + eslint-visitor-keys: 3.4.3 + espree: 9.6.1 + esquery: 1.5.0 + lodash: 4.17.21 + semver: 7.6.0 + transitivePeerDependencies: + - supports-color + dev: true + /vue-template-compiler@2.7.16: resolution: {integrity: sha512-AYbUWAJHLGGQM7+cNTELw+KsOG9nl2CnSv467WobS5Cv9uk3wFcnr1Etsz2sEIHEZvw1U+o9mRlEO6QbZvUPGQ==} dependencies: @@ -3112,10 +4938,29 @@ packages: /wrappy@1.0.2: resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} + /xml-name-validator@4.0.0: + resolution: {integrity: sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==} + engines: {node: '>=12'} + dev: true + + /y18n@5.0.8: + resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} + engines: {node: '>=10'} + dev: true + /yallist@4.0.0: resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} dev: true + /yaml-eslint-parser@1.2.2: + resolution: {integrity: sha512-pEwzfsKbTrB8G3xc/sN7aw1v6A6c/pKxLAkjclnAyo5g5qOh6eL9WGu0o3cSDQZKrTNk4KL4lQSwZW+nBkANEg==} + engines: {node: ^14.17.0 || >=16.0.0} + dependencies: + eslint-visitor-keys: 3.4.3 + lodash: 4.17.21 + yaml: 2.4.1 + dev: true + /yaml@2.3.1: resolution: {integrity: sha512-2eHWfjaoXgTBC2jNM1LRef62VQa0umtvRiDSk6HSzW7RvS5YtkabJrwYLLEKWBc8a5U2PTSCs+dJjUTJdlHsWQ==} engines: {node: '>= 14'} @@ -3126,6 +4971,34 @@ packages: hasBin: true dev: true + /yargs-parser@21.1.1: + resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} + engines: {node: '>=12'} + dev: true + + /yargs@17.7.2: + resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} + engines: {node: '>=12'} + dependencies: + cliui: 8.0.1 + escalade: 3.1.2 + get-caller-file: 2.0.5 + require-directory: 2.1.1 + string-width: 4.2.3 + y18n: 5.0.8 + yargs-parser: 21.1.1 + dev: true + + /yocto-queue@0.1.0: + resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} + engines: {node: '>=10'} + dev: true + + /yocto-queue@1.0.0: + resolution: {integrity: sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==} + engines: {node: '>=12.20'} + dev: true + /z-schema@5.0.5: resolution: {integrity: sha512-D7eujBWkLa3p2sIpJA0d1pr7es+a7m0vFAnZLlCEKq/Ij2k0MLi9Br2UPxoxdYystm5K1yeBGzub0FlYUEWj2Q==} engines: {node: '>=8.0.0'} diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 9c9be4b..600b4bb 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -1,2 +1,2 @@ packages: - - "packages/**" + - 'packages/**'