commit 8a295c4acf727a53c924376c692da26544196d84 Author: Kaloyan Danchev Date: Wed Mar 18 19:34:08 2026 +0200 Initial commit: @ampeco/design-tokens v1.0.0 Design token system for AMPECO Embedded Web Apps with light/dark themes, CSS custom properties, and runtime theme application via applyTheme(). Co-Authored-By: Claude Opus 4.6 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..f4e2c6d --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +node_modules/ +dist/ +*.tsbuildinfo diff --git a/README.md b/README.md new file mode 100644 index 0000000..0006d3a --- /dev/null +++ b/README.md @@ -0,0 +1,133 @@ +# @ampeco/design-tokens + +Design tokens for the AMPECO EWA (Embedded Web App). Provides theme definitions (light/dark), a token-to-CSS-variable mapping, and a runtime `applyTheme()` function that bridges the AMPECO mobile app design system to CSS custom properties. + +## Install + +```bash +npm install @ampeco/design-tokens +``` + +## Exports + +| Export path | What it provides | +|---|---| +| `@ampeco/design-tokens` | JS/TS: types, theme objects, `applyTheme()`, `mapAmpecoTokens()`, `TOKEN_CSS_MAP` | +| `@ampeco/design-tokens/css` | `css/variables.css` -- light-theme defaults plus spacing, radius, typography tokens | + +## Usage + +### JavaScript / TypeScript + +```ts +import { applyTheme, lightTheme, darkTheme, TOKEN_CSS_MAP } from '@ampeco/design-tokens'; + +// Apply light theme (sets CSS vars on ) +applyTheme('LIGHT'); + +// Apply dark theme with AMPECO mobile token overrides +applyTheme('DARK', { + buttonsButtonPrimaryBackground: '#FF0000', + surfaceSurfaceBackground: '#111111', +}); + +// Read a theme object directly +console.log(lightTheme.btnPrimaryBg); // '#00A573' +console.log(darkTheme.surfaceBg); // '#000000' + +// Look up the CSS variable name for a token +console.log(TOKEN_CSS_MAP.btnPrimaryBg); // '--btn-primary-bg' +``` + +### CSS + +Import the stylesheet to get light-theme defaults before JS initialises: + +```css +@import '@ampeco/design-tokens/css'; +``` + +Then use the custom properties in your styles: + +```css +.button-primary { + background: var(--btn-primary-bg); + color: var(--btn-primary-text); + font-size: var(--font-button-size); + font-weight: var(--font-button-weight); + line-height: var(--font-button-line-height); + border-radius: var(--radius-m); + padding: var(--spacing-s) var(--spacing-l); +} +``` + +### Mapping AMPECO mobile tokens + +The mobile app sends tokens using its own naming convention (e.g. `buttonsButtonPrimaryBackground`). Use `mapAmpecoTokens()` to convert them to EWA token keys: + +```ts +import { mapAmpecoTokens } from '@ampeco/design-tokens'; + +const mobileTokens = { + buttonsButtonPrimaryBackground: '#FF0000', + textsTextBase: '#333333', +}; + +const ewaTokens = mapAmpecoTokens(mobileTokens); +// { btnPrimaryBg: '#FF0000', textBase: '#333333' } +``` + +## API Reference + +### Types + +- **`AppTheme`** -- `'LIGHT' | 'DARK'` +- **`AmpecoDesignTokens`** -- Partial set of tokens as sent by the AMPECO mobile app via `postMessage` +- **`ThemeTokens`** -- Complete set of EWA theme tokens (buttons, surfaces, text, feedback, input, separator, booking status) + +### Constants + +- **`TOKEN_CSS_MAP`** -- `Record` mapping each token key to its CSS custom property name (e.g. `btnPrimaryBg` -> `'--btn-primary-bg'`) +- **`lightTheme`** -- `ThemeTokens` with light mode defaults +- **`darkTheme`** -- `ThemeTokens` with dark mode defaults +- **`AMPECO_TO_EWA_MAP`** -- `Record` mapping AMPECO mobile token names to EWA token keys + +### Functions + +- **`applyTheme(theme: AppTheme, designTokens?: AmpecoDesignTokens): void`** -- Selects the base theme, merges AMPECO overrides, sets `data-theme` attribute on ``, and writes all tokens as CSS custom properties on ``. +- **`mapAmpecoTokens(tokens: AmpecoDesignTokens): Partial`** -- Converts AMPECO mobile token names to EWA token keys. Only truthy values are included. + +## CSS Variable Categories + +The `css/variables.css` file defines variables beyond the themeable color tokens: + +| Category | Example variables | Notes | +|---|---|---| +| Spacing | `--spacing-xxxs` (2px) through `--spacing-xxxl` (64px) | 9-step scale | +| Border radius | `--radius-s` (8px) through `--radius-xl` (32px) | 4-step scale | +| Typography | `--font-h1-size`, `--font-body-medium-weight`, etc. | 12 type styles | +| Component sizes | `--size-xs` (14px) through `--size-l` (44px) | 4-step scale | + +## Build + +```bash +npm run build # one-shot build via tsup (ESM + CJS + .d.ts) +npm run dev # watch mode +``` + +Output lands in `dist/` (ESM as `index.js`, CJS as `index.cjs`, types as `index.d.ts` and `index.d.cts`). + +## Source Files + +``` +src/ + index.ts Public API barrel export + types.ts AppTheme, AmpecoDesignTokens + tokens.ts ThemeTokens interface, TOKEN_CSS_MAP + light.ts lightTheme defaults + dark.ts darkTheme defaults + tokenMapping.ts AMPECO_TO_EWA_MAP, mapAmpecoTokens() + apply.ts applyTheme() +css/ + variables.css Static CSS custom properties (light defaults + layout tokens) +``` diff --git a/css/variables.css b/css/variables.css new file mode 100644 index 0000000..e87654a --- /dev/null +++ b/css/variables.css @@ -0,0 +1,141 @@ +/* + * @ampeco/design-tokens - CSS Custom Properties + * + * These variables are set programmatically by applyTheme() at runtime. + * The :root defaults below match the light theme so the page has + * sensible values even before JavaScript initialises. + */ + +:root { + /* ─── Buttons ─────────────────────────────────────────────── */ + --btn-primary-bg: #00A573; + --btn-primary-text: #FFFFFF; + --btn-primary-pressed: #D7E4DC; + --btn-secondary-bg: #FFFFFF; + --btn-secondary-border: #00A573; + --btn-secondary-text: #000000; + + /* ─── Surfaces ────────────────────────────────────────────── */ + --surface-bg: #FFFFFF; + --surface-elevation-1: #EEF2EF; + --surface-elevation-2: #D7E4DC; + + /* ─── Text ────────────────────────────────────────────────── */ + --text-base: #000000; + --text-support: #808080; + --text-placeholder: #808080; + + /* ─── Feedback ────────────────────────────────────────────── */ + --feedback-success: #24A629; + --feedback-success-subtle: #BDE4BF; + --feedback-error: #FF6868; + --feedback-error-subtle: #FFD2D2; + --feedback-warning: #FFB23E; + --feedback-warning-subtle: #FFE8C5; + --feedback-info: #2F83FF; + --feedback-info-subtle: #C1DAFF; + + /* ─── Input ───────────────────────────────────────────────── */ + --input-fill: #EEF2EF; + --input-border: #D7E4DC; + --input-border-active: #C8DAD7; + --input-text: #000000; + --input-placeholder: #808080; + + /* ─── Separator ───────────────────────────────────────────── */ + --separator: #C8DAD7; + + /* ─── Booking Status ──────────────────────────────────────── */ + --status-accepted: #2F83FF; + --status-reserved: #24A629; + --status-completed: #808080; + --status-cancelled: #FFB23E; + --status-no-show: #FF6868; + --status-failed: #B71C1C; + + /* ─── Spacing Scale ───────────────────────────────────────── */ + --spacing-xxxs: 2px; + --spacing-xxs: 4px; + --spacing-xs: 6px; + --spacing-s: 8px; + --spacing-m: 12px; + --spacing-l: 16px; + --spacing-xl: 24px; + --spacing-xxl: 32px; + --spacing-xxxl: 64px; + + /* ─── Border Radius ───────────────────────────────────────── */ + --radius-s: 8px; + --radius-m: 12px; + --radius-l: 16px; + --radius-xl: 32px; + + /* ─── Typography ──────────────────────────────────────────── */ + --font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; + + /* H1 - Semibold 22/26 */ + --font-h1-size: 22px; + --font-h1-line-height: 26px; + --font-h1-weight: 600; + + /* H2 - Semibold 18/22 */ + --font-h2-size: 18px; + --font-h2-line-height: 22px; + --font-h2-weight: 600; + + /* H3 - Medium 16/20 */ + --font-h3-size: 16px; + --font-h3-line-height: 20px; + --font-h3-weight: 500; + + /* H4 - Medium 14/17 */ + --font-h4-size: 14px; + --font-h4-line-height: 17px; + --font-h4-weight: 500; + + /* Body Large - Regular 16/20 */ + --font-body-large-size: 16px; + --font-body-large-line-height: 20px; + --font-body-large-weight: 400; + + /* Body Medium - Regular 14/17 */ + --font-body-medium-size: 14px; + --font-body-medium-line-height: 17px; + --font-body-medium-weight: 400; + + /* Body Large Heavy - Semibold 16/20 */ + --font-body-large-heavy-size: 16px; + --font-body-large-heavy-line-height: 20px; + --font-body-large-heavy-weight: 600; + + /* Body Medium Heavy - Semibold 14/17 */ + --font-body-medium-heavy-size: 14px; + --font-body-medium-heavy-line-height: 17px; + --font-body-medium-heavy-weight: 600; + + /* Buttons - Semibold 14/20 */ + --font-button-size: 14px; + --font-button-line-height: 20px; + --font-button-weight: 600; + + /* Buttons Small - Bold 12/17 */ + --font-button-small-size: 12px; + --font-button-small-line-height: 17px; + --font-button-small-weight: 700; + + /* Label - Regular 12/15 */ + --font-label-size: 12px; + --font-label-line-height: 15px; + --font-label-weight: 400; + + /* Caption - Medium 12/15 */ + --font-caption-size: 12px; + --font-caption-line-height: 15px; + --font-caption-weight: 500; + + /* ─── Component Sizes ─────────────────────────────────────── */ + --size-xs: 14px; + --size-s: 20px; + --size-m: 32px; + --size-l: 44px; +} diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md new file mode 100644 index 0000000..b0a8ef4 --- /dev/null +++ b/docs/ARCHITECTURE.md @@ -0,0 +1,228 @@ +# Architecture + +## Overview + +`@ampeco/design-tokens` is the single source of truth for visual theming in the EWA (Embedded Web App). It bridges the AMPECO mobile app's design system to the web via CSS custom properties. + +The package has two consumers: + +1. **CSS** -- imports `css/variables.css` for static defaults (colors, spacing, typography, radii, component sizes). +2. **JavaScript** -- calls `applyTheme()` at runtime to set color tokens based on the active theme and any overrides from the mobile app. + +## Token Structure + +Tokens are organized into two layers: + +### Themeable color tokens (JS-managed) + +Defined in `src/tokens.ts` as the `ThemeTokens` interface. These are the tokens that change between light and dark mode. Each token has a corresponding CSS custom property name in `TOKEN_CSS_MAP`. + +``` +ThemeTokens key CSS variable Category +------------------------------------------------------------ +btnPrimaryBg --btn-primary-bg Buttons +btnPrimaryText --btn-primary-text Buttons +btnPrimaryPressed --btn-primary-pressed Buttons +btnSecondaryBg --btn-secondary-bg Buttons +btnSecondaryBorder --btn-secondary-border Buttons +btnSecondaryText --btn-secondary-text Buttons +surfaceBg --surface-bg Surfaces +surfaceElevation1 --surface-elevation-1 Surfaces +surfaceElevation2 --surface-elevation-2 Surfaces +textBase --text-base Text +textSupport --text-support Text +textPlaceholder --text-placeholder Text +feedbackSuccess --feedback-success Feedback +feedbackSuccessSubtle --feedback-success-subtle Feedback +feedbackError --feedback-error Feedback +feedbackErrorSubtle --feedback-error-subtle Feedback +feedbackWarning --feedback-warning Feedback +feedbackWarningSubtle --feedback-warning-subtle Feedback +feedbackInfo --feedback-info Feedback +feedbackInfoSubtle --feedback-info-subtle Feedback +inputFill --input-fill Input +inputBorder --input-border Input +inputBorderActive --input-border-active Input +inputText --input-text Input +inputPlaceholder --input-placeholder Input +separator --separator Separator +statusAccepted --status-accepted Booking status +statusReserved --status-reserved Booking status +statusCompleted --status-completed Booking status +statusCancelled --status-cancelled Booking status +statusNoShow --status-no-show Booking status +statusFailed --status-failed Booking status +``` + +### Static layout tokens (CSS-only) + +Defined only in `css/variables.css`. These do not change between themes and are not managed by JS: + +- **Spacing** -- 9-step scale from `--spacing-xxxs` (2px) to `--spacing-xxxl` (64px) +- **Border radius** -- 4-step scale: `--radius-s` (8px), `--radius-m` (12px), `--radius-l` (16px), `--radius-xl` (32px) +- **Typography** -- 12 type styles, each with `-size`, `-line-height`, and `-weight` variables. Font family: Inter with system fallbacks. +- **Component sizes** -- 4-step scale: `--size-xs` (14px) to `--size-l` (44px) + +## Theme System + +### Light and dark defaults + +Two complete `ThemeTokens` objects are exported: + +- `lightTheme` (`src/light.ts`) -- Green primary (#00A573), white surfaces, black text. +- `darkTheme` (`src/dark.ts`) -- Blue primary (#0066FF), black surfaces, white text. + +Both share identical booking status colors (these are semantic and theme-independent). + +Values are sourced from the AMPECO mobile app design system at: +`mobile-2/src/design_system/migration_file/colors/newColorsFormatExample.ts` + +### CSS fallback + +`css/variables.css` contains `:root` declarations matching the light theme. This ensures the page renders correctly even before JavaScript runs or if `applyTheme()` is never called. + +## AMPECO Mobile Token Mapping + +The AMPECO mobile app sends design tokens via `postMessage` using its own naming convention. The mapping layer (`src/tokenMapping.ts`) translates these to EWA token keys. + +### Naming convention translation + +``` +AMPECO mobile name EWA token key +----------------------------------------------------------- +buttonsButtonPrimaryBackground --> btnPrimaryBg +buttonsButtonPrimaryText --> btnPrimaryText +buttonsButtonSecondaryBackground --> btnSecondaryBg +buttonsButtonSecondaryBorder --> btnSecondaryBorder +buttonsButtonSecondaryText --> btnSecondaryText +surfaceSurfaceBackground --> surfaceBg +surfaceSurfaceElevation1 --> surfaceElevation1 +surfaceSurfaceElevation2 --> surfaceElevation2 +textsTextBase --> textBase +textsTextSupport --> textSupport +textsTextPlaceholder --> textPlaceholder +feedbackColorFeedbackSuccess --> feedbackSuccess +feedbackColorFeedbackError --> feedbackError +feedbackColorFeedbackWarning --> feedbackWarning +feedbackColorFeedbackInfo --> feedbackInfo +inputFormsInputBorder --> inputBorder +inputFormsInputFill --> inputFill +inputFormsInputTextLabels --> inputText +``` + +The AMPECO mobile app sends a subset of tokens as `AmpecoDesignTokens` (all fields optional). The EWA has additional tokens (e.g. `btnPrimaryPressed`, `feedbackSuccessSubtle`, `inputBorderActive`, `separator`, all `status*` tokens) that are not mapped from mobile tokens and always come from the base theme. + +### mapAmpecoTokens() + +```ts +function mapAmpecoTokens(tokens: AmpecoDesignTokens): Partial +``` + +Iterates `AMPECO_TO_EWA_MAP`, looks up each AMPECO key in the input, and includes only truthy values in the result. Returns a partial token set suitable for spreading over a base theme. + +## How applyTheme() Works at Runtime + +`applyTheme()` in `src/apply.ts` is the main entry point for theme application. Here is the exact sequence: + +### Step 1: Select base theme + +```ts +const base = theme === 'DARK' ? darkTheme : lightTheme; +``` + +The `theme` parameter is `'LIGHT'` or `'DARK'` (matches `AppTheme` type, which corresponds to what the mobile app sends). + +### Step 2: Map and merge AMPECO overrides + +```ts +const overrides = designTokens ? mapAmpecoTokens(designTokens) : {}; +const merged: ThemeTokens = { ...base, ...overrides }; +``` + +Mobile app tokens override the base theme. Tokens not provided by the mobile app retain their base theme defaults. + +### Step 3: Set data-theme attribute + +```ts +document.documentElement.setAttribute('data-theme', theme.toLowerCase()); +``` + +Sets `data-theme="light"` or `data-theme="dark"` on ``. This enables CSS selectors like `[data-theme="dark"] .card { ... }` for theme-conditional styling that cannot be expressed with CSS custom properties alone. + +### Step 4: Write CSS custom properties + +```ts +for (const [key, value] of Object.entries(merged)) { + const cssVar = TOKEN_CSS_MAP[key as keyof ThemeTokens]; + if (cssVar && value) { + document.documentElement.style.setProperty(cssVar, value); + } +} +``` + +Every token in the merged set is written as an inline style on ``, which overrides the `:root` defaults from `css/variables.css`. + +### Sequence diagram + +``` +Mobile App EWA DOM + | | | + |-- postMessage ------>| | + | { theme, tokens } | | + | |-- applyTheme(theme, t) ->| + | | 1. select base | + | | 2. map + merge | + | | 3. set data-theme | + | | 4. set CSS vars | + | | | + | | [page re-renders + | | with new colors] +``` + +## CSS Variable Naming Conventions + +All CSS custom properties follow a flat, kebab-case naming scheme with category prefixes: + +| Prefix | Category | Examples | +|---|---|---| +| `--btn-` | Button colors | `--btn-primary-bg`, `--btn-secondary-text` | +| `--surface-` | Surface/background | `--surface-bg`, `--surface-elevation-1` | +| `--text-` | Text colors | `--text-base`, `--text-support` | +| `--feedback-` | Feedback/status colors | `--feedback-error`, `--feedback-info-subtle` | +| `--input-` | Form input | `--input-fill`, `--input-border-active` | +| `--separator` | Divider lines | `--separator` | +| `--status-` | Booking status | `--status-accepted`, `--status-no-show` | +| `--spacing-` | Spacing scale | `--spacing-xs`, `--spacing-xxl` | +| `--radius-` | Border radius | `--radius-s`, `--radius-xl` | +| `--font-` | Typography | `--font-h1-size`, `--font-body-medium-weight` | +| `--size-` | Component sizes | `--size-xs`, `--size-l` | + +No BEM, no nesting, no component-scoped prefixes. Variables are global and intended for use across all components. + +## Build System + +The package uses [tsup](https://tsup.egoist.dev/) (configured in `tsup.config.ts`): + +- **Entry**: `src/index.ts` +- **Formats**: ESM (`dist/index.js`) + CJS (`dist/index.cjs`) +- **Types**: `dist/index.d.ts` and `dist/index.d.cts` +- **Source maps**: enabled + +The CSS file is not processed by tsup. It ships as-is from `css/variables.css` and is exposed via the `"./css"` export map entry in `package.json`. + +## File Dependency Graph + +``` +src/index.ts (barrel) + |-- src/types.ts AppTheme, AmpecoDesignTokens + |-- src/tokens.ts ThemeTokens, TOKEN_CSS_MAP + |-- src/light.ts lightTheme (imports ThemeTokens from tokens.ts) + |-- src/dark.ts darkTheme (imports ThemeTokens from tokens.ts) + |-- src/tokenMapping.ts AMPECO_TO_EWA_MAP, mapAmpecoTokens() + | (imports ThemeTokens from tokens.ts, + | AmpecoDesignTokens from types.ts) + |-- src/apply.ts applyTheme() + (imports everything above) + +css/variables.css standalone, no imports +``` diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..6a356e1 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,1475 @@ +{ + "name": "@ampeco/design-tokens", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "@ampeco/design-tokens", + "version": "1.0.0", + "devDependencies": { + "tsup": "^8.0.0", + "typescript": "^5.4.0" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.27.4", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.4.tgz", + "integrity": "sha512-cQPwL2mp2nSmHHJlCyoXgHGhbEPMrEEU5xhkcy3Hs/O7nGZqEpZ2sUtLaL9MORLtDfRvVl2/3PAuEkYZH0Ty8Q==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.27.4", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.4.tgz", + "integrity": "sha512-X9bUgvxiC8CHAGKYufLIHGXPJWnr0OCdR0anD2e21vdvgCI8lIfqFbnoeOz7lBjdrAGUhqLZLcQo6MLhTO2DKQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.27.4", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.4.tgz", + "integrity": "sha512-gdLscB7v75wRfu7QSm/zg6Rx29VLdy9eTr2t44sfTW7CxwAtQghZ4ZnqHk3/ogz7xao0QAgrkradbBzcqFPasw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.27.4", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.4.tgz", + "integrity": "sha512-PzPFnBNVF292sfpfhiyiXCGSn9HZg5BcAz+ivBuSsl6Rk4ga1oEXAamhOXRFyMcjwr2DVtm40G65N3GLeH1Lvw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.27.4", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.4.tgz", + "integrity": "sha512-b7xaGIwdJlht8ZFCvMkpDN6uiSmnxxK56N2GDTMYPr2/gzvfdQN8rTfBsvVKmIVY/X7EM+/hJKEIbbHs9oA4tQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.27.4", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.4.tgz", + "integrity": "sha512-sR+OiKLwd15nmCdqpXMnuJ9W2kpy0KigzqScqHI3Hqwr7IXxBp3Yva+yJwoqh7rE8V77tdoheRYataNKL4QrPw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.27.4", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.4.tgz", + "integrity": "sha512-jnfpKe+p79tCnm4GVav68A7tUFeKQwQyLgESwEAUzyxk/TJr4QdGog9sqWNcUbr/bZt/O/HXouspuQDd9JxFSw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.27.4", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.4.tgz", + "integrity": "sha512-2kb4ceA/CpfUrIcTUl1wrP/9ad9Atrp5J94Lq69w7UwOMolPIGrfLSvAKJp0RTvkPPyn6CIWrNy13kyLikZRZQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.27.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.4.tgz", + "integrity": "sha512-aBYgcIxX/wd5n2ys0yESGeYMGF+pv6g0DhZr3G1ZG4jMfruU9Tl1i2Z+Wnj9/KjGz1lTLCcorqE2viePZqj4Eg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.27.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.4.tgz", + "integrity": "sha512-7nQOttdzVGth1iz57kxg9uCz57dxQLHWxopL6mYuYthohPKEK0vU0C3O21CcBK6KDlkYVcnDXY099HcCDXd9dA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.27.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.4.tgz", + "integrity": "sha512-oPtixtAIzgvzYcKBQM/qZ3R+9TEUd1aNJQu0HhGyqtx6oS7qTpvjheIWBbes4+qu1bNlo2V4cbkISr8q6gRBFA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.27.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.4.tgz", + "integrity": "sha512-8mL/vh8qeCoRcFH2nM8wm5uJP+ZcVYGGayMavi8GmRJjuI3g1v6Z7Ni0JJKAJW+m0EtUuARb6Lmp4hMjzCBWzA==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.27.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.4.tgz", + "integrity": "sha512-1RdrWFFiiLIW7LQq9Q2NES+HiD4NyT8Itj9AUeCl0IVCA459WnPhREKgwrpaIfTOe+/2rdntisegiPWn/r/aAw==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.27.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.4.tgz", + "integrity": "sha512-tLCwNG47l3sd9lpfyx9LAGEGItCUeRCWeAx6x2Jmbav65nAwoPXfewtAdtbtit/pJFLUWOhpv0FpS6GQAmPrHA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.27.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.4.tgz", + "integrity": "sha512-BnASypppbUWyqjd1KIpU4AUBiIhVr6YlHx/cnPgqEkNoVOhHg+YiSVxM1RLfiy4t9cAulbRGTNCKOcqHrEQLIw==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.27.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.4.tgz", + "integrity": "sha512-+eUqgb/Z7vxVLezG8bVB9SfBie89gMueS+I0xYh2tJdw3vqA/0ImZJ2ROeWwVJN59ihBeZ7Tu92dF/5dy5FttA==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.27.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.4.tgz", + "integrity": "sha512-S5qOXrKV8BQEzJPVxAwnryi2+Iq5pB40gTEIT69BQONqR7JH1EPIcQ/Uiv9mCnn05jff9umq/5nqzxlqTOg9NA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.27.4", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.4.tgz", + "integrity": "sha512-xHT8X4sb0GS8qTqiwzHqpY00C95DPAq7nAwX35Ie/s+LO9830hrMd3oX0ZMKLvy7vsonee73x0lmcdOVXFzd6Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.27.4", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.4.tgz", + "integrity": "sha512-RugOvOdXfdyi5Tyv40kgQnI0byv66BFgAqjdgtAKqHoZTbTF2QqfQrFwa7cHEORJf6X2ht+l9ABLMP0dnKYsgg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.27.4", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.4.tgz", + "integrity": "sha512-2MyL3IAaTX+1/qP0O1SwskwcwCoOI4kV2IBX1xYnDDqthmq5ArrW94qSIKCAuRraMgPOmG0RDTA74mzYNQA9ow==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.27.4", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.4.tgz", + "integrity": "sha512-u8fg/jQ5aQDfsnIV6+KwLOf1CmJnfu1ShpwqdwC0uA7ZPwFws55Ngc12vBdeUdnuWoQYx/SOQLGDcdlfXhYmXQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.27.4", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.4.tgz", + "integrity": "sha512-JkTZrl6VbyO8lDQO3yv26nNr2RM2yZzNrNHEsj9bm6dOwwu9OYN28CjzZkH57bh4w0I2F7IodpQvUAEd1mbWXg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.27.4", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.4.tgz", + "integrity": "sha512-/gOzgaewZJfeJTlsWhvUEmUG4tWEY2Spp5M20INYRg2ZKl9QPO3QEEgPeRtLjEWSW8FilRNacPOg8R1uaYkA6g==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.27.4", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.4.tgz", + "integrity": "sha512-Z9SExBg2y32smoDQdf1HRwHRt6vAHLXcxD2uGgO/v2jK7Y718Ix4ndsbNMU/+1Qiem9OiOdaqitioZwxivhXYg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.27.4", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.4.tgz", + "integrity": "sha512-DAyGLS0Jz5G5iixEbMHi5KdiApqHBWMGzTtMiJ72ZOLhbu/bzxgAe8Ue8CTS3n3HbIUHQz/L51yMdGMeoxXNJw==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.27.4", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.4.tgz", + "integrity": "sha512-+knoa0BDoeXgkNvvV1vvbZX4+hizelrkwmGJBdT17t8FNPwG2lKemmuMZlmaNQ3ws3DKKCxpb4zRZEIp3UxFCg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.13", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "dev": true, + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.59.0.tgz", + "integrity": "sha512-upnNBkA6ZH2VKGcBj9Fyl9IGNPULcjXRlg0LLeaioQWueH30p6IXtJEbKAgvyv+mJaMxSm1l6xwDXYjpEMiLMg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.59.0.tgz", + "integrity": "sha512-hZ+Zxj3SySm4A/DylsDKZAeVg0mvi++0PYVceVyX7hemkw7OreKdCvW2oQ3T1FMZvCaQXqOTHb8qmBShoqk69Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.59.0.tgz", + "integrity": "sha512-W2Psnbh1J8ZJw0xKAd8zdNgF9HRLkdWwwdWqubSVk0pUuQkoHnv7rx4GiF9rT4t5DIZGAsConRE3AxCdJ4m8rg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.59.0.tgz", + "integrity": "sha512-ZW2KkwlS4lwTv7ZVsYDiARfFCnSGhzYPdiOU4IM2fDbL+QGlyAbjgSFuqNRbSthybLbIJ915UtZBtmuLrQAT/w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.59.0.tgz", + "integrity": "sha512-EsKaJ5ytAu9jI3lonzn3BgG8iRBjV4LxZexygcQbpiU0wU0ATxhNVEpXKfUa0pS05gTcSDMKpn3Sx+QB9RlTTA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.59.0.tgz", + "integrity": "sha512-d3DuZi2KzTMjImrxoHIAODUZYoUUMsuUiY4SRRcJy6NJoZ6iIqWnJu9IScV9jXysyGMVuW+KNzZvBLOcpdl3Vg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.59.0.tgz", + "integrity": "sha512-t4ONHboXi/3E0rT6OZl1pKbl2Vgxf9vJfWgmUoCEVQVxhW6Cw/c8I6hbbu7DAvgp82RKiH7TpLwxnJeKv2pbsw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.59.0.tgz", + "integrity": "sha512-CikFT7aYPA2ufMD086cVORBYGHffBo4K8MQ4uPS/ZnY54GKj36i196u8U+aDVT2LX4eSMbyHtyOh7D7Zvk2VvA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.59.0.tgz", + "integrity": "sha512-jYgUGk5aLd1nUb1CtQ8E+t5JhLc9x5WdBKew9ZgAXg7DBk0ZHErLHdXM24rfX+bKrFe+Xp5YuJo54I5HFjGDAA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.59.0.tgz", + "integrity": "sha512-peZRVEdnFWZ5Bh2KeumKG9ty7aCXzzEsHShOZEFiCQlDEepP1dpUl/SrUNXNg13UmZl+gzVDPsiCwnV1uI0RUA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-gnu": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.59.0.tgz", + "integrity": "sha512-gbUSW/97f7+r4gHy3Jlup8zDG190AuodsWnNiXErp9mT90iCy9NKKU0Xwx5k8VlRAIV2uU9CsMnEFg/xXaOfXg==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-musl": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.59.0.tgz", + "integrity": "sha512-yTRONe79E+o0FWFijasoTjtzG9EBedFXJMl888NBEDCDV9I2wGbFFfJQQe63OijbFCUZqxpHz1GzpbtSFikJ4Q==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-gnu": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.59.0.tgz", + "integrity": "sha512-sw1o3tfyk12k3OEpRddF68a1unZ5VCN7zoTNtSn2KndUE+ea3m3ROOKRCZxEpmT9nsGnogpFP9x6mnLTCaoLkA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-musl": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.59.0.tgz", + "integrity": "sha512-+2kLtQ4xT3AiIxkzFVFXfsmlZiG5FXYW7ZyIIvGA7Bdeuh9Z0aN4hVyXS/G1E9bTP/vqszNIN/pUKCk/BTHsKA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.59.0.tgz", + "integrity": "sha512-NDYMpsXYJJaj+I7UdwIuHHNxXZ/b/N2hR15NyH3m2qAtb/hHPA4g4SuuvrdxetTdndfj9b1WOmy73kcPRoERUg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-musl": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.59.0.tgz", + "integrity": "sha512-nLckB8WOqHIf1bhymk+oHxvM9D3tyPndZH8i8+35p/1YiVoVswPid2yLzgX7ZJP0KQvnkhM4H6QZ5m0LzbyIAg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.59.0.tgz", + "integrity": "sha512-oF87Ie3uAIvORFBpwnCvUzdeYUqi2wY6jRFWJAy1qus/udHFYIkplYRW+wo+GRUP4sKzYdmE1Y3+rY5Gc4ZO+w==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.59.0.tgz", + "integrity": "sha512-3AHmtQq/ppNuUspKAlvA8HtLybkDflkMuLK4DPo77DfthRb71V84/c4MlWJXixZz4uruIH4uaa07IqoAkG64fg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.59.0.tgz", + "integrity": "sha512-2UdiwS/9cTAx7qIUZB/fWtToJwvt0Vbo0zmnYt7ED35KPg13Q0ym1g442THLC7VyI6JfYTP4PiSOWyoMdV2/xg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-openbsd-x64": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.59.0.tgz", + "integrity": "sha512-M3bLRAVk6GOwFlPTIxVBSYKUaqfLrn8l0psKinkCFxl4lQvOSz8ZrKDz2gxcBwHFpci0B6rttydI4IpS4IS/jQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ] + }, + "node_modules/@rollup/rollup-openharmony-arm64": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.59.0.tgz", + "integrity": "sha512-tt9KBJqaqp5i5HUZzoafHZX8b5Q2Fe7UjYERADll83O4fGqJ49O1FsL6LpdzVFQcpwvnyd0i+K/VSwu/o/nWlA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.59.0.tgz", + "integrity": "sha512-V5B6mG7OrGTwnxaNUzZTDTjDS7F75PO1ae6MJYdiMu60sq0CqN5CVeVsbhPxalupvTX8gXVSU9gq+Rx1/hvu6A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.59.0.tgz", + "integrity": "sha512-UKFMHPuM9R0iBegwzKF4y0C4J9u8C6MEJgFuXTBerMk7EJ92GFVFYBfOZaSGLu6COf7FxpQNqhNS4c4icUPqxA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-gnu": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.59.0.tgz", + "integrity": "sha512-laBkYlSS1n2L8fSo1thDNGrCTQMmxjYY5G0WFWjFFYZkKPjsMBsgJfGf4TLxXrF6RyhI60L8TMOjBMvXiTcxeA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.59.0.tgz", + "integrity": "sha512-2HRCml6OztYXyJXAvdDXPKcawukWY2GpR5/nxKp4iBgiO3wcoEGkAaqctIbZcNB6KlUQBIqt8VYkNSj2397EfA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@types/estree": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", + "dev": true, + "license": "MIT" + }, + "node_modules/acorn": { + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz", + "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==", + "dev": true, + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/any-promise": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", + "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==", + "dev": true, + "license": "MIT" + }, + "node_modules/bundle-require": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/bundle-require/-/bundle-require-5.1.0.tgz", + "integrity": "sha512-3WrrOuZiyaaZPWiEt4G3+IffISVC9HYlWueJEBWED4ZH4aIAC2PnkdnuRrR94M+w6yGWn4AglWtJtBI8YqvgoA==", + "dev": true, + "license": "MIT", + "dependencies": { + "load-tsconfig": "^0.2.3" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "peerDependencies": { + "esbuild": ">=0.18" + } + }, + "node_modules/cac": { + "version": "6.7.14", + "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz", + "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/chokidar": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", + "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", + "dev": true, + "license": "MIT", + "dependencies": { + "readdirp": "^4.0.1" + }, + "engines": { + "node": ">= 14.16.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/commander": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", + "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/confbox": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/confbox/-/confbox-0.1.8.tgz", + "integrity": "sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w==", + "dev": true, + "license": "MIT" + }, + "node_modules/consola": { + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/consola/-/consola-3.4.2.tgz", + "integrity": "sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^14.18.0 || >=16.10.0" + } + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/esbuild": { + "version": "0.27.4", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.4.tgz", + "integrity": "sha512-Rq4vbHnYkK5fws5NF7MYTU68FPRE1ajX7heQ/8QXXWqNgqqJ/GkmmyxIzUnf2Sr/bakf8l54716CcMGHYhMrrQ==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "peer": true, + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.27.4", + "@esbuild/android-arm": "0.27.4", + "@esbuild/android-arm64": "0.27.4", + "@esbuild/android-x64": "0.27.4", + "@esbuild/darwin-arm64": "0.27.4", + "@esbuild/darwin-x64": "0.27.4", + "@esbuild/freebsd-arm64": "0.27.4", + "@esbuild/freebsd-x64": "0.27.4", + "@esbuild/linux-arm": "0.27.4", + "@esbuild/linux-arm64": "0.27.4", + "@esbuild/linux-ia32": "0.27.4", + "@esbuild/linux-loong64": "0.27.4", + "@esbuild/linux-mips64el": "0.27.4", + "@esbuild/linux-ppc64": "0.27.4", + "@esbuild/linux-riscv64": "0.27.4", + "@esbuild/linux-s390x": "0.27.4", + "@esbuild/linux-x64": "0.27.4", + "@esbuild/netbsd-arm64": "0.27.4", + "@esbuild/netbsd-x64": "0.27.4", + "@esbuild/openbsd-arm64": "0.27.4", + "@esbuild/openbsd-x64": "0.27.4", + "@esbuild/openharmony-arm64": "0.27.4", + "@esbuild/sunos-x64": "0.27.4", + "@esbuild/win32-arm64": "0.27.4", + "@esbuild/win32-ia32": "0.27.4", + "@esbuild/win32-x64": "0.27.4" + } + }, + "node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/fix-dts-default-cjs-exports": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/fix-dts-default-cjs-exports/-/fix-dts-default-cjs-exports-1.0.1.tgz", + "integrity": "sha512-pVIECanWFC61Hzl2+oOCtoJ3F17kglZC/6N94eRWycFgBH35hHx0Li604ZIzhseh97mf2p0cv7vVrOZGoqhlEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "magic-string": "^0.30.17", + "mlly": "^1.7.4", + "rollup": "^4.34.8" + } + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/joycon": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/joycon/-/joycon-3.1.1.tgz", + "integrity": "sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/lilconfig": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz", + "integrity": "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antonk52" + } + }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true, + "license": "MIT" + }, + "node_modules/load-tsconfig": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/load-tsconfig/-/load-tsconfig-0.2.5.tgz", + "integrity": "sha512-IXO6OCs9yg8tMKzfPZ1YmheJbZCiEsnBdcB03l0OcfK9prKnJb96siuHCr5Fl37/yo9DnKU+TLpxzTUspw9shg==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + } + }, + "node_modules/magic-string": { + "version": "0.30.21", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", + "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.5" + } + }, + "node_modules/mlly": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.8.1.tgz", + "integrity": "sha512-SnL6sNutTwRWWR/vcmCYHSADjiEesp5TGQQ0pXyLhW5IoeibRlF/CbSLailbB3CNqJUk9cVJ9dUDnbD7GrcHBQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "acorn": "^8.16.0", + "pathe": "^2.0.3", + "pkg-types": "^1.3.1", + "ufo": "^1.6.3" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/mz": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", + "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "any-promise": "^1.0.0", + "object-assign": "^4.0.1", + "thenify-all": "^1.0.0" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pathe": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", + "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", + "dev": true, + "license": "MIT" + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true, + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pirates": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.7.tgz", + "integrity": "sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/pkg-types": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-1.3.1.tgz", + "integrity": "sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "confbox": "^0.1.8", + "mlly": "^1.7.4", + "pathe": "^2.0.1" + } + }, + "node_modules/postcss-load-config": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-6.0.1.tgz", + "integrity": "sha512-oPtTM4oerL+UXmx+93ytZVN82RrlY/wPUV8IeDxFrzIjXOLF1pN+EmKPLbubvKHT2HC20xXsCAH2Z+CKV6Oz/g==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "lilconfig": "^3.1.1" + }, + "engines": { + "node": ">= 18" + }, + "peerDependencies": { + "jiti": ">=1.21.0", + "postcss": ">=8.0.9", + "tsx": "^4.8.1", + "yaml": "^2.4.2" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + }, + "postcss": { + "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true + } + } + }, + "node_modules/readdirp": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", + "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 14.18.0" + }, + "funding": { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/rollup": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.59.0.tgz", + "integrity": "sha512-2oMpl67a3zCH9H79LeMcbDhXW/UmWG/y2zuqnF2jQq5uq9TbM9TVyXvA4+t+ne2IIkBdrLpAaRQAvo7YI/Yyeg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "1.0.8" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.59.0", + "@rollup/rollup-android-arm64": "4.59.0", + "@rollup/rollup-darwin-arm64": "4.59.0", + "@rollup/rollup-darwin-x64": "4.59.0", + "@rollup/rollup-freebsd-arm64": "4.59.0", + "@rollup/rollup-freebsd-x64": "4.59.0", + "@rollup/rollup-linux-arm-gnueabihf": "4.59.0", + "@rollup/rollup-linux-arm-musleabihf": "4.59.0", + "@rollup/rollup-linux-arm64-gnu": "4.59.0", + "@rollup/rollup-linux-arm64-musl": "4.59.0", + "@rollup/rollup-linux-loong64-gnu": "4.59.0", + "@rollup/rollup-linux-loong64-musl": "4.59.0", + "@rollup/rollup-linux-ppc64-gnu": "4.59.0", + "@rollup/rollup-linux-ppc64-musl": "4.59.0", + "@rollup/rollup-linux-riscv64-gnu": "4.59.0", + "@rollup/rollup-linux-riscv64-musl": "4.59.0", + "@rollup/rollup-linux-s390x-gnu": "4.59.0", + "@rollup/rollup-linux-x64-gnu": "4.59.0", + "@rollup/rollup-linux-x64-musl": "4.59.0", + "@rollup/rollup-openbsd-x64": "4.59.0", + "@rollup/rollup-openharmony-arm64": "4.59.0", + "@rollup/rollup-win32-arm64-msvc": "4.59.0", + "@rollup/rollup-win32-ia32-msvc": "4.59.0", + "@rollup/rollup-win32-x64-gnu": "4.59.0", + "@rollup/rollup-win32-x64-msvc": "4.59.0", + "fsevents": "~2.3.2" + } + }, + "node_modules/source-map": { + "version": "0.7.6", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.6.tgz", + "integrity": "sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">= 12" + } + }, + "node_modules/sucrase": { + "version": "3.35.1", + "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.1.tgz", + "integrity": "sha512-DhuTmvZWux4H1UOnWMB3sk0sbaCVOoQZjv8u1rDoTV0HTdGem9hkAZtl4JZy8P2z4Bg0nT+YMeOFyVr4zcG5Tw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.2", + "commander": "^4.0.0", + "lines-and-columns": "^1.1.6", + "mz": "^2.7.0", + "pirates": "^4.0.1", + "tinyglobby": "^0.2.11", + "ts-interface-checker": "^0.1.9" + }, + "bin": { + "sucrase": "bin/sucrase", + "sucrase-node": "bin/sucrase-node" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/thenify": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", + "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", + "dev": true, + "license": "MIT", + "dependencies": { + "any-promise": "^1.0.0" + } + }, + "node_modules/thenify-all": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", + "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", + "dev": true, + "license": "MIT", + "dependencies": { + "thenify": ">= 3.1.0 < 4" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/tinyexec": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-0.3.2.tgz", + "integrity": "sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==", + "dev": true, + "license": "MIT" + }, + "node_modules/tinyglobby": { + "version": "0.2.15", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", + "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "fdir": "^6.5.0", + "picomatch": "^4.0.3" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/tree-kill": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", + "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", + "dev": true, + "license": "MIT", + "bin": { + "tree-kill": "cli.js" + } + }, + "node_modules/ts-interface-checker": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz", + "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/tsup": { + "version": "8.5.1", + "resolved": "https://registry.npmjs.org/tsup/-/tsup-8.5.1.tgz", + "integrity": "sha512-xtgkqwdhpKWr3tKPmCkvYmS9xnQK3m3XgxZHwSUjvfTjp7YfXe5tT3GgWi0F2N+ZSMsOeWeZFh7ZZFg5iPhing==", + "dev": true, + "license": "MIT", + "dependencies": { + "bundle-require": "^5.1.0", + "cac": "^6.7.14", + "chokidar": "^4.0.3", + "consola": "^3.4.0", + "debug": "^4.4.0", + "esbuild": "^0.27.0", + "fix-dts-default-cjs-exports": "^1.0.0", + "joycon": "^3.1.1", + "picocolors": "^1.1.1", + "postcss-load-config": "^6.0.1", + "resolve-from": "^5.0.0", + "rollup": "^4.34.8", + "source-map": "^0.7.6", + "sucrase": "^3.35.0", + "tinyexec": "^0.3.2", + "tinyglobby": "^0.2.11", + "tree-kill": "^1.2.2" + }, + "bin": { + "tsup": "dist/cli-default.js", + "tsup-node": "dist/cli-node.js" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@microsoft/api-extractor": "^7.36.0", + "@swc/core": "^1", + "postcss": "^8.4.12", + "typescript": ">=4.5.0" + }, + "peerDependenciesMeta": { + "@microsoft/api-extractor": { + "optional": true + }, + "@swc/core": { + "optional": true + }, + "postcss": { + "optional": true + }, + "typescript": { + "optional": true + } + } + }, + "node_modules/typescript": { + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "dev": true, + "license": "Apache-2.0", + "peer": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/ufo": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.6.3.tgz", + "integrity": "sha512-yDJTmhydvl5lJzBmy/hyOAA0d+aqCBuwl818haVdYCRrWV84o7YyeVm4QlVHStqNrrJSTb6jKuFAVqAFsr+K3Q==", + "dev": true, + "license": "MIT" + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..3586a82 --- /dev/null +++ b/package.json @@ -0,0 +1,29 @@ +{ + "name": "@ampeco/design-tokens", + "version": "1.0.0", + "type": "module", + "main": "dist/index.js", + "module": "dist/index.js", + "types": "dist/index.d.ts", + "exports": { + ".": { + "types": "./dist/index.d.ts", + "import": "./dist/index.js", + "require": "./dist/index.cjs" + }, + "./css": "./css/variables.css", + "./css/*": "./css/*" + }, + "files": [ + "dist", + "css" + ], + "scripts": { + "build": "tsup", + "dev": "tsup --watch" + }, + "devDependencies": { + "tsup": "^8.0.0", + "typescript": "^5.4.0" + } +} diff --git a/src/apply.ts b/src/apply.ts new file mode 100644 index 0000000..291a1d7 --- /dev/null +++ b/src/apply.ts @@ -0,0 +1,32 @@ +import type { ThemeTokens } from './tokens'; +import { TOKEN_CSS_MAP } from './tokens'; +import type { AppTheme, AmpecoDesignTokens } from './types'; +import { lightTheme } from './light'; +import { darkTheme } from './dark'; +import { mapAmpecoTokens } from './tokenMapping'; + +/** + * Applies the given theme to the document root element. + * + * 1. Selects the base theme (light or dark). + * 2. Merges in any AMPECO design token overrides received from the mobile app. + * 3. Sets the `data-theme` attribute on for CSS selectors. + * 4. Sets each token as a CSS custom property on . + * + * @param theme - The theme mode ('LIGHT' or 'DARK'). + * @param designTokens - Optional partial token overrides from the AMPECO mobile app. + */ +export function applyTheme(theme: AppTheme, designTokens?: AmpecoDesignTokens): void { + const base = theme === 'DARK' ? darkTheme : lightTheme; + const overrides = designTokens ? mapAmpecoTokens(designTokens) : {}; + const merged: ThemeTokens = { ...base, ...overrides }; + + document.documentElement.setAttribute('data-theme', theme.toLowerCase()); + + for (const [key, value] of Object.entries(merged)) { + const cssVar = TOKEN_CSS_MAP[key as keyof ThemeTokens]; + if (cssVar && value) { + document.documentElement.style.setProperty(cssVar, value); + } + } +} diff --git a/src/dark.ts b/src/dark.ts new file mode 100644 index 0000000..1a8e834 --- /dev/null +++ b/src/dark.ts @@ -0,0 +1,54 @@ +import type { ThemeTokens } from './tokens'; + +/** + * Dark theme defaults. + * Values sourced from the AMPECO mobile app design system + * (mobile-2/src/design_system/migration_file/colors/newColorsFormatExample.ts). + */ +export const darkTheme: ThemeTokens = { + // Buttons + btnPrimaryBg: '#0066FF', + btnPrimaryText: '#FFFFFF', + btnPrimaryPressed: '#2C4965', + btnSecondaryBg: '#000000', + btnSecondaryBorder: '#0066FF', + btnSecondaryText: '#FFFFFF', + + // Surfaces + surfaceBg: '#000000', + surfaceElevation1: '#1A2D3F', + surfaceElevation2: '#2C4965', + + // Text + textBase: '#FFFFFF', + textSupport: '#999999', + textPlaceholder: '#999999', + + // Feedback + feedbackSuccess: '#61E775', + feedbackSuccessSubtle: '#1D4523', + feedbackError: '#FF5454', + feedbackErrorSubtle: '#4C1919', + feedbackWarning: '#FFC062', + feedbackWarningSubtle: '#4C3A1D', + feedbackInfo: '#3C82EA', + feedbackInfoSubtle: '#122746', + + // Input + inputFill: '#1A2D3F', + inputBorder: '#2C4965', + inputBorderActive: '#3B658C', + inputText: '#FFFFFF', + inputPlaceholder: '#999999', + + // Separator + separator: '#3B658C', + + // Booking status (shared across themes) + statusAccepted: '#2F83FF', + statusReserved: '#24A629', + statusCompleted: '#808080', + statusCancelled: '#FFB23E', + statusNoShow: '#FF6868', + statusFailed: '#B71C1C', +}; diff --git a/src/index.ts b/src/index.ts new file mode 100644 index 0000000..2068f4e --- /dev/null +++ b/src/index.ts @@ -0,0 +1,16 @@ +// Types +export type { AppTheme, AmpecoDesignTokens } from './types'; +export type { ThemeTokens } from './tokens'; + +// Token definitions and CSS variable map +export { TOKEN_CSS_MAP } from './tokens'; + +// Theme defaults +export { lightTheme } from './light'; +export { darkTheme } from './dark'; + +// Token mapping (AMPECO mobile -> EWA) +export { AMPECO_TO_EWA_MAP, mapAmpecoTokens } from './tokenMapping'; + +// Theme application +export { applyTheme } from './apply'; diff --git a/src/light.ts b/src/light.ts new file mode 100644 index 0000000..0a1f8d2 --- /dev/null +++ b/src/light.ts @@ -0,0 +1,54 @@ +import type { ThemeTokens } from './tokens'; + +/** + * Light theme defaults. + * Values sourced from the AMPECO mobile app design system + * (mobile-2/src/design_system/migration_file/colors/newColorsFormatExample.ts). + */ +export const lightTheme: ThemeTokens = { + // Buttons + btnPrimaryBg: '#00A573', + btnPrimaryText: '#FFFFFF', + btnPrimaryPressed: '#D7E4DC', + btnSecondaryBg: '#FFFFFF', + btnSecondaryBorder: '#00A573', + btnSecondaryText: '#000000', + + // Surfaces + surfaceBg: '#FFFFFF', + surfaceElevation1: '#EEF2EF', + surfaceElevation2: '#D7E4DC', + + // Text + textBase: '#000000', + textSupport: '#808080', + textPlaceholder: '#808080', + + // Feedback + feedbackSuccess: '#24A629', + feedbackSuccessSubtle: '#BDE4BF', + feedbackError: '#FF6868', + feedbackErrorSubtle: '#FFD2D2', + feedbackWarning: '#FFB23E', + feedbackWarningSubtle: '#FFE8C5', + feedbackInfo: '#2F83FF', + feedbackInfoSubtle: '#C1DAFF', + + // Input + inputFill: '#EEF2EF', + inputBorder: '#D7E4DC', + inputBorderActive: '#C8DAD7', + inputText: '#000000', + inputPlaceholder: '#808080', + + // Separator + separator: '#C8DAD7', + + // Booking status (shared across themes) + statusAccepted: '#2F83FF', + statusReserved: '#24A629', + statusCompleted: '#808080', + statusCancelled: '#FFB23E', + statusNoShow: '#FF6868', + statusFailed: '#B71C1C', +}; diff --git a/src/tokenMapping.ts b/src/tokenMapping.ts new file mode 100644 index 0000000..5087536 --- /dev/null +++ b/src/tokenMapping.ts @@ -0,0 +1,45 @@ +import type { ThemeTokens } from './tokens'; +import type { AmpecoDesignTokens } from './types'; + +/** + * Maps AMPECO mobile app token property names to EWA ThemeTokens keys. + * The mobile app sends tokens using its own naming convention; this map + * translates them to the EWA internal token names. + */ +export const AMPECO_TO_EWA_MAP: Record = { + buttonsButtonPrimaryBackground: 'btnPrimaryBg', + buttonsButtonPrimaryText: 'btnPrimaryText', + buttonsButtonSecondaryBackground: 'btnSecondaryBg', + buttonsButtonSecondaryBorder: 'btnSecondaryBorder', + buttonsButtonSecondaryText: 'btnSecondaryText', + surfaceSurfaceBackground: 'surfaceBg', + surfaceSurfaceElevation1: 'surfaceElevation1', + surfaceSurfaceElevation2: 'surfaceElevation2', + textsTextBase: 'textBase', + textsTextSupport: 'textSupport', + textsTextPlaceholder: 'textPlaceholder', + feedbackColorFeedbackSuccess: 'feedbackSuccess', + feedbackColorFeedbackError: 'feedbackError', + feedbackColorFeedbackWarning: 'feedbackWarning', + feedbackColorFeedbackInfo: 'feedbackInfo', + inputFormsInputBorder: 'inputBorder', + inputFormsInputFill: 'inputFill', + inputFormsInputTextLabels: 'inputText', +}; + +/** + * Converts AMPECO mobile design tokens into the EWA ThemeTokens format. + * Only tokens that are present and have a truthy value are included in the result. + */ +export function mapAmpecoTokens(tokens: AmpecoDesignTokens): Partial { + const result: Partial = {}; + + for (const [ampecoKey, ewaKey] of Object.entries(AMPECO_TO_EWA_MAP)) { + const value = tokens[ampecoKey as keyof AmpecoDesignTokens]; + if (value) { + result[ewaKey] = value; + } + } + + return result; +} diff --git a/src/tokens.ts b/src/tokens.ts new file mode 100644 index 0000000..b1e8787 --- /dev/null +++ b/src/tokens.ts @@ -0,0 +1,102 @@ +/** + * Complete set of EWA theme tokens. + * Each key maps to a CSS custom property via TOKEN_CSS_MAP. + */ +export interface ThemeTokens { + // Buttons + btnPrimaryBg: string; + btnPrimaryText: string; + btnPrimaryPressed: string; + btnSecondaryBg: string; + btnSecondaryBorder: string; + btnSecondaryText: string; + + // Surfaces + surfaceBg: string; + surfaceElevation1: string; + surfaceElevation2: string; + + // Text + textBase: string; + textSupport: string; + textPlaceholder: string; + + // Feedback + feedbackSuccess: string; + feedbackSuccessSubtle: string; + feedbackError: string; + feedbackErrorSubtle: string; + feedbackWarning: string; + feedbackWarningSubtle: string; + feedbackInfo: string; + feedbackInfoSubtle: string; + + // Input + inputFill: string; + inputBorder: string; + inputBorderActive: string; + inputText: string; + inputPlaceholder: string; + + // Separator + separator: string; + + // Booking status + statusAccepted: string; + statusReserved: string; + statusCompleted: string; + statusCancelled: string; + statusNoShow: string; + statusFailed: string; +} + +/** + * Maps each ThemeTokens key to the corresponding CSS custom property name. + */ +export const TOKEN_CSS_MAP: Record = { + // Buttons + btnPrimaryBg: '--btn-primary-bg', + btnPrimaryText: '--btn-primary-text', + btnPrimaryPressed: '--btn-primary-pressed', + btnSecondaryBg: '--btn-secondary-bg', + btnSecondaryBorder: '--btn-secondary-border', + btnSecondaryText: '--btn-secondary-text', + + // Surfaces + surfaceBg: '--surface-bg', + surfaceElevation1: '--surface-elevation-1', + surfaceElevation2: '--surface-elevation-2', + + // Text + textBase: '--text-base', + textSupport: '--text-support', + textPlaceholder: '--text-placeholder', + + // Feedback + feedbackSuccess: '--feedback-success', + feedbackSuccessSubtle: '--feedback-success-subtle', + feedbackError: '--feedback-error', + feedbackErrorSubtle: '--feedback-error-subtle', + feedbackWarning: '--feedback-warning', + feedbackWarningSubtle: '--feedback-warning-subtle', + feedbackInfo: '--feedback-info', + feedbackInfoSubtle: '--feedback-info-subtle', + + // Input + inputFill: '--input-fill', + inputBorder: '--input-border', + inputBorderActive: '--input-border-active', + inputText: '--input-text', + inputPlaceholder: '--input-placeholder', + + // Separator + separator: '--separator', + + // Booking status + statusAccepted: '--status-accepted', + statusReserved: '--status-reserved', + statusCompleted: '--status-completed', + statusCancelled: '--status-cancelled', + statusNoShow: '--status-no-show', + statusFailed: '--status-failed', +}; diff --git a/src/types.ts b/src/types.ts new file mode 100644 index 0000000..05434d9 --- /dev/null +++ b/src/types.ts @@ -0,0 +1,29 @@ +/** + * Theme mode identifier. Matches the value sent by the AMPECO mobile app. + */ +export type AppTheme = 'LIGHT' | 'DARK'; + +/** + * Design tokens as received from the AMPECO mobile app via postMessage. + * All fields are optional because the app may send a partial override set. + */ +export interface AmpecoDesignTokens { + buttonsButtonPrimaryBackground?: string; + buttonsButtonPrimaryText?: string; + buttonsButtonSecondaryBackground?: string; + buttonsButtonSecondaryBorder?: string; + buttonsButtonSecondaryText?: string; + surfaceSurfaceBackground?: string; + surfaceSurfaceElevation1?: string; + surfaceSurfaceElevation2?: string; + textsTextBase?: string; + textsTextSupport?: string; + textsTextPlaceholder?: string; + feedbackColorFeedbackSuccess?: string; + feedbackColorFeedbackError?: string; + feedbackColorFeedbackWarning?: string; + feedbackColorFeedbackInfo?: string; + inputFormsInputBorder?: string; + inputFormsInputFill?: string; + inputFormsInputTextLabels?: string; +} diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..3be3034 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,19 @@ +{ + "compilerOptions": { + "target": "ES2020", + "module": "ESNext", + "moduleResolution": "bundler", + "strict": true, + "esModuleInterop": true, + "skipLibCheck": true, + "forceConsistentCasingInFileNames": true, + "declaration": true, + "declarationMap": true, + "sourceMap": true, + "outDir": "dist", + "rootDir": "src", + "lib": ["ES2020", "DOM"] + }, + "include": ["src"], + "exclude": ["node_modules", "dist"] +} diff --git a/tsup.config.ts b/tsup.config.ts new file mode 100644 index 0000000..7933f0c --- /dev/null +++ b/tsup.config.ts @@ -0,0 +1,9 @@ +import { defineConfig } from 'tsup'; + +export default defineConfig({ + entry: ['src/index.ts'], + format: ['esm', 'cjs'], + dts: true, + clean: true, + sourcemap: true, +});