cardbuddy 0.6.0 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -3,8 +3,9 @@
3
3
  说明:设备模拟 UI(.dlg / .dtoast / .pk-* 等原生弹框白底)模拟真机外观,不随主题变化,保持固定。 */
4
4
  /* 配色 Token 与《深浅主题配色规范手册》映射(语义单一 / 双主题同义词切换):
5
5
  --accent/-2/-soft/-border/-hover = 主色 color-primary(及 hover/active 变体)
6
- --ok/-soft/-border/-strong = 成功 success(深色提亮 #34D399 / 浅色 #10B981)
7
- --warn/-soft/-border = 警告 warning(琥珀)
6
+ --ok/-soft/-border/-strong/-solid = 成功 success(深色提亮 #34D399 / 浅色 #10B981)
7
+ --on-ok = 成功实心填充(--ok-solid)上的文字
8
+ --warn/-soft/-border/-hover = 警告 warning(琥珀);--on-warn = 警告实心填充上的深色文字
8
9
  --danger/-soft/-hover = 错误 / 危险 error(红)
9
10
  --info/-soft/-border = 信息 info(与主色同源,均为蓝)
10
11
  --on-accent = 主色填充上的文字(深色 #0F1115 / 浅色 #fff)
@@ -38,10 +39,16 @@
38
39
  --warn: #FBBF24;
39
40
  --warn-soft: rgba(251, 191, 36, 0.14);
40
41
  --warn-border: rgba(251, 191, 36, 0.4);
42
+ --warn-hover: #F59E0B;
43
+ --on-warn: #0F1115;
41
44
  --ok: #34D399;
42
45
  --ok-soft: rgba(52, 211, 153, 0.16);
43
46
  --ok-border: rgba(52, 211, 153, 0.45);
44
47
  --ok-strong: #34D399;
48
+ /* 成功态「实心填充」徽标(标签 / 角标浮在任意底色上时用):--ok-solid 为底、--on-ok 为其上文字。
49
+ 与 --ok-soft(半透明,仅适合压在已知面板色上)区分:实心版不透明,浮在白色缩略图上仍达 WCAG AA。 */
50
+ --ok-solid: #17734A;
51
+ --on-ok: #ffffff;
45
52
  --info: #6B83F7;
46
53
  --info-soft: rgba(107, 131, 247, 0.14);
47
54
  --info-border: rgba(107, 131, 247, 0.45);
@@ -192,10 +199,14 @@
192
199
  --warn: #F59E0B;
193
200
  --warn-soft: rgba(245, 158, 11, 0.14);
194
201
  --warn-border: rgba(245, 158, 11, 0.4);
202
+ --warn-hover: #D97706;
203
+ --on-warn: #0F1115;
195
204
  --ok: #10B981;
196
205
  --ok-soft: rgba(16, 185, 129, 0.14);
197
206
  --ok-border: rgba(16, 185, 129, 0.4);
198
207
  --ok-strong: #166534;
208
+ --ok-solid: #166534;
209
+ --on-ok: #ffffff;
199
210
  --info: #4F6BF2;
200
211
  --info-soft: rgba(79, 107, 242, 0.12);
201
212
  --info-border: rgba(79, 107, 242, 0.4);
@@ -382,6 +393,12 @@ body {
382
393
  height: var(--ctrl-md);
383
394
  padding: 0 8px;
384
395
  }
396
+ /* 开关型图标按钮的「开启」态(如右侧接口调用面板开关):用主题色标示当前已展开 */
397
+ .app__btn--active {
398
+ background: var(--accent-soft);
399
+ color: var(--accent);
400
+ border-color: var(--accent-border);
401
+ }
385
402
  /* 顶栏图标按钮(刷新 / 连接)与远端、op-group 统一为 28px(--ctrl-sm),不再高 32px */
386
403
  .app__bar .app__btn--icon {
387
404
  height: var(--ctrl-sm);
@@ -423,11 +440,16 @@ body {
423
440
  .app__icon--chev {
424
441
  transition: transform 0.15s;
425
442
  }
426
- /* 下拉项:保存类 hover 蓝色、同步类 hover 绿色(基础布局见 dropdown.css .app__remote-item) */
443
+ /* 下拉项:保存/上传类 hover 蓝色与琥珀、同步类 hover 绿色(基础布局见 dropdown.css .app__remote-item) */
427
444
  .app__remote-item--save:hover {
428
445
  background: var(--accent-soft);
429
446
  color: var(--accent);
430
447
  }
448
+ /* 切图上传:琥珀色,与「版本推送」(蓝)、「同步」(绿)区分——传的是素材不是版本 */
449
+ .app__remote-item--upload:hover {
450
+ background: var(--warn-soft);
451
+ color: var(--warn);
452
+ }
431
453
  .app__remote-item--sync:hover {
432
454
  background: var(--ok-soft);
433
455
  color: var(--ok);
@@ -845,6 +867,27 @@ body {
845
867
  position: relative; /* 作为绝对定位 splitter 的定位上下文 */
846
868
  }
847
869
 
870
+ /* 中右工作区:纵向 flex——上为「调试面板 + 接口调用面板」两栏,下为贯穿两栏的共同状态栏。
871
+ 状态栏由 DebugPanel 内 Teleport 注入 .workside__bar;该目标在 DOM 中先于两栏容器
872
+ (Teleport 挂载要求目标已存在),故用 order 把它视觉置底。 */
873
+ .workside {
874
+ flex: 1 1 auto;
875
+ display: flex;
876
+ flex-direction: column;
877
+ min-width: 0;
878
+ min-height: 0;
879
+ }
880
+ .workside__bar {
881
+ flex: 0 0 auto;
882
+ order: 1;
883
+ }
884
+ .workside__cols {
885
+ flex: 1 1 auto;
886
+ display: flex;
887
+ min-width: 0;
888
+ min-height: 0;
889
+ }
890
+
848
891
  .phone {
849
892
  flex: 0 0 auto;
850
893
  display: flex;
@@ -889,6 +932,11 @@ body {
889
932
  z-index: var(--z-sticky);
890
933
  transition: background 0.15s ease;
891
934
  }
935
+ /* 中右分隔条:以右侧「接口调用」面板右缘(即舞台右缘)回推面板宽度定位接缝 */
936
+ .splitter--api {
937
+ left: auto;
938
+ right: calc(var(--api-panel-width, 360px) - 3px);
939
+ }
892
940
  .splitter:hover,
893
941
  .splitter.is-dragging {
894
942
  background: var(--splitter);
@@ -1082,17 +1130,84 @@ body {
1082
1130
  flex: 1 1 auto;
1083
1131
  display: flex;
1084
1132
  flex-direction: column;
1085
- min-width: 300px;
1133
+ /* 中栏最小宽度:不得小于三分之一屏幕宽度(与中右分隔条 startApiDrag 的夹取一致) */
1134
+ min-width: 33.333vw;
1135
+ background: var(--bg-panel);
1136
+ border-left: 1px solid var(--border);
1137
+ }
1138
+
1139
+ /* 右侧常驻「接口调用」面板:默认 360px 宽,可经中右分隔条拖拽调节(最小 320px,
1140
+ 宽度由 App 以 --api-panel-width CSS 变量下发),与预览列 / 调试面板呈左中右布局。
1141
+ 展开/收起由顶栏按钮与面板内 ✕ 控制(v-if 整体挂载/卸载)。 */
1142
+ .apipanel {
1143
+ flex: 0 0 auto;
1144
+ width: var(--api-panel-width, 360px);
1145
+ min-width: 320px;
1146
+ display: flex;
1147
+ flex-direction: column;
1148
+ min-height: 0;
1086
1149
  background: var(--bg-panel);
1087
1150
  border-left: 1px solid var(--border);
1088
1151
  }
1152
+ .apipanel__head {
1153
+ flex: 0 0 auto;
1154
+ display: flex;
1155
+ align-items: center;
1156
+ gap: 8px;
1157
+ /* 与调试面板 tab 条同高(12px 上下 padding + 13px 字号 ≈ 42px),保证三条栏顶线对齐 */
1158
+ height: 40px;
1159
+ padding: 0 12px;
1160
+ border-bottom: 1px solid var(--border);
1161
+ }
1162
+ .apipanel__title {
1163
+ font-size: 13px;
1164
+ font-weight: 600;
1165
+ color: var(--text);
1166
+ white-space: nowrap;
1167
+ }
1168
+ .apipanel__spacer {
1169
+ flex: 1 1 auto;
1170
+ }
1171
+ .apipanel__btn {
1172
+ flex: 0 0 auto;
1173
+ display: inline-flex;
1174
+ align-items: center;
1175
+ justify-content: center;
1176
+ width: 28px;
1177
+ height: 28px;
1178
+ padding: 0;
1179
+ background: transparent;
1180
+ color: var(--text-dim);
1181
+ border: 1px solid transparent;
1182
+ border-radius: 8px;
1183
+ cursor: pointer;
1184
+ transition: background 0.15s, color 0.15s, border-color 0.15s, transform 0.05s;
1185
+ }
1186
+ .apipanel__btn:hover:not(:disabled) {
1187
+ background: var(--bg-hover);
1188
+ border-color: var(--border);
1189
+ color: var(--text);
1190
+ }
1191
+ .apipanel__btn:active:not(:disabled) {
1192
+ transform: translateY(1px);
1193
+ }
1194
+ .apipanel__btn:disabled {
1195
+ opacity: 0.5;
1196
+ cursor: default;
1197
+ }
1198
+ .apipanel__body {
1199
+ flex: 1 1 auto;
1200
+ overflow: auto;
1201
+ padding: 8px 12px;
1202
+ }
1089
1203
  .debug__tabs {
1090
1204
  display: flex;
1091
1205
  border-bottom: 1px solid var(--border);
1092
1206
  }
1093
1207
  .debug__tab {
1094
1208
  flex: 1;
1095
- padding: 12px 8px;
1209
+ padding: 10px 8px;
1210
+ height: 39px;
1096
1211
  background: transparent;
1097
1212
  border: none;
1098
1213
  color: var(--text-dim);
@@ -1133,12 +1248,11 @@ body {
1133
1248
  position: relative;
1134
1249
  flex: 1 1 auto;
1135
1250
  overflow: auto;
1136
- padding: 12px 16px;
1251
+ /* padding: 12px 16px; */
1137
1252
  }
1138
- .debug__placeholder {
1139
- display: block;
1140
- width: 100%;
1141
- height: 38px;
1253
+ .debug__meta {
1254
+ margin: 0;
1255
+ padding: 8px 12px;
1142
1256
  }
1143
1257
  .debug__empty {
1144
1258
  color: var(--text-faint);
@@ -1282,42 +1396,6 @@ body {
1282
1396
  color: var(--danger);
1283
1397
  background: var(--danger-soft);
1284
1398
  }
1285
- /* 接口调用标签页工具条(仿 Chrome 控制台) */
1286
- .debug__clear {
1287
- /* 通用带边框按钮:固定在接口调用 tab 右上角、不随滚动,方便随时清空日志 */
1288
- position: sticky;
1289
- top: 0;
1290
- float: right;
1291
- z-index: var(--z-sticky);
1292
- display: inline-flex;
1293
- align-items: center;
1294
- justify-content: center;
1295
- width: 28px;
1296
- height: 28px;
1297
- padding: 0;
1298
- background: var(--bg-input);
1299
- color: var(--text);
1300
- border: 1px solid var(--border-strong);
1301
- border-radius: 8px;
1302
- cursor: pointer;
1303
- box-shadow: -10px 0 10px var(--bg-panel);
1304
- transition: background 0.15s, border-color 0.15s, transform 0.05s;
1305
- }
1306
- .debug__clear:hover:not(:disabled) {
1307
- background: var(--bg-hover);
1308
- border-color: var(--accent-border);
1309
- }
1310
- .debug__clear:active:not(:disabled) {
1311
- transform: translateY(1px);
1312
- }
1313
- .debug__clear:disabled {
1314
- opacity: 0.5;
1315
- cursor: default;
1316
- }
1317
- /* 接口调用列表顶部留白,避免首行被右上角浮动的清空按钮遮挡 */
1318
- .debug__list--api {
1319
- padding-top: 34px;
1320
- }
1321
1399
  .debug__list {
1322
1400
  list-style: none;
1323
1401
  margin: 0;
@@ -1456,7 +1534,7 @@ body {
1456
1534
  /* right:0 让 JSON 树滚动条紧贴面板最右边(与其他 tab 用 body padding 作
1457
1535
  16px 滚动框不同,本 tab 滚动交给内部 .debug__scope-tree,需要贴边);
1458
1536
  left:16px 与 body 的 16px 内边距对齐,让树内容左缘与其他 tab 一致。 */
1459
- inset: 10px 10px 10px 16px;
1537
+ inset: 0;
1460
1538
  display: flex;
1461
1539
  flex-direction: column;
1462
1540
  min-height: 0;
@@ -1521,8 +1599,8 @@ body {
1521
1599
  padding: 12px 14px;
1522
1600
  background: var(--bg-input);
1523
1601
  color: var(--text);
1524
- border: 1px solid var(--border-strong);
1525
- border-radius: 8px;
1602
+ /* border: 1px solid var(--border-strong); */
1603
+ /* border-radius: 8px; */
1526
1604
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
1527
1605
  font-size: 12px;
1528
1606
  line-height: 1.6;
@@ -1531,9 +1609,9 @@ body {
1531
1609
  overflow: auto;
1532
1610
  outline: none;
1533
1611
  }
1534
- .debug__raw-editor:focus {
1612
+ /* .debug__raw-editor:focus {
1535
1613
  border-color: var(--accent-border);
1536
- }
1614
+ } */
1537
1615
  /* CodeJar 托管的原始 JSON 编辑器:Prism(json) 语法高亮配色(与 SetCode 暗色面板一致) */
1538
1616
  .debug__raw-editor .token.property,
1539
1617
  .debug__raw-editor .token.tag,
@@ -2503,6 +2581,10 @@ body {
2503
2581
  .confirm-modal__title.is-danger {
2504
2582
  color: var(--danger);
2505
2583
  }
2584
+ /* 警告级(warn):覆盖推送类操作(版本推送等)——标题与图标取琥珀警告色,见配色规范 §2.7 / §3.4 */
2585
+ .confirm-modal__title.is-warn {
2586
+ color: var(--warn);
2587
+ }
2506
2588
  .confirm-modal__icon {
2507
2589
  width: 18px;
2508
2590
  height: 18px;
@@ -2555,6 +2637,15 @@ body {
2555
2637
  .confirm-modal__btn--danger:hover {
2556
2638
  background: var(--danger-hover);
2557
2639
  }
2640
+ /* 警告级确认按钮:琥珀实心 + 深色文字(琥珀底白字对比度不足,双主题统一深色 ink) */
2641
+ .confirm-modal__btn--warn {
2642
+ border-color: var(--warn);
2643
+ background: var(--warn);
2644
+ color: var(--on-warn);
2645
+ }
2646
+ .confirm-modal__btn--warn:hover {
2647
+ background: var(--warn-hover);
2648
+ }
2558
2649
  .confirm-fade-enter-active,
2559
2650
  .confirm-fade-leave-active {
2560
2651
  transition: opacity 0.15s ease;
@@ -170,6 +170,26 @@
170
170
  background: #fff;
171
171
  border-bottom: 1px solid var(--border);
172
172
  }
173
+ /* 导入角标:悬浮在缩略图右上角,仅「有 .import-meta.json 侧车」的导入卡显示。
174
+ 配色用成功态「实心」token(--ok-solid 底 + --on-ok 白字 + --ok-solid 同色描边):
175
+ 缩略图恒为白底,半透明的 --ok-soft 压上去会被吃成 ~2:1,实心深绿才达 WCAG AA,
176
+ 且与顶栏 .app__badge--ok 同属 success 语义、不引入新色相。圆角取 --radius-xs(方形小标),无阴影。 */
177
+ .cg-tile__tag {
178
+ position: absolute;
179
+ top: 6px;
180
+ right: 6px;
181
+ z-index: 1;
182
+ padding: 2px 8px;
183
+ border-radius: var(--radius-xs);
184
+ background: var(--ok-strong);
185
+ color: var(--on-ok);
186
+ font-size: var(--fs-xs);
187
+ font-weight: 600;
188
+ line-height: 1.5;
189
+ white-space: nowrap;
190
+ user-select: none;
191
+ pointer-events: none;
192
+ }
173
193
  .cg-tile__img {
174
194
  width: 100%;
175
195
  height: 100%;
@@ -121,6 +121,21 @@
121
121
  .csel__item--selected .csel__item-id {
122
122
  color: var(--accent);
123
123
  }
124
+ /* 卡片来源圆点(6x6):绿色 = 导入卡(有 .import-meta.json),灰色 = 本地卡(无来源信息)。
125
+ align-self:center + 固定行高保证与右侧 id/name 文本视觉居中对齐(不受行高影响)。 */
126
+ .csel__dot {
127
+ flex: 0 0 auto;
128
+ align-self: center;
129
+ width: 6px;
130
+ height: 6px;
131
+ border-radius: 50%;
132
+ background: var(--text-faint);
133
+ opacity: 0.75;
134
+ }
135
+ .csel__dot--imported {
136
+ background: var(--ok);
137
+ opacity: 1;
138
+ }
124
139
  .csel__item-id {
125
140
  font-weight: 600;
126
141
  color: var(--text);
@@ -9,7 +9,7 @@
9
9
  display: flex;
10
10
  justify-content: flex-start;
11
11
  gap: 12px;
12
- padding: 4px 12px 8px;
12
+ padding: 8px 12px;
13
13
  position: sticky;
14
14
  top: 0;
15
15
  z-index: var(--z-sticky);
@@ -8,6 +8,9 @@
8
8
  .st {
9
9
  position: relative;
10
10
  min-height: 100%;
11
+ /* flex 列布局 + 底部帮助按钮 margin-top:auto:内容不足一屏时按钮仍吸附面板底部 */
12
+ display: flex;
13
+ flex-direction: column;
11
14
  }
12
15
 
13
16
  /* 顶部工具条:与 JsonTree 的 .jt__toolbar 同款(sticky 顶部),
@@ -16,7 +19,7 @@
16
19
  display: flex;
17
20
  justify-content: flex-start;
18
21
  gap: 12px;
19
- padding: 4px 0 8px;
22
+ padding: 8px 12px;
20
23
  position: sticky;
21
24
  top: 0;
22
25
  z-index: var(--z-sticky);
@@ -86,14 +89,141 @@
86
89
  list-style: none;
87
90
  }
88
91
 
89
- /* 操作提示:淡色弱文案,提示 Ctrl/⌘ 点击画布可定位节点 */
90
- .st__tip {
92
+ /* 帮助悬浮按钮容器:零高度 sticky 吸附在滚动视口底部(滚动容器为外层 .debug__body),
93
+ 内容过长时按钮仍固定于面板左下角可见,且不占用固定布局区域 */
94
+ .st__help-wrap {
95
+ position: sticky;
96
+ bottom: 10px;
97
+ height: 0;
98
+ z-index: var(--z-pop);
99
+ /* 内容较短时把按钮推到 .st 底部(即面板可见区底部);内容较长时由 sticky 吸附兜底 */
100
+ margin-top: auto;
101
+ }
102
+ .st__help {
103
+ position: absolute;
104
+ left: 10px;
105
+ bottom: 0;
106
+ display: inline-flex;
107
+ align-items: center;
108
+ justify-content: center;
109
+ width: 28px;
110
+ height: 28px;
111
+ padding: 0;
112
+ background: var(--bg-input);
113
+ color: var(--text-dim);
114
+ border: 1px solid var(--border-strong);
115
+ border-radius: 50%;
116
+ cursor: pointer;
117
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.25);
118
+ transition: background 0.15s, color 0.15s, border-color 0.15s, transform 0.05s;
119
+ }
120
+ .st__help:hover {
121
+ background: var(--bg-hover);
122
+ border-color: var(--accent-border);
123
+ color: var(--accent);
124
+ }
125
+ .st__help:active {
126
+ transform: translateY(1px);
127
+ }
128
+ /* 气泡展开时按钮保持激活态配色 */
129
+ .st__help--open {
130
+ background: var(--accent-soft);
131
+ border-color: var(--accent-border);
132
+ color: var(--accent);
133
+ }
134
+ /* 使用说明气泡:自左下角按钮向上弹出 */
135
+ .st__help-pop {
136
+ position: absolute;
137
+ left: 10px;
138
+ bottom: 36px;
139
+ width: 300px;
140
+ background: var(--bg-panel);
141
+ border: 1px solid var(--border-strong);
142
+ border-radius: 10px;
143
+ box-shadow: 0 8px 24px rgba(0, 0, 0, 0.35);
144
+ }
145
+ .st__help-pop-head {
146
+ display: flex;
147
+ align-items: center;
148
+ justify-content: space-between;
149
+ padding: 8px 12px;
150
+ border-bottom: 1px solid var(--border);
151
+ }
152
+ .st__help-pop-title {
153
+ font-size: 12px;
154
+ font-weight: 600;
155
+ color: var(--text);
156
+ }
157
+ .st__help-pop-close {
158
+ display: inline-flex;
159
+ align-items: center;
160
+ justify-content: center;
161
+ width: 18px;
162
+ height: 18px;
163
+ padding: 0;
164
+ background: none;
165
+ border: none;
166
+ color: var(--text-faint);
167
+ font-size: 12px;
168
+ cursor: pointer;
169
+ border-radius: 4px;
170
+ transition: background 0.15s, color 0.15s;
171
+ }
172
+ .st__help-pop-close:hover {
173
+ background: var(--bg-hover);
174
+ color: var(--text);
175
+ }
176
+ .st__help-pop-body {
91
177
  margin: 0;
92
- padding: 6px 8px 8px;
178
+ padding: 10px 12px;
179
+ color: var(--text-dim);
180
+ font-size: 12px;
181
+ line-height: 1.6;
182
+ }
183
+ /* 快捷键清单:左列按键示意(kbd 芯片),右列一句话说明 */
184
+ .st__keys {
185
+ list-style: none;
186
+ display: flex;
187
+ flex-direction: column;
188
+ gap: 8px;
189
+ }
190
+ .st__keys-row {
191
+ display: flex;
192
+ align-items: center;
193
+ gap: 10px;
194
+ }
195
+ .st__keys-combo {
196
+ flex: 0 0 108px; /* 左列固定宽度,组合键纵向对齐 */
197
+ display: inline-flex;
198
+ align-items: center;
199
+ gap: 3px;
200
+ white-space: nowrap;
201
+ }
202
+ .st__kbd {
203
+ display: inline-flex;
204
+ align-items: center;
205
+ justify-content: center;
206
+ min-width: 20px;
207
+ height: 20px;
208
+ padding: 0 5px;
209
+ background: var(--bg-input);
210
+ color: var(--text);
211
+ border: 1px solid var(--border-strong);
212
+ border-bottom-width: 2px; /* 键帽底部加厚,模拟按键立体感 */
213
+ border-radius: 5px;
214
+ font-family: var(--mono, ui-monospace, SFMono-Regular, Menlo, monospace);
215
+ font-size: 11px;
216
+ line-height: 1;
217
+ }
218
+ .st__kbd-plus {
93
219
  color: var(--text-faint);
94
220
  font-size: 11px;
221
+ }
222
+ .st__keys-desc {
223
+ flex: 1 1 auto;
224
+ color: var(--text-dim);
225
+ font-size: 12px;
95
226
  line-height: 1.5;
96
- border-bottom: 1px solid var(--border);
97
227
  }
98
228
 
99
229
  .st__node {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cardbuddy",
3
- "version": "0.6.0",
3
+ "version": "0.7.0",
4
4
  "description": "Local dev service for the CardBuddy card editor — decouples card CRUD (sync/save/validate/render-status/screenshot) from the static public editor, so the editor can be deployed to any static host while each developer runs a local service against their own card source.",
5
5
  "type": "module",
6
6
  "bin": {