@yunlefun-home/air-conditioner-core 0.2.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.
- package/dist/index.cjs +1334 -68
- package/dist/index.d.cts +710 -40
- package/dist/index.d.ts +710 -40
- package/dist/index.js +1281 -72
- package/package.json +6 -4
package/dist/index.d.cts
CHANGED
|
@@ -1,6 +1,30 @@
|
|
|
1
1
|
//#region src/types.d.ts
|
|
2
|
-
type AcMode = 'cold' | 'hot';
|
|
3
|
-
|
|
2
|
+
export type AcMode = 'cold' | 'hot';
|
|
3
|
+
/**
|
|
4
|
+
* Sound mode: `normal` plays everything, `sleep` lowers the volume,
|
|
5
|
+
* `mute` silences the air conditioner.
|
|
6
|
+
*/
|
|
7
|
+
export type AcSoundMode = 'normal' | 'sleep' | 'mute';
|
|
8
|
+
/**
|
|
9
|
+
* Fan speed (风速). `auto` lets the unit decide: strong at first, quieter
|
|
10
|
+
* once the room settles, with the occasional surge. The fixed speeds hold
|
|
11
|
+
* the airflow and fan sound steady.
|
|
12
|
+
*/
|
|
13
|
+
export type AcFanSpeed = 'auto' | 'low' | 'medium' | 'high';
|
|
14
|
+
/**
|
|
15
|
+
* Temperature range a device supports. Real devices (e.g. Home Assistant
|
|
16
|
+
* climate entities) report their own range and step.
|
|
17
|
+
*/
|
|
18
|
+
export interface AcLimits {
|
|
19
|
+
min: number;
|
|
20
|
+
max: number;
|
|
21
|
+
step: number;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Visual tone of the unit: idle when off, otherwise follows the mode.
|
|
25
|
+
*/
|
|
26
|
+
export type AcTone = 'idle' | 'cool' | 'heat';
|
|
27
|
+
export interface AcState {
|
|
4
28
|
/**
|
|
5
29
|
* Whether the air conditioner is powered on.
|
|
6
30
|
*/
|
|
@@ -10,75 +34,226 @@ interface AcState {
|
|
|
10
34
|
*/
|
|
11
35
|
mode: AcMode;
|
|
12
36
|
/**
|
|
13
|
-
* Target temperature in Celsius.
|
|
37
|
+
* Target temperature in Celsius, for the current mode.
|
|
14
38
|
*/
|
|
15
39
|
temperature: number;
|
|
40
|
+
/**
|
|
41
|
+
* Last target temperature of each mode, like a real remote: switching
|
|
42
|
+
* from 制冷 20 °C to 制热 and back restores 20 °C. `normalizeAcState`
|
|
43
|
+
* always fills it in, with the current mode holding `temperature`; states
|
|
44
|
+
* saved before this field existed start with both modes at their saved
|
|
45
|
+
* temperature. Optional so hand-written states keep type-checking.
|
|
46
|
+
*/
|
|
47
|
+
temperatures?: Record<AcMode, number>;
|
|
48
|
+
/**
|
|
49
|
+
* Sound mode. States saved before this field existed fall back to `normal`.
|
|
50
|
+
*/
|
|
51
|
+
sound: AcSoundMode;
|
|
52
|
+
/**
|
|
53
|
+
* Whether the airflow sweeps left and right. States saved before this
|
|
54
|
+
* field existed fall back to `false`.
|
|
55
|
+
*/
|
|
56
|
+
swing: boolean;
|
|
57
|
+
/**
|
|
58
|
+
* Fan speed. `normalizeAcState` fills in `auto` for states saved before
|
|
59
|
+
* this field existed; optional so hand-written states keep type-checking.
|
|
60
|
+
*/
|
|
61
|
+
fan?: AcFanSpeed;
|
|
16
62
|
}
|
|
17
|
-
type AcAction = {
|
|
18
|
-
type: 'increment' | 'decrement' | 'toggleStatus';
|
|
63
|
+
export type AcAction = {
|
|
64
|
+
type: 'increment' | 'decrement' | 'toggleStatus' | 'cycleSound' | 'toggleSwing' | 'cycleFan';
|
|
19
65
|
} | {
|
|
20
66
|
type: 'status';
|
|
21
67
|
status: AcState['status'];
|
|
22
|
-
} |
|
|
68
|
+
} |
|
|
69
|
+
/**
|
|
70
|
+
* 切换模式。`powerOn` 为 true 时关机状态下顺便开机(遥控器的模式键就是这样);
|
|
71
|
+
* Home Assistant 等外部同步不传,只改模式。
|
|
72
|
+
*/
|
|
73
|
+
{
|
|
23
74
|
type: 'mode';
|
|
24
75
|
mode: AcState['mode'];
|
|
76
|
+
powerOn?: boolean;
|
|
77
|
+
} | {
|
|
78
|
+
type: 'sound';
|
|
79
|
+
sound: AcState['sound'];
|
|
80
|
+
} | {
|
|
81
|
+
type: 'swing';
|
|
82
|
+
swing: AcState['swing'];
|
|
83
|
+
} | {
|
|
84
|
+
type: 'fan';
|
|
85
|
+
fan: AcFanSpeed;
|
|
25
86
|
} | {
|
|
26
87
|
type: 'update';
|
|
27
88
|
payload: Partial<AcState>;
|
|
28
89
|
};
|
|
29
|
-
type AcNotificationSeverity = 'success' | 'error' | 'info';
|
|
30
|
-
|
|
90
|
+
export type AcNotificationSeverity = 'success' | 'error' | 'info';
|
|
91
|
+
/**
|
|
92
|
+
* What a notification is about, which decides how views present it:
|
|
93
|
+
*
|
|
94
|
+
* - `tip`:节能建议,以「出风口吹出的小纸条」显示
|
|
95
|
+
* - `limit`:温度到了上下限,遥控器小屏抖一下,不弹提示
|
|
96
|
+
* - `setting`:风速、声音、扫风等设置变化,小屏已经显示,只给读屏播报
|
|
97
|
+
*/
|
|
98
|
+
export type AcNotificationKind = 'tip' | 'limit' | 'setting';
|
|
99
|
+
export interface AcNotification {
|
|
31
100
|
message: string;
|
|
32
101
|
severity: AcNotificationSeverity;
|
|
102
|
+
/** Absent on notifications from before kinds existed; treat as `tip`. */
|
|
103
|
+
kind?: AcNotificationKind;
|
|
104
|
+
/** A second, quieter line, e.g. why a tip matters. */
|
|
105
|
+
detail?: string;
|
|
33
106
|
}
|
|
34
|
-
interface AcChangeEvent {
|
|
107
|
+
export interface AcChangeEvent {
|
|
35
108
|
action: AcAction;
|
|
36
109
|
previousState: AcState;
|
|
37
110
|
state: AcState;
|
|
38
111
|
notification?: AcNotification;
|
|
39
112
|
}
|
|
40
|
-
type AcStoreListener = (event: AcChangeEvent) => void;
|
|
41
|
-
interface AcStorage {
|
|
113
|
+
export type AcStoreListener = (event: AcChangeEvent) => void;
|
|
114
|
+
export interface AcStorage {
|
|
42
115
|
getItem: (key: string) => string | null;
|
|
43
116
|
setItem: (key: string, value: string) => void;
|
|
44
117
|
removeItem?: (key: string) => void;
|
|
45
118
|
}
|
|
46
|
-
interface CreateAirConditionerStoreOptions {
|
|
119
|
+
export interface CreateAirConditionerStoreOptions {
|
|
47
120
|
initialState?: Partial<AcState>;
|
|
121
|
+
/**
|
|
122
|
+
* Device temperature limits. Defaults to 16–31 °C with a step of 1.
|
|
123
|
+
*/
|
|
124
|
+
limits?: AcLimits;
|
|
48
125
|
storage?: AcStorage | null;
|
|
49
126
|
storageKey?: string;
|
|
50
127
|
onNotify?: (notification: AcNotification, event: AcChangeEvent) => void;
|
|
51
128
|
}
|
|
52
|
-
interface AirConditionerStore {
|
|
129
|
+
export interface AirConditionerStore {
|
|
53
130
|
getState: () => AcState;
|
|
54
131
|
dispatch: (action: AcAction) => AcChangeEvent;
|
|
55
132
|
subscribe: (listener: AcStoreListener) => () => void;
|
|
56
133
|
}
|
|
57
|
-
|
|
134
|
+
/**
|
|
135
|
+
* The subset of `HTMLAudioElement` the audio controller uses. The optional
|
|
136
|
+
* members let it pause, loop and set volume when they exist.
|
|
137
|
+
*/
|
|
138
|
+
export interface AcAudioElement {
|
|
58
139
|
currentTime: number;
|
|
59
140
|
load: () => void;
|
|
60
141
|
play: () => Promise<unknown> | unknown;
|
|
142
|
+
pause?: () => void;
|
|
143
|
+
volume?: number;
|
|
144
|
+
muted?: boolean;
|
|
145
|
+
loop?: boolean;
|
|
146
|
+
/** Used to fetch the file for Web Audio playback. */
|
|
147
|
+
src?: string;
|
|
148
|
+
currentSrc?: string;
|
|
61
149
|
}
|
|
62
|
-
interface AcAudioElements {
|
|
150
|
+
export interface AcAudioElements {
|
|
63
151
|
start: AcAudioElement | null;
|
|
64
152
|
work: AcAudioElement | null;
|
|
65
153
|
beep?: AcAudioElement | null;
|
|
66
154
|
}
|
|
67
|
-
interface AcAudioController {
|
|
155
|
+
export interface AcAudioController {
|
|
68
156
|
beep: () => void;
|
|
69
157
|
toggleStatusAudio: (previousStatus: boolean) => void;
|
|
158
|
+
/**
|
|
159
|
+
* Change the volume of everything, including sounds already playing.
|
|
160
|
+
*/
|
|
161
|
+
setSoundMode: (mode: AcSoundMode) => void;
|
|
162
|
+
/**
|
|
163
|
+
* Follow the fan speed: `auto` keeps the settle / surge cycle, fixed
|
|
164
|
+
* speeds hold the fan sound at a steady level.
|
|
165
|
+
*/
|
|
166
|
+
setFanSpeed: (fan: AcFanSpeed) => void;
|
|
167
|
+
/**
|
|
168
|
+
* A soft synthesized drop of condensation (#21). Only in the `normal`
|
|
169
|
+
* sound mode and only through Web Audio; otherwise silent.
|
|
170
|
+
*/
|
|
171
|
+
drip: () => void;
|
|
70
172
|
dispose: () => void;
|
|
71
173
|
}
|
|
174
|
+
export interface CreateAcAudioControllerOptions {
|
|
175
|
+
/**
|
|
176
|
+
* Initial sound mode.
|
|
177
|
+
* @default 'normal'
|
|
178
|
+
*/
|
|
179
|
+
soundMode?: AcSoundMode;
|
|
180
|
+
/**
|
|
181
|
+
* Initial fan speed.
|
|
182
|
+
* @default 'auto'
|
|
183
|
+
*/
|
|
184
|
+
fanSpeed?: AcFanSpeed;
|
|
185
|
+
/**
|
|
186
|
+
* Play through the Web Audio API for a gapless loop and smooth fades.
|
|
187
|
+
* Falls back to the `<audio>` elements when the API is missing or the
|
|
188
|
+
* files cannot be fetched (for example across origins without CORS).
|
|
189
|
+
* @default true
|
|
190
|
+
*/
|
|
191
|
+
webAudio?: boolean;
|
|
192
|
+
/**
|
|
193
|
+
* Create the `AudioContext`. Defaults to `new AudioContext()`.
|
|
194
|
+
*/
|
|
195
|
+
createAudioContext?: () => AudioContext;
|
|
196
|
+
/**
|
|
197
|
+
* Fetch an audio file. Defaults to `fetch(url)`.
|
|
198
|
+
*/
|
|
199
|
+
loadAudioData?: (url: string) => Promise<ArrayBuffer>;
|
|
200
|
+
/**
|
|
201
|
+
* Random source for the fan's quiet / busy cycle. Defaults to `Math.random`.
|
|
202
|
+
*/
|
|
203
|
+
random?: () => number;
|
|
204
|
+
}
|
|
72
205
|
//#endregion
|
|
73
206
|
//#region src/audio.d.ts
|
|
74
|
-
|
|
207
|
+
/**
|
|
208
|
+
* 空调音效:按键「嘀」声、开机启动声与持续的风声。
|
|
209
|
+
*
|
|
210
|
+
* 默认通过 Web Audio API 播放:风声无缝循环,开关机淡入淡出,运行一段时间后
|
|
211
|
+
* 风声变小、并不定时随压缩机发力起伏。环境不支持或音频无法获取时退回
|
|
212
|
+
* `<audio>` 元素。
|
|
213
|
+
*
|
|
214
|
+
* 需在用户交互(点击遥控器)里首次调用,浏览器才允许发声。
|
|
215
|
+
*
|
|
216
|
+
* @param elements 三个音频元素;Web Audio 会从它们的 `src` 获取音频
|
|
217
|
+
* @param options 声音模式与可替换的环境依赖
|
|
218
|
+
*/
|
|
219
|
+
export declare function createAcAudioController(elements: AcAudioElements, options?: CreateAcAudioControllerOptions): AcAudioController;
|
|
220
|
+
//#endregion
|
|
221
|
+
//#region src/condensation.d.ts
|
|
222
|
+
type CondensationState = Pick<AcState, 'status' | 'mode' | 'temperature'> & {
|
|
223
|
+
fan?: AcFanSpeed;
|
|
224
|
+
};
|
|
225
|
+
/** 高于这个设定温度不滴水:冷凝水不该常见,只在开得很冷时偶尔出现 */
|
|
226
|
+
export declare const acDripMaxTemperature = 22;
|
|
227
|
+
/** 最冷(16 °C)与 {@link acDripMaxTemperature} 时,两滴水之间的间隔(ms) */
|
|
228
|
+
export declare const acDripIntervalRange: readonly [9000, 18000];
|
|
229
|
+
/**
|
|
230
|
+
* 出风口雾气的浓度(#70),0–1:只在制冷开机时出现,设定温度越低、风越大越浓。
|
|
231
|
+
*
|
|
232
|
+
* 视图把它写进 CSS 变量 `--acw-mist`,3D 等其他渲染器也可以按它控制粒子数量。
|
|
233
|
+
*/
|
|
234
|
+
export declare function getAcMist(state: CondensationState): number;
|
|
235
|
+
/**
|
|
236
|
+
* 冷凝水滴落的间隔(#21,ms):只在制冷开机、设定温度不高于 {@link acDripMaxTemperature} 时滴水,
|
|
237
|
+
* 越冷越频繁,高风再快一些;不滴水时返回 `undefined`。
|
|
238
|
+
*
|
|
239
|
+
* 视图把它写进 CSS 变量 `--acw-drip-cycle`,水珠在出风口边缘慢慢聚起再落下,开机后要等一整个间隔才滴第一滴。
|
|
240
|
+
*/
|
|
241
|
+
export declare function getAcDripInterval(state: CondensationState): number | undefined;
|
|
242
|
+
/**
|
|
243
|
+
* 视图要写到空调根元素上的雾气 / 滴水样式变量与属性。
|
|
244
|
+
*/
|
|
245
|
+
export declare function getAcCondensationStyle(state: CondensationState): {
|
|
246
|
+
mist: number;
|
|
247
|
+
dripCycle?: string;
|
|
248
|
+
drip: 'on' | 'off';
|
|
249
|
+
};
|
|
75
250
|
//#endregion
|
|
76
251
|
//#region src/constants.d.ts
|
|
77
|
-
declare const acStorageKey = "ac:state";
|
|
252
|
+
export declare const acStorageKey = "ac:state";
|
|
78
253
|
/**
|
|
79
254
|
* 各模式对应的显示图标(供各框架视图层复用)。
|
|
80
255
|
*/
|
|
81
|
-
declare const acModeIcons: Record<AcMode, string>;
|
|
256
|
+
export declare const acModeIcons: Record<AcMode, string>;
|
|
82
257
|
/**
|
|
83
258
|
* 默认音频资源文件名(不含扩展名)。
|
|
84
259
|
*
|
|
@@ -86,20 +261,77 @@ declare const acModeIcons: Record<AcMode, string>;
|
|
|
86
261
|
* - `start` 空调启动声
|
|
87
262
|
* - `work` 持续工作(出风)声
|
|
88
263
|
*/
|
|
89
|
-
declare const acAudioFileNames: {
|
|
264
|
+
export declare const acAudioFileNames: {
|
|
90
265
|
readonly beep: "di";
|
|
91
266
|
readonly start: "ac-work";
|
|
92
267
|
readonly work: "air-extractor-fan";
|
|
93
268
|
};
|
|
94
|
-
declare const minTemperature = 16;
|
|
95
|
-
declare const maxTemperature = 31;
|
|
96
|
-
declare const
|
|
97
|
-
declare const
|
|
98
|
-
declare const
|
|
99
|
-
declare const
|
|
269
|
+
export declare const minTemperature = 16;
|
|
270
|
+
export declare const maxTemperature = 31;
|
|
271
|
+
export declare const defaultAcLimits: AcLimits;
|
|
272
|
+
export declare const recommendedColdTemperature = 26;
|
|
273
|
+
export declare const recommendedHotTemperature = 20;
|
|
274
|
+
export declare const defaultAcState: AcState;
|
|
275
|
+
/**
|
|
276
|
+
* 遥控器「声音」键依次切换的顺序。
|
|
277
|
+
*/
|
|
278
|
+
export declare const acSoundModes: readonly AcSoundMode[];
|
|
279
|
+
/**
|
|
280
|
+
* 各模式的中文名称(遥控器小屏与按键提示共用)。
|
|
281
|
+
*/
|
|
282
|
+
export declare const acModeLabels: Record<AcMode, string>;
|
|
283
|
+
export declare const acSoundModeLabels: Record<AcSoundMode, string>;
|
|
284
|
+
/**
|
|
285
|
+
* 各声音模式的总音量(0–1)。
|
|
286
|
+
*/
|
|
287
|
+
export declare const acSoundVolumes: Record<AcSoundMode, number>;
|
|
288
|
+
/**
|
|
289
|
+
* 遥控器「风速」键依次切换的顺序。
|
|
290
|
+
*/
|
|
291
|
+
export declare const acFanSpeeds: readonly AcFanSpeed[];
|
|
292
|
+
export declare const acFanSpeedLabels: Record<AcFanSpeed, string>;
|
|
293
|
+
/**
|
|
294
|
+
* 小屏上点亮的风速格数(1–3)。自动风速由空调自己决定,显示为 0 并另加「自动」标记。
|
|
295
|
+
*/
|
|
296
|
+
export declare const acFanBars: Record<AcFanSpeed, number>;
|
|
297
|
+
/**
|
|
298
|
+
* 固定风速下风声的相对音量(0–1);自动风速沿用开机后的「达标 / 发力」循环。
|
|
299
|
+
*/
|
|
300
|
+
export declare const acFanSoundLevels: Record<Exclude<AcFanSpeed, 'auto'>, number>;
|
|
301
|
+
export declare function isAcFanSpeed(value: unknown): value is AcFanSpeed;
|
|
302
|
+
/**
|
|
303
|
+
* 风速键的下一档:自动 → 低 → 中 → 高 → 自动。
|
|
304
|
+
*/
|
|
305
|
+
export declare function nextAcFanSpeed(fan: AcFanSpeed | undefined): AcFanSpeed;
|
|
306
|
+
export declare function isAcSoundMode(value: unknown): value is AcSoundMode;
|
|
307
|
+
/**
|
|
308
|
+
* 声音键的下一个模式:标准 → 睡眠 → 静音 → 标准。
|
|
309
|
+
*/
|
|
310
|
+
export declare function nextAcSoundMode(mode: AcSoundMode | undefined): AcSoundMode;
|
|
311
|
+
/**
|
|
312
|
+
* 音效时序。时长单位为毫秒,`*Level` 是风声相对音量(0–1)。
|
|
313
|
+
*/
|
|
314
|
+
export declare const soundTimings: {
|
|
315
|
+
/** 开机后多久接上持续的风声(启动声约 9 秒) */
|
|
100
316
|
readonly startDelayMs: 8000;
|
|
101
|
-
|
|
102
|
-
readonly
|
|
317
|
+
/** 风声循环首尾的交叉淡化时长 */
|
|
318
|
+
readonly loopCrossfadeMs: 1500;
|
|
319
|
+
/** 关机时声音淡出时长 */
|
|
320
|
+
readonly stopFadeMs: 600;
|
|
321
|
+
/** 开机运行多久后室温达标、风声降下来 */
|
|
322
|
+
readonly settleAfterMs: 90000;
|
|
323
|
+
/** 风声降下来的渐变时长 */
|
|
324
|
+
readonly settleRampMs: 20000;
|
|
325
|
+
/** 达标后的安静风声 */
|
|
326
|
+
readonly settleLevel: 0.5;
|
|
327
|
+
/** 室温回升、压缩机重新发力时的风声 */
|
|
328
|
+
readonly surgeLevel: 0.85;
|
|
329
|
+
/** 两次发力之间安静运行的时长范围 */
|
|
330
|
+
readonly quietDurationMs: readonly [180000, 360000];
|
|
331
|
+
/** 每次发力持续的时长范围 */
|
|
332
|
+
readonly surgeDurationMs: readonly [60000, 120000];
|
|
333
|
+
/** 发力 / 回落的渐变时长 */
|
|
334
|
+
readonly surgeRampMs: 10000;
|
|
103
335
|
};
|
|
104
336
|
/**
|
|
105
337
|
* 根据基础路径解析出三个音频文件的完整 URL。
|
|
@@ -109,26 +341,464 @@ declare const soundTimings: {
|
|
|
109
341
|
* @param baseUrl 音频目录,如 `/assets/audio`
|
|
110
342
|
* @param ext 文件扩展名,默认 `m4a`
|
|
111
343
|
*/
|
|
112
|
-
declare function resolveAcAudioAssets(baseUrl?: string, ext?: string): {
|
|
344
|
+
export declare function resolveAcAudioAssets(baseUrl?: string, ext?: string): {
|
|
113
345
|
beep: string;
|
|
114
346
|
start: string;
|
|
115
347
|
work: string;
|
|
116
348
|
};
|
|
117
349
|
//#endregion
|
|
350
|
+
//#region src/layout.d.ts
|
|
351
|
+
/**
|
|
352
|
+
* 机身的设计尺寸(px),约 3:1,接近真实壁挂机(如 800–900mm × 280–300mm)的比例。
|
|
353
|
+
* 窄容器下按比例整体缩放,保持「长款」外观不被压扁。
|
|
354
|
+
*
|
|
355
|
+
* - `compact`:Vue / React 组件库 / Web Component 使用的 360 × 128 机身
|
|
356
|
+
* - `wide`:React 主站使用的 600 × 200 机身
|
|
357
|
+
*/
|
|
358
|
+
export declare const acShellSize: {
|
|
359
|
+
readonly compact: {
|
|
360
|
+
readonly width: 360;
|
|
361
|
+
readonly height: 128;
|
|
362
|
+
};
|
|
363
|
+
readonly wide: {
|
|
364
|
+
readonly width: 600;
|
|
365
|
+
readonly height: 200;
|
|
366
|
+
};
|
|
367
|
+
};
|
|
368
|
+
/**
|
|
369
|
+
* 根据可用宽度计算机身缩放比例:只缩小、不放大。
|
|
370
|
+
*/
|
|
371
|
+
export declare function getAcScale(availableWidth: number, designWidth: number): number;
|
|
372
|
+
/**
|
|
373
|
+
* 监听容器宽度变化并回调缩放比例。
|
|
374
|
+
*
|
|
375
|
+
* 不支持 `ResizeObserver` 的环境(如 SSR)直接返回空的清理函数,保持 1 倍显示。
|
|
376
|
+
*
|
|
377
|
+
* @param target 被测量宽度的容器(不要传被缩放的元素本身)
|
|
378
|
+
* @param designWidth 机身的设计宽度
|
|
379
|
+
* @param onScale 比例变化时的回调
|
|
380
|
+
* @returns 停止监听的清理函数
|
|
381
|
+
*/
|
|
382
|
+
export declare function observeAcScale(target: Element, designWidth: number, onScale: (scale: number) => void): () => void;
|
|
383
|
+
/** 指针跟随倾斜的最大角度(deg) */
|
|
384
|
+
export declare const acMaxTilt = 4;
|
|
385
|
+
/**
|
|
386
|
+
* 指针在元素上移动时回调轻微的 3D 倾斜角度(`rotateX` / `rotateY`,单位 deg),离开时回到 0。
|
|
387
|
+
*
|
|
388
|
+
* 仅在有悬停能力的精细指针(鼠标 / 触控板)上启用;`prefers-reduced-motion: reduce`、
|
|
389
|
+
* 触屏或 SSR 下直接返回空的清理函数。
|
|
390
|
+
*
|
|
391
|
+
* @returns 停止监听的清理函数
|
|
392
|
+
*/
|
|
393
|
+
export declare function observeAcTilt(target: HTMLElement, onTilt: (rotateX: number, rotateY: number) => void, maxTilt?: number): () => void;
|
|
394
|
+
//#endregion
|
|
395
|
+
//#region src/model.d.ts
|
|
396
|
+
/**
|
|
397
|
+
* 3D 模型的两种形态:挂机与柜机。
|
|
398
|
+
*
|
|
399
|
+
* 模型由 `apps/macos/Model/build_cute_ac.py` 在 Blender 里生成:原生应用读 USDZ,网页读同一个场景导出的 GLB。
|
|
400
|
+
* 这里的约定与 Swift 共享包里的 `ACModel` 一一对应,改动时两边一起改(有测试检查)。
|
|
401
|
+
*/
|
|
402
|
+
export type AcForm = 'wall' | 'tower';
|
|
403
|
+
export declare const acForms: readonly AcForm[];
|
|
404
|
+
export declare const acFormLabels: Record<AcForm, string>;
|
|
405
|
+
/** 网页用的模型文件名(站点的 `public/models/` 下) */
|
|
406
|
+
export declare const acModelFiles: Record<AcForm, string>;
|
|
407
|
+
/** 渲染器要控制的命名节点,两种形态相同 */
|
|
408
|
+
export declare const acModelParts: {
|
|
409
|
+
/** 导风板:挂机是一整块,柜机是一组百叶(子节点) */
|
|
410
|
+
readonly louver: "Louver";
|
|
411
|
+
/** 0.25 × 0.1、UV 为 0–1 的平面,贴温度画面 */
|
|
412
|
+
readonly display: "Display";
|
|
413
|
+
/** 指示灯 */
|
|
414
|
+
readonly led: "Led";
|
|
415
|
+
};
|
|
416
|
+
/**
|
|
417
|
+
* 开机时导风板怎么动:都绕本地 X 轴转;`node` 是导风板整体转,`children` 是每片百叶各自转。
|
|
418
|
+
*/
|
|
419
|
+
export interface AcLouverMotion {
|
|
420
|
+
pivot: 'node' | 'children';
|
|
421
|
+
/** 开机时的角度(度),关机为 0 */
|
|
422
|
+
openAngle: number;
|
|
423
|
+
}
|
|
424
|
+
export declare const acLouverMotion: Record<AcForm, AcLouverMotion>;
|
|
425
|
+
/**
|
|
426
|
+
* 出风的起点(相对导风板的世界坐标,Y 轴朝上、+Z 朝向观看者)、出风口的宽度和出风方向:
|
|
427
|
+
* 挂机向下吹,柜机从百叶侧面吹出。
|
|
428
|
+
*/
|
|
429
|
+
export interface AcAirflowAnchor {
|
|
430
|
+
offset: readonly [number, number, number];
|
|
431
|
+
extent: number;
|
|
432
|
+
direction: 'down' | 'side';
|
|
433
|
+
}
|
|
434
|
+
export declare const acAirflowAnchors: Record<AcForm, AcAirflowAnchor>;
|
|
435
|
+
/** 指示灯与显示窗的颜色:开机时是模式色,关机是灰色(与 `ACPalette` 一致) */
|
|
436
|
+
export declare const acModelColors: {
|
|
437
|
+
readonly cold: "#5aa9ff";
|
|
438
|
+
readonly hot: "#ff9f5a";
|
|
439
|
+
readonly off: "#8e97aa";
|
|
440
|
+
};
|
|
441
|
+
export declare function getAcLedColor(state: Pick<AcState, 'status' | 'mode'>): string;
|
|
442
|
+
export declare function isAcForm(value: unknown): value is AcForm;
|
|
443
|
+
//#endregion
|
|
444
|
+
//#region src/motion.d.ts
|
|
445
|
+
/**
|
|
446
|
+
* 动效 token:各框架视图层共用的时长与缓动曲线。
|
|
447
|
+
*
|
|
448
|
+
* 样式里统一通过 CSS 变量(`--acw-motion-*`)引用,
|
|
449
|
+
* 需要在 JS 里计时的地方(如 React 过渡组件)直接读取 `acMotion`。
|
|
450
|
+
*/
|
|
451
|
+
export declare const acMotion: {
|
|
452
|
+
readonly duration: {
|
|
453
|
+
/** 按下反馈 */
|
|
454
|
+
readonly instant: 90;
|
|
455
|
+
/** 悬停、指示灯、图标 */
|
|
456
|
+
readonly fast: 160;
|
|
457
|
+
/** 显示屏、数字切换、提示 */
|
|
458
|
+
readonly base: 240;
|
|
459
|
+
/** 导风板、出风淡入淡出 */
|
|
460
|
+
readonly slow: 420;
|
|
461
|
+
/** 出风气流单次循环 */
|
|
462
|
+
readonly flow: 1800;
|
|
463
|
+
/** 扫风:左右摆动一个来回 */
|
|
464
|
+
readonly swing: 5200;
|
|
465
|
+
};
|
|
466
|
+
readonly easing: {
|
|
467
|
+
/** 常规状态切换 */
|
|
468
|
+
readonly standard: "cubic-bezier(0.2, 0, 0, 1)";
|
|
469
|
+
/** 进入:快起慢停 */
|
|
470
|
+
readonly enter: "cubic-bezier(0, 0, 0, 1)";
|
|
471
|
+
/** 退出:慢起快走 */
|
|
472
|
+
readonly exit: "cubic-bezier(0.3, 0, 1, 1)";
|
|
473
|
+
/** 轻微回弹(按钮松开、图标弹出) */
|
|
474
|
+
readonly spring: "cubic-bezier(0.34, 1.56, 0.64, 1)";
|
|
475
|
+
};
|
|
476
|
+
};
|
|
477
|
+
export type AcMotionDuration = keyof typeof acMotion.duration;
|
|
478
|
+
export type AcMotionEasing = keyof typeof acMotion.easing;
|
|
479
|
+
/**
|
|
480
|
+
* `prefers-reduced-motion: reduce` 时使用的时长:
|
|
481
|
+
* 保留短促的淡入淡出(不涉及位移),去掉较长的过渡;循环动画由各样式表自行关闭。
|
|
482
|
+
*/
|
|
483
|
+
export declare const acReducedMotionDuration: Record<AcMotionDuration, number>;
|
|
484
|
+
export declare const acReducedMotionQuery = "(prefers-reduced-motion: reduce)";
|
|
485
|
+
/**
|
|
486
|
+
* 当前环境是否要求减少动效(SSR / 无 matchMedia 时返回 `false`)。
|
|
487
|
+
*/
|
|
488
|
+
export declare function prefersReducedMotion(): boolean;
|
|
489
|
+
/**
|
|
490
|
+
* 生成动效 CSS 变量声明(含 reduced-motion 覆盖),供 Shadow DOM 注入或样式表同步使用。
|
|
491
|
+
*
|
|
492
|
+
* @param selector 变量挂载的选择器,如 `:root`、`:host`
|
|
493
|
+
*/
|
|
494
|
+
export declare function renderAcMotionCssVars(selector?: string): string;
|
|
495
|
+
//#endregion
|
|
496
|
+
//#region src/press.d.ts
|
|
497
|
+
/** 长按连续调节的节奏(ms) */
|
|
498
|
+
export interface AcPressRepeatOptions {
|
|
499
|
+
/** 按住多久后开始连续触发 @default 500 */
|
|
500
|
+
delay?: number;
|
|
501
|
+
/** 连续触发的初始间隔 @default 200 */
|
|
502
|
+
interval?: number;
|
|
503
|
+
/** 加速后的最短间隔 @default 100 */
|
|
504
|
+
minInterval?: number;
|
|
505
|
+
/**
|
|
506
|
+
* 读取当前值(例如温度)。连续触发时值不再变化,说明到了上下限,就停下来,
|
|
507
|
+
* 不会在边界上一直「嘀」。
|
|
508
|
+
*/
|
|
509
|
+
value?: () => unknown;
|
|
510
|
+
}
|
|
511
|
+
/**
|
|
512
|
+
* 让按键支持长按连续触发,和真的遥控器一样:按下立即触发一次,按住一会儿后连续触发并逐渐加速,
|
|
513
|
+
* 松开、移出或取消时停止。键盘的 Enter / 空格仍走 `click`,每按一次触发一次。
|
|
514
|
+
*
|
|
515
|
+
* @param element 按键
|
|
516
|
+
* @param fire 每次触发时调用
|
|
517
|
+
* @param options 节奏与停止条件
|
|
518
|
+
* @returns 解除绑定的清理函数
|
|
519
|
+
*/
|
|
520
|
+
export declare function bindAcPressRepeat(element: HTMLElement, fire: () => void, options?: AcPressRepeatOptions): () => void;
|
|
521
|
+
//#endregion
|
|
118
522
|
//#region src/reducer.d.ts
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
523
|
+
/**
|
|
524
|
+
* Merge a partial state over the defaults and clamp its temperature.
|
|
525
|
+
*
|
|
526
|
+
* @param state - Partial or stored state
|
|
527
|
+
* @param limits - Device limits; omit to keep the default 16–31 °C range
|
|
528
|
+
*/
|
|
529
|
+
export declare function normalizeAcState(state: Partial<AcState> | undefined, limits?: AcLimits): AcState;
|
|
530
|
+
/**
|
|
531
|
+
* Clamp a temperature into range. When `limits` are given the value also
|
|
532
|
+
* snaps to the device step, measured from `limits.min`.
|
|
533
|
+
*
|
|
534
|
+
* @param temperature - Requested temperature in Celsius
|
|
535
|
+
* @param limits - Device limits; omit to clamp to 16–31 °C without snapping
|
|
536
|
+
*/
|
|
537
|
+
export declare function clampTemperature(temperature: number, limits?: AcLimits): number;
|
|
538
|
+
/**
|
|
539
|
+
* Apply an action to the state.
|
|
540
|
+
*
|
|
541
|
+
* @param state - Current state
|
|
542
|
+
* @param action - Action to apply
|
|
543
|
+
* @param limits - Device limits; increments use `limits.step`
|
|
544
|
+
*/
|
|
545
|
+
export declare function acReducer(state: AcState, action: AcAction, limits?: AcLimits): AcState;
|
|
546
|
+
/**
|
|
547
|
+
* 节能建议的短文案(显示在小纸条上)与补充说明。
|
|
548
|
+
*/
|
|
549
|
+
export declare function getEnergyTip(mode: AcState['mode'], temperature: number): {
|
|
550
|
+
message: string;
|
|
551
|
+
detail: string;
|
|
552
|
+
};
|
|
553
|
+
/**
|
|
554
|
+
* 视图如何呈现一条提示:
|
|
555
|
+
*
|
|
556
|
+
* - `note`:节能建议,以小纸条显示
|
|
557
|
+
* - `shake`:温度到了上下限,遥控器小屏抖一下
|
|
558
|
+
* - `announce`:设置变化,小屏已经显示,只给读屏播报
|
|
559
|
+
* - `skip`:同一模式、同一温度的建议已经提示过,不再重复
|
|
560
|
+
*/
|
|
561
|
+
export type AcNotificationPresentation = 'note' | 'shake' | 'announce' | 'skip';
|
|
562
|
+
/**
|
|
563
|
+
* 创建一个提示「呈现器」:每个视图实例一个,记住提示过的节能建议,避免重复打扰。
|
|
564
|
+
*/
|
|
565
|
+
export declare function createAcNotificationPresenter(): (notification: AcNotification, state: Pick<AcState, 'mode' | 'temperature'>) => AcNotificationPresentation;
|
|
566
|
+
export declare function getRecommendedTemperatureMessage(mode: AcState['mode'], temperature: number): string;
|
|
567
|
+
export declare function getSoundModeMessage(sound: AcState['sound']): string;
|
|
568
|
+
export declare function getFanSpeedMessage(fan: AcFanSpeed): string;
|
|
569
|
+
export declare function getSwingMessage(swing: AcState['swing']): string;
|
|
570
|
+
/**
|
|
571
|
+
* Visual tone for a state: `idle` when off, otherwise `cool` or `heat`.
|
|
572
|
+
*
|
|
573
|
+
* @param state - Current state
|
|
574
|
+
*/
|
|
575
|
+
export declare function acTone(state: Pick<AcState, 'status' | 'mode'>): AcTone;
|
|
576
|
+
export declare function getAcActionNotification(previousState: AcState, nextState: AcState, action: AcAction, limits?: AcLimits): AcNotification | undefined;
|
|
124
577
|
//#endregion
|
|
125
578
|
//#region src/storage.d.ts
|
|
126
|
-
declare function readAcState(storage: AcStorage | null | undefined, storageKey: string): AcState;
|
|
127
|
-
declare function writeAcState(storage: AcStorage | null | undefined, storageKey: string, state: AcState): void;
|
|
128
|
-
declare function createMemoryStorage(initialValue?: Record<string, string>): AcStorage;
|
|
129
|
-
declare function getBrowserStorage(): AcStorage | null;
|
|
579
|
+
export declare function readAcState(storage: AcStorage | null | undefined, storageKey: string): AcState;
|
|
580
|
+
export declare function writeAcState(storage: AcStorage | null | undefined, storageKey: string, state: AcState): void;
|
|
581
|
+
export declare function createMemoryStorage(initialValue?: Record<string, string>): AcStorage;
|
|
582
|
+
export declare function getBrowserStorage(): AcStorage | null;
|
|
130
583
|
//#endregion
|
|
131
584
|
//#region src/store.d.ts
|
|
132
|
-
declare function createAirConditionerStore(options?: CreateAirConditionerStoreOptions): AirConditionerStore;
|
|
585
|
+
export declare function createAirConditionerStore(options?: CreateAirConditionerStoreOptions): AirConditionerStore;
|
|
586
|
+
//#endregion
|
|
587
|
+
//#region src/thermal/types.d.ts
|
|
588
|
+
/**
|
|
589
|
+
* Heat levels shared by the browser Compute Pressure API and macOS
|
|
590
|
+
* `ProcessInfo.ThermalState`, so web and native hosts speak the same language.
|
|
591
|
+
*/
|
|
592
|
+
export type HeatLevel = 'nominal' | 'fair' | 'serious' | 'critical';
|
|
593
|
+
export interface HeatReading {
|
|
594
|
+
level: HeatLevel;
|
|
595
|
+
/** Real temperature, only when the source can measure one */
|
|
596
|
+
celsius?: number;
|
|
597
|
+
/** Identifier of the source that produced the reading */
|
|
598
|
+
source: string;
|
|
599
|
+
/** Epoch milliseconds */
|
|
600
|
+
at: number;
|
|
601
|
+
}
|
|
602
|
+
/**
|
|
603
|
+
* Something that reports how hot a computer is.
|
|
604
|
+
*/
|
|
605
|
+
export interface HeatSource {
|
|
606
|
+
id: string;
|
|
607
|
+
/** Whether the current environment can provide readings */
|
|
608
|
+
isSupported: () => boolean;
|
|
609
|
+
/**
|
|
610
|
+
* Start delivering readings.
|
|
611
|
+
*
|
|
612
|
+
* @returns A function that stops the source
|
|
613
|
+
*/
|
|
614
|
+
start: (listener: (reading: HeatReading) => void) => () => void;
|
|
615
|
+
}
|
|
616
|
+
/**
|
|
617
|
+
* What the virtual air conditioner should do for a heat level.
|
|
618
|
+
*/
|
|
619
|
+
export interface CoolingPlan {
|
|
620
|
+
status: true;
|
|
621
|
+
mode: 'cold';
|
|
622
|
+
temperature: number;
|
|
623
|
+
/** 0–1, drives airflow intensity */
|
|
624
|
+
airflow: number;
|
|
625
|
+
}
|
|
626
|
+
/**
|
|
627
|
+
* A native host's reading of the computer it runs on, seen as the room the
|
|
628
|
+
* air conditioner cools. Same JSON as `RoomReading` in the Swift CuteACCore
|
|
629
|
+
* package; Yun Home passes it to plugins granted `sensor:thermal`.
|
|
630
|
+
*/
|
|
631
|
+
export interface RoomReading {
|
|
632
|
+
/** CPU/SoC temperature, rounded; absent when no sensor is readable */
|
|
633
|
+
celsius?: number;
|
|
634
|
+
thermalState: HeatLevel;
|
|
635
|
+
/** Fastest fan, rounded to 100 RPM; absent on fanless computers */
|
|
636
|
+
fanRPM?: number;
|
|
637
|
+
/** Airflow strength 1–3, from fan load or the heat level */
|
|
638
|
+
windLevel: number;
|
|
639
|
+
}
|
|
640
|
+
//#endregion
|
|
641
|
+
//#region src/thermal/levels.d.ts
|
|
642
|
+
export declare const heatLevels: readonly HeatLevel[];
|
|
643
|
+
/** Default Celsius thresholds for fair, serious and critical. */
|
|
644
|
+
export declare const defaultHeatThresholds: readonly [number, number, number];
|
|
645
|
+
/**
|
|
646
|
+
* @param level - A heat level
|
|
647
|
+
* @returns Its rank from 0 (nominal) to 3 (critical)
|
|
648
|
+
*/
|
|
649
|
+
export declare function heatLevelRank(level: HeatLevel): number;
|
|
650
|
+
export declare function isHeatLevel(value: unknown): value is HeatLevel;
|
|
651
|
+
/**
|
|
652
|
+
* Convert a temperature to a heat level. With a previous level, the value
|
|
653
|
+
* must fall `hysteresis` degrees below a threshold before dropping a level,
|
|
654
|
+
* which keeps readings near a threshold from flickering.
|
|
655
|
+
*
|
|
656
|
+
* @param celsius - Measured temperature
|
|
657
|
+
* @param thresholds - Lower bounds for fair, serious and critical
|
|
658
|
+
* @param previous - Level from the previous reading
|
|
659
|
+
* @param hysteresis - Degrees required below a threshold to step down
|
|
660
|
+
*/
|
|
661
|
+
export declare function celsiusToHeatLevel(celsius: number, thresholds?: readonly [number, number, number], previous?: HeatLevel, hysteresis?: number): HeatLevel;
|
|
662
|
+
/**
|
|
663
|
+
* Create a filter that raises the level immediately but only lowers it after
|
|
664
|
+
* lower readings persist for `dwellMs`, measured with `reading.at`.
|
|
665
|
+
*
|
|
666
|
+
* @param options - Governor options
|
|
667
|
+
* @param options.dwellMs - Time a lower level must persist; defaults to 30 seconds
|
|
668
|
+
* @returns A function that maps each reading to the settled level
|
|
669
|
+
*/
|
|
670
|
+
export declare function createHeatGovernor(options?: {
|
|
671
|
+
dwellMs?: number;
|
|
672
|
+
}): (reading: HeatReading) => HeatLevel;
|
|
673
|
+
//#endregion
|
|
674
|
+
//#region src/thermal/plan.d.ts
|
|
675
|
+
/**
|
|
676
|
+
* Decide how the virtual air conditioner should respond to a heat level.
|
|
677
|
+
*
|
|
678
|
+
* @param level - Settled heat level
|
|
679
|
+
* @param limits - Device limits used to clamp the target temperature
|
|
680
|
+
* @returns A cooling plan, or `null` at `nominal` so the user keeps control
|
|
681
|
+
*/
|
|
682
|
+
export declare function planCooling(level: HeatLevel, limits?: AcLimits): CoolingPlan | null;
|
|
683
|
+
//#endregion
|
|
684
|
+
//#region src/thermal/pressure.d.ts
|
|
685
|
+
export interface ComputePressureSourceOptions {
|
|
686
|
+
/** Requested sample interval; browsers may deliver less often */
|
|
687
|
+
sampleIntervalMs?: number;
|
|
688
|
+
/** Called when observing fails, e.g. blocked by permissions policy */
|
|
689
|
+
onError?: (error: unknown) => void;
|
|
690
|
+
}
|
|
691
|
+
/**
|
|
692
|
+
* Heat source backed by the browser Compute Pressure API. It reports CPU
|
|
693
|
+
* load levels, not temperatures; browsers expose no CPU temperature.
|
|
694
|
+
*
|
|
695
|
+
* Supported in Chromium-based browsers on secure origins. The API is only
|
|
696
|
+
* touched when the source is started.
|
|
697
|
+
*
|
|
698
|
+
* @param options - Sampling and error handling options
|
|
699
|
+
*/
|
|
700
|
+
export declare function createComputePressureSource(options?: ComputePressureSourceOptions): HeatSource;
|
|
701
|
+
//#endregion
|
|
702
|
+
//#region src/icons.d.ts
|
|
703
|
+
/**
|
|
704
|
+
* 遥控器按钮与提示图标(24 × 24 viewBox 的 SVG path),全部来自 Material Design
|
|
705
|
+
* Icons,和站点通过 UnoCSS presetIcons 使用的 i-mdi-* 是同一套。
|
|
706
|
+
*/
|
|
707
|
+
export declare const acIconPaths: {
|
|
708
|
+
/** mdi:snowflake */
|
|
709
|
+
readonly cold: "m20.79 13.95l-2.33.62l-2-1.13v-2.88l2-1.13l2.33.62l.52-1.93l-1.77-.47l.46-1.77l-1.93-.52l-.62 2.33l-2 1.13L13 7.38V5.12l1.71-1.71L13.29 2L12 3.29L10.71 2L9.29 3.41L11 5.12v2.26L8.5 8.82l-2-1.13l-.58-2.33L4 5.88l.47 1.77l-1.77.47l.52 1.93l2.33-.62l2 1.13v2.89l-2 1.13l-2.33-.62l-.52 1.93l1.77.47L4 18.12l1.93.52l.62-2.33l2-1.13L11 16.62v2.26l-1.71 1.71L10.71 22L12 20.71L13.29 22l1.41-1.41l-1.7-1.71v-2.26l2.5-1.45l2 1.13l.62 2.33l1.88-.51l-.47-1.77l1.77-.47zM9.5 10.56L12 9.11l2.5 1.45v2.88L12 14.89l-2.5-1.45z";
|
|
710
|
+
/** mdi:white-balance-sunny */
|
|
711
|
+
readonly hot: "m3.55 19.09l1.41 1.41l1.8-1.79l-1.42-1.42M12 6c-3.31 0-6 2.69-6 6s2.69 6 6 6s6-2.69 6-6c0-3.32-2.69-6-6-6m8 7h3v-2h-3m-2.76 7.71l1.8 1.79l1.41-1.41l-1.79-1.8M20.45 5l-1.41-1.4l-1.8 1.79l1.42 1.42M13 1h-2v3h2M6.76 5.39L4.96 3.6L3.55 5l1.79 1.81zM1 13h3v-2H1m12 9h-2v3h2";
|
|
712
|
+
/** mdi:power */
|
|
713
|
+
readonly power: "m16.56 5.44l-1.45 1.45A5.97 5.97 0 0 1 18 12a6 6 0 0 1-6 6a6 6 0 0 1-6-6c0-2.17 1.16-4.06 2.88-5.12L7.44 5.44A7.96 7.96 0 0 0 4 12a8 8 0 0 0 8 8a8 8 0 0 0 8-8c0-2.72-1.36-5.12-3.44-6.56M13 3h-2v10h2";
|
|
714
|
+
/** mdi:plus */
|
|
715
|
+
readonly plus: "M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6z";
|
|
716
|
+
/** mdi:minus */
|
|
717
|
+
readonly minus: "M19 13H5v-2h14z";
|
|
718
|
+
/** mdi:menu-up */
|
|
719
|
+
readonly increase: "m7 15l5-5l5 5z";
|
|
720
|
+
/** mdi:menu-down */
|
|
721
|
+
readonly decrease: "m7 10l5 5l5-5z";
|
|
722
|
+
/** mdi:fan */
|
|
723
|
+
readonly fan: "M12 11a1 1 0 0 0-1 1a1 1 0 0 0 1 1a1 1 0 0 0 1-1a1 1 0 0 0-1-1m.5-9c4.5 0 4.61 3.57 2.25 4.75c-.99.49-1.43 1.54-1.62 2.47c.48.2.9.51 1.22.91c3.7-2 7.68-1.21 7.68 2.37c0 4.5-3.57 4.6-4.75 2.23c-.5-.99-1.56-1.43-2.49-1.62c-.2.48-.51.89-.91 1.23c1.99 3.69 1.2 7.66-2.38 7.66c-4.5 0-4.59-3.58-2.23-4.76c.98-.49 1.42-1.53 1.62-2.45c-.49-.2-.92-.52-1.24-.92C5.96 15.85 2 15.07 2 11.5C2 7 5.56 6.89 6.74 9.26c.5.99 1.55 1.42 2.48 1.61c.19-.48.51-.9.92-1.22C8.15 5.96 8.94 2 12.5 2";
|
|
724
|
+
/** mdi:arrow-oscillating */
|
|
725
|
+
readonly swing: "M6 14h3l-4 4l-4-4h3c0-2.7 1.7-7.4 7-7.9v2c-3.4.5-5 3.8-5 5.9m14 0c0-2.7-1.7-7.4-7-7.9v2c3.4.6 5 3.8 5 5.9h-3l4 4l4-4z";
|
|
726
|
+
/** mdi:volume-high */
|
|
727
|
+
readonly soundNormal: "M14 3.23v2.06c2.89.86 5 3.54 5 6.71s-2.11 5.84-5 6.7v2.07c4-.91 7-4.49 7-8.77s-3-7.86-7-8.77M16.5 12c0-1.77-1-3.29-2.5-4.03V16c1.5-.71 2.5-2.24 2.5-4M3 9v6h4l5 5V4L7 9z";
|
|
728
|
+
/** mdi:weather-night */
|
|
729
|
+
readonly soundSleep: "m17.75 4.09l-2.53 1.94l.91 3.06l-2.63-1.81l-2.63 1.81l.91-3.06l-2.53-1.94L12.44 4l1.06-3l1.06 3zm3.5 6.91l-1.64 1.25l.59 1.98l-1.7-1.17l-1.7 1.17l.59-1.98L15.75 11l2.06-.05L18.5 9l.69 1.95zm-2.28 4.95c.83-.08 1.72 1.1 1.19 1.85c-.32.45-.66.87-1.08 1.27C15.17 23 8.84 23 4.94 19.07c-3.91-3.9-3.91-10.24 0-14.14c.4-.4.82-.76 1.27-1.08c.75-.53 1.93.36 1.85 1.19c-.27 2.86.69 5.83 2.89 8.02a9.96 9.96 0 0 0 8.02 2.89m-1.64 2.02a12.08 12.08 0 0 1-7.8-3.47c-2.17-2.19-3.33-5-3.49-7.82c-2.81 3.14-2.7 7.96.31 10.98c3.02 3.01 7.84 3.12 10.98.31";
|
|
730
|
+
/** mdi:volume-off */
|
|
731
|
+
readonly soundMute: "M12 4L9.91 6.09L12 8.18M4.27 3L3 4.27L7.73 9H3v6h4l5 5v-6.73l4.25 4.26c-.67.51-1.42.93-2.25 1.17v2.07c1.38-.32 2.63-.95 3.68-1.81L19.73 21L21 19.73l-9-9M19 12c0 .94-.2 1.82-.54 2.64l1.51 1.51A8.9 8.9 0 0 0 21 12c0-4.28-3-7.86-7-8.77v2.06c2.89.86 5 3.54 5 6.71m-2.5 0c0-1.77-1-3.29-2.5-4.03v2.21l2.45 2.45c.05-.2.05-.42.05-.63";
|
|
732
|
+
/** mdi:leaf */
|
|
733
|
+
readonly leaf: "M17 8C8 10 5.9 16.17 3.82 21.34l1.89.66l.95-2.3c.48.17.98.3 1.34.3C19 20 22 3 22 3c-1 2-8 2.25-13 3.25S2 11.5 2 13.5s1.75 3.75 1.75 3.75C7 8 17 8 17 8";
|
|
734
|
+
};
|
|
735
|
+
//#endregion
|
|
736
|
+
//#region src/ui.d.ts
|
|
737
|
+
export type AcIconName = keyof typeof acIconPaths;
|
|
738
|
+
/**
|
|
739
|
+
* 声音键在各声音模式下显示的图标。
|
|
740
|
+
*/
|
|
741
|
+
export declare const acSoundIcons: Record<AcSoundMode, AcIconName>;
|
|
742
|
+
/**
|
|
743
|
+
* 遥控器按键发出的指令:`RemoteControl` 的 `command` 事件 / `onCommand` 参数。
|
|
744
|
+
* 模式键发出目标模式(`cold` / `hot`)。
|
|
745
|
+
*/
|
|
746
|
+
export type AcRemoteCommand = 'power' | AcMode | 'increase' | 'decrease' | 'swing' | 'sound' | 'fan';
|
|
747
|
+
/**
|
|
748
|
+
* 遥控器小屏的读屏文字与各按键的悬停提示,保证各框架文案一致。
|
|
749
|
+
*/
|
|
750
|
+
export declare function getAcRemoteText(state: AcState): {
|
|
751
|
+
display: string;
|
|
752
|
+
power: string;
|
|
753
|
+
mode: Record<AcMode, string>;
|
|
754
|
+
fan: string;
|
|
755
|
+
swing: string;
|
|
756
|
+
sound: string;
|
|
757
|
+
};
|
|
758
|
+
/**
|
|
759
|
+
* 一行「黑点 / 白点」文字占位,模拟能效标签上的细密文字。
|
|
760
|
+
*/
|
|
761
|
+
export interface AcDotRow {
|
|
762
|
+
num: number;
|
|
763
|
+
/** 点的直径(px) */
|
|
764
|
+
size: number;
|
|
765
|
+
/** 水平外边距(px) */
|
|
766
|
+
mx: number;
|
|
767
|
+
/** 垂直外边距(px) */
|
|
768
|
+
my: number;
|
|
769
|
+
color: string;
|
|
770
|
+
}
|
|
771
|
+
/**
|
|
772
|
+
* 能效标签的点阵与等级条布局:蓝白背景的「中国能效标识」,带能效信息码
|
|
773
|
+
* (二维码),样式依据《房间空气调节器能源效率标识实施规则》(CEL 010—2019)。
|
|
774
|
+
*
|
|
775
|
+
* 等级按现行 GB 21455-2019 分 5 级,1 级最高。GB 21455 的修订版征求意见稿
|
|
776
|
+
* (2026 年 5 月)拟改为 3 级、以全年动态能源消耗效率(DAPF)分级;正式发布并
|
|
777
|
+
* 实施后,再更新 `grades`、`standard` 与 `levels`。
|
|
778
|
+
*
|
|
779
|
+
* - `top`:标识名称(白点),右侧是能效信息码
|
|
780
|
+
* - 等级区:首行是 1 级绿色条和指示箭头,`levels` 是 2–5 级
|
|
781
|
+
* - `detail`:生产者、型号、APF 等参数(黑点)
|
|
782
|
+
* - `footer`:依据的国家标准编号(白点)
|
|
783
|
+
*/
|
|
784
|
+
export declare const acEnergyLabel: {
|
|
785
|
+
/** 标签所示的能效等级:云空调是 1 级 */
|
|
786
|
+
grade: number;
|
|
787
|
+
/** 等级总数 */
|
|
788
|
+
grades: number;
|
|
789
|
+
/** 依据的能源效率强制性国家标准 */
|
|
790
|
+
standard: string;
|
|
791
|
+
top: AcDotRow[];
|
|
792
|
+
detail: AcDotRow[];
|
|
793
|
+
footer: AcDotRow;
|
|
794
|
+
levels: {
|
|
795
|
+
background: string;
|
|
796
|
+
width: string;
|
|
797
|
+
}[];
|
|
798
|
+
};
|
|
799
|
+
/**
|
|
800
|
+
* 能效标签的读屏文字。
|
|
801
|
+
*/
|
|
802
|
+
export declare function getAcEnergyLabelText(): string;
|
|
133
803
|
//#endregion
|
|
134
|
-
export {
|
|
804
|
+
export {};
|