UNPKG

one

Version:

One is a React framework for web, iOS, and Android apps.

141 lines (139 loc) • 5.44 kB
const animatorKey = /* @__PURE__ */ Symbol.for("one.native.animator"); function animatedSwiftStyle(animator) { return { ...animator.samples[0], [animatorKey]: animator }; } function animatorStyleOf(style) { return style[animatorKey]; } const colorFields = /* @__PURE__ */ new Set([ "foregroundStyle", "tint", "background", "borderColor", "glassEffectTint" ]); function same(a, b) { return a === b || JSON.stringify(a) === JSON.stringify(b); } function sdkPairs(style) { return style.sdkModifiers ? JSON.parse(style.sdkModifiers) : []; } function withPayload(base, payload) { return { ...base, sdkModifiers: JSON.stringify([...sdkPairs(base), ["oneNativeAnimator", JSON.stringify(payload)]]) }; } function phaseNative(animator, natives) { const keys = [...new Set(natives.flatMap((native) => Object.keys(native)))]; const varying = keys.filter((key) => natives.some((native) => !same(native[key], natives[0][key]))); for (const key of varying) { if (colorFields.has(key) && natives.some((native) => native[key] !== void 0 && typeof native[key] !== "number")) throw new Error(`${animator.owner} content can vary ${key} by phase only with plain colors, not platform colors`); } const phases = natives.map((native) => Object.fromEntries(varying.filter((key) => native[key] !== void 0).map((key) => [key, native[key]]))); return withPayload(natives[0], { id: animator.id, kind: "phase", varying, phases }); } const numericText = /^-?(?:\d+\.?\d*|\.\d+)(?:e[+-]?\d+)?$/i; function leavesOf(value) { const leaves = []; const texts = []; const leaf = (number, text, quoted) => { leaves.push(number); texts.push(text); return quoted ? `__oneKS${leaves.length - 1}__` : `__oneKN${leaves.length - 1}__`; }; if (numericText.test(value)) return { shape: leaf(Number(value), value, true), leaves, texts }; let parsed; try { parsed = /^[[{]/.test(value) ? JSON.parse(value) : void 0; } catch { parsed = void 0; } if (parsed === void 0) return { shape: value, leaves, texts }; const walk = (item) => { if (typeof item === "number") return leaf(item, JSON.stringify(item), false); if (typeof item === "string" && numericText.test(item)) return leaf(Number(item), item, true); if (Array.isArray(item)) return item.map(walk); if (item && typeof item === "object") return Object.fromEntries(Object.entries(item).map(([key, entry]) => [key, walk(entry)])); return item; }; return { shape: JSON.stringify(walk(parsed)), leaves, texts }; } function keyframeNative(animator, natives) { const { owner, values } = animator; const fieldCount = values[0].length; const tokens = []; const bind = (samples, where) => { if (samples.every((sample) => sample === samples[0])) return void 0; const coefficients = Array.from({ length: fieldCount }, (_, field) => samples[field + 1] - samples[0]); const check = values[fieldCount + 1]; let predicted = samples[0]; for (let field = 0; field < fieldCount; field++) predicted += coefficients[field] * (check[field] - values[0][field]); const actual = samples[fieldCount + 1]; if (!(Math.abs(predicted - actual) <= 1e-6 * Math.max(1, Math.abs(actual)))) throw new Error(`${owner} content must map its value linearly to swiftStyle numbers; ${where} does not`); let base = samples[0]; for (let field = 0; field < fieldCount; field++) base -= coefficients[field] * values[0][field]; tokens.push({ base, coefficients }); return tokens.length - 1; }; const keys = [...new Set(natives.flatMap((native) => Object.keys(native)))].filter((key) => key !== "sdkModifiers"); const fields = {}; for (const key of keys) { const samples = natives.map((native) => native[key]); if (samples.every((sample) => same(sample, samples[0]))) continue; if (colorFields.has(key) || !samples.every((sample) => typeof sample === "number")) throw new Error(`${owner} content can follow its value only through swiftStyle numbers; ${key} changed`); const token = bind(samples, key); if (token !== void 0) fields[key] = token; } const pairs = natives.map(sdkPairs); const names = pairs[0].map(([name]) => name); if (pairs.some((list) => !same(list.map(([name]) => name), names))) throw new Error(`${owner} content must apply the same swiftStyle modifiers at every value`); const template = names.map((name, index) => { const parts = pairs.map((list) => leavesOf(list[index][1])); if (parts.some((part) => part.shape !== parts[0].shape)) throw new Error(`${owner} content can follow its value only through swiftStyle numbers; ${name} changed`); let value = parts[0].shape; parts[0].leaves.forEach((_, leaf) => { const token = bind(parts.map((part) => part.leaves[leaf]), name); const text = token === void 0 ? parts[0].texts[leaf] : `@@${token}@@`; value = value.replace(`"__oneKN${leaf}__"`, text).replace(`__oneKS${leaf}__`, text); }); return [name, value]; }); return withPayload(natives[0], { id: animator.id, kind: "keyframe", fields, sdkModifiers: template.length ? JSON.stringify(template) : void 0, tokens }); } function animatorStyleNative(animator, convert) { const natives = animator.samples.map((sample) => convert(sample) ?? {}); const native = animator.kind === "phase" ? phaseNative(animator, natives) : keyframeNative(animator, natives); return native; } export { animatedSwiftStyle, animatorStyleNative, animatorStyleOf }; //# sourceMappingURL=animatorStyle.mjs.map