/** A single Apple splash target (CSS px + device pixel ratio). */ export declare interface AppleSplashSpec { /** CSS width (device-width in the media query). */ width: number; /** CSS height (device-height in the media query). */ height: number; /** Device pixel ratio. */ ratio: number; } /** * Build a Tempest-flavored Vite config for a React app: the `@vitejs/plugin-react` * plugin, the `@` → `src` import alias, and sane dev-server defaults — so a * consuming app's `vite.config.ts` is a single call instead of repeated * boilerplate. Everything is overridable. * * Import it from the dedicated Node entry point: * * @example * // vite.config.ts * import { createViteConfig } from "tempest-react-sdk/vite"; * * export default createViteConfig({ * proxy: { "/api": "http://127.0.0.1:8000" }, * }); */ export declare function createViteConfig(options?: CreateViteConfigOptions): TempestViteConfig; export declare interface CreateViteConfigOptions { /** * Source directory aliased to `@`, relative to the project root. * Default: `"src"` (so `@/components/Button` → `/src/components/Button`). */ srcDir?: string; /** Dev server port. Default: `5173`. */ port?: number; /** Dev server host. Default: `"127.0.0.1"`. */ host?: string | boolean; /** Open the browser on `dev` start. Default: `false`. */ open?: boolean; /** * Dev proxy table. String values are expanded to * `{ target, changeOrigin: true }`; objects are passed through untouched. * * @example { "/api": "http://127.0.0.1:8000" } */ proxy?: Record; /** Extra path aliases merged on top of the default `@` → src alias. */ alias?: Record; /** Vite plugins appended after `@vitejs/plugin-react`. */ plugins?: unknown[]; /** * The `tempestIcons()` plugin, which generates `virtual:tempest-icons` from the * icon slugs your source mentions. On by default — it only ever removes * requests. Pass `false` to leave it out, or an options object to configure the * scan. */ icons?: boolean | TempestIconsOptions; /** * Arbitrary Vite config (a `UserConfig` object) deep-merged last, for * escape-hatch overrides (build target, define, extra `server` keys, …). */ overrides?: Record; } /** * A Vite proxy entry: either a target URL string (expanded to * `{ target, changeOrigin: true }`) or a raw Vite `ProxyOptions` object. */ export declare type ProxyEntry = string | Record; /** * How much of the reset an app takes. * * The components are written against the reset — `.tempest_button` assumes * `button { background: none; border: 0; padding: 0 }`, every width assumes * `box-sizing: border-box` — so `"none"` is not "unstyled document, styled * components": it is components missing their box model. It exists for the app * that already ships an equivalent reset of its own. */ export declare type ResetMode = "scoped" | "global" | "none"; /** Shape of `dist/styles/manifest.json`. */ export declare interface StyleManifest { /** The foundation sheet — tokens and reset together, the pre-split default. */ core: string; /** Public export name → the stylesheets it needs, transitive closure included. */ components: Record; } /** * Generate a static icon registry from the slugs your source mentions. * * Removes the reason to reach for `lucide-react`'s `DynamicIcon`: the slugs an app * writes as literals become ordinary static imports, so the bundler keeps exactly * those icons and the browser makes **no** extra request for them. A slug that only * exists at runtime still works — `` falls back to fetching one shard per * initial letter. * * The scan reads the source tree directly at `buildStart` rather than harvesting * modules as they pass through `transform`: relying on transform order would let * the virtual module load before every consumer had been seen, and the registry * would come out short on a cold dev start — silently, since the missing slugs * would still render via the lazy path. * * @example * // vite.config.ts * import { createViteConfig, tempestIcons } from "tempest-react-sdk/vite"; * * export default createViteConfig({ plugins: [tempestIcons()] }); * * @example * // src/main.tsx * import { IconProvider } from "tempest-react-sdk/icons"; * import { staticIcons } from "tempest-react-sdk/icons/virtual"; * * * * */ export declare function tempestIcons(options?: TempestIconsOptions): TempestVitePlugin; export declare interface TempestIconsOptions { /** * Directory to scan, relative to the Vite root. Default: `"src"`. */ dir?: string; /** * Extra slugs to include even when the scan cannot see them — a name built by * concatenation, or one that only ever arrives from the API but is worth * paying for statically because it is on the first screen. */ include?: readonly string[]; /** Directory names to skip. Default: `node_modules`, `dist`, `build`, `coverage`. */ skipDirs?: readonly string[]; } /** * Dev-server plugin that makes the service worker available under `npm run dev`. * * The production worker is bundled at build time (`vite.sw.config.ts`), so in * dev there is no `/sw.js` to register. This plugin compiles `swSrc` on the fly * with esbuild — through one incremental context, not a cold build per request — * and serves it as a classic worker, plus an empty `precache-manifest.json` (there are no hashed build assets to precache in * dev — push and runtime caching still work). It closes the "SW in dev" gap * that otherwise only `vite-plugin-pwa`'s `devOptions` covered. * * @example * // vite.config.ts * import { createViteConfig, tempestPwaDevSw } from "tempest-react-sdk/vite"; * * export default createViteConfig({ plugins: [tempestPwaDevSw()] }); */ export declare function tempestPwaDevSw(options?: TempestPwaDevSwOptions): TempestVitePlugin; /** Options for {@link tempestPwaDevSw}. */ export declare interface TempestPwaDevSwOptions { /** Service-worker entry, relative to the project root. Default `src/sw.ts`. */ swSrc?: string; /** * URL the worker is served at (must match `registerServiceWorker`). * Default `/sw.js`. * * Write it relative to the site root; requests are matched against both the * bare path and the path prefixed with the resolved Vite `base`, so a * project served from a subpath is handled without extra configuration. */ swUrl?: string; /** * Dev URL of the precache manifest. Default `/precache-manifest.json`. * Matched the same way as {@link TempestPwaDevSwOptions.swUrl}. */ manifestUrl?: string; /** Serve the worker in dev. Default `true`; set `false` to opt out. */ enabled?: boolean; } /** * Build plugin that rasterizes a single source image into a full PWA icon set * (regular + maskable + apple-touch-icon), the dependency-free counterpart to * `@vite-pwa/assets-generator`. Rendering uses **`sharp`**, imported lazily and * treated as optional: if it isn't installed the plugin logs a warning and skips * generation (your build still succeeds; the icons just aren't produced). * * Point your `manifest.webmanifest` icon entries at the emitted files * (`/icons/icon-192.png`, `/icons/icon-512.png`, `/icons/maskable-512.png`) and * the apple touch icon at `/apple-touch-icon.png`. * * @example * // vite.config.ts * import { createViteConfig, tempestPwaIcons } from "tempest-react-sdk/vite"; * * export default createViteConfig({ * plugins: [tempestPwaIcons({ source: "public/icon.svg" })], * }); */ export declare function tempestPwaIcons(options?: TempestPwaIconsOptions): TempestVitePlugin; /** Options for {@link tempestPwaIcons}. */ export declare interface TempestPwaIconsOptions { /** Source image (SVG or large PNG), relative to the project root. Default `public/icon.svg`. */ source?: string; /** Square "any"-purpose icon sizes to emit. Default `[192, 512]`. */ sizes?: number[]; /** Square "maskable" icon sizes to emit (with safe-zone padding). Default `[512]`. */ maskableSizes?: number[]; /** Apple touch icon size, or `false` to skip. Default `180`. */ appleTouchIcon?: number | false; /** Output directory for the icon set, under the build root. Default `icons`. */ outDir?: string; /** Opaque background for maskable + apple icons (no transparency allowed). Default `#ffffff`. */ background?: string; /** Maskable safe-zone padding as a fraction of the icon. Default `0.1` (10% each side). */ maskablePadding?: number; /** * Generate Apple splash screens (launch images) and inject the matching * `` tags. `true` uses a built-in set * of common iPhone/iPad portrait sizes; pass an array to override. Default `false`. */ appleSplash?: boolean | AppleSplashSpec[]; /** Background color for splash screens. Default: `background`. */ splashBackground?: string; /** Icon size on the splash as a fraction of the shorter side. Default `0.3`. */ splashIconScale?: number; } /** * Vite build plugin that emits a `precache-manifest.json` listing every built * asset (plus any `additionalUrls`) as root-absolute URLs, with a content-based * `version`. It is the dependency-free counterpart to Workbox's `__WB_MANIFEST`: * `installPrecache` (from `tempest-react-sdk/sw`) reads this file at the service * worker's `install` event to cache the app shell for offline use. * * @example * // vite.config.ts * import { createViteConfig, tempestPwaManifest } from "tempest-react-sdk/vite"; * * export default createViteConfig({ * plugins: [tempestPwaManifest({ additionalUrls: ["/manifest.webmanifest", "/icon.svg"] })], * }); */ export declare function tempestPwaManifest(options?: TempestPwaManifestOptions): TempestVitePlugin; /** Options for {@link tempestPwaManifest}. */ export declare interface TempestPwaManifestOptions { /** Output file name (under the build root). Default `precache-manifest.json`. */ fileName?: string; /** * Extra URLs to precache that Vite doesn't emit into the bundle — typically * `public/` assets like the web manifest and icons. Default `[]`. * * Write these relative to the site root (`/icon.svg`); the resolved Vite * `base` is prefixed for you. An entry that already carries the base is * left alone, so spelling it out by hand is still correct. */ additionalUrls?: string[]; /** Emitted files matching this are skipped. Default `/\.map$/` (source maps). */ exclude?: RegExp; /** Include emitted `.html` documents (the app shell). Default `true`. */ includeHtml?: boolean; /** * App-shell document always added to the manifest, even if Vite emits it * after this plugin runs. Must match `installPrecache`'s `navigateFallback` * so offline navigations resolve. Pass `false` to disable. Default `/index.html`. * * Like {@link TempestPwaManifestOptions.additionalUrls}, this is prefixed * with the resolved Vite `base`. */ appShell?: string | false; } /** * Import only the SDK stylesheets your app can actually reach. * * `styles.css` carries every component the SDK ships — measured at 236.71 kB raw * against the 38.94 kB an app mounting twelve of them can reach. The per-component * sheets under `styles/` have always closed that gap, but by hand: the app lists * them and keeps the list honest as it grows. This plugin makes the list the build's * problem, resolving it from the imports the source already writes. * * The closure matters more than the scan. A component pays for the CSS of every SDK * component it renders internally, so `` alone needs six sheets and * `` seven — a hand-kept list of one sheet per component the app names is * wrong in a way that only shows up as an unstyled child. * * The reset is the other half, and the half that breaks apps. `styles.css` claims * `html`, `body` and `#root`; an app with its own layout that imports it loses its * document surface, and an app that drops the import loses the box model its * components are written against — components render unstyled, which is what the * "just remove the import" fix actually costs. The default `reset: "scoped"` is the * third option: the same normalisation, confined to * `:where([class*="tempest_"])`, so it reaches inside a Tempest component and * nowhere else. * * `tempest-react-sdk/styles/auto.css` is a real file, so it resolves without the * plugin too — to the complete sheet. Dropping the plugin costs bytes, never * correctness. * * @param options - Scan configuration. * @returns The Vite plugin. * * @example * // vite.config.ts * import { createViteConfig, tempestStyles } from "tempest-react-sdk/vite"; * * export default createViteConfig({ plugins: [tempestStyles()] }); * * @example * // src/main.tsx — the one import, instead of a maintained list * import "tempest-react-sdk/styles/auto.css"; */ export declare function tempestStyles(options?: TempestStylesOptions): TempestVitePlugin; export declare interface TempestStylesOptions { /** Directory to scan, relative to the Vite root. Default: `"src"`. */ dir?: string; /** * Which reset to emit alongside the tokens. Default: `"scoped"`. * * `"scoped"` confines the reset to `:where([class*="tempest_"])`, so components * keep the normalisation they are written against and the app keeps `html`, * `body` and `#root`. `"global"` is the pre-split behaviour, correct when the * SDK owns the whole page. `"none"` emits tokens only. */ reset?: ResetMode; /** * Extra export names to style even when the scan cannot see them — a component * reached only through a namespace import, or rendered by a sibling package. */ include?: readonly string[]; /** Directory names to skip. Default: `node_modules`, `dist`, `build`, `coverage`. */ skipDirs?: readonly string[]; /** * How much of the token sheet to emit. Default: `"used"`. * * The default falls back to the whole sheet on its own whenever a token name is * assembled at runtime (`` `var(--tempest-${tone})` ``), so `"all"` is for the * case the scan cannot see at all — a token read from outside `dir`. */ tokens?: TokenMode; } /** * The resulting Vite config object. Typed loosely so the SDK's published * declarations stay free of `vite`'s internal types; assign it straight to a * `vite.config.ts` default export. */ export declare type TempestViteConfig = Record; /** * A Vite plugin object. Typed loosely so the SDK's published declarations stay * free of `vite`'s internal types (which the `.d.ts` rollup can't analyze); * assign the result straight into a `plugins: [...]` array. */ export declare type TempestVitePlugin = { name: string; } & Record; /** * How much of the token sheet an app takes. * * `"used"` emits only the tokens the selected stylesheets — and the app's own CSS — * can reach, following token-to-token references. `"all"` emits `tokens.css` whole, * which is what to reach for when the app names tokens somewhere the scan cannot * see: a token read from a CSS-in-JS library, a sibling package's stylesheet, a * `