pixel-daylight-switch-gsvegetable 2.2.0 → 3.0.1
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/INTEGRATIONS.md +139 -0
- package/README.ja.md +54 -2
- package/README.md +77 -2
- package/README.zh-CN.md +54 -2
- package/SCENE_PLUGINS.md +94 -0
- package/app.js +90 -3
- package/browser.mjs +20 -0
- package/examples/scenes/floating-island.v2.json +152 -0
- package/examples/scenes/sakura-evening.json +38 -0
- package/index.cjs +9 -2
- package/index.d.ts +65 -0
- package/index.mjs +4 -0
- package/llms.txt +90 -86
- package/package.json +26 -8
- package/scene-plugin.js +173 -0
- package/schemas/scene-manifest.v1.schema.json +117 -0
- package/schemas/scene-manifest.v2.schema.json +229 -0
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": 2,
|
|
3
|
+
"id": "floating-island",
|
|
4
|
+
"name": "Floating Island",
|
|
5
|
+
"author": "Pixel Daylight Switch",
|
|
6
|
+
"license": "CC0-1.0",
|
|
7
|
+
"canvas": {
|
|
8
|
+
"width": 24,
|
|
9
|
+
"height": 12
|
|
10
|
+
},
|
|
11
|
+
"pixels": [
|
|
12
|
+
"........................",
|
|
13
|
+
"........................",
|
|
14
|
+
"........................",
|
|
15
|
+
"........................",
|
|
16
|
+
"........................",
|
|
17
|
+
"........................",
|
|
18
|
+
"........................",
|
|
19
|
+
"........................",
|
|
20
|
+
"........................",
|
|
21
|
+
"........................",
|
|
22
|
+
"........................",
|
|
23
|
+
"........................"
|
|
24
|
+
],
|
|
25
|
+
"palettes": {
|
|
26
|
+
"day": {
|
|
27
|
+
".": "#8ed5f4",
|
|
28
|
+
"g": "#74b66d",
|
|
29
|
+
"t": "#79543f",
|
|
30
|
+
"l": "#f8d77a",
|
|
31
|
+
"c": "#ffffff"
|
|
32
|
+
},
|
|
33
|
+
"dusk": {
|
|
34
|
+
".": "#e99a91",
|
|
35
|
+
"g": "#627e69",
|
|
36
|
+
"t": "#5b4653",
|
|
37
|
+
"l": "#f6bb86",
|
|
38
|
+
"c": "#f4c6d0"
|
|
39
|
+
},
|
|
40
|
+
"night": {
|
|
41
|
+
".": "#171d3b",
|
|
42
|
+
"g": "#304b4a",
|
|
43
|
+
"t": "#302c43",
|
|
44
|
+
"l": "#f1d28a",
|
|
45
|
+
"c": "#a8b7e8"
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
"timeCycle": [
|
|
49
|
+
{
|
|
50
|
+
"at": 0,
|
|
51
|
+
"palette": "night"
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
"at": 6,
|
|
55
|
+
"palette": "night"
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
"at": 8,
|
|
59
|
+
"palette": "day"
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
"at": 17,
|
|
63
|
+
"palette": "day"
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
"at": 19,
|
|
67
|
+
"palette": "dusk"
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
"at": 21,
|
|
71
|
+
"palette": "night"
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
"at": 24,
|
|
75
|
+
"palette": "night"
|
|
76
|
+
}
|
|
77
|
+
],
|
|
78
|
+
"assets": {
|
|
79
|
+
"island": {
|
|
80
|
+
"width": 14,
|
|
81
|
+
"height": 4,
|
|
82
|
+
"pixels": [
|
|
83
|
+
"......gg......",
|
|
84
|
+
"....gggggg....",
|
|
85
|
+
"..gggggggggg..",
|
|
86
|
+
"gggggggggggggg"
|
|
87
|
+
]
|
|
88
|
+
},
|
|
89
|
+
"tree": {
|
|
90
|
+
"width": 5,
|
|
91
|
+
"height": 7,
|
|
92
|
+
"pixels": [
|
|
93
|
+
"..g..",
|
|
94
|
+
".ggg.",
|
|
95
|
+
"ggggg",
|
|
96
|
+
"..t..",
|
|
97
|
+
"..t..",
|
|
98
|
+
"..t..",
|
|
99
|
+
"..t.."
|
|
100
|
+
]
|
|
101
|
+
},
|
|
102
|
+
"cloud": {
|
|
103
|
+
"width": 8,
|
|
104
|
+
"height": 3,
|
|
105
|
+
"pixels": [
|
|
106
|
+
"..cccc..",
|
|
107
|
+
".cccccc.",
|
|
108
|
+
"cccccccc"
|
|
109
|
+
]
|
|
110
|
+
}
|
|
111
|
+
},
|
|
112
|
+
"layers": [
|
|
113
|
+
{
|
|
114
|
+
"id": "island",
|
|
115
|
+
"asset": "island",
|
|
116
|
+
"x": 5,
|
|
117
|
+
"y": 7
|
|
118
|
+
},
|
|
119
|
+
{
|
|
120
|
+
"id": "tree",
|
|
121
|
+
"asset": "tree",
|
|
122
|
+
"x": 8,
|
|
123
|
+
"y": 0
|
|
124
|
+
},
|
|
125
|
+
{
|
|
126
|
+
"id": "cloud-left",
|
|
127
|
+
"asset": "cloud",
|
|
128
|
+
"x": -3,
|
|
129
|
+
"y": 2,
|
|
130
|
+
"animation": {
|
|
131
|
+
"type": "drift",
|
|
132
|
+
"axis": "x",
|
|
133
|
+
"speed": 0.12,
|
|
134
|
+
"distance": 4,
|
|
135
|
+
"phase": 0
|
|
136
|
+
}
|
|
137
|
+
},
|
|
138
|
+
{
|
|
139
|
+
"id": "cloud-right",
|
|
140
|
+
"asset": "cloud",
|
|
141
|
+
"x": 17,
|
|
142
|
+
"y": 4,
|
|
143
|
+
"animation": {
|
|
144
|
+
"type": "bob",
|
|
145
|
+
"axis": "y",
|
|
146
|
+
"speed": 0.18,
|
|
147
|
+
"distance": 2,
|
|
148
|
+
"phase": 1.4
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
]
|
|
152
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": 1,
|
|
3
|
+
"id": "sakura-evening",
|
|
4
|
+
"name": "Sakura Evening",
|
|
5
|
+
"author": "Community Artist",
|
|
6
|
+
"license": "CC-BY-4.0",
|
|
7
|
+
"canvas": { "width": 16, "height": 8 },
|
|
8
|
+
"pixels": [
|
|
9
|
+
"................",
|
|
10
|
+
"......ccc.......",
|
|
11
|
+
".....ccccc......",
|
|
12
|
+
"...tt..s..tt....",
|
|
13
|
+
"..ttttsss.tttt..",
|
|
14
|
+
"......sss.......",
|
|
15
|
+
"gggggggggggggggg",
|
|
16
|
+
"gggggggggggggggg"
|
|
17
|
+
],
|
|
18
|
+
"palettes": {
|
|
19
|
+
"day": {
|
|
20
|
+
".": "#9bd8f5", "c": "#f4a7c8", "t": "#8a5a72", "s": "#f6d6df", "g": "#78ad72"
|
|
21
|
+
},
|
|
22
|
+
"dusk": {
|
|
23
|
+
".": "#ef9b83", "c": "#dc83b4", "t": "#563e69", "s": "#f0c0cf", "g": "#526f62"
|
|
24
|
+
},
|
|
25
|
+
"night": {
|
|
26
|
+
".": "#171d3b", "c": "#9879b5", "t": "#292744", "s": "#c3a4c8", "g": "#283f45"
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
"timeCycle": [
|
|
30
|
+
{ "at": 0, "palette": "night" },
|
|
31
|
+
{ "at": 5.5, "palette": "night" },
|
|
32
|
+
{ "at": 7, "palette": "day" },
|
|
33
|
+
{ "at": 16.5, "palette": "day" },
|
|
34
|
+
{ "at": 19, "palette": "dusk" },
|
|
35
|
+
{ "at": 21, "palette": "night" },
|
|
36
|
+
{ "at": 24, "palette": "night" }
|
|
37
|
+
]
|
|
38
|
+
}
|
package/index.cjs
CHANGED
|
@@ -1,4 +1,11 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
//
|
|
4
|
-
|
|
3
|
+
// Load the declarative scene registry before the browser runtime so registered
|
|
4
|
+
// community scenes are available when mount() initializes a root.
|
|
5
|
+
const scenes = require('./scene-plugin.js');
|
|
6
|
+
const api = require('./app.js');
|
|
7
|
+
api.registerScene = scenes.registerScene;
|
|
8
|
+
api.validateScene = scenes.validateScene;
|
|
9
|
+
api.getScene = scenes.getScene;
|
|
10
|
+
api.listScenes = scenes.listScenes;
|
|
11
|
+
module.exports = api;
|
package/index.d.ts
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
export interface ScenePalette {
|
|
2
|
+
[symbol: string]: `#${string}`;
|
|
3
|
+
}
|
|
4
|
+
export interface SceneTimeStop { at: number; palette: string; }
|
|
5
|
+
export interface ScenePixelAsset {
|
|
6
|
+
width: number;
|
|
7
|
+
height: number;
|
|
8
|
+
/** One printable-ASCII character per pixel. A dot is transparent when used as a layer. */
|
|
9
|
+
pixels: string[];
|
|
10
|
+
}
|
|
11
|
+
export interface SceneLayerAnimation {
|
|
12
|
+
/** drift and bob are deterministic sinusoidal motion tracks. */
|
|
13
|
+
type: 'drift' | 'bob';
|
|
14
|
+
axis: 'x' | 'y';
|
|
15
|
+
/** Angular speed in radians per second, from 0 to 4. */
|
|
16
|
+
speed: number;
|
|
17
|
+
/** Motion amplitude in scene pixels, from 1 to 64. */
|
|
18
|
+
distance: number;
|
|
19
|
+
/** Optional phase in radians, from 0 to 2π. */
|
|
20
|
+
phase?: number;
|
|
21
|
+
}
|
|
22
|
+
export interface SceneLayer {
|
|
23
|
+
id: string;
|
|
24
|
+
asset: string;
|
|
25
|
+
x: number;
|
|
26
|
+
y: number;
|
|
27
|
+
animation?: SceneLayerAnimation;
|
|
28
|
+
}
|
|
29
|
+
export interface SceneManifestBase {
|
|
30
|
+
id: string;
|
|
31
|
+
name: string;
|
|
32
|
+
author: string;
|
|
33
|
+
license: string;
|
|
34
|
+
canvas: { width: number; height: number };
|
|
35
|
+
pixels: string[];
|
|
36
|
+
palettes: Record<string, ScenePalette>;
|
|
37
|
+
timeCycle: SceneTimeStop[];
|
|
38
|
+
}
|
|
39
|
+
/** Manifest v1 preserves the original single pixel-matrix format. */
|
|
40
|
+
export interface SceneManifestV1 extends SceneManifestBase { schemaVersion: 1; }
|
|
41
|
+
/** Manifest v2 adds reusable pixel assets, compositing layers and declarative motion. */
|
|
42
|
+
export interface SceneManifestV2 extends SceneManifestBase {
|
|
43
|
+
schemaVersion: 2;
|
|
44
|
+
assets: Record<string, ScenePixelAsset>;
|
|
45
|
+
layers: SceneLayer[];
|
|
46
|
+
}
|
|
47
|
+
export type SceneManifest = SceneManifestV1 | SceneManifestV2;
|
|
48
|
+
export interface SceneValidationResult { valid: boolean; errors: string[]; }
|
|
49
|
+
export type UnregisterScene = () => boolean;
|
|
50
|
+
export interface PixelDaylightSwitchAPI {
|
|
51
|
+
mount(root: Element | null): (() => void) | null;
|
|
52
|
+
unmount(root: Element | null): void;
|
|
53
|
+
registerScene(manifest: SceneManifest): UnregisterScene;
|
|
54
|
+
validateScene(manifest: unknown): SceneValidationResult;
|
|
55
|
+
getScene(id: string): SceneManifest | null;
|
|
56
|
+
listScenes(): SceneManifest[];
|
|
57
|
+
}
|
|
58
|
+
declare const PixelDaylightSwitch: PixelDaylightSwitchAPI;
|
|
59
|
+
export declare const mount: PixelDaylightSwitchAPI['mount'];
|
|
60
|
+
export declare const unmount: PixelDaylightSwitchAPI['unmount'];
|
|
61
|
+
export declare const registerScene: PixelDaylightSwitchAPI['registerScene'];
|
|
62
|
+
export declare const validateScene: PixelDaylightSwitchAPI['validateScene'];
|
|
63
|
+
export declare const getScene: PixelDaylightSwitchAPI['getScene'];
|
|
64
|
+
export declare const listScenes: PixelDaylightSwitchAPI['listScenes'];
|
|
65
|
+
export default PixelDaylightSwitch;
|
package/index.mjs
CHANGED
|
@@ -2,4 +2,8 @@ import api from './index.cjs';
|
|
|
2
2
|
|
|
3
3
|
export const mount = api.mount;
|
|
4
4
|
export const unmount = api.unmount;
|
|
5
|
+
export const registerScene = api.registerScene;
|
|
6
|
+
export const validateScene = api.validateScene;
|
|
7
|
+
export const getScene = api.getScene;
|
|
8
|
+
export const listScenes = api.listScenes;
|
|
5
9
|
export default api;
|
package/llms.txt
CHANGED
|
@@ -1,118 +1,122 @@
|
|
|
1
1
|
# Pixel Daylight Switch
|
|
2
2
|
|
|
3
|
-
> A dependency-free, draggable pixel-art day/night
|
|
3
|
+
> A dependency-free, draggable pixel-art day/night UI component. Five living pixel-art environments sit inside a refractive glass lens, with continuous day-to-night color, lighting and animation transitions.
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## Zero-setup browser embed
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
Paste one line where the component should appear:
|
|
8
8
|
|
|
9
9
|
```html
|
|
10
|
-
<
|
|
11
|
-
<script src="https://cdn.jsdelivr.net/npm/pixel-daylight-switch-gsvegetable@1.3.0/app.js"></script>
|
|
10
|
+
<script src="https://gsvegetable.github.io/pixel-daylight-switch/embed.js"></script>
|
|
12
11
|
```
|
|
13
12
|
|
|
14
|
-
|
|
13
|
+
The loader creates a responsive instance and loads the runtime. Component styles are scoped; the loader does not inject the demo stylesheet or reset the host page's body, main, footer, typography or layout. Set supported `data-*` options (including `data-scene` and `data-weather`) on the script tag to configure this instance. Use the mount API for multiple instances or custom placement.
|
|
15
14
|
|
|
16
|
-
|
|
17
|
-
- ESM: `import PixelDaylightSwitch from 'pixel-daylight-switch-gsvegetable'`
|
|
18
|
-
- Named imports: `import { mount, unmount } from 'pixel-daylight-switch-gsvegetable'`
|
|
19
|
-
- CommonJS: `const PixelDaylightSwitch = require('pixel-daylight-switch-gsvegetable')`
|
|
20
|
-
- The runtime auto-mounts matching elements present when the script is evaluated.
|
|
21
|
-
- Call `mount(element)` for elements created later. Call `unmount(element)` before removing a mounted element.
|
|
22
|
-
- SSR-safe to import: DOM work only runs when `document` exists.
|
|
15
|
+
## Direct browser usage
|
|
23
16
|
|
|
24
|
-
|
|
17
|
+
```html
|
|
18
|
+
<div style="width:min(100%, 800px);margin-inline:auto">
|
|
19
|
+
<div data-ld-part="toggle-daylight" data-scene="japanese-street"></div>
|
|
20
|
+
</div>
|
|
21
|
+
<script src="https://gsvegetable.github.io/pixel-daylight-switch/app.js"></script>
|
|
22
|
+
```
|
|
25
23
|
|
|
26
|
-
-
|
|
27
|
-
- The component creates its canvas, interaction button, and live status element if they are missing.
|
|
28
|
-
- Multiple independent instances are supported.
|
|
29
|
-
- The root element should have a measurable width. Its aspect ratio is 1.6439.
|
|
24
|
+
No stylesheet import is required. The runtime injects component-scoped CSS and automatically mounts matching elements. The host/container must have a measurable width. The component preserves its 1.6439 aspect ratio and scales to its available width.
|
|
30
25
|
|
|
31
|
-
##
|
|
26
|
+
## npm
|
|
32
27
|
|
|
33
|
-
|
|
28
|
+
```bash
|
|
29
|
+
npm install pixel-daylight-switch-gsvegetable
|
|
30
|
+
```
|
|
34
31
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
| `data-ld-part` | required | `toggle-daylight` | Identifies a component root for automatic mounting. |
|
|
38
|
-
| `data-label` | localized label | Any text | Accessible label for the switch button. |
|
|
39
|
-
| `data-speed` | `9.5` | Positive number | Base motion response speed. |
|
|
40
|
-
| `data-refraction` | `1.24` | Positive number | Refraction strength of the glass lens. |
|
|
41
|
-
| `data-bezel` | `0.046` | Positive number | Glass bezel thickness ratio. |
|
|
42
|
-
| `data-start-night` | `false` | `true` / `false` | Start in night mode when exactly `true`. |
|
|
43
|
-
| `data-friction` | `0.6` | `0.1–0.9` | Release inertia damping. Lower values retain more glide. |
|
|
44
|
-
| `data-bounce` | `3.2` | `0–12` | Edge rebound impulse. |
|
|
45
|
-
| `data-dispersion` | `0.05` | `0–0.25` | RGB chromatic dispersion at the lens edge. |
|
|
46
|
-
| `data-shine` | `0.44` | `0–1.5` | Daylight lens highlight intensity. |
|
|
47
|
-
| `data-time-speed` | `1.0` | `0–8` | Pixel-world simulation speed; zero freezes world time. |
|
|
48
|
-
| `data-weather` | `default` | `default`, `snow` | Selects the weather effect. Unknown values use `default`. |
|
|
49
|
-
| `data-scene` | `countryside` | `countryside`, `japanese-street`, `apartment`, `seaside`, `mountain-cabin` | Selects the pixel environment. Unknown values use `countryside`. |
|
|
32
|
+
```js
|
|
33
|
+
import PixelDaylightSwitch, { mount, unmount } from 'pixel-daylight-switch-gsvegetable';
|
|
50
34
|
|
|
51
|
-
|
|
35
|
+
const root = document.querySelector('[data-ld-part="toggle-daylight"]');
|
|
36
|
+
mount(root);
|
|
37
|
+
// Before removing the root:
|
|
38
|
+
unmount(root);
|
|
39
|
+
```
|
|
52
40
|
|
|
53
|
-
|
|
41
|
+
CommonJS: `const PixelDaylightSwitch = require('pixel-daylight-switch-gsvegetable')`.
|
|
54
42
|
|
|
55
|
-
|
|
56
|
-
| --- | --- | --- |
|
|
57
|
-
| `--ld-bg` | `#f5ecd9` | Component background palette input. |
|
|
58
|
-
| `--ld-surface` | `#8c9a62` | Surface and environment palette input. |
|
|
59
|
-
| `--ld-fg` | `#1b2146` | Foreground palette input. |
|
|
60
|
-
| `--ld-muted` | `#7f97b3` | Muted palette input. |
|
|
61
|
-
| `--ld-accent` | `#efa02c` | Focus and accent color. |
|
|
62
|
-
| `--ld-radius` | `9999px` | Interaction button corner radius. |
|
|
63
|
-
| `--ld-font` | `system-ui, sans-serif` | Component font family. |
|
|
64
|
-
| `--ld-space` | `8px` | Focus outline offset scale. |
|
|
65
|
-
| `--ld-shadow` | `0 8px 24px rgb(27 33 70 / .2)` | Reserved theme token; current renderer does not consume it. |
|
|
66
|
-
| `--ld-motion` | `200ms` | Focus outline transition duration. |
|
|
67
|
-
| `--night` | Runtime: `0–1` | Read-only live night intensity; 0 is day, 1 is night. |
|
|
43
|
+
The package is safe to import during SSR; mount only after the target DOM element exists. `mount(element)` is idempotent and returns a cleanup function on success (or null on failure). `unmount(element)` stops rendering and removes observers/listeners; it does not remove the DOM root or forcibly invalidate the canvas context.
|
|
68
44
|
|
|
69
|
-
|
|
45
|
+
Framework lifecycle examples are in [INTEGRATIONS.md](INTEGRATIONS.md). Scene plugin authoring, manifest constraints and API examples are in [SCENE_PLUGINS.md](SCENE_PLUGINS.md).
|
|
70
46
|
|
|
71
|
-
|
|
47
|
+
## Community scene plugins (v3.0.0)
|
|
72
48
|
|
|
73
|
-
-
|
|
74
|
-
- Returns a cleanup function when mounting succeeds; returns `null` if mounting fails.
|
|
75
|
-
- Idempotent: mounting the same element twice does not create duplicate instances.
|
|
76
|
-
- Example: `const destroy = PixelDaylightSwitch.mount(element)`.
|
|
49
|
+
The optional `scene-plugin.js` registry exposes `registerScene(manifest)`, `validateScene(manifest)`, `getScene(id)` and `listScenes()`. Load the registry before `app.js` in a browser, or import `registerScene` from the npm package. Register a scene before mounting its root. Manifest v1 uses a 1–192 by 1–112 printable-ASCII pixel map, up to 8 named palettes, and a 24-hour timeline that starts at 0 and ends at 24. Every used pixel symbol must have a valid `#RGB` or `#RRGGBB` color in every palette. Data is copied and deeply frozen on registration. Arbitrary plugin JavaScript is never executed. External image/sprite assets, layered tile maps and custom animation tracks are not supported in v1; they are reserved for a future schema extension. See [SCENE_PLUGINS.md](SCENE_PLUGINS.md), the [v1 JSON Schema](schemas/scene-manifest.v1.schema.json), and the [Sakura example](examples/scenes/sakura-evening.json).
|
|
77
50
|
|
|
78
|
-
|
|
51
|
+
## Scenes and weather
|
|
79
52
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
-
|
|
53
|
+
| Attribute | Default | Accepted values |
|
|
54
|
+
| --- | --- | --- |
|
|
55
|
+
| `data-scene` | `countryside` | `countryside`, `japanese-street`, `apartment`, `seaside`, `mountain-cabin` |
|
|
56
|
+
| `data-weather` | `default` | `default`, `snow` |
|
|
57
|
+
| `data-start-night` | `false` | `true`, `false` |
|
|
83
58
|
|
|
84
|
-
|
|
59
|
+
All five scenes are authored environments, not static background images. They use time-of-day palette keys and scene-specific lighting/animation: for example, the seaside lighthouse sweeps a beam across the bay, the apartment changes window and room lighting and animates its cat/resident, and the mountain cabin includes snow/pines and aurora behavior. Scene details continue to evolve as the clock moves between dawn, day, dusk and night.
|
|
85
60
|
|
|
86
|
-
|
|
87
|
-
import PixelDaylightSwitch, { mount, unmount } from 'pixel-daylight-switch-gsvegetable';
|
|
61
|
+
## Visual and motion parameters
|
|
88
62
|
|
|
89
|
-
|
|
90
|
-
|
|
63
|
+
| Attribute | Default | Accepted values / range |
|
|
64
|
+
| --- | --- | --- |
|
|
65
|
+
| `data-speed` | `9.5` | Positive number |
|
|
66
|
+
| `data-refraction` | `1.24` | Positive number |
|
|
67
|
+
| `data-bezel` | `0.046` | Positive number |
|
|
68
|
+
| `data-friction` | `0.6` | `0.1–0.9` |
|
|
69
|
+
| `data-bounce` | `3.2` | `0–12` |
|
|
70
|
+
| `data-dispersion` | `0.05` | `0–0.25` |
|
|
71
|
+
| `data-shine` | `0.44` | `0–1.5` |
|
|
72
|
+
| `data-time-speed` | `1` | `0–8`; zero freezes world time |
|
|
73
|
+
|
|
74
|
+
Invalid values fall back to defaults; documented numeric ranges are clamped.
|
|
75
|
+
|
|
76
|
+
## JavaScript API and events
|
|
77
|
+
|
|
78
|
+
- `mount(element)`: mount one root; idempotent.
|
|
79
|
+
- `unmount(element)`: stop rendering and clean up observers and event listeners.
|
|
80
|
+
- The runtime auto-mounts existing `[data-ld-part="toggle-daylight"]` elements.
|
|
81
|
+
- Use `mount(element)` for elements created later.
|
|
82
|
+
- Listen for `daylight:change` on the root. `event.detail.night` is a boolean and the event fires when the committed day/night state changes, not every animation frame.
|
|
83
|
+
- The root exposes transition progress through CSS custom property `--night` (0 day, 1 night).
|
|
84
|
+
|
|
85
|
+
## Rendering, accessibility and performance
|
|
86
|
+
|
|
87
|
+
- WebGL2 renders the refractive glass; Canvas 2D is the fallback.
|
|
88
|
+
- Keyboard interaction, switch semantics, accessible labels and live status are provided.
|
|
89
|
+
- Respects `prefers-reduced-motion`.
|
|
90
|
+
- Rendering pauses while the page is hidden or the component is outside the viewport.
|
|
91
|
+
- Multiple independent instances are supported.
|
|
91
92
|
|
|
92
|
-
|
|
93
|
-
mount(root);
|
|
94
|
-
// Later:
|
|
95
|
-
unmount(root);
|
|
96
|
-
```
|
|
93
|
+
## Links
|
|
97
94
|
|
|
98
|
-
|
|
95
|
+
- [Live demo](https://gsvegetable.github.io/pixel-daylight-switch/)
|
|
96
|
+
- [Interactive Playground](https://gsvegetable.github.io/pixel-daylight-switch/playground.html)
|
|
97
|
+
- [Preview](https://gsvegetable.github.io/pixel-daylight-switch/preview.html)
|
|
98
|
+
- [Integration recipes](INTEGRATIONS.md)
|
|
99
|
+
- [English README](README.md) · [简体中文](README.zh-CN.md) · [日本語](README.ja.md)
|
|
100
|
+
- [Changelog](CHANGELOG.md)
|
|
99
101
|
|
|
100
|
-
### `daylight:change`
|
|
101
102
|
|
|
102
|
-
|
|
103
|
-
- Bubbles and is composed.
|
|
104
|
-
- `event.detail.night` is a boolean.
|
|
103
|
+
## Scene plugins (v3.0.0)
|
|
105
104
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
105
|
+
- Public API: registerScene(manifest), validateScene(manifest), getScene(id), listScenes().
|
|
106
|
+
- Manifest schema: schemas/scene-manifest.v1.schema.json.
|
|
107
|
+
- Example: examples/scenes/sakura-evening.json.
|
|
108
|
+
- Manifest v1: printable-ASCII pixel matrix (up to 192x112), named palettes, 24-hour palette interpolation.
|
|
109
|
+
- Scene registration is data-only; arbitrary plugin JavaScript is not executed.
|
|
110
|
+
- Browser script order: scene-plugin.js, register the manifest, then app.js. The one-line embed loader loads the registry before the renderer.
|
|
111
|
+
- Existing built-in scenes and their custom live animation code remain unchanged.
|
|
112
112
|
|
|
113
|
-
## Rendering and Compatibility
|
|
114
113
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
-
|
|
118
|
-
-
|
|
114
|
+
## Scene Manifest v2 (v3.0.1)
|
|
115
|
+
|
|
116
|
+
- Manifest v1 remains supported and its schema is unchanged.
|
|
117
|
+
- Manifest v2 adds up to 24 reusable pixel-matrix assets and up to 16 ordered layers.
|
|
118
|
+
- Layers reference named assets and integer x/y positions; '.' is transparent in overlay assets.
|
|
119
|
+
- Optional deterministic motion tracks: drift or bob, on x or y, bounded speed/distance/phase.
|
|
120
|
+
- Every symbol across the base matrix and assets must be defined in every palette.
|
|
121
|
+
- Schema: schemas/scene-manifest.v2.schema.json. Example: examples/scenes/floating-island.v2.json.
|
|
122
|
+
- No arbitrary remote image loading, eval, or executable plugin callbacks.
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pixel-daylight-switch-gsvegetable",
|
|
3
|
-
"version": "
|
|
4
|
-
"description": "A draggable pixel-art day/night switch with
|
|
3
|
+
"version": "3.0.1",
|
|
4
|
+
"description": "A draggable pixel-art day/night switch with layered, animated community scenes.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"pixel-art",
|
|
7
7
|
"day-night",
|
|
@@ -13,7 +13,11 @@
|
|
|
13
13
|
"vanilla-js",
|
|
14
14
|
"capacitor",
|
|
15
15
|
"android",
|
|
16
|
-
"ios"
|
|
16
|
+
"ios",
|
|
17
|
+
"scene-plugin",
|
|
18
|
+
"pixel-world",
|
|
19
|
+
"scene-manifest",
|
|
20
|
+
"pixel-art-scenes"
|
|
17
21
|
],
|
|
18
22
|
"author": "GSvegetable",
|
|
19
23
|
"license": "Unlicense",
|
|
@@ -27,14 +31,20 @@
|
|
|
27
31
|
},
|
|
28
32
|
"main": "./index.cjs",
|
|
29
33
|
"module": "./index.mjs",
|
|
30
|
-
"browser": "./
|
|
34
|
+
"browser": "./browser.mjs",
|
|
31
35
|
"exports": {
|
|
32
36
|
".": {
|
|
37
|
+
"types": "./index.d.ts",
|
|
38
|
+
"browser": "./browser.mjs",
|
|
33
39
|
"import": "./index.mjs",
|
|
34
40
|
"require": "./index.cjs"
|
|
35
41
|
},
|
|
36
42
|
"./app.js": "./app.js",
|
|
37
|
-
"./package.json": "./package.json"
|
|
43
|
+
"./package.json": "./package.json",
|
|
44
|
+
"./scene-plugin": {
|
|
45
|
+
"import": "./scene-plugin.js",
|
|
46
|
+
"require": "./scene-plugin.js"
|
|
47
|
+
}
|
|
38
48
|
},
|
|
39
49
|
"files": [
|
|
40
50
|
"app.js",
|
|
@@ -42,7 +52,14 @@
|
|
|
42
52
|
"index.mjs",
|
|
43
53
|
"README.md",
|
|
44
54
|
"LICENSE",
|
|
45
|
-
"llms.txt"
|
|
55
|
+
"llms.txt",
|
|
56
|
+
"INTEGRATIONS.md",
|
|
57
|
+
"SCENE_PLUGINS.md",
|
|
58
|
+
"scene-plugin.js",
|
|
59
|
+
"schemas",
|
|
60
|
+
"examples",
|
|
61
|
+
"browser.mjs",
|
|
62
|
+
"index.d.ts"
|
|
46
63
|
],
|
|
47
64
|
"sideEffects": [
|
|
48
65
|
"./app.js"
|
|
@@ -54,7 +71,7 @@
|
|
|
54
71
|
"access": "public"
|
|
55
72
|
},
|
|
56
73
|
"scripts": {
|
|
57
|
-
"test": "node tests/package-smoke.cjs && node tests/mobile-smoke.cjs",
|
|
74
|
+
"test": "node tests/package-smoke.cjs && node tests/scene-plugin-smoke.cjs && node tests/mobile-smoke.cjs && node tests/embed-smoke.cjs",
|
|
58
75
|
"test:browser": "playwright test",
|
|
59
76
|
"mobile:prepare": "node scripts/prepare-mobile.cjs",
|
|
60
77
|
"mobile:android": "npm run mobile:prepare && cap sync android && node scripts/set-android-version.cjs android/app/build.gradle",
|
|
@@ -69,5 +86,6 @@
|
|
|
69
86
|
"@capacitor/core": "8.6.0",
|
|
70
87
|
"@capacitor/android": "8.6.0",
|
|
71
88
|
"@capacitor/ios": "8.6.0"
|
|
72
|
-
}
|
|
89
|
+
},
|
|
90
|
+
"types": "./index.d.ts"
|
|
73
91
|
}
|