static 폴더 및 하위 파일 업로드

This commit is contained in:
sotam0316
2026-04-22 12:05:03 +09:00
commit 514b209a5a
203 changed files with 29494 additions and 0 deletions
+70
View File
@@ -0,0 +1,70 @@
{
"categories": [
{
"id": "Network",
"label": "Network Devices",
"icon": "router.svg"
},
{
"id": "Security",
"label": "Security & Firewalls",
"icon": "firewall.svg"
}
],
"assets": [
{
"id": "router",
"type": "Router",
"category": "Network",
"label": "Standard Router",
"path": "router.svg",
"format": "svg",
"vendor": "Cisco"
},
{
"id": "switch",
"type": "Switch",
"category": "Network",
"label": "L3 Switch",
"path": "switch.svg",
"format": "svg",
"vendor": "Cisco"
},
{
"id": "firewall_cisco",
"type": "Firewall",
"category": "Security",
"label": "Cisco Firewall",
"path": "firewall.svg",
"format": "svg",
"vendor": "Cisco"
},
{
"id": "firewall_png",
"type": "F/W",
"category": "Security",
"label": "Legacy F/w",
"path": "firewall.png",
"format": "png",
"vendor": "Generic"
},
{
"id": "server",
"type": "Server",
"category": "Compute",
"label": "Enterprise Server",
"path": "server.svg",
"format": "svg",
"vendor": "Generic"
},
{
"id": "cloud",
"type": "Internet",
"category": "External",
"label": "External Cloud",
"path": "cloud.svg",
"format": "svg",
"vendor": "Generic"
}
]
}
+3
View File
@@ -0,0 +1,3 @@
<svg width="100" height="100" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
<path d="M25 40 A15 15 0 0 1 50 25 A25 25 0 0 1 85 50 A20 20 0 0 1 70 85 H30 A20 20 0 0 1 25 40" fill="#cbd5e1" stroke="#64748b" stroke-width="2"/>
</svg>

After

Width:  |  Height:  |  Size: 247 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

+4
View File
@@ -0,0 +1,4 @@
<svg width="100" height="100" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
<rect x="15" y="20" width="70" height="60" rx="4" fill="#ef4444" stroke="#b91c1c" stroke-width="2"/>
<path d="M15 40 H85 M15 60 H85 M35 20 V40 M65 20 V40 M25 40 V60 M55 40 V60 M85 40 V60 M40 60 V80 M70 60 V80" stroke="white" stroke-width="2"/>
</svg>

After

Width:  |  Height:  |  Size: 347 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 406 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

@@ -0,0 +1,125 @@
{
"id": "cisco_base_pack",
"name": "cisco_pack",
"vendor": "Unknown",
"version": "1.0.0",
"assets": [
{
"id": "cisco_firewall",
"label": "Cisco Firewall",
"category": "Security",
"views": {
"icon": "cisco_firewall.png",
"front": "cisco_firewall.png"
}
},
{
"id": "cisco_firewallservicemodule",
"label": "Cisco Firewall service module",
"category": "Security",
"views": {
"icon": "cisco_firewallservicemodule.png",
"front": "cisco_firewallservicemodule.png"
}
},
{
"id": "cisco_generic",
"label": "Cisco Generic",
"category": "Other",
"views": {
"icon": "cisco_generic.png",
"front": "cisco_generic.png"
}
},
{
"id": "cisco_iosslb",
"label": "Cisco Iosslb",
"category": "Network",
"views": {
"icon": "cisco_iosslb.png",
"front": "cisco_iosslb.png"
}
},
{
"id": "cisco_laptop",
"label": "Cisco Laptop",
"category": "Device",
"views": {
"icon": "cisco_laptop.png",
"front": "cisco_laptop.png"
}
},
{
"id": "cisco_printer",
"label": "Cisco Printer",
"category": "Device",
"views": {
"icon": "cisco_printer.png",
"front": "cisco_printer.png"
}
},
{
"id": "cisco_wirelessrouter",
"label": "Cisco Wirelessrouter",
"category": "Network",
"views": {
"icon": "cisco_wirelessrouter.png",
"front": "cisco_wirelessrouter.png"
}
},
{
"id": "cisco_wwwserver",
"label": "Cisco Wwwserver",
"category": "Device",
"views": {
"icon": "cisco_wwwserver.png",
"front": "cisco_wwwserver.png"
}
},
{
"id": "cisco_contentservicerouter",
"label": "Cisco Contentservicerouter",
"category": "Network",
"views": {
"icon": "cisco_contentservicerouter.png",
"front": "cisco_contentservicerouter.png"
}
},
{
"id": "cisco_database",
"label": "Cisco Database",
"category": "DBMS",
"views": {
"icon": "cisco_database.png",
"front": "cisco_database.png"
}
},
{
"id": "cisco_mgx8000",
"label": "Cisco Mgx8000",
"category": "Network",
"views": {
"icon": "cisco_mgx8000.png",
"front": "cisco_mgx8000.png"
}
},
{
"id": "cisco_l2_100base",
"label": "Cisco L2 ",
"category": "Network",
"views": {
"icon": "cisco_l2_100base.png",
"front": "cisco_l2_100base.png"
}
},
{
"id": "cisco_cloud",
"label": "Cisco Cloud",
"category": "Cloud",
"views": {
"icon": "cisco_cloud.png",
"front": "cisco_cloud.png"
}
}
]
}
@@ -0,0 +1,24 @@
{
"id": "sample_cisco",
"name": "Cisco Enterprise Pack",
"vendor": "Cisco",
"version": "1.0.0",
"assets": [
{
"id": "cisco_router",
"label": "Integrated Services Router",
"category": "Network",
"views": {
"icon": "router.svg"
}
},
{
"id": "cisco_switch",
"label": "Catalyst Switch",
"category": "Network",
"views": {
"icon": "switch.svg"
}
}
]
}
@@ -0,0 +1,5 @@
<svg width="100" height="100" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
<circle cx="50" cy="50" r="45" fill="#3b82f6" stroke="#1d4ed8" stroke-width="2"/>
<path d="M50 20 L50 40 M50 80 L50 60 M20 50 L40 50 M80 50 L60 50" stroke="white" stroke-width="5" stroke-linecap="round"/>
<path d="M45 40 L50 35 L55 40 M45 60 L50 65 L55 60 M40 45 L35 50 L40 55 M60 45 L65 50 L60 55" fill="none" stroke="white" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 499 B

@@ -0,0 +1,5 @@
<svg width="100" height="100" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
<rect x="10" y="25" width="80" height="50" rx="5" fill="#3b82f6" stroke="#1d4ed8" stroke-width="2"/>
<path d="M30 40 L50 40 M50 60 L70 60" stroke="white" stroke-width="4" stroke-linecap="round"/>
<path d="M45 35 L50 40 L45 45 M55 55 L50 60 L55 65" fill="none" stroke="white" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 448 B

+5
View File
@@ -0,0 +1,5 @@
<svg width="100" height="100" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
<circle cx="50" cy="50" r="45" fill="#3b82f6" stroke="#1d4ed8" stroke-width="2"/>
<path d="M50 20 L50 40 M50 80 L50 60 M20 50 L40 50 M80 50 L60 50" stroke="white" stroke-width="5" stroke-linecap="round"/>
<path d="M45 40 L50 35 L55 40 M45 60 L50 65 L55 60 M40 45 L35 50 L40 55 M60 45 L65 50 L60 55" fill="none" stroke="white" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 499 B

+7
View File
@@ -0,0 +1,7 @@
<svg width="100" height="100" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
<rect x="25" y="10" width="50" height="80" rx="2" fill="#64748b" stroke="#334155" stroke-width="2"/>
<rect x="30" y="20" width="40" height="5" fill="#94a3b8"/>
<rect x="30" y="35" width="40" height="5" fill="#94a3b8"/>
<rect x="30" y="50" width="40" height="5" fill="#94a3b8"/>
<circle cx="35" cy="75" r="3" fill="#22c55e"/>
</svg>

After

Width:  |  Height:  |  Size: 440 B

+5
View File
@@ -0,0 +1,5 @@
<svg width="100" height="100" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
<rect x="10" y="25" width="80" height="50" rx="5" fill="#3b82f6" stroke="#1d4ed8" stroke-width="2"/>
<path d="M30 40 L50 40 M50 60 L70 60" stroke="white" stroke-width="4" stroke-linecap="round"/>
<path d="M45 35 L50 40 L45 45 M55 55 L50 60 L55 65" fill="none" stroke="white" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 448 B

File diff suppressed because one or more lines are too long
+306
View File
@@ -0,0 +1,306 @@
/* cyrillic-ext */
@font-face {
font-family: 'Inter';
font-style: normal;
font-weight: 400;
font-display: swap;
src: url(/static/fonts/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa2JL7SUc.woff2) format('woff2');
unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
}
/* cyrillic */
@font-face {
font-family: 'Inter';
font-style: normal;
font-weight: 400;
font-display: swap;
src: url(/static/fonts/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa0ZL7SUc.woff2) format('woff2');
unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
/* greek-ext */
@font-face {
font-family: 'Inter';
font-style: normal;
font-weight: 400;
font-display: swap;
src: url(/static/fonts/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa2ZL7SUc.woff2) format('woff2');
unicode-range: U+1F00-1FFF;
}
/* greek */
@font-face {
font-family: 'Inter';
font-style: normal;
font-weight: 400;
font-display: swap;
src: url(/static/fonts/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa1pL7SUc.woff2) format('woff2');
unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF;
}
/* vietnamese */
@font-face {
font-family: 'Inter';
font-style: normal;
font-weight: 400;
font-display: swap;
src: url(/static/fonts/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa2pL7SUc.woff2) format('woff2');
unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
}
/* latin-ext */
@font-face {
font-family: 'Inter';
font-style: normal;
font-weight: 400;
font-display: swap;
src: url(/static/fonts/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa25L7SUc.woff2) format('woff2');
unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
font-family: 'Inter';
font-style: normal;
font-weight: 400;
font-display: swap;
src: url(/static/fonts/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa1ZL7.woff2) format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* cyrillic-ext */
@font-face {
font-family: 'Inter';
font-style: normal;
font-weight: 600;
font-display: swap;
src: url(/static/fonts/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa2JL7SUc.woff2) format('woff2');
unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
}
/* cyrillic */
@font-face {
font-family: 'Inter';
font-style: normal;
font-weight: 600;
font-display: swap;
src: url(/static/fonts/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa0ZL7SUc.woff2) format('woff2');
unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
/* greek-ext */
@font-face {
font-family: 'Inter';
font-style: normal;
font-weight: 600;
font-display: swap;
src: url(/static/fonts/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa2ZL7SUc.woff2) format('woff2');
unicode-range: U+1F00-1FFF;
}
/* greek */
@font-face {
font-family: 'Inter';
font-style: normal;
font-weight: 600;
font-display: swap;
src: url(/static/fonts/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa1pL7SUc.woff2) format('woff2');
unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF;
}
/* vietnamese */
@font-face {
font-family: 'Inter';
font-style: normal;
font-weight: 600;
font-display: swap;
src: url(/static/fonts/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa2pL7SUc.woff2) format('woff2');
unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
}
/* latin-ext */
@font-face {
font-family: 'Inter';
font-style: normal;
font-weight: 600;
font-display: swap;
src: url(/static/fonts/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa25L7SUc.woff2) format('woff2');
unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
font-family: 'Inter';
font-style: normal;
font-weight: 600;
font-display: swap;
src: url(/static/fonts/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa1ZL7.woff2) format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* cyrillic-ext */
@font-face {
font-family: 'Inter';
font-style: normal;
font-weight: 800;
font-display: swap;
src: url(/static/fonts/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa2JL7SUc.woff2) format('woff2');
unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
}
/* cyrillic */
@font-face {
font-family: 'Inter';
font-style: normal;
font-weight: 800;
font-display: swap;
src: url(/static/fonts/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa0ZL7SUc.woff2) format('woff2');
unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
/* greek-ext */
@font-face {
font-family: 'Inter';
font-style: normal;
font-weight: 800;
font-display: swap;
src: url(/static/fonts/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa2ZL7SUc.woff2) format('woff2');
unicode-range: U+1F00-1FFF;
}
/* greek */
@font-face {
font-family: 'Inter';
font-style: normal;
font-weight: 800;
font-display: swap;
src: url(/static/fonts/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa1pL7SUc.woff2) format('woff2');
unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF;
}
/* vietnamese */
@font-face {
font-family: 'Inter';
font-style: normal;
font-weight: 800;
font-display: swap;
src: url(/static/fonts/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa2pL7SUc.woff2) format('woff2');
unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
}
/* latin-ext */
@font-face {
font-family: 'Inter';
font-style: normal;
font-weight: 800;
font-display: swap;
src: url(/static/fonts/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa25L7SUc.woff2) format('woff2');
unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
font-family: 'Inter';
font-style: normal;
font-weight: 800;
font-display: swap;
src: url(/static/fonts/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa1ZL7.woff2) format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* cyrillic-ext */
@font-face {
font-family: 'Inter';
font-style: normal;
font-weight: 900;
font-display: swap;
src: url(/static/fonts/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa2JL7SUc.woff2) format('woff2');
unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
}
/* cyrillic */
@font-face {
font-family: 'Inter';
font-style: normal;
font-weight: 900;
font-display: swap;
src: url(/static/fonts/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa0ZL7SUc.woff2) format('woff2');
unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
/* greek-ext */
@font-face {
font-family: 'Inter';
font-style: normal;
font-weight: 900;
font-display: swap;
src: url(/static/fonts/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa2ZL7SUc.woff2) format('woff2');
unicode-range: U+1F00-1FFF;
}
/* greek */
@font-face {
font-family: 'Inter';
font-style: normal;
font-weight: 900;
font-display: swap;
src: url(/static/fonts/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa1pL7SUc.woff2) format('woff2');
unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF;
}
/* vietnamese */
@font-face {
font-family: 'Inter';
font-style: normal;
font-weight: 900;
font-display: swap;
src: url(/static/fonts/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa2pL7SUc.woff2) format('woff2');
unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
}
/* latin-ext */
@font-face {
font-family: 'Inter';
font-style: normal;
font-weight: 900;
font-display: swap;
src: url(/static/fonts/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa25L7SUc.woff2) format('woff2');
unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
font-family: 'Inter';
font-style: normal;
font-weight: 900;
font-display: swap;
src: url(/static/fonts/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa1ZL7.woff2) format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* cyrillic-ext */
@font-face {
font-family: 'JetBrains Mono';
font-style: normal;
font-weight: 400;
font-display: swap;
src: url(/static/fonts/tDbY2o-flEEny0FZhsfKu5WU4zr3E_BX0PnT8RD8yKxTN1OVgaY.woff2) format('woff2');
unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
}
/* cyrillic */
@font-face {
font-family: 'JetBrains Mono';
font-style: normal;
font-weight: 400;
font-display: swap;
src: url(/static/fonts/tDbY2o-flEEny0FZhsfKu5WU4zr3E_BX0PnT8RD8yKxTPlOVgaY.woff2) format('woff2');
unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
/* greek */
@font-face {
font-family: 'JetBrains Mono';
font-style: normal;
font-weight: 400;
font-display: swap;
src: url(/static/fonts/tDbY2o-flEEny0FZhsfKu5WU4zr3E_BX0PnT8RD8yKxTOVOVgaY.woff2) format('woff2');
unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF;
}
/* vietnamese */
@font-face {
font-family: 'JetBrains Mono';
font-style: normal;
font-weight: 400;
font-display: swap;
src: url(/static/fonts/tDbY2o-flEEny0FZhsfKu5WU4zr3E_BX0PnT8RD8yKxTNVOVgaY.woff2) format('woff2');
unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
}
/* latin-ext */
@font-face {
font-family: 'JetBrains Mono';
font-style: normal;
font-weight: 400;
font-display: swap;
src: url(/static/fonts/tDbY2o-flEEny0FZhsfKu5WU4zr3E_BX0PnT8RD8yKxTNFOVgaY.woff2) format('woff2');
unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
font-family: 'JetBrains Mono';
font-style: normal;
font-weight: 400;
font-display: swap;
src: url(/static/fonts/tDbY2o-flEEny0FZhsfKu5WU4zr3E_BX0PnT8RD8yKxTOlOV.woff2) format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
+120
View File
@@ -0,0 +1,120 @@
/* analysis.css - Theme-aware styles for Inventory and Analysis Panels */
.inventory-panel {
position: absolute;
bottom: 24px;
right: 24px;
width: 260px;
max-height: 320px;
z-index: 1000;
padding: 16px;
display: flex;
flex-direction: column;
gap: 12px;
pointer-events: auto !important;
}
.inventory-header {
display: flex;
align-items: center;
gap: 10px;
font-size: 13px;
font-weight: 800;
color: var(--text-color);
border-bottom: 1px solid var(--panel-border);
padding-bottom: 10px;
letter-spacing: -0.02em;
}
.inventory-header i {
color: var(--accent-color);
font-size: 14px;
}
.inventory-list {
display: flex;
flex-direction: column;
gap: 6px;
overflow-y: auto;
padding-right: 4px;
}
/* Custom Scrollbar for Inventory */
.inventory-list::-webkit-scrollbar {
width: 4px;
}
.inventory-list::-webkit-scrollbar-track {
background: transparent;
}
.inventory-list::-webkit-scrollbar-thumb {
background: var(--panel-border);
border-radius: 4px;
}
.inventory-item {
display: flex;
justify-content: space-between;
align-items: center;
background: var(--item-bg);
padding: 8px 14px 8px 18px;
border-radius: 12px;
border: 1px solid var(--panel-border);
transition: all 0.2s ease;
}
.inventory-item:hover {
background: var(--item-hover-bg);
transform: translateX(-2px);
}
.inventory-item .lbl {
font-weight: 600;
color: var(--sub-text);
font-size: 11px;
text-transform: capitalize;
}
.inventory-item .val {
font-weight: 800;
color: var(--accent-color);
background: rgba(59, 130, 246, 0.1);
padding: 2px 8px;
border-radius: 6px;
font-size: 12px;
min-width: 24px;
text-align: center;
}
.inventory-footer {
margin-top: auto;
padding-top: 12px;
border-top: 1px solid var(--panel-border);
}
.btn-export-bom {
width: 100%;
padding: 10px;
background: var(--accent-color);
color: white;
border: none;
border-radius: 12px;
font-size: 11px;
font-weight: 800;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
gap: 8px;
transition: all 0.2s ease;
box-shadow: 0 4px 12px rgba(59, 130, 246, 0.3);
}
.btn-export-bom:hover {
background: #2563eb;
transform: translateY(-2px);
box-shadow: 0 6px 16px rgba(59, 130, 246, 0.4);
}
.btn-export-bom i {
font-size: 12px;
}
+32
View File
@@ -0,0 +1,32 @@
/* Animations */
@keyframes fadeInUp {
from { opacity: 0; transform: translateY(20px); }
to { opacity: 1; transform: translateY(0); }
}
.animate-up {
animation: fadeInUp 0.6s cubic-bezier(0.23, 1, 0.32, 1) forwards;
}
/* Edge Flow Animation */
@keyframes drawnet-flow {
from { stroke-dashoffset: 20; }
to { stroke-dashoffset: 0; }
}
.flow-animation path {
stroke-dasharray: 5, 5;
animation: drawnet-flow 1s linear infinite;
}
/* Modal Animations */
@keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } }
@keyframes fadeOut { from { opacity: 1; } to { opacity: 0; } }
@keyframes scaleUp { from { opacity: 0; transform: scale(0.9) translateY(20px); } to { opacity: 1; transform: scale(1) translateY(0); } }
@keyframes scaleDown { from { opacity: 1; transform: scale(1) translateY(0); } to { opacity: 0; transform: scale(0.9) translateY(20px); } }
.animate-fade-in { animation: fadeIn 0.3s ease forwards; }
.animate-fade-out { animation: fadeOut 0.2s ease forwards; }
.animate-scale-up { animation: scaleUp 0.4s cubic-bezier(0.18, 0.89, 0.32, 1.28) forwards; }
.animate-scale-down { animation: scaleDown 0.3s ease forwards; }
+175
View File
@@ -0,0 +1,175 @@
.asset-library {
padding: 0 16px;
flex: 1;
overflow-y: auto;
overflow-x: hidden;
}
.asset-library h3 {
font-size: 10px;
text-transform: uppercase;
letter-spacing: 1.5px;
color: var(--sub-text);
margin: 24px 16px 12px;
white-space: nowrap;
font-weight: 800;
}
.sidebar.collapsed .asset-library h3 {
opacity: 0;
}
.asset-category {
margin-bottom: 8px;
}
.category-header {
display: flex;
align-items: center;
justify-content: space-between;
padding: 12px 16px;
background: var(--item-bg);
border-radius: 12px;
cursor: pointer;
transition: background 0.2s;
}
.category-header:hover {
background: var(--item-hover-bg);
}
.category-header span {
font-size: 11px;
font-weight: 800;
color: var(--text-color);
text-transform: uppercase;
letter-spacing: 0.5px;
}
.category-header i {
font-size: 10px;
color: var(--sub-text);
transition: transform 0.3s;
}
.asset-category.active .category-header i {
transform: rotate(180deg);
}
.category-content {
display: none;
padding: 12px 0;
}
.asset-category.active .category-content {
display: block;
}
.sidebar.collapsed .category-content {
display: none !important; /* Always hide content in sidebar when collapsed */
}
.asset-grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 8px;
padding: 0 8px;
}
.asset-item {
background: var(--item-bg);
border: 1px solid var(--panel-border);
padding: 12px;
border-radius: 16px;
display: flex;
flex-direction: column;
align-items: center;
gap: 8px;
cursor: grab;
transition: all 0.3s;
min-width: 0;
}
.asset-item span {
font-size: 9px;
color: var(--text-color);
text-align: center;
word-break: break-all;
line-height: 1.3;
opacity: 0.8;
}
.sidebar.collapsed .asset-item span {
display: none;
}
.asset-item:hover {
background: var(--item-hover-bg);
transform: translateY(-2px);
box-shadow: 0 10px 20px rgba(0,0,0,0.05);
}
.asset-item img {
pointer-events: none;
}
/* Fixed Category Optimization */
.fixed-category .asset-grid {
grid-template-columns: repeat(4, 1fr);
gap: 10px;
}
.fixed-category .asset-item {
padding: 8px;
height: 44px;
width: 44px;
justify-content: center;
}
.fixed-category .asset-item span {
display: none;
}
.fixed-category .asset-item i,
.fixed-category .asset-item img {
margin-bottom: 0 !important;
}
.category-divider {
height: 1px;
background: linear-gradient(to right, transparent, rgba(255, 255, 255, 0.1), transparent);
margin: 20px 0;
position: relative;
}
.category-divider::after {
content: '-';
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background: var(--sidebar-bg);
padding: 0 10px;
font-size: 10px;
color: var(--sub-text);
font-weight: 800;
}
.asset-group-label {
font-size: 9px;
font-weight: 800;
color: var(--sub-text);
padding: 12px 16px 6px;
text-transform: uppercase;
letter-spacing: 0.8px;
opacity: 0.7;
display: flex;
align-items: center;
gap: 8px;
}
.asset-group-label::after {
content: '';
flex: 1;
height: 1px;
background: rgba(255,255,255,0.05);
}
+140
View File
@@ -0,0 +1,140 @@
:root {
--bg-color: #f8fafc;
--bg-rgb: 248, 250, 252;
--text-color: #0f172a;
--accent-color: #3b82f6;
--panel-bg: rgba(255, 255, 255, 0.7);
--panel-border: rgba(255, 255, 255, 0.5);
--shadow: 0 8px 32px 0 rgba(31, 38, 135, 0.07);
--sub-text: #64748b;
--canvas-bg: #ffffff;
--grid-color: rgba(0, 0, 0, 0.05);
--grid-size: 20px;
--item-bg: rgba(255, 255, 255, 0.4);
--item-hover-bg: #e2e8f0;
}
[data-theme="dark"] {
--bg-color: #020617;
--bg-rgb: 2, 6, 23;
--text-color: #f8fafc;
--accent-color: #3b82f6;
--panel-bg: rgba(15, 23, 42, 0.8);
--panel-border: rgba(255, 255, 255, 0.1);
--shadow: 0 8px 32px 0 rgba(0, 0, 0, 0.3);
--sub-text: #cbd5e1;
--canvas-bg: #1e293b;
--grid-color: rgba(255, 255, 255, 0.1);
--grid-size: 20px;
--item-bg: rgba(255, 255, 255, 0.05);
--item-hover-bg: rgba(255, 255, 255, 0.1);
}
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
font-family: 'Inter', -apple-system, sans-serif;
background-color: var(--bg-color);
color: var(--text-color);
height: 100vh;
overflow: hidden;
}
.glass-panel {
background: var(--panel-bg);
backdrop-filter: blur(12px) saturate(180%);
border: 1px solid var(--panel-border);
box-shadow: var(--shadow);
border-radius: 32px;
}
/* Markdown Rendering Styles */
.markdown-body {
font-size: 14px;
line-height: 1.7;
color: var(--text-color);
}
.markdown-body h1, .markdown-body h2, .markdown-body h3 {
margin-top: 24px;
margin-bottom: 16px;
font-weight: 800;
}
.markdown-body h1 { font-size: 1.8em; }
.markdown-body h2 {
font-size: 1.4em;
border-bottom: 1px solid var(--panel-border);
padding-bottom: 8px;
color: var(--accent-color);
}
.markdown-body h3 { font-size: 1.2em; }
.markdown-body p { margin-bottom: 16px; color: var(--sub-text); }
.markdown-body ul, .markdown-body ol {
padding-left: 20px;
margin-bottom: 16px;
}
.markdown-body li { margin-bottom: 8px; }
.markdown-body blockquote {
padding: 12px 20px;
margin: 16px 0;
background: var(--item-bg);
border-left: 4px solid var(--accent-color);
border-radius: 4px;
font-style: italic;
color: var(--sub-text);
}
.markdown-body code {
background: var(--item-bg);
padding: 2px 6px;
border-radius: 4px;
font-family: 'JetBrains Mono', 'Fira Code', monospace;
font-size: 0.9em;
color: var(--accent-color);
}
.markdown-body pre {
background: var(--item-bg);
padding: 16px;
border-radius: 12px;
overflow-x: auto;
margin-bottom: 16px;
}
.markdown-body table {
width: 100%;
border-collapse: collapse;
margin-bottom: 24px;
border: 1px solid var(--panel-border);
border-radius: 12px;
overflow: hidden;
}
.markdown-body th, .markdown-body td {
padding: 12px 16px;
border-bottom: 1px solid var(--panel-border);
text-align: left;
}
.markdown-body th {
background: var(--item-bg);
font-weight: 800;
color: var(--accent-color);
}
.markdown-body img {
max-width: 100%;
border-radius: 16px;
border: 1px solid var(--panel-border);
box-shadow: 0 4px 12px rgba(0,0,0,0.1);
margin: 16px 0;
}
+49
View File
@@ -0,0 +1,49 @@
.editor-panel {
position: absolute;
bottom: 24px;
right: 24px;
width: 480px;
min-width: 400px;
height: 200px;
z-index: 90;
overflow: hidden;
display: flex;
flex-direction: column;
transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);
transform-origin: bottom right;
}
.editor-panel.collapsed {
height: 40px; /* Header only height */
opacity: 0.8;
}
.editor-header {
padding: 12px 25px;
border-bottom: 1px solid var(--panel-border);
display: flex;
justify-content: space-between;
align-items: center;
}
.editor-header span {
font-size: 10px;
font-weight: 900;
color: var(--sub-text);
text-transform: uppercase;
letter-spacing: 1px;
}
#editor {
flex: 1;
width: 100%;
padding: 20px;
background: transparent;
border: none;
resize: none;
font-family: 'JetBrains Mono', 'Fira Code', monospace;
font-size: 13px;
color: var(--text-color);
outline: none;
line-height: 1.6;
}
+148
View File
@@ -0,0 +1,148 @@
.sidebar.collapsed .category-header {
display: none;
}
.category-collapsed-icon {
display: none;
width: 100%;
padding: 12px 0;
align-items: center;
justify-content: center;
cursor: pointer;
transition: all 0.2s;
position: relative;
border-radius: 12px;
}
.sidebar.collapsed .category-collapsed-icon {
display: flex;
z-index: 10;
}
.category-collapsed-icon:hover {
background: white;
transform: scale(1.1);
}
/* Flyout Panel */
.category-flyout {
position: fixed;
left: 90px;
top: auto;
width: 280px;
max-height: 80vh;
z-index: 9999;
display: flex;
flex-direction: column;
padding: 20px;
opacity: 0;
transform: translateX(-10px);
transition: all 0.3s cubic-bezier(0.18, 0.89, 0.32, 1.28);
pointer-events: none;
}
.category-flyout.active {
opacity: 1;
transform: translateX(0);
pointer-events: all;
}
.flyout-menu {
position: absolute;
bottom: 80px;
left: 20px;
width: 220px;
padding: 12px;
z-index: 1000;
box-shadow: 0 10px 30px rgba(0,0,0,0.2);
border: 1px solid var(--panel-border);
flex-direction: column;
gap: 2px;
}
.flyout-section {
display: flex;
flex-direction: column;
gap: 2px;
}
.section-label {
font-size: 9px;
font-weight: 800;
color: var(--sub-text);
text-transform: uppercase;
letter-spacing: 1px;
padding: 8px 14px 4px;
opacity: 0.6;
}
.flyout-item {
width: 100%;
padding: 10px 14px;
border: none;
background: transparent;
color: var(--text-color);
font-size: 13px;
font-weight: 600;
text-align: left;
display: flex;
align-items: center;
gap: 12px;
border-radius: 8px;
cursor: pointer;
transition: all 0.2s;
}
.flyout-item i {
width: 16px;
text-align: center;
color: var(--sub-text);
}
.flyout-item:hover {
background: var(--accent-color);
color: white;
}
.flyout-item:hover i {
color: white;
}
.flyout-item.primary {
color: var(--accent-color);
}
.flyout-item.primary:hover {
background: var(--accent-color);
color: white;
}
.divider {
height: 1px;
background: var(--panel-border);
margin: 8px 4px;
}
.flyout-header {
margin-bottom: 15px;
padding-bottom: 10px;
border-bottom: 1px solid rgba(0,0,0,0.05);
}
.flyout-header strong {
font-size: 14px;
display: block;
}
.flyout-header small {
font-size: 10px;
color: #94a3b8;
text-transform: uppercase;
}
.flyout-grid {
overflow-y: auto;
display: grid;
grid-template-columns: 1fr 1fr;
gap: 12px;
padding-right: 5px;
}
+139
View File
@@ -0,0 +1,139 @@
.header {
position: absolute;
top: 24px;
right: 24px;
height: 80px;
z-index: 90;
padding: 0 30px;
display: flex;
align-items: center;
justify-content: space-between;
transition: all 0.3s ease;
}
.header-compact {
height: 50px;
padding: 0 20px;
top: 15px;
right: 24px;
}
.header-compact h2 {
font-size: 13px !important;
}
.header-compact p {
font-size: 9px !important;
}
.header-info {
display: flex;
flex-direction: column;
}
.header-status {
display: flex;
align-items: center;
gap: 12px;
background: rgba(16, 185, 129, 0.1);
padding: 4px 12px;
border-radius: 20px;
border: 1px solid rgba(16, 185, 129, 0.2);
}
.help-circle-btn {
background: transparent;
border: none;
color: #047857;
font-size: 16px;
cursor: pointer;
transition: all 0.2s ease;
padding: 2px;
display: flex;
align-items: center;
justify-content: center;
}
.help-circle-btn:hover {
color: #10b981;
transform: scale(1.1);
}
.status-dot {
width: 6px;
height: 6px;
border-radius: 50%;
}
.status-dot.online {
background: #10b981;
box-shadow: 0 0 8px #10b981;
}
.header h2 {
font-size: 14px;
font-weight: 800;
}
.header-btns {
display: flex;
gap: 15px;
}
.btn {
padding: 12px 24px;
border-radius: 16px;
font-size: 12px;
font-weight: 700;
cursor: pointer;
border: none;
transition: all 0.2s;
}
.btn-secondary {
background: var(--item-bg);
color: var(--sub-text);
}
.btn-primary {
background: var(--accent-color);
color: white;
box-shadow: 0 4px 12px rgba(59, 130, 246, 0.3);
}
.header-search {
flex: 1;
max-width: 400px;
margin: 0 40px;
background: rgba(255, 255, 255, 0.2);
border: 1px solid var(--panel-border);
border-radius: 20px;
padding: 6px 15px;
display: flex;
align-items: center;
gap: 10px;
transition: all 0.2s;
}
.header-search:focus-within {
background: rgba(255, 255, 255, 0.4);
box-shadow: 0 4px 12px rgba(0,0,0,0.05);
}
.header-search i {
color: var(--sub-text);
font-size: 13px;
}
.header-search input {
background: transparent;
border: none;
outline: none;
color: var(--text-color);
font-size: 12px;
width: 100%;
}
.btn:active {
transform: scale(0.95);
}
+318
View File
@@ -0,0 +1,318 @@
/* layers.css - Layer Management Panel Styles */
.layer-panel {
position: absolute;
bottom: 24px;
right: 300px; /* Offset from Inventory */
width: 250px;
max-height: 400px;
z-index: 1000;
padding: 16px;
display: flex;
flex-direction: column;
gap: 12px;
pointer-events: auto !important;
}
.layer-item.dragging {
opacity: 0.4;
background: var(--primary-color-dim);
border: 1px dashed var(--primary-color);
}
.drag-handle {
cursor: grab;
color: #64748b;
margin-right: 12px;
font-size: 12px;
}
.layer-item:active .drag-handle {
cursor: grabbing;
}
.panel-header {
display: flex;
align-items: center;
justify-content: space-between;
gap: 10px;
font-size: 13px;
font-weight: 800;
color: var(--text-color);
border-bottom: 1px solid var(--panel-border);
padding-bottom: 10px;
}
.panel-header i {
color: var(--accent-color);
}
.layer-list {
display: flex;
flex-direction: column;
gap: 8px;
overflow-y: auto;
}
.layer-item {
display: flex;
align-items: center;
gap: 10px;
padding: 8px 12px;
background: var(--item-bg);
border: 1px solid var(--panel-border);
border-radius: 10px;
cursor: pointer;
transition: all 0.2s ease;
}
.layer-item:hover {
background: var(--item-hover-bg);
border-color: var(--accent-color);
}
.layer-item.active {
border-color: var(--accent-color);
background: rgba(59, 130, 246, 0.1);
}
.layer-color {
width: 12px;
height: 12px;
border-radius: 50%;
}
.layer-name {
flex: 1;
font-size: 11px;
font-weight: 600;
color: var(--text-color);
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.layer-actions {
display: flex;
gap: 4px;
}
.layer-actions button {
background: none;
border: none;
color: var(--sub-text);
cursor: pointer;
font-size: 12px;
padding: 2px;
}
.layer-actions button:hover {
color: var(--accent-color);
}
.panel-header button {
background: var(--accent-color);
color: white !important;
border: none;
border-radius: 4px;
width: 24px;
height: 24px;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
font-size: 12px;
transition: all 0.2s ease;
}
.panel-header button:hover {
background: #2563eb;
transform: scale(1.1);
}
.panel-header button i {
color: white !important; /* Force icon color */
}
.mini-btn:hover {
background: #2563eb;
}
.layer-footer {
margin-top: auto;
padding-top: 10px;
border-top: 1px solid var(--panel-border);
}
.opacity-control {
display: flex;
align-items: center;
gap: 8px;
font-size: 11px;
color: var(--sub-text);
}
.opacity-control input[type="range"] {
flex: 1;
height: 6px;
background: rgba(0, 0, 0, 0.1);
border-radius: 3px;
appearance: none;
cursor: pointer;
outline: none;
}
.opacity-control input[type="range"]::-webkit-slider-runnable-track {
background: linear-gradient(to right, var(--accent-color), #ddd);
height: 6px;
border-radius: 3px;
}
.opacity-control input[type="range"]::-webkit-slider-thumb {
appearance: none;
width: 14px;
height: 14px;
background: var(--accent-color);
border: 2px solid white;
box-shadow: 0 1px 3px rgba(0,0,0,0.3);
border-radius: 50%;
cursor: pointer;
margin-top: -4px; /* Align with track */
}
#opacity-val {
min-width: 30px;
text-align: right;
}
.layer-rename-input {
background: white;
border: 1px solid var(--accent-color);
border-radius: 4px;
padding: 2px 4px;
font-size: 13px;
width: 100px;
outline: none;
color: var(--main-text);
}
/* Trash Bin for Deletion */
.layer-trash {
margin-top: 12px;
padding: 12px;
border: 1.5px dashed rgba(239, 68, 68, 0.4);
border-radius: 10px;
color: #ef4444;
display: flex;
align-items: center;
justify-content: center;
gap: 10px;
font-size: 11px;
font-weight: 700;
transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
background: rgba(239, 68, 68, 0.05);
}
.layer-trash i {
font-size: 14px;
}
.layer-trash.drag-over {
background: #ef4444;
color: white;
border-color: #ef4444;
transform: scale(1.02);
box-shadow: 0 4px 12px rgba(239, 68, 68, 0.3);
}
/* Visual Nudge: Pulse Animation */
@keyframes nudgePulse {
0% { box-shadow: 0 0 0 0 rgba(59, 130, 246, 0.7); }
70% { box-shadow: 0 0 0 10px rgba(59, 130, 246, 0); }
100% { box-shadow: 0 0 0 0 rgba(59, 130, 246, 0); }
}
.pulse-nudge {
animation: nudgePulse 1.5s infinite;
border-radius: 4px;
background: rgba(59, 130, 246, 0.1);
}
/* Mini Guide Tooltip */
.nudge-tooltip {
position: absolute;
left: 45px;
background: #3b82f6;
color: white;
padding: 6px 10px;
border-radius: 6px;
font-size: 10px;
font-weight: 700;
white-space: nowrap;
pointer-events: none;
box-shadow: 0 4px 12px rgba(59, 130, 246, 0.4);
animation: tooltipFadeIn 0.3s ease-out forwards;
z-index: 1001;
}
.nudge-tooltip::before {
content: '';
position: absolute;
left: -4px;
top: 50%;
transform: translateY(-50%);
border-top: 4px solid transparent;
border-bottom: 4px solid transparent;
border-right: 4px solid #3b82f6;
}
@keyframes tooltipFadeIn {
from { opacity: 0; transform: translateX(-10px); }
to { opacity: 1; transform: translateX(0); }
}
@keyframes tooltipFadeOut {
from { opacity: 1; transform: translateX(0); }
to { opacity: 0; transform: translateX(5px); }
}
/* Active Layer Floating Badge */
.active-layer-badge {
position: absolute;
top: 20px;
right: 20px;
z-index: 100;
pointer-events: none;
display: flex;
align-items: center;
gap: 8px;
background: rgba(15, 23, 42, 0.6);
backdrop-filter: blur(12px);
padding: 8px 16px;
border-radius: 20px;
border: 1px solid rgba(255, 255, 255, 0.1);
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.2);
animation: fadeInDown 0.5s ease-out;
}
.active-layer-badge .badge-label {
font-size: 9px;
font-weight: 800;
color: #94a3b8;
letter-spacing: 1px;
}
.active-layer-badge .badge-value {
font-size: 13px;
font-weight: 900;
text-shadow: 0 1px 3px rgba(0, 0, 0, 0.5);
transition: all 0.3s ease;
}
@keyframes badgePop {
0% { transform: scale(1); }
50% { transform: scale(1.1); }
100% { transform: scale(1); }
}
.badge-pop {
animation: badgePop 0.3s ease-out;
}
+84
View File
@@ -0,0 +1,84 @@
/* Main Area Adjustment */
.header, .editor-panel {
left: 284px; /* Default sidebar width + margin */
transition: left 0.3s cubic-bezier(0.4, 0, 0.2, 1);
}
.sidebar.collapsed ~ .header,
.sidebar.collapsed ~ .editor-panel,
.sidebar.collapsed ~ .main-viewport {
left: 104px; /* Collapsed sidebar width + margin */
}
.main-viewport {
position: absolute;
top: 0;
left: 284px;
right: 0;
bottom: 0;
overflow: auto;
background-color: var(--bg-color);
display: flex;
/* justify-content and align-items removed to allow margin:auto to handle centering with overflow */
padding: 60px; /* Space for shadow and boundaries */
transition: left 0.3s cubic-bezier(0.4, 0, 0.2, 1);
scrollbar-gutter: stable;
}
#cy {
flex-shrink: 0;
background-color: var(--canvas-bg); /* Theme-aware paper background */
position: relative;
/* Sizes will be set by JS or default to 100% */
width: 100%;
height: 100%;
margin: auto; /* Handles centering when sized fixed (A3/A4) */
box-shadow: 0 0 40px rgba(0,0,0,0.1);
border: 1px solid var(--panel-border); /* Visible canvas boundary */
}
#cy.grid-solid {
background-image:
linear-gradient(var(--grid-color) 1px, transparent 1px),
linear-gradient(90deg, var(--grid-color) 1px, transparent 1px);
background-size: var(--grid-size) var(--grid-size);
}
#cy.grid-dashed {
background-image:
radial-gradient(var(--grid-color) 1px, transparent 1px);
background-size: var(--grid-size) var(--grid-size);
}
/* Inventory Panel Overlay (Legacy - handled in analysis.css) */
/* .inventory-panel { ... } */
.inventory-header {
font-size: 11px;
font-weight: 800;
text-transform: uppercase;
color: var(--sub-text);
margin-bottom: 12px;
display: flex;
align-items: center;
gap: 8px;
}
.inventory-item {
display: flex;
justify-content: space-between;
align-items: center;
padding: 6px 0;
font-size: 12px;
font-weight: 600;
color: var(--text-color);
border-bottom: 1px solid rgba(255,255,255,0.05);
}
.inventory-item .count {
background: var(--accent-color);
color: white;
padding: 2px 8px;
border-radius: 10px;
font-size: 10px;
font-weight: 800;
}
+141
View File
@@ -0,0 +1,141 @@
.modal-overlay {
position: fixed;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
background: rgba(0, 0, 0, 0.2);
backdrop-filter: blur(4px);
z-index: 10000;
display: flex;
align-items: center;
justify-content: center;
opacity: 0;
pointer-events: none;
transition: opacity 0.3s;
}
.modal-overlay.active {
opacity: 1;
pointer-events: all;
}
.modal-content {
width: 500px;
max-width: 90vw;
background: var(--panel-bg);
backdrop-filter: blur(20px) saturate(180%);
border: 1px solid var(--panel-border);
border-radius: 32px;
box-shadow: 0 20px 50px rgba(0,0,0,0.1);
transform: scale(0.9) translateY(20px);
transition: all 0.4s cubic-bezier(0.18, 0.89, 0.32, 1.28);
display: flex;
flex-direction: column;
overflow: hidden;
}
.modal-overlay.active .modal-content {
transform: scale(1) translateY(0);
}
.modal-header {
padding: 24px 30px;
border-bottom: 1px solid var(--panel-border);
display: flex;
justify-content: space-between;
align-items: center;
}
.modal-header h2 {
font-size: 18px;
font-weight: 800;
color: var(--text-color);
}
.close-modal {
background: transparent;
border: none;
font-size: 20px;
color: var(--sub-text);
cursor: pointer;
transition: color 0.2s;
}
.close-modal:hover {
color: var(--text-color);
}
.modal-body {
padding: 30px;
flex: 1;
}
.settings-group {
margin-bottom: 24px;
}
.settings-group h3 {
font-size: 11px;
text-transform: uppercase;
letter-spacing: 1px;
color: var(--sub-text);
margin-bottom: 12px;
}
.setting-item {
display: flex;
justify-content: space-between;
align-items: center;
padding: 10px 0;
}
.setting-label {
font-size: 14px;
font-weight: 600;
}
.setting-item select,
.setting-item input[type="number"],
.setting-item input[type="text"] {
background: var(--item-bg);
border: 1px solid var(--panel-border);
border-radius: 8px;
padding: 6px 10px;
font-size: 13px;
color: var(--text-color);
outline: none;
transition: border-color 0.2s;
}
.setting-item select:focus,
.setting-item input:focus {
border-color: var(--accent-color);
}
.setting-item select option {
background-color: var(--bg-color);
color: var(--text-color);
}
.setting-item input[type="color"] {
appearance: none;
width: 40px;
height: 24px;
border: none;
border-radius: 4px;
cursor: pointer;
background: none;
}
.setting-item input[type="color"]::-webkit-color-swatch {
border: 1px solid var(--panel-border);
border-radius: 4px;
}
.modal-footer {
padding: 20px 30px;
border-top: 1px solid var(--panel-border);
display: flex;
justify-content: flex-end;
}
+256
View File
@@ -0,0 +1,256 @@
/* Properties Sidebar Styles */
#properties-sidebar {
position: fixed;
right: -320px; /* Hidden by default */
top: 60px; /* Below header */
bottom: 0;
width: 300px;
background: var(--panel-bg);
backdrop-filter: blur(16px);
-webkit-backdrop-filter: blur(16px);
border-left: 1px solid var(--panel-border);
box-shadow: -10px 0 25px rgba(0, 0, 0, 0.3);
transition: right 0.3s cubic-bezier(0.4, 0, 0.2, 1);
z-index: 900;
display: flex;
flex-direction: column;
color: var(--text-color);
}
#properties-sidebar.open {
right: 0;
}
.sidebar-header {
padding: 18px 20px;
border-bottom: 1px solid var(--panel-border);
display: flex;
justify-content: space-between;
align-items: center;
}
.sidebar-header h3 {
margin: 0;
font-size: 16px;
font-weight: 800;
color: var(--accent-color);
}
.close-sidebar {
cursor: pointer;
font-size: 20px;
color: var(--sub-text);
transition: color 0.2s;
}
.close-sidebar:hover {
color: var(--text-color);
}
.sidebar-content {
flex: 1;
overflow-y: auto;
padding: 24px 20px;
}
.prop-group {
margin-bottom: 20px;
}
.prop-row {
display: flex;
gap: 12px;
margin-bottom: 16px;
}
.prop-row .prop-group {
flex: 1;
margin-bottom: 0;
}
.prop-group.horizontal {
display: flex;
align-items: center;
gap: 12px;
}
.prop-group.horizontal label {
flex: 0 0 80px;
margin-bottom: 0;
}
.prop-group.horizontal .prop-input {
flex: 1;
}
.prop-group label {
display: block;
font-size: 11px;
text-transform: uppercase;
letter-spacing: 0.08em;
color: var(--sub-text);
margin-bottom: 8px;
font-weight: 700;
}
.prop-input {
width: 100%;
background: var(--item-bg);
border: 1px solid var(--panel-border);
border-radius: 8px;
padding: 9px 12px;
color: var(--text-color);
font-size: 14px;
outline: none;
transition: all 0.2s;
}
.prop-input:focus {
border-color: var(--accent-color);
background: var(--item-hover-bg);
}
.sidebar-footer {
padding: 16px 20px;
border-top: 1px solid var(--panel-border);
display: flex;
gap: 12px;
background: rgba(var(--bg-rgb), 0.05);
}
.btn-apply {
flex: 1;
background: var(--accent-color);
color: white;
border: none;
padding: 12px;
border-radius: 8px;
cursor: pointer;
font-weight: 700;
transition: all 0.2s;
}
.btn-apply:hover {
filter: brightness(1.1);
transform: translateY(-1px);
}
/* Toggle Switch Styles */
.toggle-group {
margin-bottom: 24px;
}
.toggle-switch {
display: flex;
align-items: center;
justify-content: space-between;
cursor: pointer;
padding: 12px 14px;
background: var(--item-bg);
border: 1px solid var(--panel-border);
border-radius: 12px;
transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
}
.toggle-switch:hover {
background: var(--item-hover-bg);
border-color: var(--accent-color);
}
.toggle-switch span {
font-size: 13px;
font-weight: 600;
color: var(--text-color);
}
.toggle-switch input {
display: none;
}
.switch-slider {
position: relative;
width: 36px;
height: 20px;
background: #475569;
border-radius: 20px;
transition: background 0.3s;
}
.switch-slider:before {
content: "";
position: absolute;
width: 16px;
height: 16px;
left: 2px;
top: 2px;
background: white;
border-radius: 50%;
transition: transform 0.2s cubic-bezier(0.4, 0, 0.2, 1);
box-shadow: 0 1px 3px rgba(0,0,0,0.3);
}
.toggle-switch input:checked + .switch-slider {
background: var(--accent-color);
}
.toggle-switch input:checked + .switch-slider:before {
transform: translateX(16px);
}
/* Multi-Selection Alignment UI */
.alignment-grid {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 10px;
margin-top: 12px;
}
.align-btn {
aspect-ratio: 1;
background: var(--item-bg);
border: 1px solid var(--panel-border);
border-radius: 8px;
color: var(--sub-text);
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
font-size: 16px;
transition: all 0.2s;
}
.align-btn:hover:not(:disabled) {
background: var(--accent-color);
color: white;
border-color: var(--accent-color);
}
.align-btn:disabled {
opacity: 0.2;
cursor: not-allowed;
}
/* Color Input Consistency */
.input-with-color {
display: flex;
gap: 8px;
align-items: center;
}
.input-with-color .prop-input[type="color"] {
width: 44px;
height: 38px;
padding: 3px;
cursor: pointer;
flex-shrink: 0;
}
.input-with-color .prop-input[type="color"]::-webkit-color-swatch {
border: 1px solid var(--panel-border);
border-radius: 4px;
}
/* Danger variant for toggle-switch */
.toggle-switch.danger input:checked + .switch-slider {
background: #ef4444;
}
+195
View File
@@ -0,0 +1,195 @@
/* settings_panel.css - Professional Sliding Settings Panel */
.settings-panel {
position: fixed;
top: 10px;
right: -420px; /* Hidden by default */
width: 400px;
height: calc(100vh - 20px);
z-index: 2000;
display: flex;
flex-direction: column;
transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);
box-shadow: -10px 0 30px rgba(0, 0, 0, 0.3);
}
.settings-panel.active {
right: 10px;
}
.settings-header {
padding: 20px 24px;
border-bottom: 1px solid var(--panel-border);
display: flex;
justify-content: space-between;
align-items: center;
}
.header-title {
display: flex;
align-items: center;
gap: 12px;
font-size: 16px;
font-weight: 800;
color: var(--text-color);
}
.header-title i {
color: var(--accent-color);
}
.settings-container {
flex: 1;
display: flex;
overflow: hidden;
}
/* Sidebar Tabs */
.settings-sidebar {
width: 100px;
background: var(--item-bg);
border-right: 1px solid var(--panel-border);
display: flex;
flex-direction: column;
padding: 10px 0;
}
.settings-tab {
padding: 18px 10px;
display: flex;
flex-direction: column;
align-items: center;
gap: 10px;
cursor: pointer;
color: var(--sub-text);
transition: all 0.2s ease;
text-align: center;
}
.settings-tab i {
font-size: 20px;
}
.settings-tab span {
font-size: 9px;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.5px;
}
.settings-tab:hover {
color: var(--text-color);
background: var(--item-hover-bg);
}
.settings-tab.active {
color: var(--accent-color);
background: rgba(59, 130, 246, 0.1);
border-left: 3px solid var(--accent-color);
}
/* Body Content */
.settings-body {
flex: 1;
padding: 24px;
overflow-y: auto;
background: rgba(var(--bg-rgb), 0.1);
}
.settings-section {
margin-bottom: 30px;
animation: fadeIn 0.3s ease;
}
.settings-section h3 {
font-size: 11px;
color: var(--sub-text);
text-transform: uppercase;
margin-bottom: 16px;
letter-spacing: 0.8px;
font-weight: 800;
}
.setting-row {
display: flex;
justify-content: space-between;
align-items: center;
padding: 14px 0;
border-bottom: 1px solid var(--panel-border);
}
.setting-info {
display: flex;
flex-direction: column;
gap: 4px;
}
.setting-info .label {
font-size: 14px;
font-weight: 600;
color: var(--text-color);
}
.setting-info .desc {
font-size: 11px;
color: var(--sub-text);
}
.setting-ctrl select,
.setting-ctrl input[type="number"],
.setting-ctrl input[type="text"] {
background: var(--item-bg);
border: 1px solid var(--panel-border);
color: var(--text-color);
padding: 7px 12px;
border-radius: 8px;
font-size: 13px;
outline: none;
transition: border-color 0.2s;
}
.setting-ctrl select:focus,
.setting-ctrl input:focus {
border-color: var(--accent-color);
}
/* Toggle switch adjustments within settings */
.toggle-switch {
background: var(--item-bg) !important;
border: 1px solid var(--panel-border) !important;
}
.toggle-switch:hover {
background: var(--item-hover-bg) !important;
border-color: var(--accent-color) !important;
}
.toggle-switch .label {
color: var(--sub-text) !important;
}
/* Animation */
@keyframes fadeIn {
from { opacity: 0; transform: translateY(5px); }
to { opacity: 1; transform: translateY(0); }
}
.close-btn {
background: none;
border: none;
color: var(--sub-text);
cursor: pointer;
font-size: 20px;
transition: all 0.2s;
width: 32px;
height: 32px;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
}
.close-btn:hover {
background: #ef4444;
color: white;
}
+140
View File
@@ -0,0 +1,140 @@
.sidebar {
position: absolute;
left: 0;
top: 0;
bottom: 0;
width: 260px;
z-index: 100;
display: flex;
flex-direction: column;
border-radius: 0;
border-left: none;
border-top: none;
border-bottom: none;
transition: width 0.3s cubic-bezier(0.4, 0, 0.2, 1);
overflow: hidden;
overflow-x: hidden;
}
.sidebar.collapsed {
width: 80px;
overflow-x: hidden !important;
}
.sidebar-header {
padding: 24px;
display: flex;
align-items: center;
justify-content: space-between;
min-height: 80px;
transition: padding 0.3s;
overflow: hidden;
}
.sidebar.collapsed .sidebar-header {
padding: 24px 0;
flex-direction: column;
gap: 15px;
justify-content: center;
}
.menu-toggle {
background: transparent;
border: none;
color: var(--sub-text);
font-size: 20px;
cursor: pointer;
width: 32px;
height: 32px;
display: flex;
align-items: center;
justify-content: center;
border-radius: 8px;
transition: all 0.2s;
}
.sidebar.collapsed .menu-toggle {
order: -1; /* Toggle button first when collapsed */
}
.menu-toggle:hover {
background: var(--item-bg);
}
.logo-area {
display: flex;
align-items: center;
gap: 12px;
transition: opacity 0.2s;
white-space: nowrap;
}
.sidebar.collapsed .logo-text {
display: none;
}
.logo-icon {
min-width: 40px;
width: 40px;
height: 40px;
background: linear-gradient(135deg, #3b82f6, #6366f1);
border-radius: 12px;
display: flex;
align-items: center;
justify-content: center;
color: white;
font-weight: 900;
font-size: 18px;
box-shadow: 0 4px 12px rgba(59, 130, 246, 0.3);
}
.search-container {
padding: 0 24px 20px;
position: relative;
transition: padding 0.3s;
}
.search-container i {
position: absolute;
left: 40px;
top: 13px;
font-size: 14px;
color: var(--sub-text);
z-index: 5;
transition: all 0.3s;
}
#asset-search {
width: 100%;
background: var(--item-bg);
border: 1px solid var(--panel-border);
padding: 10px 15px 10px 40px;
border-radius: 12px;
font-size: 13px;
font-family: inherit;
outline: none;
transition: all 0.2s;
}
#asset-search:focus {
background: var(--item-hover-bg);
box-shadow: 0 4px 12px rgba(0,0,0,0.03);
border-color: #3b82f6;
}
.sidebar.collapsed .search-container {
padding: 10px 0;
display: flex;
justify-content: center;
}
.sidebar.collapsed #asset-search {
display: none;
}
.sidebar.collapsed .search-container i {
font-size: 18px;
color: var(--sub-text);
cursor: pointer;
position: static;
}
+68
View File
@@ -0,0 +1,68 @@
/* Sidebar Footer Settings */
.sidebar-footer {
padding: 20px 24px;
border-top: 1px solid var(--panel-border);
display: flex;
align-items: center;
gap: 12px;
margin-top: auto; /* Push to bottom */
}
.footer-btns {
display: flex;
gap: 8px;
}
.footer-btn {
width: 32px;
height: 32px;
background: var(--item-bg);
border: none;
border-radius: 8px;
color: var(--sub-text);
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
transition: all 0.2s;
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
}
.footer-btn:hover {
background: var(--item-hover-bg);
color: white;
}
#settings-btn:hover {
transform: rotate(45deg);
}
#system-menu-btn.active {
background: var(--accent-color);
color: white;
}
.footer-text {
flex: 1;
}
.footer-text p {
font-size: 11px;
font-weight: 800;
margin: 0;
}
.footer-text small {
font-size: 9px;
color: var(--sub-text);
}
.sidebar.collapsed .sidebar-footer {
padding: 20px 0;
flex-direction: column;
justify-content: center;
}
.sidebar.collapsed .footer-text {
display: none;
}
+99
View File
@@ -0,0 +1,99 @@
.floating-window {
position: fixed;
background: var(--sidebar-bg);
backdrop-filter: blur(20px);
border: 1px solid var(--panel-border);
border-radius: 16px;
box-shadow: 0 20px 50px rgba(0,0,0,0.3);
display: flex;
flex-direction: column;
overflow: hidden;
animation: win-appear 0.3s cubic-bezier(0.16, 1, 0.3, 1);
}
@keyframes win-appear {
from { opacity: 0; transform: scale(0.9) translateY(20px); }
to { opacity: 1; transform: scale(1) translateY(0); }
}
.win-header {
padding: 12px 20px;
background: rgba(255, 255, 255, 0.05);
border-bottom: 1px solid var(--panel-border);
display: flex;
align-items: center;
justify-content: space-between;
cursor: grab;
user-select: none;
}
.win-header:active {
cursor: grabbing;
}
.win-title {
font-size: 13px;
font-weight: 800;
color: var(--text-color);
display: flex;
align-items: center;
gap: 10px;
}
.win-controls {
display: flex;
gap: 10px;
}
.win-btn {
background: transparent;
border: none;
color: var(--sub-text);
cursor: pointer;
font-size: 12px;
width: 24px;
height: 24px;
display: flex;
align-items: center;
justify-content: center;
border-radius: 6px;
transition: all 0.2s;
}
.win-btn:hover {
background: var(--item-hover-bg);
color: var(--text-color);
}
.win-btn.win-close:hover {
background: #ef4444;
color: white;
}
.floating-window.minimized {
height: 48px !important;
width: 250px !important;
}
.floating-window.minimized .win-body {
display: none;
}
.win-body {
flex: 1;
overflow: auto;
padding: 20px;
}
/* Studio Specific Polish */
.studio-container {
height: 100%;
}
.studio-modal .preview-area {
min-height: 200px;
}
[data-theme='dark'] .floating-window {
background: rgba(15, 23, 42, 0.8);
}
+190
View File
@@ -0,0 +1,190 @@
/*
drawNET Premium CSS Manifest
This file imports modules to keep the production bundle organized.
*/
@import "modules/base.css";
@import "modules/sidebar.css";
@import "modules/sidebar_footer.css";
@import "modules/assets.css";
@import "modules/flyout.css";
@import "modules/header.css";
@import "modules/editor.css";
@import "modules/layout.css";
@import "modules/animations.css";
@import "modules/modal.css";
@import "modules/settings_panel.css";
@import "modules/properties_sidebar.css";
/* Floating Context Menu */
.floating-menu {
background: rgba(30, 41, 59, 0.85); /* Slate 800-ish with glassmorphism */
border: 1px solid rgba(255, 255, 255, 0.1);
border-radius: 10px;
box-shadow: 0 10px 25px -5px rgba(0, 0, 0, 0.5);
padding: 6px;
min-width: 180px;
backdrop-filter: blur(12px);
-webkit-backdrop-filter: blur(12px);
}
.menu-item {
padding: 10px 14px;
border-radius: 8px;
cursor: pointer;
font-size: 13px;
color: #f1f5f9;
transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
display: flex;
align-items: center;
}
.menu-item:hover {
background: #3b82f6; /* Blue 500 */
color: white;
transform: translateY(-1px);
}
.menu-divider {
height: 1px;
background: rgba(255, 255, 255, 0.1);
margin: 6px 0;
}
.menu-label {
padding: 6px 14px 4px;
font-size: 10px;
font-weight: 700;
color: #475569;
text-transform: uppercase;
letter-spacing: 0.05em;
}
.menu-icon-row {
display: flex;
justify-content: space-between;
padding: 4px 8px;
gap: 4px;
}
.icon-btn {
flex: 1;
height: 32px;
display: flex;
align-items: center;
justify-content: center;
border-radius: 6px;
cursor: pointer;
color: #94a3b8;
transition: all 0.2s;
font-size: 14px;
}
.icon-btn:hover {
background: #3b82f6;
color: white;
}
.icon-btn i.fa-rotate-90 {
transform: rotate(90deg);
}
/* --- X6 Port Styles --- */
.x6-port {
visibility: hidden;
transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
}
.x6-node:hover .x6-port {
visibility: visible;
}
.x6-port circle {
cursor: crosshair;
}
.x6-port circle:hover {
fill: #3b82f6 !important;
r: 6 !important;
}
/* --- X6 Edge Selection Highlight --- */
.x6-edge-selected path {
stroke: #3b82f6 !important;
stroke-width: 3px !important;
filter: drop-shadow(0 0 3px rgba(59, 130, 246, 0.8));
transition: all 0.2s ease;
}
/* Flow animation for selected flow lines */
.x6-edge-selected.flow-animation path {
stroke-width: 4px !important;
}
/* Mini buttons for editor actions */
.footer-btn.mini {
width: auto;
padding: 6px 12px;
font-size: 11px;
height: 28px;
background: rgba(59, 130, 246, 0.1);
border: 1px solid rgba(59, 130, 246, 0.2);
color: #3b82f6;
border-radius: 6px;
margin-left: 6px;
display: inline-flex;
align-items: center;
gap: 6px;
font-weight: 700;
}
.footer-btn.mini:hover {
background: #3b82f6;
color: white;
}
/* --- Export Loading Overlay --- */
.export-overlay {
position: fixed;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
background: rgba(15, 23, 42, 0.65); /* Slate 900 with transparency */
backdrop-filter: blur(8px);
-webkit-backdrop-filter: blur(8px);
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
z-index: 9999;
color: white;
font-family: inherit;
animation: fadeIn 0.3s ease-out;
}
.export-spinner {
width: 50px;
height: 50px;
border: 4px solid rgba(255, 255, 255, 0.1);
border-left-color: #3b82f6;
border-radius: 50%;
animation: spin 1s linear infinite;
margin-bottom: 20px;
}
.export-text {
font-size: 18px;
font-weight: 700;
letter-spacing: -0.02em;
text-shadow: 0 2px 4px rgba(0, 0, 0, 0.3);
}
@keyframes spin {
to { transform: rotate(360deg); }
}
@keyframes fadeIn {
from { opacity: 0; }
to { opacity: 1; }
}
+344
View File
@@ -0,0 +1,344 @@
/*
* drawNET Studio - Asset Management Styles
*/
body.studio-body {
margin: 0;
padding: 0;
background: #0f172a;
color: #f8fafc;
height: 100vh;
overflow: hidden;
font-family: 'Inter', sans-serif;
}
.studio-layout {
display: grid;
grid-template-columns: 280px 1fr 320px;
grid-template-rows: 60px 1fr;
height: 100vh;
}
.studio-header {
grid-column: 1 / 4;
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 20px;
background: rgba(30, 41, 59, 0.7);
border-bottom: 1px solid rgba(255, 255, 255, 0.05);
backdrop-filter: blur(20px);
}
.studio-header-left {
display: flex;
align-items: center;
gap: 20px;
}
.header-metadata {
display: flex;
gap: 15px;
align-items: center;
}
.meta-input-group {
display: flex;
flex-direction: column;
}
.meta-label {
font-size: 9px;
color: #64748b;
font-weight: 800;
text-transform: uppercase;
}
.meta-input {
background: rgba(0, 0, 0, 0.2);
border: 1px solid rgba(255, 255, 255, 0.1);
color: #f8fafc;
padding: 4px 8px;
border-radius: 4px;
font-size: 13px;
transition: border-color 0.2s;
}
.meta-input:focus {
outline: none;
border-color: #38bdf8;
}
.meta-input.highlight {
color: #38bdf8;
font-weight: 700;
}
.panel {
background: rgba(15, 23, 42, 0.5);
border-right: 1px solid rgba(255, 255, 255, 0.05);
display: flex;
flex-direction: column;
overflow: hidden;
}
.panel-header {
padding: 15px 20px;
border-bottom: 1px solid rgba(255, 255, 255, 0.05);
font-size: 12px;
font-weight: 800;
color: #94a3b8;
letter-spacing: 0.05em;
text-transform: uppercase;
display: flex;
align-items: center;
justify-content: space-between;
}
.panel-content {
flex: 1;
overflow-y: auto;
padding: 20px;
}
/* Source Panel (Left) */
.source-panel {
background: rgba(15, 23, 42, 0.8);
}
.upload-area {
border: 2px dashed rgba(255, 255, 255, 0.1);
border-radius: 12px;
padding: 30px 20px;
text-align: center;
cursor: pointer;
transition: all 0.2s;
margin-bottom: 20px;
}
.upload-area:hover {
background: rgba(255, 255, 255, 0.02);
border-color: #38bdf8;
}
.upload-area i {
display: block;
font-size: 24px;
color: #38bdf8;
margin-bottom: 10px;
}
.upload-text {
font-size: 12px;
margin: 0;
}
.upload-hint {
font-size: 10px;
color: #64748b;
}
.source-list {
list-style: none;
padding: 0;
margin: 0;
}
.source-item {
padding: 10px 12px;
border-radius: 8px;
font-size: 13px;
cursor: pointer;
display: flex;
align-items: center;
gap: 10px;
transition: background 0.2s;
}
.source-item:hover {
background: rgba(255, 255, 255, 0.05);
}
.source-item i {
width: 16px;
opacity: 0.6;
}
/* Workspace (Center) */
.workspace {
background: #020617;
padding: 30px;
}
.asset-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));
gap: 20px;
}
.asset-card {
background: rgba(30, 41, 59, 0.5);
border: 1px solid rgba(255, 255, 255, 0.05);
border-radius: 12px;
padding: 15px;
display: flex;
flex-direction: column;
align-items: center;
gap: 10px;
cursor: pointer;
transition: all 0.2s;
}
.asset-card:hover {
transform: translateY(-2px);
background: rgba(30, 41, 59, 0.8);
border-color: #38bdf8;
}
.asset-card.selected {
border-color: #38bdf8;
background: rgba(56, 189, 248, 0.1);
box-shadow: 0 0 0 1px #38bdf8;
}
.asset-preview {
width: 64px;
height: 64px;
display: flex;
align-items: center;
justify-content: center;
}
.asset-preview img {
max-width: 100%;
max-height: 100%;
}
.asset-name {
font-size: 12px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
width: 100%;
text-align: center;
color: #cbd5e1;
}
/* Comparison View */
.comparison-view {
display: flex;
gap: 20px;
margin-top: 20px;
padding: 15px;
background: rgba(0, 0, 0, 0.3);
border-radius: 12px;
border: 1px solid rgba(255, 255, 255, 0.05);
}
.comp-box {
flex: 1;
display: flex;
flex-direction: column;
align-items: center;
gap: 10px;
}
.comp-preview {
width: 100px;
height: 100px;
background: #1e293b;
border-radius: 8px;
display: flex;
align-items: center;
justify-content: center;
overflow: hidden;
border: 1px solid rgba(255, 255, 255, 0.1);
}
.comp-preview img, .comp-preview svg {
max-width: 90%;
max-height: 90%;
}
.comp-label {
font-size: 10px;
font-weight: 800;
color: #64748b;
text-transform: uppercase;
}
.choice-btn {
background: rgba(255, 255, 255, 0.05);
border: 1px solid rgba(255, 255, 255, 0.1);
color: #94a3b8;
padding: 8px 12px;
border-radius: 6px;
font-size: 11px;
cursor: pointer;
width: 100%;
transition: all 0.2s;
}
.choice-btn.active {
background: #38bdf8;
color: #0f172a;
border-color: #38bdf8;
font-weight: 700;
}
/* Property Panel (Right) */
.property-panel {
border-left: 1px solid rgba(255, 255, 255, 0.05);
background: rgba(15, 23, 42, 0.8);
}
.property-empty {
text-align: center;
color: #64748b;
margin-top: 50px;
}
.property-empty i {
font-size: 30px;
margin-bottom: 15px;
display: block;
}
.property-empty p {
font-size: 13px;
}
.btn-primary {
background: #38bdf8;
color: #0f172a;
border: none;
padding: 8px 16px;
border-radius: 8px;
font-weight: 700;
font-size: 13px;
cursor: pointer;
transition: all 0.2s;
}
.btn-primary:hover {
background: #7dd3fc;
transform: translateY(-1px);
}
.back-link {
text-decoration: none;
color: #94a3b8;
font-size: 13px;
display: flex;
align-items: center;
gap: 8px;
}
.back-link:hover {
color: #cbd5e1;
}
.placeholder-icon {
font-size: 32px;
color: #334155;
}
+1
View File
@@ -0,0 +1 @@
/* Ghost file to prevent MIME type 404 errors in legacy/library environments */
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 110 KiB

+54
View File
@@ -0,0 +1,54 @@
{
"hotkeys": [
{ "key": "Delete", "code": "Delete", "action": "deleteSelected", "description": "Remove selected elements" },
{ "key": "Backspace", "code": "Backspace", "action": "deleteSelected", "description": "Remove selected elements" },
{ "ctrl": true, "key": "f", "code": "KeyF", "action": "fitScreen", "description": "Fit to screen" },
{ "ctrl": true, "key": "=", "code": "Equal", "action": "zoomIn", "description": "Zoom in" },
{ "ctrl": true, "key": "+", "code": "Equal", "shift": true, "action": "zoomIn", "description": "Zoom in" },
{ "ctrl": true, "key": "-", "code": "Minus", "action": "zoomOut", "description": "Zoom out" },
{ "ctrl": true, "key": "s", "code": "KeyS", "action": "exportJson", "description": "Export JSON" },
{ "ctrl": true, "key": "o", "code": "KeyO", "action": "importJson", "description": "Import JSON" },
{ "alt": true, "key": "0", "code": "Digit0", "alwaysEnabled": true, "action": "toggleInventory", "description": "Toggle Inventory Panel" },
{ "alt": true, "key": "1", "code": "Digit1", "alwaysEnabled": true, "action": "toggleProperties", "description": "Toggle Properties Sidebar" },
{ "alt": true, "key": "Enter", "code": "Enter", "alwaysEnabled": true, "action": "toggleProperties", "description": "Open/Toggle Properties Sidebar" },
{ "key": "F2", "code": "F2", "action": "editLabel", "description": "Edit label of selected element" },
{ "key": "[", "code": "BracketLeft", "action": "sendToBack", "description": "Send selected to back" },
{ "key": "]", "code": "BracketRight", "action": "bringToFront", "description": "Bring selected to front" },
{ "ctrl": true, "key": "l", "code": "KeyL", "action": "toggleLock", "description": "Lock/Unlock selected element" },
{ "alt": true, "key": "9", "code": "Digit9", "alwaysEnabled": true, "action": "toggleLayers", "description": "Toggle Layer Panel" },
{ "ctrl": true, "shift": true, "key": "l", "code": "KeyL", "action": "arrangeLayout", "description": "Auto-arrange layout" },
{ "shift": true, "key": "a", "code": "KeyA", "action": "connectNodes", "description": "Connect selected nodes (Manhattan)" },
{ "shift": true, "key": "s", "code": "KeyS", "action": "connectStraight", "description": "Connect selected nodes (Straight)" },
{ "alt": true, "key": "m", "code": "KeyM", "action": "connectNodes", "description": "Change to Manhattan Line" },
{ "alt": true, "key": "l", "code": "KeyL", "action": "connectStraight", "description": "Change to Straight Line" },
{ "shift": true, "key": "d", "code": "KeyD", "action": "disconnectNodes", "description": "Disconnect selected nodes" },
{ "ctrl": true, "key": "g", "code": "KeyG", "action": "groupNodes", "description": "Group Selected" },
{ "ctrl": true, "key": "z", "code": "KeyZ", "action": "undo", "alwaysEnabled": true, "description": "Undo last action" },
{ "ctrl": true, "key": "y", "code": "KeyY", "action": "redo", "alwaysEnabled": true, "description": "Redo last undone action" },
{ "ctrl": true, "shift": true, "key": "z", "code": "KeyZ", "action": "redo", "alwaysEnabled": true, "description": "Redo last undone action" },
{ "ctrl": true, "key": "c", "code": "KeyC", "action": "copyNodes", "description": "Copy selected nodes" },
{ "ctrl": true, "key": "v", "code": "KeyV", "action": "pasteNodes", "description": "Paste nodes from clipboard" },
{ "ctrl": true, "key": "d", "code": "KeyD", "action": "duplicateNodes", "description": "Duplicate selected nodes (Immediate)" },
{ "ctrl": true, "shift": true, "key": "c", "code": "KeyC", "action": "copyAttributes", "description": "Copy node attributes (Format Painter)" },
{ "ctrl": true, "shift": true, "key": "v", "code": "KeyV", "action": "pasteAttributes", "description": "Paste node attributes" },
{ "shift": true, "key": "1", "code": "Digit1", "action": "alignTop", "description": "Align nodes to top" },
{ "shift": true, "key": "2", "code": "Digit2", "action": "alignBottom", "description": "Align nodes to bottom" },
{ "shift": true, "key": "3", "code": "Digit3", "action": "alignLeft", "description": "Align nodes to left" },
{ "shift": true, "key": "4", "code": "Digit4", "action": "alignRight", "description": "Align nodes to right" },
{ "shift": true, "key": "5", "code": "Digit5", "action": "alignMiddle", "description": "Align nodes to vertical center" },
{ "shift": true, "key": "6", "code": "Digit6", "action": "alignCenter", "description": "Align nodes to horizontal center" },
{ "shift": true, "key": "7", "code": "Digit7", "action": "distributeHorizontal", "description": "Distribute nodes horizontally" },
{ "shift": true, "key": "8", "code": "Digit8", "action": "distributeVertical", "description": "Distribute nodes vertically" },
{ "key": "ArrowUp", "code": "ArrowUp", "action": "moveUp", "description": "Move nodes up" },
{ "key": "ArrowDown", "code": "ArrowDown", "action": "moveDown", "description": "Move nodes down" },
{ "key": "ArrowLeft", "code": "ArrowLeft", "action": "moveLeft", "description": "Move nodes left" },
{ "key": "ArrowRight", "code": "ArrowRight", "action": "moveRight", "description": "Move nodes right" },
{ "shift": true, "key": "ArrowUp", "code": "ArrowUp", "action": "moveUpLarge", "description": "Move nodes up (large)" },
{ "shift": true, "key": "ArrowDown", "code": "ArrowDown", "action": "moveDownLarge", "description": "Move nodes down (large)" },
{ "shift": true, "key": "ArrowLeft", "code": "ArrowLeft", "action": "moveLeftLarge", "description": "Move nodes left (large)" },
{ "shift": true, "key": "ArrowRight", "code": "ArrowRight", "action": "moveRightLarge", "description": "Move nodes right (large)" },
{ "key": "Escape", "code": "Escape", "alwaysEnabled": true, "action": "cancel", "description": "Deselect all and close sidebar" }
]
}
+76
View File
@@ -0,0 +1,76 @@
import { initAssets } from './modules/assets/index.js';
import { initGraph } from './modules/graph.js';
import { initUIToggles } from './modules/ui.js';
import { initSettings } from './modules/settings/ui.js';
import { applySavedSettings, applySavedTheme } from './modules/settings/store.js';
import { initHotkeys } from './modules/hotkeys/index.js';
import { initGlobalSearch } from './modules/graph/search.js';
import { initInventory } from './modules/graph/analysis.js';
import { initLayerPanel } from './modules/ui/layer_panel.js';
import { applyLayerFilters } from './modules/graph/layers.js';
import { initI18n } from './modules/i18n.js';
import { initPropertiesSidebar } from './modules/properties_sidebar/index.js';
import { initPersistence } from './modules/persistence.js';
import { initGraphIO } from './modules/graph/io/index.js';
import { initContextMenu } from './modules/ui/context_menu/index.js';
import { logger } from './modules/utils/logger.js';
document.addEventListener('DOMContentLoaded', async () => {
// 0. Initialize i18n (Language first)
await initI18n();
// 1. Apply Saved Theme immediately (prevent flash)
applySavedTheme();
// 2. Load Assets & Sidebar
await initAssets();
// 2.5 Load Global Config
try {
const configRes = await fetch('/api/config');
if (configRes.ok) {
const configData = await configRes.json();
const { state } = await import('./modules/state.js');
state.appConfig = configData;
logger.info("Global configuration loaded from server.");
}
} catch (err) {
logger.high("Failed to load global config, using defaults.");
}
// 3. Initialize X6 Graph
initGraph();
// 4. Initialize UI Toggles
initUIToggles();
// 5. Initialize Settings Modal Logic
initSettings();
// 6. Apply Saved Visual Settings (Grid, Size)
applySavedSettings();
// 7. Initialize Keyboard Hotkeys
initHotkeys();
// 8. Initialize UI Components & Persistence
initPropertiesSidebar();
initContextMenu();
initGraphIO();
initGlobalSearch();
initInventory();
initLayerPanel();
applyLayerFilters();
initPersistence();
// Help Button
const helpBtn = document.getElementById('help-btn');
if (helpBtn) {
helpBtn.addEventListener('click', async () => {
const { showHelpModal } = await import('./modules/ui/help_modal.js');
showHelpModal();
});
}
logger.high("drawNET Premium initialized successfully.");
});
+398
View File
File diff suppressed because one or more lines are too long
+140
View File
@@ -0,0 +1,140 @@
/**
* @license
* Lodash <https://lodash.com/>
* Copyright OpenJS Foundation and other contributors <https://openjsf.org/>
* Released under MIT license <https://lodash.com/license>
* Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE>
* Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
*/
(function(){function n(n,t,r){switch(r.length){case 0:return n.call(t);case 1:return n.call(t,r[0]);case 2:return n.call(t,r[0],r[1]);case 3:return n.call(t,r[0],r[1],r[2])}return n.apply(t,r)}function t(n,t,r,e){for(var u=-1,i=null==n?0:n.length;++u<i;){var o=n[u];t(e,o,r(o),n)}return e}function r(n,t){for(var r=-1,e=null==n?0:n.length;++r<e&&t(n[r],r,n)!==!1;);return n}function e(n,t){for(var r=null==n?0:n.length;r--&&t(n[r],r,n)!==!1;);return n}function u(n,t){for(var r=-1,e=null==n?0:n.length;++r<e;)if(!t(n[r],r,n))return!1;
return!0}function i(n,t){for(var r=-1,e=null==n?0:n.length,u=0,i=[];++r<e;){var o=n[r];t(o,r,n)&&(i[u++]=o)}return i}function o(n,t){return!!(null==n?0:n.length)&&y(n,t,0)>-1}function f(n,t,r){for(var e=-1,u=null==n?0:n.length;++e<u;)if(r(t,n[e]))return!0;return!1}function c(n,t){for(var r=-1,e=null==n?0:n.length,u=Array(e);++r<e;)u[r]=t(n[r],r,n);return u}function a(n,t){for(var r=-1,e=t.length,u=n.length;++r<e;)n[u+r]=t[r];return n}function l(n,t,r,e){var u=-1,i=null==n?0:n.length;for(e&&i&&(r=n[++u]);++u<i;)r=t(r,n[u],u,n);
return r}function s(n,t,r,e){var u=null==n?0:n.length;for(e&&u&&(r=n[--u]);u--;)r=t(r,n[u],u,n);return r}function h(n,t){for(var r=-1,e=null==n?0:n.length;++r<e;)if(t(n[r],r,n))return!0;return!1}function p(n){return n.split("")}function _(n){return n.match($t)||[]}function v(n,t,r){var e;return r(n,function(n,r,u){if(t(n,r,u))return e=r,!1}),e}function g(n,t,r,e){for(var u=n.length,i=r+(e?1:-1);e?i--:++i<u;)if(t(n[i],i,n))return i;return-1}function y(n,t,r){return t===t?Z(n,t,r):g(n,b,r)}function d(n,t,r,e){
for(var u=r-1,i=n.length;++u<i;)if(e(n[u],t))return u;return-1}function b(n){return n!==n}function w(n,t){var r=null==n?0:n.length;return r?k(n,t)/r:Cn}function m(n){return function(t){return null==t?X:t[n]}}function x(n){return function(t){return null==n?X:n[t]}}function j(n,t,r,e,u){return u(n,function(n,u,i){r=e?(e=!1,n):t(r,n,u,i)}),r}function A(n,t){var r=n.length;for(n.sort(t);r--;)n[r]=n[r].value;return n}function k(n,t){for(var r,e=-1,u=n.length;++e<u;){var i=t(n[e]);i!==X&&(r=r===X?i:r+i);
}return r}function O(n,t){for(var r=-1,e=Array(n);++r<n;)e[r]=t(r);return e}function I(n,t){return c(t,function(t){return[t,n[t]]})}function R(n){return n?n.slice(0,H(n)+1).replace(Lt,""):n}function z(n){return function(t){return n(t)}}function E(n,t){return c(t,function(t){return n[t]})}function S(n,t){return n.has(t)}function W(n,t){for(var r=-1,e=n.length;++r<e&&y(t,n[r],0)>-1;);return r}function L(n,t){for(var r=n.length;r--&&y(t,n[r],0)>-1;);return r}function C(n,t){for(var r=n.length,e=0;r--;)n[r]===t&&++e;
return e}function U(n){return"\\"+Yr[n]}function B(n,t){return null==n?X:n[t]}function T(n){return Nr.test(n)}function $(n){return Pr.test(n)}function D(n){for(var t,r=[];!(t=n.next()).done;)r.push(t.value);return r}function M(n){var t=-1,r=Array(n.size);return n.forEach(function(n,e){r[++t]=[e,n]}),r}function F(n,t){return function(r){return n(t(r))}}function N(n,t){for(var r=-1,e=n.length,u=0,i=[];++r<e;){var o=n[r];o!==t&&o!==cn||(n[r]=cn,i[u++]=r)}return i}function P(n){var t=-1,r=Array(n.size);
return n.forEach(function(n){r[++t]=n}),r}function q(n){var t=-1,r=Array(n.size);return n.forEach(function(n){r[++t]=[n,n]}),r}function Z(n,t,r){for(var e=r-1,u=n.length;++e<u;)if(n[e]===t)return e;return-1}function K(n,t,r){for(var e=r+1;e--;)if(n[e]===t)return e;return e}function V(n){return T(n)?J(n):_e(n)}function G(n){return T(n)?Y(n):p(n)}function H(n){for(var t=n.length;t--&&Ct.test(n.charAt(t)););return t}function J(n){for(var t=Mr.lastIndex=0;Mr.test(n);)++t;return t}function Y(n){return n.match(Mr)||[];
}function Q(n){return n.match(Fr)||[]}var X,nn="4.17.21",tn=200,rn="Unsupported core-js use. Try https://npms.io/search?q=ponyfill.",en="Expected a function",un="Invalid `variable` option passed into `_.template`",on="__lodash_hash_undefined__",fn=500,cn="__lodash_placeholder__",an=1,ln=2,sn=4,hn=1,pn=2,_n=1,vn=2,gn=4,yn=8,dn=16,bn=32,wn=64,mn=128,xn=256,jn=512,An=30,kn="...",On=800,In=16,Rn=1,zn=2,En=3,Sn=1/0,Wn=9007199254740991,Ln=1.7976931348623157e308,Cn=NaN,Un=4294967295,Bn=Un-1,Tn=Un>>>1,$n=[["ary",mn],["bind",_n],["bindKey",vn],["curry",yn],["curryRight",dn],["flip",jn],["partial",bn],["partialRight",wn],["rearg",xn]],Dn="[object Arguments]",Mn="[object Array]",Fn="[object AsyncFunction]",Nn="[object Boolean]",Pn="[object Date]",qn="[object DOMException]",Zn="[object Error]",Kn="[object Function]",Vn="[object GeneratorFunction]",Gn="[object Map]",Hn="[object Number]",Jn="[object Null]",Yn="[object Object]",Qn="[object Promise]",Xn="[object Proxy]",nt="[object RegExp]",tt="[object Set]",rt="[object String]",et="[object Symbol]",ut="[object Undefined]",it="[object WeakMap]",ot="[object WeakSet]",ft="[object ArrayBuffer]",ct="[object DataView]",at="[object Float32Array]",lt="[object Float64Array]",st="[object Int8Array]",ht="[object Int16Array]",pt="[object Int32Array]",_t="[object Uint8Array]",vt="[object Uint8ClampedArray]",gt="[object Uint16Array]",yt="[object Uint32Array]",dt=/\b__p \+= '';/g,bt=/\b(__p \+=) '' \+/g,wt=/(__e\(.*?\)|\b__t\)) \+\n'';/g,mt=/&(?:amp|lt|gt|quot|#39);/g,xt=/[&<>"']/g,jt=RegExp(mt.source),At=RegExp(xt.source),kt=/<%-([\s\S]+?)%>/g,Ot=/<%([\s\S]+?)%>/g,It=/<%=([\s\S]+?)%>/g,Rt=/\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/,zt=/^\w*$/,Et=/[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g,St=/[\\^$.*+?()[\]{}|]/g,Wt=RegExp(St.source),Lt=/^\s+/,Ct=/\s/,Ut=/\{(?:\n\/\* \[wrapped with .+\] \*\/)?\n?/,Bt=/\{\n\/\* \[wrapped with (.+)\] \*/,Tt=/,? & /,$t=/[^\x00-\x2f\x3a-\x40\x5b-\x60\x7b-\x7f]+/g,Dt=/[()=,{}\[\]\/\s]/,Mt=/\\(\\)?/g,Ft=/\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g,Nt=/\w*$/,Pt=/^[-+]0x[0-9a-f]+$/i,qt=/^0b[01]+$/i,Zt=/^\[object .+?Constructor\]$/,Kt=/^0o[0-7]+$/i,Vt=/^(?:0|[1-9]\d*)$/,Gt=/[\xc0-\xd6\xd8-\xf6\xf8-\xff\u0100-\u017f]/g,Ht=/($^)/,Jt=/['\n\r\u2028\u2029\\]/g,Yt="\\ud800-\\udfff",Qt="\\u0300-\\u036f",Xt="\\ufe20-\\ufe2f",nr="\\u20d0-\\u20ff",tr=Qt+Xt+nr,rr="\\u2700-\\u27bf",er="a-z\\xdf-\\xf6\\xf8-\\xff",ur="\\xac\\xb1\\xd7\\xf7",ir="\\x00-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\xbf",or="\\u2000-\\u206f",fr=" \\t\\x0b\\f\\xa0\\ufeff\\n\\r\\u2028\\u2029\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000",cr="A-Z\\xc0-\\xd6\\xd8-\\xde",ar="\\ufe0e\\ufe0f",lr=ur+ir+or+fr,sr="['\u2019]",hr="["+Yt+"]",pr="["+lr+"]",_r="["+tr+"]",vr="\\d+",gr="["+rr+"]",yr="["+er+"]",dr="[^"+Yt+lr+vr+rr+er+cr+"]",br="\\ud83c[\\udffb-\\udfff]",wr="(?:"+_r+"|"+br+")",mr="[^"+Yt+"]",xr="(?:\\ud83c[\\udde6-\\uddff]){2}",jr="[\\ud800-\\udbff][\\udc00-\\udfff]",Ar="["+cr+"]",kr="\\u200d",Or="(?:"+yr+"|"+dr+")",Ir="(?:"+Ar+"|"+dr+")",Rr="(?:"+sr+"(?:d|ll|m|re|s|t|ve))?",zr="(?:"+sr+"(?:D|LL|M|RE|S|T|VE))?",Er=wr+"?",Sr="["+ar+"]?",Wr="(?:"+kr+"(?:"+[mr,xr,jr].join("|")+")"+Sr+Er+")*",Lr="\\d*(?:1st|2nd|3rd|(?![123])\\dth)(?=\\b|[A-Z_])",Cr="\\d*(?:1ST|2ND|3RD|(?![123])\\dTH)(?=\\b|[a-z_])",Ur=Sr+Er+Wr,Br="(?:"+[gr,xr,jr].join("|")+")"+Ur,Tr="(?:"+[mr+_r+"?",_r,xr,jr,hr].join("|")+")",$r=RegExp(sr,"g"),Dr=RegExp(_r,"g"),Mr=RegExp(br+"(?="+br+")|"+Tr+Ur,"g"),Fr=RegExp([Ar+"?"+yr+"+"+Rr+"(?="+[pr,Ar,"$"].join("|")+")",Ir+"+"+zr+"(?="+[pr,Ar+Or,"$"].join("|")+")",Ar+"?"+Or+"+"+Rr,Ar+"+"+zr,Cr,Lr,vr,Br].join("|"),"g"),Nr=RegExp("["+kr+Yt+tr+ar+"]"),Pr=/[a-z][A-Z]|[A-Z]{2}[a-z]|[0-9][a-zA-Z]|[a-zA-Z][0-9]|[^a-zA-Z0-9 ]/,qr=["Array","Buffer","DataView","Date","Error","Float32Array","Float64Array","Function","Int8Array","Int16Array","Int32Array","Map","Math","Object","Promise","RegExp","Set","String","Symbol","TypeError","Uint8Array","Uint8ClampedArray","Uint16Array","Uint32Array","WeakMap","_","clearTimeout","isFinite","parseInt","setTimeout"],Zr=-1,Kr={};
Kr[at]=Kr[lt]=Kr[st]=Kr[ht]=Kr[pt]=Kr[_t]=Kr[vt]=Kr[gt]=Kr[yt]=!0,Kr[Dn]=Kr[Mn]=Kr[ft]=Kr[Nn]=Kr[ct]=Kr[Pn]=Kr[Zn]=Kr[Kn]=Kr[Gn]=Kr[Hn]=Kr[Yn]=Kr[nt]=Kr[tt]=Kr[rt]=Kr[it]=!1;var Vr={};Vr[Dn]=Vr[Mn]=Vr[ft]=Vr[ct]=Vr[Nn]=Vr[Pn]=Vr[at]=Vr[lt]=Vr[st]=Vr[ht]=Vr[pt]=Vr[Gn]=Vr[Hn]=Vr[Yn]=Vr[nt]=Vr[tt]=Vr[rt]=Vr[et]=Vr[_t]=Vr[vt]=Vr[gt]=Vr[yt]=!0,Vr[Zn]=Vr[Kn]=Vr[it]=!1;var Gr={"\xc0":"A","\xc1":"A","\xc2":"A","\xc3":"A","\xc4":"A","\xc5":"A","\xe0":"a","\xe1":"a","\xe2":"a","\xe3":"a","\xe4":"a","\xe5":"a",
"\xc7":"C","\xe7":"c","\xd0":"D","\xf0":"d","\xc8":"E","\xc9":"E","\xca":"E","\xcb":"E","\xe8":"e","\xe9":"e","\xea":"e","\xeb":"e","\xcc":"I","\xcd":"I","\xce":"I","\xcf":"I","\xec":"i","\xed":"i","\xee":"i","\xef":"i","\xd1":"N","\xf1":"n","\xd2":"O","\xd3":"O","\xd4":"O","\xd5":"O","\xd6":"O","\xd8":"O","\xf2":"o","\xf3":"o","\xf4":"o","\xf5":"o","\xf6":"o","\xf8":"o","\xd9":"U","\xda":"U","\xdb":"U","\xdc":"U","\xf9":"u","\xfa":"u","\xfb":"u","\xfc":"u","\xdd":"Y","\xfd":"y","\xff":"y","\xc6":"Ae",
"\xe6":"ae","\xde":"Th","\xfe":"th","\xdf":"ss","\u0100":"A","\u0102":"A","\u0104":"A","\u0101":"a","\u0103":"a","\u0105":"a","\u0106":"C","\u0108":"C","\u010a":"C","\u010c":"C","\u0107":"c","\u0109":"c","\u010b":"c","\u010d":"c","\u010e":"D","\u0110":"D","\u010f":"d","\u0111":"d","\u0112":"E","\u0114":"E","\u0116":"E","\u0118":"E","\u011a":"E","\u0113":"e","\u0115":"e","\u0117":"e","\u0119":"e","\u011b":"e","\u011c":"G","\u011e":"G","\u0120":"G","\u0122":"G","\u011d":"g","\u011f":"g","\u0121":"g",
"\u0123":"g","\u0124":"H","\u0126":"H","\u0125":"h","\u0127":"h","\u0128":"I","\u012a":"I","\u012c":"I","\u012e":"I","\u0130":"I","\u0129":"i","\u012b":"i","\u012d":"i","\u012f":"i","\u0131":"i","\u0134":"J","\u0135":"j","\u0136":"K","\u0137":"k","\u0138":"k","\u0139":"L","\u013b":"L","\u013d":"L","\u013f":"L","\u0141":"L","\u013a":"l","\u013c":"l","\u013e":"l","\u0140":"l","\u0142":"l","\u0143":"N","\u0145":"N","\u0147":"N","\u014a":"N","\u0144":"n","\u0146":"n","\u0148":"n","\u014b":"n","\u014c":"O",
"\u014e":"O","\u0150":"O","\u014d":"o","\u014f":"o","\u0151":"o","\u0154":"R","\u0156":"R","\u0158":"R","\u0155":"r","\u0157":"r","\u0159":"r","\u015a":"S","\u015c":"S","\u015e":"S","\u0160":"S","\u015b":"s","\u015d":"s","\u015f":"s","\u0161":"s","\u0162":"T","\u0164":"T","\u0166":"T","\u0163":"t","\u0165":"t","\u0167":"t","\u0168":"U","\u016a":"U","\u016c":"U","\u016e":"U","\u0170":"U","\u0172":"U","\u0169":"u","\u016b":"u","\u016d":"u","\u016f":"u","\u0171":"u","\u0173":"u","\u0174":"W","\u0175":"w",
"\u0176":"Y","\u0177":"y","\u0178":"Y","\u0179":"Z","\u017b":"Z","\u017d":"Z","\u017a":"z","\u017c":"z","\u017e":"z","\u0132":"IJ","\u0133":"ij","\u0152":"Oe","\u0153":"oe","\u0149":"'n","\u017f":"s"},Hr={"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#39;"},Jr={"&amp;":"&","&lt;":"<","&gt;":">","&quot;":'"',"&#39;":"'"},Yr={"\\":"\\","'":"'","\n":"n","\r":"r","\u2028":"u2028","\u2029":"u2029"},Qr=parseFloat,Xr=parseInt,ne="object"==typeof global&&global&&global.Object===Object&&global,te="object"==typeof self&&self&&self.Object===Object&&self,re=ne||te||Function("return this")(),ee="object"==typeof exports&&exports&&!exports.nodeType&&exports,ue=ee&&"object"==typeof module&&module&&!module.nodeType&&module,ie=ue&&ue.exports===ee,oe=ie&&ne.process,fe=function(){
try{var n=ue&&ue.require&&ue.require("util").types;return n?n:oe&&oe.binding&&oe.binding("util")}catch(n){}}(),ce=fe&&fe.isArrayBuffer,ae=fe&&fe.isDate,le=fe&&fe.isMap,se=fe&&fe.isRegExp,he=fe&&fe.isSet,pe=fe&&fe.isTypedArray,_e=m("length"),ve=x(Gr),ge=x(Hr),ye=x(Jr),de=function p(x){function Z(n){if(cc(n)&&!bh(n)&&!(n instanceof Ct)){if(n instanceof Y)return n;if(bl.call(n,"__wrapped__"))return eo(n)}return new Y(n)}function J(){}function Y(n,t){this.__wrapped__=n,this.__actions__=[],this.__chain__=!!t,
this.__index__=0,this.__values__=X}function Ct(n){this.__wrapped__=n,this.__actions__=[],this.__dir__=1,this.__filtered__=!1,this.__iteratees__=[],this.__takeCount__=Un,this.__views__=[]}function $t(){var n=new Ct(this.__wrapped__);return n.__actions__=Tu(this.__actions__),n.__dir__=this.__dir__,n.__filtered__=this.__filtered__,n.__iteratees__=Tu(this.__iteratees__),n.__takeCount__=this.__takeCount__,n.__views__=Tu(this.__views__),n}function Yt(){if(this.__filtered__){var n=new Ct(this);n.__dir__=-1,
n.__filtered__=!0}else n=this.clone(),n.__dir__*=-1;return n}function Qt(){var n=this.__wrapped__.value(),t=this.__dir__,r=bh(n),e=t<0,u=r?n.length:0,i=Oi(0,u,this.__views__),o=i.start,f=i.end,c=f-o,a=e?f:o-1,l=this.__iteratees__,s=l.length,h=0,p=Hl(c,this.__takeCount__);if(!r||!e&&u==c&&p==c)return wu(n,this.__actions__);var _=[];n:for(;c--&&h<p;){a+=t;for(var v=-1,g=n[a];++v<s;){var y=l[v],d=y.iteratee,b=y.type,w=d(g);if(b==zn)g=w;else if(!w){if(b==Rn)continue n;break n}}_[h++]=g}return _}function Xt(n){
var t=-1,r=null==n?0:n.length;for(this.clear();++t<r;){var e=n[t];this.set(e[0],e[1])}}function nr(){this.__data__=is?is(null):{},this.size=0}function tr(n){var t=this.has(n)&&delete this.__data__[n];return this.size-=t?1:0,t}function rr(n){var t=this.__data__;if(is){var r=t[n];return r===on?X:r}return bl.call(t,n)?t[n]:X}function er(n){var t=this.__data__;return is?t[n]!==X:bl.call(t,n)}function ur(n,t){var r=this.__data__;return this.size+=this.has(n)?0:1,r[n]=is&&t===X?on:t,this}function ir(n){
var t=-1,r=null==n?0:n.length;for(this.clear();++t<r;){var e=n[t];this.set(e[0],e[1])}}function or(){this.__data__=[],this.size=0}function fr(n){var t=this.__data__,r=Wr(t,n);return!(r<0)&&(r==t.length-1?t.pop():Ll.call(t,r,1),--this.size,!0)}function cr(n){var t=this.__data__,r=Wr(t,n);return r<0?X:t[r][1]}function ar(n){return Wr(this.__data__,n)>-1}function lr(n,t){var r=this.__data__,e=Wr(r,n);return e<0?(++this.size,r.push([n,t])):r[e][1]=t,this}function sr(n){var t=-1,r=null==n?0:n.length;for(this.clear();++t<r;){
var e=n[t];this.set(e[0],e[1])}}function hr(){this.size=0,this.__data__={hash:new Xt,map:new(ts||ir),string:new Xt}}function pr(n){var t=xi(this,n).delete(n);return this.size-=t?1:0,t}function _r(n){return xi(this,n).get(n)}function vr(n){return xi(this,n).has(n)}function gr(n,t){var r=xi(this,n),e=r.size;return r.set(n,t),this.size+=r.size==e?0:1,this}function yr(n){var t=-1,r=null==n?0:n.length;for(this.__data__=new sr;++t<r;)this.add(n[t])}function dr(n){return this.__data__.set(n,on),this}function br(n){
return this.__data__.has(n)}function wr(n){this.size=(this.__data__=new ir(n)).size}function mr(){this.__data__=new ir,this.size=0}function xr(n){var t=this.__data__,r=t.delete(n);return this.size=t.size,r}function jr(n){return this.__data__.get(n)}function Ar(n){return this.__data__.has(n)}function kr(n,t){var r=this.__data__;if(r instanceof ir){var e=r.__data__;if(!ts||e.length<tn-1)return e.push([n,t]),this.size=++r.size,this;r=this.__data__=new sr(e)}return r.set(n,t),this.size=r.size,this}function Or(n,t){
var r=bh(n),e=!r&&dh(n),u=!r&&!e&&mh(n),i=!r&&!e&&!u&&Oh(n),o=r||e||u||i,f=o?O(n.length,hl):[],c=f.length;for(var a in n)!t&&!bl.call(n,a)||o&&("length"==a||u&&("offset"==a||"parent"==a)||i&&("buffer"==a||"byteLength"==a||"byteOffset"==a)||Ci(a,c))||f.push(a);return f}function Ir(n){var t=n.length;return t?n[tu(0,t-1)]:X}function Rr(n,t){return Xi(Tu(n),Mr(t,0,n.length))}function zr(n){return Xi(Tu(n))}function Er(n,t,r){(r===X||Gf(n[t],r))&&(r!==X||t in n)||Br(n,t,r)}function Sr(n,t,r){var e=n[t];
bl.call(n,t)&&Gf(e,r)&&(r!==X||t in n)||Br(n,t,r)}function Wr(n,t){for(var r=n.length;r--;)if(Gf(n[r][0],t))return r;return-1}function Lr(n,t,r,e){return ys(n,function(n,u,i){t(e,n,r(n),i)}),e}function Cr(n,t){return n&&$u(t,Pc(t),n)}function Ur(n,t){return n&&$u(t,qc(t),n)}function Br(n,t,r){"__proto__"==t&&Tl?Tl(n,t,{configurable:!0,enumerable:!0,value:r,writable:!0}):n[t]=r}function Tr(n,t){for(var r=-1,e=t.length,u=il(e),i=null==n;++r<e;)u[r]=i?X:Mc(n,t[r]);return u}function Mr(n,t,r){return n===n&&(r!==X&&(n=n<=r?n:r),
t!==X&&(n=n>=t?n:t)),n}function Fr(n,t,e,u,i,o){var f,c=t&an,a=t&ln,l=t&sn;if(e&&(f=i?e(n,u,i,o):e(n)),f!==X)return f;if(!fc(n))return n;var s=bh(n);if(s){if(f=zi(n),!c)return Tu(n,f)}else{var h=zs(n),p=h==Kn||h==Vn;if(mh(n))return Iu(n,c);if(h==Yn||h==Dn||p&&!i){if(f=a||p?{}:Ei(n),!c)return a?Mu(n,Ur(f,n)):Du(n,Cr(f,n))}else{if(!Vr[h])return i?n:{};f=Si(n,h,c)}}o||(o=new wr);var _=o.get(n);if(_)return _;o.set(n,f),kh(n)?n.forEach(function(r){f.add(Fr(r,t,e,r,n,o))}):jh(n)&&n.forEach(function(r,u){
f.set(u,Fr(r,t,e,u,n,o))});var v=l?a?di:yi:a?qc:Pc,g=s?X:v(n);return r(g||n,function(r,u){g&&(u=r,r=n[u]),Sr(f,u,Fr(r,t,e,u,n,o))}),f}function Nr(n){var t=Pc(n);return function(r){return Pr(r,n,t)}}function Pr(n,t,r){var e=r.length;if(null==n)return!e;for(n=ll(n);e--;){var u=r[e],i=t[u],o=n[u];if(o===X&&!(u in n)||!i(o))return!1}return!0}function Gr(n,t,r){if("function"!=typeof n)throw new pl(en);return Ws(function(){n.apply(X,r)},t)}function Hr(n,t,r,e){var u=-1,i=o,a=!0,l=n.length,s=[],h=t.length;
if(!l)return s;r&&(t=c(t,z(r))),e?(i=f,a=!1):t.length>=tn&&(i=S,a=!1,t=new yr(t));n:for(;++u<l;){var p=n[u],_=null==r?p:r(p);if(p=e||0!==p?p:0,a&&_===_){for(var v=h;v--;)if(t[v]===_)continue n;s.push(p)}else i(t,_,e)||s.push(p)}return s}function Jr(n,t){var r=!0;return ys(n,function(n,e,u){return r=!!t(n,e,u)}),r}function Yr(n,t,r){for(var e=-1,u=n.length;++e<u;){var i=n[e],o=t(i);if(null!=o&&(f===X?o===o&&!bc(o):r(o,f)))var f=o,c=i}return c}function ne(n,t,r,e){var u=n.length;for(r=kc(r),r<0&&(r=-r>u?0:u+r),
e=e===X||e>u?u:kc(e),e<0&&(e+=u),e=r>e?0:Oc(e);r<e;)n[r++]=t;return n}function te(n,t){var r=[];return ys(n,function(n,e,u){t(n,e,u)&&r.push(n)}),r}function ee(n,t,r,e,u){var i=-1,o=n.length;for(r||(r=Li),u||(u=[]);++i<o;){var f=n[i];t>0&&r(f)?t>1?ee(f,t-1,r,e,u):a(u,f):e||(u[u.length]=f)}return u}function ue(n,t){return n&&bs(n,t,Pc)}function oe(n,t){return n&&ws(n,t,Pc)}function fe(n,t){return i(t,function(t){return uc(n[t])})}function _e(n,t){t=ku(t,n);for(var r=0,e=t.length;null!=n&&r<e;)n=n[no(t[r++])];
return r&&r==e?n:X}function de(n,t,r){var e=t(n);return bh(n)?e:a(e,r(n))}function we(n){return null==n?n===X?ut:Jn:Bl&&Bl in ll(n)?ki(n):Ki(n)}function me(n,t){return n>t}function xe(n,t){return null!=n&&bl.call(n,t)}function je(n,t){return null!=n&&t in ll(n)}function Ae(n,t,r){return n>=Hl(t,r)&&n<Gl(t,r)}function ke(n,t,r){for(var e=r?f:o,u=n[0].length,i=n.length,a=i,l=il(i),s=1/0,h=[];a--;){var p=n[a];a&&t&&(p=c(p,z(t))),s=Hl(p.length,s),l[a]=!r&&(t||u>=120&&p.length>=120)?new yr(a&&p):X}p=n[0];
var _=-1,v=l[0];n:for(;++_<u&&h.length<s;){var g=p[_],y=t?t(g):g;if(g=r||0!==g?g:0,!(v?S(v,y):e(h,y,r))){for(a=i;--a;){var d=l[a];if(!(d?S(d,y):e(n[a],y,r)))continue n}v&&v.push(y),h.push(g)}}return h}function Oe(n,t,r,e){return ue(n,function(n,u,i){t(e,r(n),u,i)}),e}function Ie(t,r,e){r=ku(r,t),t=Gi(t,r);var u=null==t?t:t[no(jo(r))];return null==u?X:n(u,t,e)}function Re(n){return cc(n)&&we(n)==Dn}function ze(n){return cc(n)&&we(n)==ft}function Ee(n){return cc(n)&&we(n)==Pn}function Se(n,t,r,e,u){
return n===t||(null==n||null==t||!cc(n)&&!cc(t)?n!==n&&t!==t:We(n,t,r,e,Se,u))}function We(n,t,r,e,u,i){var o=bh(n),f=bh(t),c=o?Mn:zs(n),a=f?Mn:zs(t);c=c==Dn?Yn:c,a=a==Dn?Yn:a;var l=c==Yn,s=a==Yn,h=c==a;if(h&&mh(n)){if(!mh(t))return!1;o=!0,l=!1}if(h&&!l)return i||(i=new wr),o||Oh(n)?pi(n,t,r,e,u,i):_i(n,t,c,r,e,u,i);if(!(r&hn)){var p=l&&bl.call(n,"__wrapped__"),_=s&&bl.call(t,"__wrapped__");if(p||_){var v=p?n.value():n,g=_?t.value():t;return i||(i=new wr),u(v,g,r,e,i)}}return!!h&&(i||(i=new wr),vi(n,t,r,e,u,i));
}function Le(n){return cc(n)&&zs(n)==Gn}function Ce(n,t,r,e){var u=r.length,i=u,o=!e;if(null==n)return!i;for(n=ll(n);u--;){var f=r[u];if(o&&f[2]?f[1]!==n[f[0]]:!(f[0]in n))return!1}for(;++u<i;){f=r[u];var c=f[0],a=n[c],l=f[1];if(o&&f[2]){if(a===X&&!(c in n))return!1}else{var s=new wr;if(e)var h=e(a,l,c,n,t,s);if(!(h===X?Se(l,a,hn|pn,e,s):h))return!1}}return!0}function Ue(n){return!(!fc(n)||Di(n))&&(uc(n)?kl:Zt).test(to(n))}function Be(n){return cc(n)&&we(n)==nt}function Te(n){return cc(n)&&zs(n)==tt;
}function $e(n){return cc(n)&&oc(n.length)&&!!Kr[we(n)]}function De(n){return"function"==typeof n?n:null==n?La:"object"==typeof n?bh(n)?Ze(n[0],n[1]):qe(n):Fa(n)}function Me(n){if(!Mi(n))return Vl(n);var t=[];for(var r in ll(n))bl.call(n,r)&&"constructor"!=r&&t.push(r);return t}function Fe(n){if(!fc(n))return Zi(n);var t=Mi(n),r=[];for(var e in n)("constructor"!=e||!t&&bl.call(n,e))&&r.push(e);return r}function Ne(n,t){return n<t}function Pe(n,t){var r=-1,e=Hf(n)?il(n.length):[];return ys(n,function(n,u,i){
e[++r]=t(n,u,i)}),e}function qe(n){var t=ji(n);return 1==t.length&&t[0][2]?Ni(t[0][0],t[0][1]):function(r){return r===n||Ce(r,n,t)}}function Ze(n,t){return Bi(n)&&Fi(t)?Ni(no(n),t):function(r){var e=Mc(r,n);return e===X&&e===t?Nc(r,n):Se(t,e,hn|pn)}}function Ke(n,t,r,e,u){n!==t&&bs(t,function(i,o){if(u||(u=new wr),fc(i))Ve(n,t,o,r,Ke,e,u);else{var f=e?e(Ji(n,o),i,o+"",n,t,u):X;f===X&&(f=i),Er(n,o,f)}},qc)}function Ve(n,t,r,e,u,i,o){var f=Ji(n,r),c=Ji(t,r),a=o.get(c);if(a)return Er(n,r,a),X;var l=i?i(f,c,r+"",n,t,o):X,s=l===X;
if(s){var h=bh(c),p=!h&&mh(c),_=!h&&!p&&Oh(c);l=c,h||p||_?bh(f)?l=f:Jf(f)?l=Tu(f):p?(s=!1,l=Iu(c,!0)):_?(s=!1,l=Wu(c,!0)):l=[]:gc(c)||dh(c)?(l=f,dh(f)?l=Rc(f):fc(f)&&!uc(f)||(l=Ei(c))):s=!1}s&&(o.set(c,l),u(l,c,e,i,o),o.delete(c)),Er(n,r,l)}function Ge(n,t){var r=n.length;if(r)return t+=t<0?r:0,Ci(t,r)?n[t]:X}function He(n,t,r){t=t.length?c(t,function(n){return bh(n)?function(t){return _e(t,1===n.length?n[0]:n)}:n}):[La];var e=-1;return t=c(t,z(mi())),A(Pe(n,function(n,r,u){return{criteria:c(t,function(t){
return t(n)}),index:++e,value:n}}),function(n,t){return Cu(n,t,r)})}function Je(n,t){return Ye(n,t,function(t,r){return Nc(n,r)})}function Ye(n,t,r){for(var e=-1,u=t.length,i={};++e<u;){var o=t[e],f=_e(n,o);r(f,o)&&fu(i,ku(o,n),f)}return i}function Qe(n){return function(t){return _e(t,n)}}function Xe(n,t,r,e){var u=e?d:y,i=-1,o=t.length,f=n;for(n===t&&(t=Tu(t)),r&&(f=c(n,z(r)));++i<o;)for(var a=0,l=t[i],s=r?r(l):l;(a=u(f,s,a,e))>-1;)f!==n&&Ll.call(f,a,1),Ll.call(n,a,1);return n}function nu(n,t){for(var r=n?t.length:0,e=r-1;r--;){
var u=t[r];if(r==e||u!==i){var i=u;Ci(u)?Ll.call(n,u,1):yu(n,u)}}return n}function tu(n,t){return n+Nl(Ql()*(t-n+1))}function ru(n,t,r,e){for(var u=-1,i=Gl(Fl((t-n)/(r||1)),0),o=il(i);i--;)o[e?i:++u]=n,n+=r;return o}function eu(n,t){var r="";if(!n||t<1||t>Wn)return r;do t%2&&(r+=n),t=Nl(t/2),t&&(n+=n);while(t);return r}function uu(n,t){return Ls(Vi(n,t,La),n+"")}function iu(n){return Ir(ra(n))}function ou(n,t){var r=ra(n);return Xi(r,Mr(t,0,r.length))}function fu(n,t,r,e){if(!fc(n))return n;t=ku(t,n);
for(var u=-1,i=t.length,o=i-1,f=n;null!=f&&++u<i;){var c=no(t[u]),a=r;if("__proto__"===c||"constructor"===c||"prototype"===c)return n;if(u!=o){var l=f[c];a=e?e(l,c,f):X,a===X&&(a=fc(l)?l:Ci(t[u+1])?[]:{})}Sr(f,c,a),f=f[c]}return n}function cu(n){return Xi(ra(n))}function au(n,t,r){var e=-1,u=n.length;t<0&&(t=-t>u?0:u+t),r=r>u?u:r,r<0&&(r+=u),u=t>r?0:r-t>>>0,t>>>=0;for(var i=il(u);++e<u;)i[e]=n[e+t];return i}function lu(n,t){var r;return ys(n,function(n,e,u){return r=t(n,e,u),!r}),!!r}function su(n,t,r){
var e=0,u=null==n?e:n.length;if("number"==typeof t&&t===t&&u<=Tn){for(;e<u;){var i=e+u>>>1,o=n[i];null!==o&&!bc(o)&&(r?o<=t:o<t)?e=i+1:u=i}return u}return hu(n,t,La,r)}function hu(n,t,r,e){var u=0,i=null==n?0:n.length;if(0===i)return 0;t=r(t);for(var o=t!==t,f=null===t,c=bc(t),a=t===X;u<i;){var l=Nl((u+i)/2),s=r(n[l]),h=s!==X,p=null===s,_=s===s,v=bc(s);if(o)var g=e||_;else g=a?_&&(e||h):f?_&&h&&(e||!p):c?_&&h&&!p&&(e||!v):!p&&!v&&(e?s<=t:s<t);g?u=l+1:i=l}return Hl(i,Bn)}function pu(n,t){for(var r=-1,e=n.length,u=0,i=[];++r<e;){
var o=n[r],f=t?t(o):o;if(!r||!Gf(f,c)){var c=f;i[u++]=0===o?0:o}}return i}function _u(n){return"number"==typeof n?n:bc(n)?Cn:+n}function vu(n){if("string"==typeof n)return n;if(bh(n))return c(n,vu)+"";if(bc(n))return vs?vs.call(n):"";var t=n+"";return"0"==t&&1/n==-Sn?"-0":t}function gu(n,t,r){var e=-1,u=o,i=n.length,c=!0,a=[],l=a;if(r)c=!1,u=f;else if(i>=tn){var s=t?null:ks(n);if(s)return P(s);c=!1,u=S,l=new yr}else l=t?[]:a;n:for(;++e<i;){var h=n[e],p=t?t(h):h;if(h=r||0!==h?h:0,c&&p===p){for(var _=l.length;_--;)if(l[_]===p)continue n;
t&&l.push(p),a.push(h)}else u(l,p,r)||(l!==a&&l.push(p),a.push(h))}return a}function yu(n,t){return t=ku(t,n),n=Gi(n,t),null==n||delete n[no(jo(t))]}function du(n,t,r,e){return fu(n,t,r(_e(n,t)),e)}function bu(n,t,r,e){for(var u=n.length,i=e?u:-1;(e?i--:++i<u)&&t(n[i],i,n););return r?au(n,e?0:i,e?i+1:u):au(n,e?i+1:0,e?u:i)}function wu(n,t){var r=n;return r instanceof Ct&&(r=r.value()),l(t,function(n,t){return t.func.apply(t.thisArg,a([n],t.args))},r)}function mu(n,t,r){var e=n.length;if(e<2)return e?gu(n[0]):[];
for(var u=-1,i=il(e);++u<e;)for(var o=n[u],f=-1;++f<e;)f!=u&&(i[u]=Hr(i[u]||o,n[f],t,r));return gu(ee(i,1),t,r)}function xu(n,t,r){for(var e=-1,u=n.length,i=t.length,o={};++e<u;){r(o,n[e],e<i?t[e]:X)}return o}function ju(n){return Jf(n)?n:[]}function Au(n){return"function"==typeof n?n:La}function ku(n,t){return bh(n)?n:Bi(n,t)?[n]:Cs(Ec(n))}function Ou(n,t,r){var e=n.length;return r=r===X?e:r,!t&&r>=e?n:au(n,t,r)}function Iu(n,t){if(t)return n.slice();var r=n.length,e=zl?zl(r):new n.constructor(r);
return n.copy(e),e}function Ru(n){var t=new n.constructor(n.byteLength);return new Rl(t).set(new Rl(n)),t}function zu(n,t){return new n.constructor(t?Ru(n.buffer):n.buffer,n.byteOffset,n.byteLength)}function Eu(n){var t=new n.constructor(n.source,Nt.exec(n));return t.lastIndex=n.lastIndex,t}function Su(n){return _s?ll(_s.call(n)):{}}function Wu(n,t){return new n.constructor(t?Ru(n.buffer):n.buffer,n.byteOffset,n.length)}function Lu(n,t){if(n!==t){var r=n!==X,e=null===n,u=n===n,i=bc(n),o=t!==X,f=null===t,c=t===t,a=bc(t);
if(!f&&!a&&!i&&n>t||i&&o&&c&&!f&&!a||e&&o&&c||!r&&c||!u)return 1;if(!e&&!i&&!a&&n<t||a&&r&&u&&!e&&!i||f&&r&&u||!o&&u||!c)return-1}return 0}function Cu(n,t,r){for(var e=-1,u=n.criteria,i=t.criteria,o=u.length,f=r.length;++e<o;){var c=Lu(u[e],i[e]);if(c){if(e>=f)return c;return c*("desc"==r[e]?-1:1)}}return n.index-t.index}function Uu(n,t,r,e){for(var u=-1,i=n.length,o=r.length,f=-1,c=t.length,a=Gl(i-o,0),l=il(c+a),s=!e;++f<c;)l[f]=t[f];for(;++u<o;)(s||u<i)&&(l[r[u]]=n[u]);for(;a--;)l[f++]=n[u++];return l;
}function Bu(n,t,r,e){for(var u=-1,i=n.length,o=-1,f=r.length,c=-1,a=t.length,l=Gl(i-f,0),s=il(l+a),h=!e;++u<l;)s[u]=n[u];for(var p=u;++c<a;)s[p+c]=t[c];for(;++o<f;)(h||u<i)&&(s[p+r[o]]=n[u++]);return s}function Tu(n,t){var r=-1,e=n.length;for(t||(t=il(e));++r<e;)t[r]=n[r];return t}function $u(n,t,r,e){var u=!r;r||(r={});for(var i=-1,o=t.length;++i<o;){var f=t[i],c=e?e(r[f],n[f],f,r,n):X;c===X&&(c=n[f]),u?Br(r,f,c):Sr(r,f,c)}return r}function Du(n,t){return $u(n,Is(n),t)}function Mu(n,t){return $u(n,Rs(n),t);
}function Fu(n,r){return function(e,u){var i=bh(e)?t:Lr,o=r?r():{};return i(e,n,mi(u,2),o)}}function Nu(n){return uu(function(t,r){var e=-1,u=r.length,i=u>1?r[u-1]:X,o=u>2?r[2]:X;for(i=n.length>3&&"function"==typeof i?(u--,i):X,o&&Ui(r[0],r[1],o)&&(i=u<3?X:i,u=1),t=ll(t);++e<u;){var f=r[e];f&&n(t,f,e,i)}return t})}function Pu(n,t){return function(r,e){if(null==r)return r;if(!Hf(r))return n(r,e);for(var u=r.length,i=t?u:-1,o=ll(r);(t?i--:++i<u)&&e(o[i],i,o)!==!1;);return r}}function qu(n){return function(t,r,e){
for(var u=-1,i=ll(t),o=e(t),f=o.length;f--;){var c=o[n?f:++u];if(r(i[c],c,i)===!1)break}return t}}function Zu(n,t,r){function e(){return(this&&this!==re&&this instanceof e?i:n).apply(u?r:this,arguments)}var u=t&_n,i=Gu(n);return e}function Ku(n){return function(t){t=Ec(t);var r=T(t)?G(t):X,e=r?r[0]:t.charAt(0),u=r?Ou(r,1).join(""):t.slice(1);return e[n]()+u}}function Vu(n){return function(t){return l(Ra(ca(t).replace($r,"")),n,"")}}function Gu(n){return function(){var t=arguments;switch(t.length){
case 0:return new n;case 1:return new n(t[0]);case 2:return new n(t[0],t[1]);case 3:return new n(t[0],t[1],t[2]);case 4:return new n(t[0],t[1],t[2],t[3]);case 5:return new n(t[0],t[1],t[2],t[3],t[4]);case 6:return new n(t[0],t[1],t[2],t[3],t[4],t[5]);case 7:return new n(t[0],t[1],t[2],t[3],t[4],t[5],t[6])}var r=gs(n.prototype),e=n.apply(r,t);return fc(e)?e:r}}function Hu(t,r,e){function u(){for(var o=arguments.length,f=il(o),c=o,a=wi(u);c--;)f[c]=arguments[c];var l=o<3&&f[0]!==a&&f[o-1]!==a?[]:N(f,a);
return o-=l.length,o<e?oi(t,r,Qu,u.placeholder,X,f,l,X,X,e-o):n(this&&this!==re&&this instanceof u?i:t,this,f)}var i=Gu(t);return u}function Ju(n){return function(t,r,e){var u=ll(t);if(!Hf(t)){var i=mi(r,3);t=Pc(t),r=function(n){return i(u[n],n,u)}}var o=n(t,r,e);return o>-1?u[i?t[o]:o]:X}}function Yu(n){return gi(function(t){var r=t.length,e=r,u=Y.prototype.thru;for(n&&t.reverse();e--;){var i=t[e];if("function"!=typeof i)throw new pl(en);if(u&&!o&&"wrapper"==bi(i))var o=new Y([],!0)}for(e=o?e:r;++e<r;){
i=t[e];var f=bi(i),c="wrapper"==f?Os(i):X;o=c&&$i(c[0])&&c[1]==(mn|yn|bn|xn)&&!c[4].length&&1==c[9]?o[bi(c[0])].apply(o,c[3]):1==i.length&&$i(i)?o[f]():o.thru(i)}return function(){var n=arguments,e=n[0];if(o&&1==n.length&&bh(e))return o.plant(e).value();for(var u=0,i=r?t[u].apply(this,n):e;++u<r;)i=t[u].call(this,i);return i}})}function Qu(n,t,r,e,u,i,o,f,c,a){function l(){for(var y=arguments.length,d=il(y),b=y;b--;)d[b]=arguments[b];if(_)var w=wi(l),m=C(d,w);if(e&&(d=Uu(d,e,u,_)),i&&(d=Bu(d,i,o,_)),
y-=m,_&&y<a){return oi(n,t,Qu,l.placeholder,r,d,N(d,w),f,c,a-y)}var x=h?r:this,j=p?x[n]:n;return y=d.length,f?d=Hi(d,f):v&&y>1&&d.reverse(),s&&c<y&&(d.length=c),this&&this!==re&&this instanceof l&&(j=g||Gu(j)),j.apply(x,d)}var s=t&mn,h=t&_n,p=t&vn,_=t&(yn|dn),v=t&jn,g=p?X:Gu(n);return l}function Xu(n,t){return function(r,e){return Oe(r,n,t(e),{})}}function ni(n,t){return function(r,e){var u;if(r===X&&e===X)return t;if(r!==X&&(u=r),e!==X){if(u===X)return e;"string"==typeof r||"string"==typeof e?(r=vu(r),
e=vu(e)):(r=_u(r),e=_u(e)),u=n(r,e)}return u}}function ti(t){return gi(function(r){return r=c(r,z(mi())),uu(function(e){var u=this;return t(r,function(t){return n(t,u,e)})})})}function ri(n,t){t=t===X?" ":vu(t);var r=t.length;if(r<2)return r?eu(t,n):t;var e=eu(t,Fl(n/V(t)));return T(t)?Ou(G(e),0,n).join(""):e.slice(0,n)}function ei(t,r,e,u){function i(){for(var r=-1,c=arguments.length,a=-1,l=u.length,s=il(l+c),h=this&&this!==re&&this instanceof i?f:t;++a<l;)s[a]=u[a];for(;c--;)s[a++]=arguments[++r];
return n(h,o?e:this,s)}var o=r&_n,f=Gu(t);return i}function ui(n){return function(t,r,e){return e&&"number"!=typeof e&&Ui(t,r,e)&&(r=e=X),t=Ac(t),r===X?(r=t,t=0):r=Ac(r),e=e===X?t<r?1:-1:Ac(e),ru(t,r,e,n)}}function ii(n){return function(t,r){return"string"==typeof t&&"string"==typeof r||(t=Ic(t),r=Ic(r)),n(t,r)}}function oi(n,t,r,e,u,i,o,f,c,a){var l=t&yn,s=l?o:X,h=l?X:o,p=l?i:X,_=l?X:i;t|=l?bn:wn,t&=~(l?wn:bn),t&gn||(t&=~(_n|vn));var v=[n,t,u,p,s,_,h,f,c,a],g=r.apply(X,v);return $i(n)&&Ss(g,v),g.placeholder=e,
Yi(g,n,t)}function fi(n){var t=al[n];return function(n,r){if(n=Ic(n),r=null==r?0:Hl(kc(r),292),r&&Zl(n)){var e=(Ec(n)+"e").split("e");return e=(Ec(t(e[0]+"e"+(+e[1]+r)))+"e").split("e"),+(e[0]+"e"+(+e[1]-r))}return t(n)}}function ci(n){return function(t){var r=zs(t);return r==Gn?M(t):r==tt?q(t):I(t,n(t))}}function ai(n,t,r,e,u,i,o,f){var c=t&vn;if(!c&&"function"!=typeof n)throw new pl(en);var a=e?e.length:0;if(a||(t&=~(bn|wn),e=u=X),o=o===X?o:Gl(kc(o),0),f=f===X?f:kc(f),a-=u?u.length:0,t&wn){var l=e,s=u;
e=u=X}var h=c?X:Os(n),p=[n,t,r,e,u,l,s,i,o,f];if(h&&qi(p,h),n=p[0],t=p[1],r=p[2],e=p[3],u=p[4],f=p[9]=p[9]===X?c?0:n.length:Gl(p[9]-a,0),!f&&t&(yn|dn)&&(t&=~(yn|dn)),t&&t!=_n)_=t==yn||t==dn?Hu(n,t,f):t!=bn&&t!=(_n|bn)||u.length?Qu.apply(X,p):ei(n,t,r,e);else var _=Zu(n,t,r);return Yi((h?ms:Ss)(_,p),n,t)}function li(n,t,r,e){return n===X||Gf(n,gl[r])&&!bl.call(e,r)?t:n}function si(n,t,r,e,u,i){return fc(n)&&fc(t)&&(i.set(t,n),Ke(n,t,X,si,i),i.delete(t)),n}function hi(n){return gc(n)?X:n}function pi(n,t,r,e,u,i){
var o=r&hn,f=n.length,c=t.length;if(f!=c&&!(o&&c>f))return!1;var a=i.get(n),l=i.get(t);if(a&&l)return a==t&&l==n;var s=-1,p=!0,_=r&pn?new yr:X;for(i.set(n,t),i.set(t,n);++s<f;){var v=n[s],g=t[s];if(e)var y=o?e(g,v,s,t,n,i):e(v,g,s,n,t,i);if(y!==X){if(y)continue;p=!1;break}if(_){if(!h(t,function(n,t){if(!S(_,t)&&(v===n||u(v,n,r,e,i)))return _.push(t)})){p=!1;break}}else if(v!==g&&!u(v,g,r,e,i)){p=!1;break}}return i.delete(n),i.delete(t),p}function _i(n,t,r,e,u,i,o){switch(r){case ct:if(n.byteLength!=t.byteLength||n.byteOffset!=t.byteOffset)return!1;
n=n.buffer,t=t.buffer;case ft:return!(n.byteLength!=t.byteLength||!i(new Rl(n),new Rl(t)));case Nn:case Pn:case Hn:return Gf(+n,+t);case Zn:return n.name==t.name&&n.message==t.message;case nt:case rt:return n==t+"";case Gn:var f=M;case tt:var c=e&hn;if(f||(f=P),n.size!=t.size&&!c)return!1;var a=o.get(n);if(a)return a==t;e|=pn,o.set(n,t);var l=pi(f(n),f(t),e,u,i,o);return o.delete(n),l;case et:if(_s)return _s.call(n)==_s.call(t)}return!1}function vi(n,t,r,e,u,i){var o=r&hn,f=yi(n),c=f.length;if(c!=yi(t).length&&!o)return!1;
for(var a=c;a--;){var l=f[a];if(!(o?l in t:bl.call(t,l)))return!1}var s=i.get(n),h=i.get(t);if(s&&h)return s==t&&h==n;var p=!0;i.set(n,t),i.set(t,n);for(var _=o;++a<c;){l=f[a];var v=n[l],g=t[l];if(e)var y=o?e(g,v,l,t,n,i):e(v,g,l,n,t,i);if(!(y===X?v===g||u(v,g,r,e,i):y)){p=!1;break}_||(_="constructor"==l)}if(p&&!_){var d=n.constructor,b=t.constructor;d!=b&&"constructor"in n&&"constructor"in t&&!("function"==typeof d&&d instanceof d&&"function"==typeof b&&b instanceof b)&&(p=!1)}return i.delete(n),
i.delete(t),p}function gi(n){return Ls(Vi(n,X,_o),n+"")}function yi(n){return de(n,Pc,Is)}function di(n){return de(n,qc,Rs)}function bi(n){for(var t=n.name+"",r=fs[t],e=bl.call(fs,t)?r.length:0;e--;){var u=r[e],i=u.func;if(null==i||i==n)return u.name}return t}function wi(n){return(bl.call(Z,"placeholder")?Z:n).placeholder}function mi(){var n=Z.iteratee||Ca;return n=n===Ca?De:n,arguments.length?n(arguments[0],arguments[1]):n}function xi(n,t){var r=n.__data__;return Ti(t)?r["string"==typeof t?"string":"hash"]:r.map;
}function ji(n){for(var t=Pc(n),r=t.length;r--;){var e=t[r],u=n[e];t[r]=[e,u,Fi(u)]}return t}function Ai(n,t){var r=B(n,t);return Ue(r)?r:X}function ki(n){var t=bl.call(n,Bl),r=n[Bl];try{n[Bl]=X;var e=!0}catch(n){}var u=xl.call(n);return e&&(t?n[Bl]=r:delete n[Bl]),u}function Oi(n,t,r){for(var e=-1,u=r.length;++e<u;){var i=r[e],o=i.size;switch(i.type){case"drop":n+=o;break;case"dropRight":t-=o;break;case"take":t=Hl(t,n+o);break;case"takeRight":n=Gl(n,t-o)}}return{start:n,end:t}}function Ii(n){var t=n.match(Bt);
return t?t[1].split(Tt):[]}function Ri(n,t,r){t=ku(t,n);for(var e=-1,u=t.length,i=!1;++e<u;){var o=no(t[e]);if(!(i=null!=n&&r(n,o)))break;n=n[o]}return i||++e!=u?i:(u=null==n?0:n.length,!!u&&oc(u)&&Ci(o,u)&&(bh(n)||dh(n)))}function zi(n){var t=n.length,r=new n.constructor(t);return t&&"string"==typeof n[0]&&bl.call(n,"index")&&(r.index=n.index,r.input=n.input),r}function Ei(n){return"function"!=typeof n.constructor||Mi(n)?{}:gs(El(n))}function Si(n,t,r){var e=n.constructor;switch(t){case ft:return Ru(n);
case Nn:case Pn:return new e(+n);case ct:return zu(n,r);case at:case lt:case st:case ht:case pt:case _t:case vt:case gt:case yt:return Wu(n,r);case Gn:return new e;case Hn:case rt:return new e(n);case nt:return Eu(n);case tt:return new e;case et:return Su(n)}}function Wi(n,t){var r=t.length;if(!r)return n;var e=r-1;return t[e]=(r>1?"& ":"")+t[e],t=t.join(r>2?", ":" "),n.replace(Ut,"{\n/* [wrapped with "+t+"] */\n")}function Li(n){return bh(n)||dh(n)||!!(Cl&&n&&n[Cl])}function Ci(n,t){var r=typeof n;
return t=null==t?Wn:t,!!t&&("number"==r||"symbol"!=r&&Vt.test(n))&&n>-1&&n%1==0&&n<t}function Ui(n,t,r){if(!fc(r))return!1;var e=typeof t;return!!("number"==e?Hf(r)&&Ci(t,r.length):"string"==e&&t in r)&&Gf(r[t],n)}function Bi(n,t){if(bh(n))return!1;var r=typeof n;return!("number"!=r&&"symbol"!=r&&"boolean"!=r&&null!=n&&!bc(n))||(zt.test(n)||!Rt.test(n)||null!=t&&n in ll(t))}function Ti(n){var t=typeof n;return"string"==t||"number"==t||"symbol"==t||"boolean"==t?"__proto__"!==n:null===n}function $i(n){
var t=bi(n),r=Z[t];if("function"!=typeof r||!(t in Ct.prototype))return!1;if(n===r)return!0;var e=Os(r);return!!e&&n===e[0]}function Di(n){return!!ml&&ml in n}function Mi(n){var t=n&&n.constructor;return n===("function"==typeof t&&t.prototype||gl)}function Fi(n){return n===n&&!fc(n)}function Ni(n,t){return function(r){return null!=r&&(r[n]===t&&(t!==X||n in ll(r)))}}function Pi(n){var t=Cf(n,function(n){return r.size===fn&&r.clear(),n}),r=t.cache;return t}function qi(n,t){var r=n[1],e=t[1],u=r|e,i=u<(_n|vn|mn),o=e==mn&&r==yn||e==mn&&r==xn&&n[7].length<=t[8]||e==(mn|xn)&&t[7].length<=t[8]&&r==yn;
if(!i&&!o)return n;e&_n&&(n[2]=t[2],u|=r&_n?0:gn);var f=t[3];if(f){var c=n[3];n[3]=c?Uu(c,f,t[4]):f,n[4]=c?N(n[3],cn):t[4]}return f=t[5],f&&(c=n[5],n[5]=c?Bu(c,f,t[6]):f,n[6]=c?N(n[5],cn):t[6]),f=t[7],f&&(n[7]=f),e&mn&&(n[8]=null==n[8]?t[8]:Hl(n[8],t[8])),null==n[9]&&(n[9]=t[9]),n[0]=t[0],n[1]=u,n}function Zi(n){var t=[];if(null!=n)for(var r in ll(n))t.push(r);return t}function Ki(n){return xl.call(n)}function Vi(t,r,e){return r=Gl(r===X?t.length-1:r,0),function(){for(var u=arguments,i=-1,o=Gl(u.length-r,0),f=il(o);++i<o;)f[i]=u[r+i];
i=-1;for(var c=il(r+1);++i<r;)c[i]=u[i];return c[r]=e(f),n(t,this,c)}}function Gi(n,t){return t.length<2?n:_e(n,au(t,0,-1))}function Hi(n,t){for(var r=n.length,e=Hl(t.length,r),u=Tu(n);e--;){var i=t[e];n[e]=Ci(i,r)?u[i]:X}return n}function Ji(n,t){if(("constructor"!==t||"function"!=typeof n[t])&&"__proto__"!=t)return n[t]}function Yi(n,t,r){var e=t+"";return Ls(n,Wi(e,ro(Ii(e),r)))}function Qi(n){var t=0,r=0;return function(){var e=Jl(),u=In-(e-r);if(r=e,u>0){if(++t>=On)return arguments[0]}else t=0;
return n.apply(X,arguments)}}function Xi(n,t){var r=-1,e=n.length,u=e-1;for(t=t===X?e:t;++r<t;){var i=tu(r,u),o=n[i];n[i]=n[r],n[r]=o}return n.length=t,n}function no(n){if("string"==typeof n||bc(n))return n;var t=n+"";return"0"==t&&1/n==-Sn?"-0":t}function to(n){if(null!=n){try{return dl.call(n)}catch(n){}try{return n+""}catch(n){}}return""}function ro(n,t){return r($n,function(r){var e="_."+r[0];t&r[1]&&!o(n,e)&&n.push(e)}),n.sort()}function eo(n){if(n instanceof Ct)return n.clone();var t=new Y(n.__wrapped__,n.__chain__);
return t.__actions__=Tu(n.__actions__),t.__index__=n.__index__,t.__values__=n.__values__,t}function uo(n,t,r){t=(r?Ui(n,t,r):t===X)?1:Gl(kc(t),0);var e=null==n?0:n.length;if(!e||t<1)return[];for(var u=0,i=0,o=il(Fl(e/t));u<e;)o[i++]=au(n,u,u+=t);return o}function io(n){for(var t=-1,r=null==n?0:n.length,e=0,u=[];++t<r;){var i=n[t];i&&(u[e++]=i)}return u}function oo(){var n=arguments.length;if(!n)return[];for(var t=il(n-1),r=arguments[0],e=n;e--;)t[e-1]=arguments[e];return a(bh(r)?Tu(r):[r],ee(t,1));
}function fo(n,t,r){var e=null==n?0:n.length;return e?(t=r||t===X?1:kc(t),au(n,t<0?0:t,e)):[]}function co(n,t,r){var e=null==n?0:n.length;return e?(t=r||t===X?1:kc(t),t=e-t,au(n,0,t<0?0:t)):[]}function ao(n,t){return n&&n.length?bu(n,mi(t,3),!0,!0):[]}function lo(n,t){return n&&n.length?bu(n,mi(t,3),!0):[]}function so(n,t,r,e){var u=null==n?0:n.length;return u?(r&&"number"!=typeof r&&Ui(n,t,r)&&(r=0,e=u),ne(n,t,r,e)):[]}function ho(n,t,r){var e=null==n?0:n.length;if(!e)return-1;var u=null==r?0:kc(r);
return u<0&&(u=Gl(e+u,0)),g(n,mi(t,3),u)}function po(n,t,r){var e=null==n?0:n.length;if(!e)return-1;var u=e-1;return r!==X&&(u=kc(r),u=r<0?Gl(e+u,0):Hl(u,e-1)),g(n,mi(t,3),u,!0)}function _o(n){return(null==n?0:n.length)?ee(n,1):[]}function vo(n){return(null==n?0:n.length)?ee(n,Sn):[]}function go(n,t){return(null==n?0:n.length)?(t=t===X?1:kc(t),ee(n,t)):[]}function yo(n){for(var t=-1,r=null==n?0:n.length,e={};++t<r;){var u=n[t];e[u[0]]=u[1]}return e}function bo(n){return n&&n.length?n[0]:X}function wo(n,t,r){
var e=null==n?0:n.length;if(!e)return-1;var u=null==r?0:kc(r);return u<0&&(u=Gl(e+u,0)),y(n,t,u)}function mo(n){return(null==n?0:n.length)?au(n,0,-1):[]}function xo(n,t){return null==n?"":Kl.call(n,t)}function jo(n){var t=null==n?0:n.length;return t?n[t-1]:X}function Ao(n,t,r){var e=null==n?0:n.length;if(!e)return-1;var u=e;return r!==X&&(u=kc(r),u=u<0?Gl(e+u,0):Hl(u,e-1)),t===t?K(n,t,u):g(n,b,u,!0)}function ko(n,t){return n&&n.length?Ge(n,kc(t)):X}function Oo(n,t){return n&&n.length&&t&&t.length?Xe(n,t):n;
}function Io(n,t,r){return n&&n.length&&t&&t.length?Xe(n,t,mi(r,2)):n}function Ro(n,t,r){return n&&n.length&&t&&t.length?Xe(n,t,X,r):n}function zo(n,t){var r=[];if(!n||!n.length)return r;var e=-1,u=[],i=n.length;for(t=mi(t,3);++e<i;){var o=n[e];t(o,e,n)&&(r.push(o),u.push(e))}return nu(n,u),r}function Eo(n){return null==n?n:Xl.call(n)}function So(n,t,r){var e=null==n?0:n.length;return e?(r&&"number"!=typeof r&&Ui(n,t,r)?(t=0,r=e):(t=null==t?0:kc(t),r=r===X?e:kc(r)),au(n,t,r)):[]}function Wo(n,t){
return su(n,t)}function Lo(n,t,r){return hu(n,t,mi(r,2))}function Co(n,t){var r=null==n?0:n.length;if(r){var e=su(n,t);if(e<r&&Gf(n[e],t))return e}return-1}function Uo(n,t){return su(n,t,!0)}function Bo(n,t,r){return hu(n,t,mi(r,2),!0)}function To(n,t){if(null==n?0:n.length){var r=su(n,t,!0)-1;if(Gf(n[r],t))return r}return-1}function $o(n){return n&&n.length?pu(n):[]}function Do(n,t){return n&&n.length?pu(n,mi(t,2)):[]}function Mo(n){var t=null==n?0:n.length;return t?au(n,1,t):[]}function Fo(n,t,r){
return n&&n.length?(t=r||t===X?1:kc(t),au(n,0,t<0?0:t)):[]}function No(n,t,r){var e=null==n?0:n.length;return e?(t=r||t===X?1:kc(t),t=e-t,au(n,t<0?0:t,e)):[]}function Po(n,t){return n&&n.length?bu(n,mi(t,3),!1,!0):[]}function qo(n,t){return n&&n.length?bu(n,mi(t,3)):[]}function Zo(n){return n&&n.length?gu(n):[]}function Ko(n,t){return n&&n.length?gu(n,mi(t,2)):[]}function Vo(n,t){return t="function"==typeof t?t:X,n&&n.length?gu(n,X,t):[]}function Go(n){if(!n||!n.length)return[];var t=0;return n=i(n,function(n){
if(Jf(n))return t=Gl(n.length,t),!0}),O(t,function(t){return c(n,m(t))})}function Ho(t,r){if(!t||!t.length)return[];var e=Go(t);return null==r?e:c(e,function(t){return n(r,X,t)})}function Jo(n,t){return xu(n||[],t||[],Sr)}function Yo(n,t){return xu(n||[],t||[],fu)}function Qo(n){var t=Z(n);return t.__chain__=!0,t}function Xo(n,t){return t(n),n}function nf(n,t){return t(n)}function tf(){return Qo(this)}function rf(){return new Y(this.value(),this.__chain__)}function ef(){this.__values__===X&&(this.__values__=jc(this.value()));
var n=this.__index__>=this.__values__.length;return{done:n,value:n?X:this.__values__[this.__index__++]}}function uf(){return this}function of(n){for(var t,r=this;r instanceof J;){var e=eo(r);e.__index__=0,e.__values__=X,t?u.__wrapped__=e:t=e;var u=e;r=r.__wrapped__}return u.__wrapped__=n,t}function ff(){var n=this.__wrapped__;if(n instanceof Ct){var t=n;return this.__actions__.length&&(t=new Ct(this)),t=t.reverse(),t.__actions__.push({func:nf,args:[Eo],thisArg:X}),new Y(t,this.__chain__)}return this.thru(Eo);
}function cf(){return wu(this.__wrapped__,this.__actions__)}function af(n,t,r){var e=bh(n)?u:Jr;return r&&Ui(n,t,r)&&(t=X),e(n,mi(t,3))}function lf(n,t){return(bh(n)?i:te)(n,mi(t,3))}function sf(n,t){return ee(yf(n,t),1)}function hf(n,t){return ee(yf(n,t),Sn)}function pf(n,t,r){return r=r===X?1:kc(r),ee(yf(n,t),r)}function _f(n,t){return(bh(n)?r:ys)(n,mi(t,3))}function vf(n,t){return(bh(n)?e:ds)(n,mi(t,3))}function gf(n,t,r,e){n=Hf(n)?n:ra(n),r=r&&!e?kc(r):0;var u=n.length;return r<0&&(r=Gl(u+r,0)),
dc(n)?r<=u&&n.indexOf(t,r)>-1:!!u&&y(n,t,r)>-1}function yf(n,t){return(bh(n)?c:Pe)(n,mi(t,3))}function df(n,t,r,e){return null==n?[]:(bh(t)||(t=null==t?[]:[t]),r=e?X:r,bh(r)||(r=null==r?[]:[r]),He(n,t,r))}function bf(n,t,r){var e=bh(n)?l:j,u=arguments.length<3;return e(n,mi(t,4),r,u,ys)}function wf(n,t,r){var e=bh(n)?s:j,u=arguments.length<3;return e(n,mi(t,4),r,u,ds)}function mf(n,t){return(bh(n)?i:te)(n,Uf(mi(t,3)))}function xf(n){return(bh(n)?Ir:iu)(n)}function jf(n,t,r){return t=(r?Ui(n,t,r):t===X)?1:kc(t),
(bh(n)?Rr:ou)(n,t)}function Af(n){return(bh(n)?zr:cu)(n)}function kf(n){if(null==n)return 0;if(Hf(n))return dc(n)?V(n):n.length;var t=zs(n);return t==Gn||t==tt?n.size:Me(n).length}function Of(n,t,r){var e=bh(n)?h:lu;return r&&Ui(n,t,r)&&(t=X),e(n,mi(t,3))}function If(n,t){if("function"!=typeof t)throw new pl(en);return n=kc(n),function(){if(--n<1)return t.apply(this,arguments)}}function Rf(n,t,r){return t=r?X:t,t=n&&null==t?n.length:t,ai(n,mn,X,X,X,X,t)}function zf(n,t){var r;if("function"!=typeof t)throw new pl(en);
return n=kc(n),function(){return--n>0&&(r=t.apply(this,arguments)),n<=1&&(t=X),r}}function Ef(n,t,r){t=r?X:t;var e=ai(n,yn,X,X,X,X,X,t);return e.placeholder=Ef.placeholder,e}function Sf(n,t,r){t=r?X:t;var e=ai(n,dn,X,X,X,X,X,t);return e.placeholder=Sf.placeholder,e}function Wf(n,t,r){function e(t){var r=h,e=p;return h=p=X,d=t,v=n.apply(e,r)}function u(n){return d=n,g=Ws(f,t),b?e(n):v}function i(n){var r=n-y,e=n-d,u=t-r;return w?Hl(u,_-e):u}function o(n){var r=n-y,e=n-d;return y===X||r>=t||r<0||w&&e>=_;
}function f(){var n=fh();return o(n)?c(n):(g=Ws(f,i(n)),X)}function c(n){return g=X,m&&h?e(n):(h=p=X,v)}function a(){g!==X&&As(g),d=0,h=y=p=g=X}function l(){return g===X?v:c(fh())}function s(){var n=fh(),r=o(n);if(h=arguments,p=this,y=n,r){if(g===X)return u(y);if(w)return As(g),g=Ws(f,t),e(y)}return g===X&&(g=Ws(f,t)),v}var h,p,_,v,g,y,d=0,b=!1,w=!1,m=!0;if("function"!=typeof n)throw new pl(en);return t=Ic(t)||0,fc(r)&&(b=!!r.leading,w="maxWait"in r,_=w?Gl(Ic(r.maxWait)||0,t):_,m="trailing"in r?!!r.trailing:m),
s.cancel=a,s.flush=l,s}function Lf(n){return ai(n,jn)}function Cf(n,t){if("function"!=typeof n||null!=t&&"function"!=typeof t)throw new pl(en);var r=function(){var e=arguments,u=t?t.apply(this,e):e[0],i=r.cache;if(i.has(u))return i.get(u);var o=n.apply(this,e);return r.cache=i.set(u,o)||i,o};return r.cache=new(Cf.Cache||sr),r}function Uf(n){if("function"!=typeof n)throw new pl(en);return function(){var t=arguments;switch(t.length){case 0:return!n.call(this);case 1:return!n.call(this,t[0]);case 2:
return!n.call(this,t[0],t[1]);case 3:return!n.call(this,t[0],t[1],t[2])}return!n.apply(this,t)}}function Bf(n){return zf(2,n)}function Tf(n,t){if("function"!=typeof n)throw new pl(en);return t=t===X?t:kc(t),uu(n,t)}function $f(t,r){if("function"!=typeof t)throw new pl(en);return r=null==r?0:Gl(kc(r),0),uu(function(e){var u=e[r],i=Ou(e,0,r);return u&&a(i,u),n(t,this,i)})}function Df(n,t,r){var e=!0,u=!0;if("function"!=typeof n)throw new pl(en);return fc(r)&&(e="leading"in r?!!r.leading:e,u="trailing"in r?!!r.trailing:u),
Wf(n,t,{leading:e,maxWait:t,trailing:u})}function Mf(n){return Rf(n,1)}function Ff(n,t){return ph(Au(t),n)}function Nf(){if(!arguments.length)return[];var n=arguments[0];return bh(n)?n:[n]}function Pf(n){return Fr(n,sn)}function qf(n,t){return t="function"==typeof t?t:X,Fr(n,sn,t)}function Zf(n){return Fr(n,an|sn)}function Kf(n,t){return t="function"==typeof t?t:X,Fr(n,an|sn,t)}function Vf(n,t){return null==t||Pr(n,t,Pc(t))}function Gf(n,t){return n===t||n!==n&&t!==t}function Hf(n){return null!=n&&oc(n.length)&&!uc(n);
}function Jf(n){return cc(n)&&Hf(n)}function Yf(n){return n===!0||n===!1||cc(n)&&we(n)==Nn}function Qf(n){return cc(n)&&1===n.nodeType&&!gc(n)}function Xf(n){if(null==n)return!0;if(Hf(n)&&(bh(n)||"string"==typeof n||"function"==typeof n.splice||mh(n)||Oh(n)||dh(n)))return!n.length;var t=zs(n);if(t==Gn||t==tt)return!n.size;if(Mi(n))return!Me(n).length;for(var r in n)if(bl.call(n,r))return!1;return!0}function nc(n,t){return Se(n,t)}function tc(n,t,r){r="function"==typeof r?r:X;var e=r?r(n,t):X;return e===X?Se(n,t,X,r):!!e;
}function rc(n){if(!cc(n))return!1;var t=we(n);return t==Zn||t==qn||"string"==typeof n.message&&"string"==typeof n.name&&!gc(n)}function ec(n){return"number"==typeof n&&Zl(n)}function uc(n){if(!fc(n))return!1;var t=we(n);return t==Kn||t==Vn||t==Fn||t==Xn}function ic(n){return"number"==typeof n&&n==kc(n)}function oc(n){return"number"==typeof n&&n>-1&&n%1==0&&n<=Wn}function fc(n){var t=typeof n;return null!=n&&("object"==t||"function"==t)}function cc(n){return null!=n&&"object"==typeof n}function ac(n,t){
return n===t||Ce(n,t,ji(t))}function lc(n,t,r){return r="function"==typeof r?r:X,Ce(n,t,ji(t),r)}function sc(n){return vc(n)&&n!=+n}function hc(n){if(Es(n))throw new fl(rn);return Ue(n)}function pc(n){return null===n}function _c(n){return null==n}function vc(n){return"number"==typeof n||cc(n)&&we(n)==Hn}function gc(n){if(!cc(n)||we(n)!=Yn)return!1;var t=El(n);if(null===t)return!0;var r=bl.call(t,"constructor")&&t.constructor;return"function"==typeof r&&r instanceof r&&dl.call(r)==jl}function yc(n){
return ic(n)&&n>=-Wn&&n<=Wn}function dc(n){return"string"==typeof n||!bh(n)&&cc(n)&&we(n)==rt}function bc(n){return"symbol"==typeof n||cc(n)&&we(n)==et}function wc(n){return n===X}function mc(n){return cc(n)&&zs(n)==it}function xc(n){return cc(n)&&we(n)==ot}function jc(n){if(!n)return[];if(Hf(n))return dc(n)?G(n):Tu(n);if(Ul&&n[Ul])return D(n[Ul]());var t=zs(n);return(t==Gn?M:t==tt?P:ra)(n)}function Ac(n){if(!n)return 0===n?n:0;if(n=Ic(n),n===Sn||n===-Sn){return(n<0?-1:1)*Ln}return n===n?n:0}function kc(n){
var t=Ac(n),r=t%1;return t===t?r?t-r:t:0}function Oc(n){return n?Mr(kc(n),0,Un):0}function Ic(n){if("number"==typeof n)return n;if(bc(n))return Cn;if(fc(n)){var t="function"==typeof n.valueOf?n.valueOf():n;n=fc(t)?t+"":t}if("string"!=typeof n)return 0===n?n:+n;n=R(n);var r=qt.test(n);return r||Kt.test(n)?Xr(n.slice(2),r?2:8):Pt.test(n)?Cn:+n}function Rc(n){return $u(n,qc(n))}function zc(n){return n?Mr(kc(n),-Wn,Wn):0===n?n:0}function Ec(n){return null==n?"":vu(n)}function Sc(n,t){var r=gs(n);return null==t?r:Cr(r,t);
}function Wc(n,t){return v(n,mi(t,3),ue)}function Lc(n,t){return v(n,mi(t,3),oe)}function Cc(n,t){return null==n?n:bs(n,mi(t,3),qc)}function Uc(n,t){return null==n?n:ws(n,mi(t,3),qc)}function Bc(n,t){return n&&ue(n,mi(t,3))}function Tc(n,t){return n&&oe(n,mi(t,3))}function $c(n){return null==n?[]:fe(n,Pc(n))}function Dc(n){return null==n?[]:fe(n,qc(n))}function Mc(n,t,r){var e=null==n?X:_e(n,t);return e===X?r:e}function Fc(n,t){return null!=n&&Ri(n,t,xe)}function Nc(n,t){return null!=n&&Ri(n,t,je);
}function Pc(n){return Hf(n)?Or(n):Me(n)}function qc(n){return Hf(n)?Or(n,!0):Fe(n)}function Zc(n,t){var r={};return t=mi(t,3),ue(n,function(n,e,u){Br(r,t(n,e,u),n)}),r}function Kc(n,t){var r={};return t=mi(t,3),ue(n,function(n,e,u){Br(r,e,t(n,e,u))}),r}function Vc(n,t){return Gc(n,Uf(mi(t)))}function Gc(n,t){if(null==n)return{};var r=c(di(n),function(n){return[n]});return t=mi(t),Ye(n,r,function(n,r){return t(n,r[0])})}function Hc(n,t,r){t=ku(t,n);var e=-1,u=t.length;for(u||(u=1,n=X);++e<u;){var i=null==n?X:n[no(t[e])];
i===X&&(e=u,i=r),n=uc(i)?i.call(n):i}return n}function Jc(n,t,r){return null==n?n:fu(n,t,r)}function Yc(n,t,r,e){return e="function"==typeof e?e:X,null==n?n:fu(n,t,r,e)}function Qc(n,t,e){var u=bh(n),i=u||mh(n)||Oh(n);if(t=mi(t,4),null==e){var o=n&&n.constructor;e=i?u?new o:[]:fc(n)&&uc(o)?gs(El(n)):{}}return(i?r:ue)(n,function(n,r,u){return t(e,n,r,u)}),e}function Xc(n,t){return null==n||yu(n,t)}function na(n,t,r){return null==n?n:du(n,t,Au(r))}function ta(n,t,r,e){return e="function"==typeof e?e:X,
null==n?n:du(n,t,Au(r),e)}function ra(n){return null==n?[]:E(n,Pc(n))}function ea(n){return null==n?[]:E(n,qc(n))}function ua(n,t,r){return r===X&&(r=t,t=X),r!==X&&(r=Ic(r),r=r===r?r:0),t!==X&&(t=Ic(t),t=t===t?t:0),Mr(Ic(n),t,r)}function ia(n,t,r){return t=Ac(t),r===X?(r=t,t=0):r=Ac(r),n=Ic(n),Ae(n,t,r)}function oa(n,t,r){if(r&&"boolean"!=typeof r&&Ui(n,t,r)&&(t=r=X),r===X&&("boolean"==typeof t?(r=t,t=X):"boolean"==typeof n&&(r=n,n=X)),n===X&&t===X?(n=0,t=1):(n=Ac(n),t===X?(t=n,n=0):t=Ac(t)),n>t){
var e=n;n=t,t=e}if(r||n%1||t%1){var u=Ql();return Hl(n+u*(t-n+Qr("1e-"+((u+"").length-1))),t)}return tu(n,t)}function fa(n){return Qh(Ec(n).toLowerCase())}function ca(n){return n=Ec(n),n&&n.replace(Gt,ve).replace(Dr,"")}function aa(n,t,r){n=Ec(n),t=vu(t);var e=n.length;r=r===X?e:Mr(kc(r),0,e);var u=r;return r-=t.length,r>=0&&n.slice(r,u)==t}function la(n){return n=Ec(n),n&&At.test(n)?n.replace(xt,ge):n}function sa(n){return n=Ec(n),n&&Wt.test(n)?n.replace(St,"\\$&"):n}function ha(n,t,r){n=Ec(n),t=kc(t);
var e=t?V(n):0;if(!t||e>=t)return n;var u=(t-e)/2;return ri(Nl(u),r)+n+ri(Fl(u),r)}function pa(n,t,r){n=Ec(n),t=kc(t);var e=t?V(n):0;return t&&e<t?n+ri(t-e,r):n}function _a(n,t,r){n=Ec(n),t=kc(t);var e=t?V(n):0;return t&&e<t?ri(t-e,r)+n:n}function va(n,t,r){return r||null==t?t=0:t&&(t=+t),Yl(Ec(n).replace(Lt,""),t||0)}function ga(n,t,r){return t=(r?Ui(n,t,r):t===X)?1:kc(t),eu(Ec(n),t)}function ya(){var n=arguments,t=Ec(n[0]);return n.length<3?t:t.replace(n[1],n[2])}function da(n,t,r){return r&&"number"!=typeof r&&Ui(n,t,r)&&(t=r=X),
(r=r===X?Un:r>>>0)?(n=Ec(n),n&&("string"==typeof t||null!=t&&!Ah(t))&&(t=vu(t),!t&&T(n))?Ou(G(n),0,r):n.split(t,r)):[]}function ba(n,t,r){return n=Ec(n),r=null==r?0:Mr(kc(r),0,n.length),t=vu(t),n.slice(r,r+t.length)==t}function wa(n,t,r){var e=Z.templateSettings;r&&Ui(n,t,r)&&(t=X),n=Ec(n),t=Sh({},t,e,li);var u,i,o=Sh({},t.imports,e.imports,li),f=Pc(o),c=E(o,f),a=0,l=t.interpolate||Ht,s="__p += '",h=sl((t.escape||Ht).source+"|"+l.source+"|"+(l===It?Ft:Ht).source+"|"+(t.evaluate||Ht).source+"|$","g"),p="//# sourceURL="+(bl.call(t,"sourceURL")?(t.sourceURL+"").replace(/\s/g," "):"lodash.templateSources["+ ++Zr+"]")+"\n";
n.replace(h,function(t,r,e,o,f,c){return e||(e=o),s+=n.slice(a,c).replace(Jt,U),r&&(u=!0,s+="' +\n__e("+r+") +\n'"),f&&(i=!0,s+="';\n"+f+";\n__p += '"),e&&(s+="' +\n((__t = ("+e+")) == null ? '' : __t) +\n'"),a=c+t.length,t}),s+="';\n";var _=bl.call(t,"variable")&&t.variable;if(_){if(Dt.test(_))throw new fl(un)}else s="with (obj) {\n"+s+"\n}\n";s=(i?s.replace(dt,""):s).replace(bt,"$1").replace(wt,"$1;"),s="function("+(_||"obj")+") {\n"+(_?"":"obj || (obj = {});\n")+"var __t, __p = ''"+(u?", __e = _.escape":"")+(i?", __j = Array.prototype.join;\nfunction print() { __p += __j.call(arguments, '') }\n":";\n")+s+"return __p\n}";
var v=Xh(function(){return cl(f,p+"return "+s).apply(X,c)});if(v.source=s,rc(v))throw v;return v}function ma(n){return Ec(n).toLowerCase()}function xa(n){return Ec(n).toUpperCase()}function ja(n,t,r){if(n=Ec(n),n&&(r||t===X))return R(n);if(!n||!(t=vu(t)))return n;var e=G(n),u=G(t);return Ou(e,W(e,u),L(e,u)+1).join("")}function Aa(n,t,r){if(n=Ec(n),n&&(r||t===X))return n.slice(0,H(n)+1);if(!n||!(t=vu(t)))return n;var e=G(n);return Ou(e,0,L(e,G(t))+1).join("")}function ka(n,t,r){if(n=Ec(n),n&&(r||t===X))return n.replace(Lt,"");
if(!n||!(t=vu(t)))return n;var e=G(n);return Ou(e,W(e,G(t))).join("")}function Oa(n,t){var r=An,e=kn;if(fc(t)){var u="separator"in t?t.separator:u;r="length"in t?kc(t.length):r,e="omission"in t?vu(t.omission):e}n=Ec(n);var i=n.length;if(T(n)){var o=G(n);i=o.length}if(r>=i)return n;var f=r-V(e);if(f<1)return e;var c=o?Ou(o,0,f).join(""):n.slice(0,f);if(u===X)return c+e;if(o&&(f+=c.length-f),Ah(u)){if(n.slice(f).search(u)){var a,l=c;for(u.global||(u=sl(u.source,Ec(Nt.exec(u))+"g")),u.lastIndex=0;a=u.exec(l);)var s=a.index;
c=c.slice(0,s===X?f:s)}}else if(n.indexOf(vu(u),f)!=f){var h=c.lastIndexOf(u);h>-1&&(c=c.slice(0,h))}return c+e}function Ia(n){return n=Ec(n),n&&jt.test(n)?n.replace(mt,ye):n}function Ra(n,t,r){return n=Ec(n),t=r?X:t,t===X?$(n)?Q(n):_(n):n.match(t)||[]}function za(t){var r=null==t?0:t.length,e=mi();return t=r?c(t,function(n){if("function"!=typeof n[1])throw new pl(en);return[e(n[0]),n[1]]}):[],uu(function(e){for(var u=-1;++u<r;){var i=t[u];if(n(i[0],this,e))return n(i[1],this,e)}})}function Ea(n){
return Nr(Fr(n,an))}function Sa(n){return function(){return n}}function Wa(n,t){return null==n||n!==n?t:n}function La(n){return n}function Ca(n){return De("function"==typeof n?n:Fr(n,an))}function Ua(n){return qe(Fr(n,an))}function Ba(n,t){return Ze(n,Fr(t,an))}function Ta(n,t,e){var u=Pc(t),i=fe(t,u);null!=e||fc(t)&&(i.length||!u.length)||(e=t,t=n,n=this,i=fe(t,Pc(t)));var o=!(fc(e)&&"chain"in e&&!e.chain),f=uc(n);return r(i,function(r){var e=t[r];n[r]=e,f&&(n.prototype[r]=function(){var t=this.__chain__;
if(o||t){var r=n(this.__wrapped__);return(r.__actions__=Tu(this.__actions__)).push({func:e,args:arguments,thisArg:n}),r.__chain__=t,r}return e.apply(n,a([this.value()],arguments))})}),n}function $a(){return re._===this&&(re._=Al),this}function Da(){}function Ma(n){return n=kc(n),uu(function(t){return Ge(t,n)})}function Fa(n){return Bi(n)?m(no(n)):Qe(n)}function Na(n){return function(t){return null==n?X:_e(n,t)}}function Pa(){return[]}function qa(){return!1}function Za(){return{}}function Ka(){return"";
}function Va(){return!0}function Ga(n,t){if(n=kc(n),n<1||n>Wn)return[];var r=Un,e=Hl(n,Un);t=mi(t),n-=Un;for(var u=O(e,t);++r<n;)t(r);return u}function Ha(n){return bh(n)?c(n,no):bc(n)?[n]:Tu(Cs(Ec(n)))}function Ja(n){var t=++wl;return Ec(n)+t}function Ya(n){return n&&n.length?Yr(n,La,me):X}function Qa(n,t){return n&&n.length?Yr(n,mi(t,2),me):X}function Xa(n){return w(n,La)}function nl(n,t){return w(n,mi(t,2))}function tl(n){return n&&n.length?Yr(n,La,Ne):X}function rl(n,t){return n&&n.length?Yr(n,mi(t,2),Ne):X;
}function el(n){return n&&n.length?k(n,La):0}function ul(n,t){return n&&n.length?k(n,mi(t,2)):0}x=null==x?re:be.defaults(re.Object(),x,be.pick(re,qr));var il=x.Array,ol=x.Date,fl=x.Error,cl=x.Function,al=x.Math,ll=x.Object,sl=x.RegExp,hl=x.String,pl=x.TypeError,_l=il.prototype,vl=cl.prototype,gl=ll.prototype,yl=x["__core-js_shared__"],dl=vl.toString,bl=gl.hasOwnProperty,wl=0,ml=function(){var n=/[^.]+$/.exec(yl&&yl.keys&&yl.keys.IE_PROTO||"");return n?"Symbol(src)_1."+n:""}(),xl=gl.toString,jl=dl.call(ll),Al=re._,kl=sl("^"+dl.call(bl).replace(St,"\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$"),Ol=ie?x.Buffer:X,Il=x.Symbol,Rl=x.Uint8Array,zl=Ol?Ol.allocUnsafe:X,El=F(ll.getPrototypeOf,ll),Sl=ll.create,Wl=gl.propertyIsEnumerable,Ll=_l.splice,Cl=Il?Il.isConcatSpreadable:X,Ul=Il?Il.iterator:X,Bl=Il?Il.toStringTag:X,Tl=function(){
try{var n=Ai(ll,"defineProperty");return n({},"",{}),n}catch(n){}}(),$l=x.clearTimeout!==re.clearTimeout&&x.clearTimeout,Dl=ol&&ol.now!==re.Date.now&&ol.now,Ml=x.setTimeout!==re.setTimeout&&x.setTimeout,Fl=al.ceil,Nl=al.floor,Pl=ll.getOwnPropertySymbols,ql=Ol?Ol.isBuffer:X,Zl=x.isFinite,Kl=_l.join,Vl=F(ll.keys,ll),Gl=al.max,Hl=al.min,Jl=ol.now,Yl=x.parseInt,Ql=al.random,Xl=_l.reverse,ns=Ai(x,"DataView"),ts=Ai(x,"Map"),rs=Ai(x,"Promise"),es=Ai(x,"Set"),us=Ai(x,"WeakMap"),is=Ai(ll,"create"),os=us&&new us,fs={},cs=to(ns),as=to(ts),ls=to(rs),ss=to(es),hs=to(us),ps=Il?Il.prototype:X,_s=ps?ps.valueOf:X,vs=ps?ps.toString:X,gs=function(){
function n(){}return function(t){if(!fc(t))return{};if(Sl)return Sl(t);n.prototype=t;var r=new n;return n.prototype=X,r}}();Z.templateSettings={escape:kt,evaluate:Ot,interpolate:It,variable:"",imports:{_:Z}},Z.prototype=J.prototype,Z.prototype.constructor=Z,Y.prototype=gs(J.prototype),Y.prototype.constructor=Y,Ct.prototype=gs(J.prototype),Ct.prototype.constructor=Ct,Xt.prototype.clear=nr,Xt.prototype.delete=tr,Xt.prototype.get=rr,Xt.prototype.has=er,Xt.prototype.set=ur,ir.prototype.clear=or,ir.prototype.delete=fr,
ir.prototype.get=cr,ir.prototype.has=ar,ir.prototype.set=lr,sr.prototype.clear=hr,sr.prototype.delete=pr,sr.prototype.get=_r,sr.prototype.has=vr,sr.prototype.set=gr,yr.prototype.add=yr.prototype.push=dr,yr.prototype.has=br,wr.prototype.clear=mr,wr.prototype.delete=xr,wr.prototype.get=jr,wr.prototype.has=Ar,wr.prototype.set=kr;var ys=Pu(ue),ds=Pu(oe,!0),bs=qu(),ws=qu(!0),ms=os?function(n,t){return os.set(n,t),n}:La,xs=Tl?function(n,t){return Tl(n,"toString",{configurable:!0,enumerable:!1,value:Sa(t),
writable:!0})}:La,js=uu,As=$l||function(n){return re.clearTimeout(n)},ks=es&&1/P(new es([,-0]))[1]==Sn?function(n){return new es(n)}:Da,Os=os?function(n){return os.get(n)}:Da,Is=Pl?function(n){return null==n?[]:(n=ll(n),i(Pl(n),function(t){return Wl.call(n,t)}))}:Pa,Rs=Pl?function(n){for(var t=[];n;)a(t,Is(n)),n=El(n);return t}:Pa,zs=we;(ns&&zs(new ns(new ArrayBuffer(1)))!=ct||ts&&zs(new ts)!=Gn||rs&&zs(rs.resolve())!=Qn||es&&zs(new es)!=tt||us&&zs(new us)!=it)&&(zs=function(n){var t=we(n),r=t==Yn?n.constructor:X,e=r?to(r):"";
if(e)switch(e){case cs:return ct;case as:return Gn;case ls:return Qn;case ss:return tt;case hs:return it}return t});var Es=yl?uc:qa,Ss=Qi(ms),Ws=Ml||function(n,t){return re.setTimeout(n,t)},Ls=Qi(xs),Cs=Pi(function(n){var t=[];return 46===n.charCodeAt(0)&&t.push(""),n.replace(Et,function(n,r,e,u){t.push(e?u.replace(Mt,"$1"):r||n)}),t}),Us=uu(function(n,t){return Jf(n)?Hr(n,ee(t,1,Jf,!0)):[]}),Bs=uu(function(n,t){var r=jo(t);return Jf(r)&&(r=X),Jf(n)?Hr(n,ee(t,1,Jf,!0),mi(r,2)):[]}),Ts=uu(function(n,t){
var r=jo(t);return Jf(r)&&(r=X),Jf(n)?Hr(n,ee(t,1,Jf,!0),X,r):[]}),$s=uu(function(n){var t=c(n,ju);return t.length&&t[0]===n[0]?ke(t):[]}),Ds=uu(function(n){var t=jo(n),r=c(n,ju);return t===jo(r)?t=X:r.pop(),r.length&&r[0]===n[0]?ke(r,mi(t,2)):[]}),Ms=uu(function(n){var t=jo(n),r=c(n,ju);return t="function"==typeof t?t:X,t&&r.pop(),r.length&&r[0]===n[0]?ke(r,X,t):[]}),Fs=uu(Oo),Ns=gi(function(n,t){var r=null==n?0:n.length,e=Tr(n,t);return nu(n,c(t,function(n){return Ci(n,r)?+n:n}).sort(Lu)),e}),Ps=uu(function(n){
return gu(ee(n,1,Jf,!0))}),qs=uu(function(n){var t=jo(n);return Jf(t)&&(t=X),gu(ee(n,1,Jf,!0),mi(t,2))}),Zs=uu(function(n){var t=jo(n);return t="function"==typeof t?t:X,gu(ee(n,1,Jf,!0),X,t)}),Ks=uu(function(n,t){return Jf(n)?Hr(n,t):[]}),Vs=uu(function(n){return mu(i(n,Jf))}),Gs=uu(function(n){var t=jo(n);return Jf(t)&&(t=X),mu(i(n,Jf),mi(t,2))}),Hs=uu(function(n){var t=jo(n);return t="function"==typeof t?t:X,mu(i(n,Jf),X,t)}),Js=uu(Go),Ys=uu(function(n){var t=n.length,r=t>1?n[t-1]:X;return r="function"==typeof r?(n.pop(),
r):X,Ho(n,r)}),Qs=gi(function(n){var t=n.length,r=t?n[0]:0,e=this.__wrapped__,u=function(t){return Tr(t,n)};return!(t>1||this.__actions__.length)&&e instanceof Ct&&Ci(r)?(e=e.slice(r,+r+(t?1:0)),e.__actions__.push({func:nf,args:[u],thisArg:X}),new Y(e,this.__chain__).thru(function(n){return t&&!n.length&&n.push(X),n})):this.thru(u)}),Xs=Fu(function(n,t,r){bl.call(n,r)?++n[r]:Br(n,r,1)}),nh=Ju(ho),th=Ju(po),rh=Fu(function(n,t,r){bl.call(n,r)?n[r].push(t):Br(n,r,[t])}),eh=uu(function(t,r,e){var u=-1,i="function"==typeof r,o=Hf(t)?il(t.length):[];
return ys(t,function(t){o[++u]=i?n(r,t,e):Ie(t,r,e)}),o}),uh=Fu(function(n,t,r){Br(n,r,t)}),ih=Fu(function(n,t,r){n[r?0:1].push(t)},function(){return[[],[]]}),oh=uu(function(n,t){if(null==n)return[];var r=t.length;return r>1&&Ui(n,t[0],t[1])?t=[]:r>2&&Ui(t[0],t[1],t[2])&&(t=[t[0]]),He(n,ee(t,1),[])}),fh=Dl||function(){return re.Date.now()},ch=uu(function(n,t,r){var e=_n;if(r.length){var u=N(r,wi(ch));e|=bn}return ai(n,e,t,r,u)}),ah=uu(function(n,t,r){var e=_n|vn;if(r.length){var u=N(r,wi(ah));e|=bn;
}return ai(t,e,n,r,u)}),lh=uu(function(n,t){return Gr(n,1,t)}),sh=uu(function(n,t,r){return Gr(n,Ic(t)||0,r)});Cf.Cache=sr;var hh=js(function(t,r){r=1==r.length&&bh(r[0])?c(r[0],z(mi())):c(ee(r,1),z(mi()));var e=r.length;return uu(function(u){for(var i=-1,o=Hl(u.length,e);++i<o;)u[i]=r[i].call(this,u[i]);return n(t,this,u)})}),ph=uu(function(n,t){return ai(n,bn,X,t,N(t,wi(ph)))}),_h=uu(function(n,t){return ai(n,wn,X,t,N(t,wi(_h)))}),vh=gi(function(n,t){return ai(n,xn,X,X,X,t)}),gh=ii(me),yh=ii(function(n,t){
return n>=t}),dh=Re(function(){return arguments}())?Re:function(n){return cc(n)&&bl.call(n,"callee")&&!Wl.call(n,"callee")},bh=il.isArray,wh=ce?z(ce):ze,mh=ql||qa,xh=ae?z(ae):Ee,jh=le?z(le):Le,Ah=se?z(se):Be,kh=he?z(he):Te,Oh=pe?z(pe):$e,Ih=ii(Ne),Rh=ii(function(n,t){return n<=t}),zh=Nu(function(n,t){if(Mi(t)||Hf(t))return $u(t,Pc(t),n),X;for(var r in t)bl.call(t,r)&&Sr(n,r,t[r])}),Eh=Nu(function(n,t){$u(t,qc(t),n)}),Sh=Nu(function(n,t,r,e){$u(t,qc(t),n,e)}),Wh=Nu(function(n,t,r,e){$u(t,Pc(t),n,e);
}),Lh=gi(Tr),Ch=uu(function(n,t){n=ll(n);var r=-1,e=t.length,u=e>2?t[2]:X;for(u&&Ui(t[0],t[1],u)&&(e=1);++r<e;)for(var i=t[r],o=qc(i),f=-1,c=o.length;++f<c;){var a=o[f],l=n[a];(l===X||Gf(l,gl[a])&&!bl.call(n,a))&&(n[a]=i[a])}return n}),Uh=uu(function(t){return t.push(X,si),n(Mh,X,t)}),Bh=Xu(function(n,t,r){null!=t&&"function"!=typeof t.toString&&(t=xl.call(t)),n[t]=r},Sa(La)),Th=Xu(function(n,t,r){null!=t&&"function"!=typeof t.toString&&(t=xl.call(t)),bl.call(n,t)?n[t].push(r):n[t]=[r]},mi),$h=uu(Ie),Dh=Nu(function(n,t,r){
Ke(n,t,r)}),Mh=Nu(function(n,t,r,e){Ke(n,t,r,e)}),Fh=gi(function(n,t){var r={};if(null==n)return r;var e=!1;t=c(t,function(t){return t=ku(t,n),e||(e=t.length>1),t}),$u(n,di(n),r),e&&(r=Fr(r,an|ln|sn,hi));for(var u=t.length;u--;)yu(r,t[u]);return r}),Nh=gi(function(n,t){return null==n?{}:Je(n,t)}),Ph=ci(Pc),qh=ci(qc),Zh=Vu(function(n,t,r){return t=t.toLowerCase(),n+(r?fa(t):t)}),Kh=Vu(function(n,t,r){return n+(r?"-":"")+t.toLowerCase()}),Vh=Vu(function(n,t,r){return n+(r?" ":"")+t.toLowerCase()}),Gh=Ku("toLowerCase"),Hh=Vu(function(n,t,r){
return n+(r?"_":"")+t.toLowerCase()}),Jh=Vu(function(n,t,r){return n+(r?" ":"")+Qh(t)}),Yh=Vu(function(n,t,r){return n+(r?" ":"")+t.toUpperCase()}),Qh=Ku("toUpperCase"),Xh=uu(function(t,r){try{return n(t,X,r)}catch(n){return rc(n)?n:new fl(n)}}),np=gi(function(n,t){return r(t,function(t){t=no(t),Br(n,t,ch(n[t],n))}),n}),tp=Yu(),rp=Yu(!0),ep=uu(function(n,t){return function(r){return Ie(r,n,t)}}),up=uu(function(n,t){return function(r){return Ie(n,r,t)}}),ip=ti(c),op=ti(u),fp=ti(h),cp=ui(),ap=ui(!0),lp=ni(function(n,t){
return n+t},0),sp=fi("ceil"),hp=ni(function(n,t){return n/t},1),pp=fi("floor"),_p=ni(function(n,t){return n*t},1),vp=fi("round"),gp=ni(function(n,t){return n-t},0);return Z.after=If,Z.ary=Rf,Z.assign=zh,Z.assignIn=Eh,Z.assignInWith=Sh,Z.assignWith=Wh,Z.at=Lh,Z.before=zf,Z.bind=ch,Z.bindAll=np,Z.bindKey=ah,Z.castArray=Nf,Z.chain=Qo,Z.chunk=uo,Z.compact=io,Z.concat=oo,Z.cond=za,Z.conforms=Ea,Z.constant=Sa,Z.countBy=Xs,Z.create=Sc,Z.curry=Ef,Z.curryRight=Sf,Z.debounce=Wf,Z.defaults=Ch,Z.defaultsDeep=Uh,
Z.defer=lh,Z.delay=sh,Z.difference=Us,Z.differenceBy=Bs,Z.differenceWith=Ts,Z.drop=fo,Z.dropRight=co,Z.dropRightWhile=ao,Z.dropWhile=lo,Z.fill=so,Z.filter=lf,Z.flatMap=sf,Z.flatMapDeep=hf,Z.flatMapDepth=pf,Z.flatten=_o,Z.flattenDeep=vo,Z.flattenDepth=go,Z.flip=Lf,Z.flow=tp,Z.flowRight=rp,Z.fromPairs=yo,Z.functions=$c,Z.functionsIn=Dc,Z.groupBy=rh,Z.initial=mo,Z.intersection=$s,Z.intersectionBy=Ds,Z.intersectionWith=Ms,Z.invert=Bh,Z.invertBy=Th,Z.invokeMap=eh,Z.iteratee=Ca,Z.keyBy=uh,Z.keys=Pc,Z.keysIn=qc,
Z.map=yf,Z.mapKeys=Zc,Z.mapValues=Kc,Z.matches=Ua,Z.matchesProperty=Ba,Z.memoize=Cf,Z.merge=Dh,Z.mergeWith=Mh,Z.method=ep,Z.methodOf=up,Z.mixin=Ta,Z.negate=Uf,Z.nthArg=Ma,Z.omit=Fh,Z.omitBy=Vc,Z.once=Bf,Z.orderBy=df,Z.over=ip,Z.overArgs=hh,Z.overEvery=op,Z.overSome=fp,Z.partial=ph,Z.partialRight=_h,Z.partition=ih,Z.pick=Nh,Z.pickBy=Gc,Z.property=Fa,Z.propertyOf=Na,Z.pull=Fs,Z.pullAll=Oo,Z.pullAllBy=Io,Z.pullAllWith=Ro,Z.pullAt=Ns,Z.range=cp,Z.rangeRight=ap,Z.rearg=vh,Z.reject=mf,Z.remove=zo,Z.rest=Tf,
Z.reverse=Eo,Z.sampleSize=jf,Z.set=Jc,Z.setWith=Yc,Z.shuffle=Af,Z.slice=So,Z.sortBy=oh,Z.sortedUniq=$o,Z.sortedUniqBy=Do,Z.split=da,Z.spread=$f,Z.tail=Mo,Z.take=Fo,Z.takeRight=No,Z.takeRightWhile=Po,Z.takeWhile=qo,Z.tap=Xo,Z.throttle=Df,Z.thru=nf,Z.toArray=jc,Z.toPairs=Ph,Z.toPairsIn=qh,Z.toPath=Ha,Z.toPlainObject=Rc,Z.transform=Qc,Z.unary=Mf,Z.union=Ps,Z.unionBy=qs,Z.unionWith=Zs,Z.uniq=Zo,Z.uniqBy=Ko,Z.uniqWith=Vo,Z.unset=Xc,Z.unzip=Go,Z.unzipWith=Ho,Z.update=na,Z.updateWith=ta,Z.values=ra,Z.valuesIn=ea,
Z.without=Ks,Z.words=Ra,Z.wrap=Ff,Z.xor=Vs,Z.xorBy=Gs,Z.xorWith=Hs,Z.zip=Js,Z.zipObject=Jo,Z.zipObjectDeep=Yo,Z.zipWith=Ys,Z.entries=Ph,Z.entriesIn=qh,Z.extend=Eh,Z.extendWith=Sh,Ta(Z,Z),Z.add=lp,Z.attempt=Xh,Z.camelCase=Zh,Z.capitalize=fa,Z.ceil=sp,Z.clamp=ua,Z.clone=Pf,Z.cloneDeep=Zf,Z.cloneDeepWith=Kf,Z.cloneWith=qf,Z.conformsTo=Vf,Z.deburr=ca,Z.defaultTo=Wa,Z.divide=hp,Z.endsWith=aa,Z.eq=Gf,Z.escape=la,Z.escapeRegExp=sa,Z.every=af,Z.find=nh,Z.findIndex=ho,Z.findKey=Wc,Z.findLast=th,Z.findLastIndex=po,
Z.findLastKey=Lc,Z.floor=pp,Z.forEach=_f,Z.forEachRight=vf,Z.forIn=Cc,Z.forInRight=Uc,Z.forOwn=Bc,Z.forOwnRight=Tc,Z.get=Mc,Z.gt=gh,Z.gte=yh,Z.has=Fc,Z.hasIn=Nc,Z.head=bo,Z.identity=La,Z.includes=gf,Z.indexOf=wo,Z.inRange=ia,Z.invoke=$h,Z.isArguments=dh,Z.isArray=bh,Z.isArrayBuffer=wh,Z.isArrayLike=Hf,Z.isArrayLikeObject=Jf,Z.isBoolean=Yf,Z.isBuffer=mh,Z.isDate=xh,Z.isElement=Qf,Z.isEmpty=Xf,Z.isEqual=nc,Z.isEqualWith=tc,Z.isError=rc,Z.isFinite=ec,Z.isFunction=uc,Z.isInteger=ic,Z.isLength=oc,Z.isMap=jh,
Z.isMatch=ac,Z.isMatchWith=lc,Z.isNaN=sc,Z.isNative=hc,Z.isNil=_c,Z.isNull=pc,Z.isNumber=vc,Z.isObject=fc,Z.isObjectLike=cc,Z.isPlainObject=gc,Z.isRegExp=Ah,Z.isSafeInteger=yc,Z.isSet=kh,Z.isString=dc,Z.isSymbol=bc,Z.isTypedArray=Oh,Z.isUndefined=wc,Z.isWeakMap=mc,Z.isWeakSet=xc,Z.join=xo,Z.kebabCase=Kh,Z.last=jo,Z.lastIndexOf=Ao,Z.lowerCase=Vh,Z.lowerFirst=Gh,Z.lt=Ih,Z.lte=Rh,Z.max=Ya,Z.maxBy=Qa,Z.mean=Xa,Z.meanBy=nl,Z.min=tl,Z.minBy=rl,Z.stubArray=Pa,Z.stubFalse=qa,Z.stubObject=Za,Z.stubString=Ka,
Z.stubTrue=Va,Z.multiply=_p,Z.nth=ko,Z.noConflict=$a,Z.noop=Da,Z.now=fh,Z.pad=ha,Z.padEnd=pa,Z.padStart=_a,Z.parseInt=va,Z.random=oa,Z.reduce=bf,Z.reduceRight=wf,Z.repeat=ga,Z.replace=ya,Z.result=Hc,Z.round=vp,Z.runInContext=p,Z.sample=xf,Z.size=kf,Z.snakeCase=Hh,Z.some=Of,Z.sortedIndex=Wo,Z.sortedIndexBy=Lo,Z.sortedIndexOf=Co,Z.sortedLastIndex=Uo,Z.sortedLastIndexBy=Bo,Z.sortedLastIndexOf=To,Z.startCase=Jh,Z.startsWith=ba,Z.subtract=gp,Z.sum=el,Z.sumBy=ul,Z.template=wa,Z.times=Ga,Z.toFinite=Ac,Z.toInteger=kc,
Z.toLength=Oc,Z.toLower=ma,Z.toNumber=Ic,Z.toSafeInteger=zc,Z.toString=Ec,Z.toUpper=xa,Z.trim=ja,Z.trimEnd=Aa,Z.trimStart=ka,Z.truncate=Oa,Z.unescape=Ia,Z.uniqueId=Ja,Z.upperCase=Yh,Z.upperFirst=Qh,Z.each=_f,Z.eachRight=vf,Z.first=bo,Ta(Z,function(){var n={};return ue(Z,function(t,r){bl.call(Z.prototype,r)||(n[r]=t)}),n}(),{chain:!1}),Z.VERSION=nn,r(["bind","bindKey","curry","curryRight","partial","partialRight"],function(n){Z[n].placeholder=Z}),r(["drop","take"],function(n,t){Ct.prototype[n]=function(r){
r=r===X?1:Gl(kc(r),0);var e=this.__filtered__&&!t?new Ct(this):this.clone();return e.__filtered__?e.__takeCount__=Hl(r,e.__takeCount__):e.__views__.push({size:Hl(r,Un),type:n+(e.__dir__<0?"Right":"")}),e},Ct.prototype[n+"Right"]=function(t){return this.reverse()[n](t).reverse()}}),r(["filter","map","takeWhile"],function(n,t){var r=t+1,e=r==Rn||r==En;Ct.prototype[n]=function(n){var t=this.clone();return t.__iteratees__.push({iteratee:mi(n,3),type:r}),t.__filtered__=t.__filtered__||e,t}}),r(["head","last"],function(n,t){
var r="take"+(t?"Right":"");Ct.prototype[n]=function(){return this[r](1).value()[0]}}),r(["initial","tail"],function(n,t){var r="drop"+(t?"":"Right");Ct.prototype[n]=function(){return this.__filtered__?new Ct(this):this[r](1)}}),Ct.prototype.compact=function(){return this.filter(La)},Ct.prototype.find=function(n){return this.filter(n).head()},Ct.prototype.findLast=function(n){return this.reverse().find(n)},Ct.prototype.invokeMap=uu(function(n,t){return"function"==typeof n?new Ct(this):this.map(function(r){
return Ie(r,n,t)})}),Ct.prototype.reject=function(n){return this.filter(Uf(mi(n)))},Ct.prototype.slice=function(n,t){n=kc(n);var r=this;return r.__filtered__&&(n>0||t<0)?new Ct(r):(n<0?r=r.takeRight(-n):n&&(r=r.drop(n)),t!==X&&(t=kc(t),r=t<0?r.dropRight(-t):r.take(t-n)),r)},Ct.prototype.takeRightWhile=function(n){return this.reverse().takeWhile(n).reverse()},Ct.prototype.toArray=function(){return this.take(Un)},ue(Ct.prototype,function(n,t){var r=/^(?:filter|find|map|reject)|While$/.test(t),e=/^(?:head|last)$/.test(t),u=Z[e?"take"+("last"==t?"Right":""):t],i=e||/^find/.test(t);
u&&(Z.prototype[t]=function(){var t=this.__wrapped__,o=e?[1]:arguments,f=t instanceof Ct,c=o[0],l=f||bh(t),s=function(n){var t=u.apply(Z,a([n],o));return e&&h?t[0]:t};l&&r&&"function"==typeof c&&1!=c.length&&(f=l=!1);var h=this.__chain__,p=!!this.__actions__.length,_=i&&!h,v=f&&!p;if(!i&&l){t=v?t:new Ct(this);var g=n.apply(t,o);return g.__actions__.push({func:nf,args:[s],thisArg:X}),new Y(g,h)}return _&&v?n.apply(this,o):(g=this.thru(s),_?e?g.value()[0]:g.value():g)})}),r(["pop","push","shift","sort","splice","unshift"],function(n){
var t=_l[n],r=/^(?:push|sort|unshift)$/.test(n)?"tap":"thru",e=/^(?:pop|shift)$/.test(n);Z.prototype[n]=function(){var n=arguments;if(e&&!this.__chain__){var u=this.value();return t.apply(bh(u)?u:[],n)}return this[r](function(r){return t.apply(bh(r)?r:[],n)})}}),ue(Ct.prototype,function(n,t){var r=Z[t];if(r){var e=r.name+"";bl.call(fs,e)||(fs[e]=[]),fs[e].push({name:t,func:r})}}),fs[Qu(X,vn).name]=[{name:"wrapper",func:X}],Ct.prototype.clone=$t,Ct.prototype.reverse=Yt,Ct.prototype.value=Qt,Z.prototype.at=Qs,
Z.prototype.chain=tf,Z.prototype.commit=rf,Z.prototype.next=ef,Z.prototype.plant=of,Z.prototype.reverse=ff,Z.prototype.toJSON=Z.prototype.valueOf=Z.prototype.value=cf,Z.prototype.first=Z.prototype.head,Ul&&(Z.prototype[Ul]=uf),Z},be=de();"function"==typeof define&&"object"==typeof define.amd&&define.amd?(re._=be,define(function(){return be})):ue?((ue.exports=be)._=be,ee._=be):re._=be}).call(this);
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+95
View File
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+1
View File
@@ -0,0 +1 @@
!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports,require("@antv/x6")):"function"==typeof define&&define.amd?define(["exports","@antv/x6"],e):e((t="undefined"!=typeof globalThis?globalThis:t||self).X6PluginClipboard={},t.X6)}(this,(function(t,e){"use strict";class i{constructor(){this.cells=[]}copy(t,i,s={}){this.options=Object.assign({},s);const o=(e.Model.isModel(i)?i:i.model).cloneSubGraph(t,s);this.cells=e.ArrayExt.sortBy(Object.keys(o).map((t=>o[t])),(t=>t.isEdge()?2:1)),this.serialize(s)}cut(t,i,s={}){this.copy(t,i,s);(e.Graph.isGraph(i)?i.model:i).batchUpdate("cut",(()=>{t.forEach((t=>t.remove()))}))}paste(t,i={}){const s=Object.assign(Object.assign({},this.options),i),{offset:o,edgeProps:n,nodeProps:l}=s;let r=20,a=20;o&&(r="number"==typeof o?o:o.dx,a="number"==typeof o?o:o.dy),this.deserialize(s);const c=this.cells;c.forEach((t=>{t.model=null,t.removeProp("zIndex"),(r||a)&&t.translate(r,a),l&&t.isNode()&&t.prop(l),n&&t.isEdge()&&t.prop(n)}));const p=e.Graph.isGraph(t)?t.model:t;return p.batchUpdate("paste",(()=>{p.addCells(this.cells)})),this.copy(c,t,i),c}serialize(t){!1!==t.useLocalStorage&&s.save(this.cells)}deserialize(t){if(t.useLocalStorage){const t=s.fetch();t&&(this.cells=t)}}isEmpty(t={}){return t.useLocalStorage&&this.deserialize(t),this.cells.length<=0}clean(){this.options={},this.cells=[],s.clean()}}var s;!function(t){const i=`${e.Config.prefixCls}.clipboard.cells`;t.save=function(t){if(window.localStorage){const e=t.map((t=>t.toJSON()));localStorage.setItem(i,JSON.stringify(e))}},t.fetch=function(){if(window.localStorage){const t=localStorage.getItem(i),s=t?JSON.parse(t):[];if(s)return e.Model.fromJSON(s)}},t.clean=function(){window.localStorage&&localStorage.removeItem(i)}}(s||(s={})),e.Graph.prototype.isClipboardEnabled=function(){const t=this.getPlugin("clipboard");return!!t&&t.isEnabled()},e.Graph.prototype.enableClipboard=function(){const t=this.getPlugin("clipboard");return t&&t.enable(),this},e.Graph.prototype.disableClipboard=function(){const t=this.getPlugin("clipboard");return t&&t.disable(),this},e.Graph.prototype.toggleClipboard=function(t){const e=this.getPlugin("clipboard");return e&&e.toggleEnabled(t),this},e.Graph.prototype.isClipboardEmpty=function(t){const e=this.getPlugin("clipboard");return!e||e.isEmpty(t)},e.Graph.prototype.getCellsInClipboard=function(){const t=this.getPlugin("clipboard");return t?t.getCellsInClipboard():[]},e.Graph.prototype.cleanClipboard=function(){const t=this.getPlugin("clipboard");return t&&t.clean(),this},e.Graph.prototype.copy=function(t,e){const i=this.getPlugin("clipboard");return i&&i.copy(t,e),this},e.Graph.prototype.cut=function(t,e){const i=this.getPlugin("clipboard");return i&&i.cut(t,e),this},e.Graph.prototype.paste=function(t,e){const i=this.getPlugin("clipboard");return i?i.paste(t,e):[]};class o extends e.Basecoat{get disabled(){return!0!==this.options.enabled}get cells(){return this.clipboardImpl.cells}constructor(t={}){super(),this.name="clipboard",this.options=Object.assign({enabled:!0},t)}init(t){this.graph=t,this.clipboardImpl=new i,this.clipboardImpl.deserialize(this.options)}isEnabled(){return!this.disabled}enable(){this.disabled&&(this.options.enabled=!0)}disable(){this.disabled||(this.options.enabled=!1)}toggleEnabled(t){return null!=t?t!==this.isEnabled()&&(t?this.enable():this.disable()):this.isEnabled()?this.disable():this.enable(),this}isEmpty(t={}){return this.clipboardImpl.isEmpty(t)}getCellsInClipboard(){return this.cells}clean(t){return this.disabled&&!t||(this.clipboardImpl.clean(),this.notify("clipboard:changed",{cells:[]})),this}copy(t,e={}){return this.disabled||(this.clipboardImpl.copy(t,this.graph,Object.assign(Object.assign({},this.commonOptions),e)),this.notify("clipboard:changed",{cells:t})),this}cut(t,e={}){return this.disabled||(this.clipboardImpl.cut(t,this.graph,Object.assign(Object.assign({},this.commonOptions),e)),this.notify("clipboard:changed",{cells:t})),this}paste(t={},e=this.graph){return this.disabled?[]:this.clipboardImpl.paste(e,Object.assign(Object.assign({},this.commonOptions),t))}get commonOptions(){return function(t,e){var i={};for(var s in t)Object.prototype.hasOwnProperty.call(t,s)&&e.indexOf(s)<0&&(i[s]=t[s]);if(null!=t&&"function"==typeof Object.getOwnPropertySymbols){var o=0;for(s=Object.getOwnPropertySymbols(t);o<s.length;o++)e.indexOf(s[o])<0&&Object.prototype.propertyIsEnumerable.call(t,s[o])&&(i[s[o]]=t[s[o]])}return i}(this.options,["enabled"])}notify(t,e){this.trigger(t,e),this.graph.trigger(t,e)}dispose(){this.clean(!0),this.off()}}!function(t,e,i,s){var o,n=arguments.length,l=n<3?e:null===s?s=Object.getOwnPropertyDescriptor(e,i):s;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)l=Reflect.decorate(t,e,i,s);else for(var r=t.length-1;r>=0;r--)(o=t[r])&&(l=(n<3?o(l):n>3?o(e,i,l):o(e,i))||l);n>3&&l&&Object.defineProperty(e,i,l)}([e.Basecoat.dispose()],o.prototype,"dispose",null),t.Clipboard=o}));
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+17
View File
@@ -0,0 +1,17 @@
import { state } from '../state.js';
import { logger } from '../utils/logger.js';
/**
* fetchAssets - Fetches the complete asset and pack list from the server
*/
export async function fetchAssets() {
try {
const response = await fetch('/assets');
const data = await response.json();
state.assetsData = data.assets || [];
return data;
} catch (e) {
logger.critical("Failed to fetch assets:", e);
return { assets: [], packs: [] };
}
}
+110
View File
@@ -0,0 +1,110 @@
import { state } from '../state.js';
import { t } from '../i18n.js';
export const FIXED_ASSETS = [
{ id: 'fixed-group', type: 'group', label: 'Group Container', icon: 'group.png', is_img: true },
{ id: 'fixed-rect', type: 'rect', label: 'Rectangle', icon: 'far fa-square', is_img: false },
{ id: 'fixed-rounded-rect', type: 'rounded-rect', label: 'Rounded Rectangle', icon: 'fas fa-vector-square', is_img: false },
{ id: 'fixed-circle', type: 'circle', label: 'Circle', icon: 'far fa-circle', is_img: false },
{ id: 'fixed-text', type: 'text-box', label: 'Text Box', icon: 'fas fa-font', is_img: false },
{ id: 'fixed-label', type: 'label', label: 'Label', icon: 'fas fa-tag', is_img: false },
{ id: 'fixed-blank', type: 'blank', label: 'Blank Point (Invisible)', icon: 'fas fa-crosshairs', is_img: false, extra_style: 'opacity: 0.5;' },
{ id: 'fixed-dot', type: 'dot', label: 'Dot (Small visible point)', icon: 'fas fa-circle', is_img: false, extra_style: 'font-size: 6px;' },
{ id: 'fixed-ellipse', type: 'ellipse', label: 'Ellipse', icon: 'fas fa-egg', is_img: false, extra_style: 'transform: rotate(-45deg);' },
{ id: 'fixed-polyline', type: 'polyline', label: 'Polyline', icon: 'fas fa-chart-line', is_img: false },
{ id: 'fixed-browser', type: 'browser', label: 'Browser', icon: 'fas fa-window-maximize', is_img: false },
{ id: 'fixed-user', type: 'user', label: 'User', icon: 'fas fa-user', is_img: false },
{ id: 'fixed-admin', type: 'admin', label: 'Admin', icon: 'fas fa-user-shield', is_img: false },
{ id: 'fixed-triangle', type: 'triangle', label: 'Triangle', icon: 'fas fa-caret-up', is_img: false, extra_style: 'font-size: 22px; margin-top: -2px;' },
{ id: 'fixed-diamond', type: 'diamond', label: 'Diamond', icon: 'fas fa-square', is_img: false, extra_style: 'transform: rotate(45deg) scale(0.8);' },
{ id: 'fixed-parallelogram', type: 'parallelogram', label: 'Parallelogram', icon: 'fas fa-square', is_img: false, extra_style: 'transform: skewX(-20deg) scaleX(1.2);' },
{ id: 'fixed-cylinder', type: 'cylinder', label: 'Cylinder', icon: 'fas fa-database', is_img: false },
{ id: 'fixed-document', type: 'document', label: 'Document', icon: 'fas fa-file-alt', is_img: false },
{ id: 'fixed-manual-input', type: 'manual-input', label: 'Manual Input', icon: 'fas fa-keyboard', is_img: false },
{ id: 'fixed-table', type: 'table', label: 'Table', icon: 'fas fa-table', is_img: false },
{ id: 'fixed-rack', type: 'rack', label: 'Rack', icon: 'fas fa-columns', is_img: false },
{ id: 'fixed-hourglass', type: 'hourglass', label: 'Hourglass', icon: 'fas fa-hourglass-half', is_img: false },
{ id: 'fixed-arrow-up', type: 'arrow-up', label: 'Arrow Up', icon: 'fas fa-arrow-up', is_img: false },
{ id: 'fixed-arrow-down', type: 'arrow-down', label: 'Arrow Down', icon: 'fas fa-arrow-down', is_img: false },
{ id: 'fixed-arrow-left', type: 'arrow-left', label: 'Arrow Left', icon: 'fas fa-arrow-left', is_img: false },
{ id: 'fixed-arrow-right', type: 'arrow-right', label: 'Arrow Right', icon: 'fas fa-arrow-right', is_img: false },
{ id: 'fixed-rich-card', type: 'rich-card', label: t('rich_card') || 'Rich Text Card', icon: 'fas fa-address-card', is_img: false }
];
export function renderFixedSection(container) {
const fixedSection = document.createElement('div');
fixedSection.className = 'asset-category fixed-category';
const title = t('fixed_objects') || 'Fixed Objects';
fixedSection.innerHTML = `
<div class="category-header">
<span data-i18n="fixed_objects">${title}</span>
<i class="fas fa-chevron-down"></i>
</div>
<div class="category-collapsed-icon" title="${title}">
<i class="fas fa-layer-group" style="font-size: 20px; color: #64748b;"></i>
</div>
<div class="category-content">
<div class="asset-grid"></div>
</div>
<div class="category-divider" style="height: 1px; background: rgba(255,255,255,0.1); margin: 15px 10px;"></div>
`;
// Toggle Logic
const header = fixedSection.querySelector('.category-header');
header.addEventListener('click', () => {
if (!document.getElementById('sidebar').classList.contains('collapsed')) {
fixedSection.classList.toggle('active');
}
});
// Handle Sidebar Collapsed State (Flyout)
const collapsedIcon = fixedSection.querySelector('.category-collapsed-icon');
collapsedIcon.addEventListener('click', (e) => {
if (document.getElementById('sidebar').classList.contains('collapsed')) {
e.stopPropagation();
// Since we don't want to import renderFlyout here to avoid circular dependencies
// we'll dispatch a custom event or check if it's available globally (though not recommended)
// or just let assets.js handle it if we restructure.
// For now, let's trigger a click on a hidden flyout handler or use state.
const event = new CustomEvent('render-fixed-flyout', {
detail: {
container: fixedSection,
assets: FIXED_ASSETS,
meta: { id: 'fixed_objects', label: title }
}
});
document.dispatchEvent(event);
}
});
const grid = fixedSection.querySelector('.asset-grid');
FIXED_ASSETS.forEach(asset => {
const item = document.createElement('div');
item.className = 'asset-item';
item.draggable = true;
item.dataset.type = asset.type;
item.dataset.assetId = asset.id;
item.title = asset.label;
if (asset.is_img) {
item.innerHTML = `<img src="/static/assets/${asset.icon}" width="22" height="22" loading="lazy">`;
} else {
item.innerHTML = `<i class="${asset.icon}" style="font-size: 18px; color: #64748b; ${asset.extra_style || ''}"></i>`;
}
item.addEventListener('dragstart', (e) => {
e.dataTransfer.setData('assetId', asset.id);
state.assetMap[asset.id] = {
id: asset.id,
type: asset.type,
path: asset.is_img ? asset.icon : '',
label: asset.label
};
});
grid.appendChild(item);
});
container.appendChild(fixedSection);
}
+60
View File
@@ -0,0 +1,60 @@
import { state } from '../state.js';
import { t } from '../i18n.js';
import { fetchAssets } from './api.js';
import { renderLibrary, createAssetElement, renderFlyout } from './renderer.js';
import { renderPackSelector } from './selector.js';
import { initSearch } from './search.js';
import { renderFixedSection } from './fixed_objects.js';
import { logger } from '../utils/logger.js';
/**
* initAssets - Main initialization for the asset library sidebar
*/
export async function initAssets() {
try {
const data = await fetchAssets();
const library = document.querySelector('.asset-library');
if (!library) return;
// 1. Initial Header & Global UI
library.innerHTML = `
<div style="display: flex; justify-content: space-between; align-items: center; margin: 24px 16px 12px; border-bottom: 1px solid rgba(255,255,255,0.05); padding-bottom: 8px;">
<h3 style="margin:0; font-size: 10px; text-transform: uppercase; letter-spacing: 1.5px; color: var(--sub-text); font-weight: 800;">
${t('asset_library') || 'Asset Library'}
</h3>
<button id="manage-packs-btn" style="background:none; border:none; color: var(--sub-text); cursor:pointer; font-size: 12px; transition: color 0.2s;" title="Manage Packages">
<i class="fas fa-filter"></i>
</button>
</div>
`;
// 2. Setup Manage Packs Button
document.getElementById('manage-packs-btn').onclick = (e) => {
e.stopPropagation();
renderPackSelector(data.packs || []);
};
// 3. Initialize selection if empty
if (state.selectedPackIds.length === 0 && data.packs && data.packs.length > 0) {
state.selectedPackIds = data.packs.map(p => p.id);
localStorage.setItem('selectedPackIds', JSON.stringify(state.selectedPackIds));
}
// 4. Render Sections
renderFixedSection(library);
renderLibrary({ ...data, state }, library, renderPackSelector);
// 5. Handle Flyouts for Fixed/Custom Sections via Event
document.addEventListener('render-fixed-flyout', (e) => {
const { container, assets, meta } = e.detail;
renderFlyout(container, assets, meta);
});
initSearch();
} catch (e) {
logger.critical("Asset Initialization Error:", e);
}
}
export { createAssetElement, renderFlyout, renderPackSelector };
+197
View File
@@ -0,0 +1,197 @@
import { t } from '../i18n.js';
import { DEFAULTS } from '../constants.js';
/**
* createAssetElement - Creates a single asset item DOM element
* @param {Object} asset
* @returns {HTMLElement}
*/
export function createAssetElement(asset, compositeId = null) {
const item = document.createElement('div');
item.className = 'asset-item';
item.draggable = true;
item.dataset.type = asset.type || asset.id;
item.dataset.assetId = compositeId || asset.id;
item.title = asset.label;
// Support legacy 'path', new 'views.icon' or FontAwesome icon class
const isFontAwesome = asset.is_img === false || (!asset.path && !asset.views && asset.icon && asset.icon.includes('fa-'));
if (isFontAwesome) {
item.innerHTML = `
<i class="${asset.icon}" style="font-size: 18px; color: #64748b; ${asset.extra_style || ''}"></i>
<span>${t(asset.id) || asset.label || asset.id}</span>
`;
} else {
const iconPath = (asset.views && asset.views.icon) ? asset.views.icon : (asset.path || DEFAULTS.DEFAULT_ICON);
item.innerHTML = `
<img src="/static/assets/${iconPath}" width="24" height="24" loading="lazy">
<span>${t(asset.id) || asset.label || asset.id}</span>
`;
}
item.addEventListener('dragstart', (e) => {
e.dataTransfer.setData('assetId', item.dataset.assetId);
});
return item;
}
/**
* renderFlyout - Renders the floating category window when sidebar is collapsed
* @param {HTMLElement} container
* @param {Array} assets
* @param {Object} meta
*/
export function renderFlyout(container, assets, meta) {
document.querySelectorAll('.category-flyout').forEach(f => f.remove());
const flyout = document.createElement('div');
flyout.className = 'category-flyout glass-panel active';
const rect = container.getBoundingClientRect();
flyout.style.top = `${Math.max(10, Math.min(window.innerHeight - 400, rect.top))}px`;
flyout.style.left = '90px';
flyout.innerHTML = `
<div class="flyout-header">
<strong>${t(meta.id) || meta.name || meta.label}</strong>
<small>${assets.length} items</small>
</div>
<div class="flyout-content" style="max-height: 400px; overflow-y: auto;"></div>
`;
const content = flyout.querySelector('.flyout-content');
// Group by category for flyout as well
const groups = assets.reduce((acc, a) => {
const cat = a.category || 'Other';
if (!acc[cat]) acc[cat] = [];
acc[cat].push(a);
return acc;
}, {});
Object.keys(groups).sort().forEach(catName => {
if (Object.keys(groups).length > 1 || catName !== 'Other') {
const label = document.createElement('div');
label.className = 'asset-group-label';
label.textContent = catName;
content.appendChild(label);
}
const grid = document.createElement('div');
grid.className = 'asset-grid flyout-grid';
groups[catName].forEach(asset => grid.appendChild(createAssetElement(asset)));
content.appendChild(grid);
});
document.body.appendChild(flyout);
const closeFlyout = (e) => {
if (!flyout.contains(e.target)) {
flyout.remove();
document.removeEventListener('click', closeFlyout);
}
};
setTimeout(() => document.addEventListener('click', closeFlyout), 10);
}
/**
* renderLibrary - The main loop that renders the entire asset library
*/
export function renderLibrary(data, library, renderPackSelector) {
const { state } = data; // We expect state to be passed or accessible
const packs = data.packs || [];
const filteredPacks = packs.filter(p => state.selectedPackIds.includes(p.id));
// 1. Clear Library (except fixed categories and header)
const dynamicPacks = library.querySelectorAll('.asset-category:not(.fixed-category)');
dynamicPacks.forEach(p => p.remove());
// 2. Group Custom Assets by Pack -> Category
const packGroups = state.assetsData.reduce((acc, asset) => {
const packId = asset.pack_id || 'legacy';
if (packId !== 'legacy' && !state.selectedPackIds.includes(packId)) return acc;
const category = asset.category || 'Other';
if (!acc[packId]) acc[packId] = {};
if (!acc[packId][category]) acc[packId][category] = [];
acc[packId][category].push(asset);
return acc;
}, {});
// 3. Render each visible Pack
Object.keys(packGroups).forEach((packId, index) => {
const packMeta = packs.find(p => p.id === packId) || { id: packId, name: (packId === 'legacy' ? t('other_assets') : packId) };
const categories = packGroups[packId];
const allAssetsInPack = Object.values(categories).flat();
// Ensure proper path is set for pack-based assets
if (packId !== 'legacy') {
allAssetsInPack.forEach(asset => {
if (asset.views && asset.views.icon) {
const icon = asset.views.icon;
// Only prepend packs/ if not already present
if (!icon.startsWith('packs/')) {
asset.path = `packs/${packId}/${icon}`;
} else {
asset.path = icon;
}
}
});
}
const firstAsset = allAssetsInPack[0] || {};
const iconPath = (firstAsset.views && firstAsset.views.icon) ? firstAsset.views.icon : (firstAsset.path || DEFAULTS.DEFAULT_ICON);
const catContainer = document.createElement('div');
catContainer.className = `asset-category shadow-sm`;
const header = document.createElement('div');
header.className = 'category-header';
header.innerHTML = `<span>${packMeta.name || packMeta.id}</span><i class="fas fa-chevron-down"></i>`;
header.onclick = () => {
if (!document.getElementById('sidebar').classList.contains('collapsed')) {
catContainer.classList.toggle('active');
}
};
const collapsedIcon = document.createElement('div');
collapsedIcon.className = 'category-collapsed-icon';
collapsedIcon.title = packMeta.name || packMeta.id;
collapsedIcon.innerHTML = `<img src="/static/assets/${iconPath}" width="28" height="28">`;
collapsedIcon.onclick = (e) => {
if (document.getElementById('sidebar').classList.contains('collapsed')) {
e.stopPropagation();
renderFlyout(catContainer, allAssetsInPack, packMeta);
}
};
const content = document.createElement('div');
content.className = 'category-content';
// Render each Category within the Pack
Object.keys(categories).sort().forEach(catName => {
const assets = categories[catName];
if (Object.keys(categories).length > 1 || catName !== 'Other') {
const subHeader = document.createElement('div');
subHeader.className = 'asset-group-label';
subHeader.textContent = catName;
content.appendChild(subHeader);
}
const itemGrid = document.createElement('div');
itemGrid.className = 'asset-grid';
assets.forEach(asset => {
const compositeId = `${packId}|${asset.id}`;
state.assetMap[compositeId] = asset;
itemGrid.appendChild(createAssetElement(asset, compositeId));
});
content.appendChild(itemGrid);
});
catContainer.append(header, collapsedIcon, content);
library.appendChild(catContainer);
});
}
+35
View File
@@ -0,0 +1,35 @@
import { state } from '../state.js';
/**
* initSearch - Initializes the asset search input listener
*/
export function initSearch() {
const searchInput = document.getElementById('asset-search');
if (!searchInput) return;
searchInput.addEventListener('input', (e) => {
const query = e.target.value.toLowerCase().trim();
const categories = document.querySelectorAll('.asset-category');
categories.forEach(cat => {
const items = cat.querySelectorAll('.asset-item');
let hasVisibleItem = false;
items.forEach(item => {
const assetId = item.dataset.assetId;
const asset = state.assetMap[assetId];
if (!asset) return;
const matches = (asset.type && asset.type.toLowerCase().includes(query)) ||
(asset.label && asset.label.toLowerCase().includes(query)) ||
(asset.vendor && asset.vendor.toLowerCase().includes(query));
item.style.display = matches ? 'flex' : 'none';
if (matches) hasVisibleItem = true;
});
cat.style.display = (hasVisibleItem || query === '') ? 'block' : 'none';
if (query !== '' && hasVisibleItem) cat.classList.add('active');
});
});
}
+64
View File
@@ -0,0 +1,64 @@
import { state } from '../state.js';
import { t } from '../i18n.js';
/**
* renderPackSelector - Show a modal to enable/disable asset packages
*/
export function renderPackSelector(packs) {
let modal = document.getElementById('pack-selector-modal');
if (!modal) {
modal = document.createElement('div');
modal.id = 'pack-selector-modal';
modal.className = 'modal-overlay';
document.body.appendChild(modal);
}
const selectedIds = state.selectedPackIds;
modal.innerHTML = `
<div class="modal-content" style="width: 400px; max-height: 80vh; overflow-y: auto;">
<div class="modal-header">
<h3>${t('manage_packages') || 'Manage Packages'}</h3>
<i class="fas fa-times close-modal"></i>
</div>
<div class="modal-body" style="padding: 15px;">
<p style="font-size: 12px; color: #64748b; margin-bottom: 15px;">Select which asset packages to load in your sidebar.</p>
<div class="pack-list">
${packs.map(p => `
<div class="pack-item" style="display: flex; align-items: center; justify-content: space-between; padding: 10px; border-bottom: 1px solid rgba(255,255,255,0.05);">
<div style="display: flex; align-items: center; gap: 10px;">
<i class="fas fa-box" style="color: #38bdf8; font-size: 14px;"></i>
<span style="font-size: 13px; font-weight: 600;">${p.name || p.id}</span>
</div>
<input type="checkbox" data-id="${p.id}" ${selectedIds.includes(p.id) ? 'checked' : ''} style="width: 18px; height: 18px; cursor: pointer;">
</div>
`).join('')}
</div>
</div>
<div class="modal-footer" style="padding: 15px; border-top: 1px solid rgba(255,255,255,0.05); text-align: right;">
<button class="btn-primary apply-packs" style="background: #38bdf8; color: #0f172a; border: none; padding: 8px 16px; border-radius: 6px; font-weight: 700; cursor: pointer;">Apply & Refresh</button>
</div>
</div>
`;
modal.classList.add('active');
// Close handlers
modal.querySelector('.close-modal').onclick = () => modal.classList.remove('active');
modal.onclick = (e) => { if (e.target === modal) modal.classList.remove('active'); };
// Apply handler
modal.querySelector('.apply-packs').onclick = () => {
const checkboxes = modal.querySelectorAll('input[type="checkbox"]');
const newSelectedIds = Array.from(checkboxes)
.filter(cb => cb.checked)
.map(cb => cb.dataset.id);
state.selectedPackIds = newSelectedIds;
localStorage.setItem('selectedPackIds', JSON.stringify(newSelectedIds));
// This is a global refresh to re-init everything with new filters
// For a more seamless experience, we could re-call initAssets()
window.location.reload();
};
}
+29
View File
@@ -0,0 +1,29 @@
/**
* constants.js - Central repository for magic strings and app configuration
*/
// LocalStorage Keys
export const STORAGE_KEYS = {
SETTINGS: 'drawNET-settings',
THEME: 'drawNET-theme',
AUTOSAVE: 'drawNET_autosave',
LANGUAGE: 'drawNET_lang'
};
// Default Configuration
export const DEFAULTS = {
GRID_SPACING: 20,
GRID_COLOR: '#e2e8f0',
MAJOR_GRID_COLOR: '#cbd5e1',
MAJOR_GRID_INTERVAL: 5,
CANVAS_PRESET: 'A4',
CANVAS_ORIENTATION: 'portrait',
APP_VERSION: '2.0.0-pro',
DEFAULT_ICON: 'router.svg'
};
// UI Toggles & States
export const UI_STATES = {
QUAKE_COLLAPSED_HEIGHT: '40px',
QUAKE_EXPANDED_HEIGHT: '300px'
};
+34
View File
@@ -0,0 +1,34 @@
/**
* graph.js - Main Entry for AntV X6 Graph Module
* Modularized version splitting styles, events, interactions, and IO.
*/
import { state } from './state.js';
import { registerCustomShapes } from './graph/styles.js';
import { initGraphEvents } from './graph/events/index.js';
import { initInteractions } from './graph/interactions/index.js';
import { initGraphIO } from './graph/io/index.js';
import { initPropertiesSidebar } from './properties_sidebar/index.js';
import { initContextMenu } from './ui/context_menu/index.js';
import { getGraphConfig } from './graph/config.js';
import { initGraphPlugins } from './graph/plugins.js';
import { logger } from './utils/logger.js';
export function initGraph() {
const container = document.getElementById('graph-container');
if (!container) return;
// 1. Register Custom Shapes
registerCustomShapes();
// 2. Initialize AntV X6 Graph Instance
state.graph = new X6.Graph(getGraphConfig(container));
// 3. Enable Plugins
initGraphPlugins(state.graph);
// 4. Initialize Sub-modules
initGraphEvents();
initInteractions();
logger.high("AntV X6 Graph initialized with modules.");
}
+139
View File
@@ -0,0 +1,139 @@
import { state } from '../state.js';
import { logger } from '../utils/logger.js';
/**
* Alignment and Distribution tools for drawNET (X6 version).
*/
/**
* alignNodes - Aligns selected nodes based on the FIRST selected node
* @param {'top'|'bottom'|'left'|'right'|'middle'|'center'} type
*/
export function alignNodes(type) {
if (!state.graph) return;
const selected = state.graph.getSelectedCells().filter(c => c.isNode());
if (selected.length < 2) return;
// First selected object is the reference per user request
const reference = selected[0];
const refPos = reference.getPosition();
const refSize = reference.getSize();
selected.slice(1).forEach(node => {
const pos = node.getPosition();
const size = node.getSize();
switch (type) {
case 'top':
node.setPosition(pos.x, refPos.y);
break;
case 'bottom':
node.setPosition(pos.x, refPos.y + refSize.height - size.height);
break;
case 'left':
node.setPosition(refPos.x, pos.y);
break;
case 'right':
node.setPosition(refPos.x + refSize.width - size.width, pos.y);
break;
case 'middle':
node.setPosition(pos.x, refPos.y + (refSize.height / 2) - (size.height / 2));
break;
case 'center':
node.setPosition(refPos.x + (refSize.width / 2) - (size.width / 2), pos.y);
break;
}
});
notifyChanges();
logger.info(`drawNET: Aligned ${selected.length} nodes (${type}).`);
}
/**
* moveNodes - Moves selected nodes by dx, dy
*/
export function moveNodes(dx, dy) {
if (!state.graph) return;
const selected = state.graph.getSelectedCells().filter(c => c.isNode());
if (selected.length === 0) return;
selected.forEach(node => {
const pos = node.getPosition();
node.setPosition(pos.x + dx, pos.y + dy);
});
// Sync with persistence after move (with debounce)
clearTimeout(state.moveSyncTimer);
state.moveSyncTimer = setTimeout(() => {
notifyChanges();
}, 500);
}
export function distributeNodes(type) {
if (!state.graph) return;
const selected = state.graph.getSelectedCells().filter(c => c.isNode());
if (selected.length < 3) return;
const bboxes = selected.map(node => ({
node,
bbox: node.getBBox()
}));
if (type === 'horizontal') {
// Sort nodes from left to right
bboxes.sort((a, b) => a.bbox.x - b.bbox.x);
const first = bboxes[0];
const last = bboxes[bboxes.length - 1];
// Calculate Total Span (Right edge of last - Left edge of first)
const totalSpan = (last.bbox.x + last.bbox.width) - first.bbox.x;
// Calculate Sum of Node Widths
const sumWidths = bboxes.reduce((sum, b) => sum + b.bbox.width, 0);
// Total Gap Space
const totalGapSpace = totalSpan - sumWidths;
if (totalGapSpace < 0) return; // Overlapping too much? Skip for now
const gapSize = totalGapSpace / (bboxes.length - 1);
let currentX = first.bbox.x;
bboxes.forEach((b, i) => {
if (i > 0) {
currentX += bboxes[i-1].bbox.width + gapSize;
b.node.setPosition(currentX, b.bbox.y);
}
});
} else if (type === 'vertical') {
// Sort nodes from top to bottom
bboxes.sort((a, b) => a.bbox.y - b.bbox.y);
const first = bboxes[0];
const last = bboxes[bboxes.length - 1];
const totalSpan = (last.bbox.y + last.bbox.height) - first.bbox.y;
const sumHeights = bboxes.reduce((sum, b) => sum + b.bbox.height, 0);
const totalGapSpace = totalSpan - sumHeights;
if (totalGapSpace < 0) return;
const gapSize = totalGapSpace / (bboxes.length - 1);
let currentY = first.bbox.y;
bboxes.forEach((b, i) => {
if (i > 0) {
currentY += bboxes[i-1].bbox.height + gapSize;
b.node.setPosition(b.bbox.x, currentY);
}
});
}
notifyChanges();
}
/**
* notifyChanges - Marks dirty for persistence
*/
function notifyChanges() {
import('/static/js/modules/persistence.js').then(m => m.markDirty());
}
+167
View File
@@ -0,0 +1,167 @@
import { state } from '../state.js';
import { logger } from '../utils/logger.js';
import { t } from '../i18n.js';
import { makeDraggable } from '../ui/utils.js';
/**
* initInventory - Initializes the real-time inventory counting panel
*/
export function initInventory() {
const inventoryPanel = document.getElementById('inventory-panel');
const inventoryList = document.getElementById('inventory-list');
if (!inventoryPanel || !inventoryList) return;
// Make Draggable
makeDraggable(inventoryPanel, '.inventory-header');
// Initial update
updateInventory(inventoryList);
// Listen for graph changes
if (state.graph) {
state.graph.on('node:added', () => updateInventory(inventoryList));
state.graph.on('node:removed', () => updateInventory(inventoryList));
state.graph.on('cell:changed', ({ cell }) => {
if (cell.isNode()) updateInventory(inventoryList);
});
// project:restored 이벤트 수신 (복구 시점)
state.graph.on('project:restored', () => {
logger.info("Project restored. Updating inventory.");
updateInventory(inventoryList);
});
}
}
/**
* toggleInventory - Toggles the visibility of the inventory panel
*/
export function toggleInventory() {
const panel = document.getElementById('inventory-panel');
if (!panel) return;
// Use getComputedStyle for more reliable check
const currentDisplay = window.getComputedStyle(panel).display;
if (currentDisplay === 'none') {
panel.style.display = 'flex';
panel.classList.add('animate-up');
} else {
panel.style.display = 'none';
}
}
/**
* updateInventory - Aggregates node counts by type and updates the UI
*/
export function updateInventory(container) {
if (!state.graph) return;
// Use default container if not provided
if (!container) {
container = document.getElementById('inventory-list');
}
if (!container) return;
const nodes = state.graph.getNodes();
const counts = {};
nodes.forEach(node => {
const data = node.getData() || {};
const type = data.type || 'Unknown';
counts[type] = (counts[type] || 0) + 1;
});
// Render list
container.innerHTML = '';
const sortedTypes = Object.keys(counts).sort();
if (sortedTypes.length === 0) {
container.innerHTML = `<div style="font-size: 10px; color: #94a3b8; text-align: center; margin-top: 10px;">${t('no_objects_found') || 'No objects found'}</div>`;
return;
}
sortedTypes.forEach(type => {
const item = document.createElement('div');
item.className = 'inventory-item';
const displayType = t(type.toLowerCase()) || type;
item.innerHTML = `
<span class="lbl">${displayType}</span>
<span class="val">${counts[type]}</span>
`;
container.appendChild(item);
});
// BOM 내보내기 버튼 추가 (푸터)
let footer = document.querySelector('.inventory-footer');
if (!footer) {
footer = document.createElement('div');
footer.className = 'inventory-footer';
}
footer.innerHTML = `
<button id="btn-export-bom" class="btn-export-bom">
<i class="fas fa-file-excel"></i>
<span>${t('export_bom') || 'Export BOM (Excel)'}</span>
</button>
`;
container.appendChild(footer);
const btn = document.getElementById('btn-export-bom');
if (btn) btn.onclick = downloadBOM;
}
/**
* downloadBOM - 가시화된 모든 노드 정보를 엑셀/CSV 형태로 추출
*/
function downloadBOM() {
if (!state.graph) return;
const nodes = state.graph.getNodes();
if (nodes.length === 0) return;
// 헤더 정의
const headers = [
t('prop_id'), t('display_name'), t('prop_type'),
t('prop_vendor'), t('prop_model'), t('prop_ip'),
t('prop_status'), t('prop_asset_tag'), t('prop_project'), t('prop_env')
];
// 데이터 행 생성
const rows = nodes.map(node => {
const data = node.getData() || {};
const label = node.attr('label/text') || '';
return [
node.id,
label,
data.type || '',
data.vendor || '',
data.model || '',
data.ip || '',
data.status || '',
data.asset_tag || '',
data.project || '',
data.env || ''
].map(val => `"${String(val).replace(/"/g, '""')}"`); // CSV 이스케이프
});
// CSV 문자열 합치기
const csvContent = "\uFEFF" + // UTF-8 BOM for Excel kor
headers.join(',') + "\n" +
rows.map(r => r.join(',')).join('\n');
// 다운로드 트리거
const blob = new Blob([csvContent], { type: 'text/csv;charset=utf-8;' });
const url = URL.createObjectURL(blob);
const link = document.createElement("a");
const timestamp = new Date().toISOString().replace(/[:.]/g, '-').slice(0, 19);
link.setAttribute("href", url);
link.setAttribute("download", `drawNET_BOM_${timestamp}.csv`);
link.style.visibility = 'hidden';
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
logger.info("BOM exported successfully.");
}
+125
View File
@@ -0,0 +1,125 @@
import { DEFAULTS } from '../constants.js';
import { state } from '../state.js';
import { calculateCellZIndex } from './layers.js';
/**
* graph/config.js - X6 Graph configuration options
*/
export const getGraphConfig = (container) => ({
// ... (rest of the top part)
container: container,
autoResize: true,
background: { color: document.documentElement.getAttribute('data-theme') === 'dark' ? '#1e293b' : '#f8fafc' },
grid: {
visible: true,
type: 'dot',
size: DEFAULTS.GRID_SPACING,
args: { color: DEFAULTS.GRID_COLOR, thickness: 1 },
},
panning: {
enabled: true,
modifiers: 'space',
},
history: {
enabled: true,
},
mousewheel: {
enabled: true,
modifiers: ['ctrl', 'meta'],
factor: state.appConfig?.mousewheel?.factor || 1.05,
minScale: state.appConfig?.mousewheel?.minScale || 0.1,
maxScale: state.appConfig?.mousewheel?.maxScale || 10,
},
connecting: {
router: null,
connector: { name: 'jumpover', args: { type: 'arc', size: 6 } },
anchor: 'orth',
connectionPoint: 'boundary',
allowNode: false,
allowBlank: false,
snap: { radius: 20 },
createEdge() {
const edgeData = {
layerId: state.activeLayerId || 'l1',
routing_offset: 20,
direction: 'none',
description: "",
asset_tag: ""
};
return new X6.Shape.Edge({
attrs: {
line: {
stroke: '#94a3b8',
strokeWidth: 2,
targetMarker: null
},
},
zIndex: calculateCellZIndex(edgeData, 0, false),
data: edgeData
})
},
validateConnection({ sourceMagnet, targetMagnet }) {
return !!sourceMagnet && !!targetMagnet;
},
highlight: true,
},
embedding: {
enabled: true,
findParent({ node }) {
const bbox = node.getBBox();
const candidates = this.getNodes().filter((n) => {
const data = n.getData();
if (data && data.is_group && n.id !== node.id) {
const targetBBox = n.getBBox();
return targetBBox.containsRect(bbox);
}
return false;
});
if (candidates.length === 0) return [];
if (candidates.length === 1) return [candidates[0]];
// Return the one with the smallest area (the innermost one)
const bestParent = candidates.reduce((smallest, current) => {
const smallestBBox = smallest.getBBox();
const currentBBox = current.getBBox();
const currentArea = currentBBox.width * currentBBox.height;
const smallestArea = smallestBBox.width * smallestBBox.height;
if (currentArea < smallestArea) return current;
if (currentArea > smallestArea) return smallest;
// If areas are equal, pick the one that is a descendant of the other
if (current.getAncestors().some(a => a.id === smallest.id)) return current;
return smallest;
});
return [bestParent];
},
validate({ child, parent }) {
return parent.getData()?.is_group;
},
},
interacting: {
nodeMovable: (view) => {
if (state.isCtrlPressed) return false; // Block default move during Ctrl+Drag
return view.cell.getProp('movable') !== false;
},
edgeMovable: (view) => {
if (state.isCtrlPressed) return false;
return view.cell.getProp('movable') !== false;
},
edgeLabelMovable: (view) => view.cell.getProp('movable') !== false,
arrowheadMovable: (view) => view.cell.getProp('movable') !== false,
vertexMovable: (view) => view.cell.getProp('movable') !== false,
vertexAddable: (view) => {
if (view.cell.getProp('movable') === false) return false;
// Only allow adding vertices if the edge is ALREADY selected.
// This prevents accidental addition on the first click (which selects the edge).
return view.graph.isSelected(view.cell);
},
vertexDeletable: (view) => view.cell.getProp('movable') !== false,
},
});
+18
View File
@@ -0,0 +1,18 @@
import { initSystemEvents } from './system.js';
import { initViewportEvents } from './viewport.js';
import { initSelectionEvents } from './selection.js';
import { initNodeEvents } from './nodes.js';
import { initRoutingEvents } from './routing.js';
export { updateGridBackground } from './system.js';
/**
* initGraphEvents - Orchestrates the initialization of all specialized event modules.
*/
export function initGraphEvents() {
initSystemEvents();
initViewportEvents();
initSelectionEvents();
initNodeEvents();
initRoutingEvents();
}
+98
View File
@@ -0,0 +1,98 @@
import { state } from '../../state.js';
import { generateRackUnitsPath } from '../styles/utils.js';
export function initNodeEvents() {
if (!state.graph) return;
// Hover Guides for specific objects
state.graph.on('node:mouseenter', ({ node }) => {
if (node.shape === 'drawnet-dot') {
node.attr('hit/stroke', 'rgba(59, 130, 246, 0.4)');
node.attr('hit/strokeDasharray', '2,2');
}
});
state.graph.on('node:mouseleave', ({ node }) => {
if (node.shape === 'drawnet-dot') {
node.attr('hit/stroke', 'transparent');
node.attr('hit/strokeDasharray', '0');
}
});
// Rack Drill Down Interaction
state.graph.on('node:dblclick', ({ node }) => {
const data = node.getData() || {};
if (data.layerId !== state.activeLayerId) return; // Guard: Block drills into other layers
if (node.shape === 'drawnet-rack') {
state.graph.zoomToCell(node, {
padding: { top: 60, bottom: 60, left: 100, right: 100 },
animation: { duration: 600 }
});
state.graph.getCells().forEach(cell => {
if (cell.id !== node.id && !node.getDescendants().some(d => d.id === cell.id)) {
cell.setAttrs({ body: { opacity: 0.1 }, image: { opacity: 0.1 }, label: { opacity: 0.1 }, line: { opacity: 0.1 } });
} else {
cell.setAttrs({ body: { opacity: 1 }, image: { opacity: 1 }, label: { opacity: 1 }, line: { opacity: 1 } });
}
});
showBackToTopBtn();
}
});
// Parent/Structural Changes
state.graph.on('node:change:parent', ({ node, current }) => {
const parentId = current || null;
const currentData = node.getData() || {};
node.setData({ ...currentData, parent: parentId });
import('../layers.js').then(m => m.applyLayerFilters());
import('/static/js/modules/properties_sidebar/index.js').then(m => m.renderProperties());
import('/static/js/modules/persistence.js').then(m => m.markDirty());
});
// Data Syncing (Rack-specific)
state.graph.on('node:change:data', ({ node, current }) => {
if (node.shape === 'drawnet-rack') {
const slots = current.slots || 42;
const bbox = node.getBBox();
node.attr('units/d', generateRackUnitsPath(bbox.height, slots));
if (!current.label || current.label.startsWith('Rack (')) {
node.attr('label/text', `Rack (${slots}U)`);
}
}
// Rich Card Content Refresh on Data Change
if (node.shape === 'drawnet-rich-card') {
import('../styles/utils.js').then(m => m.renderRichContent(node));
}
});
}
function showBackToTopBtn() {
let btn = document.getElementById('rack-back-btn');
if (btn) btn.remove();
btn = document.createElement('div');
btn.id = 'rack-back-btn';
btn.innerHTML = '<i class="fas fa-arrow-left"></i> Back to Topology';
btn.style.cssText = `
position: absolute; top: 100px; left: 300px; z-index: 1000;
padding: 10px 20px; background: #3b82f6; color: white;
border-radius: 8px; cursor: pointer; font-weight: bold;
box-shadow: 0 4px 12px rgba(0,0,0,0.2); transition: all 0.2s;
`;
btn.onclick = () => {
state.graph.zoomToFit({ padding: 100, animation: { duration: 500 } });
state.graph.getCells().forEach(cell => {
cell.setAttrs({ body: { opacity: 1 }, image: { opacity: 1 }, label: { opacity: 1 }, line: { opacity: 1 } });
});
btn.remove();
};
document.getElementById('graph-container').parentElement.appendChild(btn);
}
+60
View File
@@ -0,0 +1,60 @@
import { state } from '../../state.js';
import { logger } from '../../utils/logger.js';
export function initRoutingEvents() {
if (!state.graph) return;
// Re-evaluate routing when nodes are moved to handle adaptive fallback (Phase 1.18)
state.graph.on('node:change:position', ({ node }) => {
const edges = state.graph.getConnectedEdges(node);
if (edges.length === 0) return;
import('/static/js/modules/graph/styles.js').then(({ getX6EdgeConfig }) => {
edges.forEach(edge => {
const data = edge.getData() || {};
const config = getX6EdgeConfig({
source: edge.getSource().cell,
target: edge.getTarget().cell,
...data
});
if (config.router !== edge.getRouter()) {
edge.setRouter(config.router || null);
logger.info(`drawNET: Dynamic Routing Update for ${edge.id}`);
}
if (config.connector !== edge.getConnector()) {
edge.setConnector(config.connector);
}
// Sync physical connections during move (especially for manual anchors)
if (config.source) edge.setSource(config.source);
if (config.target) edge.setTarget(config.target);
});
});
});
// Unify styling when an edge is newly connected via mouse (Phase 1.19)
state.graph.on('edge:connected', ({ edge }) => {
if (!edge || !edge.isEdge()) return;
import('/static/js/modules/graph/styles.js').then(({ getX6EdgeConfig }) => {
const data = edge.getData() || {};
const config = getX6EdgeConfig({
source: edge.getSource().cell,
target: edge.getTarget().cell,
...data
});
// Apply official style & configuration
if (config.source) edge.setSource(config.source);
if (config.target) edge.setTarget(config.target);
edge.setRouter(config.router || null);
edge.setConnector(config.connector);
edge.setZIndex(config.zIndex || 5);
if (config.attrs) {
edge.setAttrs(config.attrs);
}
logger.info(`drawNET: Unified Style applied to new edge ${edge.id}`);
});
});
}
@@ -0,0 +1,55 @@
import { state } from '../../state.js';
export function initSelectionEvents() {
if (!state.graph) return;
state.graph.on('cell:selected', ({ cell }) => {
if (cell.isNode()) {
if (!state.selectionOrder.includes(cell.id)) {
state.selectionOrder.push(cell.id);
}
} else if (cell.isEdge()) {
// Add vertices tool for manual routing control (unless locked)
if (!cell.getData()?.locked) {
cell.addTools([{ name: 'vertices' }]);
}
// ADD S/T labels for clear identification of Start and Target
const currentLabels = cell.getLabels() || [];
cell.setLabels([
...currentLabels,
{ id: 'selection-source-label', position: { distance: 0.05 }, attrs: { text: { text: 'S', fill: '#10b981', fontSize: 10, fontWeight: 'bold' }, rect: { fill: '#ffffff', stroke: '#10b981', strokeWidth: 1, rx: 2, ry: 2 } } },
{ id: 'selection-target-label', position: { distance: 0.95 }, attrs: { text: { text: 'T', fill: '#ef4444', fontSize: 10, fontWeight: 'bold' }, rect: { fill: '#ffffff', stroke: '#ef4444', strokeWidth: 1, rx: 2, ry: 2 } } }
]);
}
});
state.graph.on('cell:unselected', ({ cell }) => {
const isLocked = cell.getData()?.locked;
if (cell.isEdge()) {
if (!isLocked) {
cell.removeTools();
} else {
// Keep boundary if locked, but remove selection-only tools if any
cell.removeTools(['vertices']);
}
// Remove selection labels safely
const labels = cell.getLabels() || [];
const filteredLabels = labels.filter(l =>
l.id !== 'selection-source-label' && l.id !== 'selection-target-label'
);
cell.setLabels(filteredLabels);
} else if (cell.isNode()) {
if (!isLocked) {
cell.removeTools();
}
}
state.selectionOrder = state.selectionOrder.filter(id => id !== cell.id);
});
state.graph.on('blank:click', () => {
state.selectionOrder = [];
});
}
+125
View File
@@ -0,0 +1,125 @@
import { state } from '../../state.js';
import { updateGraphTheme } from '../styles.js';
import { DEFAULTS } from '../../constants.js';
export function initSystemEvents() {
if (!state.graph) return;
// Theme changes
window.addEventListener('themeChanged', () => {
updateGraphTheme();
const isDark = document.documentElement.getAttribute('data-theme') === 'dark';
state.graph.drawBackground({ color: isDark ? '#1e293b' : '#f8fafc' });
});
// Canvas resize event
window.addEventListener('canvasResize', (e) => {
const { width, height } = e.detail;
state.canvasSize = { width, height };
const container = document.getElementById('graph-container');
if (width === '100%') {
container.style.width = '100%';
container.style.height = '100%';
container.style.boxShadow = 'none';
container.style.margin = '0';
state.graph.resize();
} else {
container.style.width = `${width}px`;
container.style.height = `${height}px`;
container.style.boxShadow = '0 10px 30px rgba(0,0,0,0.1)';
container.style.margin = '40px auto';
container.style.backgroundColor = '#fff';
state.graph.resize(width, height);
}
});
// Grid type change
window.addEventListener('gridChanged', (e) => {
state.gridStyle = e.detail.style;
if (!state.graph) return;
if (e.detail.style === 'none') {
state.graph.hideGrid();
state.isSnapEnabled = false;
} else {
state.graph.showGrid();
state.isSnapEnabled = true;
if (e.detail.showMajor) {
state.graph.drawGrid({
type: 'doubleMesh',
args: [
{
color: e.detail.majorColor || DEFAULTS.MAJOR_GRID_COLOR,
thickness: (e.detail.thickness || 1) * 1.5,
factor: e.detail.majorInterval || DEFAULTS.MAJOR_GRID_INTERVAL
},
{
color: e.detail.color || DEFAULTS.GRID_COLOR,
thickness: e.detail.thickness || 1
},
],
});
} else {
const gridType = e.detail.style === 'solid' ? 'mesh' : (e.detail.style === 'dashed' ? 'doubleMesh' : 'dot');
state.graph.drawGrid({
type: gridType,
args: [
{
color: e.detail.color || DEFAULTS.GRID_COLOR,
thickness: e.detail.thickness || 1
},
],
});
}
state.graph.setGridSize(state.gridSpacing || DEFAULTS.GRID_SPACING);
}
});
// Grid spacing change
window.addEventListener('gridSpacingChanged', (e) => {
state.gridSpacing = e.detail.spacing;
if (state.graph) {
state.graph.setGridSize(state.gridSpacing);
}
});
// Global Data Sanitizer & Enforcer (Ensures all objects have latest schema defaults)
// This handles all creation paths: Drag-and-Drop, Copy-Paste, Grouping, and programatic addEdge.
state.graph.on('cell:added', ({ cell }) => {
const data = cell.getData() || {};
let updated = false;
// 1. Common Fields for all Node/Edge objects
if (data.description === undefined) { data.description = ""; updated = true; }
if (data.asset_tag === undefined) { data.asset_tag = ""; updated = true; }
if (!data.tags) { data.tags = []; updated = true; }
if (data.locked === undefined) { data.locked = false; updated = true; }
// 2. Ensure label_pos exists to prevent display reset
if (data.label_pos === undefined) {
data.label_pos = data.is_group ? 'top' : (['rect', 'circle', 'rounded-rect', 'text-box', 'label'].includes((data.type || '').toLowerCase()) ? 'center' : 'bottom');
updated = true;
}
// 3. Edge Specific Defaults
if (cell.isEdge()) {
if (data.routing_offset === undefined) { data.routing_offset = 20; updated = true; }
}
if (updated) {
// Use silent: true to prevent triggering another 'cell:added' if someone is listening to data changes
cell.setData(data, { silent: true });
}
// Keep existing layer logic
import('../layers.js').then(m => m.applyLayerFilters());
});
}
export function updateGridBackground() {
if (!state.graph) return;
state.graph.setGridSize(state.gridSpacing || DEFAULTS.GRID_SPACING);
state.graph.showGrid();
}
@@ -0,0 +1,80 @@
import { state } from '../../state.js';
let isRightDragging = false;
let startX = 0;
let startY = 0;
const threshold = 5;
/**
* Handle mousedown on the graph to initialize right-click panning.
*/
const handleGraphMouseDown = ({ e }) => {
if (e.button === 2) { // Right Click
isRightDragging = false;
startX = e.clientX;
startY = e.clientY;
state.isRightDragging = false;
}
};
/**
* Global event handler for mousemove to support panning.
* Registered only once on document level.
*/
const onMouseMove = (e) => {
if (e.buttons === 2 && state.graph) {
const dx = e.clientX - startX;
const dy = e.clientY - startY;
// Detect dragging start (beyond threshold)
if (!isRightDragging && (Math.abs(dx) > threshold || Math.abs(dy) > threshold)) {
isRightDragging = true;
state.isRightDragging = true;
// Sync start positions to current mouse position to avoid the initial jump
startX = e.clientX;
startY = e.clientY;
return;
}
if (isRightDragging) {
state.graph.translateBy(dx, dy);
startX = e.clientX;
startY = e.clientY;
}
}
};
/**
* Global event handler for mouseup to finish panning.
* Registered only once on document level.
*/
const onMouseUp = () => {
if (isRightDragging) {
// Reset after a short delay to allow contextmenu event to check the flag
setTimeout(() => {
state.isRightDragging = false;
isRightDragging = false;
}, 100);
}
};
/**
* Initializes viewport-related events for the current graph instance.
* Should be called whenever a new graph is created.
*/
export function initViewportEvents() {
if (!state.graph) return;
// Attach to the specific graph instance, ensuring no duplicates
state.graph.off('blank:mousedown', handleGraphMouseDown);
state.graph.on('blank:mousedown', handleGraphMouseDown);
state.graph.off('cell:mousedown', handleGraphMouseDown);
state.graph.on('cell:mousedown', handleGraphMouseDown);
// Register document-level listeners only once per page session
if (!window._drawNetViewportEventsInitialized) {
document.addEventListener('mousemove', onMouseMove);
document.addEventListener('mouseup', onMouseUp);
window._drawNetViewportEventsInitialized = true;
}
}
@@ -0,0 +1,95 @@
import { state } from '../../state.js';
import { logger } from '../../utils/logger.js';
import { t } from '../../i18n.js';
import { getX6NodeConfig } from '../styles.js';
/**
* initDropHandling - Sets up drag and drop from the asset library to the graph
*/
export function initDropHandling(container) {
container.addEventListener('dragover', (e) => e.preventDefault());
container.addEventListener('drop', (e) => {
e.preventDefault();
const assetId = e.dataTransfer.getData('assetId');
const asset = state.assetMap[assetId];
const pos = state.graph.clientToLocal(e.clientX, e.clientY);
logger.info(`Drop Event at {${pos.x}, ${pos.y}}`, {
assetId: assetId,
found: !!asset,
id: asset?.id,
path: asset?.path,
type: asset?.type,
rawAsset: asset
});
if (!asset) {
logger.high(`Asset [${assetId}] not found in map`);
return;
}
// Logical Layer Guard: Block dropping new nodes
const activeLayer = state.layers.find(l => l.id === state.activeLayerId);
if (activeLayer && activeLayer.type === 'logical') {
import('../../ui/utils.js').then(m => m.showToast(t('err_logical_layer_drop'), 'warning'));
return;
}
const isPrimitive = ['rect', 'rounded-rect', 'circle', 'text-box', 'label'].includes(asset.type);
const prefix = asset.id === 'fixed-group' ? 'group_' : (asset.type === 'blank' || asset.type === 'dot' ? 'p_' : (isPrimitive ? 'shp_' : 'node_'));
const id = prefix + Math.random().toString(36).substr(2, 4);
// Use translate keys or asset label first, or fallback to generic name
let initialLabel = asset.label || t(asset.id) || (asset.id === 'fixed-group' ? 'New Group' : 'New ' + (asset.type || 'Object'));
if (asset.id === 'fixed-group') initialLabel = t('group') || 'New Group';
// Find if dropped over a group (prefer the smallest/innermost one)
const candidates = state.graph.getNodes().filter(n => {
if (!n.getData()?.is_group) return false;
const bbox = n.getBBox();
return bbox.containsPoint(pos);
});
const parent = candidates.length > 0
? candidates.reduce((smallest, current) => {
const smallestBBox = smallest.getBBox();
const currentBBox = current.getBBox();
const currentArea = currentBBox.width * currentBBox.height;
const smallestArea = smallestBBox.width * smallestBBox.height;
if (currentArea < smallestArea) return current;
if (currentArea > smallestArea) return smallest;
// If areas are equal, pick the one that is a descendant of the other
if (current.getAncestors().some(a => a.id === smallest.id)) return current;
return smallest;
})
: undefined;
// 2. Add to X6 immediately
const config = getX6NodeConfig({
id: id,
label: initialLabel,
type: asset.type || asset.category || asset.label || 'Unknown',
assetId: assetId, // Store unique composite ID for lookup
assetPath: asset.id === 'fixed-group' ? undefined : asset.path,
is_group: asset.id === 'fixed-group' || asset.is_group === true,
pos: { x: pos.x, y: pos.y },
parent: parent ? parent.id : undefined,
layerId: state.activeLayerId,
description: "",
asset_tag: "",
tags: []
});
const newNode = state.graph.addNode(config);
if (parent) {
parent.addChild(newNode);
}
// Ensure the new node follows the active layer's interaction rules immediately
import('../layers.js').then(m => m.applyLayerFilters());
});
}
@@ -0,0 +1,47 @@
/**
* graph/interactions/edges.js - Handles edge connection logic and metadata assignment.
*/
import { state } from '../../state.js';
/**
* initEdgeHandling - Sets up edge connection events
*/
export function initEdgeHandling() {
state.graph.on('edge:connected', ({ edge }) => {
const sourceId = edge.getSourceCellId();
const targetId = edge.getTargetCellId();
if (!sourceId || !targetId) return;
// Assign to current active layer and apply standard styling
import('/static/js/modules/graph/styles.js').then(({ getX6EdgeConfig }) => {
// [6개월 뒤의 나를 위한 메모]
// 단순 유추가 아닌 명시적 기록을 통해, 도면 전체를 전송하지 않고도 연결선 단독으로
// 크로스 레이어 여부를 파악할수 있게 하여 외부 도구/AI 연동 안정성을 높임.
const sourceNode = state.graph.getCellById(sourceId);
const targetNode = state.graph.getCellById(targetId);
const sourceLayer = sourceNode?.getData()?.layerId || state.activeLayerId;
const targetLayer = targetNode?.getData()?.layerId || state.activeLayerId;
const isCrossLayer = (sourceLayer !== targetLayer);
const edgeData = {
source: sourceId,
target: targetId,
layerId: state.activeLayerId,
source_layer: sourceLayer,
target_layer: targetLayer,
is_cross_layer: isCrossLayer,
...edge.getData()
};
const config = getX6EdgeConfig(edgeData);
// Apply standardized config to the new edge
edge.setData(edgeData, { silent: true });
if (config.router) edge.setRouter(config.router);
else edge.setRouter(null);
if (config.connector) edge.setConnector(config.connector);
edge.setAttrs(config.attrs);
});
});
}

Some files were not shown because too many files have changed in this diff Show More