diff --git a/design/design-qa.md b/design/design-qa.md new file mode 100644 index 00000000..dc70b820 --- /dev/null +++ b/design/design-qa.md @@ -0,0 +1,41 @@ +# DataTable unified header design QA + +- Source visual truth: `C:\Users\user\AppData\Local\Temp\codex-clipboard-3cfee13a-b444-4ae7-84d0-2141c3fada51.png` +- Implementation screenshot: `C:\Users\user\.codex\visualizations\2026\08\02\019fc172-c8b8-7253-83ff-1261f079edf3\table-header-item-focused.png` +- Combined focused comparison: `C:\Users\user\.codex\visualizations\2026\08\02\019fc172-c8b8-7253-83ff-1261f079edf3\table-header-reference-comparison.png` +- Viewport: 1920 x 1200 CSS px +- Density: deviceScaleFactor 2 +- Source pixels: 338 x 43; effective header crop 326 x 33, normalized to 593 x 60 +- Implementation pixels: 1120 x 60; CSS size 560 x 30 +- State: normal sortable table header, with sort interaction tested separately + +## Full-view comparison evidence + +SkillDamageDetail, CompactGradientRow, and ItemRow panel captures confirm that the shared header treatment remains legible and aligned in each table layout. The page contains 29 component panels with no console errors or broken images. + +## Focused comparison evidence + +The combined comparison normalizes the reference and implementation header height. Both use a near-black outer edge, gold-brown inner line, brown-to-black vertical gradient, muted gold label, square corners, and a solid downward sort triangle. A focused comparison is required because these border and glyph details are too small to judge in the full board. + +## Required fidelity surfaces + +- Fonts and typography: existing DCalc/SimSun stack retained; muted gold labels remain crisp at the component scale. +- Spacing and layout rhythm: all four DataTable header variants are 30px high; 1px column gaps and internal padding are consistent. +- Colors and visual tokens: shared colors reuse the existing `#4a3c26` border and `#bc9e58` text palette, with one common brown-black gradient. +- Image quality and asset fidelity: no raster asset is required or introduced; the reference contains only code-native table UI. +- Copy and content: existing table labels are unchanged. + +## Comparison history + +1. First pass found the generic header cell at 29px while the other variants were 30px. Removed the inherited row bottom border; all header and cell heights now measure 30px. +2. Second pass found ItemRow `锻造` and `拍卖信息` sort arrows clipped by narrow tracks. Expanded only those aligned header/body tracks; the final capture shows complete labels and triangles. + +## Findings + +No actionable P0, P1, or P2 mismatch remains. + +## Remaining risk + +Only Chrome was rendered. Other browser font rasterization may differ slightly. + +final result: passed diff --git a/design/index-web.html b/design/index-web.html new file mode 100644 index 00000000..260ea4b0 --- /dev/null +++ b/design/index-web.html @@ -0,0 +1,635 @@ + + + + + + DNF UI Component Library — Abstracted Preview + + + + + +
+
+
+
DNF UI Component Library / Abstracted Preview
+

Foundations & Construction Anatomy

+
截图定义视觉语法,素材定义构造方式;组件不包含任何游戏截图裁片
+
+
01 / 06FOUNDATIONS · TOKENS · ASSETS
+
+ +
+
+ +
+
+ +
+ +
+
+ +
+
+ +
+
+
+ +
+ +
+
+
+
DNF UI Component Library / Abstracted Preview
+

Core Controls

+
可替换文案、图标和状态;保持深蓝动作面、黄铜边线与紧凑密度
+
+
02 / 06BUTTON · FIELD · SELECTION · RATE
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+
+ +
+ +
+
+
+
DNF UI Component Library / Abstracted Preview
+

Navigation & Overlays

+
相同行为共享 primitive,不同 anatomy 保持独立 visual family
+
+
03 / 06TABS · DISCLOSURE · MENU · WINDOW
+
+ +
+
+
+ +
+
+ +
+
+ +
+ +
+
+ +
+
+ +
+
+
+ +
+ +
+
+
+
DNF UI Component Library / Abstracted Preview
+

Data Display & Product Patterns

+
由小组件组成设置表单、数据表、稀有度槽位和状态反馈,不把整张界面做成组件
+
+
04 / 06FORM ROW · TABLE · BADGE · QUALITY
+
+ +
+
+
+ +
+
+ +
+
+ +
+ +
+
+
+ +
+ +
+
+
+
DNF UI Component Library / Abstracted Preview
+

Search & Complex Dialog Composition

+
搜索组件保持原生输入语法;复杂弹窗由 WindowDialog、List、Table 与 Plain Scrollbar 组合
+
+
05 / 06AUTOCOMPLETE · SEARCH TREE · DIALOG PRESET
+
+ +
+
+ +
+
+ +
+ +
+
+
+
DNF UI Component Library / Abstracted Preview
+

DataTable Density & Item Variants

+
同一表格语义,拆分技能明细、紧凑记录、DataTable ItemRow 与无表头 ShopItemRow
+
+
06 / 06SORT · COMPACT · ITEM ROW · SHOP ITEM
+
+ +
+
+ +
+
+ +
+ +
+
+
+ +
+ + + + + + diff --git a/design/src-web/README.md b/design/src-web/README.md new file mode 100644 index 00000000..33cdaa7c --- /dev/null +++ b/design/src-web/README.md @@ -0,0 +1,13 @@ +# Component source layout + +Each component folder contains: + +- `index.html`: one or more named HTML templates. Root pages load them with `index.html#fragment`. +- `style/index.css`: the component styles. +- `component.js`: the local-file compatible registry generated from `index.html`. +- `img/`: only the image assets referenced by that component. + +`shared/` contains global tokens, base styles, the component loader, and shared glyph samples. +The complete pre-organization snapshot is stored under `../old/`. + +After editing a component `index.html`, run `python src-web/sync-components.py` from the project root. diff --git a/design/src-web/autocomplete/component.js b/design/src-web/autocomplete/component.js new file mode 100644 index 00000000..7b8fcddb --- /dev/null +++ b/design/src-web/autocomplete/component.js @@ -0,0 +1,4 @@ +(() => { + window.componentRegistry ||= {}; + window.componentRegistry["src-web/autocomplete/index.html"] = {"showcase":"
\n
Autocomplete
Two visual families over the same combobox behavior
\n
\n
\n
ComboboxFlatCAPTURED
\n
\n
DNF
\n
\n
\n
DNF Toonies(1天)
\n
DNF Toonies(3天)
\n
DNF毒战者
\n
DNF智者
\n
闪耀之DNF勇士
\n
\n
\n\n
\n
SearchTreeCAPTURED
\n
\n \"search\"\n
西风\"clear\"
\n
搜索
\n
刷新
\n
\n
\n
剧情角色名称
\n
素喃
\n
西风
\n
阿斯卡
\n
小铁柱
\n
黄昏之海(寂静城)
\n
\n
\n
\n
"}; +})(); diff --git a/design/src-web/autocomplete/img/sprite_interface.NPK/windowcommon.chn.img/561.PNG b/design/src-web/autocomplete/img/sprite_interface.NPK/windowcommon.chn.img/561.PNG new file mode 100644 index 00000000..4c455bdd Binary files /dev/null and b/design/src-web/autocomplete/img/sprite_interface.NPK/windowcommon.chn.img/561.PNG differ diff --git a/design/src-web/autocomplete/img/sprite_interface.NPK/windowcommon.chn.img/565.PNG b/design/src-web/autocomplete/img/sprite_interface.NPK/windowcommon.chn.img/565.PNG new file mode 100644 index 00000000..2e3699dc Binary files /dev/null and b/design/src-web/autocomplete/img/sprite_interface.NPK/windowcommon.chn.img/565.PNG differ diff --git a/design/src-web/autocomplete/img/sprite_interface.NPK/windowcommon.chn.img/582.PNG b/design/src-web/autocomplete/img/sprite_interface.NPK/windowcommon.chn.img/582.PNG new file mode 100644 index 00000000..5a2fcccc Binary files /dev/null and b/design/src-web/autocomplete/img/sprite_interface.NPK/windowcommon.chn.img/582.PNG differ diff --git a/design/src-web/autocomplete/img/sprite_interface.NPK/windowcommon.chn.img/652.PNG b/design/src-web/autocomplete/img/sprite_interface.NPK/windowcommon.chn.img/652.PNG new file mode 100644 index 00000000..fe02d586 Binary files /dev/null and b/design/src-web/autocomplete/img/sprite_interface.NPK/windowcommon.chn.img/652.PNG differ diff --git a/design/src-web/autocomplete/index.html b/design/src-web/autocomplete/index.html new file mode 100644 index 00000000..4989679b --- /dev/null +++ b/design/src-web/autocomplete/index.html @@ -0,0 +1,54 @@ + + + + + + + autocomplete component catalog + + + + + + + + diff --git a/design/src-web/autocomplete/style/index.css b/design/src-web/autocomplete/style/index.css new file mode 100644 index 00000000..869a40b2 --- /dev/null +++ b/design/src-web/autocomplete/style/index.css @@ -0,0 +1,23 @@ +/* Source module: autocomplete.css */ +.autocomplete-grid { display:grid;grid-template-columns:.9fr 1.1fr;gap:22px;height:calc(100% - 46px); } +.autocomplete-family { min-width:0;padding:10px 12px;border:1px solid #292b27;background:#070807; } +.family-head { height:24px;display:flex;align-items:center;justify-content:space-between;color:var(--gold);font-size:13px; } +.autocomplete-line,.search-toolbar { display:flex;align-items:center;gap:6px; } +.search-icon { flex:0 0 auto;width:auto;height:auto;max-width:18px;max-height:18px;image-rendering:pixelated; } +.autocomplete-field { min-width:0;flex:1; } +.clear-icon { flex:0 0 auto;width:9px;height:9px;margin:0 1px 0 4px;image-rendering:pixelated; } +.autocomplete-menu { margin:1px 0 0 24px;border:1px solid #5c4a2c;background:#010201;box-shadow:0 8px 18px #000; } +.flat-autocomplete .autocomplete-menu { margin-left:0; } +.autocomplete-item { height:27px;padding:0 9px;display:flex;align-items:center;border-bottom:1px solid #24231f;color:var(--gold);background:#030403; } +.autocomplete-item:hover { color:#f3d777;background:#101612;cursor:pointer; } +.autocomplete-item:active { color:#fff0a4;background:#07121b; } +.autocomplete-item:focus-visible { outline:1px solid var(--focus);outline-offset:-2px; } +.autocomplete-item.selected { color:var(--selected);background:#1b1508;box-shadow:inset 2px 0 0 var(--selected); } +.compact-shell { padding:2px;border-radius:0; } +.compact-shell .dnf-btn { min-width:58px;height:30px;padding:0 8px; } +.search-tree { height:170px;margin:4px 0 0 24px;padding:3px 0;border:1px solid #4f4229;background:#010201;overflow:hidden; } +.search-tree-row { height:26px;padding:0 9px;display:flex;align-items:center;gap:6px;border-bottom:1px solid #24231f;color:var(--gold); } +.search-tree-row img { max-width:12px;max-height:12px;image-rendering:pixelated; } +.search-tree-row.branch { padding-left:28px;color:#c6b46f; } +.search-tree-row.leaf { padding-left:50px; } +.search-tree-row.selected { color:var(--selected);background:#1a1509;box-shadow:inset 2px 0 0 var(--selected); } diff --git a/design/src-web/button/component.js b/design/src-web/button/component.js new file mode 100644 index 00000000..a5e5a24b --- /dev/null +++ b/design/src-web/button/component.js @@ -0,0 +1,4 @@ +(() => { + window.componentRegistry ||= {}; + window.componentRegistry["src-web/button/index.html"] = {"construction":"
\n
3-slice control surface
SOURCE ASSET
\n
\n
\n
\"button
\n
\n
Left cap固定像素,不横向拉伸
\n
Center仅中段伸缩,承载文字
\n
Right cap保留边角和金属高光
\n
\n
\n
\n
Responsive reconstruction
\n
\n \n CAPSTRETCHABLE FILLCAP\n
\n
\n
+创建预设
\n
\n
","showcase":"
\n
TextButton / IconButton
CSS + NINE-PATCH PRIMARYninepatch_resource.img
\n
\n
\n
Implementation / CSS原生渐变与描边 · 可编辑
\n
Rest
+创建角色
\n
Hover
+创建角色
\n
Pressed
+创建角色
\n
Disabled
购买
\n\n
Implementation / CSS ReplicaCSS gradient + inner glow · primary
\n
Rest
+创建角色
\n
Hover
+创建角色
\n
Pressed
+创建角色
\n
Disabled
购买
\n\n
CSS / Tone familyderived states · hover / press interactive
\n
Default · 4–7
\n
Green · 12–15
\n
Orange Red · 20–23
\n
Disabled · captured
\n
\n
Corner Radius = 0Shadow = NoneSize = Compact · Default · LargeLeadingIcon = BooleanLabel = TextHover = Lighter 1 TonePressed = Hover Tone + Y 1px
\n
\n
"}; +})(); diff --git a/design/src-web/button/img/sprite_interface_ninepatch_resource.NPK/ninepatch_resource.img/24.PNG b/design/src-web/button/img/sprite_interface_ninepatch_resource.NPK/ninepatch_resource.img/24.PNG new file mode 100644 index 00000000..39bd079f Binary files /dev/null and b/design/src-web/button/img/sprite_interface_ninepatch_resource.NPK/ninepatch_resource.img/24.PNG differ diff --git a/design/src-web/button/index.html b/design/src-web/button/index.html new file mode 100644 index 00000000..17680886 --- /dev/null +++ b/design/src-web/button/index.html @@ -0,0 +1,66 @@ + + + + + + + button component catalog + + + + + + + + + diff --git a/design/src-web/button/style/index.css b/design/src-web/button/style/index.css new file mode 100644 index 00000000..73a85c5a --- /dev/null +++ b/design/src-web/button/style/index.css @@ -0,0 +1,204 @@ +/* Source module: button.css */ +.btn-shell { + display: inline-flex; + padding: 4px; + border-radius: 0; + background: none; + box-shadow: none; +} + +.dnf-btn { + appearance: none; + position: relative; + height: 30px; + min-width: 110px; + padding: 0 14px; + display: inline-flex; + align-items: center; + justify-content: center; + gap: 7px; + color: var(--gold); + border: 1px solid transparent; + border-radius: 0; + background: + linear-gradient(180deg, #1f355e 0%, #1d2f53 55%, #1a2849 100%) padding-box, + linear-gradient(180deg, #684f2d 0%, #483423 100%) border-box; + box-shadow: none; + font-size: 13px; + line-height: 1; + text-align: center; + white-space: nowrap; +} + +button.dnf-btn { + font-family: inherit; + cursor: pointer; +} +button.dnf-btn.normal:not(.raster-tone):not(.image):hover, +button.dnf-btn.normal:not(.raster-tone):not(.image):focus-visible { + color: #eee2aa; + background: + linear-gradient(180deg, #29457f 0%, #273f74 55%, #24386a 100%) padding-box, + linear-gradient(180deg, #725f4e 0%, #524444 100%) border-box; + outline: none; +} +button.dnf-btn.normal:not(.raster-tone):not(.image):active { + color: #eee2aa; + transform: translateY(1px); + background: + linear-gradient(180deg, #29457f 0%, #273f74 55%, #24386a 100%) padding-box, + linear-gradient(180deg, #725f4e 0%, #524444 100%) border-box; +} +button.dnf-btn:disabled { + cursor: default; +} + +.dnf-btn.normal { + background: + linear-gradient(180deg, #1f355e 0%, #1d2f53 55%, #1a2849 100%) padding-box, + linear-gradient(180deg, #684f2d 0%, #483423 100%) border-box; +} +.dnf-btn.hover { + color: #eee2aa; + background: + linear-gradient(180deg, #29457f 0%, #273f74 55%, #24386a 100%) padding-box, + linear-gradient(180deg, #725f4e 0%, #524444 100%) border-box; +} +.dnf-btn.pressed { + transform: translateY(1px); + background: + linear-gradient(180deg, #29457f 0%, #263e73 58%, #213462 100%) padding-box, + linear-gradient(180deg, #725f4e 0%, #524444 100%) border-box; +} +.dnf-btn.disabled { + color: #666566; + background: + linear-gradient(180deg, #2c2c2c 0%, #272727 55%, #222 100%) padding-box, + linear-gradient(180deg, #343434 0%, #262626 100%) border-box; +} +.dnf-btn.large { + height: 44px; + min-width: 168px; + font-size: 16px; +} + +/* CSS replica of the compact NinePatch family. State colors are derived from the base tone. */ +.dnf-btn.image, +.dnf-btn.raster-tone { + --button-top: var(--control-blue-top); + --button-bottom: var(--control-blue-bottom); + --button-edge-top: var(--control-edge-top); + --button-edge-bottom: var(--control-edge-bottom); + --button-state-top: var(--button-top); + --button-state-bottom: var(--button-bottom); + --button-state-edge-top: var(--button-edge-top); + --button-state-edge-bottom: var(--button-edge-bottom); + --button-hover-r: 10; + --button-hover-g: 16; + --button-hover-b: 33; + height: 26px; + min-width: 112px; + padding: 0 10px; + isolation:isolate; + border:1px solid rgba(0,0,0,.6); + border-radius: 0; + background:transparent; + box-shadow:none; +} +.dnf-btn.image::before, +.dnf-btn.raster-tone::before { + content:""; + position:absolute; + z-index:-1; + inset:0; + margin:1px; + border:1px solid transparent; + background: + linear-gradient(180deg,var(--button-state-top),var(--button-state-bottom)) padding-box, + linear-gradient(180deg,var(--button-state-edge-top),var(--button-state-edge-bottom)) border-box; + box-shadow:inset 0 0 0 1px rgba(0,0,0,.12); + pointer-events:none; +} +.dnf-btn.image.hover, +.dnf-btn.raster-tone.normal:hover, +.dnf-btn.raster-tone.hover { + --button-state-top:rgb(from var(--button-top) calc(r + var(--button-hover-r)) calc(g + var(--button-hover-g)) calc(b + var(--button-hover-b))); + --button-state-bottom:rgb(from var(--button-bottom) calc(r + var(--button-hover-r)) calc(g + var(--button-hover-g)) calc(b + var(--button-hover-b))); + --button-state-edge-top:rgb(from var(--button-edge-top) calc(r + var(--button-hover-r)) calc(g + var(--button-hover-g)) calc(b + var(--button-hover-b))); + --button-state-edge-bottom:rgb(from var(--button-edge-bottom) calc(r + var(--button-hover-r)) calc(g + var(--button-hover-g)) calc(b + var(--button-hover-b))); +} +.dnf-btn.image.pressed, +.dnf-btn.raster-tone.normal:active, +.dnf-btn.raster-tone.pressed { + --button-state-top:rgb(from var(--button-top) calc(r + var(--button-hover-r)) calc(g + var(--button-hover-g)) calc(b + var(--button-hover-b))); + --button-state-bottom:rgb(from var(--button-bottom) calc(r + var(--button-hover-r)) calc(g + var(--button-hover-g)) calc(b + var(--button-hover-b))); + --button-state-edge-top:rgb(from var(--button-edge-top) calc(r + var(--button-hover-r)) calc(g + var(--button-hover-g)) calc(b + var(--button-hover-b))); + --button-state-edge-bottom:rgb(from var(--button-edge-bottom) calc(r + var(--button-hover-r)) calc(g + var(--button-hover-g)) calc(b + var(--button-hover-b))); + transform:translateY(1px); +} +.dnf-btn.image.disabled, +.dnf-btn.raster-tone.disabled { + --button-state-top:var(--control-disabled-top); + --button-state-bottom:var(--control-disabled-bottom); + --button-state-edge-top:var(--control-disabled-edge-top); + --button-state-edge-bottom:var(--control-disabled-edge-bottom); + color:#666566; +} +.dnf-btn.raster-tone.tone-green { + --button-top:var(--control-green-top); + --button-bottom:var(--control-green-bottom); + --button-hover-r:10; + --button-hover-g:33; + --button-hover-b:14; +} +.dnf-btn.raster-tone.tone-orange { + --button-top:var(--control-orange-top); + --button-bottom:var(--control-orange-bottom); + --button-hover-r:33; + --button-hover-g:22; + --button-hover-b:10; +} + +.button-showcase-panel .panel-body { padding:10px 18px; } +.button-state-grid { gap:4px 14px; } +.button-state-grid .sample-cell { height:44px;padding:4px 12px;display:grid;grid-template-columns:auto 1fr;align-items:center;gap:8px; } +.button-state-grid .sample-label { margin:0; } +.button-state-grid .button-implementation-label { min-height:44px;padding:5px 10px; } +.button-showcase-panel .spec-row[style] { margin-top:8px!important; } + +.button-implementation-label { + min-height: 52px; + padding: 8px 10px; + display: flex; + flex-direction: column; + justify-content: center; + border-left: 2px solid var(--brass); + background: #080908; + color: var(--gold); + font-size: 13px; +} +.button-implementation-label small { + margin-top: 4px; + color: var(--muted); + font-size: 11px; +} + +.dnf-btn:has(> .btn-icon), +.dnf-btn:has(> .button-glyph) { padding-inline:30px; } +.dnf-btn > .btn-icon, +.dnf-btn > .button-glyph { position:absolute;left:10px;top:50%;transform:translateY(-50%); } +.btn-icon { font: 18px/1 Georgia, serif; color: #e4c98f; } + +.icon-btn { + width: 30px; + height: 30px; + display: inline-flex; + align-items: center; + justify-content: center; + border: 1px solid #7a6238; + background: linear-gradient(#2e4779, #1b2b4f); + box-shadow: inset 0 0 0 1px #12203d, 0 0 0 3px #111317; + color: #ddc47e; +} + +.icon-btn img, .pixel { image-rendering: pixelated; } diff --git a/design/src-web/complex-dialog/component.js b/design/src-web/complex-dialog/component.js new file mode 100644 index 00000000..77504325 --- /dev/null +++ b/design/src-web/complex-dialog/component.js @@ -0,0 +1,4 @@ +(() => { + window.componentRegistry ||= {}; + window.componentRegistry["src-web/complex-dialog/index.html"] = {"preset":"
\n
PresetManagementDialog / composition template
DEFAULTRENAMINGSELECTED ROW ACTIONSSHOW ALL / SCROLLABLE
\n
\n
\n
管理设置
\n
\n
※ 可以针对自己的游戏习惯作出选择,一次性变更多项设置。
※ 如果预设已满,请使用文件保存功能。
\n
\n
\n
我的游戏设置
\n
西瓜°_07/31
\n
迪酱_07/31
\n \n
\n
\n
\n
\n
\n
\n
\n
\n
\n\n
\n
西瓜°_07/31
\n
\n
\n
保存账号设置
\n
装备信息对比ON→OFF
\n
保存角色设置
\n
光环效果OFF→ON
\n
角色技能效果透明32%→12%
\n
角色道具特效透明16%→13%
\n
本地储存选项
\n
画质提升ON→ON
\n
垂直同步OFF→OFF
\n
\n
\n
\n
\n
\n
\n \n
\n
\n
"}; +})(); diff --git a/design/src-web/complex-dialog/img/sprite_interface.NPK/windowcommon.chn.img/42.PNG b/design/src-web/complex-dialog/img/sprite_interface.NPK/windowcommon.chn.img/42.PNG new file mode 100644 index 00000000..9d542834 Binary files /dev/null and b/design/src-web/complex-dialog/img/sprite_interface.NPK/windowcommon.chn.img/42.PNG differ diff --git a/design/src-web/complex-dialog/img/sprite_interface.NPK/windowcommon.chn.img/561.PNG b/design/src-web/complex-dialog/img/sprite_interface.NPK/windowcommon.chn.img/561.PNG new file mode 100644 index 00000000..4c455bdd Binary files /dev/null and b/design/src-web/complex-dialog/img/sprite_interface.NPK/windowcommon.chn.img/561.PNG differ diff --git a/design/src-web/complex-dialog/img/sprite_interface.NPK/windowcommon_2x.img/30.PNG b/design/src-web/complex-dialog/img/sprite_interface.NPK/windowcommon_2x.img/30.PNG new file mode 100644 index 00000000..727f6259 Binary files /dev/null and b/design/src-web/complex-dialog/img/sprite_interface.NPK/windowcommon_2x.img/30.PNG differ diff --git a/design/src-web/complex-dialog/img/sprite_interface.NPK/windowcommon_2x.img/32.PNG b/design/src-web/complex-dialog/img/sprite_interface.NPK/windowcommon_2x.img/32.PNG new file mode 100644 index 00000000..a4199d1a Binary files /dev/null and b/design/src-web/complex-dialog/img/sprite_interface.NPK/windowcommon_2x.img/32.PNG differ diff --git a/design/src-web/complex-dialog/img/sprite_interface.NPK/windowcommon_2x.img/6.PNG b/design/src-web/complex-dialog/img/sprite_interface.NPK/windowcommon_2x.img/6.PNG new file mode 100644 index 00000000..eabf06e5 Binary files /dev/null and b/design/src-web/complex-dialog/img/sprite_interface.NPK/windowcommon_2x.img/6.PNG differ diff --git a/design/src-web/complex-dialog/img/sprite_interface2_option.NPK/option.img/88.PNG b/design/src-web/complex-dialog/img/sprite_interface2_option.NPK/option.img/88.PNG new file mode 100644 index 00000000..3bd41ad2 Binary files /dev/null and b/design/src-web/complex-dialog/img/sprite_interface2_option.NPK/option.img/88.PNG differ diff --git a/design/src-web/complex-dialog/index.html b/design/src-web/complex-dialog/index.html new file mode 100644 index 00000000..7efc7019 --- /dev/null +++ b/design/src-web/complex-dialog/index.html @@ -0,0 +1,64 @@ + + + + + + + complex-dialog component catalog + + + + + + + + diff --git a/design/src-web/complex-dialog/style/index.css b/design/src-web/complex-dialog/style/index.css new file mode 100644 index 00000000..57bfb09e --- /dev/null +++ b/design/src-web/complex-dialog/style/index.css @@ -0,0 +1,87 @@ +/* Source module: complex-dialog.css */ +.preset-stage { height:calc(100% - 46px);padding:14px;display:flex;align-items:center;justify-content:center;background:rgba(0,0,0,.18); } +.preset-window { width:1280px;height:574px;display:flex;flex-direction:column;background:rgba(4,5,5,.82); } +.preset-window > .window-titlebar { flex:0 0 31px; } +.preset-body-shell { flex:1;min-height:0;padding:9px;display:flex;flex-direction:column;gap:8px;background:rgba(4,5,5,.82); } +.preset-intro { flex:0 0 68px;display:flex;align-items:center;justify-content:center;text-align:center;line-height:1.45;color:#b7a467; } +.preset-intro.dialog-content-well { min-height:68px; } +.preset-main { flex:1;min-height:0;display:grid;grid-template-columns:.46fr .54fr;gap:10px; } +.preset-column { min-width:0;min-height:0;display:flex;flex-direction:column;border:1px solid #30332f;background:#000; } +.preset-section-head { flex:0 0 32px;padding:0 9px;display:flex;align-items:center;justify-content:space-between;border-bottom:1px solid #504329;background:#171916;color:#d2ba6f;font-size:13px; } +.preset-row { flex:0 0 33px;padding:0 9px;display:grid;grid-template-columns:20px 1fr auto;align-items:center;border-bottom:1px solid #272823;background:#090a09;color:#a9965e; } +.preset-row:nth-child(3) { background:#1d1e1c; } +.preset-row.selected { color:#f1d46d;box-shadow:inset 0 0 0 1px #3d99d0;background:#07121b; } +.preset-radio { width:14px;height:14px;image-rendering:auto; } +.preset-row-actions { display:flex;gap:5px; } +.preset-row-actions img { max-width:13px;max-height:13px;image-rendering:pixelated; } +.preset-row-action { appearance:none;width:20px;height:20px;padding:0;display:inline-flex;align-items:center;justify-content:center;border:0;background:none;cursor:pointer; } +.preset-row-action img { filter:brightness(1);transform:translateY(0); } +.preset-row-action:hover img,.preset-row-action:focus-visible img,.preset-row-action:active img,.preset-row-action[aria-pressed="true"] img { filter:brightness(1.28); } +.preset-row-action:focus-visible { outline:1px solid rgba(225,204,135,.72);outline-offset:-2px; } +.preset-row-action:active img { transform:translateY(1px); } +.preset-row.is-renaming .preset-name { color:#fff0a5;text-decoration:underline;text-decoration-style:dotted;text-underline-offset:3px; } +.preset-row.is-demo-deleted { opacity:.46; } +.preset-row.is-demo-deleted .preset-name { text-decoration:line-through; } +.preset-add { appearance:none;flex:0 0 35px;display:flex;align-items:center;justify-content:center;gap:6px;border:0;border-bottom:1px solid #242520;color:#d5b04c;background:#030403;font:inherit;cursor:pointer; } +.preset-add:hover,.preset-add:focus-visible,.preset-add:active { color:#ffe28a;background:#11130f;outline:none; } +.preset-add:active { transform:translateY(1px); } +.preset-add img,.button-glyph { max-width:12px;max-height:12px;image-rendering:pixelated; } +.preset-spacer { flex:1;background:#020302; } +.preset-actions { flex:0 0 auto;padding:9px 0 8px;display:grid;gap:5px;justify-content:center;border-top:1px solid #292a26;background:#030403; } +.preset-actions .btn-shell { padding:2px;border-radius:0; } +.preset-actions .dnf-btn { width:270px;height:28px; } +.preset-separator { height:1px;margin:3px -38px;background:#2b2d29; } +.show-all { appearance:none;padding:2px 3px;display:flex;align-items:center;gap:5px;border:0;background:none;color:inherit;font:inherit;cursor:pointer; } +.show-all:hover,.show-all:focus-visible,.show-all:active { color:#f1dc91;outline:none; } +.show-all:active { transform:translateY(1px); } +.show-all img { image-rendering:pixelated; } +.preset-diff-scroll { flex:1;min-height:0;display:grid;grid-template-columns:1fr 15px;background:#020403; } +.preset-diff-list { min-width:0;padding:4px 9px;overflow:hidden; } +.preset-group-title { height:28px;display:flex;align-items:center;border-bottom:1px solid #26333a;color:#ba9d51;font-size:13px; } +.diff-row { height:28px;display:grid;grid-template-columns:1fr 64px 28px 64px;align-items:center;border-bottom:1px solid #222c30;color:#b49f67; } +.diff-row em { color:#777b77;font-style:normal;text-align:center; } +.diff-row b { color:#747a76;font-weight:400;text-align:center; } +.diff-row strong { color:var(--selected);font-weight:500;text-align:center; } +.diff-row.muted strong { color:#888b84; } +.compact-scroll { width:15px;height:100%; } +.preset-footer { flex:0 0 42px;position:relative;justify-content:center; } +.preset-footer .dialog-status { position:absolute;left:112px;max-width:270px;overflow:hidden;text-overflow:ellipsis; } +.preset-footer .back-action { position:absolute;left:8px; } +.footer-actions { display:flex;gap:8px; } +.preset-footer .dnf-btn { min-width:78px; } + +.anatomy { + display:grid; + grid-template-columns:120px 1fr; + gap:18px; + align-items:center; +} +.asset-tile { min-height:78px;display:flex;align-items:center;justify-content:center;background:#262726;border:1px dashed #5f5e58; } +.asset-tile img { image-rendering:pixelated; } +.anatomy-list { display:grid;gap:7px; } +.anatomy-line { display:grid;grid-template-columns:76px 1fr;gap:9px;color:var(--text-3);font-size:11px; } +.anatomy-line strong { color:var(--gold);font-weight:500; } + +.slice-demo { + position:relative; + height:64px; + border:5px solid transparent; + border-radius:2px; + background: + linear-gradient(180deg, #1f355e 0%, #1d2f53 55%, #1a2849 100%) padding-box, + linear-gradient(180deg, #684f2d 0%, #483423 100%) border-box; +} +.slice-demo .cut { position:absolute;top:-6px;bottom:-6px;width:1px;border-left:1px dashed var(--focus); } +.slice-demo .cut.left { left:7px; }.slice-demo .cut.right { right:7px; } +.slice-demo .slice-label { position:absolute;top:69px;color:var(--text-3);font-size:9px; } + +.nine-grid { display:grid;grid-template-columns:22px 1fr 22px;grid-template-rows:22px 76px 22px;width:260px;height:120px; } +.nine-grid > div { border:1px dashed rgba(75,167,211,.55);background:linear-gradient(#242b31,#0b0e10); } +.nine-grid .center { background:linear-gradient(#15191c,#090a0b); } + +.callout-list { margin:0;padding:0;list-style:none;display:grid;gap:9px;color:var(--text-2);font-size:12px; } +.callout-list li { display:flex;align-items:flex-start;gap:8px; } +.callout-list li::before { content:"";width:5px;height:5px;margin-top:6px;background:var(--selected);box-shadow:0 0 6px rgba(218,164,29,.4); } + +.footer-note { position:absolute;left:46px;right:46px;bottom:20px;display:flex;justify-content:space-between;color:#767773;font-size:10px;letter-spacing:.4px; } +.token-label { color:var(--text-3);font:10px/1.35 Consolas,monospace; } diff --git a/design/src-web/data-section/component.js b/design/src-web/data-section/component.js new file mode 100644 index 00000000..393a0a8e --- /dev/null +++ b/design/src-web/data-section/component.js @@ -0,0 +1,4 @@ +(() => { + window.componentRegistry ||= {}; + window.componentRegistry["src-web/data-section/index.html"] = {"showcase":"
\n
DataSection
FAMILY C
\n
\n
\n
\n \n
\n
魔法暴击+113.5%
\n
技能等级46
\n
精神不可用
\n
\n
\n
\n \n \n
\n
\n
ExpandedCollapsedInteractiveData rows
\n
\n
"}; +})(); diff --git a/design/src-web/data-section/img/sprite_interface.NPK/windowcommon.chn.img/561.PNG b/design/src-web/data-section/img/sprite_interface.NPK/windowcommon.chn.img/561.PNG new file mode 100644 index 00000000..4c455bdd Binary files /dev/null and b/design/src-web/data-section/img/sprite_interface.NPK/windowcommon.chn.img/561.PNG differ diff --git a/design/src-web/data-section/img/sprite_interface.NPK/windowcommon.chn.img/565.PNG b/design/src-web/data-section/img/sprite_interface.NPK/windowcommon.chn.img/565.PNG new file mode 100644 index 00000000..2e3699dc Binary files /dev/null and b/design/src-web/data-section/img/sprite_interface.NPK/windowcommon.chn.img/565.PNG differ diff --git a/design/src-web/data-section/index.html b/design/src-web/data-section/index.html new file mode 100644 index 00000000..614b07d2 --- /dev/null +++ b/design/src-web/data-section/index.html @@ -0,0 +1,49 @@ + + + + + + + data-section component catalog + + + + + + + + diff --git a/design/src-web/data-section/style/index.css b/design/src-web/data-section/style/index.css new file mode 100644 index 00000000..3f8f9f13 --- /dev/null +++ b/design/src-web/data-section/style/index.css @@ -0,0 +1,21 @@ +/* Source module: data-section.css */ +.disclosure { + border: 1px solid #4b3d26; + background: #070807; + color: var(--gold); +} +.disclosure-head { min-height: 32px; padding: 0 9px; display:flex;align-items:center;gap:7px;background:linear-gradient(#2a2925,#10110f);border-bottom:1px solid #25221b; } +.disclosure-head.focus { outline: 1px solid var(--focus); outline-offset: -2px; } +.disclosure-body { padding: 7px 9px; } +.tree-row { height: 25px; padding-left: calc(var(--depth,0) * 16px); display:flex;align-items:center;gap:6px;color:#c9bb7e;border-bottom:1px solid #24231f; } +.tree-row.focus { outline:1px solid var(--focus); outline-offset:-2px;background:#07131b; } +.tree-row.selected { color:#f1d667;background:#302711; } + +.data-section-stack { display:flex;flex-direction:column;gap:7px; } +.disclosure-head { width:100%;border:0;color:inherit;font:inherit;text-align:left;cursor:pointer; } +.disclosure-head:focus-visible { outline:1px solid var(--selected);outline-offset:-2px; } +.disclosure-head img { flex:0 0 auto;max-width:13px;max-height:13px;image-rendering:pixelated; } +.disclosure-state { margin-left:auto;color:var(--text-3);font-size:10px; } +.disclosure.is-collapsed .disclosure-head { border-bottom:0; } +.disclosure.is-collapsed .disclosure-state { color:#857a57; } +.disclosure-body[hidden] { display:none; } diff --git a/design/src-web/data-table/component.js b/design/src-web/data-table/component.js new file mode 100644 index 00000000..47819c5e --- /dev/null +++ b/design/src-web/data-table/component.js @@ -0,0 +1,4 @@ +(() => { + window.componentRegistry ||= {}; + window.componentRegistry["src-web/data-table/index.html"] = {"composition":"
\n
DataTable / StatTable composition
Dense rows, semantic text, real raster icon slots
\n
\n
Selection
\n
\n
图标
\n
魔剑共鸣核心
+12
出售完成
湖北 4
\n
史诗灵魂结晶
+10
购买完成
跨区
\n
养猪备注:团队共享养成角色\"编辑\"\"删除\"
\n
稀有装备增幅券
+0
购买失败
西北 1
\n
太初之光碎片
+13
已完成
华东
\n
\n
Density = Compact · DefaultContentState = Populated · Empty
◀1 / 2▶
\n
\n
LinearProgress · milestones
\n
\n
\n
","skill":"
\n
DataTable / SkillDamageDetail
No zebra striping · fixed summary · bottom utility row
\n
\n
\n
技能
使用次数
总伤害
平均伤害
伤害占比
\n
\n
1.\"技能
34
953,379,872,000
28,040,584,470
25.9%
\n
2.\"技能
1
615,930,416,128
615,930,416,128
16.7%
\n
3.\"技能
1
367,626,199,040
367,626,199,040
10.0%
\n
4.\"技能
1
335,615,315,968
335,615,315,968
9.1%
\n
5.\"技能
1
238,860,883,968
238,860,883,968
6.5%
\n
6.\"技能
10
164,943,300,413
16,494,330,041
4.5%
\n
7.\"技能
4
163,055,895,552
40,763,973,888
4.4%
\n
8.\"技能
2
155,930,977,504
77,965,488,752
4.2%
\n
9.\"技能
2
148,375,164,928
74,187,582,464
4.0%
\n
\n
总和
—
3,678,555,852,653
—
\n
\n
\n
\n
\n
","compact":"
\n
DataTable / CompactGradientRow
30px unified header · 20px row · square corners
\n
\n
\n
\n
\n
07/31
跨五
绝唱
\n
07/30
湖北 4
西瓜°
\n
07/29
跨一
Mikiyla
\n
07/28
华东
浅笑ツ
\n
07/27
跨六
武神四月
\n
07/26
湖北 4
蛋猪超人
\n
\n
\n
\n
Density = CompactRadius = 0Gap = 5
\n
\n
","item":"
\n
DataTable / ItemRow
CSS 43 rest · 44 hover · 46 selected
\n
\n
\n
\n
\n
+0
+0
人造神 3 号纳波尔宝珠
购买完成
湖北 4
绝唱
\n
+0
+0
果味整夏收集箱宝珠自选
出售完成
湖北 4
绝唱
\n
+2
+0
魔法封印转换灵魂
购买完成
湖北 4
蛋猪超人
\n
+0
+0
史诗灵魂结晶
购买完成
湖北 4
蛋猪超人
\n
+0
+0
史诗灵魂结晶
购买完成
湖北 4
蛋猪超人
\n
\n
\n
Rest / Hover / Selected = CSSHeight = 38Header = Sortable
\n
\n
"}; +})(); diff --git a/design/src-web/data-table/img/sprite_interface.NPK/windowcommon.chn.img/42.PNG b/design/src-web/data-table/img/sprite_interface.NPK/windowcommon.chn.img/42.PNG new file mode 100644 index 00000000..9d542834 Binary files /dev/null and b/design/src-web/data-table/img/sprite_interface.NPK/windowcommon.chn.img/42.PNG differ diff --git a/design/src-web/data-table/img/sprite_interface.NPK/windowcommon.chn.img/652.PNG b/design/src-web/data-table/img/sprite_interface.NPK/windowcommon.chn.img/652.PNG new file mode 100644 index 00000000..fe02d586 Binary files /dev/null and b/design/src-web/data-table/img/sprite_interface.NPK/windowcommon.chn.img/652.PNG differ diff --git a/design/src-web/data-table/img/sprite_interface.NPK/windowcommon_2x.img/24.PNG b/design/src-web/data-table/img/sprite_interface.NPK/windowcommon_2x.img/24.PNG new file mode 100644 index 00000000..a0423ebd Binary files /dev/null and b/design/src-web/data-table/img/sprite_interface.NPK/windowcommon_2x.img/24.PNG differ diff --git a/design/src-web/data-table/img/sprite_interface2_option.NPK/option.img/88.PNG b/design/src-web/data-table/img/sprite_interface2_option.NPK/option.img/88.PNG new file mode 100644 index 00000000..3bd41ad2 Binary files /dev/null and b/design/src-web/data-table/img/sprite_interface2_option.NPK/option.img/88.PNG differ diff --git a/design/src-web/data-table/img/sprite_item.NPK/equipmentskill.img/0.PNG b/design/src-web/data-table/img/sprite_item.NPK/equipmentskill.img/0.PNG new file mode 100644 index 00000000..6e0b1e48 Binary files /dev/null and b/design/src-web/data-table/img/sprite_item.NPK/equipmentskill.img/0.PNG differ diff --git a/design/src-web/data-table/img/sprite_item.NPK/equipmentskill.img/1.PNG b/design/src-web/data-table/img/sprite_item.NPK/equipmentskill.img/1.PNG new file mode 100644 index 00000000..d7f2db60 Binary files /dev/null and b/design/src-web/data-table/img/sprite_item.NPK/equipmentskill.img/1.PNG differ diff --git a/design/src-web/data-table/img/sprite_item.NPK/equipmentskill.img/2.PNG b/design/src-web/data-table/img/sprite_item.NPK/equipmentskill.img/2.PNG new file mode 100644 index 00000000..13fa3616 Binary files /dev/null and b/design/src-web/data-table/img/sprite_item.NPK/equipmentskill.img/2.PNG differ diff --git a/design/src-web/data-table/img/sprite_item.NPK/equipmentskill.img/3.PNG b/design/src-web/data-table/img/sprite_item.NPK/equipmentskill.img/3.PNG new file mode 100644 index 00000000..db40e39f Binary files /dev/null and b/design/src-web/data-table/img/sprite_item.NPK/equipmentskill.img/3.PNG differ diff --git a/design/src-web/data-table/img/sprite_item.NPK/equipmentskill.img/4.PNG b/design/src-web/data-table/img/sprite_item.NPK/equipmentskill.img/4.PNG new file mode 100644 index 00000000..4d3ffb0e Binary files /dev/null and b/design/src-web/data-table/img/sprite_item.NPK/equipmentskill.img/4.PNG differ diff --git a/design/src-web/data-table/img/sprite_item.NPK/equipmentskill.img/5.PNG b/design/src-web/data-table/img/sprite_item.NPK/equipmentskill.img/5.PNG new file mode 100644 index 00000000..84311ba4 Binary files /dev/null and b/design/src-web/data-table/img/sprite_item.NPK/equipmentskill.img/5.PNG differ diff --git a/design/src-web/data-table/img/sprite_item.NPK/equipmentskill.img/6.PNG b/design/src-web/data-table/img/sprite_item.NPK/equipmentskill.img/6.PNG new file mode 100644 index 00000000..bb55e587 Binary files /dev/null and b/design/src-web/data-table/img/sprite_item.NPK/equipmentskill.img/6.PNG differ diff --git a/design/src-web/data-table/img/sprite_item.NPK/equipmentskill.img/7.PNG b/design/src-web/data-table/img/sprite_item.NPK/equipmentskill.img/7.PNG new file mode 100644 index 00000000..065856e0 Binary files /dev/null and b/design/src-web/data-table/img/sprite_item.NPK/equipmentskill.img/7.PNG differ diff --git a/design/src-web/data-table/img/sprite_item.NPK/equipmentskill.img/8.PNG b/design/src-web/data-table/img/sprite_item.NPK/equipmentskill.img/8.PNG new file mode 100644 index 00000000..fea1b324 Binary files /dev/null and b/design/src-web/data-table/img/sprite_item.NPK/equipmentskill.img/8.PNG differ diff --git a/design/src-web/data-table/img/sprite_item.NPK/equipmentskill.img/9.PNG b/design/src-web/data-table/img/sprite_item.NPK/equipmentskill.img/9.PNG new file mode 100644 index 00000000..63b66ad9 Binary files /dev/null and b/design/src-web/data-table/img/sprite_item.NPK/equipmentskill.img/9.PNG differ diff --git a/design/src-web/data-table/index.html b/design/src-web/data-table/index.html new file mode 100644 index 00000000..a509a093 --- /dev/null +++ b/design/src-web/data-table/index.html @@ -0,0 +1,98 @@ + + + + + + + data-table component catalog + + + + + + + + + + + diff --git a/design/src-web/data-table/style/index.css b/design/src-web/data-table/style/index.css new file mode 100644 index 00000000..4c1d5fab --- /dev/null +++ b/design/src-web/data-table/style/index.css @@ -0,0 +1,135 @@ +/* Source module: data-table.css */ +.data-table { border:1px solid #4a3c26;border-radius:0;background:#030403;overflow:hidden; } +.table-toolbar { height:26px;margin-bottom:6px;display:flex;align-items:center;justify-content:flex-end;gap:5px;color:var(--text-3);font-size:10px; } +.table-mode-button { appearance:none;height:20px;padding:0 8px;border:1px solid #3c3b31;border-radius:0;background:#0c0d0c;color:#918967;font:10px/1 "DCalc",SimSun,sans-serif; } +.table-mode-button.is-active { border-color:#806329;color:#e2c968;background:#1a160d; } + +.sortable-header { appearance:none;min-width:0;height:100%;padding:0 9px;display:flex;align-items:center;justify-content:space-between;gap:7px;border-radius:0;color:#bc9e58;font:11px/1 "DCalc",SimSun,sans-serif;text-align:left;cursor:pointer; } +.sortable-header:hover { --table-header-top:color-mix(in srgb,#352817 84%,#fff);--table-header-mid:color-mix(in srgb,#1b170d 88%,#fff); } +.sortable-header:active, +.sortable-header.is-pressed { --table-header-top:#211a10;--table-header-mid:#15130c;transform:translateY(1px); } +.sortable-header.is-sorted { color:#bc9e58; } +.sort-glyph { flex:0 0 auto;width:10px;color:currentColor;font-size:0;line-height:1;text-align:center; } +.sort-glyph::before { content:"▼";font:10px/1 SimSun,"DCalc",serif; } + +.sortable-header, +.table-row.header > div, +.skill-table-row.header > *, +.compact-table-row.header > *, +.item-table-row.header > * { + --table-header-top:#352817; + --table-header-mid:#1b170d; + --table-header-bottom:#090a07; + border:1px solid #070806; + background:linear-gradient(180deg,var(--table-header-top) 0%,var(--table-header-mid) 48%,var(--table-header-bottom) 100%); + box-shadow:inset 0 0 0 1px #4a3c26,inset 0 1px 0 #65502a; + color:#bc9e58; +} + +.table-row { min-height:38px;display:grid;grid-template-columns:46px 1.8fr .7fr .8fr .7fr;align-items:center;border-bottom:1px solid #2c2b26;color:#d2c78f; } +.table-row > div { min-width:0;padding:5px 9px;border-right:1px solid #292720;white-space:nowrap;overflow:hidden;text-overflow:ellipsis; } +.table-row.header { min-height:30px;height:30px;column-gap:1px;border-bottom:0;background:#030403;color:#bc9e58;font-size:11px; } +.table-row.header > div { height:100%;display:flex;align-items:center; } +.table-row.data-row { cursor:pointer; } +.table-row.data-row:nth-of-type(odd) { background:#101210; } +.data-table-core.selection-gold .data-row.is-selected { position:relative;background:linear-gradient(90deg,#352b11 0,#161207 60%,#090a08 100%);outline:1px solid #d6ad37;outline-offset:-1px;box-shadow:inset 0 0 0 1px #6d5218; } +.data-table-core.selection-blue .data-row.is-selected { position:relative;background:linear-gradient(90deg,#132b43 0,#0b1824 58%,#070a0d 100%);outline:1px solid #3b91bd;outline-offset:-1px;box-shadow:inset 0 0 0 1px #174963; } +.table-note-row { min-height:34px;display:block;background:linear-gradient(90deg,#17130b,#080908); } +.table-note-row > div { height:34px;padding:0 10px;display:flex;align-items:center;gap:14px;border:0;color:#9e936d; } +.table-note-row strong { color:#d7bc62;font-weight:400; } +.table-note-row .table-note-actions { margin-left:auto;display:flex;gap:9px; } +.table-note-row img { max-width:13px;max-height:13px;image-rendering:pixelated; } +.table-row .status { color:var(--info); }.table-row .success { color:var(--success); }.table-row .danger { color:var(--danger); } +.table-row .epic-text { color:var(--quality-epic); }.table-row .rare-text { color:var(--quality-artifact); } +.table-icon { display:flex;align-items:center;justify-content:center; }.table-icon img { width:28px;height:28px;image-rendering:pixelated; } + +.progress { position:relative;height:14px;background:#0a0b0a;border:1px solid #3c3425; }.progress-fill { height:100%;width:var(--value,50%);background:linear-gradient(#9abe23,#63820a);box-shadow:inset 0 0 0 1px #cce43c; }.progress-marker { position:absolute;top:-5px;width:0;height:0;border-left:4px solid transparent;border-right:4px solid transparent;border-top:5px solid #d7bd61;left:var(--left,50%); } +.badge-demo { display:flex;gap:18px;align-items:center; }.badge-anchor { position:relative;width:42px;height:42px;display:flex;align-items:center;justify-content:center;border:1px solid #48412f;background:#171817;border-radius:8px; }.badge-anchor > img:first-child { max-width:24px;max-height:24px;image-rendering:pixelated; }.alert-badge { position:absolute;right:-2px;top:-2px;width:12px;height:12px;image-rendering:pixelated; }.level-badge { width:42px;height:54px;display:flex;align-items:center;justify-content:center;border:1px solid #6b5432;background:linear-gradient(#22231f,#111210);color:#e3bf46;font-size:11px; } + +.table-variant-board { display:grid;grid-template-rows:560px minmax(0,1fr);gap:18px; } +.table-variant-grid { min-height:0; }.table-variant-grid > .panel { min-height:0; }.table-variant-grid .panel-body { height:calc(100% - 46px);display:flex;flex-direction:column; }.table-variant-spec { margin-top:auto;padding-top:10px; } +.skill-damage-table { position:relative;height:472px;padding-right:15px;display:flex;flex-direction:column;border-color:#463820;background:#010201; } +.skill-table-row { display:grid;grid-template-columns:.56fr 1fr 1fr 1fr .74fr 42px;align-items:center;color:#c6a659;font-size:13px;font-variant-numeric:tabular-nums; } +.skill-table-row > * { min-width:0;padding:0 11px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis; } +.skill-table-row.header { flex:0 0 30px;column-gap:1px;background:#030403;color:#bc9e58;font-size:14px;text-align:center; } +.skill-table-row.header > * { height:30px;padding:0 6px;display:flex;align-items:center;justify-content:center; } +.skill-table-row.header > :nth-child(5) { grid-column:5 / 7; } +.skill-table-row.header > :nth-child(6) { display:none; } +.skill-table-body { flex:0 0 360px;min-height:0;overflow:hidden;background:#010201; } +.skill-table-body .skill-table-row { height:40px;border:0;background:#010201; } +.skill-name-cell { display:grid!important;grid-template-columns:24px 36px;align-items:center;gap:5px;padding-left:8px!important; } +.skill-name-cell b { color:#c7a557;font-weight:400;text-align:right; } +.skill-name-cell img { width:34px;height:34px;image-rendering:pixelated;filter:sepia(.9) saturate(3.2) hue-rotate(350deg) brightness(1.08) contrast(1.04); } +.table-action-button,.inspect-button { + --action-top:#1261a4; + --action-bottom:#071f3b; + --action-edge-top:#5b472a; + --action-edge-bottom:#5b472a; + appearance:none; + padding:0; + display:inline-flex; + align-items:center; + justify-content:center; + border:2px solid transparent; + border-radius:0; + background: + linear-gradient(180deg,var(--action-top),var(--action-bottom)) padding-box, + linear-gradient(180deg,var(--action-edge-top),var(--action-edge-bottom)) border-box; + box-shadow:0 0 0 1px rgba(0,0,0,.3),inset 0 0 0 1px #0f0f0f; + line-height:0; + cursor:pointer; +} +.table-action-button:hover,.inspect-button:hover { --action-top:#1d9bdb;--action-bottom:#0b325e;--action-edge-top:#927243;--action-edge-bottom:#927243; } +.table-action-button:active,.inspect-button:active { --action-top:#1d9bdb;--action-bottom:#0b325e;--action-edge-top:#927243;--action-edge-bottom:#927243;transform:translateY(1px); } +.table-action-button:disabled,.inspect-button:disabled { --action-top:#5b5b5b;--action-bottom:#212121;--action-edge-top:#424242;--action-edge-bottom:#424242;cursor:default; } +.table-action-button { width:28px;height:28px; }.table-action-button img { max-width:16px;max-height:16px;image-rendering:auto; } +.skill-summary { flex:0 0 47px;border-top:1px solid #47463f;border-bottom:1px solid #383832;background:#010201;color:#c8a75d; } +.skill-summary > :first-child { padding-left:28px;font-size:18px;font-weight:700; } +.skill-table-footer { flex:0 0 34px;padding:0 10px;display:flex;align-items:center;border-bottom:1px solid #33342f;background:#010201; } +.skill-table-footer button { appearance:none;height:28px;padding:0 15px 0 1px;border:0;border-right:1px solid #51514a;border-radius:0;background:none;color:#d1af62;font:700 17px/1 "DCalc",SimSun,sans-serif; } +.skill-table-scrollbar { position:absolute;top:30px;right:0;bottom:81px;width:15px;display:grid;grid-template-rows:15px 1fr 15px;border-left:1px solid #2b2924;background:#050606; } +.skill-scroll-arrow { display:flex;align-items:center;justify-content:center;border:1px solid #514229;background:linear-gradient(#24241f,#10110f); } +.skill-scroll-arrow::before { content:"";width:0;height:0;border-left:4px solid transparent;border-right:4px solid transparent;border-bottom:4px solid #a98b46;filter:drop-shadow(0 1px 0 #000); } +.skill-scroll-arrow:last-child::before { border-bottom:0;border-top:4px solid #a98b46; } +.skill-scroll-track { position:relative;background:linear-gradient(90deg,#080908,#151513,#070807); } +.skill-scroll-thumb { position:absolute;left:2px;right:2px;top:8px;height:78px;border:1px solid #68532d;background:linear-gradient(90deg,#1b1d1c,#363530,#161817); } + +.compact-data-table { position:relative;height:184px;padding:4px 18px 5px 5px;border:1px solid #4b3b2a;background:#020302;overflow:hidden; } +.compact-table-row { height:20px;display:grid;grid-template-columns:.78fr .82fr 1.2fr;align-items:center;color:#c9bd84;font-size:11px; } +.compact-table-row > * { min-width:0;padding:0 9px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis; } +.compact-table-row.header { height:30px;margin-bottom:5px;column-gap:1px; } +.compact-table-body { display:flex;flex-direction:column;gap:5px; } +.compact-table-body .compact-table-row { height:20px;border:1px solid #222522;border-radius:0;background:linear-gradient(180deg,#171917 0,#0d0f0e 42%,#070808 100%);box-shadow:inset 0 1px 0 #202220,inset 0 -1px 0 #050605; } +.compact-table-scrollbar { position:absolute;top:4px;right:3px;bottom:5px;width:12px;display:grid;grid-template-rows:16px 1fr 16px;border-left:1px solid #20221f;background:#050606; } +.compact-table-scrollbar .skill-scroll-arrow { border-color:#31342f;background:linear-gradient(#171917,#0b0c0b); } +.compact-table-scrollbar .skill-scroll-arrow::before { border-left-width:3px;border-right-width:3px;border-bottom-width:4px;opacity:.72; } +.compact-table-scrollbar .skill-scroll-arrow:last-child::before { border-bottom:0;border-top:4px solid #8b794d; } +.compact-table-scrollbar .skill-scroll-thumb { top:8px;height:54px;border-color:#4b4433;background:linear-gradient(90deg,#111312,#2a2b27,#101211); } + +/* DataTable ItemRow: 43 rest, 44 hover, 46 selected. */ +.item-data-table { border:0;background:transparent;overflow:visible; } +.item-table-row { position:relative;min-height:38px;display:grid;grid-template-columns:34px 32px 50px minmax(90px,1.55fr) 76px .92fr 1.1fr;align-items:center;color:#cabd82;font-size:11px;isolation:isolate; } +.item-table-row > *:not(.item-row-frame) { min-width:0;padding:0 7px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis; } +.item-table-row.header { min-height:30px;height:30px;margin-bottom:5px;column-gap:1px;grid-template-columns:66px 50px minmax(90px,1.55fr) 76px .92fr 1.1fr; } +.item-table-body { display:flex;flex-direction:column;gap:4px; } +.item-table-body .item-table-row { + --dt-outer:rgba(0,0,0,.012);--dt-middle:#000;--dt-accent:rgba(43,43,43,.85);--dt-inner:rgba(18,18,18,.73); + --dt-surface:linear-gradient(180deg,rgba(29,29,29,.7),rgba(13,13,13,.7)); + cursor:pointer; +} +.item-table-body .item-table-row:hover { --dt-outer:#000820;--dt-middle:#082068;--dt-accent:#1888b8;--dt-inner:#082040;--dt-surface:#000810; } +.item-table-body .item-table-row.is-selected { --dt-outer:#201808;--dt-middle:#604818;--dt-accent:#e8a828;--dt-inner:#302008;--dt-surface:#100800; } +.item-table-body .item-table-row::before, +.item-table-body .item-table-row::after, +.item-row-frame, +.item-row-frame::before, +.item-row-frame::after { content:"";position:absolute;pointer-events:none; } +.item-table-body .item-table-row::before { z-index:-3;inset:0;background:var(--dt-outer);border-radius:4px; } +.item-table-body .item-row-frame { z-index:-2;inset:1px;background:var(--dt-middle);border-radius:3px;clip-path:none;filter:none; } +.item-table-body .item-row-frame::before { inset:1px;background:var(--dt-accent);border-radius:2px;clip-path:none; } +.item-table-body .item-row-frame::after { inset:2px;background:var(--dt-inner);border-radius:1px;clip-path:none; } +.item-table-body .item-table-row::after { z-index:-1;inset:4px;background:var(--dt-surface);border-radius:1px;clip-path:none;filter:none; } +.item-row-icon { width:32px;height:34px;padding:0!important;display:flex;align-items:center;justify-content:center; } +.item-row-icon img { max-width:26px;max-height:26px;image-rendering:pixelated; } +.inspect-button { width:28px;height:24px; } +.inspect-button img { max-width:16px;max-height:16px;image-rendering:pixelated; } diff --git a/design/src-web/dialog/component.js b/design/src-web/dialog/component.js new file mode 100644 index 00000000..6b3a2ea4 --- /dev/null +++ b/design/src-web/dialog/component.js @@ -0,0 +1,4 @@ +(() => { + window.componentRegistry ||= {}; + window.componentRegistry["src-web/dialog/index.html"] = {"construction":"
\n
9-slice window surface
NORMALIZED
\n
\n
\n
\n
\n
\n
\n
\n
\n
Corners4 个角保持原尺寸
\n
Edges沿单轴平铺或拉伸
\n
Center语义 Surface token
\n
Titlebar钢蓝渐变独立构造
\n
\n
\n
\n
\n
组件预览窗口
\n
Content Slot / Auto Layout
\n
\n
\n
","showcase":"
\n
WindowDialog / UtilitySheet
Shared chrome, separate visual families
\n
\n
\n
游戏设置
\n
\n
\n
首页
声音
游戏
\n
简易设置
画面品质
高品质
UI 大小
39%
\n
\n
\n \n
\n\n
\n
装扮栏
\n
物品栏
装扮
宠物
\n
\n
\n
\n \n
\n
\n
"}; +})(); diff --git a/design/src-web/dialog/img/equipment-rarity/epic.png b/design/src-web/dialog/img/equipment-rarity/epic.png new file mode 100644 index 00000000..9166969d Binary files /dev/null and b/design/src-web/dialog/img/equipment-rarity/epic.png differ diff --git a/design/src-web/dialog/img/equipment-rarity/rare.png b/design/src-web/dialog/img/equipment-rarity/rare.png new file mode 100644 index 00000000..618085ed Binary files /dev/null and b/design/src-web/dialog/img/equipment-rarity/rare.png differ diff --git a/design/src-web/dialog/img/sprite_interface.NPK/windowcommon.chn.img/618.PNG b/design/src-web/dialog/img/sprite_interface.NPK/windowcommon.chn.img/618.PNG new file mode 100644 index 00000000..ebbe15d1 Binary files /dev/null and b/design/src-web/dialog/img/sprite_interface.NPK/windowcommon.chn.img/618.PNG differ diff --git a/design/src-web/dialog/img/sprite_interface.NPK/windowcommon_2x.img/6.PNG b/design/src-web/dialog/img/sprite_interface.NPK/windowcommon_2x.img/6.PNG new file mode 100644 index 00000000..eabf06e5 Binary files /dev/null and b/design/src-web/dialog/img/sprite_interface.NPK/windowcommon_2x.img/6.PNG differ diff --git a/design/src-web/dialog/img/sprite_interface.NPK/windowheadereffect.img/0.PNG b/design/src-web/dialog/img/sprite_interface.NPK/windowheadereffect.img/0.PNG new file mode 100644 index 00000000..e5216092 Binary files /dev/null and b/design/src-web/dialog/img/sprite_interface.NPK/windowheadereffect.img/0.PNG differ diff --git a/design/src-web/dialog/img/sprite_interface.NPK/windowheadereffect.img/1.PNG b/design/src-web/dialog/img/sprite_interface.NPK/windowheadereffect.img/1.PNG new file mode 100644 index 00000000..b589c7a4 Binary files /dev/null and b/design/src-web/dialog/img/sprite_interface.NPK/windowheadereffect.img/1.PNG differ diff --git a/design/src-web/dialog/img/sprite_interface.NPK/windowheadereffect.img/10.PNG b/design/src-web/dialog/img/sprite_interface.NPK/windowheadereffect.img/10.PNG new file mode 100644 index 00000000..32cba177 Binary files /dev/null and b/design/src-web/dialog/img/sprite_interface.NPK/windowheadereffect.img/10.PNG differ diff --git a/design/src-web/dialog/img/sprite_interface.NPK/windowheadereffect.img/11.PNG b/design/src-web/dialog/img/sprite_interface.NPK/windowheadereffect.img/11.PNG new file mode 100644 index 00000000..5c7f029f Binary files /dev/null and b/design/src-web/dialog/img/sprite_interface.NPK/windowheadereffect.img/11.PNG differ diff --git a/design/src-web/dialog/img/sprite_interface.NPK/windowheadereffect.img/12.PNG b/design/src-web/dialog/img/sprite_interface.NPK/windowheadereffect.img/12.PNG new file mode 100644 index 00000000..5a7c2f16 Binary files /dev/null and b/design/src-web/dialog/img/sprite_interface.NPK/windowheadereffect.img/12.PNG differ diff --git a/design/src-web/dialog/img/sprite_interface.NPK/windowheadereffect.img/13.PNG b/design/src-web/dialog/img/sprite_interface.NPK/windowheadereffect.img/13.PNG new file mode 100644 index 00000000..8d3fa237 Binary files /dev/null and b/design/src-web/dialog/img/sprite_interface.NPK/windowheadereffect.img/13.PNG differ diff --git a/design/src-web/dialog/img/sprite_interface.NPK/windowheadereffect.img/14.PNG b/design/src-web/dialog/img/sprite_interface.NPK/windowheadereffect.img/14.PNG new file mode 100644 index 00000000..31f76e45 Binary files /dev/null and b/design/src-web/dialog/img/sprite_interface.NPK/windowheadereffect.img/14.PNG differ diff --git a/design/src-web/dialog/img/sprite_interface.NPK/windowheadereffect.img/15.PNG b/design/src-web/dialog/img/sprite_interface.NPK/windowheadereffect.img/15.PNG new file mode 100644 index 00000000..ef039dda Binary files /dev/null and b/design/src-web/dialog/img/sprite_interface.NPK/windowheadereffect.img/15.PNG differ diff --git a/design/src-web/dialog/img/sprite_interface.NPK/windowheadereffect.img/16.PNG b/design/src-web/dialog/img/sprite_interface.NPK/windowheadereffect.img/16.PNG new file mode 100644 index 00000000..d7c07681 Binary files /dev/null and b/design/src-web/dialog/img/sprite_interface.NPK/windowheadereffect.img/16.PNG differ diff --git a/design/src-web/dialog/img/sprite_interface.NPK/windowheadereffect.img/17.PNG b/design/src-web/dialog/img/sprite_interface.NPK/windowheadereffect.img/17.PNG new file mode 100644 index 00000000..56a4d6b8 Binary files /dev/null and b/design/src-web/dialog/img/sprite_interface.NPK/windowheadereffect.img/17.PNG differ diff --git a/design/src-web/dialog/img/sprite_interface.NPK/windowheadereffect.img/18.PNG b/design/src-web/dialog/img/sprite_interface.NPK/windowheadereffect.img/18.PNG new file mode 100644 index 00000000..49d34e32 Binary files /dev/null and b/design/src-web/dialog/img/sprite_interface.NPK/windowheadereffect.img/18.PNG differ diff --git a/design/src-web/dialog/img/sprite_interface.NPK/windowheadereffect.img/19.PNG b/design/src-web/dialog/img/sprite_interface.NPK/windowheadereffect.img/19.PNG new file mode 100644 index 00000000..aeec3c38 Binary files /dev/null and b/design/src-web/dialog/img/sprite_interface.NPK/windowheadereffect.img/19.PNG differ diff --git a/design/src-web/dialog/img/sprite_interface.NPK/windowheadereffect.img/2.PNG b/design/src-web/dialog/img/sprite_interface.NPK/windowheadereffect.img/2.PNG new file mode 100644 index 00000000..183e1338 Binary files /dev/null and b/design/src-web/dialog/img/sprite_interface.NPK/windowheadereffect.img/2.PNG differ diff --git a/design/src-web/dialog/img/sprite_interface.NPK/windowheadereffect.img/20.PNG b/design/src-web/dialog/img/sprite_interface.NPK/windowheadereffect.img/20.PNG new file mode 100644 index 00000000..3329a97b Binary files /dev/null and b/design/src-web/dialog/img/sprite_interface.NPK/windowheadereffect.img/20.PNG differ diff --git a/design/src-web/dialog/img/sprite_interface.NPK/windowheadereffect.img/21.PNG b/design/src-web/dialog/img/sprite_interface.NPK/windowheadereffect.img/21.PNG new file mode 100644 index 00000000..cc6108f6 Binary files /dev/null and b/design/src-web/dialog/img/sprite_interface.NPK/windowheadereffect.img/21.PNG differ diff --git a/design/src-web/dialog/img/sprite_interface.NPK/windowheadereffect.img/22.PNG b/design/src-web/dialog/img/sprite_interface.NPK/windowheadereffect.img/22.PNG new file mode 100644 index 00000000..27634230 Binary files /dev/null and b/design/src-web/dialog/img/sprite_interface.NPK/windowheadereffect.img/22.PNG differ diff --git a/design/src-web/dialog/img/sprite_interface.NPK/windowheadereffect.img/23.PNG b/design/src-web/dialog/img/sprite_interface.NPK/windowheadereffect.img/23.PNG new file mode 100644 index 00000000..eae2c088 Binary files /dev/null and b/design/src-web/dialog/img/sprite_interface.NPK/windowheadereffect.img/23.PNG differ diff --git a/design/src-web/dialog/img/sprite_interface.NPK/windowheadereffect.img/24.PNG b/design/src-web/dialog/img/sprite_interface.NPK/windowheadereffect.img/24.PNG new file mode 100644 index 00000000..f3bb5b7f Binary files /dev/null and b/design/src-web/dialog/img/sprite_interface.NPK/windowheadereffect.img/24.PNG differ diff --git a/design/src-web/dialog/img/sprite_interface.NPK/windowheadereffect.img/25.PNG b/design/src-web/dialog/img/sprite_interface.NPK/windowheadereffect.img/25.PNG new file mode 100644 index 00000000..1f29a2a9 Binary files /dev/null and b/design/src-web/dialog/img/sprite_interface.NPK/windowheadereffect.img/25.PNG differ diff --git a/design/src-web/dialog/img/sprite_interface.NPK/windowheadereffect.img/26.PNG b/design/src-web/dialog/img/sprite_interface.NPK/windowheadereffect.img/26.PNG new file mode 100644 index 00000000..24821e9b Binary files /dev/null and b/design/src-web/dialog/img/sprite_interface.NPK/windowheadereffect.img/26.PNG differ diff --git a/design/src-web/dialog/img/sprite_interface.NPK/windowheadereffect.img/27.PNG b/design/src-web/dialog/img/sprite_interface.NPK/windowheadereffect.img/27.PNG new file mode 100644 index 00000000..58f14de2 Binary files /dev/null and b/design/src-web/dialog/img/sprite_interface.NPK/windowheadereffect.img/27.PNG differ diff --git a/design/src-web/dialog/img/sprite_interface.NPK/windowheadereffect.img/28.PNG b/design/src-web/dialog/img/sprite_interface.NPK/windowheadereffect.img/28.PNG new file mode 100644 index 00000000..e323856b Binary files /dev/null and b/design/src-web/dialog/img/sprite_interface.NPK/windowheadereffect.img/28.PNG differ diff --git a/design/src-web/dialog/img/sprite_interface.NPK/windowheadereffect.img/29.PNG b/design/src-web/dialog/img/sprite_interface.NPK/windowheadereffect.img/29.PNG new file mode 100644 index 00000000..ce047365 Binary files /dev/null and b/design/src-web/dialog/img/sprite_interface.NPK/windowheadereffect.img/29.PNG differ diff --git a/design/src-web/dialog/img/sprite_interface.NPK/windowheadereffect.img/3.PNG b/design/src-web/dialog/img/sprite_interface.NPK/windowheadereffect.img/3.PNG new file mode 100644 index 00000000..2b158bda Binary files /dev/null and b/design/src-web/dialog/img/sprite_interface.NPK/windowheadereffect.img/3.PNG differ diff --git a/design/src-web/dialog/img/sprite_interface.NPK/windowheadereffect.img/30.PNG b/design/src-web/dialog/img/sprite_interface.NPK/windowheadereffect.img/30.PNG new file mode 100644 index 00000000..723163bf Binary files /dev/null and b/design/src-web/dialog/img/sprite_interface.NPK/windowheadereffect.img/30.PNG differ diff --git a/design/src-web/dialog/img/sprite_interface.NPK/windowheadereffect.img/31.PNG b/design/src-web/dialog/img/sprite_interface.NPK/windowheadereffect.img/31.PNG new file mode 100644 index 00000000..4946e0e5 Binary files /dev/null and b/design/src-web/dialog/img/sprite_interface.NPK/windowheadereffect.img/31.PNG differ diff --git a/design/src-web/dialog/img/sprite_interface.NPK/windowheadereffect.img/32.PNG b/design/src-web/dialog/img/sprite_interface.NPK/windowheadereffect.img/32.PNG new file mode 100644 index 00000000..9c3e2188 Binary files /dev/null and b/design/src-web/dialog/img/sprite_interface.NPK/windowheadereffect.img/32.PNG differ diff --git a/design/src-web/dialog/img/sprite_interface.NPK/windowheadereffect.img/33.PNG b/design/src-web/dialog/img/sprite_interface.NPK/windowheadereffect.img/33.PNG new file mode 100644 index 00000000..4bf072de Binary files /dev/null and b/design/src-web/dialog/img/sprite_interface.NPK/windowheadereffect.img/33.PNG differ diff --git a/design/src-web/dialog/img/sprite_interface.NPK/windowheadereffect.img/34.PNG b/design/src-web/dialog/img/sprite_interface.NPK/windowheadereffect.img/34.PNG new file mode 100644 index 00000000..e3430d42 Binary files /dev/null and b/design/src-web/dialog/img/sprite_interface.NPK/windowheadereffect.img/34.PNG differ diff --git a/design/src-web/dialog/img/sprite_interface.NPK/windowheadereffect.img/35.PNG b/design/src-web/dialog/img/sprite_interface.NPK/windowheadereffect.img/35.PNG new file mode 100644 index 00000000..08c1f486 Binary files /dev/null and b/design/src-web/dialog/img/sprite_interface.NPK/windowheadereffect.img/35.PNG differ diff --git a/design/src-web/dialog/img/sprite_interface.NPK/windowheadereffect.img/36.PNG b/design/src-web/dialog/img/sprite_interface.NPK/windowheadereffect.img/36.PNG new file mode 100644 index 00000000..d02e5d4a Binary files /dev/null and b/design/src-web/dialog/img/sprite_interface.NPK/windowheadereffect.img/36.PNG differ diff --git a/design/src-web/dialog/img/sprite_interface.NPK/windowheadereffect.img/37.PNG b/design/src-web/dialog/img/sprite_interface.NPK/windowheadereffect.img/37.PNG new file mode 100644 index 00000000..a347f0cd Binary files /dev/null and b/design/src-web/dialog/img/sprite_interface.NPK/windowheadereffect.img/37.PNG differ diff --git a/design/src-web/dialog/img/sprite_interface.NPK/windowheadereffect.img/38.PNG b/design/src-web/dialog/img/sprite_interface.NPK/windowheadereffect.img/38.PNG new file mode 100644 index 00000000..2363255f Binary files /dev/null and b/design/src-web/dialog/img/sprite_interface.NPK/windowheadereffect.img/38.PNG differ diff --git a/design/src-web/dialog/img/sprite_interface.NPK/windowheadereffect.img/39.PNG b/design/src-web/dialog/img/sprite_interface.NPK/windowheadereffect.img/39.PNG new file mode 100644 index 00000000..ed349ed5 Binary files /dev/null and b/design/src-web/dialog/img/sprite_interface.NPK/windowheadereffect.img/39.PNG differ diff --git a/design/src-web/dialog/img/sprite_interface.NPK/windowheadereffect.img/4.PNG b/design/src-web/dialog/img/sprite_interface.NPK/windowheadereffect.img/4.PNG new file mode 100644 index 00000000..413b8f3a Binary files /dev/null and b/design/src-web/dialog/img/sprite_interface.NPK/windowheadereffect.img/4.PNG differ diff --git a/design/src-web/dialog/img/sprite_interface.NPK/windowheadereffect.img/40.PNG b/design/src-web/dialog/img/sprite_interface.NPK/windowheadereffect.img/40.PNG new file mode 100644 index 00000000..66814eb3 Binary files /dev/null and b/design/src-web/dialog/img/sprite_interface.NPK/windowheadereffect.img/40.PNG differ diff --git a/design/src-web/dialog/img/sprite_interface.NPK/windowheadereffect.img/41.PNG b/design/src-web/dialog/img/sprite_interface.NPK/windowheadereffect.img/41.PNG new file mode 100644 index 00000000..f7aa711c Binary files /dev/null and b/design/src-web/dialog/img/sprite_interface.NPK/windowheadereffect.img/41.PNG differ diff --git a/design/src-web/dialog/img/sprite_interface.NPK/windowheadereffect.img/42.PNG b/design/src-web/dialog/img/sprite_interface.NPK/windowheadereffect.img/42.PNG new file mode 100644 index 00000000..d6e39cb5 Binary files /dev/null and b/design/src-web/dialog/img/sprite_interface.NPK/windowheadereffect.img/42.PNG differ diff --git a/design/src-web/dialog/img/sprite_interface.NPK/windowheadereffect.img/43.PNG b/design/src-web/dialog/img/sprite_interface.NPK/windowheadereffect.img/43.PNG new file mode 100644 index 00000000..e43d9dd6 Binary files /dev/null and b/design/src-web/dialog/img/sprite_interface.NPK/windowheadereffect.img/43.PNG differ diff --git a/design/src-web/dialog/img/sprite_interface.NPK/windowheadereffect.img/44.PNG b/design/src-web/dialog/img/sprite_interface.NPK/windowheadereffect.img/44.PNG new file mode 100644 index 00000000..053d444d Binary files /dev/null and b/design/src-web/dialog/img/sprite_interface.NPK/windowheadereffect.img/44.PNG differ diff --git a/design/src-web/dialog/img/sprite_interface.NPK/windowheadereffect.img/5.PNG b/design/src-web/dialog/img/sprite_interface.NPK/windowheadereffect.img/5.PNG new file mode 100644 index 00000000..72bf764b Binary files /dev/null and b/design/src-web/dialog/img/sprite_interface.NPK/windowheadereffect.img/5.PNG differ diff --git a/design/src-web/dialog/img/sprite_interface.NPK/windowheadereffect.img/6.PNG b/design/src-web/dialog/img/sprite_interface.NPK/windowheadereffect.img/6.PNG new file mode 100644 index 00000000..effb1c49 Binary files /dev/null and b/design/src-web/dialog/img/sprite_interface.NPK/windowheadereffect.img/6.PNG differ diff --git a/design/src-web/dialog/img/sprite_interface.NPK/windowheadereffect.img/7.PNG b/design/src-web/dialog/img/sprite_interface.NPK/windowheadereffect.img/7.PNG new file mode 100644 index 00000000..3f1fc0a6 Binary files /dev/null and b/design/src-web/dialog/img/sprite_interface.NPK/windowheadereffect.img/7.PNG differ diff --git a/design/src-web/dialog/img/sprite_interface.NPK/windowheadereffect.img/8.PNG b/design/src-web/dialog/img/sprite_interface.NPK/windowheadereffect.img/8.PNG new file mode 100644 index 00000000..d82b86b0 Binary files /dev/null and b/design/src-web/dialog/img/sprite_interface.NPK/windowheadereffect.img/8.PNG differ diff --git a/design/src-web/dialog/img/sprite_interface.NPK/windowheadereffect.img/9.PNG b/design/src-web/dialog/img/sprite_interface.NPK/windowheadereffect.img/9.PNG new file mode 100644 index 00000000..8d2d6a8b Binary files /dev/null and b/design/src-web/dialog/img/sprite_interface.NPK/windowheadereffect.img/9.PNG differ diff --git a/design/src-web/dialog/img/sprite_interface2_option.NPK/option.img/82.PNG b/design/src-web/dialog/img/sprite_interface2_option.NPK/option.img/82.PNG new file mode 100644 index 00000000..2fe27054 Binary files /dev/null and b/design/src-web/dialog/img/sprite_interface2_option.NPK/option.img/82.PNG differ diff --git a/design/src-web/dialog/img/sprite_interface2_option.NPK/option.img/94.PNG b/design/src-web/dialog/img/sprite_interface2_option.NPK/option.img/94.PNG new file mode 100644 index 00000000..23ca3d47 Binary files /dev/null and b/design/src-web/dialog/img/sprite_interface2_option.NPK/option.img/94.PNG differ diff --git a/design/src-web/dialog/img/sprite_interface2_option.NPK/option.img/97.PNG b/design/src-web/dialog/img/sprite_interface2_option.NPK/option.img/97.PNG new file mode 100644 index 00000000..94278fbd Binary files /dev/null and b/design/src-web/dialog/img/sprite_interface2_option.NPK/option.img/97.PNG differ diff --git a/design/src-web/dialog/img/sprite_item.NPK/equipmentskill.img/0.PNG b/design/src-web/dialog/img/sprite_item.NPK/equipmentskill.img/0.PNG new file mode 100644 index 00000000..6e0b1e48 Binary files /dev/null and b/design/src-web/dialog/img/sprite_item.NPK/equipmentskill.img/0.PNG differ diff --git a/design/src-web/dialog/img/sprite_item.NPK/equipmentskill.img/1.PNG b/design/src-web/dialog/img/sprite_item.NPK/equipmentskill.img/1.PNG new file mode 100644 index 00000000..d7f2db60 Binary files /dev/null and b/design/src-web/dialog/img/sprite_item.NPK/equipmentskill.img/1.PNG differ diff --git a/design/src-web/dialog/img/sprite_item.NPK/equipmentskill.img/2.PNG b/design/src-web/dialog/img/sprite_item.NPK/equipmentskill.img/2.PNG new file mode 100644 index 00000000..13fa3616 Binary files /dev/null and b/design/src-web/dialog/img/sprite_item.NPK/equipmentskill.img/2.PNG differ diff --git a/design/src-web/dialog/img/sprite_item.NPK/equipmentskill.img/3.PNG b/design/src-web/dialog/img/sprite_item.NPK/equipmentskill.img/3.PNG new file mode 100644 index 00000000..db40e39f Binary files /dev/null and b/design/src-web/dialog/img/sprite_item.NPK/equipmentskill.img/3.PNG differ diff --git a/design/src-web/dialog/img/sprite_item.NPK/equipmentskill.img/4.PNG b/design/src-web/dialog/img/sprite_item.NPK/equipmentskill.img/4.PNG new file mode 100644 index 00000000..4d3ffb0e Binary files /dev/null and b/design/src-web/dialog/img/sprite_item.NPK/equipmentskill.img/4.PNG differ diff --git a/design/src-web/dialog/img/sprite_item.NPK/equipmentskill.img/7.PNG b/design/src-web/dialog/img/sprite_item.NPK/equipmentskill.img/7.PNG new file mode 100644 index 00000000..065856e0 Binary files /dev/null and b/design/src-web/dialog/img/sprite_item.NPK/equipmentskill.img/7.PNG differ diff --git a/design/src-web/dialog/img/sprite_item.NPK/equipmentskill.img/8.PNG b/design/src-web/dialog/img/sprite_item.NPK/equipmentskill.img/8.PNG new file mode 100644 index 00000000..fea1b324 Binary files /dev/null and b/design/src-web/dialog/img/sprite_item.NPK/equipmentskill.img/8.PNG differ diff --git a/design/src-web/dialog/img/sprite_item.NPK/equipmentskill.img/9.PNG b/design/src-web/dialog/img/sprite_item.NPK/equipmentskill.img/9.PNG new file mode 100644 index 00000000..63b66ad9 Binary files /dev/null and b/design/src-web/dialog/img/sprite_item.NPK/equipmentskill.img/9.PNG differ diff --git a/design/src-web/dialog/index.html b/design/src-web/dialog/index.html new file mode 100644 index 00000000..66793860 --- /dev/null +++ b/design/src-web/dialog/index.html @@ -0,0 +1,67 @@ + + + + + + + dialog component catalog + + + + + + + + + diff --git a/design/src-web/dialog/style/index.css b/design/src-web/dialog/style/index.css new file mode 100644 index 00000000..9b2a6f8b --- /dev/null +++ b/design/src-web/dialog/style/index.css @@ -0,0 +1,298 @@ +/* Source module: dialog.css */ +.window { + border: 1px solid #6c5a37; + background: #050606; + box-shadow: + 0 18px 38px rgba(0, 0, 0, 0.8), + inset 0 0 0 1px #0e1418; + overflow: hidden; +} +.window-titlebar { + position: relative; + isolation: isolate; + overflow: hidden; + height: 28px; + display: grid; + grid-template-columns: 1fr auto 1fr; + align-items: center; + padding: 0 8px; + background: linear-gradient(#5a7099, #415272 55%, #313e58); + border-bottom: 1px solid #1d2735; + color: #f0f2ef; + text-shadow: 0 1px 1px #000; + font-size: 13px; + transition: + background 0.12s linear, + color 0.12s linear; +} +.window-titlebar > :not(.window-title-effect) { + position: relative; + z-index: 2; +} +.window-titlebar .title { + grid-column: 2; +} +.window-titlebar .close { + width: 10px; + height: 9px; + image-rendering: auto; +} +.window-titlebar > .dialog-icon-button { + grid-column: 3; + justify-self: end; +} +.window-titlebar .title-actions { + grid-column: 3; + justify-self: end; + display: flex; + align-items: center; + gap: 8px; +} +.window-titlebar .title-actions img { + flex: 0 0 auto; + image-rendering: pixelated; + object-fit: contain; +} +.dialog-icon-button { + appearance: none; + width: 20px; + height: 20px; + padding: 0; + display: inline-flex; + align-items: center; + justify-content: center; + border: 0; + background: none; + box-shadow: none; + cursor: pointer; +} +.dialog-icon-button > img { + display: block; + transform: translateY(0); + filter: brightness(1); +} +.dialog-icon-button:hover > img, +.dialog-icon-button:focus-visible > img, +.dialog-icon-button:active > img { + filter: brightness(1.28); +} +.dialog-icon-button:focus-visible { + outline: 1px solid rgba(225, 204, 135, 0.72); + outline-offset: -2px; +} +.dialog-icon-button:active > img { + transform: translateY(1px); +} +.dialog-icon-button[aria-pressed="true"] > img { + filter: brightness(1.28); +} +.window.is-unfocused > .window-titlebar { + background: linear-gradient(#303b50, #263247 56%, #1d2839); + color: #8993a0; + text-shadow: 0 1px 1px #0a0d12; +} +.window.is-focused > .window-titlebar { + background: linear-gradient(#6079a5, #435a80 55%, #30425f); + color: #f4f6f2; +} +.window-title-effect { + position: absolute; + z-index: 1; + left: 50%; + top: 0; + width: 1100px; + height: 100%; + max-width: none; + transform: translateX(-50%); + object-fit: fill; + pointer-events: none; + mix-blend-mode: screen; + filter: brightness(1.55) contrast(1.06); + opacity: 0.72; + image-rendering: auto; +} +.window.is-unfocused > .window-titlebar .window-title-effect { + display: none; +} +.window-content { + min-height: 230px; + padding: 14px; + background: linear-gradient( + 135deg, + rgba(31, 36, 40, 0.82), + rgba(4, 5, 5, 0.98) + ); +} +.window-footer { + height: 38px; + padding: 4px 8px; + display: flex; + align-items: center; + justify-content: flex-end; + gap: 8px; + border-top: 1px solid #332c22; + background: linear-gradient(#20201d, #11110f); +} +.dialog-body-shell { + padding: 10px !important; + background: rgba(4, 5, 5, 0.82) !important; +} +.dialog-content-well { + min-height: 0; + padding: 0; + border: 1px solid #262824; + background: #000; + color: var(--gold); +} +.dialog-body-shell > .dialog-content-well { + min-height: 248px; +} +.dialog-footer { + position: relative; + background: rgba(4, 5, 5, 0.82); + border-top-color: #2b2924; +} +.dialog-status { + min-width: 0; + margin-right: auto; + color: #8fc885; + font-size: 11px; + line-height: 1; + white-space: nowrap; +} +.dialog-status:empty { display: none; } +.dialog-status.is-updated { animation: dialog-status-pulse 0.32s ease-out; } +@keyframes dialog-status-pulse { + from { opacity: 0.35; transform: translateY(1px); } + to { opacity: 1; transform: translateY(0); } +} +.window.is-demo-dismissed { animation: dialog-dismiss-feedback 0.28s ease-out; } +@keyframes dialog-dismiss-feedback { + 50% { opacity: 0.58; } +} + +.sheet-filter-button { + appearance: none; + padding: 2px 3px; + border: 0; + background: none; + color: #9c8e64; + font: inherit; + cursor: pointer; +} +.sheet-filter-button:hover, +.sheet-filter-button:focus-visible, +.sheet-filter-button:active, +.sheet-filter-button[aria-pressed="true"] { + color: #d9c78a; + outline: none; +} +.sheet-filter-button:active { transform: translateY(1px); } + +.sheet { + width: 390px; +} +.sheet .window-content { + min-height: 340px; +} +.sheet-tabs { + display: flex; + height: 30px; + border-bottom: 1px solid #7b6439; +} +.sheet-tab { + flex: 1; + display: flex; + align-items: center; + justify-content: center; + color: #b8a36b; + border-right: 1px solid #322b20; +} +.sheet-tab.selected { + color: #f2d97c; + background: #271e0d; +} +.inventory-grid { + display: grid; + grid-template-columns: repeat(6, 38px); + gap: 4px; + margin-top: 12px; +} +.item-slot { + position: relative; + width: 38px; + height: 38px; + display: flex; + align-items: center; + justify-content: center; + background: #080909; + border: 1px solid #3e3524; +} +.item-slot.rare, +.item-slot.epic { + border-color: #3e3524; + box-shadow: none; +} +.item-slot.rare::after, +.item-slot.epic::after { + content: ""; + position: absolute; + z-index: 2; + left: 50%; + top: 50%; + width: 28px; + height: 28px; + transform: translate(-50%, -50%); + background-repeat: no-repeat; + background-size: 28px 28px; + pointer-events: none; + image-rendering: pixelated; +} +.item-slot.rare::after { + background-image: url("../img/equipment-rarity/rare.png"); +} +.item-slot.epic::after { + background-image: url("../img/equipment-rarity/epic.png"); +} +.item-slot img { + width: 28px; + height: 28px; + image-rendering: pixelated; +} + +.popover { + width: 420px; + padding: 12px 14px; + border: 1px solid #5e4d2d; + background: rgba(4, 5, 4, 0.97); + color: var(--gold); + box-shadow: 0 12px 26px #000; +} +.popover-cols { + display: grid; + grid-template-columns: repeat(3, 1fr); + gap: 16px; +} +.popover h4 { + margin: 0 0 7px; + color: #d8bd5d; + font-size: 13px; +} + +.tooltip { + padding: 5px 7px; + border: 1px solid #6c5c3d; + background: #020302; + color: #f5f5ef; + box-shadow: 0 6px 14px #000; + font-size: 12px; +} +.tooltip.rich { + width: 310px; + padding: 10px; + color: #e8e5da; + line-height: 1.35; +} +.tooltip.rich strong { + color: #e2c962; +} diff --git a/design/src-web/form-controls/component.js b/design/src-web/form-controls/component.js new file mode 100644 index 00000000..838aa16c --- /dev/null +++ b/design/src-web/form-controls/component.js @@ -0,0 +1,4 @@ +(() => { + window.componentRegistry ||= {}; + window.componentRegistry["src-web/form-controls/index.html"] = {"showcase":"
\n
Checkbox / RadioGroup / Switch / Rate
Value state is independent from interaction
\n
\n
\n
\n
Checkbox
\n
交互示例 · 未选择
\n
Emphasized
\n
已选择
\n
已禁用
\n
\n
\n
RadioGroup
\n
关闭
\n
弱
\n
强
\n
禁用
\n
\n
\n
Switch
\n
Interactive · Off
\n
Hover
\n
On
\n
Disabled
\n
\n
\n
Rate · Value = 1 / 5
\n
\n \"第\n \"第\n \"第\n \"第\n \"第\n
\n
Value = Number 0–5
Readonly = Boolean
Star = raster asset
\n
\n
\n
\n
Checked = Off · On · MixedInteraction = Rest · Hover · Focus · Disabled
\n
\n
"}; +})(); diff --git a/design/src-web/form-controls/img/sprite_interface2_popup_menu.NPK/popup_icon_npc.img/126.PNG b/design/src-web/form-controls/img/sprite_interface2_popup_menu.NPK/popup_icon_npc.img/126.PNG new file mode 100644 index 00000000..74f7cab2 Binary files /dev/null and b/design/src-web/form-controls/img/sprite_interface2_popup_menu.NPK/popup_icon_npc.img/126.PNG differ diff --git a/design/src-web/form-controls/img/sprite_interface2_popup_menu.NPK/popup_icon_npc.img/149.PNG b/design/src-web/form-controls/img/sprite_interface2_popup_menu.NPK/popup_icon_npc.img/149.PNG new file mode 100644 index 00000000..31f6e965 Binary files /dev/null and b/design/src-web/form-controls/img/sprite_interface2_popup_menu.NPK/popup_icon_npc.img/149.PNG differ diff --git a/design/src-web/form-controls/index.html b/design/src-web/form-controls/index.html new file mode 100644 index 00000000..13c75313 --- /dev/null +++ b/design/src-web/form-controls/index.html @@ -0,0 +1,59 @@ + + + + + + + form-controls component catalog + + + + + + + + diff --git a/design/src-web/form-controls/style/index.css b/design/src-web/form-controls/style/index.css new file mode 100644 index 00000000..4e0cb853 --- /dev/null +++ b/design/src-web/form-controls/style/index.css @@ -0,0 +1,183 @@ +/* Source module: form-controls.css */ +.fast-step { width:26px;height:28px;display:flex;flex-direction:column;gap:0;margin-left:3px;align-self:center; } +.fast-step-button { + --fast-r:0; + --fast-g:0; + --fast-b:0; + --fast-cap-dark:#080d17; + --fast-cap-core:#2f518f; + --fast-glyph:rgb(from #b69260 calc(r + var(--fast-r)) calc(g + var(--fast-g)) calc(b + var(--fast-b))); + appearance:none; + position:relative; + flex:0 0 14px; + width:26px; + height:14px; + padding:0; + border:0; + background: + linear-gradient(90deg,rgb(from #3c66b4 calc(r + var(--fast-r)) calc(g + var(--fast-g)) calc(b + var(--fast-b))) 0 1px,transparent 1px 23px,rgb(from #3c66b4 calc(r + var(--fast-r)) calc(g + var(--fast-g)) calc(b + var(--fast-b))) 23px) 1px 4px / 24px 9px no-repeat, + linear-gradient(180deg,rgb(from #325596 calc(r + var(--fast-r)) calc(g + var(--fast-g)) calc(b + var(--fast-b))),rgb(from #1d2f53 calc(r + var(--fast-r)) calc(g + var(--fast-g)) calc(b + var(--fast-b))) 46% 72%,rgb(from #2b4378 calc(r + var(--fast-r)) calc(g + var(--fast-g)) calc(b + var(--fast-b)))) 1px 4px / 24px 9px no-repeat, + linear-gradient(#000,#000) 0 3px / 26px 11px no-repeat; + color:var(--fast-glyph); + cursor:pointer; +} +.fast-step-button::before { + content:""; + position:absolute; + left:9px; + top:0; + width:7px; + height:3px; + background: + linear-gradient(#000,#000) center 0 / 3px 1px no-repeat, + linear-gradient(90deg,#000 0 1px,var(--fast-cap-dark) 1px 2px,var(--fast-cap-core) 2px 3px,var(--fast-cap-dark) 3px 4px,#000 4px) center 1px / 5px 1px no-repeat, + linear-gradient(90deg,#000 0 1px,var(--fast-cap-dark) 1px 2px,var(--fast-cap-core) 2px 5px,var(--fast-cap-dark) 5px 6px,#000 6px) center 2px / 7px 1px no-repeat; + pointer-events:none; +} +.fast-step-button + .fast-step-button { + background: + linear-gradient(90deg,rgb(from #3e6cbe calc(r + var(--fast-r)) calc(g + var(--fast-g)) calc(b + var(--fast-b))) 0 1px,transparent 1px 23px,rgb(from #3e6cbe calc(r + var(--fast-r)) calc(g + var(--fast-g)) calc(b + var(--fast-b))) 23px) 1px 1px / 24px 9px no-repeat, + linear-gradient(180deg,rgb(from #345a9e calc(r + var(--fast-r)) calc(g + var(--fast-g)) calc(b + var(--fast-b))),rgb(from #1d2f53 calc(r + var(--fast-r)) calc(g + var(--fast-g)) calc(b + var(--fast-b))) 46% 72%,rgb(from #2d4782 calc(r + var(--fast-r)) calc(g + var(--fast-g)) calc(b + var(--fast-b)))) 1px 1px / 24px 9px no-repeat, + linear-gradient(#000,#000) 0 0 / 26px 11px no-repeat; +} +.fast-step-button + .fast-step-button::before { + top:auto; + bottom:0; + background: + linear-gradient(90deg,#000 0 1px,var(--fast-cap-dark) 1px 2px,var(--fast-cap-core) 2px 5px,var(--fast-cap-dark) 5px 6px,#000 6px) center 0 / 7px 1px no-repeat, + linear-gradient(90deg,#000 0 1px,var(--fast-cap-dark) 1px 2px,var(--fast-cap-core) 2px 3px,var(--fast-cap-dark) 3px 4px,#000 4px) center 1px / 5px 1px no-repeat, + linear-gradient(#000,#000) center 2px / 3px 1px no-repeat; +} +.fast-step-button:hover, +.fast-step-button:active { + --fast-r:10; + --fast-g:16; + --fast-b:33; + --fast-cap-dark:#090f1b; + --fast-cap-core:#375da8; +} +.fast-step-button:active { background-position:1px 5px,1px 5px,0 3px; } +.fast-step-button:active::before { top:1px; } +.fast-step-button + .fast-step-button:active { background-position:1px 2px,1px 2px,0 0; } +.fast-step-button + .fast-step-button:active::before { top:auto;bottom:0; } +.fast-step-button:focus-visible { outline:1px solid var(--focus);outline-offset:1px; } +.fast-step-label { + position:absolute; + left:50%; + top:5px; + color:var(--fast-glyph); + font:400 7px/7px Arial,sans-serif; + letter-spacing:-.55px; + white-space:nowrap; + transform:translateX(-50%) scaleX(.9); + transform-origin:center; + pointer-events:none; +} +.fast-step-button + .fast-step-button .fast-step-label { top:2px; } +.fast-step-button:active .fast-step-label { transform:translate(-50%,1px) scaleX(.9); } + +.check-row, .radio-row, .switch-row { display: flex; align-items: center; gap: 7px; min-height: 26px; color: var(--gold); font-size: 13px; } +.switch-row { position:relative; } +.check-row[data-checkbox], .radio-row[data-radio], .switch-row[data-switch] { cursor:pointer;user-select:none; } +.check-row[data-checkbox]:focus-visible, .radio-row[data-radio]:focus-visible, .switch-row[data-switch]:focus-visible { outline:1px solid var(--focus);outline-offset:-1px; } +.checkbox-control { + --check-edge-top:#635036; + --check-edge-bottom:#3c2e1b; + --check-top:#242424; + --check-bottom:#0f0f0f; + position:relative; + flex:0 0 auto; + width:16px; + height:16px; + display:flex; + align-items:center; + justify-content:center; + border:1px solid transparent; + background:linear-gradient(180deg,var(--check-top),var(--check-bottom)) padding-box,linear-gradient(180deg,var(--check-edge-top),var(--check-edge-bottom)) border-box; + box-shadow:0 0 0 1px rgba(0,0,0,.3),inset 0 1px 0 rgba(255,255,255,.025); +} +.checkbox-control::after { + content:""; + position:absolute; + width:18px; + height:14px; + background:linear-gradient(180deg,#dfb142,#eac75f); + clip-path:polygon(0 42%,7% 34%,39% 66%,94% 4%,100% 10%,39% 82%); + filter:drop-shadow(0 0 1px rgba(230,192,86,.45)); + transform:scale(0); + transition:transform 70ms ease-out; +} +.checkbox-control.is-checked::after { transform:scale(1); } +.check-row:hover .checkbox-control, +.check-row.is-emphasized .checkbox-control { --check-edge-top:#bf9d6a;--check-edge-bottom:#947853;--check-top:#3a3a3a;--check-bottom:#181818; } +.check-row:active .checkbox-control { --check-edge-top:#bf9d6a;--check-edge-bottom:#947853;--check-top:#3a3a3a;--check-bottom:#181818;transform:translateY(1px); } +.check-row.control-disabled { opacity:1;filter:none;color:var(--disabled); } +.check-row.control-disabled .checkbox-control { --check-edge-top:#414141;--check-edge-bottom:#252525;--check-top:#1f1f1f;--check-bottom:#0d0d0d; } +.radio-row::before { + content:""; + box-sizing:border-box; + flex:0 0 auto; + width:14px; + height:14px; + border:1px solid #614f36; + border-radius:50%; + background:linear-gradient(180deg,#2e2e2e,#171717); + box-shadow:inset 0 1px 0 rgba(255,255,255,.04); +} +.radio-row[data-radio]:hover::before { border-color:#d6c889;background:linear-gradient(180deg,#4a4a4a,#252525);box-shadow:inset 0 1px 0 rgba(255,255,255,.05); } +.radio-row[data-radio][aria-checked="true"]::before { + border:1px solid transparent; + background: + linear-gradient(180deg,#dbaa3a 0%,#edd067 100%) padding-box, + linear-gradient(180deg,#f0dfa0 0%,#d3aa70 52%,#a17e50 100%) border-box; + box-shadow:inset 0 0 0 1px #272727; +} +.radio-row[data-radio]:active::before { transform:translateY(1px);filter:brightness(.82); } +.radio-row.control-disabled::before { border-color:#3b3b3b;background:linear-gradient(135deg,transparent 43%,#313131 46% 54%,transparent 57%),linear-gradient(180deg,#252525,#121212); } +.switch-row::before { + content:""; + box-sizing:border-box; + flex:0 0 auto; + width:28px; + height:16px; + border:1px solid transparent; + border-radius:8px / 50%; + background:linear-gradient(180deg,#141414,#0f0f0f) padding-box,linear-gradient(180deg,#846a48,#453520) border-box; + box-shadow:inset 0 1px 3px #090909; +} +.switch-row::after { + content:""; + box-sizing:border-box; + position:absolute; + left:2px; + top:50%; + width:12px; + height:12px; + border-radius:50%; + background:linear-gradient(180deg,var(--control-blue-top),var(--control-blue-bottom)); + box-shadow:inset 0 1px 0 rgba(255,255,255,.04); + transform:translateY(-50%); + transition:transform 90ms ease-out; +} +.switch-row[data-switch]:hover::before, +.switch-row.is-hover::before { filter:brightness(1.04); } +.switch-row[data-switch]:hover::after, +.switch-row.is-hover::after { background:linear-gradient(180deg,#29457f,#24386a); } +.switch-row[data-switch][aria-checked="true"]::before, +.switch-row.is-on::before { + background:linear-gradient(#eccb65,#eccb65) padding-box,linear-gradient(180deg,#846a48,#453520) border-box; + box-shadow:inset 0 0 0 1px #0d0d0d,inset 0 0 2px 1px rgba(9,9,9,.12); +} +.switch-row[data-switch][aria-checked="true"]::after, +.switch-row.is-on::after { transform:translate(12px,-50%); } +.switch-row[data-switch]:active::after { transform:translateY(calc(-50% + 1px)); } +.switch-row[data-switch][aria-checked="true"]:active::after { transform:translate(12px,calc(-50% + 1px)); } +.switch-row.control-disabled::before { background:linear-gradient(180deg,#141414,#0f0f0f) padding-box,linear-gradient(180deg,#846a48,#453520) border-box;filter:none; } +.switch-row.control-disabled::after { left:3px;background:linear-gradient(180deg,#304b8a,#273f74);filter:none;opacity:.58; } +.control-disabled { opacity: .45; filter: grayscale(.8); } +.rate { width:max-content;min-height:46px;padding:8px 12px;display:flex;align-items:center;gap:2px;border-radius:22px;background:#1a1917;box-shadow:inset 0 1px 0 rgba(255,255,255,.025); } +.rate img { width:24px;height:auto;image-rendering:pixelated; } +.rate[data-rate] { cursor:pointer; } +.rate[data-rate]:focus-visible { outline:1px solid var(--focus);outline-offset:2px; } +.rate[data-rate] img:hover { filter:brightness(1.22);transform:translateY(-1px); } +.rate[data-rate] img:active { filter:brightness(.8);transform:translateY(1px); } diff --git a/design/src-web/foundations/component.js b/design/src-web/foundations/component.js new file mode 100644 index 00000000..07db70db --- /dev/null +++ b/design/src-web/foundations/component.js @@ -0,0 +1,4 @@ +(() => { + window.componentRegistry ||= {}; + window.componentRegistry["src-web/foundations/index.html"] = {"colors":"
\n
Color foundations / semantic roles
UI semantics and item quality are separate token groups
\n
\n
\n
Surface / Window#090808
\n
Surface / Panel#131515
\n
Surface / Row#1F1F1E
\n
Action / Primary · 主色#1A2B4E
\n
Chrome / Titlebar#5A7099 → #313E58
\n
Border / Brass#907746
\n
State / Selected#DAA41D
\n
State / Focus#4BA7D3
\n
Text / Primary · 主要文字#F6F8F4
\n
Text / Secondary · 次要文字#D6D3C6
\n
Text / Muted#A7A396
\n
Text / Disabled#4D4B4D
\n
Status / Info · 信息#54C1DB
\n
Status / Success · 成功#49A355
\n
Status / Warning · 警告#C28954
\n
Status / Danger · 失败#BB3331
\n
\n
\n QUALITY\n 普通#FFFFFF\n 高级#68D5ED\n 稀有#9879DA\n 神器#EF28C1\n 传说#FF7700\n 史诗#FCB600\n 勇者#FF6666\n 神话#F8C63D → #CC66E7\n 太初#5AFF62 → #58C6FF\n
\n
\n SKILL\n 技能进化 / Evolution#BB56F1\n 被动技能 / Passive#00CE08\n 主动技能 / Active#B69B33\n 觉醒技能 / Awakening#F27300\n Buff 技能 / Buff#63C8E1\n
\n
\n CONTENT\n 人物属性 / Label#9A7D49\n 人物属性 / Value#469B51\n 通用禁用 / Disabled#4D4B4D\n 数值上升 / Success#49A355\n 数值下降 / Danger#BB3331\n
\n
\n
","typography":"
\n
Typography & density
DNF density, product-level structure
\n
\n
\n
设置行 / 辅助信息12 px
\n
控件标签 / 菜单项目14 px
\n
面板标题 / 重点数据16 px
\n
窗口标题 / 关键状态20 px
\n
\n
\n
Canonical density
\n
control/height/compact  24
\n
control/height/default  30
\n
control/height/large    44
\n
row/height/default      38
\n
stroke/hairline         1
\n
radius/surface          0–2
\n
\n
CAPTURED GEOMETRYPRODUCT SIZE
\n
\n
\n
","architecture":"
\n
Component property architecture
Prevent variant explosion
\n
\n
\n
Variant
Interaction
Rest · Hover · Pressed
Focus · Disabled
\n
Orthogonal
Value state
Selected · Open
Checked · Expanded
\n
Properties
Content
Text · Boolean
Instance Swap
\n
\n
\n
Captured = screenshot evidenceDerived = product completion
\n \n
\n
","evidence":"
\n
Evidence & implementation contract
Design now, Reka later
\n
\n
CAPTUREDDERIVEDASSET-BUILT
\n
\n \n
\n
QA target
• native pixel grid
• 1 px strokes
• no clipped labels
• no unknown state presented as captured
• no screenshot content in component masters
\n
\n
"}; +})(); diff --git a/design/src-web/foundations/img/.gitkeep b/design/src-web/foundations/img/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/design/src-web/foundations/index.html b/design/src-web/foundations/index.html new file mode 100644 index 00000000..2df15569 --- /dev/null +++ b/design/src-web/foundations/index.html @@ -0,0 +1,131 @@ + + + + + + + foundations component catalog + + + + + + + + + + + diff --git a/design/src-web/foundations/style/index.css b/design/src-web/foundations/style/index.css new file mode 100644 index 00000000..f705055a --- /dev/null +++ b/design/src-web/foundations/style/index.css @@ -0,0 +1,65 @@ +/* Source module: foundations.css */ +.color-foundation-body { padding: 12px 16px 10px; } +.palette { display: grid; grid-template-columns: repeat(8, 1fr); gap: 7px 9px; } +.swatch { + height: 48px; + min-width: 0; + display: grid; + grid-template-columns: 26px 1fr; + grid-template-rows: 1fr 1fr; + column-gap: 7px; + padding: 5px 7px; + border: 1px solid #33352f; + background: #0a0b0a; + color: var(--text-2); + font-size: 9px; + text-shadow: 0 1px 2px #000; +} +.swatch i { grid-row: 1 / 3; width: 26px; border: 1px solid #524a39; background: var(--swatch); box-shadow: inset 0 0 0 1px rgba(0,0,0,.45); } +.swatch span { align-self: end; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } +.swatch code { align-self: start; color: var(--text-3); font: 8.5px/1.2 Consolas, monospace; } + +.quality-strip { display: grid; grid-template-columns: 64px repeat(9, minmax(0,1fr)); gap: 7px; align-items: stretch; margin-top: 9px; } +.quality-label { display:flex;align-items:center;justify-content:center;border:1px solid #383a36;color:var(--text-3);font:9px/1 Consolas,monospace;letter-spacing:1px;background:#0a0b0a; } +.quality-chip { min-width:0;height:34px;padding:4px 6px;display:flex;flex-direction:column;justify-content:center;border:1px solid #30322e;background:#080908;font-size:10px;white-space:nowrap;overflow:hidden; } +.quality-chip code { margin-top:2px;color:var(--text-3);font:7.5px/1 Consolas,monospace;text-shadow:none; } +.q-normal { color: var(--quality-normal) !important; } +.q-advanced { color: var(--quality-advanced) !important; } +.q-rare { color: var(--quality-rare) !important; } +.q-artifact { color: var(--quality-artifact) !important; } +.q-legend { color: var(--quality-legend) !important; } +.q-epic { color: var(--quality-epic) !important; } +.q-chronicle { color: var(--quality-chronicle) !important; } +.q-myth { color:transparent !important;background-image:linear-gradient(to bottom,#f8c63d,#cc66e7);background-clip:text;-webkit-background-clip:text;text-shadow:none !important; } +.q-primeval { color:transparent !important;background-image:linear-gradient(to bottom,#5aff62,#58c6ff);background-clip:text;-webkit-background-clip:text;text-shadow:none !important; } +.quality-chip.q-myth, .quality-chip.q-primeval { background-color:#080908; } +.quality-chip.q-myth code, .quality-chip.q-primeval code { color:var(--text-3);-webkit-text-fill-color:var(--text-3); } +.skill-strip { display:grid;grid-template-columns:64px repeat(5,minmax(0,1fr));gap:7px;margin-top:7px; } +.semantic-content-strip { display:grid;grid-template-columns:64px repeat(5,minmax(0,1fr));gap:7px;margin-top:7px; } +.semantic-chip { height:34px;min-width:0;padding:4px 8px;display:flex;flex-direction:column;justify-content:center;border:1px solid #30322e;background:#080908;font-size:10px;white-space:nowrap;overflow:hidden; } +.semantic-chip code { margin-top:2px;color:var(--text-3);font:7.5px/1 Consolas,monospace; } +.skill-evolution { color:var(--skill-evolution);border-color:#4c235f;background:#120718; } +.skill-passive { color:var(--skill-passive);border-color:#1f5d22;background:#071407; } +.skill-active { color:var(--skill-active);border-color:#5c4d1f;background:#141107; } +.skill-awakening { color:var(--skill-awakening);border-color:#6a3409;background:#170b03; } +.skill-buff { color:var(--skill-buff);border-color:#285865;background:#061217; } +.attribute-label-tone { color:var(--attribute-label); } +.attribute-value-tone { color:var(--attribute-value); } +.disabled-tone { color:var(--disabled); } +.success-tone { color:var(--success); } +.danger-tone { color:var(--danger); } + +.type-sample { + padding: 10px 12px; + border-left: 2px solid var(--brass); + background: #0a0b0b; +} +.type-sample + .type-sample { margin-top: 8px; } +.type-sample .zh { color: var(--gold); } +.type-sample .num { color: var(--text); float: right; } +.type-xs { font-size: 12px; } +.type-sm { font-size: 14px; } +.type-md { font-size: 16px; } +.type-lg { font-size: 20px; } +.glyph-select-2x { width:11px;height:6px; } +.glyph-close-2x { width:10px;height:9px; } diff --git a/design/src-web/index.css b/design/src-web/index.css new file mode 100644 index 00000000..884dffdb --- /dev/null +++ b/design/src-web/index.css @@ -0,0 +1,19 @@ +@import url("./shared/style/index.css"); +@import url("./foundations/style/index.css"); +@import url("./button/style/index.css"); +@import url("./input/style/index.css"); +@import url("./form-controls/style/index.css"); +@import url("./slider/style/index.css"); +@import url("./select/style/index.css"); +@import url("./tabs/style/index.css"); +@import url("./navigation/style/index.css"); +@import url("./data-section/style/index.css"); +@import url("./menu/style/index.css"); +@import url("./dialog/style/index.css"); +@import url("./scrollbar/style/index.css"); +@import url("./settings/style/index.css"); +@import url("./data-table/style/index.css"); +@import url("./shop-item-row/style/index.css"); +@import url("./rarity/style/index.css"); +@import url("./autocomplete/style/index.css"); +@import url("./complex-dialog/style/index.css"); diff --git a/design/src-web/input/component.js b/design/src-web/input/component.js new file mode 100644 index 00000000..6719181d --- /dev/null +++ b/design/src-web/input/component.js @@ -0,0 +1,4 @@ +(() => { + window.componentRegistry ||= {}; + window.componentRegistry["src-web/input/index.html"] = {"showcase":"
\n
TextInput / CommandInput / NumberField
Native field grammar, normalized anatomy
\n
\n
\n
TextInput · Empty
\n
TextInput · Placeholder
请输入卡片/宝珠名称。
\n
TextInput · Focus
关键词
\n
TextInput · Disabled
不可编辑
\n
\n
\n
\n
\n
CommandInput · Rest
\n
普通
\n
\n
\n
CommandInput · Suggestions open
\n
普通/fa
\n
普通/fa
建筑/fs
\n
\n
\n
NumberField + FastStep
数量:1
\n
Placeholder / Command capturedInvalid / Readonly derivedPrefix = nested anatomy
\n
\n
"}; +})(); diff --git a/design/src-web/input/img/.gitkeep b/design/src-web/input/img/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/design/src-web/input/index.html b/design/src-web/input/index.html new file mode 100644 index 00000000..78a33d7b --- /dev/null +++ b/design/src-web/input/index.html @@ -0,0 +1,43 @@ + + + + + + + input component catalog + + + + + + + + diff --git a/design/src-web/input/style/index.css b/design/src-web/input/style/index.css new file mode 100644 index 00000000..0f206c30 --- /dev/null +++ b/design/src-web/input/style/index.css @@ -0,0 +1,227 @@ +/* Source module: input.css */ +.field { + position: relative; + height: 30px; + min-width: 210px; + display: inline-flex; + align-items: center; + background: linear-gradient(#0b0c0d, #000100); + border: 1px solid var(--brass-dark); + color: var(--gold); + box-shadow: inset 0 0 0 1px #050505; +} + +.field.focus { + border-color: var(--focus); + box-shadow: + inset 0 0 0 1px #071722, + 0 0 0 1px #24617c; +} + +.field.disabled { + border-color: #343331; + color: var(--disabled); + background: #101110; +} +.field-label { + padding: 0 9px; + flex: 1; + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; +} +.field.placeholder { + color: var(--text-3); +} +.field.placeholder .field-label { + opacity: 0.62; +} +.caret-line { + width: 1px; + height: 16px; + background: #f2f4ef; + margin-left: 1px; + box-shadow: 0 0 2px #fff; +} +.field-action { + align-self: stretch; + min-width: 30px; + display: flex; + align-items: center; + justify-content: center; + border-left: 1px solid #6c542d; + background: linear-gradient(#263d68, #172747); +} + +.field-action img { + max-width: 17px; + max-height: 16px; + image-rendering: pixelated; +} +.input-state-grid { + gap: 7px 12px; +} +.input-state-grid .sample-label { + margin-bottom: 4px; +} +.input-state-grid .field { + width: 100%; +} +.command-grid { + display: grid; + grid-template-columns: 1fr 1fr; + gap: 12px; + min-height: 60px; +} +.command-grid .sample-label { + margin-bottom: 4px; +} +.command-field { + width: 100%; +} +.command-prefix { + align-self: stretch; + min-width: 52px; + padding: 0 8px; + display: inline-flex; + align-items: center; + justify-content: center; + border-right: 1px solid #5e4c2d; + background: #191712; + color: #d7c47e; +} +.command-prefix.green { + color: #9bd8a7; +} +.command-prefix.mini { + min-width: 42px; + height: 20px; + margin-right: 8px; + border: 1px solid #4f422a; + background: #17150f; +} +.command-query { + flex: 1; + padding: 0 8px; + color: var(--text); +} +.command-open-demo { + position: relative; +} +.command-suggestions { + position: absolute; + z-index: 3; + left: 0; + right: 0; + top: 49px; + border: 1px solid #5a4828; + background: #020302; + box-shadow: 0 8px 16px #000; +} +.command-suggestions > div { + height: 26px; + padding: 2px 6px; + display: flex; + align-items: center; + border-bottom: 1px solid #25231f; + color: var(--gold); +} +.number-inline { + width: calc(50% - 6px); + display: flex; + flex-direction: column; + align-items: stretch; + margin-top: 8px; +} +.number-inline .sample-label { + margin: 0 0 4px; +} +.input-specs { + margin-top: 10px; +} + +.select-field { + justify-content: space-between; +} +.select-field[role="button"], +.select-field[role="combobox"] { + cursor: pointer; +} +.select-field.has-select-icon::after { + --select-top:var(--control-blue-top); + --select-bottom:var(--control-blue-bottom); + --select-edge-top:var(--control-edge-top); + --select-edge-bottom:var(--control-edge-bottom); + content:""; + box-sizing:border-box; + flex:0 0 21px; + height:18px; + align-self:center; + margin:0 3px 0 5px; + border:1px solid transparent; + background: + linear-gradient(180deg,var(--select-top),var(--select-bottom)) padding-box, + linear-gradient(180deg,var(--select-edge-top),var(--select-edge-bottom)) border-box; + box-shadow:0 0 0 1px rgba(0,0,0,.6),inset 0 1px 0 rgba(255,255,255,.025); +} +.select-field.has-select-icon::before { + content:""; + position:absolute; + z-index:1; + top:50%; + right:8px; + width:11px; + height:6px; + background:var(--control-glyph); + clip-path:polygon(0 0,100% 0,50% 100%); + transform:translateY(-50%); + pointer-events:none; +} +.select-field.has-select-icon:hover::after, +.select-field.has-select-icon.is-hover::after { --select-top:#29457f;--select-bottom:#24386a;--select-edge-top:#725f4e;--select-edge-bottom:#524444; } +.select-field.has-select-icon:active::after, +.select-field.has-select-icon.is-pressed::after { --select-top:#29457f;--select-bottom:#24386a;--select-edge-top:#725f4e;--select-edge-bottom:#524444;transform:translateY(1px); } +.select-field.has-select-icon:active::before, +.select-field.has-select-icon.is-pressed::before { transform:translateY(calc(-50% + 1px)); } +.select-field:focus-visible { + outline: 1px solid var(--focus); + outline-offset: 1px; +} +.spinner { + width: 23px; + align-self: stretch; + border-left: 1px solid #4b412d; +} +.spin-half { + appearance: none; + width: 100%; + height: 50%; + padding: 0; + display: flex; + align-items: center; + justify-content: center; + border: 0; + background: transparent; +} +.spin-half + .spin-half { + border-top: 1px solid #2e2d28; +} +.spin-half:hover { + background: rgba(255, 255, 255, 0.035); +} +.spin-half:active { + background: rgba(0, 0, 0, 0.35); +} +.tri-up, +.tri-down { + width: 0; + height: 0; + border-left: 7px solid transparent; + border-right: 7px solid transparent; +} +.tri-up { + border-bottom: 8px solid #b99550; +} +.tri-down { + border-top: 8px solid #b99550; +} diff --git a/design/src-web/manifest.json b/design/src-web/manifest.json new file mode 100644 index 00000000..3c9de48e --- /dev/null +++ b/design/src-web/manifest.json @@ -0,0 +1,189 @@ +{ + "variant": "src-web", + "root": "index-web.html", + "components": { + "shared": { + "fragments": [ + "glyphs" + ], + "styles": [ + "tokens.css", + "base.css" + ], + "assetCount": 7 + }, + "foundations": { + "fragments": [ + "colors", + "typography", + "architecture", + "evidence" + ], + "styles": [ + "foundations.css" + ], + "assetCount": 0 + }, + "button": { + "fragments": [ + "construction", + "showcase" + ], + "styles": [ + "button.css" + ], + "assetCount": 1 + }, + "input": { + "fragments": [ + "showcase" + ], + "styles": [ + "input.css" + ], + "assetCount": 0 + }, + "form-controls": { + "fragments": [ + "showcase" + ], + "styles": [ + "form-controls.css" + ], + "assetCount": 10 + }, + "slider": { + "fragments": [ + "showcase" + ], + "styles": [ + "slider.css" + ], + "assetCount": 0 + }, + "select": { + "fragments": [ + "showcase" + ], + "styles": [ + "select.css", + "cascader.css" + ], + "assetCount": 3 + }, + "tabs": { + "fragments": [ + "showcase" + ], + "styles": [ + "tabs.css" + ], + "assetCount": 0 + }, + "navigation": { + "fragments": [ + "favorite-drawer", + "settings-nav" + ], + "styles": [ + "navigation.css" + ], + "assetCount": 5 + }, + "data-section": { + "fragments": [ + "showcase" + ], + "styles": [ + "data-section.css" + ], + "assetCount": 2 + }, + "menu": { + "fragments": [ + "showcase" + ], + "styles": [ + "menu.css" + ], + "assetCount": 9 + }, + "dialog": { + "fragments": [ + "construction", + "showcase" + ], + "styles": [ + "dialog.css" + ], + "assetCount": 61 + }, + "scrollbar": { + "fragments": [ + "showcase" + ], + "styles": [ + "scrollbar.css" + ], + "assetCount": 3 + }, + "settings": { + "fragments": [ + "showcase" + ], + "styles": [ + "settings.css" + ], + "assetCount": 4 + }, + "data-table": { + "fragments": [ + "composition", + "skill", + "compact", + "item" + ], + "styles": [ + "data-table.css" + ], + "assetCount": 14 + }, + "shop-item-row": { + "fragments": [ + "showcase" + ], + "styles": [ + "shop-item-row.css" + ], + "assetCount": 6 + }, + "rarity": { + "fragments": [ + "showcase", + "badges" + ], + "styles": [ + "rarity.css" + ], + "assetCount": 13 + }, + "autocomplete": { + "fragments": [ + "showcase" + ], + "styles": [ + "autocomplete.css" + ], + "assetCount": 5 + }, + "complex-dialog": { + "fragments": [ + "preset" + ], + "styles": [ + "complex-dialog.css" + ], + "assetCount": 7 + } + } +} diff --git a/design/src-web/menu/component.js b/design/src-web/menu/component.js new file mode 100644 index 00000000..656c1d44 --- /dev/null +++ b/design/src-web/menu/component.js @@ -0,0 +1,4 @@ +(() => { + window.componentRegistry ||= {}; + window.componentRegistry["src-web/menu/index.html"] = {"showcase":"
\n
SettingsDropdown / CompactContext
Separate anatomy, not Size variants
\n
\n
\n
设置菜单
\n
滑动锁定
\n
背景画面设置
\n
重新查看指南
\n
\n
\n
赛丽亚·克鲁敏
\n
聊天
\n
商店
\n
任务
\n
设置二级密码
\n
赠送
\n
品级调整
\n
\n
\n
"}; +})(); diff --git a/design/src-web/menu/img/sprite_interface.NPK/windowcommon.chn.img/239.PNG b/design/src-web/menu/img/sprite_interface.NPK/windowcommon.chn.img/239.PNG new file mode 100644 index 00000000..b9c56f25 Binary files /dev/null and b/design/src-web/menu/img/sprite_interface.NPK/windowcommon.chn.img/239.PNG differ diff --git a/design/src-web/menu/img/sprite_interface2_popup_menu.NPK/popup_icon_npc.img/13.PNG b/design/src-web/menu/img/sprite_interface2_popup_menu.NPK/popup_icon_npc.img/13.PNG new file mode 100644 index 00000000..db9ce63a Binary files /dev/null and b/design/src-web/menu/img/sprite_interface2_popup_menu.NPK/popup_icon_npc.img/13.PNG differ diff --git a/design/src-web/menu/img/sprite_interface2_popup_menu.NPK/popup_icon_npc.img/14.PNG b/design/src-web/menu/img/sprite_interface2_popup_menu.NPK/popup_icon_npc.img/14.PNG new file mode 100644 index 00000000..42db3b0c Binary files /dev/null and b/design/src-web/menu/img/sprite_interface2_popup_menu.NPK/popup_icon_npc.img/14.PNG differ diff --git a/design/src-web/menu/img/sprite_interface2_popup_menu.NPK/popup_icon_npc.img/15.PNG b/design/src-web/menu/img/sprite_interface2_popup_menu.NPK/popup_icon_npc.img/15.PNG new file mode 100644 index 00000000..9ddbc93c Binary files /dev/null and b/design/src-web/menu/img/sprite_interface2_popup_menu.NPK/popup_icon_npc.img/15.PNG differ diff --git a/design/src-web/menu/img/sprite_interface2_popup_menu.NPK/popup_icon_npc.img/17.PNG b/design/src-web/menu/img/sprite_interface2_popup_menu.NPK/popup_icon_npc.img/17.PNG new file mode 100644 index 00000000..f27cc6f5 Binary files /dev/null and b/design/src-web/menu/img/sprite_interface2_popup_menu.NPK/popup_icon_npc.img/17.PNG differ diff --git a/design/src-web/menu/img/sprite_interface2_popup_menu.NPK/popup_icon_npc.img/2.PNG b/design/src-web/menu/img/sprite_interface2_popup_menu.NPK/popup_icon_npc.img/2.PNG new file mode 100644 index 00000000..c43a0db5 Binary files /dev/null and b/design/src-web/menu/img/sprite_interface2_popup_menu.NPK/popup_icon_npc.img/2.PNG differ diff --git a/design/src-web/menu/img/sprite_interface2_popup_menu.NPK/popup_icon_npc.img/3.PNG b/design/src-web/menu/img/sprite_interface2_popup_menu.NPK/popup_icon_npc.img/3.PNG new file mode 100644 index 00000000..131eb5a7 Binary files /dev/null and b/design/src-web/menu/img/sprite_interface2_popup_menu.NPK/popup_icon_npc.img/3.PNG differ diff --git a/design/src-web/menu/img/sprite_interface2_popup_menu.NPK/popup_icon_npc.img/4.PNG b/design/src-web/menu/img/sprite_interface2_popup_menu.NPK/popup_icon_npc.img/4.PNG new file mode 100644 index 00000000..bfe872d7 Binary files /dev/null and b/design/src-web/menu/img/sprite_interface2_popup_menu.NPK/popup_icon_npc.img/4.PNG differ diff --git a/design/src-web/menu/img/sprite_interface2_popup_menu.NPK/popup_icon_npc.img/7.PNG b/design/src-web/menu/img/sprite_interface2_popup_menu.NPK/popup_icon_npc.img/7.PNG new file mode 100644 index 00000000..7a91b3ee Binary files /dev/null and b/design/src-web/menu/img/sprite_interface2_popup_menu.NPK/popup_icon_npc.img/7.PNG differ diff --git a/design/src-web/menu/index.html b/design/src-web/menu/index.html new file mode 100644 index 00000000..547733d5 --- /dev/null +++ b/design/src-web/menu/index.html @@ -0,0 +1,38 @@ + + + + + + + menu component catalog + + + + + + + + diff --git a/design/src-web/menu/style/index.css b/design/src-web/menu/style/index.css new file mode 100644 index 00000000..0a871ed8 --- /dev/null +++ b/design/src-web/menu/style/index.css @@ -0,0 +1,20 @@ +/* Source module: menu.css */ +.dropdown { + width: 275px; + border: 1px solid #463923; + padding: 4px; + background: #050606; + box-shadow: 0 14px 28px #000; +} +.dropdown-title { height:36px;display:flex;align-items:center;justify-content:center;color:#d8b44f;background:linear-gradient(#302814,#151008);border:1px solid #554527; } +.menu-row { height:48px;display:grid;grid-template-columns:45px 1fr;align-items:center;border:1px solid #2d2c28;color:#cab980;background:linear-gradient(#181a19,#0c0d0c); } +.menu-row.focus { outline:2px solid #278bc0;outline-offset:-3px;background:#101d2b; } +.menu-icon { display:flex;align-items:center;justify-content:center; } +.menu-icon img { image-rendering: pixelated; } + +.context-menu { width:190px;padding:0 3px 4px;border:1px solid rgba(19,17,13,.92);background:rgba(48,46,38,.72);box-shadow:0 10px 20px rgba(0,0,0,.78);backdrop-filter:blur(1px); } +.context-title { height:28px;margin:0 -3px 2px;padding:0 9px;display:flex;align-items:center;border-bottom:1px solid #161513;background:#030403;color:#eee8d5;font-size:13px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis; } +.context-row { height:28px;padding:0 7px;display:grid;grid-template-columns:25px minmax(0,1fr);gap:5px;align-items:center;border:1px solid transparent;color:#e1d7ba;background:transparent; } +.context-row img { max-width:20px;max-height:20px;justify-self:center;image-rendering:pixelated; } +.context-row:hover, +.context-row.focus { border-color:#000;background:rgba(15,14,12,.28);color:#ffefad;box-shadow:inset 0 0 0 1px rgba(132,113,76,.13); } diff --git a/design/src-web/navigation/component.js b/design/src-web/navigation/component.js new file mode 100644 index 00000000..04582df7 --- /dev/null +++ b/design/src-web/navigation/component.js @@ -0,0 +1,4 @@ +(() => { + window.componentRegistry ||= {}; + window.componentRegistry["src-web/navigation/index.html"] = {"favorite-drawer":"
\n
FavoriteDrawer
FAMILY A
\n
\n
神圣的黄金增幅书 ×
甜蜜果实收纳箱 ×
稀有装备图鉴 ×
\n
Open · CollapsedRemove actionScroll
\n
\n
","settings-nav":"
\n
SettingsNav
FAMILY B
\n
\n
\n
首页
\n
画面
\n
特效
\n
\n
\n
"}; +})(); diff --git a/design/src-web/navigation/img/sprite_interface2_option.NPK/option.img/103.PNG b/design/src-web/navigation/img/sprite_interface2_option.NPK/option.img/103.PNG new file mode 100644 index 00000000..3905eadf Binary files /dev/null and b/design/src-web/navigation/img/sprite_interface2_option.NPK/option.img/103.PNG differ diff --git a/design/src-web/navigation/img/sprite_interface2_option.NPK/option.img/106.PNG b/design/src-web/navigation/img/sprite_interface2_option.NPK/option.img/106.PNG new file mode 100644 index 00000000..55d16b2f Binary files /dev/null and b/design/src-web/navigation/img/sprite_interface2_option.NPK/option.img/106.PNG differ diff --git a/design/src-web/navigation/img/sprite_interface2_option.NPK/option.img/82.PNG b/design/src-web/navigation/img/sprite_interface2_option.NPK/option.img/82.PNG new file mode 100644 index 00000000..2fe27054 Binary files /dev/null and b/design/src-web/navigation/img/sprite_interface2_option.NPK/option.img/82.PNG differ diff --git a/design/src-web/navigation/img/sprite_interface2_option.NPK/option.img/85.PNG b/design/src-web/navigation/img/sprite_interface2_option.NPK/option.img/85.PNG new file mode 100644 index 00000000..f18f623f Binary files /dev/null and b/design/src-web/navigation/img/sprite_interface2_option.NPK/option.img/85.PNG differ diff --git a/design/src-web/navigation/img/sprite_interface2_option.NPK/option.img/91.PNG b/design/src-web/navigation/img/sprite_interface2_option.NPK/option.img/91.PNG new file mode 100644 index 00000000..f83d74dd Binary files /dev/null and b/design/src-web/navigation/img/sprite_interface2_option.NPK/option.img/91.PNG differ diff --git a/design/src-web/navigation/index.html b/design/src-web/navigation/index.html new file mode 100644 index 00000000..20b097cb --- /dev/null +++ b/design/src-web/navigation/index.html @@ -0,0 +1,37 @@ + + + + + + + navigation component catalog + + + + + + + + + diff --git a/design/src-web/navigation/style/index.css b/design/src-web/navigation/style/index.css new file mode 100644 index 00000000..c7170740 --- /dev/null +++ b/design/src-web/navigation/style/index.css @@ -0,0 +1,14 @@ +/* Source module: navigation.css */ +.nav-menu { width: 250px; border: 1px solid #20251f; background: #030403; } +.nav-row { height: 48px; padding: 0 13px; display: grid; grid-template-columns: 24px 1fr 12px; align-items: center; border-bottom: 1px solid #25221a; color: #c5b573; } +.nav-row.selected { background: linear-gradient(90deg,#80601b,#1b160b 72%); color:#f1d66e; } +.nav-row img { image-rendering: pixelated; } +.favorite-drawer .disclosure-head { width:100%;border:0;border-bottom:1px solid #25221b;color:inherit;font:inherit;text-align:left;cursor:pointer; } +.favorite-drawer .disclosure-head:hover { background:linear-gradient(#35342f,#191a17); } +.favorite-drawer .disclosure-head:active { background:linear-gradient(#35342f,#191a17); } +.favorite-drawer .disclosure-head:active > *, +.favorite-drawer .disclosure-head.is-pressed > * { transform:translateY(1px); } +.favorite-drawer-state { color:var(--text-3);font-size:10px; } +.favorite-drawer-arrow { width:12px;color:#c8b36d;text-align:center; } +.favorite-drawer.is-collapsed .disclosure-head { border-bottom:0; } +.favorite-drawer.is-collapsed .disclosure-body { display:none; } diff --git a/design/src-web/rarity/component.js b/design/src-web/rarity/component.js new file mode 100644 index 00000000..a42437bc --- /dev/null +++ b/design/src-web/rarity/component.js @@ -0,0 +1,4 @@ +(() => { + window.componentRegistry ||= {}; + window.componentRegistry["src-web/rarity/index.html"] = {"showcase":"
\n
ItemIcon / Rarity token application
Content asset + frame component + semantic tone + optional emphasis
\n
\n
\n
稀有 / Rare
\n
神器 / Artifact
\n
传说 / Legend
\n
史诗 / Epic
\n
太初 / Primeval
\n
强调 / Emphasis
\n
\n
\n
RasterIconIconFrame = Instance SwapRarityTone = TokenEmphasis = Optional modifier
\n
\n
","badges":"
\n
NoticeBadge / LevelBadge
Separate families
\n
\n
Notice badge placements
\n
\n
\n
\n
\n
\n
Level markers
\n
1级
2级
56级
\n
Captured tonesCount deferred
\n
\n
"}; +})(); diff --git a/design/src-web/rarity/img/equipment-rarity/artifact.png b/design/src-web/rarity/img/equipment-rarity/artifact.png new file mode 100644 index 00000000..12d0d063 Binary files /dev/null and b/design/src-web/rarity/img/equipment-rarity/artifact.png differ diff --git a/design/src-web/rarity/img/equipment-rarity/epic.png b/design/src-web/rarity/img/equipment-rarity/epic.png new file mode 100644 index 00000000..9166969d Binary files /dev/null and b/design/src-web/rarity/img/equipment-rarity/epic.png differ diff --git a/design/src-web/rarity/img/equipment-rarity/legend.png b/design/src-web/rarity/img/equipment-rarity/legend.png new file mode 100644 index 00000000..8162c33b Binary files /dev/null and b/design/src-web/rarity/img/equipment-rarity/legend.png differ diff --git a/design/src-web/rarity/img/equipment-rarity/primeval.png b/design/src-web/rarity/img/equipment-rarity/primeval.png new file mode 100644 index 00000000..2efcc308 Binary files /dev/null and b/design/src-web/rarity/img/equipment-rarity/primeval.png differ diff --git a/design/src-web/rarity/img/equipment-rarity/rare.png b/design/src-web/rarity/img/equipment-rarity/rare.png new file mode 100644 index 00000000..618085ed Binary files /dev/null and b/design/src-web/rarity/img/equipment-rarity/rare.png differ diff --git a/design/src-web/rarity/img/sprite_interface.NPK/windowcommon.chn.img/301.PNG b/design/src-web/rarity/img/sprite_interface.NPK/windowcommon.chn.img/301.PNG new file mode 100644 index 00000000..fff847d2 Binary files /dev/null and b/design/src-web/rarity/img/sprite_interface.NPK/windowcommon.chn.img/301.PNG differ diff --git a/design/src-web/rarity/img/sprite_interface2_option.NPK/option.img/100.PNG b/design/src-web/rarity/img/sprite_interface2_option.NPK/option.img/100.PNG new file mode 100644 index 00000000..74de768f Binary files /dev/null and b/design/src-web/rarity/img/sprite_interface2_option.NPK/option.img/100.PNG differ diff --git a/design/src-web/rarity/img/sprite_interface2_option.NPK/option.img/97.PNG b/design/src-web/rarity/img/sprite_interface2_option.NPK/option.img/97.PNG new file mode 100644 index 00000000..94278fbd Binary files /dev/null and b/design/src-web/rarity/img/sprite_interface2_option.NPK/option.img/97.PNG differ diff --git a/design/src-web/rarity/img/sprite_item.NPK/equipmentskill.img/0.PNG b/design/src-web/rarity/img/sprite_item.NPK/equipmentskill.img/0.PNG new file mode 100644 index 00000000..6e0b1e48 Binary files /dev/null and b/design/src-web/rarity/img/sprite_item.NPK/equipmentskill.img/0.PNG differ diff --git a/design/src-web/rarity/img/sprite_item.NPK/equipmentskill.img/1.PNG b/design/src-web/rarity/img/sprite_item.NPK/equipmentskill.img/1.PNG new file mode 100644 index 00000000..d7f2db60 Binary files /dev/null and b/design/src-web/rarity/img/sprite_item.NPK/equipmentskill.img/1.PNG differ diff --git a/design/src-web/rarity/img/sprite_item.NPK/equipmentskill.img/2.PNG b/design/src-web/rarity/img/sprite_item.NPK/equipmentskill.img/2.PNG new file mode 100644 index 00000000..13fa3616 Binary files /dev/null and b/design/src-web/rarity/img/sprite_item.NPK/equipmentskill.img/2.PNG differ diff --git a/design/src-web/rarity/img/sprite_item.NPK/equipmentskill.img/3.PNG b/design/src-web/rarity/img/sprite_item.NPK/equipmentskill.img/3.PNG new file mode 100644 index 00000000..db40e39f Binary files /dev/null and b/design/src-web/rarity/img/sprite_item.NPK/equipmentskill.img/3.PNG differ diff --git a/design/src-web/rarity/img/sprite_item.NPK/equipmentskill.img/4.PNG b/design/src-web/rarity/img/sprite_item.NPK/equipmentskill.img/4.PNG new file mode 100644 index 00000000..4d3ffb0e Binary files /dev/null and b/design/src-web/rarity/img/sprite_item.NPK/equipmentskill.img/4.PNG differ diff --git a/design/src-web/rarity/index.html b/design/src-web/rarity/index.html new file mode 100644 index 00000000..978bdeb0 --- /dev/null +++ b/design/src-web/rarity/index.html @@ -0,0 +1,49 @@ + + + + + + + rarity component catalog + + + + + + + + + diff --git a/design/src-web/rarity/style/index.css b/design/src-web/rarity/style/index.css new file mode 100644 index 00000000..4b284c58 --- /dev/null +++ b/design/src-web/rarity/style/index.css @@ -0,0 +1,24 @@ +/* Source module: rarity.css */ +.rarity-grid { display:grid;grid-template-columns:repeat(6,1fr);gap:8px; } +.rarity-card { min-width:0;padding:8px 5px;border:1px solid #292a27;background:#070807; } +.rarity-slot { position:relative;width:40px;height:40px;margin:0 auto 7px;display:flex;align-items:center;justify-content:center;background:#030404; } +.rarity-slot.is-emphasized { background:rgba(0,0,0,.9); } +.rarity-slot.is-emphasized::before, +.rarity-slot.is-emphasized::after { content:"";position:absolute;pointer-events:none; } +.rarity-slot.is-emphasized::before { + z-index:0; + inset:4px; + border:1px solid #ffa800; + box-shadow: + 0 0 2px 1px rgba(255,168,0,.88), + 0 0 5px 4px rgba(255,168,0,.46), + inset 0 0 2px rgba(255,168,0,.7); +} +.rarity-slot.is-emphasized::after { + z-index:3; + inset:5px; + border:1px solid #fffc2a; +} +.rarity-slot .frame { position:absolute;z-index:2;left:50%;top:50%;width:28px;height:28px;transform:translate(-50%,-50%);image-rendering:pixelated; } +.rarity-slot .item { position:relative;z-index:1;width:28px;height:28px;image-rendering:pixelated; } +.rarity-name { text-align:center;font-size:11px;color:var(--gold); } diff --git a/design/src-web/scrollbar/component.js b/design/src-web/scrollbar/component.js new file mode 100644 index 00000000..586f9e6c --- /dev/null +++ b/design/src-web/scrollbar/component.js @@ -0,0 +1,4 @@ +(() => { + window.componentRegistry ||= {}; + window.componentRegistry["src-web/scrollbar/index.html"] = {"showcase":"
\n
Popover / Tooltip / Scrollbar
No generic floating white cards
\n
\n
\n
Popover · Placement = Top
\n

物品设置

锁定排序
按部位

排序方式

名望对比
相同装备优先

其他支持

显示帮助
\n
SimpleTooltip
恢复游戏设置前的状态
RichHelp
▣ 排序锁定
锁定后固定该物品。排序时不会移动物品位置。
▣ 交易锁定
锁定后无法交易、强化、分解。
\n
\n
\n
Scrollbar · Style = Plain
\n
\n
Plain vertical captured
\n
\n
\n
"}; +})(); diff --git a/design/src-web/scrollbar/index.html b/design/src-web/scrollbar/index.html new file mode 100644 index 00000000..f0f6ea86 --- /dev/null +++ b/design/src-web/scrollbar/index.html @@ -0,0 +1,33 @@ + + + + + + + scrollbar component catalog + + + + + + + + diff --git a/design/src-web/scrollbar/style/index.css b/design/src-web/scrollbar/style/index.css new file mode 100644 index 00000000..fca1319c --- /dev/null +++ b/design/src-web/scrollbar/style/index.css @@ -0,0 +1,8 @@ +/* Source module: scrollbar.css */ +.scroll-demo { display:flex;gap:28px;justify-content:center;align-items:flex-start; } +.scrollbar { width:15px;height:250px;display:grid;grid-template-rows:18px 1fr 18px;border:1px solid #2b2924;background:#050606; } +.scroll-arrow { display:flex;align-items:center;justify-content:center;background:linear-gradient(#24241f,#10110f); } +.scroll-arrow::before { content:"";width:0;height:0;border-left:4px solid transparent;border-right:4px solid transparent;border-bottom:5px solid #a98b46;filter:drop-shadow(0 1px 0 #000); } +.scroll-arrow:last-child::before { border-bottom:0;border-top:5px solid #a98b46; } +.scroll-track { position:relative;background:linear-gradient(90deg,#080908,#151513,#070807); } +.scroll-thumb { position:absolute;left:2px;right:2px;top:44px;height:64px;border:1px solid #68532d;background:linear-gradient(90deg,#1b1d1c,#363530,#161817); } diff --git a/design/src-web/select/component.js b/design/src-web/select/component.js new file mode 100644 index 00000000..dd319019 --- /dev/null +++ b/design/src-web/select/component.js @@ -0,0 +1,4 @@ +(() => { + window.componentRegistry ||= {}; + window.componentRegistry["src-web/select/index.html"] = {"showcase":"
\n
Select / TreeSelect / CascaderFilter
OPEN + FOCUS ROW
\n
\n
\n
Select · Closed
\n
所有部位
\n
Select · Open
\n
\n
名称
\n
名称
关键词
更新时间
\n
\n
CascaderFilter · Open + focused row
\n
\n
\n \n \n
\n
\n \n \n \n \n
\n
\n
\n
\n
TreeSelect · Single-column rarity tree
\n
\n
稀有
\n
\n
所有稀有度
\n
普通
\n
高级
\n
稀有
\n
神器
\n
传说
\n
史诗
\n
神话
\n
太初
\n
\n
\n
\n
\n
"}; +})(); diff --git a/design/src-web/select/index.html b/design/src-web/select/index.html new file mode 100644 index 00000000..39708297 --- /dev/null +++ b/design/src-web/select/index.html @@ -0,0 +1,62 @@ + + + + + + + select component catalog + + + + + + + + diff --git a/design/src-web/select/style/index.css b/design/src-web/select/style/index.css new file mode 100644 index 00000000..29b0c073 --- /dev/null +++ b/design/src-web/select/style/index.css @@ -0,0 +1,229 @@ +/* Source module: select.css */ +.select-menu { + width: 230px; + margin-top: 1px; + border: 1px solid #5a4828; + background: #050606; + box-shadow: 0 8px 18px #000; +} +.select-demo { + position: relative; +} +.select-demo:not(.is-open) > .select-menu, +.tree-select-demo:not(.is-open) > .tree-select-menu { + display: none; +} +.select-item { + height: 27px; + padding: 0 10px; + display: flex; + align-items: center; + color: var(--gold); + border-bottom: 1px solid #25231f; +} +.select-item:hover { + color: #f3d777; + background: #101612; +} +.select-item:active { + color: #fff0a4; + background: #07121b; +} +.select-item:focus-visible { + outline: 1px solid var(--focus); + outline-offset: -2px; + background: #091731; +} +.select-item.focused { + outline: 1px solid var(--focus); + outline-offset: -2px; + background: #091731; +} +.select-item.selected { + color: var(--selected); +} +.tree-select-menu { + padding: 2px 3px; + background: #010201; + display: flex; + flex-direction: column; + gap: 2px; +} +.tree-select-item { + min-height: 24px; + padding: 0 7px 0 calc(7px + var(--depth, 0) * 14px); + display: flex; + align-items: center; + gap: 6px; + border: 1px solid #0d0f0d; + background: linear-gradient(180deg, #2c2a2c 0, #202220 16%, #0c0e0c 100%); + color: var(--gold); + box-shadow: + inset 0 1px 0 #3e3c3e, + inset 1px 0 0 #252725, + inset -1px 0 0 #111311, + inset 0 -1px 0 #111311; +} +.tree-select-item:hover { + border-color: #4f4b3c; + color: #f2da85; + filter: brightness(1.12); + cursor: pointer; +} +.tree-select-item:active { + border-color: #806329; + filter: brightness(0.86); +} +.tree-select-item:focus-visible { + outline: 1px solid var(--focus); + outline-offset: -2px; +} +.tree-select-demo.is-tree-collapsed .tree-select-item:not(.tree-parent) { + display: none; +} +.tree-parent { + position: relative; +} +.tree-parent::before { + content: ""; + flex: 0 0 auto; + width: 13px; + height: 13px; + border: 1px solid #5f4a2b; + background: linear-gradient(180deg, #272720, #11120f); + box-shadow: + 0 0 0 1px #090a09, + inset 0 1px 0 rgba(255, 255, 255, 0.04); +} +.tree-parent::after { + content: ""; + position: absolute; + left: 11px; + top: 50%; + width: 7px; + height: 1px; + background: #a98b46; + box-shadow: 0 1px #000; + transform: translateY(-50%); +} +.tree-parent[aria-expanded="false"]::after { + height: 7px; + background: + linear-gradient(#a98b46, #a98b46) center / 7px 1px no-repeat, + linear-gradient(#a98b46, #a98b46) center / 1px 7px no-repeat; + box-shadow: 0 1px #000; +} +.tree-select-item.is-selected { + border-color: #efb62f; + box-shadow: + inset 0 0 0 1px #7c5d1d, + inset 0 1px 0 #f1c75f, + 0 0 4px rgba(239, 182, 47, 0.48); +} +.tree-select-item.q-myth { + color: #f8c63d !important; +} +.tree-select-item.q-primeval { + color: #5aff62 !important; +} + +/* Source module: cascader.css */ +.cascader-filter { + width: 100%; + position: relative; +} +.cascader-fields { + height: 30px; + display: flex; + border-bottom: 1px solid #583916; + background: #030403; +} +.cascader-trigger { + appearance: none; + min-width: 0; + height: 29px; + padding: 0 10px; + display: flex; + align-items: center; + justify-content: space-between; + gap: 8px; + border: 1px solid #332a1b; + border-bottom: 0; + border-radius: 0; + background: linear-gradient(180deg, #2b2920 0, #171710 52%, #0b0c0a 100%); + color: #c3a15e; + font: + 13px/1 "DCalc", + SimSun, + sans-serif; + text-shadow: 1px 1px 0 #000; + cursor: pointer; +} +.cascader-trigger.primary { + width: 39%; + border-right: 0; +} +.cascader-trigger.secondary { + flex: 1; +} +.cascader-trigger span { + min-width: 0; + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; +} +.cascader-trigger::after { + content: ""; + flex: 0 0 auto; + width: 0; + height: 0; + border-left: 4px solid transparent; + border-right: 4px solid transparent; + border-top: 5px solid var(--control-glyph); + filter: drop-shadow(0 1px 0 #000); + transition: transform 90ms ease-out; +} +.cascader-filter.is-open .cascader-trigger.primary::after { + transform: rotate(180deg); +} +.cascader-trigger:hover, +.cascader-trigger.is-hover { + border-color: #756132; + background: linear-gradient(180deg, #817444 0, #514b2b 52%, #252315 100%); + color: #fff1a4; + box-shadow: inset 0 1px 0 #a89a61; +} +.cascader-menu { + display: none; + width: 39%; + margin-top: 1px; + border: 1px solid #432b14; + background: #010201; + box-shadow: 0 8px 16px #000; +} +.cascader-filter.is-open .cascader-menu { + display: block; +} +.cascader-option { + appearance: none; + width: 100%; + height: 22px; + padding: 0 7px; + display: flex; + align-items: center; + border: 0; + background: #010201; + color: #d1ae61; + font: + 13px/1 "DCalc", + SimSun, + sans-serif; + text-align: left; + cursor: pointer; +} +.cascader-option:hover, +.cascader-option.focused { + color: #f5d56d; + background: #09284b; + box-shadow: inset 2px 0 0 #3a9ad0; +} diff --git a/design/src-web/settings/component.js b/design/src-web/settings/component.js new file mode 100644 index 00000000..ca5f68bb --- /dev/null +++ b/design/src-web/settings/component.js @@ -0,0 +1,4 @@ +(() => { + window.componentRegistry ||= {}; + window.componentRegistry["src-web/settings/index.html"] = {"showcase":"
\n
SettingsRow / SectionHeader
The source folder “items” resolves to form rows
\n
\n
\n
显示特效
\n
阴影效果
关闭
\n
光环效果
开启
\n
角色轮廓
12%
\n
转职 / 觉醒特效
关闭
\n
队员角色特效
\n
队员技能插图特效
不可用
\n
队友伤害字体显示
开启
\n
\n
ControlSlot = Instance SwapIndent = 0 · 1 · 2Help = Boolean
\n
\n
"}; +})(); diff --git a/design/src-web/settings/img/sprite_interface.NPK/windowcommon.chn.img/239.PNG b/design/src-web/settings/img/sprite_interface.NPK/windowcommon.chn.img/239.PNG new file mode 100644 index 00000000..b9c56f25 Binary files /dev/null and b/design/src-web/settings/img/sprite_interface.NPK/windowcommon.chn.img/239.PNG differ diff --git a/design/src-web/settings/index.html b/design/src-web/settings/index.html new file mode 100644 index 00000000..550425c8 --- /dev/null +++ b/design/src-web/settings/index.html @@ -0,0 +1,34 @@ + + + + + + + settings component catalog + + + + + + + + diff --git a/design/src-web/settings/style/index.css b/design/src-web/settings/style/index.css new file mode 100644 index 00000000..fac78a09 --- /dev/null +++ b/design/src-web/settings/style/index.css @@ -0,0 +1,8 @@ +/* Source module: settings.css */ +.settings-group { border:1px solid #2c2c28;background:#050606; } +.section-row { height:34px;padding:0 10px;display:flex;align-items:center;color:#e4cc7c;border:1px solid #4c402a;background:linear-gradient(#22231f,#0e0f0e); } +.setting-row { min-height:38px;padding:5px 10px;display:grid;grid-template-columns:minmax(190px,1fr) minmax(210px,1.1fr);align-items:center;border-bottom:1px solid #23231f;color:#bcae73; } +.setting-row.alt { background:#171817; } +.setting-row.focus { outline:1px solid var(--focus);outline-offset:-2px;background:#071017; } +.setting-label { display:flex;align-items:center;gap:6px; } +.setting-control { justify-self:end; } diff --git a/design/src-web/shared/component-loader.js b/design/src-web/shared/component-loader.js new file mode 100644 index 00000000..9b322e75 --- /dev/null +++ b/design/src-web/shared/component-loader.js @@ -0,0 +1,39 @@ +(() => { + const references = [...document.querySelectorAll('[data-component-src]')]; + const componentPaths = [...new Set(references.map((reference) => reference.dataset.componentSrc.split('#')[0]))]; + const registriesReady = Promise.all(componentPaths.map((path) => new Promise((resolve) => { + const script = document.createElement('script'); + script.src = path.replace(/index\.html$/, 'component.js'); + script.onload = resolve; + script.onerror = resolve; + document.head.append(script); + }))); + + window.componentsReady = registriesReady.then(() => Promise.all(references.map(async (reference) => { + const specifier = reference.dataset.componentSrc; + const [path, fragmentId] = specifier.split('#'); + const registered = window.componentRegistry?.[path]?.[fragmentId]; + if (registered !== undefined) { + const template = document.createElement('template'); + template.innerHTML = registered; + reference.replaceWith(template.content.cloneNode(true)); + return; + } + const response = await fetch(path); + if (!response.ok) throw new Error(`Component load failed: ${specifier} (${response.status})`); + const source = await response.text(); + const documentFragment = new DOMParser().parseFromString(source, 'text/html'); + const template = fragmentId ? documentFragment.getElementById(fragmentId) : null; + if (!(template instanceof HTMLTemplateElement)) throw new Error(`Component fragment missing: ${specifier}`); + reference.replaceWith(template.content.cloneNode(true)); + }))).then(() => { + document.documentElement.dataset.componentsReady = 'true'; + }).catch((error) => { + document.documentElement.dataset.componentsReady = 'error'; + const overlay = document.createElement('pre'); + overlay.className = 'component-load-error'; + overlay.textContent = error.stack || error.message; + document.body.prepend(overlay); + throw error; + }); +})(); diff --git a/design/src-web/shared/component.js b/design/src-web/shared/component.js new file mode 100644 index 00000000..b10ae119 --- /dev/null +++ b/design/src-web/shared/component.js @@ -0,0 +1,4 @@ +(() => { + window.componentRegistry ||= {}; + window.componentRegistry["src-web/shared/index.html"] = {"glyphs":"
\n
Native glyph assets
1× / 2× RASTER
\n
\n
\n
Select arrow · 2x
\n
\"Check\"
Check
\n
Close · 2x
\n
Expand
\n
Notice
\n
Settings
\n
\n
\n \n
\n
"}; +})(); diff --git a/design/src-web/shared/img/fonts/dcalc.ttf b/design/src-web/shared/img/fonts/dcalc.ttf new file mode 100644 index 00000000..2022d830 Binary files /dev/null and b/design/src-web/shared/img/fonts/dcalc.ttf differ diff --git a/design/src-web/shared/img/sprite_interface.NPK/windowcommon.chn.img/301.PNG b/design/src-web/shared/img/sprite_interface.NPK/windowcommon.chn.img/301.PNG new file mode 100644 index 00000000..fff847d2 Binary files /dev/null and b/design/src-web/shared/img/sprite_interface.NPK/windowcommon.chn.img/301.PNG differ diff --git a/design/src-web/shared/img/sprite_interface.NPK/windowcommon.chn.img/561.PNG b/design/src-web/shared/img/sprite_interface.NPK/windowcommon.chn.img/561.PNG new file mode 100644 index 00000000..4c455bdd Binary files /dev/null and b/design/src-web/shared/img/sprite_interface.NPK/windowcommon.chn.img/561.PNG differ diff --git a/design/src-web/shared/img/sprite_interface.NPK/windowcommon_2x.img/0.PNG b/design/src-web/shared/img/sprite_interface.NPK/windowcommon_2x.img/0.PNG new file mode 100644 index 00000000..84c19be4 Binary files /dev/null and b/design/src-web/shared/img/sprite_interface.NPK/windowcommon_2x.img/0.PNG differ diff --git a/design/src-web/shared/img/sprite_interface.NPK/windowcommon_2x.img/4.PNG b/design/src-web/shared/img/sprite_interface.NPK/windowcommon_2x.img/4.PNG new file mode 100644 index 00000000..c5902cb8 Binary files /dev/null and b/design/src-web/shared/img/sprite_interface.NPK/windowcommon_2x.img/4.PNG differ diff --git a/design/src-web/shared/img/sprite_interface.NPK/windowcommon_2x.img/6.PNG b/design/src-web/shared/img/sprite_interface.NPK/windowcommon_2x.img/6.PNG new file mode 100644 index 00000000..eabf06e5 Binary files /dev/null and b/design/src-web/shared/img/sprite_interface.NPK/windowcommon_2x.img/6.PNG differ diff --git a/design/src-web/shared/img/sprite_interface2_option.NPK/option.img/88.PNG b/design/src-web/shared/img/sprite_interface2_option.NPK/option.img/88.PNG new file mode 100644 index 00000000..3bd41ad2 Binary files /dev/null and b/design/src-web/shared/img/sprite_interface2_option.NPK/option.img/88.PNG differ diff --git a/design/src-web/shared/index.html b/design/src-web/shared/index.html new file mode 100644 index 00000000..3addc35a --- /dev/null +++ b/design/src-web/shared/index.html @@ -0,0 +1,37 @@ + + + + + + + shared component catalog + + + + + + + + diff --git a/design/src-web/shared/style/index.css b/design/src-web/shared/style/index.css new file mode 100644 index 00000000..05a254bf --- /dev/null +++ b/design/src-web/shared/style/index.css @@ -0,0 +1,233 @@ +/* Source module: tokens.css */ +@font-face { + font-family: "DCalc"; + src: url("../img/fonts/dcalc.ttf") format("truetype"); + font-display: block; +} + +:root { + --black-950: #050505; + --black-900: #090808; + --panel: #131515; + --row: #1f1f1e; + --row-2: #2e2e2c; + --title-top: #5a7099; + --title-mid: #415272; + --title-bottom: #313e58; + --primary: #1a2b4e; + --primary-hover: #203259; + --primary-active: #16264c; + --brass-dark: #504029; + --brass: #907746; + --gold: #d6c487; + --selected: #daa41d; + --focus: #4ba7d3; + --text: #f6f8f4; + --text-2: #d6d3c6; + --text-3: #a7a396; + --disabled: #4d4b4d; + --info: #54c1db; + --success: #49a355; + --warning: #c28954; + --danger: #bb3331; + /* Captured control palette. These fill gaps in the semantic palette without changing it. */ + --control-blue: var(--primary); + --control-blue-top: #1f355e; + --control-blue-bottom: #1a2849; + --control-green-top: #014f22; + --control-green-bottom: #013f1b; + --control-orange-top: #522d01; + --control-orange-bottom: #412401; + --control-edge-top: #684f2d; + --control-edge-bottom: #483423; + --control-disabled-top: #2c2c2c; + --control-disabled-bottom: #222222; + --control-disabled-edge-top: #343434; + --control-disabled-edge-bottom: #262626; + --control-glyph: #b69260; + --control-highlight: var(--gold); + --attribute-label: #9a7d49; + --attribute-value: #469b51; + --skill-evolution: #bb56f1; + --skill-passive: #00ce08; + --skill-active: #b69b33; + --skill-awakening: #f27300; + --skill-buff: #63c8e1; + --quality-normal: #ffffff; + --quality-advanced: #68d5ed; + --quality-rare: #9879da; + --quality-artifact: #ef28c1; + --quality-legend: #ff7700; + --quality-epic: #fcb600; + --quality-chronicle: #ff6666; +} + +* { box-sizing: border-box; } + +html, + +/* Source module: base.css */ +body { + margin: 0; + background: #242524; + color: var(--text-2); + font-family: "Segoe UI", "Microsoft YaHei", sans-serif; +} + +body { + width: 1920px; + display: flex; + flex-direction: column; + gap: 48px; + padding: 0; +} + +.board { + position: relative; + width: 1920px; + height: 1200px; + padding: 38px 46px 42px; + overflow: hidden; + background: + radial-gradient(circle at 84% 7%, rgba(65, 82, 114, 0.12), transparent 22%), + linear-gradient(180deg, #090b0b 0, #050505 150px, #070707 100%); + border: 1px solid #161817; +} + +.board::after { + content: ""; + position: absolute; + inset: 0; + pointer-events: none; + background-image: linear-gradient(rgba(255,255,255,.012) 1px, transparent 1px); + background-size: 100% 4px; + opacity: .45; +} + +.board-header { + position: relative; + z-index: 2; + height: 88px; + display: flex; + align-items: flex-start; + justify-content: space-between; + border-bottom: 1px solid var(--brass-dark); +} + +.board-kicker { + color: var(--selected); + font-size: 12px; + letter-spacing: 2.6px; + text-transform: uppercase; + margin-bottom: 8px; +} + +.board-title { + margin: 0; + color: #e5d69a; + font-size: 30px; + line-height: 1.1; + font-weight: 650; + letter-spacing: .7px; +} + +.board-subtitle { + margin-top: 8px; + color: var(--text-3); + font-size: 13px; +} + +.board-index { + padding-top: 9px; + text-align: right; + color: var(--text-3); + font-size: 12px; + letter-spacing: .8px; +} + +.board-index strong { + display: block; + color: var(--gold); + font-size: 22px; + font-weight: 500; + margin-bottom: 5px; +} + +.content { + position: relative; + z-index: 2; + height: 1010px; + padding-top: 22px; +} + +.grid { display: grid; gap: 18px; } +.grid.cols-2 { grid-template-columns: 1fr 1fr; } +.grid.cols-3 { grid-template-columns: repeat(3, 1fr); } +.grid.cols-4 { grid-template-columns: repeat(4, 1fr); } + +.panel { + position: relative; + min-width: 0; + background: linear-gradient(180deg, rgba(20,22,22,.98), rgba(7,8,8,.98)); + border: 1px solid #403421; + box-shadow: inset 0 1px 0 rgba(214,196,135,.06), 0 12px 28px rgba(0,0,0,.32); +} + +.panel-heading { + height: 46px; + padding: 0 16px; + display: flex; + align-items: center; + justify-content: space-between; + border-bottom: 1px solid #242725; + background: #111313; +} + +.panel-title { + color: var(--gold); + font-size: 17px; + font-weight: 600; +} + +.panel-note { color: var(--text-3); font-size: 11px; } +.panel-body { padding: 18px; } + +.rule-label { + color: var(--text-3); + font-size: 10px; + letter-spacing: 1.2px; + text-transform: uppercase; + margin-bottom: 9px; +} + +.sample-label { + color: var(--text-3); + font-size: 11px; + margin-bottom: 8px; +} + +.spec-row { display: flex; gap: 7px; flex-wrap: wrap; } +.spec-chip { + height: 20px; + padding: 0 7px; + display: inline-flex; + align-items: center; + border: 1px solid #3c3e3c; + background: #101111; + color: var(--text-3); + font-size: 10px; + letter-spacing: .4px; +} + +.spec-chip.captured { border-color: #6f5a32; color: var(--gold); } +.spec-chip.derived { border-color: #24566d; color: var(--focus); } +.spec-chip.asset { border-color: #34533e; color: var(--success); } + +.divider { height: 1px; background: #292b29; margin: 14px 0; } + +.dnf-ui { + font-family: "DCalc", SimSun, "Microsoft YaHei", sans-serif; + text-shadow: 1px 1px 0 #000, 0 0 2px #000; +} + +.asset-2x { image-rendering:auto !important; } diff --git a/design/src-web/shop-item-row/component.js b/design/src-web/shop-item-row/component.js new file mode 100644 index 00000000..3743203e --- /dev/null +++ b/design/src-web/shop-item-row/component.js @@ -0,0 +1,4 @@ +(() => { + window.componentRegistry ||= {}; + window.componentRegistry["src-web/shop-item-row/index.html"] = {"showcase":"
\n
ShopItemRow
No header · dual normal rows · hover / selected
\n
\n
\n
\n
+0
+0
人造神 3 号纳波尔宝珠
购买完成
湖北 4
绝唱
\n
+0
+0
果味整夏收集箱宝珠自选
出售完成
湖北 4
绝唱
\n
+2
+0
魔法封印转换灵魂
购买完成
湖北 4
蛋猪超人
\n
+0
+0
史诗灵魂结晶
购买完成
湖北 4
蛋猪超人
\n
+0
+0
史诗灵魂结晶
购买完成
湖北 4
蛋猪超人
\n
\n
\n
RowNormal = CSS 96 / 85Hover / Selected = CSS 86 / 87Header = None
\n
\n
"}; +})(); diff --git a/design/src-web/shop-item-row/img/sprite_interface.NPK/windowcommon.chn.img/652.PNG b/design/src-web/shop-item-row/img/sprite_interface.NPK/windowcommon.chn.img/652.PNG new file mode 100644 index 00000000..fe02d586 Binary files /dev/null and b/design/src-web/shop-item-row/img/sprite_interface.NPK/windowcommon.chn.img/652.PNG differ diff --git a/design/src-web/shop-item-row/img/sprite_item.NPK/equipmentskill.img/3.PNG b/design/src-web/shop-item-row/img/sprite_item.NPK/equipmentskill.img/3.PNG new file mode 100644 index 00000000..db40e39f Binary files /dev/null and b/design/src-web/shop-item-row/img/sprite_item.NPK/equipmentskill.img/3.PNG differ diff --git a/design/src-web/shop-item-row/img/sprite_item.NPK/equipmentskill.img/4.PNG b/design/src-web/shop-item-row/img/sprite_item.NPK/equipmentskill.img/4.PNG new file mode 100644 index 00000000..4d3ffb0e Binary files /dev/null and b/design/src-web/shop-item-row/img/sprite_item.NPK/equipmentskill.img/4.PNG differ diff --git a/design/src-web/shop-item-row/img/sprite_item.NPK/equipmentskill.img/7.PNG b/design/src-web/shop-item-row/img/sprite_item.NPK/equipmentskill.img/7.PNG new file mode 100644 index 00000000..065856e0 Binary files /dev/null and b/design/src-web/shop-item-row/img/sprite_item.NPK/equipmentskill.img/7.PNG differ diff --git a/design/src-web/shop-item-row/img/sprite_item.NPK/equipmentskill.img/8.PNG b/design/src-web/shop-item-row/img/sprite_item.NPK/equipmentskill.img/8.PNG new file mode 100644 index 00000000..fea1b324 Binary files /dev/null and b/design/src-web/shop-item-row/img/sprite_item.NPK/equipmentskill.img/8.PNG differ diff --git a/design/src-web/shop-item-row/img/sprite_item.NPK/equipmentskill.img/9.PNG b/design/src-web/shop-item-row/img/sprite_item.NPK/equipmentskill.img/9.PNG new file mode 100644 index 00000000..63b66ad9 Binary files /dev/null and b/design/src-web/shop-item-row/img/sprite_item.NPK/equipmentskill.img/9.PNG differ diff --git a/design/src-web/shop-item-row/index.html b/design/src-web/shop-item-row/index.html new file mode 100644 index 00000000..7308eecc --- /dev/null +++ b/design/src-web/shop-item-row/index.html @@ -0,0 +1,30 @@ + + + + + + + shop item row component catalog + + + + + + + diff --git a/design/src-web/shop-item-row/style/index.css b/design/src-web/shop-item-row/style/index.css new file mode 100644 index 00000000..f4a82a2a --- /dev/null +++ b/design/src-web/shop-item-row/style/index.css @@ -0,0 +1,37 @@ +/* Source module: shop-item-row.css */ +.shop-item-table { border:0;background:transparent;overflow:visible; } +.shop-item-row { position:relative;min-height:48px;box-sizing:border-box;padding-inline:18px;display:grid;grid-template-columns:42px 36px 48px minmax(130px,1.55fr) 72px .92fr 1.1fr;align-items:center;color:#cabd82;font-size:11px;isolation:isolate; } +.shop-item-row > *:not(.shop-item-row-frame) { min-width:0;padding:0 7px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis; } +.shop-item-body { display:flex;flex-direction:column;gap:4px; } +.shop-item-body .shop-item-row { + --shop-frame-inset:5px;--shop-frame-corner:7px;--shop-surface-inset:8px;--shop-surface-corner:5px; + --shop-outer:#2e2e2e;--shop-middle:#191919;--shop-accent:#050505;--shop-inner:transparent; + --shop-surface:linear-gradient(180deg,#070707 0%,#080808 100%);--shop-shadow:transparent; + --shop-frame-filter:drop-shadow(0 0 4px rgba(0,0,0,.42));--shop-surface-filter:none; + cursor:pointer; +} +.shop-item-body .shop-item-row:nth-child(even) { --shop-outer:#60503a;--shop-middle:#342b1f;--shop-accent:#080808;--shop-surface:linear-gradient(180deg,#0b0b0b 0%,#0e0e0e 100%); } +.shop-item-body .shop-item-row:hover { + --shop-frame-inset:3px;--shop-frame-corner:9px;--shop-surface-inset:7px; + --shop-outer:#000820;--shop-middle:#082068;--shop-accent:#1888b8;--shop-inner:#082040;--shop-surface:#000810;--shop-shadow:#000;--shop-frame-filter:none; + --shop-surface-filter:drop-shadow(1px 0 0 var(--shop-inner)) drop-shadow(-1px 0 0 var(--shop-inner)) drop-shadow(0 1px 0 var(--shop-inner)) drop-shadow(0 -1px 0 var(--shop-inner)); +} +.shop-item-body .shop-item-row.is-selected { + --shop-frame-inset:3px;--shop-frame-corner:9px;--shop-surface-inset:7px; + --shop-outer:#201808;--shop-middle:#604818;--shop-accent:#e8a828;--shop-inner:#302008;--shop-surface:#100800;--shop-shadow:#000;--shop-frame-filter:none; + --shop-surface-filter:drop-shadow(1px 0 0 var(--shop-inner)) drop-shadow(-1px 0 0 var(--shop-inner)) drop-shadow(0 1px 0 var(--shop-inner)) drop-shadow(0 -1px 0 var(--shop-inner)); +} +.shop-item-row::before,.shop-item-row::after,.shop-item-row-frame,.shop-item-row-frame::before,.shop-item-row-frame::after { content:"";position:absolute;pointer-events:none; } +.shop-item-row::before { z-index:-3;inset:0;background:var(--shop-shadow); } +.shop-item-row-frame { z-index:-2;inset:var(--shop-frame-inset);background:var(--shop-outer);clip-path:polygon(var(--shop-frame-corner) 0,calc(100% - var(--shop-frame-corner)) 0,100% var(--shop-frame-corner),100% calc(100% - var(--shop-frame-corner)),calc(100% - var(--shop-frame-corner)) 100%,var(--shop-frame-corner) 100%,0 calc(100% - var(--shop-frame-corner)),0 var(--shop-frame-corner));filter:var(--shop-frame-filter); } +.shop-item-row-frame::before { inset:1px;background:var(--shop-middle);clip-path:polygon(calc(var(--shop-frame-corner) - 1px) 0,calc(100% - var(--shop-frame-corner) + 1px) 0,100% calc(var(--shop-frame-corner) - 1px),100% calc(100% - var(--shop-frame-corner) + 1px),calc(100% - var(--shop-frame-corner) + 1px) 100%,calc(var(--shop-frame-corner) - 1px) 100%,0 calc(100% - var(--shop-frame-corner) + 1px),0 calc(var(--shop-frame-corner) - 1px)); } +.shop-item-row-frame::after { inset:2px;background:var(--shop-accent);clip-path:polygon(calc(var(--shop-frame-corner) - 2px) 0,calc(100% - var(--shop-frame-corner) + 2px) 0,100% calc(var(--shop-frame-corner) - 2px),100% calc(100% - var(--shop-frame-corner) + 2px),calc(100% - var(--shop-frame-corner) + 2px) 100%,calc(var(--shop-frame-corner) - 2px) 100%,0 calc(100% - var(--shop-frame-corner) + 2px),0 calc(var(--shop-frame-corner) - 2px)); } +.shop-item-row::after { z-index:-1;inset:var(--shop-surface-inset);background:var(--shop-surface);clip-path:polygon(var(--shop-surface-corner) 0,calc(100% - var(--shop-surface-corner)) 0,100% var(--shop-surface-corner),100% calc(100% - var(--shop-surface-corner)),calc(100% - var(--shop-surface-corner)) 100%,var(--shop-surface-corner) 100%,0 calc(100% - var(--shop-surface-corner)),0 var(--shop-surface-corner));filter:var(--shop-surface-filter); } +.shop-item-row-icon { width:36px;height:38px;padding:0!important;display:flex;align-items:center;justify-content:center; } +.shop-item-row-icon img { max-width:28px;max-height:28px;image-rendering:pixelated; } +.shop-inspect-button { --shop-action-top:#1261a4;--shop-action-bottom:#071f3b;appearance:none;width:28px;height:24px;padding:0;display:inline-flex;align-items:center;justify-content:center;border:2px solid #5b472a;border-radius:0;background:linear-gradient(180deg,var(--shop-action-top),var(--shop-action-bottom));box-shadow:0 0 0 1px rgba(0,0,0,.3),inset 0 0 0 1px #0f0f0f;line-height:0;cursor:pointer; } +.shop-inspect-button:hover { --shop-action-top:#1d9bdb;--shop-action-bottom:#0b325e;border-color:#927243; } +.shop-inspect-button:active { transform:translateY(1px); } +.shop-inspect-button img { max-width:16px;max-height:16px;image-rendering:pixelated; } +.shop-item-row .status { color:var(--info); }.shop-item-row .success { color:var(--success); } +.shop-item-row-spec { margin-top:auto;padding-top:10px; } diff --git a/design/src-web/slider/component.js b/design/src-web/slider/component.js new file mode 100644 index 00000000..e81f4bd0 --- /dev/null +++ b/design/src-web/slider/component.js @@ -0,0 +1,4 @@ +(() => { + window.componentRegistry ||= {}; + window.componentRegistry["src-web/slider/index.html"] = {"showcase":"
\n
SliderStandard / SliderCompact
Gold range · graphite rail · blue/brass thumb
\n
\n
\n
0% · Normal / CSS
0%
\n
29% · Hover / CSS
29%
\n
100% · Pressed / CSS
100%
\n
\n
\n
\n
40%
\n
禁用
\n
\n
Percent / Seconds / Ticks capturedDrag / Focus derived
\n
\n
"}; +})(); diff --git a/design/src-web/slider/img/.gitkeep b/design/src-web/slider/img/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/design/src-web/slider/index.html b/design/src-web/slider/index.html new file mode 100644 index 00000000..d60a915f --- /dev/null +++ b/design/src-web/slider/index.html @@ -0,0 +1,34 @@ + + + + + + + slider component catalog + + + + + + + + diff --git a/design/src-web/slider/style/index.css b/design/src-web/slider/style/index.css new file mode 100644 index 00000000..832263cc --- /dev/null +++ b/design/src-web/slider/style/index.css @@ -0,0 +1,64 @@ +/* Source module: slider.css */ +.slider { + width: 270px; + min-height: 34px; + display: flex; + align-items: center; + gap: 10px; + padding: 0; + border-radius: 0; + background: transparent; + box-shadow: none; +} + +.slider-track { position: relative; flex: 1; height: 3px; background: #515351; box-shadow: 0 1px 0 #020202; } +.slider-range { position: absolute; inset: 0 auto 0 0; width: var(--value, 50%); background: #f3d367; box-shadow: 0 0 3px rgba(243,211,103,.25); } +.slider-thumb { + --thumb-edge-top:#86693f; + --thumb-edge-bottom:#76593a; + --thumb-top:#21365e; + --thumb-bottom:#1b2b4d; + box-sizing:border-box; + position:absolute; + left:var(--value,50%); + top:50%; + width:17px; + height:17px; + transform:translate(-50%,-50%); + border:1px solid transparent; + border-radius:50%; + background: + radial-gradient(circle at 50% 28%,var(--thumb-top),var(--thumb-bottom) 78%) padding-box, + linear-gradient(180deg,var(--thumb-edge-top),var(--thumb-edge-bottom)) border-box; + box-shadow:0 0 0 1px rgba(0,0,0,.4),inset 0 1px 0 rgba(255,255,255,.025); +} +.slider-value { min-width: 40px; color: var(--gold); font-size: 12px; text-align: right; } +.slider.compact { width: 238px; } +.slider.compact, +.slider.surface { padding:0 12px;border-radius:17px; } +.slider.disabled .slider-range { background:#686868;box-shadow:none; } +.slider.disabled .slider-value { color:var(--disabled); } +.slider[data-slider] { cursor:pointer;touch-action:none; } +.slider[data-slider]:focus-visible { outline:1px solid var(--focus);outline-offset:2px; } +.slider.is-hover .slider-thumb, +.slider[data-slider]:hover .slider-thumb { + --thumb-edge-top:#907960; + --thumb-edge-bottom:#80695b; + --thumb-top:#2b467f; + --thumb-bottom:#253b6e; +} +.slider.is-pressed .slider-thumb, +.slider[data-slider].is-dragging .slider-thumb, +.slider[data-slider]:active .slider-thumb { + --thumb-edge-top:#907960; + --thumb-edge-bottom:#80695b; + --thumb-top:#2b467f; + --thumb-bottom:#253b6e; +} +.slider.disabled .slider-thumb { + --thumb-edge-top:#454545; + --thumb-edge-bottom:#3e3e3e; + --thumb-top:#2c2c2c; + --thumb-bottom:#242424; + box-shadow:0 0 0 1px rgba(0,0,0,.35); +} diff --git a/design/src-web/sync-components.py b/design/src-web/sync-components.py new file mode 100644 index 00000000..bd4e6fc1 --- /dev/null +++ b/design/src-web/sync-components.py @@ -0,0 +1,28 @@ +from __future__ import annotations + +import json +import re +from pathlib import Path + + +ROOT = Path(__file__).resolve().parent +TEMPLATE = re.compile(r'\s*(.*?)\s*', re.S) + + +for component in sorted(path for path in ROOT.iterdir() if path.is_dir()): + source = component / "index.html" + if not source.is_file(): + continue + fragments = dict(TEMPLATE.findall(source.read_text(encoding="utf-8"))) + if not fragments: + raise RuntimeError(f"No templates found in {source}") + key = f"{ROOT.name}/{component.name}/index.html" + payload = json.dumps(fragments, ensure_ascii=False, separators=(",", ":")) + script = ( + "(() => {\n" + " window.componentRegistry ||= {};\n" + f" window.componentRegistry[{json.dumps(key)}] = {payload};\n" + "})();\n" + ) + (component / "component.js").write_text(script, encoding="utf-8", newline="\n") + print(f"Updated {component.name}/component.js") diff --git a/design/src-web/tabs/component.js b/design/src-web/tabs/component.js new file mode 100644 index 00000000..c832738b --- /dev/null +++ b/design/src-web/tabs/component.js @@ -0,0 +1,4 @@ +(() => { + window.componentRegistry ||= {}; + window.componentRegistry["src-web/tabs/index.html"] = {"showcase":"
\n
Tabs / Pagination
CSS 126 hover base + CSS 667 selected overlay · CSS 127/128/180
\n
\n
\n
\n
Tabs · Marker = Arrow · first tab selected
\n
\n
\n
\n
Tabs · Marker = Line
\n
\n
\n
\n
\n
◀1 / 15▶搜索出 142 个
\n
ITEM WIDTH = EQUALIZED MAX CONTENTDEFAULT / HOVER / CLICK CAPTURED
\n
\n
\n
"}; +})(); diff --git a/design/src-web/tabs/img/.gitkeep b/design/src-web/tabs/img/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/design/src-web/tabs/index.html b/design/src-web/tabs/index.html new file mode 100644 index 00000000..6d87e0dd --- /dev/null +++ b/design/src-web/tabs/index.html @@ -0,0 +1,37 @@ + + + + + + + tabs component catalog + + + + + + + + diff --git a/design/src-web/tabs/style/index.css b/design/src-web/tabs/style/index.css new file mode 100644 index 00000000..d7d7f717 --- /dev/null +++ b/design/src-web/tabs/style/index.css @@ -0,0 +1,149 @@ +/* Source module: tabs.css */ +.component-stack { display: flex; flex-direction: column; gap: 12px; } +.sample-grid { display: grid; grid-template-columns: repeat(4, minmax(0,1fr)); gap: 14px; } +.sample-grid.cols-3 { grid-template-columns: repeat(3, minmax(0,1fr)); } +.sample-grid.cols-2 { grid-template-columns: repeat(2, minmax(0,1fr)); } +.sample-cell { min-width: 0; padding: 12px; border: 1px solid #202321; background: rgba(0,0,0,.22); } + +.tabs-showcase { display:grid;grid-template-columns:1fr 1fr;gap:18px; } +.game-tabs { + position:relative; + width:100%; + height:40px; + display:flex; + justify-content:flex-start; + align-items:flex-start; + padding:5px 7px; + overflow:visible; + border:0; + border-radius:0; + background:#090709; + box-shadow:none; +} +.game-tabs::after { + content:""; + position:absolute; + z-index:3; + left:7px; + right:7px; + top:35px; + height:1px; + background:#584840; + pointer-events:none; +} +.game-tab { + --tab-126-glow:linear-gradient(90deg, + transparent 0%, + rgba(48,24,8,.18) 10%, + rgba(48,24,8,.72) 28%, + #301808 50%, + rgba(48,24,8,.72) 72%, + rgba(48,24,8,.18) 90%, + transparent 100%); + --tab-667-glow:radial-gradient(ellipse 58% 46% at 50% 100%, + rgba(114,97,30,.94) 0%, + rgba(88,74,23,.74) 34%, + rgba(52,44,14,.38) 66%, + transparent 100%); + appearance:none; + position:relative; + min-width:0; + width:var(--tab-item-width,auto); + flex:0 0 var(--tab-item-width,auto); + display:inline-flex; + align-items:center; + justify-content:center; + z-index:auto; + height:30px; + padding:0 12px; + border:0; + background:#080808; + color:#9c815a; + font:16px/1 "DCalc",SimSun,sans-serif; + text-shadow:1px 1px 0 #000,0 0 2px #000; + white-space:nowrap; + cursor:pointer; +} +.game-tab:not(:last-of-type)::after { + content:""; + position:absolute; + top:5px; + right:0; + width:1px; + height:19px; + background:linear-gradient(180deg, + rgba(52,47,42,.153) 0%, + rgba(52,47,42,.376) 5.56%, + rgba(52,47,42,.624) 11.11%, + rgba(52,47,42,.847) 16.67%, + #342f2a 22.22%, + #342f2a 77.78%, + rgba(52,47,42,.847) 83.33%, + rgba(52,47,42,.624) 88.89%, + rgba(52,47,42,.376) 94.44%, + rgba(52,47,42,.153) 100%); + pointer-events:none; +} +.game-tab:hover { + color:#e4ca90; + background-image:var(--tab-126-glow); +} +.game-tab.selected, +.game-tab.selected:hover { + color:#e4ca90; + background-image:var(--tab-667-glow),var(--tab-126-glow); +} +.game-tab .tab-label { position:relative;z-index:1;display:inline-block; } +.game-tab:active { transform:none; } +.game-tab:active .tab-label, +.game-tab.is-pressed .tab-label { transform:translateY(1px); } +.game-tabs > .tab-marker { position:absolute;z-index:4;left:0;bottom:0;width:39px;height:5px;opacity:0;transform:translateX(-50%);pointer-events:none; } +.game-tabs > .tab-marker::before { + content:""; + position:absolute; + inset:0 0 auto; + height:1px; + background:linear-gradient(90deg, + rgba(208,165,106,.024) 0%, + rgba(208,165,106,.22) 10%, + rgba(208,165,106,.49) 23%, + rgba(208,165,106,.82) 36%, + #9d7a35 44%, + #9d7a35 56%, + rgba(208,165,106,.82) 64%, + rgba(208,165,106,.49) 77%, + rgba(208,165,106,.22) 90%, + rgba(208,165,106,.024) 100%); +} +.game-tabs > .tab-marker::after { + content:""; + position:absolute; + left:50%; + top:1px; + width:9px; + height:4px; + background:linear-gradient(180deg,#9d7a35 0%,#a7823f 46%,#d0a56a 100%); + clip-path:polygon(0 0,100% 0,50% 100%); + transform:translateX(-50%); + filter:drop-shadow(0 0 1px rgba(157,122,53,.22)); +} +.game-tabs > .tab-marker.is-ready { opacity:1;transition:left 300ms cubic-bezier(.22,.61,.36,1); } +.game-tabs > .tab-marker-line::before { + background:linear-gradient(90deg, + rgba(208,165,106,.024) 0%, + rgba(208,165,106,.286) 15%, + rgba(208,165,106,.631) 28%, + rgba(208,165,106,.875) 38%, + #d0a56a 50%, + rgba(208,165,106,.875) 62%, + rgba(208,165,106,.631) 72%, + rgba(208,165,106,.286) 85%, + rgba(208,165,106,.024) 100%); +} +.game-tabs > .tab-marker-line::after { display:none; } +@media (prefers-reduced-motion:reduce) { .game-tabs > .tab-marker.is-ready { transition:none; } } +.tabs-pager-row { display:flex;align-items:center;justify-content:space-between;margin-top:10px; } + +.pager { height: 34px; display: flex; align-items: center; gap: 8px; color: var(--gold); } +.pager-btn { width: 27px; height: 25px; display:flex;align-items:center;justify-content:center;border:1px solid #514125;background:#101211;color:#8b8778; } +.pager-btn.active { background: #1b315c; color: #e3c977; } diff --git a/frontend-ui/.editorconfig b/frontend-ui/.editorconfig new file mode 100644 index 00000000..5a5809db --- /dev/null +++ b/frontend-ui/.editorconfig @@ -0,0 +1,9 @@ +[*.{js,jsx,mjs,cjs,ts,tsx,mts,cts,vue,css,scss,sass,less,styl}] +charset = utf-8 +indent_size = 2 +indent_style = space +insert_final_newline = true +trim_trailing_whitespace = true + +end_of_line = lf +max_line_length = 100 diff --git a/frontend-ui/.oxfmtrc.json b/frontend-ui/.oxfmtrc.json new file mode 100644 index 00000000..6157266b --- /dev/null +++ b/frontend-ui/.oxfmtrc.json @@ -0,0 +1,7 @@ +{ + "$schema": "./node_modules/oxfmt/configuration_schema.json", + "printWidth": 100, + "semi": false, + "singleQuote": true, + "ignorePatterns": ["dist", "src/types/auto-imports.d.ts", "components.d.ts"] +} diff --git a/frontend-ui/README.md b/frontend-ui/README.md new file mode 100644 index 00000000..cb5877e4 --- /dev/null +++ b/frontend-ui/README.md @@ -0,0 +1,49 @@ +# DCalc frontend-ui + +`frontend-ui` is the progressive UI refactor of the current `frontend` application. The original +project remains available as the behavior baseline. + +## Foundation + +- Vue 3, Vue Router, Pinia, Vite and TypeScript track the current stable release line. +- Reka UI provides accessible interaction primitives. +- Tailwind CSS 4 provides layout utilities without Preflight during the migration period. +- CSS variables define the stable semantic contract between components and themes. +- SCSS/CSS remains available for game textures, image borders and state effects. +- `class-variance-authority` defines component variants in the local, source-owned UI layer. +- Oxc (`oxlint` and `oxfmt`) handles linting and formatting. + +## Theme model + +Components consume `--ui-*` semantic variables. Each skin maps its own palette and effects to that +contract under `[data-theme]`. Add a theme stylesheet and register it in `useTheme.ts`; component +code should not need to change. + +The initial themes are: + +- `dcalc`: tokens captured from `design/src-web`. +- `midnight`: a second skin used to verify that components are not coupled to the classic palette. + +## Commands + +```sh +pnpm install +pnpm dev +pnpm check +pnpm build +``` + +Open `/components` for the complete catalog of currently introduced components and their live +interactions. `/ui-preview` remains the smaller foundation smoke-test page. + +See [`docs/ui-migration-standard.md`](docs/ui-migration-standard.md) for the reusable component +migration, theming, responsive implementation and browser QA standard. + +The current catalog covers Button, Badge, Panel, Input, NumberField, Checkbox, RadioGroup, Switch, +Rating, Select, Slider, Progress, Tabs, ItemSlot, DataTable, Tooltip, DropdownMenu and Dialog. + +## Migration rule + +New UI components live under `src/components/ui`. Route changes, keyboard shortcuts and DNF data +mapping belong to pages, composables or domain components instead of generic primitives. Existing +`calc-*` components remain only until their business call sites are migrated. diff --git a/frontend-ui/design-qa.md b/frontend-ui/design-qa.md new file mode 100644 index 00000000..32ee179e --- /dev/null +++ b/frontend-ui/design-qa.md @@ -0,0 +1,56 @@ +# Component fidelity QA + +- Source visual truth: `/Users/xigua/.codex/visualizations/2026/08/04/019fcbb3-69c4-7363-81ba-fa53cab1424e/design-board-2-1920.png` +- Implementation: `/Users/xigua/.codex/visualizations/2026/08/04/019fcbb3-69c4-7363-81ba-fa53cab1424e/catalog-fidelity-audit-final-1920.png` +- Viewport: 1920 × 1200 CSS px +- Source pixels: 1920 × 1200 +- Implementation pixels: 1920 × 1200 +- Density normalization: devicePixelRatio 1; no resampling required +- State: default catalog with Button state matrix; interactive Dialog state captured separately at `catalog-audit-dialog-animated.png` + +## Full-view comparison + +The implementation keeps the source board's full-width dark surface, 46 px panel headings, brass dividers, DCalc typography, square corners, compact 30 px controls, and dense state matrices. The catalog intentionally adds a component index, theme controls, and implementation-specific copy; these are catalog navigation rather than component anatomy changes. + +## Focused comparisons + +- Button: three five-column state rows now match the source's Rest, Hover, Pressed, Disabled, and tone-family organization. Panel height is 281.5 px versus the 292 px source module target; the difference is the catalog's smaller bottom spacing and is visually non-material. +- NumberField: 30 px field, 23 px spinner, visible up/down arrows, and two 14 px `+10`/`-10` fast-step buttons match the source anatomy. +- Tabs: 40 px list, 30 px triggers, glow layers, divider line, animated 39 × 5 px arrow marker, and line-marker variant are present. Marker movement follows Reka selection state and respects reduced motion. +- Dialog: the titlebar uses the exact 45 raster frames from `windowheadereffect.img`, advances every 66 ms while focused, and hides the effect in the unfocused/reduced-motion state. +- Responsive: document overflow is absent at 1920, 1280, 768, and 390 widths. At 390 px, DataTable keeps a 328 px viewport with an intentional 560 px internal scroll surface. + +## Required fidelity surfaces + +- Fonts and typography: DCalc/SimSun control typography and Segoe UI/Chinese fallbacks retain the source hierarchy and compact line-height. +- Spacing and layout rhythm: page gutters use `clamp()`, panels use container-relative padding, grids collapse at 1280/900/520 breakpoints, and atomic game-control sizes stay pixel-aligned. +- Colors and tokens: blue action surfaces, brass edges, gold selection, blue focus, disabled gray, semantic status colors, and rarity colors map to DCalc CSS variables. +- Image quality and assets: stars, rarity frames, item icons, select arrow, dialog close icon, and all 45 title-effect frames use original raster assets with zero broken images. +- Copy and content: catalog copy differs only where it documents the Reka implementation or exposes live state; component labels and source examples remain representative. + +## Interaction verification + +- NumberField fast step: 1 → 11. +- Tabs: line marker moved to `来源`; selected state became active. +- Checkbox: unchecked → checked. +- Switch: checked → unchecked. +- Rating: 1 → 3. +- Select: 装备 → 材料. +- DropdownMenu: `导出结果` updated live status. +- Dialog: title frame changed from `4.PNG` to `5.PNG`; cancel restored focus to `打开 WindowDialog`. + +## Comparison history + +- P1: NumberField step affordances were too small and FastStep was missing. Fixed with source-sized arrows and `+10`/`-10` controls. +- P1: Tabs used a trigger-local pseudo marker and could not reproduce source movement. Fixed with a list-owned marker driven by active Reka tab geometry. +- P1: Dialog titlebar had a static gradient only. Fixed with the exact focused 45-frame animation. +- P2: Button showcase omitted source state rows. Fixed with the complete three-row state matrix. +- P2: shadcn-like radii, generic focus rings, menu surface, and tooltip transitions drifted from DNF styling. Replaced with source-specific square surfaces and state treatments. +- P2: layout relied on fixed page spacing. Replaced page-level spacing and grids with fluid/container-responsive rules while preserving atomic raster dimensions. + +## Remaining intentional deviations + +- The catalog header includes theme switching and a component index that are not present on Design board 2. +- Components not yet migrated (CommandInput, TreeSelect, Cascader, navigation, ScrollArea, and complex product dialogs) are out of this comparison and must be covered in later migration batches. + +final result: passed diff --git a/frontend-ui/docs/ui-migration-standard.md b/frontend-ui/docs/ui-migration-standard.md new file mode 100644 index 00000000..015cf19a --- /dev/null +++ b/frontend-ui/docs/ui-migration-standard.md @@ -0,0 +1,257 @@ +# DCalc UI 统一迁移与实现标准 + +本文档用于在其他 Vue 项目中复用当前 `frontend-ui` 的组件库迁移方法。目标不是机械复制页面,而是在保持业务功能的前提下,统一交互底座、视觉语言、主题能力、响应式策略和验收流程。 + +## 1. 标准目标 + +- 以现有业务实现为功能基线,允许调整业务代码以适配新的组件组合方式。 +- 以 `design` 的组件结构、状态、动效、素材和交互为视觉事实来源。 +- 使用 Reka UI 承担无障碍、键盘、焦点、受控状态和 Portal 等交互语义。 +- 使用 Tailwind CSS 处理通用布局,关闭 Preflight,避免迁移期全局样式突变。 +- 使用 CSS Variables 建立 DCalc Token 和语义 Token,组件只消费语义 Token。 +- 使用 CSS/SCSS 实现游戏质感、像素素材、复杂渐变、边框和状态效果。 +- 参考 shadcn-vue 的目录、组合、表单和 variants 规范,不要求引入整套默认视觉。 +- 使用 Oxc 统一格式化和静态检查。 + +## 2. 事实来源与优先级 + +发生冲突时按以下顺序判断: + +1. 业务功能、数据边界和用户可完成的操作不能丢失。 +2. `design` 中的组件结构、状态矩阵、动效和真实素材决定视觉结果。 +3. Reka UI 的可访问性与交互语义决定组件的基础 DOM 和状态模型。 +4. 组件 API、目录和组合方式遵循本标准。 +5. 仅在不影响以上约束时使用通用 Tailwind 工具类简化布局。 + +不要以静态截图代替业务与交互核对。设计中未展示的状态仍需覆盖 hover、pressed、focus-visible、disabled、open/closed、checked/unchecked 和 reduced-motion。 + +## 3. 推荐技术栈 + +| 层级 | 标准职责 | +| ------------------------ | ----------------------------------------------------------- | +| Vue 3 + TypeScript | 使用 Composition API、` + + + + + + + + diff --git a/frontend-ui/package.json b/frontend-ui/package.json new file mode 100644 index 00000000..480ad07e --- /dev/null +++ b/frontend-ui/package.json @@ -0,0 +1,56 @@ +{ + "name": "frontend-ui", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "run-p type-check build-only", + "preview": "vite preview", + "build-only": "vite build", + "type-check": "vue-tsc --build", + "check": "run-s format:check lint type-check", + "lint": "oxlint --deny-warnings .", + "lint:fix": "oxlint --fix .", + "format": "oxfmt --write .", + "format:check": "oxfmt --check ." + }, + "dependencies": { + "@vueuse/core": "^14.4.0", + "axios": "^1.8.2", + "class-variance-authority": "^0.7.1", + "clsx": "^2.1.1", + "hoci": "^0.6.0", + "pako": "^2.1.0", + "pinia": "^4.0.2", + "query-string": "^9.1.1", + "reka-ui": "^2.10.1", + "tailwind-merge": "^3.6.0", + "vue": "^3.5.40", + "vue-router": "^5.2.0" + }, + "devDependencies": { + "@tailwindcss/vite": "^4.3.3", + "@tsconfig/node24": "^24.0.4", + "@types/node": "^26.1.2", + "@types/pako": "^2.0.3", + "@vitejs/plugin-vue": "^6.0.8", + "@vitejs/plugin-vue-jsx": "^5.1.6", + "@vue/tsconfig": "^0.9.1", + "jiti": "^2.7.0", + "npm-run-all2": "^9.0.3", + "oxfmt": "^0.62.0", + "oxlint": "^1.77.0", + "sass": "^1.102.0", + "tailwindcss": "^4.3.3", + "typescript": "~6.0.3", + "unplugin-auto-import": "^21.1.0", + "unplugin-vue-components": "^32.1.0", + "vite": "^8.2.0", + "vue-tsc": "^3.3.9" + }, + "engines": { + "node": ">=22.12.0" + }, + "packageManager": "pnpm@10.25.0" +} diff --git a/frontend-ui/pnpm-lock.yaml b/frontend-ui/pnpm-lock.yaml new file mode 100644 index 00000000..a83af701 --- /dev/null +++ b/frontend-ui/pnpm-lock.yaml @@ -0,0 +1,3940 @@ +lockfileVersion: '9.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +importers: + + .: + dependencies: + '@vueuse/core': + specifier: ^14.4.0 + version: 14.4.0(vue@3.5.40(typescript@6.0.3)) + axios: + specifier: ^1.8.2 + version: 1.8.2 + class-variance-authority: + specifier: ^0.7.1 + version: 0.7.1 + clsx: + specifier: ^2.1.1 + version: 2.1.1 + hoci: + specifier: ^0.6.0 + version: 0.6.0(@babel/parser@7.29.8)(@vueuse/core@14.4.0(vue@3.5.40(typescript@6.0.3)))(rollup@4.35.0)(vue@3.5.40(typescript@6.0.3)) + pako: + specifier: ^2.1.0 + version: 2.1.0 + pinia: + specifier: ^4.0.2 + version: 4.0.2(@vue/devtools-api@8.2.1)(typescript@6.0.3)(vue@3.5.40(typescript@6.0.3)) + query-string: + specifier: ^9.1.1 + version: 9.1.1 + reka-ui: + specifier: ^2.10.1 + version: 2.10.1(vue@3.5.40(typescript@6.0.3)) + tailwind-merge: + specifier: ^3.6.0 + version: 3.6.0 + vue: + specifier: ^3.5.40 + version: 3.5.40(typescript@6.0.3) + vue-router: + specifier: ^5.2.0 + version: 5.2.0(@vue/compiler-sfc@3.5.40)(pinia@4.0.2(@vue/devtools-api@8.2.1)(typescript@6.0.3)(vue@3.5.40(typescript@6.0.3)))(rolldown@1.2.2)(rollup@4.35.0)(vite@8.2.0(@types/node@26.1.2)(jiti@2.7.0)(sass@1.102.0)(yaml@2.9.0))(vue@3.5.40(typescript@6.0.3)) + devDependencies: + '@tailwindcss/vite': + specifier: ^4.3.3 + version: 4.3.3(vite@8.2.0(@types/node@26.1.2)(jiti@2.7.0)(sass@1.102.0)(yaml@2.9.0)) + '@tsconfig/node24': + specifier: ^24.0.4 + version: 24.0.4 + '@types/node': + specifier: ^26.1.2 + version: 26.1.2 + '@types/pako': + specifier: ^2.0.3 + version: 2.0.3 + '@vitejs/plugin-vue': + specifier: ^6.0.8 + version: 6.0.8(vite@8.2.0(@types/node@26.1.2)(jiti@2.7.0)(sass@1.102.0)(yaml@2.9.0))(vue@3.5.40(typescript@6.0.3)) + '@vitejs/plugin-vue-jsx': + specifier: ^5.1.6 + version: 5.1.6(vite@8.2.0(@types/node@26.1.2)(jiti@2.7.0)(sass@1.102.0)(yaml@2.9.0))(vue@3.5.40(typescript@6.0.3)) + '@vue/tsconfig': + specifier: ^0.9.1 + version: 0.9.1(typescript@6.0.3)(vue@3.5.40(typescript@6.0.3)) + jiti: + specifier: ^2.7.0 + version: 2.7.0 + npm-run-all2: + specifier: ^9.0.3 + version: 9.0.3 + oxfmt: + specifier: ^0.62.0 + version: 0.62.0 + oxlint: + specifier: ^1.77.0 + version: 1.77.0 + sass: + specifier: ^1.102.0 + version: 1.102.0 + tailwindcss: + specifier: ^4.3.3 + version: 4.3.3 + typescript: + specifier: ~6.0.3 + version: 6.0.3 + unplugin-auto-import: + specifier: ^21.1.0 + version: 21.1.0(@vueuse/core@14.4.0(vue@3.5.40(typescript@6.0.3)))(rolldown@1.2.2)(rollup@4.35.0)(vite@8.2.0(@types/node@26.1.2)(jiti@2.7.0)(sass@1.102.0)(yaml@2.9.0)) + unplugin-vue-components: + specifier: ^32.1.0 + version: 32.1.0(rolldown@1.2.2)(rollup@4.35.0)(vite@8.2.0(@types/node@26.1.2)(jiti@2.7.0)(sass@1.102.0)(yaml@2.9.0))(vue@3.5.40(typescript@6.0.3)) + vite: + specifier: ^8.2.0 + version: 8.2.0(@types/node@26.1.2)(jiti@2.7.0)(sass@1.102.0)(yaml@2.9.0) + vue-tsc: + specifier: ^3.3.9 + version: 3.3.9(typescript@6.0.3) + +packages: + + '@antfu/utils@0.7.10': + resolution: {integrity: sha512-+562v9k4aI80m1+VuMHehNJWLOFjBnXn3tdOitzD0il5b7smkSBal4+a3oKiQTbrwMmN/TBUMDvbdoWDehgOww==} + + '@babel/code-frame@7.29.7': + resolution: {integrity: sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw==} + engines: {node: '>=6.9.0'} + + '@babel/compat-data@7.29.7': + resolution: {integrity: sha512-locTkQyKvwIEgBzVrn8693ebc97F2U8ZHjbXwDXJ5Fn2TCpNwTlKcaKLkdHop5c/icOFE7qt7Q9JC5hnKNa6Gg==} + engines: {node: '>=6.9.0'} + + '@babel/core@7.29.7': + resolution: {integrity: sha512-RgHBCvtjbOK2gXSNBNIkNoEc9qoVEtau3hj8gEqKQuL3HZAibKarWFEI3Lfm6EYKkLalOh8eSrj9b+ch9H/VBA==} + engines: {node: '>=6.9.0'} + + '@babel/generator@7.29.8': + resolution: {integrity: sha512-gZbepsdh3WDtgZKWL+vTPh71LSBrm/Y4/QDZBVCcYfmeTEEuoOYwlSy+G1StfJg+/Zy550u/3TATbm7qDbbMtg==} + engines: {node: '>=6.9.0'} + + '@babel/generator@8.0.0': + resolution: {integrity: sha512-NT9NrVwJsbSV6Y2FSstWa71EETOnzrjkL5/wX3D2mYHtKM+qvqB1DvR4D0Setb/gDBsHzRICifwEWMO8CnTF6g==} + engines: {node: ^22.18.0 || >=24.11.0} + + '@babel/helper-annotate-as-pure@7.29.7': + resolution: {integrity: sha512-OoK6239jHPuSQOoS0kfTVKn0b/rVTk0seKq4Gd2UMLtmOVLjDC0ki3e+c90Trqv2gMfvJFqkiljrr568+qddiw==} + engines: {node: '>=6.9.0'} + + '@babel/helper-compilation-targets@7.29.7': + resolution: {integrity: sha512-wem6WaBj4NaVYVdNhLPPVacES6ZJ+KBBfSkTMD3YZxbP3rm3Di85tJU5ljaUNhaOynt+Aj0xruhYuzQBt8n71g==} + engines: {node: '>=6.9.0'} + + '@babel/helper-create-class-features-plugin@7.29.7': + resolution: {integrity: sha512-IY3ZD9Tmooqr3TUhc3DUWxiuo8xx1DWLhd5M7hQ+ZWJamqM2BbalrBJb2MisSLoYorOj75U03qULCxQTY9r3hg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/helper-globals@7.29.7': + resolution: {integrity: sha512-3nQVUAtvkKH9zahfWgw96Jc/uFOmjACE1kQz82E2lqWmHBgjzbNlsC22nuQTfahmWeQtTq5nQ/4Nnd2A1wj4zA==} + engines: {node: '>=6.9.0'} + + '@babel/helper-member-expression-to-functions@7.29.7': + resolution: {integrity: sha512-j+7JYmk1JYDtACIGj0QJqqWZjoUpMoEikQGADMaHgCMCSDqd2+P32rfcibUNrGOMWrlzK1WJBdxrB3JJQZwWtg==} + engines: {node: '>=6.9.0'} + + '@babel/helper-module-imports@7.29.7': + resolution: {integrity: sha512-ejHwrQQYcm9xnTivShn2IDOlIzInN34AXskvq9QicvCtEzq1Vzclu/tKF8Jq1Cg8JG2GL6/EmjgsCT7lXepE3g==} + engines: {node: '>=6.9.0'} + + '@babel/helper-module-transforms@7.29.7': + resolution: {integrity: sha512-UPUVSyXbOh627KiCIGQSgwWzGeBKLkaJ9PJEdrngIwMSzxLR4jS4+f1f1jb7VzBbg8nFLaYotvVPFCTqdrmTAg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/helper-optimise-call-expression@7.29.7': + resolution: {integrity: sha512-+kmGVjcT9RGYzoDwdwEqEvGgKe3BYq+O1iGzjFubaNgZHwYHP6lsF2Yghf4kEuv9BV7tYDZ913aBW9am6YKong==} + engines: {node: '>=6.9.0'} + + '@babel/helper-plugin-utils@7.29.7': + resolution: {integrity: sha512-G7sHYigPY17oO5SYWnfD/0MTBwVR781S/JI643e/JhUYgVgWE/61SoW3NH9KWUKyKq5LVh3npif99Wkt6j86Jw==} + engines: {node: '>=6.9.0'} + + '@babel/helper-replace-supers@7.29.7': + resolution: {integrity: sha512-atfGXWSeCiF4DnKZIfmJfQRkSw9b9gNNXR1kqKjbhG4pGYCOnkp8OcTB8E3NXjBu8NpheSnOeNKz8KT7UNFTmQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/helper-skip-transparent-expression-wrappers@7.29.7': + resolution: {integrity: sha512-brcMGQaVzIeUb+6/bs1Av0f8YuNNjKY2JyvfRCsFuFsdKccEQ5Ges2y74D74NZ1Rz8lKJ9ksJkfqwQFJ/iNEyQ==} + engines: {node: '>=6.9.0'} + + '@babel/helper-string-parser@7.25.9': + resolution: {integrity: sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==} + engines: {node: '>=6.9.0'} + + '@babel/helper-string-parser@7.29.7': + resolution: {integrity: sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==} + engines: {node: '>=6.9.0'} + + '@babel/helper-string-parser@8.0.0': + resolution: {integrity: sha512-6mJgmFFFIIO82vvoLt9XtRC7/TkzXfts1t/SpRX4IHSzMgqoPYCWesVu1udUPUWioAE/2fcG6WuI8zrkE1gwrg==} + engines: {node: ^22.18.0 || >=24.11.0} + + '@babel/helper-validator-identifier@7.25.9': + resolution: {integrity: sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==} + engines: {node: '>=6.9.0'} + + '@babel/helper-validator-identifier@7.29.7': + resolution: {integrity: sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==} + engines: {node: '>=6.9.0'} + + '@babel/helper-validator-identifier@8.0.4': + resolution: {integrity: sha512-4wFaiLd0bVo4cIoTXI3zKI038NIWE/cr3jvBjejOVYVxV/m8Ltav1USiGzG1fmS5J2RhgEOgXNNK46cRPnRsrg==} + engines: {node: ^22.18.0 || >=24.11.0} + + '@babel/helper-validator-option@7.29.7': + resolution: {integrity: sha512-N9ZErrD+yW5geCDtBqnOoxmR8+tNKiGuxKlDpuJxfsqpa2dFcexaziGAE/qoHLiDDreVNMupxGmSoNlyvsA3gw==} + engines: {node: '>=6.9.0'} + + '@babel/helpers@7.29.7': + resolution: {integrity: sha512-1k2lAGRMfHTcwuNYcCNUmaUffmQv8KWMfh2iJUUeRlwlwH4FdNG7mfPI10NPfLHJFThE4Tyr4mv7kTNZOiPuBg==} + engines: {node: '>=6.9.0'} + + '@babel/parser@7.26.9': + resolution: {integrity: sha512-81NWa1njQblgZbQHxWHpxxCzNsa3ZwvFqpUg7P+NNUU6f3UU2jBEg4OlF/J6rl8+PQGh1q6/zWScd001YwcA5A==} + engines: {node: '>=6.0.0'} + hasBin: true + + '@babel/parser@7.29.8': + resolution: {integrity: sha512-E8lTAYNB1KW+FH+VGJuZM1ioAx2E6oVlvQFRrf5P8ZZmsiJXYAD9vTFV7yyEURNzgh1dFqMZuO6tUwcARbqFCA==} + engines: {node: '>=6.0.0'} + hasBin: true + + '@babel/parser@8.0.4': + resolution: {integrity: sha512-srpptsAkEbbNIC/q8nT7o+m6CQe8CJUTV/t7MYc9NnWlgYVtHOb7JH6SorxMhN0kuRJjVqXbKClG6xSbPtzz+g==} + engines: {node: ^22.18.0 || >=24.11.0} + hasBin: true + + '@babel/plugin-syntax-jsx@7.29.7': + resolution: {integrity: sha512-TSu8+mHCoEaaCDEZ0I3+6mvTBYR4PCxQwf2z9/r5Tbztv6NaLR3B9thGTTxX2WGuGHJqRiAbKPeGTJ5XWXVg6A==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-typescript@7.29.7': + resolution: {integrity: sha512-ngr+82Sh0xMz25TPCZi+nC2iTzjfCdWS2ONXTp/PtSCHCgaCNBpdMqgvJ2ccdLlClVZ7sisIgB914j/JFe+RZA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-typescript@7.29.7': + resolution: {integrity: sha512-jK52h8LaLc7JarhQV2ofeFMts4H7vnOXnqZNA6fYglBTZewRBE51KWt3BUltW1P+KoPsYkHoJeXePuz4zo2LMw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/template@7.29.7': + resolution: {integrity: sha512-puq+Gf35oI24FeN11LkoUQFqv9uwNeWpxXZi/Ji3rRIoKAzKnxRaZ+Gkj0vKS9ZCiTESfng1N9LyOyXvo+m+Gg==} + engines: {node: '>=6.9.0'} + + '@babel/traverse@7.29.8': + resolution: {integrity: sha512-I5z7H3bf/41ktsNVLtpN0wAa336HkqIHQ5BuPLEhTkt1jVSyZpeNKIzTgEWmlxjdg81R0IgUCcaE+Ok3NvrfZg==} + engines: {node: '>=6.9.0'} + + '@babel/types@7.26.9': + resolution: {integrity: sha512-Y3IR1cRnOxOCDvMmNiym7XpXQ93iGDDPHx+Zj+NM+rg0fBaShfQLkg+hKPaZCEvg5N/LeCo4+Rj/i3FuJsIQaw==} + engines: {node: '>=6.9.0'} + + '@babel/types@7.29.8': + resolution: {integrity: sha512-Vj1jF3cPfxg7OAfoI7QnVKLoILlm2JF9pnVHrX8qx7AHMiYWT+NDAA7jChlNgRS4WTLc/fD1lXLmPixluj+3Gg==} + engines: {node: '>=6.9.0'} + + '@babel/types@8.0.4': + resolution: {integrity: sha512-eY+Yn3dCqTGmyiq2QRU66lA5FL8lqqqvecHt0fF3uHONIa7ToYsaCiWV8lOKqAs0Rb2SjixiKFROngnulPtt2g==} + engines: {node: ^22.18.0 || >=24.11.0} + + '@floating-ui/core@1.8.0': + resolution: {integrity: sha512-0CIZ5itps/8x7BG8dEIhs53BvCUH2PCoogtakwRTut+Arm58sJooJ0AuZhLw2HJYIR5cMLNPBSS728sPho2khQ==} + + '@floating-ui/dom@1.8.0': + resolution: {integrity: sha512-yXSrzeHZBTZadLOlfyhCkJHNeLJnHRnRInwdZ40L7ZiaAtrBwoYlsDrX3v5zB1Utk7CLfzcOVnVVWoXEky7Ceg==} + + '@floating-ui/utils@0.2.12': + resolution: {integrity: sha512-HpCo8tmWzLVad5s2d19EhAz5zqrrQ6s69qd6moPMQvkOuSwDT1YgRfWSVuc4ennqrgv3OHppiOGMQ7oC13yIww==} + + '@floating-ui/vue@1.1.11': + resolution: {integrity: sha512-HzHKCNVxnGS35r9fCHBc3+uCnjw9IWIlCPL683cGgM9Kgj2BiAl8x1mS7vtvP6F9S/e/q4O6MApwSHj8hNLGfw==} + + '@hoci/components@0.6.0': + resolution: {integrity: sha512-FKWh6JmV5iezDGdQq/UOQ6PfJNRzWfjrN6C6s8Q2QoQMJTC3wAQXJjsKP+OsO2tdizYA1NBBwfow4Oi2X6GZcg==} + peerDependencies: + '@vueuse/core': '>=9.0.0' + vue: ^3.0.0-0 + + '@hoci/core@0.6.0': + resolution: {integrity: sha512-lFV5gFNNzdH5cTmXHonKRaRKt0FDZX9kQ18xwWP89yoDAXrpXbRt5ZK8oQgqCHdWYtwDcVrAMZ+IZmhkCBiO6g==} + peerDependencies: + vue: ^3.0.0-0 + + '@hoci/shared@0.6.0': + resolution: {integrity: sha512-XreSiu+AFisDKorgugX8zjNEsv889U6SbbkTLPHlYIcLvSYk33TmwQ5jHpHe1RAE2KE2Xxn9fBqYRlOCAn8ujg==} + peerDependencies: + '@vueuse/core': '>=9.0.0' + vue: ^3.0.0-0 + + '@internationalized/date@3.12.3': + resolution: {integrity: sha512-fuLX+3ZKLsxI73y8b01EG/WjHb6gE6weCqlfawPO27kBWGMh9G1yH6Csv1uU7/cac9H2GHmOMt6CjmuQ1aia4Q==} + + '@internationalized/number@3.6.7': + resolution: {integrity: sha512-3ji1fcrT+FPAK86UqEhB/psHixYo6niWPJtt7+qRaYFynt/BaJG8GhAPimtWUpEiVSTq8ZM8L5psMxGquiB/Vg==} + + '@jridgewell/gen-mapping@0.3.13': + resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==} + + '@jridgewell/gen-mapping@0.3.8': + resolution: {integrity: sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==} + engines: {node: '>=6.0.0'} + + '@jridgewell/remapping@2.3.5': + resolution: {integrity: sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==} + + '@jridgewell/resolve-uri@3.1.2': + resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} + engines: {node: '>=6.0.0'} + + '@jridgewell/set-array@1.2.1': + resolution: {integrity: sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==} + engines: {node: '>=6.0.0'} + + '@jridgewell/sourcemap-codec@1.5.0': + resolution: {integrity: sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==} + + '@jridgewell/sourcemap-codec@1.5.5': + resolution: {integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==} + + '@jridgewell/trace-mapping@0.3.25': + resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==} + + '@jridgewell/trace-mapping@0.3.31': + resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==} + + '@nodelib/fs.scandir@2.1.5': + resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} + engines: {node: '>= 8'} + + '@nodelib/fs.stat@2.0.5': + resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} + engines: {node: '>= 8'} + + '@nodelib/fs.walk@1.2.8': + resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} + engines: {node: '>= 8'} + + '@oxc-project/types@0.142.0': + resolution: {integrity: sha512-7W+2q5AKQVU36fkaryontrHn3YDt1RyUYXatw9i5H8ocYe2sPKSFB6eS8WNPeRKiN1qAWWZUPm7gwFzJGrccqQ==} + + '@oxfmt/binding-android-arm-eabi@0.62.0': + resolution: {integrity: sha512-pdsv0C4gPjJ8H1+sd8u0BDx+yLACTL+rgeMIOL1ln4ihSnhw8CWXtYWgvcSkyTfgGBIzFKab+d8rx9Xl4en/Kw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm] + os: [android] + + '@oxfmt/binding-android-arm64@0.62.0': + resolution: {integrity: sha512-WC3YQ7uS/KtDrjmqwBviwFKe9qeoi+eXx8aX1z/ffG23Md75myjrJaQqTuJvdOLPoa4EYTjDWH0dHXfwulCVog==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [android] + + '@oxfmt/binding-darwin-arm64@0.62.0': + resolution: {integrity: sha512-GM8Yf3LjjaR1I8PD0SfeoIlwhsh9GvSF+cQ8sf624Yxnjsyumn95aFzYfKJVefblfDIiOAnZ7QVm2sa21Er/0Q==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [darwin] + + '@oxfmt/binding-darwin-x64@0.62.0': + resolution: {integrity: sha512-d5THp7F8bCxLqNogEXDORRsQD6dosf3EyFtnXfBer6v+8tGdcWIjoDX9WaXrrF/26zOmL8qHpPTKCEvpBDmZkQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [darwin] + + '@oxfmt/binding-freebsd-x64@0.62.0': + resolution: {integrity: sha512-1DnrtXGZooOZ0fHgAXZUaDQzBVh1CM2MNW4oBXyQ2aWKvCHjyljvT9fgBkOM0fEOb96X5eqtcfJ0YUVt9jj66g==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [freebsd] + + '@oxfmt/binding-linux-arm-gnueabihf@0.62.0': + resolution: {integrity: sha512-4pQDHOYRH+Huqe0StIaWyvk2CVl/aTaqSrbZpA3/pLS2xH24ME7lBgYprhQF2fRkHBzhGGGKliwxFsDdHwx59g==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm] + os: [linux] + + '@oxfmt/binding-linux-arm-musleabihf@0.62.0': + resolution: {integrity: sha512-X0jAaZJFMCVKhB6YyWVTQ/wN2DLsBcZKSMqTS76bF6riT+XZdtg2FPEdjDvdVbunO9cG+tWiVaEs4Zs38lxYog==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm] + os: [linux] + + '@oxfmt/binding-linux-arm64-gnu@0.62.0': + resolution: {integrity: sha512-682Z8T5s8T5ATArYtsejKvbIfd8LEAXyyDkKkoZVq8HND7Vx8TYLlrDjDSeYfodMeVwHOgkj13lJYR8cj6vUSg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + + '@oxfmt/binding-linux-arm64-musl@0.62.0': + resolution: {integrity: sha512-lk25fAl7KWaLWVJcW0CHEXB7QlQZtx5eDkjpaGMK0hzXTjUe0Wmlu8IKuFHoviSOcEJedRTs4VE/506VqGxGew==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + + '@oxfmt/binding-linux-ppc64-gnu@0.62.0': + resolution: {integrity: sha512-SFyNqHQLwySceWNLhiSldx7wPXRAzP0L0WcW9GegP3uWrpZGJiZlQO85NbHAFPEfxR9PhZ9qSnZryEh7+v+4Gw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [ppc64] + os: [linux] + + '@oxfmt/binding-linux-riscv64-gnu@0.62.0': + resolution: {integrity: sha512-KYj55C1ywJfHo6+aKDuEmUtVEdJALsC5GwayDGsI6FGz2GxFqNr/mA8nxVsNbJzm7sE5MRqTQ9ziImSzhYXysA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [riscv64] + os: [linux] + + '@oxfmt/binding-linux-riscv64-musl@0.62.0': + resolution: {integrity: sha512-BhZDNo5GOU5nC378RhD0/XpvaEBHsH3HLgJp8YZX3A0InC7oivzA63HsRmiXFLtLSHAstEVrDf6fbC7Rs8Jh/A==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [riscv64] + os: [linux] + + '@oxfmt/binding-linux-s390x-gnu@0.62.0': + resolution: {integrity: sha512-UyAFmyHkgSgUJ/wOM4p3U8AC2yAFvRH5PNBs7TnK0fObTT/XSWcdr/lAzPSWaekHaZFaMeFZyk9n93Joq3J93A==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [s390x] + os: [linux] + + '@oxfmt/binding-linux-x64-gnu@0.62.0': + resolution: {integrity: sha512-1iYMP0leytWazFubD/WnINJuIrzRPuoL1aWEJdlGezEzDbTxcd29R4r8IUzP2oWeKst5V02uMJgR2NILlPlG6w==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + + '@oxfmt/binding-linux-x64-musl@0.62.0': + resolution: {integrity: sha512-4rA/URtJSTVNVAQz6Q8wf7SaRvOXVy+TizriT9hs/Y1XhLR/R+92uWKRQG8yFWRAIEBbFHJ6WevQcl/G9SXEfw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + + '@oxfmt/binding-openharmony-arm64@0.62.0': + resolution: {integrity: sha512-mSZuFHU2ar1KLUjXpI2QBQcJ1VsOB3mOCgQXuXCpKs19dgh4u+OaovNfrWDfiJb+ihJ2+f7YFcaO9bS2dlTCXA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [openharmony] + + '@oxfmt/binding-win32-arm64-msvc@0.62.0': + resolution: {integrity: sha512-OfwuhkcjDlqC4EgDojtiV9mzpLqeB9KqTOWPOjLEYBVdDCVSxqW3qzp/xcIxsbtI0UgGCnKvAqYKyY25kf5JZw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [win32] + + '@oxfmt/binding-win32-ia32-msvc@0.62.0': + resolution: {integrity: sha512-P9uDDNFRzghO3X8QAzhkjKhK7JvtABsVn8UYtFX7uor12IAnwNt8nNIctvfWj1JkQU/kE+fmLRPiw7XlrIHsZw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [ia32] + os: [win32] + + '@oxfmt/binding-win32-x64-msvc@0.62.0': + resolution: {integrity: sha512-dlI5SY7XYQCiCBafntWagCR6HcAJB/NpsLtdlPx8x08+Osz8Ok1HHz1GZuusegCe/VoJ6pAnF5a4pd5OZAq7qQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [win32] + + '@oxlint/binding-android-arm-eabi@1.77.0': + resolution: {integrity: sha512-E06sKWS6PiI6HRxS1wyQg22HvApt01hI7fV+T3wUk3OSbaaP4a3hYGY/MIQDmASqCiRjBdpRQYkgMkqH82cWmQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm] + os: [android] + + '@oxlint/binding-android-arm64@1.77.0': + resolution: {integrity: sha512-NvsKz0KZxTp9cYWPLf+FXaSZwB3oO3peAjtukpOMBgse2vhQSoIIVqeO1yR0lEo/UcdZIDL18uq+kL0LzQ0ytA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [android] + + '@oxlint/binding-darwin-arm64@1.77.0': + resolution: {integrity: sha512-bgjTn6nW4bQCFBvSvuHCpDD+sONvmpo4lGI4PxzMt1quBA+xYxhczk6RiCn3GZ9gY8uhaBbwhj9MdKGfu6T9DA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [darwin] + + '@oxlint/binding-darwin-x64@1.77.0': + resolution: {integrity: sha512-aotaIttH1R6j1Rwhx0M0htgeZyGtVQqYNTVEYMN/UcgHPquGA6kmk9OyuDc3a2GKUQBC+3C3GVQCcrRPMYqAFA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [darwin] + + '@oxlint/binding-freebsd-x64@1.77.0': + resolution: {integrity: sha512-nNx/wta7ksRAdYvq+l4AWjXkLxEXHALhENxjj2cYbQAIR4ybaA5L+hCbE63HOmft5czQ6ks+hb8vmEAnn7YGPg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [freebsd] + + '@oxlint/binding-linux-arm-gnueabihf@1.77.0': + resolution: {integrity: sha512-tMLLjM7xXtzXisVCzkOTXNCy9bZVId2wteNwjohlFDR/jY6WagpEDA1c1wu4xRc20Hojaxj+V6DSR7gbKxijWA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm] + os: [linux] + + '@oxlint/binding-linux-arm-musleabihf@1.77.0': + resolution: {integrity: sha512-MiAFDFaqR0tmHTAyo0YDcZ5hyLREdYw/RQhc2R3cbT+8O3tB+zqPM2th9TTQ+Uo3jn/embS+DO+HyX9ztCPkOQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm] + os: [linux] + + '@oxlint/binding-linux-arm64-gnu@1.77.0': + resolution: {integrity: sha512-/xqQ3B16i1T4cyt/9Mn+4CpzhUXoBXp7kVpIwzOXNFLj5JmK1bIjsbSnX296Gg8A/o7oDtKWikFgBx0SLwztkw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + + '@oxlint/binding-linux-arm64-musl@1.77.0': + resolution: {integrity: sha512-LSbwuRKiNCenPDcbARqAZ5RfBy7gmj7vOvfJRLeCDU3gFtSxWbhv/+VTlaUqzUhNj1gFLHB8h7ALnxa/Az6z6g==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + + '@oxlint/binding-linux-ppc64-gnu@1.77.0': + resolution: {integrity: sha512-QWdcH31mXEUe5Nq1s0CfCpceaKjIo9uZtwDjAuL681g1axf+5x8xrg/eXWaw//4NCxYZ4V4e5Hu5tvdR+pTBlg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [ppc64] + os: [linux] + + '@oxlint/binding-linux-riscv64-gnu@1.77.0': + resolution: {integrity: sha512-GnOfYgJxbcElOiPZaDFDl406ONddwvOWk2jvAAAEjwAl4GofNoHF+/HHUIBYa6bFCArlcGPi0XjC4cU1pkgF/Q==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [riscv64] + os: [linux] + + '@oxlint/binding-linux-riscv64-musl@1.77.0': + resolution: {integrity: sha512-AyEMTUCf0xY+hHF+IxqXFQIX0yQOIR8ykpY0lJNOw9xYqOzUX8dyZfRvlG0RfXwuQn2eonf/8NrMmDSZJjdqsA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [riscv64] + os: [linux] + + '@oxlint/binding-linux-s390x-gnu@1.77.0': + resolution: {integrity: sha512-sPLzEcNvxd/oyVQ5oZo92CiHkFkpBeRop13E/P3TPY+hZfXHKCOWKI70TE2RYwMKFJDc20EMjH16L7NZICtKTw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [s390x] + os: [linux] + + '@oxlint/binding-linux-x64-gnu@1.77.0': + resolution: {integrity: sha512-1Oh2ssH2L7lwyvkdSqaMUfsGfwU2Wfvew+obBUYjRVqhpBcUpwnsPSEr1IzVi9XqkuY10geiLsNKecqaZC34Dw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + + '@oxlint/binding-linux-x64-musl@1.77.0': + resolution: {integrity: sha512-0j/2wRgNGO+Qj/M1uu/p57h/hFTTWWcfie0ufkbabeus2s5+/QqkCflnMOwLLN5m2GsNeWp4xdl4cPa4n7QCOQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + + '@oxlint/binding-openharmony-arm64@1.77.0': + resolution: {integrity: sha512-BJ/j54qS0usEnyDkLYURMj2iiD9h5Cyy+ppzeMSXBGRXaGRNWnj1Mw14NqWMR5E/PzdgB30OOCCzLzbRoduafw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [openharmony] + + '@oxlint/binding-win32-arm64-msvc@1.77.0': + resolution: {integrity: sha512-Yh8w+g2Lpx7StrvtYkoz9JJvXjB9wxgFChFNb85nrXm/wj/XTwGWS1hve9+900HL7llrntYB3YP+y32E3tRqzA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [win32] + + '@oxlint/binding-win32-ia32-msvc@1.77.0': + resolution: {integrity: sha512-zja5b7+6a7UsRFgAQSrnax5vrzliEyNPLCjfXONu/vTWswaIVZGFajJZptaeRvPE4LghtFdAzVFlexTm7MVTGA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [ia32] + os: [win32] + + '@oxlint/binding-win32-x64-msvc@1.77.0': + resolution: {integrity: sha512-+teyvPDZ2RjUvo+SuCqS/UhaJl1QtdW5fWT5NJTV61V5MIuIS90Db9LixmtEGvXixyttiK62P96MSu3UlpviBw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [win32] + + '@parcel/watcher-android-arm64@2.5.1': + resolution: {integrity: sha512-KF8+j9nNbUN8vzOFDpRMsaKBHZ/mcjEjMToVMJOhTozkDonQFFrRcfdLWn6yWKCmJKmdVxSgHiYvTCef4/qcBA==} + engines: {node: '>= 10.0.0'} + cpu: [arm64] + os: [android] + + '@parcel/watcher-darwin-arm64@2.5.1': + resolution: {integrity: sha512-eAzPv5osDmZyBhou8PoF4i6RQXAfeKL9tjb3QzYuccXFMQU0ruIc/POh30ePnaOyD1UXdlKguHBmsTs53tVoPw==} + engines: {node: '>= 10.0.0'} + cpu: [arm64] + os: [darwin] + + '@parcel/watcher-darwin-x64@2.5.1': + resolution: {integrity: sha512-1ZXDthrnNmwv10A0/3AJNZ9JGlzrF82i3gNQcWOzd7nJ8aj+ILyW1MTxVk35Db0u91oD5Nlk9MBiujMlwmeXZg==} + engines: {node: '>= 10.0.0'} + cpu: [x64] + os: [darwin] + + '@parcel/watcher-freebsd-x64@2.5.1': + resolution: {integrity: sha512-SI4eljM7Flp9yPuKi8W0ird8TI/JK6CSxju3NojVI6BjHsTyK7zxA9urjVjEKJ5MBYC+bLmMcbAWlZ+rFkLpJQ==} + engines: {node: '>= 10.0.0'} + cpu: [x64] + os: [freebsd] + + '@parcel/watcher-linux-arm-glibc@2.5.1': + resolution: {integrity: sha512-RCdZlEyTs8geyBkkcnPWvtXLY44BCeZKmGYRtSgtwwnHR4dxfHRG3gR99XdMEdQ7KeiDdasJwwvNSF5jKtDwdA==} + engines: {node: '>= 10.0.0'} + cpu: [arm] + os: [linux] + + '@parcel/watcher-linux-arm-musl@2.5.1': + resolution: {integrity: sha512-6E+m/Mm1t1yhB8X412stiKFG3XykmgdIOqhjWj+VL8oHkKABfu/gjFj8DvLrYVHSBNC+/u5PeNrujiSQ1zwd1Q==} + engines: {node: '>= 10.0.0'} + cpu: [arm] + os: [linux] + + '@parcel/watcher-linux-arm64-glibc@2.5.1': + resolution: {integrity: sha512-LrGp+f02yU3BN9A+DGuY3v3bmnFUggAITBGriZHUREfNEzZh/GO06FF5u2kx8x+GBEUYfyTGamol4j3m9ANe8w==} + engines: {node: '>= 10.0.0'} + cpu: [arm64] + os: [linux] + + '@parcel/watcher-linux-arm64-musl@2.5.1': + resolution: {integrity: sha512-cFOjABi92pMYRXS7AcQv9/M1YuKRw8SZniCDw0ssQb/noPkRzA+HBDkwmyOJYp5wXcsTrhxO0zq1U11cK9jsFg==} + engines: {node: '>= 10.0.0'} + cpu: [arm64] + os: [linux] + + '@parcel/watcher-linux-x64-glibc@2.5.1': + resolution: {integrity: sha512-GcESn8NZySmfwlTsIur+49yDqSny2IhPeZfXunQi48DMugKeZ7uy1FX83pO0X22sHntJ4Ub+9k34XQCX+oHt2A==} + engines: {node: '>= 10.0.0'} + cpu: [x64] + os: [linux] + + '@parcel/watcher-linux-x64-musl@2.5.1': + resolution: {integrity: sha512-n0E2EQbatQ3bXhcH2D1XIAANAcTZkQICBPVaxMeaCVBtOpBZpWJuf7LwyWPSBDITb7In8mqQgJ7gH8CILCURXg==} + engines: {node: '>= 10.0.0'} + cpu: [x64] + os: [linux] + + '@parcel/watcher-win32-arm64@2.5.1': + resolution: {integrity: sha512-RFzklRvmc3PkjKjry3hLF9wD7ppR4AKcWNzH7kXR7GUe0Igb3Nz8fyPwtZCSquGrhU5HhUNDr/mKBqj7tqA2Vw==} + engines: {node: '>= 10.0.0'} + cpu: [arm64] + os: [win32] + + '@parcel/watcher-win32-ia32@2.5.1': + resolution: {integrity: sha512-c2KkcVN+NJmuA7CGlaGD1qJh1cLfDnQsHjE89E60vUEMlqduHGCdCLJCID5geFVM0dOtA3ZiIO8BoEQmzQVfpQ==} + engines: {node: '>= 10.0.0'} + cpu: [ia32] + os: [win32] + + '@parcel/watcher-win32-x64@2.5.1': + resolution: {integrity: sha512-9lHBdJITeNR++EvSQVUcaZoWupyHfXe1jZvGZ06O/5MflPcuPLtEphScIBL+AiCWBO46tDSHzWyD0uDmmZqsgA==} + engines: {node: '>= 10.0.0'} + cpu: [x64] + os: [win32] + + '@parcel/watcher@2.5.1': + resolution: {integrity: sha512-dfUnCxiN9H4ap84DvD2ubjw+3vUNpstxa0TneY/Paat8a3R4uQZDLSvWjmznAY/DoahqTHl9V46HF/Zs3F29pg==} + engines: {node: '>= 10.0.0'} + + '@rolldown/binding-android-arm64@1.2.2': + resolution: {integrity: sha512-l7x215OGvo1s52JWmR8U/DAVzEDWBCIbTm28aeJV/WDTSHgcKXaZTuBT0hJMs5NggilfJTW3clZVvd24yfKJxA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [android] + + '@rolldown/binding-darwin-arm64@1.2.2': + resolution: {integrity: sha512-9u9Xv6c1AJZT0FfwH5vrMG5Jjcwhc1MlyrPu0XfTqkzsmqfks2M6W/o5XwAJgVVN/jHpqqngC1WevHKKTIUtIA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [darwin] + + '@rolldown/binding-darwin-x64@1.2.2': + resolution: {integrity: sha512-9W1mbGZAfW3oqd85bhBkmpyHCCzL1TeG/zFFP3vg7b0rlly8cxOcre5nXwz+LHazCwac2MNWgPdPCHndABjpWQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [darwin] + + '@rolldown/binding-freebsd-x64@1.2.2': + resolution: {integrity: sha512-0p1lhiCSCyaerFwtrdZQUx7NqGk6LQnaRKWX7tFQqwQgvX0rjM15cIkm3pax1UpEakK14C4mOxx/jSqCBdBRqQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [freebsd] + + '@rolldown/binding-linux-arm-gnueabihf@1.2.2': + resolution: {integrity: sha512-e+cOJXrJ2L3zx6YzqPg+f6Wbk3V1cKB8bOhbaYdVYN3DdquzNdRAmrbETz1qnt5yp/c7JNlNjmITiA2cVneQ7w==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm] + os: [linux] + + '@rolldown/binding-linux-arm64-gnu@1.2.2': + resolution: {integrity: sha512-JsSMsj6sNat/MuhG5fnBD7QgbtpHKVe30x5/bAVirDHdhoQRXJkF6xc0Jqk8O4fiCUQAzMOoH9wZi3m60c8wtg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + + '@rolldown/binding-linux-arm64-musl@1.2.2': + resolution: {integrity: sha512-B5G/zJdHaoJn9vD50eGHWkiWfmq8Uhi3IiLPJTzmZTrAalk1bztUikSXo0qga18ibE0IXboyeMUnhPjhAJ45wQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + + '@rolldown/binding-linux-ppc64-gnu@1.2.2': + resolution: {integrity: sha512-6mC/awzKka8W6EoekjegpfGkjz8jXWDX63pqu/HYVpyKtZfu65Jsh4QAH3Kej3CAv/c1oGX7psTmFEbr0mDxLA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [ppc64] + os: [linux] + + '@rolldown/binding-linux-s390x-gnu@1.2.2': + resolution: {integrity: sha512-412MX9fJLdA1IK28EZnc8jYv2HRTleOZgfLQumJ5zy7OeJLZlg/CETwFaXjNmGVxG51cFHpKLqb5LKvBC+HsHA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [s390x] + os: [linux] + + '@rolldown/binding-linux-x64-gnu@1.2.2': + resolution: {integrity: sha512-Q/+HI/ToJafZ1iCqGgVQXUEkIjufHCTF0gBQ2a5o3cg7GJ2h0qyq3nvvSmU+bGda2/7ygXpTY4TM6gO9OhQ0ZA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + + '@rolldown/binding-linux-x64-musl@1.2.2': + resolution: {integrity: sha512-ZKp/w41n6wCvxzxQHtQSbuphfX3Y4cCvbjkKHusrLx4lh+JWLTU7StSltO/DKARISzbj368d+qUaCjI8K2wzXw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + + '@rolldown/binding-openharmony-arm64@1.2.2': + resolution: {integrity: sha512-pxE6xD4KS3eAROkKK5yrhB9/3+vhlhVGMvlQLbdpzrBGDbKrnzx3RLwPaHvasLo6jgaiBLn7e04Df9C4tYhjmA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [openharmony] + + '@rolldown/binding-win32-arm64-msvc@1.2.2': + resolution: {integrity: sha512-4MqEue5re+xIZzAWsB8sj0P1kqZySWqIuN4t6QaIO/YA6SFwySOLruvWQFzfmqk8LBK2P30KCSJwf6mJCZZ5/A==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [win32] + + '@rolldown/binding-win32-x64-msvc@1.2.2': + resolution: {integrity: sha512-NweNxxD0Nf9t8v7kodun45Ijp3EIwYY+uydPP6qBEYvfBqhIjN6dZMzlQja3tqX/aLs3F3Uz+AxDpKgRhpOZQg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [win32] + + '@rolldown/pluginutils@1.0.1': + resolution: {integrity: sha512-2j9bGt5Jh8hj+vPtgzPtl72j0yRxHAyumoo6TNfAjsLB04UtpSvPbPcDcBMxz7n+9CYB0c1GxQFxYRg2jimqGw==} + + '@rollup/pluginutils@5.1.4': + resolution: {integrity: sha512-USm05zrsFxYLPdWWq+K3STlWiT/3ELn3RcV5hJMghpeAIhxfsUIg6mt12CBJBInWMV4VneoV7SfGv8xIwo2qNQ==} + engines: {node: '>=14.0.0'} + peerDependencies: + rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 + peerDependenciesMeta: + rollup: + optional: true + + '@rollup/rollup-android-arm-eabi@4.35.0': + resolution: {integrity: sha512-uYQ2WfPaqz5QtVgMxfN6NpLD+no0MYHDBywl7itPYd3K5TjjSghNKmX8ic9S8NU8w81NVhJv/XojcHptRly7qQ==} + cpu: [arm] + os: [android] + + '@rollup/rollup-android-arm64@4.35.0': + resolution: {integrity: sha512-FtKddj9XZudurLhdJnBl9fl6BwCJ3ky8riCXjEw3/UIbjmIY58ppWwPEvU3fNu+W7FUsAsB1CdH+7EQE6CXAPA==} + cpu: [arm64] + os: [android] + + '@rollup/rollup-darwin-arm64@4.35.0': + resolution: {integrity: sha512-Uk+GjOJR6CY844/q6r5DR/6lkPFOw0hjfOIzVx22THJXMxktXG6CbejseJFznU8vHcEBLpiXKY3/6xc+cBm65Q==} + cpu: [arm64] + os: [darwin] + + '@rollup/rollup-darwin-x64@4.35.0': + resolution: {integrity: sha512-3IrHjfAS6Vkp+5bISNQnPogRAW5GAV1n+bNCrDwXmfMHbPl5EhTmWtfmwlJxFRUCBZ+tZ/OxDyU08aF6NI/N5Q==} + cpu: [x64] + os: [darwin] + + '@rollup/rollup-freebsd-arm64@4.35.0': + resolution: {integrity: sha512-sxjoD/6F9cDLSELuLNnY0fOrM9WA0KrM0vWm57XhrIMf5FGiN8D0l7fn+bpUeBSU7dCgPV2oX4zHAsAXyHFGcQ==} + cpu: [arm64] + os: [freebsd] + + '@rollup/rollup-freebsd-x64@4.35.0': + resolution: {integrity: sha512-2mpHCeRuD1u/2kruUiHSsnjWtHjqVbzhBkNVQ1aVD63CcexKVcQGwJ2g5VphOd84GvxfSvnnlEyBtQCE5hxVVw==} + cpu: [x64] + os: [freebsd] + + '@rollup/rollup-linux-arm-gnueabihf@4.35.0': + resolution: {integrity: sha512-mrA0v3QMy6ZSvEuLs0dMxcO2LnaCONs1Z73GUDBHWbY8tFFocM6yl7YyMu7rz4zS81NDSqhrUuolyZXGi8TEqg==} + cpu: [arm] + os: [linux] + + '@rollup/rollup-linux-arm-musleabihf@4.35.0': + resolution: {integrity: sha512-DnYhhzcvTAKNexIql8pFajr0PiDGrIsBYPRvCKlA5ixSS3uwo/CWNZxB09jhIapEIg945KOzcYEAGGSmTSpk7A==} + cpu: [arm] + os: [linux] + + '@rollup/rollup-linux-arm64-gnu@4.35.0': + resolution: {integrity: sha512-uagpnH2M2g2b5iLsCTZ35CL1FgyuzzJQ8L9VtlJ+FckBXroTwNOaD0z0/UF+k5K3aNQjbm8LIVpxykUOQt1m/A==} + cpu: [arm64] + os: [linux] + + '@rollup/rollup-linux-arm64-musl@4.35.0': + resolution: {integrity: sha512-XQxVOCd6VJeHQA/7YcqyV0/88N6ysSVzRjJ9I9UA/xXpEsjvAgDTgH3wQYz5bmr7SPtVK2TsP2fQ2N9L4ukoUg==} + cpu: [arm64] + os: [linux] + + '@rollup/rollup-linux-loongarch64-gnu@4.35.0': + resolution: {integrity: sha512-5pMT5PzfgwcXEwOaSrqVsz/LvjDZt+vQ8RT/70yhPU06PTuq8WaHhfT1LW+cdD7mW6i/J5/XIkX/1tCAkh1W6g==} + cpu: [loong64] + os: [linux] + + '@rollup/rollup-linux-powerpc64le-gnu@4.35.0': + resolution: {integrity: sha512-c+zkcvbhbXF98f4CtEIP1EBA/lCic5xB0lToneZYvMeKu5Kamq3O8gqrxiYYLzlZH6E3Aq+TSW86E4ay8iD8EA==} + cpu: [ppc64] + os: [linux] + + '@rollup/rollup-linux-riscv64-gnu@4.35.0': + resolution: {integrity: sha512-s91fuAHdOwH/Tad2tzTtPX7UZyytHIRR6V4+2IGlV0Cej5rkG0R61SX4l4y9sh0JBibMiploZx3oHKPnQBKe4g==} + cpu: [riscv64] + os: [linux] + + '@rollup/rollup-linux-s390x-gnu@4.35.0': + resolution: {integrity: sha512-hQRkPQPLYJZYGP+Hj4fR9dDBMIM7zrzJDWFEMPdTnTy95Ljnv0/4w/ixFw3pTBMEuuEuoqtBINYND4M7ujcuQw==} + cpu: [s390x] + os: [linux] + + '@rollup/rollup-linux-x64-gnu@4.35.0': + resolution: {integrity: sha512-Pim1T8rXOri+0HmV4CdKSGrqcBWX0d1HoPnQ0uw0bdp1aP5SdQVNBy8LjYncvnLgu3fnnCt17xjWGd4cqh8/hA==} + cpu: [x64] + os: [linux] + + '@rollup/rollup-linux-x64-musl@4.35.0': + resolution: {integrity: sha512-QysqXzYiDvQWfUiTm8XmJNO2zm9yC9P/2Gkrwg2dH9cxotQzunBHYr6jk4SujCTqnfGxduOmQcI7c2ryuW8XVg==} + cpu: [x64] + os: [linux] + + '@rollup/rollup-win32-arm64-msvc@4.35.0': + resolution: {integrity: sha512-OUOlGqPkVJCdJETKOCEf1mw848ZyJ5w50/rZ/3IBQVdLfR5jk/6Sr5m3iO2tdPgwo0x7VcncYuOvMhBWZq8ayg==} + cpu: [arm64] + os: [win32] + + '@rollup/rollup-win32-ia32-msvc@4.35.0': + resolution: {integrity: sha512-2/lsgejMrtwQe44glq7AFFHLfJBPafpsTa6JvP2NGef/ifOa4KBoglVf7AKN7EV9o32evBPRqfg96fEHzWo5kw==} + cpu: [ia32] + os: [win32] + + '@rollup/rollup-win32-x64-msvc@4.35.0': + resolution: {integrity: sha512-PIQeY5XDkrOysbQblSW7v3l1MDZzkTEzAfTPkj5VAu3FW8fS4ynyLg2sINp0fp3SjZ8xkRYpLqoKcYqAkhU1dw==} + cpu: [x64] + os: [win32] + + '@swc/helpers@0.5.23': + resolution: {integrity: sha512-5lSsMOTXURePglDfvuAQUqkGek9Hg2kksOYay2m0+XR++b2NWYL/4sWyuvVBIs8oKnJaxkdi9whaL/sqN13afw==} + + '@tailwindcss/node@4.3.3': + resolution: {integrity: sha512-/T8IKEsf9VTU6tLjgC7+sv2mOPtQxzE2jMw7u4Tt40Tx+QSZxpzh95/H6cMKoja9XuW7iMdLJYBB0o9G1CaAgg==} + + '@tailwindcss/oxide-android-arm64@4.3.3': + resolution: {integrity: sha512-Y85A2gmPSkl5Ve5qR86GL4HT509cFqQh1aes9p3sSkyTPwt0Pppf3GkwGe4JPACcRYjgJIEhQgM6dBClnr0NYw==} + engines: {node: '>= 20'} + cpu: [arm64] + os: [android] + + '@tailwindcss/oxide-darwin-arm64@4.3.3': + resolution: {integrity: sha512-BiaWatpBcERQFDlOjRDpIVXuFK5PJez5SA4JMg6VYZdBYU+qKfV/vqjcIs+IYmtitf1xYQZTwXvU/8y4lfZUGw==} + engines: {node: '>= 20'} + cpu: [arm64] + os: [darwin] + + '@tailwindcss/oxide-darwin-x64@4.3.3': + resolution: {integrity: sha512-fAeUqfV5ndhxRwai8cXGzdLvul9utWOmeTkv69unv4ZXixjn61Z+p9lCWdwOwA3TYboG3BwdVuN/RDjhBRl0mw==} + engines: {node: '>= 20'} + cpu: [x64] + os: [darwin] + + '@tailwindcss/oxide-freebsd-x64@4.3.3': + resolution: {integrity: sha512-iyf5bV6+wnAlflVeEy7R25dupxTNECZN5QMI0qNT6eT+EgaGdZcKhGkr5SdoaWiLJ3spLqIY9VCeSGrwmtg4kw==} + engines: {node: '>= 20'} + cpu: [x64] + os: [freebsd] + + '@tailwindcss/oxide-linux-arm-gnueabihf@4.3.3': + resolution: {integrity: sha512-aAYUprJAJQWWbRrPvtjdroZ56Md+JM8pMiopS6xGEwDfLhqj+2ver2p4nU4Mb3CRqcMmNBjo8KkUgcxhkzVQGQ==} + engines: {node: '>= 20'} + cpu: [arm] + os: [linux] + + '@tailwindcss/oxide-linux-arm64-gnu@4.3.3': + resolution: {integrity: sha512-nDxldcEENOxZRzC2uu9jrutZdAAQtb+8WWDCSnWL1zvBk1+FN+x6MtDViPB5AJMfttVCUhehGWus3XBPgatM/w==} + engines: {node: '>= 20'} + cpu: [arm64] + os: [linux] + + '@tailwindcss/oxide-linux-arm64-musl@4.3.3': + resolution: {integrity: sha512-Md44bD6veX/PC5iyF8cDVnw4HBIANZepRZZ7a8DQOvkfo5WUBwcp6iAuCUz23u+4SUkhJlD3eL7hNdW8ezd/kA==} + engines: {node: '>= 20'} + cpu: [arm64] + os: [linux] + + '@tailwindcss/oxide-linux-x64-gnu@4.3.3': + resolution: {integrity: sha512-tx7us1muwOKAKWao2v/GaafFeQboE6aj88vC6ziN2NCGcRm8gWUhwjzg+YdVB1e4boAtdtma4L43onunI6NS4w==} + engines: {node: '>= 20'} + cpu: [x64] + os: [linux] + + '@tailwindcss/oxide-linux-x64-musl@4.3.3': + resolution: {integrity: sha512-SJxX60smvHgasZoBy11dX6YRjXJFovwWBoedhbQPOBzgFWBHGB+TVPWB9BxzR7TTxU8FQZAI2AyiNCMzFm8Img==} + engines: {node: '>= 20'} + cpu: [x64] + os: [linux] + + '@tailwindcss/oxide-wasm32-wasi@4.3.3': + resolution: {integrity: sha512-jx1+rPhY/5Ympkktd656HBWEBLxP7dH06losBLjjf5vgCODXvi9KhtftWcMIwTFIDqBr7cRnQkdLnAG+IOlGvQ==} + engines: {node: '>=14.0.0'} + cpu: [wasm32] + bundledDependencies: + - '@napi-rs/wasm-runtime' + - '@emnapi/core' + - '@emnapi/runtime' + - '@tybys/wasm-util' + - '@emnapi/wasi-threads' + - tslib + + '@tailwindcss/oxide-win32-arm64-msvc@4.3.3': + resolution: {integrity: sha512-3rc292Ca2ceK6Ulcc/bAVnTs/3nDtoPhyEKlgPv+yQJQi/JS/AMJlqzxvlDacL1nekbrcf6bTqp/jV4qgnPxNQ==} + engines: {node: '>= 20'} + cpu: [arm64] + os: [win32] + + '@tailwindcss/oxide-win32-x64-msvc@4.3.3': + resolution: {integrity: sha512-yJ0pwIVc/nYeGoV02WtsN8KYyLQv7kyI2wDnkezyJlGGjkd4QLwDGAwl47YpPJeuI0M0ObaXGSPjvWDPeTPggw==} + engines: {node: '>= 20'} + cpu: [x64] + os: [win32] + + '@tailwindcss/oxide@4.3.3': + resolution: {integrity: sha512-krXjAikiaFSPaK/FkAQT5UTx3VormQaiZ5hBFlJZ9UFQGB/rwg1MZIhHAG9smMQRTdyJxP6Qt5MwMtdyU5FWrA==} + engines: {node: '>= 20'} + + '@tailwindcss/vite@4.3.3': + resolution: {integrity: sha512-yYU8cogLeSh/ms2jh8Fj7jaba/EWa7Ja6GoUqYZaraEuCI5YS6ms6ObZgjjedm+jm6XZjdNRWBpPP6Z86oOxcw==} + peerDependencies: + vite: ^5.2.0 || ^6 || ^7 || ^8 + + '@tanstack/virtual-core@3.17.7': + resolution: {integrity: sha512-bp+v10y65sp2H7WpWfIMyxTNfl8ZVfxFTLRjPIFRryi6FV/J33z4IS53WO4pTk36KlvJ4iLiQz+oaydDC1xbcA==} + + '@tanstack/vue-virtual@3.13.35': + resolution: {integrity: sha512-lOfSPvgPdlaH6Qy+CyIc3XpycitaSQ9GECndGpTuDiu+uDA1am+90yWXwzDSd/20ZM196ggWJLS+Qb6WjVd/OA==} + peerDependencies: + vue: ^2.7.0 || ^3.0.0 + + '@tsconfig/node24@24.0.4': + resolution: {integrity: sha512-2A933l5P5oCbv6qSxHs7ckKwobs8BDAe9SJ/Xr2Hy+nDlwmLE1GhFh/g/vXGRZWgxBg9nX/5piDtHR9Dkw/XuA==} + + '@types/estree@1.0.6': + resolution: {integrity: sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==} + + '@types/jsesc@2.5.1': + resolution: {integrity: sha512-9VN+6yxLOPLOav+7PwjZbxiID2bVaeq0ED4qSQmdQTdjnXJSaCVKTR58t15oqH1H5t8Ng2ZX1SabJVoN9Q34bw==} + + '@types/node@26.1.2': + resolution: {integrity: sha512-Vu4a5UFA9rIIFJ7rB/Vaafh9lrCQszopTCx6KjFboXTGQbPNasehVR5TEiithSDGyd1DEiUByggTZsg8jukeIg==} + + '@types/pako@2.0.3': + resolution: {integrity: sha512-bq0hMV9opAcrmE0Byyo0fY3Ew4tgOevJmQ9grUhpXQhYfyLJ1Kqg3P33JT5fdbT2AjeAjR51zqqVjAL/HMkx7Q==} + + '@types/web-bluetooth@0.0.15': + resolution: {integrity: sha512-w7hEHXnPMEZ+4nGKl/KDRVpxkwYxYExuHOYXyzIzCDzEZ9ZCGMAewulr9IqJu2LR4N37fcnb1XVeuZ09qgOxhA==} + + '@types/web-bluetooth@0.0.21': + resolution: {integrity: sha512-oIQLCGWtcFZy2JW77j9k8nHzAOpqMHLQejDA48XXMWH6tjCQHz5RCFz1bzsmROyL6PUm+LLnUiI4BCn221inxA==} + + '@vitejs/plugin-vue-jsx@5.1.6': + resolution: {integrity: sha512-YXvi4as2clxt6DFw5+a0tTA97ntiQXm/raR8ofNj3aNwwdlVGTiG2gp7EvfZW17P50acL/9bP0ccF4XnqNmlgA==} + engines: {node: ^20.19.0 || >=22.12.0} + peerDependencies: + vite: ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 + vue: ^3.0.0 + + '@vitejs/plugin-vue@6.0.8': + resolution: {integrity: sha512-0ZjgOg7oO6farnNGup7yvoM/YXZV84OZxHAwtflItNa/6zzQyVb5LNxyea3FEKEX2XlagIKzrlH7wwxkKgtiew==} + engines: {node: ^20.19.0 || >=22.12.0} + peerDependencies: + vite: ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 + vue: ^3.2.25 + + '@volar/language-core@2.4.28': + resolution: {integrity: sha512-w4qhIJ8ZSitgLAkVay6AbcnC7gP3glYM3fYwKV3srj8m494E3xtrCv6E+bWviiK/8hs6e6t1ij1s2Endql7vzQ==} + + '@volar/source-map@2.4.28': + resolution: {integrity: sha512-yX2BDBqJkRXfKw8my8VarTyjv48QwxdJtvRgUpNE5erCsgEUdI2DsLbpa+rOQVAJYshY99szEcRDmyHbF10ggQ==} + + '@volar/typescript@2.4.28': + resolution: {integrity: sha512-Ja6yvWrbis2QtN4ClAKreeUZPVYMARDYZl9LMEv1iQ1QdepB6wn0jTRxA9MftYmYa4DQ4k/DaSZpFPUfxl8giw==} + + '@vue-macros/common@3.1.4': + resolution: {integrity: sha512-/5Fv+6DgIcM9ajY05ZmKBv+LMX1M9A0X+IUwDRVdt67ciw8OV9bvG2r34p3RiEadlsQybjhKPRKNXDC8Bp23cw==} + engines: {node: '>=20.19.0'} + peerDependencies: + vue: ^2.7.0 || ^3.2.25 + peerDependenciesMeta: + vue: + optional: true + + '@vue/babel-helper-vue-transform-on@2.0.1': + resolution: {integrity: sha512-uZ66EaFbnnZSYqYEyplWvn46GhZ1KuYSThdT68p+am7MgBNbQ3hphTL9L+xSIsWkdktwhPYLwPgVWqo96jDdRA==} + + '@vue/babel-plugin-jsx@2.0.1': + resolution: {integrity: sha512-a8CaLQjD/s4PVdhrLD/zT574ZNPnZBOY+IhdtKWRB4HRZ0I2tXBi5ne7d9eCfaYwp5gU5+4KIyFTV1W1YL9xZA==} + peerDependencies: + '@babel/core': ^7.0.0-0 + peerDependenciesMeta: + '@babel/core': + optional: true + + '@vue/babel-plugin-resolve-type@2.0.1': + resolution: {integrity: sha512-ybwgIuRGRRBhOU37GImDoWQoz+TlSqap65qVI6iwg/J7FfLTLmMf97TS7xQH9I7Qtr/gp161kYVdhr1ZMraSYQ==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@vue/compiler-core@3.5.13': + resolution: {integrity: sha512-oOdAkwqUfW1WqpwSYJce06wvt6HljgY3fGeM9NcVA1HaYOij3mZG9Rkysn0OHuyUAGMbEbARIpsG+LPVlBJ5/Q==} + + '@vue/compiler-core@3.5.40': + resolution: {integrity: sha512-39E8IgOhTbVDnoJFMKc2DvYnypcZwUqgUhQkccva/0m6FUwtIKSGV7n1hpVmYcFaoRAwf9pBcwnKlCEsN63ZEQ==} + + '@vue/compiler-dom@3.5.13': + resolution: {integrity: sha512-ZOJ46sMOKUjO3e94wPdCzQ6P1Lx/vhp2RSvfaab88Ajexs0AHeV0uasYhi99WPaogmBlRHNRuly8xV75cNTMDA==} + + '@vue/compiler-dom@3.5.40': + resolution: {integrity: sha512-pwkx4vqlqOspFstrcmzwkKLePVMD3PT65imRzLhanU2V1Fj4K13g6OXjanOyzw3aTAuRk84BOmY8f3rEHqPaVA==} + + '@vue/compiler-sfc@3.5.40': + resolution: {integrity: sha512-gIf497P4kpuALcvs5n3AEg1Vdn0pSY4XbjASIfHNYF1/MP3T2Mf2STERTubysBxCRxzJGJYtF/O7vwJrxFB3Vw==} + + '@vue/compiler-ssr@3.5.40': + resolution: {integrity: sha512-rrE5xiXG663+vHCHa3J9p2z5OcBRjXmoqenprJxAFQxg5pSshzeBiCE6pu46axapRJ2Adk0YDA2BRZVjiHXnhg==} + + '@vue/devtools-api@8.2.1': + resolution: {integrity: sha512-6u4vXBlIBAC1wMplIZgpyPn7uh/s4Bf6F5bMzvLv+EdJ0aHs/+4B7Ygv864EStQSjRbsRzTko/kUG1A1IejQ3A==} + + '@vue/devtools-kit@8.2.1': + resolution: {integrity: sha512-FIGIuq3AWReEpbAHY/cRGeHDfI0qOb8OCQ3YjbEAX04uaxIDbGc9rhkbVcG7rnfHPXE3RsU5KrWOu9V/okd8AQ==} + + '@vue/devtools-shared@8.2.1': + resolution: {integrity: sha512-Fkac7lUdGReh6pVOi3AYPRGe82LQqRmAfThW7RRligOAP0ZA/Z1z9XLHDM9dv34pV2HRc79DK8uKPeG2fLnA/g==} + + '@vue/language-core@3.3.9': + resolution: {integrity: sha512-in/68oAa4BCtVY6n/nkuhLIkV8DHYd2UivedJ6cMZ6UYtlq9jaoaSNUBHYCVO44z3nKg7MdE5OBoHKt5SxeBKQ==} + + '@vue/reactivity@3.5.40': + resolution: {integrity: sha512-B7ot9UlUZOi1zbq61/LvE88ZLTV8IlajTdiZTAEiDQgrnIMIZoPr9kGw0Zw46ObW62O9+H/Be3kMbfb7kYPQZA==} + + '@vue/runtime-core@3.5.40': + resolution: {integrity: sha512-KAZLweuZ6uUJPK1PMSQPgBU5gCjgrrfjUhSglmU9NhH+Zjepa8cnwSydPWDWHDwOgY4g3VcZ+PljbiHlURNCbw==} + + '@vue/runtime-dom@3.5.40': + resolution: {integrity: sha512-ZfrX8ssZQds900L9pr8AuK05ddnMsR4MPMZr8cPN9GoqoPWcXLhjvvbIA2SMv+7a97sJ1vv9pj/zxK0Cq/eEFQ==} + + '@vue/server-renderer@3.5.40': + resolution: {integrity: sha512-XNJym9WpevhTVt1HuwOrCRJ5Q+9z4BjTMrDtjTrvx74SmUll8spNTw6whWJa9mEkO4PKn5TihI/bm/8ds2QVJw==} + + '@vue/shared@3.5.13': + resolution: {integrity: sha512-/hnE/qP5ZoGpol0a5mDi45bOd7t3tjYJBjsgCsivow7D48cJeV5l05RD82lPqi7gRiphZM37rnhW1l6ZoCNNnQ==} + + '@vue/shared@3.5.40': + resolution: {integrity: sha512-WxnBtruIqOoV3rA4jeKDWzrYI5h7Cp4+pjwDi8kWGHz+IslhiN+wguLVVhtv2l8VoU02rzDCVfDjgCl1lNpZVg==} + + '@vue/tsconfig@0.9.1': + resolution: {integrity: sha512-buvjm+9NzLCJL29KY1j1991YYJ5e6275OiK+G4jtmfIb+z4POywbdm0wXusT9adVWqe0xqg70TbI7+mRx4uU9w==} + peerDependencies: + typescript: '>= 5.8' + vue: ^3.4.0 + peerDependenciesMeta: + typescript: + optional: true + vue: + optional: true + + '@vueuse/core@14.4.0': + resolution: {integrity: sha512-X4WHz1HlCzCBoYXesUkifzzWBAcZgXG8Fi5iNPQg/epdzOB3gu8Fawj3hvuwYR1nGcXGnvxwYYcUC/71++svtQ==} + peerDependencies: + vue: ^3.5.0 + + '@vueuse/core@9.0.0': + resolution: {integrity: sha512-hMMc2ajuVknkL7Z39JdP9gFFND2OgnDTSS5mmuinWGAE1Vxy1AwDvTHm3+juyk+GzJjYRAktnBIPy7Fq53iOnw==} + + '@vueuse/metadata@14.4.0': + resolution: {integrity: sha512-swx/255R6JyHZFJhx845iz5CRWDZdCfvkZOpACWc5+c5WHcG24mv8gUT1WIdFQaHt6dq79rvILd9QnCWiyVm9g==} + + '@vueuse/metadata@9.0.0': + resolution: {integrity: sha512-79YVIsAP1bbWm5GdQuG7jDVF/9uuExzhkO0Sd4/TLuSfzH2uZOrHvGwy+ZNJHjbyRn3uf56rKINWLJdBuTLSqQ==} + + '@vueuse/shared@14.4.0': + resolution: {integrity: sha512-JRgY90Sz8DDtPMsaDflvPMp9xYk69JZAmbuDvAquUVXKr2gEjqtzGNTTthLfckH0BzBqvnu31gb4a8TGLRe79g==} + peerDependencies: + vue: ^3.5.0 + + '@vueuse/shared@9.0.0': + resolution: {integrity: sha512-WRCyr/wIz5e/2gR/+qFucbCUcGMyJKkQZAzlECl3e71ebQQ9X/w3aBWT9FbnogJX+DNZ/t3Pj+TqPbC7TH1Yog==} + + acorn@8.14.1: + resolution: {integrity: sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==} + engines: {node: '>=0.4.0'} + hasBin: true + + acorn@8.18.0: + resolution: {integrity: sha512-lGq+9yr1/GuAWaVYIHRjvvySG5/4VfKIvC8EWxStPdcDh/Ka7FG3twP6v4d5BkravUilhIAsG4Qj83t02LWUPQ==} + engines: {node: '>=0.4.0'} + hasBin: true + + alien-signals@3.2.1: + resolution: {integrity: sha512-I8FjmltrfnDFoZedi5CG8DghVYNhzb/Ijluz7tCSJH0xpd0484Kowhbb1XDYOxfJpU1p5wnM2X54dA+IfGyD1g==} + + ansi-styles@7.0.0: + resolution: {integrity: sha512-kKvt3m4uwzqL0wlkPd09CmljPJGOZZ4D0fP65sqFSvPkMRKhNi+74MgIJ5QxE6SxqB4t4KyUFGg8+n5zjo6hew==} + engines: {node: '>=22'} + + anymatch@3.1.3: + resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} + engines: {node: '>= 8'} + + aria-hidden@1.2.6: + resolution: {integrity: sha512-ik3ZgC9dY/lYVVM++OISsaYDeg1tb0VtP5uL3ouh1koGOaUMDPpbFIei4JkFimWUFPn90sbMNMXQAIVOlnYKJA==} + engines: {node: '>=10'} + + ast-kit@2.2.0: + resolution: {integrity: sha512-m1Q/RaVOnTp9JxPX+F+Zn7IcLYMzM8kZofDImfsKZd8MbR+ikdOzTeztStWqfrqIxZnYWryyI9ePm3NGjnZgGw==} + engines: {node: '>=20.19.0'} + + ast-walker-scope@0.9.0: + resolution: {integrity: sha512-IJdzo2vLiElBxKzwS36VsCue/62d6IdWjnPB2v3nuPKeWGynp6FF/CYoLa5i/3jXH/z97ZDdsXz6abpgM6w07A==} + engines: {node: '>=20.19.0'} + + asynckit@0.4.0: + resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} + + axios@1.8.2: + resolution: {integrity: sha512-ls4GYBm5aig9vWx8AWDSGLpnpDQRtWAfrjU+EuytuODrFBkqesN2RkOQCBzrA1RQNHw1SmRMSDDDSwzNAYQ6Rg==} + + balanced-match@1.0.2: + resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + + binary-extensions@2.3.0: + resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} + engines: {node: '>=8'} + + birpc@2.9.0: + resolution: {integrity: sha512-KrayHS5pBi69Xi9JmvoqrIgYGDkD6mcSe/i6YKi3w5kekCLzrX4+nawcXqrj2tIp50Kw/mT/s3p+GVK0A0sKxw==} + + brace-expansion@2.0.1: + resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} + + braces@3.0.3: + resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} + engines: {node: '>=8'} + + browserslist@4.24.4: + resolution: {integrity: sha512-KDi1Ny1gSePi1vm0q4oxSF8b4DR44GF4BbmS2YdhPLOEqd8pDviZOGH/GsmRwoWJ2+5Lr085X7naowMwKHDG1A==} + engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} + hasBin: true + + call-bind-apply-helpers@1.0.2: + resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==} + engines: {node: '>= 0.4'} + + caniuse-lite@1.0.30001702: + resolution: {integrity: sha512-LoPe/D7zioC0REI5W73PeR1e1MLCipRGq/VkovJnd6Df+QVqT+vT33OXCp8QUd7kA7RZrHWxb1B36OQKI/0gOA==} + + chokidar@3.6.0: + resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} + engines: {node: '>= 8.10.0'} + + chokidar@5.0.0: + resolution: {integrity: sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw==} + engines: {node: '>= 20.19.0'} + + class-variance-authority@0.7.1: + resolution: {integrity: sha512-Ka+9Trutv7G8M6WT6SeiRWz792K5qEqIGEGzXKhAE6xOWAY6pPH8U+9IY3oCMv6kqTmLsv7Xh/2w2RigkePMsg==} + + clsx@2.1.1: + resolution: {integrity: sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==} + engines: {node: '>=6'} + + combined-stream@1.0.8: + resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} + engines: {node: '>= 0.8'} + + confbox@0.1.8: + resolution: {integrity: sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w==} + + confbox@0.2.4: + resolution: {integrity: sha512-ysOGlgTFbN2/Y6Cg3Iye8YKulHw+R2fNXHrgSmXISQdMnomY6eNDprVdW9R5xBguEqI954+S6709UyiO7B+6OQ==} + + convert-source-map@2.0.0: + resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} + + cross-spawn@7.0.6: + resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} + engines: {node: '>= 8'} + + csstype@3.1.3: + resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==} + + csstype@3.2.3: + resolution: {integrity: sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==} + + debug@4.4.0: + resolution: {integrity: sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + decode-uri-component@0.4.1: + resolution: {integrity: sha512-+8VxcR21HhTy8nOt6jf20w0c9CADrw1O8d+VZ/YzzCt4bJ3uBjw+D1q2osAB8RnpwwaeYBxy0HyKQxD5JBMuuQ==} + engines: {node: '>=14.16'} + + defu@6.1.4: + resolution: {integrity: sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==} + + defu@6.1.7: + resolution: {integrity: sha512-7z22QmUWiQ/2d0KkdYmANbRUVABpZ9SNYyH5vx6PZ+nE5bcC0l7uFvEfHlyld/HcGBFTL536ClDt3DEcSlEJAQ==} + + delayed-stream@1.0.0: + resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} + engines: {node: '>=0.4.0'} + + detect-libc@1.0.3: + resolution: {integrity: sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==} + engines: {node: '>=0.10'} + hasBin: true + + detect-libc@2.1.2: + resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==} + engines: {node: '>=8'} + + dunder-proto@1.0.1: + resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} + engines: {node: '>= 0.4'} + + electron-to-chromium@1.5.113: + resolution: {integrity: sha512-wjT2O4hX+wdWPJ76gWSkMhcHAV2PTMX+QetUCPYEdCIe+cxmgzzSSiGRCKW8nuh4mwKZlpv0xvoW7OF2X+wmHg==} + + enhanced-resolve@5.24.5: + resolution: {integrity: sha512-L1l8TNvomm6UVW5B253AGxQagSQr+vGwhMlrrfRS2qmhx46AMpMVJKQYLvWYbysTMY8VoicOvzHzoHMbyzB+4A==} + engines: {node: '>=10.13.0'} + + entities@4.5.0: + resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} + engines: {node: '>=0.12'} + + entities@7.0.1: + resolution: {integrity: sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==} + engines: {node: '>=0.12'} + + es-define-property@1.0.1: + resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==} + engines: {node: '>= 0.4'} + + es-errors@1.3.0: + resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} + engines: {node: '>= 0.4'} + + es-object-atoms@1.1.1: + resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==} + engines: {node: '>= 0.4'} + + es-set-tostringtag@2.1.0: + resolution: {integrity: sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==} + engines: {node: '>= 0.4'} + + escalade@3.2.0: + resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} + engines: {node: '>=6'} + + escape-string-regexp@5.0.0: + resolution: {integrity: sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==} + engines: {node: '>=12'} + + estree-walker@2.0.2: + resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} + + estree-walker@3.0.3: + resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==} + + exsolve@1.1.1: + resolution: {integrity: sha512-9U/jZUgjnSGyntRr6y5Muu1MJcwFl6kPu7k8qLF0IMNfLqvw0NZ4nnVDq0RVoZ0RvCyumib4Ez3KYrVfilrw+g==} + + fast-glob@3.3.3: + resolution: {integrity: sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==} + engines: {node: '>=8.6.0'} + + fastq@1.19.1: + resolution: {integrity: sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==} + + fdir@6.5.0: + resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==} + engines: {node: '>=12.0.0'} + peerDependencies: + picomatch: ^3 || ^4 + peerDependenciesMeta: + picomatch: + optional: true + + fill-range@7.1.1: + resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} + engines: {node: '>=8'} + + filter-obj@5.1.0: + resolution: {integrity: sha512-qWeTREPoT7I0bifpPUXtxkZJ1XJzxWtfoWWkdVGqa+eCr3SHW/Ocp89o8vLvbUuQnadybJpjOKu4V+RwO6sGng==} + engines: {node: '>=14.16'} + + follow-redirects@1.15.9: + resolution: {integrity: sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==} + engines: {node: '>=4.0'} + peerDependencies: + debug: '*' + peerDependenciesMeta: + debug: + optional: true + + form-data@4.0.2: + resolution: {integrity: sha512-hGfm/slu0ZabnNt4oaRZ6uREyfCj6P4fT/n6A1rGV+Z0VdGXjfOhVUpkn6qVQONHGIFwmveGXyDs75+nr6FM8w==} + engines: {node: '>= 6'} + + fsevents@2.3.3: + resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + + function-bind@1.1.2: + resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} + + gensync@1.0.0-beta.2: + resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} + engines: {node: '>=6.9.0'} + + get-intrinsic@1.3.0: + resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==} + engines: {node: '>= 0.4'} + + get-proto@1.0.1: + resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==} + engines: {node: '>= 0.4'} + + glob-parent@5.1.2: + resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} + engines: {node: '>= 6'} + + gopd@1.2.0: + resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==} + engines: {node: '>= 0.4'} + + graceful-fs@4.2.11: + resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} + + has-symbols@1.1.0: + resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==} + engines: {node: '>= 0.4'} + + has-tostringtag@1.0.2: + resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} + engines: {node: '>= 0.4'} + + hasown@2.0.2: + resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} + engines: {node: '>= 0.4'} + + hoci@0.6.0: + resolution: {integrity: sha512-PtSPRtQm5/OUKxSU8lVelhBc+3TVW2cB2hGlG9pfzQ0rbSBFgLHWSLImBgLZnau72wKOrMNjBxzprQ941+rTWw==} + peerDependencies: + vue: ^3.0.0 + + hookable@5.5.3: + resolution: {integrity: sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==} + + immutable@5.1.9: + resolution: {integrity: sha512-m8nVez3rwrgmWxtLMt1ZYXB2Lv7OKYn/disyxAlSDYAlKSlFoPPfIAmAM/M5xqL4m4C/wAPw7S2/CNaUii1Hxg==} + + is-binary-path@2.1.0: + resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} + engines: {node: '>=8'} + + is-extglob@2.1.1: + resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} + engines: {node: '>=0.10.0'} + + is-glob@4.0.3: + resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} + engines: {node: '>=0.10.0'} + + is-number@7.0.0: + resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} + engines: {node: '>=0.12.0'} + + isexe@2.0.0: + resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + + isexe@4.0.0: + resolution: {integrity: sha512-FFUtZMpoZ8RqHS3XeXEmHWLA4thH+ZxCv2lOiPIn1Xc7CxrqhWzNSDzD+/chS/zbYezmiwWLdQC09JdQKmthOw==} + engines: {node: '>=20'} + + jiti@2.7.0: + resolution: {integrity: sha512-AC/7JofJvZGrrneWNaEnJeOLUx+JlGt7tNa0wZiRPT4MY1wmfKjt2+6O2p2uz2+skll8OZZmJMNqeke7kKbNgQ==} + hasBin: true + + js-tokens@10.0.0: + resolution: {integrity: sha512-lM/UBzQmfJRo9ABXbPWemivdCW8V2G8FHaHdypQaIy523snUjog0W71ayWXTjiR+ixeMyVHN2XcpnTd/liPg/Q==} + + js-tokens@4.0.0: + resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} + + jsesc@3.1.0: + resolution: {integrity: sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==} + engines: {node: '>=6'} + hasBin: true + + json-parse-even-better-errors@6.0.0: + resolution: {integrity: sha512-2/8adwnK1/+Fdjyts4r6wSpfANWw8zdNhU9U/Llk59c6O+DjSisPWPykwoL8gZmocP9Dy64S7oie2g+Mia123A==} + engines: {node: ^22.22.2 || ^24.15.0 || >=26.0.0} + + json5@2.2.3: + resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} + engines: {node: '>=6'} + hasBin: true + + lightningcss-android-arm64@1.32.0: + resolution: {integrity: sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [android] + + lightningcss-android-arm64@1.33.0: + resolution: {integrity: sha512-gEpRTalKdosp4Bb8qWtc2iOgE5SeIHlpS1up9bFq2wAyYhl1UdTObYiHe98zEM9SQvSoqQZ1IQD0JNpg3Ml5pg==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [android] + + lightningcss-darwin-arm64@1.32.0: + resolution: {integrity: sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [darwin] + + lightningcss-darwin-arm64@1.33.0: + resolution: {integrity: sha512-Sciaz8eenNTKn9b3t7+xr0ipTp9YxKQY4npwQ3mrRuL0BAVHBLyZxofhaKBAVtzmtRZ/zTyo0/to4B1uWG/Djg==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [darwin] + + lightningcss-darwin-x64@1.32.0: + resolution: {integrity: sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [darwin] + + lightningcss-darwin-x64@1.33.0: + resolution: {integrity: sha512-Z5UPAxzrjlWNNyGy6i65cJzzvgJ5D3T6wMvs+gWpY9d7qRhANrxqAp6LhxIgZhWEw18RfJTGcRxjuLIBr+m8XQ==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [darwin] + + lightningcss-freebsd-x64@1.32.0: + resolution: {integrity: sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [freebsd] + + lightningcss-freebsd-x64@1.33.0: + resolution: {integrity: sha512-QQM/Ti/hQajJwCY+RiWuCZ9sdtI/XQk7nDK5vC8kkdwixezOlDgvDx7+RT+QjK6FcFT4MpsuoBnHIo/O3StRRg==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [freebsd] + + lightningcss-linux-arm-gnueabihf@1.32.0: + resolution: {integrity: sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw==} + engines: {node: '>= 12.0.0'} + cpu: [arm] + os: [linux] + + lightningcss-linux-arm-gnueabihf@1.33.0: + resolution: {integrity: sha512-N7FVBe6iS24MlM6R/4RBTxGhQheZGs7tiQ9U32UtF75NzP5Q7xWPRqLBCKxlRQRk3rY1jCIPLzx7WzOhuUIRLQ==} + engines: {node: '>= 12.0.0'} + cpu: [arm] + os: [linux] + + lightningcss-linux-arm64-gnu@1.32.0: + resolution: {integrity: sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [linux] + + lightningcss-linux-arm64-gnu@1.33.0: + resolution: {integrity: sha512-j2v/itmy4HlNxlc6voKXYgBqNi0Ng2LShg4z7GufpEgs05P+2suBVyi9I6YHq5uoVFx9ETin3eCEhLVyXGQnKg==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [linux] + + lightningcss-linux-arm64-musl@1.32.0: + resolution: {integrity: sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [linux] + + lightningcss-linux-arm64-musl@1.33.0: + resolution: {integrity: sha512-yiO5ROMuYQgXbC60yjZU5CYSFZGKXL0HFATXt9mHJn1+zW55oCtMI9NfcVhYLMFDL7gV7oBPon/EmMMGg2OvtQ==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [linux] + + lightningcss-linux-x64-gnu@1.32.0: + resolution: {integrity: sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [linux] + + lightningcss-linux-x64-gnu@1.33.0: + resolution: {integrity: sha512-ar+Ju7LmcN0Jo4FpL4hpFybwNG9/3A/Br5KW2n2jyODg3MEZXaDYADdemoNS+BDNfMgKvylJLj4S5tyRActuAg==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [linux] + + lightningcss-linux-x64-musl@1.32.0: + resolution: {integrity: sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [linux] + + lightningcss-linux-x64-musl@1.33.0: + resolution: {integrity: sha512-RYiYbkokw0trfKqqzfF55lginwEPrD3OJDfTuJzFs1MK6iFnDenaz1fqLLtX4ITG3OktJQXOeTaw1awrBAlZPw==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [linux] + + lightningcss-win32-arm64-msvc@1.32.0: + resolution: {integrity: sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [win32] + + lightningcss-win32-arm64-msvc@1.33.0: + resolution: {integrity: sha512-1K+MPfLSFVpphzpdbfkhlWk6wBrTObBzS2T6db10PNOZgR9GoVsAWzwNyuhUYYbTp23j+4RrncfujZ4uAzXvwA==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [win32] + + lightningcss-win32-x64-msvc@1.32.0: + resolution: {integrity: sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [win32] + + lightningcss-win32-x64-msvc@1.33.0: + resolution: {integrity: sha512-OlEICDx/Xl0FqSp4bry8zFnCvGpig3Gl4gCquvYwHuqJKEC1+n9NgDniFvqHGmMv1ZkqDJrDqKKSykTDX+ehuA==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [win32] + + lightningcss@1.32.0: + resolution: {integrity: sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==} + engines: {node: '>= 12.0.0'} + + lightningcss@1.33.0: + resolution: {integrity: sha512-WkUDrojuJs0xkgGf2udWxa3yGBRxPtxUkB79i6aCZLRgc7PM8fZe9TosfPDcvEpQZbuFASnHYmRLBLUbmLOIIA==} + engines: {node: '>= 12.0.0'} + + local-pkg@0.5.1: + resolution: {integrity: sha512-9rrA30MRRP3gBD3HTGnC6cDFpaE1kVDWxWgqWJUN0RvDNAo+Nz/9GxB+nHOH0ifbVFy0hSA1V6vFDvnx54lTEQ==} + engines: {node: '>=14'} + + local-pkg@1.2.1: + resolution: {integrity: sha512-++gUqRDEvcnN6Zhqrr+y/CkVEHhlrR96vZn3nZZPYzMcBUyBtTKzB9NadClFIsIVSsu+3i9tfk/erqy9kAmt7Q==} + engines: {node: '>=14'} + + lru-cache@5.1.1: + resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} + + magic-string-ast@1.0.3: + resolution: {integrity: sha512-CvkkH1i81zl7mmb94DsRiFeG9V2fR2JeuK8yDgS8oiZSFa++wWLEgZ5ufEOyLHbvSbD1gTRKv9NdX69Rnvr9JA==} + engines: {node: '>=20.19.0'} + + magic-string@0.30.17: + resolution: {integrity: sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==} + + magic-string@0.30.21: + resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==} + + magic-string@1.1.0: + resolution: {integrity: sha512-kS3VHe0nEPST2saQV4Rbkchcd3UBRkVTQHo1D3h/ZTwFDhai/mfKkmtPAtD129EOI7K3HlHIsFOt0WrI2/oU9g==} + + math-intrinsics@1.1.0: + resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} + engines: {node: '>= 0.4'} + + maybe-types@0.2.0: + resolution: {integrity: sha512-4ul+RHPcxNznI+Ke6xUT2/mcQTl54fYUdRZQ3QNkQsC4USfAxXkPTh+wEOx4UBsXYg214867v2ZeirQDJT7uOA==} + + memorystream@0.3.1: + resolution: {integrity: sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw==} + engines: {node: '>= 0.10.0'} + + merge2@1.4.1: + resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} + engines: {node: '>= 8'} + + micromatch@4.0.8: + resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} + engines: {node: '>=8.6'} + + mime-db@1.52.0: + resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} + engines: {node: '>= 0.6'} + + mime-types@2.1.35: + resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} + engines: {node: '>= 0.6'} + + minimatch@9.0.5: + resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==} + engines: {node: '>=16 || 14 >=14.17'} + + mlly@1.7.4: + resolution: {integrity: sha512-qmdSIPC4bDJXgZTCR7XosJiNKySV7O215tsPtDN9iEO/7q/76b/ijtgRu/+epFXSJhijtTCCGp3DWS549P3xKw==} + + mlly@1.8.2: + resolution: {integrity: sha512-d+ObxMQFmbt10sretNDytwt85VrbkhhUA/JBGm1MPaWJ65Cl4wOgLaB1NYvJSZ0Ef03MMEU/0xpPMXUIQ29UfA==} + + ms@2.1.3: + resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + + muggle-string@0.4.1: + resolution: {integrity: sha512-VNTrAak/KhO2i8dqqnqnAHOa3cYBwXEZe9h+D5h/1ZqFSTEFHdM65lR7RoIqq3tBBYavsOXV84NoHXZ0AkPyqQ==} + + nanoid@3.3.17: + resolution: {integrity: sha512-xQLf0A3HOMlgHq0n247/LRuAOYmB7dXJ/DvAxGvsSBij45XtBSmQycu+F8ODbHwns/XyFZagyL1+J0Offw1E0g==} + engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} + hasBin: true + + node-addon-api@7.1.1: + resolution: {integrity: sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==} + + node-releases@2.0.19: + resolution: {integrity: sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==} + + normalize-path@3.0.0: + resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} + engines: {node: '>=0.10.0'} + + nostics@1.2.0: + resolution: {integrity: sha512-FGqEfhQjrvo1lL8KFifdTQiNwwQHJxC1jtYE1Rc54qF/jxONUNL+kC9gS1krX8Q65PgrQ5fCqH/I4NhWBvdSqg==} + + npm-normalize-package-bin@6.0.0: + resolution: {integrity: sha512-tdt4aFn9QamlhdN3HV2D2ccpBwO5/fyjjbXUxYA6uBjyekMZcZvDq0aSj9t5Jo+tih6AYFnt/cuIRn9013e0Uw==} + engines: {node: ^22.22.2 || ^24.15.0 || >=26.0.0} + + npm-run-all2@9.0.3: + resolution: {integrity: sha512-BQAEdU1PtYc48qYRdghW2BVTQT3VqWCoFQmO87NlM1h1PYwMCKQpUWaNyB20V26caNzFsXQDfyOdznLlHCih6g==} + engines: {node: ^22.22.2 || ^24.15.0 || >=26.0.0, npm: '>= 10'} + hasBin: true + + obug@2.1.4: + resolution: {integrity: sha512-4a+OsYv9UktOJKE+l1A4OufDgdRF9PifWj+tJnHURo/P+WOxpG4GzUFL9qCalmWauao6ogiG+QvnCovwPoyAWA==} + engines: {node: '>=12.20.0'} + + ohash@2.0.11: + resolution: {integrity: sha512-RdR9FQrFwNBNXAr4GixM8YaRZRJ5PUWbKYbE5eOsrwAjJW0q2REGcf79oYPsLyskQCZG1PLN+S/K1V00joZAoQ==} + + oxfmt@0.62.0: + resolution: {integrity: sha512-vxgGHTmnDU9j4CX7dDBLzxgmHxfda/yPcgJkGCMUSCwRmz+euo/V08xXLNgXTeqAB9Fhf3Pe2nO1RNKLCVgphQ==} + engines: {node: ^20.19.0 || >=22.12.0} + hasBin: true + peerDependencies: + svelte: ^5.0.0 + vite-plus: '*' + peerDependenciesMeta: + svelte: + optional: true + vite-plus: + optional: true + + oxlint@1.77.0: + resolution: {integrity: sha512-qnGh8XJHaQ0dprrDXNQZgS0FgjI6v+V3+X8DwmaV++5Aamy6jGKfDdQ1TUvhUxtmKFAbEf4/WeO5QZX+5WSngg==} + engines: {node: ^20.19.0 || >=22.12.0} + hasBin: true + peerDependencies: + oxlint-tsgolint: '>=7.0.2001' + vite-plus: '*' + peerDependenciesMeta: + oxlint-tsgolint: + optional: true + vite-plus: + optional: true + + pako@2.1.0: + resolution: {integrity: sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug==} + + path-browserify@1.0.1: + resolution: {integrity: sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==} + + path-key@3.1.1: + resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} + engines: {node: '>=8'} + + pathe@2.0.3: + resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==} + + perfect-debounce@2.1.0: + resolution: {integrity: sha512-LjgdTytVFXeUgtHZr9WYViYSM/g8MkcTPYDlPa3cDqMirHjKiSZPYd6DoL7pK8AJQr+uWkQvCjHNdiMqsrJs+g==} + + picocolors@1.1.1: + resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} + + picomatch@2.3.1: + resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} + engines: {node: '>=8.6'} + + picomatch@4.0.2: + resolution: {integrity: sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==} + engines: {node: '>=12'} + + picomatch@4.0.5: + resolution: {integrity: sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==} + engines: {node: '>=12'} + + pidtree@1.0.0: + resolution: {integrity: sha512-avfAvjB9Dd0wdj3rjJX//yS+G79OO0KrS5pJHFJENjYGX6N4SMgEDBBI/yFy0lloOYSaC6XQxzpOAMPfSYFV/Q==} + engines: {node: '>=18'} + hasBin: true + + pinia@4.0.2: + resolution: {integrity: sha512-yKVVA7bSj5oRZFp/Ab9wLlmyb5gPUYEiIm4ryiWTe/xe7PtkRdMVOp1X1ggvq0c6Uj7Q0Du1HnV2mtAwM0Ks1g==} + peerDependencies: + '@vue/devtools-api': ^8.1.5 + typescript: '>=5.6.0' + vue: ^3.5.11 + peerDependenciesMeta: + typescript: + optional: true + + pkg-types@1.3.1: + resolution: {integrity: sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ==} + + pkg-types@2.3.1: + resolution: {integrity: sha512-y+ichcgc2LrADuhLNAx8DFjVfgz91pRxfZdI3UDhxHvcVEZsenLO+7XaU5vOp0u/7V/wZ+plyuQxtrDlZJ+yeg==} + + postcss@8.5.25: + resolution: {integrity: sha512-DTPx3RWSSnWyzLxQnlH0rJP+EW5ekl16ZU4/psbIhA0e53kJfdgaN5vKM+xP7yJtXVu+nfdVFmlgFDEKAe4Pyw==} + engines: {node: ^10 || ^12 || >=14} + + proxy-from-env@1.1.0: + resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} + + quansync@0.2.11: + resolution: {integrity: sha512-AifT7QEbW9Nri4tAwR5M/uzpBuqfZf+zwaEM/QkzEjj7NBuFD2rBuy0K3dE+8wltbezDV7JMA0WfnCPYRSYbXA==} + + query-string@9.1.1: + resolution: {integrity: sha512-MWkCOVIcJP9QSKU52Ngow6bsAWAPlPK2MludXvcrS2bGZSl+T1qX9MZvRIkqUIkGLJquMJHWfsT6eRqUpp4aWg==} + engines: {node: '>=18'} + + queue-microtask@1.2.3: + resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} + + read-package-json-fast@6.0.0: + resolution: {integrity: sha512-PNaGjoCnw9DBA2Kl8D+8po957z778q/HOPuY2u3Bkw/JO3eC8MDx7jn/PgMtSgpcBbs+6UOjDbwReGpXmRvs0g==} + engines: {node: ^22.22.2 || ^24.15.0 || >=26.0.0} + + readdirp@3.6.0: + resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} + engines: {node: '>=8.10.0'} + + readdirp@5.0.0: + resolution: {integrity: sha512-9u/XQ1pvrQtYyMpZe7DXKv2p5CNvyVwzUB6uhLAnQwHMSgKMBR62lc7AHljaeteeHXn11XTAaLLUVZYVZyuRBQ==} + engines: {node: '>= 20.19.0'} + + reka-ui@2.10.1: + resolution: {integrity: sha512-drcOQ4rQtDYAcGCsyQBqQg8QQ+H3B+zDaMJU0h8KPEPMa7g9BHu3zcOi4OB39XJSWizceFoNO0Z9tctSGLOXqg==} + peerDependencies: + vue: '>= 3.4.0' + + reusify@1.1.0: + resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==} + engines: {iojs: '>=1.0.0', node: '>=0.10.0'} + + rolldown@1.2.2: + resolution: {integrity: sha512-opwpo1tQBAcpSUJDt94B7hhLNGOKjCdE//XXjeLrnx9b83bjnw45tXdg1b09yEw/VLFBJGZpwRULMmOZo7ol+A==} + engines: {node: ^20.19.0 || >=22.12.0} + hasBin: true + + rollup@4.35.0: + resolution: {integrity: sha512-kg6oI4g+vc41vePJyO6dHt/yl0Rz3Thv0kJeVQ3D1kS3E5XSuKbPc29G4IpT/Kv1KQwgHVcN+HtyS+HYLNSvQg==} + engines: {node: '>=18.0.0', npm: '>=8.0.0'} + hasBin: true + + run-parallel@1.2.0: + resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} + + sass@1.102.0: + resolution: {integrity: sha512-NSOyTnaQF7rTAEOtI2fwb386vL+akyiQLBZu8Na7hXCb+umJy0GAqlcMIaqACZ6Z1VgTBS4K9PG6B3IdjHGJsw==} + engines: {node: '>=20.19.0'} + hasBin: true + + scule@1.3.0: + resolution: {integrity: sha512-6FtHJEvt+pVMIB9IBY+IcCJ6Z5f1iQnytgyfKMhDKgmzYG+TeH/wx1y3l27rshSbLiSanrR9ffZDrEsmjlQF2g==} + + semver@6.3.1: + resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} + hasBin: true + + shebang-command@2.0.0: + resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} + engines: {node: '>=8'} + + shebang-regex@3.0.0: + resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} + engines: {node: '>=8'} + + shell-quote@1.10.0: + resolution: {integrity: sha512-w1aiOKwKuRgtwAReIIj89puqg+I7GvX4IbLrvmhXbzQsj1+Zwi4VO3+fa6ZF91TWSjIxoEkKnMeHcLEODK5ZXA==} + engines: {node: '>= 0.4'} + + source-map-js@1.2.1: + resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} + engines: {node: '>=0.10.0'} + + split-on-first@3.0.0: + resolution: {integrity: sha512-qxQJTx2ryR0Dw0ITYyekNQWpz6f8dGd7vffGNflQQ3Iqj9NJ6qiZ7ELpZsJ/QBhIVAiDfXdag3+Gp8RvWa62AA==} + engines: {node: '>=12'} + + strip-literal@4.0.0: + resolution: {integrity: sha512-PaqAvfUZKBwc/SLmNZtHmzK+v19Z4O4eS3cKPeGvbIv/U3pnyEq4Tuw3/4v/FwfM8VQaEawsyCcOQ0P+kpwWWw==} + + tailwind-merge@3.6.0: + resolution: {integrity: sha512-uxL7qAVQriqRQPAyK3pj66VqskWqoZ37PW94jwOTwNfq/z9oyu1V+eqrZqtR2+fCiXdYOZe/Modt8GtvqNzu+w==} + + tailwindcss@4.3.3: + resolution: {integrity: sha512-gOhV3P7ufE62QDGg1zVaTgCR+EtPv92k2nIhVcVKcLmxT1sUBsQGhnZj175j+MqRt4zLF7ic+sCYjfhxMxj7YQ==} + + tapable@2.3.3: + resolution: {integrity: sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A==} + engines: {node: '>=6'} + + tinyglobby@0.2.17: + resolution: {integrity: sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==} + engines: {node: '>=12.0.0'} + + tinypool@2.1.0: + resolution: {integrity: sha512-Pugqs6M0m7Lv1I7FtxN4aoyToKg1C4tu+/381vH35y8oENM/Ai7f7C4StcoK4/+BSw9ebcS8jRiVrORFKCALLw==} + engines: {node: ^20.0.0 || >=22.0.0} + + to-regex-range@5.0.1: + resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} + engines: {node: '>=8.0'} + + tslib@2.8.1: + resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} + + tslx@0.1.1: + resolution: {integrity: sha512-MYh2I7iw8owRx3xFVq8DXp3JWoJ7G7oMA5uUrCwGvuOipV6w9XvlJKo3yVJMh75Y+5caIaYhCsUZ1WTnxQRk7A==} + + type-fest@4.38.0: + resolution: {integrity: sha512-2dBz5D5ycHIoliLYLi0Q2V7KRaDlH0uWIvmk7TYlAg5slqwiPv1ezJdZm1QEM0xgk29oYWMCbIG7E6gHpvChlg==} + engines: {node: '>=16'} + + typescript@6.0.3: + resolution: {integrity: sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw==} + engines: {node: '>=14.17'} + hasBin: true + + ufo@1.5.4: + resolution: {integrity: sha512-UsUk3byDzKd04EyoZ7U4DOlxQaD14JUKQl6/P7wiX4FNvUfm3XL246n9W5AmqwW5RSFJ27NAuM0iLscAOYUiGQ==} + + ufo@1.6.4: + resolution: {integrity: sha512-JFNbkD1Svwe0KvGi8GOeLcP4kAWQ609twvCdcHxq1oSL8svv39ZuSvajcD8B+5D0eL4+s1Is2D/O6KN3qcTeRA==} + + undici-types@8.3.0: + resolution: {integrity: sha512-j375ScV60dom+YkPFIfTLcOiPxkN/buHz5GobjLhixFuANaNs3C9l4GmrWqejgXWJ7BbJcFYpTEUkS1Ge8bpZQ==} + + unimport@6.4.0: + resolution: {integrity: sha512-JJOOuNMFq8b4ZPBKwQUxEcba4MplskDzYI1Lvrf8rJfWphZTWvPNXWa493qsPngHUmub89w6C7j+SeLWTE/UIQ==} + engines: {node: '>=18.12.0'} + peerDependencies: + oxc-parser: '*' + rolldown: ^1.0.0 + peerDependenciesMeta: + oxc-parser: + optional: true + rolldown: + optional: true + + unplugin-auto-import@21.1.0: + resolution: {integrity: sha512-EzrSqWIBulEqCuP7idADXH+tVKYrbwKlR5+r/lOWik0o+Ksny1kitmtryHGNSv7puzzORlcIwT/x2JStiszlHA==} + engines: {node: '>=20.19.0'} + peerDependencies: + '@nuxt/kit': ^4.0.0 + '@vueuse/core': '*' + peerDependenciesMeta: + '@nuxt/kit': + optional: true + '@vueuse/core': + optional: true + + unplugin-utils@0.3.2: + resolution: {integrity: sha512-xVToRh2CTmLk2HnEG7ac4rl1MJTT3RFkpS8B++/SnB0kXvuaavD+n3m/vrzyWQOdJNSZQACnbz01pnppbwV5BA==} + engines: {node: '>=20.19.0'} + + unplugin-vue-components@0.27.5: + resolution: {integrity: sha512-m9j4goBeNwXyNN8oZHHxvIIYiG8FQ9UfmKWeNllpDvhU7btKNNELGPt+o3mckQKuPwrE7e0PvCsx+IWuDSD9Vg==} + engines: {node: '>=14'} + peerDependencies: + '@babel/parser': ^7.15.8 + '@nuxt/kit': ^3.2.2 + vue: 2 || 3 + peerDependenciesMeta: + '@babel/parser': + optional: true + '@nuxt/kit': + optional: true + + unplugin-vue-components@32.1.0: + resolution: {integrity: sha512-YiUkSxuRjab18XFOrX5VsIxXzccrfmHVGsGeJgSgklb829DQmCy9E4vvDUE4tuvZZdxyFJZX0Oc4TPnnxiiMyg==} + engines: {node: '>=20.19.0'} + peerDependencies: + '@nuxt/kit': ^3.2.2 || ^4.0.0 + vue: ^3.0.0 + peerDependenciesMeta: + '@nuxt/kit': + optional: true + + unplugin@1.16.1: + resolution: {integrity: sha512-4/u/j4FrCKdi17jaxuJA0jClGxB1AvU2hw/IuayPc4ay1XGaJs/rbb4v5WKwAjNifjmXK9PIFyuPiaK8azyR9w==} + engines: {node: '>=14.0.0'} + + unplugin@3.3.0: + resolution: {integrity: sha512-qa66K+crbfyE6JK10GjvbJeRrOsuC/JpbnHctfyp/i4oBTxWOzJfRZyDiOk1PtErMFRu8JhsU/wPvOdBNWe5Rg==} + engines: {node: ^20.19.0 || >=22.12.0} + peerDependencies: + '@farmfe/core': '*' + '@rspack/core': '*' + bun-types-no-globals: '*' + esbuild: '*' + rolldown: '*' + rollup: '*' + unloader: '*' + vite: '*' + webpack: '*' + peerDependenciesMeta: + '@farmfe/core': + optional: true + '@rspack/core': + optional: true + bun-types-no-globals: + optional: true + esbuild: + optional: true + rolldown: + optional: true + rollup: + optional: true + unloader: + optional: true + vite: + optional: true + webpack: + optional: true + + update-browserslist-db@1.1.3: + resolution: {integrity: sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==} + hasBin: true + peerDependencies: + browserslist: '>= 4.21.0' + + vite@8.2.0: + resolution: {integrity: sha512-pn+CFpM0lwDeKwmOq1ZaBK/9sjorZcgqxki6MbY/jPEVd9vichIlmlD4HmQ5wdP5EgqQCFRaACBxMC7uEGc6lQ==} + engines: {node: ^20.19.0 || >=22.12.0} + hasBin: true + peerDependencies: + '@types/node': ^20.19.0 || >=22.12.0 + '@vitejs/devtools': ^0.4.0 + esbuild: ^0.27.0 || ^0.28.0 + jiti: '>=1.21.0' + less: ^4.0.0 + sass: ^1.70.0 + sass-embedded: ^1.70.0 + stylus: '>=0.54.8' + sugarss: ^5.0.0 + terser: ^5.16.0 + tsx: ^4.8.1 + yaml: ^2.4.2 + peerDependenciesMeta: + '@types/node': + optional: true + '@vitejs/devtools': + optional: true + esbuild: + optional: true + jiti: + optional: true + less: + optional: true + sass: + optional: true + sass-embedded: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + tsx: + optional: true + yaml: + optional: true + + vscode-uri@3.1.0: + resolution: {integrity: sha512-/BpdSx+yCQGnCvecbyXdxHDkuk55/G3xwnC0GqY4gmQ3j+A+g8kzzgB4Nk/SINjqn6+waqw3EgbVF2QKExkRxQ==} + + vue-demi@0.14.10: + resolution: {integrity: sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg==} + engines: {node: '>=12'} + hasBin: true + peerDependencies: + '@vue/composition-api': ^1.0.0-rc.1 + vue: ^3.0.0-0 || ^2.6.0 + peerDependenciesMeta: + '@vue/composition-api': + optional: true + + vue-router@5.2.0: + resolution: {integrity: sha512-QAC5i0LEb1GLG0LXDQmHu8L7FX12j0KwU/JTKmLQUJMrn04gQdKP6Du+p0QwpHb3iy71vBlqnHQ8WAfOSAWhqw==} + peerDependencies: + '@pinia/colada': '>=0.21.2' + '@vue/compiler-sfc': ^3.5.34 || ^4.0.0 + pinia: ^3.0.4 || ^4.0.2 + vite: ^7.3.0 || ^8.0.0 + vue: ^3.5.34 || ^4.0.0 + peerDependenciesMeta: + '@pinia/colada': + optional: true + '@vue/compiler-sfc': + optional: true + pinia: + optional: true + vite: + optional: true + + vue-tsc@3.3.9: + resolution: {integrity: sha512-TS3Y1ux/IRoE8OCP2PpACAeOseuIs0UvWrcr7u+w3PmfY+SlCfEf8zjrBgnQksHUgLpthi5vHlffcQTQTdPBZA==} + hasBin: true + peerDependencies: + typescript: '>=5.0.0' + + vue@3.5.40: + resolution: {integrity: sha512-+8PJ4SJXdn/cHGImF4CKdxlWHIN5Dkt7DoufRREM6h6uVCx2m7QxgcEQmmzyOK8A9mcafg7sFbJFYsdFVubTig==} + peerDependencies: + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + + webpack-virtual-modules@0.6.2: + resolution: {integrity: sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ==} + + which@2.0.2: + resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} + engines: {node: '>= 8'} + hasBin: true + + which@7.0.0: + resolution: {integrity: sha512-RancgH2dmbLdHl6LRhEqvklWMgl/Hdnun0Y90KhBOLkMefg8Qa7/Zel8Sm+8HEcP6DEjzsWzpkuBQEZok58isA==} + engines: {node: ^22.22.2 || ^24.15.0 || >=26.0.0} + hasBin: true + + yallist@3.1.1: + resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} + + yaml@2.9.0: + resolution: {integrity: sha512-2AvhNX3mb8zd6Zy7INTtSpl1F15HW6Wnqj0srWlkKLcpYl/gMIMJiyuGq2KeI2YFxUPjdlB+3Lc10seMLtL4cA==} + engines: {node: '>= 14.6'} + hasBin: true + +snapshots: + + '@antfu/utils@0.7.10': + optional: true + + '@babel/code-frame@7.29.7': + dependencies: + '@babel/helper-validator-identifier': 7.29.7 + js-tokens: 4.0.0 + picocolors: 1.1.1 + + '@babel/compat-data@7.29.7': {} + + '@babel/core@7.29.7': + dependencies: + '@babel/code-frame': 7.29.7 + '@babel/generator': 7.29.8 + '@babel/helper-compilation-targets': 7.29.7 + '@babel/helper-module-transforms': 7.29.7(@babel/core@7.29.7) + '@babel/helpers': 7.29.7 + '@babel/parser': 7.29.8 + '@babel/template': 7.29.7 + '@babel/traverse': 7.29.8 + '@babel/types': 7.29.8 + '@jridgewell/remapping': 2.3.5 + convert-source-map: 2.0.0 + debug: 4.4.0 + gensync: 1.0.0-beta.2 + json5: 2.2.3 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + + '@babel/generator@7.29.8': + dependencies: + '@babel/parser': 7.29.8 + '@babel/types': 7.29.8 + '@jridgewell/gen-mapping': 0.3.13 + '@jridgewell/trace-mapping': 0.3.31 + jsesc: 3.1.0 + + '@babel/generator@8.0.0': + dependencies: + '@babel/parser': 8.0.4 + '@babel/types': 8.0.4 + '@jridgewell/gen-mapping': 0.3.13 + '@jridgewell/trace-mapping': 0.3.31 + '@types/jsesc': 2.5.1 + jsesc: 3.1.0 + + '@babel/helper-annotate-as-pure@7.29.7': + dependencies: + '@babel/types': 7.29.8 + + '@babel/helper-compilation-targets@7.29.7': + dependencies: + '@babel/compat-data': 7.29.7 + '@babel/helper-validator-option': 7.29.7 + browserslist: 4.24.4 + lru-cache: 5.1.1 + semver: 6.3.1 + + '@babel/helper-create-class-features-plugin@7.29.7(@babel/core@7.29.7)': + dependencies: + '@babel/core': 7.29.7 + '@babel/helper-annotate-as-pure': 7.29.7 + '@babel/helper-member-expression-to-functions': 7.29.7 + '@babel/helper-optimise-call-expression': 7.29.7 + '@babel/helper-replace-supers': 7.29.7(@babel/core@7.29.7) + '@babel/helper-skip-transparent-expression-wrappers': 7.29.7 + '@babel/traverse': 7.29.8 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + + '@babel/helper-globals@7.29.7': {} + + '@babel/helper-member-expression-to-functions@7.29.7': + dependencies: + '@babel/traverse': 7.29.8 + '@babel/types': 7.29.8 + transitivePeerDependencies: + - supports-color + + '@babel/helper-module-imports@7.29.7': + dependencies: + '@babel/traverse': 7.29.8 + '@babel/types': 7.29.8 + transitivePeerDependencies: + - supports-color + + '@babel/helper-module-transforms@7.29.7(@babel/core@7.29.7)': + dependencies: + '@babel/core': 7.29.7 + '@babel/helper-module-imports': 7.29.7 + '@babel/helper-validator-identifier': 7.29.7 + '@babel/traverse': 7.29.8 + transitivePeerDependencies: + - supports-color + + '@babel/helper-optimise-call-expression@7.29.7': + dependencies: + '@babel/types': 7.29.8 + + '@babel/helper-plugin-utils@7.29.7': {} + + '@babel/helper-replace-supers@7.29.7(@babel/core@7.29.7)': + dependencies: + '@babel/core': 7.29.7 + '@babel/helper-member-expression-to-functions': 7.29.7 + '@babel/helper-optimise-call-expression': 7.29.7 + '@babel/traverse': 7.29.8 + transitivePeerDependencies: + - supports-color + + '@babel/helper-skip-transparent-expression-wrappers@7.29.7': + dependencies: + '@babel/traverse': 7.29.8 + '@babel/types': 7.29.8 + transitivePeerDependencies: + - supports-color + + '@babel/helper-string-parser@7.25.9': {} + + '@babel/helper-string-parser@7.29.7': {} + + '@babel/helper-string-parser@8.0.0': {} + + '@babel/helper-validator-identifier@7.25.9': {} + + '@babel/helper-validator-identifier@7.29.7': {} + + '@babel/helper-validator-identifier@8.0.4': {} + + '@babel/helper-validator-option@7.29.7': {} + + '@babel/helpers@7.29.7': + dependencies: + '@babel/template': 7.29.7 + '@babel/types': 7.29.8 + + '@babel/parser@7.26.9': + dependencies: + '@babel/types': 7.26.9 + + '@babel/parser@7.29.8': + dependencies: + '@babel/types': 7.29.8 + + '@babel/parser@8.0.4': + dependencies: + '@babel/types': 8.0.4 + + '@babel/plugin-syntax-jsx@7.29.7(@babel/core@7.29.7)': + dependencies: + '@babel/core': 7.29.7 + '@babel/helper-plugin-utils': 7.29.7 + + '@babel/plugin-syntax-typescript@7.29.7(@babel/core@7.29.7)': + dependencies: + '@babel/core': 7.29.7 + '@babel/helper-plugin-utils': 7.29.7 + + '@babel/plugin-transform-typescript@7.29.7(@babel/core@7.29.7)': + dependencies: + '@babel/core': 7.29.7 + '@babel/helper-annotate-as-pure': 7.29.7 + '@babel/helper-create-class-features-plugin': 7.29.7(@babel/core@7.29.7) + '@babel/helper-plugin-utils': 7.29.7 + '@babel/helper-skip-transparent-expression-wrappers': 7.29.7 + '@babel/plugin-syntax-typescript': 7.29.7(@babel/core@7.29.7) + transitivePeerDependencies: + - supports-color + + '@babel/template@7.29.7': + dependencies: + '@babel/code-frame': 7.29.7 + '@babel/parser': 7.29.8 + '@babel/types': 7.29.8 + + '@babel/traverse@7.29.8': + dependencies: + '@babel/code-frame': 7.29.7 + '@babel/generator': 7.29.8 + '@babel/helper-globals': 7.29.7 + '@babel/parser': 7.29.8 + '@babel/template': 7.29.7 + '@babel/types': 7.29.8 + debug: 4.4.0 + transitivePeerDependencies: + - supports-color + + '@babel/types@7.26.9': + dependencies: + '@babel/helper-string-parser': 7.25.9 + '@babel/helper-validator-identifier': 7.25.9 + + '@babel/types@7.29.8': + dependencies: + '@babel/helper-string-parser': 7.29.7 + '@babel/helper-validator-identifier': 7.29.7 + + '@babel/types@8.0.4': + dependencies: + '@babel/helper-string-parser': 8.0.0 + '@babel/helper-validator-identifier': 8.0.4 + + '@floating-ui/core@1.8.0': + dependencies: + '@floating-ui/utils': 0.2.12 + + '@floating-ui/dom@1.8.0': + dependencies: + '@floating-ui/core': 1.8.0 + '@floating-ui/utils': 0.2.12 + + '@floating-ui/utils@0.2.12': {} + + '@floating-ui/vue@1.1.11(vue@3.5.40(typescript@6.0.3))': + dependencies: + '@floating-ui/dom': 1.8.0 + '@floating-ui/utils': 0.2.12 + vue-demi: 0.14.10(vue@3.5.40(typescript@6.0.3)) + transitivePeerDependencies: + - '@vue/composition-api' + - vue + + '@hoci/components@0.6.0(@vueuse/core@14.4.0(vue@3.5.40(typescript@6.0.3)))(vue@3.5.40(typescript@6.0.3))': + dependencies: + '@hoci/core': 0.6.0(vue@3.5.40(typescript@6.0.3)) + '@hoci/shared': 0.6.0(@vueuse/core@14.4.0(vue@3.5.40(typescript@6.0.3)))(vue@3.5.40(typescript@6.0.3)) + '@vueuse/core': 14.4.0(vue@3.5.40(typescript@6.0.3)) + maybe-types: 0.2.0 + tslx: 0.1.1 + vue: 3.5.40(typescript@6.0.3) + transitivePeerDependencies: + - '@vue/composition-api' + + '@hoci/core@0.6.0(vue@3.5.40(typescript@6.0.3))': + dependencies: + '@hoci/shared': 0.6.0(@vueuse/core@9.0.0(vue@3.5.40(typescript@6.0.3)))(vue@3.5.40(typescript@6.0.3)) + '@vueuse/core': 9.0.0(vue@3.5.40(typescript@6.0.3)) + maybe-types: 0.2.0 + tslx: 0.1.1 + vue: 3.5.40(typescript@6.0.3) + transitivePeerDependencies: + - '@vue/composition-api' + + '@hoci/shared@0.6.0(@vueuse/core@14.4.0(vue@3.5.40(typescript@6.0.3)))(vue@3.5.40(typescript@6.0.3))': + dependencies: + '@vueuse/core': 14.4.0(vue@3.5.40(typescript@6.0.3)) + defu: 6.1.4 + maybe-types: 0.2.0 + type-fest: 4.38.0 + vue: 3.5.40(typescript@6.0.3) + + '@hoci/shared@0.6.0(@vueuse/core@9.0.0(vue@3.5.40(typescript@6.0.3)))(vue@3.5.40(typescript@6.0.3))': + dependencies: + '@vueuse/core': 9.0.0(vue@3.5.40(typescript@6.0.3)) + defu: 6.1.4 + maybe-types: 0.2.0 + type-fest: 4.38.0 + vue: 3.5.40(typescript@6.0.3) + + '@internationalized/date@3.12.3': + dependencies: + '@swc/helpers': 0.5.23 + + '@internationalized/number@3.6.7': + dependencies: + '@swc/helpers': 0.5.23 + + '@jridgewell/gen-mapping@0.3.13': + dependencies: + '@jridgewell/sourcemap-codec': 1.5.0 + '@jridgewell/trace-mapping': 0.3.31 + + '@jridgewell/gen-mapping@0.3.8': + dependencies: + '@jridgewell/set-array': 1.2.1 + '@jridgewell/sourcemap-codec': 1.5.0 + '@jridgewell/trace-mapping': 0.3.25 + + '@jridgewell/remapping@2.3.5': + dependencies: + '@jridgewell/gen-mapping': 0.3.8 + '@jridgewell/trace-mapping': 0.3.25 + + '@jridgewell/resolve-uri@3.1.2': {} + + '@jridgewell/set-array@1.2.1': {} + + '@jridgewell/sourcemap-codec@1.5.0': {} + + '@jridgewell/sourcemap-codec@1.5.5': {} + + '@jridgewell/trace-mapping@0.3.25': + dependencies: + '@jridgewell/resolve-uri': 3.1.2 + '@jridgewell/sourcemap-codec': 1.5.0 + + '@jridgewell/trace-mapping@0.3.31': + dependencies: + '@jridgewell/resolve-uri': 3.1.2 + '@jridgewell/sourcemap-codec': 1.5.0 + + '@nodelib/fs.scandir@2.1.5': + dependencies: + '@nodelib/fs.stat': 2.0.5 + run-parallel: 1.2.0 + optional: true + + '@nodelib/fs.stat@2.0.5': + optional: true + + '@nodelib/fs.walk@1.2.8': + dependencies: + '@nodelib/fs.scandir': 2.1.5 + fastq: 1.19.1 + optional: true + + '@oxc-project/types@0.142.0': {} + + '@oxfmt/binding-android-arm-eabi@0.62.0': + optional: true + + '@oxfmt/binding-android-arm64@0.62.0': + optional: true + + '@oxfmt/binding-darwin-arm64@0.62.0': + optional: true + + '@oxfmt/binding-darwin-x64@0.62.0': + optional: true + + '@oxfmt/binding-freebsd-x64@0.62.0': + optional: true + + '@oxfmt/binding-linux-arm-gnueabihf@0.62.0': + optional: true + + '@oxfmt/binding-linux-arm-musleabihf@0.62.0': + optional: true + + '@oxfmt/binding-linux-arm64-gnu@0.62.0': + optional: true + + '@oxfmt/binding-linux-arm64-musl@0.62.0': + optional: true + + '@oxfmt/binding-linux-ppc64-gnu@0.62.0': + optional: true + + '@oxfmt/binding-linux-riscv64-gnu@0.62.0': + optional: true + + '@oxfmt/binding-linux-riscv64-musl@0.62.0': + optional: true + + '@oxfmt/binding-linux-s390x-gnu@0.62.0': + optional: true + + '@oxfmt/binding-linux-x64-gnu@0.62.0': + optional: true + + '@oxfmt/binding-linux-x64-musl@0.62.0': + optional: true + + '@oxfmt/binding-openharmony-arm64@0.62.0': + optional: true + + '@oxfmt/binding-win32-arm64-msvc@0.62.0': + optional: true + + '@oxfmt/binding-win32-ia32-msvc@0.62.0': + optional: true + + '@oxfmt/binding-win32-x64-msvc@0.62.0': + optional: true + + '@oxlint/binding-android-arm-eabi@1.77.0': + optional: true + + '@oxlint/binding-android-arm64@1.77.0': + optional: true + + '@oxlint/binding-darwin-arm64@1.77.0': + optional: true + + '@oxlint/binding-darwin-x64@1.77.0': + optional: true + + '@oxlint/binding-freebsd-x64@1.77.0': + optional: true + + '@oxlint/binding-linux-arm-gnueabihf@1.77.0': + optional: true + + '@oxlint/binding-linux-arm-musleabihf@1.77.0': + optional: true + + '@oxlint/binding-linux-arm64-gnu@1.77.0': + optional: true + + '@oxlint/binding-linux-arm64-musl@1.77.0': + optional: true + + '@oxlint/binding-linux-ppc64-gnu@1.77.0': + optional: true + + '@oxlint/binding-linux-riscv64-gnu@1.77.0': + optional: true + + '@oxlint/binding-linux-riscv64-musl@1.77.0': + optional: true + + '@oxlint/binding-linux-s390x-gnu@1.77.0': + optional: true + + '@oxlint/binding-linux-x64-gnu@1.77.0': + optional: true + + '@oxlint/binding-linux-x64-musl@1.77.0': + optional: true + + '@oxlint/binding-openharmony-arm64@1.77.0': + optional: true + + '@oxlint/binding-win32-arm64-msvc@1.77.0': + optional: true + + '@oxlint/binding-win32-ia32-msvc@1.77.0': + optional: true + + '@oxlint/binding-win32-x64-msvc@1.77.0': + optional: true + + '@parcel/watcher-android-arm64@2.5.1': + optional: true + + '@parcel/watcher-darwin-arm64@2.5.1': + optional: true + + '@parcel/watcher-darwin-x64@2.5.1': + optional: true + + '@parcel/watcher-freebsd-x64@2.5.1': + optional: true + + '@parcel/watcher-linux-arm-glibc@2.5.1': + optional: true + + '@parcel/watcher-linux-arm-musl@2.5.1': + optional: true + + '@parcel/watcher-linux-arm64-glibc@2.5.1': + optional: true + + '@parcel/watcher-linux-arm64-musl@2.5.1': + optional: true + + '@parcel/watcher-linux-x64-glibc@2.5.1': + optional: true + + '@parcel/watcher-linux-x64-musl@2.5.1': + optional: true + + '@parcel/watcher-win32-arm64@2.5.1': + optional: true + + '@parcel/watcher-win32-ia32@2.5.1': + optional: true + + '@parcel/watcher-win32-x64@2.5.1': + optional: true + + '@parcel/watcher@2.5.1': + dependencies: + detect-libc: 1.0.3 + is-glob: 4.0.3 + micromatch: 4.0.8 + node-addon-api: 7.1.1 + optionalDependencies: + '@parcel/watcher-android-arm64': 2.5.1 + '@parcel/watcher-darwin-arm64': 2.5.1 + '@parcel/watcher-darwin-x64': 2.5.1 + '@parcel/watcher-freebsd-x64': 2.5.1 + '@parcel/watcher-linux-arm-glibc': 2.5.1 + '@parcel/watcher-linux-arm-musl': 2.5.1 + '@parcel/watcher-linux-arm64-glibc': 2.5.1 + '@parcel/watcher-linux-arm64-musl': 2.5.1 + '@parcel/watcher-linux-x64-glibc': 2.5.1 + '@parcel/watcher-linux-x64-musl': 2.5.1 + '@parcel/watcher-win32-arm64': 2.5.1 + '@parcel/watcher-win32-ia32': 2.5.1 + '@parcel/watcher-win32-x64': 2.5.1 + optional: true + + '@rolldown/binding-android-arm64@1.2.2': + optional: true + + '@rolldown/binding-darwin-arm64@1.2.2': + optional: true + + '@rolldown/binding-darwin-x64@1.2.2': + optional: true + + '@rolldown/binding-freebsd-x64@1.2.2': + optional: true + + '@rolldown/binding-linux-arm-gnueabihf@1.2.2': + optional: true + + '@rolldown/binding-linux-arm64-gnu@1.2.2': + optional: true + + '@rolldown/binding-linux-arm64-musl@1.2.2': + optional: true + + '@rolldown/binding-linux-ppc64-gnu@1.2.2': + optional: true + + '@rolldown/binding-linux-s390x-gnu@1.2.2': + optional: true + + '@rolldown/binding-linux-x64-gnu@1.2.2': + optional: true + + '@rolldown/binding-linux-x64-musl@1.2.2': + optional: true + + '@rolldown/binding-openharmony-arm64@1.2.2': + optional: true + + '@rolldown/binding-win32-arm64-msvc@1.2.2': + optional: true + + '@rolldown/binding-win32-x64-msvc@1.2.2': + optional: true + + '@rolldown/pluginutils@1.0.1': {} + + '@rollup/pluginutils@5.1.4(rollup@4.35.0)': + dependencies: + '@types/estree': 1.0.6 + estree-walker: 2.0.2 + picomatch: 4.0.2 + optionalDependencies: + rollup: 4.35.0 + optional: true + + '@rollup/rollup-android-arm-eabi@4.35.0': + optional: true + + '@rollup/rollup-android-arm64@4.35.0': + optional: true + + '@rollup/rollup-darwin-arm64@4.35.0': + optional: true + + '@rollup/rollup-darwin-x64@4.35.0': + optional: true + + '@rollup/rollup-freebsd-arm64@4.35.0': + optional: true + + '@rollup/rollup-freebsd-x64@4.35.0': + optional: true + + '@rollup/rollup-linux-arm-gnueabihf@4.35.0': + optional: true + + '@rollup/rollup-linux-arm-musleabihf@4.35.0': + optional: true + + '@rollup/rollup-linux-arm64-gnu@4.35.0': + optional: true + + '@rollup/rollup-linux-arm64-musl@4.35.0': + optional: true + + '@rollup/rollup-linux-loongarch64-gnu@4.35.0': + optional: true + + '@rollup/rollup-linux-powerpc64le-gnu@4.35.0': + optional: true + + '@rollup/rollup-linux-riscv64-gnu@4.35.0': + optional: true + + '@rollup/rollup-linux-s390x-gnu@4.35.0': + optional: true + + '@rollup/rollup-linux-x64-gnu@4.35.0': + optional: true + + '@rollup/rollup-linux-x64-musl@4.35.0': + optional: true + + '@rollup/rollup-win32-arm64-msvc@4.35.0': + optional: true + + '@rollup/rollup-win32-ia32-msvc@4.35.0': + optional: true + + '@rollup/rollup-win32-x64-msvc@4.35.0': + optional: true + + '@swc/helpers@0.5.23': + dependencies: + tslib: 2.8.1 + + '@tailwindcss/node@4.3.3': + dependencies: + '@jridgewell/remapping': 2.3.5 + enhanced-resolve: 5.24.5 + jiti: 2.7.0 + lightningcss: 1.32.0 + magic-string: 0.30.21 + source-map-js: 1.2.1 + tailwindcss: 4.3.3 + + '@tailwindcss/oxide-android-arm64@4.3.3': + optional: true + + '@tailwindcss/oxide-darwin-arm64@4.3.3': + optional: true + + '@tailwindcss/oxide-darwin-x64@4.3.3': + optional: true + + '@tailwindcss/oxide-freebsd-x64@4.3.3': + optional: true + + '@tailwindcss/oxide-linux-arm-gnueabihf@4.3.3': + optional: true + + '@tailwindcss/oxide-linux-arm64-gnu@4.3.3': + optional: true + + '@tailwindcss/oxide-linux-arm64-musl@4.3.3': + optional: true + + '@tailwindcss/oxide-linux-x64-gnu@4.3.3': + optional: true + + '@tailwindcss/oxide-linux-x64-musl@4.3.3': + optional: true + + '@tailwindcss/oxide-wasm32-wasi@4.3.3': + optional: true + + '@tailwindcss/oxide-win32-arm64-msvc@4.3.3': + optional: true + + '@tailwindcss/oxide-win32-x64-msvc@4.3.3': + optional: true + + '@tailwindcss/oxide@4.3.3': + optionalDependencies: + '@tailwindcss/oxide-android-arm64': 4.3.3 + '@tailwindcss/oxide-darwin-arm64': 4.3.3 + '@tailwindcss/oxide-darwin-x64': 4.3.3 + '@tailwindcss/oxide-freebsd-x64': 4.3.3 + '@tailwindcss/oxide-linux-arm-gnueabihf': 4.3.3 + '@tailwindcss/oxide-linux-arm64-gnu': 4.3.3 + '@tailwindcss/oxide-linux-arm64-musl': 4.3.3 + '@tailwindcss/oxide-linux-x64-gnu': 4.3.3 + '@tailwindcss/oxide-linux-x64-musl': 4.3.3 + '@tailwindcss/oxide-wasm32-wasi': 4.3.3 + '@tailwindcss/oxide-win32-arm64-msvc': 4.3.3 + '@tailwindcss/oxide-win32-x64-msvc': 4.3.3 + + '@tailwindcss/vite@4.3.3(vite@8.2.0(@types/node@26.1.2)(jiti@2.7.0)(sass@1.102.0)(yaml@2.9.0))': + dependencies: + '@tailwindcss/node': 4.3.3 + '@tailwindcss/oxide': 4.3.3 + tailwindcss: 4.3.3 + vite: 8.2.0(@types/node@26.1.2)(jiti@2.7.0)(sass@1.102.0)(yaml@2.9.0) + + '@tanstack/virtual-core@3.17.7': {} + + '@tanstack/vue-virtual@3.13.35(vue@3.5.40(typescript@6.0.3))': + dependencies: + '@tanstack/virtual-core': 3.17.7 + vue: 3.5.40(typescript@6.0.3) + + '@tsconfig/node24@24.0.4': {} + + '@types/estree@1.0.6': {} + + '@types/jsesc@2.5.1': {} + + '@types/node@26.1.2': + dependencies: + undici-types: 8.3.0 + + '@types/pako@2.0.3': {} + + '@types/web-bluetooth@0.0.15': {} + + '@types/web-bluetooth@0.0.21': {} + + '@vitejs/plugin-vue-jsx@5.1.6(vite@8.2.0(@types/node@26.1.2)(jiti@2.7.0)(sass@1.102.0)(yaml@2.9.0))(vue@3.5.40(typescript@6.0.3))': + dependencies: + '@babel/core': 7.29.7 + '@babel/plugin-syntax-typescript': 7.29.7(@babel/core@7.29.7) + '@babel/plugin-transform-typescript': 7.29.7(@babel/core@7.29.7) + '@rolldown/pluginutils': 1.0.1 + '@vue/babel-plugin-jsx': 2.0.1(@babel/core@7.29.7) + vite: 8.2.0(@types/node@26.1.2)(jiti@2.7.0)(sass@1.102.0)(yaml@2.9.0) + vue: 3.5.40(typescript@6.0.3) + transitivePeerDependencies: + - supports-color + + '@vitejs/plugin-vue@6.0.8(vite@8.2.0(@types/node@26.1.2)(jiti@2.7.0)(sass@1.102.0)(yaml@2.9.0))(vue@3.5.40(typescript@6.0.3))': + dependencies: + '@rolldown/pluginutils': 1.0.1 + vite: 8.2.0(@types/node@26.1.2)(jiti@2.7.0)(sass@1.102.0)(yaml@2.9.0) + vue: 3.5.40(typescript@6.0.3) + + '@volar/language-core@2.4.28': + dependencies: + '@volar/source-map': 2.4.28 + + '@volar/source-map@2.4.28': {} + + '@volar/typescript@2.4.28': + dependencies: + '@volar/language-core': 2.4.28 + path-browserify: 1.0.1 + vscode-uri: 3.1.0 + + '@vue-macros/common@3.1.4(vue@3.5.40(typescript@6.0.3))': + dependencies: + '@vue/compiler-sfc': 3.5.40 + ast-kit: 2.2.0 + local-pkg: 1.2.1 + magic-string-ast: 1.0.3 + unplugin-utils: 0.3.2 + optionalDependencies: + vue: 3.5.40(typescript@6.0.3) + + '@vue/babel-helper-vue-transform-on@2.0.1': {} + + '@vue/babel-plugin-jsx@2.0.1(@babel/core@7.29.7)': + dependencies: + '@babel/helper-module-imports': 7.29.7 + '@babel/helper-plugin-utils': 7.29.7 + '@babel/plugin-syntax-jsx': 7.29.7(@babel/core@7.29.7) + '@babel/template': 7.29.7 + '@babel/traverse': 7.29.8 + '@babel/types': 7.29.8 + '@vue/babel-helper-vue-transform-on': 2.0.1 + '@vue/babel-plugin-resolve-type': 2.0.1(@babel/core@7.29.7) + '@vue/shared': 3.5.40 + optionalDependencies: + '@babel/core': 7.29.7 + transitivePeerDependencies: + - supports-color + + '@vue/babel-plugin-resolve-type@2.0.1(@babel/core@7.29.7)': + dependencies: + '@babel/code-frame': 7.29.7 + '@babel/core': 7.29.7 + '@babel/helper-module-imports': 7.29.7 + '@babel/helper-plugin-utils': 7.29.7 + '@babel/parser': 7.29.8 + '@vue/compiler-sfc': 3.5.40 + transitivePeerDependencies: + - supports-color + + '@vue/compiler-core@3.5.13': + dependencies: + '@babel/parser': 7.26.9 + '@vue/shared': 3.5.13 + entities: 4.5.0 + estree-walker: 2.0.2 + source-map-js: 1.2.1 + + '@vue/compiler-core@3.5.40': + dependencies: + '@babel/parser': 7.29.8 + '@vue/shared': 3.5.40 + entities: 7.0.1 + estree-walker: 2.0.2 + source-map-js: 1.2.1 + + '@vue/compiler-dom@3.5.13': + dependencies: + '@vue/compiler-core': 3.5.13 + '@vue/shared': 3.5.13 + + '@vue/compiler-dom@3.5.40': + dependencies: + '@vue/compiler-core': 3.5.40 + '@vue/shared': 3.5.40 + + '@vue/compiler-sfc@3.5.40': + dependencies: + '@babel/parser': 7.29.8 + '@vue/compiler-core': 3.5.40 + '@vue/compiler-dom': 3.5.40 + '@vue/compiler-ssr': 3.5.40 + '@vue/shared': 3.5.40 + estree-walker: 2.0.2 + magic-string: 0.30.21 + postcss: 8.5.25 + source-map-js: 1.2.1 + + '@vue/compiler-ssr@3.5.40': + dependencies: + '@vue/compiler-dom': 3.5.40 + '@vue/shared': 3.5.40 + + '@vue/devtools-api@8.2.1': + dependencies: + '@vue/devtools-kit': 8.2.1 + + '@vue/devtools-kit@8.2.1': + dependencies: + '@vue/devtools-shared': 8.2.1 + birpc: 2.9.0 + hookable: 5.5.3 + perfect-debounce: 2.1.0 + + '@vue/devtools-shared@8.2.1': {} + + '@vue/language-core@3.3.9': + dependencies: + '@volar/language-core': 2.4.28 + '@vue/compiler-dom': 3.5.13 + '@vue/shared': 3.5.13 + alien-signals: 3.2.1 + muggle-string: 0.4.1 + path-browserify: 1.0.1 + picomatch: 4.0.5 + + '@vue/reactivity@3.5.40': + dependencies: + '@vue/shared': 3.5.40 + + '@vue/runtime-core@3.5.40': + dependencies: + '@vue/reactivity': 3.5.40 + '@vue/shared': 3.5.40 + + '@vue/runtime-dom@3.5.40': + dependencies: + '@vue/reactivity': 3.5.40 + '@vue/runtime-core': 3.5.40 + '@vue/shared': 3.5.40 + csstype: 3.2.3 + + '@vue/server-renderer@3.5.40': + dependencies: + '@vue/compiler-ssr': 3.5.40 + '@vue/runtime-dom': 3.5.40 + '@vue/shared': 3.5.40 + + '@vue/shared@3.5.13': {} + + '@vue/shared@3.5.40': {} + + '@vue/tsconfig@0.9.1(typescript@6.0.3)(vue@3.5.40(typescript@6.0.3))': + optionalDependencies: + typescript: 6.0.3 + vue: 3.5.40(typescript@6.0.3) + + '@vueuse/core@14.4.0(vue@3.5.40(typescript@6.0.3))': + dependencies: + '@types/web-bluetooth': 0.0.21 + '@vueuse/metadata': 14.4.0 + '@vueuse/shared': 14.4.0(vue@3.5.40(typescript@6.0.3)) + vue: 3.5.40(typescript@6.0.3) + + '@vueuse/core@9.0.0(vue@3.5.40(typescript@6.0.3))': + dependencies: + '@types/web-bluetooth': 0.0.15 + '@vueuse/metadata': 9.0.0 + '@vueuse/shared': 9.0.0(vue@3.5.40(typescript@6.0.3)) + vue-demi: 0.14.10(vue@3.5.40(typescript@6.0.3)) + transitivePeerDependencies: + - '@vue/composition-api' + - vue + + '@vueuse/metadata@14.4.0': {} + + '@vueuse/metadata@9.0.0': {} + + '@vueuse/shared@14.4.0(vue@3.5.40(typescript@6.0.3))': + dependencies: + vue: 3.5.40(typescript@6.0.3) + + '@vueuse/shared@9.0.0(vue@3.5.40(typescript@6.0.3))': + dependencies: + vue-demi: 0.14.10(vue@3.5.40(typescript@6.0.3)) + transitivePeerDependencies: + - '@vue/composition-api' + - vue + + acorn@8.14.1: {} + + acorn@8.18.0: {} + + alien-signals@3.2.1: {} + + ansi-styles@7.0.0: {} + + anymatch@3.1.3: + dependencies: + normalize-path: 3.0.0 + picomatch: 2.3.1 + optional: true + + aria-hidden@1.2.6: + dependencies: + tslib: 2.8.1 + + ast-kit@2.2.0: + dependencies: + '@babel/parser': 7.29.8 + pathe: 2.0.3 + + ast-walker-scope@0.9.0: + dependencies: + '@babel/parser': 7.29.8 + '@babel/types': 7.29.8 + ast-kit: 2.2.0 + + asynckit@0.4.0: {} + + axios@1.8.2: + dependencies: + follow-redirects: 1.15.9 + form-data: 4.0.2 + proxy-from-env: 1.1.0 + transitivePeerDependencies: + - debug + + balanced-match@1.0.2: + optional: true + + binary-extensions@2.3.0: + optional: true + + birpc@2.9.0: {} + + brace-expansion@2.0.1: + dependencies: + balanced-match: 1.0.2 + optional: true + + braces@3.0.3: + dependencies: + fill-range: 7.1.1 + optional: true + + browserslist@4.24.4: + dependencies: + caniuse-lite: 1.0.30001702 + electron-to-chromium: 1.5.113 + node-releases: 2.0.19 + update-browserslist-db: 1.1.3(browserslist@4.24.4) + + call-bind-apply-helpers@1.0.2: + dependencies: + es-errors: 1.3.0 + function-bind: 1.1.2 + + caniuse-lite@1.0.30001702: {} + + chokidar@3.6.0: + dependencies: + anymatch: 3.1.3 + braces: 3.0.3 + glob-parent: 5.1.2 + is-binary-path: 2.1.0 + is-glob: 4.0.3 + normalize-path: 3.0.0 + readdirp: 3.6.0 + optionalDependencies: + fsevents: 2.3.3 + optional: true + + chokidar@5.0.0: + dependencies: + readdirp: 5.0.0 + + class-variance-authority@0.7.1: + dependencies: + clsx: 2.1.1 + + clsx@2.1.1: {} + + combined-stream@1.0.8: + dependencies: + delayed-stream: 1.0.0 + + confbox@0.1.8: {} + + confbox@0.2.4: {} + + convert-source-map@2.0.0: {} + + cross-spawn@7.0.6: + dependencies: + path-key: 3.1.1 + shebang-command: 2.0.0 + which: 2.0.2 + + csstype@3.1.3: {} + + csstype@3.2.3: {} + + debug@4.4.0: + dependencies: + ms: 2.1.3 + + decode-uri-component@0.4.1: {} + + defu@6.1.4: {} + + defu@6.1.7: {} + + delayed-stream@1.0.0: {} + + detect-libc@1.0.3: + optional: true + + detect-libc@2.1.2: {} + + dunder-proto@1.0.1: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-errors: 1.3.0 + gopd: 1.2.0 + + electron-to-chromium@1.5.113: {} + + enhanced-resolve@5.24.5: + dependencies: + graceful-fs: 4.2.11 + tapable: 2.3.3 + + entities@4.5.0: {} + + entities@7.0.1: {} + + es-define-property@1.0.1: {} + + es-errors@1.3.0: {} + + es-object-atoms@1.1.1: + dependencies: + es-errors: 1.3.0 + + es-set-tostringtag@2.1.0: + dependencies: + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + has-tostringtag: 1.0.2 + hasown: 2.0.2 + + escalade@3.2.0: {} + + escape-string-regexp@5.0.0: {} + + estree-walker@2.0.2: {} + + estree-walker@3.0.3: + dependencies: + '@types/estree': 1.0.6 + + exsolve@1.1.1: {} + + fast-glob@3.3.3: + dependencies: + '@nodelib/fs.stat': 2.0.5 + '@nodelib/fs.walk': 1.2.8 + glob-parent: 5.1.2 + merge2: 1.4.1 + micromatch: 4.0.8 + optional: true + + fastq@1.19.1: + dependencies: + reusify: 1.1.0 + optional: true + + fdir@6.5.0(picomatch@4.0.5): + optionalDependencies: + picomatch: 4.0.5 + + fill-range@7.1.1: + dependencies: + to-regex-range: 5.0.1 + optional: true + + filter-obj@5.1.0: {} + + follow-redirects@1.15.9: {} + + form-data@4.0.2: + dependencies: + asynckit: 0.4.0 + combined-stream: 1.0.8 + es-set-tostringtag: 2.1.0 + mime-types: 2.1.35 + + fsevents@2.3.3: + optional: true + + function-bind@1.1.2: {} + + gensync@1.0.0-beta.2: {} + + get-intrinsic@1.3.0: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-define-property: 1.0.1 + es-errors: 1.3.0 + es-object-atoms: 1.1.1 + function-bind: 1.1.2 + get-proto: 1.0.1 + gopd: 1.2.0 + has-symbols: 1.1.0 + hasown: 2.0.2 + math-intrinsics: 1.1.0 + + get-proto@1.0.1: + dependencies: + dunder-proto: 1.0.1 + es-object-atoms: 1.1.1 + + glob-parent@5.1.2: + dependencies: + is-glob: 4.0.3 + optional: true + + gopd@1.2.0: {} + + graceful-fs@4.2.11: {} + + has-symbols@1.1.0: {} + + has-tostringtag@1.0.2: + dependencies: + has-symbols: 1.1.0 + + hasown@2.0.2: + dependencies: + function-bind: 1.1.2 + + hoci@0.6.0(@babel/parser@7.29.8)(@vueuse/core@14.4.0(vue@3.5.40(typescript@6.0.3)))(rollup@4.35.0)(vue@3.5.40(typescript@6.0.3)): + dependencies: + '@hoci/components': 0.6.0(@vueuse/core@14.4.0(vue@3.5.40(typescript@6.0.3)))(vue@3.5.40(typescript@6.0.3)) + '@hoci/core': 0.6.0(vue@3.5.40(typescript@6.0.3)) + vue: 3.5.40(typescript@6.0.3) + optionalDependencies: + unplugin-vue-components: 0.27.5(@babel/parser@7.29.8)(rollup@4.35.0)(vue@3.5.40(typescript@6.0.3)) + transitivePeerDependencies: + - '@babel/parser' + - '@nuxt/kit' + - '@vue/composition-api' + - '@vueuse/core' + - rollup + - supports-color + + hookable@5.5.3: {} + + immutable@5.1.9: {} + + is-binary-path@2.1.0: + dependencies: + binary-extensions: 2.3.0 + optional: true + + is-extglob@2.1.1: + optional: true + + is-glob@4.0.3: + dependencies: + is-extglob: 2.1.1 + optional: true + + is-number@7.0.0: + optional: true + + isexe@2.0.0: {} + + isexe@4.0.0: {} + + jiti@2.7.0: {} + + js-tokens@10.0.0: {} + + js-tokens@4.0.0: {} + + jsesc@3.1.0: {} + + json-parse-even-better-errors@6.0.0: {} + + json5@2.2.3: {} + + lightningcss-android-arm64@1.32.0: + optional: true + + lightningcss-android-arm64@1.33.0: + optional: true + + lightningcss-darwin-arm64@1.32.0: + optional: true + + lightningcss-darwin-arm64@1.33.0: + optional: true + + lightningcss-darwin-x64@1.32.0: + optional: true + + lightningcss-darwin-x64@1.33.0: + optional: true + + lightningcss-freebsd-x64@1.32.0: + optional: true + + lightningcss-freebsd-x64@1.33.0: + optional: true + + lightningcss-linux-arm-gnueabihf@1.32.0: + optional: true + + lightningcss-linux-arm-gnueabihf@1.33.0: + optional: true + + lightningcss-linux-arm64-gnu@1.32.0: + optional: true + + lightningcss-linux-arm64-gnu@1.33.0: + optional: true + + lightningcss-linux-arm64-musl@1.32.0: + optional: true + + lightningcss-linux-arm64-musl@1.33.0: + optional: true + + lightningcss-linux-x64-gnu@1.32.0: + optional: true + + lightningcss-linux-x64-gnu@1.33.0: + optional: true + + lightningcss-linux-x64-musl@1.32.0: + optional: true + + lightningcss-linux-x64-musl@1.33.0: + optional: true + + lightningcss-win32-arm64-msvc@1.32.0: + optional: true + + lightningcss-win32-arm64-msvc@1.33.0: + optional: true + + lightningcss-win32-x64-msvc@1.32.0: + optional: true + + lightningcss-win32-x64-msvc@1.33.0: + optional: true + + lightningcss@1.32.0: + dependencies: + detect-libc: 2.1.2 + optionalDependencies: + lightningcss-android-arm64: 1.32.0 + lightningcss-darwin-arm64: 1.32.0 + lightningcss-darwin-x64: 1.32.0 + lightningcss-freebsd-x64: 1.32.0 + lightningcss-linux-arm-gnueabihf: 1.32.0 + lightningcss-linux-arm64-gnu: 1.32.0 + lightningcss-linux-arm64-musl: 1.32.0 + lightningcss-linux-x64-gnu: 1.32.0 + lightningcss-linux-x64-musl: 1.32.0 + lightningcss-win32-arm64-msvc: 1.32.0 + lightningcss-win32-x64-msvc: 1.32.0 + + lightningcss@1.33.0: + dependencies: + detect-libc: 2.1.2 + optionalDependencies: + lightningcss-android-arm64: 1.33.0 + lightningcss-darwin-arm64: 1.33.0 + lightningcss-darwin-x64: 1.33.0 + lightningcss-freebsd-x64: 1.33.0 + lightningcss-linux-arm-gnueabihf: 1.33.0 + lightningcss-linux-arm64-gnu: 1.33.0 + lightningcss-linux-arm64-musl: 1.33.0 + lightningcss-linux-x64-gnu: 1.33.0 + lightningcss-linux-x64-musl: 1.33.0 + lightningcss-win32-arm64-msvc: 1.33.0 + lightningcss-win32-x64-msvc: 1.33.0 + + local-pkg@0.5.1: + dependencies: + mlly: 1.7.4 + pkg-types: 1.3.1 + optional: true + + local-pkg@1.2.1: + dependencies: + mlly: 1.7.4 + pkg-types: 2.3.1 + quansync: 0.2.11 + + lru-cache@5.1.1: + dependencies: + yallist: 3.1.1 + + magic-string-ast@1.0.3: + dependencies: + magic-string: 0.30.21 + + magic-string@0.30.17: + dependencies: + '@jridgewell/sourcemap-codec': 1.5.0 + optional: true + + magic-string@0.30.21: + dependencies: + '@jridgewell/sourcemap-codec': 1.5.5 + + magic-string@1.1.0: + dependencies: + '@jridgewell/sourcemap-codec': 1.5.5 + + math-intrinsics@1.1.0: {} + + maybe-types@0.2.0: {} + + memorystream@0.3.1: {} + + merge2@1.4.1: + optional: true + + micromatch@4.0.8: + dependencies: + braces: 3.0.3 + picomatch: 2.3.1 + optional: true + + mime-db@1.52.0: {} + + mime-types@2.1.35: + dependencies: + mime-db: 1.52.0 + + minimatch@9.0.5: + dependencies: + brace-expansion: 2.0.1 + optional: true + + mlly@1.7.4: + dependencies: + acorn: 8.14.1 + pathe: 2.0.3 + pkg-types: 1.3.1 + ufo: 1.5.4 + + mlly@1.8.2: + dependencies: + acorn: 8.18.0 + pathe: 2.0.3 + pkg-types: 1.3.1 + ufo: 1.6.4 + + ms@2.1.3: {} + + muggle-string@0.4.1: {} + + nanoid@3.3.17: {} + + node-addon-api@7.1.1: + optional: true + + node-releases@2.0.19: {} + + normalize-path@3.0.0: + optional: true + + nostics@1.2.0: {} + + npm-normalize-package-bin@6.0.0: {} + + npm-run-all2@9.0.3: + dependencies: + ansi-styles: 7.0.0 + cross-spawn: 7.0.6 + memorystream: 0.3.1 + picomatch: 4.0.2 + pidtree: 1.0.0 + read-package-json-fast: 6.0.0 + shell-quote: 1.10.0 + which: 7.0.0 + + obug@2.1.4: {} + + ohash@2.0.11: {} + + oxfmt@0.62.0: + dependencies: + tinypool: 2.1.0 + optionalDependencies: + '@oxfmt/binding-android-arm-eabi': 0.62.0 + '@oxfmt/binding-android-arm64': 0.62.0 + '@oxfmt/binding-darwin-arm64': 0.62.0 + '@oxfmt/binding-darwin-x64': 0.62.0 + '@oxfmt/binding-freebsd-x64': 0.62.0 + '@oxfmt/binding-linux-arm-gnueabihf': 0.62.0 + '@oxfmt/binding-linux-arm-musleabihf': 0.62.0 + '@oxfmt/binding-linux-arm64-gnu': 0.62.0 + '@oxfmt/binding-linux-arm64-musl': 0.62.0 + '@oxfmt/binding-linux-ppc64-gnu': 0.62.0 + '@oxfmt/binding-linux-riscv64-gnu': 0.62.0 + '@oxfmt/binding-linux-riscv64-musl': 0.62.0 + '@oxfmt/binding-linux-s390x-gnu': 0.62.0 + '@oxfmt/binding-linux-x64-gnu': 0.62.0 + '@oxfmt/binding-linux-x64-musl': 0.62.0 + '@oxfmt/binding-openharmony-arm64': 0.62.0 + '@oxfmt/binding-win32-arm64-msvc': 0.62.0 + '@oxfmt/binding-win32-ia32-msvc': 0.62.0 + '@oxfmt/binding-win32-x64-msvc': 0.62.0 + + oxlint@1.77.0: + optionalDependencies: + '@oxlint/binding-android-arm-eabi': 1.77.0 + '@oxlint/binding-android-arm64': 1.77.0 + '@oxlint/binding-darwin-arm64': 1.77.0 + '@oxlint/binding-darwin-x64': 1.77.0 + '@oxlint/binding-freebsd-x64': 1.77.0 + '@oxlint/binding-linux-arm-gnueabihf': 1.77.0 + '@oxlint/binding-linux-arm-musleabihf': 1.77.0 + '@oxlint/binding-linux-arm64-gnu': 1.77.0 + '@oxlint/binding-linux-arm64-musl': 1.77.0 + '@oxlint/binding-linux-ppc64-gnu': 1.77.0 + '@oxlint/binding-linux-riscv64-gnu': 1.77.0 + '@oxlint/binding-linux-riscv64-musl': 1.77.0 + '@oxlint/binding-linux-s390x-gnu': 1.77.0 + '@oxlint/binding-linux-x64-gnu': 1.77.0 + '@oxlint/binding-linux-x64-musl': 1.77.0 + '@oxlint/binding-openharmony-arm64': 1.77.0 + '@oxlint/binding-win32-arm64-msvc': 1.77.0 + '@oxlint/binding-win32-ia32-msvc': 1.77.0 + '@oxlint/binding-win32-x64-msvc': 1.77.0 + + pako@2.1.0: {} + + path-browserify@1.0.1: {} + + path-key@3.1.1: {} + + pathe@2.0.3: {} + + perfect-debounce@2.1.0: {} + + picocolors@1.1.1: {} + + picomatch@2.3.1: + optional: true + + picomatch@4.0.2: {} + + picomatch@4.0.5: {} + + pidtree@1.0.0: {} + + pinia@4.0.2(@vue/devtools-api@8.2.1)(typescript@6.0.3)(vue@3.5.40(typescript@6.0.3)): + dependencies: + '@vue/devtools-api': 8.2.1 + nostics: 1.2.0 + vue: 3.5.40(typescript@6.0.3) + optionalDependencies: + typescript: 6.0.3 + + pkg-types@1.3.1: + dependencies: + confbox: 0.1.8 + mlly: 1.7.4 + pathe: 2.0.3 + + pkg-types@2.3.1: + dependencies: + confbox: 0.2.4 + exsolve: 1.1.1 + pathe: 2.0.3 + + postcss@8.5.25: + dependencies: + nanoid: 3.3.17 + picocolors: 1.1.1 + source-map-js: 1.2.1 + + proxy-from-env@1.1.0: {} + + quansync@0.2.11: {} + + query-string@9.1.1: + dependencies: + decode-uri-component: 0.4.1 + filter-obj: 5.1.0 + split-on-first: 3.0.0 + + queue-microtask@1.2.3: + optional: true + + read-package-json-fast@6.0.0: + dependencies: + json-parse-even-better-errors: 6.0.0 + npm-normalize-package-bin: 6.0.0 + + readdirp@3.6.0: + dependencies: + picomatch: 2.3.1 + optional: true + + readdirp@5.0.0: {} + + reka-ui@2.10.1(vue@3.5.40(typescript@6.0.3)): + dependencies: + '@floating-ui/dom': 1.8.0 + '@floating-ui/vue': 1.1.11(vue@3.5.40(typescript@6.0.3)) + '@internationalized/date': 3.12.3 + '@internationalized/number': 3.6.7 + '@tanstack/vue-virtual': 3.13.35(vue@3.5.40(typescript@6.0.3)) + '@vueuse/core': 14.4.0(vue@3.5.40(typescript@6.0.3)) + '@vueuse/shared': 14.4.0(vue@3.5.40(typescript@6.0.3)) + aria-hidden: 1.2.6 + defu: 6.1.7 + ohash: 2.0.11 + vue: 3.5.40(typescript@6.0.3) + transitivePeerDependencies: + - '@vue/composition-api' + + reusify@1.1.0: + optional: true + + rolldown@1.2.2: + dependencies: + '@oxc-project/types': 0.142.0 + '@rolldown/pluginutils': 1.0.1 + optionalDependencies: + '@rolldown/binding-android-arm64': 1.2.2 + '@rolldown/binding-darwin-arm64': 1.2.2 + '@rolldown/binding-darwin-x64': 1.2.2 + '@rolldown/binding-freebsd-x64': 1.2.2 + '@rolldown/binding-linux-arm-gnueabihf': 1.2.2 + '@rolldown/binding-linux-arm64-gnu': 1.2.2 + '@rolldown/binding-linux-arm64-musl': 1.2.2 + '@rolldown/binding-linux-ppc64-gnu': 1.2.2 + '@rolldown/binding-linux-s390x-gnu': 1.2.2 + '@rolldown/binding-linux-x64-gnu': 1.2.2 + '@rolldown/binding-linux-x64-musl': 1.2.2 + '@rolldown/binding-openharmony-arm64': 1.2.2 + '@rolldown/binding-win32-arm64-msvc': 1.2.2 + '@rolldown/binding-win32-x64-msvc': 1.2.2 + + rollup@4.35.0: + dependencies: + '@types/estree': 1.0.6 + optionalDependencies: + '@rollup/rollup-android-arm-eabi': 4.35.0 + '@rollup/rollup-android-arm64': 4.35.0 + '@rollup/rollup-darwin-arm64': 4.35.0 + '@rollup/rollup-darwin-x64': 4.35.0 + '@rollup/rollup-freebsd-arm64': 4.35.0 + '@rollup/rollup-freebsd-x64': 4.35.0 + '@rollup/rollup-linux-arm-gnueabihf': 4.35.0 + '@rollup/rollup-linux-arm-musleabihf': 4.35.0 + '@rollup/rollup-linux-arm64-gnu': 4.35.0 + '@rollup/rollup-linux-arm64-musl': 4.35.0 + '@rollup/rollup-linux-loongarch64-gnu': 4.35.0 + '@rollup/rollup-linux-powerpc64le-gnu': 4.35.0 + '@rollup/rollup-linux-riscv64-gnu': 4.35.0 + '@rollup/rollup-linux-s390x-gnu': 4.35.0 + '@rollup/rollup-linux-x64-gnu': 4.35.0 + '@rollup/rollup-linux-x64-musl': 4.35.0 + '@rollup/rollup-win32-arm64-msvc': 4.35.0 + '@rollup/rollup-win32-ia32-msvc': 4.35.0 + '@rollup/rollup-win32-x64-msvc': 4.35.0 + fsevents: 2.3.3 + optional: true + + run-parallel@1.2.0: + dependencies: + queue-microtask: 1.2.3 + optional: true + + sass@1.102.0: + dependencies: + chokidar: 5.0.0 + immutable: 5.1.9 + source-map-js: 1.2.1 + optionalDependencies: + '@parcel/watcher': 2.5.1 + + scule@1.3.0: {} + + semver@6.3.1: {} + + shebang-command@2.0.0: + dependencies: + shebang-regex: 3.0.0 + + shebang-regex@3.0.0: {} + + shell-quote@1.10.0: {} + + source-map-js@1.2.1: {} + + split-on-first@3.0.0: {} + + strip-literal@4.0.0: + dependencies: + js-tokens: 10.0.0 + + tailwind-merge@3.6.0: {} + + tailwindcss@4.3.3: {} + + tapable@2.3.3: {} + + tinyglobby@0.2.17: + dependencies: + fdir: 6.5.0(picomatch@4.0.5) + picomatch: 4.0.5 + + tinypool@2.1.0: {} + + to-regex-range@5.0.1: + dependencies: + is-number: 7.0.0 + optional: true + + tslib@2.8.1: {} + + tslx@0.1.1: + dependencies: + csstype: 3.1.3 + + type-fest@4.38.0: {} + + typescript@6.0.3: {} + + ufo@1.5.4: {} + + ufo@1.6.4: {} + + undici-types@8.3.0: {} + + unimport@6.4.0(rolldown@1.2.2)(rollup@4.35.0)(vite@8.2.0(@types/node@26.1.2)(jiti@2.7.0)(sass@1.102.0)(yaml@2.9.0)): + dependencies: + acorn: 8.18.0 + escape-string-regexp: 5.0.0 + estree-walker: 3.0.3 + local-pkg: 1.2.1 + magic-string: 1.1.0 + mlly: 1.8.2 + pathe: 2.0.3 + picomatch: 4.0.5 + pkg-types: 2.3.1 + scule: 1.3.0 + strip-literal: 4.0.0 + tinyglobby: 0.2.17 + unplugin: 3.3.0(rolldown@1.2.2)(rollup@4.35.0)(vite@8.2.0(@types/node@26.1.2)(jiti@2.7.0)(sass@1.102.0)(yaml@2.9.0)) + unplugin-utils: 0.3.2 + optionalDependencies: + rolldown: 1.2.2 + transitivePeerDependencies: + - '@farmfe/core' + - '@rspack/core' + - bun-types-no-globals + - esbuild + - rollup + - unloader + - vite + - webpack + + unplugin-auto-import@21.1.0(@vueuse/core@14.4.0(vue@3.5.40(typescript@6.0.3)))(rolldown@1.2.2)(rollup@4.35.0)(vite@8.2.0(@types/node@26.1.2)(jiti@2.7.0)(sass@1.102.0)(yaml@2.9.0)): + dependencies: + local-pkg: 1.2.1 + magic-string: 1.1.0 + picomatch: 4.0.5 + unimport: 6.4.0(rolldown@1.2.2)(rollup@4.35.0)(vite@8.2.0(@types/node@26.1.2)(jiti@2.7.0)(sass@1.102.0)(yaml@2.9.0)) + unplugin: 3.3.0(rolldown@1.2.2)(rollup@4.35.0)(vite@8.2.0(@types/node@26.1.2)(jiti@2.7.0)(sass@1.102.0)(yaml@2.9.0)) + unplugin-utils: 0.3.2 + optionalDependencies: + '@vueuse/core': 14.4.0(vue@3.5.40(typescript@6.0.3)) + transitivePeerDependencies: + - '@farmfe/core' + - '@rspack/core' + - bun-types-no-globals + - esbuild + - oxc-parser + - rolldown + - rollup + - unloader + - vite + - webpack + + unplugin-utils@0.3.2: + dependencies: + pathe: 2.0.3 + picomatch: 4.0.5 + + unplugin-vue-components@0.27.5(@babel/parser@7.29.8)(rollup@4.35.0)(vue@3.5.40(typescript@6.0.3)): + dependencies: + '@antfu/utils': 0.7.10 + '@rollup/pluginutils': 5.1.4(rollup@4.35.0) + chokidar: 3.6.0 + debug: 4.4.0 + fast-glob: 3.3.3 + local-pkg: 0.5.1 + magic-string: 0.30.17 + minimatch: 9.0.5 + mlly: 1.7.4 + unplugin: 1.16.1 + vue: 3.5.40(typescript@6.0.3) + optionalDependencies: + '@babel/parser': 7.29.8 + transitivePeerDependencies: + - rollup + - supports-color + optional: true + + unplugin-vue-components@32.1.0(rolldown@1.2.2)(rollup@4.35.0)(vite@8.2.0(@types/node@26.1.2)(jiti@2.7.0)(sass@1.102.0)(yaml@2.9.0))(vue@3.5.40(typescript@6.0.3)): + dependencies: + chokidar: 5.0.0 + local-pkg: 1.2.1 + magic-string: 0.30.21 + mlly: 1.8.2 + obug: 2.1.4 + picomatch: 4.0.5 + tinyglobby: 0.2.17 + unplugin: 3.3.0(rolldown@1.2.2)(rollup@4.35.0)(vite@8.2.0(@types/node@26.1.2)(jiti@2.7.0)(sass@1.102.0)(yaml@2.9.0)) + unplugin-utils: 0.3.2 + vue: 3.5.40(typescript@6.0.3) + transitivePeerDependencies: + - '@farmfe/core' + - '@rspack/core' + - bun-types-no-globals + - esbuild + - rolldown + - rollup + - unloader + - vite + - webpack + + unplugin@1.16.1: + dependencies: + acorn: 8.14.1 + webpack-virtual-modules: 0.6.2 + optional: true + + unplugin@3.3.0(rolldown@1.2.2)(rollup@4.35.0)(vite@8.2.0(@types/node@26.1.2)(jiti@2.7.0)(sass@1.102.0)(yaml@2.9.0)): + dependencies: + '@jridgewell/remapping': 2.3.5 + picomatch: 4.0.5 + webpack-virtual-modules: 0.6.2 + optionalDependencies: + rolldown: 1.2.2 + rollup: 4.35.0 + vite: 8.2.0(@types/node@26.1.2)(jiti@2.7.0)(sass@1.102.0)(yaml@2.9.0) + + update-browserslist-db@1.1.3(browserslist@4.24.4): + dependencies: + browserslist: 4.24.4 + escalade: 3.2.0 + picocolors: 1.1.1 + + vite@8.2.0(@types/node@26.1.2)(jiti@2.7.0)(sass@1.102.0)(yaml@2.9.0): + dependencies: + lightningcss: 1.33.0 + picomatch: 4.0.5 + postcss: 8.5.25 + rolldown: 1.2.2 + tinyglobby: 0.2.17 + optionalDependencies: + '@types/node': 26.1.2 + fsevents: 2.3.3 + jiti: 2.7.0 + sass: 1.102.0 + yaml: 2.9.0 + + vscode-uri@3.1.0: {} + + vue-demi@0.14.10(vue@3.5.40(typescript@6.0.3)): + dependencies: + vue: 3.5.40(typescript@6.0.3) + + vue-router@5.2.0(@vue/compiler-sfc@3.5.40)(pinia@4.0.2(@vue/devtools-api@8.2.1)(typescript@6.0.3)(vue@3.5.40(typescript@6.0.3)))(rolldown@1.2.2)(rollup@4.35.0)(vite@8.2.0(@types/node@26.1.2)(jiti@2.7.0)(sass@1.102.0)(yaml@2.9.0))(vue@3.5.40(typescript@6.0.3)): + dependencies: + '@babel/generator': 8.0.0 + '@vue-macros/common': 3.1.4(vue@3.5.40(typescript@6.0.3)) + '@vue/devtools-api': 8.2.1 + ast-walker-scope: 0.9.0 + chokidar: 5.0.0 + json5: 2.2.3 + local-pkg: 1.2.1 + magic-string: 0.30.21 + mlly: 1.8.2 + muggle-string: 0.4.1 + nostics: 1.2.0 + pathe: 2.0.3 + picomatch: 4.0.5 + scule: 1.3.0 + tinyglobby: 0.2.17 + unplugin: 3.3.0(rolldown@1.2.2)(rollup@4.35.0)(vite@8.2.0(@types/node@26.1.2)(jiti@2.7.0)(sass@1.102.0)(yaml@2.9.0)) + unplugin-utils: 0.3.2 + vue: 3.5.40(typescript@6.0.3) + yaml: 2.9.0 + optionalDependencies: + '@vue/compiler-sfc': 3.5.40 + pinia: 4.0.2(@vue/devtools-api@8.2.1)(typescript@6.0.3)(vue@3.5.40(typescript@6.0.3)) + vite: 8.2.0(@types/node@26.1.2)(jiti@2.7.0)(sass@1.102.0)(yaml@2.9.0) + transitivePeerDependencies: + - '@farmfe/core' + - '@rspack/core' + - bun-types-no-globals + - esbuild + - rolldown + - rollup + - unloader + - webpack + + vue-tsc@3.3.9(typescript@6.0.3): + dependencies: + '@volar/typescript': 2.4.28 + '@vue/language-core': 3.3.9 + typescript: 6.0.3 + + vue@3.5.40(typescript@6.0.3): + dependencies: + '@vue/compiler-dom': 3.5.40 + '@vue/compiler-sfc': 3.5.40 + '@vue/runtime-dom': 3.5.40 + '@vue/server-renderer': 3.5.40 + '@vue/shared': 3.5.40 + optionalDependencies: + typescript: 6.0.3 + + webpack-virtual-modules@0.6.2: {} + + which@2.0.2: + dependencies: + isexe: 2.0.0 + + which@7.0.0: + dependencies: + isexe: 4.0.0 + + yallist@3.1.1: {} + + yaml@2.9.0: {} diff --git a/frontend-ui/public/favicon.ico b/frontend-ui/public/favicon.ico new file mode 100644 index 00000000..8b14d919 Binary files /dev/null and b/frontend-ui/public/favicon.ico differ diff --git a/frontend-ui/src/api/calc/index.ts b/frontend-ui/src/api/calc/index.ts new file mode 100644 index 00000000..622a3663 --- /dev/null +++ b/frontend-ui/src/api/calc/index.ts @@ -0,0 +1,12 @@ +import type { IConfig } from '@/stores' +import { defineRequest } from '../common' +import type { IResult } from './type' +export default defineRequest((request) => { + return { + async calc(config: IConfig) { + const res = await request.post('/calc', config) + return res.data + }, + } +}) +// Compare this snippet from frontend/src/api/common/index.ts: diff --git a/frontend-ui/src/api/calc/type.ts b/frontend-ui/src/api/calc/type.ts new file mode 100644 index 00000000..6a8a673b --- /dev/null +++ b/frontend-ui/src/api/calc/type.ts @@ -0,0 +1,56 @@ +export interface IResult { + uuid: string + skills: IResultSkill[] + info: IResultUserInfo[] + suits: { + suit?: IResultSuit + oath?: IResultSuit + correction?: number + } + buffer: boolean +} + +export interface IResultSkill { + name: string + icon: string + lv: number + data: number + ratio: number + cd: number + damage: number + mode: string + buff: number[] + learnLv: number + type: string +} + +export interface IResultUserInfo { + id: number + name: string + value: string | number +} + +export interface IResultSuit { + id: string + count: number + imageUrl: string + level: number + name: string + point: number + rarity: string + value: string + suitId: string + skills: { + id: string + skillId: string + name: string + imageUrl: string + enable: boolean + }[] +} + +export interface IResultSkillCount { + count: number + mode: string + name: string +} diff --git a/frontend-ui/src/api/common.ts b/frontend-ui/src/api/common.ts new file mode 100644 index 00000000..a3b75356 --- /dev/null +++ b/frontend-ui/src/api/common.ts @@ -0,0 +1,118 @@ +import type { AxiosInstance, AxiosResponse } from 'axios' +import axios from 'axios' +import { h } from 'vue' +import { ungzip } from 'pako' +import { useInfoStore } from '@/stores' +import { useDialog } from '@/components/hooks/dialog' +// import { useAppStore, useConfigStore } from '@/store' +// import { useDialog } from '@/components/hooks/dialog' + +export interface HttpResponse extends AxiosResponse { + code?: number + message: string + data: T + state?: number +} + +let instance: AxiosInstance | null = null + +let baseURL = '/api' + +// 避免远程开发的时候冲突 +if (process.env.NODE_ENV == 'development') { + baseURL = '/api' +} + +if (import.meta.env.MODE == 'web' || import.meta.env.MODE == 'show') { + baseURL = 'https://api.dnftools.com/' +} + +if (import.meta.env.MODE == 'test') { + baseURL = 'https://testapi.dnftools.com/' +} + +// 解压 +function unzip(key: string) { + // 将二进制字符串转换为字符数组 + + const charData = key.split('').map((x) => { + return x?.charCodeAt(0) + }) + + // 将数字数组转换成字节数组 + const binData = new Uint8Array(charData) + + // 解压 + const data = ungzip(binData) + + const decoder = new TextDecoder() + const str = decoder.decode(data) + + // unescape(str) --->解压后解码,防止中午乱码 + return str +} + +export function defineRequest(fn: (ax: AxiosInstance) => T) { + if (!instance) { + instance = axios.create({ + baseURL, + }) + + instance.interceptors.request.use( + (request) => { + // const configStore = useConfigStore() + // const token = configStore.token + // const uid = useAppStore().uid + + const token = useInfoStore().alter_token + + if (token) { + request.headers['Alter-Token'] = token + } + + return request + }, + (error) => { + // do something + return Promise.reject(error) + }, + ) + + instance.defaults.headers.post['Content-Type'] = 'application/json;charset=UTF-8' + // instance.defaults.headers["Accept-Encoding"] = "gzip" + // instance.defaults.headers["Content-Encoding"] = "gzip" + // add response interceptors + instance.interceptors.response.use( + async (response: AxiosResponse) => { + if (response.data.code === 500) { + const { alert } = useDialog() + await alert({ + content: () => { + return h( + 'div', + { + class: 'justify-center text-#d4d6b6 text-center', + style: 'white-space:pre-wrap;width:250px;margin:10px', + }, + `出现错误,可加群反馈:183439472\n${response.data.message}`, + ) + }, + }) + } + // 解密数据 + if (typeof response.data.data == 'string') { + try { + const data = unzip(atob(response.data.data as string)) + response.data.data = JSON.parse(data) + } catch {} + } + return response.data + }, + async (error: Error) => { + return Promise.reject(error) + }, + ) + } + + return fn(Object.create(instance)) +} diff --git a/frontend-ui/src/api/index.ts b/frontend-ui/src/api/index.ts new file mode 100644 index 00000000..c97be7d7 --- /dev/null +++ b/frontend-ui/src/api/index.ts @@ -0,0 +1,4 @@ +import info from './info' +import calc from './calc' + +export default { ...info, ...calc } diff --git a/frontend-ui/src/api/info/index.ts b/frontend-ui/src/api/info/index.ts new file mode 100644 index 00000000..bc6541ba --- /dev/null +++ b/frontend-ui/src/api/info/index.ts @@ -0,0 +1,48 @@ +import { defineRequest } from '../common' +import type { IAdventureInfo, IAlterInfo, ICharacterInfo, IHelperInfo, ISkillInfo } from './type' + +export default defineRequest((request) => { + return { + async adventures() { + const res = await request.get('/adventure') + return res.data + }, + async alterByName(name: string) { + const res = await request.get('/adventure', { params: { name } }) + return res.data + }, + async createToken(alter: string, equVersion?: string) { + const res = await request.get(`/token/get/${alter}`, { params: { equVersion } }) + return res.data + }, + async characterInfo() { + const res = await request.get('/character') + return res.data + }, + async skillDetail(skillId: string, level: number) { + const res = await request.get(`/skill/${skillId}/${level}`) + return res.data + }, + async getConfigFromHelper(uid: string) { + const res = await request.get(`/dnfhelper/${uid}/`) + return res.data + }, + async getConfigFromHelperAlter(uid: string, alter: string) { + const res = await request.get(`/dnfhelper/${uid}/${alter}/`) + return res.data + }, + async getSkillFromCode(code: string) { + const res = await request.post(`/skillTree/`, { code }) + return res.data + }, + async getOathInfo(suitId: string, skillId: string, rarity: string, lv: number) { + const res = await request.get(`/info/oath/${suitId}/${skillId}`, { params: { rarity, lv } }) + return res.data + }, + async getHelperList(id: string) { + const res = await request.get(`/dnfhelper/${id}/list`) + await new Promise((resolve) => setTimeout(resolve, 30000)) + return res.data + }, + } +}) diff --git a/frontend-ui/src/api/info/type.ts b/frontend-ui/src/api/info/type.ts new file mode 100644 index 00000000..0659c95b --- /dev/null +++ b/frontend-ui/src/api/info/type.ts @@ -0,0 +1,232 @@ +export interface IAdventureInfo { + title: string + name: string + children: IAlterInfo[] +} +export interface IAlterOption { + name: string + title: string + value?: string +} + +export interface IAlterInfo { + name: string + url?: string + title: string + default_value: string + options?: IAlterOption[] + open?: boolean + comment?: string + value?: string +} + +export interface ICharacterInfo { + role: string + alter: string + name: string + buffer: boolean + equVersion: string + equips: IEquipment[] + properties: string[] + stones: IEquipment[] + enchants: IEnchantingInfo[] + emblems: IEmblemInfo[] + oaths: IEquipment[] + weapons: string[] + subweapons: string[] + skills: ISkill[] + suits: ISuit[] + avatar: Record + jades: IJade[] + sundry: Record + options: { id: number; name: string; options: string[] }[] + oaths_skills: Record< + string, + { + suitInfo: { + name: string + rarity: string + SkillAttack: number + Buffer: number + Attack: number + }[] + skills: { skillId: string; name: string; icon: string }[] + } + > +} + +export interface ISundry { + id: number + options: { + name: string + value: number + }[] +} + +export interface IEquipment { + id: string + imageUrl: string + itemType: string + itemDetailType: string + name: string + categorize: string + suit: string[] + rarity: string + max_adaptation: number + STR: number[] + INT: number[] + Vitality: number[] + Spirit: number[] + AtkP: number[] + AtkM: number[] + AtkI: number[] + SkillAttack: number[] + Attack: number[] + Buffer: number[] + detail: string + bufferDetail: string + position: string[] + wearUrl: string[] + oathPos: string + displayUrl?: string +} + +export interface ISkill { + icon: string + name: string + id: number + learnLv: number + position: number + line: number + type: string + maxLearnLv: number + maxLv: number + bind: boolean + hasVP: boolean + hasUP: boolean + vps: { + name: string + desc: string + }[] + uuid: string + upType: 'damage' | 'heal' +} + +export interface ISuit { + id: number + name: string + imageUrl: string + suitId: number + suitName: string + point: number + rarity: string + level: number + SkillAttack: number + Buffer: number + value: string + bufferValue: string +} + +export interface IEnchantingInfo { + id: string | number + fame: number | undefined + position: string[] + detail: string + categorize: string[] + rarity?: string + type?: string +} + +export interface IEmblemInfo { + fame: number + id: string + rarity: string + type: string + value: string +} + +export interface IAvatarInfo { + id: number + options: string[] + part: string + rarity: string + suit?: string + name: string +} + +export interface IJade { + name: string + id: number + max: number + min: number + pre: number + unit: string +} + +export interface ISkillInfo { + name: string + type: string + desc: string + descDetail: string + consumeItem: ConsumeItem + descSpecial: string[] + maxLevel: number + requiredLevel: number + requiredLevelRange: number + preRequiredSkill: any + jobId: string + jobName: string + jobGrowLevel: any[] + evolution: Evolution[] + enhancement: Enhancement[] + attribute: Attribute +} + +export interface ConsumeItem { + itemId: string + itemName: string + value: number +} + +export interface Evolution { + type: number + name: string + desc: string + descDetail: string + skills?: string[] +} + +export interface Enhancement { + type: number + status: Status[] +} + +export interface Status { + name: string + value: string +} + +export interface Attribute { + optionDesc: string + level: number + consumeMp: number + coolTime: number + castingTime?: number + optionValue: Record<`value${string}`, string> + detail: string +} + +export interface IHelperRoleInfo { + roleId: string + roleName: string + roleJob: string + avatarLink: string + fame: number +} + +export interface IHelperInfo { + id: string + avatar: string + name: string + roleList: IHelperRoleInfo[] +} diff --git a/frontend-ui/src/api/types.ts b/frontend-ui/src/api/types.ts new file mode 100644 index 00000000..9284c439 --- /dev/null +++ b/frontend-ui/src/api/types.ts @@ -0,0 +1,6 @@ +export interface IDataType { + code?: number + message: string + data: T + state?: number +} diff --git a/frontend-ui/src/assets/cursor/basic.cur b/frontend-ui/src/assets/cursor/basic.cur new file mode 100644 index 00000000..afae4c03 Binary files /dev/null and b/frontend-ui/src/assets/cursor/basic.cur differ diff --git a/frontend-ui/src/assets/cursor/basic_press.cur b/frontend-ui/src/assets/cursor/basic_press.cur new file mode 100644 index 00000000..1780337d Binary files /dev/null and b/frontend-ui/src/assets/cursor/basic_press.cur differ diff --git a/frontend-ui/src/assets/cursor/cursor.png b/frontend-ui/src/assets/cursor/cursor.png new file mode 100644 index 00000000..06d291b4 Binary files /dev/null and b/frontend-ui/src/assets/cursor/cursor.png differ diff --git a/frontend-ui/src/assets/favicon.ico b/frontend-ui/src/assets/favicon.ico new file mode 100644 index 00000000..8b14d919 Binary files /dev/null and b/frontend-ui/src/assets/favicon.ico differ diff --git a/frontend-ui/src/assets/fonts/dcalc.ttf b/frontend-ui/src/assets/fonts/dcalc.ttf new file mode 100644 index 00000000..2022d830 Binary files /dev/null and b/frontend-ui/src/assets/fonts/dcalc.ttf differ diff --git a/frontend-ui/src/assets/fonts/test.ttf b/frontend-ui/src/assets/fonts/test.ttf new file mode 100644 index 00000000..bc415372 Binary files /dev/null and b/frontend-ui/src/assets/fonts/test.ttf differ diff --git a/frontend-ui/src/assets/img/active.png b/frontend-ui/src/assets/img/active.png new file mode 100644 index 00000000..d2082873 Binary files /dev/null and b/frontend-ui/src/assets/img/active.png differ diff --git a/frontend-ui/src/assets/img/control/active_top.png b/frontend-ui/src/assets/img/control/active_top.png new file mode 100644 index 00000000..9ed65400 Binary files /dev/null and b/frontend-ui/src/assets/img/control/active_top.png differ diff --git a/frontend-ui/src/assets/img/control/checkbox_checked.png b/frontend-ui/src/assets/img/control/checkbox_checked.png new file mode 100644 index 00000000..58290a55 Binary files /dev/null and b/frontend-ui/src/assets/img/control/checkbox_checked.png differ diff --git a/frontend-ui/src/assets/img/control/checkbox_disable.png b/frontend-ui/src/assets/img/control/checkbox_disable.png new file mode 100644 index 00000000..9ccba4e5 Binary files /dev/null and b/frontend-ui/src/assets/img/control/checkbox_disable.png differ diff --git a/frontend-ui/src/assets/img/control/checkbox_hover.png b/frontend-ui/src/assets/img/control/checkbox_hover.png new file mode 100644 index 00000000..a1f33efa Binary files /dev/null and b/frontend-ui/src/assets/img/control/checkbox_hover.png differ diff --git a/frontend-ui/src/assets/img/control/checkbox_uncheck.png b/frontend-ui/src/assets/img/control/checkbox_uncheck.png new file mode 100644 index 00000000..0764381a Binary files /dev/null and b/frontend-ui/src/assets/img/control/checkbox_uncheck.png differ diff --git a/frontend-ui/src/assets/img/control/dictionary_line.png b/frontend-ui/src/assets/img/control/dictionary_line.png new file mode 100644 index 00000000..1dd4cfd9 Binary files /dev/null and b/frontend-ui/src/assets/img/control/dictionary_line.png differ diff --git a/frontend-ui/src/assets/img/control/hover_mask.png b/frontend-ui/src/assets/img/control/hover_mask.png new file mode 100644 index 00000000..3c0e1484 Binary files /dev/null and b/frontend-ui/src/assets/img/control/hover_mask.png differ diff --git a/frontend-ui/src/assets/img/control/item_checked.png b/frontend-ui/src/assets/img/control/item_checked.png new file mode 100644 index 00000000..3900cef1 Binary files /dev/null and b/frontend-ui/src/assets/img/control/item_checked.png differ diff --git a/frontend-ui/src/assets/img/control/item_hover.png b/frontend-ui/src/assets/img/control/item_hover.png new file mode 100644 index 00000000..fff7a3d5 Binary files /dev/null and b/frontend-ui/src/assets/img/control/item_hover.png differ diff --git a/frontend-ui/src/assets/img/control/radio_checked.png b/frontend-ui/src/assets/img/control/radio_checked.png new file mode 100644 index 00000000..52a90516 Binary files /dev/null and b/frontend-ui/src/assets/img/control/radio_checked.png differ diff --git a/frontend-ui/src/assets/img/control/radio_disable.png b/frontend-ui/src/assets/img/control/radio_disable.png new file mode 100644 index 00000000..d2ee5ad1 Binary files /dev/null and b/frontend-ui/src/assets/img/control/radio_disable.png differ diff --git a/frontend-ui/src/assets/img/control/radio_hover.png b/frontend-ui/src/assets/img/control/radio_hover.png new file mode 100644 index 00000000..f4eafd42 Binary files /dev/null and b/frontend-ui/src/assets/img/control/radio_hover.png differ diff --git a/frontend-ui/src/assets/img/control/radio_uncheck.png b/frontend-ui/src/assets/img/control/radio_uncheck.png new file mode 100644 index 00000000..4bef4c61 Binary files /dev/null and b/frontend-ui/src/assets/img/control/radio_uncheck.png differ diff --git a/frontend-ui/src/assets/img/control/title.png b/frontend-ui/src/assets/img/control/title.png new file mode 100644 index 00000000..5e5cc15b Binary files /dev/null and b/frontend-ui/src/assets/img/control/title.png differ diff --git a/frontend-ui/src/assets/img/icon/159.png b/frontend-ui/src/assets/img/icon/159.png new file mode 100644 index 00000000..ab8062fd Binary files /dev/null and b/frontend-ui/src/assets/img/icon/159.png differ diff --git a/frontend-ui/src/assets/img/icon/239.png b/frontend-ui/src/assets/img/icon/239.png new file mode 100644 index 00000000..7295426c Binary files /dev/null and b/frontend-ui/src/assets/img/icon/239.png differ diff --git a/frontend-ui/src/assets/img/icon/240.png b/frontend-ui/src/assets/img/icon/240.png new file mode 100644 index 00000000..a400fe08 Binary files /dev/null and b/frontend-ui/src/assets/img/icon/240.png differ diff --git a/frontend-ui/src/assets/img/icon/272.png b/frontend-ui/src/assets/img/icon/272.png new file mode 100644 index 00000000..889ef739 Binary files /dev/null and b/frontend-ui/src/assets/img/icon/272.png differ diff --git a/frontend-ui/src/assets/img/icon/273.png b/frontend-ui/src/assets/img/icon/273.png new file mode 100644 index 00000000..6945f2ed Binary files /dev/null and b/frontend-ui/src/assets/img/icon/273.png differ diff --git a/frontend-ui/src/assets/img/icon/274.png b/frontend-ui/src/assets/img/icon/274.png new file mode 100644 index 00000000..9da7325c Binary files /dev/null and b/frontend-ui/src/assets/img/icon/274.png differ diff --git a/frontend-ui/src/assets/img/icon/275.png b/frontend-ui/src/assets/img/icon/275.png new file mode 100644 index 00000000..b5976d53 Binary files /dev/null and b/frontend-ui/src/assets/img/icon/275.png differ diff --git a/frontend-ui/src/assets/img/icon/305.png b/frontend-ui/src/assets/img/icon/305.png new file mode 100644 index 00000000..79e93b5c Binary files /dev/null and b/frontend-ui/src/assets/img/icon/305.png differ diff --git a/frontend-ui/src/assets/img/icon/306.png b/frontend-ui/src/assets/img/icon/306.png new file mode 100644 index 00000000..3ff780f5 Binary files /dev/null and b/frontend-ui/src/assets/img/icon/306.png differ diff --git a/frontend-ui/src/assets/img/icon/307.png b/frontend-ui/src/assets/img/icon/307.png new file mode 100644 index 00000000..50048c55 Binary files /dev/null and b/frontend-ui/src/assets/img/icon/307.png differ diff --git a/frontend-ui/src/assets/img/icon/308.png b/frontend-ui/src/assets/img/icon/308.png new file mode 100644 index 00000000..d2905758 Binary files /dev/null and b/frontend-ui/src/assets/img/icon/308.png differ diff --git a/frontend-ui/src/assets/img/icon/309.png b/frontend-ui/src/assets/img/icon/309.png new file mode 100644 index 00000000..d38a8299 Binary files /dev/null and b/frontend-ui/src/assets/img/icon/309.png differ diff --git a/frontend-ui/src/assets/img/icon/310.png b/frontend-ui/src/assets/img/icon/310.png new file mode 100644 index 00000000..6ac71155 Binary files /dev/null and b/frontend-ui/src/assets/img/icon/310.png differ diff --git a/frontend-ui/src/assets/img/icon/311.png b/frontend-ui/src/assets/img/icon/311.png new file mode 100644 index 00000000..8c413d0e Binary files /dev/null and b/frontend-ui/src/assets/img/icon/311.png differ diff --git a/frontend-ui/src/assets/img/icon/312.png b/frontend-ui/src/assets/img/icon/312.png new file mode 100644 index 00000000..e822878b Binary files /dev/null and b/frontend-ui/src/assets/img/icon/312.png differ diff --git a/frontend-ui/src/assets/img/icon/455.png b/frontend-ui/src/assets/img/icon/455.png new file mode 100644 index 00000000..d0e0fa96 Binary files /dev/null and b/frontend-ui/src/assets/img/icon/455.png differ diff --git a/frontend-ui/src/assets/img/icon/456.png b/frontend-ui/src/assets/img/icon/456.png new file mode 100644 index 00000000..dc70cf84 Binary files /dev/null and b/frontend-ui/src/assets/img/icon/456.png differ diff --git a/frontend-ui/src/assets/img/icon/457.png b/frontend-ui/src/assets/img/icon/457.png new file mode 100644 index 00000000..26ea3cb9 Binary files /dev/null and b/frontend-ui/src/assets/img/icon/457.png differ diff --git a/frontend-ui/src/assets/img/icon/458.png b/frontend-ui/src/assets/img/icon/458.png new file mode 100644 index 00000000..3fc90eeb Binary files /dev/null and b/frontend-ui/src/assets/img/icon/458.png differ diff --git a/frontend-ui/src/assets/img/icon/459.png b/frontend-ui/src/assets/img/icon/459.png new file mode 100644 index 00000000..7ccc81ad Binary files /dev/null and b/frontend-ui/src/assets/img/icon/459.png differ diff --git a/frontend-ui/src/assets/img/icon/460.png b/frontend-ui/src/assets/img/icon/460.png new file mode 100644 index 00000000..29cf16b5 Binary files /dev/null and b/frontend-ui/src/assets/img/icon/460.png differ diff --git a/frontend-ui/src/assets/img/icon/461.png b/frontend-ui/src/assets/img/icon/461.png new file mode 100644 index 00000000..a7d1a972 Binary files /dev/null and b/frontend-ui/src/assets/img/icon/461.png differ diff --git a/frontend-ui/src/assets/img/icon/462.png b/frontend-ui/src/assets/img/icon/462.png new file mode 100644 index 00000000..ca168b39 Binary files /dev/null and b/frontend-ui/src/assets/img/icon/462.png differ diff --git a/frontend-ui/src/assets/img/icon/463.png b/frontend-ui/src/assets/img/icon/463.png new file mode 100644 index 00000000..e0112052 Binary files /dev/null and b/frontend-ui/src/assets/img/icon/463.png differ diff --git a/frontend-ui/src/assets/img/icon/464.png b/frontend-ui/src/assets/img/icon/464.png new file mode 100644 index 00000000..46991b50 Binary files /dev/null and b/frontend-ui/src/assets/img/icon/464.png differ diff --git a/frontend-ui/src/assets/img/icon/469.png b/frontend-ui/src/assets/img/icon/469.png new file mode 100644 index 00000000..7295426c Binary files /dev/null and b/frontend-ui/src/assets/img/icon/469.png differ diff --git a/frontend-ui/src/assets/img/icon/470.png b/frontend-ui/src/assets/img/icon/470.png new file mode 100644 index 00000000..a400fe08 Binary files /dev/null and b/frontend-ui/src/assets/img/icon/470.png differ diff --git a/frontend-ui/src/assets/img/icon/504.png b/frontend-ui/src/assets/img/icon/504.png new file mode 100644 index 00000000..6bfa4baf Binary files /dev/null and b/frontend-ui/src/assets/img/icon/504.png differ diff --git a/frontend-ui/src/assets/img/icon/505.png b/frontend-ui/src/assets/img/icon/505.png new file mode 100644 index 00000000..4ad1ecb1 Binary files /dev/null and b/frontend-ui/src/assets/img/icon/505.png differ diff --git a/frontend-ui/src/assets/img/icon/540.png b/frontend-ui/src/assets/img/icon/540.png new file mode 100644 index 00000000..cee27adb Binary files /dev/null and b/frontend-ui/src/assets/img/icon/540.png differ diff --git a/frontend-ui/src/assets/img/icon/541.png b/frontend-ui/src/assets/img/icon/541.png new file mode 100644 index 00000000..a2d5c5b5 Binary files /dev/null and b/frontend-ui/src/assets/img/icon/541.png differ diff --git a/frontend-ui/src/assets/img/icon/542.png b/frontend-ui/src/assets/img/icon/542.png new file mode 100644 index 00000000..f9d017d2 Binary files /dev/null and b/frontend-ui/src/assets/img/icon/542.png differ diff --git a/frontend-ui/src/assets/img/icon/543.png b/frontend-ui/src/assets/img/icon/543.png new file mode 100644 index 00000000..87c314ae Binary files /dev/null and b/frontend-ui/src/assets/img/icon/543.png differ diff --git a/frontend-ui/src/assets/img/icon/55.png b/frontend-ui/src/assets/img/icon/55.png new file mode 100644 index 00000000..a41b9751 Binary files /dev/null and b/frontend-ui/src/assets/img/icon/55.png differ diff --git a/frontend-ui/src/assets/img/icon/588.png b/frontend-ui/src/assets/img/icon/588.png new file mode 100644 index 00000000..6a4f9f93 Binary files /dev/null and b/frontend-ui/src/assets/img/icon/588.png differ diff --git a/frontend-ui/src/assets/img/icon/593.png b/frontend-ui/src/assets/img/icon/593.png new file mode 100644 index 00000000..90b32866 Binary files /dev/null and b/frontend-ui/src/assets/img/icon/593.png differ diff --git a/frontend-ui/src/assets/img/icon/594.png b/frontend-ui/src/assets/img/icon/594.png new file mode 100644 index 00000000..e64ec4ca Binary files /dev/null and b/frontend-ui/src/assets/img/icon/594.png differ diff --git a/frontend-ui/src/assets/img/icon/595.png b/frontend-ui/src/assets/img/icon/595.png new file mode 100644 index 00000000..e64ec4ca Binary files /dev/null and b/frontend-ui/src/assets/img/icon/595.png differ diff --git a/frontend-ui/src/assets/img/icon/596.png b/frontend-ui/src/assets/img/icon/596.png new file mode 100644 index 00000000..9e6b8f65 Binary files /dev/null and b/frontend-ui/src/assets/img/icon/596.png differ diff --git a/frontend-ui/src/assets/img/icon/606.png b/frontend-ui/src/assets/img/icon/606.png new file mode 100644 index 00000000..cf78deb0 Binary files /dev/null and b/frontend-ui/src/assets/img/icon/606.png differ diff --git a/frontend-ui/src/assets/img/icon/614.png b/frontend-ui/src/assets/img/icon/614.png new file mode 100644 index 00000000..9cb24763 Binary files /dev/null and b/frontend-ui/src/assets/img/icon/614.png differ diff --git a/frontend-ui/src/assets/img/icon/615.png b/frontend-ui/src/assets/img/icon/615.png new file mode 100644 index 00000000..bcf098af Binary files /dev/null and b/frontend-ui/src/assets/img/icon/615.png differ diff --git a/frontend-ui/src/assets/img/icon/616.png b/frontend-ui/src/assets/img/icon/616.png new file mode 100644 index 00000000..9a931a9d Binary files /dev/null and b/frontend-ui/src/assets/img/icon/616.png differ diff --git a/frontend-ui/src/assets/img/icon/617.png b/frontend-ui/src/assets/img/icon/617.png new file mode 100644 index 00000000..065d5a2a Binary files /dev/null and b/frontend-ui/src/assets/img/icon/617.png differ diff --git a/frontend-ui/src/assets/img/icon/bakal.png b/frontend-ui/src/assets/img/icon/bakal.png new file mode 100644 index 00000000..47544fb0 Binary files /dev/null and b/frontend-ui/src/assets/img/icon/bakal.png differ diff --git a/frontend-ui/src/assets/img/icon/bakalraid.png b/frontend-ui/src/assets/img/icon/bakalraid.png new file mode 100644 index 00000000..9cfacedd Binary files /dev/null and b/frontend-ui/src/assets/img/icon/bakalraid.png differ diff --git a/frontend-ui/src/assets/img/icon/detail.png b/frontend-ui/src/assets/img/icon/detail.png new file mode 100644 index 00000000..5a2a872f Binary files /dev/null and b/frontend-ui/src/assets/img/icon/detail.png differ diff --git a/frontend-ui/src/assets/img/icon/detail_active.png b/frontend-ui/src/assets/img/icon/detail_active.png new file mode 100644 index 00000000..c4268842 Binary files /dev/null and b/frontend-ui/src/assets/img/icon/detail_active.png differ diff --git a/frontend-ui/src/assets/img/icon/detail_disabled.png b/frontend-ui/src/assets/img/icon/detail_disabled.png new file mode 100644 index 00000000..33809ff3 Binary files /dev/null and b/frontend-ui/src/assets/img/icon/detail_disabled.png differ diff --git a/frontend-ui/src/assets/img/icon/detail_hover.png b/frontend-ui/src/assets/img/icon/detail_hover.png new file mode 100644 index 00000000..bd5fbda6 Binary files /dev/null and b/frontend-ui/src/assets/img/icon/detail_hover.png differ diff --git a/frontend-ui/src/assets/img/icon/down.png b/frontend-ui/src/assets/img/icon/down.png new file mode 100644 index 00000000..4861b24f Binary files /dev/null and b/frontend-ui/src/assets/img/icon/down.png differ diff --git a/frontend-ui/src/assets/img/icon/dropdown.png b/frontend-ui/src/assets/img/icon/dropdown.png new file mode 100644 index 00000000..7672ee58 Binary files /dev/null and b/frontend-ui/src/assets/img/icon/dropdown.png differ diff --git a/frontend-ui/src/assets/img/icon/dropdown_active.png b/frontend-ui/src/assets/img/icon/dropdown_active.png new file mode 100644 index 00000000..71f4145b Binary files /dev/null and b/frontend-ui/src/assets/img/icon/dropdown_active.png differ diff --git a/frontend-ui/src/assets/img/icon/dropdown_disabled.png b/frontend-ui/src/assets/img/icon/dropdown_disabled.png new file mode 100644 index 00000000..800355f3 Binary files /dev/null and b/frontend-ui/src/assets/img/icon/dropdown_disabled.png differ diff --git a/frontend-ui/src/assets/img/icon/dropdown_hover.png b/frontend-ui/src/assets/img/icon/dropdown_hover.png new file mode 100644 index 00000000..825284b9 Binary files /dev/null and b/frontend-ui/src/assets/img/icon/dropdown_hover.png differ diff --git a/frontend-ui/src/assets/img/icon/exchange.png b/frontend-ui/src/assets/img/icon/exchange.png new file mode 100644 index 00000000..8d1279ae Binary files /dev/null and b/frontend-ui/src/assets/img/icon/exchange.png differ diff --git a/frontend-ui/src/assets/img/icon/exchange.svg b/frontend-ui/src/assets/img/icon/exchange.svg new file mode 100644 index 00000000..5c6a0614 --- /dev/null +++ b/frontend-ui/src/assets/img/icon/exchange.svg @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/frontend-ui/src/assets/img/icon/exchange_active.png b/frontend-ui/src/assets/img/icon/exchange_active.png new file mode 100644 index 00000000..6de8ffaf Binary files /dev/null and b/frontend-ui/src/assets/img/icon/exchange_active.png differ diff --git a/frontend-ui/src/assets/img/icon/exchange_active.svg b/frontend-ui/src/assets/img/icon/exchange_active.svg new file mode 100644 index 00000000..83847eb5 --- /dev/null +++ b/frontend-ui/src/assets/img/icon/exchange_active.svg @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/frontend-ui/src/assets/img/icon/exchange_disabled.png b/frontend-ui/src/assets/img/icon/exchange_disabled.png new file mode 100644 index 00000000..d701bb6b Binary files /dev/null and b/frontend-ui/src/assets/img/icon/exchange_disabled.png differ diff --git a/frontend-ui/src/assets/img/icon/exchange_disabled.svg b/frontend-ui/src/assets/img/icon/exchange_disabled.svg new file mode 100644 index 00000000..4438229c --- /dev/null +++ b/frontend-ui/src/assets/img/icon/exchange_disabled.svg @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/frontend-ui/src/assets/img/icon/exchange_hover.png b/frontend-ui/src/assets/img/icon/exchange_hover.png new file mode 100644 index 00000000..ba963c97 Binary files /dev/null and b/frontend-ui/src/assets/img/icon/exchange_hover.png differ diff --git a/frontend-ui/src/assets/img/icon/exchange_hover.svg b/frontend-ui/src/assets/img/icon/exchange_hover.svg new file mode 100644 index 00000000..43a5a168 --- /dev/null +++ b/frontend-ui/src/assets/img/icon/exchange_hover.svg @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/frontend-ui/src/assets/img/icon/exit.png b/frontend-ui/src/assets/img/icon/exit.png new file mode 100644 index 00000000..5cd6eac4 Binary files /dev/null and b/frontend-ui/src/assets/img/icon/exit.png differ diff --git a/frontend-ui/src/assets/img/icon/home.png b/frontend-ui/src/assets/img/icon/home.png new file mode 100644 index 00000000..d7e00935 Binary files /dev/null and b/frontend-ui/src/assets/img/icon/home.png differ diff --git a/frontend-ui/src/assets/img/icon/home_active.png b/frontend-ui/src/assets/img/icon/home_active.png new file mode 100644 index 00000000..6c5bbad9 Binary files /dev/null and b/frontend-ui/src/assets/img/icon/home_active.png differ diff --git a/frontend-ui/src/assets/img/icon/home_disabled.png b/frontend-ui/src/assets/img/icon/home_disabled.png new file mode 100644 index 00000000..6f5a4105 Binary files /dev/null and b/frontend-ui/src/assets/img/icon/home_disabled.png differ diff --git a/frontend-ui/src/assets/img/icon/home_hover.png b/frontend-ui/src/assets/img/icon/home_hover.png new file mode 100644 index 00000000..b792b9f0 Binary files /dev/null and b/frontend-ui/src/assets/img/icon/home_hover.png differ diff --git a/frontend-ui/src/assets/img/icon/import.png b/frontend-ui/src/assets/img/icon/import.png new file mode 100644 index 00000000..2b57c419 Binary files /dev/null and b/frontend-ui/src/assets/img/icon/import.png differ diff --git a/frontend-ui/src/assets/img/icon/import_active.png b/frontend-ui/src/assets/img/icon/import_active.png new file mode 100644 index 00000000..517913bb Binary files /dev/null and b/frontend-ui/src/assets/img/icon/import_active.png differ diff --git a/frontend-ui/src/assets/img/icon/import_disabled.png b/frontend-ui/src/assets/img/icon/import_disabled.png new file mode 100644 index 00000000..3fd94f96 Binary files /dev/null and b/frontend-ui/src/assets/img/icon/import_disabled.png differ diff --git a/frontend-ui/src/assets/img/icon/import_hover.png b/frontend-ui/src/assets/img/icon/import_hover.png new file mode 100644 index 00000000..8a095d6b Binary files /dev/null and b/frontend-ui/src/assets/img/icon/import_hover.png differ diff --git a/frontend-ui/src/assets/img/icon/increase.png b/frontend-ui/src/assets/img/icon/increase.png new file mode 100644 index 00000000..cb0f2228 Binary files /dev/null and b/frontend-ui/src/assets/img/icon/increase.png differ diff --git a/frontend-ui/src/assets/img/icon/increase_active.png b/frontend-ui/src/assets/img/icon/increase_active.png new file mode 100644 index 00000000..f9985b45 Binary files /dev/null and b/frontend-ui/src/assets/img/icon/increase_active.png differ diff --git a/frontend-ui/src/assets/img/icon/increase_disabled.png b/frontend-ui/src/assets/img/icon/increase_disabled.png new file mode 100644 index 00000000..75605772 Binary files /dev/null and b/frontend-ui/src/assets/img/icon/increase_disabled.png differ diff --git a/frontend-ui/src/assets/img/icon/increase_hover.png b/frontend-ui/src/assets/img/icon/increase_hover.png new file mode 100644 index 00000000..ad6e882e Binary files /dev/null and b/frontend-ui/src/assets/img/icon/increase_hover.png differ diff --git a/frontend-ui/src/assets/img/icon/input_lower.png b/frontend-ui/src/assets/img/icon/input_lower.png new file mode 100644 index 00000000..7e6aa83f Binary files /dev/null and b/frontend-ui/src/assets/img/icon/input_lower.png differ diff --git a/frontend-ui/src/assets/img/icon/input_upper.png b/frontend-ui/src/assets/img/icon/input_upper.png new file mode 100644 index 00000000..69e081ba Binary files /dev/null and b/frontend-ui/src/assets/img/icon/input_upper.png differ diff --git a/frontend-ui/src/assets/img/icon/lock.png b/frontend-ui/src/assets/img/icon/lock.png new file mode 100644 index 00000000..87a16509 Binary files /dev/null and b/frontend-ui/src/assets/img/icon/lock.png differ diff --git a/frontend-ui/src/assets/img/icon/max.png b/frontend-ui/src/assets/img/icon/max.png new file mode 100644 index 00000000..125c9cdf Binary files /dev/null and b/frontend-ui/src/assets/img/icon/max.png differ diff --git a/frontend-ui/src/assets/img/icon/max_active.png b/frontend-ui/src/assets/img/icon/max_active.png new file mode 100644 index 00000000..d88cbc27 Binary files /dev/null and b/frontend-ui/src/assets/img/icon/max_active.png differ diff --git a/frontend-ui/src/assets/img/icon/max_disabled.png b/frontend-ui/src/assets/img/icon/max_disabled.png new file mode 100644 index 00000000..88e1197f Binary files /dev/null and b/frontend-ui/src/assets/img/icon/max_disabled.png differ diff --git a/frontend-ui/src/assets/img/icon/max_hover.png b/frontend-ui/src/assets/img/icon/max_hover.png new file mode 100644 index 00000000..ae7ecc38 Binary files /dev/null and b/frontend-ui/src/assets/img/icon/max_hover.png differ diff --git a/frontend-ui/src/assets/img/icon/menu/drug.png b/frontend-ui/src/assets/img/icon/menu/drug.png new file mode 100644 index 00000000..e8df484a Binary files /dev/null and b/frontend-ui/src/assets/img/icon/menu/drug.png differ diff --git a/frontend-ui/src/assets/img/icon/menu/drug_active.png b/frontend-ui/src/assets/img/icon/menu/drug_active.png new file mode 100644 index 00000000..2569f714 Binary files /dev/null and b/frontend-ui/src/assets/img/icon/menu/drug_active.png differ diff --git a/frontend-ui/src/assets/img/icon/menu/drug_disabled.png b/frontend-ui/src/assets/img/icon/menu/drug_disabled.png new file mode 100644 index 00000000..774684e2 Binary files /dev/null and b/frontend-ui/src/assets/img/icon/menu/drug_disabled.png differ diff --git a/frontend-ui/src/assets/img/icon/menu/drug_hover.png b/frontend-ui/src/assets/img/icon/menu/drug_hover.png new file mode 100644 index 00000000..531a9c07 Binary files /dev/null and b/frontend-ui/src/assets/img/icon/menu/drug_hover.png differ diff --git a/frontend-ui/src/assets/img/icon/menu/favourite.png b/frontend-ui/src/assets/img/icon/menu/favourite.png new file mode 100644 index 00000000..f7e2c291 Binary files /dev/null and b/frontend-ui/src/assets/img/icon/menu/favourite.png differ diff --git a/frontend-ui/src/assets/img/icon/menu/favourite_active.png b/frontend-ui/src/assets/img/icon/menu/favourite_active.png new file mode 100644 index 00000000..fb937e41 Binary files /dev/null and b/frontend-ui/src/assets/img/icon/menu/favourite_active.png differ diff --git a/frontend-ui/src/assets/img/icon/menu/favourite_disabled.png b/frontend-ui/src/assets/img/icon/menu/favourite_disabled.png new file mode 100644 index 00000000..d7cf31fa Binary files /dev/null and b/frontend-ui/src/assets/img/icon/menu/favourite_disabled.png differ diff --git a/frontend-ui/src/assets/img/icon/menu/favourite_hover.png b/frontend-ui/src/assets/img/icon/menu/favourite_hover.png new file mode 100644 index 00000000..8a64e13f Binary files /dev/null and b/frontend-ui/src/assets/img/icon/menu/favourite_hover.png differ diff --git a/frontend-ui/src/assets/img/icon/menu/navigation.png b/frontend-ui/src/assets/img/icon/menu/navigation.png new file mode 100644 index 00000000..ac485e13 Binary files /dev/null and b/frontend-ui/src/assets/img/icon/menu/navigation.png differ diff --git a/frontend-ui/src/assets/img/icon/menu/navigation_active.png b/frontend-ui/src/assets/img/icon/menu/navigation_active.png new file mode 100644 index 00000000..b69272ff Binary files /dev/null and b/frontend-ui/src/assets/img/icon/menu/navigation_active.png differ diff --git a/frontend-ui/src/assets/img/icon/menu/navigation_disabled.png b/frontend-ui/src/assets/img/icon/menu/navigation_disabled.png new file mode 100644 index 00000000..8745a813 Binary files /dev/null and b/frontend-ui/src/assets/img/icon/menu/navigation_disabled.png differ diff --git a/frontend-ui/src/assets/img/icon/menu/navigation_hover.png b/frontend-ui/src/assets/img/icon/menu/navigation_hover.png new file mode 100644 index 00000000..b69272ff Binary files /dev/null and b/frontend-ui/src/assets/img/icon/menu/navigation_hover.png differ diff --git a/frontend-ui/src/assets/img/icon/menu/recommend.png b/frontend-ui/src/assets/img/icon/menu/recommend.png new file mode 100644 index 00000000..2fa899c1 Binary files /dev/null and b/frontend-ui/src/assets/img/icon/menu/recommend.png differ diff --git a/frontend-ui/src/assets/img/icon/menu/recommend_active.png b/frontend-ui/src/assets/img/icon/menu/recommend_active.png new file mode 100644 index 00000000..d0043f4f Binary files /dev/null and b/frontend-ui/src/assets/img/icon/menu/recommend_active.png differ diff --git a/frontend-ui/src/assets/img/icon/menu/recommend_disabled.png b/frontend-ui/src/assets/img/icon/menu/recommend_disabled.png new file mode 100644 index 00000000..7ff8023b Binary files /dev/null and b/frontend-ui/src/assets/img/icon/menu/recommend_disabled.png differ diff --git a/frontend-ui/src/assets/img/icon/menu/recommend_hover.png b/frontend-ui/src/assets/img/icon/menu/recommend_hover.png new file mode 100644 index 00000000..e2982042 Binary files /dev/null and b/frontend-ui/src/assets/img/icon/menu/recommend_hover.png differ diff --git a/frontend-ui/src/assets/img/icon/menu/set.png b/frontend-ui/src/assets/img/icon/menu/set.png new file mode 100644 index 00000000..0bdabfce Binary files /dev/null and b/frontend-ui/src/assets/img/icon/menu/set.png differ diff --git a/frontend-ui/src/assets/img/icon/menu/set_active.png b/frontend-ui/src/assets/img/icon/menu/set_active.png new file mode 100644 index 00000000..09533703 Binary files /dev/null and b/frontend-ui/src/assets/img/icon/menu/set_active.png differ diff --git a/frontend-ui/src/assets/img/icon/menu/set_disabled.png b/frontend-ui/src/assets/img/icon/menu/set_disabled.png new file mode 100644 index 00000000..db89768d Binary files /dev/null and b/frontend-ui/src/assets/img/icon/menu/set_disabled.png differ diff --git a/frontend-ui/src/assets/img/icon/menu/set_hover.png b/frontend-ui/src/assets/img/icon/menu/set_hover.png new file mode 100644 index 00000000..05840c04 Binary files /dev/null and b/frontend-ui/src/assets/img/icon/menu/set_hover.png differ diff --git a/frontend-ui/src/assets/img/icon/menu/specificity.png b/frontend-ui/src/assets/img/icon/menu/specificity.png new file mode 100644 index 00000000..1b613bce Binary files /dev/null and b/frontend-ui/src/assets/img/icon/menu/specificity.png differ diff --git a/frontend-ui/src/assets/img/icon/menu/specificity_active.png b/frontend-ui/src/assets/img/icon/menu/specificity_active.png new file mode 100644 index 00000000..5135c709 Binary files /dev/null and b/frontend-ui/src/assets/img/icon/menu/specificity_active.png differ diff --git a/frontend-ui/src/assets/img/icon/menu/specificity_disabled.png b/frontend-ui/src/assets/img/icon/menu/specificity_disabled.png new file mode 100644 index 00000000..fc661420 Binary files /dev/null and b/frontend-ui/src/assets/img/icon/menu/specificity_disabled.png differ diff --git a/frontend-ui/src/assets/img/icon/menu/specificity_hover.png b/frontend-ui/src/assets/img/icon/menu/specificity_hover.png new file mode 100644 index 00000000..dff8481e Binary files /dev/null and b/frontend-ui/src/assets/img/icon/menu/specificity_hover.png differ diff --git a/frontend-ui/src/assets/img/icon/min.png b/frontend-ui/src/assets/img/icon/min.png new file mode 100644 index 00000000..9aa454a6 Binary files /dev/null and b/frontend-ui/src/assets/img/icon/min.png differ diff --git a/frontend-ui/src/assets/img/icon/min_active.png b/frontend-ui/src/assets/img/icon/min_active.png new file mode 100644 index 00000000..f6479eae Binary files /dev/null and b/frontend-ui/src/assets/img/icon/min_active.png differ diff --git a/frontend-ui/src/assets/img/icon/min_disabled.png b/frontend-ui/src/assets/img/icon/min_disabled.png new file mode 100644 index 00000000..0683a977 Binary files /dev/null and b/frontend-ui/src/assets/img/icon/min_disabled.png differ diff --git a/frontend-ui/src/assets/img/icon/min_hover.png b/frontend-ui/src/assets/img/icon/min_hover.png new file mode 100644 index 00000000..ea00edef Binary files /dev/null and b/frontend-ui/src/assets/img/icon/min_hover.png differ diff --git a/frontend-ui/src/assets/img/icon/next.png b/frontend-ui/src/assets/img/icon/next.png new file mode 100644 index 00000000..7c80c23a Binary files /dev/null and b/frontend-ui/src/assets/img/icon/next.png differ diff --git a/frontend-ui/src/assets/img/icon/next_active.png b/frontend-ui/src/assets/img/icon/next_active.png new file mode 100644 index 00000000..ad640ebd Binary files /dev/null and b/frontend-ui/src/assets/img/icon/next_active.png differ diff --git a/frontend-ui/src/assets/img/icon/next_disabled.png b/frontend-ui/src/assets/img/icon/next_disabled.png new file mode 100644 index 00000000..4d99a2bc Binary files /dev/null and b/frontend-ui/src/assets/img/icon/next_disabled.png differ diff --git a/frontend-ui/src/assets/img/icon/next_hover.png b/frontend-ui/src/assets/img/icon/next_hover.png new file mode 100644 index 00000000..345e47d1 Binary files /dev/null and b/frontend-ui/src/assets/img/icon/next_hover.png differ diff --git a/frontend-ui/src/assets/img/icon/plus.png b/frontend-ui/src/assets/img/icon/plus.png new file mode 100644 index 00000000..6d130140 Binary files /dev/null and b/frontend-ui/src/assets/img/icon/plus.png differ diff --git a/frontend-ui/src/assets/img/icon/plus_active.png b/frontend-ui/src/assets/img/icon/plus_active.png new file mode 100644 index 00000000..9683da53 Binary files /dev/null and b/frontend-ui/src/assets/img/icon/plus_active.png differ diff --git a/frontend-ui/src/assets/img/icon/plus_disabled.png b/frontend-ui/src/assets/img/icon/plus_disabled.png new file mode 100644 index 00000000..3ed8ee02 Binary files /dev/null and b/frontend-ui/src/assets/img/icon/plus_disabled.png differ diff --git a/frontend-ui/src/assets/img/icon/plus_hover.png b/frontend-ui/src/assets/img/icon/plus_hover.png new file mode 100644 index 00000000..dd002ec1 Binary files /dev/null and b/frontend-ui/src/assets/img/icon/plus_hover.png differ diff --git a/frontend-ui/src/assets/img/icon/prev.png b/frontend-ui/src/assets/img/icon/prev.png new file mode 100644 index 00000000..653092c7 Binary files /dev/null and b/frontend-ui/src/assets/img/icon/prev.png differ diff --git a/frontend-ui/src/assets/img/icon/prev_active.png b/frontend-ui/src/assets/img/icon/prev_active.png new file mode 100644 index 00000000..af559ae3 Binary files /dev/null and b/frontend-ui/src/assets/img/icon/prev_active.png differ diff --git a/frontend-ui/src/assets/img/icon/prev_disabled.png b/frontend-ui/src/assets/img/icon/prev_disabled.png new file mode 100644 index 00000000..80224914 Binary files /dev/null and b/frontend-ui/src/assets/img/icon/prev_disabled.png differ diff --git a/frontend-ui/src/assets/img/icon/prev_hover.png b/frontend-ui/src/assets/img/icon/prev_hover.png new file mode 100644 index 00000000..3cc8b662 Binary files /dev/null and b/frontend-ui/src/assets/img/icon/prev_hover.png differ diff --git a/frontend-ui/src/assets/img/icon/reduce.png b/frontend-ui/src/assets/img/icon/reduce.png new file mode 100644 index 00000000..043d71cf Binary files /dev/null and b/frontend-ui/src/assets/img/icon/reduce.png differ diff --git a/frontend-ui/src/assets/img/icon/reduce_active.png b/frontend-ui/src/assets/img/icon/reduce_active.png new file mode 100644 index 00000000..1716931d Binary files /dev/null and b/frontend-ui/src/assets/img/icon/reduce_active.png differ diff --git a/frontend-ui/src/assets/img/icon/reduce_disabled.png b/frontend-ui/src/assets/img/icon/reduce_disabled.png new file mode 100644 index 00000000..4243916c Binary files /dev/null and b/frontend-ui/src/assets/img/icon/reduce_disabled.png differ diff --git a/frontend-ui/src/assets/img/icon/reduce_hover.png b/frontend-ui/src/assets/img/icon/reduce_hover.png new file mode 100644 index 00000000..d252d5b4 Binary files /dev/null and b/frontend-ui/src/assets/img/icon/reduce_hover.png differ diff --git a/frontend-ui/src/assets/img/icon/reflesh.png b/frontend-ui/src/assets/img/icon/reflesh.png new file mode 100644 index 00000000..28b0c715 Binary files /dev/null and b/frontend-ui/src/assets/img/icon/reflesh.png differ diff --git a/frontend-ui/src/assets/img/icon/reflesh_active.png b/frontend-ui/src/assets/img/icon/reflesh_active.png new file mode 100644 index 00000000..3878fede Binary files /dev/null and b/frontend-ui/src/assets/img/icon/reflesh_active.png differ diff --git a/frontend-ui/src/assets/img/icon/reflesh_disabled.png b/frontend-ui/src/assets/img/icon/reflesh_disabled.png new file mode 100644 index 00000000..65239d71 Binary files /dev/null and b/frontend-ui/src/assets/img/icon/reflesh_disabled.png differ diff --git a/frontend-ui/src/assets/img/icon/reflesh_hover.png b/frontend-ui/src/assets/img/icon/reflesh_hover.png new file mode 100644 index 00000000..4ec30490 Binary files /dev/null and b/frontend-ui/src/assets/img/icon/reflesh_hover.png differ diff --git a/frontend-ui/src/assets/img/icon/reset.png b/frontend-ui/src/assets/img/icon/reset.png new file mode 100644 index 00000000..5963019a Binary files /dev/null and b/frontend-ui/src/assets/img/icon/reset.png differ diff --git a/frontend-ui/src/assets/img/icon/reset_active.png b/frontend-ui/src/assets/img/icon/reset_active.png new file mode 100644 index 00000000..ed20405c Binary files /dev/null and b/frontend-ui/src/assets/img/icon/reset_active.png differ diff --git a/frontend-ui/src/assets/img/icon/reset_disabled.png b/frontend-ui/src/assets/img/icon/reset_disabled.png new file mode 100644 index 00000000..f9a1eff0 Binary files /dev/null and b/frontend-ui/src/assets/img/icon/reset_disabled.png differ diff --git a/frontend-ui/src/assets/img/icon/reset_hover.png b/frontend-ui/src/assets/img/icon/reset_hover.png new file mode 100644 index 00000000..f9aad4b3 Binary files /dev/null and b/frontend-ui/src/assets/img/icon/reset_hover.png differ diff --git a/frontend-ui/src/assets/img/icon/search.png b/frontend-ui/src/assets/img/icon/search.png new file mode 100644 index 00000000..30f7b0a4 Binary files /dev/null and b/frontend-ui/src/assets/img/icon/search.png differ diff --git a/frontend-ui/src/assets/img/icon/search_active.png b/frontend-ui/src/assets/img/icon/search_active.png new file mode 100644 index 00000000..5d92deb2 Binary files /dev/null and b/frontend-ui/src/assets/img/icon/search_active.png differ diff --git a/frontend-ui/src/assets/img/icon/search_disabled.png b/frontend-ui/src/assets/img/icon/search_disabled.png new file mode 100644 index 00000000..802fb28b Binary files /dev/null and b/frontend-ui/src/assets/img/icon/search_disabled.png differ diff --git a/frontend-ui/src/assets/img/icon/search_hover.png b/frontend-ui/src/assets/img/icon/search_hover.png new file mode 100644 index 00000000..7653c52b Binary files /dev/null and b/frontend-ui/src/assets/img/icon/search_hover.png differ diff --git a/frontend-ui/src/assets/img/icon/set.png b/frontend-ui/src/assets/img/icon/set.png new file mode 100644 index 00000000..c8b835e2 Binary files /dev/null and b/frontend-ui/src/assets/img/icon/set.png differ diff --git a/frontend-ui/src/assets/img/icon/set_active.png b/frontend-ui/src/assets/img/icon/set_active.png new file mode 100644 index 00000000..e7ac646f Binary files /dev/null and b/frontend-ui/src/assets/img/icon/set_active.png differ diff --git a/frontend-ui/src/assets/img/icon/set_disabled.png b/frontend-ui/src/assets/img/icon/set_disabled.png new file mode 100644 index 00000000..50434bb4 Binary files /dev/null and b/frontend-ui/src/assets/img/icon/set_disabled.png differ diff --git a/frontend-ui/src/assets/img/icon/set_hover.png b/frontend-ui/src/assets/img/icon/set_hover.png new file mode 100644 index 00000000..c25b597c Binary files /dev/null and b/frontend-ui/src/assets/img/icon/set_hover.png differ diff --git a/frontend-ui/src/assets/img/icon/share.png b/frontend-ui/src/assets/img/icon/share.png new file mode 100644 index 00000000..d2a17ff5 Binary files /dev/null and b/frontend-ui/src/assets/img/icon/share.png differ diff --git a/frontend-ui/src/assets/img/icon/share_active.png b/frontend-ui/src/assets/img/icon/share_active.png new file mode 100644 index 00000000..13c566bc Binary files /dev/null and b/frontend-ui/src/assets/img/icon/share_active.png differ diff --git a/frontend-ui/src/assets/img/icon/share_disabled.png b/frontend-ui/src/assets/img/icon/share_disabled.png new file mode 100644 index 00000000..44ca81e8 Binary files /dev/null and b/frontend-ui/src/assets/img/icon/share_disabled.png differ diff --git a/frontend-ui/src/assets/img/icon/share_hover.png b/frontend-ui/src/assets/img/icon/share_hover.png new file mode 100644 index 00000000..fa6743d6 Binary files /dev/null and b/frontend-ui/src/assets/img/icon/share_hover.png differ diff --git a/frontend-ui/src/assets/img/icon/switch.png b/frontend-ui/src/assets/img/icon/switch.png new file mode 100644 index 00000000..c40a81c5 Binary files /dev/null and b/frontend-ui/src/assets/img/icon/switch.png differ diff --git a/frontend-ui/src/assets/img/icon/up.png b/frontend-ui/src/assets/img/icon/up.png new file mode 100644 index 00000000..b017add4 Binary files /dev/null and b/frontend-ui/src/assets/img/icon/up.png differ diff --git a/frontend-ui/src/assets/img/icon/update.png b/frontend-ui/src/assets/img/icon/update.png new file mode 100644 index 00000000..5964711f Binary files /dev/null and b/frontend-ui/src/assets/img/icon/update.png differ diff --git a/frontend-ui/src/assets/img/icon/update_active.png b/frontend-ui/src/assets/img/icon/update_active.png new file mode 100644 index 00000000..904c0cb0 Binary files /dev/null and b/frontend-ui/src/assets/img/icon/update_active.png differ diff --git a/frontend-ui/src/assets/img/icon/update_disabled.png b/frontend-ui/src/assets/img/icon/update_disabled.png new file mode 100644 index 00000000..be6d9122 Binary files /dev/null and b/frontend-ui/src/assets/img/icon/update_disabled.png differ diff --git a/frontend-ui/src/assets/img/icon/update_hover.png b/frontend-ui/src/assets/img/icon/update_hover.png new file mode 100644 index 00000000..79470b76 Binary files /dev/null and b/frontend-ui/src/assets/img/icon/update_hover.png differ diff --git a/frontend-ui/src/assets/img/oath/1.png b/frontend-ui/src/assets/img/oath/1.png new file mode 100644 index 00000000..2fefd5a0 Binary files /dev/null and b/frontend-ui/src/assets/img/oath/1.png differ diff --git a/frontend-ui/src/assets/img/oath/2.png b/frontend-ui/src/assets/img/oath/2.png new file mode 100644 index 00000000..b22d381e Binary files /dev/null and b/frontend-ui/src/assets/img/oath/2.png differ diff --git a/frontend-ui/src/assets/img/oath/active.png b/frontend-ui/src/assets/img/oath/active.png new file mode 100755 index 00000000..6802c187 Binary files /dev/null and b/frontend-ui/src/assets/img/oath/active.png differ diff --git a/frontend-ui/src/assets/img/oath/disabled.png b/frontend-ui/src/assets/img/oath/disabled.png new file mode 100755 index 00000000..4a44cde1 Binary files /dev/null and b/frontend-ui/src/assets/img/oath/disabled.png differ diff --git a/frontend-ui/src/assets/img/share.png b/frontend-ui/src/assets/img/share.png new file mode 100644 index 00000000..4a1a73d7 Binary files /dev/null and b/frontend-ui/src/assets/img/share.png differ diff --git a/frontend-ui/src/assets/img/specificity/lv.png b/frontend-ui/src/assets/img/specificity/lv.png new file mode 100644 index 00000000..98735a7c Binary files /dev/null and b/frontend-ui/src/assets/img/specificity/lv.png differ diff --git a/frontend-ui/src/assets/img/specificity/lv_active.png b/frontend-ui/src/assets/img/specificity/lv_active.png new file mode 100644 index 00000000..f40269df Binary files /dev/null and b/frontend-ui/src/assets/img/specificity/lv_active.png differ diff --git a/frontend-ui/src/assets/img/specificity/lv_master.png b/frontend-ui/src/assets/img/specificity/lv_master.png new file mode 100644 index 00000000..14deca3b Binary files /dev/null and b/frontend-ui/src/assets/img/specificity/lv_master.png differ diff --git a/frontend-ui/src/assets/img/specificity/system.png b/frontend-ui/src/assets/img/specificity/system.png new file mode 100644 index 00000000..a1dc845f Binary files /dev/null and b/frontend-ui/src/assets/img/specificity/system.png differ diff --git a/frontend-ui/src/assets/img/talisman.png b/frontend-ui/src/assets/img/talisman.png new file mode 100644 index 00000000..9ba3d9a0 Binary files /dev/null and b/frontend-ui/src/assets/img/talisman.png differ diff --git a/frontend-ui/src/assets/img/underline.png b/frontend-ui/src/assets/img/underline.png new file mode 100644 index 00000000..b876f525 Binary files /dev/null and b/frontend-ui/src/assets/img/underline.png differ diff --git a/frontend-ui/src/components/base/README b/frontend-ui/src/components/base/README new file mode 100644 index 00000000..1bb61d6c --- /dev/null +++ b/frontend-ui/src/components/base/README @@ -0,0 +1 @@ +无样式的基础组件 diff --git a/frontend-ui/src/components/base/index.ts b/frontend-ui/src/components/base/index.ts new file mode 100644 index 00000000..a2e05bfe --- /dev/null +++ b/frontend-ui/src/components/base/index.ts @@ -0,0 +1 @@ +export { default as NTooltip } from './tooltip' diff --git a/frontend-ui/src/components/base/tooltip.tsx b/frontend-ui/src/components/base/tooltip.tsx new file mode 100644 index 00000000..00761ccc --- /dev/null +++ b/frontend-ui/src/components/base/tooltip.tsx @@ -0,0 +1,173 @@ +import { syncRefs, useVModel } from '@vueuse/core' +import type { CSSProperties, PropType } from 'vue' +import { + Teleport, + Transition, + computed, + defineComponent, + nextTick, + reactive, + ref, + renderSlot, + watch, +} from 'vue' +import { provideShow } from '../hooks/show' + +export const tooltipProps = { + popClass: { + type: String, + }, + position: { + type: String as PropType<'bottom' | 'top' | 'left' | 'right' | 'auto'>, + default: () => 'auto', + }, + offset: { + type: Number, + default: () => 8, + }, + lazy: { + type: Boolean, + default: () => false, + }, + visible: { + type: Boolean, + default: () => false, + }, + disabled: { + type: Boolean, + default: () => false, + }, +} + +export default defineComponent({ + name: 'ITooltip', + props: tooltipProps, + emits: ['change', 'update:visible'], + setup(props, { slots, emit }) { + const isOpen = ref(props.visible) + + syncRefs(useVModel(props, 'visible'), isOpen) + + provideShow(isOpen) + + let timer: NodeJS.Timeout + + const triggerRef = ref() + const popupRef = ref() + + const dropdownPosition = reactive({ x: 0, y: 0 }) + + const isShow = computed( + () => + isOpen.value && + triggerRef.value && + popupRef.value && + dropdownPosition.x + dropdownPosition.y > 0, + ) + + const dropdownStyle = computed(() => { + return { + left: `${dropdownPosition.x}px`, + top: `${dropdownPosition.y}px`, + visibility: isShow.value ? 'visible' : 'hidden', + } + }) + + const mounted = ref(false) + + function onMouseover() { + if (props.disabled) { + return + } + timer = setTimeout( + () => { + isOpen.value = true + emit('change', true) + }, + props.lazy ? 800 : 100, + ) + } + + function onMouseout() { + if (props.disabled) { + return + } + clearTimeout(timer) + isOpen.value = false + emit('change', false) + } + + function resize() { + const trigger = triggerRef.value + const popup = popupRef.value + + if (!!trigger && !!popup) { + const { width, height, left, top } = trigger.getBoundingClientRect() + + const { clientWidth: pWidth, clientHeight: pHeight } = popup + + let x = 0 + let y = 0 + + const offset = props.offset + + switch (props.position) { + case 'auto': + case 'bottom': + x = left + width / 2 + y = top + height + offset + break + case 'top': + x = left + y = top - pHeight - offset + break + case 'left': + x = left - pWidth - offset + y = top + break + case 'right': + x = left + width + offset + y = top + break + } + if (props.position == 'auto') { + x = window.innerWidth - x > 500 ? x + 20 : x - 20 - 310 + y = + window.innerHeight - y > popup.offsetHeight + 50 + ? y + : window.innerHeight - (popup.offsetHeight + 50) + } + dropdownPosition.x = x + dropdownPosition.y = y + } + } + + watch(isOpen, (val) => { + if (val) { + mounted.value = true + } + nextTick(resize) + }) + + return () => { + return ( +
+ {renderSlot(slots, 'default')} + + + {mounted.value && !props.disabled && ( +
+ {renderSlot(slots, 'popper')} +
+ )} +
+
+
+ ) + } + }, +}) diff --git a/frontend-ui/src/components/calc/README b/frontend-ui/src/components/calc/README new file mode 100644 index 00000000..2ad1d84e --- /dev/null +++ b/frontend-ui/src/components/calc/README @@ -0,0 +1 @@ +DNF风格定制组件 diff --git a/frontend-ui/src/components/calc/action-dialog/index.vue b/frontend-ui/src/components/calc/action-dialog/index.vue new file mode 100644 index 00000000..f390834b --- /dev/null +++ b/frontend-ui/src/components/calc/action-dialog/index.vue @@ -0,0 +1,207 @@ + + + diff --git a/frontend-ui/src/components/calc/autocomplete/index.vue b/frontend-ui/src/components/calc/autocomplete/index.vue new file mode 100644 index 00000000..f3d3bd3b --- /dev/null +++ b/frontend-ui/src/components/calc/autocomplete/index.vue @@ -0,0 +1,250 @@ + + + diff --git a/frontend-ui/src/components/calc/button/index.vue b/frontend-ui/src/components/calc/button/index.vue new file mode 100644 index 00000000..1580c10f --- /dev/null +++ b/frontend-ui/src/components/calc/button/index.vue @@ -0,0 +1,120 @@ + + + diff --git a/frontend-ui/src/components/calc/cascader/img/down.png b/frontend-ui/src/components/calc/cascader/img/down.png new file mode 100644 index 00000000..4861b24f Binary files /dev/null and b/frontend-ui/src/components/calc/cascader/img/down.png differ diff --git a/frontend-ui/src/components/calc/cascader/img/img/down.png b/frontend-ui/src/components/calc/cascader/img/img/down.png new file mode 100644 index 00000000..4861b24f Binary files /dev/null and b/frontend-ui/src/components/calc/cascader/img/img/down.png differ diff --git a/frontend-ui/src/components/calc/cascader/img/img/select_down.png b/frontend-ui/src/components/calc/cascader/img/img/select_down.png new file mode 100644 index 00000000..450ba106 Binary files /dev/null and b/frontend-ui/src/components/calc/cascader/img/img/select_down.png differ diff --git a/frontend-ui/src/components/calc/cascader/img/img/select_down_clicked.png b/frontend-ui/src/components/calc/cascader/img/img/select_down_clicked.png new file mode 100644 index 00000000..a51fbeb7 Binary files /dev/null and b/frontend-ui/src/components/calc/cascader/img/img/select_down_clicked.png differ diff --git a/frontend-ui/src/components/calc/cascader/img/img/select_down_disabled.png b/frontend-ui/src/components/calc/cascader/img/img/select_down_disabled.png new file mode 100644 index 00000000..c8d948ea Binary files /dev/null and b/frontend-ui/src/components/calc/cascader/img/img/select_down_disabled.png differ diff --git a/frontend-ui/src/components/calc/cascader/img/img/up.png b/frontend-ui/src/components/calc/cascader/img/img/up.png new file mode 100644 index 00000000..b017add4 Binary files /dev/null and b/frontend-ui/src/components/calc/cascader/img/img/up.png differ diff --git a/frontend-ui/src/components/calc/cascader/img/select_down.png b/frontend-ui/src/components/calc/cascader/img/select_down.png new file mode 100644 index 00000000..450ba106 Binary files /dev/null and b/frontend-ui/src/components/calc/cascader/img/select_down.png differ diff --git a/frontend-ui/src/components/calc/cascader/img/select_down_clicked.png b/frontend-ui/src/components/calc/cascader/img/select_down_clicked.png new file mode 100644 index 00000000..a51fbeb7 Binary files /dev/null and b/frontend-ui/src/components/calc/cascader/img/select_down_clicked.png differ diff --git a/frontend-ui/src/components/calc/cascader/img/select_down_disabled.png b/frontend-ui/src/components/calc/cascader/img/select_down_disabled.png new file mode 100644 index 00000000..c8d948ea Binary files /dev/null and b/frontend-ui/src/components/calc/cascader/img/select_down_disabled.png differ diff --git a/frontend-ui/src/components/calc/cascader/img/up.png b/frontend-ui/src/components/calc/cascader/img/up.png new file mode 100644 index 00000000..b017add4 Binary files /dev/null and b/frontend-ui/src/components/calc/cascader/img/up.png differ diff --git a/frontend-ui/src/components/calc/cascader/index.vue b/frontend-ui/src/components/calc/cascader/index.vue new file mode 100644 index 00000000..f5f59345 --- /dev/null +++ b/frontend-ui/src/components/calc/cascader/index.vue @@ -0,0 +1,277 @@ + + + diff --git a/frontend-ui/src/components/calc/checkbox-group/index.vue b/frontend-ui/src/components/calc/checkbox-group/index.vue new file mode 100644 index 00000000..1010c06f --- /dev/null +++ b/frontend-ui/src/components/calc/checkbox-group/index.vue @@ -0,0 +1,73 @@ + + + diff --git a/frontend-ui/src/components/calc/checkbox/index.vue b/frontend-ui/src/components/calc/checkbox/index.vue new file mode 100644 index 00000000..9a52fed9 --- /dev/null +++ b/frontend-ui/src/components/calc/checkbox/index.vue @@ -0,0 +1,226 @@ + + + diff --git a/frontend-ui/src/components/calc/collapse/index.vue b/frontend-ui/src/components/calc/collapse/index.vue new file mode 100644 index 00000000..0efe864e --- /dev/null +++ b/frontend-ui/src/components/calc/collapse/index.vue @@ -0,0 +1,41 @@ + diff --git a/frontend-ui/src/components/calc/dialog/index.vue b/frontend-ui/src/components/calc/dialog/index.vue new file mode 100644 index 00000000..2f93db30 --- /dev/null +++ b/frontend-ui/src/components/calc/dialog/index.vue @@ -0,0 +1,201 @@ + + + diff --git a/frontend-ui/src/components/calc/iconselect/index.vue b/frontend-ui/src/components/calc/iconselect/index.vue new file mode 100644 index 00000000..4d7baa66 --- /dev/null +++ b/frontend-ui/src/components/calc/iconselect/index.vue @@ -0,0 +1,257 @@ + + + diff --git a/frontend-ui/src/components/calc/index.ts b/frontend-ui/src/components/calc/index.ts new file mode 100644 index 00000000..825c115d --- /dev/null +++ b/frontend-ui/src/components/calc/index.ts @@ -0,0 +1,40 @@ +import type { App } from 'vue' +import Button from './button/index.vue' +import Tabs from './tabs/index.vue' +import Tab from './tab/index.vue' +import Select from './select/index.vue' +import Option from './option/index.vue' +import Menu from './menu/menu.vue' +import Checkbox from './checkbox/index.vue' +import Collapse from './collapse/index.vue' +import Dialog from './dialog/index.vue' +import Tooltip from './tooltip/index.vue' +import Iconselect from './iconselect/index.vue' +import Selection from './selection/index.vue' +import Slider from './slider/index.vue' + +export const components = { + Button, + Tabs, + Option, + Tab, + Select, + Menu, + Checkbox, + Collapse, + Dialog, + Tooltip, + Iconselect, + Selection, + Slider, +} + +export type CalcComponents = typeof components + +export function install(app: App) { + for (const [key, value] of Object.entries(components)) { + app.component(`calc-${key.toLocaleLowerCase()}`, value) + } +} + +export default components diff --git a/frontend-ui/src/components/calc/input/index.vue b/frontend-ui/src/components/calc/input/index.vue new file mode 100644 index 00000000..5331d7da --- /dev/null +++ b/frontend-ui/src/components/calc/input/index.vue @@ -0,0 +1,69 @@ + + + diff --git a/frontend-ui/src/components/calc/item/index.vue b/frontend-ui/src/components/calc/item/index.vue new file mode 100644 index 00000000..996d40aa --- /dev/null +++ b/frontend-ui/src/components/calc/item/index.vue @@ -0,0 +1,4 @@ + diff --git a/frontend-ui/src/components/calc/loading/index.vue b/frontend-ui/src/components/calc/loading/index.vue new file mode 100644 index 00000000..e93202ea --- /dev/null +++ b/frontend-ui/src/components/calc/loading/index.vue @@ -0,0 +1,95 @@ + + + diff --git a/frontend-ui/src/components/calc/menu/img/plus.svg b/frontend-ui/src/components/calc/menu/img/plus.svg new file mode 100644 index 00000000..f92ba0fd --- /dev/null +++ b/frontend-ui/src/components/calc/menu/img/plus.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/frontend-ui/src/components/calc/menu/menu.vue b/frontend-ui/src/components/calc/menu/menu.vue new file mode 100644 index 00000000..ae79b322 --- /dev/null +++ b/frontend-ui/src/components/calc/menu/menu.vue @@ -0,0 +1,73 @@ + + + diff --git a/frontend-ui/src/components/calc/option/index.vue b/frontend-ui/src/components/calc/option/index.vue new file mode 100644 index 00000000..996d40aa --- /dev/null +++ b/frontend-ui/src/components/calc/option/index.vue @@ -0,0 +1,4 @@ + diff --git a/frontend-ui/src/components/calc/pagination/index.vue b/frontend-ui/src/components/calc/pagination/index.vue new file mode 100644 index 00000000..f4aee767 --- /dev/null +++ b/frontend-ui/src/components/calc/pagination/index.vue @@ -0,0 +1,97 @@ + + + diff --git a/frontend-ui/src/components/calc/progress/index.vue b/frontend-ui/src/components/calc/progress/index.vue new file mode 100644 index 00000000..b465ba72 --- /dev/null +++ b/frontend-ui/src/components/calc/progress/index.vue @@ -0,0 +1,51 @@ + + + diff --git a/frontend-ui/src/components/calc/select/img/down.png b/frontend-ui/src/components/calc/select/img/down.png new file mode 100644 index 00000000..4861b24f Binary files /dev/null and b/frontend-ui/src/components/calc/select/img/down.png differ diff --git a/frontend-ui/src/components/calc/select/img/select_down.png b/frontend-ui/src/components/calc/select/img/select_down.png new file mode 100644 index 00000000..450ba106 Binary files /dev/null and b/frontend-ui/src/components/calc/select/img/select_down.png differ diff --git a/frontend-ui/src/components/calc/select/img/select_down_clicked.png b/frontend-ui/src/components/calc/select/img/select_down_clicked.png new file mode 100644 index 00000000..a51fbeb7 Binary files /dev/null and b/frontend-ui/src/components/calc/select/img/select_down_clicked.png differ diff --git a/frontend-ui/src/components/calc/select/img/select_down_disabled.png b/frontend-ui/src/components/calc/select/img/select_down_disabled.png new file mode 100644 index 00000000..c8d948ea Binary files /dev/null and b/frontend-ui/src/components/calc/select/img/select_down_disabled.png differ diff --git a/frontend-ui/src/components/calc/select/img/up.png b/frontend-ui/src/components/calc/select/img/up.png new file mode 100644 index 00000000..b017add4 Binary files /dev/null and b/frontend-ui/src/components/calc/select/img/up.png differ diff --git a/frontend-ui/src/components/calc/select/index.vue b/frontend-ui/src/components/calc/select/index.vue new file mode 100644 index 00000000..c2019b8d --- /dev/null +++ b/frontend-ui/src/components/calc/select/index.vue @@ -0,0 +1,330 @@ + + + diff --git a/frontend-ui/src/components/calc/selection/index.vue b/frontend-ui/src/components/calc/selection/index.vue new file mode 100644 index 00000000..24b57370 --- /dev/null +++ b/frontend-ui/src/components/calc/selection/index.vue @@ -0,0 +1,5 @@ + diff --git a/frontend-ui/src/components/calc/shared.ts b/frontend-ui/src/components/calc/shared.ts new file mode 100644 index 00000000..879e13a8 --- /dev/null +++ b/frontend-ui/src/components/calc/shared.ts @@ -0,0 +1,3 @@ +import type { InjectionKey } from 'vue' + +export const CHECKBOX_GROUP: InjectionKey = Symbol('checkbox-group') diff --git a/frontend-ui/src/components/calc/slider/index.vue b/frontend-ui/src/components/calc/slider/index.vue new file mode 100644 index 00000000..a05249d6 --- /dev/null +++ b/frontend-ui/src/components/calc/slider/index.vue @@ -0,0 +1,211 @@ + + + diff --git a/frontend-ui/src/components/calc/tab/index.vue b/frontend-ui/src/components/calc/tab/index.vue new file mode 100644 index 00000000..52393709 --- /dev/null +++ b/frontend-ui/src/components/calc/tab/index.vue @@ -0,0 +1,24 @@ + diff --git a/frontend-ui/src/components/calc/tabs/constants.ts b/frontend-ui/src/components/calc/tabs/constants.ts new file mode 100644 index 00000000..4577bcc1 --- /dev/null +++ b/frontend-ui/src/components/calc/tabs/constants.ts @@ -0,0 +1,5 @@ +export const AciveSymbol = Symbol('[i-tabs]active') + +export const AciveClassSymbol = Symbol('[i-tabs]active-class') + +export const ChangeActiveSymbol = Symbol('[i-tabs]change-active') diff --git a/frontend-ui/src/components/calc/tabs/index.vue b/frontend-ui/src/components/calc/tabs/index.vue new file mode 100644 index 00000000..8c2589e5 --- /dev/null +++ b/frontend-ui/src/components/calc/tabs/index.vue @@ -0,0 +1,141 @@ + + + diff --git a/frontend-ui/src/components/calc/tooltip/index.vue b/frontend-ui/src/components/calc/tooltip/index.vue new file mode 100644 index 00000000..c4f5578c --- /dev/null +++ b/frontend-ui/src/components/calc/tooltip/index.vue @@ -0,0 +1,28 @@ + + + diff --git a/frontend-ui/src/components/calc/tree/img/collapse_down.png b/frontend-ui/src/components/calc/tree/img/collapse_down.png new file mode 100644 index 00000000..bba85eac Binary files /dev/null and b/frontend-ui/src/components/calc/tree/img/collapse_down.png differ diff --git a/frontend-ui/src/components/calc/tree/img/collapse_up.png b/frontend-ui/src/components/calc/tree/img/collapse_up.png new file mode 100644 index 00000000..9d4c0296 Binary files /dev/null and b/frontend-ui/src/components/calc/tree/img/collapse_up.png differ diff --git a/frontend-ui/src/components/calc/tree/img/dictionary_line.png b/frontend-ui/src/components/calc/tree/img/dictionary_line.png new file mode 100644 index 00000000..1dd4cfd9 Binary files /dev/null and b/frontend-ui/src/components/calc/tree/img/dictionary_line.png differ diff --git a/frontend-ui/src/components/calc/tree/img/item_active.png b/frontend-ui/src/components/calc/tree/img/item_active.png new file mode 100644 index 00000000..50d3f93e Binary files /dev/null and b/frontend-ui/src/components/calc/tree/img/item_active.png differ diff --git a/frontend-ui/src/components/calc/tree/img/item_hover.png b/frontend-ui/src/components/calc/tree/img/item_hover.png new file mode 100644 index 00000000..3c0e1484 Binary files /dev/null and b/frontend-ui/src/components/calc/tree/img/item_hover.png differ diff --git a/frontend-ui/src/components/calc/tree/index.vue b/frontend-ui/src/components/calc/tree/index.vue new file mode 100644 index 00000000..b790bbe3 --- /dev/null +++ b/frontend-ui/src/components/calc/tree/index.vue @@ -0,0 +1,105 @@ + + + diff --git a/frontend-ui/src/components/calc/tree/node.vue b/frontend-ui/src/components/calc/tree/node.vue new file mode 100644 index 00000000..d4f93e55 --- /dev/null +++ b/frontend-ui/src/components/calc/tree/node.vue @@ -0,0 +1,171 @@ + + + diff --git a/frontend-ui/src/components/calc/tree/types.ts b/frontend-ui/src/components/calc/tree/types.ts new file mode 100644 index 00000000..bd4cf8a6 --- /dev/null +++ b/frontend-ui/src/components/calc/tree/types.ts @@ -0,0 +1,10 @@ +export interface TreeNode { + label: string + id?: string | number + value?: any + children?: TreeNode[] + onSelect?: () => void + [key: string]: any +} + +export interface TreeData {} diff --git a/frontend-ui/src/components/dnf/Avatar/List/index.vue b/frontend-ui/src/components/dnf/Avatar/List/index.vue new file mode 100644 index 00000000..f90e74ec --- /dev/null +++ b/frontend-ui/src/components/dnf/Avatar/List/index.vue @@ -0,0 +1,69 @@ + + + + + diff --git a/frontend-ui/src/components/dnf/Emblem/Images/emblem/none.png b/frontend-ui/src/components/dnf/Emblem/Images/emblem/none.png new file mode 100644 index 00000000..373f26ee Binary files /dev/null and b/frontend-ui/src/components/dnf/Emblem/Images/emblem/none.png differ diff --git a/frontend-ui/src/components/dnf/Emblem/Images/emblem/华丽.png b/frontend-ui/src/components/dnf/Emblem/Images/emblem/华丽.png new file mode 100644 index 00000000..a5da15d7 Binary files /dev/null and b/frontend-ui/src/components/dnf/Emblem/Images/emblem/华丽.png differ diff --git a/frontend-ui/src/components/dnf/Emblem/Images/emblem/灿烂.png b/frontend-ui/src/components/dnf/Emblem/Images/emblem/灿烂.png new file mode 100644 index 00000000..3bd742a3 Binary files /dev/null and b/frontend-ui/src/components/dnf/Emblem/Images/emblem/灿烂.png differ diff --git a/frontend-ui/src/components/dnf/Emblem/Images/emblem/白金.png b/frontend-ui/src/components/dnf/Emblem/Images/emblem/白金.png new file mode 100644 index 00000000..7868a974 Binary files /dev/null and b/frontend-ui/src/components/dnf/Emblem/Images/emblem/白金.png differ diff --git a/frontend-ui/src/components/dnf/Emblem/Images/emblem/神圣.png b/frontend-ui/src/components/dnf/Emblem/Images/emblem/神圣.png new file mode 100644 index 00000000..3ed1dce8 Binary files /dev/null and b/frontend-ui/src/components/dnf/Emblem/Images/emblem/神圣.png differ diff --git a/frontend-ui/src/components/dnf/Emblem/Images/emblem/闪耀.png b/frontend-ui/src/components/dnf/Emblem/Images/emblem/闪耀.png new file mode 100644 index 00000000..0e1678d0 Binary files /dev/null and b/frontend-ui/src/components/dnf/Emblem/Images/emblem/闪耀.png differ diff --git a/frontend-ui/src/components/dnf/Emblem/Images/head.png b/frontend-ui/src/components/dnf/Emblem/Images/head.png new file mode 100644 index 00000000..4e632c4e Binary files /dev/null and b/frontend-ui/src/components/dnf/Emblem/Images/head.png differ diff --git a/frontend-ui/src/components/dnf/Emblem/Images/part/彩色.png b/frontend-ui/src/components/dnf/Emblem/Images/part/彩色.png new file mode 100644 index 00000000..0db4b159 Binary files /dev/null and b/frontend-ui/src/components/dnf/Emblem/Images/part/彩色.png differ diff --git a/frontend-ui/src/components/dnf/Emblem/Images/part/白金.png b/frontend-ui/src/components/dnf/Emblem/Images/part/白金.png new file mode 100644 index 00000000..862e0646 Binary files /dev/null and b/frontend-ui/src/components/dnf/Emblem/Images/part/白金.png differ diff --git a/frontend-ui/src/components/dnf/Emblem/Images/part/红色.png b/frontend-ui/src/components/dnf/Emblem/Images/part/红色.png new file mode 100644 index 00000000..d5f34acc Binary files /dev/null and b/frontend-ui/src/components/dnf/Emblem/Images/part/红色.png differ diff --git a/frontend-ui/src/components/dnf/Emblem/Images/part/绿色.png b/frontend-ui/src/components/dnf/Emblem/Images/part/绿色.png new file mode 100644 index 00000000..40de9d7c Binary files /dev/null and b/frontend-ui/src/components/dnf/Emblem/Images/part/绿色.png differ diff --git a/frontend-ui/src/components/dnf/Emblem/Images/part/蓝色.png b/frontend-ui/src/components/dnf/Emblem/Images/part/蓝色.png new file mode 100644 index 00000000..fe2ebabc Binary files /dev/null and b/frontend-ui/src/components/dnf/Emblem/Images/part/蓝色.png differ diff --git a/frontend-ui/src/components/dnf/Emblem/Images/part/黄色.png b/frontend-ui/src/components/dnf/Emblem/Images/part/黄色.png new file mode 100644 index 00000000..9ffc4039 Binary files /dev/null and b/frontend-ui/src/components/dnf/Emblem/Images/part/黄色.png differ diff --git a/frontend-ui/src/components/dnf/Emblem/Images/rarity/0.png b/frontend-ui/src/components/dnf/Emblem/Images/rarity/0.png new file mode 100644 index 00000000..26e32aa1 Binary files /dev/null and b/frontend-ui/src/components/dnf/Emblem/Images/rarity/0.png differ diff --git a/frontend-ui/src/components/dnf/Emblem/Images/rarity/1.png b/frontend-ui/src/components/dnf/Emblem/Images/rarity/1.png new file mode 100644 index 00000000..f7a5d7f9 Binary files /dev/null and b/frontend-ui/src/components/dnf/Emblem/Images/rarity/1.png differ diff --git a/frontend-ui/src/components/dnf/Emblem/Images/rarity/2.png b/frontend-ui/src/components/dnf/Emblem/Images/rarity/2.png new file mode 100644 index 00000000..8517bc29 Binary files /dev/null and b/frontend-ui/src/components/dnf/Emblem/Images/rarity/2.png differ diff --git a/frontend-ui/src/components/dnf/Emblem/Images/rarity/3.png b/frontend-ui/src/components/dnf/Emblem/Images/rarity/3.png new file mode 100644 index 00000000..7ee84298 Binary files /dev/null and b/frontend-ui/src/components/dnf/Emblem/Images/rarity/3.png differ diff --git a/frontend-ui/src/components/dnf/Emblem/List/index.vue b/frontend-ui/src/components/dnf/Emblem/List/index.vue new file mode 100644 index 00000000..eb118342 --- /dev/null +++ b/frontend-ui/src/components/dnf/Emblem/List/index.vue @@ -0,0 +1,135 @@ + + + + + diff --git a/frontend-ui/src/components/dnf/Equipment/Icon/index.vue b/frontend-ui/src/components/dnf/Equipment/Icon/index.vue new file mode 100644 index 00000000..220e09e4 --- /dev/null +++ b/frontend-ui/src/components/dnf/Equipment/Icon/index.vue @@ -0,0 +1,84 @@ + + + +`` + + diff --git a/frontend-ui/src/components/dnf/Equipment/Icon/rarity/artifact.png b/frontend-ui/src/components/dnf/Equipment/Icon/rarity/artifact.png new file mode 100644 index 00000000..12d0d063 Binary files /dev/null and b/frontend-ui/src/components/dnf/Equipment/Icon/rarity/artifact.png differ diff --git a/frontend-ui/src/components/dnf/Equipment/Icon/rarity/epic.png b/frontend-ui/src/components/dnf/Equipment/Icon/rarity/epic.png new file mode 100644 index 00000000..9166969d Binary files /dev/null and b/frontend-ui/src/components/dnf/Equipment/Icon/rarity/epic.png differ diff --git a/frontend-ui/src/components/dnf/Equipment/Icon/rarity/legend.png b/frontend-ui/src/components/dnf/Equipment/Icon/rarity/legend.png new file mode 100644 index 00000000..8162c33b Binary files /dev/null and b/frontend-ui/src/components/dnf/Equipment/Icon/rarity/legend.png differ diff --git a/frontend-ui/src/components/dnf/Equipment/Icon/rarity/primeval.png b/frontend-ui/src/components/dnf/Equipment/Icon/rarity/primeval.png new file mode 100644 index 00000000..2efcc308 Binary files /dev/null and b/frontend-ui/src/components/dnf/Equipment/Icon/rarity/primeval.png differ diff --git a/frontend-ui/src/components/dnf/Equipment/Icon/rarity/rare.png b/frontend-ui/src/components/dnf/Equipment/Icon/rarity/rare.png new file mode 100644 index 00000000..618085ed Binary files /dev/null and b/frontend-ui/src/components/dnf/Equipment/Icon/rarity/rare.png differ diff --git a/frontend-ui/src/components/dnf/Equipment/Info/index.vue b/frontend-ui/src/components/dnf/Equipment/Info/index.vue new file mode 100644 index 00000000..1d09bc52 --- /dev/null +++ b/frontend-ui/src/components/dnf/Equipment/Info/index.vue @@ -0,0 +1,115 @@ + + + + + diff --git a/frontend-ui/src/components/dnf/Equipment/List/index.vue b/frontend-ui/src/components/dnf/Equipment/List/index.vue new file mode 100644 index 00000000..3363dd0b --- /dev/null +++ b/frontend-ui/src/components/dnf/Equipment/List/index.vue @@ -0,0 +1,155 @@ + + + + + diff --git a/frontend-ui/src/components/dnf/Equipment/Oath/index.vue b/frontend-ui/src/components/dnf/Equipment/Oath/index.vue new file mode 100644 index 00000000..ed3f80c2 --- /dev/null +++ b/frontend-ui/src/components/dnf/Equipment/Oath/index.vue @@ -0,0 +1,182 @@ + + + + + diff --git a/frontend-ui/src/components/dnf/Equipment/Oath/info.vue b/frontend-ui/src/components/dnf/Equipment/Oath/info.vue new file mode 100644 index 00000000..e69de29b diff --git a/frontend-ui/src/components/dnf/Equipment/PartSelect/index.vue b/frontend-ui/src/components/dnf/Equipment/PartSelect/index.vue new file mode 100644 index 00000000..e70f816f --- /dev/null +++ b/frontend-ui/src/components/dnf/Equipment/PartSelect/index.vue @@ -0,0 +1,129 @@ + + + diff --git a/frontend-ui/src/components/dnf/Equipment/RaritySelect/index.vue b/frontend-ui/src/components/dnf/Equipment/RaritySelect/index.vue new file mode 100644 index 00000000..6bfd488b --- /dev/null +++ b/frontend-ui/src/components/dnf/Equipment/RaritySelect/index.vue @@ -0,0 +1,57 @@ + + + + + diff --git a/frontend-ui/src/components/dnf/Equipment/SuitInfo/index.vue b/frontend-ui/src/components/dnf/Equipment/SuitInfo/index.vue new file mode 100644 index 00000000..efd6968e --- /dev/null +++ b/frontend-ui/src/components/dnf/Equipment/SuitInfo/index.vue @@ -0,0 +1,98 @@ + + + + + diff --git a/frontend-ui/src/components/hooks/README b/frontend-ui/src/components/hooks/README new file mode 100644 index 00000000..f5efaf4e --- /dev/null +++ b/frontend-ui/src/components/hooks/README @@ -0,0 +1 @@ +通用的函数式组件 diff --git a/frontend-ui/src/components/hooks/dialog.ts b/frontend-ui/src/components/hooks/dialog.ts new file mode 100644 index 00000000..a59bb1a4 --- /dev/null +++ b/frontend-ui/src/components/hooks/dialog.ts @@ -0,0 +1,214 @@ +import { h, reactive, renderList } from 'vue' +import { createSharedComposable } from '@vueuse/core' +import ActionDialog from '@/components/calc/action-dialog/index.vue' +import type { JSX } from 'vue/jsx-runtime' + +export type ConfirmDialogOption = Omit +export type AlertDialogOption = Omit +export type ElementLike = JSX.Element | string | ElementLike[] + +function randomId() { + return Symbol(Math.random().toString(36).slice(2, 9)) +} + +type DialogID = string | number | symbol + +export interface ShowDialogOption { + id?: DialogID + /** + * 标题 + */ + header?: string | boolean + /** + * 内容插槽 + */ + content?: (() => ElementLike) | ElementLike + /** + * 操作区插槽 + */ + action?: (() => ElementLike) | ElementLike + + cache?: boolean + + /** + * 超时自动关闭 + */ + timeout?: number + + /** + * 关闭时的延迟动画 + */ + duration?: number + + /** + * 确定按钮文本 为false时不显示 + */ + okButton?: string | boolean + /** + * 取消按钮文本 为false时不显示 + */ + cancelButton?: string | boolean + /** + * 拒绝按钮文本 为false时不显示 + */ + rejectButton?: string | boolean + + // 默认状态 + defaultStatus?: DialogResult['status'] + + mask?: boolean + + scale?: number +} + +export interface DialogInstance { + id?: DialogID + visible: boolean + render: (visible?: boolean) => ElementLike + resolve: (result: DialogResult) => void +} + +export interface DialogResult { + id: DialogID + status: 'ok' | 'reject' | 'cancel' | 'none' + data?: any + readonly isOk: boolean + readonly isCancel: boolean + readonly isReject: boolean +} + +export const useDialog = createSharedComposable(() => { + const dialogs = reactive(new Map()) + + // 注册窗口 + function open(dialog: DialogInstance) { + const id = dialog.id ?? randomId() + dialogs.set(id, dialog) + return id + } + + function close(id: DialogID, status = 'cancel', duration = 400) { + const dialog = dialogs.get(id) + if (!dialog) { + return + } + dialog.resolve({ + id, + status: 'ok', + get isOk() { + return status == 'ok' + }, + get isCancel() { + return status == 'cancel' + }, + get isReject() { + return status == 'reject' + }, + }) + dialog.visible = false + const fn = () => dialogs.delete(id) + if (duration > 0) { + setTimeout(fn, duration) + } else { + fn() + } + } + + function render() { + return renderList(dialogs.values(), (e) => e.render(e.visible)) + } + + async function show(option: ShowDialogOption = {}) { + return new Promise((resolve) => { + const { + id = randomId(), + header = true, + content, + action, + timeout, + okButton = false, + cancelButton = false, + rejectButton = false, + defaultStatus = 'none', + duration = 400, + mask = false, + scale = 1.0, + } = option + + const onClose = (status: DialogResult['status'] = defaultStatus) => { + close(id, status, duration) + } + + open({ + id, + visible: true, + resolve, + render(visible = true) { + return h( + ActionDialog, + { + header, + okButton, + cancelButton, + rejectButton, + visible, + onClose, + mask, + scale, + }, + { + default() { + switch (typeof content) { + case 'function': + return content() + case 'string': + return h( + 'div', + { + class: 'w-full justify-center text-#d4d6b6 text-center', + style: 'margin:10px', + }, + content, + ) + default: + return content + } + }, + action: typeof action == 'function' || !action ? action : () => action, + }, + ) + }, + }) + + if (timeout) { + setTimeout(onClose, timeout) + } + }) + } + + async function alert(option: AlertDialogOption = {}) { + return show({ + ...option, + defaultStatus: 'ok', + okButton: true, + cancelButton: false, + }) + } + + async function confirm(option: ConfirmDialogOption = {}) { + return show({ + ...option, + defaultStatus: 'cancel', + okButton: true, + cancelButton: true, + }) + } + return { + confirm, + alert, + render, + show, + close, + randomId, + } +}) diff --git a/frontend-ui/src/components/hooks/show.ts b/frontend-ui/src/components/hooks/show.ts new file mode 100644 index 00000000..8a47c5eb --- /dev/null +++ b/frontend-ui/src/components/hooks/show.ts @@ -0,0 +1,29 @@ +import type { Fn } from '@vueuse/core' +import type { InjectionKey, Ref } from 'vue' +import { inject, provide, ref, watch } from 'vue' + +const IsOpenSymbol: InjectionKey> = Symbol('is-open') + +export function isShow() { + return inject(IsOpenSymbol, ref(false)) +} + +interface OnShowOption { + immediate?: boolean +} + +export function onShow(fn: Fn, { immediate = false }: OnShowOption = {}) { + return watch( + isShow(), + (val) => { + if (val) { + fn() + } + }, + { immediate }, + ) +} + +export function provideShow(ref: Ref) { + provide(IsOpenSymbol, ref) +} diff --git a/frontend-ui/src/components/hooks/types.ts b/frontend-ui/src/components/hooks/types.ts new file mode 100644 index 00000000..6b879ca9 --- /dev/null +++ b/frontend-ui/src/components/hooks/types.ts @@ -0,0 +1,13 @@ +import type { PropType } from 'vue' + +export type ClassType = string | string[] + +export type BaseType = string | number | boolean | object | symbol | undefined + +export const valuePropType = [String, Number, Object, Boolean, Array] as PropType + +export const classPropType = [String, Array] as PropType + +export const labelPropType = [String, Function] as PropType< + string | ((val?: BaseType) => string) | null +> diff --git a/frontend-ui/src/components/ui/badge/UiBadge.vue b/frontend-ui/src/components/ui/badge/UiBadge.vue new file mode 100644 index 00000000..37c6c396 --- /dev/null +++ b/frontend-ui/src/components/ui/badge/UiBadge.vue @@ -0,0 +1,24 @@ + + + diff --git a/frontend-ui/src/components/ui/badge/badgeVariants.ts b/frontend-ui/src/components/ui/badge/badgeVariants.ts new file mode 100644 index 00000000..bea0d658 --- /dev/null +++ b/frontend-ui/src/components/ui/badge/badgeVariants.ts @@ -0,0 +1,20 @@ +import { cva, type VariantProps } from 'class-variance-authority' + +export const badgeVariants = cva( + 'inline-flex h-[18px] items-center rounded-none border px-[7px] text-[10px] font-normal leading-none', + { + variants: { + variant: { + default: 'border-border bg-primary text-primary-foreground', + secondary: 'border-border bg-secondary text-secondary-foreground', + outline: 'border-border bg-transparent text-foreground', + destructive: 'border-destructive bg-destructive text-destructive-foreground', + }, + }, + defaultVariants: { + variant: 'default', + }, + }, +) + +export type BadgeVariants = VariantProps diff --git a/frontend-ui/src/components/ui/badge/index.ts b/frontend-ui/src/components/ui/badge/index.ts new file mode 100644 index 00000000..3a2fbe1f --- /dev/null +++ b/frontend-ui/src/components/ui/badge/index.ts @@ -0,0 +1,2 @@ +export { default as UiBadge } from './UiBadge.vue' +export { badgeVariants, type BadgeVariants } from './badgeVariants' diff --git a/frontend-ui/src/components/ui/button/UiButton.vue b/frontend-ui/src/components/ui/button/UiButton.vue new file mode 100644 index 00000000..ef832721 --- /dev/null +++ b/frontend-ui/src/components/ui/button/UiButton.vue @@ -0,0 +1,34 @@ + + + diff --git a/frontend-ui/src/components/ui/button/buttonVariants.ts b/frontend-ui/src/components/ui/button/buttonVariants.ts new file mode 100644 index 00000000..fb1778cf --- /dev/null +++ b/frontend-ui/src/components/ui/button/buttonVariants.ts @@ -0,0 +1,28 @@ +import { cva, type VariantProps } from 'class-variance-authority' + +export const buttonVariants = cva( + 'ui-button inline-flex items-center justify-center gap-2 whitespace-nowrap outline-none transition-[color,background,border-color,transform] disabled:pointer-events-none [&_[data-icon]]:pointer-events-none [&_[data-icon]]:shrink-0', + { + variants: { + variant: { + primary: 'ui-button--primary', + secondary: 'ui-button--secondary', + outline: 'ui-button--outline', + destructive: 'ui-button--destructive', + ghost: 'ui-button--ghost', + }, + size: { + default: 'h-[30px] min-w-[110px] px-[14px] text-[13px]', + sm: 'h-6 min-w-20 px-2.5 text-xs', + lg: 'h-11 min-w-[168px] px-5 text-base', + icon: 'size-[30px] min-w-[30px] p-0', + }, + }, + defaultVariants: { + variant: 'primary', + size: 'default', + }, + }, +) + +export type ButtonVariants = VariantProps diff --git a/frontend-ui/src/components/ui/button/index.ts b/frontend-ui/src/components/ui/button/index.ts new file mode 100644 index 00000000..f6e8cd6a --- /dev/null +++ b/frontend-ui/src/components/ui/button/index.ts @@ -0,0 +1,2 @@ +export { default as UiButton } from './UiButton.vue' +export { buttonVariants, type ButtonVariants } from './buttonVariants' diff --git a/frontend-ui/src/components/ui/checkbox/UiCheckbox.vue b/frontend-ui/src/components/ui/checkbox/UiCheckbox.vue new file mode 100644 index 00000000..a849c45d --- /dev/null +++ b/frontend-ui/src/components/ui/checkbox/UiCheckbox.vue @@ -0,0 +1,94 @@ + + + + + diff --git a/frontend-ui/src/components/ui/checkbox/index.ts b/frontend-ui/src/components/ui/checkbox/index.ts new file mode 100644 index 00000000..b296ac73 --- /dev/null +++ b/frontend-ui/src/components/ui/checkbox/index.ts @@ -0,0 +1 @@ +export { default as UiCheckbox } from './UiCheckbox.vue' diff --git a/frontend-ui/src/components/ui/data-table/UiDataTable.vue b/frontend-ui/src/components/ui/data-table/UiDataTable.vue new file mode 100644 index 00000000..1a9380a0 --- /dev/null +++ b/frontend-ui/src/components/ui/data-table/UiDataTable.vue @@ -0,0 +1,173 @@ + + + + + diff --git a/frontend-ui/src/components/ui/data-table/index.ts b/frontend-ui/src/components/ui/data-table/index.ts new file mode 100644 index 00000000..489c129f --- /dev/null +++ b/frontend-ui/src/components/ui/data-table/index.ts @@ -0,0 +1,2 @@ +export { default as UiDataTable } from './UiDataTable.vue' +export type { UiDataTableColumn, UiDataTableRow } from './UiDataTable.vue' diff --git a/frontend-ui/src/components/ui/dialog/UiDialogContent.vue b/frontend-ui/src/components/ui/dialog/UiDialogContent.vue new file mode 100644 index 00000000..26cb1d6f --- /dev/null +++ b/frontend-ui/src/components/ui/dialog/UiDialogContent.vue @@ -0,0 +1,47 @@ + + + + + diff --git a/frontend-ui/src/components/ui/dialog/UiDialogDescription.vue b/frontend-ui/src/components/ui/dialog/UiDialogDescription.vue new file mode 100644 index 00000000..c609f4c9 --- /dev/null +++ b/frontend-ui/src/components/ui/dialog/UiDialogDescription.vue @@ -0,0 +1,20 @@ + + + diff --git a/frontend-ui/src/components/ui/dialog/UiDialogFooter.vue b/frontend-ui/src/components/ui/dialog/UiDialogFooter.vue new file mode 100644 index 00000000..38655003 --- /dev/null +++ b/frontend-ui/src/components/ui/dialog/UiDialogFooter.vue @@ -0,0 +1,18 @@ + + + diff --git a/frontend-ui/src/components/ui/dialog/UiDialogHeader.vue b/frontend-ui/src/components/ui/dialog/UiDialogHeader.vue new file mode 100644 index 00000000..b63e55fb --- /dev/null +++ b/frontend-ui/src/components/ui/dialog/UiDialogHeader.vue @@ -0,0 +1,140 @@ + + + + + diff --git a/frontend-ui/src/components/ui/dialog/UiDialogOverlay.vue b/frontend-ui/src/components/ui/dialog/UiDialogOverlay.vue new file mode 100644 index 00000000..440b189c --- /dev/null +++ b/frontend-ui/src/components/ui/dialog/UiDialogOverlay.vue @@ -0,0 +1,30 @@ + + + + + diff --git a/frontend-ui/src/components/ui/dialog/UiDialogTitle.vue b/frontend-ui/src/components/ui/dialog/UiDialogTitle.vue new file mode 100644 index 00000000..16720693 --- /dev/null +++ b/frontend-ui/src/components/ui/dialog/UiDialogTitle.vue @@ -0,0 +1,20 @@ + + + diff --git a/frontend-ui/src/components/ui/dialog/index.ts b/frontend-ui/src/components/ui/dialog/index.ts new file mode 100644 index 00000000..ea708b91 --- /dev/null +++ b/frontend-ui/src/components/ui/dialog/index.ts @@ -0,0 +1,7 @@ +export { DialogClose, DialogPortal, DialogRoot, DialogTrigger } from 'reka-ui' +export { default as UiDialogContent } from './UiDialogContent.vue' +export { default as UiDialogDescription } from './UiDialogDescription.vue' +export { default as UiDialogFooter } from './UiDialogFooter.vue' +export { default as UiDialogHeader } from './UiDialogHeader.vue' +export { default as UiDialogOverlay } from './UiDialogOverlay.vue' +export { default as UiDialogTitle } from './UiDialogTitle.vue' diff --git a/frontend-ui/src/components/ui/dropdown-menu/UiDropdownMenuContent.vue b/frontend-ui/src/components/ui/dropdown-menu/UiDropdownMenuContent.vue new file mode 100644 index 00000000..6c9c9207 --- /dev/null +++ b/frontend-ui/src/components/ui/dropdown-menu/UiDropdownMenuContent.vue @@ -0,0 +1,61 @@ + + + + + diff --git a/frontend-ui/src/components/ui/dropdown-menu/UiDropdownMenuItem.vue b/frontend-ui/src/components/ui/dropdown-menu/UiDropdownMenuItem.vue new file mode 100644 index 00000000..45c3d5e3 --- /dev/null +++ b/frontend-ui/src/components/ui/dropdown-menu/UiDropdownMenuItem.vue @@ -0,0 +1,59 @@ + + + + + diff --git a/frontend-ui/src/components/ui/dropdown-menu/index.ts b/frontend-ui/src/components/ui/dropdown-menu/index.ts new file mode 100644 index 00000000..6931b374 --- /dev/null +++ b/frontend-ui/src/components/ui/dropdown-menu/index.ts @@ -0,0 +1,9 @@ +export { + DropdownMenuGroup, + DropdownMenuLabel, + DropdownMenuRoot, + DropdownMenuSeparator, + DropdownMenuTrigger, +} from 'reka-ui' +export { default as UiDropdownMenuContent } from './UiDropdownMenuContent.vue' +export { default as UiDropdownMenuItem } from './UiDropdownMenuItem.vue' diff --git a/frontend-ui/src/components/ui/input/UiInput.vue b/frontend-ui/src/components/ui/input/UiInput.vue new file mode 100644 index 00000000..057accc2 --- /dev/null +++ b/frontend-ui/src/components/ui/input/UiInput.vue @@ -0,0 +1,57 @@ + + + + + diff --git a/frontend-ui/src/components/ui/input/index.ts b/frontend-ui/src/components/ui/input/index.ts new file mode 100644 index 00000000..ad141f55 --- /dev/null +++ b/frontend-ui/src/components/ui/input/index.ts @@ -0,0 +1 @@ +export { default as UiInput } from './UiInput.vue' diff --git a/frontend-ui/src/components/ui/item-slot/UiItemSlot.vue b/frontend-ui/src/components/ui/item-slot/UiItemSlot.vue new file mode 100644 index 00000000..b7a9319d --- /dev/null +++ b/frontend-ui/src/components/ui/item-slot/UiItemSlot.vue @@ -0,0 +1,97 @@ + + + + + diff --git a/frontend-ui/src/components/ui/item-slot/index.ts b/frontend-ui/src/components/ui/item-slot/index.ts new file mode 100644 index 00000000..6a1b9f56 --- /dev/null +++ b/frontend-ui/src/components/ui/item-slot/index.ts @@ -0,0 +1 @@ +export { default as UiItemSlot } from './UiItemSlot.vue' diff --git a/frontend-ui/src/components/ui/number-field/UiNumberField.vue b/frontend-ui/src/components/ui/number-field/UiNumberField.vue new file mode 100644 index 00000000..5dcf4dda --- /dev/null +++ b/frontend-ui/src/components/ui/number-field/UiNumberField.vue @@ -0,0 +1,224 @@ + + + + + diff --git a/frontend-ui/src/components/ui/number-field/index.ts b/frontend-ui/src/components/ui/number-field/index.ts new file mode 100644 index 00000000..a7441589 --- /dev/null +++ b/frontend-ui/src/components/ui/number-field/index.ts @@ -0,0 +1 @@ +export { default as UiNumberField } from './UiNumberField.vue' diff --git a/frontend-ui/src/components/ui/panel/UiPanel.vue b/frontend-ui/src/components/ui/panel/UiPanel.vue new file mode 100644 index 00000000..ae674307 --- /dev/null +++ b/frontend-ui/src/components/ui/panel/UiPanel.vue @@ -0,0 +1,77 @@ + + + + + diff --git a/frontend-ui/src/components/ui/panel/index.ts b/frontend-ui/src/components/ui/panel/index.ts new file mode 100644 index 00000000..2a1e1534 --- /dev/null +++ b/frontend-ui/src/components/ui/panel/index.ts @@ -0,0 +1 @@ +export { default as UiPanel } from './UiPanel.vue' diff --git a/frontend-ui/src/components/ui/progress/UiProgress.vue b/frontend-ui/src/components/ui/progress/UiProgress.vue new file mode 100644 index 00000000..b7ce8588 --- /dev/null +++ b/frontend-ui/src/components/ui/progress/UiProgress.vue @@ -0,0 +1,54 @@ + + + + + diff --git a/frontend-ui/src/components/ui/progress/index.ts b/frontend-ui/src/components/ui/progress/index.ts new file mode 100644 index 00000000..60251a24 --- /dev/null +++ b/frontend-ui/src/components/ui/progress/index.ts @@ -0,0 +1 @@ +export { default as UiProgress } from './UiProgress.vue' diff --git a/frontend-ui/src/components/ui/radio-group/UiRadioGroup.vue b/frontend-ui/src/components/ui/radio-group/UiRadioGroup.vue new file mode 100644 index 00000000..006a0844 --- /dev/null +++ b/frontend-ui/src/components/ui/radio-group/UiRadioGroup.vue @@ -0,0 +1,31 @@ + + + + + diff --git a/frontend-ui/src/components/ui/radio-group/UiRadioGroupItem.vue b/frontend-ui/src/components/ui/radio-group/UiRadioGroupItem.vue new file mode 100644 index 00000000..4fc65e3c --- /dev/null +++ b/frontend-ui/src/components/ui/radio-group/UiRadioGroupItem.vue @@ -0,0 +1,76 @@ + + + + + diff --git a/frontend-ui/src/components/ui/radio-group/index.ts b/frontend-ui/src/components/ui/radio-group/index.ts new file mode 100644 index 00000000..9069bb98 --- /dev/null +++ b/frontend-ui/src/components/ui/radio-group/index.ts @@ -0,0 +1,2 @@ +export { default as UiRadioGroup } from './UiRadioGroup.vue' +export { default as UiRadioGroupItem } from './UiRadioGroupItem.vue' diff --git a/frontend-ui/src/components/ui/rating/UiRating.vue b/frontend-ui/src/components/ui/rating/UiRating.vue new file mode 100644 index 00000000..39f66b46 --- /dev/null +++ b/frontend-ui/src/components/ui/rating/UiRating.vue @@ -0,0 +1,88 @@ + + + + + diff --git a/frontend-ui/src/components/ui/rating/index.ts b/frontend-ui/src/components/ui/rating/index.ts new file mode 100644 index 00000000..f432de8b --- /dev/null +++ b/frontend-ui/src/components/ui/rating/index.ts @@ -0,0 +1 @@ +export { default as UiRating } from './UiRating.vue' diff --git a/frontend-ui/src/components/ui/select/UiSelectContent.vue b/frontend-ui/src/components/ui/select/UiSelectContent.vue new file mode 100644 index 00000000..702da2cb --- /dev/null +++ b/frontend-ui/src/components/ui/select/UiSelectContent.vue @@ -0,0 +1,75 @@ + + + + + diff --git a/frontend-ui/src/components/ui/select/UiSelectItem.vue b/frontend-ui/src/components/ui/select/UiSelectItem.vue new file mode 100644 index 00000000..0dd1f867 --- /dev/null +++ b/frontend-ui/src/components/ui/select/UiSelectItem.vue @@ -0,0 +1,66 @@ + + + + + diff --git a/frontend-ui/src/components/ui/select/UiSelectTrigger.vue b/frontend-ui/src/components/ui/select/UiSelectTrigger.vue new file mode 100644 index 00000000..4bd83c43 --- /dev/null +++ b/frontend-ui/src/components/ui/select/UiSelectTrigger.vue @@ -0,0 +1,83 @@ + + + + + diff --git a/frontend-ui/src/components/ui/select/index.ts b/frontend-ui/src/components/ui/select/index.ts new file mode 100644 index 00000000..52dda2da --- /dev/null +++ b/frontend-ui/src/components/ui/select/index.ts @@ -0,0 +1,4 @@ +export { SelectGroup, SelectLabel, SelectRoot, SelectSeparator, SelectValue } from 'reka-ui' +export { default as UiSelectContent } from './UiSelectContent.vue' +export { default as UiSelectItem } from './UiSelectItem.vue' +export { default as UiSelectTrigger } from './UiSelectTrigger.vue' diff --git a/frontend-ui/src/components/ui/slider/UiSlider.vue b/frontend-ui/src/components/ui/slider/UiSlider.vue new file mode 100644 index 00000000..1406ba29 --- /dev/null +++ b/frontend-ui/src/components/ui/slider/UiSlider.vue @@ -0,0 +1,149 @@ + + + + + diff --git a/frontend-ui/src/components/ui/slider/index.ts b/frontend-ui/src/components/ui/slider/index.ts new file mode 100644 index 00000000..27c13481 --- /dev/null +++ b/frontend-ui/src/components/ui/slider/index.ts @@ -0,0 +1 @@ +export { default as UiSlider } from './UiSlider.vue' diff --git a/frontend-ui/src/components/ui/switch/UiSwitch.vue b/frontend-ui/src/components/ui/switch/UiSwitch.vue new file mode 100644 index 00000000..a18d5eb6 --- /dev/null +++ b/frontend-ui/src/components/ui/switch/UiSwitch.vue @@ -0,0 +1,92 @@ + + + + + diff --git a/frontend-ui/src/components/ui/switch/index.ts b/frontend-ui/src/components/ui/switch/index.ts new file mode 100644 index 00000000..e6374362 --- /dev/null +++ b/frontend-ui/src/components/ui/switch/index.ts @@ -0,0 +1 @@ +export { default as UiSwitch } from './UiSwitch.vue' diff --git a/frontend-ui/src/components/ui/tabs/UiTabsContent.vue b/frontend-ui/src/components/ui/tabs/UiTabsContent.vue new file mode 100644 index 00000000..dd23b2b1 --- /dev/null +++ b/frontend-ui/src/components/ui/tabs/UiTabsContent.vue @@ -0,0 +1,32 @@ + + + + + diff --git a/frontend-ui/src/components/ui/tabs/UiTabsList.vue b/frontend-ui/src/components/ui/tabs/UiTabsList.vue new file mode 100644 index 00000000..e00a4993 --- /dev/null +++ b/frontend-ui/src/components/ui/tabs/UiTabsList.vue @@ -0,0 +1,148 @@ + + + + + diff --git a/frontend-ui/src/components/ui/tabs/UiTabsTrigger.vue b/frontend-ui/src/components/ui/tabs/UiTabsTrigger.vue new file mode 100644 index 00000000..3f39e54c --- /dev/null +++ b/frontend-ui/src/components/ui/tabs/UiTabsTrigger.vue @@ -0,0 +1,88 @@ + + + + + diff --git a/frontend-ui/src/components/ui/tabs/index.ts b/frontend-ui/src/components/ui/tabs/index.ts new file mode 100644 index 00000000..137f777e --- /dev/null +++ b/frontend-ui/src/components/ui/tabs/index.ts @@ -0,0 +1,4 @@ +export { TabsRoot } from 'reka-ui' +export { default as UiTabsContent } from './UiTabsContent.vue' +export { default as UiTabsList } from './UiTabsList.vue' +export { default as UiTabsTrigger } from './UiTabsTrigger.vue' diff --git a/frontend-ui/src/components/ui/tooltip/UiTooltipContent.vue b/frontend-ui/src/components/ui/tooltip/UiTooltipContent.vue new file mode 100644 index 00000000..a402bb98 --- /dev/null +++ b/frontend-ui/src/components/ui/tooltip/UiTooltipContent.vue @@ -0,0 +1,63 @@ + + + + + diff --git a/frontend-ui/src/components/ui/tooltip/index.ts b/frontend-ui/src/components/ui/tooltip/index.ts new file mode 100644 index 00000000..25bf8915 --- /dev/null +++ b/frontend-ui/src/components/ui/tooltip/index.ts @@ -0,0 +1,2 @@ +export { TooltipProvider, TooltipRoot, TooltipTrigger } from 'reka-ui' +export { default as UiTooltipContent } from './UiTooltipContent.vue' diff --git a/frontend-ui/src/composables/useTheme.ts b/frontend-ui/src/composables/useTheme.ts new file mode 100644 index 00000000..7ff624e5 --- /dev/null +++ b/frontend-ui/src/composables/useTheme.ts @@ -0,0 +1,49 @@ +import { readonly, shallowRef } from 'vue' + +export const themes = [ + { value: 'dcalc', label: 'DCalc 经典' }, + { value: 'midnight', label: '深海蓝' }, +] as const + +export type ThemeName = (typeof themes)[number]['value'] + +const THEME_STORAGE_KEY = 'dcalc-ui-theme' +const activeTheme = shallowRef('dcalc') +let initialized = false + +function isThemeName(value: string | null): value is ThemeName { + return themes.some((theme) => theme.value === value) +} + +function applyTheme(theme: ThemeName) { + activeTheme.value = theme + + if (typeof document !== 'undefined') { + document.documentElement.dataset.theme = theme + } +} + +export function initializeTheme() { + if (initialized || typeof window === 'undefined') { + return + } + + const storedTheme = window.localStorage.getItem(THEME_STORAGE_KEY) + applyTheme(isThemeName(storedTheme) ? storedTheme : 'dcalc') + initialized = true +} + +export function useTheme() { + initializeTheme() + + function setTheme(theme: ThemeName) { + applyTheme(theme) + window.localStorage.setItem(THEME_STORAGE_KEY, theme) + } + + return { + activeTheme: readonly(activeTheme), + themes, + setTheme, + } +} diff --git a/frontend-ui/src/lib/utils.ts b/frontend-ui/src/lib/utils.ts new file mode 100644 index 00000000..abba253f --- /dev/null +++ b/frontend-ui/src/lib/utils.ts @@ -0,0 +1,7 @@ +import type { ClassValue } from 'clsx' +import { clsx } from 'clsx' +import { twMerge } from 'tailwind-merge' + +export function cn(...inputs: ClassValue[]) { + return twMerge(clsx(inputs)) +} diff --git a/frontend-ui/src/main.ts b/frontend-ui/src/main.ts new file mode 100644 index 00000000..af3ed6b0 --- /dev/null +++ b/frontend-ui/src/main.ts @@ -0,0 +1,23 @@ +import '@/style/index.scss' +import '@/style/tailwind.css' + +import { createApp } from 'vue' +import { pinia } from '@/stores' +import { initializeTheme } from '@/composables/useTheme' + +import App from '@/pages/IndexView.vue' + +import router from './router' + +const appContainer = document.createElement('div') +appContainer.setAttribute('style', 'text-rendering: geometricPrecision;letter-spacing: -0.1px;') +document.body.appendChild(appContainer) + +initializeTheme() + +const app = createApp(App) + +app.use(pinia) +app.use(router) + +app.mount(appContainer) diff --git a/frontend-ui/src/pages/Character/Config/import.vue b/frontend-ui/src/pages/Character/Config/import.vue new file mode 100644 index 00000000..c18e806a --- /dev/null +++ b/frontend-ui/src/pages/Character/Config/import.vue @@ -0,0 +1,72 @@ + diff --git a/frontend-ui/src/pages/Character/Config/importDnfhelper.vue b/frontend-ui/src/pages/Character/Config/importDnfhelper.vue new file mode 100644 index 00000000..663799b8 --- /dev/null +++ b/frontend-ui/src/pages/Character/Config/importDnfhelper.vue @@ -0,0 +1,80 @@ + diff --git a/frontend-ui/src/pages/Character/Config/importSkill.vue b/frontend-ui/src/pages/Character/Config/importSkill.vue new file mode 100644 index 00000000..5a2d775c --- /dev/null +++ b/frontend-ui/src/pages/Character/Config/importSkill.vue @@ -0,0 +1,71 @@ + diff --git a/frontend-ui/src/pages/Character/Equipment/Index.vue b/frontend-ui/src/pages/Character/Equipment/Index.vue new file mode 100644 index 00000000..9f6679ef --- /dev/null +++ b/frontend-ui/src/pages/Character/Equipment/Index.vue @@ -0,0 +1,49 @@ + + + diff --git a/frontend-ui/src/pages/Character/Equipment/components/Else.vue b/frontend-ui/src/pages/Character/Equipment/components/Else.vue new file mode 100644 index 00000000..c8e3ff79 --- /dev/null +++ b/frontend-ui/src/pages/Character/Equipment/components/Else.vue @@ -0,0 +1,49 @@ + + + + + diff --git a/frontend-ui/src/pages/Character/Equipment/components/Stone.vue b/frontend-ui/src/pages/Character/Equipment/components/Stone.vue new file mode 100644 index 00000000..629c1695 --- /dev/null +++ b/frontend-ui/src/pages/Character/Equipment/components/Stone.vue @@ -0,0 +1,97 @@ + + + + + diff --git a/frontend-ui/src/pages/Character/Equipment/components/StoneUniversal.vue b/frontend-ui/src/pages/Character/Equipment/components/StoneUniversal.vue new file mode 100644 index 00000000..7ce2acef --- /dev/null +++ b/frontend-ui/src/pages/Character/Equipment/components/StoneUniversal.vue @@ -0,0 +1,45 @@ + + + + + diff --git a/frontend-ui/src/pages/Character/Equipment/components/SubWeapon.vue b/frontend-ui/src/pages/Character/Equipment/components/SubWeapon.vue new file mode 100644 index 00000000..6c45b358 --- /dev/null +++ b/frontend-ui/src/pages/Character/Equipment/components/SubWeapon.vue @@ -0,0 +1,47 @@ + + + + + diff --git a/frontend-ui/src/pages/Character/Equipment/components/Suit.vue b/frontend-ui/src/pages/Character/Equipment/components/Suit.vue new file mode 100644 index 00000000..e2ccc85d --- /dev/null +++ b/frontend-ui/src/pages/Character/Equipment/components/Suit.vue @@ -0,0 +1,111 @@ + + + + + diff --git a/frontend-ui/src/pages/Character/Equipment/components/Universal.vue b/frontend-ui/src/pages/Character/Equipment/components/Universal.vue new file mode 100644 index 00000000..526db9b1 --- /dev/null +++ b/frontend-ui/src/pages/Character/Equipment/components/Universal.vue @@ -0,0 +1,43 @@ + + + + + diff --git a/frontend-ui/src/pages/Character/Equipment/components/Weapon.vue b/frontend-ui/src/pages/Character/Equipment/components/Weapon.vue new file mode 100644 index 00000000..9b7d8227 --- /dev/null +++ b/frontend-ui/src/pages/Character/Equipment/components/Weapon.vue @@ -0,0 +1,45 @@ + + + + + diff --git a/frontend-ui/src/pages/Character/EquipmentDictionary/Index.vue b/frontend-ui/src/pages/Character/EquipmentDictionary/Index.vue new file mode 100644 index 00000000..1fb565e6 --- /dev/null +++ b/frontend-ui/src/pages/Character/EquipmentDictionary/Index.vue @@ -0,0 +1,496 @@ + + + + diff --git a/frontend-ui/src/pages/Character/EquipmentDictionary/components/options.vue b/frontend-ui/src/pages/Character/EquipmentDictionary/components/options.vue new file mode 100644 index 00000000..8bebc2ac --- /dev/null +++ b/frontend-ui/src/pages/Character/EquipmentDictionary/components/options.vue @@ -0,0 +1,23 @@ + + + diff --git a/frontend-ui/src/pages/Character/EquipmentDictionary/formatData.ts b/frontend-ui/src/pages/Character/EquipmentDictionary/formatData.ts new file mode 100644 index 00000000..5ab2e651 --- /dev/null +++ b/frontend-ui/src/pages/Character/EquipmentDictionary/formatData.ts @@ -0,0 +1,326 @@ +import type { IEquipment } from '@/api/info/type' + +export const rowCount = 10 + +export const formatEqu = (total: IEquipment[], subweapons?: string[], curSuit?: string) => { + // 武器 + const item_weapon = total.filter((a) => a.itemType == '武器') ?? [] + const weapons: (IEquipment | undefined)[] = [] + if (item_weapon.length > 0) { + Array.from(new Set(item_weapon.map((item) => item.rarity))) + .filter((a) => !['稀有', '神器'].includes(a)) + .forEach((rarity) => { + const weapon = item_weapon + .filter((item) => item.rarity === rarity) + .sort((a, b) => { + if (a.categorize == b.categorize) { + return a.itemDetailType.localeCompare(b.itemDetailType) + } + return b.categorize.localeCompare(a.categorize) + }) + weapons.push( + ...weapon.filter((a) => !['传世武器升级', '狄瑞吉传世武器'].includes(a.categorize)), + ) + const remind = weapons.length % rowCount + if (remind > 0) { + weapons.push(...Array(rowCount - remind).fill(undefined)) + } + }) + if (item_weapon.some((a) => a.categorize === '传世武器升级')) { + const length = item_weapon.filter((a) => a.categorize === '传世武器升级').length + weapons.push(...Array(length).fill(undefined)) + weapons.push( + ...item_weapon + .filter((a) => a.categorize === '传世武器升级') + .sort((a, b) => { + return a.itemDetailType.localeCompare(b.itemDetailType) + }), + ) + } + let remind = weapons.length % rowCount + if (remind > 0) { + weapons.push(...Array(rowCount - remind).fill(undefined)) + } + if (item_weapon.some((a) => a.categorize === '狄瑞吉传世武器')) { + const length = item_weapon.filter((a) => a.categorize === '狄瑞吉传世武器').length + weapons.push(...Array(length).fill(undefined)) + weapons.push( + ...item_weapon + .filter((a) => a.categorize === '狄瑞吉传世武器') + .sort((a, b) => { + return a.itemDetailType.localeCompare(b.itemDetailType) + }), + ) + } + remind = weapons.length % rowCount + if (remind > 0) { + weapons.push(...Array(rowCount - remind).fill(undefined)) + } + } + + // # region 副武器 + const subWeapons: (IEquipment | undefined)[] = [] + const item_sub_weapon = (total.filter((a) => subweapons?.includes(a.itemDetailType)) ?? []).sort( + (a, b) => { + if (a.categorize == b.categorize) { + return a.itemDetailType.localeCompare(b.itemDetailType) + } + return b.categorize.localeCompare(a.categorize) + }, + ) + if (item_sub_weapon.length > 0) { + subWeapons.push( + ...item_sub_weapon.map((a) => ({ ...a, itemType: '副武器' })), + ...Array(rowCount - (item_sub_weapon.length % rowCount)).fill(undefined), + ) + } + // # endregion + + // 秘宝 + const item_treasure = total.filter((equip) => equip.categorize.includes('秘宝')) + const treasures: (IEquipment | undefined)[] = [] + if (item_treasure.length > 0) { + treasures.push( + ...item_treasure, + ...Array(rowCount - (item_treasure.length % rowCount)).fill(undefined), + ) + } + // 套装 + const item_suits = total.filter( + (equip) => equip.categorize.includes('套装') || equip.categorize.includes('通宝'), + ) + const suits: (IEquipment | undefined)[] = [] + const raritiyList = Array.from(new Set(item_suits.map((item) => item.rarity))).filter( + (a) => !['稀有', '神器'].includes(a), + ) + raritiyList.forEach((rarity) => { + const armor = item_suits.filter( + (item) => item.rarity === rarity && item.itemType === '防具' && !item.name.includes('侵蚀'), + ) + if (armor.length > 0) { + suits.push(...armor, undefined) + } + + const special = item_suits.filter( + (item) => item.rarity === rarity && item.itemType === '特殊装备', + ) + if (special.length > 0) { + suits.push(...special) + if (suits.length % rowCount > 0) { + suits.push(...Array(rowCount - (suits.length % rowCount)).fill(undefined)) + } + } + + const jewelry = item_suits.filter((item) => item.rarity === rarity && item.itemType === '首饰') + const jewelryNormal = jewelry.filter((a) => !a.name.includes('黑牙')) ?? [] + const jewelryHY = jewelry.filter((a) => a.name.includes('黑牙')) ?? [] + + if (jewelry.length > 0) { + suits.push( + ...Array(3 - jewelryHY.length + 2).fill(undefined), + ...jewelryHY, + undefined, + ...jewelryNormal, + ) + suits.push(...Array(rowCount - (suits.length % rowCount)).fill(undefined)) + } + + const armorUpgrade = item_suits.filter( + (item) => item.rarity === rarity && item.itemType === '防具' && item.name.includes('侵蚀'), + ) + if (armorUpgrade.length > 0) { + suits.push(...armorUpgrade) + } + + if (suits.length % rowCount > 0) { + suits.push(...Array(rowCount - (suits.length % rowCount)).fill(undefined)) + } + }) + // 称号 + const item_title = total.filter((equip) => equip.itemDetailType == '称号') + const title: (IEquipment | undefined)[] = [] + if (item_title.length > 0) { + title.push(...item_title, ...Array(rowCount - (item_title.length % rowCount)).fill(undefined)) + } + // 宠物 + const item_pets = total.filter((equip) => equip.itemDetailType == '宠物') + const pet: (IEquipment | undefined)[] = [] + if (item_pets.length > 0) { + pet.push(...item_pets, ...Array(rowCount - (item_pets.length % rowCount)).fill(undefined)) + } + + // 称号 + return [ + { + name: '武器', + equs: weapons, + }, + { + name: '副武器', + equs: subWeapons, + }, + { + name: '秘宝', + equs: treasures, + }, + { + name: `${curSuit} 套装`, + equs: suits, + }, + { + name: '称号', + equs: title, + }, + { + name: '宠物', + equs: pet, + }, + ] +} + +export const formatStone = (total: IEquipment[], curSuit?: string) => { + // 套装 + const item_suits = total.filter((equip) => equip.suit.length == 1) + const suits: (IEquipment | undefined)[] = [] + const raritiyList = Array.from(new Set(item_suits.map((item) => item.rarity))) + raritiyList.forEach((rarity) => { + const armor = item_suits.filter((item) => item.rarity === rarity && item.itemType === '防具') + if (armor.length > 0) { + suits.push(...armor, undefined) + } + + const special = item_suits.filter( + (item) => item.rarity === rarity && item.itemType === '特殊装备', + ) + if (special.length > 0) { + suits.push(...special) + if (suits.length % rowCount > 0) { + suits.push(...Array(rowCount - (suits.length % rowCount)).fill(undefined)) + } + } + + const jewelry = item_suits.filter((item) => item.rarity === rarity && item.itemType === '首饰') + const jewelryNormal = jewelry.filter((a) => !a.name.includes('黑牙')) ?? [] + const jewelryHY = jewelry.filter((a) => a.name.includes('黑牙')) ?? [] + if (jewelry.length > 0) { + suits.push( + ...Array(3 - jewelryHY.length + 2).fill(undefined), + ...jewelryHY, + undefined, + ...jewelryNormal, + ) + suits.push(...Array(rowCount - (suits.length % rowCount)).fill(undefined)) + } + if (suits.length % rowCount > 0) { + suits.push(...Array(rowCount - (suits.length % rowCount)).fill(undefined)) + } + }) + + const item_suits_wns = total.filter((equip) => equip.categorize.includes('维纳斯通宝')) + const wns: (IEquipment | undefined)[] = [] + const categorizeList = Array.from(new Set(item_suits_wns.map((item) => item.categorize))) + categorizeList.forEach((categorize) => { + ;['神器', '史诗'].forEach((raritiy) => { + const temp = item_suits_wns.filter( + (item) => item.categorize === categorize && item.rarity === raritiy, + ) + const remind = temp.length % (rowCount / 2) + wns.push(...temp, ...Array(temp.length == 0 ? rowCount / 2 - remind : remind).fill(undefined)) + }) + }) + + const item_suits_nbe = total.filter((equip) => equip.categorize.includes('纳波尔通宝')) + const nbes: (IEquipment | undefined)[] = [] + const nbeList = Array.from(new Set(item_suits_nbe.map((item) => item.categorize))) + nbeList.forEach((categorize) => { + ;['神器', '史诗'].forEach((raritiy) => { + const temp = item_suits_nbe.filter( + (item) => item.categorize === categorize && item.rarity === raritiy, + ) + const remind = temp.length % (rowCount / 2) + nbes.push( + ...temp, + ...Array(temp.length == 0 ? rowCount / 2 - remind : remind - 1).fill(undefined), + ) + }) + }) + + const items_suits_rzs = total.filter((equip) => equip.categorize.includes('人造神')) + const rzs: (IEquipment | undefined)[] = [] + const partList = Array.from(new Set(items_suits_rzs.map((item) => item.itemDetailType))) + // const raritiy = Array.from(new Set(items_suits_rzs.map((item) => item.rarity))) + partList.forEach((part) => { + raritiyList.forEach((rarity) => { + const temp = items_suits_rzs.filter( + (item) => item.itemDetailType === part && item.rarity === rarity, + ) + if (temp.length > 0) { + rzs.push(...temp, ...Array(rowCount - temp.length).fill(undefined)) + } + }) + // const temp = items_suits_rzs.filter((item) => item.itemDetailType === part) + // const remind = temp.length % rowCount + // rzs.push(...temp, ...Array(temp.length == 0 ? rowCount-remind : remind).fill(undefined)) + }) + // const items_sj = total.filter((equip) => equip.categorize.includes('神界')) + // const sj: (IEquipment | undefined)[] = [] + // sj.push(...items_sj, ...Array(rowCount * 2 - (items_sj.length % rowCount)).fill(undefined)) + // const temp = items_suits_rzs.filter((item) => item.itemDetailType === part) + // const remind = temp.length % rowCount + // rzs.push(...temp, ...Array(temp.length == 0 ? rowCount-remind : remind).fill(undefined)) + return [ + { + name: `${curSuit} 套装`, + equs: suits, + }, + { + name: '维纳斯通宝', + equs: wns, + }, + { + name: '纳波尔通宝', + equs: nbes, + }, + { + name: '人造神', + equs: rzs, + }, + // { + // name: '神界', + // equs: sj, + // }, + ] +} + +export const formatOath = ( + total: IEquipment[], + curSuit?: { name: string; value: number; imageUrl: string }, +) => { + // oath + const oath = total.filter( + (equip) => equip.itemDetailType == '誓约' && equip.categorize != '通宝装备', + ) + oath.push(...Array(rowCount - (oath.length % rowCount)).fill(undefined)) + // primer + const primer = [] + const primerItem = total.filter( + (equip) => equip.itemDetailType == '星蕴石' && equip.rarity != '稀有', + ) + for (let i = 0; i < 11; i++) { + const temp = primerItem.filter((a) => a.oathPos == i.toString()) + primer.push( + ...temp, + ...Array(temp.length == 0 ? rowCount : rowCount - (temp.length % rowCount)).fill(undefined), + ) + } + return [ + { + name: `${curSuit?.name} 誓约`, + equs: oath, + }, + { + name: `${curSuit?.name} 星蕴石`, + equs: primer, + }, + ] +} diff --git a/frontend-ui/src/pages/Character/Forge/components/Avatars.vue b/frontend-ui/src/pages/Character/Forge/components/Avatars.vue new file mode 100644 index 00000000..cbf9ee43 --- /dev/null +++ b/frontend-ui/src/pages/Character/Forge/components/Avatars.vue @@ -0,0 +1,139 @@ + + + diff --git a/frontend-ui/src/pages/Character/Forge/components/Emblems.vue b/frontend-ui/src/pages/Character/Forge/components/Emblems.vue new file mode 100644 index 00000000..29236dc5 --- /dev/null +++ b/frontend-ui/src/pages/Character/Forge/components/Emblems.vue @@ -0,0 +1,185 @@ + + + diff --git a/frontend-ui/src/pages/Character/Forge/components/Equipments.vue b/frontend-ui/src/pages/Character/Forge/components/Equipments.vue new file mode 100644 index 00000000..86352296 --- /dev/null +++ b/frontend-ui/src/pages/Character/Forge/components/Equipments.vue @@ -0,0 +1,251 @@ + + + diff --git a/frontend-ui/src/pages/Character/Forge/components/Jades.vue b/frontend-ui/src/pages/Character/Forge/components/Jades.vue new file mode 100644 index 00000000..f020b4c1 --- /dev/null +++ b/frontend-ui/src/pages/Character/Forge/components/Jades.vue @@ -0,0 +1,92 @@ + + + diff --git a/frontend-ui/src/pages/Character/Forge/components/Oaths.vue b/frontend-ui/src/pages/Character/Forge/components/Oaths.vue new file mode 100644 index 00000000..1e18bfd7 --- /dev/null +++ b/frontend-ui/src/pages/Character/Forge/components/Oaths.vue @@ -0,0 +1,101 @@ + + + diff --git a/frontend-ui/src/pages/Character/Forge/components/Sundry.vue b/frontend-ui/src/pages/Character/Forge/components/Sundry.vue new file mode 100644 index 00000000..fde66840 --- /dev/null +++ b/frontend-ui/src/pages/Character/Forge/components/Sundry.vue @@ -0,0 +1,140 @@ + + + diff --git a/frontend-ui/src/pages/Character/Forge/index.vue b/frontend-ui/src/pages/Character/Forge/index.vue new file mode 100644 index 00000000..b6ac69ad --- /dev/null +++ b/frontend-ui/src/pages/Character/Forge/index.vue @@ -0,0 +1,58 @@ + + + + diff --git a/frontend-ui/src/pages/Character/Index.vue b/frontend-ui/src/pages/Character/Index.vue new file mode 100644 index 00000000..07a26c8c --- /dev/null +++ b/frontend-ui/src/pages/Character/Index.vue @@ -0,0 +1,166 @@ + + + + + diff --git a/frontend-ui/src/pages/Character/Result/Index.vue b/frontend-ui/src/pages/Character/Result/Index.vue new file mode 100644 index 00000000..98569abf --- /dev/null +++ b/frontend-ui/src/pages/Character/Result/Index.vue @@ -0,0 +1,108 @@ + + + + + diff --git a/frontend-ui/src/pages/Character/Result/components/BufferSkill.vue b/frontend-ui/src/pages/Character/Result/components/BufferSkill.vue new file mode 100644 index 00000000..3bf16ed5 --- /dev/null +++ b/frontend-ui/src/pages/Character/Result/components/BufferSkill.vue @@ -0,0 +1,247 @@ + + + + + diff --git a/frontend-ui/src/pages/Character/Result/components/Info.vue b/frontend-ui/src/pages/Character/Result/components/Info.vue new file mode 100644 index 00000000..4885755b --- /dev/null +++ b/frontend-ui/src/pages/Character/Result/components/Info.vue @@ -0,0 +1,325 @@ + + + + + diff --git a/frontend-ui/src/pages/Character/Result/components/Skill.vue b/frontend-ui/src/pages/Character/Result/components/Skill.vue new file mode 100644 index 00000000..dedd372e --- /dev/null +++ b/frontend-ui/src/pages/Character/Result/components/Skill.vue @@ -0,0 +1,299 @@ + + + + + diff --git a/frontend-ui/src/pages/Character/Skill/components/SkillDetail/index.tsx b/frontend-ui/src/pages/Character/Skill/components/SkillDetail/index.tsx new file mode 100644 index 00000000..79603358 --- /dev/null +++ b/frontend-ui/src/pages/Character/Skill/components/SkillDetail/index.tsx @@ -0,0 +1,183 @@ +import { asyncComputed } from '@vueuse/core' +import api from '@/api' +import './style.scss' +import CalcTabs from '@/components/calc/tabs/index.vue' +import CalcTab from '@/components/calc/tab/index.vue' + +export default defineComponent({ + name: 'SkillDetail', + props: { + skillId: { + type: String, + required: true, + }, + level: { + type: Number, + default: 1, + }, + }, + setup(props) { + const currentSkill = computed(() => props.skillId) + const currentLevel = computed(() => props.level) + + const skillInfo = asyncComputed(async () => { + if (!currentSkill.value && !currentLevel.value) return undefined + const res = await api.skillDetail(currentSkill.value, currentLevel.value) + return res + }) + + const curTab = ref(0) + + const basic = computed(() => + !skillInfo.value + ? [] + : [ + { label: '技能等级', value: skillInfo.value?.attribute?.level ?? props.level }, + { label: '学习等级', value: skillInfo.value?.requiredLevel }, + { label: '等级上限', value: skillInfo.value?.maxLevel }, + { + label: '冷却时间', + value: skillInfo.value?.attribute?.coolTime + ? `${skillInfo.value?.attribute?.coolTime.toFixed(1)}秒` + : undefined, + }, + { + label: '施放时间', + value: !skillInfo.value?.attribute?.castingTime + ? '瞬发' + : `${skillInfo.value?.attribute?.castingTime.toFixed(1)}秒`, + }, + { label: '魔法值', value: skillInfo.value?.attribute?.consumeMp }, + { + label: '消耗无色小晶块', + value: skillInfo.value?.consumeItem?.value + ? `${skillInfo.value?.consumeItem?.value}个` + : undefined, + }, + ], + ) + + const desc = computed(() => skillInfo.value?.descDetail.split('\n')) + + const detail = computed(() => { + const items = + skillInfo.value?.attribute?.optionDesc?.split('\n').filter((item) => !!item) ?? [] + const details = items?.map((a) => { + const beforeReplace = a.match(/^(.+?)\s*(\{value\d+\}.*)$/) + if (beforeReplace) { + a = `${beforeReplace[1]}${beforeReplace[2]}` + } + const matches = a.match(/{([^}]+)}/g) + if (matches) { + matches.forEach((match) => { + const key = match.replace(/[{}]/g, '') + // Only access if key matches the expected pattern + if (/^value.+/.test(key)) { + const value = skillInfo.value?.attribute?.optionValue[key as `value${string}`] ?? '-' + if (value) { + a = a.replace(match, `${value}`) + } + } + }) + } + return a + }) + return details || [] + }) + + const renderSkillDetail = () => ( + <> +
基本信息
+
+ {basic.value.map( + (item) => + !!item.value && ( +
+ {item.label} + {item.value} +
+ ), + )} +
+
技能描述
+
+
+ {desc.value?.map((item) => ( + // item.startsWith('[') || item.startsWith('-') || item.startsWith('<') ? ( + //
{item}
+ // ) : +
+ {item} +
+ ))} +
+
+ {detail.value.length > 0 && ( + <> +
技能属性
+
+
+ {detail.value.map((item) => ( +
+ ))} +
+
+ + )} + + ) + + const renderSkillVp = () => ( + <> +
+
+ {skillInfo.value?.evolution?.map((item) => ( + <> +
+
{item.name}
+
技能描述
+
+
+ {item.descDetail} +
+
+
+ + ))} +
+
+ + ) + + onMounted(() => { + watchEffect(() => { + // eslint-disable-next-line @typescript-eslint/no-unused-expressions + ;(skillInfo.value?.evolution?.length ?? 0) == 0 && (curTab.value = 0) + }) + }) + + return () => ( + <> +
+
{skillInfo.value?.name}
+
+ + + 技能信息 + + + 技能进化 + + +
+ {curTab.value === 0 && renderSkillDetail()} + {curTab.value === 1 && renderSkillVp()} +
+ + ) + }, +}) diff --git a/frontend-ui/src/pages/Character/Skill/components/SkillDetail/style.scss b/frontend-ui/src/pages/Character/Skill/components/SkillDetail/style.scss new file mode 100644 index 00000000..990b3f3a --- /dev/null +++ b/frontend-ui/src/pages/Character/Skill/components/SkillDetail/style.scss @@ -0,0 +1,97 @@ +.skill_name { + border-width: 1px; + border-style: solid; + border-image-source: linear-gradient(90deg, #7d5f07 0%, #2e302e 100%); + border-image-slice: 1; + display: flex; + align-items: center; + justify-content: center; + position: relative; + height: 20px; + z-index: 5; + transform-style: preserve-3d; + color: #c1a238; + &::before { + width: 100%; + position: absolute; + content: ''; + height: 50%; + bottom: 0; + background: linear-gradient(90deg, #281e06 0%, #121212 100%); + transform: translateZ(-1px); + } + + &::after { + width: 100%; + position: absolute; + content: ''; + height: 50%; + top: 0; + background: linear-gradient(90deg, #563e02 0%, #121212 100%); + transform: translateZ(-1px); + } +} + +.skill_vp_title { + border-width: 1px; + border-style: solid; + border-image-source: linear-gradient(90deg, #691b86 0%, #2e302e 100%); + border-image-slice: 1; + display: flex; + align-items: center; + justify-content: center; + position: relative; + height: 20px; + z-index: 5; + transform-style: preserve-3d; + color: #9443be; + &::before { + width: 100%; + position: absolute; + content: ''; + height: 50%; + bottom: 0; + background: linear-gradient(90deg, #3a0f47 0%, #121212 100%); + transform: translateZ(-1px); + } + + &::after { + width: 100%; + position: absolute; + content: ''; + height: 50%; + top: 0; + background: linear-gradient(90deg, #1e0b24 0%, #171717 100%); + transform: translateZ(-1px); + } +} + +.skill_title { + border: 1px solid #3e4040; + color: #c1a238; + background: linear-gradient(180deg, #2b292b 0%, #0b0b0b 100%); + height: 20px; + display: flex; + align-items: center; + padding: 0px 5px; +} + +.item { + background-color: #171616; + padding: 0px 5px; + .label { + color: #907b54; + } + .value { + color: #4aa256; + } +} + +.skill_info_value { + white-space: nowrap; + display: flex; + align-items: center; + margin-left: auto; + margin-top: auto; + color: #4aa256; +} diff --git a/frontend-ui/src/pages/Character/Skill/components/SkillTree/img/add.svg b/frontend-ui/src/pages/Character/Skill/components/SkillTree/img/add.svg new file mode 100755 index 00000000..b8187f6a --- /dev/null +++ b/frontend-ui/src/pages/Character/Skill/components/SkillTree/img/add.svg @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/frontend-ui/src/pages/Character/Skill/components/SkillTree/img/awake_50.png b/frontend-ui/src/pages/Character/Skill/components/SkillTree/img/awake_50.png new file mode 100644 index 00000000..9bb5df99 Binary files /dev/null and b/frontend-ui/src/pages/Character/Skill/components/SkillTree/img/awake_50.png differ diff --git a/frontend-ui/src/pages/Character/Skill/components/SkillTree/img/awake_85.png b/frontend-ui/src/pages/Character/Skill/components/SkillTree/img/awake_85.png new file mode 100644 index 00000000..b54882dc Binary files /dev/null and b/frontend-ui/src/pages/Character/Skill/components/SkillTree/img/awake_85.png differ diff --git a/frontend-ui/src/pages/Character/Skill/components/SkillTree/img/max.svg b/frontend-ui/src/pages/Character/Skill/components/SkillTree/img/max.svg new file mode 100755 index 00000000..3e242af5 --- /dev/null +++ b/frontend-ui/src/pages/Character/Skill/components/SkillTree/img/max.svg @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/frontend-ui/src/pages/Character/Skill/components/SkillTree/img/min.svg b/frontend-ui/src/pages/Character/Skill/components/SkillTree/img/min.svg new file mode 100755 index 00000000..17452681 --- /dev/null +++ b/frontend-ui/src/pages/Character/Skill/components/SkillTree/img/min.svg @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/frontend-ui/src/pages/Character/Skill/components/SkillTree/img/skill.png b/frontend-ui/src/pages/Character/Skill/components/SkillTree/img/skill.png new file mode 100644 index 00000000..a49422b3 Binary files /dev/null and b/frontend-ui/src/pages/Character/Skill/components/SkillTree/img/skill.png differ diff --git a/frontend-ui/src/pages/Character/Skill/components/SkillTree/img/skillActive.png b/frontend-ui/src/pages/Character/Skill/components/SkillTree/img/skillActive.png new file mode 100644 index 00000000..32d80df5 Binary files /dev/null and b/frontend-ui/src/pages/Character/Skill/components/SkillTree/img/skillActive.png differ diff --git a/frontend-ui/src/pages/Character/Skill/components/SkillTree/img/sub.svg b/frontend-ui/src/pages/Character/Skill/components/SkillTree/img/sub.svg new file mode 100755 index 00000000..8e9cf31f --- /dev/null +++ b/frontend-ui/src/pages/Character/Skill/components/SkillTree/img/sub.svg @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/frontend-ui/src/pages/Character/Skill/components/SkillTree/index.tsx b/frontend-ui/src/pages/Character/Skill/components/SkillTree/index.tsx new file mode 100644 index 00000000..f8a75e0c --- /dev/null +++ b/frontend-ui/src/pages/Character/Skill/components/SkillTree/index.tsx @@ -0,0 +1,280 @@ +import { getImageURL } from '@/utils/images' +import type { ISkill } from '@/api/info/type' +import { useVModel } from '@vueuse/core' +import CalcButton from '@/components/calc/button/index.vue' +import './style.scss' + +export default defineComponent({ + name: 'SkillTree', + props: { + skills: { + type: Array as PropType, + default: () => [], + }, + lvInfo: { + type: Object as PropType>, + default: () => ({}), + }, + bindAwake: { + type: Number, + default: () => 50, + }, + }, + emits: ['chooseSkill'], + setup(props, { emit }) { + const skills = computed(() => props.skills) + const lvInfo = useVModel(props, 'lvInfo') + const bindAwake = useVModel(props, 'bindAwake') + // const emit = defineEmits(['chooseSkill']) + + const getSkill = (lvStart: number, lvEnd: number, position: number) => { + if (position >= 0) + return skills.value.find( + (item) => + item.line > lvStart - 5 && + item.line <= Math.max(lvEnd - 5, 1) && + item.position == position, + ) + else + return skills.value.filter( + (item) => item.line > lvStart - 5 && item.line <= Math.max(lvEnd - 5, 1), + ) + } + + const lvList = [15, 20, 25, 30, 35, 40, 45, 50, 60, 70, 80, 90, 100] + + const columns = Array.from({ length: 11 }, (_, index) => index) + + const activeSkill = ref(-1) + + const chooseSkill = (skill?: ISkill, operation: string = 'add') => { + if (!skill) { + activeSkill.value = -1 + return + } + if (activeSkill.value == skill.id) actionSkillLv(skill, operation) + else activeSkill.value = skill.id + emit('chooseSkill', skill.id) + } + + const awakeSkill_1 = computed(() => + skills.value.find((item) => item.learnLv == 50 && item.type == 'active' && item.bind), + ) + const awakeSkill_2 = computed(() => + skills.value.find((item) => item.learnLv == 85 && item.type == 'active' && item.bind), + ) + + const actionSkillLv = (skill: ISkill, operation: string) => { + if (operation == 'add') { + lvInfo.value[skill.id.toString()].lv = Math.min( + lvInfo.value[skill.id.toString()]?.lv + 1, + skill.maxLv, + ) + return + } + if (operation == 'addMax') { + lvInfo.value[skill.id.toString()].lv = skill.maxLearnLv + return + } + if (operation == 'sub') { + lvInfo.value[skill.id.toString()].lv = Math.max( + lvInfo.value[skill.id.toString()]?.lv - 1, + 0, + ) + return + } + if (operation == 'subMax') { + lvInfo.value[skill.id.toString()] = { lv: 0, vp: 0, up: 0 } + return + } + emit('chooseSkill', skill.id) + } + + const chooseBindAwake = (lv: number) => { + bindAwake.value = lv + } + + const renderSkill = (skill: ISkill, index: number) => { + const info = lvInfo.value?.[skill.id.toString()] + let color = 'white' + if (info?.lv < skill.maxLearnLv) color = '#32E432' + if (info?.lv > skill.maxLearnLv) color = '#58E0FC' + return ( + <> +
+
+ {info?.vp > 0 &&
} + {info?.up > 0 &&
} +
+ {activeSkill.value == skill.id && renderSkillAction(skill)} +
{ + e.stopPropagation() + chooseSkill(skill) + }} + onContextmenu={(e) => { + e.stopPropagation() + e.preventDefault() + chooseSkill(skill, 'sub') + }} + key={index} + > + {skill.name} +
+ {info?.lv ?? 0} +
+
+ {skill.learnLv == 100 && skill.bind && ( + <> +
+
chooseBindAwake(50)} + > + +
+ 1次 +
+
+
chooseBindAwake(85)} + > + +
+ 2次 +
+
+
+ + )} +
+ + ) + } + + const renderSkillAction = (skill: ISkill) => ( + <> + <> +
+
+ { + e.stopPropagation() + actionSkillLv(skill, 'subMax') + }} + > + { + e.stopPropagation() + actionSkillLv(skill, 'sub') + }} + > + { + e.stopPropagation() + actionSkillLv(skill, 'add') + }} + > + = skill.maxLearnLv} + onClick={(e: Event) => { + e.stopPropagation() + actionSkillLv(skill, 'addMax') + }} + > + {/* { + e.stopPropagation() + actionSkillLv(skill, 'subMax') + }} + > + { + e.stopPropagation() + actionSkillLv(skill, 'sub') + }} + > + { + e.stopPropagation() + actionSkillLv(skill, 'add') + }} + > + { + e.stopPropagation() + actionSkillLv(skill, 'addMax') + }} + > */} +
+
+ + + ) + + return () => ( + <> +
(activeSkill.value = -1)}> + {((getSkill(0, 15, -1) ?? []) as ISkill[]).length > 0 && ( + <> +
+
+ 其
余 +
+ {((getSkill(0, 15, -1) ?? []) as ISkill[])?.map((skill, index) => + renderSkill(skill, index), + )} +
+ + )} + + {lvList.map((lv, index) => + ((getSkill(lv, lvList[index + 1] ?? 150, -1) as ISkill[])?.length ?? 0) > 0 ? ( +
+ {lv == 1 || lv % 10 == 0 ? ( +
{lv}
+ ) : ( +
+ )} + {columns.map((column) => { + const skill = getSkill(lv, lvList[index + 1] ?? 150, column) as ISkill + return skill ? renderSkill(skill, index) :
+ })} +
(activeSkill.value = -1)}>
+
+ ) : ( + <> + ), + )} +
+ + ) + }, +}) diff --git a/frontend-ui/src/pages/Character/Skill/components/SkillTree/style.scss b/frontend-ui/src/pages/Character/Skill/components/SkillTree/style.scss new file mode 100644 index 00000000..d62a2c1d --- /dev/null +++ b/frontend-ui/src/pages/Character/Skill/components/SkillTree/style.scss @@ -0,0 +1,66 @@ +.skill-tree-line { + height: 80px; + width: auto; + &:nth-child(n + 1) { + background-color: #000000; + } + &:nth-child(2n + 1) { + background-color: #202020; + } +} + +.passive { + filter: grayscale(100%) invert(3%) sepia(14%) saturate(874%) hue-rotate(65deg) brightness(105%) + contrast(102%); +} + +.skill { + background-image: url('./img/skill.png'); + background-size: 100% 100%; +} + +.skill-active { + background-image: url('./img/skillActive.png'); + background-size: 100% 100%; +} + +.awake_50 { + background-image: url('./img/awake_50.png'); + background-size: 100% 100%; +} + +.awake_85 { + background-image: url('./img/awake_85.png'); + background-size: 100% 100%; +} + +.vp_1 { + width: 18px; + height: 18px; + background-position: center center; + background-repeat: no-repeat; + background-image: url(../img/vp_1.png); +} + +.vp_2 { + width: 18px; + height: 18px; + background-position: center center; + background-repeat: no-repeat; + background-image: url(../img/vp_2.png); +} + +.up_1 { + width: 18px; + height: 18px; + background-position: center center; + background-repeat: no-repeat; + background-image: url(../img/up_1.png); +} +.up_2 { + width: 18px; + height: 18px; + background-position: center center; + background-repeat: no-repeat; + background-image: url(../img/up_2.png); +} diff --git a/frontend-ui/src/pages/Character/Skill/components/SkillUP/img/106.png b/frontend-ui/src/pages/Character/Skill/components/SkillUP/img/106.png new file mode 100644 index 00000000..c01bbc9d Binary files /dev/null and b/frontend-ui/src/pages/Character/Skill/components/SkillUP/img/106.png differ diff --git a/frontend-ui/src/pages/Character/Skill/components/SkillUP/img/107.png b/frontend-ui/src/pages/Character/Skill/components/SkillUP/img/107.png new file mode 100644 index 00000000..9a1e4cd0 Binary files /dev/null and b/frontend-ui/src/pages/Character/Skill/components/SkillUP/img/107.png differ diff --git a/frontend-ui/src/pages/Character/Skill/components/SkillUP/img/108.png b/frontend-ui/src/pages/Character/Skill/components/SkillUP/img/108.png new file mode 100644 index 00000000..199703d9 Binary files /dev/null and b/frontend-ui/src/pages/Character/Skill/components/SkillUP/img/108.png differ diff --git a/frontend-ui/src/pages/Character/Skill/components/SkillUP/img/attack.png b/frontend-ui/src/pages/Character/Skill/components/SkillUP/img/attack.png new file mode 100644 index 00000000..4201749d Binary files /dev/null and b/frontend-ui/src/pages/Character/Skill/components/SkillUP/img/attack.png differ diff --git a/frontend-ui/src/pages/Character/Skill/components/SkillUP/img/bg.png b/frontend-ui/src/pages/Character/Skill/components/SkillUP/img/bg.png new file mode 100644 index 00000000..c225b4ec Binary files /dev/null and b/frontend-ui/src/pages/Character/Skill/components/SkillUP/img/bg.png differ diff --git a/frontend-ui/src/pages/Character/Skill/components/SkillUP/img/bgBack.png b/frontend-ui/src/pages/Character/Skill/components/SkillUP/img/bgBack.png new file mode 100644 index 00000000..89e0bfc6 Binary files /dev/null and b/frontend-ui/src/pages/Character/Skill/components/SkillUP/img/bgBack.png differ diff --git a/frontend-ui/src/pages/Character/Skill/components/SkillUP/img/cd.png b/frontend-ui/src/pages/Character/Skill/components/SkillUP/img/cd.png new file mode 100644 index 00000000..8c25d6e1 Binary files /dev/null and b/frontend-ui/src/pages/Character/Skill/components/SkillUP/img/cd.png differ diff --git a/frontend-ui/src/pages/Character/Skill/components/SkillUP/img/title.png b/frontend-ui/src/pages/Character/Skill/components/SkillUP/img/title.png new file mode 100644 index 00000000..1a88807b Binary files /dev/null and b/frontend-ui/src/pages/Character/Skill/components/SkillUP/img/title.png differ diff --git a/frontend-ui/src/pages/Character/Skill/components/SkillUP/img/up_1.png b/frontend-ui/src/pages/Character/Skill/components/SkillUP/img/up_1.png new file mode 100644 index 00000000..33194445 Binary files /dev/null and b/frontend-ui/src/pages/Character/Skill/components/SkillUP/img/up_1.png differ diff --git a/frontend-ui/src/pages/Character/Skill/components/SkillUP/img/up_2.png b/frontend-ui/src/pages/Character/Skill/components/SkillUP/img/up_2.png new file mode 100644 index 00000000..5b6659a9 Binary files /dev/null and b/frontend-ui/src/pages/Character/Skill/components/SkillUP/img/up_2.png differ diff --git a/frontend-ui/src/pages/Character/Skill/components/SkillUP/img/up_3.png b/frontend-ui/src/pages/Character/Skill/components/SkillUP/img/up_3.png new file mode 100644 index 00000000..7c48850a Binary files /dev/null and b/frontend-ui/src/pages/Character/Skill/components/SkillUP/img/up_3.png differ diff --git a/frontend-ui/src/pages/Character/Skill/components/SkillUP/img/up_active.png b/frontend-ui/src/pages/Character/Skill/components/SkillUP/img/up_active.png new file mode 100644 index 00000000..34c19b9b Binary files /dev/null and b/frontend-ui/src/pages/Character/Skill/components/SkillUP/img/up_active.png differ diff --git a/frontend-ui/src/pages/Character/Skill/components/SkillUP/index.tsx b/frontend-ui/src/pages/Character/Skill/components/SkillUP/index.tsx new file mode 100644 index 00000000..f087307f --- /dev/null +++ b/frontend-ui/src/pages/Character/Skill/components/SkillUP/index.tsx @@ -0,0 +1,307 @@ +import { getImageURL } from '@/utils/images' +import type { ISkill } from '@/api/info/type' +import { useVModel } from '@vueuse/core' +import CalcButton from '@/components/calc/button/index.vue' +import CaclIconSelect from '@/components/calc/iconselect/index.vue' +import CalcOption from '@/components/calc/option/index.vue' +import { renderList } from 'vue' +import './style.scss' + +export default defineComponent({ + name: 'SkillTree', + props: { + skills: { + type: Array as PropType, + default: () => [], + }, + lvInfo: { + type: Object as PropType>, + default: () => ({}), + }, + buffer: { + type: Boolean, + default: false, + }, + }, + setup(props) { + const lvInfo = useVModel(props, 'lvInfo') + const skills = (index: number = 0) => { + index -= 1 + const upList = Object.keys(lvInfo.value).filter( + (a) => !!lvInfo.value[a].up && lvInfo.value[a].up > 0, + ) + const currentUPSkill = index >= 0 ? upList[index] : undefined + return computed(() => + props.skills + .filter( + (a) => + a.id.toString() === currentUPSkill || + (a.hasUP && + (!lvInfo.value[a.id]?.up || lvInfo.value[a.id]?.up == 0) && + lvInfo.value[a.id].lv > 0), + ) + .sort((a, b) => a.learnLv - b.learnLv), + ) + } + + const itemChecked = (index: number, up: number) => { + index -= 1 + return computed({ + get() { + const upList = Object.keys(lvInfo.value).filter( + (a) => !!lvInfo.value[a].up && lvInfo.value[a].up > 0, + ) + const currentUPSkill = upList[index] + const currentUP = lvInfo.value[currentUPSkill]?.up + return currentUP == up ? currentUPSkill : undefined + }, + set(value: string | undefined) { + if (!value) return + const upList = Object.keys(lvInfo.value).filter( + (a) => !!lvInfo.value[a].up && lvInfo.value[a].up > 0, + ) + const currentUPSkill = upList[index] + if (currentUPSkill) { + lvInfo.value[currentUPSkill].up = 0 + } + lvInfo.value[value].up = up + }, + }) + } + + const exchange = (index: number) => { + const skill = itemChecked(index, 1).value || itemChecked(index, 2).value + if (!skill) return + lvInfo.value[skill].up = lvInfo.value[skill].up == 1 ? 2 : 1 + } + + return () => ( + <> + {lvInfo.value && Object.keys(lvInfo.value).length > 0 ? ( +
+
+
+
+
+
+
+
技能攻击力增加
+
+
+
+
+ 技能冷却时间减少 +
+ 技能攻击力增加 +
+
+
+
+ {renderList(3, (index) => ( + <> +
+
+ + { + +
+
+ } + {renderList(skills(index).value, (item) => ( + <> + + {item.name} + + + ))} +
+
+ exchange(index)}> +
+ + {renderList(skills(index).value, (item) => ( + <> + + {item.name} + + + ))} + +
+
+ + ))} +
+
+
+
+
目标技能
+
+ {renderList(skills().value, (item) => ( +
+ {item.name} +
+ ))} + {renderList(36 - skills().value.length, (item) => ( +
+ ))} +
+
+ {renderList( + Object.keys(lvInfo.value).filter( + (a) => !!lvInfo.value[a].up && lvInfo.value[a].up > 0, + ), + (index) => { + const skill = props.skills.find((a) => a.id.toString() === index) + let tooltip = '' + if (skill) { + if (lvInfo.value[skill.id.toString()].up == 1) { + if (skill.upType == 'damage') { + tooltip = `技能攻击力 +${skill.learnLv < 35 ? '60' : 55}%` + } else { + tooltip = `生命值恢复量 +20%` + } + } + if (lvInfo.value[skill.id.toString()].up == 2) { + if (skill.upType == 'damage') { + tooltip = `技能冷却时间 -15%
技能攻击力 +${skill.learnLv < 35 ? '43' : 38}%` + } else { + tooltip = `技能冷却时间 -10%
生命值恢复量 +5%` + } + } + } + if (props.buffer) { + tooltip += ` / 主属性 +40` + } + return skill ? ( +
+
+ {skill.name} +
+
+
+ ) : ( + <> + ) + }, + )} +
+
+ {/*
+ {renderList(3, (index) => ( + <> +
+
+ + {renderList(skills(index).value, (item) => ( + <> + + {item.name} + + + ))} + +
+ exchange(index)}> +
+ + {renderList(skills(index).value, (item) => ( + <> + + {item.name} + + + ))} + +
+
+ + ))} +
+
+
+ {renderList(skills().value, (item) => ( +
+ {item.name} +
+ ))} + {renderList(36 - skills().value.length, (item) => ( +
+ ))} +
+
+ {renderList( + Object.keys(lvInfo.value).filter( + (a) => !!lvInfo.value[a].up && lvInfo.value[a].up > 0, + ), + (index) => { + const skill = props.skills.find((a) => a.id.toString() === index) + let tooltip = '' + if (skill) { + if (lvInfo.value[skill.id.toString()].up == 1) { + tooltip = `技能攻击力 +${skill.learnLv < 35 ? '60' : 55}%` + } + if (lvInfo.value[skill.id.toString()].up == 2) { + tooltip = `技能攻击力 +${skill.learnLv < 35 ? '43' : 38}%
技能冷却时间 -15%` + } + } + + return skill ? ( +
+
+ {skill.name} +
+
+
+ ) : ( + <> + ) + }, + )} +
+
*/} +
+
+ ) : ( + <> + )} + + ) + }, +}) diff --git a/frontend-ui/src/pages/Character/Skill/components/SkillUP/style.scss b/frontend-ui/src/pages/Character/Skill/components/SkillUP/style.scss new file mode 100644 index 00000000..f6715d16 --- /dev/null +++ b/frontend-ui/src/pages/Character/Skill/components/SkillUP/style.scss @@ -0,0 +1,75 @@ +.skill-up { + width: 540px; + // height: 334px; + // background-image: url('./img/bg.png'); + // background-size: 100% 100%; + padding: 5px 10px; + padding-bottom: 10px; + background-color: black; + + .left { + width: 240px; + height: 325px; + border-radius: 2px; + border: 1px solid #2e2e2e; + background: linear-gradient(to bottom, #1c1c1c 0%, #0a0d0a 100%); + display: flex; + padding: 5px 10px; + + .up_head_1, + .up_head_2 { + display: flex; + flex-direction: column; + align-items: center; + + .icon { + width: 80px; + height: 80px; + background-position: center center; + } + } + + .up_head_1 .icon { + background-image: url('./img/attack.png'); + } + + .up_head_2 .icon { + background-image: url('./img/cd.png'); + } + } + + .right { + .title { + width: 261px; + height: 48px; + background: url('./img/title.png') no-repeat center center; + } + } + + .up_1, + .up_2, + .up_3, + .up_active { + width: 54px; + height: 54px; + display: flex; + align-items: center; + justify-content: center; + } + + .up_1 { + background: url('./img/up_1.png') no-repeat center center; + } + + .up_2 { + background: url('./img/up_2.png') no-repeat center center; + } + + .up_3 { + background: url('./img/up_3.png') no-repeat center center; + } + + .up_active { + background: url('./img/up_active.png') no-repeat center center; + } +} diff --git a/frontend-ui/src/pages/Character/Skill/components/SkillVP/img/106.png b/frontend-ui/src/pages/Character/Skill/components/SkillVP/img/106.png new file mode 100644 index 00000000..10485dff Binary files /dev/null and b/frontend-ui/src/pages/Character/Skill/components/SkillVP/img/106.png differ diff --git a/frontend-ui/src/pages/Character/Skill/components/SkillVP/img/108.png b/frontend-ui/src/pages/Character/Skill/components/SkillVP/img/108.png new file mode 100644 index 00000000..199703d9 Binary files /dev/null and b/frontend-ui/src/pages/Character/Skill/components/SkillVP/img/108.png differ diff --git a/frontend-ui/src/pages/Character/Skill/components/SkillVP/img/bg.png b/frontend-ui/src/pages/Character/Skill/components/SkillVP/img/bg.png new file mode 100755 index 00000000..1404d6b8 Binary files /dev/null and b/frontend-ui/src/pages/Character/Skill/components/SkillVP/img/bg.png differ diff --git a/frontend-ui/src/pages/Character/Skill/components/SkillVP/img/selected.png b/frontend-ui/src/pages/Character/Skill/components/SkillVP/img/selected.png new file mode 100644 index 00000000..9a1e4cd0 Binary files /dev/null and b/frontend-ui/src/pages/Character/Skill/components/SkillVP/img/selected.png differ diff --git a/frontend-ui/src/pages/Character/Skill/components/SkillVP/index.tsx b/frontend-ui/src/pages/Character/Skill/components/SkillVP/index.tsx new file mode 100644 index 00000000..110e6491 --- /dev/null +++ b/frontend-ui/src/pages/Character/Skill/components/SkillVP/index.tsx @@ -0,0 +1,132 @@ +import { getImageURL } from '@/utils/images' +import type { ISkill } from '@/api/info/type' +import { useVModel } from '@vueuse/core' +import CalcCheckbox from '@/components/calc/checkbox/index.vue' +import { renderList } from 'vue' +import './style.scss' +export default defineComponent({ + name: 'SkillVP', + props: { + skills: { + type: Array as PropType, + default: () => [], + }, + lvInfo: { + type: Object as PropType>, + default: () => ({}), + }, + }, + emits: ['chooseSkill'], + setup(props, { emit }) { + const lvInfo = useVModel(props, 'lvInfo') + const skills = computed(() => + props.skills.filter((a) => a.hasVP && lvInfo).sort((a, b) => a.learnLv - b.learnLv), + ) + + const currentUsedVP = computed(() => { + return Object.keys(lvInfo.value) + .filter((a) => skills.value.find((skill) => skill.id.toString() === a)) + .map((a) => lvInfo.value[a].vp) + .filter((a) => !!a && a > 0).length + }) + + const itemChecked = (skillID: string, vp: number) => { + return computed({ + get() { + if (!lvInfo.value[skillID].vp) { + lvInfo.value[skillID].vp = 0 + } + return lvInfo.value[skillID]?.vp == vp + }, + set(value: boolean) { + // 选中当前VP形态 并且当前已选VP大于5 并且当前技能没有VP + if (value && currentUsedVP.value >= 5 && lvInfo.value[skillID]?.vp == 0) { + return + } + if (value) { + lvInfo.value[skillID].vp = vp + } else { + lvInfo.value[skillID].vp = 0 + } + }, + }) + } + + return () => ( + <> +
+ {renderList(skills.value, (item) => ( +
+
{item.learnLv}
+
+
+ {item.name} +
+
{item.name}
+
+ {renderList(2, (index) => ( +
{ + emit('chooseSkill', item.id) + itemChecked(item.id.toString(), index).value = !itemChecked( + item.id.toString(), + index, + ).value + }} + > + {' '} +
+
+
+ = 5 && lvInfo.value[item.id.toString()]?.vp == 0 + } + /> +
+
+
+ {item.name} +
+
+
+
+
+ {item.vps[index - 1]?.name} +
+ {renderList( + item.vps[index - 1]?.desc + ? item.vps[index - 1].desc.replace(//g, '\n').split('\n') + : [], + (desc) => ( +
{desc}
+ ), + )} +
+
+ ))} +
+ ))} +
+ + ) + }, +}) diff --git a/frontend-ui/src/pages/Character/Skill/components/SkillVP/style.scss b/frontend-ui/src/pages/Character/Skill/components/SkillVP/style.scss new file mode 100644 index 00000000..e5cae6b1 --- /dev/null +++ b/frontend-ui/src/pages/Character/Skill/components/SkillVP/style.scss @@ -0,0 +1,47 @@ +.vp { + &:nth-child(n + 1) { + background-color: #000000; + } + &:nth-child(2n + 1) { + background-color: #080808; + } + + .vp-item { + height: 120px; + width: 148px; + padding: 1px; + display: flex; + align-items: center; + justify-content: center; + background-image: url(./img/bg.png); + // padding:5px 10px ; + box-sizing: border-box; + } + + .selected { + background-image: url(./img/selected.png); + background-repeat: no-repeat; + background-position: center center; + background-size: calc(100% - 2.5px) calc(100% + 2.5px); + + .selected-name { + color: #cf57ff !important; + } + } + + .vp_1 { + width: 18px; + height: 18px; + background-position: center center; + background-repeat: no-repeat; + background-image: url(../img/vp_1.png); + } + + .vp_2 { + width: 18px; + height: 18px; + background-position: center center; + background-repeat: no-repeat; + background-image: url(../img/vp_2.png); + } +} diff --git a/frontend-ui/src/pages/Character/Skill/components/img/detail.png b/frontend-ui/src/pages/Character/Skill/components/img/detail.png new file mode 100644 index 00000000..4bb3f092 Binary files /dev/null and b/frontend-ui/src/pages/Character/Skill/components/img/detail.png differ diff --git a/frontend-ui/src/pages/Character/Skill/components/img/up_1.png b/frontend-ui/src/pages/Character/Skill/components/img/up_1.png new file mode 100644 index 00000000..3ee58261 Binary files /dev/null and b/frontend-ui/src/pages/Character/Skill/components/img/up_1.png differ diff --git a/frontend-ui/src/pages/Character/Skill/components/img/up_2.png b/frontend-ui/src/pages/Character/Skill/components/img/up_2.png new file mode 100644 index 00000000..86c62218 Binary files /dev/null and b/frontend-ui/src/pages/Character/Skill/components/img/up_2.png differ diff --git a/frontend-ui/src/pages/Character/Skill/components/img/vp_1.png b/frontend-ui/src/pages/Character/Skill/components/img/vp_1.png new file mode 100644 index 00000000..afda59f9 Binary files /dev/null and b/frontend-ui/src/pages/Character/Skill/components/img/vp_1.png differ diff --git a/frontend-ui/src/pages/Character/Skill/components/img/vp_2.png b/frontend-ui/src/pages/Character/Skill/components/img/vp_2.png new file mode 100644 index 00000000..a345f1b9 Binary files /dev/null and b/frontend-ui/src/pages/Character/Skill/components/img/vp_2.png differ diff --git a/frontend-ui/src/pages/Character/Skill/index.vue b/frontend-ui/src/pages/Character/Skill/index.vue new file mode 100644 index 00000000..7aeed4fb --- /dev/null +++ b/frontend-ui/src/pages/Character/Skill/index.vue @@ -0,0 +1,172 @@ + + + + + diff --git a/frontend-ui/src/pages/ComponentCatalog/Index.vue b/frontend-ui/src/pages/ComponentCatalog/Index.vue new file mode 100644 index 00000000..29918471 --- /dev/null +++ b/frontend-ui/src/pages/ComponentCatalog/Index.vue @@ -0,0 +1,857 @@ + + + + + diff --git a/frontend-ui/src/pages/Dnfhelper/bind.vue b/frontend-ui/src/pages/Dnfhelper/bind.vue new file mode 100644 index 00000000..8e4064b6 --- /dev/null +++ b/frontend-ui/src/pages/Dnfhelper/bind.vue @@ -0,0 +1,44 @@ + + diff --git a/frontend-ui/src/pages/Dnfhelper/index.vue b/frontend-ui/src/pages/Dnfhelper/index.vue new file mode 100644 index 00000000..4a198336 --- /dev/null +++ b/frontend-ui/src/pages/Dnfhelper/index.vue @@ -0,0 +1,37 @@ + + diff --git a/frontend-ui/src/pages/Dnfhelper/list.vue b/frontend-ui/src/pages/Dnfhelper/list.vue new file mode 100644 index 00000000..99a96eb6 --- /dev/null +++ b/frontend-ui/src/pages/Dnfhelper/list.vue @@ -0,0 +1,95 @@ + + diff --git a/frontend-ui/src/pages/Dnfhelper/processing.vue b/frontend-ui/src/pages/Dnfhelper/processing.vue new file mode 100644 index 00000000..bd60105a --- /dev/null +++ b/frontend-ui/src/pages/Dnfhelper/processing.vue @@ -0,0 +1,10 @@ + + diff --git a/frontend-ui/src/pages/Home/Index.vue b/frontend-ui/src/pages/Home/Index.vue new file mode 100644 index 00000000..c5c38387 --- /dev/null +++ b/frontend-ui/src/pages/Home/Index.vue @@ -0,0 +1,157 @@ + + + diff --git a/frontend-ui/src/pages/IndexView.vue b/frontend-ui/src/pages/IndexView.vue new file mode 100644 index 00000000..dc0d2ec6 --- /dev/null +++ b/frontend-ui/src/pages/IndexView.vue @@ -0,0 +1,42 @@ + + + diff --git a/frontend-ui/src/pages/UiPreview/Index.vue b/frontend-ui/src/pages/UiPreview/Index.vue new file mode 100644 index 00000000..250e6b9c --- /dev/null +++ b/frontend-ui/src/pages/UiPreview/Index.vue @@ -0,0 +1,110 @@ + + + + + diff --git a/frontend-ui/src/router/index.ts b/frontend-ui/src/router/index.ts new file mode 100644 index 00000000..b8c81fef --- /dev/null +++ b/frontend-ui/src/router/index.ts @@ -0,0 +1,71 @@ +import { createRouter, createWebHistory, type RouteRecordRaw } from 'vue-router' +const routes: RouteRecordRaw[] = [ + // { + // path: '/:pathMatch(.*)', + // redirect: '/', + // }, + { + path: '/', + name: 'home', + component: () => import('@/pages/Home/Index.vue'), + }, + { + path: '/dnfhelper', + name: 'dnfhelper', + component: () => import('@/pages/Dnfhelper/index.vue'), + }, + { + path: '/ui-preview', + name: 'ui-preview', + component: () => import('@/pages/UiPreview/Index.vue'), + }, + { + path: '/components', + name: 'component-catalog', + meta: { disableAppZoom: true }, + component: () => import('@/pages/ComponentCatalog/Index.vue'), + }, + { + path: '/character/:alter', + redirect: (to) => { + return { path: `/character/equipment/${to.params.alter}`, query: to.query } + }, + props: true, + name: 'character', + component: () => import('@/pages/Character/Index.vue'), + children: [ + { + path: '/character/equipment/:alter', + name: 'equipment', + props: true, + component: () => import('@/pages/Character/EquipmentDictionary/Index.vue'), + }, + // { + // path: '/character/equipment/:alter', + // name: 'equipment', + // props: true, + // component: (() => import('@/pages/Character/Equipment/Index.vue')), + // },{ + { + path: '/character/skill/:alter', + name: 'skill', + props: true, + component: () => import('@/pages/Character/Skill/index.vue'), + }, + { + path: '/character/forge/:alter', + name: 'forge', + props: true, + component: () => import('@/pages/Character/Forge/index.vue'), + }, + ], + }, +] + +const router = createRouter({ + // routes, + routes, + history: createWebHistory(import.meta.env.BASE_URL), +}) + +export default router diff --git a/frontend-ui/src/stores/config.ts b/frontend-ui/src/stores/config.ts new file mode 100644 index 00000000..0f3ad005 --- /dev/null +++ b/frontend-ui/src/stores/config.ts @@ -0,0 +1,295 @@ +import { defineStore } from 'pinia' +import { useInfoStore } from './info' +import api from '@/api' +import type { IEquipment } from '@/api/info/type' +import type { IResultSkillCount } from '@/api/calc/type' +// | '上衣' +// | '头肩' +// | '下装' +// | '腰带' +// | '鞋' +// | '手镯' +// | '项链' +// | '戒指' +// | '耳环' +// | '辅助装备' +// | '魔法石' +// | '武器', + +export interface IConfigEquip { + id: string + reinforce: number + reinforceType: number + enchant: string + emblem_0: string + emblem_1: string + upgrade: number + refine: number + adaptation: number + fusion: string + precision: number + weaponFusion: number +} + +export interface IConfigOath { + id: string + adaptation: number + upgrade: number[] +} + +export interface IConfigEmblem { + lv: number + items: string[] +} + +export interface IConfig { + skills: Record + equips: Record + oaths: Record + oathSkill: string + jades: Record< + string, + { + id: number + value: number + } + > + avatar: Record< + string, + { + id: string + enchant: string + emblem_0: string + emblem_1: string + option: string + } + > + sundry: Record + bindAwake: number + /** 系统奶 */ + DSB: boolean + /** 奶 */ + BUFF: boolean + options: Record + avatarLink: string + emblems: Record +} + +const defaultEqusConfig = { + id: '', + reinforce: 0, + reinforceType: 0, + enchant: '', + emblem_0: '', + emblem_1: '', + upgrade: 0, + refine: 0, + adaptation: 0, + fusion: '', + precision: 0, + weaponFusion: 0, +} + +const defaultAvatarConfig = { + id: '', + enchant: '', + emblem_0: '', + emblem_1: '', + option: '0', +} + +const createDefaultOathConfig = (): IConfigOath => ({ + id: '', + adaptation: 0, + upgrade: [0, 0, 0, 0], +}) + +const defaultOathConfig = createDefaultOathConfig() + +const createDefaultEmblemConfig = (): IConfigEmblem => ({ + lv: 0, + items: ['', '', '', '', '', ''], +}) + +const defaultEmblemConfig = createDefaultEmblemConfig() + +export const useConfigStore = defineStore('configStore', () => { + const config = ref({ + skills: {}, + equips: {}, + oaths: {}, + oathSkill: '1', + jades: {}, + avatar: {}, + sundry: {}, + bindAwake: 50, + DSB: false, + BUFF: false, + options: {}, + avatarLink: '', + emblems: {}, + }) + + const skillCountConfig = ref([]) + + const loadConfig = () => { + const infoStore = useInfoStore() + const alter = infoStore.infos?.alter + + if (alter) { + const localConfig = localStorage.getItem(`dcalc/${alter}/config`) + const localSkillConfig = localStorage.getItem(`dcalc/${alter}/config/skillCount`) + if (localConfig) { + config.value = JSON.parse(localConfig) + } + if (localSkillConfig) { + skillCountConfig.value = JSON.parse(localSkillConfig) + } + } + if (!config.value) { + config.value = { + skills: {}, + equips: {}, + oaths: {}, + oathSkill: '1', + jades: {}, + avatar: {}, + sundry: {}, + bindAwake: 50, + DSB: false, + BUFF: false, + options: {}, + avatarLink: '', + emblems: {}, + } + } + if (!config.value?.equips) config.value.equips = {} + if (!config.value?.skills) config.value.skills = {} + if (!config.value?.jades) config.value.jades = {} + if (!config.value?.avatar) config.value.avatar = {} + if (!config.value?.sundry) config.value.sundry = {} + if (!config.value?.bindAwake) config.value.bindAwake = 50 + if (!config.value?.options) config.value.options = {} + if (!config.value?.oaths) config.value.oaths = {} + if (!config.value?.emblems) config.value.emblems = {} + + const part = [...infoStore.parts, '宠物', '副武器'].filter( + (a) => !config.value?.equips.hasOwnProperty(a), + ) + const avatarPart = infoStore.avatarParts + .filter((a) => a != '宠物') + .filter((a) => !config.value?.avatar.hasOwnProperty(a)) + + const skillIDs = infoStore.skills + .map((skill) => skill.id.toString()) + .filter((a) => !config.value?.skills.hasOwnProperty(a)) + + part.forEach((p) => { + // eslint-disable-next-line @typescript-eslint/no-unused-expressions + config.value && (config.value.equips[p] = { ...defaultEqusConfig }) + }) + + avatarPart.forEach((p) => { + // eslint-disable-next-line @typescript-eslint/no-unused-expressions + config.value && (config.value.avatar[p] = { ...defaultAvatarConfig }) + }) + + infoStore.oathParts.forEach((p) => { + // eslint-disable-next-line @typescript-eslint/no-unused-expressions + config.value && + !config.value?.oaths.hasOwnProperty(p) && + (config.value.oaths[p.toString()] = createDefaultOathConfig()) + }) + + infoStore.options.forEach((option) => { + if (Object.keys(config.value.options).includes(option.id.toString())) return + config.value.options[option.id.toString()] = 0 + }) + + skillIDs.forEach((id) => { + // eslint-disable-next-line @typescript-eslint/no-unused-expressions + config.value && + (config.value.skills[id] = { + lv: infoStore.skills.find((skill) => skill.id.toString() === id)?.maxLearnLv ?? 0, + vp: 0, + up: 0, + }) + }) + ;( + ['0', '1', '2', '3'].filter((key) => !Object.keys(config.value.jades).includes(key)) ?? [] + ).forEach((key) => { + config.value.jades[key] = { + id: -1, + value: 0, + } + }) + } + + const saveConfig = () => { + const infoStore = useInfoStore() + const alter = infoStore.infos?.alter + if (alter) { + localStorage.setItem(`dcalc/${alter}/config`, JSON.stringify(config.value)) + localStorage.setItem( + `dcalc/${alter}/config/skillCount`, + JSON.stringify(skillCountConfig.value), + ) + } + } + + const calc = async () => { + if (!useInfoStore().infos?.alter) return undefined + const res = await api.calc(config.value) + if (res.suits.oath?.suitId != res.suits.suit?.suitId) { + config.value.oathSkill = '1' + } + return res + } + + const chooseEqu = ( + equip: IEquipment | undefined, + isFusion: boolean = false, + isSubWeapon: boolean = false, + ) => { + if (!equip) return + const part = isSubWeapon ? '副武器' : equip?.itemType == '武器' ? '武器' : equip?.itemDetailType + if (equip && config.value.equips[part]) { + const key = isFusion ? 'fusion' : 'id' + if (config.value.equips[part][key] == equip.id) { + config.value.equips[part][key] = '' + } else { + config.value.equips[part][key] = equip.id + } + } + } + + const result = useAsyncState( + () => { + return calc() + }, + { + uuid: '', + skills: [], + info: [], + suits: {}, + buffer: false, + }, + { resetOnExecute: false }, + ) + + return { + config, + loadConfig, + saveConfig, + calc, + result, + chooseEqu, + skillCountConfig, + defaultEqusConfig, + defaultAvatarConfig, + defaultOathConfig, + createDefaultOathConfig, + defaultEmblemConfig, + createDefaultEmblemConfig, + } +}) diff --git a/frontend-ui/src/stores/dnfhelper.ts b/frontend-ui/src/stores/dnfhelper.ts new file mode 100644 index 00000000..6c874204 --- /dev/null +++ b/frontend-ui/src/stores/dnfhelper.ts @@ -0,0 +1,55 @@ +import { defineStore } from 'pinia' +import api from '@/api' +import type { IHelperInfo } from '@/api/info/type' + +export const useDnfHelperStore = defineStore('dnfHelperStore', () => { + const helperInfo = useLocalStorage('dnfHelperInfo', null, { + serializer: { + read: (v) => (v ? JSON.parse(v) : null), + write: (v) => JSON.stringify(v), + }, + }) + + const loading = ref(false) + const errorMessage = ref('') + + const refreshHelperInfoInner = async (uid?: string) => { + if (!uid) return + loading.value = true + errorMessage.value = '' + try { + const data = await api.getHelperList(uid) + if (data) { + helperInfo.value = data + } + } catch (error) { + errorMessage.value = error instanceof Error ? error.message : '同步助手数据失败' + throw error + } finally { + loading.value = false + } + } + + const refreshHelperInfo = async (uid?: string) => { + await refreshHelperInfoInner(uid) + } + + // Keep compatibility with existing callers. + const refleshHelperInfo = async (uid?: string) => { + await refreshHelperInfoInner(uid) + } + + const logout = () => { + helperInfo.value = null + errorMessage.value = '' + } + + return { + helperInfo, + loading, + errorMessage, + refleshHelperInfo, + refreshHelperInfo, + logout, + } +}) diff --git a/frontend-ui/src/stores/index.ts b/frontend-ui/src/stores/index.ts new file mode 100644 index 00000000..dcd07ad3 --- /dev/null +++ b/frontend-ui/src/stores/index.ts @@ -0,0 +1,6 @@ +import { createPinia } from 'pinia' + +export * from './info' +export * from './config' + +export const pinia = createPinia() diff --git a/frontend-ui/src/stores/info.ts b/frontend-ui/src/stores/info.ts new file mode 100644 index 00000000..5b738713 --- /dev/null +++ b/frontend-ui/src/stores/info.ts @@ -0,0 +1,194 @@ +import api from '@/api' +import type { ICharacterInfo, IEquipment, ISuit } from '@/api/info/type' +import { defineStore } from 'pinia' +import { useConfigStore } from './config' +import type { IResult, IResultSkill, IResultSkillCount } from '@/api/calc/type' + +export const useInfoStore = defineStore('infoStore', () => { + const alter_token = ref('') + const infos = ref(null) + + const oathCache = ref< + { + suitId: string + skillId: string + rarity: string + lv: number + data: ISuit + }[] + >([]) + + const skills = computed(() => infos.value?.skills ?? []) + + const equips = computed(() => infos.value?.equips ?? []) + + const suits = computed(() => infos.value?.suits ?? []) + + const enchants = computed(() => infos.value?.enchants ?? []) + + const emblems = computed(() => infos.value?.emblems ?? []) + + // const stones = computed(() => infos.value?.stones ?? []) + + const avatars = computed(() => infos.value?.avatar ?? {}) + + const jades = computed(() => infos.value?.jades ?? []) + + const sundries = computed(() => infos.value?.sundry ?? {}) + + const options = computed(() => infos.value?.options ?? []) + + const oaths = computed(() => { + const origin = infos.value?.oaths ?? [] + const result: IEquipment[] = [] + origin.forEach((o) => { + o.position.forEach((p) => { + result.push({ + ...o, + oathPos: p, + displayUrl: o.wearUrl?.[parseInt(p)] + ? `/equipment/icon/oathprimer/primer_equip/${o.wearUrl?.[parseInt(p)]}` + : o.imageUrl, + }) + }) + }) + return result + }) + + const getOathInfo = async (suitId: string, skillId: string, rarity: string, lv: number) => { + const res = oathCache.value.find( + (o) => o.suitId === suitId && o.skillId === skillId && o.rarity === rarity && o.lv === lv, + ) + if (res) { + return { + ...res.data, + } + } + const data: ISuit = await api.getOathInfo(suitId, skillId, rarity, lv) + oathCache.value.push({ suitId, skillId, rarity, lv, data }) + return { + ...data, + } + } + + const oathSkills = computed(() => { + const origin = infos.value?.oaths_skills + if (!origin) return origin + + const skillOrder = ['2', '1', '3'] + + return Object.fromEntries( + Object.entries(origin).map(([key, value]) => [ + key, + { + ...value, + skills: [...value.skills].sort((left, right) => { + const leftIndex = skillOrder.indexOf(left.skillId) + const rightIndex = skillOrder.indexOf(right.skillId) + const normalizedLeftIndex = leftIndex === -1 ? skillOrder.length : leftIndex + const normalizedRightIndex = rightIndex === -1 ? skillOrder.length : rightIndex + + return normalizedLeftIndex - normalizedRightIndex + }), + }, + ]), + ) + }) + const standardUUID = ref() + + const setStandard = ( + result?: IResult, + skillCount?: { + count: number + mode: string + name: string + }[], + ) => { + if (!result) { + if (standardUUID.value) { + sessionStorage.removeItem(standardUUID.value) + } + standardUUID.value = undefined + } else { + standardUUID.value = result.uuid + sessionStorage.setItem(result.uuid, JSON.stringify({ skills: result.skills, skillCount })) + } + } + + const standard = computed(() => { + const value = sessionStorage.getItem(standardUUID.value ?? '') + if (!value) return undefined + else return JSON.parse(value) as { skills: IResultSkill[]; skillCount: IResultSkillCount[] } + }) + + const parts = [ + '头肩', + '上衣', + '下装', + '腰带', + '鞋', + '武器', + '称号', + '手镯', + '项链', + '辅助装备', + '戒指', + '耳环', + '魔法石', + '宠物', + ] + + const avatarParts = [ + '武器装扮', + '头部', + '帽子', + '脸部', + '光环', + '胸部', + '上衣', + '皮肤', + '快捷栏装备', + '腰带', + '下装', + '鞋', + '宠物', + '宠物装备-红', + '宠物装备-绿', + '宠物装备-蓝', + ] + + const oathParts = Array.from({ length: 12 }, (_, i) => i.toString()) + + const emblemParts = ['彩色', '红色', '蓝色', '绿色', '黄色', '白金'] + + const createCharacter = async (alter: string, equVersion?: string) => { + const time = new Date().getTime() + alter_token.value = btoa(JSON.stringify({ alter, equVersion, time })) + infos.value = await api.characterInfo() + useConfigStore().loadConfig() + } + + return { + alter_token, + infos, + skills, + equips, + suits, + createCharacter, + enchants, + emblems, + parts, + oaths, + avatarParts, + oathParts, + emblemParts, + avatars, + jades, + setStandard, + standard, + sundries, + options, + oathSkills, + getOathInfo, + } +}) diff --git a/frontend-ui/src/style/animation.scss b/frontend-ui/src/style/animation.scss new file mode 100644 index 00000000..0c630b74 --- /dev/null +++ b/frontend-ui/src/style/animation.scss @@ -0,0 +1,55 @@ +@keyframes fade-in { + from { + opacity: 0; + } + to { + opacity: 1; + } +} + +@keyframes zoom-in { + from { + opacity: 0; + transform: scale(0.3); + } + to { + opacity: 1; + } +} + +@keyframes zoom-out { + 0% { + opacity: 1; + } + 50% { + opacity: 0; + transform: scale(0.3); + } + 100% { + opacity: 0; + } +} + +@keyframes dropdown-enter { + from { + max-height: 0; + opacity: 0; + } + to { + max-height: 160px; + opacity: 1; + transform: translateY(0); + } +} + +@keyframes dropdown-leave { + from { + opacity: 1; + max-height: 160px; + transform: translateY(0); + } + to { + opacity: 0; + max-height: 0; + } +} diff --git a/frontend-ui/src/style/app.scss b/frontend-ui/src/style/app.scss new file mode 100644 index 00000000..9c0922c5 --- /dev/null +++ b/frontend-ui/src/style/app.scss @@ -0,0 +1,458 @@ +@use './animation.scss'; + +.text-shadow { + text-shadow: + 0 0 1px #000, + 0 0 1px #000, + 0 0 1px #000, + 0 0 1px #000, + 0 0 1px #000, + 0 0 1px #000, + 0 0 1px #000, + 0 0 1px #000, + 0 0 1px #000, + 0 0 1px #000, + 0 0 1px #000, + 0 0 1px #000, + 0 0 1px #000, + 0 0 1px #000, + 0 0 1px #000, + 0 0 1px #000, + 0 0 1px #000, + 0 0 1px #000, + 0 0 1px #000, + 0 0 1px #000, + 0 0 1px #000, + 0 0 1px #000, + 0 0 1px #000, + 0 0 1px #000, + 0 0 1px #000, + 0 0 1px #000, + 0 0 1px #000, + 0 0 1px #000, + 0 0 1px #000, + 0 0 1px #000, + 0 0 1px #000, + 0 0 1px #000, + 0 0 1px #000, + 0 0 1px #000; +} + +@font-face { + font-family: 'dcalc'; + src: url('@/assets/fonts/dcalc.ttf'); +} + +:root { + font-size: 16px; + --cursor-pointer: + url('@/assets/cursor/basic.cur'), url('@/assets/cursor/cursor.png'), pointer !important; + --cursor-active: + url('@/assets/cursor/basic_press.cur'), url('@/assets/cursor/cursor.png'), pointer !important; +} + +html, +body, +[data-v-app] { + padding: 0; + margin: 0; + width: 100%; + height: 100%; + overflow-y: hidden; + overflow-x: hidden; + // letter-spacing: -0.05px; + + // font-family: "ArkPixel", "Consola", sans-serif; +} + +* { + // font-family: "ArkPixel", "Consola", sans-serif; + font-family: 'dcalc', 'SimSun'; + // font-family: "STSong"; + font-size: 12px; + text-shadow: + 0 0 1px #000, + 0 0 1px #000, + 0 0 1px #000, + 0 0 1px #000, + 0 0 1px #000, + 0 0 1px #000, + 0 0 1px #000, + 0 0 1px #000, + 0 0 1px #000, + 0 0 1px #000, + 0 0 1px #000, + 0 0 1px #000, + 0 0 1px #000, + 0 0 1px #000, + 0 0 1px #000, + 0 0 1px #000, + 0 0 1px #000, + 0 0 1px #000, + 0 0 1px #000, + 0 0 1px #000, + 0 0 1px #000, + 0 0 1px #000, + 0 0 1px #000, + 0 0 1px #000, + 0 0 1px #000, + 0 0 1px #000, + 0 0 1px #000, + 0 0 1px #000, + 0 0 1px #000, + 0 0 1px #000, + 0 0 1px #000, + 0 0 1px #000, + 0 0 1px #000, + 0 0 1px #000; + // image-rendering:pixelated; + // text-rendering: geometricPrecision; + // letter-spacing: -0.5px; +} + +@mixin pointer() { + cursor: var(--cursor-pointer); + + &:active { + cursor: var(--cursor-active); + } +} + +* { + user-select: none; + @include pointer(); +} + +.cursor-pointer { + @include pointer(); +} + +::-webkit-scrollbar { + background: rgb(0, 0, 0, 0.9); + width: 11px; + margin: 0px 0px 0px 0px; + @include pointer(); +} + +::-webkit-scrollbar-thumb { + background: rgb(36, 36, 36); + border: 1px solid rgb(76, 61, 39); + border-radius: 1px; + + &:hover { + background: rgb(52, 52, 52); + } +} + +::-webkit-scrollbar-button:vertical:single-button:start { + width: 11px; + // 添加标题栏后调整相关位置 + background: url('@/assets/img/icon/up.png') 0px 1px no-repeat; +} + +::-webkit-scrollbar-button:vertical:single-button:end { + width: 11px; + background: url('@/assets/img/icon/down.png') 0px 1px no-repeat; +} + +.divider { + width: calc(100% - 4px); + height: 1px; + background-color: rgba(58, 57, 58, 0.8); + margin: 8px 0; +} + +.mask-full { + width: 100%; + height: 100%; + position: absolute; + left: 0; + top: 0; + z-index: -1; + overflow: hidden; +} + +.icon { + width: 28px; + height: 28px; + position: relative; +} + +.icon-lay:not(.active) { + position: absolute; + width: 28px; + height: 28px; + z-index: 2; + background-color: rgba(0, 0, 0, 0.5); +} + +.tooltip { + width: 210px; + float: left; + border: 1px solid rgb(128, 128, 128); + padding: 10px 5px 10px 5px; + font-size: 0.75rem; + + .name { + padding: 0px 5px 0px 5px; + &::after { + content: ''; + width: 210px; + height: 8px; + background: url('@/assets/img/underline.png'); + display: block; + background-size: contain; + left: 5px; + margin-top: 4px; + } + } +} + +.tooltip-equipment { + @extend .tooltip; +} + +.tooltip-skill { + @extend .tooltip; + background-color: rgba(0, 0, 0, 0.3); + .name { + color: rgb(197, 172, 72); + } + + .name-p { + @extend .name; + color: rgb(139, 254, 133); + } + + .info { + color: rgb(132, 119, 78); + margin: 5px; + } +} + +.subitem { + background-color: rgb(11, 11, 11); + + .head-sec { + color: #b99460; + // font-size: 12px; + text-align: center; + height: 24px; + line-height: 24px; + background-image: linear-gradient(#2d281a, #16120c); + border-top: #443c2b solid 1px; + border-bottom: #211e10 solid 1px; + border-right: none; + border-left: none; + } + + .body-sec { + padding-top: 8px; + } +} + +.app-header { + // -webkit-app-region: drag; + background-image: url('@/assets/img/control/title.png'); + background-size: 100% 100%; + color: #9d8c5b; + border-top: 1px solid #6c81a7; + border-bottom: 1px solid #232d41; +} + +.min-icon { + -webkit-app-region: no-drag; + background: url('@/assets/img/icon/min.png') no-repeat; + + background-size: 10px 10px; + background-position: center; +} + +.close-icon { + -webkit-app-region: no-drag; + background: url('@/assets/img/icon/exit.png') no-repeat; + background-size: 10px 10px; + background-position: center; +} + +.normal { + color: #ffffff; +} +.advanced { + color: #68d5ed; +} +.rare { + color: #9879da; +} +.artifact { + color: #ef28c1; +} +.legend { + color: #ff7700; +} +.epic { + color: #fcb600; +} +.chronicle { + color: #ff6666; +} +.myth { + background-image: -webkit-gradient( + linear, + left top, + left bottom, + color-stop(0, #f8c63d), + color-stop(1, #cc66e7) + ); + color: transparent; + background-clip: text; + text-shadow: none; + -webkit-background-clip: text; + > span { + text-shadow: none !important; + } +} + +.primeval { + background-image: linear-gradient(to bottom, #5aff62, #58c6ff); + color: transparent; + background-clip: text; + text-shadow: none; + -webkit-background-clip: text; + > span { + text-shadow: none !important; + } +} + +// @keyframes primeval { +// 0% { +// background-image: url("@/assets/img/effect/primeval/0.png"); +// } +// 3.45% { +// background-image: url("@/assets/img/effect/primeval/1.png"); +// } +// 6.9% { +// background-image: url("@/assets/img/effect/primeval/2.png"); +// } +// 10.35% { +// background-image: url("@/assets/img/effect/primeval/3.png"); +// } +// 13.8% { +// background-image: url("@/assets/img/effect/primeval/4.png"); +// } +// 17.25% { +// background-image: url("@/assets/img/effect/primeval/5.png"); +// } +// 20.7% { +// background-image: url("@/assets/img/effect/primeval/6.png"); +// } +// 24.15% { +// background-image: url("@/assets/img/effect/primeval/7.png"); +// } +// 27.6% { +// background-image: url("@/assets/img/effect/primeval/8.png"); +// } +// 31.05% { +// background-image: url("@/assets/img/effect/primeval/9.png"); +// } +// 34.5% { +// background-image: url("@/assets/img/effect/primeval/10.png"); +// } +// 37.95% { +// background-image: url("@/assets/img/effect/primeval/11.png"); +// } +// 41.4% { +// background-image: url("@/assets/img/effect/primeval/12.png"); +// } +// 44.85% { +// background-image: url("@/assets/img/effect/primeval/13.png"); +// } +// 48.3% { +// background-image: url("@/assets/img/effect/primeval/14.png"); +// } +// 51.75% { +// background-image: url("@/assets/img/effect/primeval/15.png"); +// } +// 55.2% { +// background-image: url("@/assets/img/effect/primeval/16.png"); +// } +// 58.65% { +// background-image: url("@/assets/img/effect/primeval/17.png"); +// } +// 62.1% { +// background-image: url("@/assets/img/effect/primeval/18.png"); +// } +// 65.55% { +// background-image: url("@/assets/img/effect/primeval/19.png"); +// } +// 69% { +// background-image: url("@/assets/img/effect/primeval/20.png"); +// } +// 72.45% { +// background-image: url("@/assets/img/effect/primeval/21.png"); +// } +// 75.9% { +// background-image: url("@/assets/img/effect/primeval/22.png"); +// } +// 79.35% { +// background-image: url("@/assets/img/effect/primeval/23.png"); +// } +// 82.8% { +// background-image: url("@/assets/img/effect/primeval/24.png"); +// } +// 86.25% { +// background-image: url("@/assets/img/effect/primeval/25.png"); +// } +// 89.7% { +// background-image: url("@/assets/img/effect/primeval/26.png"); +// } +// 93.15% { +// background-image: url("@/assets/img/effect/primeval/27.png"); +// } +// 96.6% { +// background-image: url("@/assets/img/effect/primeval/28.png"); +// } +// 100% { +// background-image: url("@/assets/img/effect/primeval/29.png"); +// } +// } + +// .primeval_effect { +// // 应用动画到div上 +// width: 27px; +// height: 27px; +// background-size: cover; +// animation: primeval 2s infinite; +// // 设置动画名称,持续时间,和循环次数 +// mix-blend-mode: color-dodge; +// } + +.lvInfo { + background-image: url('@/assets/img/specificity/lv.png'); + background-repeat: no-repeat !important; + background-size: auto auto !important; + width: 30px; + height: 16px; + z-index: 10; + color: #4e3d1b; +} + +.lvInfoActive { + background-image: url('@/assets/img/specificity/lv_active.png'); + background-repeat: no-repeat !important; + background-size: auto auto !important; + width: 30px; + height: 16px; + z-index: 10; + color: #feb300; +} + +.lvInfoMaster { + background-image: url('@/assets/img/specificity/lv_master.png'); + background-repeat: no-repeat !important; + background-size: auto auto !important; + width: 30px; + height: 16px; + z-index: 10; + color: #feb300; +} diff --git a/frontend-ui/src/style/char-face.scss b/frontend-ui/src/style/char-face.scss new file mode 100644 index 00000000..cb4605cc --- /dev/null +++ b/frontend-ui/src/style/char-face.scss @@ -0,0 +1,403 @@ +// 极诣·剑魂 +.weapon_master { + background-image: url(https://bbscdn.df.nexon.com/pg/characters/img/main/mc_01_01.png); + background-position: -526 -102; +} + +// 极诣·鬼泣 +.soul_bender { + background-image: url(https://bbscdn.df.nexon.com/pg/characters/img/main/mc_01_02.png); + background-position: -516 -110; +} + +// 极诣·狂战士 +.berserker { + background-image: url(https://bbscdn.df.nexon.com/pg/characters/img/main/mc_01_03.png); + background-position: -294 -340; +} + +// 极诣·阿修罗 +.asura { + background-image: url(https://bbscdn.df.nexon.com/pg/characters/img/main/mc_01_04.png); + background-position: -608 -372; +} + +// 极诣·剑影 +.ghostblade { + background-image: url(https://bbscdn.df.nexon.com/pg/characters/img/main/mc_01_05.png); + background-position: -654 -302; +} + +// 极诣·驭剑士 +.sword_master { + background-image: url(https://bbscdn.df.nexon.com/pg/characters/img/main/mc_02_01.png); + background-position: -440 -160; +} + +// 极诣·暗殿骑士 +.dark_templar { + background-image: url(https://bbscdn.df.nexon.com/pg/characters/img/main/mc_02_04.png); + background-position: -573 -242; +} + +// 极诣·契魔者 +.demon_slayer { + background-image: url(https://bbscdn.df.nexon.com/pg/characters/img/main/mc_02_02.png); + background-position: -640 -134; +} + +// 极诣·流浪武士 +.vegabond { + background-image: url(https://bbscdn.df.nexon.com/pg/characters/img/main/mc_02_03.png); + background-position: -575 -193; +} + +// 极诣·刃影 +.spectre { + background-image: url(https://bbscdn.df.nexon.com/pg/characters/img/main/mc_02_05.png); + background-position: -567 -82; +} + +// 归元·气功师 +.nenmaster_male { + background-image: url(https://bbscdn.df.nexon.com/pg/characters/img/main/mc_03_01.png); + background-position: -554 -116; +} + +// 归元·散打 +.striker_male { + background-image: url(https://bbscdn.df.nexon.com/pg/characters/img/main/mc_03_02.png); + background-position: -429 -96; +} + +// 归元·街霸 +.brawler_male { + background-image: url(https://bbscdn.df.nexon.com/pg/characters/img/main/mc_03_03.png); + background-position: -602 -46; +} + +// 归元·柔道家 +.grappler_male { + background-image: url(https://bbscdn.df.nexon.com/pg/characters/img/main/mc_03_04.png); + background-position: -482 -95; +} + +// 归元·气功师 +.nenmaster_female { + background-image: url(https://bbscdn.df.nexon.com/pg/characters/img/main/mc_04_01.png); + background-position: -557 -219; +} + +// 归元·散打 +.striker_female { + background-image: url(https://bbscdn.df.nexon.com/pg/characters/img/main/mc_04_02.png); + background-position: -584 -127; +} + +// 归元·街霸 +.brawler_female { + background-image: url(https://bbscdn.df.nexon.com/pg/characters/img/main/mc_04_03.png); + background-position: -527 -215; +} + +// 归元·柔道家 +.grappler_female { + background-image: url(https://bbscdn.df.nexon.com/pg/characters/img/main/mc_04_04.png); + background-position: -561 -240; +} + +// 重霄·漫游枪手 +.ranger_male { + background-image: url(https://bbscdn.df.nexon.com/pg/characters/img/main/mc_05_01.png); + background-position: -670 -56; +} + +// 重霄·枪炮师 +.launcher_male { + background-image: url(https://bbscdn.df.nexon.com/pg/characters/img/main/mc_05_02.png); + background-position: -671 -74; +} + +// 重霄·机械师 +.mechanic_male { + background-image: url(https://bbscdn.df.nexon.com/pg/characters/img/main/mc_05_03.png); + background-position: -610 -93; +} + +// 重霄·弹药专家 +.spitfire_male { + background-image: url(https://bbscdn.df.nexon.com/pg/characters/img/main/mc_05_04.png); + background-position: -547 -234; +} + +// 重霄·合金战士 +.assault { + background-image: url(https://bbscdn.df.nexon.com/pg/characters/img/main/mc_05_05.png); + background-position: -537 -148; +} + +// 重霄·漫游枪手 +.ranger_female { + background-image: url(https://bbscdn.df.nexon.com/pg/characters/img/main/mc_06_01.png); + background-position: -626 -202; +} + +// 重霄·枪炮师 +.launcher_female { + background-image: url(https://bbscdn.df.nexon.com/pg/characters/img/main/mc_06_02.png); + background-position: -723 -296; +} + +// 重霄·机械师 +.mechanic_female { + background-image: url(https://bbscdn.df.nexon.com/pg/characters/img/main/mc_06_03.png); + background-position: -414 -242; +} + +// 重霄·弹药专家 +.spitfire_female { + background-image: url(https://bbscdn.df.nexon.com/pg/characters/img/main/mc_06_04.png); + background-position: -647 -261; +} + +// 知源·元素爆破师 +.elemental_bomber { + background-image: url(https://bbscdn.df.nexon.com/pg/characters/img/main/mc_07_01.png); + background-position: -384 -96; +} + +// 知源·冰结师 +.glacial_master { + background-image: url(https://bbscdn.df.nexon.com/pg/characters/img/main/mc_07_02.png); + background-position: -424 -220; +} + +// 知源·血法师 +.blood_mage { + background-image: url(https://bbscdn.df.nexon.com/pg/characters/img/main/mc_07_03.png); + background-position: -658 -340; +} + +// 知源·逐风者 +.swift_master { + background-image: url(https://bbscdn.df.nexon.com/pg/characters/img/main/mc_07_04.png); + background-position: -533 -560; +} + +// 知源·次元行者 +.dimension_walker { + background-image: url(https://bbscdn.df.nexon.com/pg/characters/img/main/mc_07_05.png); + background-position: -238 -68; +} + +// 知源·元素师 +.elementalist { + background-image: url(https://bbscdn.df.nexon.com/pg/characters/img/main/mc_08_01.png); + background-position: -591 -226; +} + +// 知源·召唤师 +.summoner { + background-image: url(https://bbscdn.df.nexon.com/pg/characters/img/main/mc_08_02.png); + background-position: -582 -341; +} + +// 知源·战斗法师 +.battle_mage { + background-image: url(https://bbscdn.df.nexon.com/pg/characters/img/main/mc_08_03.png); + background-position: -499 -97; +} + +// 知源·魔道学者 +.witch { + background-image: url(https://bbscdn.df.nexon.com/pg/characters/img/main/mc_08_04.png); + background-position: -625 -176; +} + +// 知源·小魔女 +.enchantress, +.enchantress_carry { + background-image: url(https://bbscdn.df.nexon.com/pg/characters/img/main/mc_08_05.png); + background-position: -593 -334; +} + +// 神启·圣骑士 +.crusader_male, +.crusader_male_carry { + background-image: url(https://bbscdn.df.nexon.com/pg/characters/img/main/mc_09_01.png); + background-position: -575 -245; +} + +// 神启·蓝拳圣使 +.infighter { + background-image: url(https://bbscdn.df.nexon.com/pg/characters/img/main/mc_09_02.png); + background-position: -583 -193; +} + +// 神启·驱魔师 +.exorcist { + background-image: url(https://bbscdn.df.nexon.com/pg/characters/img/main/mc_09_03.png); + background-position: -549 -192; +} + +// 神启·复仇者 +.avenger { + background-image: url(https://bbscdn.df.nexon.com/pg/characters/img/main/mc_09_04.png); + background-position: -489 -400; +} + +// 神启·圣骑士 +.crusader_female { + background-image: url(https://bbscdn.df.nexon.com/pg/characters/img/main/mc_10_01.png); + background-position: -560 -352; +} + +// 神启·异端审判者 +.inquistor { + background-image: url(https://bbscdn.df.nexon.com/pg/characters/img/main/mc_10_02.png); + background-position: -573 -293; +} + +// 神启·巫女 +.sorceress { + background-image: url(https://bbscdn.df.nexon.com/pg/characters/img/main/mc_10_03.png); + background-position: -407 -260; +} + +// 神启·诱魔者 +.mistress { + background-image: url(https://bbscdn.df.nexon.com/pg/characters/img/main/mc_10_04.png); + background-position: -646 -499; +} + +// 隐夜·刺客 +.rogue { + background-image: url(https://bbscdn.df.nexon.com/pg/characters/img/main/mc_11_01.png); + background-position: -344 -337; +} + +// 隐夜·死灵术士 +.necro { + background-image: url(https://bbscdn.df.nexon.com/pg/characters/img/main/mc_11_02.png); + background-position: -576 -352; +} + +// 隐夜·忍者 +.kunoichi { + background-image: url(https://bbscdn.df.nexon.com/pg/characters/img/main/mc_11_03.png); + background-position: -487 -229; +} + +// 隐夜·影舞者 +.shadow_dancer { + background-image: url(https://bbscdn.df.nexon.com/pg/characters/img/main/mc_11_04.png); + background-position: -758 -181; +} + +// 皓曦·精灵骑士 +.elven_knight { + background-image: url(https://bbscdn.df.nexon.com/pg/characters/img/main/mc_12_01.png); + background-position: -585 -280; +} + +// 皓曦·混沌魔灵 +.chaos { + background-image: url(https://bbscdn.df.nexon.com/pg/characters/img/main/mc_12_02.png); + background-position: -627 -379; +} + +// 皓曦·帕拉丁 +.paladin { + background-image: url(https://bbscdn.df.nexon.com/pg/characters/img/main/mc_12_03.png); + background-position: -545 -265; +} + +// 皓曦·龙骑士 +.dragon_knight { + background-image: url(https://bbscdn.df.nexon.com/pg/characters/img/main/mc_12_04.png); + background-position: -625 -335; +} + +// 千魂·征战者 +.vanguard { + background-image: url(https://bbscdn.df.nexon.com/pg/characters/img/main/mc_13_01.png); + background-position: -607 -186; +} + +// 千魂·决战者 +.skirmisher { + background-image: url(https://bbscdn.df.nexon.com/pg/characters/img/main/mc_13_02.png); + background-position: -452 -321; +} + +// 千魂·狩猎者 +.dragoon { + background-image: url(https://bbscdn.df.nexon.com/pg/characters/img/main/mc_13_03.png); + background-position: -564 -351; +} + +// 千魂·暗枪士 +.impaler { + background-image: url(https://bbscdn.df.nexon.com/pg/characters/img/main/mc_13_04.png); + background-position: -542 -289; +} + +// 苍暮·暗刃 +.hitman { + background-image: url(https://bbscdn.df.nexon.com/pg/characters/img/main/mc_14_03.png); + background-position: -533 -116; +} + +// 苍暮·特工 +.agent { + background-image: url(https://bbscdn.df.nexon.com/pg/characters/img/main/mc_14_01.png); + background-position: -575 -158; +} + +// 苍暮·战线佣兵 +.trouble_shooter { + background-image: url(https://bbscdn.df.nexon.com/pg/characters/img/main/mc_14_02.png); + background-position: -472 -234; +} + +// 苍暮·源能专家 +.specialist { + background-image: url(https://bbscdn.df.nexon.com/pg/characters/img/main/mc_14_04.png); + background-position: -662 -90; +} + +// 极诣·黑暗武士 +.dark_knight { + background-image: url(https://bbscdn.df.nexon.com/pg/characters/img/main/mc_17_01.png); + background-position: -502 -180; +} + +// 知源·缔造者 +.creator { + background-image: url(https://bbscdn.df.nexon.com/pg/characters/img/main/mc_18_01.png); + background-position: -571 -294; +} + +// 聆风·缪斯 +.muse { + background-image: url(https://bbscdn.df.nexon.com/pg/characters/img/main/mc_15_01.png); + background-position: -498 -94; +} + +// 聆风·旅人 +.traveler { + background-image: url(https://bbscdn.df.nexon.com/pg/characters/img/main/mc_15_02.png); + background-position: -607 -102; +} + +// 聆风·猎人 +.hunter { + background-image: url(https://bbscdn.df.nexon.com/pg/characters/img/main/mc_15_03.png); + background-position: -615 -126; +} + +// 聆风·妖护使 +.vigilante { + background-image: url(https://bbscdn.df.nexon.com/pg/characters/img/main/mc_15_04.png); + background-position: -422 -265; +} diff --git a/frontend-ui/src/style/char-img-jpg.scss b/frontend-ui/src/style/char-img-jpg.scss new file mode 100644 index 00000000..96551846 --- /dev/null +++ b/frontend-ui/src/style/char-img-jpg.scss @@ -0,0 +1,285 @@ +// 极诣·剑魂 +.weapon_master { + background: url(https://cdn.df.nexon.com/img/char_info/bg/bg01_3.jpg) no-repeat; +} +// 极诣·鬼泣 +.soul_bender { + background: url(https://cdn.df.nexon.com/img/char_info/bg/bg02_3.jpg) no-repeat; +} +// 极诣·狂战士 +.berserker { + background: url(https://cdn.df.nexon.com/img/char_info/bg/bg03_3.jpg) no-repeat; +} +// 极诣·阿修罗 +.asura { + background: url(https://cdn.df.nexon.com/img/char_info/bg/bg04_3.jpg) no-repeat; +} +// 极诣·剑影 +.ghostblade { + background: url(https://cdn.df.nexon.com/img/char_info/bg/bg05_3.jpg) no-repeat; +} +// 极诣·驭剑士 +.sword_master { + background: url(https://cdn.df.nexon.com/img/char_info/bg/bg06_3.jpg) no-repeat; +} +// 极诣·暗殿骑士 +.dark_templar { + background: url(https://cdn.df.nexon.com/img/char_info/bg/bg09_3.jpg) no-repeat; +} +// 极诣·契魔者 +.demon_slayer { + background: url(https://cdn.df.nexon.com/img/char_info/bg/bg07_3.jpg) no-repeat; +} +// 极诣·流浪武士 +.vegabond { + background: url(https://cdn.df.nexon.com/img/char_info/bg/bg08_3.jpg) no-repeat; +} +// 极诣·刃影 +.spectre { + background: url(https://cdn.df.nexon.com/img/char_info/bg/bg62_3.jpg) no-repeat; +} +// 归元·气功师 +.nenmaster_male { + background: url(https://cdn.df.nexon.com/img/char_info/bg/bg10_3.jpg) no-repeat; +} +// 归元·散打 +.striker_male { + background: url(https://cdn.df.nexon.com/img/char_info/bg/bg11_3.jpg) no-repeat; +} +// 归元·街霸 +.brawler_male { + background: url(https://cdn.df.nexon.com/img/char_info/bg/bg12_3.jpg) no-repeat; +} +// 归元·柔道家 +.grappler_male { + background: url(https://cdn.df.nexon.com/img/char_info/bg/bg13_3.jpg) no-repeat; +} +// 归元·气功师 +.nenmaster_female { + background: url(https://cdn.df.nexon.com/img/char_info/bg/bg14_3.jpg) no-repeat; +} +// 归元·散打 +.striker_female { + background: url(https://cdn.df.nexon.com/img/char_info/bg/bg15_3.jpg) no-repeat; +} +// 归元·街霸 +.brawler_female { + background: url(https://cdn.df.nexon.com/img/char_info/bg/bg16_3.jpg) no-repeat; +} +// 归元·柔道家 +.grappler_female { + background: url(https://cdn.df.nexon.com/img/char_info/bg/bg17_3.jpg) no-repeat; +} +// 重霄·漫游枪手 +.ranger_male { + background: url(https://cdn.df.nexon.com/img/char_info/bg/bg18_3.jpg) no-repeat; +} +// 重霄·枪炮师 +.launcher_male { + background: url(https://bbscdn.df.nexon.com/pg/characters/img/bg/bg19_3.jpg) no-repeat; +} +// 重霄·机械师 +.mechanic_male { + background: url(https://cdn.df.nexon.com/img/char_info/bg/bg20_3.jpg) no-repeat; +} +// 重霄·弹药专家 +.spitfire_male { + background: url(https://cdn.df.nexon.com/img/char_info/bg/bg21_3.jpg) no-repeat; +} +// 重霄·合金战士 +.assault { + background: url(https://cdn.df.nexon.com/img/char_info/bg/bg63_3.jpg) no-repeat; +} +// 重霄·漫游枪手 +.ranger_female { + background: url(https://cdn.df.nexon.com/img/char_info/bg/bg22_3.jpg) no-repeat; +} +// 重霄·枪炮师 +.launcher_female { + background: url(https://cdn.df.nexon.com/img/char_info/bg/bg23_3.jpg) no-repeat; +} +// 重霄·机械师 +.mechanic_female { + background: url(https://cdn.df.nexon.com/img/char_info/bg/bg24_3.jpg) no-repeat; +} +// 重霄·弹药专家 +.spitfire_female { + background: url(https://cdn.df.nexon.com/img/char_info/bg/bg25_3.jpg) no-repeat; +} +// 知源·元素爆破师 +.elemental_bomber { + background: url(https://cdn.df.nexon.com/img/char_info/bg/bg26_3.jpg) no-repeat; +} +// 知源·冰结师 +.glacial_master { + background: url(https://cdn.df.nexon.com/img/char_info/bg/bg27_3.jpg) no-repeat; +} +// 知源·血法师 +.blood_mage { + background: url(https://cdn.df.nexon.com/img/char_info/bg/bg28_3.jpg) no-repeat; +} +// 知源·逐风者 +.swift_master { + background: url(https://cdn.df.nexon.com/img/char_info/bg/bg29_3.jpg) no-repeat; +} +// 知源·次元行者 +.dimension_walker { + background: url(https://cdn.df.nexon.com/img/char_info/bg/bg30_3.jpg) no-repeat; +} +// 知源·元素师 +.elementalist { + background: url(https://cdn.df.nexon.com/img/char_info/bg/bg31_3.jpg) no-repeat; +} +// 知源·召唤师 +.summoner { + background: url(https://cdn.df.nexon.com/img/char_info/bg/bg32_3.jpg) no-repeat; +} +// 知源·战斗法师 +.battle_mage { + background: url(https://cdn.df.nexon.com/img/char_info/bg/bg33_3.jpg) no-repeat; +} +// 知源·魔道学者 +.witch { + background: url(https://cdn.df.nexon.com/img/char_info/bg/bg34_3.jpg) no-repeat; +} +// 知源·小魔女 +.enchantress { + background: url(https://cdn.df.nexon.com/img/char_info/bg/bg35_3.jpg) no-repeat; +} +// 神启·圣骑士 +.crusader_male, +.crusader_male_carry { + background: url(https://cdn.df.nexon.com/img/char_info/bg/bg36_3.jpg) no-repeat; +} +// 神启·蓝拳圣使 +.infighter { + background: url(https://cdn.df.nexon.com/img/char_info/bg/bg37_3.jpg) no-repeat; +} +// 神启·驱魔师 +.exorcist { + background: url(https://cdn.df.nexon.com/img/char_info/bg/bg38_3.jpg) no-repeat; +} +// 神启·复仇者 +.avenger { + background: url(https://cdn.df.nexon.com/img/char_info/bg/bg39_3.jpg) no-repeat; +} +// 神启·圣骑士 +.crusader_female { + background: url(https://cdn.df.nexon.com/img/char_info/bg/bg40_3.jpg) no-repeat; +} +// 神启·异端审判者 +.inquistor { + background: url(https://cdn.df.nexon.com/img/char_info/bg/bg41_3.jpg) no-repeat; +} +// 神启·巫女 +.sorceress { + background: url(https://cdn.df.nexon.com/img/char_info/bg/bg42_3.jpg) no-repeat; +} +// 神启·诱魔者 +.mistress { + background: url(https://cdn.df.nexon.com/img/char_info/bg/bg43_3.jpg) no-repeat; +} +// 隐夜·刺客 +.rogue { + background: url(https://cdn.df.nexon.com/img/char_info/bg/bg44_3.jpg) no-repeat; +} +// 隐夜·死灵术士 +.necro { + background: url(https://cdn.df.nexon.com/img/char_info/bg/bg45_3.jpg) no-repeat; +} +// 隐夜·忍者 +.kunoichi { + background: url(https://cdn.df.nexon.com/img/char_info/bg/bg46_3.jpg) no-repeat; +} +// 隐夜·影舞者 +.shadow_dancer { + background: url(https://cdn.df.nexon.com/img/char_info/bg/bg47_3.jpg) no-repeat; +} +// 皓曦·精灵骑士 +.elven_knight { + background: url(https://cdn.df.nexon.com/img/char_info/bg/bg48_3.jpg) no-repeat; +} +// 皓曦·混沌魔灵 +.chaos { + background: url(https://cdn.df.nexon.com/img/char_info/bg/bg49_3.jpg) no-repeat; +} +// 皓曦·帕拉丁 +.paladin { + background: url(https://cdn.df.nexon.com/img/char_info/bg/bg50_3.jpg) no-repeat; +} +// 皓曦·龙骑士 +.dragon_knight { + background: url(https://cdn.df.nexon.com/img/char_info/bg/bg51_3.jpg) no-repeat; +} +// 千魂·征战者 +.vanguard { + background: url(https://cdn.df.nexon.com/img/char_info/bg/bg52_3.jpg) no-repeat; +} +// 千魂·决战者 +.skirmisher { + background: url(https://cdn.df.nexon.com/img/char_info/bg/bg53_3.jpg) no-repeat; +} +// 千魂·狩猎者 +.dragoon { + background: url(https://cdn.df.nexon.com/img/char_info/bg/bg54_3.jpg) no-repeat; +} +// 千魂·暗枪士 +.impaler { + background: url(https://cdn.df.nexon.com/img/char_info/bg/bg55_3.jpg) no-repeat; +} +// 苍暮·暗刃 +.hitman { + background: url(https://cdn.df.nexon.com/img/char_info/bg/bg58_3.jpg) no-repeat; +} +// 苍暮·特工 +.agent { + background: url(https://cdn.df.nexon.com/img/char_info/bg/bg56_3.jpg) no-repeat; +} +// 苍暮·战线佣兵 +.trouble_shooter { + background: url(https://cdn.df.nexon.com/img/char_info/bg/bg57_3.jpg) no-repeat; +} +// 苍暮·源能专家 +.specialist { + background: url(https://cdn.df.nexon.com/img/char_info/bg/bg59_3.jpg) no-repeat; +} +.muse { + background: url(https://cdn.df.nexon.com/img/char_info/bg/bg64_3.jpg) no-repeat; +} +.traveler { + background: url(https://cdn.df.nexon.com/img/char_info/bg/bg65_3.jpg) no-repeat; +} +.hunter { + background: url(https://cdn.df.nexon.com/img/char_info/bg/bg66_3.jpg) no-repeat; +} +.vigilante { + background: url(https://cdn.df.nexon.com/img/char_info/bg/bg67_3.jpg) no-repeat; +} +// 知源·缔造者 +.creator { + background: url(https://cdn.df.nexon.com/img/char_info/bg/bg61_3.jpg) no-repeat; +} +// 极诣·黑暗武士 +.dark_knight { + background: url(https://cdn.df.nexon.com/img/char_info/bg/bg60_3.jpg) no-repeat; +} + +// 奇美拉 +.chimera { + background: url(https://bbscdn.df.nexon.com/pg/characters/img/bg/bg68_3.jpg) no-repeat; +} + +// 协战师 +.paramedic { + background: url(https://bbscdn.df.nexon.com/pg/characters/img/bg/bg69_3.jpg) no-repeat; +} + +// 蓝拳圣使 +.infighter_female { + background: url(https://bbscdn.df.nexon.com/pg/characters/img/bg/bg71_3.jpg) no-repeat; +} + +// 破浪者 +.breaker { + background: url(https://bbscdn.df.nexon.com/pg/characters/img/bg/bg70_3.jpg) no-repeat; +} diff --git a/frontend-ui/src/style/char-img.scss b/frontend-ui/src/style/char-img.scss new file mode 100644 index 00000000..55b3c4b0 --- /dev/null +++ b/frontend-ui/src/style/char-img.scss @@ -0,0 +1,355 @@ +// 极诣·剑魂 +.weapon_master { + background: url(https://bbscdn.df.nexon.com/pg/characters/img/main/mc_01_01.png) no-repeat; +} + +// 极诣·鬼泣 +.soul_bender { + background: url(https://bbscdn.df.nexon.com/pg/characters/img/main/mc_01_02.png) no-repeat; +} + +// 极诣·狂战士 +.berserker { + background: url(https://bbscdn.df.nexon.com/pg/characters/img/main/mc_01_03.png) no-repeat; +} + +// 极诣·阿修罗 +.asura { + background: url(https://bbscdn.df.nexon.com/pg/characters/img/main/mc_01_04.png) no-repeat; +} + +// 极诣·剑影 +.ghostblade { + background: url(https://bbscdn.df.nexon.com/pg/characters/img/main/mc_01_05.png) no-repeat; +} + +// 极诣·驭剑士 +.sword_master { + background: url(https://bbscdn.df.nexon.com/pg/characters/img/main/mc_02_01.png) no-repeat; +} + +// 极诣·暗殿骑士 +.dark_templar { + background: url(https://bbscdn.df.nexon.com/pg/characters/img/main/mc_02_04.png) no-repeat; +} + +// 极诣·契魔者 +.demon_slayer { + background: url(https://bbscdn.df.nexon.com/pg/characters/img/main/mc_02_02.png) no-repeat; +} + +// 极诣·流浪武士 +.vegabond { + background: url(https://bbscdn.df.nexon.com/pg/characters/img/main/mc_02_03.png) no-repeat; +} + +// 极诣·刃影 +.spectre { + background: url(https://bbscdn.df.nexon.com/pg/characters/img/main/mc_02_05.png) no-repeat; +} + +// 归元·气功师 +.nenmaster_male { + background: url(https://bbscdn.df.nexon.com/pg/characters/img/main/mc_03_01.png) no-repeat; +} + +// 归元·散打 +.striker_male { + background: url(https://bbscdn.df.nexon.com/pg/characters/img/main/mc_03_02.png) no-repeat; +} + +// 归元·街霸 +.brawler_male { + background: url(https://bbscdn.df.nexon.com/pg/characters/img/main/mc_03_03.png) no-repeat; +} + +// 归元·柔道家 +.grappler_male { + background: url(https://bbscdn.df.nexon.com/pg/characters/img/main/mc_03_04.png) no-repeat; +} + +// 归元·气功师 +.nenmaster_female { + background: url(https://bbscdn.df.nexon.com/pg/characters/img/main/mc_04_01.png) no-repeat; +} + +// 归元·散打 +.striker_female { + background: url(https://bbscdn.df.nexon.com/pg/characters/img/main/mc_04_02.png) no-repeat; +} + +// 归元·街霸 +.brawler_female { + background: url(https://bbscdn.df.nexon.com/pg/characters/img/main/mc_04_03.png) no-repeat; +} + +// 归元·柔道家 +.grappler_female { + background: url(https://bbscdn.df.nexon.com/pg/characters/img/main/mc_04_04.png) no-repeat; +} + +// 重霄·漫游枪手 +.ranger_male { + background: url(https://bbscdn.df.nexon.com/pg/characters/img/main/mc_05_01.png) no-repeat; +} + +// 重霄·枪炮师 +.launcher_male { + background: url(https://bbscdn.df.nexon.com/pg/characters/img/main/mc_05_02.png) no-repeat; +} + +// 重霄·机械师 +.mechanic_male { + background: url(https://bbscdn.df.nexon.com/pg/characters/img/main/mc_05_03.png) no-repeat; +} + +// 重霄·弹药专家 +.spitfire_male { + background: url(https://bbscdn.df.nexon.com/pg/characters/img/main/mc_05_04.png) no-repeat; +} + +// 重霄·合金战士 +.assault { + background: url(https://bbscdn.df.nexon.com/pg/characters/img/main/mc_05_05.png) no-repeat; +} + +// 重霄·漫游枪手 +.ranger_female { + background: url(https://bbscdn.df.nexon.com/pg/characters/img/main/mc_06_01.png) no-repeat; +} + +// 重霄·枪炮师 +.launcher_female { + background: url(https://bbscdn.df.nexon.com/pg/characters/img/main/mc_06_02.png) no-repeat; +} + +// 重霄·机械师 +.mechanic_female { + background: url(https://bbscdn.df.nexon.com/pg/characters/img/main/mc_06_03.png) no-repeat; +} + +// 重霄·弹药专家 +.spitfire_female { + background: url(https://bbscdn.df.nexon.com/pg/characters/img/main/mc_06_04.png) no-repeat; +} + +// 重霄·协战师 +.paramedic { + background: url(https://bbscdn.df.nexon.com/pg/characters/img/main/mc_06_05.png) no-repeat; +} + +// 知源·元素爆破师 +.elemental_bomber { + background: url(https://bbscdn.df.nexon.com/pg/characters/img/main/mc_07_01.png) no-repeat; +} + +// 知源·冰结师 +.glacial_master { + background: url(https://bbscdn.df.nexon.com/pg/characters/img/main/mc_07_02.png) no-repeat; +} + +// 知源·血法师 +.blood_mage { + background: url(https://bbscdn.df.nexon.com/pg/characters/img/main/mc_07_03.png) no-repeat; +} + +// 知源·逐风者 +.swift_master { + background: url(https://bbscdn.df.nexon.com/pg/characters/img/main/mc_07_04.png) no-repeat; +} + +// 知源·次元行者 +.dimension_walker { + background: url(https://bbscdn.df.nexon.com/pg/characters/img/main/mc_07_05.png) no-repeat; +} + +// 知源·元素师 +.elementalist { + background: url(https://bbscdn.df.nexon.com/pg/characters/img/main/mc_08_01.png) no-repeat; +} + +// 知源·召唤师 +.summoner { + background: url(https://bbscdn.df.nexon.com/pg/characters/img/main/mc_08_02.png) no-repeat; +} + +// 知源·战斗法师 +.battle_mage { + background: url(https://bbscdn.df.nexon.com/pg/characters/img/main/mc_08_03.png) no-repeat; +} + +// 知源·魔道学者 +.witch { + background: url(https://bbscdn.df.nexon.com/pg/characters/img/main/mc_08_04.png) no-repeat; +} + +// 知源·小魔女 +.enchantress, +.enchantress_carry { + background: url(https://bbscdn.df.nexon.com/pg/characters/img/main/mc_08_05.png) no-repeat; +} + +// 神启·圣骑士 +.crusader_male, +.crusader_male_carry { + background: url(https://bbscdn.df.nexon.com/pg/characters/img/main/mc_09_01.png) no-repeat; +} + +// 神启·蓝拳圣使 +.infighter { + background: url(https://bbscdn.df.nexon.com/pg/characters/img/main/mc_09_02.png) no-repeat; +} + +// 神启·驱魔师 +.exorcist { + background: url(https://bbscdn.df.nexon.com/pg/characters/img/main/mc_09_03.png) no-repeat; +} + +// 神启·复仇者 +.avenger { + background: url(https://bbscdn.df.nexon.com/pg/characters/img/main/mc_09_04.png) no-repeat; +} + +// 神启·圣骑士 +.crusader_female { + background: url(https://bbscdn.df.nexon.com/pg/characters/img/main/mc_10_01.png) no-repeat; +} + +// 神启·异端审判者 +.inquistor { + background: url(https://bbscdn.df.nexon.com/pg/characters/img/main/mc_10_02.png) no-repeat; +} + +// 神启·巫女 +.sorceress { + background: url(https://bbscdn.df.nexon.com/pg/characters/img/main/mc_10_03.png) no-repeat; +} + +// 神启·诱魔者 +.mistress { + background: url(https://bbscdn.df.nexon.com/pg/characters/img/main/mc_10_04.png) no-repeat; +} + +// 神启·蓝拳圣使 +.infighter_female { + background: url(https://bbscdn.df.nexon.com/pg/characters/img/main/mc_10_05.png) no-repeat; +} + +// 隐夜·刺客 +.rogue { + background: url(https://bbscdn.df.nexon.com/pg/characters/img/main/mc_11_01.png) no-repeat; +} + +// 隐夜·死灵术士 +.necro { + background: url(https://bbscdn.df.nexon.com/pg/characters/img/main/mc_11_02.png) no-repeat; +} + +// 隐夜·忍者 +.kunoichi { + background: url(https://bbscdn.df.nexon.com/pg/characters/img/main/mc_11_03.png) no-repeat; +} + +// 隐夜·影舞者 +.shadow_dancer { + background: url(https://bbscdn.df.nexon.com/pg/characters/img/main/mc_11_04.png) no-repeat; +} + +// 皓曦·精灵骑士 +.elven_knight { + background: url(https://bbscdn.df.nexon.com/pg/characters/img/main/mc_12_01.png) no-repeat; +} + +// 皓曦·混沌魔灵 +.chaos { + background: url(https://bbscdn.df.nexon.com/pg/characters/img/main/mc_12_02.png) no-repeat; +} + +// 皓曦·帕拉丁 +.paladin { + background: url(https://bbscdn.df.nexon.com/pg/characters/img/main/mc_12_03.png) no-repeat; +} + +// 皓曦·龙骑士 +.dragon_knight { + background: url(https://bbscdn.df.nexon.com/pg/characters/img/main/mc_12_04.png) no-repeat; +} + +// 千魂·征战者 +.vanguard { + background: url(https://bbscdn.df.nexon.com/pg/characters/img/main/mc_13_01.png) no-repeat; +} + +// 千魂·决战者 +.skirmisher { + background: url(https://bbscdn.df.nexon.com/pg/characters/img/main/mc_13_02.png) no-repeat; +} + +// 千魂·狩猎者 +.dragoon { + background: url(https://bbscdn.df.nexon.com/pg/characters/img/main/mc_13_03.png) no-repeat; +} + +// 千魂·暗枪士 +.impaler { + background: url(https://bbscdn.df.nexon.com/pg/characters/img/main/mc_13_04.png) no-repeat; +} + +// 苍暮·暗刃 +.hitman { + background: url(https://bbscdn.df.nexon.com/pg/characters/img/main/mc_14_03.png) no-repeat; +} + +// 苍暮·特工 +.agent { + background: url(https://bbscdn.df.nexon.com/pg/characters/img/main/mc_14_01.png) no-repeat; +} + +// 苍暮·战线佣兵 +.trouble_shooter { + background: url(https://bbscdn.df.nexon.com/pg/characters/img/main/mc_14_02.png) no-repeat; +} + +// 苍暮·源能专家 +.specialist { + background: url(https://bbscdn.df.nexon.com/pg/characters/img/main/mc_14_04.png) no-repeat; +} + +// 极诣·黑暗武士 +.dark_knight { + background: url(https://bbscdn.df.nexon.com/pg/characters/img/main/mc_17_01.png) no-repeat; +} + +// 知源·缔造者 +.creator { + background: url(https://bbscdn.df.nexon.com/pg/characters/img/main/mc_18_01.png) no-repeat; +} + +// 聆风·缪斯 +.muse { + background: url(https://bbscdn.df.nexon.com/pg/characters/img/main/mc_15_01.png) no-repeat; +} + +// 聆风·旅人 +.traveler { + background: url(https://bbscdn.df.nexon.com/pg/characters/img/main/mc_15_02.png) no-repeat; +} + +// 聆风·猎人 +.hunter { + background: url(https://bbscdn.df.nexon.com/pg/characters/img/main/mc_15_03.png) no-repeat; +} + +// 聆风·妖护使 +.vigilante { + background: url(https://bbscdn.df.nexon.com/pg/characters/img/main/mc_15_04.png) no-repeat; +} + +.chimera { + background: url(https://bbscdn.df.nexon.com/pg/characters/img/main/mc_15_05.png) no-repeat; +} + +// 鸣锋·破浪者 +.breaker { + background: url(https://bbscdn.df.nexon.com/pg/characters/img/main/mc_16_01.png) no-repeat; +} diff --git a/frontend-ui/src/style/components/button.css b/frontend-ui/src/style/components/button.css new file mode 100644 index 00000000..88796df1 --- /dev/null +++ b/frontend-ui/src/style/components/button.css @@ -0,0 +1,85 @@ +.ui-button { + border-width: 1px; + border-style: solid; + border-radius: 0; + color: var(--ui-primary-foreground); + font-family: inherit; + font-weight: 400; + text-decoration: none; + text-shadow: + 1px 1px 0 #000, + 0 0 2px #000; + box-shadow: none; +} + +.ui-button:focus-visible { + outline: 1px solid var(--ui-ring); + outline-offset: 1px; + color: #eee2aa; +} + +.ui-button:active:not(:disabled) { + transform: translateY(1px); +} + +.ui-button--primary { + border-color: var(--ui-control-border); + background: var(--ui-control-background); +} + +.ui-button--primary:hover:not(:disabled), +.ui-button--primary.is-demo-hover { + color: var(--ui-accent-foreground); + background: var(--ui-control-background-hover); +} + +.ui-button--primary:active:not(:disabled), +.ui-button--primary.is-demo-pressed { + border-color: var(--ui-control-border-active); + background: var(--ui-control-background-active); +} + +.ui-button.is-demo-pressed { + transform: translateY(1px); +} + +.ui-button--secondary { + border-color: #4f5128; + background: linear-gradient(180deg, #014f22, #013f1b); + color: #b7d895; +} + +.ui-button--outline { + border-color: var(--ui-border); + background: #101211; + color: var(--ui-foreground); +} + +.ui-button--outline:hover:not(:disabled), +.ui-button--secondary:hover:not(:disabled) { + filter: brightness(1.18); + color: var(--ui-accent-foreground); +} + +.ui-button--destructive { + border-color: #6a4829; + background: linear-gradient(180deg, #522d01, #412401); + color: #e2b46e; +} + +.ui-button--ghost { + border-color: transparent; + background: transparent; + color: var(--ui-foreground); +} + +.ui-button--ghost:hover:not(:disabled) { + background: var(--ui-muted); +} + +.ui-button:disabled { + border-color: var(--ui-control-disabled-border); + background: var(--ui-control-disabled-background); + color: var(--ui-control-disabled-foreground); + opacity: 1; +} diff --git a/frontend-ui/src/style/icon.scss b/frontend-ui/src/style/icon.scss new file mode 100644 index 00000000..5974e99e --- /dev/null +++ b/frontend-ui/src/style/icon.scss @@ -0,0 +1,134 @@ +@mixin icon-style( + $icon-name, + $width: 20px, + $height: 20px, + $size: 100% 100%, + $position: center center, + $img-type: 'png' +) { + background-image: url('@/assets/img/icon/#{$icon-name}.#{$img-type}') !important; + background-repeat: no-repeat !important; + background-size: $size !important; + background-position: $position !important; + width: $width !important; + height: $height !important; + + &:hover { + background-image: url('@/assets/img/icon/#{$icon-name}_hover.#{$img-type}') !important; + } + &:active { + background-image: url('@/assets/img/icon/#{$icon-name}_active.#{$img-type}') !important; + height: $height - 2px !important; + } + &:disabled { + background-image: url('@/assets/img/icon/#{$icon-name}_disabled.#{$img-type}') !important; + } +} + +.icon-reset { + @include icon-style('reset'); +} + +.icon-set { + @include icon-style('set'); +} + +.icon-prev { + @include icon-style('prev', 16px, 16px); +} + +.icon-next { + @include icon-style('next', 16px, 16px); +} + +.icon-dropdown { + @include icon-style('dropdown', 16px, 16px); +} + +.icon-search { + @include icon-style('search'); +} + +.icon-increase { + @include icon-style('increase'); +} + +.icon-reduce { + @include icon-style('reduce'); +} + +.icon-plus { + @include icon-style('plus'); +} + +.icon-detail { + @include icon-style('detail'); +} + +.icon-home { + @include icon-style('home'); +} + +.icon-reflesh { + @include icon-style('reflesh'); +} + +.icon-update { + @include icon-style('update'); +} + +.icon-share { + @include icon-style('share'); +} + +.icon-import { + @include icon-style('import'); +} + +.icon-menu-drug { + @include icon-style('menu/drug', 20px, 20px, auto 100%); +} + +.icon-menu-specificity { + @include icon-style('menu/specificity', 20px, 20px, auto 100%); +} + +.icon-menu-favourite { + @include icon-style('menu/favourite', 20px, 20px, auto 100%); +} + +.icon-menu-recommend { + @include icon-style('menu/recommend', 20px, 20px, auto 100%); +} + +.icon-menu-set { + @include icon-style('menu/set', 20px, 20px, auto 100%); +} + +.icon-max { + @include icon-style('max'); +} + +.icon-min { + @include icon-style('min'); +} + +.icon-exchange { + @include icon-style('exchange', 22px, 20px, auto 100%, center center, svg); +} + +.icon-increase-little { + @include icon-style('increase', 16px, 16px); +} + +.icon-reduce-little { + @include icon-style('reduce', 16px, 16px); +} + +.icon-max-little { + @include icon-style('max', 16px, 16px); +} + +.icon-min-little { + @include icon-style('min', 16px, 16px); +} diff --git a/frontend-ui/src/style/index.scss b/frontend-ui/src/style/index.scss new file mode 100644 index 00000000..f2d02958 --- /dev/null +++ b/frontend-ui/src/style/index.scss @@ -0,0 +1,3 @@ +@use './app.scss'; +@use './icon.scss'; +@use './char-img.scss'; diff --git a/frontend-ui/src/style/tailwind.css b/frontend-ui/src/style/tailwind.css new file mode 100644 index 00000000..36e69c9b --- /dev/null +++ b/frontend-ui/src/style/tailwind.css @@ -0,0 +1,64 @@ +@layer theme, base, components, utilities; + +@import 'tailwindcss/theme.css' layer(theme); +@import './tokens/primitives.css'; +@import './themes/dcalc.css'; +@import './themes/midnight.css'; +@import './components/button.css'; +@import 'tailwindcss/utilities.css' layer(utilities); + +@source '../**/*.{vue,ts,tsx}'; + +@theme inline { + --font-sans: 'DCalc', 'dcalc', SimSun, 'Microsoft YaHei', sans-serif; + + --color-background: var(--ui-background); + --color-foreground: var(--ui-foreground); + --color-card: var(--ui-surface); + --color-card-foreground: var(--ui-surface-foreground); + --color-popover: var(--ui-popover); + --color-popover-foreground: var(--ui-popover-foreground); + --color-primary: var(--ui-primary); + --color-primary-foreground: var(--ui-primary-foreground); + --color-secondary: var(--ui-secondary); + --color-secondary-foreground: var(--ui-secondary-foreground); + --color-muted: var(--ui-muted); + --color-muted-foreground: var(--ui-muted-foreground); + --color-accent: var(--ui-accent); + --color-accent-foreground: var(--ui-accent-foreground); + --color-destructive: var(--ui-destructive); + --color-destructive-foreground: var(--ui-destructive-foreground); + --color-border: var(--ui-border); + --color-input: var(--ui-input); + --color-ring: var(--ui-ring); + + --radius-sm: var(--ui-radius-sm); + --radius-md: var(--ui-radius-md); + --radius-lg: var(--ui-radius-lg); +} + +@keyframes fade-in { + from { + opacity: 0; + } +} + +@keyframes fade-out { + to { + opacity: 0; + } +} + +@keyframes dialog-in { + from { + opacity: 0; + transform: translate(-50%, -48%) scale(0.98); + } +} + +@keyframes dialog-out { + to { + opacity: 0; + transform: translate(-50%, -48%) scale(0.98); + } +} diff --git a/frontend-ui/src/style/themes/dcalc.css b/frontend-ui/src/style/themes/dcalc.css new file mode 100644 index 00000000..a4d9b5bd --- /dev/null +++ b/frontend-ui/src/style/themes/dcalc.css @@ -0,0 +1,49 @@ +:root, +[data-theme='dcalc'] { + color-scheme: dark; + + --ui-background: var(--dcalc-black-950); + --ui-foreground: var(--dcalc-text-secondary); + --ui-surface: var(--dcalc-panel); + --ui-surface-foreground: var(--dcalc-text-secondary); + --ui-popover: #090a0a; + --ui-popover-foreground: var(--dcalc-text); + --ui-primary: var(--dcalc-blue-900); + --ui-primary-foreground: #e9c556; + --ui-secondary: var(--dcalc-row); + --ui-secondary-foreground: var(--dcalc-gold); + --ui-muted: #191a19; + --ui-muted-foreground: var(--dcalc-text-muted); + --ui-accent: #2d4e9f; + --ui-accent-foreground: #fee97d; + --ui-destructive: var(--dcalc-danger); + --ui-destructive-foreground: #fff4f4; + --ui-border: var(--dcalc-brass-dark); + --ui-input: #5b472a; + --ui-ring: var(--dcalc-focus); + --ui-overlay: rgb(0 0 0 / 66%); + + --ui-radius-sm: 2px; + --ui-radius-md: 2px; + --ui-radius-lg: 2px; + + --ui-titlebar-background: linear-gradient(180deg, #5a7099, #415272 55%, #313e58); + --ui-titlebar-foreground: #f0f2ef; + --ui-panel-heading: #111313; + --ui-panel-heading-border: #242725; + --ui-panel-border: #403421; + --ui-row-background: #101210; + --ui-table-header: linear-gradient(180deg, #352817 0%, #1b170d 48%, #090a07 100%); + --ui-table-header-foreground: #bc9e58; + + --ui-control-background: linear-gradient(180deg, #223768, #122438); + --ui-control-background-hover: linear-gradient(180deg, #2b477f, #213766); + --ui-control-background-active: linear-gradient(180deg, #2b477f, #213766); + --ui-control-border: #684f2d; + --ui-control-border-active: #927243; + --ui-control-disabled-background: linear-gradient(180deg, #2c2c2c, #222); + --ui-control-disabled-border: #343434; + --ui-control-disabled-foreground: #4d4b4d; + --ui-panel-background: linear-gradient(180deg, rgb(20 22 22 / 98%), rgb(7 8 8 / 98%)); + --ui-panel-shadow: inset 0 1px 0 rgb(214 196 135 / 6%), 0 12px 28px rgb(0 0 0 / 32%); +} diff --git a/frontend-ui/src/style/themes/midnight.css b/frontend-ui/src/style/themes/midnight.css new file mode 100644 index 00000000..4006187f --- /dev/null +++ b/frontend-ui/src/style/themes/midnight.css @@ -0,0 +1,35 @@ +[data-theme='midnight'] { + color-scheme: dark; + + --ui-background: #080b12; + --ui-foreground: #d9e3f2; + --ui-surface: #111827; + --ui-surface-foreground: #e5edf8; + --ui-popover: #0c1220; + --ui-popover-foreground: #edf5ff; + --ui-primary: #23406f; + --ui-primary-foreground: #dcecff; + --ui-secondary: #1a2435; + --ui-secondary-foreground: #c9d8ef; + --ui-muted: #151d2a; + --ui-muted-foreground: #8da0bc; + --ui-accent: #315c97; + --ui-accent-foreground: #ffffff; + --ui-destructive: #a73f45; + --ui-destructive-foreground: #fff4f4; + --ui-border: #40577a; + --ui-input: #354b6e; + --ui-ring: #6fb5e6; + --ui-overlay: rgb(2 6 14 / 72%); + + --ui-control-background: linear-gradient(180deg, #294d80, #172b4b); + --ui-control-background-hover: linear-gradient(180deg, #376aa7, #1e3b64); + --ui-control-background-active: linear-gradient(180deg, #244e82, #142b4a); + --ui-control-border: #526f98; + --ui-control-border-active: #9ac8ef; + --ui-control-disabled-background: linear-gradient(180deg, #303846, #202733); + --ui-control-disabled-border: #3f4958; + --ui-control-disabled-foreground: #748094; + --ui-panel-background: linear-gradient(180deg, rgb(17 24 39 / 98%), rgb(7 12 22 / 98%)); + --ui-panel-shadow: inset 0 1px 0 rgb(143 196 241 / 8%), 0 12px 30px rgb(0 0 0 / 40%); +} diff --git a/frontend-ui/src/style/tokens/primitives.css b/frontend-ui/src/style/tokens/primitives.css new file mode 100644 index 00000000..560d167b --- /dev/null +++ b/frontend-ui/src/style/tokens/primitives.css @@ -0,0 +1,34 @@ +:root { + --dcalc-black-950: #050505; + --dcalc-black-900: #090808; + --dcalc-panel: #131515; + --dcalc-row: #1f1f1e; + --dcalc-row-strong: #2e2e2c; + --dcalc-title-top: #5a7099; + --dcalc-title-middle: #415272; + --dcalc-title-bottom: #313e58; + --dcalc-blue-900: #1a2b4e; + --dcalc-blue-800: #203259; + --dcalc-blue-950: #16264c; + --dcalc-brass-dark: #504029; + --dcalc-brass: #907746; + --dcalc-gold: #d6c487; + --dcalc-selected: #daa41d; + --dcalc-focus: #4ba7d3; + --dcalc-text: #f6f8f4; + --dcalc-text-secondary: #d6d3c6; + --dcalc-text-muted: #a7a396; + --dcalc-disabled: #4d4b4d; + --dcalc-info: #54c1db; + --dcalc-success: #49a355; + --dcalc-warning: #c28954; + --dcalc-danger: #bb3331; + + --dcalc-quality-normal: #ffffff; + --dcalc-quality-advanced: #68d5ed; + --dcalc-quality-rare: #9879da; + --dcalc-quality-artifact: #ef28c1; + --dcalc-quality-legend: #ff7700; + --dcalc-quality-epic: #fcb600; + --dcalc-quality-chronicle: #ff6666; +} diff --git a/frontend-ui/src/types/auto-imports.d.ts b/frontend-ui/src/types/auto-imports.d.ts new file mode 100644 index 00000000..485c3daf --- /dev/null +++ b/frontend-ui/src/types/auto-imports.d.ts @@ -0,0 +1,311 @@ +/* eslint-disable */ +/* prettier-ignore */ +/* oxlint-disable */ +/* oxfmt-ignore */ +// @ts-nocheck +// noinspection JSUnusedGlobalSymbols +// Generated by unplugin-auto-import +// biome-ignore lint: disable +export {} +declare global { + const EffectScope: typeof import('vue').EffectScope + const asyncComputed: typeof import('@vueuse/core').asyncComputed + const autoResetRef: typeof import('@vueuse/core').autoResetRef + const computed: typeof import('vue').computed + const computedAsync: typeof import('@vueuse/core').computedAsync + const computedEager: typeof import('@vueuse/core').computedEager + const computedInject: typeof import('@vueuse/core').computedInject + const computedWithControl: typeof import('@vueuse/core').computedWithControl + const controlledComputed: typeof import('@vueuse/core').controlledComputed + const controlledRef: typeof import('@vueuse/core').controlledRef + const createApp: typeof import('vue').createApp + const createDisposableDirective: typeof import('@vueuse/core').createDisposableDirective + const createEventHook: typeof import('@vueuse/core').createEventHook + const createGlobalState: typeof import('@vueuse/core').createGlobalState + const createInjectionState: typeof import('@vueuse/core').createInjectionState + const createReactiveFn: typeof import('@vueuse/core').createReactiveFn + const createRef: typeof import('@vueuse/core').createRef + const createReusableTemplate: typeof import('@vueuse/core').createReusableTemplate + const createSharedComposable: typeof import('@vueuse/core').createSharedComposable + const createTemplatePromise: typeof import('@vueuse/core').createTemplatePromise + const createUnrefFn: typeof import('@vueuse/core').createUnrefFn + const customRef: typeof import('vue').customRef + const debouncedRef: typeof import('@vueuse/core').debouncedRef + const debouncedWatch: typeof import('@vueuse/core').debouncedWatch + const defineAsyncComponent: typeof import('vue').defineAsyncComponent + const defineComponent: typeof import('vue').defineComponent + const eagerComputed: typeof import('@vueuse/core').eagerComputed + const effectScope: typeof import('vue').effectScope + const extendRef: typeof import('@vueuse/core').extendRef + const getCurrentInstance: typeof import('vue').getCurrentInstance + const getCurrentScope: typeof import('vue').getCurrentScope + const getCurrentWatcher: typeof import('vue').getCurrentWatcher + const h: typeof import('vue').h + const ignorableWatch: typeof import('@vueuse/core').ignorableWatch + const inject: typeof import('vue').inject + const injectLocal: typeof import('@vueuse/core').injectLocal + const isDefined: typeof import('@vueuse/core').isDefined + const isProxy: typeof import('vue').isProxy + const isReactive: typeof import('vue').isReactive + const isReadonly: typeof import('vue').isReadonly + const isRef: typeof import('vue').isRef + const isShallow: typeof import('vue').isShallow + const makeDestructurable: typeof import('@vueuse/core').makeDestructurable + const markRaw: typeof import('vue').markRaw + const nextTick: typeof import('vue').nextTick + const onActivated: typeof import('vue').onActivated + const onBeforeMount: typeof import('vue').onBeforeMount + const onBeforeRouteLeave: typeof import('vue-router').onBeforeRouteLeave + const onBeforeRouteUpdate: typeof import('vue-router').onBeforeRouteUpdate + const onBeforeUnmount: typeof import('vue').onBeforeUnmount + const onBeforeUpdate: typeof import('vue').onBeforeUpdate + const onClickOutside: typeof import('@vueuse/core').onClickOutside + const onDeactivated: typeof import('vue').onDeactivated + const onElementRemoval: typeof import('@vueuse/core').onElementRemoval + const onErrorCaptured: typeof import('vue').onErrorCaptured + const onKeyStroke: typeof import('@vueuse/core').onKeyStroke + const onLongPress: typeof import('@vueuse/core').onLongPress + const onMounted: typeof import('vue').onMounted + const onRenderTracked: typeof import('vue').onRenderTracked + const onRenderTriggered: typeof import('vue').onRenderTriggered + const onScopeDispose: typeof import('vue').onScopeDispose + const onServerPrefetch: typeof import('vue').onServerPrefetch + const onStartTyping: typeof import('@vueuse/core').onStartTyping + const onUnmounted: typeof import('vue').onUnmounted + const onUpdated: typeof import('vue').onUpdated + const onWatcherCleanup: typeof import('vue').onWatcherCleanup + const pausableWatch: typeof import('@vueuse/core').pausableWatch + const provide: typeof import('vue').provide + const provideLocal: typeof import('@vueuse/core').provideLocal + const reactify: typeof import('@vueuse/core').reactify + const reactifyObject: typeof import('@vueuse/core').reactifyObject + const reactive: typeof import('vue').reactive + const reactiveComputed: typeof import('@vueuse/core').reactiveComputed + const reactiveOmit: typeof import('@vueuse/core').reactiveOmit + const reactivePick: typeof import('@vueuse/core').reactivePick + const readonly: typeof import('vue').readonly + const ref: typeof import('vue').ref + const refAutoReset: typeof import('@vueuse/core').refAutoReset + const refDebounced: typeof import('@vueuse/core').refDebounced + const refDefault: typeof import('@vueuse/core').refDefault + const refManualReset: typeof import('@vueuse/core').refManualReset + const refThrottled: typeof import('@vueuse/core').refThrottled + const refWithControl: typeof import('@vueuse/core').refWithControl + const resolveComponent: typeof import('vue').resolveComponent + const resolveRef: typeof import('@vueuse/core')['resolveRef'] + const resolveUnref: typeof import('@vueuse/core')['resolveUnref'] + const shallowReactive: typeof import('vue').shallowReactive + const shallowReadonly: typeof import('vue').shallowReadonly + const shallowRef: typeof import('vue').shallowRef + const syncRef: typeof import('@vueuse/core').syncRef + const syncRefs: typeof import('@vueuse/core').syncRefs + const templateRef: typeof import('@vueuse/core').templateRef + const throttledRef: typeof import('@vueuse/core').throttledRef + const throttledWatch: typeof import('@vueuse/core').throttledWatch + const toRaw: typeof import('vue').toRaw + const toReactive: typeof import('@vueuse/core').toReactive + const toRef: typeof import('vue').toRef + const toRefs: typeof import('vue').toRefs + const toValue: typeof import('vue').toValue + const triggerRef: typeof import('vue').triggerRef + const tryOnBeforeMount: typeof import('@vueuse/core').tryOnBeforeMount + const tryOnBeforeUnmount: typeof import('@vueuse/core').tryOnBeforeUnmount + const tryOnMounted: typeof import('@vueuse/core').tryOnMounted + const tryOnScopeDispose: typeof import('@vueuse/core').tryOnScopeDispose + const tryOnUnmounted: typeof import('@vueuse/core').tryOnUnmounted + const unref: typeof import('vue').unref + const unrefElement: typeof import('@vueuse/core').unrefElement + const until: typeof import('@vueuse/core').until + const useActiveElement: typeof import('@vueuse/core').useActiveElement + const useAnimate: typeof import('@vueuse/core').useAnimate + const useArrayDifference: typeof import('@vueuse/core').useArrayDifference + const useArrayEvery: typeof import('@vueuse/core').useArrayEvery + const useArrayFilter: typeof import('@vueuse/core').useArrayFilter + const useArrayFind: typeof import('@vueuse/core').useArrayFind + const useArrayFindIndex: typeof import('@vueuse/core').useArrayFindIndex + const useArrayFindLast: typeof import('@vueuse/core').useArrayFindLast + const useArrayIncludes: typeof import('@vueuse/core').useArrayIncludes + const useArrayJoin: typeof import('@vueuse/core').useArrayJoin + const useArrayMap: typeof import('@vueuse/core').useArrayMap + const useArrayReduce: typeof import('@vueuse/core').useArrayReduce + const useArraySome: typeof import('@vueuse/core').useArraySome + const useArrayUnique: typeof import('@vueuse/core').useArrayUnique + const useAsyncQueue: typeof import('@vueuse/core').useAsyncQueue + const useAsyncState: typeof import('@vueuse/core').useAsyncState + const useAttrs: typeof import('vue').useAttrs + const useBase64: typeof import('@vueuse/core').useBase64 + const useBattery: typeof import('@vueuse/core').useBattery + const useBluetooth: typeof import('@vueuse/core').useBluetooth + const useBreakpoints: typeof import('@vueuse/core').useBreakpoints + const useBroadcastChannel: typeof import('@vueuse/core').useBroadcastChannel + const useBrowserLocation: typeof import('@vueuse/core').useBrowserLocation + const useCached: typeof import('@vueuse/core').useCached + const useClipboard: typeof import('@vueuse/core').useClipboard + const useClipboardItems: typeof import('@vueuse/core').useClipboardItems + const useCloned: typeof import('@vueuse/core').useCloned + const useColorMode: typeof import('@vueuse/core').useColorMode + const useConfirmDialog: typeof import('@vueuse/core').useConfirmDialog + const useCountdown: typeof import('@vueuse/core').useCountdown + const useCounter: typeof import('@vueuse/core').useCounter + const useCssModule: typeof import('vue').useCssModule + const useCssSupports: typeof import('@vueuse/core').useCssSupports + const useCssVar: typeof import('@vueuse/core').useCssVar + const useCssVars: typeof import('vue').useCssVars + const useCurrentElement: typeof import('@vueuse/core').useCurrentElement + const useCycleList: typeof import('@vueuse/core').useCycleList + const useDark: typeof import('@vueuse/core').useDark + const useDateFormat: typeof import('@vueuse/core').useDateFormat + const useDebounce: typeof import('@vueuse/core').useDebounce + const useDebounceFn: typeof import('@vueuse/core').useDebounceFn + const useDebouncedRefHistory: typeof import('@vueuse/core').useDebouncedRefHistory + const useDeviceMotion: typeof import('@vueuse/core').useDeviceMotion + const useDeviceOrientation: typeof import('@vueuse/core').useDeviceOrientation + const useDevicePixelRatio: typeof import('@vueuse/core').useDevicePixelRatio + const useDevicesList: typeof import('@vueuse/core').useDevicesList + const useDisplayMedia: typeof import('@vueuse/core').useDisplayMedia + const useDocumentVisibility: typeof import('@vueuse/core').useDocumentVisibility + const useDraggable: typeof import('@vueuse/core').useDraggable + const useDropZone: typeof import('@vueuse/core').useDropZone + const useElementBounding: typeof import('@vueuse/core').useElementBounding + const useElementByPoint: typeof import('@vueuse/core').useElementByPoint + const useElementHover: typeof import('@vueuse/core').useElementHover + const useElementOverflow: typeof import('@vueuse/core').useElementOverflow + const useElementSize: typeof import('@vueuse/core').useElementSize + const useElementVisibility: typeof import('@vueuse/core').useElementVisibility + const useEventBus: typeof import('@vueuse/core').useEventBus + const useEventListener: typeof import('@vueuse/core').useEventListener + const useEventSource: typeof import('@vueuse/core').useEventSource + const useEyeDropper: typeof import('@vueuse/core').useEyeDropper + const useFavicon: typeof import('@vueuse/core').useFavicon + const useFetch: typeof import('@vueuse/core').useFetch + const useFileDialog: typeof import('@vueuse/core').useFileDialog + const useFileSystemAccess: typeof import('@vueuse/core').useFileSystemAccess + const useFocus: typeof import('@vueuse/core').useFocus + const useFocusWithin: typeof import('@vueuse/core').useFocusWithin + const useFps: typeof import('@vueuse/core').useFps + const useFullscreen: typeof import('@vueuse/core').useFullscreen + const useGamepad: typeof import('@vueuse/core').useGamepad + const useGeolocation: typeof import('@vueuse/core').useGeolocation + const useId: typeof import('vue').useId + const useIdle: typeof import('@vueuse/core').useIdle + const useImage: typeof import('@vueuse/core').useImage + const useInfiniteScroll: typeof import('@vueuse/core').useInfiniteScroll + const useIntersectionObserver: typeof import('@vueuse/core').useIntersectionObserver + const useInterval: typeof import('@vueuse/core').useInterval + const useIntervalFn: typeof import('@vueuse/core').useIntervalFn + const useKeyModifier: typeof import('@vueuse/core').useKeyModifier + const useLastChanged: typeof import('@vueuse/core').useLastChanged + const useLink: typeof import('vue-router').useLink + const useLocalStorage: typeof import('@vueuse/core').useLocalStorage + const useMagicKeys: typeof import('@vueuse/core').useMagicKeys + const useManualRefHistory: typeof import('@vueuse/core').useManualRefHistory + const useMediaControls: typeof import('@vueuse/core').useMediaControls + const useMediaQuery: typeof import('@vueuse/core').useMediaQuery + const useMemoize: typeof import('@vueuse/core').useMemoize + const useMemory: typeof import('@vueuse/core').useMemory + const useModel: typeof import('vue').useModel + const useMounted: typeof import('@vueuse/core').useMounted + const useMouse: typeof import('@vueuse/core').useMouse + const useMouseInElement: typeof import('@vueuse/core').useMouseInElement + const useMousePressed: typeof import('@vueuse/core').useMousePressed + const useMutationObserver: typeof import('@vueuse/core').useMutationObserver + const useNavigatorLanguage: typeof import('@vueuse/core').useNavigatorLanguage + const useNetwork: typeof import('@vueuse/core').useNetwork + const useNow: typeof import('@vueuse/core').useNow + const useObjectUrl: typeof import('@vueuse/core').useObjectUrl + const useOffsetPagination: typeof import('@vueuse/core').useOffsetPagination + const useOnline: typeof import('@vueuse/core').useOnline + const usePageLeave: typeof import('@vueuse/core').usePageLeave + const useParallax: typeof import('@vueuse/core').useParallax + const useParentElement: typeof import('@vueuse/core').useParentElement + const usePerformanceObserver: typeof import('@vueuse/core').usePerformanceObserver + const usePermission: typeof import('@vueuse/core').usePermission + const usePointer: typeof import('@vueuse/core').usePointer + const usePointerLock: typeof import('@vueuse/core').usePointerLock + const usePointerSwipe: typeof import('@vueuse/core').usePointerSwipe + const usePreferredColorScheme: typeof import('@vueuse/core').usePreferredColorScheme + const usePreferredContrast: typeof import('@vueuse/core').usePreferredContrast + const usePreferredDark: typeof import('@vueuse/core').usePreferredDark + const usePreferredLanguages: typeof import('@vueuse/core').usePreferredLanguages + const usePreferredReducedMotion: typeof import('@vueuse/core').usePreferredReducedMotion + const usePreferredReducedTransparency: typeof import('@vueuse/core').usePreferredReducedTransparency + const usePrevious: typeof import('@vueuse/core').usePrevious + const useRafFn: typeof import('@vueuse/core').useRafFn + const useRefHistory: typeof import('@vueuse/core').useRefHistory + const useResizeObserver: typeof import('@vueuse/core').useResizeObserver + const useRoute: typeof import('vue-router').useRoute + const useRouter: typeof import('vue-router').useRouter + const useSSRWidth: typeof import('@vueuse/core').useSSRWidth + const useScreenOrientation: typeof import('@vueuse/core').useScreenOrientation + const useScreenSafeArea: typeof import('@vueuse/core').useScreenSafeArea + const useScriptTag: typeof import('@vueuse/core').useScriptTag + const useScroll: typeof import('@vueuse/core').useScroll + const useScrollLock: typeof import('@vueuse/core').useScrollLock + const useSessionStorage: typeof import('@vueuse/core').useSessionStorage + const useShare: typeof import('@vueuse/core').useShare + const useSlots: typeof import('vue').useSlots + const useSorted: typeof import('@vueuse/core').useSorted + const useSpeechRecognition: typeof import('@vueuse/core').useSpeechRecognition + const useSpeechSynthesis: typeof import('@vueuse/core').useSpeechSynthesis + const useStepper: typeof import('@vueuse/core').useStepper + const useStorage: typeof import('@vueuse/core').useStorage + const useStorageAsync: typeof import('@vueuse/core').useStorageAsync + const useStyleTag: typeof import('@vueuse/core').useStyleTag + const useSupported: typeof import('@vueuse/core').useSupported + const useSwipe: typeof import('@vueuse/core').useSwipe + const useTemplateRef: typeof import('vue').useTemplateRef + const useTemplateRefsList: typeof import('@vueuse/core').useTemplateRefsList + const useTextDirection: typeof import('@vueuse/core').useTextDirection + const useTextSelection: typeof import('@vueuse/core').useTextSelection + const useTextareaAutosize: typeof import('@vueuse/core').useTextareaAutosize + const useThrottle: typeof import('@vueuse/core').useThrottle + const useThrottleFn: typeof import('@vueuse/core').useThrottleFn + const useThrottledRefHistory: typeof import('@vueuse/core').useThrottledRefHistory + const useTimeAgo: typeof import('@vueuse/core').useTimeAgo + const useTimeAgoIntl: typeof import('@vueuse/core').useTimeAgoIntl + const useTimeout: typeof import('@vueuse/core').useTimeout + const useTimeoutFn: typeof import('@vueuse/core').useTimeoutFn + const useTimeoutPoll: typeof import('@vueuse/core').useTimeoutPoll + const useTimestamp: typeof import('@vueuse/core').useTimestamp + const useTitle: typeof import('@vueuse/core').useTitle + const useToNumber: typeof import('@vueuse/core').useToNumber + const useToString: typeof import('@vueuse/core').useToString + const useToggle: typeof import('@vueuse/core').useToggle + const useTransition: typeof import('@vueuse/core').useTransition + const useUrlSearchParams: typeof import('@vueuse/core').useUrlSearchParams + const useUserMedia: typeof import('@vueuse/core').useUserMedia + const useVModel: typeof import('@vueuse/core').useVModel + const useVModels: typeof import('@vueuse/core').useVModels + const useVibrate: typeof import('@vueuse/core').useVibrate + const useVirtualList: typeof import('@vueuse/core').useVirtualList + const useWakeLock: typeof import('@vueuse/core').useWakeLock + const useWebNotification: typeof import('@vueuse/core').useWebNotification + const useWebSocket: typeof import('@vueuse/core').useWebSocket + const useWebWorker: typeof import('@vueuse/core').useWebWorker + const useWebWorkerFn: typeof import('@vueuse/core').useWebWorkerFn + const useWindowFocus: typeof import('@vueuse/core').useWindowFocus + const useWindowScroll: typeof import('@vueuse/core').useWindowScroll + const useWindowSize: typeof import('@vueuse/core').useWindowSize + const watch: typeof import('vue').watch + const watchArray: typeof import('@vueuse/core').watchArray + const watchAtMost: typeof import('@vueuse/core').watchAtMost + const watchDebounced: typeof import('@vueuse/core').watchDebounced + const watchDeep: typeof import('@vueuse/core').watchDeep + const watchEffect: typeof import('vue').watchEffect + const watchIgnorable: typeof import('@vueuse/core').watchIgnorable + const watchImmediate: typeof import('@vueuse/core').watchImmediate + const watchOnce: typeof import('@vueuse/core').watchOnce + const watchPausable: typeof import('@vueuse/core').watchPausable + const watchPostEffect: typeof import('vue').watchPostEffect + const watchSyncEffect: typeof import('vue').watchSyncEffect + const watchThrottled: typeof import('@vueuse/core').watchThrottled + const watchTriggerable: typeof import('@vueuse/core').watchTriggerable + const watchWithFilter: typeof import('@vueuse/core').watchWithFilter + const whenever: typeof import('@vueuse/core').whenever +} +// for type re-export +declare global { + // @ts-ignore + export type { Component, Slot, Slots, ComponentPublicInstance, ComputedRef, DirectiveBinding, ExtractDefaultPropTypes, ExtractPropTypes, ExtractPublicPropTypes, InjectionKey, PropType, Ref, ShallowRef, MaybeRef, MaybeRefOrGetter, VNode, WritableComputedRef } from 'vue' + import('vue') +} diff --git a/frontend-ui/src/types/global.d.ts b/frontend-ui/src/types/global.d.ts new file mode 100644 index 00000000..edb6e38b --- /dev/null +++ b/frontend-ui/src/types/global.d.ts @@ -0,0 +1,22 @@ +interface Number { + plus(value: number): number + + minus(value: number): number + + multiply(value: number): number + + divide(value: number): number + + perMulti(value: number): number + + round(digit?: number): number + + floor(digit?: number): number + + exactlyDivide(value: number): number +} + +interface Array { + min(callback: (t: T) => number): [number, T | undefined] + max(callback: (t: T) => number): [number, T | undefined] +} diff --git a/frontend-ui/src/utils/images.ts b/frontend-ui/src/utils/images.ts new file mode 100644 index 00000000..1ee9b549 --- /dev/null +++ b/frontend-ui/src/utils/images.ts @@ -0,0 +1,19 @@ +let baseURL = 'https://image.dnftools.com' + +// 避免远程开发的时候冲突 +if (process.env.NODE_ENV == 'development') { + baseURL = '/image' +} + +if (import.meta.env.MODE == 'web' || import.meta.env.MODE == 'show') { + baseURL = 'https://image.dnftools.com' +} + +export const getImageURL = (image: string) => { + image = image.startsWith('/') ? image : `/${image}` + return `${baseURL}${image}` +} + +export const getLocalImageURL = (url: string) => { + return new URL(url, import.meta.url).href +} diff --git a/frontend-ui/src/utils/index.ts b/frontend-ui/src/utils/index.ts new file mode 100644 index 00000000..7d7b724c --- /dev/null +++ b/frontend-ui/src/utils/index.ts @@ -0,0 +1,362 @@ +export function in_range(num: number, start: number, end: number) { + return start <= num && num <= end +} + +export function to_percent(num?: number, defaultValue: number = 0, suffix = '', withPlus = false) { + num = num ?? defaultValue + return (num > 0 && withPlus ? '+' : '') + num?.multiply(100).round(2).toString().concat(suffix) +} + +export function get_num(num?: number, defaultValue: number = 0) { + return num ?? defaultValue +} + +export function format_string(str: string, params: any = {}, ...args: any[]) { + let num = 0 + str = str.replace(/{}/g, (match) => { + return args[num++] ?? match + }) + str = str.replace(/{\d+}/g, (match) => { + const i = Number.parseInt(match.slice(1, -1)) + return args[i] ?? match + }) + str = str.replace(/{\w+}/g, (match) => { + const name = match.slice(1, -1) + return params[name] ?? match + }) + return str +} + +export function format_bytes(bytes: number, decimals = 2) { + if (bytes === 0) { + return '0 Bytes' + } + const k = 1024 + const dm = decimals < 0 ? 0 : decimals + const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'] + + const i = Math.floor(Math.log(bytes) / Math.log(k)) + + return `${Number.parseFloat((bytes / k ** i).toFixed(dm))} ${sizes[i]}` +} + +export function getFloat(value: any, n: any) { + value = Number(value) + n = n ? Number.parseInt(n) : 0 + if (n <= 0) { + return Math.round(value) + } + value = Math.round(value * 10 ** n) / 10 ** n + value = Number(value).toFixed(n) + return value +} + +export function cartesian(...arr: T[][]): T[][] { + if (arr.length < 2) { + return arr + } + return arr.reduce( + (a, b) => { + const ret: T[][] = [] + a.forEach((a) => { + b.forEach((b) => { + ret.push(a.concat([b])) + }) + }) + return ret + }, + [[]] as T[][], + ) +} + +export function groupBy(array: T[], callback: (t: T) => K) { + const map = new Map() + for (let i = 0; i < array.length; i++) { + const t = array[i] + const key = callback(t) + const temp: T[] = map.get(key) || [] + if (!map.has(key)) { + map.set(key, temp) + } + temp.push(t) + } + + return Array.from(map.values()) +} + +export function debounce_last(func: Function, wait: number) { + let timer = Number.NaN + return function () { + if (timer) { + clearTimeout(timer) + } + timer = setTimeout(func, wait) + } +} + +export function padding(num: number | string, length: number): string { + if (`${num}`.length >= length) { + return `${num}` + } + return padding(`0${num}`, length) +} + +export function format_float(f: number, digit: number = 2) { + const m = 10 ** digit + return (f * m).round(10) / m +} + +export function mapRecord( + status: Record, + callback: (value: K, key: T) => K, +) { + const new_status = {} as Record + for (const key in status) { + const value = callback(status[key], key) + if (value) { + new_status[key] = value + } + } + return new_status +} + +Array.prototype.max = function (callback: (t: T) => number): [number, T | undefined] { + let rs: [number, T | undefined] = [-1, undefined] + let max = -1 + for (let i = 0; i < this.length; i++) { + const item = this.at(i) as T + const count = callback(item) + if (count > max) { + max = count + rs = [i, item] + } + } + return rs +} + +Array.prototype.min = function (callback: (t: T) => number): [number, T | undefined] { + let rs: [number, T | undefined] = [-1, undefined] + let min = -1 + for (let i = 0; i < this.length; i++) { + const item = this.at(i) as T + const count = callback(item) + if (count < min) { + min = count + rs = [i, item] + } + } + return rs +} + +Number.prototype.multiply = function (value: number) { + return Number(this) * value +} + +Number.prototype.round = function (digit?: number) { + const m = 10 ** (digit ?? 0) + return Math.round(Number(this) * m) / m +} + +export function formatStr(template: string, ...params: any) { + let str = template + + if (params.length == 1 && params[0].length > 0) { + params = params[0] + } + + for (let i = 0; i < params.length; i++) { + str = str.replaceAll(`{${i}}`, params[i]) + } + + return str +} + +export function toObj(data: any): any { + const temp = {} + for (const key in data) { + try { + if (typeof data[key] === 'number' || typeof data[key] === 'string') { + Object.defineProperty(temp, key, { + value: data[key], + writable: true, + enumerable: true, + configurable: true, + }) + } else { + Object.defineProperty(temp, key, { + value: RecordToObj(data[key]), + writable: true, + enumerable: true, + configurable: true, + }) + } + } catch { + Object.defineProperty(temp, key, { + value: data[key], + writable: true, + enumerable: true, + configurable: true, + }) + } + } + return temp +} + +export function toMap(data: any, except: string[] = []) { + const temp = {} + for (const key in data) { + if (typeof data[key] === 'object' && data[key].constructor != Array && !except.includes(key)) { + // 需要转换部分,不能是Array,也会被转换 + const sub = {} + for (const subkey in data[key]) { + Object.defineProperty(sub, subkey, { + value: new Map(Object.entries(data[key][subkey])), + writable: true, + enumerable: true, + configurable: true, + }) + } + Object.defineProperty(temp, key, { + value: sub, + writable: true, + enumerable: true, + configurable: true, + }) + } else { + Object.defineProperty(temp, key, { + value: data[key], + writable: true, + enumerable: true, + configurable: true, + }) + } + } + return temp +} + +export function RecordToObj(todo: Record>) { + const temp = {} + for (const key in todo) { + Object.defineProperty(temp, key, { + value: Object.fromEntries(todo[key]), + writable: true, + enumerable: true, + configurable: true, + }) + } + return temp +} + +export function getUuid() { + if (typeof crypto === 'object') { + if (typeof crypto.randomUUID === 'function') { + return crypto.randomUUID() + } + if (typeof crypto.getRandomValues === 'function' && typeof Uint8Array === 'function') { + const callback = (c: any) => { + const num = Number(c) + return (num ^ (crypto.getRandomValues(new Uint8Array(1))[0] & (15 >> (num / 4)))).toString( + 16, + ) + } + return '10000000-1000-4000-8000-100000000000'.replace(/[018]/g, callback) + } + } + let timestamp = new Date().getTime() + let perforNow = + (typeof performance !== 'undefined' && performance.now && performance.now() * 1000) || 0 + return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => { + let random = Math.random() * 16 + if (timestamp > 0) { + random = Math.trunc((timestamp + random) % 16) + timestamp = Math.floor(timestamp / 16) + } else { + random = Math.trunc((perforNow + random) % 16) + perforNow = Math.floor(perforNow / 16) + } + return (c === 'x' ? random : (random & 0x3) | 0x8).toString(16) + }) +} + +export function rarityClass(type: string) { + switch (type) { + case '太初': + return 'primeval' + case '史诗': + return 'epic' + case '神话': + return 'myth' + case '智慧产物': + return 'epic' + case '神器': + return 'artifact' + case '稀有': + return 'rare' + case '传说': + return 'legend' + case '勇者': + return 'chronicle' + case '高级': + return 'advanced' + default: + return 'epic' + } +} + +export function formatAttr(type: string, value: number) { + switch (type) { + case 'STR': + return `力量 ${value}` + case 'INT': + return `智力 ${value}` + case 'Vitality': + return `体力 ${value}` + case 'Spirit': + return `精神 ${value}` + case 'AtkP': + return `物理攻击力 ${value}` + case 'AtkM': + return `魔法攻击力 ${value}` + case 'AtkI': + return `独立攻击力 ${value}` + case 'SkillAttack': + return `技能伤害 增加 ${(value * 100).toFixed(2)}%` + case 'Attack': + return `攻击强化 +${value.toFixed(1)}%` + case 'Buffer': + return `增益量 ${value}` + default: + return `${type} ${value}` + } +} + +export const decrypt = (encryptedData: string) => { + try { + encryptedData = decodeURIComponent(encryptedData) + .split('') + .map((a) => { + if (a == '=') { + return a + } else { + return String.fromCharCode(a.charCodeAt(0) - 1) + } + }) + .join('') + const decryptedData = atob(encryptedData) + + const len = decryptedData.length + const decryptedBinaryOffset = decryptedData.slice(0, len - 13) + const decryptedTimestamp = decryptedData.slice(len - 13, len) + + return { + uid: parseInt(decryptedBinaryOffset, 2), + time: parseInt(decryptedTimestamp), + } + } catch { + // console.log(e) + return { + uid: -1, + time: 0, + } + } +} diff --git a/frontend-ui/src/utils/open.ts b/frontend-ui/src/utils/open.ts new file mode 100644 index 00000000..8b6e0b03 --- /dev/null +++ b/frontend-ui/src/utils/open.ts @@ -0,0 +1,112 @@ +import type { MaybeRef } from 'vue' +import querystring from 'query-string' +import { h, isRef } from 'vue' +import { useRouter } from 'vue-router' +import { useDialog } from '@/components/hooks/dialog' + +interface UseOpenOption { + /* + + */ + width?: number + height?: number + scale?: number + query?: Record + + /** + * 是否打开新页面 + */ + target?: '_blank' | '_self' | false + + title?: string +} + +export function useOpenWindow() { + const { show, close, randomId } = useDialog() + const router = useRouter() + + return async ( + maybeUrl: MaybeRef | (() => string), + { + width = 0, + height = 0, + target = '_self', + query = {}, + title = 'DNF计算器 & Colg', + scale = 1.0, + }: UseOpenOption = {}, + ) => { + let url = isRef(maybeUrl) + ? maybeUrl.value + : typeof maybeUrl === 'function' + ? maybeUrl() + : maybeUrl + if (!url) { + return + } + + if (url.startsWith('/')) { + url = router.resolve(url).href + } + query.r = `${Math.random()}` + url = querystring.stringifyUrl({ url, query }) + try { + let _target = target + if (!_target) { + const rs = await show({ + content: '请确认打开新页面的方式', + okButton: '当前窗口', + rejectButton: '新窗口', + cancelButton: true, + defaultStatus: 'cancel', + }) + if (rs.isOk) { + _target = '_self' + } else if (rs.isReject) { + _target = '_blank' + } + } + + if (_target == '_blank' || width * height < 1) { + window.open(url, _target as string) + } else if (_target == '_self') { + const id = randomId() + const onClose = (e: MessageEvent) => { + if (e.data == 'close') { + close(id) + } + } + window.addEventListener('message', onClose) + const temp = await show({ + id, + header: title, + mask: true, + scale, + content() { + return h('iframe', { + name: Math.random().toString(36).slice(2), + referrerpolicy: 'no-referrer', + frameborder: 0, + src: url, + style: { + width: `${width}px`, + height: `${height}px`, + }, + }) + }, + }) + window.removeEventListener('message', onClose) + return temp + } + } catch (err) { + // let routerURL = router?.resolve({ + // path: url + // }) + // window.open(routerURL?.href) + // router.push(url) + // 网页端打开 + router?.push(url) + console.error(err) + } + } +} diff --git a/frontend-ui/src/utils/position.ts b/frontend-ui/src/utils/position.ts new file mode 100644 index 00000000..654909e5 --- /dev/null +++ b/frontend-ui/src/utils/position.ts @@ -0,0 +1,32 @@ +export function resolveTeleportTarget(target?: string | Element | null) { + if (typeof window === 'undefined') { + return null + } + + if (typeof target === 'string') { + return document.querySelector(target) + } + + return target ?? document.body +} + +export function getElementZoom(target?: string | Element | null) { + if (typeof window === 'undefined') { + return 1 + } + + let zoom = 1 + let current = resolveTeleportTarget(target) as HTMLElement | null + + while (current) { + const currentZoom = Number.parseFloat(window.getComputedStyle(current).zoom) + + if (Number.isFinite(currentZoom) && currentZoom > 0) { + zoom *= currentZoom + } + + current = current.parentElement + } + + return zoom || 1 +} diff --git a/frontend-ui/tsconfig.app.json b/frontend-ui/tsconfig.app.json new file mode 100644 index 00000000..45e24803 --- /dev/null +++ b/frontend-ui/tsconfig.app.json @@ -0,0 +1,13 @@ +{ + "extends": "@vue/tsconfig/tsconfig.dom.json", + "include": ["env.d.ts", "src/**/*", "src/**/*.vue"], + "exclude": ["src/**/__tests__/*", "src/pages/Character/Equipment/**/*"], + "compilerOptions": { + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", + "lib": ["ES2023", "DOM", "DOM.Iterable"], + "types": ["node"], + "paths": { + "@/*": ["./src/*"] + } + } +} diff --git a/frontend-ui/tsconfig.json b/frontend-ui/tsconfig.json new file mode 100644 index 00000000..767fcd9e --- /dev/null +++ b/frontend-ui/tsconfig.json @@ -0,0 +1,12 @@ +{ + "files": [], + "references": [ + { + "path": "./tsconfig.node.json" + }, + { + "path": "./tsconfig.app.json" + } + ], + "include": ["src/type/*"] +} diff --git a/frontend-ui/tsconfig.node.json b/frontend-ui/tsconfig.node.json new file mode 100644 index 00000000..c12d60e4 --- /dev/null +++ b/frontend-ui/tsconfig.node.json @@ -0,0 +1,20 @@ +{ + "extends": "@tsconfig/node24/tsconfig.json", + "include": [ + "vite.config.*", + "vitest.config.*", + "cypress.config.*", + "nightwatch.conf.*", + "playwright.config.*", + "eslint.config.*" + ], + "compilerOptions": { + "noEmit": true, + "lib": ["ES2021.String", "dom"], + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", + "jsx": "preserve", + "module": "ESNext", + "moduleResolution": "Bundler", + "types": ["node"] + } +} diff --git a/frontend-ui/vite.config.ts b/frontend-ui/vite.config.ts new file mode 100644 index 00000000..230f7468 --- /dev/null +++ b/frontend-ui/vite.config.ts @@ -0,0 +1,52 @@ +import { fileURLToPath, URL } from 'node:url' + +import { defineConfig } from 'vite' +import vue from '@vitejs/plugin-vue' +import vueJsx from '@vitejs/plugin-vue-jsx' +import tailwindcss from '@tailwindcss/vite' +import AutoImport from 'unplugin-auto-import/vite' +import uncomponents from 'unplugin-vue-components/vite' + +// https://vite.dev/config/ +export default defineConfig({ + plugins: [ + vue(), + vueJsx(), + tailwindcss(), + uncomponents({ + dts: true, + dirs: ['src/components/'], + allowOverrides: true, + directoryAsNamespace: true, + }), + AutoImport({ + imports: ['vue', 'vue-router', '@vueuse/core'], + include: [ + /\.[tj]sx?$/, // .ts, .tsx, .js, .jsx + /\.vue$/, + /\.vue\?vue/, // .vue + ], + dts: 'src/types/auto-imports.d.ts', // specify the dts file path + }), + ], + server: { + host: '0.0.0.0', + proxy: { + '/api': { + target: 'http://127.0.0.1:47173/api', + changeOrigin: false, + rewrite: (path) => path.replace(/^\/api/, ''), + }, + '/image': { + target: 'http://127.0.0.1:3000', + changeOrigin: false, + rewrite: (path) => path.replace(/^\/image/, ''), + }, + }, + }, + resolve: { + alias: { + '@': fileURLToPath(new URL('./src', import.meta.url)), + }, + }, +}) diff --git a/package.json b/package.json index 23742eac..0ca003c2 100644 --- a/package.json +++ b/package.json @@ -6,6 +6,7 @@ "scripts": { "dev:image": "node scripts/image.js", "dev:frontend": "pnpm --dir frontend dev", + "dev:frontend-ui": "pnpm --dir frontend-ui dev", "dev:frontendNew": "pnpm --dir frontendNew dev", "dev:backend": "cd backend && uv run main.py" },