@sumi-forge/react 0.0.0-stage → 1.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.
@@ -0,0 +1,68 @@
1
+ import { Point2D, VFXConfig } from './types';
2
+ /**
3
+ * Técnica #01: PRNG Determinístico (Mulberry32)
4
+ * Estado inteiro de 32 bits incrementado por 0x6D2B79F5 a cada chamada,
5
+ * garantindo coerência temporal entre todos os quadros sem cintilação (flicker).
6
+ */
7
+ export declare function createSeededRandom(seed: number): () => number;
8
+ /**
9
+ * Técnica #01: Value Noise 2D suavizado por curva Hermite cúbica (Smoothstep)
10
+ * u = xf² · (3 - 2·xf) e v = yf² · (3 - 2·yf)
11
+ */
12
+ export declare function sampleNoise2D(x: number, y: number, seed: number): number;
13
+ /**
14
+ * Técnica #01: FBM 2D de 3 Oitavas
15
+ * FBM(x, y, seed) = 0.55 · N(x, y, s) + 0.30 · N(2.15x + 13.7, 2.15y + 7.3, s + 101) + 0.15 · N(4.4x - 5.2, 4.4y + 19.1, s + 307)
16
+ */
17
+ export declare function fbmNoise2D(x: number, y: number, seed: number): number;
18
+ /**
19
+ * Técnica #02: Amostrador de Curva Bézier Cúbica (S-Curve) com Vetores Normais Analíticos
20
+ */
21
+ export declare function sampleCubicCurve(p0: {
22
+ x: number;
23
+ y: number;
24
+ }, p1: {
25
+ x: number;
26
+ y: number;
27
+ }, p2: {
28
+ x: number;
29
+ y: number;
30
+ }, p3: {
31
+ x: number;
32
+ y: number;
33
+ }, steps?: number, jitterAmount?: number, seed?: number): Point2D[];
34
+ /**
35
+ * Técnica #02: Amostrador de Curva Bézier Quadrática com Normais Analíticas
36
+ */
37
+ export declare function sampleQuadraticCurve(p0: {
38
+ x: number;
39
+ y: number;
40
+ }, p1: {
41
+ x: number;
42
+ y: number;
43
+ }, p2: {
44
+ x: number;
45
+ y: number;
46
+ }, steps?: number, jitterAmount?: number, seed?: number): Point2D[];
47
+ /**
48
+ * Técnica #02: Arco Polar / Elíptico com Tilt 3D e Fator Espiral
49
+ */
50
+ export declare function samplePolarArc(cx: number, cy: number, rx: number, ry: number, startAngle: number, endAngle: number, tiltRadians?: number, spiralFactor?: number, steps?: number, jitterAmount?: number, seed?: number): Point2D[];
51
+ /**
52
+ * Converte amostras de ponteiro do usuário em uma espinha dorsal Point2D suavizada
53
+ */
54
+ export declare function samplesToSpine(rawPoints: {
55
+ x: number;
56
+ y: number;
57
+ }[], jitterAmount?: number, seed?: number): Point2D[];
58
+ export declare function hexToRgb(hex: string): [number, number, number];
59
+ export declare function rgbaStr(hex: string, alpha: number): string;
60
+ export declare function mixHex(hexA: string, hexB: string, t: number): string;
61
+ /**
62
+ * Técnica #11: Shader de Recolorização por Separação de 3 Canais (CPU ImageData & GPU Shader Equivalente)
63
+ * L = 0.299·R + 0.587·G + 0.114·B
64
+ * W_core = (min(R, G, B))^2.2
65
+ * W_energy = clamp(chroma * 2.1 + max(0, L - 0.18) * (1 - W_core), 0, 1)
66
+ * W_ink = max(0, 1 - W_energy - W_core)
67
+ */
68
+ export declare function recolorReferenceSheetData(src: ImageData, config: VFXConfig): ImageData;
@@ -0,0 +1,21 @@
1
+ import { ArchetypeId, MagicSchool, SansuiComposition, SansuiThemeId, SansuiThemePreset, SchoolId, SumiLayerIntensities, TechniqueSpec, VFXConfig } from './types';
2
+ export declare const SANSUI_THEMES: Record<Exclude<SansuiThemeId, 'auto'>, SansuiThemePreset>;
3
+ export declare const SANSUI_COMPOSITIONS: {
4
+ id: SansuiComposition;
5
+ name: string;
6
+ jp: string;
7
+ romaji: string;
8
+ ptMeaning: string;
9
+ description: string;
10
+ }[];
11
+ export declare const MAGIC_SCHOOLS: Record<SchoolId, MagicSchool>;
12
+ export declare const ARCHETYPE_CATALOG: {
13
+ id: ArchetypeId;
14
+ name: string;
15
+ category: string;
16
+ defaultSchool: SchoolId;
17
+ description: string;
18
+ }[];
19
+ export declare const DEFAULT_VFX_CONFIG: VFXConfig;
20
+ export declare const DEFAULT_FUJI_LAYERS: SumiLayerIntensities;
21
+ export declare const TECHNIQUES_CATALOG: TechniqueSpec[];
@@ -0,0 +1,107 @@
1
+ import rough from 'roughjs';
2
+ import type { Options as RoughOptions } from 'roughjs/bin/core';
3
+ import { Point2D, SumiColors, VFXConfig } from './types';
4
+ type RoughCanvasInstance = ReturnType<typeof rough.canvas>;
5
+ /**
6
+ * Técnica #10: Opções Determinísticas para Rough.js
7
+ */
8
+ export declare function makeFineRoughOptions(config: VFXConfig, scale: number, seedOffset: number, overrides?: Partial<RoughOptions>): RoughOptions;
9
+ /**
10
+ * Técnica #03 & #04: Fita Caligráfica Multi-Cerdas Sumi-e com Efeito Kasure (Flying-White)
11
+ * + Erosão Celular Progressiva por Limiar de Ruído FBM 2D
12
+ */
13
+ export interface KasureRibbonOpts {
14
+ spine: Point2D[];
15
+ maxWidth: number;
16
+ bristleCount: number;
17
+ dryBrushGap: number;
18
+ taperStart: number;
19
+ taperEnd: number;
20
+ color: string;
21
+ alpha?: number;
22
+ offsetNormal?: number;
23
+ headReach?: number;
24
+ tailRetract?: number;
25
+ erosionProgress?: number;
26
+ erosionScale?: number;
27
+ hookWaves?: number;
28
+ roundHeadCap?: boolean;
29
+ seed: number;
30
+ }
31
+ export declare function drawSumiKasureRibbon(ctx: CanvasRenderingContext2D, opts: KasureRibbonOpts): void;
32
+ /**
33
+ * Técnica #04: Gotas Centrífugas Alongadas na Direção Tangente + Normal
34
+ */
35
+ export declare function drawCentrifugalSplatters(ctx: CanvasRenderingContext2D, spine: Point2D[], frameNorm: number, splatterCount: number, splatterSpread: number, scale: number, colors: SumiColors, seed: number): void;
36
+ /**
37
+ * Técnica #05: Pétalas de Chama Aquareladas em S-Curve com Estrias Fibrosas & Fitas Desprendidas
38
+ */
39
+ export interface FlamePetalTongueOpts {
40
+ rootX: number;
41
+ rootY: number;
42
+ ctrl1X: number;
43
+ ctrl1Y: number;
44
+ ctrl2X: number;
45
+ ctrl2Y: number;
46
+ tipX: number;
47
+ tipY: number;
48
+ maxBellyWidth: number;
49
+ striationCount?: number;
50
+ alpha?: number;
51
+ seed: number;
52
+ }
53
+ export declare function drawFlamePetalTongue(ctx: CanvasRenderingContext2D, rc: RoughCanvasInstance | null, config: VFXConfig, scale: number, opts: FlamePetalTongueOpts): void;
54
+ export declare function drawDetachedSumiFlameWisp(ctx: CanvasRenderingContext2D, startX: number, startY: number, endX: number, endY: number, width: number, color: string, seed: number): void;
55
+ /**
56
+ * Técnica #06: Cristas de Onda Ukiyo-e (Hokusai), 5 Correntes Listradas & Garras Fractais de Espuma
57
+ */
58
+ export declare function drawHokusaiFoamClawCluster(ctx: CanvasRenderingContext2D, rc: RoughCanvasInstance | null, cx: number, cy: number, baseAngle: number, curlDir: 1 | -1, clawCount: number, radius: number, config: VFXConfig, scale: number, seed: number): void;
59
+ export declare function drawHokusaiWaveCrest(ctx: CanvasRenderingContext2D, rc: RoughCanvasInstance | null, spine: Point2D[], maxWidth: number, curlDir: 1 | -1, clawCount: number, config: VFXConfig, scale: number, alpha: number, seed: number): void;
60
+ /**
61
+ * Técnica #07: Bancos de Nuvens & Fumaça Ukiyo-e (Kumo) com Volutas em C-Hook e Caracóis Internos
62
+ */
63
+ export interface KumoVoluteOpts {
64
+ startX: number;
65
+ startY: number;
66
+ endX: number;
67
+ endY: number;
68
+ maxThickness: number;
69
+ lobeCount?: number;
70
+ curlRadius?: number;
71
+ flip?: 1 | -1;
72
+ alpha?: number;
73
+ seed: number;
74
+ }
75
+ export declare function drawUkiyoeCloudScrollVolute(ctx: CanvasRenderingContext2D, rc: RoughCanvasInstance | null, config: VFXConfig, scale: number, opts: KumoVoluteOpts): void;
76
+ export declare function drawUkiyoeCloudBank(ctx: CanvasRenderingContext2D, rc: RoughCanvasInstance | null, cx: number, cy: number, spanWidth: number, puffCount: number, config: VFXConfig, scale: number, alpha: number, seed: number): void;
77
+ /**
78
+ * Técnica #08: Núcleo Sólido 100% Opaco com Oclusão Real (Alpha 1.0 em todas as paradas)
79
+ */
80
+ export declare function drawSolidOpaqueCoreSphere(ctx: CanvasRenderingContext2D, rc: RoughCanvasInstance | null, cx: number, cy: number, rx: number, ry: number, dirAngle: number, wobbleAmount: number, config: VFXConfig, scale: number, seed: number): void;
81
+ /**
82
+ * Técnica #09: Aguada Suibokuga (Tarashikomi) com Borda de Sangria de Pigmento
83
+ */
84
+ export declare function drawTarashikomiWashBlob(ctx: CanvasRenderingContext2D, cx: number, cy: number, rx: number, ry: number, rotation: number, coreColor: string, edgeColor: string, alpha: number, seed: number): void;
85
+ /**
86
+ * Técnica #10: Geometria Poligonal Sólida Hand-Made com Rough.js (Cristais Chanfrados Cel-Shaded)
87
+ */
88
+ export declare function drawFacetedRoughCrystal(ctx: CanvasRenderingContext2D, rc: RoughCanvasInstance | null, baseX: number, baseY: number, angle: number, length: number, width: number, config: VFXConfig, scale: number, seed: number): void;
89
+ /**
90
+ * Flor de Sakura (Cerejeira) Aquarelada Suibokuga com 5 pétalas chanfradas e estames
91
+ */
92
+ export declare function drawSakuraBlossom(ctx: CanvasRenderingContext2D, cx: number, cy: number, radius: number, rotation: number, petalColor: string, coreColor: string, inkColor: string, alpha?: number, seed?: number): void;
93
+ /**
94
+ * Pétala Individual de Sakura Flutuando ao Vento
95
+ */
96
+ export declare function drawFloatingSakuraPetal(ctx: CanvasRenderingContext2D, x: number, y: number, size: number, angle: number, tiltRatio: number, color: string, alpha?: number): void;
97
+ /**
98
+ * Carpa Japonesa (Nishikigoi / Kohaku) pintada a pincel Sumi-e & Suibokuga
99
+ * Corpo em curva S fluida, nadadeiras peitorais caligráficas, manchas vermelhas e ondulações de rio.
100
+ */
101
+ export declare function drawCalligraphicKoiCarp(ctx: CanvasRenderingContext2D, cx: number, cy: number, length: number, angle: number, swimPhase: number, inkColor: string, crimsonColor: string, bodyLightColor: string, alpha?: number, seed?: number): void;
102
+ /**
103
+ * Galho Ornamental de Sakura (Cerejeira) com Sub-Ramos e Cachos de Flores
104
+ * Usado para emoldurar cantos e seções com elegância orgânica japonesa.
105
+ */
106
+ export declare function drawCornerSakuraBranch(ctx: CanvasRenderingContext2D, startX: number, startY: number, endX: number, endY: number, archDir: 1 | -1, maxTrunkWidth: number, reachProgress: number, swayTime: number, inkColor: string, petalColor: string, coreColor: string, seed: number): void;
107
+ export {};
@@ -0,0 +1,129 @@
1
+ export type SchoolId = 'fuji_sakura' | 'calligraphy_tide' | 'fungal_emerald' | 'toxic_venom' | 'abyssal_curse' | 'blood_shadow' | 'necro_phantom' | 'capoeira_dende' | 'abyssal_flame' | 'celestial_thunder' | 'astral_gold';
2
+ export type ArchetypeId = 'hyb_slash_great_wave_katana' | 'hyb_slash_crimson_phoenix_arc' | 'hyb_slash_blood_moon_scythe' | 'crescent' | 'water_slash' | 'enso_sigil' | 'elem_fire_meteor_bolide' | 'elem_water_glacial_spikes' | 'solid_ref_fumaca' | 'elem_water_healing_fountain' | 'sakura_tempest_slash' | 'portal_abyssal_vortex';
3
+ export type ChannelMode = 'composite' | 'ink_only' | 'energy_only' | 'shader_rgb_mask';
4
+ export type BgMode = 'washi' | 'checker' | 'dark' | 'transparent';
5
+ export type RoughFillStyle = 'solid' | 'hachure' | 'cross-hatch' | 'zigzag';
6
+ export interface Point2D {
7
+ x: number;
8
+ y: number;
9
+ nx: number;
10
+ ny: number;
11
+ t: number;
12
+ }
13
+ export interface SumiColors {
14
+ inkPrimary: string;
15
+ energySecondary: string;
16
+ coreGlow: string;
17
+ sporeAccent: string;
18
+ }
19
+ export interface SumiBrushConfig {
20
+ bristleCount: number;
21
+ strokeThickness: number;
22
+ taperStart: number;
23
+ taperEnd: number;
24
+ dryBrushGap: number;
25
+ curvature: number;
26
+ angle: number;
27
+ arcSweep: number;
28
+ }
29
+ export interface SumiDynamicsConfig {
30
+ splatterCount: number;
31
+ splatterSpread: number;
32
+ hookWaves: number;
33
+ erosionStrength: number;
34
+ erosionScale: number;
35
+ glowIntensity: number;
36
+ colorOffset: number;
37
+ jitterAmount: number;
38
+ }
39
+ export interface SumiRoughConfig {
40
+ roughness: number;
41
+ bowing: number;
42
+ outlineWidth: number;
43
+ fillStyle: RoughFillStyle;
44
+ celSteps: number;
45
+ }
46
+ export interface SumiLayerIntensities {
47
+ sunIntensity: number;
48
+ mountainIntensity: number;
49
+ sakuraBranchIntensity: number;
50
+ sakuraPetalsIntensity: number;
51
+ waterReflectionIntensity: number;
52
+ mistKumoIntensity: number;
53
+ }
54
+ export interface VFXConfig {
55
+ archetype: ArchetypeId;
56
+ school: SchoolId;
57
+ colors: SumiColors;
58
+ bgMode: BgMode;
59
+ channelMode: ChannelMode;
60
+ brush: SumiBrushConfig;
61
+ dynamics: SumiDynamicsConfig;
62
+ rough: SumiRoughConfig;
63
+ totalFrames: number;
64
+ fps: number;
65
+ seed: number;
66
+ frameSize: 96 | 128 | 192 | 256;
67
+ }
68
+ export interface MagicSchool {
69
+ id: SchoolId;
70
+ name: string;
71
+ elementStyle: string;
72
+ colors: SumiColors;
73
+ }
74
+ export interface TechniqueSpec {
75
+ id: number;
76
+ code: string;
77
+ title: string;
78
+ subtitle: string;
79
+ origin: string;
80
+ archetype: ArchetypeId;
81
+ school: SchoolId;
82
+ equations: string[];
83
+ invariantsDo: string[];
84
+ invariantsDont: string[];
85
+ description: string;
86
+ }
87
+ export type InteractiveBrushType = 'sumi_kasure' | 'sakura_branch' | 'hokusai_wave' | 'suibokuga_flame' | 'kumo_cloud' | 'tarashikomi_wash' | 'rough_crystal';
88
+ export interface BrushPointSample {
89
+ x: number;
90
+ y: number;
91
+ pressure: number;
92
+ velocity: number;
93
+ timestamp: number;
94
+ }
95
+ export interface RecordedBrushStroke {
96
+ id: string;
97
+ brushType: InteractiveBrushType;
98
+ points: BrushPointSample[];
99
+ colors: SumiColors;
100
+ thickness: number;
101
+ bristleCount: number;
102
+ dryBrushGap: number;
103
+ seed: number;
104
+ layerId: 'background' | 'midground' | 'foreground';
105
+ }
106
+ export type MaskChoreography = 'fuji_masterpiece' | 'katana_slashes' | 'enso_spiral' | 'hokusai_tide' | 'interactive_brush';
107
+ export type SansuiComposition = 'panoramic_river' | 'karst_peaks' | 'layered_valley' | 'twin_gorges';
108
+ export type SansuiThemeId = 'classic_washi' | 'jade_mineral' | 'night_obsidian' | 'crimson_dawn' | 'cobalt_porcelain' | 'auto';
109
+ export interface SansuiColors {
110
+ /** Cor do papel / céu e extensão das águas */
111
+ background: string;
112
+ /** Cor principal do nanquim / contorno caligráfico das cristas, árvores e barco */
113
+ ink: string;
114
+ /** Cor da aguada mineral ou sombreado interno das montanhas */
115
+ wash: string;
116
+ /** Cor da neblina atmosférica que separa os planos de profundidade */
117
+ mist: string;
118
+ /** Cor de acento opcional (folhagem, sol discreto ou selo) */
119
+ accent: string;
120
+ }
121
+ export interface SansuiThemePreset {
122
+ id: Exclude<SansuiThemeId, 'auto'>;
123
+ name: string;
124
+ jp: string;
125
+ romaji: string;
126
+ subtitle: string;
127
+ isDark?: boolean;
128
+ colors: SansuiColors;
129
+ }
@@ -0,0 +1,13 @@
1
+ import { VFXConfig } from './types';
2
+ /**
3
+ * Renderiza um único quadro [0..15] no espaço canônico 128×128 multiplicado por scale = width / 128.
4
+ * Segue a Cinética Não-Linear de Ataque (Sakuga Timing):
5
+ * - Quadros 0..3 (frameNorm 0.00..0.20): Aceleração explosiva headReach = 1 - (1 - frameNorm)^3.4
6
+ * - Quadros 4..6 (frameNorm 0.25..0.40): Ápice de impacto com núcleo branco e extensão máxima
7
+ * - Quadros 7..15 (frameNorm 0.46..1.00): Erosão celular progressiva por FBM 2D + gotas centrífugas
8
+ */
9
+ export declare function renderVFXFrame(ctx: CanvasRenderingContext2D, frameIndex: number, totalFrames: number, width: number, height: number, config: VFXConfig, transparentBg?: boolean): void;
10
+ /**
11
+ * Técnica #12: Pipeline de Composição de Sprite Sheet 4×4 com Isolamento Estrito por Célula (ctx.clip)
12
+ */
13
+ export declare function renderCompleteSpriteSheet(canvas: HTMLCanvasElement, config: VFXConfig, columns?: number): void;
package/package.json CHANGED
@@ -1,6 +1,92 @@
1
1
  {
2
2
  "name": "@sumi-forge/react",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "version": "1.0.1",
4
+ "description": "Japanese Sumi-e (ink wash painting) physics & generative canvas components for React",
5
+ "author": "Christopher Marques Correa",
6
+ "license": "Apache-2.0",
7
+ "keywords": [
8
+ "react",
9
+ "sumi-e",
10
+ "canvas",
11
+ "brush",
12
+ "roughjs",
13
+ "ink-wash",
14
+ "generative-art",
15
+ "japanese-calligraphy",
16
+ "vfx"
17
+ ],
18
+ "type": "module",
19
+ "main": "./dist-lib/index.cjs",
20
+ "module": "./dist-lib/index.js",
21
+ "types": "./dist-lib/index.d.ts",
22
+ "exports": {
23
+ ".": {
24
+ "types": "./dist-lib/index.d.ts",
25
+ "import": "./dist-lib/index.js",
26
+ "require": "./dist-lib/index.cjs"
27
+ }
28
+ },
29
+ "files": [
30
+ "dist-lib",
31
+ "README.md",
32
+ "LICENSE.md"
33
+ ],
34
+ "publishConfig": {
35
+ "access": "public"
36
+ },
37
+ "sideEffects": false,
38
+ "repository": {
39
+ "type": "git",
40
+ "url": "git+https://github.com/ChristopherMarques/sumiforge.git"
41
+ },
42
+ "homepage": "https://sumiforge.vercel.app",
43
+ "bugs": {
44
+ "url": "https://github.com/ChristopherMarques/sumiforge/issues"
45
+ },
46
+ "scripts": {
47
+ "dev": "vite --port=3000 --host=0.0.0.0",
48
+ "clean": "rm -rf dist dist-lib dist-app",
49
+ "build:types": "tsc -p tsconfig.lib.json",
50
+ "build:lib": "rm -rf dist-lib && npm run build:types && vite build --config vite.config.lib.ts",
51
+ "build:app": "vite build",
52
+ "build": "npm run clean && npm run build:app && npm run build:lib",
53
+ "preview": "vite preview",
54
+ "lint": "tsc --noEmit",
55
+ "prepublishOnly": "npm run build:lib",
56
+ "deploy": "npm run build && npm version patch && npm publish --access public"
57
+ },
58
+ "dependencies": {
59
+ "roughjs": "^4.6.6"
60
+ },
61
+ "peerDependencies": {
62
+ "react": ">=18.0.0",
63
+ "react-dom": ">=18.0.0"
64
+ },
65
+ "peerDependenciesMeta": {
66
+ "react-dom": {
67
+ "optional": true
68
+ }
69
+ },
70
+ "devDependencies": {
71
+ "@google/genai": "^2.4.0",
72
+ "@tailwindcss/vite": "^4.3.3",
73
+ "@types/express": "^4.17.21",
74
+ "@types/node": "^22.14.0",
75
+ "@types/react": "^19.3.0",
76
+ "@types/react-dom": "^19.3.0",
77
+ "@vitejs/plugin-react": "^6.1.1",
78
+ "autoprefixer": "^10.4.21",
79
+ "dotenv": "^17.2.3",
80
+ "esbuild": "^0.25.0",
81
+ "express": "^4.21.2",
82
+ "gsap": "^3.15.1",
83
+ "lucide-react": "^0.546.0",
84
+ "motion": "^12.23.24",
85
+ "react": "^19.0.1",
86
+ "react-dom": "^19.0.1",
87
+ "tailwindcss": "^4.3.3",
88
+ "tsx": "^4.21.0",
89
+ "typescript": "^7.0.2",
90
+ "vite": "^8.3.0"
91
+ }
92
+ }