fancy-ui-react 0.2.1 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +56 -20
- package/dist/components/animated-beam/AnimatedBeam.d.ts +47 -11
- package/dist/components/animated-beam/AnimatedBeam.js +293 -118
- package/dist/components/animated-tooltip/AnimatedTooltip.d.ts +10 -1
- package/dist/components/animated-tooltip/AnimatedTooltip.js +170 -101
- package/dist/components/bento-grid/BentoFrame.d.ts +16 -0
- package/dist/components/bento-grid/BentoFrame.js +28 -0
- package/dist/components/bento-grid/BentoGrid.d.ts +5 -1
- package/dist/components/bento-grid/BentoGrid.js +71 -2
- package/dist/components/bento-grid/BentoGridCard.js +34 -26
- package/dist/components/bento-grid/BentoGridItem.js +10 -10
- package/dist/components/border-beam/BorderBeam.d.ts +55 -10
- package/dist/components/border-beam/BorderBeam.js +93 -16
- package/dist/components/button/Button.js +5 -1
- package/dist/components/compare/Compare.d.ts +32 -8
- package/dist/components/compare/Compare.js +213 -95
- package/dist/components/container-scroll/ContainerScroll.d.ts +26 -4
- package/dist/components/container-scroll/ContainerScroll.js +88 -49
- package/dist/components/datamosh-transition/DatamoshTransition.d.ts +76 -0
- package/dist/components/datamosh-transition/DatamoshTransition.js +368 -0
- package/dist/components/datamosh-transition/datamosh-transition-core.d.ts +180 -0
- package/dist/components/datamosh-transition/datamosh-transition-core.js +370 -0
- package/dist/components/datamosh-transition/index.d.ts +3 -0
- package/dist/components/dock/Dock.d.ts +10 -7
- package/dist/components/dock/Dock.js +76 -31
- package/dist/components/dock/DockIcon.d.ts +14 -3
- package/dist/components/dock/DockIcon.js +23 -19
- package/dist/components/dock/DockSeparator.d.ts +4 -1
- package/dist/components/dock/DockSeparator.js +5 -2
- package/dist/components/dock/types.d.ts +13 -6
- package/dist/components/dropdown-menu/menu-shared.d.ts +11 -8
- package/dist/components/editorial-engine/engine.js +1 -14
- package/dist/components/fireworks-hdr/webgl2-renderer.js +0 -19
- package/dist/components/fireworks-hdr/webgpu-renderer.js +3 -22
- package/dist/components/flip-card/FlipCard.d.ts +42 -1
- package/dist/components/flip-card/FlipCard.js +178 -25
- package/dist/components/flip-card/index.d.ts +1 -1
- package/dist/components/fluid-cursor/FluidCursor.js +5 -4
- package/dist/components/fluid-cursor/dev.d.ts +1 -0
- package/dist/components/fluid-cursor/dev.js +8 -0
- package/dist/components/fluid-cursor/fluid-shared.d.ts +0 -2
- package/dist/components/fluid-cursor/fluid-shared.js +0 -2
- package/dist/components/fluid-cursor/webgpu-engine.js +10 -24
- package/dist/components/glow-border/GlowBorder.d.ts +41 -1
- package/dist/components/glow-border/GlowBorder.js +96 -16
- package/dist/components/glow-border/index.d.ts +2 -2
- package/dist/components/gradient-button/GradientButton.d.ts +10 -5
- package/dist/components/gradient-button/GradientButton.js +25 -18
- package/dist/components/image-trail-cursor/ImageTrailCursor.js +1 -0
- package/dist/components/image-trail-cursor/trail-variants.d.ts +37 -1
- package/dist/components/image-trail-cursor/trail-variants.js +331 -8
- package/dist/components/interactive-hover-button/InteractiveHoverButton.js +30 -35
- package/dist/components/marquee/Marquee.d.ts +7 -3
- package/dist/components/marquee/Marquee.js +134 -2
- package/dist/components/marquee/ReviewCard.d.ts +2 -1
- package/dist/components/marquee/ReviewCard.js +20 -9
- package/dist/components/meteors/Meteors.d.ts +32 -10
- package/dist/components/meteors/Meteors.js +53 -20
- package/dist/components/mosaic-glow/mosaic-glow-core.d.ts +98 -10
- package/dist/components/neon-border/NeonBorder.d.ts +24 -5
- package/dist/components/neon-border/NeonBorder.js +37 -7
- package/dist/components/pagination/Pagination.js +220 -82
- package/dist/components/rainbow-button/RainbowButton.js +13 -5
- package/dist/components/ripple-button/RippleButton.d.ts +20 -1
- package/dist/components/ripple-button/RippleButton.js +44 -21
- package/dist/components/shimmer-button/ShimmerButton.d.ts +5 -5
- package/dist/components/shimmer-button/ShimmerButton.js +17 -19
- package/dist/components/smooth-cursor/SmoothCursor.d.ts +13 -9
- package/dist/components/smooth-cursor/SmoothCursor.js +114 -163
- package/dist/components/smooth-cursor/smooth-cursor-core.d.ts +85 -0
- package/dist/components/smooth-cursor/smooth-cursor-core.js +327 -0
- package/dist/components/stepper/Step.js +32 -19
- package/dist/components/stepper/Stepper.js +18 -2
- package/dist/components/stepper/types.d.ts +13 -0
- package/dist/components/timeline/Timeline.d.ts +8 -1
- package/dist/components/timeline/Timeline.js +165 -76
- package/dist/index.d.ts +1 -0
- package/dist/index.js +6 -1
- package/dist/internals/markdown.d.ts +5 -0
- package/dist/internals/motion/haptics.d.ts +0 -4
- package/dist/internals/motion/presence-core.d.ts +59 -0
- package/dist/internals/motion/presence-core.js +162 -0
- package/dist/internals/motion/presence.d.ts +2 -4
- package/dist/internals/motion/presence.js +1 -156
- package/dist/internals/motion/raf.d.ts +1 -1
- package/dist/internals/motion/stagger.d.ts +3 -4
- package/dist/internals/motion/tokens.js +4 -0
- package/dist/internals/motion/transitions.d.ts +17 -17
- package/dist/internals/motion/types.d.ts +6 -7
- package/dist/internals/relative-time.d.ts +1 -1
- package/dist/styles.css +3545 -204
- package/package.json +18 -2
- package/dist/components/fireworks-hdr/webgpu-types.d.ts +0 -159
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DatamoshTransition core — pure math, no DOM.
|
|
3
|
+
*
|
|
4
|
+
* The look: flat blocks of saturated colour in a FIXED column grid, each column
|
|
5
|
+
* a stack of tiles falling along one sigmoid curve — slivers at the top and
|
|
6
|
+
* bottom, one fat tile snapping open through the middle. Nothing ever moves
|
|
7
|
+
* horizontally; only the vertical tiling animates.
|
|
8
|
+
*
|
|
9
|
+
* On top of that sits the transition itself: every column owns a covered band
|
|
10
|
+
* [top, bot] (0..1 of the height). Cover drops the band's bottom edge like a
|
|
11
|
+
* curtain, reveal lets its top edge fall away, columns staggered right to left.
|
|
12
|
+
*/
|
|
13
|
+
export declare const DEFAULT_COLORS: readonly ["#ffffff", "#3566ff", "#ffcf00", "#192aff", "#d62036", "#282142", "#ec4978", "#ff9900", "#14101f", "#00dd33", "#00ef82"];
|
|
14
|
+
/** Column edges sit at W·(i/N)^power: narrow left, wide right — reads as receding perspective. */
|
|
15
|
+
export declare const DEFAULT_COLUMNS = 11;
|
|
16
|
+
export declare const DEFAULT_POWER = 1.65;
|
|
17
|
+
/** Odd so exactly one tile sits dead centre and takes the whole bulge. */
|
|
18
|
+
export declare const DEFAULT_TILES = 15;
|
|
19
|
+
/** Seconds per tile step at speed 1. */
|
|
20
|
+
export declare const CYCLE = 0.2;
|
|
21
|
+
/** Seconds between neighbouring columns starting to fall (right column first). */
|
|
22
|
+
export declare const FALL_STAGGER = 0.006;
|
|
23
|
+
/** Sigmoid exponent — steepness at the centre is tile height. */
|
|
24
|
+
export declare const STRETCH = 8.5;
|
|
25
|
+
/** Exponential arrival rate inside a tile step (the "spring"). */
|
|
26
|
+
export declare const SPRING_K = 1.6;
|
|
27
|
+
/** Each tile overhangs the one below by this fraction of the height. */
|
|
28
|
+
export declare const BLEED = 0.012;
|
|
29
|
+
/** Phase offset per column, in tiles — the zig-zag. Negative: stacks ride higher to the right. */
|
|
30
|
+
export declare const COL_PHASE = -0.4;
|
|
31
|
+
/** Slope of the curve past both ends; clamping would pile off-screen tiles onto y = 0. */
|
|
32
|
+
export declare const TAIL_SLOPE = 0.05;
|
|
33
|
+
/** Length of the cyclic colour strip every column reads. */
|
|
34
|
+
export declare const STRIP_LENGTH = 61;
|
|
35
|
+
/** Small, fast, seedable PRNG (32-bit state). Same seed → same sequence. */
|
|
36
|
+
export declare function mulberry32(seed: number): () => number;
|
|
37
|
+
/** Relative luminance of a hex (#rgb / #rrggbb) or rgb() colour; null when unparseable. */
|
|
38
|
+
export declare function luminance(color: string): number | null;
|
|
39
|
+
export interface PaletteRoles {
|
|
40
|
+
/** The lightest colour — recurs most often (~a quarter of the strip). */
|
|
41
|
+
light: number;
|
|
42
|
+
/** The darkest one or two colours — the other contrast anchor. */
|
|
43
|
+
darks: number[];
|
|
44
|
+
/** Everything else. */
|
|
45
|
+
hues: number[];
|
|
46
|
+
}
|
|
47
|
+
/** Split a palette into contrast anchors and mid-tone hues by luminance. */
|
|
48
|
+
export declare function paletteRoles(colors: readonly string[]): PaletteRoles;
|
|
49
|
+
/**
|
|
50
|
+
* The cyclic colour strip, as palette indices. Light and dark anchors recur
|
|
51
|
+
* often on purpose: a fixed palette stride walks past them and leaves flat
|
|
52
|
+
* mid-tone corduroy. No two neighbours repeat, including across the wrap.
|
|
53
|
+
*/
|
|
54
|
+
export declare function buildStrip(seed: number, colors: readonly string[], len?: number): number[];
|
|
55
|
+
/** Colour for a tile, keyed by its IDENTITY (never its on-screen slot) — colours stay put. */
|
|
56
|
+
export declare function stripIndex(strip: readonly number[], id: number, column: number): number;
|
|
57
|
+
/** Column edges in device px: W·(i/N)^power, rounded. Length = columns + 1. */
|
|
58
|
+
export declare function columnEdges(width: number, columns: number, power: number): number[];
|
|
59
|
+
/** Force a usable odd tile count (≥ 3). */
|
|
60
|
+
export declare function oddTiles(tiles: number): number;
|
|
61
|
+
/**
|
|
62
|
+
* Where tile boundary `k` sits, 0..1 of the height. Sigmoid across [0, tiles],
|
|
63
|
+
* extended LINEARLY (shallow slope) past both ends rather than clamped.
|
|
64
|
+
*/
|
|
65
|
+
export declare function tileEdge(k: number, tiles: number, stretch?: number): number;
|
|
66
|
+
/**
|
|
67
|
+
* Re-time the fraction of one tile step: exponential arrival mirrored at the
|
|
68
|
+
* halfway point. Rushes in, hangs at the centre (fattest), releases. Monotonic,
|
|
69
|
+
* exact at 0 and 1, so the stack never drifts off schedule.
|
|
70
|
+
*/
|
|
71
|
+
export declare function springStep(p: number): number;
|
|
72
|
+
/**
|
|
73
|
+
* Unbounded phase of column `i` at `elapsed` seconds. Never wrapped: tile
|
|
74
|
+
* identity is derived from it, so a wrap would teleport every boundary.
|
|
75
|
+
*/
|
|
76
|
+
export declare function columnFlow(elapsed: number, column: number, columns: number, speed?: number): number;
|
|
77
|
+
export interface TileRect {
|
|
78
|
+
id: number;
|
|
79
|
+
/** Device px, unclamped. */
|
|
80
|
+
top: number;
|
|
81
|
+
/** Device px, bleed included, unclamped. */
|
|
82
|
+
bot: number;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* The tiles of one column at `flow`, ordered BOTTOM-UP (paint order): each
|
|
86
|
+
* tile overhangs the one below it by `bleed` px, so painting upward laps the
|
|
87
|
+
* overhang over the lower tile instead of hiding it under it.
|
|
88
|
+
*/
|
|
89
|
+
export declare function columnTiles(flow: number, tiles: number, height: number, bleed: number): TileRect[];
|
|
90
|
+
export type Direction = "cover" | "reveal";
|
|
91
|
+
export interface Coverage {
|
|
92
|
+
/** Covered band per column, linear 0..1 (eased only when drawn). */
|
|
93
|
+
top: Float32Array;
|
|
94
|
+
bot: Float32Array;
|
|
95
|
+
}
|
|
96
|
+
export declare function createCoverage(columns: number, covered?: boolean): Coverage;
|
|
97
|
+
/** Order in which the columns move. */
|
|
98
|
+
export type DatamoshSweep = "right" | "left" | "center" | "edges" | "random";
|
|
99
|
+
/**
|
|
100
|
+
* Delay before each column moves, in seconds. `right` starts at the rightmost
|
|
101
|
+
* column, `center` fans out from the middle, `edges` closes in from both
|
|
102
|
+
* sides, `random` is a seeded shuffle.
|
|
103
|
+
*/
|
|
104
|
+
export declare function columnDelays(columns: number, sweep: DatamoshSweep, stagger: number, seed?: number): number[];
|
|
105
|
+
/**
|
|
106
|
+
* Advance every column one step toward `direction`. Cover drops the band's
|
|
107
|
+
* bottom edge to 1 (and pulls a half-fallen top back up); reveal lets the top
|
|
108
|
+
* edge fall onto the bottom one. Monotonic per column, so an interruption just
|
|
109
|
+
* reverses from wherever each column is. Returns true once every column is done.
|
|
110
|
+
*/
|
|
111
|
+
export declare function stepCoverage(cov: Coverage, direction: Direction, phaseTime: number, dt: number, duration: number, delays: ArrayLike<number>): boolean;
|
|
112
|
+
/** Snap every column to the end of `direction`. */
|
|
113
|
+
export declare function settleCoverage(cov: Coverage, direction: Direction): void;
|
|
114
|
+
/** Ease for a band edge: cubic in-out, exact at 0 and 1. */
|
|
115
|
+
export declare function easeEdge(a: number): number;
|
|
116
|
+
/**
|
|
117
|
+
* Shape of the covered band. `curtain` drops from the top and falls away,
|
|
118
|
+
* `rise` climbs from the bottom and lifts off, `split` opens from the centre
|
|
119
|
+
* line and squeezes shut onto it, `interlace` alternates curtain and rise
|
|
120
|
+
* column by column. Everything stays vertical.
|
|
121
|
+
*/
|
|
122
|
+
export type DatamoshEffect = "curtain" | "rise" | "split" | "interlace";
|
|
123
|
+
export interface Band {
|
|
124
|
+
/** 0..1 of the height. */
|
|
125
|
+
y0: number;
|
|
126
|
+
y1: number;
|
|
127
|
+
/** Draw the tile stack upside down (tiles rise instead of fall). */
|
|
128
|
+
mirror: boolean;
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Map a column's curtain-space band `[top, bot]` (already eased) onto the
|
|
132
|
+
* screen for `effect`. Curtain space is what `stepCoverage` animates; every
|
|
133
|
+
* effect is a pure re-mapping of it, so interruptions behave the same.
|
|
134
|
+
*/
|
|
135
|
+
export declare function columnBand(effect: DatamoshEffect, column: number, top: number, bot: number): Band;
|
|
136
|
+
/** Ready-made palettes. Each keeps one light anchor and a couple of near-blacks. */
|
|
137
|
+
export declare const DATAMOSH_PALETTES: {
|
|
138
|
+
readonly broadcast: readonly ["#ffffff", "#3566ff", "#ffcf00", "#192aff", "#d62036", "#282142", "#ec4978", "#ff9900", "#14101f", "#00dd33", "#00ef82"];
|
|
139
|
+
readonly thermal: readonly ["#fff4d6", "#ffd23f", "#ff9f1c", "#ff5a1f", "#e0282e", "#b0125b", "#6a0f63", "#2a0a3d", "#0d0614"];
|
|
140
|
+
readonly sunset: readonly ["#fff6d8", "#fbc56b", "#f59a3a", "#e97a1d", "#c85a14", "#8a4a22", "#5a3b25", "#2d1c16", "#140b08"];
|
|
141
|
+
readonly mono: readonly ["#ffffff", "#e5e5e5", "#b5b5b5", "#8a8a8a", "#5c5c5c", "#2e2e2e", "#141414", "#050505"];
|
|
142
|
+
readonly acid: readonly ["#f4ffe8", "#e4ff1a", "#00ff9c", "#00e0ff", "#3d5afe", "#8c3dff", "#ff2bd6", "#1b0b36", "#070707"];
|
|
143
|
+
};
|
|
144
|
+
export type DatamoshPaletteName = keyof typeof DATAMOSH_PALETTES;
|
|
145
|
+
/** Resolve a palette name or colour list; falls back to the default for anything unusable. */
|
|
146
|
+
export declare function resolvePalette(colors: readonly string[] | DatamoshPaletteName | undefined): string[];
|
|
147
|
+
/** Largest brightness gain the `boost` auto-levels may apply. */
|
|
148
|
+
export declare const MAX_GAIN = 1.6;
|
|
149
|
+
/** Share of the picture's height the slots sample from, centred. */
|
|
150
|
+
export declare const SOURCE_SPAN = 0.6;
|
|
151
|
+
/**
|
|
152
|
+
* Height (0..1) a slot samples the picture at: spread linearly over the middle
|
|
153
|
+
* `SOURCE_SPAN` of the picture. Not along the fall's sigmoid, which packs
|
|
154
|
+
* almost every slot against the edges, and not over the full height, where
|
|
155
|
+
* frames and borders (the darkest, dullest parts of most pictures) sit.
|
|
156
|
+
*/
|
|
157
|
+
export declare function sourceSlotY(slot: number, tiles: number): number;
|
|
158
|
+
/**
|
|
159
|
+
* Which rest slot a tile's colour is sampled from. Keyed by IDENTITY, like the
|
|
160
|
+
* colour strip: a tile keeps its piece of the picture as it falls, so the
|
|
161
|
+
* image gets dragged down in chunks instead of sliding under the grid.
|
|
162
|
+
*/
|
|
163
|
+
export declare function sourceSlot(id: number, column: number, tiles: number): number;
|
|
164
|
+
/** Source rect that fits an image over a box like `object-fit: cover`. */
|
|
165
|
+
export declare function coverFit(imgW: number, imgH: number, boxW: number, boxH: number): {
|
|
166
|
+
sx: number;
|
|
167
|
+
sy: number;
|
|
168
|
+
sw: number;
|
|
169
|
+
sh: number;
|
|
170
|
+
};
|
|
171
|
+
/**
|
|
172
|
+
* Colour table `[column][slot]` sampled from an RGBA buffer that already maps
|
|
173
|
+
* onto the overlay box. Each cell averages a 3×3 neighbourhood at the column's
|
|
174
|
+
* centre and the slot's height. `edges` are column edges normalised to 0..1.
|
|
175
|
+
*
|
|
176
|
+
* With `boost` (default), the table is auto-levelled (darkest cell → black,
|
|
177
|
+
* brightest → white) and saturated, so a moody picture still decodes into the
|
|
178
|
+
* flat, saturated blocks the effect is about.
|
|
179
|
+
*/
|
|
180
|
+
export declare function sampleSource(pixels: ArrayLike<number>, pw: number, ph: number, edges: readonly number[], tiles: number, boost?: boolean): string[][];
|
|
@@ -0,0 +1,370 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
const DEFAULT_COLORS = [
|
|
3
|
+
"#ffffff",
|
|
4
|
+
"#3566ff",
|
|
5
|
+
"#ffcf00",
|
|
6
|
+
"#192aff",
|
|
7
|
+
"#d62036",
|
|
8
|
+
"#282142",
|
|
9
|
+
"#ec4978",
|
|
10
|
+
"#ff9900",
|
|
11
|
+
"#14101f",
|
|
12
|
+
"#00dd33",
|
|
13
|
+
"#00ef82"
|
|
14
|
+
];
|
|
15
|
+
const DEFAULT_COLUMNS = 11;
|
|
16
|
+
const DEFAULT_POWER = 1.65;
|
|
17
|
+
const DEFAULT_TILES = 15;
|
|
18
|
+
const CYCLE = 0.2;
|
|
19
|
+
const FALL_STAGGER = 6e-3;
|
|
20
|
+
const STRETCH = 8.5;
|
|
21
|
+
const BLEED = 0.012;
|
|
22
|
+
const COL_PHASE = -0.4;
|
|
23
|
+
const TAIL_SLOPE = 0.05;
|
|
24
|
+
const STRIP_LENGTH = 61;
|
|
25
|
+
function mulberry32(seed) {
|
|
26
|
+
let a = seed >>> 0;
|
|
27
|
+
return () => {
|
|
28
|
+
a = a + 1831565813 >>> 0;
|
|
29
|
+
let t = a;
|
|
30
|
+
t = Math.imul(t ^ t >>> 15, t | 1);
|
|
31
|
+
t ^= t + Math.imul(t ^ t >>> 7, t | 61);
|
|
32
|
+
return ((t ^ t >>> 14) >>> 0) / 4294967296;
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
function luminance(color) {
|
|
36
|
+
const s = color.trim().toLowerCase();
|
|
37
|
+
let rgb = null;
|
|
38
|
+
const hex = s.match(/^#([0-9a-f]{3}|[0-9a-f]{6})$/);
|
|
39
|
+
if (hex) {
|
|
40
|
+
const h = hex[1];
|
|
41
|
+
const full = h.length === 3 ? h.split("").map((c) => c + c).join("") : h;
|
|
42
|
+
rgb = [0, 2, 4].map((i) => parseInt(full.slice(i, i + 2), 16));
|
|
43
|
+
} else {
|
|
44
|
+
const m = s.match(/^rgba?\(\s*(\d+)[\s,]+(\d+)[\s,]+(\d+)/);
|
|
45
|
+
if (m) rgb = [Number(m[1]), Number(m[2]), Number(m[3])];
|
|
46
|
+
}
|
|
47
|
+
if (!rgb) return null;
|
|
48
|
+
const [r, g, b] = rgb.map((v) => {
|
|
49
|
+
const c = Math.min(255, v) / 255;
|
|
50
|
+
return c <= 0.04045 ? c / 12.92 : ((c + 0.055) / 1.055) ** 2.4;
|
|
51
|
+
});
|
|
52
|
+
return 0.2126 * r + 0.7152 * g + 0.0722 * b;
|
|
53
|
+
}
|
|
54
|
+
function paletteRoles(colors) {
|
|
55
|
+
const ranked = colors.map((c, i) => ({ i, l: luminance(c) ?? 0.5 })).sort((a, b) => a.l - b.l || a.i - b.i);
|
|
56
|
+
const light = ranked[ranked.length - 1].i;
|
|
57
|
+
const darkCount = colors.length >= 5 ? 2 : 1;
|
|
58
|
+
const darks = ranked.slice(0, darkCount).map((r) => r.i);
|
|
59
|
+
const hues = ranked.slice(darkCount, -1).map((r) => r.i);
|
|
60
|
+
return { light, darks, hues };
|
|
61
|
+
}
|
|
62
|
+
function pickDifferent(from, avoid, len) {
|
|
63
|
+
for (let i = 1; i <= len; i++) {
|
|
64
|
+
const c = (from + i) % len;
|
|
65
|
+
if (!avoid.includes(c)) return c;
|
|
66
|
+
}
|
|
67
|
+
return from;
|
|
68
|
+
}
|
|
69
|
+
function buildStrip(seed, colors, len = STRIP_LENGTH) {
|
|
70
|
+
const n = colors.length;
|
|
71
|
+
if (n < 2) return Array.from({ length: len }, () => 0);
|
|
72
|
+
const { light, darks, hues } = paletteRoles(colors);
|
|
73
|
+
const pool = hues.length ? hues : darks;
|
|
74
|
+
const rand = mulberry32(seed);
|
|
75
|
+
const strip = [];
|
|
76
|
+
let lastHue = -1;
|
|
77
|
+
for (let k = 0; k < len; k++) {
|
|
78
|
+
const r = rand();
|
|
79
|
+
let next;
|
|
80
|
+
if (r < 0.26) {
|
|
81
|
+
next = light;
|
|
82
|
+
} else if (r < 0.42) {
|
|
83
|
+
next = darks[Math.floor(rand() * darks.length)];
|
|
84
|
+
} else {
|
|
85
|
+
let h = pool[Math.floor(rand() * pool.length)];
|
|
86
|
+
if (h === lastHue && pool.length > 1) h = pool[(pool.indexOf(h) + 1) % pool.length];
|
|
87
|
+
lastHue = h;
|
|
88
|
+
next = h;
|
|
89
|
+
}
|
|
90
|
+
if (k > 0 && next === strip[k - 1]) next = pickDifferent(next, [strip[k - 1]], n);
|
|
91
|
+
strip.push(next);
|
|
92
|
+
}
|
|
93
|
+
if (len > 2 && strip[len - 1] === strip[0]) {
|
|
94
|
+
strip[len - 1] = pickDifferent(strip[len - 1], [strip[len - 2], strip[0]], n);
|
|
95
|
+
}
|
|
96
|
+
return strip;
|
|
97
|
+
}
|
|
98
|
+
function stripIndex(strip, id, column) {
|
|
99
|
+
const len = strip.length;
|
|
100
|
+
const s = id - column;
|
|
101
|
+
return strip[(s % len + len) % len];
|
|
102
|
+
}
|
|
103
|
+
function columnEdges(width, columns, power) {
|
|
104
|
+
const edges = [];
|
|
105
|
+
for (let i = 0; i <= columns; i++) {
|
|
106
|
+
edges.push(Math.round(width * Math.pow(i / columns, power)));
|
|
107
|
+
}
|
|
108
|
+
return edges;
|
|
109
|
+
}
|
|
110
|
+
function oddTiles(tiles) {
|
|
111
|
+
const t = Math.max(3, Math.round(Number.isFinite(tiles) ? tiles : DEFAULT_TILES));
|
|
112
|
+
return t % 2 === 0 ? t + 1 : t;
|
|
113
|
+
}
|
|
114
|
+
function tileEdge(k, tiles, stretch = STRETCH) {
|
|
115
|
+
const u = k / tiles;
|
|
116
|
+
if (u < 0) return u * TAIL_SLOPE;
|
|
117
|
+
if (u > 1) return 1 + (u - 1) * TAIL_SLOPE;
|
|
118
|
+
const a = Math.pow(u, stretch);
|
|
119
|
+
return a / (a + Math.pow(1 - u, stretch));
|
|
120
|
+
}
|
|
121
|
+
const SPRING_NORM = 1 - Math.exp(-1.6);
|
|
122
|
+
function springStep(p) {
|
|
123
|
+
const half = (t) => (1 - Math.exp(-1.6 * t)) / SPRING_NORM;
|
|
124
|
+
return p < 0.5 ? 0.5 * half(2 * p) : 1 - 0.5 * half(2 * (1 - p));
|
|
125
|
+
}
|
|
126
|
+
function columnFlow(elapsed, column, columns, speed = 1) {
|
|
127
|
+
const delay = (columns - 1 - column) * FALL_STAGGER;
|
|
128
|
+
const t = elapsed - delay;
|
|
129
|
+
const raw = t <= 0 ? 0 : t * speed / CYCLE;
|
|
130
|
+
const linear = raw + column * COL_PHASE;
|
|
131
|
+
const step = Math.floor(linear);
|
|
132
|
+
return step + springStep(linear - step);
|
|
133
|
+
}
|
|
134
|
+
function columnTiles(flow, tiles, height, bleed) {
|
|
135
|
+
const out = [];
|
|
136
|
+
const base = -Math.floor(flow);
|
|
137
|
+
for (let n = tiles + 2; n >= -2; n--) {
|
|
138
|
+
const id = base + n;
|
|
139
|
+
const k = id + flow;
|
|
140
|
+
const top = Math.round(tileEdge(k, tiles) * height);
|
|
141
|
+
const bot = Math.round(tileEdge(k + 1, tiles) * height) + bleed;
|
|
142
|
+
if (bot <= top) continue;
|
|
143
|
+
out.push({ id, top, bot });
|
|
144
|
+
}
|
|
145
|
+
return out;
|
|
146
|
+
}
|
|
147
|
+
function createCoverage(columns, covered = false) {
|
|
148
|
+
const top = new Float32Array(columns);
|
|
149
|
+
const bot = new Float32Array(columns);
|
|
150
|
+
if (covered) bot.fill(1);
|
|
151
|
+
return { top, bot };
|
|
152
|
+
}
|
|
153
|
+
function columnDelays(columns, sweep, stagger, seed = 1) {
|
|
154
|
+
const mid = (columns - 1) / 2;
|
|
155
|
+
const rank = (i) => {
|
|
156
|
+
switch (sweep) {
|
|
157
|
+
case "left":
|
|
158
|
+
return i;
|
|
159
|
+
case "center":
|
|
160
|
+
return Math.abs(i - mid);
|
|
161
|
+
case "edges":
|
|
162
|
+
return mid - Math.abs(i - mid);
|
|
163
|
+
case "random":
|
|
164
|
+
return 0;
|
|
165
|
+
default:
|
|
166
|
+
return columns - 1 - i;
|
|
167
|
+
}
|
|
168
|
+
};
|
|
169
|
+
if (sweep === "random") {
|
|
170
|
+
const order = Array.from({ length: columns }, (_, i) => i);
|
|
171
|
+
const rand = mulberry32(seed ^ 24301);
|
|
172
|
+
for (let i = order.length - 1; i > 0; i--) {
|
|
173
|
+
const j = Math.floor(rand() * (i + 1));
|
|
174
|
+
[order[i], order[j]] = [order[j], order[i]];
|
|
175
|
+
}
|
|
176
|
+
const delays = new Array(columns);
|
|
177
|
+
order.forEach((col, k) => delays[col] = k * stagger);
|
|
178
|
+
return delays;
|
|
179
|
+
}
|
|
180
|
+
return Array.from({ length: columns }, (_, i) => rank(i) * stagger);
|
|
181
|
+
}
|
|
182
|
+
function stepCoverage(cov, direction, phaseTime, dt, duration, delays) {
|
|
183
|
+
const n = cov.top.length;
|
|
184
|
+
const rate = duration > 0 ? dt / duration : Infinity;
|
|
185
|
+
let done = true;
|
|
186
|
+
for (let i = 0; i < n; i++) {
|
|
187
|
+
const started = phaseTime >= (delays[i] ?? 0);
|
|
188
|
+
if (direction === "cover") {
|
|
189
|
+
if (cov.bot[i] - cov.top[i] <= 1e-6 && cov.bot[i] < 1) {
|
|
190
|
+
cov.top[i] = 0;
|
|
191
|
+
cov.bot[i] = 0;
|
|
192
|
+
}
|
|
193
|
+
if (started) {
|
|
194
|
+
cov.bot[i] = Math.min(1, cov.bot[i] + rate);
|
|
195
|
+
cov.top[i] = Math.max(0, cov.top[i] - rate);
|
|
196
|
+
}
|
|
197
|
+
if (cov.bot[i] < 1 || cov.top[i] > 0) done = false;
|
|
198
|
+
} else {
|
|
199
|
+
if (started) cov.top[i] = Math.min(cov.bot[i], cov.top[i] + rate);
|
|
200
|
+
if (cov.top[i] < cov.bot[i]) done = false;
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
return done;
|
|
204
|
+
}
|
|
205
|
+
function settleCoverage(cov, direction) {
|
|
206
|
+
if (direction === "cover") {
|
|
207
|
+
cov.top.fill(0);
|
|
208
|
+
cov.bot.fill(1);
|
|
209
|
+
} else {
|
|
210
|
+
cov.top.fill(0);
|
|
211
|
+
cov.bot.fill(0);
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
function easeEdge(a) {
|
|
215
|
+
const x = Math.min(1, Math.max(0, a));
|
|
216
|
+
return x < 0.5 ? 4 * x * x * x : 1 - Math.pow(-2 * x + 2, 3) / 2;
|
|
217
|
+
}
|
|
218
|
+
function columnBand(effect, column, top, bot) {
|
|
219
|
+
const rise = effect === "rise" || effect === "interlace" && column % 2 === 1;
|
|
220
|
+
if (effect === "split") {
|
|
221
|
+
const half = Math.max(0, bot - top) / 2;
|
|
222
|
+
return { y0: 0.5 - half, y1: 0.5 + half, mirror: false };
|
|
223
|
+
}
|
|
224
|
+
if (rise) return { y0: 1 - bot, y1: 1 - top, mirror: true };
|
|
225
|
+
return { y0: top, y1: bot, mirror: false };
|
|
226
|
+
}
|
|
227
|
+
const DATAMOSH_PALETTES = {
|
|
228
|
+
broadcast: DEFAULT_COLORS,
|
|
229
|
+
thermal: [
|
|
230
|
+
"#fff4d6",
|
|
231
|
+
"#ffd23f",
|
|
232
|
+
"#ff9f1c",
|
|
233
|
+
"#ff5a1f",
|
|
234
|
+
"#e0282e",
|
|
235
|
+
"#b0125b",
|
|
236
|
+
"#6a0f63",
|
|
237
|
+
"#2a0a3d",
|
|
238
|
+
"#0d0614"
|
|
239
|
+
],
|
|
240
|
+
sunset: [
|
|
241
|
+
"#fff6d8",
|
|
242
|
+
"#fbc56b",
|
|
243
|
+
"#f59a3a",
|
|
244
|
+
"#e97a1d",
|
|
245
|
+
"#c85a14",
|
|
246
|
+
"#8a4a22",
|
|
247
|
+
"#5a3b25",
|
|
248
|
+
"#2d1c16",
|
|
249
|
+
"#140b08"
|
|
250
|
+
],
|
|
251
|
+
mono: ["#ffffff", "#e5e5e5", "#b5b5b5", "#8a8a8a", "#5c5c5c", "#2e2e2e", "#141414", "#050505"],
|
|
252
|
+
acid: [
|
|
253
|
+
"#f4ffe8",
|
|
254
|
+
"#e4ff1a",
|
|
255
|
+
"#00ff9c",
|
|
256
|
+
"#00e0ff",
|
|
257
|
+
"#3d5afe",
|
|
258
|
+
"#8c3dff",
|
|
259
|
+
"#ff2bd6",
|
|
260
|
+
"#1b0b36",
|
|
261
|
+
"#070707"
|
|
262
|
+
]
|
|
263
|
+
};
|
|
264
|
+
function resolvePalette(colors) {
|
|
265
|
+
if (typeof colors === "string") return [...DATAMOSH_PALETTES[colors] ?? DEFAULT_COLORS];
|
|
266
|
+
return colors && colors.length >= 2 ? [...colors] : [...DEFAULT_COLORS];
|
|
267
|
+
}
|
|
268
|
+
const MAX_GAIN = 1.6;
|
|
269
|
+
const SOURCE_SPAN = 0.6;
|
|
270
|
+
function sourceSlotY(slot, tiles) {
|
|
271
|
+
return 0.5 + ((slot + 0.5) / tiles - 0.5) * SOURCE_SPAN;
|
|
272
|
+
}
|
|
273
|
+
function sourceSlot(id, column, tiles) {
|
|
274
|
+
const s = id - column;
|
|
275
|
+
return (s % tiles + tiles) % tiles;
|
|
276
|
+
}
|
|
277
|
+
function coverFit(imgW, imgH, boxW, boxH) {
|
|
278
|
+
if (imgW <= 0 || imgH <= 0 || boxW <= 0 || boxH <= 0) return { sx: 0, sy: 0, sw: imgW, sh: imgH };
|
|
279
|
+
const scale = Math.max(boxW / imgW, boxH / imgH);
|
|
280
|
+
const sw = boxW / scale;
|
|
281
|
+
const sh = boxH / scale;
|
|
282
|
+
return { sx: (imgW - sw) / 2, sy: (imgH - sh) / 2, sw, sh };
|
|
283
|
+
}
|
|
284
|
+
function sampleSource(pixels, pw, ph, edges, tiles, boost = true) {
|
|
285
|
+
const at = (x, y) => {
|
|
286
|
+
const cx = Math.min(pw - 1, Math.max(0, x));
|
|
287
|
+
const cy = Math.min(ph - 1, Math.max(0, y));
|
|
288
|
+
return (cy * pw + cx) * 4;
|
|
289
|
+
};
|
|
290
|
+
const cells = [];
|
|
291
|
+
let lo = Infinity;
|
|
292
|
+
let hi = -Infinity;
|
|
293
|
+
for (let i = 0; i + 1 < edges.length; i++) {
|
|
294
|
+
const x = Math.round((edges[i] + edges[i + 1]) / 2 * (pw - 1));
|
|
295
|
+
const row = [];
|
|
296
|
+
for (let s = 0; s < tiles; s++) {
|
|
297
|
+
const y = Math.round(sourceSlotY(s, tiles) * (ph - 1));
|
|
298
|
+
let r = 0;
|
|
299
|
+
let g = 0;
|
|
300
|
+
let b = 0;
|
|
301
|
+
for (let dy = -1; dy <= 1; dy++) {
|
|
302
|
+
for (let dx = -1; dx <= 1; dx++) {
|
|
303
|
+
const k = at(x + dx, y + dy);
|
|
304
|
+
r += pixels[k];
|
|
305
|
+
g += pixels[k + 1];
|
|
306
|
+
b += pixels[k + 2];
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
const cell = [r / 9, g / 9, b / 9];
|
|
310
|
+
const l = 0.2126 * cell[0] + 0.7152 * cell[1] + 0.0722 * cell[2];
|
|
311
|
+
lo = Math.min(lo, l);
|
|
312
|
+
hi = Math.max(hi, l);
|
|
313
|
+
row.push(cell);
|
|
314
|
+
}
|
|
315
|
+
cells.push(row);
|
|
316
|
+
}
|
|
317
|
+
const span = hi - lo;
|
|
318
|
+
const level = boost && span > 8 ? Math.min(MAX_GAIN, 255 / (hi - lo * 0.5)) : 1;
|
|
319
|
+
const offset = boost && span > 8 ? lo * 0.5 : 0;
|
|
320
|
+
const saturation = boost ? 1.35 : 1;
|
|
321
|
+
const clamp = (v) => Math.round(Math.min(255, Math.max(0, v)));
|
|
322
|
+
return cells.map(
|
|
323
|
+
(row) => row.map(([r, g, b]) => {
|
|
324
|
+
let [nr, ng, nb] = [(r - offset) * level, (g - offset) * level, (b - offset) * level];
|
|
325
|
+
const l = 0.2126 * nr + 0.7152 * ng + 0.0722 * nb;
|
|
326
|
+
nr = l + (nr - l) * saturation;
|
|
327
|
+
ng = l + (ng - l) * saturation;
|
|
328
|
+
nb = l + (nb - l) * saturation;
|
|
329
|
+
return `rgb(${clamp(nr)}, ${clamp(ng)}, ${clamp(nb)})`;
|
|
330
|
+
})
|
|
331
|
+
);
|
|
332
|
+
}
|
|
333
|
+
export {
|
|
334
|
+
BLEED,
|
|
335
|
+
COL_PHASE,
|
|
336
|
+
CYCLE,
|
|
337
|
+
DATAMOSH_PALETTES,
|
|
338
|
+
DEFAULT_COLORS,
|
|
339
|
+
DEFAULT_COLUMNS,
|
|
340
|
+
DEFAULT_POWER,
|
|
341
|
+
DEFAULT_TILES,
|
|
342
|
+
FALL_STAGGER,
|
|
343
|
+
MAX_GAIN,
|
|
344
|
+
SOURCE_SPAN,
|
|
345
|
+
STRETCH,
|
|
346
|
+
STRIP_LENGTH,
|
|
347
|
+
TAIL_SLOPE,
|
|
348
|
+
buildStrip,
|
|
349
|
+
columnBand,
|
|
350
|
+
columnDelays,
|
|
351
|
+
columnEdges,
|
|
352
|
+
columnFlow,
|
|
353
|
+
columnTiles,
|
|
354
|
+
coverFit,
|
|
355
|
+
createCoverage,
|
|
356
|
+
easeEdge,
|
|
357
|
+
luminance,
|
|
358
|
+
mulberry32,
|
|
359
|
+
oddTiles,
|
|
360
|
+
paletteRoles,
|
|
361
|
+
resolvePalette,
|
|
362
|
+
sampleSource,
|
|
363
|
+
settleCoverage,
|
|
364
|
+
sourceSlot,
|
|
365
|
+
sourceSlotY,
|
|
366
|
+
springStep,
|
|
367
|
+
stepCoverage,
|
|
368
|
+
stripIndex,
|
|
369
|
+
tileEdge
|
|
370
|
+
};
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export { DatamoshTransition } from "./DatamoshTransition.js";
|
|
2
|
+
export type { DatamoshTransitionProps, DatamoshTransitionPhase, DatamoshTransitionHandle, } from "./DatamoshTransition.js";
|
|
3
|
+
export { DATAMOSH_PALETTES, type DatamoshEffect, type DatamoshSweep, type DatamoshPaletteName, } from "./datamosh-transition-core.js";
|
|
@@ -7,22 +7,25 @@ export interface DockProps {
|
|
|
7
7
|
magnification?: number;
|
|
8
8
|
/** Pointer distance over which the magnification falls off. */
|
|
9
9
|
distance?: number;
|
|
10
|
-
/**
|
|
10
|
+
/** Cross-axis alignment of the icons. */
|
|
11
11
|
direction?: Direction;
|
|
12
12
|
/** Dock orientation. */
|
|
13
13
|
orientation?: DataOrientation;
|
|
14
|
-
/**
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
14
|
+
/** A soft pool of accent light inside the shelf that follows the pointer. */
|
|
15
|
+
spotlight?: boolean;
|
|
16
|
+
/** A soft contact shadow / glow ellipse under each icon that grows with it. */
|
|
17
|
+
reflection?: boolean;
|
|
18
|
+
/** Accessible name for the toolbar. */
|
|
18
19
|
ariaLabel?: string;
|
|
19
20
|
/** The `DockIcon`s and `DockSeparator`s. */
|
|
20
21
|
children?: ReactNode;
|
|
21
22
|
}
|
|
22
23
|
/**
|
|
23
|
-
* An icon dock
|
|
24
|
+
* An icon dock on a lit glass shelf: icons swell on a cosine curve as the
|
|
25
|
+
* pointer approaches, a pool of light follows it across the shelf, and the
|
|
26
|
+
* shelf edge brightens near it.
|
|
24
27
|
*
|
|
25
28
|
* No `ref` prop: the source exposes no bindable ref, and no rest props either —
|
|
26
29
|
* it reads only these props and spreads nothing.
|
|
27
30
|
*/
|
|
28
|
-
export declare function Dock({ className, magnification, distance, direction, orientation, ariaLabel, children, }: DockProps): import("react").JSX.Element;
|
|
31
|
+
export declare function Dock({ className, magnification, distance, direction, orientation, spotlight, reflection, ariaLabel, children, }: DockProps): import("react").JSX.Element;
|