import Color from "colorjs.io"; import { LucideIcon } from "lucide-react"; import { RemoteDomSerializableValue } from "@fluid-app/widget-runtime/worker"; //#region ../core/src/data-sources/types.d.ts type StaticSourceType = "collections" | "categories" | "tags"; type ShareableType = "Medium" | "Page" | "EnrollmentPack" | "Library" | "Product"; interface SelectedItem { /** The unique ID of the selected item */ id: string | number; /** The type of shareable content */ shareableType: ShareableType; /** Optional cached data for preview/display purposes in the editor UI */ cachedData?: { title?: string; imageUrl?: string; kind?: string; }; /** Widget-specific per-item configuration overrides */ widgetConfig?: Record; } interface ApiDataSource { type: "api"; /** If this source was created from a preset, the preset's unique ID. At runtime, the preset's current endpoint/resultPath/transform are used instead of the stored snapshot values. */ presetId?: string; /** API endpoint URL (can include {variable} placeholders, e.g., /api/reps/{rep_id}/items) */ endpoint: string; /** HTTP method (defaults to GET) */ method?: "GET" | "POST" | "PUT" | "DELETE"; /** Request headers */ headers?: Record; /** Request body for POST/PUT (will be JSON.stringify'd) */ body?: unknown; /** * Path to extract from response using dot notation * e.g., "data.items" extracts response.data.items */ resultPath?: string; /** * Which widget props this source populates * e.g., ['data'] means the fetched result goes to props.data */ targetProps: string[]; /** * Name of a registered transform function to process the data * Transform is applied after resultPath extraction */ transform?: string; /** Per-source variables for endpoint template interpolation (e.g., { limit: "10" }) */ variables?: Record; /** * Auto-refresh interval in milliseconds * 0 or undefined = no auto-refresh */ refreshInterval?: number; } interface CustomDataSource { type: "custom"; /** Array of selected items to fetch */ selectedItems: SelectedItem[]; /** * Which widget props this source populates * e.g., ['slides'] means the fetched results go to props.slides */ targetProps: string[]; /** * Name of a registered transform function to process the data * Transform is applied after all items are fetched */ transform?: string; /** * Auto-refresh interval in milliseconds * 0 or undefined = no auto-refresh */ refreshInterval?: number; } interface StaticDataSource { type: "static"; /** The type of static data (collections, categories, tags) */ staticType: StaticSourceType; /** The selected item ID */ selectedId: string | number; /** Cached data for preview/display in editor UI */ cachedData?: { title?: string; imageUrl?: string; }; /** * Which widget props this source populates */ targetProps: string[]; /** * Name of a registered transform function to process the data */ transform?: string; /** * Auto-refresh interval in milliseconds * 0 or undefined = no auto-refresh */ refreshInterval?: number; } type DataSource = ApiDataSource | CustomDataSource | StaticDataSource; interface DataSourceConfig { /** Array of data sources (usually just one, but supports multiple) */ sources: DataSource[]; /** Loading state configuration */ loading?: { /** Show skeleton placeholder while loading (default: true) */showSkeleton?: boolean; }; /** Error handling configuration */ error?: { /** Fallback props to use when fetch fails */fallback?: Record; /** Number of retry attempts (default: 0) */ retryCount?: number; /** Delay between retries in ms (default: 1000) */ retryDelay?: number; }; } //#endregion //#region ../core/src/registries/property-schema-types.d.ts /** * Tab configuration for organizing properties */ interface TabConfig { /** Unique identifier for the tab */ id: string; /** Display label for the tab */ label: string; } /** * Property field type constant - single source of truth for field types. * Use PROPERTY_FIELD_TYPES.text instead of "text" for type-safe comparisons. */ declare const PROPERTY_FIELD_TYPES: { readonly text: "text"; readonly textarea: "textarea"; readonly number: "number"; readonly boolean: "boolean"; readonly select: "select"; /** @deprecated Use `colorSelect` for semantic portal-theme colors. */ readonly color: "color"; readonly range: "range"; readonly dataSource: "dataSource"; readonly resource: "resource"; readonly image: "image"; readonly alignment: "alignment"; readonly slider: "slider"; readonly colorPicker: "colorPicker"; readonly sectionHeader: "sectionHeader"; readonly separator: "separator"; readonly buttonGroup: "buttonGroup"; readonly colorSelect: "colorSelect"; readonly sectionLayoutSelect: "sectionLayoutSelect"; readonly background: "background"; readonly contentPosition: "contentPosition"; readonly textSizeSelect: "textSizeSelect"; readonly cssUnit: "cssUnit"; readonly fontPicker: "fontPicker"; readonly stringArray: "stringArray"; readonly quoteList: "quoteList"; readonly borderRadius: "borderRadius"; readonly screenPicker: "screenPicker"; }; /** * Union type of all property field types, derived from PROPERTY_FIELD_TYPES constant. * @see deriving-typeof-for-object-keys pattern */ type PropertyFieldType = (typeof PROPERTY_FIELD_TYPES)[keyof typeof PROPERTY_FIELD_TYPES]; /** * Runtime validation for property field types. * @param value - The value to check * @returns true if value is a valid PropertyFieldType */ declare function isPropertyFieldType(value: string): value is PropertyFieldType; /** * Base schema for a property field */ interface PropertyFieldSchema { /** Property key in the widget props */ key: string; /** Display label for the field */ label: string; /** Field type determines the input control */ type: PropertyFieldType; /** Optional description/help text */ description?: string; /** Optional default value */ defaultValue?: unknown; /** Optional tab ID (must match a TabConfig id if widget has tabsConfig) */ tab?: string; /** Optional group for organizing fields within a tab */ group?: string; /** * When true, this field is treated as an override of a value that can * otherwise be inherited from the active theme (e.g. border radius, * padding, border width). Advanced fields are automatically bucketed * into the `CUSTOM_STYLING_GROUP` at the bottom of their tab and * rendered collapsed by default so the default surface area stays * minimal. */ advanced?: boolean; /** * @deprecated Use requiresKeyValue instead */ requiresKeyToBeTrue?: string; /** Optional requires a specific key to have a specific value. Supports single condition or array (AND logic). */ requiresKeyValue?: { key: string; value: unknown; } | Array<{ key: string; value: unknown; }>; } /** * Text field schema */ interface TextFieldSchema extends PropertyFieldSchema { type: "text"; placeholder?: string; maxLength?: number; /** * Optional quick-insert chips rendered below the input. Clicking a chip * inserts `{{value}}` at the caret. Used for URL template tokens * (e.g. `{{username}}`, `{{replicated_url || /signup}}`) so admins * don't have to remember the exact spelling. */ tokenSuggestions?: ReadonlyArray<{ /** Chip label shown to the admin (e.g. `username`). */label: string; /** Token body inserted between `{{` and `}}` (e.g. `username || /signup`). */ value: string; }>; } /** * Textarea field schema */ interface TextareaFieldSchema extends PropertyFieldSchema { type: "textarea"; placeholder?: string; rows?: number; maxLength?: number; } /** * Number field schema */ interface NumberFieldSchema extends PropertyFieldSchema { type: "number"; min?: number; max?: number; step?: number; } /** * Boolean field schema */ interface BooleanFieldSchema extends PropertyFieldSchema { type: "boolean"; } /** * Select field schema with type-safe option values. * Uses StrictOmit to ensure "defaultValue" key exists on PropertyFieldSchema. */ interface SelectFieldSchema extends StrictOmit { type: "select"; options: Array<{ label: string; value: T; }>; defaultValue?: T; } /** * Legacy free-form color field schema. * * @deprecated Use {@link ColorSelectFieldSchema} (`type: "colorSelect"`) so * widget authors select a semantic color token supplied by the portal theme. */ interface ColorFieldSchema extends PropertyFieldSchema { type: "color"; } /** * Range slider field schema */ interface RangeFieldSchema extends PropertyFieldSchema { type: "range"; min: number; max: number; step?: number; } /** * Data source field schema for configuring widget data sources */ interface DataSourceFieldSchema extends PropertyFieldSchema { /** Identifies this field as the data-source editor. */ type: "dataSource"; /** Widget props that this data-source editor can populate. */ targetProps?: ReadonlyArray<{ /** Widget prop key populated with the resolved data-source result. */key: string; /** Description emitted for this prop in the portal JSON Schema and types. */ description: string; }>; } /** * Resource field schema for selecting a single resource from the selection modal */ interface ResourceFieldSchema extends PropertyFieldSchema { type: "resource"; /** Optional filter to specific shareable types */ allowedTypes?: string[]; } /** * Image field schema for selecting a single asset (image or video) from the * image picker. Despite the legacy "image" name, this field supports video * picking via the `accept` parameter — `VideoWidget`, `ListWidget` Featured * Asset, and `NestedWidget` Primary Media all use it for video-or-mixed * content. */ interface ImageFieldSchema extends PropertyFieldSchema { type: "image"; /** * Restricts which MIME categories the picker offers. Defaults to "image". */ accept?: "image" | "video" | "any"; } /** * Alignment field schema */ interface AlignmentFieldSchema extends PropertyFieldSchema { type: "alignment"; options: { verticalEnabled: boolean; horizontalEnabled: boolean; }; defaultValue?: AlignOptions; } /** * Slider field schema with optional unit suffix (e.g., "rem", "px") */ interface SliderFieldSchema extends PropertyFieldSchema { type: "slider"; min: number; max: number; step?: number; unit?: string; } /** * Color picker field schema with optional swatches */ interface ColorPickerFieldSchema extends PropertyFieldSchema { type: "colorPicker"; swatches?: string[]; } /** * Section header field schema for visual grouping */ interface SectionHeaderFieldSchema extends PropertyFieldSchema { type: "sectionHeader"; subtitle?: string; } /** * Separator field schema for visual separation */ interface SeparatorFieldSchema extends PropertyFieldSchema { type: "separator"; } /** * Button group field schema. * Uses StrictOmit to ensure "defaultValue" key exists on PropertyFieldSchema. */ interface ButtonGroupFieldSchema extends StrictOmit { type: "buttonGroup"; options: Array<{ label?: string; ariaLabel?: string; icon?: LucideIcon; value: T; }>; defaultValue?: T; } /** * Semantic theme-color token selector. Prefer this field over free-form color * controls so widgets continue to work across portal themes and color modes. */ interface ColorSelectFieldSchema extends PropertyFieldSchema { type: "colorSelect"; defaultValue?: ColorOptions; excludeColors?: ColorOptions[]; } /** * Section layout select field schema for visual masonry layout selector */ interface SectionLayoutSelectFieldSchema extends PropertyFieldSchema { type: "sectionLayoutSelect"; defaultValue?: SectionLayoutType; } /** * Background field combines resource selection and color properties. * Uses StrictOmit to exclude conflicting "type" discriminant from parents. */ interface BackgroundFieldSchema extends StrictOmit, StrictOmit { type: "background"; } /** * Content position field schema for 3x3 grid position picker */ interface ContentPositionFieldSchema extends PropertyFieldSchema { type: "contentPosition"; defaultValue?: string; } /** * Text size select field schema for visual font size selector */ interface TextSizeSelectFieldSchema extends PropertyFieldSchema { type: "textSizeSelect"; defaultValue?: FontSizeOptions; } /** * CSS unit type for height/width fields */ type CssUnit = "px" | "rem" | "vh" | "%"; /** * CSS unit field schema for numeric values with selectable units (px, rem, vh, %) */ interface CssUnitFieldSchema extends PropertyFieldSchema { type: "cssUnit"; minByUnit?: Partial>; maxByUnit?: Partial>; stepByUnit?: Partial>; allowedUnits?: CssUnit[]; defaultUnit?: CssUnit; } /** * Font picker field schema for Google Fonts selection */ interface FontPickerFieldSchema extends PropertyFieldSchema { type: "fontPicker"; placeholder?: string; } /** * String array field schema for managing lists of text items */ interface StringArrayFieldSchema extends PropertyFieldSchema { type: "stringArray"; placeholder?: string; defaultValue?: string[]; } /** * A single quote in a QuoteList: the text plus optional attribution + role. */ interface QuoteListItem { quote: string; attribution?: string; role?: string; } /** * An editable list of quotes (add / remove / edit inline in the panel). Powers * the Quote widget's one-or-many quotes. */ interface QuoteListFieldSchema extends PropertyFieldSchema { type: "quoteList"; defaultValue?: QuoteListItem[]; } /** * Border radius composite field schema for controlling 4 corners with a single field. * Maps to 4 individual widget prop keys (topLeft, topRight, bottomLeft, bottomRight). */ interface BorderRadiusFieldSchema extends PropertyFieldSchema { type: "borderRadius"; keys: { topLeft: string; topRight: string; bottomLeft: string; bottomRight: string; }; defaultValue?: BorderRadiusOptions; } /** * Screen picker field schema for selecting a portal screen (navigation, system, or available) */ interface ScreenPickerFieldSchema extends PropertyFieldSchema { type: "screenPicker"; /** Whether to include system navigation items in the picker */ includeSystemItems?: boolean; } /** * Union of all field schema types */ type PropertyField = TextFieldSchema | TextareaFieldSchema | NumberFieldSchema | BooleanFieldSchema | SelectFieldSchema | ColorFieldSchema | RangeFieldSchema | DataSourceFieldSchema | ResourceFieldSchema | ImageFieldSchema | AlignmentFieldSchema | SliderFieldSchema | ColorPickerFieldSchema | SectionHeaderFieldSchema | SeparatorFieldSchema | ButtonGroupFieldSchema | ColorSelectFieldSchema | SectionLayoutSelectFieldSchema | BackgroundFieldSchema | ContentPositionFieldSchema | TextSizeSelectFieldSchema | CssUnitFieldSchema | FontPickerFieldSchema | StringArrayFieldSchema | QuoteListFieldSchema | BorderRadiusFieldSchema | ScreenPickerFieldSchema; /** * Schema for per-item configuration in custom data sources. * Widgets can define this to allow users to configure widget-specific * settings for each selected item (e.g., title, description, button). */ interface ItemConfigSchema { /** Fields available for per-item configuration */ fields: PropertyField[]; /** Optional description shown at top of item config panel */ description?: string; } /** * Schema for a widget's editable properties */ interface WidgetPropertySchema { /** Widget type this schema applies to */ widgetType: WidgetType; /** Display name for the widget */ displayName: string; /** Optional tab configuration - if present, tabs are enabled */ tabsConfig?: TabConfig[]; /** Editable property fields */ fields: PropertyField[]; /** Optional custom validator function */ validate?: (props: Record) => string | null; /** Props that can be populated from data sources */ dataSourceTargetProps?: string[]; /** Optional schema for per-item configurations in custom data sources */ itemConfigSchema?: ItemConfigSchema; } /** * Group property fields by their group property. * * Fields flagged with `advanced: true` are collected into the * `CUSTOM_STYLING_GROUP` bucket regardless of their declared `group`, * and that bucket is always placed last so it renders at the bottom of * the tab. Non-advanced fields keep their author-declared group and * their relative insertion order, including fields that explicitly use * `CUSTOM_STYLING_GROUP`. */ declare function groupPropertyFields(fields: readonly PropertyField[]): Record; /** * Extract current values from widget props based on property fields */ declare function extractPropertyValues(widget: Readonly, fields: readonly PropertyField[]): Record; /** * Apply property values to widget props */ declare function applyPropertyValues(widget: Readonly, values: Readonly>): WidgetSchema; //#endregion //#region ../core/src/remote-dom-widget-package.d.ts declare const REMOTE_DOM_WIDGET_MANIFEST_VERSION: 1; declare const REMOTE_DOM_WIDGET_RUNTIME: "remote-dom"; type JsonPrimitive = string | number | boolean | null; type JsonValue = JsonPrimitive | readonly JsonValue[] | JsonObject; interface JsonObject { readonly [key: string]: JsonValue; } type SerializableValue = unknown extends Value ? JsonValue : Value extends JsonValue ? Value : Value extends readonly (infer Item)[] ? readonly SerializableValue[] : Value extends object ? { readonly [Key in keyof Value as NonNullable extends ((...args: never[]) => unknown) ? never : Key]: SerializableValue } : never; /** * A property field that can be included in published widget metadata. * * The legacy `color` field is deprecated. Use `colorSelect` so the value is a * semantic color token supplied by the portal theme. */ type WidgetSourcePropertyField = PropertyField extends infer Field ? Field extends ButtonGroupFieldSchema ? Omit, "options"> & { /** Serializable button choices. Runtime icon components are not supported. */readonly options: readonly { readonly label?: string; readonly ariaLabel?: string; readonly value: string | number; }[]; } : SerializableValue : never; /** * JSON-serializable property editor schema accepted by widget source metadata. * The build adds `widgetType`; authors must not supply it. */ interface WidgetSourcePropertySchema { /** Optional tabs used to organize the property editor. */ readonly tabsConfig?: SerializableValue>; /** Editable fields shown in the property editor. */ readonly fields: readonly WidgetSourcePropertyField[]; /** Widget props that data sources can populate. */ readonly dataSourceTargetProps?: readonly string[]; /** Optional per-item fields for custom data-source selections. */ readonly itemConfigSchema?: { /** Fields available for each selected item. */readonly fields: readonly WidgetSourcePropertyField[]; /** Help text shown above the per-item editor. */ readonly description?: string; }; } interface RemoteDomWidgetCapabilityDeclaration { readonly name: string; readonly version: string; } interface RemoteDomWidgetDefinition { readonly type: string; readonly displayName: string; readonly description: string; readonly icon: string; readonly category: string; readonly propertySchema: JsonObject; readonly defaultProps: JsonObject; readonly container: "inline" | "block" | "card" | "fullscreen"; readonly resizable: boolean | "horizontal" | "vertical" | "both"; readonly minSdkVersion: string; readonly capabilities: readonly RemoteDomWidgetCapabilityDeclaration[]; } /** * Canonical package contract shared by the CLI, catalog APIs, and portal hosts. * Catalog producers resolve every artifact to its public URL before returning * this descriptor; consumers do not translate legacy manifest shapes. */ interface RemoteDomWidgetPackageDescriptor { readonly manifestVersion: typeof REMOTE_DOM_WIDGET_MANIFEST_VERSION; readonly runtime: typeof REMOTE_DOM_WIDGET_RUNTIME; readonly packageId: string; readonly source: "company" | "droplet"; readonly version: string; readonly workerEntryUrl: string; readonly cssUrls: readonly string[]; readonly assetUrls: readonly string[]; readonly widgets: readonly RemoteDomWidgetDefinition[]; } //#endregion //#region ../core/src/remote-widget-capability-grants.d.ts interface RemoteWidgetCapabilityGrant { readonly packageId: string; readonly packageVersion: string; readonly capabilityVersion: string; } type RemoteWidgetCapabilityGrants = Readonly>; //#endregion //#region ../core/src/types/widget-schema.d.ts /** * Generic component type — avoids React dependency in core. * Accepts both function components and class component constructors. */ type AnyComponent = ((props: any) => any) | (new (props: any) => any); /** * Widget type names as a const object. * This serves as the single source of truth for widget discriminants. * Use `as const` for literal type inference (safety-as-const-deep-readonly rule). */ declare const WIDGET_TYPE_NAMES: { readonly Alert: "AlertWidget"; readonly Announcement: "AnnouncementWidget"; readonly BulletList: "BulletListWidget"; readonly Calendar: "CalendarWidget"; readonly Card: "CardWidget"; readonly Carousel: "CarouselWidget"; readonly CatchUp: "CatchUpWidget"; readonly Chart: "ChartWidget"; readonly Container: "ContainerWidget"; readonly Embed: "EmbedWidget"; readonly Image: "ImageWidget"; readonly Layout: "LayoutWidget"; readonly Link: "LinkWidget"; readonly List: "ListWidget"; readonly MySite: "MySiteWidget"; readonly Nested: "NestedWidget"; readonly Points: "PointsWidget"; readonly Quote: "QuoteWidget"; readonly QuickLinks: "QuickLinksWidget"; readonly QuickShare: "QuickShareWidget"; readonly RecentActivity: "RecentActivityWidget"; readonly Separator: "SeparatorWidget"; readonly Shop: "ShopWidget"; readonly Spacer: "SpacerWidget"; readonly Table: "TableWidget"; readonly Text: "TextWidget"; readonly ToDo: "ToDoWidget"; readonly Video: "VideoWidget"; }; /** * Union of all known widget type names. * Derived from WIDGET_TYPE_NAMES to avoid duplication (deriving-typeof-for-object-keys rule). */ type WidgetTypeName = (typeof WIDGET_TYPE_NAMES)[keyof typeof WIDGET_TYPE_NAMES]; /** * Legacy alias for backwards compatibility. * Prefer using WidgetTypeName for new code when you need the union type. */ type WidgetType = string; type WidgetRegistry = Record; /** * Base widget schema with loose typing for runtime data. * Use TypedWidgetSchema when you have a known registry for better type safety. */ type WidgetSchema = { readonly type: WidgetType; readonly props: Readonly>; readonly id?: string; /** Optional data source configuration for data-bound widgets */ readonly dataSource?: DataSourceConfig | undefined; /** Column index for masonry layouts (0-indexed) */ readonly columnIndex?: number; /** Host-approved capabilities for a specific remote widget package version. */ readonly capabilityGrants?: RemoteWidgetCapabilityGrants; }; /** * Type-safe widget schema based on registry. * Uses discriminated unions - the `type` field serves as discriminant. * When narrowed (e.g., `if (widget.type === "AlertWidget")`), * TypeScript automatically knows the correct props type. */ type TypedWidgetSchema> = { [K in keyof T]: { readonly type: K; readonly props: Readonly any) ? P : T[K] extends (new (props: infer P) => any) ? P : never>; readonly id?: string; readonly dataSource?: DataSourceConfig | undefined; /** Column index for masonry layouts (0-indexed) */ readonly columnIndex?: number; readonly capabilityGrants?: RemoteWidgetCapabilityGrants; } }[keyof T]; /** * Widget path in the tree - array of indices. * Readonly tuple to prevent accidental mutation. */ type WidgetPath = readonly number[]; /** * Type predicate to check if a string is a known widget type name. * Use for runtime validation of widget types. * * @example * if (isWidgetTypeName(widget.type)) { * // TypeScript knows widget.type is WidgetTypeName * } */ declare function isWidgetTypeName(type: string): type is WidgetTypeName; /** * Type predicate to check if a widget has a specific type. * Enables type-safe widget narrowing without `as` assertions. * * @example * if (isWidgetType(widget, "LayoutWidget")) { * // TypeScript knows widget.type === "LayoutWidget" * // and widget.props is LayoutWidget props * } */ declare function isWidgetType(widget: WidgetSchema | null | undefined, typeName: T): widget is WidgetSchema & { readonly type: T; }; /** * Helper for exhaustive switch statements on widget types. * Use in the default case to ensure all widget types are handled. * * @example * switch (widget.type) { * case "AlertWidget": return handleAlert(); * case "TextWidget": return handleText(); * // ... all other widget types * default: return assertNever(widget.type, "widget type"); * } */ declare function assertNever(value: never, context?: string): never; /** * Assertion function that throws if value is undefined. * Narrows the type to exclude undefined. * * @example * const widget = screen[0]; * assertDefined(widget, "widget at index 0"); * // TypeScript knows widget is defined here */ declare function assertDefined(value: T | undefined | null, name?: string): asserts value is T; //#endregion //#region ../../platform/theme-engine/src/types.d.ts declare const SEMANTIC_COLOR_NAMES: readonly ["background", "foreground", "primary", "secondary", "accent", "muted", "destructive"]; type SemanticColorName = (typeof SEMANTIC_COLOR_NAMES)[number]; declare const FONT_SIZE_KEYS: readonly ["extraSmall", "small", "regular", "large", "extraLarge", "giant"]; type FontSizeKey = (typeof FONT_SIZE_KEYS)[number]; declare const FONT_FAMILY_KEYS: readonly ["header", "body"]; type FontFamilyKey = (typeof FONT_FAMILY_KEYS)[number]; declare const RADIUS_KEYS: readonly ["small", "medium", "large", "extraLarge"]; type RadiusKey = (typeof RADIUS_KEYS)[number]; /** Author-time color input (what the user configures) */ interface ThemeColorInput { base: Color; foreground: Color; } /** Complete theme definition — stored in-memory with Color objects */ interface ThemeDefinition { id: string; name: string; /** Light mode — always fully specified */ light: Record; /** * Dark mode — only user-overridden colors. * Missing keys are auto-derived from `light` at resolve time. */ dark: Partial>>; fontSizes: Record; fontFamilies: Record; spacing: string; radii: Record; /** When true, theme colors are re-derived from brand guidelines on every load */ syncWithBrandColors?: boolean; } /** Resolved semantic color */ interface ResolvedSemanticColor { base: Color; foreground: Color; } /** Complete resolved color set for one mode */ type ResolvedColorSet = Record; /** Fully resolved theme — all colors materialised for both modes */ interface ResolvedTheme { id: string; name: string; light: ResolvedColorSet; dark: ResolvedColorSet; fontSizes: ThemeDefinition["fontSizes"]; fontFamilies: ThemeDefinition["fontFamilies"]; spacing: string; radii: ThemeDefinition["radii"]; } /** Plain OKLCH triplet for JSON serialisation (no Color dependency) */ interface OklchPlain { l: number; c: number; h: number; } /** Serialised color pair as stored in the backend payload */ interface ThemeColorPlain { base: OklchPlain; foreground: OklchPlain; } /** Backend payload — plain JSON, no Color objects */ interface ThemePayload { [key: string]: unknown; id: string; name: string; light: Record; dark: Partial>; fontSizes: Record; fontFamilies: Record; spacing: string; radii: Record; syncWithBrandColors?: boolean; } //#endregion //#region ../../platform/theme-engine/src/color-engine.d.ts /** * Attempt to convert any string into a Color using colorjs.io. * If the string is exactly 6 hex digits it is assumed to be a bare hex value * (e.g. "3b82f6") and a "#" prefix is added before parsing. Six-letter * named colours like "orange" or "maroon" are left untouched. * * @returns the parsed Color, or a neutral gray (`oklch(0.5 0 0)`) on failure */ declare function parseColor(value: string): Color; /** * Returns either the original foreground or a corrected lightness variant, * whichever provides better contrast against `color`. * Inversion triggers when the |APCA contrast| is below 50 — APCA is signed * (negative for dark-on-light, positive for light-on-dark), so comparing the * absolute value avoids flipping dark text that already contrasts well on a * medium background. */ declare function getForegroundColor(foreground: Color, color: Color): Color; /** * Derive a dark-mode ThemeColorInput from its light-mode counterpart. */ declare function deriveDarkVariant(name: SemanticColorName, light: ThemeColorInput): ThemeColorInput; /** * Merge auto-derived dark colors with any user-specified overrides. * For each semantic color, if the user has fully overridden both base and * foreground those are used; otherwise the missing channels are derived. */ declare function mergeDarkOverrides(def: ThemeDefinition): Record; /** * Resolve a ThemeDefinition into a complete ResolvedTheme. * Dark mode colors are derived from light where not overridden. */ declare function resolveTheme(def: ThemeDefinition): ResolvedTheme; //#endregion //#region ../../platform/theme-engine/src/css-generator.d.ts interface GenerateThemeCSSOptions { /** Whether or not to allow prefers-color-scheme to choose the theme mode */ disableAutoTheme?: boolean; /** Whether to emit Tailwind built-in color overrides (default true) */ mapTailwindColors?: boolean; } /** * Generate a complete CSS string for a resolved theme. * Outputs 2–3 blocks: light default, dark explicit via `[data-theme-mode="dark"]`, * and (unless `disableAutoTheme`) a `prefers-color-scheme: dark` media query block. */ declare function generateThemeCSS(theme: ResolvedTheme, options?: GenerateThemeCSSOptions): string; //#endregion //#region ../../platform/theme-engine/src/serialisation.d.ts /** * Serialise a ThemeDefinition (with Color objects) to a plain JSON payload * suitable for backend storage. */ declare function serialiseTheme(def: ThemeDefinition): ThemePayload; /** * Deserialise a backend payload into a ThemeDefinition with Color objects. * Accepts `Record` because API data is untyped at the boundary. * Falls back to default colors for any missing light-mode entries. */ declare function deserialiseTheme(payload: Record): ThemeDefinition; //#endregion //#region ../../platform/theme-engine/src/transforms.d.ts /** Shape of a raw theme from the FluidOS API */ interface RawApiTheme { id: number; config?: Record | null; active?: boolean | null; name?: string | null; } /** * Build a ThemeDefinition from a single API theme object. * Handles both new structured format and legacy flat format. */ declare function buildThemeDefinition(theme: RawApiTheme): ThemeDefinition; /** * Transform raw API themes to ThemeDefinition[]. * Catches and logs errors per theme (graceful degradation). */ declare function transformThemes(themes: RawApiTheme[]): ThemeDefinition[]; /** * Get the active theme ID from a list of raw API themes. * Falls back to the first theme if none is marked active. */ declare function getActiveThemeId(themes: RawApiTheme[]): string | undefined; //#endregion //#region ../../platform/theme-engine/src/theme-applicator.d.ts /** * Inject or update a `