UNPKG

react-code-canvas

Version:

A browser-based canvas for rendering React components at runtime

70 lines (69 loc) 3.45 kB
type Scope = Record<string, any>; /** * Everything cheap enough to ship in the first chunk. React is a peer * dependency (already on the page), the edit helpers are our own code, and * react-helmet-async is ~6 KB -- not worth a round trip. */ export declare const baseScope: Scope; /** * `PascalCase` -> `kebab-case`. Must stay in step with the same function in * scripts/generate-scope-maps.mjs, which is what decided the ICON_LOADERS keys. */ export declare function toKebab(name: string): string; /** * Every identifier-shaped token in the source. * * Deliberately a regex and not a parse: this runs before evaluation on every * code change, and the only consequence of over-matching is loading a module * that turns out to be unused. A word inside a string or comment can trigger a * needless fetch; nothing breaks. * * Under-matching would break things, and cannot happen -- every name the code * can reference appears literally in the source. Names assembled at runtime * (`scope['Ac' + 'tivity']`) were never resolvable here anyway, because the * scope is passed as `new Function` parameters. */ export declare function collectIdentifiers(code: string): Set<string>; /** The dynamic import for an icon name, or undefined if it is not a lucide icon. */ export declare function iconLoaderFor(name: string): (() => Promise<any>) | undefined; /** * Copy a module namespace into the scope, skipping `default`. * * A namespace object always carries `default`, which is a reserved word and so * cannot become a `new Function` parameter. The generated name lists exclude it * for the same reason -- otherwise the `default` in every `export default` * would look like a reference to recharts. */ export declare function assignNamespace(scope: Scope, mod: Record<string, unknown>): void; /** True if the name is a lucide icon, without loading anything. */ export declare const isIconName: (name: string) => boolean; /** True if the name comes from recharts. */ export declare const isRechartsName: (name: string) => boolean; /** True if the name comes from motion/react. */ export declare const isMotionName: (name: string) => boolean; /** True if the name is a Font Awesome icon from react-icons/fa. */ export declare const isFaName: (name: string) => boolean; /** * The names `resolveScope` would put in scope for this code, without loading * anything. Mirrors resolveScope exactly, because it is what decides the * `new Function` parameter list -- and therefore which top-level declarations * in the code count as duplicates. */ export declare function scopeNamesFor(code: string, extra?: string[]): string[]; /** * Build the scope the given code actually needs. * * The old behaviour was to spread every export of lucide-react (5670 names), * recharts and motion into one object at module load. That forced ~300 KB * (brotli) into the first chunk regardless of what the code used, and handed * ~5800 parameters to `new Function` on every single evaluation. * * Here each group is fetched only when the code references it: icons one file * at a time (~0.7 KB each), recharts and motion whole (they are not usefully * splittable). Repeat calls are free -- the browser caches resolved modules, so * an already-loaded icon resolves in a microtask. * * `extra` is merged last so a caller-supplied scope always wins. */ export declare function resolveScope(code: string, extra?: Scope): Promise<Scope>; export {};