@code-of-chaos/dither 0.0.0-stage → 0.2.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/README.md CHANGED
@@ -1,3 +1,217 @@
1
- # Temporary Holding Version
1
+ # Dither.Js
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ Framework-agnostic animated bitmap-dithered gradient backgrounds - plain
4
+ TypeScript, DOM and CSS - with a tileable Perlin/fBm noise engine for
5
+ generating your own dither tiles.
6
+
7
+ The texture is a real Bayer-dithered noise bitmap (Perlin islands + fine
8
+ detail), generated once on a canvas and scrolled with a GPU-friendly CSS
9
+ transform. Everything visual - colors, grid, fade, speed, direction - is an
10
+ option, driven through CSS custom properties so it can be animated at runtime.
11
+
12
+ ## Install
13
+
14
+ ```sh
15
+ npm install @code-of-chaos/dither
16
+ ```
17
+
18
+ ## Usage
19
+
20
+ ```ts
21
+ import { DitherBackground } from "@code-of-chaos/dither";
22
+ import "@code-of-chaos/dither/style.css";
23
+
24
+ const background = new DitherBackground({ noiseColor: "var(--accent)" });
25
+ background.mount(document.getElementById("root")!);
26
+
27
+ // Animate at runtime - cheap, the tile only rebuilds for tile inputs:
28
+ background.update({ gridSize: 64, noiseOpacity: 0.4 });
29
+
30
+ // Revert the element to its unmounted state:
31
+ background.destroy();
32
+ ```
33
+
34
+ `mount()` decorates the element: it prepends the hidden background layers
35
+ and applies the CSS custom properties. Anything else in the element renders
36
+ above the layers, so frameworks keep rendering their children normally.
37
+
38
+ ### Framework recipes
39
+
40
+ React (class, OOP):
41
+
42
+ ```tsx
43
+ import { Component, createRef, type ReactNode } from "react";
44
+ import {
45
+ DitherBackground,
46
+ type DitherBackgroundOptions,
47
+ } from "@code-of-chaos/dither";
48
+ import "@code-of-chaos/dither/style.css";
49
+
50
+ type Props = { options?: DitherBackgroundOptions; children?: ReactNode };
51
+
52
+ export class DitherBackdrop extends Component<Props> {
53
+ private ref = createRef<HTMLDivElement>();
54
+ private background?: DitherBackground;
55
+
56
+ override componentDidMount(): void {
57
+ this.background = new DitherBackground(this.props.options);
58
+ this.background.mount(this.ref.current!);
59
+ }
60
+
61
+ override componentDidUpdate(prev: Props): void {
62
+ if (prev.options !== this.props.options) {
63
+ this.background?.update(this.props.options ?? {});
64
+ }
65
+ }
66
+
67
+ override componentWillUnmount(): void {
68
+ this.background?.destroy();
69
+ }
70
+
71
+ override render(): ReactNode {
72
+ return <div ref={this.ref}>{this.props.children}</div>;
73
+ }
74
+ }
75
+ ```
76
+
77
+ Next.js: the tile needs a browser canvas - mount inside a client component
78
+ (`"use client"`) or in `useEffect`.
79
+
80
+ Angular (directive):
81
+
82
+ ```ts
83
+ @Directive({ selector: "[ditherBackground]" })
84
+ export class DitherBackgroundDirective
85
+ implements AfterViewInit, OnChanges, OnDestroy
86
+ {
87
+ @Input() ditherBackground: DitherBackgroundOptions = {};
88
+
89
+ private background?: DitherBackground;
90
+
91
+ constructor(private el: ElementRef<HTMLElement>) {}
92
+
93
+ ngAfterViewInit(): void {
94
+ this.background = new DitherBackground(this.ditherBackground);
95
+ this.background.mount(this.el.nativeElement);
96
+ }
97
+
98
+ ngOnChanges(): void {
99
+ this.background?.update(this.ditherBackground);
100
+ }
101
+
102
+ ngOnDestroy(): void {
103
+ this.background?.destroy();
104
+ }
105
+ }
106
+ ```
107
+
108
+ Vue (composable):
109
+
110
+ ```ts
111
+ export function useDitherBackground(
112
+ el: Ref<HTMLElement | null>,
113
+ options: Ref<DitherBackgroundOptions>,
114
+ ) {
115
+ let background: DitherBackground | undefined;
116
+
117
+ onMounted(() => {
118
+ background = new DitherBackground(options.value);
119
+ background.mount(el.value!);
120
+ });
121
+ watch(options, (next) => background?.update(next), { deep: true });
122
+ onBeforeUnmount(() => background?.destroy());
123
+ }
124
+ ```
125
+
126
+ Svelte (action):
127
+
128
+ ```ts
129
+ export function dither(
130
+ node: HTMLElement,
131
+ options: DitherBackgroundOptions = {},
132
+ ) {
133
+ const background = new DitherBackground(options);
134
+ background.mount(node);
135
+ return {
136
+ update: (next: DitherBackgroundOptions) => background.update(next),
137
+ destroy: () => background.destroy(),
138
+ };
139
+ }
140
+ ```
141
+
142
+ Every visual option is optional (defaults in parentheses):
143
+
144
+ | Option | Purpose |
145
+ | --------------------------------------------------------------- | --------------------------------------------------------------------------- |
146
+ | `backgroundColor` | Base fill, any CSS color or gradient |
147
+ | `gridColor`, `gridSize`, `gridOpacity` | Structural grid lines (steel, 41px, 0.23) |
148
+ | `noiseColor`, `noiseOpacity` | Dither tile color and layer opacity (scarlet, 0.5) |
149
+ | `noiseSize` | Displayed size of each dither pixel in px (3) |
150
+ | `noiseDensity`, `noiseContrast`, `noiseMaxFill`, `noiseJitter` | Dither character: fill amount, hardness, density cap, Bayer/random mix |
151
+ | `noiseScale`, `noiseOctaves` | Island field (clump size, fBm depth) |
152
+ | `noiseDetailScale`, `noiseDetailOctaves`, `noiseDetailStrength` | Fine detail field layered on the islands |
153
+ | `noiseClampLow`, `noiseClampHigh` | Soft-clamp the noise: clean voids low, no saturation high |
154
+ | `noiseTileCells`, `noiseSeed` | Tile resolution and reproducible randomness |
155
+ | `noiseSpeed`, `noiseAngle`, `noiseTravel` | Scroll animation: seconds per loop, direction in degrees, distance in tiles |
156
+ | `fadeStart`, `fadeEnd` | Vertical fade of the dither layer (0%, 90%) |
157
+ | `animateNoise`, `animateGlow` | Enable the scroll / ambient glow (both on) |
158
+
159
+ Colors accept `var(--token, fallback)` references; they are resolved against
160
+ the document root, so theme variables work as parameters.
161
+
162
+ ## Lower-level pieces
163
+
164
+ - `DitherTile` - generates a seamless Bayer-dithered PNG data URL from the
165
+ noise fields; use it for static overlays and textures.
166
+ - `DitherBackgroundView` - resolves options to defaults and computes the CSS
167
+ custom properties; useful when writing a thin framework wrapper.
168
+ - `PerlinNoise` / `FractalBrownianNoise` - tileable gradient noise.
169
+ - `MathUtils` / `RgbColor` - helpers used by the engine.
170
+
171
+ ## Development
172
+
173
+ ```sh
174
+ npm install
175
+ npm run dev # playground at demo/
176
+ npm test # vitest
177
+ npm run lint # biome
178
+ npm run build # dist/ (ESM + types + style.css)
179
+ ```
180
+
181
+ ## Releasing
182
+
183
+ Releases use npm staged publishing with a stage-only token: CI stages the
184
+ version but can never publish directly (a leaked token cannot release a
185
+ version on its own).
186
+
187
+ 1. Bump `version` in `package.json` (semver).
188
+ 2. Tag and push: `git tag vX.Y.Z && git push origin vX.Y.Z`.
189
+ 3. The release workflow verifies the tag matches the package version, runs
190
+ `npm stage publish --provenance` (needs an `NPM_TOKEN` repository secret
191
+ holding a stage-only token) and creates a GitHub release.
192
+ 4. A maintainer reviews and approves the staged version - with 2FA, either:
193
+ - CLI: `npm stage list` to find the stage id, then
194
+ `npm stage approve <stage-id>`
195
+ - or the "Staged Packages" tab on npmjs.com and click Approve
196
+
197
+ The version becomes installable only after approval. Discard a bad stage
198
+ with `npm stage reject <stage-id>`.
199
+
200
+ Notes:
201
+
202
+ - `npm stage publish` does not prompt for 2FA - proof of presence is deferred
203
+ to the approval step. Requires npm CLI 11.15+ (Node 22.14+).
204
+ - The first release creates the package (shown as a `0.0.0-stage` placeholder)
205
+ until the staged version is approved.
206
+ - Direct `npm publish` with the stage-only token fails with `E_STAGE_REQUIRED`.
207
+
208
+ ## Notes
209
+
210
+ - The tile is generated in the browser (canvas), so mounting is client-side
211
+ only.
212
+ - `prefers-reduced-motion` disables the animations.
213
+ - Zero runtime dependencies; plain TypeScript + DOM + CSS.
214
+
215
+ ## License
216
+
217
+ GPL-3.0-only (see `LICENSE`).
@@ -0,0 +1,37 @@
1
+ import "./DitherBackground.css";
2
+ import type { DitherBackgroundOptions } from "./DitherBackgroundView";
3
+ /**
4
+ * Framework-agnostic layered background: a scrolling Bayer-dithered noise
5
+ * texture, a static grid and an optional ambient glow. Plain DOM — mount it
6
+ * on any element from any framework (or none).
7
+ *
8
+ * `mount()` decorates the container: it prepends the hidden layer elements
9
+ * and applies the base class plus the CSS custom properties. Anything else
10
+ * in the container renders above the layers, so frameworks keep rendering
11
+ * their children normally. Options map 1:1 to the CSS custom properties and
12
+ * can be changed at any time via `update()`; the dither bitmap is only
13
+ * regenerated when one of the tile inputs changes.
14
+ *
15
+ * The tile is generated on a canvas, so `mount()` requires a browser DOM.
16
+ */
17
+ export declare class DitherBackground {
18
+ static readonly ROOT_CLASS = "dither-grid-background";
19
+ static readonly ANIMATED_CLASS = "dither-grid-background--animated";
20
+ static readonly GLOW_CLASS = "dither-grid-background--glow";
21
+ private view;
22
+ private noiseImage;
23
+ private root;
24
+ private layers;
25
+ constructor(options?: DitherBackgroundOptions);
26
+ /** Decorates `container` with the background layers. Idempotent per instance. */
27
+ mount(container: HTMLElement): void;
28
+ /** Merges new options; regenerates the tile only when tile inputs change. */
29
+ update(partial: DitherBackgroundOptions): void;
30
+ /** Removes the layers and reverts the container to its unmounted state. */
31
+ destroy(): void;
32
+ /** The decorated container element, or `null` before mount / after destroy. */
33
+ get element(): HTMLElement | null;
34
+ private apply;
35
+ private createNoiseImage;
36
+ }
37
+ //# sourceMappingURL=DitherBackground.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DitherBackground.d.ts","sourceRoot":"","sources":["../src/DitherBackground.ts"],"names":[],"mappings":"AAAA,OAAO,wBAAwB,CAAC;AAEhC,OAAO,KAAK,EAER,uBAAuB,EAC1B,MAAM,wBAAwB,CAAC;AAGhC;;;;;;;;;;;;;GAaG;AACH,qBAAa,gBAAgB;IACzB,MAAM,CAAC,QAAQ,CAAC,UAAU,4BAA4B;IACtD,MAAM,CAAC,QAAQ,CAAC,cAAc,sCAAsC;IACpE,MAAM,CAAC,QAAQ,CAAC,UAAU,kCAAkC;IAE5D,OAAO,CAAC,IAAI,CAAuB;IACnC,OAAO,CAAC,UAAU,CAAM;IACxB,OAAO,CAAC,IAAI,CAA4B;IACxC,OAAO,CAAC,MAAM,CAAqB;IAEnC,YAAY,OAAO,GAAE,uBAA4B,EAEhD;IAED,iFAAiF;IACjF,KAAK,CAAC,SAAS,EAAE,WAAW,GAAG,IAAI,CAsBlC;IAED,6EAA6E;IAC7E,MAAM,CAAC,OAAO,EAAE,uBAAuB,GAAG,IAAI,CAQ7C;IAED,2EAA2E;IAC3E,OAAO,IAAI,IAAI,CAkBd;IAED,+EAA+E;IAC/E,IAAI,OAAO,IAAI,WAAW,GAAG,IAAI,CAEhC;IAED,OAAO,CAAC,KAAK;IAsBb,OAAO,CAAC,gBAAgB;CAG3B"}
@@ -0,0 +1,65 @@
1
+ import type { DitherTileOptions } from "./DitherTile";
2
+ /**
3
+ * Every visual knob of a dither background. All fields are optional and fall
4
+ * back to `DitherBackgroundView.DEFAULTS`. Values are applied as CSS custom
5
+ * properties, so they can be animated at runtime without rebuilding the
6
+ * background; only `DitherBackgroundView.TILE_INPUTS` regenerate the dither
7
+ * bitmap itself.
8
+ */
9
+ export type DitherBackgroundOptions = {
10
+ backgroundColor?: string;
11
+ gridColor?: string;
12
+ gridSize?: number;
13
+ gridOpacity?: number;
14
+ noiseColor?: string;
15
+ noiseOpacity?: number;
16
+ noiseSize?: number;
17
+ noiseTileCells?: number;
18
+ noiseDensity?: number;
19
+ noiseContrast?: number;
20
+ noiseScale?: number;
21
+ noiseOctaves?: number;
22
+ noiseDetailScale?: number;
23
+ noiseDetailOctaves?: number;
24
+ noiseDetailStrength?: number;
25
+ noiseClampLow?: number;
26
+ noiseClampHigh?: number;
27
+ noiseSeed?: number;
28
+ noiseMaxFill?: number;
29
+ noiseJitter?: number;
30
+ noiseSpeed?: number;
31
+ noiseAngle?: number;
32
+ noiseTravel?: number;
33
+ fadeStart?: number;
34
+ fadeEnd?: number;
35
+ animateNoise?: boolean;
36
+ animateGlow?: boolean;
37
+ };
38
+ export type DitherBackgroundCssVars = Record<`--${string}`, string>;
39
+ /**
40
+ * Resolves `DitherBackgroundOptions` against the defaults and computes the
41
+ * derived values (tile geometry, scroll travel, CSS custom properties). Used
42
+ * internally by `DitherBackground`; framework wrappers can use it standalone.
43
+ */
44
+ export declare class DitherBackgroundView {
45
+ static readonly DEFAULTS: Required<DitherBackgroundOptions>;
46
+ /** Options that affect the generated tile; all others only set CSS variables. */
47
+ static readonly TILE_INPUTS: ReadonlyArray<keyof DitherBackgroundOptions>;
48
+ readonly options: Required<DitherBackgroundOptions>;
49
+ constructor(options?: DitherBackgroundOptions);
50
+ /** Returns a new view with `partial` merged in; `undefined` values are ignored. */
51
+ merge(partial: DitherBackgroundOptions): DitherBackgroundView;
52
+ /** True when the two views would produce different dither tiles. */
53
+ rebuildsTile(other: DitherBackgroundView): boolean;
54
+ tileOptions(): DitherTileOptions;
55
+ get tileSize(): number;
56
+ /** Horizontal scroll distance in px, snapped to whole tiles (seamless loop). */
57
+ get travelX(): number;
58
+ /** Vertical scroll distance in px, snapped to whole tiles (seamless loop). */
59
+ get travelY(): number;
60
+ /** Oversizes the texture wrapper so the scroll never exposes its edges. */
61
+ get overscan(): number;
62
+ cssVars(noiseImage: string): DitherBackgroundCssVars;
63
+ private static defined;
64
+ }
65
+ //# sourceMappingURL=DitherBackgroundView.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DitherBackgroundView.d.ts","sourceRoot":"","sources":["../src/DitherBackgroundView.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAGtD;;;;;;GAMG;AACH,MAAM,MAAM,uBAAuB,GAAG;IAClC,eAAe,CAAC,EAAE,MAAM,CAAC;IAEzB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,WAAW,CAAC,EAAE,OAAO,CAAC;CACzB,CAAC;AAEF,MAAM,MAAM,uBAAuB,GAAG,MAAM,CAAC,KAAK,MAAM,EAAE,EAAE,MAAM,CAAC,CAAC;AAEpE;;;;GAIG;AACH,qBAAa,oBAAoB;IAC7B,MAAM,CAAC,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC,uBAAuB,CAAC,CAiCzD;IAEF,iFAAiF;IACjF,MAAM,CAAC,QAAQ,CAAC,WAAW,EAAE,aAAa,CAAC,MAAM,uBAAuB,CAAC,CAgBnE;IAEN,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC,uBAAuB,CAAC,CAAC;IAEpD,YAAY,OAAO,GAAE,uBAA4B,EAKhD;IAED,mFAAmF;IACnF,KAAK,CAAC,OAAO,EAAE,uBAAuB,GAAG,oBAAoB,CAK5D;IAED,oEAAoE;IACpE,YAAY,CAAC,KAAK,EAAE,oBAAoB,GAAG,OAAO,CAIjD;IAED,WAAW,IAAI,iBAAiB,CAkB/B;IAED,IAAI,QAAQ,IAAI,MAAM,CAErB;IAED,gFAAgF;IAChF,IAAI,OAAO,IAAI,MAAM,CAMpB;IAED,8EAA8E;IAC9E,IAAI,OAAO,IAAI,MAAM,CAMpB;IAED,2EAA2E;IAC3E,IAAI,QAAQ,IAAI,MAAM,CAKrB;IAED,OAAO,CAAC,UAAU,EAAE,MAAM,GAAG,uBAAuB,CAqBnD;IAED,OAAO,CAAC,MAAM,CAAC,OAAO;CAQzB"}
@@ -0,0 +1,42 @@
1
+ /**
2
+ * All visual knobs of the tile. `scale`/`octaves` shape the large island
3
+ * field, `detail*` the fine detail field; `clampLow`/`clampHigh` soft-clip
4
+ * the blend (clean voids at the low end, no saturation at the high end),
5
+ * `maxFill` caps how dense the dither can get, and `jitter` blends the
6
+ * Bayer threshold with per-pixel random values for an organic look.
7
+ */
8
+ export type DitherTileOptions = {
9
+ cells: number;
10
+ color: string;
11
+ density: number;
12
+ contrast: number;
13
+ scale: number;
14
+ octaves: number;
15
+ detailScale: number;
16
+ detailOctaves: number;
17
+ detailStrength: number;
18
+ clampLow: number;
19
+ clampHigh: number;
20
+ seed: number;
21
+ maxFill: number;
22
+ jitter: number;
23
+ };
24
+ /**
25
+ * Renders a seamless dithered noise tile as a PNG data URL.
26
+ *
27
+ * Per pixel: the island and detail noise fields are blended into a density
28
+ * value, soft-clamped, then thresholded against a Bayer matrix mixed with
29
+ * per-pixel jitter to decide whether the pixel is inked. Because the noise
30
+ * fields tile seamlessly, the resulting image can be repeated and scrolled
31
+ * forever without visible seams.
32
+ */
33
+ export declare class DitherTile {
34
+ private readonly options;
35
+ static readonly DEFAULT_CELLS = 512;
36
+ private static readonly BAYER_4X4;
37
+ private readonly islands;
38
+ private readonly detail;
39
+ constructor(options: DitherTileOptions);
40
+ toDataURL(): string;
41
+ }
42
+ //# sourceMappingURL=DitherTile.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DitherTile.d.ts","sourceRoot":"","sources":["../src/DitherTile.ts"],"names":[],"mappings":"AAIA;;;;;;GAMG;AACH,MAAM,MAAM,iBAAiB,GAAG;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;IACtB,cAAc,EAAE,MAAM,CAAC;IACvB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF;;;;;;;;GAQG;AACH,qBAAa,UAAU;IAaP,OAAO,CAAC,QAAQ,CAAC,OAAO;IAZpC,MAAM,CAAC,QAAQ,CAAC,aAAa,OAAO;IAEpC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,CAKc;IAE/C,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAuB;IAC/C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAuB;IAE9C,YAA6B,OAAO,EAAE,iBAAiB,EAatD;IAED,SAAS,IAAI,MAAM,CA+DlB;CACJ"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Fractal Brownian motion: stacks PerlinNoise octaves with halved amplitude
3
+ * and doubled frequency per octave. Coordinates are expressed in tile cells,
4
+ * keeping every octave (and therefore the whole field) seamlessly tileable.
5
+ * Output is normalized to [0, 1].
6
+ */
7
+ export declare class FractalBrownianNoise {
8
+ private readonly octaves;
9
+ private readonly totalAmplitude;
10
+ constructor(cells: number, scale: number, octaves: number, seed: number);
11
+ sample(x: number, y: number): number;
12
+ }
13
+ //# sourceMappingURL=FractalBrownianNoise.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FractalBrownianNoise.d.ts","sourceRoot":"","sources":["../src/FractalBrownianNoise.ts"],"names":[],"mappings":"AAWA;;;;;GAKG;AACH,qBAAa,oBAAoB;IAC7B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAgB;IACxC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAS;IAExC,YAAY,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAkBtE;IAED,MAAM,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAanC;CACJ"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Small math helpers used by the noise and dither pipeline.
3
+ * The standard Math library has no clamp/lerp/smoothstep/mod equivalents.
4
+ */
5
+ export declare class MathUtils {
6
+ static clamp(value: number, min: number, max: number): number;
7
+ static lerp(a: number, b: number, t: number): number;
8
+ static smoothstep(edge0: number, edge1: number, x: number): number;
9
+ static mod(value: number, period: number): number;
10
+ static hash2(x: number, y: number, seed: number): number;
11
+ }
12
+ //# sourceMappingURL=MathUtils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MathUtils.d.ts","sourceRoot":"","sources":["../src/MathUtils.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,qBAAa,SAAS;IAClB,MAAM,CAAC,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAE5D;IAED,MAAM,CAAC,IAAI,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAEnD;IAED,MAAM,CAAC,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAGjE;IAED,MAAM,CAAC,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAEhD;IAED,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAQvD;CACJ"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Tileable 2D Perlin gradient noise. Lattice coordinates wrap at `period`,
3
+ * so sampling the [0, period) cell range produces a seamless tile.
4
+ * Raw output is roughly in [-1, 1] (see FractalBrownianNoise for normalized values).
5
+ */
6
+ export declare class PerlinNoise {
7
+ private readonly period;
8
+ private readonly seed;
9
+ private static readonly GRADIENTS;
10
+ constructor(period: number, seed: number);
11
+ sample(x: number, y: number): number;
12
+ private gradientDot;
13
+ }
14
+ //# sourceMappingURL=PerlinNoise.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PerlinNoise.d.ts","sourceRoot":"","sources":["../src/PerlinNoise.ts"],"names":[],"mappings":"AAEA;;;;GAIG;AACH,qBAAa,WAAW;IAShB,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,IAAI;IATzB,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,CAK9B;IAEH,YACqB,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EAC7B;IAEJ,MAAM,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAwBnC;IAED,OAAO,CAAC,WAAW;CAetB"}
@@ -0,0 +1,18 @@
1
+ /** Immutable RGB triple with CSS color parsing. */
2
+ export declare class RgbColor {
3
+ readonly r: number;
4
+ readonly g: number;
5
+ readonly b: number;
6
+ constructor(r: number, g: number, b: number);
7
+ /**
8
+ * Parses any CSS color (named, hex, rgb()/rgba()) by letting the canvas
9
+ * resolve it: assigning to fillStyle normalizes the value to a canonical
10
+ * string which is then read back. Falls back to white on invalid input.
11
+ *
12
+ * A single var(--token, fallback) reference is resolved against the
13
+ * document root first, so theme variables can be used as color parameters.
14
+ */
15
+ static fromCss(ctx: CanvasRenderingContext2D, css: string): RgbColor;
16
+ private static resolveVariable;
17
+ }
18
+ //# sourceMappingURL=RgbColor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RgbColor.d.ts","sourceRoot":"","sources":["../src/RgbColor.ts"],"names":[],"mappings":"AAAA,mDAAmD;AACnD,qBAAa,QAAQ;IAEb,QAAQ,CAAC,CAAC,EAAE,MAAM;IAClB,QAAQ,CAAC,CAAC,EAAE,MAAM;IAClB,QAAQ,CAAC,CAAC,EAAE,MAAM;IAHtB,YACa,CAAC,EAAE,MAAM,EACT,CAAC,EAAE,MAAM,EACT,CAAC,EAAE,MAAM,EAClB;IAEJ;;;;;;;OAOG;IACH,MAAM,CAAC,OAAO,CAAC,GAAG,EAAE,wBAAwB,EAAE,GAAG,EAAE,MAAM,GAAG,QAAQ,CAgCnE;IAED,OAAO,CAAC,MAAM,CAAC,eAAe;CAWjC"}
@@ -0,0 +1,10 @@
1
+ export { DitherBackground } from "./DitherBackground";
2
+ export type { DitherBackgroundCssVars, DitherBackgroundOptions, } from "./DitherBackgroundView";
3
+ export { DitherBackgroundView } from "./DitherBackgroundView";
4
+ export type { DitherTileOptions } from "./DitherTile";
5
+ export { DitherTile } from "./DitherTile";
6
+ export { FractalBrownianNoise } from "./FractalBrownianNoise";
7
+ export { MathUtils } from "./MathUtils";
8
+ export { PerlinNoise } from "./PerlinNoise";
9
+ export { RgbColor } from "./RgbColor";
10
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,YAAY,EACR,uBAAuB,EACvB,uBAAuB,GAC1B,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAC9D,YAAY,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AACtD,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAC9D,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC"}