@nsnanocat/preference-panes 0.3.0 → 0.4.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.
@@ -0,0 +1,134 @@
1
+ /* 通用菜单样式;项目可通过 JSON 引用官方组件样式。
2
+ * Generic menu styles; projects may reference official component styles through JSON. */
3
+ body {
4
+ margin: 0;
5
+ overflow-x: hidden;
6
+ font-family: system-ui, sans-serif;
7
+ background: #f6f7f8;
8
+ color: #18191c;
9
+ }
10
+ .pp-home {
11
+ max-width: 720px;
12
+ margin: auto;
13
+ padding: 32px 16px;
14
+ }
15
+ .brand-logo {
16
+ display: block;
17
+ width: 64px;
18
+ height: 64px;
19
+ margin: auto;
20
+ }
21
+ .brand-logo img {
22
+ display: block;
23
+ width: 100%;
24
+ height: 100%;
25
+ object-fit: contain;
26
+ }
27
+ .pp-home h1 {
28
+ text-align: center;
29
+ font-size: 26px;
30
+ margin: 12px 0 32px;
31
+ }
32
+ .self-panel {
33
+ padding: 12px;
34
+ background: #fff;
35
+ border-radius: 12px;
36
+ }
37
+ .self-panel .header {
38
+ font-size: 16px;
39
+ margin: 0;
40
+ padding: 0 6px;
41
+ }
42
+ .self-panel .container {
43
+ margin-top: 16px;
44
+ }
45
+ .self-panel .self-item {
46
+ width: 25%;
47
+ min-width: 0;
48
+ border: 0;
49
+ background: none;
50
+ padding: 12px 2px;
51
+ color: inherit;
52
+ cursor: pointer;
53
+ }
54
+ .self-panel .self-item .logo {
55
+ display: block;
56
+ width: 56px;
57
+ height: 56px;
58
+ padding: 10px;
59
+ box-sizing: border-box;
60
+ border-radius: 50%;
61
+ background: #f1f2f3;
62
+ }
63
+ .self-panel .logo img {
64
+ display: block;
65
+ width: 100%;
66
+ height: 100%;
67
+ object-fit: contain;
68
+ }
69
+ .self-panel .self-item.is-zh .name {
70
+ font-size: 13px;
71
+ line-height: 20px;
72
+ margin-top: 8px;
73
+ white-space: normal;
74
+ }
75
+ .module-status {
76
+ font-size: 11px;
77
+ line-height: 16px;
78
+ min-height: 16px;
79
+ color: #9499a0;
80
+ }
81
+ .self-item:disabled {
82
+ opacity: 0.45;
83
+ cursor: default;
84
+ }
85
+ .settings-note {
86
+ font-size: 13px;
87
+ line-height: 1.6;
88
+ color: #797f89;
89
+ padding: 16px 0;
90
+ }
91
+ @media (prefers-color-scheme: dark) {
92
+ body {
93
+ background: #101114;
94
+ color: #e3e5e7;
95
+ }
96
+ .self-panel {
97
+ background: #1c1d20;
98
+ }
99
+ .self-panel .self-item .logo {
100
+ background: #303136;
101
+ }
102
+ }
103
+ :root[data-theme="dark"] body {
104
+ background: #101114;
105
+ color: #e3e5e7;
106
+ }
107
+ :root[data-theme="dark"] .self-panel {
108
+ background: #1c1d20;
109
+ }
110
+ :root[data-theme="dark"] .self-panel .self-item .logo {
111
+ background: #303136;
112
+ }
113
+ :root[data-theme="light"] body {
114
+ background: #f6f7f8;
115
+ color: #18191c;
116
+ }
117
+ :root[data-theme="light"] .self-panel {
118
+ background: #fff;
119
+ }
120
+ :root[data-theme="light"] .self-panel .self-item .logo {
121
+ background: #f1f2f3;
122
+ }
123
+
124
+ .self-panel .scroll {
125
+ display: flex;
126
+ }
127
+ .self-panel .self-item {
128
+ display: flex;
129
+ flex-direction: column;
130
+ align-items: center;
131
+ }
132
+ .pp-site-error {
133
+ padding: 16px;
134
+ }
@@ -147,6 +147,8 @@ export function createPreferencesClient(options?: PreferencesClientOptions): Pre
147
147
  /**
148
148
  * 按 /settings/{module} 挂载动态面板,监听导航和页面恢复事件。
149
149
  * Mount a dynamic panel at /settings/{module} and observe navigation and page restoration.
150
+ * 控件变化即时串行写入;多选用二级页,返回不重新读取设置。
151
+ * Control changes save immediately in sequence; multi-select uses a secondary page without refetching on return.
150
152
  * @param options 挂载选项 / Mount options.
151
153
  * @returns 面板生命周期句柄 / Panel lifecycle handle.
152
154
  */
@@ -1,106 +1,274 @@
1
+ /* 分组列表沿用 Bilibili 设置页的行结构,样式限定在面板内。
2
+ * Grouped rows follow the Bilibili settings layout, scoped to the panel. */
1
3
  .pp-panel {
4
+ --pp-text: #18191c;
5
+ --pp-background: #f6f7f8;
6
+ --pp-surface: #fff;
7
+ --pp-border: #e3e5e7;
8
+ --pp-muted: #9499a0;
9
+ --pp-accent: #fb7299;
2
10
  font:
3
- 15px / 1.5 system-ui,
11
+ 15px / 1.5 -apple-system,
12
+ BlinkMacSystemFont,
13
+ "Segoe UI",
4
14
  sans-serif;
5
- color: var(--pp-text, #18191c);
6
- background: var(--pp-background, #f6f7f8);
7
- max-width: 760px;
8
- margin: auto;
15
+ color: var(--pp-text);
16
+ background: var(--pp-background);
9
17
  position: relative;
18
+ min-height: 100vh;
10
19
  }
11
20
  .pp-panel * {
12
21
  box-sizing: border-box;
22
+ letter-spacing: 0;
13
23
  }
14
24
  .pp-header {
25
+ height: calc(52px + env(safe-area-inset-top));
26
+ padding: env(safe-area-inset-top) 12px 0;
15
27
  display: flex;
16
28
  align-items: center;
17
- gap: 12px;
18
- padding: 12px 16px;
19
- background: var(--pp-surface, #fff);
29
+ background: var(--pp-surface);
30
+ border-bottom: 1px solid var(--pp-border);
31
+ position: relative;
20
32
  }
21
33
  .pp-title {
22
- font-size: 18px;
34
+ font-size: 17px;
35
+ font-weight: 500;
23
36
  margin: 0;
24
- overflow-wrap: anywhere;
25
37
  min-width: 0;
38
+ overflow-wrap: anywhere;
26
39
  }
27
- .pp-module-info {
28
- display: flex;
29
- gap: 12px;
30
- margin-bottom: 16px;
40
+ .pp-header .pp-title {
41
+ flex: 1;
42
+ text-align: center;
31
43
  }
32
- .pp-module-icon {
33
- width: 48px;
34
- height: 48px;
44
+ .pp-nav-spacer {
45
+ width: 44px;
35
46
  flex: none;
36
- object-fit: contain;
37
- }
38
- .pp-module-details {
39
- min-width: 0;
40
- overflow-wrap: anywhere;
41
47
  }
42
- .pp-module-source {
48
+ .pp-panel button {
49
+ font: inherit;
50
+ cursor: pointer;
51
+ border: 0;
52
+ background: none;
43
53
  color: inherit;
44
- text-decoration: underline;
54
+ }
55
+ .pp-panel .pp-back {
56
+ width: 44px;
57
+ height: 44px;
58
+ flex: none;
59
+ font-size: 34px;
60
+ line-height: 32px;
61
+ padding: 0;
62
+ }
63
+ .pp-panel button:disabled {
64
+ opacity: 0.5;
65
+ cursor: wait;
45
66
  }
46
67
  .pp-viewport {
47
- max-height: 80vh;
68
+ position: relative;
69
+ height: calc(100vh - 52px - env(safe-area-inset-top));
70
+ overflow: hidden;
71
+ }
72
+ @supports (height: 100dvh) {
73
+ .pp-viewport {
74
+ height: calc(100dvh - 52px - env(safe-area-inset-top));
75
+ }
76
+ }
77
+ .pp-fields,
78
+ .pp-choice-page {
79
+ position: absolute;
80
+ inset: 0;
48
81
  overflow: auto;
49
- padding: 16px;
82
+ padding: 12px max(16px, calc((100% - 688px) / 2)) calc(28px + env(safe-area-inset-bottom));
83
+ background: var(--pp-background);
50
84
  }
51
- .pp-panel button {
52
- font: inherit;
53
- cursor: pointer;
54
- border: 1px solid var(--pp-border, #d8dce0);
85
+ .pp-panel .form-group {
86
+ margin: 0 0 12px;
87
+ }
88
+ .pp-panel .form-group__title {
89
+ font-size: 12px;
90
+ line-height: 17px;
91
+ font-weight: 400;
92
+ color: var(--pp-muted);
93
+ padding-left: 12px;
94
+ margin: 12px 0 6px;
95
+ }
96
+ .pp-panel .form-group__row {
55
97
  border-radius: 8px;
56
- padding: 8px 12px;
57
- color: inherit;
58
- background: var(--pp-surface, #fff);
98
+ overflow: hidden;
99
+ background: var(--pp-surface);
59
100
  }
60
- .pp-panel button:disabled {
61
- opacity: 0.45;
62
- cursor: default;
63
- }
64
- .pp-field {
65
- margin: 0 0 16px;
66
- padding: 16px;
67
- border: 1px solid var(--pp-border, #d8dce0);
68
- border-radius: 10px;
69
- background: var(--pp-surface, #fff);
101
+ .pp-panel .form-row {
102
+ position: relative;
103
+ display: flex;
104
+ align-items: center;
105
+ width: 100%;
106
+ min-height: 46px;
107
+ padding: 12px;
108
+ border: 0;
109
+ border-bottom: 1px solid var(--pp-border);
110
+ background: var(--pp-surface);
111
+ gap: 12px;
112
+ }
113
+ .pp-panel .form-row:last-child {
114
+ border-bottom: 0;
115
+ }
116
+ .pp-panel .form-row__text {
117
+ flex: 1;
70
118
  min-width: 0;
119
+ margin: 0;
120
+ display: flex;
121
+ flex-direction: column;
71
122
  }
72
- .pp-description {
123
+ .pp-panel .form-row__title {
124
+ font-size: 15px;
125
+ line-height: 22px;
126
+ color: var(--pp-text);
127
+ text-align: left;
128
+ }
129
+ .pp-panel .form-row__subtitle {
130
+ font-size: 12px;
131
+ line-height: 18px;
132
+ color: var(--pp-muted);
133
+ overflow-wrap: anywhere;
134
+ margin-top: 2px;
135
+ }
136
+ .pp-choice-link {
137
+ display: flex;
138
+ align-items: center;
139
+ justify-content: flex-end;
140
+ gap: 8px;
141
+ max-width: 45%;
142
+ min-width: 44px;
143
+ min-height: 44px;
144
+ padding: 0;
145
+ text-align: right;
146
+ flex: 1;
147
+ }
148
+ .pp-summary {
149
+ color: var(--pp-muted);
73
150
  font-size: 13px;
74
- opacity: 0.7;
75
- margin: 0 0 8px;
76
- white-space: pre-wrap;
151
+ line-height: 18px;
152
+ display: -webkit-box;
153
+ -webkit-line-clamp: 2;
154
+ -webkit-box-orient: vertical;
155
+ overflow: hidden;
77
156
  overflow-wrap: anywhere;
78
157
  }
79
- .pp-input:not([type="checkbox"]) {
80
- width: 100%;
158
+ .pp-chevron {
159
+ color: var(--pp-muted);
160
+ font-size: 22px;
161
+ flex: none;
162
+ }
163
+ .pp-input {
81
164
  font: inherit;
82
- padding: 8px;
83
- border: 1px solid var(--pp-border, #d8dce0);
165
+ color: var(--pp-text);
166
+ background: var(--pp-surface);
167
+ border: 1px solid var(--pp-border);
84
168
  border-radius: 6px;
85
- background: var(--pp-surface, #fff);
86
- color: inherit;
169
+ padding: 8px;
170
+ min-width: 0;
171
+ max-width: 45%;
172
+ width: 45%;
87
173
  }
88
- .pp-choice {
174
+ select.pp-input {
175
+ text-overflow: ellipsis;
176
+ font-size: 13px;
177
+ }
178
+ .pp-panel .pp-multiline {
89
179
  display: block;
90
- margin: 6px 0;
180
+ }
181
+ .pp-multiline .pp-input {
182
+ max-width: 100%;
183
+ width: 100%;
184
+ margin-top: 10px;
185
+ }
186
+ .pp-switch {
187
+ appearance: none;
188
+ -webkit-appearance: none;
189
+ position: relative;
190
+ flex: none;
191
+ width: 32px;
192
+ height: 20px;
193
+ max-width: none;
194
+ border: 0;
195
+ border-radius: 15px;
196
+ padding: 0;
197
+ background: #c9ccd0;
198
+ cursor: pointer;
199
+ transition: background 0.2s;
200
+ }
201
+ .pp-switch::before {
202
+ content: "";
203
+ position: absolute;
204
+ top: 3px;
205
+ left: 3px;
206
+ width: 14px;
207
+ height: 14px;
208
+ border-radius: 50%;
209
+ background: white;
210
+ transition: transform 0.2s;
211
+ }
212
+ .pp-switch:checked {
213
+ background: var(--pp-accent);
214
+ }
215
+ .pp-switch:checked::before {
216
+ transform: translateX(12px);
217
+ }
218
+ .pp-choice {
219
+ justify-content: space-between;
220
+ cursor: pointer;
91
221
  }
92
222
  .pp-choice input {
93
- margin-right: 8px;
223
+ width: 20px;
224
+ height: 20px;
225
+ flex: none;
226
+ accent-color: var(--pp-accent);
227
+ margin: 0;
228
+ }
229
+ .pp-description {
230
+ font-size: 12px;
231
+ line-height: 1.6;
232
+ color: var(--pp-muted);
233
+ white-space: pre-wrap;
234
+ overflow-wrap: anywhere;
235
+ }
236
+ .pp-module-info {
237
+ display: flex;
238
+ gap: 12px;
239
+ margin: 12px 0;
240
+ }
241
+ .pp-module-icon {
242
+ width: 48px;
243
+ height: 48px;
244
+ object-fit: contain;
245
+ flex: none;
246
+ }
247
+ .pp-module-details {
248
+ min-width: 0;
249
+ overflow-wrap: anywhere;
250
+ }
251
+ .pp-module-source {
252
+ color: inherit;
253
+ text-decoration: underline;
254
+ }
255
+ .pp-maintenance {
256
+ margin-top: 24px;
94
257
  }
95
258
  .pp-actions {
96
259
  display: flex;
97
260
  flex-wrap: wrap;
98
261
  gap: 8px;
99
- margin-top: 12px;
100
262
  }
101
- .pp-maintenance {
102
- border-top: 1px solid var(--pp-border, #d8dce0);
103
- padding-top: 16px;
263
+ .pp-actions button,
264
+ .pp-error button {
265
+ min-height: 44px;
266
+ padding: 8px 12px;
267
+ border-radius: 6px;
268
+ background: var(--pp-surface);
269
+ }
270
+ .pp-panel .pp-danger {
271
+ color: #e45656;
104
272
  }
105
273
  .pp-cache {
106
274
  max-height: 320px;
@@ -108,33 +276,50 @@
108
276
  white-space: pre-wrap;
109
277
  overflow-wrap: anywhere;
110
278
  }
111
- .pp-panel .pp-danger {
112
- color: #d34242;
113
- }
114
279
  .pp-toast {
280
+ pointer-events: none;
115
281
  position: fixed;
116
- bottom: 32px;
282
+ bottom: calc(30px + env(safe-area-inset-bottom));
117
283
  left: 50%;
118
284
  transform: translateX(-50%);
119
- padding: 10px 18px;
120
- border-radius: 10px;
121
- background: #252525;
122
- color: #fff;
123
285
  max-width: 90vw;
124
- z-index: 1000;
286
+ padding: 10px 16px;
287
+ border-radius: 8px;
288
+ background: #333e;
289
+ color: white;
290
+ font-size: 13px;
291
+ z-index: 20;
125
292
  }
126
293
  .pp-toast[data-kind="error"] {
127
294
  background: #8d2424;
128
295
  }
129
296
  .pp-panel :focus-visible {
130
- outline: 2px solid #008ac5;
131
- outline-offset: 2px;
297
+ outline: 2px solid var(--pp-accent);
298
+ outline-offset: -2px;
132
299
  }
133
300
  @media (prefers-color-scheme: dark) {
134
301
  .pp-panel {
135
- --pp-text: #eee;
136
- --pp-background: #18191c;
137
- --pp-surface: #25262a;
138
- --pp-border: #47494e;
302
+ --pp-text: #e3e5e7;
303
+ --pp-background: #17181a;
304
+ --pp-surface: #232427;
305
+ --pp-border: #343538;
306
+ }
307
+ }
308
+ :root[data-theme="dark"] .pp-panel {
309
+ --pp-text: #e3e5e7;
310
+ --pp-background: #17181a;
311
+ --pp-surface: #232427;
312
+ --pp-border: #343538;
313
+ }
314
+ :root[data-theme="light"] .pp-panel {
315
+ --pp-text: #18191c;
316
+ --pp-background: #f6f7f8;
317
+ --pp-surface: #fff;
318
+ --pp-border: #e3e5e7;
319
+ }
320
+ @media (prefers-reduced-motion: reduce) {
321
+ .pp-panel .pp-switch,
322
+ .pp-panel .pp-switch::before {
323
+ transition: none;
139
324
  }
140
325
  }