Compare commits
12 Commits
4d5dc38d27
...
d6fec531b2
| Author | SHA1 | Date | |
|---|---|---|---|
|
d6fec531b2
|
|||
|
f491268c62
|
|||
|
a33a405a07
|
|||
|
e2fe240877
|
|||
|
b3e1b67515
|
|||
|
1a529e4139
|
|||
|
9d1d5b10d6
|
|||
|
51dc1ed377
|
|||
|
7fdd2b2465
|
|||
|
23be95d533
|
|||
|
eaba5aa372
|
|||
|
46b6e9f969
|
228
package-lock.json
generated
228
package-lock.json
generated
@@ -33,6 +33,7 @@
|
|||||||
"@types/react-dom": "^18.3.1",
|
"@types/react-dom": "^18.3.1",
|
||||||
"@typescript/ata": "^0.9.7",
|
"@typescript/ata": "^0.9.7",
|
||||||
"@vitejs/plugin-react": "^4.3.3",
|
"@vitejs/plugin-react": "^4.3.3",
|
||||||
|
"@xyflow/react": "^12.3.2",
|
||||||
"antd": "^5.21.6",
|
"antd": "^5.21.6",
|
||||||
"antd-style": "^3.7.1",
|
"antd-style": "^3.7.1",
|
||||||
"axios": "^1.7.7",
|
"axios": "^1.7.7",
|
||||||
@@ -3288,6 +3289,55 @@
|
|||||||
"@types/responselike": "^1.0.0"
|
"@types/responselike": "^1.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/d3-color": {
|
||||||
|
"version": "3.1.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/d3-color/-/d3-color-3.1.3.tgz",
|
||||||
|
"integrity": "sha512-iO90scth9WAbmgv7ogoq57O9YpKmFBbmoEoCHDB2xMBY0+/KVrqAaCDyCE16dUspeOvIxFFRI+0sEtqDqy2b4A==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"node_modules/@types/d3-drag": {
|
||||||
|
"version": "3.0.7",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/d3-drag/-/d3-drag-3.0.7.tgz",
|
||||||
|
"integrity": "sha512-HE3jVKlzU9AaMazNufooRJ5ZpWmLIoc90A37WU2JMmeq28w1FQqCZswHZ3xR+SuxYftzHq6WU6KJHvqxKzTxxQ==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@types/d3-selection": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@types/d3-interpolate": {
|
||||||
|
"version": "3.0.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/d3-interpolate/-/d3-interpolate-3.0.4.tgz",
|
||||||
|
"integrity": "sha512-mgLPETlrpVV1YRJIglr4Ez47g7Yxjl1lj7YKsiMCb27VJH9W8NVM6Bb9d8kkpG/uAQS5AmbA48q2IAolKKo1MA==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@types/d3-color": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@types/d3-selection": {
|
||||||
|
"version": "3.0.11",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/d3-selection/-/d3-selection-3.0.11.tgz",
|
||||||
|
"integrity": "sha512-bhAXu23DJWsrI45xafYpkQ4NtcKMwWnAC/vKrd2l+nxMFuvOT3XMYTIj2opv8vq8AO5Yh7Qac/nSeP/3zjTK0w==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"node_modules/@types/d3-transition": {
|
||||||
|
"version": "3.0.9",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/d3-transition/-/d3-transition-3.0.9.tgz",
|
||||||
|
"integrity": "sha512-uZS5shfxzO3rGlu0cC3bjmMFKsXv+SmZZcgp0KD22ts4uGXp5EVYGzu/0YdwZeKmddhcAccYtREJKkPfXkZuCg==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@types/d3-selection": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@types/d3-zoom": {
|
||||||
|
"version": "3.0.8",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/d3-zoom/-/d3-zoom-3.0.8.tgz",
|
||||||
|
"integrity": "sha512-iqMC4/YlFCSlO8+2Ii1GGGliCAY4XdeG748w5vQUbevlbDu0zSjH/+jojorQVBK/se0j6DUFNPBGSqD3YWYnDw==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@types/d3-interpolate": "*",
|
||||||
|
"@types/d3-selection": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@types/debug": {
|
"node_modules/@types/debug": {
|
||||||
"version": "4.1.12",
|
"version": "4.1.12",
|
||||||
"resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz",
|
"resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz",
|
||||||
@@ -3736,6 +3786,36 @@
|
|||||||
"node": ">=10.0.0"
|
"node": ">=10.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@xyflow/react": {
|
||||||
|
"version": "12.3.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@xyflow/react/-/react-12.3.3.tgz",
|
||||||
|
"integrity": "sha512-hKwnY68fijc393/KCCCyJUi+vESPnY0Vht0Brbny8feMpp/iHtTNGbpwzQtSDmbvvnnIwIAWrxPZPgiUQmK8Kw==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@xyflow/system": "0.0.44",
|
||||||
|
"classcat": "^5.0.3",
|
||||||
|
"zustand": "^4.4.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"react": ">=17",
|
||||||
|
"react-dom": ">=17"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@xyflow/system": {
|
||||||
|
"version": "0.0.44",
|
||||||
|
"resolved": "https://registry.npmjs.org/@xyflow/system/-/system-0.0.44.tgz",
|
||||||
|
"integrity": "sha512-hKHtH8hUVKmCCXbTdEYUWNqRkcSBwYxdzZhIxpJst60AEnlobfphNu8eAOJArEJJl+MrjidvY5K/BOzYUcwCug==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@types/d3-drag": "^3.0.7",
|
||||||
|
"@types/d3-selection": "^3.0.10",
|
||||||
|
"@types/d3-transition": "^3.0.8",
|
||||||
|
"@types/d3-zoom": "^3.0.8",
|
||||||
|
"d3-drag": "^3.0.0",
|
||||||
|
"d3-selection": "^3.0.0",
|
||||||
|
"d3-zoom": "^3.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/7zip-bin": {
|
"node_modules/7zip-bin": {
|
||||||
"version": "5.2.0",
|
"version": "5.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/7zip-bin/-/7zip-bin-5.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/7zip-bin/-/7zip-bin-5.2.0.tgz",
|
||||||
@@ -4764,6 +4844,12 @@
|
|||||||
"node": ">=8"
|
"node": ">=8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/classcat": {
|
||||||
|
"version": "5.0.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/classcat/-/classcat-5.0.5.tgz",
|
||||||
|
"integrity": "sha512-JhZUT7JFcQy/EzW605k/ktHtncoo9vnyW/2GspNYwFlN1C/WmjuV/xtS04e9SOkL2sTdw0VAZ2UGCcQ9lR6p6w==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"node_modules/classnames": {
|
"node_modules/classnames": {
|
||||||
"version": "2.5.1",
|
"version": "2.5.1",
|
||||||
"resolved": "https://registry.npmjs.org/classnames/-/classnames-2.5.1.tgz",
|
"resolved": "https://registry.npmjs.org/classnames/-/classnames-2.5.1.tgz",
|
||||||
@@ -5242,6 +5328,111 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/d3-color": {
|
||||||
|
"version": "3.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/d3-color/-/d3-color-3.1.0.tgz",
|
||||||
|
"integrity": "sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==",
|
||||||
|
"dev": true,
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/d3-dispatch": {
|
||||||
|
"version": "3.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-3.0.1.tgz",
|
||||||
|
"integrity": "sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg==",
|
||||||
|
"dev": true,
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/d3-drag": {
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/d3-drag/-/d3-drag-3.0.0.tgz",
|
||||||
|
"integrity": "sha512-pWbUJLdETVA8lQNJecMxoXfH6x+mO2UQo8rSmZ+QqxcbyA3hfeprFgIT//HW2nlHChWeIIMwS2Fq+gEARkhTkg==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"d3-dispatch": "1 - 3",
|
||||||
|
"d3-selection": "3"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/d3-ease": {
|
||||||
|
"version": "3.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-3.0.1.tgz",
|
||||||
|
"integrity": "sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==",
|
||||||
|
"dev": true,
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/d3-interpolate": {
|
||||||
|
"version": "3.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-3.0.1.tgz",
|
||||||
|
"integrity": "sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"d3-color": "1 - 3"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/d3-selection": {
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-3.0.0.tgz",
|
||||||
|
"integrity": "sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==",
|
||||||
|
"dev": true,
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/d3-timer": {
|
||||||
|
"version": "3.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-3.0.1.tgz",
|
||||||
|
"integrity": "sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==",
|
||||||
|
"dev": true,
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/d3-transition": {
|
||||||
|
"version": "3.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/d3-transition/-/d3-transition-3.0.1.tgz",
|
||||||
|
"integrity": "sha512-ApKvfjsSR6tg06xrL434C0WydLr7JewBB3V+/39RMHsaXTOG0zmt/OAXeng5M5LBm0ojmxJrpomQVZ1aPvBL4w==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"d3-color": "1 - 3",
|
||||||
|
"d3-dispatch": "1 - 3",
|
||||||
|
"d3-ease": "1 - 3",
|
||||||
|
"d3-interpolate": "1 - 3",
|
||||||
|
"d3-timer": "1 - 3"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"d3-selection": "2 - 3"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/d3-zoom": {
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/d3-zoom/-/d3-zoom-3.0.0.tgz",
|
||||||
|
"integrity": "sha512-b8AmV3kfQaqWAuacbPuNbL6vahnOJflOhexLzMMNLga62+/nh0JzvJ0aO/5a5MVgUFGS7Hu1P9P03o3fJkDCyw==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"d3-dispatch": "1 - 3",
|
||||||
|
"d3-drag": "2 - 3",
|
||||||
|
"d3-interpolate": "1 - 3",
|
||||||
|
"d3-selection": "2 - 3",
|
||||||
|
"d3-transition": "2 - 3"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/data-urls": {
|
"node_modules/data-urls": {
|
||||||
"version": "5.0.0",
|
"version": "5.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/data-urls/-/data-urls-5.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/data-urls/-/data-urls-5.0.0.tgz",
|
||||||
@@ -11596,6 +11787,15 @@
|
|||||||
"react": ">= 16.x"
|
"react": ">= 16.x"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/use-sync-external-store": {
|
||||||
|
"version": "1.2.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.2.tgz",
|
||||||
|
"integrity": "sha512-PElTlVMwpblvbNqQ82d2n6RjStvdSoNe9FG28kNfz3WiXilJm4DdNkEzRhCZuIDwY8U08WVihhGR5iRqAwfDiw==",
|
||||||
|
"dev": true,
|
||||||
|
"peerDependencies": {
|
||||||
|
"react": "^16.8.0 || ^17.0.0 || ^18.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/utf8-byte-length": {
|
"node_modules/utf8-byte-length": {
|
||||||
"version": "1.0.5",
|
"version": "1.0.5",
|
||||||
"resolved": "https://registry.npmjs.org/utf8-byte-length/-/utf8-byte-length-1.0.5.tgz",
|
"resolved": "https://registry.npmjs.org/utf8-byte-length/-/utf8-byte-length-1.0.5.tgz",
|
||||||
@@ -12055,6 +12255,34 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "0BSD"
|
"license": "0BSD"
|
||||||
},
|
},
|
||||||
|
"node_modules/zustand": {
|
||||||
|
"version": "4.5.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/zustand/-/zustand-4.5.5.tgz",
|
||||||
|
"integrity": "sha512-+0PALYNJNgK6hldkgDq2vLrw5f6g/jCInz52n9RTpropGgeAf/ioFUCdtsjCqu4gNhW9D01rUQBROoRjdzyn2Q==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"use-sync-external-store": "1.2.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12.7.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@types/react": ">=16.8",
|
||||||
|
"immer": ">=9.0.6",
|
||||||
|
"react": ">=16.8"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"@types/react": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"immer": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"react": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/zwitch": {
|
"node_modules/zwitch": {
|
||||||
"version": "2.0.4",
|
"version": "2.0.4",
|
||||||
"resolved": "https://registry.npmjs.org/zwitch/-/zwitch-2.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/zwitch/-/zwitch-2.0.4.tgz",
|
||||||
|
|||||||
@@ -54,6 +54,7 @@
|
|||||||
"@types/react-dom": "^18.3.1",
|
"@types/react-dom": "^18.3.1",
|
||||||
"@typescript/ata": "^0.9.7",
|
"@typescript/ata": "^0.9.7",
|
||||||
"@vitejs/plugin-react": "^4.3.3",
|
"@vitejs/plugin-react": "^4.3.3",
|
||||||
|
"@xyflow/react": "^12.3.2",
|
||||||
"antd": "^5.21.6",
|
"antd": "^5.21.6",
|
||||||
"antd-style": "^3.7.1",
|
"antd-style": "^3.7.1",
|
||||||
"axios": "^1.7.7",
|
"axios": "^1.7.7",
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import { electronApp, optimizer, is } from '@electron-toolkit/utils'
|
|||||||
import icon from '../../build/icon.ico?asset'
|
import icon from '../../build/icon.ico?asset'
|
||||||
import path from 'node:path'
|
import path from 'node:path'
|
||||||
import url from 'node:url'
|
import url from 'node:url'
|
||||||
|
import fs from 'fs'
|
||||||
|
|
||||||
let mainWindow: BrowserWindow
|
let mainWindow: BrowserWindow
|
||||||
|
|
||||||
@@ -105,8 +106,19 @@ void app.whenReady().then(() => {
|
|||||||
protocol.handle('local', (request) => {
|
protocol.handle('local', (request) => {
|
||||||
const { host } = new URL(request.url)
|
const { host } = new URL(request.url)
|
||||||
if (host === 'oxygen.fatweb.top') {
|
if (host === 'oxygen.fatweb.top') {
|
||||||
const filePath = request.url.slice('local://oxygen.fatweb.top/'.length)
|
let filePath = request.url.slice('local://oxygen.fatweb.top/'.length)
|
||||||
return net.fetch(url.pathToFileURL(filePath).toString())
|
if (fs.existsSync(filePath)) {
|
||||||
|
return net.fetch(url.pathToFileURL(filePath).toString())
|
||||||
|
}
|
||||||
|
|
||||||
|
filePath = join(join(__dirname, '../renderer'), filePath)
|
||||||
|
if (fs.existsSync(filePath)) {
|
||||||
|
return net.fetch(url.pathToFileURL(filePath).toString())
|
||||||
|
}
|
||||||
|
|
||||||
|
return net.fetch(
|
||||||
|
url.pathToFileURL(join(__dirname, '../renderer/index.html')).toString()
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
const filePath = request.url.slice('local://'.length)
|
const filePath = request.url.slice('local://'.length)
|
||||||
return net.fetch(url.pathToFileURL(filePath).toString())
|
return net.fetch(url.pathToFileURL(filePath).toString())
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ interface EditorProps {
|
|||||||
options?: IEditorOptions
|
options?: IEditorOptions
|
||||||
onJumpFile?: (fileName: string) => void
|
onJumpFile?: (fileName: string) => void
|
||||||
extraLibs?: ExtraLib[]
|
extraLibs?: ExtraLib[]
|
||||||
|
onEditorDidMount?: (editor: editor.IStandaloneCodeEditor, monaco: Monaco) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
const Editor = ({
|
const Editor = ({
|
||||||
@@ -35,7 +36,8 @@ const Editor = ({
|
|||||||
onChange,
|
onChange,
|
||||||
options,
|
options,
|
||||||
onJumpFile,
|
onJumpFile,
|
||||||
extraLibs = []
|
extraLibs = [],
|
||||||
|
onEditorDidMount
|
||||||
}: EditorProps) => {
|
}: EditorProps) => {
|
||||||
const { styles } = useStyles()
|
const { styles } = useStyles()
|
||||||
const editorRef = useRef<editor.IStandaloneCodeEditor>()
|
const editorRef = useRef<editor.IStandaloneCodeEditor>()
|
||||||
@@ -96,6 +98,8 @@ const Editor = ({
|
|||||||
monaco.languages.typescript.typescriptDefaults.addExtraLib(item.content, item.path)
|
monaco.languages.typescript.typescriptDefaults.addExtraLib(item.content, item.path)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
onEditorDidMount?.(editor, monaco)
|
||||||
|
|
||||||
void autoLoadExtraLib(editor, monaco, file.value, onWatch)
|
void autoLoadExtraLib(editor, monaco, file.value, onWatch)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ import { createStyles } from 'antd-style'
|
|||||||
export default createStyles(({ token }) => ({
|
export default createStyles(({ token }) => ({
|
||||||
root: {
|
root: {
|
||||||
position: 'relative',
|
position: 'relative',
|
||||||
width: '100%',
|
|
||||||
height: '100%'
|
height: '100%'
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import { Monaco } from '@monaco-editor/react'
|
||||||
|
import { editor } from 'monaco-editor'
|
||||||
import _ from 'lodash'
|
import _ from 'lodash'
|
||||||
import useStyles from '@/components/Playground/CodeEditor/index.style'
|
import useStyles from '@/components/Playground/CodeEditor/index.style'
|
||||||
import FlexBox from '@/components/common/FlexBox'
|
import FlexBox from '@/components/common/FlexBox'
|
||||||
@@ -22,6 +24,7 @@ interface CodeEditorProps {
|
|||||||
selectedFileName?: string
|
selectedFileName?: string
|
||||||
options?: IEditorOptions
|
options?: IEditorOptions
|
||||||
extraLibs?: ExtraLib[]
|
extraLibs?: ExtraLib[]
|
||||||
|
onEditorDidMount?: (editor: editor.IStandaloneCodeEditor, monaco: Monaco) => void
|
||||||
onSelectedFileChange?: (fileName: string) => void
|
onSelectedFileChange?: (fileName: string) => void
|
||||||
onAddFile?: (fileName: string, files: IFiles) => void
|
onAddFile?: (fileName: string, files: IFiles) => void
|
||||||
onRemoveFile?: (fileName: string, files: IFiles) => void
|
onRemoveFile?: (fileName: string, files: IFiles) => void
|
||||||
@@ -46,6 +49,7 @@ const CodeEditor = ({
|
|||||||
onChangeFileContent,
|
onChangeFileContent,
|
||||||
onError,
|
onError,
|
||||||
extraLibs,
|
extraLibs,
|
||||||
|
onEditorDidMount,
|
||||||
...props
|
...props
|
||||||
}: CodeEditorProps) => {
|
}: CodeEditorProps) => {
|
||||||
const { styles } = useStyles()
|
const { styles } = useStyles()
|
||||||
@@ -157,6 +161,7 @@ const CodeEditor = ({
|
|||||||
onChange={handleOnChangeFileContent}
|
onChange={handleOnChangeFileContent}
|
||||||
onJumpFile={handleOnChangeSelectedFile}
|
onJumpFile={handleOnChangeSelectedFile}
|
||||||
extraLibs={extraLibs}
|
extraLibs={extraLibs}
|
||||||
|
onEditorDidMount={onEditorDidMount}
|
||||||
/>
|
/>
|
||||||
{errorMsg && <div className={styles.errorMessage}>{errorMsg}</div>}
|
{errorMsg && <div className={styles.errorMessage}>{errorMsg}</div>}
|
||||||
</FlexBox>
|
</FlexBox>
|
||||||
|
|||||||
@@ -1,256 +1,144 @@
|
|||||||
import { ChangeEvent } from 'react'
|
import Icon from '@ant-design/icons'
|
||||||
|
import { Background, Controls, MiniMap, Node, Panel, ReactFlow } from '@xyflow/react'
|
||||||
|
import '@xyflow/react/dist/style.css'
|
||||||
|
import { AppContext } from '@/App'
|
||||||
import useStyles from '@/components/Playground/Output/Preview/render.style'
|
import useStyles from '@/components/Playground/Output/Preview/render.style'
|
||||||
import iframeRaw from '@/components/Playground/Output/Preview/iframe.html?raw'
|
import iframeRaw from '@/components/Playground/Output/Preview/iframe.html?raw'
|
||||||
import HideScrollbar from '@/components/common/HideScrollbar'
|
import devices, { DeviceName } from '@/components/Playground/Output/Preview/devices'
|
||||||
|
import Simulation, { SimulationData } from '@/components/Playground/Output/Preview/Simulation'
|
||||||
|
|
||||||
interface RenderProps {
|
interface RenderProps {
|
||||||
iframeKey: string
|
iframeKey: string
|
||||||
compiledCode: string
|
compiledCode: string
|
||||||
mobileMode?: boolean
|
mobileMode?: boolean
|
||||||
|
globalJsVariables?: Record<string, unknown>
|
||||||
|
globalCssVariables?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
interface IMessage {
|
interface IMessage {
|
||||||
type: 'LOADED' | 'ERROR' | 'UPDATE' | 'DONE' | 'SCALE'
|
type: 'LOADED' | 'ERROR' | 'UPDATE' | 'DONE' | 'GLOBAL_VARIABLES'
|
||||||
msg: string
|
msg: string
|
||||||
data: {
|
data: {
|
||||||
compiledCode?: string
|
compiledCode?: string
|
||||||
zoom?: number
|
zoom?: number
|
||||||
|
globalJsVariables?: Record<string, unknown>
|
||||||
|
globalCssVariables?: string
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
interface IDevice {
|
|
||||||
name: string
|
|
||||||
width: number
|
|
||||||
height: number
|
|
||||||
}
|
|
||||||
|
|
||||||
const getIframeUrl = (iframeRaw: string) => {
|
const getIframeUrl = (iframeRaw: string) => {
|
||||||
const shimsUrl = '//unpkg.com/es-module-shims/dist/es-module-shims.js'
|
return URL.createObjectURL(new Blob([iframeRaw], { type: 'text/html' }))
|
||||||
// 判断浏览器是否支持esm ,不支持esm就引入es-module-shims
|
|
||||||
const newIframeRaw =
|
|
||||||
typeof import.meta === 'undefined'
|
|
||||||
? iframeRaw.replace(
|
|
||||||
'<!-- es-module-shims -->',
|
|
||||||
`<script async src="${shimsUrl}"></script>`
|
|
||||||
)
|
|
||||||
: iframeRaw
|
|
||||||
return URL.createObjectURL(new Blob([newIframeRaw], { type: 'text/html' }))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const iframeUrl = getIframeUrl(iframeRaw)
|
const iframeUrl = getIframeUrl(iframeRaw)
|
||||||
|
|
||||||
const Render = ({ iframeKey, compiledCode, mobileMode = false }: RenderProps) => {
|
const Render = ({
|
||||||
const { styles, theme, cx } = useStyles()
|
iframeKey,
|
||||||
|
compiledCode,
|
||||||
|
mobileMode = false,
|
||||||
|
globalJsVariables,
|
||||||
|
globalCssVariables
|
||||||
|
}: RenderProps) => {
|
||||||
|
const { styles, theme } = useStyles()
|
||||||
|
const { isDarkMode } = useContext(AppContext)
|
||||||
const iframeRef = useRef<HTMLIFrameElement>(null)
|
const iframeRef = useRef<HTMLIFrameElement>(null)
|
||||||
const [isLoaded, setIsLoaded] = useState(false)
|
const [isLoaded, setIsLoaded] = useState(false)
|
||||||
const [selectedDevice, setSelectedDevice] = useState('Pixel 7')
|
const [selectedDevice, setSelectedDevice] = useState<DeviceName>('Pixel 7')
|
||||||
const [zoom, setZoom] = useState(1)
|
|
||||||
const [isRotate, setIsRotate] = useState(false)
|
const [isRotate, setIsRotate] = useState(false)
|
||||||
|
const [nodes, setNodes] = useState<Node<SimulationData>[]>([])
|
||||||
const devices: IDevice[] = [
|
|
||||||
{
|
|
||||||
name: 'iPhone SE',
|
|
||||||
width: 375,
|
|
||||||
height: 667
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'iPhone XR',
|
|
||||||
width: 414,
|
|
||||||
height: 896
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'iPhone 12 Pro',
|
|
||||||
width: 390,
|
|
||||||
height: 844
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'iPhone 14 Pro Max',
|
|
||||||
width: 430,
|
|
||||||
height: 932
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'Pixel 7',
|
|
||||||
width: 412,
|
|
||||||
height: 915
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'Samsung Galaxy S8+',
|
|
||||||
width: 360,
|
|
||||||
height: 740
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'Samsung Galaxy S20 Ultra',
|
|
||||||
width: 412,
|
|
||||||
height: 915
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'iPad Mini',
|
|
||||||
width: 768,
|
|
||||||
height: 1024
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'iPad Air',
|
|
||||||
width: 820,
|
|
||||||
height: 1180
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'iPad Pro',
|
|
||||||
width: 1024,
|
|
||||||
height: 1366
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'Surface Pro 7',
|
|
||||||
width: 912,
|
|
||||||
height: 1368
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'Surface Duo',
|
|
||||||
width: 540,
|
|
||||||
height: 720
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'Galaxy Fold',
|
|
||||||
width: 280,
|
|
||||||
height: 653
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'Asus Zenbook Fold',
|
|
||||||
width: 853,
|
|
||||||
height: 1280
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'Samsung Galaxy A51/71',
|
|
||||||
width: 412,
|
|
||||||
height: 914
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'Nest Hub',
|
|
||||||
width: 1024,
|
|
||||||
height: 600
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'Nest Hub Max',
|
|
||||||
width: 1280,
|
|
||||||
height: 800
|
|
||||||
}
|
|
||||||
]
|
|
||||||
|
|
||||||
const handleOnChangeDevice = (e: ChangeEvent<HTMLSelectElement>) => {
|
|
||||||
setSelectedDevice(e.target.value)
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleOnChangeZoom = (e: ChangeEvent<HTMLInputElement>) => {
|
|
||||||
setZoom(Number(e.target.value))
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleOnRotateDevice = () => {
|
const handleOnRotateDevice = () => {
|
||||||
setIsRotate(!isRotate)
|
setIsRotate(!isRotate)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const loadGlobalVariables = () => {
|
||||||
|
iframeRef.current?.contentWindow?.postMessage(
|
||||||
|
{
|
||||||
|
type: 'GLOBAL_VARIABLES',
|
||||||
|
data: { globalJsVariables, globalCssVariables }
|
||||||
|
} as IMessage,
|
||||||
|
'*'
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (isLoaded) {
|
if (!isLoaded) {
|
||||||
iframeRef.current?.contentWindow?.postMessage(
|
return
|
||||||
{
|
|
||||||
type: 'UPDATE',
|
|
||||||
data: { compiledCode }
|
|
||||||
} as IMessage,
|
|
||||||
'*'
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
iframeRef.current?.contentWindow?.postMessage(
|
||||||
|
{
|
||||||
|
type: 'UPDATE',
|
||||||
|
data: { compiledCode }
|
||||||
|
} as IMessage,
|
||||||
|
'*'
|
||||||
|
)
|
||||||
|
loadGlobalVariables()
|
||||||
}, [isLoaded, compiledCode])
|
}, [isLoaded, compiledCode])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (isLoaded) {
|
if (!isLoaded) {
|
||||||
iframeRef.current?.contentWindow?.postMessage(
|
return
|
||||||
{
|
|
||||||
type: 'SCALE',
|
|
||||||
data: { zoom }
|
|
||||||
} as IMessage,
|
|
||||||
'*'
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}, [isLoaded, zoom])
|
loadGlobalVariables()
|
||||||
|
}, [isLoaded, globalJsVariables, globalCssVariables])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setNodes([
|
||||||
|
{
|
||||||
|
id: 'device',
|
||||||
|
type: 'simulation',
|
||||||
|
position: { x: 0, y: 0 },
|
||||||
|
data: {
|
||||||
|
deviceWidth: devices[selectedDevice].width,
|
||||||
|
deviceHeight: devices[selectedDevice].height,
|
||||||
|
isRotate,
|
||||||
|
iframeKey,
|
||||||
|
iframeRef,
|
||||||
|
iframeUrl,
|
||||||
|
setIsLoaded
|
||||||
|
}
|
||||||
|
}
|
||||||
|
])
|
||||||
|
}, [selectedDevice, isRotate, iframeKey, iframeRef, iframeUrl, setIsLoaded])
|
||||||
|
|
||||||
return mobileMode ? (
|
return mobileMode ? (
|
||||||
<>
|
<>
|
||||||
<HideScrollbar
|
<ReactFlow
|
||||||
className={styles.mobileModeRoot}
|
colorMode={isDarkMode ? 'dark' : 'light'}
|
||||||
isShowVerticalScrollbar
|
nodeTypes={{ simulation: Simulation }}
|
||||||
isShowHorizontalScrollbar
|
nodes={nodes}
|
||||||
autoHideWaitingTime={1000}
|
proOptions={{ hideAttribution: true }}
|
||||||
|
fitView
|
||||||
>
|
>
|
||||||
<div className={styles.mobileModeContent} style={{ zoom }}>
|
<Background bgColor={theme.colorBgLayout} />
|
||||||
<div className={cx(styles.device, isRotate ? styles.rotate : '')}>
|
<MiniMap bgColor={theme.colorBgMask} zoomStep={1} pannable zoomable />
|
||||||
<div
|
<Controls />
|
||||||
className={cx(
|
<Panel>
|
||||||
styles.deviceHeader,
|
<AntdSpace>
|
||||||
isRotate ? styles.rotatedDeviceHeader : ''
|
<AntdSelect
|
||||||
)}
|
size={'small'}
|
||||||
|
options={Object.values(devices).map((item) => ({
|
||||||
|
label: item.name,
|
||||||
|
value: item.name
|
||||||
|
}))}
|
||||||
|
value={selectedDevice}
|
||||||
|
onChange={setSelectedDevice}
|
||||||
/>
|
/>
|
||||||
<div
|
<AntdButton
|
||||||
className={cx(
|
size={'small'}
|
||||||
styles.deviceContent,
|
title={'旋转屏幕'}
|
||||||
isRotate ? styles.rotatedDeviceContent : ''
|
onClick={handleOnRotateDevice}
|
||||||
)}
|
icon={
|
||||||
style={{
|
<Icon
|
||||||
width: isRotate
|
component={
|
||||||
? (devices.find((value) => value.name === selectedDevice)
|
isRotate ? IconOxygenRotateRight : IconOxygenRotateLeft
|
||||||
?.height ?? 915)
|
}
|
||||||
: (devices.find((value) => value.name === selectedDevice)
|
/>
|
||||||
?.width ?? 412),
|
}
|
||||||
height: isRotate
|
|
||||||
? (devices.find((value) => value.name === selectedDevice)
|
|
||||||
?.width ?? 412)
|
|
||||||
: (devices.find((value) => value.name === selectedDevice)
|
|
||||||
?.height ?? 915)
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<iframe
|
|
||||||
className={styles.renderRoot}
|
|
||||||
key={iframeKey}
|
|
||||||
ref={iframeRef}
|
|
||||||
src={iframeUrl}
|
|
||||||
onLoad={() => setIsLoaded(true)}
|
|
||||||
sandbox="allow-downloads allow-forms allow-modals allow-scripts"
|
|
||||||
allow={'clipboard-read; clipboard-write'}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
className={cx(
|
|
||||||
styles.deviceFooter,
|
|
||||||
isRotate ? styles.rotatedDeviceFooter : ''
|
|
||||||
)}
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</AntdSpace>
|
||||||
</div>
|
</Panel>
|
||||||
</HideScrollbar>
|
</ReactFlow>
|
||||||
|
|
||||||
<div className={styles.switchDevice}>
|
|
||||||
<IconOxygenMobile fill={theme.colorText} />
|
|
||||||
<select value={selectedDevice} onChange={handleOnChangeDevice}>
|
|
||||||
{devices.map((value) => (
|
|
||||||
<option value={value.name}>{value.name}</option>
|
|
||||||
))}
|
|
||||||
</select>
|
|
||||||
<div title={'旋转屏幕'} onClick={handleOnRotateDevice}>
|
|
||||||
{isRotate ? (
|
|
||||||
<IconOxygenRotateRight fill={theme.colorText} />
|
|
||||||
) : (
|
|
||||||
<IconOxygenRotateLeft fill={theme.colorText} />
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className={styles.switchZoom}>
|
|
||||||
<IconOxygenZoom fill={theme.colorText} />
|
|
||||||
<input
|
|
||||||
type={'range'}
|
|
||||||
min={0.5}
|
|
||||||
max={2}
|
|
||||||
step={0.1}
|
|
||||||
value={zoom}
|
|
||||||
onChange={handleOnChangeZoom}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
<iframe
|
<iframe
|
||||||
|
|||||||
@@ -0,0 +1,52 @@
|
|||||||
|
import { Dispatch, RefObject, SetStateAction } from 'react'
|
||||||
|
import { Node, NodeProps } from '@xyflow/react'
|
||||||
|
import useStyles from '@/components/Playground/Output/Preview/simulation.style'
|
||||||
|
|
||||||
|
export type SimulationData = {
|
||||||
|
deviceWidth: number
|
||||||
|
deviceHeight: number
|
||||||
|
isRotate: boolean
|
||||||
|
iframeKey: string
|
||||||
|
iframeRef: RefObject<HTMLIFrameElement>
|
||||||
|
iframeUrl: string
|
||||||
|
setIsLoaded: Dispatch<SetStateAction<boolean>>
|
||||||
|
}
|
||||||
|
|
||||||
|
export type SimulationNode = Node<SimulationData, 'simulation'>
|
||||||
|
|
||||||
|
const Simulation = ({ data }: NodeProps<SimulationNode>) => {
|
||||||
|
const { styles, cx } = useStyles()
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={cx(styles.device, data.isRotate ? styles.rotate : '')}>
|
||||||
|
<div
|
||||||
|
className={cx(styles.deviceHeader, data.isRotate ? styles.rotatedDeviceHeader : '')}
|
||||||
|
/>
|
||||||
|
<div
|
||||||
|
className={cx(
|
||||||
|
styles.deviceContent,
|
||||||
|
data.isRotate ? styles.rotatedDeviceContent : ''
|
||||||
|
)}
|
||||||
|
style={{
|
||||||
|
width: data.isRotate ? data.deviceHeight : data.deviceWidth,
|
||||||
|
height: data.isRotate ? data.deviceWidth : data.deviceHeight
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<iframe
|
||||||
|
className={styles.renderRoot}
|
||||||
|
key={data.iframeKey}
|
||||||
|
ref={data.iframeRef}
|
||||||
|
src={data.iframeUrl}
|
||||||
|
onLoad={() => data.setIsLoaded(true)}
|
||||||
|
sandbox={'allow-downloads allow-forms allow-modals allow-scripts'}
|
||||||
|
allow={'clipboard-read; clipboard-write'}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
className={cx(styles.deviceFooter, data.isRotate ? styles.rotatedDeviceFooter : '')}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Simulation
|
||||||
114
src/renderer/src/components/Playground/Output/Preview/devices.ts
Normal file
114
src/renderer/src/components/Playground/Output/Preview/devices.ts
Normal file
@@ -0,0 +1,114 @@
|
|||||||
|
export type DeviceName =
|
||||||
|
| 'iPhone SE'
|
||||||
|
| 'iPhone XR'
|
||||||
|
| 'iPhone 12 Pro'
|
||||||
|
| 'iPhone 14 Pro Max'
|
||||||
|
| 'Pixel 7'
|
||||||
|
| 'Samsung Galaxy S8+'
|
||||||
|
| 'Samsung Galaxy S20 Ultra'
|
||||||
|
| 'iPad Mini'
|
||||||
|
| 'iPad Air'
|
||||||
|
| 'iPad Pro'
|
||||||
|
| 'Surface Pro 7'
|
||||||
|
| 'Surface Duo'
|
||||||
|
| 'Galaxy Fold'
|
||||||
|
| 'Asus Zenbook Fold'
|
||||||
|
| 'Samsung Galaxy A51/71'
|
||||||
|
| 'Nest Hub'
|
||||||
|
| 'Nest Hub Max'
|
||||||
|
|
||||||
|
export interface IDevice {
|
||||||
|
name: DeviceName
|
||||||
|
width: number
|
||||||
|
height: number
|
||||||
|
}
|
||||||
|
|
||||||
|
const devices: Record<DeviceName, IDevice> = {
|
||||||
|
'iPhone SE': {
|
||||||
|
name: 'iPhone SE',
|
||||||
|
width: 375,
|
||||||
|
height: 667
|
||||||
|
},
|
||||||
|
'iPhone XR': {
|
||||||
|
name: 'iPhone XR',
|
||||||
|
width: 414,
|
||||||
|
height: 896
|
||||||
|
},
|
||||||
|
'iPhone 12 Pro': {
|
||||||
|
name: 'iPhone 12 Pro',
|
||||||
|
width: 390,
|
||||||
|
height: 844
|
||||||
|
},
|
||||||
|
'iPhone 14 Pro Max': {
|
||||||
|
name: 'iPhone 14 Pro Max',
|
||||||
|
width: 430,
|
||||||
|
height: 932
|
||||||
|
},
|
||||||
|
'Pixel 7': {
|
||||||
|
name: 'Pixel 7',
|
||||||
|
width: 412,
|
||||||
|
height: 915
|
||||||
|
},
|
||||||
|
'Samsung Galaxy S8+': {
|
||||||
|
name: 'Samsung Galaxy S8+',
|
||||||
|
width: 360,
|
||||||
|
height: 740
|
||||||
|
},
|
||||||
|
'Samsung Galaxy S20 Ultra': {
|
||||||
|
name: 'Samsung Galaxy S20 Ultra',
|
||||||
|
width: 412,
|
||||||
|
height: 915
|
||||||
|
},
|
||||||
|
'iPad Mini': {
|
||||||
|
name: 'iPad Mini',
|
||||||
|
width: 768,
|
||||||
|
height: 1024
|
||||||
|
},
|
||||||
|
'iPad Air': {
|
||||||
|
name: 'iPad Air',
|
||||||
|
width: 820,
|
||||||
|
height: 1180
|
||||||
|
},
|
||||||
|
'iPad Pro': {
|
||||||
|
name: 'iPad Pro',
|
||||||
|
width: 1024,
|
||||||
|
height: 1366
|
||||||
|
},
|
||||||
|
'Surface Pro 7': {
|
||||||
|
name: 'Surface Pro 7',
|
||||||
|
width: 912,
|
||||||
|
height: 1368
|
||||||
|
},
|
||||||
|
'Surface Duo': {
|
||||||
|
name: 'Surface Duo',
|
||||||
|
width: 540,
|
||||||
|
height: 720
|
||||||
|
},
|
||||||
|
'Galaxy Fold': {
|
||||||
|
name: 'Galaxy Fold',
|
||||||
|
width: 280,
|
||||||
|
height: 653
|
||||||
|
},
|
||||||
|
'Asus Zenbook Fold': {
|
||||||
|
name: 'Asus Zenbook Fold',
|
||||||
|
width: 853,
|
||||||
|
height: 1280
|
||||||
|
},
|
||||||
|
'Samsung Galaxy A51/71': {
|
||||||
|
name: 'Samsung Galaxy A51/71',
|
||||||
|
width: 412,
|
||||||
|
height: 914
|
||||||
|
},
|
||||||
|
'Nest Hub': {
|
||||||
|
name: 'Nest Hub',
|
||||||
|
width: 1024,
|
||||||
|
height: 600
|
||||||
|
},
|
||||||
|
'Nest Hub Max': {
|
||||||
|
name: 'Nest Hub Max',
|
||||||
|
width: 1280,
|
||||||
|
height: 800
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default devices
|
||||||
@@ -4,14 +4,14 @@
|
|||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<title>Preview</title>
|
<title>Preview</title>
|
||||||
<!-- es-module-shims -->
|
<style id="global-css-variable"></style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<script>
|
<script>
|
||||||
window.addEventListener("message", ({ data }) => {
|
window.addEventListener("message", ({ data }) => {
|
||||||
if (data?.type === "UPDATE") {
|
if (data?.type === "UPDATE") {
|
||||||
// Record old styles that need to be removed
|
// Record old styles that need to be removed
|
||||||
const appStyleElement = document.querySelectorAll("style:not(style[id$=\"_oxygen_base_style.css\"])") || [];
|
const appStyleElement = document.querySelectorAll("style:not(:is(style[id$=\"_oxygen_base_style.css\"], style[id=\"global-css-variable\"]))") || [];
|
||||||
|
|
||||||
// Remove old app
|
// Remove old app
|
||||||
const appSrcElement = document.querySelector("#appSrc");
|
const appSrcElement = document.querySelector("#appSrc");
|
||||||
@@ -37,8 +37,11 @@
|
|||||||
URL.revokeObjectURL(oldSrc);
|
URL.revokeObjectURL(oldSrc);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data?.type === "SCALE") {
|
if (data?.type === "GLOBAL_VARIABLES") {
|
||||||
document.getElementById("root").style.zoom = data.data.zoom;
|
document.querySelector("#global-css-variable").textContent = data.data.globalCssVariables;
|
||||||
|
for (const key in data.data.globalJsVariables) {
|
||||||
|
globalThis[key] = data.data.globalJsVariables[key]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -11,6 +11,8 @@ interface PreviewProps {
|
|||||||
preExpansionCode?: string
|
preExpansionCode?: string
|
||||||
postExpansionCode?: string
|
postExpansionCode?: string
|
||||||
mobileMode?: boolean
|
mobileMode?: boolean
|
||||||
|
globalJsVariables?: Record<string, unknown>
|
||||||
|
globalCssVariables?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
const Preview = ({
|
const Preview = ({
|
||||||
@@ -20,7 +22,9 @@ const Preview = ({
|
|||||||
entryPoint,
|
entryPoint,
|
||||||
preExpansionCode = '',
|
preExpansionCode = '',
|
||||||
postExpansionCode = '',
|
postExpansionCode = '',
|
||||||
mobileMode = false
|
mobileMode = false,
|
||||||
|
globalJsVariables,
|
||||||
|
globalCssVariables
|
||||||
}: PreviewProps) => {
|
}: PreviewProps) => {
|
||||||
const { styles } = useStyles()
|
const { styles } = useStyles()
|
||||||
const [errorMsg, setErrorMsg] = useState('')
|
const [errorMsg, setErrorMsg] = useState('')
|
||||||
@@ -44,7 +48,13 @@ const Preview = ({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styles.root}>
|
<div className={styles.root}>
|
||||||
<Render iframeKey={iframeKey} compiledCode={compiledCode} mobileMode={mobileMode} />
|
<Render
|
||||||
|
iframeKey={iframeKey}
|
||||||
|
compiledCode={compiledCode}
|
||||||
|
mobileMode={mobileMode}
|
||||||
|
globalJsVariables={globalJsVariables}
|
||||||
|
globalCssVariables={globalCssVariables}
|
||||||
|
/>
|
||||||
{errorMsg && <div className={styles.errorMessage}>{errorMsg}</div>}
|
{errorMsg && <div className={styles.errorMessage}>{errorMsg}</div>}
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,84 +1,10 @@
|
|||||||
import { createStyles } from 'antd-style'
|
import { createStyles } from 'antd-style'
|
||||||
|
|
||||||
export default createStyles(({ token }) => ({
|
export default createStyles(() => ({
|
||||||
renderRoot: {
|
renderRoot: {
|
||||||
border: 'none',
|
border: 'none',
|
||||||
height: '100%',
|
height: '100%',
|
||||||
width: '100%',
|
width: '100%',
|
||||||
flex: 1
|
flex: 1
|
||||||
},
|
|
||||||
|
|
||||||
mobileModeRoot: {
|
|
||||||
backgroundColor: token.colorBgLayout
|
|
||||||
},
|
|
||||||
|
|
||||||
mobileModeContent: {
|
|
||||||
padding: 80
|
|
||||||
},
|
|
||||||
|
|
||||||
device: {
|
|
||||||
display: 'flex',
|
|
||||||
flexDirection: 'column',
|
|
||||||
backgroundColor: token.colorBgElevated,
|
|
||||||
width: 'fit-content',
|
|
||||||
margin: '0 auto',
|
|
||||||
borderRadius: 40
|
|
||||||
},
|
|
||||||
|
|
||||||
rotate: {
|
|
||||||
flexDirection: 'row'
|
|
||||||
},
|
|
||||||
|
|
||||||
deviceHeader: {
|
|
||||||
margin: '20px auto',
|
|
||||||
width: 60,
|
|
||||||
height: 10,
|
|
||||||
borderRadius: 5,
|
|
||||||
backgroundColor: token.colorBgMask
|
|
||||||
},
|
|
||||||
|
|
||||||
rotatedDeviceHeader: {
|
|
||||||
margin: 'auto 20px',
|
|
||||||
width: 10,
|
|
||||||
height: 60
|
|
||||||
},
|
|
||||||
|
|
||||||
deviceContent: {
|
|
||||||
margin: '0 10px',
|
|
||||||
backgroundColor: token.colorBgLayout
|
|
||||||
},
|
|
||||||
|
|
||||||
rotatedDeviceContent: {
|
|
||||||
margin: '10px 0'
|
|
||||||
},
|
|
||||||
|
|
||||||
deviceFooter: {
|
|
||||||
margin: '20px auto',
|
|
||||||
width: 40,
|
|
||||||
height: 40,
|
|
||||||
borderRadius: '50%',
|
|
||||||
backgroundColor: token.colorBgMask
|
|
||||||
},
|
|
||||||
|
|
||||||
rotatedDeviceFooter: {
|
|
||||||
margin: 'auto 20px'
|
|
||||||
},
|
|
||||||
|
|
||||||
switchDevice: {
|
|
||||||
display: 'flex',
|
|
||||||
position: 'absolute',
|
|
||||||
top: 10,
|
|
||||||
left: 10,
|
|
||||||
alignItems: 'center',
|
|
||||||
gap: 4
|
|
||||||
},
|
|
||||||
|
|
||||||
switchZoom: {
|
|
||||||
display: 'flex',
|
|
||||||
position: 'absolute',
|
|
||||||
top: 10,
|
|
||||||
right: 10,
|
|
||||||
alignItems: 'center',
|
|
||||||
gap: 4
|
|
||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
|
|||||||
@@ -0,0 +1,58 @@
|
|||||||
|
import { createStyles } from 'antd-style'
|
||||||
|
|
||||||
|
export default createStyles(({ token }) => ({
|
||||||
|
renderRoot: {
|
||||||
|
border: `1px solid ${token.colorBorder}`,
|
||||||
|
height: '100%',
|
||||||
|
width: '100%',
|
||||||
|
flex: 1
|
||||||
|
},
|
||||||
|
|
||||||
|
device: {
|
||||||
|
display: 'flex',
|
||||||
|
flexDirection: 'column',
|
||||||
|
backgroundColor: token.colorBgElevated,
|
||||||
|
width: 'fit-content',
|
||||||
|
margin: '0 auto',
|
||||||
|
borderRadius: 40
|
||||||
|
},
|
||||||
|
|
||||||
|
rotate: {
|
||||||
|
flexDirection: 'row'
|
||||||
|
},
|
||||||
|
|
||||||
|
deviceHeader: {
|
||||||
|
margin: '20px auto',
|
||||||
|
width: 60,
|
||||||
|
height: 10,
|
||||||
|
borderRadius: 5,
|
||||||
|
backgroundColor: token.colorBgMask
|
||||||
|
},
|
||||||
|
|
||||||
|
rotatedDeviceHeader: {
|
||||||
|
margin: 'auto 20px',
|
||||||
|
width: 10,
|
||||||
|
height: 60
|
||||||
|
},
|
||||||
|
|
||||||
|
deviceContent: {
|
||||||
|
margin: '0 10px',
|
||||||
|
backgroundColor: token.colorBgLayout
|
||||||
|
},
|
||||||
|
|
||||||
|
rotatedDeviceContent: {
|
||||||
|
margin: '10px 0'
|
||||||
|
},
|
||||||
|
|
||||||
|
deviceFooter: {
|
||||||
|
margin: '20px auto',
|
||||||
|
width: 40,
|
||||||
|
height: 40,
|
||||||
|
borderRadius: '50%',
|
||||||
|
backgroundColor: token.colorBgMask
|
||||||
|
},
|
||||||
|
|
||||||
|
rotatedDeviceFooter: {
|
||||||
|
margin: 'auto 20px'
|
||||||
|
}
|
||||||
|
}))
|
||||||
@@ -13,6 +13,8 @@ interface OutputProps {
|
|||||||
preExpansionCode?: string
|
preExpansionCode?: string
|
||||||
postExpansionCode?: string
|
postExpansionCode?: string
|
||||||
mobileMode?: boolean
|
mobileMode?: boolean
|
||||||
|
globalJsVariables?: Record<string, unknown>
|
||||||
|
globalCssVariables?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
const Output = ({
|
const Output = ({
|
||||||
@@ -23,7 +25,9 @@ const Output = ({
|
|||||||
entryPoint,
|
entryPoint,
|
||||||
preExpansionCode,
|
preExpansionCode,
|
||||||
postExpansionCode,
|
postExpansionCode,
|
||||||
mobileMode = false
|
mobileMode = false,
|
||||||
|
globalJsVariables,
|
||||||
|
globalCssVariables
|
||||||
}: OutputProps) => {
|
}: OutputProps) => {
|
||||||
const [selectedTab, setSelectedTab] = useState('Preview')
|
const [selectedTab, setSelectedTab] = useState('Preview')
|
||||||
|
|
||||||
@@ -47,6 +51,8 @@ const Output = ({
|
|||||||
preExpansionCode={preExpansionCode}
|
preExpansionCode={preExpansionCode}
|
||||||
postExpansionCode={postExpansionCode}
|
postExpansionCode={postExpansionCode}
|
||||||
mobileMode={mobileMode}
|
mobileMode={mobileMode}
|
||||||
|
globalJsVariables={globalJsVariables}
|
||||||
|
globalCssVariables={globalCssVariables}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{selectedTab === 'Transform' && (
|
{selectedTab === 'Transform' && (
|
||||||
|
|||||||
@@ -262,7 +262,9 @@ const SignIn = () => {
|
|||||||
<FlexBox direction={'horizontal'} className={styles.addition}>
|
<FlexBox direction={'horizontal'} className={styles.addition}>
|
||||||
<a
|
<a
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
navigateToRoot(navigate)
|
setTimeout(() => {
|
||||||
|
navigateToRoot(navigate)
|
||||||
|
})
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
返回主页
|
返回主页
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import {
|
|||||||
DATABASE_SELECT_SUCCESS,
|
DATABASE_SELECT_SUCCESS,
|
||||||
DATABASE_UPDATE_SUCCESS
|
DATABASE_UPDATE_SUCCESS
|
||||||
} from '@/constants/common.constants'
|
} from '@/constants/common.constants'
|
||||||
import { message, modal } from '@/util/common'
|
import { addExtraCssVariables, message, modal } from '@/util/common'
|
||||||
import { utcToLocalTime } from '@/util/datetime'
|
import { utcToLocalTime } from '@/util/datetime'
|
||||||
import { hasPermission } from '@/util/auth'
|
import { hasPermission } from '@/util/auth'
|
||||||
import editorExtraLibs from '@/util/editorExtraLibs'
|
import editorExtraLibs from '@/util/editorExtraLibs'
|
||||||
@@ -1113,6 +1113,7 @@ const Base = () => {
|
|||||||
!hasPermission('system:tool:modify:base')
|
!hasPermission('system:tool:modify:base')
|
||||||
}
|
}
|
||||||
extraLibs={editorExtraLibs}
|
extraLibs={editorExtraLibs}
|
||||||
|
onEditorDidMount={(_, monaco) => addExtraCssVariables(monaco)}
|
||||||
/>
|
/>
|
||||||
<div
|
<div
|
||||||
className={styles.closeEditorBtn}
|
className={styles.closeEditorBtn}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import Draggable from 'react-draggable'
|
|||||||
import Icon from '@ant-design/icons'
|
import Icon from '@ant-design/icons'
|
||||||
import useStyles from '@/assets/css/pages/system/tools/code.style'
|
import useStyles from '@/assets/css/pages/system/tools/code.style'
|
||||||
import { DATABASE_NO_RECORD_FOUND, DATABASE_SELECT_SUCCESS } from '@/constants/common.constants'
|
import { DATABASE_NO_RECORD_FOUND, DATABASE_SELECT_SUCCESS } from '@/constants/common.constants'
|
||||||
import { message, modal, checkDesktop } from '@/util/common'
|
import { message, modal, checkDesktop, addExtraCssVariables } from '@/util/common'
|
||||||
import { navigateToExecute, navigateToRepository } from '@/util/navigation'
|
import { navigateToExecute, navigateToRepository } from '@/util/navigation'
|
||||||
import editorExtraLibs from '@/util/editorExtraLibs'
|
import editorExtraLibs from '@/util/editorExtraLibs'
|
||||||
import { r_sys_tool_get_one } from '@/services/system'
|
import { r_sys_tool_get_one } from '@/services/system'
|
||||||
@@ -64,8 +64,9 @@ const Code = () => {
|
|||||||
render(response.data!)
|
render(response.data!)
|
||||||
break
|
break
|
||||||
case DATABASE_NO_RECORD_FOUND:
|
case DATABASE_NO_RECORD_FOUND:
|
||||||
void message.error('未找到指定工具')
|
message.error('未找到指定工具').then(() => {
|
||||||
navigateToRepository(navigate)
|
navigateToRepository(navigate)
|
||||||
|
})
|
||||||
break
|
break
|
||||||
default:
|
default:
|
||||||
void message.error('获取工具信息失败,请稍后重试')
|
void message.error('获取工具信息失败,请稍后重试')
|
||||||
@@ -92,6 +93,7 @@ const Code = () => {
|
|||||||
selectedFileName={selectedFileName}
|
selectedFileName={selectedFileName}
|
||||||
onSelectedFileChange={setSelectedFileName}
|
onSelectedFileChange={setSelectedFileName}
|
||||||
extraLibs={editorExtraLibs}
|
extraLibs={editorExtraLibs}
|
||||||
|
onEditorDidMount={(_, monaco) => addExtraCssVariables(monaco)}
|
||||||
/>
|
/>
|
||||||
</Card>
|
</Card>
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,14 @@
|
|||||||
import useStyles from '@/assets/css/pages/system/tools/execute.style'
|
import useStyles from '@/assets/css/pages/system/tools/execute.style'
|
||||||
import { DATABASE_NO_RECORD_FOUND, DATABASE_SELECT_SUCCESS } from '@/constants/common.constants'
|
import { DATABASE_NO_RECORD_FOUND, DATABASE_SELECT_SUCCESS } from '@/constants/common.constants'
|
||||||
import { message } from '@/util/common'
|
import {
|
||||||
|
checkDesktop,
|
||||||
|
generateThemeCssVariables,
|
||||||
|
message,
|
||||||
|
removeUselessAttributes
|
||||||
|
} from '@/util/common'
|
||||||
import { navigateToTools } from '@/util/navigation'
|
import { navigateToTools } from '@/util/navigation'
|
||||||
import { r_sys_tool_get_one } from '@/services/system'
|
import { r_sys_tool_get_one } from '@/services/system'
|
||||||
|
import { AppContext } from '@/App'
|
||||||
import FitFullscreen from '@/components/common/FitFullscreen'
|
import FitFullscreen from '@/components/common/FitFullscreen'
|
||||||
import Card from '@/components/common/Card'
|
import Card from '@/components/common/Card'
|
||||||
import Playground from '@/components/Playground'
|
import Playground from '@/components/Playground'
|
||||||
@@ -11,14 +17,29 @@ import { IImportMap } from '@/components/Playground/shared'
|
|||||||
import { base64ToFiles, base64ToStr, IMPORT_MAP_FILE_NAME } from '@/components/Playground/files'
|
import { base64ToFiles, base64ToStr, IMPORT_MAP_FILE_NAME } from '@/components/Playground/files'
|
||||||
|
|
||||||
const Execute = () => {
|
const Execute = () => {
|
||||||
const { styles } = useStyles()
|
const { styles, theme } = useStyles()
|
||||||
|
const { isDarkMode } = useContext(AppContext)
|
||||||
const navigate = useNavigate()
|
const navigate = useNavigate()
|
||||||
const { id } = useParams()
|
const { id } = useParams()
|
||||||
const [isLoading, setIsLoading] = useState(false)
|
const [isLoading, setIsLoading] = useState(false)
|
||||||
const [compiledCode, setCompiledCode] = useState('')
|
const [compiledCode, setCompiledCode] = useState('')
|
||||||
|
const [isMobileMode, setIsMobileMode] = useState(false)
|
||||||
|
|
||||||
const render = (toolVo: ToolVo) => {
|
const render = (toolVo: ToolVo) => {
|
||||||
try {
|
try {
|
||||||
|
switch (toolVo.platform) {
|
||||||
|
case 'ANDROID':
|
||||||
|
setIsMobileMode(true)
|
||||||
|
break
|
||||||
|
case 'DESKTOP':
|
||||||
|
if (!checkDesktop()) {
|
||||||
|
message.warning('此应用需要桌面端环境,请在桌面端打开').then(() => {
|
||||||
|
navigateToTools(navigate)
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const baseDist = base64ToStr(toolVo.base.dist.data!)
|
const baseDist = base64ToStr(toolVo.base.dist.data!)
|
||||||
const files = base64ToFiles(toolVo.source.data!)
|
const files = base64ToFiles(toolVo.source.data!)
|
||||||
const importMap = JSON.parse(files[IMPORT_MAP_FILE_NAME].value) as IImportMap
|
const importMap = JSON.parse(files[IMPORT_MAP_FILE_NAME].value) as IImportMap
|
||||||
@@ -55,8 +76,9 @@ const Execute = () => {
|
|||||||
render(response.data!)
|
render(response.data!)
|
||||||
break
|
break
|
||||||
case DATABASE_NO_RECORD_FOUND:
|
case DATABASE_NO_RECORD_FOUND:
|
||||||
void message.error('未找到指定工具')
|
message.error('未找到指定工具').then(() => {
|
||||||
navigateToTools(navigate)
|
navigateToTools(navigate)
|
||||||
|
})
|
||||||
break
|
break
|
||||||
default:
|
default:
|
||||||
void message.error('获取工具信息失败,请稍后重试')
|
void message.error('获取工具信息失败,请稍后重试')
|
||||||
@@ -75,7 +97,15 @@ const Execute = () => {
|
|||||||
return (
|
return (
|
||||||
<FitFullscreen className={styles.root}>
|
<FitFullscreen className={styles.root}>
|
||||||
<Card className={styles.rootBox}>
|
<Card className={styles.rootBox}>
|
||||||
<Playground.Output.Preview.Render iframeKey={`${id}`} compiledCode={compiledCode} />
|
<Playground.Output.Preview.Render
|
||||||
|
iframeKey={`${id}`}
|
||||||
|
compiledCode={compiledCode}
|
||||||
|
mobileMode={isMobileMode}
|
||||||
|
globalJsVariables={{
|
||||||
|
OxygenTheme: { ...removeUselessAttributes(theme), isDarkMode }
|
||||||
|
}}
|
||||||
|
globalCssVariables={generateThemeCssVariables(theme).styles}
|
||||||
|
/>
|
||||||
</Card>
|
</Card>
|
||||||
</FitFullscreen>
|
</FitFullscreen>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import {
|
|||||||
DATABASE_SELECT_SUCCESS,
|
DATABASE_SELECT_SUCCESS,
|
||||||
DATABASE_UPDATE_SUCCESS
|
DATABASE_UPDATE_SUCCESS
|
||||||
} from '@/constants/common.constants'
|
} from '@/constants/common.constants'
|
||||||
import { message, modal } from '@/util/common'
|
import { addExtraCssVariables, message, modal } from '@/util/common'
|
||||||
import { utcToLocalTime } from '@/util/datetime'
|
import { utcToLocalTime } from '@/util/datetime'
|
||||||
import { hasPermission } from '@/util/auth'
|
import { hasPermission } from '@/util/auth'
|
||||||
import editorExtraLibs from '@/util/editorExtraLibs'
|
import editorExtraLibs from '@/util/editorExtraLibs'
|
||||||
@@ -1056,6 +1056,7 @@ const Template = () => {
|
|||||||
!hasPermission('system:tool:modify:template')
|
!hasPermission('system:tool:modify:template')
|
||||||
}
|
}
|
||||||
extraLibs={editorExtraLibs}
|
extraLibs={editorExtraLibs}
|
||||||
|
onEditorDidMount={(_, monaco) => addExtraCssVariables(monaco)}
|
||||||
/>
|
/>
|
||||||
<div
|
<div
|
||||||
className={styles.closeEditorBtn}
|
className={styles.closeEditorBtn}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import {
|
|||||||
DATABASE_INSERT_SUCCESS,
|
DATABASE_INSERT_SUCCESS,
|
||||||
DATABASE_SELECT_SUCCESS
|
DATABASE_SELECT_SUCCESS
|
||||||
} from '@/constants/common.constants'
|
} from '@/constants/common.constants'
|
||||||
import { message } from '@/util/common'
|
import { generateThemeCssVariables, message, removeUselessAttributes } from '@/util/common'
|
||||||
import { navigateToEdit } from '@/util/navigation'
|
import { navigateToEdit } from '@/util/navigation'
|
||||||
import {
|
import {
|
||||||
r_tool_category_get,
|
r_tool_category_get,
|
||||||
@@ -13,6 +13,7 @@ import {
|
|||||||
r_tool_template_get,
|
r_tool_template_get,
|
||||||
r_tool_template_get_one
|
r_tool_template_get_one
|
||||||
} from '@/services/tool'
|
} from '@/services/tool'
|
||||||
|
import { AppContext } from '@/App'
|
||||||
import compiler from '@/components/Playground/compiler'
|
import compiler from '@/components/Playground/compiler'
|
||||||
import { IImportMap } from '@/components/Playground/shared'
|
import { IImportMap } from '@/components/Playground/shared'
|
||||||
import { base64ToFiles, base64ToStr, IMPORT_MAP_FILE_NAME } from '@/components/Playground/files'
|
import { base64ToFiles, base64ToStr, IMPORT_MAP_FILE_NAME } from '@/components/Playground/files'
|
||||||
@@ -23,7 +24,8 @@ import HideScrollbar from '@/components/common/HideScrollbar'
|
|||||||
import Playground from '@/components/Playground'
|
import Playground from '@/components/Playground'
|
||||||
|
|
||||||
const Create = () => {
|
const Create = () => {
|
||||||
const { styles } = useStyles()
|
const { styles, theme } = useStyles()
|
||||||
|
const { isDarkMode } = useContext(AppContext)
|
||||||
const navigate = useNavigate()
|
const navigate = useNavigate()
|
||||||
const [form] = AntdForm.useForm<ToolCreateParam>()
|
const [form] = AntdForm.useForm<ToolCreateParam>()
|
||||||
const formValues = AntdForm.useWatch([], form)
|
const formValues = AntdForm.useWatch([], form)
|
||||||
@@ -380,6 +382,10 @@ const Create = () => {
|
|||||||
iframeKey={previewTemplate}
|
iframeKey={previewTemplate}
|
||||||
compiledCode={compiledCode}
|
compiledCode={compiledCode}
|
||||||
mobileMode={formValues.platform === 'ANDROID'}
|
mobileMode={formValues.platform === 'ANDROID'}
|
||||||
|
globalJsVariables={{
|
||||||
|
OxygenTheme: { ...removeUselessAttributes(theme), isDarkMode }
|
||||||
|
}}
|
||||||
|
globalCssVariables={generateThemeCssVariables(theme).styles}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<span className={styles.noPreview}>暂无预览</span>
|
<span className={styles.noPreview}>暂无预览</span>
|
||||||
|
|||||||
@@ -8,7 +8,12 @@ import {
|
|||||||
TOOL_HAS_BEEN_PUBLISHED,
|
TOOL_HAS_BEEN_PUBLISHED,
|
||||||
TOOL_UNDER_REVIEW
|
TOOL_UNDER_REVIEW
|
||||||
} from '@/constants/common.constants'
|
} from '@/constants/common.constants'
|
||||||
import { message } from '@/util/common'
|
import {
|
||||||
|
addExtraCssVariables,
|
||||||
|
generateThemeCssVariables,
|
||||||
|
message,
|
||||||
|
removeUselessAttributes
|
||||||
|
} from '@/util/common'
|
||||||
import { navigateToRepository } from '@/util/navigation'
|
import { navigateToRepository } from '@/util/navigation'
|
||||||
import editorExtraLibs from '@/util/editorExtraLibs'
|
import editorExtraLibs from '@/util/editorExtraLibs'
|
||||||
import { r_tool_category_get, r_tool_detail, r_tool_update } from '@/services/tool'
|
import { r_tool_category_get, r_tool_detail, r_tool_update } from '@/services/tool'
|
||||||
@@ -28,7 +33,7 @@ import LoadingMask from '@/components/common/LoadingMask'
|
|||||||
import Card from '@/components/common/Card'
|
import Card from '@/components/common/Card'
|
||||||
|
|
||||||
const Edit = () => {
|
const Edit = () => {
|
||||||
const { styles } = useStyles()
|
const { styles, theme } = useStyles()
|
||||||
const { isDarkMode } = useContext(AppContext)
|
const { isDarkMode } = useContext(AppContext)
|
||||||
const blocker = useBlocker(
|
const blocker = useBlocker(
|
||||||
({ currentLocation, nextLocation }) =>
|
({ currentLocation, nextLocation }) =>
|
||||||
@@ -457,6 +462,7 @@ const Edit = () => {
|
|||||||
onChangeFileContent={handleOnChangeFileContent}
|
onChangeFileContent={handleOnChangeFileContent}
|
||||||
onSelectedFileChange={setSelectedFileName}
|
onSelectedFileChange={setSelectedFileName}
|
||||||
extraLibs={editorExtraLibs}
|
extraLibs={editorExtraLibs}
|
||||||
|
onEditorDidMount={(_, monaco) => addExtraCssVariables(monaco)}
|
||||||
/>
|
/>
|
||||||
<Playground.Output
|
<Playground.Output
|
||||||
isDarkMode={isDarkMode}
|
isDarkMode={isDarkMode}
|
||||||
@@ -466,6 +472,10 @@ const Edit = () => {
|
|||||||
entryPoint={entryPoint}
|
entryPoint={entryPoint}
|
||||||
postExpansionCode={baseDist}
|
postExpansionCode={baseDist}
|
||||||
mobileMode={toolData?.platform === 'ANDROID'}
|
mobileMode={toolData?.platform === 'ANDROID'}
|
||||||
|
globalJsVariables={{
|
||||||
|
OxygenTheme: { ...removeUselessAttributes(theme), isDarkMode }
|
||||||
|
}}
|
||||||
|
globalCssVariables={generateThemeCssVariables(theme).styles}
|
||||||
/>
|
/>
|
||||||
</LoadingMask>
|
</LoadingMask>
|
||||||
{isShowDraggableMask && <div className={styles.draggableMask} />}
|
{isShowDraggableMask && <div className={styles.draggableMask} />}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import useStyles from '@/assets/css/pages/tools/source.style'
|
import useStyles from '@/assets/css/pages/tools/source.style'
|
||||||
import { DATABASE_NO_RECORD_FOUND, DATABASE_SELECT_SUCCESS } from '@/constants/common.constants'
|
import { DATABASE_NO_RECORD_FOUND, DATABASE_SELECT_SUCCESS } from '@/constants/common.constants'
|
||||||
import { message } from '@/util/common'
|
import { addExtraCssVariables, message } from '@/util/common'
|
||||||
import { getLoginStatus } from '@/util/auth'
|
import { getLoginStatus } from '@/util/auth'
|
||||||
import { navigateToRepository, navigateToSource } from '@/util/navigation'
|
import { navigateToRepository, navigateToSource } from '@/util/navigation'
|
||||||
import editorExtraLibs from '@/util/editorExtraLibs'
|
import editorExtraLibs from '@/util/editorExtraLibs'
|
||||||
@@ -98,6 +98,7 @@ const Source = () => {
|
|||||||
selectedFileName={selectedFileName}
|
selectedFileName={selectedFileName}
|
||||||
onSelectedFileChange={setSelectedFileName}
|
onSelectedFileChange={setSelectedFileName}
|
||||||
extraLibs={editorExtraLibs}
|
extraLibs={editorExtraLibs}
|
||||||
|
onEditorDidMount={(_, monaco) => addExtraCssVariables(monaco)}
|
||||||
/>
|
/>
|
||||||
</Card>
|
</Card>
|
||||||
</FitFullscreen>
|
</FitFullscreen>
|
||||||
|
|||||||
@@ -1,6 +1,11 @@
|
|||||||
import useStyles from '@/assets/css/pages/tools/view.style'
|
import useStyles from '@/assets/css/pages/tools/view.style'
|
||||||
import { DATABASE_NO_RECORD_FOUND, DATABASE_SELECT_SUCCESS } from '@/constants/common.constants'
|
import { DATABASE_NO_RECORD_FOUND, DATABASE_SELECT_SUCCESS } from '@/constants/common.constants'
|
||||||
import { message } from '@/util/common'
|
import {
|
||||||
|
checkDesktop,
|
||||||
|
generateThemeCssVariables,
|
||||||
|
message,
|
||||||
|
removeUselessAttributes
|
||||||
|
} from '@/util/common'
|
||||||
import { getLoginStatus } from '@/util/auth'
|
import { getLoginStatus } from '@/util/auth'
|
||||||
import {
|
import {
|
||||||
navigateToInstall,
|
navigateToInstall,
|
||||||
@@ -9,6 +14,7 @@ import {
|
|||||||
navigateToView
|
navigateToView
|
||||||
} from '@/util/navigation'
|
} from '@/util/navigation'
|
||||||
import { l_tool_detail, r_tool_detail } from '@/services/tool'
|
import { l_tool_detail, r_tool_detail } from '@/services/tool'
|
||||||
|
import { AppContext } from '@/App'
|
||||||
import compiler from '@/components/Playground/compiler'
|
import compiler from '@/components/Playground/compiler'
|
||||||
import { IImportMap } from '@/components/Playground/shared'
|
import { IImportMap } from '@/components/Playground/shared'
|
||||||
import { base64ToFiles, base64ToStr, IMPORT_MAP_FILE_NAME } from '@/components/Playground/files'
|
import { base64ToFiles, base64ToStr, IMPORT_MAP_FILE_NAME } from '@/components/Playground/files'
|
||||||
@@ -17,7 +23,8 @@ import Playground from '@/components/Playground'
|
|||||||
import Card from '@/components/common/Card'
|
import Card from '@/components/common/Card'
|
||||||
|
|
||||||
const View = () => {
|
const View = () => {
|
||||||
const { styles } = useStyles()
|
const { styles, theme } = useStyles()
|
||||||
|
const { isDarkMode } = useContext(AppContext)
|
||||||
const navigate = useNavigate()
|
const navigate = useNavigate()
|
||||||
const { username, toolId, ver } = useParams()
|
const { username, toolId, ver } = useParams()
|
||||||
const [searchParams] = useSearchParams({
|
const [searchParams] = useSearchParams({
|
||||||
@@ -25,10 +32,21 @@ const View = () => {
|
|||||||
})
|
})
|
||||||
const [isLoading, setIsLoading] = useState(false)
|
const [isLoading, setIsLoading] = useState(false)
|
||||||
const [compiledCode, setCompiledCode] = useState('')
|
const [compiledCode, setCompiledCode] = useState('')
|
||||||
const [isAndroid, setIsAndroid] = useState(false)
|
const [isMobileMode, setIsMobileMode] = useState(false)
|
||||||
|
|
||||||
const render = (toolVo: ToolVo) => {
|
const render = (toolVo: ToolVo) => {
|
||||||
setIsAndroid(toolVo.platform === 'ANDROID')
|
switch (toolVo.platform) {
|
||||||
|
case 'ANDROID':
|
||||||
|
setIsMobileMode(true)
|
||||||
|
break
|
||||||
|
case 'DESKTOP':
|
||||||
|
if (!checkDesktop()) {
|
||||||
|
message.warning('此应用需要桌面端环境,请在桌面端打开').then(() => {
|
||||||
|
navigateToRepository(navigate)
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
if (username === '!') {
|
if (username === '!') {
|
||||||
try {
|
try {
|
||||||
const baseDist = base64ToStr(toolVo.base.dist.data!)
|
const baseDist = base64ToStr(toolVo.base.dist.data!)
|
||||||
@@ -145,7 +163,11 @@ const View = () => {
|
|||||||
<Playground.Output.Preview.Render
|
<Playground.Output.Preview.Render
|
||||||
iframeKey={`${username}:${toolId}:${ver}`}
|
iframeKey={`${username}:${toolId}:${ver}`}
|
||||||
compiledCode={compiledCode}
|
compiledCode={compiledCode}
|
||||||
mobileMode={isAndroid}
|
mobileMode={isMobileMode}
|
||||||
|
globalJsVariables={{
|
||||||
|
OxygenTheme: { ...removeUselessAttributes(theme), isDarkMode }
|
||||||
|
}}
|
||||||
|
globalCssVariables={generateThemeCssVariables(theme).styles}
|
||||||
/>
|
/>
|
||||||
</Card>
|
</Card>
|
||||||
</FitFullscreen>
|
</FitFullscreen>
|
||||||
|
|||||||
@@ -29,11 +29,6 @@ export const tools: RouteJsonObject[] = [
|
|||||||
icon: lazy(() => import('~icons/oxygen/installed')),
|
icon: lazy(() => import('~icons/oxygen/installed')),
|
||||||
menu: true
|
menu: true
|
||||||
},
|
},
|
||||||
{
|
|
||||||
path: '',
|
|
||||||
absolutePath: '/',
|
|
||||||
element: <Navigate to="/store" replace />
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
path: 'store/:username',
|
path: 'store/:username',
|
||||||
absolutePath: '/store',
|
absolutePath: '/store',
|
||||||
@@ -92,7 +87,7 @@ export const tools: RouteJsonObject[] = [
|
|||||||
{
|
{
|
||||||
path: '*',
|
path: '*',
|
||||||
absolutePath: '*',
|
absolutePath: '*',
|
||||||
element: <Navigate to="/" replace />
|
element: <Navigate to="/store" replace />
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,10 @@
|
|||||||
import { createRoot } from 'react-dom/client'
|
import { createRoot } from 'react-dom/client'
|
||||||
|
import { editor, languages, Position } from 'monaco-editor'
|
||||||
|
import { Monaco } from '@monaco-editor/react'
|
||||||
|
import { MessageInstance } from 'antd/es/message/interface'
|
||||||
|
import { HookAPI } from 'antd/es/modal/useModal'
|
||||||
|
import { NotificationInstance } from 'antd/es/notification/interface'
|
||||||
|
import { css, AntdToken, Theme } from 'antd-style'
|
||||||
import { floor } from 'lodash'
|
import { floor } from 'lodash'
|
||||||
import {
|
import {
|
||||||
STORAGE_COLLAPSE_SIDEBAR_KEY,
|
STORAGE_COLLAPSE_SIDEBAR_KEY,
|
||||||
@@ -10,9 +16,6 @@ import {
|
|||||||
} from '@/constants/common.constants'
|
} from '@/constants/common.constants'
|
||||||
import { getLocalStorage, setLocalStorage } from '@/util/browser'
|
import { getLocalStorage, setLocalStorage } from '@/util/browser'
|
||||||
import FullscreenLoadingMask from '@/components/common/FullscreenLoadingMask'
|
import FullscreenLoadingMask from '@/components/common/FullscreenLoadingMask'
|
||||||
import { MessageInstance } from 'antd/es/message/interface'
|
|
||||||
import { NotificationInstance } from 'antd/es/notification/interface'
|
|
||||||
import { HookAPI } from 'antd/es/modal/useModal'
|
|
||||||
|
|
||||||
export type ThemeMode = typeof THEME_FOLLOW_SYSTEM | typeof THEME_LIGHT | typeof THEME_DARK
|
export type ThemeMode = typeof THEME_FOLLOW_SYSTEM | typeof THEME_LIGHT | typeof THEME_DARK
|
||||||
|
|
||||||
@@ -215,7 +218,6 @@ const substringByByte = (str: string, start: number, length: number) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const omitTextByByte = (text: string, length: number) => {
|
export const omitTextByByte = (text: string, length: number) => {
|
||||||
console.log(getByteLength(text))
|
|
||||||
if (getByteLength(text) <= length) {
|
if (getByteLength(text) <= length) {
|
||||||
return text
|
return text
|
||||||
}
|
}
|
||||||
@@ -242,3 +244,314 @@ export const getThemeMode = (): ThemeMode => {
|
|||||||
export const setThemeMode = (themeMode: ThemeMode) => {
|
export const setThemeMode = (themeMode: ThemeMode) => {
|
||||||
setLocalStorage(STORAGE_THEME_MODE_KEY, themeMode)
|
setLocalStorage(STORAGE_THEME_MODE_KEY, themeMode)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const cssColors = [
|
||||||
|
'blue',
|
||||||
|
'purple',
|
||||||
|
'cyan',
|
||||||
|
'green',
|
||||||
|
'magenta',
|
||||||
|
'pink',
|
||||||
|
'red',
|
||||||
|
'orange',
|
||||||
|
'yellow',
|
||||||
|
'volcano',
|
||||||
|
'geekblue',
|
||||||
|
'gold',
|
||||||
|
'lime'
|
||||||
|
].reduce((prev: string[], current) => {
|
||||||
|
let temp: string[] = []
|
||||||
|
for (let i = 1; i <= 10; i++) {
|
||||||
|
temp = [...temp, `${current}${i}`]
|
||||||
|
}
|
||||||
|
return [...prev, current, ...temp]
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
const cssVariables: string[] = [
|
||||||
|
...cssColors,
|
||||||
|
'colorPrimary',
|
||||||
|
'colorSuccess',
|
||||||
|
'colorWarning',
|
||||||
|
'colorError',
|
||||||
|
'colorInfo',
|
||||||
|
'colorLink',
|
||||||
|
'colorTextBase',
|
||||||
|
'colorBgBase',
|
||||||
|
'fontFamily',
|
||||||
|
'fontFamilyCode',
|
||||||
|
'fontSize',
|
||||||
|
'lineWidth',
|
||||||
|
'lineType',
|
||||||
|
'motionUnit',
|
||||||
|
'motionBase',
|
||||||
|
'motionEaseOutCirc',
|
||||||
|
'motionEaseInOutCirc',
|
||||||
|
'motionEaseOut',
|
||||||
|
'motionEaseInOut',
|
||||||
|
'motionEaseOutBack',
|
||||||
|
'motionEaseInBack',
|
||||||
|
'motionEaseInQuint',
|
||||||
|
'motionEaseOutQuint',
|
||||||
|
'borderRadius',
|
||||||
|
'sizeUnit',
|
||||||
|
'sizeStep',
|
||||||
|
'sizePopupArrow',
|
||||||
|
'controlHeight',
|
||||||
|
'zIndexBase',
|
||||||
|
'zIndexPopupBase',
|
||||||
|
'opacityImage',
|
||||||
|
'colorLinkHover',
|
||||||
|
'colorText',
|
||||||
|
'colorTextSecondary',
|
||||||
|
'colorTextTertiary',
|
||||||
|
'colorTextQuaternary',
|
||||||
|
'colorFill',
|
||||||
|
'colorFillSecondary',
|
||||||
|
'colorFillTertiary',
|
||||||
|
'colorFillQuaternary',
|
||||||
|
'colorBgSolid',
|
||||||
|
'colorBgSolidHover',
|
||||||
|
'colorBgSolidActive',
|
||||||
|
'colorBgLayout',
|
||||||
|
'colorBgContainer',
|
||||||
|
'colorBgElevated',
|
||||||
|
'colorBgSpotlight',
|
||||||
|
'colorBgBlur',
|
||||||
|
'colorBorder',
|
||||||
|
'colorBorderSecondary',
|
||||||
|
'colorPrimaryBg',
|
||||||
|
'colorPrimaryBgHover',
|
||||||
|
'colorPrimaryBorder',
|
||||||
|
'colorPrimaryBorderHover',
|
||||||
|
'colorPrimaryHover',
|
||||||
|
'colorPrimaryActive',
|
||||||
|
'colorPrimaryTextHover',
|
||||||
|
'colorPrimaryText',
|
||||||
|
'colorPrimaryTextActive',
|
||||||
|
'colorSuccessBg',
|
||||||
|
'colorSuccessBgHover',
|
||||||
|
'colorSuccessBorder',
|
||||||
|
'colorSuccessBorderHover',
|
||||||
|
'colorSuccessHover',
|
||||||
|
'colorSuccessActive',
|
||||||
|
'colorSuccessTextHover',
|
||||||
|
'colorSuccessText',
|
||||||
|
'colorSuccessTextActive',
|
||||||
|
'colorErrorBg',
|
||||||
|
'colorErrorBgHover',
|
||||||
|
'colorErrorBgFilledHover',
|
||||||
|
'colorErrorBgActive',
|
||||||
|
'colorErrorBorder',
|
||||||
|
'colorErrorBorderHover',
|
||||||
|
'colorErrorHover',
|
||||||
|
'colorErrorActive',
|
||||||
|
'colorErrorTextHover',
|
||||||
|
'colorErrorText',
|
||||||
|
'colorErrorTextActive',
|
||||||
|
'colorWarningBg',
|
||||||
|
'colorWarningBgHover',
|
||||||
|
'colorWarningBorder',
|
||||||
|
'colorWarningBorderHover',
|
||||||
|
'colorWarningHover',
|
||||||
|
'colorWarningActive',
|
||||||
|
'colorWarningTextHover',
|
||||||
|
'colorWarningText',
|
||||||
|
'colorWarningTextActive',
|
||||||
|
'colorInfoBg',
|
||||||
|
'colorInfoBgHover',
|
||||||
|
'colorInfoBorder',
|
||||||
|
'colorInfoBorderHover',
|
||||||
|
'colorInfoHover',
|
||||||
|
'colorInfoActive',
|
||||||
|
'colorInfoTextHover',
|
||||||
|
'colorInfoText',
|
||||||
|
'colorInfoTextActive',
|
||||||
|
'colorLinkActive',
|
||||||
|
'colorBgMask',
|
||||||
|
'colorWhite',
|
||||||
|
'fontSizeSM',
|
||||||
|
'fontSizeLG',
|
||||||
|
'fontSizeXL',
|
||||||
|
'fontSizeHeading1',
|
||||||
|
'fontSizeHeading2',
|
||||||
|
'fontSizeHeading3',
|
||||||
|
'fontSizeHeading4',
|
||||||
|
'fontSizeHeading5',
|
||||||
|
'lineHeight',
|
||||||
|
'lineHeightLG',
|
||||||
|
'lineHeightSM',
|
||||||
|
'lineHeightHeading1',
|
||||||
|
'lineHeightHeading2',
|
||||||
|
'lineHeightHeading3',
|
||||||
|
'lineHeightHeading4',
|
||||||
|
'lineHeightHeading5',
|
||||||
|
'sizeXXL',
|
||||||
|
'sizeXL',
|
||||||
|
'sizeLG',
|
||||||
|
'sizeMD',
|
||||||
|
'sizeMS',
|
||||||
|
'size',
|
||||||
|
'sizeSM',
|
||||||
|
'sizeXS',
|
||||||
|
'sizeXXS',
|
||||||
|
'controlHeightSM',
|
||||||
|
'controlHeightXS',
|
||||||
|
'controlHeightLG',
|
||||||
|
'motionDurationFast',
|
||||||
|
'motionDurationMid',
|
||||||
|
'motionDurationSlow',
|
||||||
|
'lineWidthBold',
|
||||||
|
'borderRadiusXS',
|
||||||
|
'borderRadiusSM',
|
||||||
|
'borderRadiusLG',
|
||||||
|
'borderRadiusOuter',
|
||||||
|
'colorFillContent',
|
||||||
|
'colorFillContentHover',
|
||||||
|
'colorFillAlter',
|
||||||
|
'colorBgContainerDisabled',
|
||||||
|
'colorBorderBg',
|
||||||
|
'colorSplit',
|
||||||
|
'colorTextPlaceholder',
|
||||||
|
'colorTextDisabled',
|
||||||
|
'colorTextHeading',
|
||||||
|
'colorTextLabel',
|
||||||
|
'colorTextDescription',
|
||||||
|
'colorTextLightSolid',
|
||||||
|
'colorHighlight',
|
||||||
|
'colorBgTextHover',
|
||||||
|
'colorBgTextActive',
|
||||||
|
'colorIcon',
|
||||||
|
'colorIconHover',
|
||||||
|
'colorErrorOutline',
|
||||||
|
'colorWarningOutline',
|
||||||
|
'fontSizeIcon',
|
||||||
|
'lineWidthFocus',
|
||||||
|
'controlOutlineWidth',
|
||||||
|
'controlInteractiveSize',
|
||||||
|
'controlItemBgHover',
|
||||||
|
'controlItemBgActive',
|
||||||
|
'controlItemBgActiveHover',
|
||||||
|
'controlItemBgActiveDisabled',
|
||||||
|
'controlOutline',
|
||||||
|
'fontWeightStrong',
|
||||||
|
'opacityLoading',
|
||||||
|
'linkDecoration',
|
||||||
|
'linkHoverDecoration',
|
||||||
|
'linkFocusDecoration',
|
||||||
|
'controlPaddingHorizontal',
|
||||||
|
'controlPaddingHorizontalSM',
|
||||||
|
'paddingXXS',
|
||||||
|
'paddingXS',
|
||||||
|
'paddingSM',
|
||||||
|
'padding',
|
||||||
|
'paddingMD',
|
||||||
|
'paddingLG',
|
||||||
|
'paddingXL',
|
||||||
|
'paddingContentHorizontalLG',
|
||||||
|
'paddingContentVerticalLG',
|
||||||
|
'paddingContentHorizontal',
|
||||||
|
'paddingContentVertical',
|
||||||
|
'paddingContentHorizontalSM',
|
||||||
|
'paddingContentVerticalSM',
|
||||||
|
'marginXXS',
|
||||||
|
'marginXS',
|
||||||
|
'marginSM',
|
||||||
|
'margin',
|
||||||
|
'marginMD',
|
||||||
|
'marginLG',
|
||||||
|
'marginXL',
|
||||||
|
'marginXXL',
|
||||||
|
'boxShadow',
|
||||||
|
'boxShadowSecondary',
|
||||||
|
'boxShadowTertiary',
|
||||||
|
'screenXS',
|
||||||
|
'screenXSMin',
|
||||||
|
'screenXSMax',
|
||||||
|
'screenSM',
|
||||||
|
'screenSMMin',
|
||||||
|
'screenSMMax',
|
||||||
|
'screenMD',
|
||||||
|
'screenMDMin',
|
||||||
|
'screenMDMax',
|
||||||
|
'screenLG',
|
||||||
|
'screenLGMin',
|
||||||
|
'screenLGMax',
|
||||||
|
'screenXL',
|
||||||
|
'screenXLMin',
|
||||||
|
'screenXLMax',
|
||||||
|
'screenXXL',
|
||||||
|
'screenXXLMin'
|
||||||
|
]
|
||||||
|
|
||||||
|
export const generateThemeCssVariables = (theme: AntdToken) => {
|
||||||
|
const cssContent = cssVariables
|
||||||
|
.map((variable) => `--${variable}: ${theme[variable]};`)
|
||||||
|
.join('\n')
|
||||||
|
|
||||||
|
return css`
|
||||||
|
:root {
|
||||||
|
${cssContent}
|
||||||
|
}
|
||||||
|
`
|
||||||
|
}
|
||||||
|
|
||||||
|
export const addExtraCssVariables = (monaco: Monaco) => {
|
||||||
|
monaco.languages.registerCompletionItemProvider('css', {
|
||||||
|
provideCompletionItems: (
|
||||||
|
model: editor.ITextModel,
|
||||||
|
position: Position
|
||||||
|
): languages.ProviderResult<languages.CompletionList> => {
|
||||||
|
const textUntilPosition = model.getValueInRange({
|
||||||
|
startLineNumber: 1,
|
||||||
|
startColumn: 1,
|
||||||
|
endLineNumber: position.lineNumber,
|
||||||
|
endColumn: position.column
|
||||||
|
})
|
||||||
|
if (!textUntilPosition.match(/var\(([^)]*)$/)) {
|
||||||
|
return { suggestions: [] }
|
||||||
|
}
|
||||||
|
|
||||||
|
const word = model.getWordUntilPosition(position)
|
||||||
|
const range = new monaco.Range(
|
||||||
|
position.lineNumber,
|
||||||
|
word.startColumn,
|
||||||
|
position.lineNumber,
|
||||||
|
word.endColumn
|
||||||
|
)
|
||||||
|
|
||||||
|
return {
|
||||||
|
suggestions: cssVariables.map(
|
||||||
|
(variable): languages.CompletionItem => ({
|
||||||
|
label: `--${variable}`,
|
||||||
|
kind: monaco.languages.CompletionItemKind.Variable,
|
||||||
|
insertText: `--${variable}`,
|
||||||
|
range,
|
||||||
|
detail: 'Oxygen Theme Variable'
|
||||||
|
})
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export const removeUselessAttributes = (theme: Omit<Theme, 'prefixCls'>) => {
|
||||||
|
const {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||||
|
// @ts-expect-error
|
||||||
|
Tree,
|
||||||
|
appearance,
|
||||||
|
browserPrefers,
|
||||||
|
isDarkMode,
|
||||||
|
setAppearance,
|
||||||
|
setThemeMode,
|
||||||
|
stylish,
|
||||||
|
themeMode,
|
||||||
|
wireframe,
|
||||||
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||||
|
// @ts-expect-error
|
||||||
|
_tokenKey,
|
||||||
|
...result
|
||||||
|
} = theme
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|||||||
1581
src/renderer/src/util/editorExtraLibs/_index.d.ts
vendored
1581
src/renderer/src/util/editorExtraLibs/_index.d.ts
vendored
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user