dsh-theme-mineradio 2.2.8 → 2.3.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.
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Cinematic camera for the ambient scene — makes the backdrop read as a 3D
3
+ * stage rather than a flat wallpaper:
4
+ *
5
+ * 1. CURSOR PARALLAX + 3D TILT (the "wow"): the fluid board (far) and the
6
+ * star-river (near) shift, tilt (rotateX/rotateY under perspective) and
7
+ * roll at different rates as the pointer moves — the near layer travels
8
+ * ~2× further, so moving the mouse parallax-reveals real depth.
9
+ * 2. IDLE DRIFT (the "breathe"): a slow low-frequency sine sway + roll so
10
+ * the scene keeps floating when the pointer is still — a 2D port of
11
+ * Mineradio's `cineTheta = sin(t*0.08)*0.012` idle orbit.
12
+ *
13
+ * Pure CSS-transform work (one rAF, GPU-composited); reduced-motion renders
14
+ * nothing (the scene stays a clean static frame).
15
+ */
16
+ export interface CinemaDriftHandle {
17
+ dispose(): void;
18
+ }
19
+ /** Start the cinematic camera over the ambient scene. */
20
+ export declare function startCinemaDrift(ambient: HTMLElement): CinemaDriftHandle;
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Wallpaper color extraction — a small, dependency-free dominant-hue finder.
3
+ *
4
+ * The wallpaper (image or video frame) is drawn onto a tiny canvas, and the
5
+ * pixels are folded into a circular hue histogram weighted by saturation and
6
+ * mid-lightness, so gray/black/white areas contribute nothing and the result
7
+ * is the image's most vivid, representative hue. Returns a single hue in
8
+ * degrees (0-360), or null when the source is too desaturated to read.
9
+ */
10
+ /**
11
+ * Extract the dominant hue from a canvas-image source (img / video / canvas).
12
+ * @returns a hue in degrees, or null when the source yields no vivid color.
13
+ */
14
+ export declare function extractDominantHue(source: CanvasImageSource): number | null;
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Ambient marine-life scene: the markup the layer injects behind the app
3
+ * frame — brand-fish silhouettes drifting, a shrimp or two crawling the
4
+ * bottom, rising bubbles, twinkling plankton. Positions, sizes, and
5
+ * per-critter timing ride inline styles; the motion itself lives in
6
+ * aqua.module.css (and silences under prefers-reduced-motion).
7
+ */
8
+ /**
9
+ * The complete ambient scene markup: one fixed, click-transparent container
10
+ * the layer prepends to <body> while enabled and removes on disable. The
11
+ * deepseek.com fluid shader canvas forms the board; marine life rides over it.
12
+ */
13
+ export declare const AMBIENT_SCENE: string;
14
+ /** Build the ambient container element (or reuse an existing one). */
15
+ export declare function ensureAmbientScene(): HTMLElement;
16
+ /** Remove the ambient container wherever it lives. */
17
+ export declare function removeAmbientScene(): void;
18
+ /** Add the page edge-fade bands (5px gradient blur over the chat content). */
19
+ export declare function ensurePageFades(): void;
20
+ /** Remove the edge-fade bands. */
21
+ export declare function removePageFades(): void;
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Fluid interaction feeds: buttons ripple on hover/click with a damped
3
+ * stir (the shader settles the wake softly). Scroll wakes were removed by
4
+ * request — feedback stays action-driven and gentle. Coordinates are
5
+ * normalized per the single full-screen canvas so the ripple lands where
6
+ * the action happened. Site policy (no passive mouse trail) is preserved.
7
+ */
8
+ import type { FluidShaderHandle } from './fluid-shader.ts';
9
+ /** The one live fluid surface. */
10
+ export interface FluidTargets {
11
+ main: FluidShaderHandle;
12
+ mainCanvas: HTMLCanvasElement;
13
+ }
14
+ /**
15
+ * Attach the button ripple listeners.
16
+ * @param targets - the fluid handle and its canvas.
17
+ * @returns disposer removing every listener.
18
+ */
19
+ export declare function attachFluidInteractions(targets: FluidTargets): () => void;
@@ -0,0 +1,57 @@
1
+ /**
2
+ * Faithful port of the deepseek.com join-section fluid shader
3
+ * (`ds-join-shader-bg`): a WebGL2 two-pass fluid simulation — a quarter-res
4
+ * flow field (decay + pointer brush with velocity, ping-ponged between two
5
+ * framebuffers) sampled by a full-res domain-warped noise renderer with
6
+ * swirl iterations and a three-color soft blend. Shader sources are verbatim
7
+ * from the site bundle; uniform wiring, the 30fps throttle, the 1.5x pixel
8
+ * ratio cap, and the pointer-listener policy (touch and Windows skip the
9
+ * mouse feed) are replicated exactly. Reduced-motion renders one static
10
+ * frame instead of the loop.
11
+ */
12
+ /** Site-default parameters (the join-section look). */
13
+ export interface FluidParams {
14
+ mouseRadius: number;
15
+ mouseStrength: number;
16
+ decay: number;
17
+ distortBoost: number;
18
+ noiseBoost: number;
19
+ swirlBoost: number;
20
+ speed: number;
21
+ distortion: number;
22
+ swirl: number;
23
+ swirlIterations: number;
24
+ scale: number;
25
+ rotation: number;
26
+ proportion: number;
27
+ softness: number;
28
+ shapeScale: number;
29
+ offsetX: number;
30
+ offsetY: number;
31
+ color1: string;
32
+ color2: string;
33
+ color3: string;
34
+ }
35
+ /** The exact default parameter set shipped by the site. */
36
+ export declare const SITE_FLUID_PARAMS: FluidParams;
37
+ /** Handle returned by {@link attachFluidShader}. */
38
+ export interface FluidShaderHandle {
39
+ /** Update simulation parameters (e.g. a palette switch) without re-mounting. */
40
+ setParams: (params: FluidParams) => void;
41
+ /** Stir the fluid at normalized coordinates with a velocity burst (wakes). */
42
+ stir: (x: number, y: number, vx: number, vy: number) => void;
43
+ /** Audio reactivity: bass energy 0..1 speeds the flow and amplifies the
44
+ * turbulence (ripple amplitude). */
45
+ setAudioLow: (level: number) => void;
46
+ /** Pause or resume the simulation loop. A paused board keeps the last frame. */
47
+ setRunning: (on: boolean) => void;
48
+ /** Stop the loop and release listeners. */
49
+ dispose: () => void;
50
+ }
51
+ /**
52
+ * Mount the fluid simulation on a canvas and run it until disposed.
53
+ * @param canvas - full-size canvas element (CSS-sized by the ambient layer).
54
+ * @param params - simulation parameters (site defaults are the natural input).
55
+ * @returns the live handle.
56
+ */
57
+ export declare function attachFluidShader(canvas: HTMLCanvasElement, params: FluidParams): FluidShaderHandle;
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Continuous fluid palette: hue (0-360) and depth (0-100) sliders drive the
3
+ * shader colors directly through HSL interpolation — stepless, no preset
4
+ * steps. Depth 0 = the deep, saturated version of the hue (e.g. #8B0000 for
5
+ * red), depth 100 = the pale, light version (e.g. #FFCCCB); the deep base
6
+ * stop stays near-neutral so the colorless areas keep their true color.
7
+ */
8
+ export interface FluidToneColors {
9
+ /** Bright bloom stop. */
10
+ color1: string;
11
+ /** Mid wash stop. */
12
+ color2: string;
13
+ /** Deep base stop (near-neutral). */
14
+ color3: string;
15
+ }
16
+ /** The slider's 0/360 lands directly on the hue (HUE_BASE 0 keeps the
17
+ * Mineradio default at 44 = champagne gold), sweeping clockwise around the
18
+ * wheel — 44 lands on warm amber, 180 on mint. */
19
+ export declare const HUE_BASE = 0;
20
+ /**
21
+ * Palette for the given hue (0-360) and depth (0-100), per scheme.
22
+ * The depth ramp is piecewise: the lower half sweeps from the absolute
23
+ * extreme — pure black in dark mode, the deep saturated shade (e.g. #8B0000
24
+ * for red) in light mode — up to the shipped mid look; the upper half
25
+ * sweeps from mid to pale (#FFCCCB for red). Stepless HSL interpolation.
26
+ */
27
+ export declare function fluidToneColors(dark: boolean, hue: number, depth: number): FluidToneColors;
28
+ /** Vivid, fixed-lightness colour for a hue — used to fill the rainbow-strip
29
+ * thumb so it always shows the picked colour in dark and light mode alike. */
30
+ export declare function fluidHueSwatch(hue: number): string;
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Mineradio glass dispersion filter — a reworked, single-tint port of the
3
+ * player's `mineradio-control-glass-filter`.
4
+ *
5
+ * The original couples refraction and RGB channel split (which screen-blends
6
+ * into an ugly magenta/purple). Here the two are separated:
7
+ *
8
+ * - REFRACTION: a colourless `feDisplacementMap` warps the backdrop through
9
+ * a generated noise map (a blurred rounded-rect "clear centre" + red/blue
10
+ * gradients), so the things behind the glass visibly bend at the edges.
11
+ * - EDGE TINT: the refracted backdrop is laterally shifted and differenced
12
+ * against itself (`feBlend mode="difference"`), which isolates the edge
13
+ * signal only; a `feColorMatrix` then fills that signal with a SINGLE
14
+ * user-picked hue, luminance-driven alpha (so it stays transparent and
15
+ * edge-only), screen-blended over the refraction.
16
+ *
17
+ * The tint hue is adjustable at runtime via `setTint(hue)`. Chromium-only
18
+ * (SVG `url()` in `backdrop-filter` is unsupported by Safari/Firefox); the
19
+ * layer keeps its plain blur fallback there.
20
+ */
21
+ export interface GlassDispersionHandle {
22
+ /** Re-colour the edge tint (hue in degrees, continuous). */
23
+ setTint(hue: number): void;
24
+ /** Set the refraction strength (0-100 — the feDisplacementMap scale). */
25
+ setRefraction(scale: number): void;
26
+ dispose(): void;
27
+ }
28
+ /** Start the glass dispersion filter and stamp the enabling attribute. */
29
+ export declare function startGlassDispersion(): GlassDispersionHandle;
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Hero greeting pool: time-of-day buckets, random pick per new-session
3
+ * mount, no immediate repeat. Disabling the Aqua layer resets the hero back
4
+ * to the stock greeting for the active locale.
5
+ */
6
+ /**
7
+ * Pick the greeting for the next hero mount.
8
+ * @param locale - active locale id (`zh` pools by time of day; anything else
9
+ * uses the English pool).
10
+ * @returns the greeting string.
11
+ */
12
+ export declare function pickGreeting(locale: string): string;
13
+ /**
14
+ * Restore the stock hero copy for the active locale (called when the Aqua
15
+ * layer is switched off, so the UI returns to its original wording).
16
+ * @param locale - active locale id.
17
+ */
18
+ export declare function resetHeroCopy(locale: string): void;
19
+ /**
20
+ * Mineradio placeholder for the hero composer, matched to the active locale.
21
+ * @param locale - active locale id.
22
+ * @returns the placeholder string.
23
+ */
24
+ export declare function mineradioPlaceholder(locale: string): string;
@@ -1,10 +1,21 @@
1
1
  /**
2
- * Mineradio client plugin body.
3
- * @module dsh-theme-mineradio/client
2
+ * Mineradio client plugin body: the toggleable cinematic glass skin. Owns the
3
+ * durable enable flag (localStorage), applies/retracts the theme layer through
4
+ * {@link MineradioLayer}, and registers two settings surfaces:
5
+ * - the master on/off card into the Plugins section (`settings.plugin.item`,
6
+ * same shape as the other plugin cards);
7
+ * - every glass knob into the General section's Appearance row area
8
+ * (`settings.general.item`, right under 外观).
9
+ * One click on the master switch returns the stock UI (every layer is an
10
+ * effect, disposed on flip).
4
11
  */
5
- import type { ClientContext } from '@deepseek-ai/dsh-client-runtime/client';
6
-
12
+ import type { Context } from '@deepseek-ai/cordis';
13
+ import './mineradio.module.css';
14
+ import './fonts.module.css';
7
15
  /** Required services: theme override stack plus the settings-card surfaces. */
8
16
  export declare const inject: string[];
9
- /** Client plugin body. */
10
- export declare function apply(ctx: ClientContext): void;
17
+ /**
18
+ * Client plugin body.
19
+ * @param ctx - client cordis context.
20
+ */
21
+ export declare function apply(ctx: Context): void;
@@ -0,0 +1,140 @@
1
+ /** `settings.mineradio` namespace dictionaries (the settings-row copy). */
2
+ /** Dictionary namespace owned by this plugin. */
3
+ export declare const NS = "settings.mineradio";
4
+ /** Simplified Chinese dictionary (the key-set source of truth). */
5
+ export declare const zh: {
6
+ 'mineradio.title': string;
7
+ 'mineradio.description': string;
8
+ 'mineradio.enable': string;
9
+ 'mineradio.disable': string;
10
+ 'mineradio.mode': string;
11
+ 'mineradio.modeMica': string;
12
+ 'mineradio.modeCompat': string;
13
+ 'mineradio.textColor': string;
14
+ 'mineradio.textColorChampagne': string;
15
+ 'mineradio.textColorNeutral': string;
16
+ 'mineradio.textColorMint': string;
17
+ 'mineradio.textColorRose': string;
18
+ 'mineradio.scene': string;
19
+ 'mineradio.sceneStudio': string;
20
+ 'mineradio.sceneDeepsea': string;
21
+ 'mineradio.sceneMidnight': string;
22
+ 'mineradio.sceneMist': string;
23
+ 'mineradio.sceneRainbow': string;
24
+ 'mineradio.perf': string;
25
+ 'mineradio.perfPerformance': string;
26
+ 'mineradio.perfBalanced': string;
27
+ 'mineradio.perfVivid': string;
28
+ 'mineradio.foldLooks': string;
29
+ 'mineradio.foldMaterial': string;
30
+ 'mineradio.foldBackdrop': string;
31
+ 'mineradio.foldMotion': string;
32
+ 'mineradio.materialGroup': string;
33
+ 'mineradio.decorAmbient': string;
34
+ 'mineradio.decorHover': string;
35
+ 'mineradio.whale': string;
36
+ 'mineradio.critters': string;
37
+ 'mineradio.mesh': string;
38
+ 'mineradio.starDensity': string;
39
+ 'mineradio.spotlight': string;
40
+ 'mineradio.press': string;
41
+ 'mineradio.audioReact': string;
42
+ 'mineradio.blur': string;
43
+ 'mineradio.frost': string;
44
+ 'mineradio.fluidHue': string;
45
+ 'mineradio.fluidDepth': string;
46
+ 'mineradio.dispersionHue': string;
47
+ 'mineradio.dispersionRefract': string;
48
+ 'mineradio.bgBrightness': string;
49
+ 'mineradio.bgBrightnessHintDark': string;
50
+ 'mineradio.bgBrightnessHintLight': string;
51
+ 'mineradio.background': string;
52
+ 'mineradio.backgroundFluid': string;
53
+ 'mineradio.backgroundWallpaper': string;
54
+ 'mineradio.wallpaper': string;
55
+ 'mineradio.autoTint': string;
56
+ 'mineradio.wallpaperHint': string;
57
+ 'mineradio.chooseImage': string;
58
+ 'mineradio.chooseVideo': string;
59
+ 'mineradio.deleteWallpaper': string;
60
+ 'mineradio.wallpaperBlur': string;
61
+ 'mineradio.wallpaperFrost': string;
62
+ 'mineradio.wallpaperMask': string;
63
+ 'mineradio.wallpaperMaskBlur': string;
64
+ 'mineradio.wallpaperMaskOpacity': string;
65
+ 'mineradio.videoBlur': string;
66
+ 'mineradio.videoBrightness': string;
67
+ 'mineradio.videoHint': string;
68
+ };
69
+ export type MineradioLocaleKey = keyof typeof zh;
70
+ declare module '@deepseek-ai/dsh-client-ui-slots' {
71
+ interface LocaleNamespaceMap {
72
+ /** The Mineradio settings row's copy. */
73
+ 'settings.mineradio': MineradioLocaleKey;
74
+ }
75
+ }
76
+ /** English dictionary. */
77
+ export declare const en: {
78
+ 'mineradio.title': string;
79
+ 'mineradio.description': string;
80
+ 'mineradio.enable': string;
81
+ 'mineradio.disable': string;
82
+ 'mineradio.mode': string;
83
+ 'mineradio.modeMica': string;
84
+ 'mineradio.modeCompat': string;
85
+ 'mineradio.textColor': string;
86
+ 'mineradio.textColorChampagne': string;
87
+ 'mineradio.textColorNeutral': string;
88
+ 'mineradio.textColorMint': string;
89
+ 'mineradio.textColorRose': string;
90
+ 'mineradio.scene': string;
91
+ 'mineradio.sceneStudio': string;
92
+ 'mineradio.sceneDeepsea': string;
93
+ 'mineradio.sceneMidnight': string;
94
+ 'mineradio.sceneMist': string;
95
+ 'mineradio.sceneRainbow': string;
96
+ 'mineradio.perf': string;
97
+ 'mineradio.perfPerformance': string;
98
+ 'mineradio.perfBalanced': string;
99
+ 'mineradio.perfVivid': string;
100
+ 'mineradio.foldLooks': string;
101
+ 'mineradio.foldMaterial': string;
102
+ 'mineradio.foldBackdrop': string;
103
+ 'mineradio.foldMotion': string;
104
+ 'mineradio.materialGroup': string;
105
+ 'mineradio.decorAmbient': string;
106
+ 'mineradio.decorHover': string;
107
+ 'mineradio.whale': string;
108
+ 'mineradio.critters': string;
109
+ 'mineradio.mesh': string;
110
+ 'mineradio.starDensity': string;
111
+ 'mineradio.spotlight': string;
112
+ 'mineradio.press': string;
113
+ 'mineradio.audioReact': string;
114
+ 'mineradio.blur': string;
115
+ 'mineradio.frost': string;
116
+ 'mineradio.fluidHue': string;
117
+ 'mineradio.fluidDepth': string;
118
+ 'mineradio.dispersionHue': string;
119
+ 'mineradio.dispersionRefract': string;
120
+ 'mineradio.bgBrightness': string;
121
+ 'mineradio.bgBrightnessHintDark': string;
122
+ 'mineradio.bgBrightnessHintLight': string;
123
+ 'mineradio.background': string;
124
+ 'mineradio.backgroundFluid': string;
125
+ 'mineradio.backgroundWallpaper': string;
126
+ 'mineradio.wallpaper': string;
127
+ 'mineradio.autoTint': string;
128
+ 'mineradio.wallpaperHint': string;
129
+ 'mineradio.chooseImage': string;
130
+ 'mineradio.chooseVideo': string;
131
+ 'mineradio.deleteWallpaper': string;
132
+ 'mineradio.wallpaperBlur': string;
133
+ 'mineradio.wallpaperFrost': string;
134
+ 'mineradio.wallpaperMask': string;
135
+ 'mineradio.wallpaperMaskBlur': string;
136
+ 'mineradio.wallpaperMaskOpacity': string;
137
+ 'mineradio.videoBlur': string;
138
+ 'mineradio.videoBrightness': string;
139
+ 'mineradio.videoHint': string;
140
+ };
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Interactive mesh: the deepseek.com/harness hero's dot-grid decoration —
3
+ * a 90px grid of dots with spring physics that repel from the pointer
4
+ * (radius 140px), the grid lines stretching with them. Faithful port of the
5
+ * site's `h()` grid component (30fps, dpr ≤ 2, idle-pause). Rendered inside
6
+ * the ambient scene behind the app content; pointer-events pass through.
7
+ */
8
+ /** Mesh handle: disposal. */
9
+ export interface MeshHandle {
10
+ /** Stop the engine and remove the canvas. */
11
+ dispose: () => void;
12
+ }
13
+ /**
14
+ * Mount the interactive mesh into `host` (the ambient scene).
15
+ * @param host - the container the mesh canvas is appended to.
16
+ * @returns the handle.
17
+ */
18
+ export declare function mountMesh(host: HTMLElement): MeshHandle;
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Runtime seam stamper.
3
+ *
4
+ * The Aqua stylesheet keys off stable data-* hooks (`data-dsh-frame`,
5
+ * `data-dsh-sidebar-root`, `data-hero-headline`, …). In the monorepo those
6
+ * hooks are authored into the base packages' source; for a self-contained
7
+ * distribution (installed against a stock DSH) this module stamps them onto
8
+ * the matching elements at runtime, so the stylesheet works with zero base
9
+ * edits. Each selector uses only stable attributes already present in the
10
+ * stock UI (`data-composer-card`, `data-conversation-composer-overlay`,
11
+ * ARIA roles) or lightningcss-preserved class-name substrings.
12
+ *
13
+ * Stamps are idempotent and inert without the `data-dsh-aqua` root attribute
14
+ * (the whole stylesheet is gated on it), so they are simply left in place when
15
+ * the layer flips off — "off" still renders the exact stock UI.
16
+ */
17
+ /**
18
+ * Stamp the seams once, then keep them stamped as React remounts nodes.
19
+ * @returns a disposer that disconnects the observer.
20
+ */
21
+ export declare function startSeamStamper(): () => void;
@@ -0,0 +1,115 @@
1
+ /**
2
+ * Mineradio row slot store: a mirror of the layer's state (enable flag plus the
3
+ * knobs and the backdrop source). The plugin's apply-world change listener is
4
+ * the only writer; the row component reads via props.useStore.
5
+ */
6
+ import { type EngineStoreHandle } from '@deepseek-ai/dsh-client-store';
7
+ import type { PerfTier, TextStyle } from './theme-layer.ts';
8
+ /** Store state mirrored from the Mineradio settings scope. */
9
+ export interface MineradioRowState {
10
+ /** Persisted layer enable flag. */
11
+ enabled: boolean;
12
+ /** Rendering mode: mica or stock layout with generic glass. */
13
+ mode: 'mica' | 'compat';
14
+ /** Global text-ink tint preset. */
15
+ textStyle: TextStyle;
16
+ /** Glass blur radius, px. */
17
+ blur: number;
18
+ /** Glass frost amount, 0-100. */
19
+ frost: number;
20
+ /** Fluid hue, degrees (0-360, continuous). */
21
+ fluidHue: number;
22
+ /** Fluid depth, 0-100 (continuous). */
23
+ fluidDepth: number;
24
+ /** Glass dispersion tint hue, degrees (0-360, continuous). */
25
+ dispersionHue: number;
26
+ /** Glass refraction strength, 0-100. */
27
+ dispersionRefract: number;
28
+ /** Background brightness, 0-100. */
29
+ bgBrightness: number;
30
+ /** Resolved palette is dark (brightness knob = darkening half). */
31
+ dark: boolean;
32
+ /** Backdrop source: fluid board or custom wallpaper. */
33
+ background: 'fluid' | 'wallpaper';
34
+ /** Wallpaper image data URL. */
35
+ wallpaper: string;
36
+ /** Auto-derive the accent hue from the wallpaper. */
37
+ autoTint: boolean;
38
+ /** Particle whale in the chat area center. */
39
+ whale: boolean;
40
+ /** Ambient star particles. */
41
+ critters: boolean;
42
+ /** Interactive mesh (the site's dot-grid with pointer repel). */
43
+ mesh: boolean;
44
+ /** Star-river particle density, 0-100. */
45
+ starDensity: number;
46
+ /** Cursor spotlight glow following the pointer over the glass panes. */
47
+ spotlight: boolean;
48
+ /** Hover press-down for the glass panes. */
49
+ press: boolean;
50
+ /** Audio reactivity (mic-driven backdrop pulse). */
51
+ audioReact: boolean;
52
+ /** Wallpaper blur radius, px. */
53
+ wallpaperBlur: number;
54
+ /** Wallpaper frost veil, 0-100. */
55
+ wallpaperFrost: number;
56
+ /** Frosted-glass mask over the wallpaper (readability veil + stronger blur). */
57
+ wallpaperMask: boolean;
58
+ /** Frost mask blur radius, px. */
59
+ wallpaperMaskBlur: number;
60
+ /** Frost mask veil opacity, 0-100. */
61
+ wallpaperMaskOpacity: number;
62
+ /** Video wallpaper blur radius, px. */
63
+ videoBlur: number;
64
+ /** Video wallpaper brightness, 0-100. */
65
+ videoBrightness: number;
66
+ /** Performance gate. */
67
+ perf: PerfTier;
68
+ /** Rainbow fluid drift. */
69
+ rainbow: boolean;
70
+ /** Monotonic revision; -1 until first sync so revision 0 lands as a change. */
71
+ revision: number;
72
+ }
73
+ /** The full payload the layer pushes into the row store on every change. */
74
+ export interface MineradioSettingsPayload {
75
+ enabled: boolean;
76
+ mode: 'mica' | 'compat';
77
+ textStyle: TextStyle;
78
+ blur: number;
79
+ frost: number;
80
+ fluidHue: number;
81
+ fluidDepth: number;
82
+ dispersionHue: number;
83
+ dispersionRefract: number;
84
+ bgBrightness: number;
85
+ dark: boolean;
86
+ background: 'fluid' | 'wallpaper';
87
+ wallpaper: string;
88
+ autoTint: boolean;
89
+ whale: boolean;
90
+ critters: boolean;
91
+ mesh: boolean;
92
+ starDensity: number;
93
+ spotlight: boolean;
94
+ press: boolean;
95
+ audioReact: boolean;
96
+ wallpaperBlur: number;
97
+ wallpaperFrost: number;
98
+ wallpaperMask: boolean;
99
+ wallpaperMaskBlur: number;
100
+ wallpaperMaskOpacity: number;
101
+ videoBlur: number;
102
+ videoBrightness: number;
103
+ perf: PerfTier;
104
+ rainbow: boolean;
105
+ }
106
+ /** Declared action shape giving the exported factory a stable return type. */
107
+ type MineradioRowActions = {
108
+ sync: (draft: MineradioRowState, next: MineradioSettingsPayload, revision: number) => void;
109
+ };
110
+ /**
111
+ * Declares the Mineradio row state and write surface.
112
+ * @returns the store handle.
113
+ */
114
+ export declare function createMineradioRowStore(): EngineStoreHandle<MineradioRowState, MineradioRowActions>;
115
+ export {};
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Attach the specular parallax feed.
3
+ * @returns a disposer that drops listeners and inline vars.
4
+ */
5
+ export declare function startSpecularParallax(): () => void;
@@ -0,0 +1,52 @@
1
+ /**
2
+ * Spot geometry + overlay maintenance, shared by the spotlight/tilt
3
+ * controller (spotlight.ts).
4
+ *
5
+ * A "spot" is a floating-glass pane stamped with `data-dsh-aqua-spot` by the
6
+ * seam-stamper. One injected overlay lives inside a spot:
7
+ * `data-dsh-aqua-glow` — the cursor glow surface (geometry set by the hover
8
+ * controller; the radial fill lives in the stylesheet). It is re-attached
9
+ * after React re-renders wipe it (one shared MutationObserver).
10
+ */
11
+ /** Seam attribute marking a floating-glass pane as a spotlight target. */
12
+ export declare const SPOT_ATTR = "data-dsh-aqua-spot";
13
+ /** Attribute on the injected glow overlay div. */
14
+ export declare const GLOW_ATTR = "data-dsh-aqua-glow";
15
+ /** Marker set on a pane while the pointer is inside it. */
16
+ export declare const ON_ATTR = "data-spot-on";
17
+ /** Selector matching every stamped pane. */
18
+ export declare const SPOT_SELECTOR = "[data-dsh-aqua-spot]";
19
+ /** Nearest stamped pane from an event target (null when outside all panes). */
20
+ export declare function closestSpot(target: EventTarget | null): HTMLElement | null;
21
+ /** Every stamped pane in document order. */
22
+ export declare function spotElements(): HTMLElement[];
23
+ /**
24
+ * The visible glass region of a pane (viewport rect). The fused
25
+ * composer+stats spot is the wider invisible inputbar wrapper — its glass is
26
+ * the union of the composer card and the docked stats band, so the wrapper's
27
+ * side gutters stay outside every effect.
28
+ */
29
+ export declare function visualRect(spot: HTMLElement): DOMRect;
30
+ /** Is the pointer over the visible glass of the pane? */
31
+ export declare function inside(visual: DOMRect, clientX: number, clientY: number): boolean;
32
+ /**
33
+ * The visible glass region of a pane in the pane's own local space
34
+ * (untransformed — safe to measure while tilted). For the fused
35
+ * composer+stats spot this is the union of the composer card and the docked
36
+ * stats band; for the other panes it is the pane's own box.
37
+ */
38
+ export declare function glassLocalRect(spot: HTMLElement): {
39
+ left: number;
40
+ top: number;
41
+ width: number;
42
+ height: number;
43
+ };
44
+ /** Ensure the pane carries exactly one glow overlay div. */
45
+ export declare function ensureGlow(spot: HTMLElement): HTMLElement;
46
+ /**
47
+ * One shared observer + resize feed: keeps the glow divs glued to the panes
48
+ * through React re-renders and notifies the caller of DOM/layout changes
49
+ * (the caller coalesces the callbacks).
50
+ * @returns a disposer that removes every injected glow div.
51
+ */
52
+ export declare function startOverlayKeeper(onChange: () => void): () => void;
@@ -0,0 +1,11 @@
1
+ /** html attribute the layer uses to switch the glow effect (its toggle). */
2
+ export declare const SPOTLIGHT_ATTRIBUTE = "data-dsh-aqua-spotlight";
3
+ /** html attribute the layer uses to switch the tilt effect (its toggle). */
4
+ export declare const PRESS_ATTRIBUTE = "data-dsh-aqua-press";
5
+ /**
6
+ * Attach the delegated pointer feeds. Everything is document-level: no
7
+ * per-pane listeners, and the rAF merge collapses pointermove bursts to one
8
+ * style write per frame.
9
+ * @returns a disposer that drops listeners, overlays, and inline styles.
10
+ */
11
+ export declare function startSpotlight(): () => void;
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Mineradio-style particle stage — a from-scratch Canvas 2D re-creation of the
3
+ * music player's signature backdrop motion (no code copied from the player):
4
+ *
5
+ * 1. STAR RIVER — hundreds of dust points organised in horizontal "bands"
6
+ * that drift sideways while sine waves carry them up/down. Cool
7
+ * blue→violet particles with a warm champagne ridge per band, plus a
8
+ * slow twinkle. Reads as a slow galaxy river flowing behind the glass.
9
+ * 2. POINTER FIELD — particles near the cursor brighten and swell, like
10
+ * the player's silk cover reacting to the mouse.
11
+ * 3. RIPPLES — a click drops a ripple: particles ride the expanding ring
12
+ * outwards and flash brighter, then everything settles back.
13
+ *
14
+ * Performance discipline: fixed particle cap, DPR capped at 1.5, sprite-based
15
+ * rendering (one pre-baked radial dot per colour, no per-particle gradients),
16
+ * `requestAnimationFrame` loop paused on `visibilitychange`, and a single
17
+ * static frame under `prefers-reduced-motion`.
18
+ */
19
+ /** Public knob: dark scheme runs the full galaxy, light scheme dims it. */
20
+ export interface StarRiverOptions {
21
+ dark: boolean;
22
+ /** Particle density, 0-100 (50 = 1× the default field, 100 = 2×). */
23
+ density?: number;
24
+ /** Respect the OS reduced-motion preference by rendering one static frame
25
+ * instead of animating. OFF by default: the star river is the skin's
26
+ * signature motion, so it animates unless an app-level switch opts in to
27
+ * accessibility static frames. */
28
+ respectReducedMotion?: boolean;
29
+ }
30
+ /** Handle returned by {@link mountStarRiver}. */
31
+ export interface StarRiverHandle {
32
+ /** Update the scheme knob. */
33
+ setDark(dark: boolean): void;
34
+ /** Update the particle density (0-100) and rebuild the field live. */
35
+ setDensity(density: number): void;
36
+ /** Audio reactivity: bass `low` drives the hop, treble `high` the sparkle. */
37
+ setAudio(low: number, high: number): void;
38
+ /** Tear the stage down (canvas, listeners, animation). */
39
+ dispose(): void;
40
+ }
41
+ /** Mount the particle stage inside the ambient container. Idempotent: a
42
+ * second call reuses the existing canvas. */
43
+ export declare function mountStarRiver(ambient: HTMLElement, options: StarRiverOptions): StarRiverHandle;