@zinejs/core 0.6.0 → 0.7.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/dist/bundled-Cp43MIt0.js +100 -0
- package/dist/bundled-Cp43MIt0.js.map +1 -0
- package/dist/curls.js +133 -0
- package/dist/curls.js.map +1 -0
- package/dist/geometry/curls/bundled.d.ts +16 -0
- package/dist/geometry/curls/index.d.ts +8 -4
- package/dist/geometry/curls/types.d.ts +23 -1
- package/dist/index.d.ts +3 -2
- package/dist/index.js +160 -152
- package/dist/index.js.map +1 -1
- package/dist/index.umd.js +6 -6
- package/dist/index.umd.js.map +1 -1
- package/dist/renderer/types.d.ts +2 -2
- package/dist/types-DEz3mRLI.js +11 -0
- package/dist/types-DEz3mRLI.js.map +1 -0
- package/dist/{webglRenderer-BK-ArG1G.js → webglRenderer-BcNhTqG8.js} +33 -248
- package/dist/webglRenderer-BcNhTqG8.js.map +1 -0
- package/dist/zine.d.ts +15 -3
- package/options.schema.json +2 -2
- package/package.json +12 -2
- package/dist/types-CcPVyhOJ.js +0 -13
- package/dist/types-CcPVyhOJ.js.map +0 -1
- package/dist/webglRenderer-BK-ArG1G.js.map +0 -1
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { r as e } from "./types-DEz3mRLI.js";
|
|
2
|
+
//#region src/geometry/curls/mesh.ts
|
|
3
|
+
function t(e, t) {
|
|
4
|
+
let n = e + 1, r = t + 1, i = n * r, a = new Float32Array(i * 2);
|
|
5
|
+
for (let i = 0; i < r; i++) for (let r = 0; r < n; r++) {
|
|
6
|
+
let o = i * n + r;
|
|
7
|
+
a[o * 2] = r / e, a[o * 2 + 1] = i / t;
|
|
8
|
+
}
|
|
9
|
+
return {
|
|
10
|
+
cols: e,
|
|
11
|
+
rows: t,
|
|
12
|
+
uvs: a,
|
|
13
|
+
positions: new Float32Array(i * 3),
|
|
14
|
+
normals: new Float32Array(i * 3)
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
function n(e) {
|
|
18
|
+
let t = e.cols + 1, n = e.rows + 1, r = e.positions, i = e.normals;
|
|
19
|
+
for (let e = 0; e < n; e++) for (let a = 0; a < t; a++) {
|
|
20
|
+
let o = a > 0 ? a - 1 : a, s = a < t - 1 ? a + 1 : a, c = e > 0 ? e - 1 : e, l = e < n - 1 ? e + 1 : e, u = (e * t + s) * 3, d = (e * t + o) * 3, f = (l * t + a) * 3, p = (c * t + a) * 3, m = r[u] - r[d], h = r[u + 1] - r[d + 1], g = r[u + 2] - r[d + 2], _ = r[f] - r[p], v = r[f + 1] - r[p + 1], y = r[f + 2] - r[p + 2], b = h * y - g * v, x = g * _ - m * y, S = m * v - h * _, C = Math.hypot(b, x, S) || 1;
|
|
21
|
+
b /= C, x /= C, S /= C;
|
|
22
|
+
let w = (e * t + a) * 3;
|
|
23
|
+
i[w] = b, i[w + 1] = x, i[w + 2] = S;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
//#endregion
|
|
27
|
+
//#region src/geometry/curls/cone.ts
|
|
28
|
+
var r = 30 * Math.PI / 180, i = 44 * Math.PI / 180, a = 1.35, o = .7, s = 1.85, c = 1.15, l = .42, u = 1.08;
|
|
29
|
+
function d(e, t, d, f, p) {
|
|
30
|
+
let m = e.cols + 1, h = e.rows + 1, g = e.positions, _ = !!p.fill, v = Math.sin(Math.PI * f) ** .85, y = _ ? i : r, b = Math.PI / 2 - v * (Math.PI / 2 - y), x = Math.sin(b), S = Math.cos(b), C = 1 / Math.max(x, 1e-6), w = _ ? s : a, T = d * (w + ((_ ? c : o) - w) * v), E = (p.y - .5) * 2, D = E >= 0, O = Math.min(1, Math.abs(E) / l), k = 1 - O, A = D ? d + T : -T, j = Math.hypot(t, .5 * d - A), M = Math.max(j * x, t / Math.PI), N = _ ? f ** +u : f, P = -Math.PI * N, F = Math.cos(P), I = Math.sin(P);
|
|
31
|
+
if (v < 1e-4) {
|
|
32
|
+
for (let n = 0; n < h; n++) {
|
|
33
|
+
let r = n / e.rows * d;
|
|
34
|
+
for (let i = 0; i < m; i++) {
|
|
35
|
+
let a = i / e.cols * t, o = (n * m + i) * 3;
|
|
36
|
+
g[o] = a * F, g[o + 1] = r, g[o + 2] = -a * I;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
n(e);
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
for (let n = 0; n < h; n++) {
|
|
43
|
+
let r = n / e.rows * d;
|
|
44
|
+
for (let i = 0; i < m; i++) {
|
|
45
|
+
let a = i / e.cols * t, o = a, s = r, c = 0;
|
|
46
|
+
if (O > 1e-5) {
|
|
47
|
+
let e = D ? d - r : r, t = -T, n = Math.hypot(a, e - t);
|
|
48
|
+
if (n > 1e-8) {
|
|
49
|
+
let e = n * x, r = Math.asin(Math.min(1, Math.max(0, a / n))) * C, i = 1 - Math.cos(r), l = n + t - e * i * x;
|
|
50
|
+
o = e * Math.sin(r), s = D ? d - l : l, c = e * i * S;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
let l = o, u = s, f = c;
|
|
54
|
+
if (k > 1e-5) {
|
|
55
|
+
let e = a / M, t = M * Math.sin(e), n = M * (1 - Math.cos(e));
|
|
56
|
+
l = O * o + k * t, u = O * s + k * r, f = O * c + k * n;
|
|
57
|
+
}
|
|
58
|
+
let p = (n * m + i) * 3;
|
|
59
|
+
g[p] = l * F + f * I, g[p + 1] = u, g[p + 2] = -l * I + f * F;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
n(e);
|
|
63
|
+
}
|
|
64
|
+
//#endregion
|
|
65
|
+
//#region src/geometry/curls/simple.ts
|
|
66
|
+
function f(e, t, r, i) {
|
|
67
|
+
let a = e.cols + 1, o = e.rows + 1, s = e.positions, c = i * Math.PI, l = Math.cos(c), u = Math.sin(c);
|
|
68
|
+
for (let n = 0; n < a; n++) {
|
|
69
|
+
let i = n / e.cols * t, c = i * l, d = i * u;
|
|
70
|
+
for (let t = 0; t < o; t++) {
|
|
71
|
+
let i = (t * a + n) * 3;
|
|
72
|
+
s[i] = c, s[i + 1] = t / e.rows * r, s[i + 2] = d;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
n(e);
|
|
76
|
+
}
|
|
77
|
+
//#endregion
|
|
78
|
+
//#region src/geometry/curls/bundled.ts
|
|
79
|
+
var p = {
|
|
80
|
+
deform: d,
|
|
81
|
+
anchored: !0
|
|
82
|
+
}, m = {
|
|
83
|
+
deform: f,
|
|
84
|
+
anchored: !1,
|
|
85
|
+
flat: !0,
|
|
86
|
+
gloss: !1
|
|
87
|
+
}, h = {
|
|
88
|
+
cone: p,
|
|
89
|
+
simple: m
|
|
90
|
+
};
|
|
91
|
+
function g(t) {
|
|
92
|
+
if (typeof t != "string") return t;
|
|
93
|
+
let n = h[t];
|
|
94
|
+
if (n) return n;
|
|
95
|
+
throw e.includes(t) ? Error(`Zine: the '${t}' curl is not bundled. Import it and pass the model: import { ${t} } from '@zinejs/core/curls' → curl: ${t}`) : Error(`Zine: unknown curl ${JSON.stringify(t)}.`);
|
|
96
|
+
}
|
|
97
|
+
//#endregion
|
|
98
|
+
export { n as a, m as i, p as n, t as o, g as r, h as t };
|
|
99
|
+
|
|
100
|
+
//# sourceMappingURL=bundled-Cp43MIt0.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bundled-Cp43MIt0.js","names":[],"sources":["../src/geometry/curls/mesh.ts","../src/geometry/curls/cone.ts","../src/geometry/curls/simple.ts","../src/geometry/curls/bundled.ts"],"sourcesContent":["/**\n * Shared grid mesh + normal utilities for the page-curl models.\n *\n * A curl model fills `positions`/`normals` in place each frame; UVs are static grid\n * coordinates (no texture swimming). All models bend the same (cols+1)×(rows+1) grid.\n */\n\nexport interface PageMesh {\n readonly cols: number;\n readonly rows: number;\n /** ((cols+1)*(rows+1))*2 — static grid UVs (u across width, v down height). */\n readonly uvs: Float32Array;\n /** *3 — deformed positions, updated by the curl model. */\n readonly positions: Float32Array;\n /** *3 — per-vertex normals, updated by the curl model. */\n readonly normals: Float32Array;\n}\n\n/** Allocate a (cols+1)×(rows+1) grid mesh with static UVs (positions/normals filled by a curl). */\nexport function createPageMesh(cols: number, rows: number): PageMesh {\n const nx = cols + 1;\n const ny = rows + 1;\n const count = nx * ny;\n const uvs = new Float32Array(count * 2);\n for (let j = 0; j < ny; j++) {\n for (let i = 0; i < nx; i++) {\n const k = j * nx + i;\n uvs[k * 2] = i / cols;\n uvs[k * 2 + 1] = j / rows;\n }\n }\n return {\n cols,\n rows,\n uvs,\n positions: new Float32Array(count * 3),\n normals: new Float32Array(count * 3),\n };\n}\n\n/** Per-vertex normals from central differences of the deformed grid (front = +z when flat). */\nexport function computeNormals(mesh: PageMesh): void {\n const nx = mesh.cols + 1;\n const ny = mesh.rows + 1;\n const pos = mesh.positions;\n const nrm = mesh.normals;\n\n for (let j = 0; j < ny; j++) {\n for (let i = 0; i < nx; i++) {\n const iPrev = i > 0 ? i - 1 : i;\n const iNext = i < nx - 1 ? i + 1 : i;\n const jPrev = j > 0 ? j - 1 : j;\n const jNext = j < ny - 1 ? j + 1 : j;\n\n const a = (j * nx + iNext) * 3;\n const b = (j * nx + iPrev) * 3;\n const c = (jNext * nx + i) * 3;\n const e = (jPrev * nx + i) * 3;\n\n const tuX = pos[a]! - pos[b]!;\n const tuY = pos[a + 1]! - pos[b + 1]!;\n const tuZ = pos[a + 2]! - pos[b + 2]!;\n const tvX = pos[c]! - pos[e]!;\n const tvY = pos[c + 1]! - pos[e + 1]!;\n const tvZ = pos[c + 2]! - pos[e + 2]!;\n\n let nx0 = tuY * tvZ - tuZ * tvY;\n let ny0 = tuZ * tvX - tuX * tvZ;\n let nz0 = tuX * tvY - tuY * tvX;\n const l = Math.hypot(nx0, ny0, nz0) || 1;\n nx0 /= l;\n ny0 /= l;\n nz0 /= l;\n\n const k = (j * nx + i) * 3;\n nrm[k] = nx0;\n nrm[k + 1] = ny0;\n nrm[k + 2] = nz0;\n }\n }\n}\n","import { computeNormals, type PageMesh } from './mesh';\nimport type { CurlAnchor } from './types';\n\n/**\n * Cone angle at peak curl. π/2 is flat; smaller values wind the sheet tighter.\n * ~30° gives a soft, paper-like ridge without self-intersection on typical page\n * aspect ratios (Hong / Nuon / Project Austin all land in the 18–35° band).\n */\nconst THETA_MIN = (30 * Math.PI) / 180;\n/** Gentler opening for full-width lone pages — a tight cone reads as a funnel when\n * the leaf owns the whole viewport and hinges at the edge. */\nconst THETA_MIN_FILL = (44 * Math.PI) / 180;\n\n/**\n * How far past the page the cone apex sits, as a fraction of height, at rest.\n * Closer mid-turn sharpens the diagonal; farther reads more cylindrical.\n * Kept moderately distant so the sheet stays page-like without cloth-y sliding.\n */\nconst APEX_REST = 1.35;\nconst APEX_PEAK = 0.7;\n/** Farther apex on fill: softer diagonal, less cloth-y twist across the full leaf. */\nconst APEX_REST_FILL = 1.85;\nconst APEX_PEAK_FILL = 1.15;\n\n/**\n * Above this |anchor.y − 0.5| the deform is a pure cone; at the mid-edge it\n * blends fully to a cylinder (Project Austin’s conicContribution).\n */\nconst CORNER_PURE = 0.42;\n\n/**\n * Power on fill flop progress. Slightly >1 delays spine rotation so the cone develops\n * over the page before the leaf swings past the edge hinge — kept close to 1 so the\n * flop isn't packed into a late whip (lone pages dissolve rather than land).\n */\nconst FILL_RHO_POWER = 1.08;\n\n/**\n * Natural conical page curl — the Xerox PARC / iBooks model.\n *\n * The leaf wraps an imaginary right circular cone whose apex rides the spine and\n * whose opening angle θ breathes over the turn (Hong, Card & Chen, 2004). A corner\n * grab yields a diagonal cone; a mid-edge grab blends toward a cylinder so the\n * free edge lifts as one. The curled sheet then rotates about the spine and settles\n * flat on the far side. Arc length from the apex is preserved, so the paper never\n * stretches — the motion reads as stiff, premium stock rather than cloth.\n *\n * On a full-width lone page (`anchor.fill`) the hinge is the container edge with no\n * facing half to land on: the cone softens, the flop is delayed so the peel stays\n * over the page longer, and the renderer dissolves the sheet as it finishes.\n */\nexport function deformCone(mesh: PageMesh, W: number, H: number, t: number, anchor: CurlAnchor): void {\n const nx = mesh.cols + 1;\n const ny = mesh.rows + 1;\n const pos = mesh.positions;\n const fill = !!anchor.fill;\n\n // Curl envelope: 0 at the ends (flat), 1 at mid-turn. Soft power keeps the\n // ridge full through the middle third — paper holds its bend rather than\n // peaking and collapsing.\n const curl = Math.pow(Math.sin(Math.PI * t), 0.85);\n\n // θ: π/2 (identity) → THETA_MIN (pronounced curl) → π/2.\n const thetaMin = fill ? THETA_MIN_FILL : THETA_MIN;\n const theta = Math.PI / 2 - curl * (Math.PI / 2 - thetaMin);\n const sinTheta = Math.sin(theta);\n const cosTheta = Math.cos(theta);\n const invSinTheta = 1 / Math.max(sinTheta, 1e-6);\n\n // Apex distance: pulled in as the curl develops for a tighter diagonal.\n const apexRest = fill ? APEX_REST_FILL : APEX_REST;\n const apexPeak = fill ? APEX_PEAK_FILL : APEX_PEAK;\n const apexDist = H * (apexRest + (apexPeak - apexRest) * curl);\n\n // Corner bias: −1 = top edge, +1 = bottom. Near 0 → cylinder blend.\n const bias = (anchor.y - 0.5) * 2;\n const fromBottom = bias >= 0;\n const absBias = Math.abs(bias);\n let conic = Math.min(1, absBias / CORNER_PURE);\n const cylWeight = 1 - conic;\n\n // Cylinder radius matched to the cone’s free-edge cross-section (Austin), so\n // the blend is continuous as the grab slides from corner to mid-edge.\n // Apex sits past the *leading* edge (below for a bottom grab, above for top).\n const AyRef = fromBottom ? H + apexDist : -apexDist;\n const cylR = Math.hypot(W, 0.5 * H - AyRef);\n const cylRadius = Math.max(cylR * sinTheta, W / Math.PI);\n\n // Spine rotation: concurrent with the cone so the page flops while it curls.\n // Same x–z convention as `roll` (ρ: 0 → −π). On fill, delay the flop so the\n // peel develops over the page before the leaf swings past the edge hinge.\n const rhoT = fill ? Math.pow(t, FILL_RHO_POWER) : t;\n const rho = -Math.PI * rhoT;\n const cosR = Math.cos(rho);\n const sinR = Math.sin(rho);\n\n // Near the rests the cone is the identity plane. A finite-radius cylinder blend\n // still carries a tiny residual arc — skip it and rotate the flat sheet.\n if (curl < 1e-4) {\n for (let j = 0; j < ny; j++) {\n const y = (j / mesh.rows) * H;\n for (let i = 0; i < nx; i++) {\n const x0 = (i / mesh.cols) * W;\n const k = (j * nx + i) * 3;\n pos[k] = x0 * cosR;\n pos[k + 1] = y;\n pos[k + 2] = -x0 * sinR;\n }\n }\n computeNormals(mesh);\n return;\n }\n\n for (let j = 0; j < ny; j++) {\n const y0 = (j / mesh.rows) * H;\n for (let i = 0; i < nx; i++) {\n const x0 = (i / mesh.cols) * W;\n\n let cx = x0;\n let cy = y0;\n let cz = 0;\n\n if (conic > 1e-5) {\n // Canonical cone: apex above the page (A < 0) makes the *near* edge lead.\n // In our y-down leaf, that means the top. For a bottom grab we flip into\n // that space, deform, then flip back — one code path for both corners.\n const yIn = fromBottom ? H - y0 : y0;\n const A = -apexDist;\n const R = Math.hypot(x0, yIn - A);\n if (R > 1e-8) {\n const r = R * sinTheta;\n const beta = Math.asin(Math.min(1, Math.max(0, x0 / R))) * invSinTheta;\n const oneCos = 1 - Math.cos(beta);\n const yCone = R + A - r * oneCos * sinTheta;\n cx = r * Math.sin(beta);\n cy = fromBottom ? H - yCone : yCone;\n cz = r * oneCos * cosTheta;\n }\n }\n\n let bx = cx;\n let by = cy;\n let bz = cz;\n\n if (cylWeight > 1e-5) {\n const beta = x0 / cylRadius;\n const sx = cylRadius * Math.sin(beta);\n const sz = cylRadius * (1 - Math.cos(beta));\n bx = conic * cx + cylWeight * sx;\n by = conic * cy + cylWeight * y0;\n bz = conic * cz + cylWeight * sz;\n }\n\n const k = (j * nx + i) * 3;\n pos[k] = bx * cosR + bz * sinR;\n pos[k + 1] = by;\n pos[k + 2] = -bx * sinR + bz * cosR;\n }\n }\n\n computeNormals(mesh);\n}\n","import { computeNormals, type PageMesh } from './mesh';\n\n/**\n * Flat page turn — the plainest flip, matching the CSS renderer. The leaf stays a rigid\n * flat sheet and rotates around the spine (angle 0→π), going edge-on at the midpoint. No\n * cylinder bend; GPU-rendered here with the shared perspective so it reads like the CSS fold.\n */\nexport function deformSimple(mesh: PageMesh, W: number, H: number, t: number): void {\n const nx = mesh.cols + 1;\n const ny = mesh.rows + 1;\n const pos = mesh.positions;\n\n const angle = t * Math.PI;\n const cosA = Math.cos(angle);\n const sinA = Math.sin(angle);\n\n for (let i = 0; i < nx; i++) {\n const x0 = (i / mesh.cols) * W; // distance from the spine\n const X = x0 * cosA;\n const Z = x0 * sinA;\n for (let j = 0; j < ny; j++) {\n const k = (j * nx + i) * 3;\n pos[k] = X;\n pos[k + 1] = (j / mesh.rows) * H;\n pos[k + 2] = Z;\n }\n }\n\n computeNormals(mesh);\n}\n","import { deformCone } from './cone';\nimport { deformSimple } from './simple';\nimport { IMPORTABLE_CURLS, type CurlModel, type CurlSpec, type CurlType } from './types';\n\n/**\n * The curl models carried in the bundle, and the only ones nameable by string.\n *\n * Kept apart from `./index` so importing them does not drag in the other four: the barrel names\n * every model, which is right for a caller picking one but wrong for the renderer, which must\n * only ever pull these two.\n */\nexport const cone: CurlModel = { deform: deformCone, anchored: true };\nexport const simple: CurlModel = {\n deform: deformSimple,\n anchored: false,\n flat: true,\n gloss: false,\n};\n\nexport const BUNDLED_CURLS: Record<CurlType, CurlModel> = { cone, simple };\n\n/**\n * Turn a `curl` option into a model. Strings name a bundled curl; anything else is already a\n * model, imported from `@zinejs/core/curls` or written by the caller.\n */\nexport function resolveCurl(spec: CurlSpec): CurlModel {\n if (typeof spec !== 'string') return spec;\n const model = BUNDLED_CURLS[spec];\n if (model) return model;\n // Reached only when validation was bypassed (a renderer used directly, say), so name the fix\n // rather than the mistake: these curls are real, they just are not bundled.\n if (IMPORTABLE_CURLS.includes(spec)) {\n throw new Error(\n `Zine: the '${spec}' curl is not bundled. Import it and pass the model: ` +\n `import { ${spec} } from '@zinejs/core/curls' → curl: ${spec}`,\n );\n }\n throw new Error(`Zine: unknown curl ${JSON.stringify(spec)}.`);\n}\n"],"mappings":"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"}
|
package/dist/curls.js
ADDED
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import { n as e, r as t, t as n } from "./types-DEz3mRLI.js";
|
|
2
|
+
import { a as r, i, n as a, o, t as s } from "./bundled-Cp43MIt0.js";
|
|
3
|
+
//#region src/geometry/curls/roll.ts
|
|
4
|
+
function c(e, t, n, i) {
|
|
5
|
+
let a = e.cols + 1, o = e.rows + 1, s = e.positions, c = Math.max(1e-6, i < .5 ? i * 2 * Math.PI : (1 - (i - .5) * 2) * Math.PI), l = t / c, u = i < .5 ? 0 : -(i - .5) * 2 * Math.PI, d = Math.cos(u), f = Math.sin(u);
|
|
6
|
+
for (let t = 0; t < a; t++) {
|
|
7
|
+
let r = t / e.cols * c, i = Math.sin(r) * l, u = (1 - Math.cos(r)) * l, p = i * d + u * f, m = -i * f + u * d;
|
|
8
|
+
for (let r = 0; r < o; r++) {
|
|
9
|
+
let i = (r * a + t) * 3;
|
|
10
|
+
s[i] = p, s[i + 1] = r / e.rows * n, s[i + 2] = m;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
r(e);
|
|
14
|
+
}
|
|
15
|
+
//#endregion
|
|
16
|
+
//#region src/geometry/curls/leaf.ts
|
|
17
|
+
var l = .34, u = 11 * Math.PI / 180, d = 128;
|
|
18
|
+
function f() {
|
|
19
|
+
let e = /* @__PURE__ */ new Float64Array(129), t = /* @__PURE__ */ new Float64Array(129), n = 1 / d, r = (e) => Math.PI * e - .5 * Math.sin(2 * Math.PI * e);
|
|
20
|
+
for (let i = 1; i <= d; i++) {
|
|
21
|
+
let a = r((i - 1) * n), o = r(i * n);
|
|
22
|
+
e[i] = e[i - 1] + .5 * (Math.cos(a) + Math.cos(o)) * n, t[i] = t[i - 1] + .5 * (Math.sin(a) + Math.sin(o)) * n;
|
|
23
|
+
}
|
|
24
|
+
return e[d] = 0, {
|
|
25
|
+
x: e,
|
|
26
|
+
z: t
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
var p = f(), m = p.z[d];
|
|
30
|
+
function h(e) {
|
|
31
|
+
let t = Math.max(0, Math.min(1, e)) * d, n = Math.min(d - 1, Math.floor(t)), r = t - n;
|
|
32
|
+
return [p.x[n] + (p.x[n + 1] - p.x[n]) * r, p.z[n] + (p.z[n + 1] - p.z[n]) * r];
|
|
33
|
+
}
|
|
34
|
+
function g(e, t, n, i, a) {
|
|
35
|
+
let o = e.cols + 1, s = e.rows + 1, c = e.positions;
|
|
36
|
+
if (i <= 1e-7 || i >= .9999999) {
|
|
37
|
+
let a = i < .5 ? 1 : -1;
|
|
38
|
+
for (let r = 0; r < s; r++) {
|
|
39
|
+
let i = r / e.rows * n;
|
|
40
|
+
for (let n = 0; n < o; n++) {
|
|
41
|
+
let s = (r * o + n) * 3;
|
|
42
|
+
c[s] = a * (n / e.cols) * t, c[s + 1] = i, c[s + 2] = 0;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
r(e);
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
let d = Math.sin(Math.PI * i) ** .72, f = Math.max(1e-6, t * l * d), p = Math.max(-1, Math.min(1, (a.y - .5) * 2)) * u * Math.sin(Math.PI * i) ** 1.15, g = Math.cos(p), _ = Math.sin(p), v = -_, y = g, b = Math.abs(_) * n * .5, x = t + b / g, S = x + (-(f + b) / g - x) * i, C = n * .5;
|
|
49
|
+
for (let r = 0; r < s; r++) {
|
|
50
|
+
let i = r / e.rows * n;
|
|
51
|
+
for (let n = 0; n < o; n++) {
|
|
52
|
+
let a = n / e.cols * t, s = a - S, l = i - C, u = s * g + l * _, d = s * v + l * y, p = (r * o + n) * 3;
|
|
53
|
+
if (u <= 0) {
|
|
54
|
+
c[p] = a, c[p + 1] = i, c[p + 2] = 0;
|
|
55
|
+
continue;
|
|
56
|
+
}
|
|
57
|
+
let b, x;
|
|
58
|
+
if (u < f) {
|
|
59
|
+
let [e, t] = h(u / f);
|
|
60
|
+
b = f * e, x = f * t;
|
|
61
|
+
} else b = -(u - f), x = f * m;
|
|
62
|
+
c[p] = S + v * d + g * b, c[p + 1] = C + y * d + _ * b, c[p + 2] = x;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
r(e);
|
|
66
|
+
}
|
|
67
|
+
//#endregion
|
|
68
|
+
//#region src/geometry/curls/flick.ts
|
|
69
|
+
var _ = .45;
|
|
70
|
+
function v(e, t, n, i, a) {
|
|
71
|
+
let o = e.cols + 1, s = e.rows + 1, c = e.cols, l = e.positions, u = t / c, d = Math.PI * i, f = -.52 * Math.sin(2 * Math.PI * i);
|
|
72
|
+
for (let t = 0; t < s; t++) {
|
|
73
|
+
let r = t / e.rows, i = f * (1 + _ * Math.abs(r - a.y)), s = r * n, p = 0, m = 0, h = Math.cos(d), g = Math.sin(d);
|
|
74
|
+
l[t * o * 3] = 0, l[t * o * 3 + 1] = s, l[t * o * 3 + 2] = 0;
|
|
75
|
+
for (let e = 1; e < o; e++) {
|
|
76
|
+
let n = e / c, r = d + i * n * n, a = Math.cos(r), f = Math.sin(r);
|
|
77
|
+
p += .5 * (h + a) * u, m += .5 * (g + f) * u, h = a, g = f;
|
|
78
|
+
let _ = (t * o + e) * 3;
|
|
79
|
+
l[_] = p, l[_ + 1] = s, l[_ + 2] = m;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
r(e);
|
|
83
|
+
}
|
|
84
|
+
//#endregion
|
|
85
|
+
//#region src/geometry/curls/silk.ts
|
|
86
|
+
var y = .52, b = .62, x = .5, S = 1.12;
|
|
87
|
+
function C(e, t, n, i, a) {
|
|
88
|
+
let o = e.cols + 1, s = e.rows + 1, c = e.cols, l = e.positions, u = t / c, d = !!a.fill;
|
|
89
|
+
if (i <= 1e-7 || i >= .9999999) {
|
|
90
|
+
let a = i < .5 ? 1 : -1;
|
|
91
|
+
for (let r = 0; r < s; r++) {
|
|
92
|
+
let i = r / e.rows * n;
|
|
93
|
+
for (let n = 0; n < o; n++) {
|
|
94
|
+
let s = (r * o + n) * 3;
|
|
95
|
+
l[s] = a * (n / e.cols) * t, l[s + 1] = i, l[s + 2] = 0;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
r(e);
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
let f = Math.PI * (d ? i ** +S : i), p = y * Math.sin(Math.PI * i) ** .8, m = b * Math.sin(Math.PI * i) * (1 - i);
|
|
102
|
+
for (let t = 0; t < s; t++) {
|
|
103
|
+
let r = t / e.rows, i = r * n, s = 1 - x * Math.abs(r - a.y), d = p * (.75 + .25 * s), h = m * s, g = 0, _ = 0, v = Math.cos(f), y = Math.sin(f);
|
|
104
|
+
l[t * o * 3] = 0, l[t * o * 3 + 1] = i, l[t * o * 3 + 2] = 0;
|
|
105
|
+
for (let e = 1; e < o; e++) {
|
|
106
|
+
let n = e / c, r = f + d * Math.sin(2 * Math.PI * n) + h * n * n, a = Math.cos(r), s = Math.sin(r);
|
|
107
|
+
g += .5 * (v + a) * u, _ += .5 * (y + s) * u, v = a, y = s;
|
|
108
|
+
let p = (t * o + e) * 3;
|
|
109
|
+
l[p] = g, l[p + 1] = i, l[p + 2] = _;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
r(e);
|
|
113
|
+
}
|
|
114
|
+
//#endregion
|
|
115
|
+
//#region src/geometry/curls/index.ts
|
|
116
|
+
var w = {
|
|
117
|
+
deform: c,
|
|
118
|
+
anchored: !1,
|
|
119
|
+
flat: !0
|
|
120
|
+
}, T = {
|
|
121
|
+
deform: g,
|
|
122
|
+
anchored: !0
|
|
123
|
+
}, E = {
|
|
124
|
+
deform: v,
|
|
125
|
+
anchored: !0
|
|
126
|
+
}, D = {
|
|
127
|
+
deform: C,
|
|
128
|
+
anchored: !0
|
|
129
|
+
};
|
|
130
|
+
//#endregion
|
|
131
|
+
export { s as BUNDLED_CURLS, n as CURL_TYPES, e as DEFAULT_CURL, t as IMPORTABLE_CURLS, r as computeNormals, a as cone, o as createPageMesh, E as flick, T as leaf, w as roll, D as silk, i as simple };
|
|
132
|
+
|
|
133
|
+
//# sourceMappingURL=curls.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"curls.js","names":[],"sources":["../src/geometry/curls/roll.ts","../src/geometry/curls/leaf.ts","../src/geometry/curls/flick.ts","../src/geometry/curls/silk.ts","../src/geometry/curls/index.ts"],"sourcesContent":["import { computeNormals, type PageMesh } from './mesh';\n\n/**\n * Roll-and-flop. The leaf wraps a cylinder whose wrap angle grows 0→π over the first\n * half while its radius (= W/theta) shrinks, so the sheet rolls up off the surface in\n * place; over the second half it unwraps π→0 while rigidly rotating around the spine\n * 0→-π down onto the far side. Arc length across the width is exactly preserved.\n */\nexport function deformRoll(mesh: PageMesh, W: number, H: number, t: number): void {\n const nx = mesh.cols + 1;\n const ny = mesh.rows + 1;\n const pos = mesh.positions;\n\n const theta = Math.max(1e-6, t < 0.5 ? t * 2 * Math.PI : (1 - (t - 0.5) * 2) * Math.PI);\n const radius = W / theta;\n const rot = t < 0.5 ? 0 : -(t - 0.5) * 2 * Math.PI;\n const cosR = Math.cos(rot);\n const sinR = Math.sin(rot);\n\n for (let i = 0; i < nx; i++) {\n const rad = (i / mesh.cols) * theta;\n const cx = Math.sin(rad) * radius;\n const cz = (1 - Math.cos(rad)) * radius;\n const X = cx * cosR + cz * sinR;\n const Z = -cx * sinR + cz * cosR;\n for (let j = 0; j < ny; j++) {\n const k = (j * nx + i) * 3;\n pos[k] = X;\n pos[k + 1] = (j / mesh.rows) * H;\n pos[k + 2] = Z;\n }\n }\n\n computeNormals(mesh);\n}\n","import { computeNormals, type PageMesh } from './mesh';\nimport type { CurlAnchor } from './types';\n\n/** Peak material width occupied by the bending wave. */\nconst MAX_BEND_LENGTH = 0.34;\n\n/** Maximum tilt of the rolling axis for a corner-led turn. */\nconst MAX_TILT = (11 * Math.PI) / 180;\n\nconst PROFILE_STEPS = 128;\n\n/**\n * Unit-length raised-cosine curvature profile.\n *\n * κ(s) = π(1 - cos(2πs)), so its integrated tangent angle is\n * θ(s) = πs - ½sin(2πs). Curvature is exactly zero at both ends and integrates\n * to π: the incoming and outgoing planes are flat, opposite-facing, and meet\n * the bend without a crease. X/Z are arc-length integrals of cos(θ)/sin(θ).\n */\nfunction makeProfile(): { x: Float64Array; z: Float64Array } {\n const x = new Float64Array(PROFILE_STEPS + 1);\n const z = new Float64Array(PROFILE_STEPS + 1);\n const ds = 1 / PROFILE_STEPS;\n const theta = (s: number): number => Math.PI * s - 0.5 * Math.sin(2 * Math.PI * s);\n for (let i = 1; i <= PROFILE_STEPS; i++) {\n const a = theta((i - 1) * ds);\n const b = theta(i * ds);\n x[i] = x[i - 1]! + 0.5 * (Math.cos(a) + Math.cos(b)) * ds;\n z[i] = z[i - 1]! + 0.5 * (Math.sin(a) + Math.sin(b)) * ds;\n }\n // Symmetry makes this analytically zero; remove accumulated floating-point drift.\n x[PROFILE_STEPS] = 0;\n return { x, z };\n}\n\nconst PROFILE = makeProfile();\nconst PROFILE_HEIGHT = PROFILE.z[PROFILE_STEPS]!;\n\nfunction sampleProfile(s: number): [x: number, z: number] {\n const p = Math.max(0, Math.min(1, s)) * PROFILE_STEPS;\n const i = Math.min(PROFILE_STEPS - 1, Math.floor(p));\n const f = p - i;\n return [\n PROFILE.x[i]! + (PROFILE.x[i + 1]! - PROFILE.x[i]!) * f,\n PROFILE.z[i]! + (PROFILE.z[i + 1]! - PROFILE.z[i]!) * f,\n ];\n}\n\n/**\n * Traveling smooth-curvature leaf curl.\n *\n * Inspired by rolling-cylinder page curls and modern developable-surface book\n * simulations, but with a compact raised-cosine curvature wave instead of a\n * constant-radius cylinder. The sheet has three regions:\n *\n * 1. untouched paper before the wave,\n * 2. an isometric bend whose curvature smoothly rises and falls,\n * 3. a flat, reflected flap after the wave.\n *\n * The wave travels from the free edge to just beyond the spine while its width grows\n * and collapses. Integrating a unit tangent preserves material length exactly; straight\n * ruling lines preserve distance along the curl axis. Curvature reaches zero at both\n * seams, eliminating the hard crease shared by circular/fold models.\n */\nexport function deformLeaf(mesh: PageMesh, W: number, H: number, t: number, anchor: CurlAnchor): void {\n const nx = mesh.cols + 1;\n const ny = mesh.rows + 1;\n const pos = mesh.positions;\n\n // Exact rest poses avoid the tiny numerical ridge left by a vanishing wave.\n if (t <= 1e-7 || t >= 1 - 1e-7) {\n const side = t < 0.5 ? 1 : -1;\n for (let j = 0; j < ny; j++) {\n const y = (j / mesh.rows) * H;\n for (let i = 0; i < nx; i++) {\n const k = (j * nx + i) * 3;\n pos[k] = side * (i / mesh.cols) * W;\n pos[k + 1] = y;\n pos[k + 2] = 0;\n }\n }\n computeNormals(mesh);\n return;\n }\n\n // The wave broadens through the middle, then tightens as the leaf settles.\n const envelope = Math.pow(Math.sin(Math.PI * t), 0.72);\n const bendLength = Math.max(1e-6, W * MAX_BEND_LENGTH * envelope);\n\n // Bottom grabs tilt the ruling clockwise in page coordinates; top grabs mirror it.\n // The tilt fades at both rest states so the page lands exactly square.\n const anchorBias = Math.max(-1, Math.min(1, (anchor.y - 0.5) * 2));\n const tilt = anchorBias * MAX_TILT * Math.pow(Math.sin(Math.PI * t), 1.15);\n const nX = Math.cos(tilt);\n const nY = Math.sin(tilt);\n const fX = -nY;\n const fY = nX;\n\n // Place the axis outside the whole rectangle at t=0 and beyond the spine at t=1.\n // Accounting for tilt keeps every row in the correct physical region at the ends.\n const diagonalReach = Math.abs(nY) * H * 0.5;\n const startX = W + diagonalReach / nX;\n const endX = -(bendLength + diagonalReach) / nX;\n const axisX = startX + (endX - startX) * t;\n const axisY = H * 0.5;\n\n for (let j = 0; j < ny; j++) {\n const y0 = (j / mesh.rows) * H;\n for (let i = 0; i < nx; i++) {\n const x0 = (i / mesh.cols) * W;\n const relX = x0 - axisX;\n const relY = y0 - axisY;\n const d = relX * nX + relY * nY;\n const e = relX * fX + relY * fY;\n const k = (j * nx + i) * 3;\n\n if (d <= 0) {\n // The wave has not reached this point: untouched front-facing paper.\n pos[k] = x0;\n pos[k + 1] = y0;\n pos[k + 2] = 0;\n continue;\n }\n\n let normalDistance: number;\n let z: number;\n if (d < bendLength) {\n // Scale the unit arc-length profile by the material width of this wave.\n const [profileX, profileZ] = sampleProfile(d / bendLength);\n normalDistance = bendLength * profileX;\n z = bendLength * profileZ;\n } else {\n // The tangent has rotated by π; paper leaves the wave flat and reversed.\n normalDistance = -(d - bendLength);\n z = bendLength * PROFILE_HEIGHT;\n }\n\n pos[k] = axisX + fX * e + nX * normalDistance;\n pos[k + 1] = axisY + fY * e + nY * normalDistance;\n pos[k + 2] = z;\n }\n }\n\n computeNormals(mesh);\n}\n","import { computeNormals, type PageMesh } from './mesh';\nimport type { CurlAnchor } from './types';\n\n/**\n * Peak inertial tip lag in radians (~30°). How far the free edge trails the\n * spine rotation at the height of the acceleration phase, and symmetrically how\n * far it follows through while the turn decelerates.\n */\nconst SWAY = 0.52;\n\n/**\n * Extra lag for rows far from the grabbed corner (0 = whole edge moves as one).\n * The driven corner is held; the diagonal remainder of the sheet trails it.\n */\nconst LAG = 0.45;\n\n/**\n * Inertial follow-through page flick.\n *\n * The leaf is a cantilever clamped at the spine and driven through a rotation\n * ρ(t) = πt. Paper inertia (the Euler force, ∝ −ρ̈) bends the sheet opposite the\n * angular acceleration with a first-mode-like profile — zero curvature at the\n * clamped spine, maximal at the free edge. Under an eased turn the acceleration\n * changes sign at mid-flight, so the free edge trails while the turn winds up,\n * swings through vertical, then overtakes and settles as the turn slows: the\n * follow-through/overlapping-action principle, grounded in base-rotated\n * cantilever dynamics. Tangent angles are integrated along the width, so the\n * sheet never stretches, and the curvature direction reversing over the turn is\n * what none of the wrap-style curls do.\n *\n * Rows far from the grabbed corner lag slightly more than the driven row, so a\n * corner grab pulls a soft living diagonal across the sheet.\n */\nexport function deformFlick(mesh: PageMesh, W: number, H: number, t: number, anchor: CurlAnchor): void {\n const nx = mesh.cols + 1;\n const ny = mesh.rows + 1;\n const cols = mesh.cols;\n const pos = mesh.positions;\n const ds = W / cols;\n\n // Base rotation about the spine, 0 → π (same landing convention as `simple`).\n const rho = Math.PI * t;\n\n // Inertial amplitude ∝ −ρ̈ of an eased unit turn: the tip trails (negative)\n // while accelerating, leads (positive) while braking, and is zero at both\n // rests and at peak speed mid-turn.\n const amplitude = -SWAY * Math.sin(2 * Math.PI * t);\n\n for (let j = 0; j < ny; j++) {\n const v = j / mesh.rows;\n // The grabbed row is driven directly; distance from it adds trailing inertia.\n const rowAmplitude = amplitude * (1 + LAG * Math.abs(v - anchor.y));\n const y = v * H;\n\n // Integrate the unit tangent of θ(u) = ρ + A·u² across the width (trapezoid\n // per grid cell). u² is the first-mode tangent shape: clamped flat at the\n // spine, curving ever more freely toward the edge. Exact arc length.\n let x = 0;\n let z = 0;\n let cosPrev = Math.cos(rho);\n let sinPrev = Math.sin(rho);\n pos[(j * nx) * 3] = 0;\n pos[(j * nx) * 3 + 1] = y;\n pos[(j * nx) * 3 + 2] = 0;\n for (let i = 1; i < nx; i++) {\n const u = i / cols;\n const theta = rho + rowAmplitude * u * u;\n const cosCur = Math.cos(theta);\n const sinCur = Math.sin(theta);\n x += 0.5 * (cosPrev + cosCur) * ds;\n z += 0.5 * (sinPrev + sinCur) * ds;\n cosPrev = cosCur;\n sinPrev = sinCur;\n\n const k = (j * nx + i) * 3;\n pos[k] = x;\n pos[k + 1] = y;\n pos[k + 2] = z;\n }\n }\n\n computeNormals(mesh);\n}\n","import { computeNormals, type PageMesh } from './mesh';\nimport type { CurlAnchor } from './types';\n\n/**\n * Peak S-curve amplitude in radians. Mid-turn the tangent oscillates about the\n * spine angle so the cross-section forms a true inflection (two opposite bends).\n * ~30° reads as thick stock turned by hand, not a knife crease.\n */\nconst S_AMP = 0.52;\n\n/**\n * Early free-edge peel lead in radians. The grabbed tip lifts ahead of the body\n * — first motion of a careful hand turn. Strongest near t≈0.35, gone by rest.\n */\nconst PEEL_LEAD = 0.62;\n\n/**\n * How much rows far from the grab trail the driven corner (0 = rigid across height).\n * Builds the soft diagonal of a corner-led hand turn.\n */\nconst ROW_LAG = 0.5;\n\n/**\n * Power on spine progress for full-width lone pages. >1 delays the flop so the\n * S develops over the sheet before the leaf dissolves off the edge hinge.\n */\nconst FILL_RHO_POWER = 1.12;\n\n/**\n * Silk — hand-turned S-curve page.\n *\n * This is not a traveling contact wave (`leaf`), not a cone wrap (`cone`), not a\n * cylinder roll (`roll`), and not a single-mode inertial cantilever (`flick`).\n *\n * Real paper turned by hand takes an S-shaped cross-section: a main bend through\n * the near half and a reverse bend through the far half (the flap over the\n * fingers). The sheet is a developable strip clamped at the spine and driven\n * through a base rotation ρ(t) = πt. Along the width the tangent is:\n *\n * θ(u) = ρ + env·S·sin(2πu) + peel(t)·u²\n *\n * where:\n * - sin(2πu) is a full-period S (zero net at spine and free edge, opposite\n * bends in the two halves) — a true inflection that none of the other\n * models produce mid-turn,\n * - u² is an early peel lead that lifts the free edge first, then releases.\n *\n * env = sin(πt) holds the S through the middle and forces exact flat rests.\n * Rows far from the tap lag so a corner grab draws a living diagonal.\n * Arc length is integrated with the unit tangent (trapezoid per grid cell), so\n * the paper never stretches.\n */\nexport function deformSilk(mesh: PageMesh, W: number, H: number, t: number, anchor: CurlAnchor): void {\n const nx = mesh.cols + 1;\n const ny = mesh.rows + 1;\n const cols = mesh.cols;\n const pos = mesh.positions;\n const ds = W / cols;\n const fill = !!anchor.fill;\n\n // Exact rests: shaping terms vanish with env, but pin the mesh explicitly.\n if (t <= 1e-7 || t >= 1 - 1e-7) {\n const side = t < 0.5 ? 1 : -1;\n for (let j = 0; j < ny; j++) {\n const y = (j / mesh.rows) * H;\n for (let i = 0; i < nx; i++) {\n const k = (j * nx + i) * 3;\n pos[k] = side * (i / mesh.cols) * W;\n pos[k + 1] = y;\n pos[k + 2] = 0;\n }\n }\n computeNormals(mesh);\n return;\n }\n\n // Spine rotation. On a fill leaf, delay slightly so the S develops on-page.\n const rhoT = fill ? Math.pow(t, FILL_RHO_POWER) : t;\n const rho = Math.PI * rhoT;\n\n // S envelope: 0 at rests, full through the middle third.\n const env = Math.pow(Math.sin(Math.PI * t), 0.8);\n const sAmp = S_AMP * env;\n\n // Early peel lead on the free edge: peaks before mid-turn, zero at both rests.\n // sin(πt)·(1−t) peaks near t≈0.35 — corner lifts while the body catches up.\n const peelAmp = PEEL_LEAD * Math.sin(Math.PI * t) * (1 - t);\n\n for (let j = 0; j < ny; j++) {\n const v = j / mesh.rows;\n const y = v * H;\n // Grabbed row is driven hardest; far rows trail (soft diagonal).\n const rowLead = 1 - ROW_LAG * Math.abs(v - anchor.y);\n const rowS = sAmp * (0.75 + 0.25 * rowLead);\n const rowPeel = peelAmp * rowLead;\n\n let x = 0;\n let z = 0;\n let cosPrev = Math.cos(rho);\n let sinPrev = Math.sin(rho);\n pos[j * nx * 3] = 0;\n pos[j * nx * 3 + 1] = y;\n pos[j * nx * 3 + 2] = 0;\n\n for (let i = 1; i < nx; i++) {\n const u = i / cols;\n // S inflection + early free-edge peel. Spine (u=0) is exactly ρ.\n const theta = rho + rowS * Math.sin(2 * Math.PI * u) + rowPeel * u * u;\n const cosCur = Math.cos(theta);\n const sinCur = Math.sin(theta);\n x += 0.5 * (cosPrev + cosCur) * ds;\n z += 0.5 * (sinPrev + sinCur) * ds;\n cosPrev = cosCur;\n sinPrev = sinCur;\n\n const k = (j * nx + i) * 3;\n pos[k] = x;\n pos[k + 1] = y;\n pos[k + 2] = z;\n }\n }\n\n computeNormals(mesh);\n}\n","/**\n * Page-curl registry. Each model turns a 0→1 flip progress into a bent page mesh; the\n * WebGL2 renderer picks one by the `curl` option. `anchored` models fold from a corner\n * given by `anchor.y` (0 = top, 1 = bottom — where the reader tapped); the others roll\n * or rotate the whole free edge and ignore it.\n *\n * Only `cone` (the default) and `simple` (used for reduced motion) are reachable from the\n * engine, so only those two are bundled. The rest are exported here as individual models for\n * callers to import and pass to `curl` — see `@zinejs/core/curls`. Each is a separate binding\n * rather than a member of one object, which is what lets a bundler drop the ones nobody names.\n */\nimport { deformRoll } from './roll';\nimport { deformLeaf } from './leaf';\nimport { deformFlick } from './flick';\nimport { deformSilk } from './silk';\nimport type { CurlModel } from './types';\n\nexport { createPageMesh, computeNormals, type PageMesh } from './mesh';\nexport { CURL_TYPES, DEFAULT_CURL, IMPORTABLE_CURLS } from './types';\nexport type { CurlAnchor, CurlDeform, CurlModel, CurlType, CurlSpec } from './types';\nexport { cone, simple, BUNDLED_CURLS } from './bundled';\n\n// `flat` says the sheet is already flat by mid-turn, so a lone page may dissolve on the earlier\n// schedule. Roll qualifies despite bending: it rolls up and flops over well before it lands.\nexport const roll: CurlModel = { deform: deformRoll, anchored: false, flat: true };\nexport const leaf: CurlModel = { deform: deformLeaf, anchored: true };\nexport const flick: CurlModel = { deform: deformFlick, anchored: true };\nexport const silk: CurlModel = { deform: deformSilk, anchored: true };\n"],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { type CurlModel, type CurlSpec, type CurlType } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* The curl models carried in the bundle, and the only ones nameable by string.
|
|
4
|
+
*
|
|
5
|
+
* Kept apart from `./index` so importing them does not drag in the other four: the barrel names
|
|
6
|
+
* every model, which is right for a caller picking one but wrong for the renderer, which must
|
|
7
|
+
* only ever pull these two.
|
|
8
|
+
*/
|
|
9
|
+
export declare const cone: CurlModel;
|
|
10
|
+
export declare const simple: CurlModel;
|
|
11
|
+
export declare const BUNDLED_CURLS: Record<CurlType, CurlModel>;
|
|
12
|
+
/**
|
|
13
|
+
* Turn a `curl` option into a model. Strings name a bundled curl; anything else is already a
|
|
14
|
+
* model, imported from `@zinejs/core/curls` or written by the caller.
|
|
15
|
+
*/
|
|
16
|
+
export declare function resolveCurl(spec: CurlSpec): CurlModel;
|
|
@@ -1,5 +1,9 @@
|
|
|
1
|
-
import type { CurlModel
|
|
1
|
+
import type { CurlModel } from './types';
|
|
2
2
|
export { createPageMesh, computeNormals, type PageMesh } from './mesh';
|
|
3
|
-
export { CURL_TYPES, DEFAULT_CURL } from './types';
|
|
4
|
-
export type { CurlAnchor, CurlDeform, CurlModel, CurlType } from './types';
|
|
5
|
-
export
|
|
3
|
+
export { CURL_TYPES, DEFAULT_CURL, IMPORTABLE_CURLS } from './types';
|
|
4
|
+
export type { CurlAnchor, CurlDeform, CurlModel, CurlType, CurlSpec } from './types';
|
|
5
|
+
export { cone, simple, BUNDLED_CURLS } from './bundled';
|
|
6
|
+
export declare const roll: CurlModel;
|
|
7
|
+
export declare const leaf: CurlModel;
|
|
8
|
+
export declare const flick: CurlModel;
|
|
9
|
+
export declare const silk: CurlModel;
|
|
@@ -19,7 +19,29 @@ export interface CurlModel {
|
|
|
19
19
|
readonly deform: CurlDeform;
|
|
20
20
|
/** True when the fold originates at a corner (`anchor.y`) rather than the whole edge. */
|
|
21
21
|
readonly anchored: boolean;
|
|
22
|
+
/**
|
|
23
|
+
* True when the sheet is flat by mid-turn, so a lone page can start dissolving earlier: there
|
|
24
|
+
* is no curl left to read. Defaults to false, which suits a model still bent as it lands.
|
|
25
|
+
*/
|
|
26
|
+
readonly flat?: boolean;
|
|
27
|
+
/**
|
|
28
|
+
* False to drop the specular highlight, for a sheet that never bends and so has no curve to
|
|
29
|
+
* catch the light. Defaults to true.
|
|
30
|
+
*/
|
|
31
|
+
readonly gloss?: boolean;
|
|
22
32
|
}
|
|
23
|
-
|
|
33
|
+
/**
|
|
34
|
+
* The curl models carried in the bundle: the default, and the flat turn reduced motion falls
|
|
35
|
+
* back to. Everything else is imported from `@zinejs/core/curls` and passed as a model, so a
|
|
36
|
+
* book that never uses it never pays for it.
|
|
37
|
+
*/
|
|
38
|
+
export type CurlType = 'cone' | 'simple';
|
|
24
39
|
export declare const CURL_TYPES: CurlType[];
|
|
40
|
+
/**
|
|
41
|
+
* Curl models that exist but are not bundled. Named only so passing one as a string can say what
|
|
42
|
+
* to do about it instead of failing as an unknown value.
|
|
43
|
+
*/
|
|
44
|
+
export declare const IMPORTABLE_CURLS: string[];
|
|
25
45
|
export declare const DEFAULT_CURL: CurlType;
|
|
46
|
+
/** What the `curl` option accepts: a bundled name, or a model imported (or written) by the caller. */
|
|
47
|
+
export type CurlSpec = CurlType | CurlModel;
|
package/dist/index.d.ts
CHANGED
|
@@ -9,5 +9,6 @@ export type { RendererOption, RendererKind } from './renderer/select';
|
|
|
9
9
|
export type { Renderer, SpreadContent, PageContent, FlipDirection, LayoutMetrics, RenderOptions } from './renderer/types';
|
|
10
10
|
export type { ZineEventMap } from './engine/emitter';
|
|
11
11
|
export type { Direction, Spread } from './engine/spread';
|
|
12
|
-
export { CURL_TYPES } from './geometry/curls/types';
|
|
13
|
-
export type { CurlType, CurlAnchor } from './geometry/curls/types';
|
|
12
|
+
export { CURL_TYPES, IMPORTABLE_CURLS } from './geometry/curls/types';
|
|
13
|
+
export type { CurlType, CurlSpec, CurlModel, CurlDeform, CurlAnchor } from './geometry/curls/types';
|
|
14
|
+
export type { PageMesh } from './geometry/curls/mesh';
|