hold off on context menu

This commit is contained in:
ChrisColeTech
2024-09-01 22:03:09 -04:00
parent f76e7ee2e0
commit d074afcab7
6 changed files with 1 additions and 1481 deletions
+1 -1
View File
@@ -1,7 +1,7 @@
[project]
name = "comfyui-line-counter"
description = "This custom node package for ComfyUI is designed to streamline your workflow with powerful file-counting capabilities."
version = "1.0.3"
version = "1.0.4"
license = {file = "LICENSE"}
[project.urls]
-623
View File
@@ -1,623 +0,0 @@
.elegant-top-messages-container {
position: fixed;
z-index: 9999;
top: 0;
left: 0;
width: 100%;
height: 0;
display: flex;
flex-direction: column;
align-items: center;
justify-content: start;
}
.elegant-top-messages-container > div {
position: relative;
height: fit-content;
padding: 4px;
margin-top: -100px; /* re-set by JS */
opacity: 0;
transition: all 0.33s ease-in-out;
z-index: 3;
}
.elegant-top-messages-container > div:last-child {
z-index: 2;
}
.elegant-top-messages-container > div:not(.-show) {
z-index: 1;
}
.elegant-top-messages-container > div.-show {
opacity: 1;
margin-top: 0px !important;
}
.elegant-top-messages-container > div.-show {
opacity: 1;
transform: translateY(0%);
}
.elegant-top-messages-container > div > div {
position: relative;
background: #353535;
color: #fff;
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
height: fit-content;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.88);
padding: 6px 12px;
border-radius: 4px;
font-family: Arial, sans-serif;
font-size: 14px;
}
.elegant-top-messages-container > div > div > span {
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
}
.elegant-top-messages-container > div > div > span svg {
width: 20px;
height: auto;
margin-right: 8px;
}
.elegant-top-messages-container > div > div > span svg.icon-checkmark {
fill: #2e9720;
}
.elegant-top-messages-container [type='warn']::before,
.elegant-top-messages-container [type='success']::before {
content: '⚠️';
display: inline-block;
flex: 0 0 auto;
font-size: 18px;
margin-right: 4px;
line-height: 1;
}
.elegant-top-messages-container [type='success']::before {
content: '🎉';
}
.elegant-top-messages-container a {
cursor: pointer;
text-decoration: underline;
color: #fc0;
margin-left: 4px;
display: inline-block;
line-height: 1;
}
.elegant-top-messages-container a:hover {
color: #fc0;
text-decoration: none;
}
/* Fix node selector being crazy long b/c of array types. */
.litegraph.litesearchbox input,
.litegraph.litesearchbox select {
max-width: 250px;
}
/* There's no reason for this z-index to be so high. It layers on top of things it shouldn't,
(like pythongssss' image gallery, the properties panel, etc.) */
.comfy-multiline-input {
z-index: 1 !important;
}
.comfy-multiline-input:focus {
z-index: 2 !important;
}
.litegraph .dialog {
z-index: 3 !important; /* This is set to 1, but goes under the multi-line inputs, so bump it. */
}
:not(#fakeid) .elegant-button-reset {
position: relative;
appearance: none;
cursor: pointer;
border: 0;
background: transparent;
color: inherit;
padding: 0;
margin: 0;
}
:not(#fakeid) .elegant-button {
--padding-top: 7px;
--padding-bottom: 9px;
--padding-x: 16px;
position: relative;
cursor: pointer;
border: 0;
border-radius: 0.25rem;
background: rgba(0, 0, 0, 0.5);
color: white;
font-family: system-ui, sans-serif;
font-size: 1rem;
line-height: 1;
white-space: nowrap;
text-decoration: none;
margin: 0.25rem;
box-shadow: 0px 0px 2px rgb(0, 0, 0);
background: #212121;
transition: all 0.1s ease-in-out;
padding: var(--padding-top) var(--padding-x) var(--padding-bottom);
display: inline-flex;
flex-direction: row;
align-items: center;
justify-content: center;
}
:not(#fakeid) .elegant-button::before,
:not(#fakeid) .elegant-button::after {
content: '';
display: block;
position: absolute;
border-radius: 0.25rem;
left: 0;
top: 0;
width: 100%;
height: 100%;
box-shadow: inset 1px 1px 0px rgba(255, 255, 255, 0.12), inset -1px -1px 0px rgba(0, 0, 0, 0.75);
background: linear-gradient(to bottom, rgba(255, 255, 255, 0.06), rgba(0, 0, 0, 0.15));
mix-blend-mode: screen;
}
:not(#fakeid) .elegant-button::after {
mix-blend-mode: multiply;
}
:not(#fakeid) .elegant-button:hover {
background: #303030;
}
:not(#fakeid) .elegant-button:active {
box-shadow: 0px 0px 0px rgba(0, 0, 0, 0);
background: #121212;
padding: calc(var(--padding-top) + 1px) calc(var(--padding-x) - 1px)
calc(var(--padding-bottom) - 1px) calc(var(--padding-x) + 1px);
}
:not(#fakeid) .elegant-button:active::before,
:not(#fakeid) .elegant-button:active::after {
box-shadow: 1px 1px 0px rgba(255, 255, 255, 0.15), inset 1px 1px 0px rgba(0, 0, 0, 0.5),
inset 1px 3px 5px rgba(0, 0, 0, 0.33);
}
:not(#fakeid) .elegant-button.-blue {
background: #346599 !important;
}
:not(#fakeid) .elegant-button.-blue:hover {
background: #3b77b8 !important;
}
:not(#fakeid) .elegant-button.-blue:active {
background: #1d5086 !important;
}
:not(#fakeid) .elegant-button.-green {
background: linear-gradient(to bottom, rgba(255, 255, 255, 0.06), rgba(0, 0, 0, 0.15)), #14580b;
}
:not(#fakeid) .elegant-button.-green:hover {
background: linear-gradient(to bottom, rgba(255, 255, 255, 0.06), rgba(0, 0, 0, 0.15)), #1a6d0f;
}
:not(#fakeid) .elegant-button.-green:active {
background: linear-gradient(to bottom, rgba(0, 0, 0, 0.15), rgba(255, 255, 255, 0.06)), #0f3f09;
}
:not(#fakeid) .elegant-button[disabled] {
box-shadow: none;
background: #666 !important;
color: #aaa;
pointer-events: none;
}
:not(#fakeid) .elegant-button[disabled]::before,
:not(#fakeid) .elegant-button[disabled]::after {
display: none;
}
.elegant-dialog {
outline: 0;
border: 0;
border-radius: 6px;
background: #414141;
color: #fff;
box-shadow: inset 1px 1px 0px rgba(255, 255, 255, 0.05), inset -1px -1px 0px rgba(0, 0, 0, 0.5),
2px 2px 20px rgb(0, 0, 0);
max-width: 800px;
box-sizing: border-box;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
font-size: 1rem;
padding: 0;
max-height: calc(100% - 32px);
}
.elegant-dialog *,
.elegant-dialog *::before,
.elegant-dialog *::after {
box-sizing: inherit;
}
.elegant-dialog-container > * {
padding: 8px 16px;
}
.elegant-dialog-container > *:first-child {
padding-top: 16px;
}
.elegant-dialog-container > *:last-child {
padding-bottom: 16px;
}
.elegant-dialog.-iconed::after {
content: '';
font-size: 276px;
position: absolute;
right: 0px;
bottom: 0px;
opacity: 0.15;
display: block;
width: 237px;
overflow: hidden;
height: 186px;
line-height: 1;
pointer-events: none;
z-index: -1;
}
.elegant-dialog.-iconed.-help::after {
content: '🛟';
}
.elegant-dialog.-iconed.-settings::after {
content: '⚙️';
}
@media (max-width: 832px) {
.elegant-dialog {
max-width: calc(100% - 32px);
}
}
.elegant-dialog-container-title {
display: flex;
flex-direction: row;
align-items: center;
justify-content: start;
}
.elegant-dialog-container-title > svg:first-child {
width: 36px;
height: 36px;
margin-right: 16px;
}
.elegant-dialog-container-title h2 {
font-size: 1.375rem;
margin: 0;
font-weight: bold;
}
.elegant-dialog-container-title h2 small {
font-size: 0.8125rem;
font-weight: normal;
opacity: 0.75;
}
.elegant-dialog-container-content {
overflow: auto;
max-height: calc(100vh - 200px); /* Arbitrary height to copensate for margin, title, and footer.*/
}
.elegant-dialog-container-content p {
font-size: 0.8125rem;
margin-top: 0;
}
.elegant-dialog-container-content ul li p {
margin-bottom: 4px;
}
.elegant-dialog-container-content ul li p + p {
margin-top: 0.5em;
}
.elegant-dialog-container-content ul li ul {
margin-top: 0.5em;
margin-bottom: 1em;
}
.elegant-dialog-container-content p code {
display: inline-block;
padding: 2px 4px;
margin: 0px 2px;
border: 1px solid rgba(255, 255, 255, 0.25);
border-radius: 3px;
background: rgba(255, 255, 255, 0.1);
}
.elegant-dialog-container-footer {
display: flex;
align-items: center;
justify-content: center;
}
body.elegant-dialog-open > *:not(.elegant-dialog):not(.elegant-top-messages-container) {
filter: blur(5px);
}
.elegant-menu {
list-style: none;
padding: 0;
margin: 0;
position: fixed;
z-index: 999999;
pointer-events: none;
opacity: 0;
transition: opacity 0.08s ease-in-out;
color: #dde;
background-color: #111;
font-size: 12px;
box-shadow: 0 0 10px black !important;
}
.elegant-menu > li {
position: relative;
padding: 4px 6px;
z-index: 9999;
white-space: nowrap;
}
.elegant-menu > li[role='button'] {
background-color: var(--comfy-menu-bg) !important;
color: var(--input-text);
cursor: pointer;
}
.elegant-menu > li[role='button']:hover {
filter: brightness(155%);
}
.elegant-menu[state^='measuring'] {
display: block;
opacity: 0;
}
.elegant-menu[state='open'] {
display: block;
opacity: 1;
pointer-events: all;
}
.elegant-top-menu {
box-sizing: border-box;
white-space: nowrap;
background: var(--content-bg);
color: var(--content-fg);
display: flex;
flex-direction: column;
}
.elegant-top-menu * {
box-sizing: inherit;
}
.elegant-top-menu menu {
list-style: none;
padding: 0;
margin: 0;
}
.elegant-top-menu menu > li:not(#fakeid) {
list-style: none;
padding: 0;
margin: 0;
}
.elegant-top-menu menu > li:not(#fakeid) > button {
cursor: pointer;
padding: 8px 12px 8px 8px;
width: 100%;
text-align: start;
display: flex;
flex-direction: row;
align-items: center;
justify-content: start;
}
.elegant-top-menu menu > li:not(#fakeid) > button:hover {
background-color: var(--comfy-input-bg);
}
.elegant-top-menu menu > li:not(#fakeid) > button svg {
height: 16px;
width: auto;
margin-inline-end: 0.6em;
}
.elegant-top-menu menu > li:not(#fakeid) > button svg.github-star {
fill: rgb(227, 179, 65);
}
.elegant-top-menu menu > li:not(#fakeid).elegant-message {
min-height: 32px;
}
.elegant-top-menu menu > li:not(#fakeid).elegant-message > span {
padding: 8px 12px;
display: block;
width: 100%;
text-align: center;
font-style: italic;
font-size: 12px;
}
.elegant-dialog.-settings {
width: 100%;
}
.elegant-dialog.-settings fieldset {
border: 1px solid rgba(255, 255, 255, 0.25);
padding: 0 12px 8px;
margin-bottom: 16px;
}
.elegant-dialog.-settings fieldset > legend {
margin-left: 8px;
padding: 0 8px;
opacity: 0.5;
}
.elegant-dialog.-settings .formrow {
display: flex;
flex-direction: column;
}
.elegant-dialog.-settings .formrow + .formrow {
border-top: 1px solid rgba(255, 255, 255, 0.25);
}
.elegant-dialog.-settings .fieldrow {
display: flex;
flex-direction: row;
}
.elegant-dialog.-settings .fieldrow > label {
flex: 1 1 auto;
user-select: none;
padding: 8px 12px 12px;
}
.elegant-dialog.-settings .fieldrow > label span {
font-weight: bold;
}
.elegant-dialog.-settings .fieldrow > label small {
display: block;
margin-top: 4px;
font-size: 0.6875rem;
opacity: 0.75;
padding-left: 16px;
}
.elegant-dialog.-settings .fieldrow ~ .fieldrow {
font-size: 0.9rem;
border-top: 1px dotted rgba(255, 255, 255, 0.25);
}
.elegant-dialog.-settings .fieldrow ~ .fieldrow label {
padding-left: 28px;
}
.elegant-dialog.-settings .fieldrow:first-child:not(.-checked) ~ .fieldrow {
display: none;
}
.elegant-dialog.-settings .fieldrow:hover {
background: rgba(255, 255, 255, 0.1);
}
.elegant-dialog.-settings .fieldrow ~ .fieldrow span {
font-weight: normal;
}
.elegant-dialog.-settings .fieldrow > .fieldrow-value {
display: flex;
align-items: center;
justify-content: end;
flex: 0 0 auto;
width: 50%;
max-width: 230px;
}
.elegant-dialog.-settings .fieldrow.-type-boolean > .fieldrow-value {
max-width: 64px;
}
.elegant-dialog.-settings .fieldrow.-type-number input {
width: 48px;
text-align: right;
}
.elegant-dialog.-settings .fieldrow input[type='checkbox'] {
width: 24px;
height: 24px;
cursor: pointer;
}
.elegant-comfyui-settings-row div {
display: flex;
flex-direction: row;
align-items: center;
justify-content: end;
}
.elegant-comfyui-settings-row div svg {
width: 36px;
height: 36px;
margin-right: 16px;
}
.litegraph.litecontextmenu .litemenu-title .elegant-contextmenu-title-elegant-comfy,
.litegraph.litecontextmenu .litemenu-entry.elegant-contextmenu-item {
display: flex;
flex-direction: row;
align-items: center;
justify-content: start;
}
.litegraph.litecontextmenu .litemenu-title .elegant-contextmenu-title-elegant-comfy svg,
.litegraph.litecontextmenu .litemenu-entry.elegant-contextmenu-item svg {
fill: currentColor;
width: auto;
height: 16px;
margin-right: 6px;
}
.litegraph.litecontextmenu .litemenu-entry.elegant-contextmenu-item svg.github-star {
fill: rgb(227, 179, 65);
}
.litegraph.litecontextmenu .litemenu-title .elegant-contextmenu-title-elegant-comfy,
.litegraph.litecontextmenu .litemenu-entry.elegant-contextmenu-label {
color: #dde;
background-color: #212121 !important;
margin: 0;
padding: 2px;
cursor: default;
opacity: 1;
padding: 4px;
font-weight: bold;
}
.litegraph.litecontextmenu .litemenu-title .elegant-contextmenu-title-elegant-comfy {
font-size: 1.1em;
color: #fff;
background-color: #090909 !important;
justify-content: center;
padding: 4px 8px;
}
elegant-progress-bar {
display: block;
position: relative;
z-index: 999;
top: 0;
left: 0;
height: 14px;
font-size: 10px;
width: 100%;
overflow: hidden;
box-shadow: 0px 0px 3px rgba(0, 0, 0, 0.25);
box-shadow: inset 0px -1px 0px rgba(0, 0, 0, 0.25), 0px 1px 0px rgba(255, 255, 255, 0.125);
}
* ~ elegant-progress-bar,
.comfyui-body-bottom elegant-progress-bar {
box-shadow: 0px -1px 0px rgb(0, 0, 0), inset 0px 1px 0px rgba(255, 255, 255, 0.15),
inset 0px -1px 0px rgba(0, 0, 0, 0.25), 0px 1px 0px rgba(255, 255, 255, 0.125);
}
body:not([style*='grid']) elegant-progress-bar {
position: fixed;
top: 0px;
bottom: auto;
}
body:not([style*='grid']) elegant-progress-bar.elegant-pos-bottom {
top: auto;
bottom: 0px;
}
.elegant-debug-keydowns {
display: block;
position: fixed;
z-index: 999;
top: 3px;
right: 8px;
font-size: 10px;
color: #fff;
font-family: sans-serif;
}
-291
View File
@@ -1,291 +0,0 @@
import { app, ComfyApp } from '/scripts/app.js'
import { api } from '/scripts/api.js'
import { iconGear, iconNode, iconReplace, iconStarFilled } from './svgs.js'
import { injectCss } from './shared_utils.js'
class Elegant extends EventTarget {
constructor() {
var _a, _b, _c, _d
super()
this.api = api
this.settingsDialog = null
this.progressBarEl = null
this.queueNodeIds = null
this.monitorBadLinksAlerted = false
this.monitorLinkTimeout = null
this.processingQueue = false
this.loadingApiJson = false
this.replacingReroute = null
this.processingMouseDown = false
this.processingMouseUp = false
this.processingMouseMove = false
this.lastAdjustedMouseEvent = null
this.canvasCurrentlyCopyingToClipboard = false
this.canvasCurrentlyCopyingToClipboardWithMultipleNodes = false
this.initialGraphToPromptSerializedWorkflowBecauseComfyUIBrokeStuff = null
this.elDebugKeydowns = null
this.nodes = []
this.isMac = !!(
((_a = navigator.platform) === null || _a === void 0
? void 0
: _a.toLocaleUpperCase().startsWith('MAC')) ||
((_c = (_b = navigator.userAgentData) === null || _b === void 0 ? void 0 : _b.platform) ===
null || _c === void 0
? void 0
: _c.toLocaleUpperCase().startsWith('MAC'))
)
this.initializeGraphAndCanvasHooks()
// Wrap the method
const originalGetNodeDefs = api.getNodeDefs.bind(api)
api.getNodeDefs = async function (...args) {
// Trigger a custom event before calling the original method
const event = new CustomEvent('getNodeDefsCalled', {
detail: { args },
})
window.dispatchEvent(event)
// Call the original method
const result = await originalGetNodeDefs(...args)
// Optionally, you can also dispatch another event after the method completes
window.dispatchEvent(
new CustomEvent('getNodeDefsCompleted', {
detail: { result },
}),
)
return result
}
// Add event listeners
window.addEventListener('getNodeDefsCalled', (event) => {})
window.addEventListener('getNodeDefsCompleted', (event) => {
this.nodes = Object.values(event.detail.result).filter((n) => n.category.includes('CCTech'))
})
this.initializeContextMenu()
this.cssPromise = injectCss('extensions/ComfyUI-Line-counter/comfyui/elegant.css')
}
async initializeGraphAndCanvasHooks() {
const elegant = this
const graphSerialize = LGraph.prototype.serialize
LGraph.prototype.serialize = function () {
const response = graphSerialize.apply(this, [...arguments])
elegant.initialGraphToPromptSerializedWorkflowBecauseComfyUIBrokeStuff = response
return response
}
const processMouseDown = LGraphCanvas.prototype.processMouseDown
LGraphCanvas.prototype.processMouseDown = function (e) {
elegant.processingMouseDown = true
const returnVal = processMouseDown.apply(this, [...arguments])
elegant.dispatchCustomEvent('on-process-mouse-down', { originalEvent: e })
elegant.processingMouseDown = false
return returnVal
}
const adjustMouseEvent = LGraphCanvas.prototype.adjustMouseEvent
LGraphCanvas.prototype.adjustMouseEvent = function (e) {
adjustMouseEvent.apply(this, [...arguments])
elegant.lastAdjustedMouseEvent = e
}
const copyToClipboard = LGraphCanvas.prototype.copyToClipboard
LGraphCanvas.prototype.copyToClipboard = function (nodes) {
elegant.canvasCurrentlyCopyingToClipboard = true
elegant.canvasCurrentlyCopyingToClipboardWithMultipleNodes =
Object.values(nodes || this.selected_nodes || []).length > 1
copyToClipboard.apply(this, [...arguments])
elegant.canvasCurrentlyCopyingToClipboard = false
elegant.canvasCurrentlyCopyingToClipboardWithMultipleNodes = false
}
const onGroupAdd = LGraphCanvas.onGroupAdd
LGraphCanvas.onGroupAdd = function (...args) {
const graph = app.graph
onGroupAdd.apply(this, [...args])
LGraphCanvas.onShowPropertyEditor(
{},
null,
null,
null,
graph._groups[graph._groups.length - 1],
)
}
}
async invokeExtensionsAsync(method, ...args) {
return Promise.resolve()
}
dispatchCustomEvent(event, detail) {
if (detail != null) {
return this.dispatchEvent(new CustomEvent(event, { detail }))
}
return this.dispatchEvent(new CustomEvent(event))
}
async initializeContextMenu() {
const that = this
setTimeout(async () => {
const getCanvasMenuOptions = LGraphCanvas.prototype.getCanvasMenuOptions
LGraphCanvas.prototype.getCanvasMenuOptions = function (...args) {
let existingOptions = getCanvasMenuOptions.apply(this, [...args])
const options = []
options.push(null)
options.push(null)
options.push(null)
options.push({
content: `🤖 CCTech`,
className: 'elegant-contextmenu-item elegant-contextmenu-main-item-elegant-comfy',
submenu: {
options: that.getElegantContextMenuItems(),
},
})
options.push(null)
options.push(null)
let idx = null
idx =
idx ||
existingOptions.findIndex((o) => {
var _a, _b
return (_b =
(_a = o === null || o === void 0 ? void 0 : o.content) === null || _a === void 0
? void 0
: _a.startsWith) === null || _b === void 0
? void 0
: _b.call(_a, 'Queue Group')
}) + 1
idx =
idx ||
existingOptions.findIndex((o) => {
var _a, _b
return (_b =
(_a = o === null || o === void 0 ? void 0 : o.content) === null || _a === void 0
? void 0
: _a.startsWith) === null || _b === void 0
? void 0
: _b.call(_a, 'Queue Selected')
}) + 1
idx =
idx ||
existingOptions.findIndex((o) => {
var _a, _b
return (_b =
(_a = o === null || o === void 0 ? void 0 : o.content) === null || _a === void 0
? void 0
: _a.startsWith) === null || _b === void 0
? void 0
: _b.call(_a, 'Convert to Group')
})
idx =
idx ||
existingOptions.findIndex((o) => {
var _a, _b
return (_b =
(_a = o === null || o === void 0 ? void 0 : o.content) === null || _a === void 0
? void 0
: _a.startsWith) === null || _b === void 0
? void 0
: _b.call(_a, 'Arrange (')
})
idx = idx || existingOptions.findIndex((o) => !o) + 1
idx = idx || 3
existingOptions.splice(idx, 0, ...options)
for (let i = existingOptions.length; i > 0; i--) {
if (existingOptions[i] === null && existingOptions[i + 1] === null) {
existingOptions.splice(i, 1)
}
}
return existingOptions
}
}, 1016)
}
getElegantContextMenuItems() {
const [canvas, graph] = [app.canvas, app.graph]
const selectedNodes = Object.values(canvas.selected_nodes || {})
let rerouteNodes = []
if (selectedNodes.length) {
rerouteNodes = selectedNodes.filter((n) => n.type === 'Reroute')
} else {
rerouteNodes = graph._nodes.filter((n) => n.type == 'Reroute')
}
const rerouteLabel = selectedNodes.length ? 'selected' : 'all'
const bookmarkMenuItems = getBookmarks() ?? []
return [
{
content: 'Nodes',
disabled: true,
className: 'elegant-contextmenu-item elegant-contextmenu-label',
},
{
content: iconNode + 'All',
className: 'elegant-contextmenu-item',
has_submenu: true,
submenu: {
options: this.nodes.map((n) => n.display_name),
callback: (value, options, event) => {
const nodeValue = this.nodes.find((n) => n.display_name.includes(value))
const node = LiteGraph.createNode(nodeValue.name)
node.pos = [this.lastAdjustedMouseEvent.canvasX, this.lastAdjustedMouseEvent.canvasY]
canvas.graph.add(node)
canvas.selectNode(node)
app.graph.setDirtyCanvas(true, true)
},
extra: { elegant_doNotNest: true },
},
},
// {
// content: 'Actions',
// disabled: true,
// className: 'elegant-contextmenu-item elegant-contextmenu-label',
// },
// {
// content: iconGear + 'Settings (coming soon)',
// disabled: true,
// className: 'elegant-contextmenu-item',
// callback: (...args) => {
// this.settingsDialog.addEventListener('close', (e) => {
// this.settingsDialog = null
// })
// },
// },
...bookmarkMenuItems,
{
content: 'More...',
disabled: true,
className: 'elegant-contextmenu-item elegant-contextmenu-label',
},
{
content: iconStarFilled + 'Star on Github',
className: 'elegant-contextmenu-item elegant-contextmenu-github',
callback: (...args) => {
window.open('https://github.com/ChrisColeTech/', '_blank')
},
},
]
}
}
function getBookmarks() {
const graph = app.graph
const bookmarks = graph._nodes
.filter((n) => n.type === 'NodeTypesString.BOOKMARK')
.sort((a, b) => a.title.localeCompare(b.title))
.map((n) => ({
content: `[${n.shortcutKey}] ${n.title}`,
className: 'elegant-contextmenu-item',
callback: () => {
n.canvasToBookmark()
},
}))
return !bookmarks.length
? []
: [
{
content: '🔖 Bookmarks',
disabled: true,
className: 'elegant-contextmenu-item elegant-contextmenu-label',
},
...bookmarks,
]
}
export const elegant = new Elegant()
window.elegant = elegant
-115
View File
@@ -1,115 +0,0 @@
export function getResolver(timeout = 5000) {
const resolver = {}
resolver.id = generateId(8)
resolver.completed = false
resolver.resolved = false
resolver.rejected = false
resolver.promise = new Promise((resolve, reject) => {
resolver.reject = () => {
resolver.completed = true
resolver.rejected = true
reject()
}
resolver.resolve = (data) => {
resolver.completed = true
resolver.resolved = true
resolve(data)
}
})
resolver.timeout = setTimeout(() => {
if (!resolver.completed) {
resolver.reject()
}
}, timeout)
return resolver
}
const DEBOUNCE_FN_TO_PROMISE = new WeakMap()
export function debounce(fn, ms = 64) {
if (!DEBOUNCE_FN_TO_PROMISE.get(fn)) {
DEBOUNCE_FN_TO_PROMISE.set(
fn,
wait(ms).then(() => {
DEBOUNCE_FN_TO_PROMISE.delete(fn)
fn()
}),
)
}
return DEBOUNCE_FN_TO_PROMISE.get(fn)
}
export function wait(ms = 16) {
if (ms === 16) {
return new Promise((resolve) => {
requestAnimationFrame(() => {
resolve()
})
})
}
return new Promise((resolve) => {
setTimeout(() => {
resolve()
}, ms)
})
}
function dec2hex(dec) {
return dec.toString(16).padStart(2, '0')
}
export function generateId(length) {
const arr = new Uint8Array(length / 2)
crypto.getRandomValues(arr)
return Array.from(arr, dec2hex).join('')
}
export function getObjectValue(obj, objKey, def) {
if (!obj || !objKey) return def
const keys = objKey.split('.')
const key = keys.shift()
const found = obj[key]
if (keys.length) {
return getObjectValue(found, keys.join('.'), def)
}
return found
}
export function setObjectValue(obj, objKey, value, createMissingObjects = true) {
if (!obj || !objKey) return obj
const keys = objKey.split('.')
const key = keys.shift()
if (obj[key] === undefined) {
if (!createMissingObjects) {
return
}
obj[key] = {}
}
if (!keys.length) {
obj[key] = value
} else {
if (typeof obj[key] != 'object') {
obj[key] = {}
}
setObjectValue(obj[key], keys.join('.'), value, createMissingObjects)
}
return obj
}
export function moveArrayItem(arr, itemOrFrom, to) {
const from = typeof itemOrFrom === 'number' ? itemOrFrom : arr.indexOf(itemOrFrom)
arr.splice(to, 0, arr.splice(from, 1)[0])
}
export function removeArrayItem(arr, itemOrIndex) {
const index = typeof itemOrIndex === 'number' ? itemOrIndex : arr.indexOf(itemOrIndex)
arr.splice(index, 1)
}
export function injectCss(href) {
if (document.querySelector(`link[href^="${href}"]`)) {
return Promise.resolve()
}
return new Promise((resolve) => {
const link = document.createElement('link')
link.setAttribute('rel', 'stylesheet')
link.setAttribute('type', 'text/css')
const timeout = setTimeout(resolve, 1000)
link.addEventListener('load', (e) => {
clearInterval(timeout)
resolve()
})
link.href = href
document.head.appendChild(link)
})
}
-160
View File
@@ -1,160 +0,0 @@
import { createElement as $el } from './utils_dom.js'
export const logoElegant = `<svg viewBox="0 0 256 256" fill="currentColor" class="rgthree-logo">
<path d="M88.503,158.997 L152.731,196.103 L152.738,196.092 L152.762,196.103 L152.769,196.106 L152.771,196.103 L183.922,142.084 L174.153,136.437 L148.611,180.676 L101.512,153.484 L132.193,30.415 L156.124,71.869 L165.896,66.225 L128.002,0.59 "></path>
<path d="M55.586,148.581l13.44,47.521l0.014,0.051l0.168-0.051l10.689-3.022l-6.589-23.313l45.609,26.335l0.087,0.051l0.027-0.051 l5.617-9.718l-42.648-24.622l35.771-143.45L33.232,164.729l9.77,5.645L55.586,148.581z M87.394,93.484l-16.708,67.018l-5.018-17.747 l-8.028,2.27L87.394,93.484z"></path>
<path d="M189.85,107.717 L137.892,137.718 L143.532,147.49 L185.723,123.133 L231.109,201.746 L24.895,201.746 L37.363,180.146 L27.592,174.505 L5.347,213.03 L250.653,213.03 "></path>
<path d="M5.347,247.299v8.111h245.307v-8.111l-41.94-0.003c-1.336,0-2.404-1.065-2.441-2.396v-12.14 c0.037-1.315,1.089-2.368,2.41-2.385h41.972v-8.11H5.347v8.11h41.951c1.338,0.017,2.427,1.104,2.427,2.449v12.01 c0,1.365-1.105,2.462-2.457,2.462L5.347,247.299z M139.438,247.296c-1.334,0-2.406-1.065-2.439-2.396v-12.14 c0.033-1.315,1.085-2.368,2.41-2.385h46.415c1.335,0.017,2.425,1.104,2.425,2.449v12.01c0,1.365-1.103,2.462-2.459,2.462H139.438z M70.193,247.296c-1.339,0-2.408-1.065-2.441-2.396v-12.14c0.033-1.315,1.086-2.368,2.407-2.385h46.418 c1.336,0.017,2.425,1.104,2.425,2.449v12.01c0,1.365-1.103,2.462-2.458,2.462H70.193z"></path>
</svg>`
export const github = `<svg viewBox="0 0 16 16" fill="currentColor" class="github-logo">
<path d="M8 0c4.42 0 8 3.58 8 8a8.013 8.013 0 0 1-5.45 7.59c-.4.08-.55-.17-.55-.38 0-.27.01-1.13.01-2.2 0-.75-.25-1.23-.54-1.48 1.78-.2 3.65-.88 3.65-3.95 0-.88-.31-1.59-.82-2.15.08-.2.36-1.02-.08-2.12 0 0-.67-.22-2.2.82-.64-.18-1.32-.27-2-.27-.68 0-1.36.09-2 .27-1.53-1.03-2.2-.82-2.2-.82-.44 1.1-.16 1.92-.08 2.12-.51.56-.82 1.28-.82 2.15 0 3.06 1.86 3.75 3.64 3.95-.23.2-.44.55-.51 1.07-.46.21-1.61.55-2.33-.66-.15-.24-.6-.83-1.23-.82-.67.01-.27.38.01.53.34.19.73.9.82 1.13.16.45.68 1.31 2.69.94 0 .67.01 1.3.01 1.49 0 .21-.15.45-.55.38A7.995 7.995 0 0 1 0 8c0-4.42 3.58-8 8-8Z"></path>
</svg>`
export const iconStarFilled = `<svg viewBox="0 0 16 16" fill="currentColor" class="github-star">
<path d="M8 .25a.75.75 0 0 1 .673.418l1.882 3.815 4.21.612a.75.75 0 0 1 .416 1.279l-3.046 2.97.719 4.192a.751.751 0 0 1-1.088.791L8 12.347l-3.766 1.98a.75.75 0 0 1-1.088-.79l.72-4.194L.818 6.374a.75.75 0 0 1 .416-1.28l4.21-.611L7.327.668A.75.75 0 0 1 8 .25Z"></path>
</svg>`
export const iconReplace = `<svg viewBox="0 0 52 52" fill="currentColor">
<path d="M20,37.5c0-0.8-0.7-1.5-1.5-1.5h-15C2.7,36,2,36.7,2,37.5v11C2,49.3,2.7,50,3.5,50h15c0.8,0,1.5-0.7,1.5-1.5 V37.5z"/>
<path d="M8.1,22H3.2c-1,0-1.5,0.9-0.9,1.4l8,8.3c0.4,0.3,1,0.3,1.4,0l8-8.3c0.6-0.6,0.1-1.4-0.9-1.4h-4.7 c0-5,4.9-10,9.9-10V6C15,6,8.1,13,8.1,22z"/>
<path d="M41.8,20.3c-0.4-0.3-1-0.3-1.4,0l-8,8.3c-0.6,0.6-0.1,1.4,0.9,1.4h4.8c0,6-4.1,10-10.1,10v6 c9,0,16.1-7,16.1-16H49c1,0,1.5-0.9,0.9-1.4L41.8,20.3z"/>
<path d="M50,3.5C50,2.7,49.3,2,48.5,2h-15C32.7,2,32,2.7,32,3.5v11c0,0.8,0.7,1.5,1.5,1.5h15c0.8,0,1.5-0.7,1.5-1.5 V3.5z"/>
</svg>`
export const iconNode = `<svg viewBox="0 -0.5 25 25" fill="none">
<path fill-rule="evenodd" clip-rule="evenodd" d="M15.5 19H9.5C7.29086 19 5.5 17.2091 5.5 15V9C5.5 6.79086 7.29086 5 9.5 5H15.5C17.7091 5 19.5 6.79086 19.5 9V15C19.5 17.2091 17.7091 19 15.5 19Z" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M19.5 9.75C19.9142 9.75 20.25 9.41421 20.25 9C20.25 8.58579 19.9142 8.25 19.5 8.25V9.75ZM5.5 8.25C5.08579 8.25 4.75 8.58579 4.75 9C4.75 9.41421 5.08579 9.75 5.5 9.75V8.25ZM11.5 14.25C11.0858 14.25 10.75 14.5858 10.75 15C10.75 15.4142 11.0858 15.75 11.5 15.75V14.25ZM13.5 15.75C13.9142 15.75 14.25 15.4142 14.25 15C14.25 14.5858 13.9142 14.25 13.5 14.25V15.75ZM19.5 8.25H5.5V9.75H19.5V8.25ZM11.5 15.75H13.5V14.25H11.5V15.75Z" fill="currentColor" />
</svg>`
export const iconGear = `<svg viewBox="0 0 24 24" fill="currentColor">
<path fill-rule="evenodd" clip-rule="evenodd" d="M12.7848 0.449982C13.8239 0.449982 14.7167 1.16546 14.9122 2.15495L14.9991 2.59495C15.3408 4.32442 17.1859 5.35722 18.9016 4.7794L19.3383 4.63233C20.3199 4.30175 21.4054 4.69358 21.9249 5.56605L22.7097 6.88386C23.2293 7.75636 23.0365 8.86366 22.2504 9.52253L21.9008 9.81555C20.5267 10.9672 20.5267 13.0328 21.9008 14.1844L22.2504 14.4774C23.0365 15.1363 23.2293 16.2436 22.7097 17.1161L21.925 18.4339C21.4054 19.3064 20.3199 19.6982 19.3382 19.3676L18.9017 19.2205C17.1859 18.6426 15.3408 19.6754 14.9991 21.405L14.9122 21.845C14.7167 22.8345 13.8239 23.55 12.7848 23.55H11.2152C10.1761 23.55 9.28331 22.8345 9.08781 21.8451L9.00082 21.4048C8.65909 19.6754 6.81395 18.6426 5.09822 19.2205L4.66179 19.3675C3.68016 19.6982 2.59465 19.3063 2.07505 18.4338L1.2903 17.1161C0.770719 16.2436 0.963446 15.1363 1.74956 14.4774L2.09922 14.1844C3.47324 13.0327 3.47324 10.9672 2.09922 9.8156L1.74956 9.52254C0.963446 8.86366 0.77072 7.75638 1.2903 6.8839L2.07508 5.56608C2.59466 4.69359 3.68014 4.30176 4.66176 4.63236L5.09831 4.77939C6.81401 5.35722 8.65909 4.32449 9.00082 2.59506L9.0878 2.15487C9.28331 1.16542 10.176 0.449982 11.2152 0.449982H12.7848ZM12 15.3C13.8225 15.3 15.3 13.8225 15.3 12C15.3 10.1774 13.8225 8.69998 12 8.69998C10.1774 8.69998 8.69997 10.1774 8.69997 12C8.69997 13.8225 10.1774 15.3 12 15.3Z" />
</svg>`
export const checkmark = `<svg viewBox="0 0 32 32" fill="currentColor" class="icon-checkmark">
<g transform="translate(-518.000000, -1039.000000)">
<path d="M548.783,1040.2 C547.188,1038.57 544.603,1038.57 543.008,1040.2 L528.569,1054.92 L524.96,1051.24 C523.365,1049.62 520.779,1049.62 519.185,1051.24 C517.59,1052.87 517.59,1055.51 519.185,1057.13 L525.682,1063.76 C527.277,1065.39 529.862,1065.39 531.457,1063.76 L548.783,1046.09 C550.378,1044.46 550.378,1041.82 548.783,1040.2"></path>
</g>
</svg>`
export const logoCivitai = `<svg viewBox="0 0 178 178" class="logo-civitai">
<defs>
<linearGradient id="bgblue" gradientUnits="userSpaceOnUse" x1="89.3" y1="-665.5" x2="89.3" y2="-841.1" gradientTransform="matrix(1 0 0 -1 0 -664)">
<stop offset="0" style="stop-color:#1284F7"/>
<stop offset="1" style="stop-color:#0A20C9"/>
</linearGradient>
</defs>
<path fill="#000" d="M13.3,45.4v87.7l76,43.9l76-43.9V45.4l-76-43.9L13.3,45.4z"/>
<path style="fill:url(#bgblue);" d="M89.3,29.2l52,30v60l-52,30l-52-30v-60 L89.3,29.2 M89.3,1.5l-76,43.9v87.8l76,43.9l76-43.9V45.4L89.3,1.5z" />
<path fill="#FFF" d="M104.1,97.2l-14.9,8.5l-14.9-8.5v-17l14.9-8.5l14.9,8.5h18.2V69.7l-33-19l-33,19v38.1l33,19l33-19V97.2H104.1z" />
</svg>`
export const iconOutLink = `<svg viewBox="0 0 32 32">
<path d="M 18 5 L 18 7 L 23.5625 7 L 11.28125 19.28125 L 12.71875 20.71875 L 25 8.4375 L 25 14 L 27 14 L 27 5 Z M 5 9 L 5 27 L 23 27 L 23 14 L 21 16 L 21 25 L 7 25 L 7 11 L 16 11 L 18 9 Z"></path>
</svg>`
export const link = `<svg viewBox="0 0 640 512">
<path d="M598.6 41.41C570.1 13.8 534.8 0 498.6 0s-72.36 13.8-99.96 41.41l-43.36 43.36c15.11 8.012 29.47 17.58 41.91 30.02c3.146 3.146 5.898 6.518 8.742 9.838l37.96-37.96C458.5 72.05 477.1 64 498.6 64c20.67 0 40.1 8.047 54.71 22.66c14.61 14.61 22.66 34.04 22.66 54.71s-8.049 40.1-22.66 54.71l-133.3 133.3C405.5 343.1 386 352 365.4 352s-40.1-8.048-54.71-22.66C296 314.7 287.1 295.3 287.1 274.6s8.047-40.1 22.66-54.71L314.2 216.4C312.1 212.5 309.9 208.5 306.7 205.3C298.1 196.7 286.8 192 274.6 192c-11.93 0-23.1 4.664-31.61 12.97c-30.71 53.96-23.63 123.6 22.39 169.6C293 402.2 329.2 416 365.4 416c36.18 0 72.36-13.8 99.96-41.41L598.6 241.3c28.45-28.45 42.24-66.01 41.37-103.3C639.1 102.1 625.4 68.16 598.6 41.41zM234 387.4L196.1 425.3C181.5 439.1 162 448 141.4 448c-20.67 0-40.1-8.047-54.71-22.66c-14.61-14.61-22.66-34.04-22.66-54.71s8.049-40.1 22.66-54.71l133.3-133.3C234.5 168 253.1 160 274.6 160s40.1 8.048 54.71 22.66c14.62 14.61 22.66 34.04 22.66 54.71s-8.047 40.1-22.66 54.71L325.8 295.6c2.094 3.939 4.219 7.895 7.465 11.15C341.9 315.3 353.3 320 365.4 320c11.93 0 23.1-4.664 31.61-12.97c30.71-53.96 23.63-123.6-22.39-169.6C346.1 109.8 310.8 96 274.6 96C238.4 96 202.3 109.8 174.7 137.4L41.41 270.7c-27.6 27.6-41.41 63.78-41.41 99.96c-.0001 36.18 13.8 72.36 41.41 99.97C69.01 498.2 105.2 512 141.4 512c36.18 0 72.36-13.8 99.96-41.41l43.36-43.36c-15.11-8.012-29.47-17.58-41.91-30.02C239.6 394.1 236.9 390.7 234 387.4z"/>
</svg>`
export const pencil = `<svg viewBox="0 0 24 24">
<path d="M 16.9375 1.0625 L 3.875 14.125 L 1.0742188 22.925781 L 9.875 20.125 L 22.9375 7.0625 C 22.9375 7.0625 22.8375 4.9615 20.9375 3.0625 C 19.0375 1.1625 16.9375 1.0625 16.9375 1.0625 z M 17.3125 2.6875 C 18.3845 2.8915 19.237984 3.3456094 19.896484 4.0214844 C 20.554984 4.6973594 21.0185 5.595 21.3125 6.6875 L 19.5 8.5 L 15.5 4.5 L 16.9375 3.0625 L 17.3125 2.6875 z M 4.9785156 15.126953 C 4.990338 15.129931 6.1809555 15.430955 7.375 16.625 C 8.675 17.825 8.875 18.925781 8.875 18.925781 L 8.9179688 18.976562 L 5.3691406 20.119141 L 3.8730469 18.623047 L 4.9785156 15.126953 z"/>
</svg>`
export const dotdotdot = `<svg viewBox="0 0 24 24" fill="currentColor">
<circle cy="12" r="3" cx="3"></circle>
<circle cy="12" r="3" cx="12"></circle>
<circle cx="21" cy="12" r="3"></circle>
</svg>`
export const models = `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M4 4h6v6h-6z"></path>
<path d="M14 4h6v6h-6z"></path>
<path d="M4 14h6v6h-6z"></path>
<path d="M17 17m-3 0a3 3 0 1 0 6 0a3 3 0 1 0 -6 0"></path>
</svg>`
export const pencilColored = `<svg viewBox="0 0 64 64">
<path fill="#ffce31" d="M7.934 41.132L39.828 9.246l14.918 14.922l-31.895 31.886z"></path>
<path d="M61.3 4.6l-1.9-1.9C55.8-.9 50-.9 46.3 2.7l-6.5 6.5l15 15l6.5-6.5c3.6-3.6 3.6-9.5 0-13.1" fill="#ed4c5c"></path>
<path fill="#93a2aa" d="M35.782 13.31l4.1-4.102l14.92 14.92l-4.1 4.101z"></path>
<path fill="#c7d3d8" d="M37.338 14.865l4.1-4.101l11.739 11.738l-4.102 4.1z"></path>
<path fill="#fed0ac" d="M7.9 41.1l-6.5 17l4.5 4.5l17-6.5z"/>
<path d="M.3 61.1c-.9 2.4.3 3.5 2.7 2.6l8.2-3.1l-7.7-7.7l-3.2 8.2" fill="#333"></path>
<path fill="#ffdf85" d="M7.89 41.175l27.86-27.86l4.95 4.95l-27.86 27.86z"/>
<path fill="#ff8736" d="M17.904 51.142l27.86-27.86l4.95 4.95l-27.86 27.86z"></path>
</svg>`
export const diskColored = `<svg viewBox="-0.01 -0.008 100.016 100.016">
<path fill="#26f" fill_="#23475F" d="M88.555-.008H83v.016a2 2 0 0 1-2 2H19a2 2 0 0 1-2-2v-.016H4a4 4 0 0 0-4 4v92.016a4 4 0 0 0 4 4h92a4 4 0 0 0 4-4V11.517c.049-.089-11.436-11.454-11.445-11.525z"/>
<path fill="#04d" fill_="#1C3C50" d="M81.04 53.008H18.96a2 2 0 0 0-2 2v45h66.08v-45c0-1.106-.895-2-2-2zm-61.957-10h61.834a2 2 0 0 0 2-2V.547A1.993 1.993 0 0 1 81 2.007H19c-.916 0-1.681-.62-1.917-1.46v40.46a2 2 0 0 0 2 2.001z"/>
<path fill="#EBF0F1" d="M22 55.977h56a2 2 0 0 1 2 2v37.031a2 2 0 0 1-2 2H22c-1.104 0-2-.396-2-1.5V57.977a2 2 0 0 1 2-2z"/>
<path fill="#BCC4C8" d="M25 77.008h50v1H25v-1zm0 10h50v1H25v-1z"/>
<path fill="#1C3C50" d="M7 84.008h3a2 2 0 0 1 2 2v3a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2v-3a2 2 0 0 1 2-2zm83 0h3a2 2 0 0 1 2 2v3a2 2 0 0 1-2 2h-3a2 2 0 0 1-2-2v-3a2 2 0 0 1 2-2z"/>
<path fill="#BCC4C8" d="M37 1.981v36.026a2 2 0 0 0 2 2h39a2 2 0 0 0 2-2V1.981c0 .007-42.982.007-43 0zm37 29.027a2 2 0 0 1-2 2h-6a2 2 0 0 1-2-2V10.981a2 2 0 0 1 2-2h6a2 2 0 0 1 2 2v20.027z"/>
<path fill="#FF9D00" d="M78 55.977H22a2 2 0 0 0-2 2v10.031h60V57.977a2 2 0 0 0-2-2z"/>
</svg>`
export const folderColored = `<svg viewBox="0 0 501.379 501.379">
<path style="fill:#EF9F2C;" d="M406.423,93.889H205.889c-17.067,0-30.933-13.867-30.933-30.933s-13.867-30.933-30.933-30.933H30.956
c-17.067,0-30.933,13.867-30.933,30.933v375.467c0,17.067,13.867,30.933,30.933,30.933h375.467
c17.067,0,30.933-13.867,30.933-30.933v-313.6C436.289,107.756,422.423,93.889,406.423,93.889z"/>
<path style="fill:#FEC656;" d="M470.423,157.889H97.089c-13.867,0-26.667,9.6-29.867,22.4l-66.133,249.6
c-5.333,19.2,9.6,38.4,29.867,38.4h373.333c13.867,0,26.667-9.6,29.867-22.4l66.133-248.533
C505.623,177.089,490.689,157.889,470.423,157.889z"/>
</svg>`
export const modelsColored = `<svg viewBox="0 0 24 24">
<path fill="#aa3366" d="M0 0h10v10h-10z"></path>
<path d="M14 0h10v10h-10z" fill="#3366aa"></path>
<path d="M0 14h10v10h-10z" fill="#66aa33"></path>
<path fill="#dd9922" d="M19 19m-5 0 a5 5 0 1 0 10 0 a5 5 0 1 0 -10 0"></path>
</svg>`
export const legoBlocksColored = `<svg viewBox="0 0 512 512">
<g>
<rect x="57.67" style="fill:#00BAB9;" width="101.275" height="78.769"/>
<rect x="205.363" style="fill:#00BAB9;" width="101.275" height="78.769"/>
<rect x="353.055" style="fill:#00BAB9;" width="101.275" height="78.769"/>
</g>
<polygon style="fill:#B8DE6F;" points="478.242,289.758 478.242,512 33.758,512 33.758,289.758 256,267.253 "/>
<polygon style="fill:#41D4D3;" points="478.242,67.516 478.242,289.758 33.758,289.758 33.758,67.516 57.67,67.516 158.945,67.516
205.363,67.516 306.637,67.516 353.055,67.516 454.33,67.516 "/>
<g>
<circle style="fill:#00BAB9;" cx="402.286" cy="143.473" r="8.44"/>
<circle style="fill:#00BAB9;" cx="368.527" cy="177.231" r="8.44"/>
</g>
<circle style="fill:#7BD288;" cx="109.714" cy="436.044" r="8.44"/>
</svg>`
export const legoBlockColored = `<svg viewBox="0 0 256 256">
<style>
.s0 { fill: #ff0000 }
.s1 { fill: #c30000 }
.s2 { fill: #800000 }
.s3 { fill: #cc0000 }
.s4 { fill: #e00000 }
</style>
<g id="Folder 2">
<path id="Shape 1 copy 2" class="s0" d="m128 61l116 45-116 139-116-139z"/>
<path id="Shape 1" class="s1" d="m12 106l116 45v95l-116-45z"/>
<path id="Shape 1 copy" class="s2" d="m244 106l-116 45v95l116-45z"/>
<g id="Folder 1">
<path id="Shape 2" class="s3" d="m102 111.2c0-6.1 11.4-9.9 25.5-9.9 14.1 0 25.5 3.8 25.5 9.9 0 3.3 0 13.3 0 16.6 0 6.1-11.4 10.9-25.5 10.9-14.1 0-25.5-4.8-25.5-10.9 0-3.3 0-13.3 0-16.6z"/>
<path id="Shape 2 copy 4" class="s1" d="m102 111.2c0-6.1 11.4-9.9 25.5-9.9 14.1 0 25.5 3.8 25.5 9.9 0 3.3 0 13.3 0 16.6 0 6.1-11.4 10.9-25.5 10.9-14.1 0-25.5-4.8-25.5-10.9 0-3.3 0-13.3 0-16.6z"/>
<path id="Shape 2 copy 2" class="s2" d="m127.5 101.3c14.1 0 25.5 3.8 25.5 9.9 0 3.3 0 13.3 0 16.6 0 6.1-11.4 10.9-25.5 10.9 0-13.1 0-25.7 0-37.4z"/>
<path id="Shape 2 copy" class="s0" d="m127.5 118.8c-12.2 0-22-3.4-22-7.6 0-4.2 9.8-7.7 22-7.7 12.2 0 22 3.5 22 7.7 0 4.2-9.8 7.6-22 7.6zm0 0c-12.2 0-22-3.4-22-7.6 0-4.2 9.8-7.7 22-7.7 12.2 0 22 3.5 22 7.7 0 4.2-9.8 7.6-22 7.6z"/>
</g>
<g id="Folder 1 copy">
<path id="Shape 2" class="s4" d="m103 67.5c0-5.8 11-9.5 24.5-9.5 13.5 0 24.5 3.7 24.5 9.5 0 3.2 0 12.8 0 16 0 5.8-11 10.5-24.5 10.5-13.5 0-24.5-4.7-24.5-10.5 0-3.2 0-12.8 0-16z"/>
<path id="Shape 2 copy 4" class="s1" d="m103 67.5c0-5.8 11-9.5 24.5-9.5 13.5 0 24.5 3.7 24.5 9.5 0 3.2 0 12.8 0 16 0 5.8-11 10.5-24.5 10.5-13.5 0-24.5-4.7-24.5-10.5 0-3.2 0-12.8 0-16z"/>
<path id="Shape 2 copy 2" class="s2" d="m127.5 58c13.5 0 24.5 3.7 24.5 9.5 0 3.2 0 12.8 0 16 0 5.8-11 10.5-24.5 10.5 0-12.6 0-24.8 0-36z"/>
<path id="Shape 2 copy" class="s0" d="m127.5 74.9c-11.7 0-21.2-3.3-21.2-7.4 0-4.1 9.5-7.4 21.2-7.4 11.7 0 21.2 3.3 21.2 7.4 0 4.1-9.5 7.4-21.2 7.4zm0 0c-11.7 0-21.2-3.3-21.2-7.4 0-4.1 9.5-7.4 21.2-7.4 11.7 0 21.2 3.3 21.2 7.4 0 4.1-9.5 7.4-21.2 7.4z"/>
</g>
<g id="Folder 1 copy 2">
<path id="Shape 2" class="s4" d="m161 89.5c0-5.8 11-9.5 24.5-9.5 13.5 0 24.5 3.7 24.5 9.5 0 3.2 0 12.8 0 16 0 5.8-11 10.5-24.5 10.5-13.5 0-24.5-4.7-24.5-10.5 0-3.2 0-12.8 0-16z"/>
<path id="Shape 2 copy 4" class="s1" d="m161 89.5c0-5.8 11-9.5 24.5-9.5 13.5 0 24.5 3.7 24.5 9.5 0 3.2 0 12.8 0 16 0 5.8-11 10.5-24.5 10.5-13.5 0-24.5-4.7-24.5-10.5 0-3.2 0-12.8 0-16z"/>
<path id="Shape 2 copy 2" class="s2" d="m185.5 80c13.5 0 24.5 3.7 24.5 9.5 0 3.2 0 12.8 0 16 0 5.8-11 10.5-24.5 10.5 0-12.6 0-24.8 0-36z"/>
<path id="Shape 2 copy" class="s0" d="m185.5 96.9c-11.7 0-21.2-3.3-21.2-7.4 0-4.1 9.5-7.4 21.2-7.4 11.7 0 21.2 3.3 21.2 7.4 0 4.1-9.5 7.4-21.2 7.4zm0 0c-11.7 0-21.2-3.3-21.2-7.4 0-4.1 9.5-7.4 21.2-7.4 11.7 0 21.2 3.3 21.2 7.4 0 4.1-9.5 7.4-21.2 7.4z"/>
</g>
<g id="Folder 1 copy 3">
<path id="Shape 2" class="s4" d="m45 89.5c0-5.8 11-9.5 24.5-9.5 13.5 0 24.5 3.7 24.5 9.5 0 3.2 0 12.8 0 16 0 5.8-11 10.5-24.5 10.5-13.5 0-24.5-4.7-24.5-10.5 0-3.2 0-12.8 0-16z"/>
<path id="Shape 2 copy 4" class="s1" d="m45 89.5c0-5.8 11-9.5 24.5-9.5 13.5 0 24.5 3.7 24.5 9.5 0 3.2 0 12.8 0 16 0 5.8-11 10.5-24.5 10.5-13.5 0-24.5-4.7-24.5-10.5 0-3.2 0-12.8 0-16z"/>
<path id="Shape 2 copy 2" class="s2" d="m69.5 80c13.5 0 24.5 3.7 24.5 9.5 0 3.2 0 12.8 0 16 0 5.8-11 10.5-24.5 10.5 0-12.6 0-24.8 0-36z"/>
<path id="Shape 2 copy" class="s0" d="m69.5 96.9c-11.7 0-21.2-3.3-21.2-7.4 0-4.1 9.5-7.4 21.2-7.4 11.7 0 21.2 3.3 21.2 7.4 0 4.1-9.5 7.4-21.2 7.4zm0 0c-11.7 0-21.2-3.3-21.2-7.4 0-4.1 9.5-7.4 21.2-7.4 11.7 0 21.2 3.3 21.2 7.4 0 4.1-9.5 7.4-21.2 7.4z"/>
</g>
</g>
</svg>`
export const gearColored = `<svg viewBox="0 0 128 128" preserveAspectRatio="xMidYMid meet">
<path d="M124 71.85v-15.7c0-.59-.45-1.09-1.03-1.15l-17.83-1.89c-.47-.05-.85-.38-.98-.83c-.86-2.95-2.03-5.76-3.48-8.39c-.23-.41-.19-.92.11-1.28l11.28-13.94c.37-.46.34-1.13-.08-1.54l-11.1-11.1a1.15 1.15 0 0 0-1.54-.08L85.39 27.22c-.37.3-.87.33-1.28.11a41.796 41.796 0 0 0-8.39-3.48c-.45-.13-.78-.51-.83-.98L73 5.03C72.94 4.45 72.44 4 71.85 4h-15.7c-.59 0-1.09.45-1.15 1.03l-1.89 17.83c-.05.47-.38.85-.83.98c-2.95.86-5.76 2.03-8.39 3.48c-.41.23-.92.19-1.28-.11L28.67 15.94a1.15 1.15 0 0 0-1.54.08l-11.1 11.1a1.15 1.15 0 0 0-.08 1.54L27.23 42.6c.3.37.33.87.11 1.28a41.796 41.796 0 0 0-3.48 8.39c-.13.45-.51.78-.98.83L5.03 55c-.58.06-1.03.56-1.03 1.15v15.7c0 .59.45 1.09 1.03 1.15l17.83 1.89c.47.05.85.38.98.83c.86 2.95 2.03 5.76 3.48 8.39c.23.41.19.92-.11 1.28L15.94 99.33c-.37.46-.34 1.13.08 1.54l11.1 11.1c.42.42 1.08.45 1.54.08l13.94-11.28c.37-.3.87-.33 1.28-.11c2.64 1.45 5.45 2.62 8.39 3.48c.45.13.78.51.83.98l1.9 17.85c.06.59.56 1.03 1.15 1.03h15.7c.59 0 1.09-.45 1.15-1.03l1.89-17.83c.05-.47.38-.85.83-.98c2.95-.86 5.76-2.03 8.39-3.48c.41-.23.92-.19 1.28.11l13.94 11.28c.46.37 1.13.34 1.54-.08l11.1-11.1c.42-.42.45-1.08.08-1.54l-11.28-13.94c-.3-.37-.33-.87-.11-1.28c1.45-2.64 2.62-5.45 3.48-8.39c.13-.45.51-.78.98-.83L122.97 73c.58-.06 1.03-.56 1.03-1.15zm-60 3.43c-6.23 0-11.28-5.05-11.28-11.28S57.77 52.72 64 52.72S75.28 57.77 75.28 64S70.23 75.28 64 75.28z" fill="#82aec0"></path>
<path d="M80.56 49.48c3.67 4.18 5.78 9.77 5.43 15.85c-.65 11.16-9.83 20.19-21 20.68c-4.75.21-9.18-1.09-12.86-3.45c-.28-.18-.58.2-.34.44a22.412 22.412 0 0 0 17.85 6.67c10.78-.85 19.56-9.5 20.55-20.27c.77-8.36-3.06-15.87-9.23-20.33c-.29-.2-.62.15-.4.41z" fill="#2f7889"></path>
<path d="M43.87 65.32c-.67-13.15 7.83-22.79 20.01-22.79c.65 0 1.68 0 2.48.92c1.01 1.18 1.1 2.6 0 3.77c-.81.86-1.95.92-2.53 1c-12.3 1.59-15.18 9.35-15.83 16.77c-.03.33.06 2.35-1.71 2.56c-2.15.25-2.41-1.91-2.42-2.23z" fill="#b9e4ea"></path>
<path d="M25.24 65.87c-.01-22.03 15.9-40.19 38.13-41.05c.68-.03 2.45 0 3.55.99c1.01.91 1.38 2.51.79 3.82c-.95 2.11-2.85 2.07-3.36 2.09c-18.51.66-34.18 15.73-34.19 33.95c0 .29-.05.58-.15.84l-.1.25c-.76 1.98-3.52 2.09-4.43.18c-.15-.34-.24-.7-.24-1.07z" fill="#94d1e0"></path>
</svg>`
export function $svg(markup, attrs) {
if (!markup.match(/^\s*<svg/)) {
throw new Error('Cannot call $svg with non-svg markup.')
}
return $el(markup, attrs || {})
}
-291
View File
@@ -1,291 +0,0 @@
const DIRECT_ATTRIBUTE_MAP = {
cellpadding: 'cellPadding',
cellspacing: 'cellSpacing',
colspan: 'colSpan',
frameborder: 'frameBorder',
height: 'height',
maxlength: 'maxLength',
nonce: 'nonce',
role: 'role',
rowspan: 'rowSpan',
type: 'type',
usemap: 'useMap',
valign: 'vAlign',
width: 'width',
}
const RGX_NUMERIC_STYLE_UNIT = 'px'
const RGX_NUMERIC_STYLE =
/^((max|min)?(width|height)|margin|padding|(margin|padding)?(left|top|bottom|right)|fontsize|borderwidth)$/i
const RGX_DEFAULT_VALUE_PROP = /input|textarea|select/i
function localAssertNotFalsy(input, errorMsg = `Input is not of type.`) {
if (input == null) {
throw new Error(errorMsg)
}
return input
}
const RGX_STRING_VALID = '[a-z0-9_-]'
const RGX_TAG = new RegExp(`^([a-z]${RGX_STRING_VALID}*)(\\.|\\[|\\#|$)`, 'i')
const RGX_ATTR_ID = new RegExp(`#(${RGX_STRING_VALID}+)`, 'gi')
const RGX_ATTR_CLASS = new RegExp(`(^|\\S)\\.([a-z0-9_\\-\\.]+)`, 'gi')
const RGX_STRING_CONTENT_TO_SQUARES = '(.*?)(\\[|\\])'
const RGX_ATTRS_MAYBE_OPEN = new RegExp(`\\[${RGX_STRING_CONTENT_TO_SQUARES}`, 'gi')
const RGX_ATTRS_FOLLOW_OPEN = new RegExp(`^${RGX_STRING_CONTENT_TO_SQUARES}`, 'gi')
export function query(selectors, parent = document) {
return Array.from(parent.querySelectorAll(selectors)).filter((n) => !!n)
}
export function queryOne(selectors, parent = document) {
var _a
return (_a = parent.querySelector(selectors)) !== null && _a !== void 0 ? _a : null
}
export function createText(text) {
return document.createTextNode(text)
}
export function getClosestOrSelf(element, query) {
const el = element
return (
((el === null || el === void 0 ? void 0 : el.closest) &&
((el.matches(query) && el) || el.closest(query))) ||
null
)
}
export function createElement(selectorOrMarkup, attrs) {
const frag = getHtmlFragment(selectorOrMarkup)
let element = frag === null || frag === void 0 ? void 0 : frag.firstElementChild
let selector = ''
if (!element) {
selector = selectorOrMarkup.replace(/[\r\n]\s*/g, '')
const tag = getSelectorTag(selector) || 'div'
element = document.createElement(tag)
selector = selector.replace(RGX_TAG, '$2')
selector = selector.replace(RGX_ATTR_ID, '[id="$1"]')
selector = selector.replace(
RGX_ATTR_CLASS,
(match, p1, p2) => `${p1}[class="${p2.replace(/\./g, ' ')}"]`,
)
}
const selectorAttrs = getSelectorAttributes(selector)
if (selectorAttrs) {
for (const attr of selectorAttrs) {
let matches = attr.substring(1, attr.length - 1).split('=')
let key = localAssertNotFalsy(matches.shift())
let value = matches.join('=')
if (value === undefined) {
setAttribute(element, key, true)
} else {
value = value.replace(/^['"](.*)['"]$/, '$1')
setAttribute(element, key, value)
}
}
}
if (attrs) {
setAttributes(element, attrs)
}
return element
}
function getSelectorTag(str) {
return tryMatch(str, RGX_TAG)
}
function getSelectorAttributes(selector) {
RGX_ATTRS_MAYBE_OPEN.lastIndex = 0
let attrs = []
let result
while ((result = RGX_ATTRS_MAYBE_OPEN.exec(selector))) {
let attr = result[0]
if (attr.endsWith(']')) {
attrs.push(attr)
} else {
attr =
result[0] + getOpenAttributesRecursive(selector.substr(RGX_ATTRS_MAYBE_OPEN.lastIndex), 2)
RGX_ATTRS_MAYBE_OPEN.lastIndex += attr.length - result[0].length
attrs.push(attr)
}
}
return attrs
}
function getOpenAttributesRecursive(selectorSubstring, openCount) {
let matches = selectorSubstring.match(RGX_ATTRS_FOLLOW_OPEN)
let result = ''
if (matches && matches.length) {
result = matches[0]
openCount += result.endsWith(']') ? -1 : 1
if (openCount > 0) {
result += getOpenAttributesRecursive(selectorSubstring.substr(result.length), openCount)
}
}
return result
}
function tryMatch(str, rgx, index = 1) {
var _a
let found = ''
try {
found = ((_a = str.match(rgx)) === null || _a === void 0 ? void 0 : _a[index]) || ''
} catch (e) {
found = ''
}
return found
}
export function setAttributes(element, data) {
let attr
for (attr in data) {
if (data.hasOwnProperty(attr)) {
setAttribute(element, attr, data[attr])
}
}
}
function getHtmlFragment(value) {
if (value.match(/^\s*<.*?>[\s\S]*<\/[a-z0-9]+>\s*$/)) {
return document.createRange().createContextualFragment(value.trim())
}
return null
}
function getChild(value) {
if (value instanceof Node) {
return value
}
if (typeof value === 'string') {
let child = getHtmlFragment(value)
if (child) {
return child
}
if (getSelectorTag(value)) {
return createElement(value)
}
return createText(value)
}
if (value && typeof value.toElement === 'function') {
return value.toElement()
}
return null
}
export function setAttribute(element, attribute, value) {
let isRemoving = value == null
if (attribute === 'default') {
attribute = RGX_DEFAULT_VALUE_PROP.test(element.nodeName) ? 'value' : 'text'
}
if (attribute === 'text') {
empty(element).appendChild(createText(value != null ? String(value) : ''))
} else if (attribute === 'html') {
empty(element).innerHTML += value != null ? String(value) : ''
} else if (attribute == 'style') {
if (typeof value === 'string') {
element.style.cssText = isRemoving ? '' : value != null ? String(value) : ''
} else {
for (const [styleKey, styleValue] of Object.entries(value)) {
element.style[styleKey] = styleValue
}
}
} else if (attribute == 'events') {
for (const [key, fn] of Object.entries(value)) {
addEvent(element, key, fn)
}
} else if (attribute === 'parent') {
value.appendChild(element)
} else if (attribute === 'child' || attribute === 'children') {
if (typeof value === 'string' && /^\[[^\[\]]+\]$/.test(value)) {
const parseable = value.replace(/^\[([^\[\]]+)\]$/, '["$1"]').replace(/,/g, '","')
try {
const parsed = JSON.parse(parseable)
value = parsed
} catch (e) {
console.error(e)
}
}
if (attribute === 'children') {
empty(element)
}
let children = value instanceof Array ? value : [value]
for (let child of children) {
child = getChild(child)
if (child instanceof Node) {
if (element instanceof HTMLTemplateElement) {
element.content.appendChild(child)
} else {
element.appendChild(child)
}
}
}
} else if (attribute == 'for') {
element.htmlFor = value != null ? String(value) : ''
if (isRemoving) {
element.removeAttribute('for')
}
} else if (attribute === 'class' || attribute === 'className' || attribute === 'classes') {
element.className = isRemoving ? '' : Array.isArray(value) ? value.join(' ') : String(value)
} else if (attribute === 'dataset') {
if (typeof value !== 'object') {
console.error('Expecting an object for dataset')
return
}
for (const [key, val] of Object.entries(value)) {
element.dataset[key] = String(val)
}
} else if (attribute == 'onclick' && typeof value === 'function') {
element.addEventListener('click', value)
} else if (['checked', 'disabled', 'readonly', 'required', 'selected'].includes(attribute)) {
element[attribute] = !!value
if (!value) {
element.removeAttribute(attribute)
} else {
element.setAttribute(attribute, attribute)
}
} else if (DIRECT_ATTRIBUTE_MAP.hasOwnProperty(attribute)) {
if (isRemoving) {
element.removeAttribute(DIRECT_ATTRIBUTE_MAP[attribute])
} else {
element.setAttribute(DIRECT_ATTRIBUTE_MAP[attribute], String(value))
}
} else if (isRemoving) {
element.removeAttribute(attribute)
} else {
let oldVal = element.getAttribute(attribute)
if (oldVal !== value) {
element.setAttribute(attribute, String(value))
}
}
}
function addEvent(element, key, fn) {
element.addEventListener(key, fn)
}
function setStyles(element, styles = null) {
if (styles) {
for (let name in styles) {
setStyle(element, name, styles[name])
}
}
return element
}
function setStyle(element, name, value) {
name = name.indexOf('float') > -1 ? 'cssFloat' : name
if (name.indexOf('-') != -1) {
name = name.replace(/-\D/g, (match) => {
return match.charAt(1).toUpperCase()
})
}
if (value == String(Number(value)) && RGX_NUMERIC_STYLE.test(name)) {
value = value + RGX_NUMERIC_STYLE_UNIT
}
if (name === 'display' && typeof value !== 'string') {
value = !!value ? null : 'none'
}
element.style[name] = value === null ? null : String(value)
return element
}
export function empty(element) {
while (element.firstChild) {
element.removeChild(element.firstChild)
}
return element
}
export function appendChildren(el, children) {
children = !Array.isArray(children) ? [children] : children
for (let child of children) {
child = getChild(child)
if (child instanceof Node) {
if (el instanceof HTMLTemplateElement) {
el.content.appendChild(child)
} else {
el.appendChild(child)
}
}
}
}