pixel-daylight-switch-gsvegetable 1.3.1 → 2.1.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.
Files changed (5) hide show
  1. package/README.ja.md +207 -0
  2. package/README.md +134 -360
  3. package/README.zh-CN.md +207 -0
  4. package/app.js +664 -267
  5. package/package.json +19 -4
package/README.md CHANGED
@@ -1,433 +1,207 @@
1
1
  # Pixel Daylight Switch
2
2
 
3
- 一个可以拖动的像素昼夜开关组件。拖动玻璃滑块,场景会从白天流动到夜晚;像素小人生活在开关内部,随着时间变化活动。
3
+ [![Quality checks](https://github.com/GSvegetable/pixel-daylight-switch/actions/workflows/ci.yml/badge.svg)](https://github.com/GSvegetable/pixel-daylight-switch/actions/workflows/ci.yml)
4
+ [![npm version](https://img.shields.io/npm/v/pixel-daylight-switch-gsvegetable)](https://www.npmjs.com/package/pixel-daylight-switch-gsvegetable)
5
+ [![License: Unlicense](https://img.shields.io/badge/license-Unlicense-blue.svg)](LICENSE)
4
6
 
5
- <p align="center">
6
- <a href="https://gsvegetable.github.io/pixel-daylight-switch/">在线演示</a> ·
7
- <a href="https://gsvegetable.github.io/pixel-daylight-switch/playground.html">参数实验室 Playground</a> ·
8
- <a href="https://github.com/GSvegetable/pixel-daylight-switch/releases">版本发布</a>
9
- </p>
7
+ **Languages:** [English](README.md) · [简体中文](README.zh-CN.md) · [日本語](README.ja.md)
10
8
 
11
- <p align="center">
12
- <img src="https://github.com/user-attachments/assets/f7f248a5-c39c-432c-92f6-73237abdfe6b" width="49%" alt="白天模式" />
13
- <img src="https://github.com/user-attachments/assets/b2e24e65-a378-4ac6-be7b-efd3070e4da8" width="49%" alt="夜晚模式" />
14
- </p>
9
+ ![Five animated pixel-world scenes](assets/scene-gallery.png)
15
10
 
16
- **中文文档在前,English documentation is below.** [跳转到 English](#english)
11
+ *A tiny animated world, held inside a refractive glass switch.*
17
12
 
18
- ## 目录
13
+ Pixel Daylight Switch is a draggable day/night UI component. Move its glass control to travel between day, dusk and night while a miniature pixel-art world changes inside the lens. It uses vanilla JavaScript, WebGL2 and a Canvas 2D fallback, with no third-party runtime dependency.
19
14
 
20
- - [快速开始](#快速开始)
21
- - [参数实验室](#参数实验室-playground)
22
- - [HTML 参数配置](#html-参数配置)
23
- - [交互与页面主题](#交互与页面主题)
24
- - [自定义外观](#自定义外观)
25
- - [动态挂载](#动态挂载)
26
- - [兼容性与本地开发](#兼容性与本地开发)
27
- - [更新记录](#更新记录)
28
- - [许可证](#许可证)
15
+ **[Open the live demo](https://gsvegetable.github.io/pixel-daylight-switch/)** · **[Launch the parameter lab](https://gsvegetable.github.io/pixel-daylight-switch/playground.html)** · **[Install from npm](https://www.npmjs.com/package/pixel-daylight-switch-gsvegetable)**
29
16
 
30
- ## 快速开始
17
+ ## Start here
31
18
 
32
- 无需 npm、依赖安装或构建步骤。把下面两行放进 HTML:
19
+ | Goal | Direct link |
20
+ | --- | --- |
21
+ | Experience the switch | [Live demo](https://gsvegetable.github.io/pixel-daylight-switch/) |
22
+ | Customize scenes and visual behavior | [Interactive parameter lab](https://gsvegetable.github.io/pixel-daylight-switch/playground.html) |
23
+ | Inspect the component | [Preview page](https://gsvegetable.github.io/pixel-daylight-switch/preview.html) |
24
+ | Add it to a website with one script | [Embed loader source](embed.js) |
25
+ | Use it in a JavaScript project | [npm package](https://www.npmjs.com/package/pixel-daylight-switch-gsvegetable) |
26
+ | Read implementation details | [Runtime](app.js) · [Styles](style.css) |
27
+ | Download mobile builds | [Build notes and limitations](builds/README.md) · [GitHub Actions artifacts](https://github.com/GSvegetable/pixel-daylight-switch/actions/workflows/mobile-build.yml) |
28
+ | Check tests | [CI workflow](https://github.com/GSvegetable/pixel-daylight-switch/actions/workflows/ci.yml) |
29
+ | Review changes | [Changelog](CHANGELOG.md) |
30
+ | Report a bug | [Issue tracker](https://github.com/GSvegetable/pixel-daylight-switch/issues) |
33
31
 
34
- ```html
35
- <div data-ld-part="toggle-daylight"></div>
36
- <script src="https://gsvegetable.github.io/pixel-daylight-switch/app.js"></script>
37
- ```
38
-
39
- 脚本会自动创建组件内部的 Canvas、交互区域和辅助无障碍元素。组件宽度跟随父容器,高度保持固定比例。一个页面可以放置多个独立实例。
40
-
41
- 如果你需要离线部署,也可以直接下载仓库中的 `app.js` 并自行托管。
42
-
43
- ### 使用 NPM
44
-
45
- 适合 Vite、Webpack、Rspack 等构建项目:
46
-
47
- ```bash
48
- npm install pixel-daylight-switch-gsvegetable
49
- ```
50
-
51
- **原生 JavaScript / ESM**
52
-
53
- ```js
54
- import PixelDaylightSwitch from 'pixel-daylight-switch-gsvegetable';
55
-
56
- const root = document.querySelector('[data-ld-part="toggle-daylight"]');
57
- PixelDaylightSwitch.mount(root);
58
-
59
- // 页面卸载或组件移除前
60
- PixelDaylightSwitch.unmount(root);
61
- ```
62
-
63
- **React**
64
-
65
- ```jsx
66
- import { useEffect, useRef } from 'react';
67
- import PixelDaylightSwitch from 'pixel-daylight-switch-gsvegetable';
68
-
69
- export function DaylightSwitch() {
70
- const rootRef = useRef(null);
71
-
72
- useEffect(() => {
73
- const root = rootRef.current;
74
- PixelDaylightSwitch.mount(root);
75
- return () => PixelDaylightSwitch.unmount(root);
76
- }, []);
77
-
78
- return <div ref={rootRef} data-ld-part="toggle-daylight" />;
79
- }
80
- ```
81
-
82
- **Vue 3**
83
-
84
- ```vue
85
- <script setup>
86
- import { ref, onMounted, onBeforeUnmount } from 'vue';
87
- import PixelDaylightSwitch from 'pixel-daylight-switch-gsvegetable';
88
-
89
- const root = ref(null);
90
- onMounted(() => PixelDaylightSwitch.mount(root.value));
91
- onBeforeUnmount(() => PixelDaylightSwitch.unmount(root.value));
92
- </script>
32
+ ## Features
93
33
 
94
- <template>
95
- <div ref="root" data-ld-part="toggle-daylight"></div>
96
- </template>
97
- ```
98
-
99
- NPM 入口同时提供 CommonJS 与 ESM。导入在服务端渲染环境中不会访问 DOM;实际挂载应在浏览器端执行。
100
-
101
- ## 参数实验室 Playground
102
-
103
- **不想手动试参数?打开 [Pixel Daylight Playground](https://gsvegetable.github.io/pixel-daylight-switch/playground.html)。**
104
-
105
- - 左侧实时预览组件,直接拖动开关测试手感。
106
- - 右侧按「运动反馈、玻璃光学、世界节奏、场景环境」四组调整参数。
107
- - 使用场景预设快速切换乡村小屋、日本街道、现代公寓、海边灯塔和山间木屋。
108
- - 调整参数时只更新数值;点击「应用参数」后才刷新独立预览,避免拖动滑块时反复重建 WebGL。
109
- - 预览运行在独立页面中,与控制面板隔离,减少渲染状态互相干扰。
110
-
111
- Playground 是独立页面,不会改变组件本身的零依赖接入方式。
112
-
113
- ## HTML 参数配置
114
-
115
- 所有参数都写在组件容器的 `data-*` 属性上。每个实例可以使用不同配置。参数可省略;缺失、空值或无效数值会回退到默认值。
34
+ - Five scenes: countryside, Japanese street, modern apartment, seaside lighthouse and mountain cabin.
35
+ - Refractive glass rendering with WebGL2 and a Canvas 2D fallback.
36
+ - Continuous drag interaction, tap/click switching and keyboard operation.
37
+ - Configurable motion, inertia, bounce, refraction, glass details, world speed, weather and scene.
38
+ - Multiple independent instances on one page.
39
+ - Switch semantics, live status announcements and `prefers-reduced-motion` support.
40
+ - `mount()` and `unmount()` lifecycle methods for dynamic applications.
41
+ - Rendering pauses when the document is hidden or the component is outside the viewport.
116
42
 
117
- ### 全部参数
43
+ ## Quick start — browser, no build step
118
44
 
119
- | HTML 属性 | 默认值 | 作用 |
120
- | --- | ---: | --- |
121
- | `data-speed` | `9.5` | 开关运动的基础速度 |
122
- | `data-refraction` | `1.24` | 玻璃镜片的折射强度 |
123
- | `data-bezel` | `0.046` | 外框厚度系数,相对于开关高度 |
124
- | `data-start-night` | `false` | 设置为 `true` 时,初始化为夜晚状态 |
125
- | `data-friction` | `0.6` | 松手后的惯性阻尼,范围 `0.1–0.9`;越小越容易继续滑动 |
126
- | `data-bounce` | `3.2` | 滑块到达边缘时的回弹力度;越大弹性反馈越明显 |
127
- | `data-dispersion` | `0.05` | 玻璃边缘 RGB 色散强度,范围 `0–0.25`;设为 `0` 可关闭彩虹边 |
128
- | `data-shine` | `0.44` | 白天玻璃表面高光强度,范围 `0–1.5` |
129
- | `data-time-speed` | `1.0` | 像素世界时间倍率,范围 `0–8`;`0` 冻结世界动态,`2` 为两倍速度 |
130
- | `data-weather` | `default` | 天气预设:`default` 或 `snow`;雪天会出现飘落的像素雪花 |
131
- | `data-scene` | `countryside` | 世界场景:`countryside`、`japanese-street`、`apartment`、`seaside` 或 `mountain-cabin` |
132
-
133
- ### 完整配置示例
45
+ Place a mount point on your page and load the runtime:
134
46
 
135
47
  ```html
136
- <div
137
- data-ld-part="toggle-daylight"
138
- data-speed="12"
139
- data-refraction="1.5"
140
- data-bezel="0.05"
141
- data-start-night="true"
142
- data-friction="0.45"
143
- data-bounce="4.2"
144
- data-dispersion="0.12"
145
- data-shine="0.6"
146
- data-time-speed="1.5"
147
- data-weather="snow"
148
- data-scene="mountain-cabin"
149
- ></div>
48
+ <div data-ld-part="toggle-daylight" style="width: min(100%, 800px);">
49
+ </div>
150
50
 
151
- <script src="https://gsvegetable.github.io/pixel-daylight-switch/app.js"></script>
51
+ <script defer src="https://gsvegetable.github.io/pixel-daylight-switch/app.js"></script>
152
52
  ```
153
53
 
154
- ### 参数分组与调校建议
155
-
156
- **运动反馈 / Motion**
157
-
158
- - `data-speed` 控制开关运动的基础速度。
159
- - `data-friction` 控制松手后的惯性衰减。较小的值更滑,较大的值更黏。
160
- - `data-bounce` 控制滑块触及边缘时的回弹力度。
161
-
162
- **玻璃光学 / Glass Optics**
54
+ The browser runtime finds the mount point and creates the component UI. The host element needs a usable width.
163
55
 
164
- - `data-refraction` 控制镜片折射强度。
165
- - `data-bezel` 控制镜片外框厚度。
166
- - `data-dispersion` 控制边缘色散。数值越大,彩虹色边缘越明显。
167
- - `data-shine` 控制白天镜片高光。
56
+ ### Embed with one script
168
57
 
169
- **世界节奏 / World Rhythm**
170
-
171
- - `data-time-speed="0"` 可以冻结世界时间和动态。
172
- - `data-time-speed="2"` 会让世界模拟以两倍速度运行。
173
- - `data-weather="snow"` 开启飘雪;省略或填写其他值时使用默认天气。
174
- - `data-scene` 选择完整的像素环境:乡村、日本街道、公寓室内、海边或山间木屋。
175
- - `data-start-night="true"` 让组件从夜晚开始。
176
-
177
- ### 默认值与兼容性
178
-
179
- 场景、天气和初始昼夜状态归入「场景环境」;它们不是连续数值,因此使用选择器与开关,而不是滑动条。
180
-
181
- 如果只写:
58
+ For a self-inserting embed, add this script where you want the component to appear:
182
59
 
183
60
  ```html
184
- <div data-ld-part="toggle-daylight"></div>
61
+ <script src="https://gsvegetable.github.io/pixel-daylight-switch/embed.js"></script>
185
62
  ```
186
63
 
187
- 组件会使用默认参数。v1.2.0 的新增参数默认值与 v1.1.0 的原有参数保持一致,未配置新属性时不会主动改变原有视觉设定。数值参数会进行数字转换、有效性检查和范围限制;未知天气值回退到 `default`。
188
-
189
- ## 交互与页面主题
190
-
191
- - **拖动**:拖动滑块,让世界从白天经过黄昏进入夜晚。
192
- - **点击**:点击开关,在白天和夜晚之间切换。
193
- - **键盘**:聚焦开关后使用方向键调整。
194
- - **无障碍**:使用 switch 语义,并尊重系统的减少动态效果偏好。
195
-
196
- 组件会把当前夜晚程度写入根元素的 CSS 自定义属性 `--night`:
197
-
198
- - `0` 表示白天;
199
- - `1` 表示夜晚;
200
- - 中间值表示昼夜过渡。
64
+ The loader inserts its own container, stylesheet and runtime. It currently creates one default instance with a fixed maximum display size; use the mount-point approach above when you need precise layout or custom attributes.
201
65
 
202
- 例如,让页面背景跟随开关变化:
203
-
204
- ```css
205
- body {
206
- background: color-mix(
207
- in srgb,
208
- #f5ecd9,
209
- #1b2146 calc(var(--night, 0) * 100%)
210
- );
211
- }
212
- ```
213
-
214
- 如果只需要在昼夜状态变化时执行逻辑,可以监听事件:
215
-
216
- ```js
217
- document.addEventListener('daylight:change', (event) => {
218
- document.documentElement.classList.toggle('dark', event.detail.night);
219
- });
220
- ```
221
-
222
- ## 自定义外观
223
-
224
- 在组件容器上覆盖 CSS 自定义属性:
225
-
226
- ```css
227
- [data-ld-part="toggle-daylight"] {
228
- --ld-bg: #f5ecd9;
229
- --ld-surface: #8c9a62;
230
- --ld-fg: #1b2146;
231
- --ld-muted: #7f97b3;
232
- --ld-accent: #efa02c;
233
- }
234
- ```
235
-
236
- | CSS 变量 | 默认值 | 用途 |
237
- | --- | --- | --- |
238
- | `--ld-bg` | `#f5ecd9` | 背景色 |
239
- | `--ld-surface` | `#8c9a62` | 表面与场景色 |
240
- | `--ld-fg` | `#1b2146` | 前景色 |
241
- | `--ld-muted` | `#7f97b3` | 次要颜色 |
242
- | `--ld-accent` | `#efa02c` | 强调色 |
243
-
244
- ## 动态挂载
245
-
246
- 如果组件容器是在页面加载后动态创建的,可以手动挂载:
247
-
248
- ```js
249
- const destroy = PixelDaylightSwitch.mount(element);
250
-
251
- // 不再需要时:
252
- PixelDaylightSwitch.unmount(element);
253
- ```
254
-
255
- ## 兼容性与本地开发
256
-
257
- - 优先使用 WebGL2 渲染玻璃效果;不可用时回退到 Canvas 2D。
258
- - 支持减少动态效果偏好。
259
- - 页面不可见或组件离开视口时会暂停不必要的绘制。
260
- - 不需要构建工具。
261
-
262
- 本地运行:
263
-
264
- ```bash
265
- git clone https://github.com/GSvegetable/pixel-daylight-switch.git
266
- cd pixel-daylight-switch
267
- ```
268
-
269
- 使用浏览器打开 `index.html` 即可。主要文件:
270
-
271
- - `app.js`:组件实现。
272
- - `index.html`:基础演示页面。
273
- - `playground.html`:参数实验室与场景切换。
274
-
275
- ## 更新记录
276
-
277
- ### v1.3.0
278
-
279
- - 新增四个独立像素环境:日本街道、现代公寓、海边灯塔和山间木屋。
280
- - Playground 新增真实场景选择,可与玻璃参数、昼夜和天气效果组合。
281
-
282
- ### v1.2.0
283
-
284
- 本次版本包含两轮未发布的更新:
285
-
286
- - 新增物理参数:惯性阻尼与边缘回弹。
287
- - 新增液态玻璃参数:色散与表面高光。
288
- - 新增世界时间倍率和像素飘雪天气。
289
- - 新增独立 Playground,可实时调节参数、套用预设并复制 HTML。
290
- - 重组 README,将中文说明置于文档顶部,并提供中英文跳转。
291
-
292
- ### v1.1.0
293
-
294
- - 新增动画速度、镜片折射、外框厚度和初始夜晚状态的 HTML 参数配置。
295
-
296
- ### v1.0.0
297
-
298
- - 首个公开版本。
299
-
300
- ## 许可证
301
-
302
- [Unlicense](https://unlicense.org/) — 公有领域协议。允许自由使用,包括商业用途,无需署名。
303
-
304
- ---
305
-
306
- ## English
307
-
308
- A draggable day/night switch with a tiny pixel world living inside the glass. Move the switch to transition between daylight, dusk, and night.
309
-
310
- **Quick links:** [Live demo](https://gsvegetable.github.io/pixel-daylight-switch/) · [Interactive Playground](https://gsvegetable.github.io/pixel-daylight-switch/playground.html) · [Releases](https://github.com/GSvegetable/pixel-daylight-switch/releases)
311
-
312
- ### Quick start
313
-
314
- No npm, dependencies, or build step required:
315
-
316
- ```html
317
- <div data-ld-part="toggle-daylight"></div>
318
- <script src="https://gsvegetable.github.io/pixel-daylight-switch/app.js"></script>
319
- ```
320
-
321
- The script creates the internal canvas, interaction target, and accessibility elements. The component is responsive and supports multiple independent instances on one page.
322
-
323
- ### NPM installation
66
+ ## Install from npm
324
67
 
325
68
  ```bash
326
69
  npm install pixel-daylight-switch-gsvegetable
327
70
  ```
328
71
 
329
- ESM / native build tools:
72
+ **ES modules**
330
73
 
331
74
  ```js
332
75
  import PixelDaylightSwitch from 'pixel-daylight-switch-gsvegetable';
333
76
 
334
77
  const root = document.querySelector('[data-ld-part="toggle-daylight"]');
335
78
  PixelDaylightSwitch.mount(root);
336
- // Before removing the root:
79
+
80
+ // Call before removing the root from the DOM.
337
81
  PixelDaylightSwitch.unmount(root);
338
82
  ```
339
83
 
340
- React and Vue 3 integrations should call `mount(element)` after the element is created and `unmount(element)` before it is removed. The package exposes both ESM and CommonJS entry points and is safe to import during SSR; mount only in the browser.
84
+ **CommonJS**
341
85
 
342
- ### Interactive Playground
86
+ ```js
87
+ const PixelDaylightSwitch = require('pixel-daylight-switch-gsvegetable');
88
+ ```
343
89
 
344
- Open the [Pixel Daylight Playground](https://gsvegetable.github.io/pixel-daylight-switch/playground.html) to tune all component settings visually, try presets, preview changes, and copy generated HTML.
90
+ The package exposes ESM and CommonJS entry points. Importing is safe in an SSR environment; call `mount()` only in a browser after the target element exists. The package's published file list is defined in [package.json](package.json).
345
91
 
346
- ### HTML configuration
92
+ ## Configuration
347
93
 
348
- All settings are optional and configured per instance using `data-*` attributes.
94
+ Set optional attributes on the mount element. Defaults apply when an attribute is omitted or invalid.
349
95
 
350
96
  | Attribute | Default | Description |
351
97
  | --- | ---: | --- |
352
- | `data-speed` | `9.5` | Base switch motion speed. |
353
- | `data-refraction` | `1.24` | Glass lens refraction strength. |
354
- | `data-bezel` | `0.046` | Bezel thickness relative to component height. |
355
- | `data-start-night` | `false` | Initialize in night mode when set to `true`. |
356
- | `data-friction` | `0.6` | Release inertia damping; lower values feel more slippery. |
357
- | `data-bounce` | `3.2` | Rebound impulse at the switch edges. |
358
- | `data-dispersion` | `0.05` | RGB chromatic dispersion at the glass edge; `0` disables it. |
359
- | `data-shine` | `0.44` | Daytime glass highlight intensity. |
360
- | `data-time-speed` | `1.0` | World simulation speed; `0` freezes world dynamics and `2` doubles the speed. |
361
- | `data-weather` | `default` | Weather preset: `default` or `snow`. |
362
- | `data-scene` | `countryside` | Pixel environment: `countryside`, `japanese-street`, `apartment`, `seaside`, or `mountain-cabin`. |
98
+ | `data-speed` | `9.5` | Base response speed; greater than zero. |
99
+ | `data-refraction` | `1.24` | Glass lens refraction strength; greater than zero. |
100
+ | `data-bezel` | `0.046` | Relative glass-edge thickness; greater than zero. |
101
+ | `data-start-night` | `false` | Exact string `"true"` starts in night mode. |
102
+ | `data-friction` | `0.6` | Release inertia damping; clamped to `0.1–0.9`. |
103
+ | `data-bounce` | `3.2` | Edge rebound strength; clamped to `0–12`. |
104
+ | `data-dispersion` | `0.05` | RGB dispersion at the glass edge; clamped to `0–0.25`. |
105
+ | `data-shine` | `0.44` | Daylight glass highlight; clamped to `0–1.5`. |
106
+ | `data-time-speed` | `1` | World simulation speed; clamped to `0–8`. Set to `0` to freeze world motion. |
107
+ | `data-weather` | `default` | `default` or `snow`. Unknown values fall back to `default`. |
108
+ | `data-scene` | `countryside` | `countryside`, `japanese-street`, `apartment`, `seaside` or `mountain-cabin`. |
363
109
 
364
110
  Example:
365
111
 
366
112
  ```html
367
113
  <div
368
114
  data-ld-part="toggle-daylight"
369
- data-speed="12"
370
- data-refraction="1.5"
371
- data-bezel="0.05"
372
115
  data-start-night="true"
373
- data-friction="0.45"
374
- data-bounce="4.2"
375
- data-dispersion="0.12"
376
- data-shine="0.6"
377
- data-time-speed="1.5"
116
+ data-scene="seaside"
378
117
  data-weather="snow"
379
- data-scene="mountain-cabin"
380
- ></div>
118
+ data-time-speed="1.4"
119
+ data-refraction="1.3">
120
+ </div>
381
121
  ```
382
122
 
383
- Missing or invalid numeric values fall back to defaults. Unknown weather values fall back to `default`; unknown scene values fall back to `countryside`. With no new v1.2.0 or v1.3.0 attributes, the component retains the intended default appearance.
384
-
385
- ### Page theme integration
123
+ ## Events and state
386
124
 
387
- The component exposes the current night level as the `--night` CSS custom property on the root element: `0` is day, `1` is night, and intermediate values represent the transition.
388
-
389
- ```css
390
- body {
391
- background: color-mix(in srgb, #f5ecd9, #1b2146 calc(var(--night, 0) * 100%));
392
- }
393
- ```
125
+ The root element exposes transition progress through the CSS custom property `--night`: `0` is day, `1` is night, and values between them represent the transition.
394
126
 
395
- Listen for state changes with:
127
+ When the committed day/night state changes, the root dispatches a bubbling, composed `daylight:change` event. `event.detail.night` is a boolean. It is not emitted on every animation frame.
396
128
 
397
129
  ```js
398
- document.addEventListener('daylight:change', (event) => {
399
- document.documentElement.classList.toggle('dark', event.detail.night);
130
+ const root = document.querySelector('[data-ld-part="toggle-daylight"]');
131
+
132
+ root.addEventListener('daylight:change', (event) => {
133
+ console.log(event.detail.night ? 'Night' : 'Day');
400
134
  });
401
135
  ```
402
136
 
403
- ### Theme colors
137
+ ## Rendering, accessibility and performance
404
138
 
405
- Override `--ld-bg`, `--ld-surface`, `--ld-fg`, `--ld-muted`, and `--ld-accent` on the component element to customize its palette.
139
+ - WebGL2 renders the refractive lens; Canvas 2D is used if WebGL2 is unavailable or fails to initialize.
140
+ - The component scales its drawing surface to its container.
141
+ - Rendering pauses while the document is hidden or the component is outside the viewport.
142
+ - Keyboard and switch semantics are provided, with a live status announcement.
143
+ - The runtime respects the operating system's `prefers-reduced-motion` preference.
406
144
 
407
- ### Dynamic mounting
145
+ Performance varies with browser, graphics hardware, device pixel ratio and the number of visible instances.
408
146
 
409
- ```js
410
- PixelDaylightSwitch.mount(element);
411
- PixelDaylightSwitch.unmount(element);
412
- ```
413
-
414
- ### Browser support
415
-
416
- WebGL2 is used for the glass effect when available, with Canvas 2D as a fallback. The component respects reduced-motion preferences and pauses unnecessary rendering when hidden or offscreen.
417
-
418
- ### Development
147
+ ## Development and tests
419
148
 
420
149
  ```bash
421
150
  git clone https://github.com/GSvegetable/pixel-daylight-switch.git
422
151
  cd pixel-daylight-switch
152
+ npm test
423
153
  ```
424
154
 
425
- Open `index.html` in a modern browser. No build step is needed.
426
-
427
- ### Version status
155
+ Run the Chromium browser regression suite:
428
156
 
429
- v1.3.0 adds four new pixel environments and a reorganized Playground. See [CHANGELOG.md](./CHANGELOG.md) for the detailed history.
430
-
431
- ### License
432
-
433
- [Unlicense](https://unlicense.org/) — public domain. Free for personal and commercial use without attribution.
157
+ ```bash
158
+ npm install --no-save @playwright/test@1.56.1
159
+ npx playwright install chromium
160
+ npm run test:browser
161
+ ```
162
+
163
+ GitHub Actions runs package and SSR checks on Node.js 18, 20 and 22, plus Chromium interaction and mobile regression tests. See [current workflow runs](https://github.com/GSvegetable/pixel-daylight-switch/actions/workflows/ci.yml).
164
+
165
+ ## Android and iOS
166
+
167
+ The repository includes Capacitor 8 build workflows that reuse the web runtime. GitHub Actions produces an Android debug APK and an unsigned iOS Simulator app archive. These are development artifacts, not store-ready releases: the Android APK is not a Play Store release, and the iOS Simulator build cannot be installed on a physical iPhone or iPad. See [mobile build notes](builds/README.md) and the [mobile workflow](https://github.com/GSvegetable/pixel-daylight-switch/actions/workflows/mobile-build.yml).
168
+
169
+ ## Repository map
170
+
171
+ ```text
172
+ pixel-daylight-switch/
173
+ ├── .github/workflows/ # CI, native mobile builds, npm publishing
174
+ ├── assets/
175
+ │ └── scene-gallery.png # Five-scene overview image
176
+ ├── builds/
177
+ │ └── README.md # Mobile artifact notes; binaries are workflow outputs
178
+ ├── mobile/
179
+ │ ├── index.html # Capacitor app entry
180
+ │ └── mobile.css # Mobile-only layout
181
+ ├── scripts/
182
+ │ └── prepare-mobile.cjs # Prepare the shared web runtime for Capacitor
183
+ ├── tests/
184
+ │ ├── browser/ # Playwright interaction and mobile regressions
185
+ │ ├── fixture.html
186
+ │ ├── mobile-smoke.cjs
187
+ │ ├── package-smoke.cjs
188
+ │ └── server.cjs
189
+ ├── app.js # Component runtime, scenes, input and rendering
190
+ ├── style.css # Component styles
191
+ ├── embed.js # One-script website embed loader
192
+ ├── index.html # Live demo page
193
+ ├── preview.html # Component preview
194
+ ├── playground.html # Interactive parameter lab
195
+ ├── index.mjs / index.cjs # ESM and CommonJS package entry points
196
+ ├── package.json # Package metadata and scripts
197
+ ├── capacitor.config.json # Capacitor configuration
198
+ ├── playwright.config.cjs # Browser test configuration
199
+ ├── CHANGELOG.md
200
+ ├── llms.txt
201
+ ├── LICENSE
202
+ └── README*.md # English, Simplified Chinese and Japanese docs
203
+ ```
204
+
205
+ ## License
206
+
207
+ Released under [The Unlicense](LICENSE). You may copy, modify, publish, distribute and use the software for personal or commercial purposes without attribution. It is provided without warranty.