meno-astro 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +26 -0
- package/dist/chunks/chunk-IVGZB6XN.js +2921 -0
- package/dist/chunks/chunk-IVGZB6XN.js.map +7 -0
- package/dist/chunks/chunk-LEMVUKVG.js +90 -0
- package/dist/chunks/chunk-LEMVUKVG.js.map +7 -0
- package/dist/chunks/chunk-PQQAY42O.js +91 -0
- package/dist/chunks/chunk-PQQAY42O.js.map +7 -0
- package/dist/chunks/chunk-ZYQNHI3W.js +16 -0
- package/dist/chunks/chunk-ZYQNHI3W.js.map +7 -0
- package/dist/lib/components/BaseLayout.astro +53 -0
- package/dist/lib/components/Embed.astro +24 -0
- package/dist/lib/components/Link.astro +19 -0
- package/dist/lib/components/LocaleList.astro +75 -0
- package/dist/lib/components/index.js +14 -0
- package/dist/lib/components/index.js.map +7 -0
- package/dist/lib/dialect/index.js +1385 -0
- package/dist/lib/dialect/index.js.map +7 -0
- package/dist/lib/index.js +141 -0
- package/dist/lib/index.js.map +7 -0
- package/dist/lib/integration/index.js +56 -0
- package/dist/lib/integration/index.js.map +7 -0
- package/dist/lib/runtime/localeMiddleware.js +16 -0
- package/dist/lib/runtime/localeMiddleware.js.map +7 -0
- package/package.json +36 -0
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../core/lib/shared/constants.ts", "../../../core/lib/shared/validation/schemas.ts", "../../../core/lib/shared/registry/ComponentRegistry.ts", "../../../core/lib/shared/registry/ClientRegistry.ts", "../../../core/lib/shared/registry/SSRRegistry.ts", "../../../core/lib/shared/registry/RegistryManager.ts", "../../../core/lib/shared/registry/BaseNodeTypeRegistry.ts", "../../../core/lib/shared/registry/ClientNodeTypeRegistry.ts", "../../../core/lib/shared/registry/SSRNodeTypeRegistry.ts", "../../../core/lib/shared/registry/NodeTypeManager.ts", "../../../core/lib/shared/registry/defineNodeType.ts", "../../../core/lib/shared/registry/createNodeType.ts", "../../../core/lib/shared/registry/fieldPresets.ts", "../../../core/lib/shared/registry/nodeTypes/HtmlNodeType.ts", "../../../core/lib/shared/registry/nodeTypes/ComponentInstanceNodeType.ts", "../../../core/lib/shared/registry/nodeTypes/SlotMarkerType.ts", "../../../core/lib/shared/registry/nodeTypes/EmbedNodeType.ts", "../../../core/lib/shared/registry/nodeTypes/LinkNodeType.ts", "../../../core/lib/shared/registry/nodeTypes/LocaleListNodeType.ts", "../../../core/lib/shared/registry/nodeTypes/ListNodeType.ts", "../../../core/lib/shared/registry/nodeTypes/index.ts", "../../../core/lib/shared/registry/index.ts", "../../../core/lib/shared/i18n.ts", "../../../core/lib/shared/cmsQueryParser.ts", "../../../core/lib/shared/index.ts", "../../../core/lib/shared/nodeUtils.ts", "../../../core/lib/shared/breakpoints.ts", "../../../core/lib/shared/cssProperties.ts", "../../../core/lib/shared/utilityClassConfig.ts", "../../../core/lib/shared/responsiveScaling.ts", "../../../core/lib/shared/pxToRem.ts", "../../../core/lib/shared/cssGeneration.ts", "../../../core/lib/shared/utilityClassMapper.ts", "../../../core/lib/shared/elementClassName.ts", "../../../core/lib/shared/validation/index.ts", "../../../core/lib/shared/validation/validators.ts", "../../../core/lib/shared/validation/cmsValidators.ts", "../../../core/lib/shared/validation/commentValidators.ts", "../../../core/lib/shared/expressionEvaluator.ts", "../../../core/lib/shared/globalTemplateContext.ts", "../../../core/lib/shared/interactiveStyleMappings.ts", "../../lib/server/loadI18nConfig.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * Shared constants used across the application\n */\n\n// Read PORT from environment variable, fallback to 3000\n// Safe for browser environments where process is not defined\nexport const SERVER_PORT = typeof process !== 'undefined' && process.env?.PORT\n ? parseInt(process.env.PORT, 10)\n : 3000;\n\n// Port for serving built static files (SSR preview)\n// Reads MENO_SERVE_PORT env var so each project instance can get its own port\nexport const SERVE_PORT = typeof process !== 'undefined' && process.env?.MENO_SERVE_PORT\n ? parseInt(process.env.MENO_SERVE_PORT, 10)\n : 8080;\n\nexport const API_ROUTES = {\n PAGES: '/api/pages',\n COMPONENTS: '/api/components',\n PAGE_CONTENT: '/api/page-content', // Returns raw JSON text for a page\n PAGE_DATA: '/api/page-data', // Returns parsed JSON for a specific page\n COMPONENT_DATA: '/api/component-data', // Returns parsed JSON for a specific component\n SAVE_PAGE: '/api/save-page',\n SAVE_COMPONENT: '/api/save-component',\n SAVE_COMPONENT_JS: '/api/save-component-js', // Save JavaScript to .js file\n SAVE_COMPONENT_CSS: '/api/save-component-css', // Save CSS to .css file\n COMPONENT_CATEGORY: '/api/component-category', // Move component to category folder\n COMPONENT_FOLDER: '/api/component-folder', // Create component folder\n COMPONENT_FOLDERS: '/api/component-folders', // List all component folders\n COMPONENT_JS: '/api/component-js', // Get JavaScript from .js file\n CONFIG: '/api/config', // Get project config\n SAVE_CONFIG: '/api/save-config', // Save project config\n COMPONENTS_CONFIG: '/api/components-config', // Get components config\n SAVE_COMPONENTS_CONFIG: '/api/save-components-config', // Save components config\n SELECTION: '/api/selection', // Editor selection state (for AI integration)\n // CMS API routes\n CMS_COLLECTIONS: '/api/cms/collections', // List all CMS collections\n CMS_BASE: '/api/cms', // Base path for CMS item operations\n // Colors API routes\n COLORS_CONFIG: '/api/colors-config', // Get full colors config\n SAVE_COLORS: '/api/save-colors', // Save colors config\n // Page deletion\n DELETE_PAGE: '/api/delete-page', // Delete a page\n // Page folder management\n PAGE_FOLDER: '/api/page-folder', // Create page folder\n PAGE_FOLDERS: '/api/page-folders', // List all page folders\n MOVE_PAGE: '/api/move-page', // Move page to folder\n // Component preview\n COMPONENT_PREVIEW: '/api/component-preview', // Render component preview HTML\n // Website import\n IMPORT_WEBSITE: '/api/import-website', // Import external website for reference\n IMPORTED_WEBSITES: '/api/imported-websites', // List imported website folders\n ANALYZE_WEBSITE: '/api/analyze-website', // Analyze imported website into section map\n CONVERT_TO_MENO: '/api/convert-to-meno', // Convert imported HTML to flat Meno page JSON\n EXTRACT_CONTENT: '/api/extract-content', // Extract content from imported website for template mapping\n GENERATE_WIREFRAME_PROMPT: '/api/generate-wireframe-prompt', // Generate wireframe conversion prompt from extraction\n GENERATE_DESIGN_TOKEN_PROMPT: '/api/generate-design-token-prompt', // Generate design token extraction prompt\n GENERATE_CONTENT_PROMPT: '/api/generate-content-prompt', // Generate content conversion prompt using existing components\n GENERATE_SIMPLIFIED_PROMPT: '/api/generate-simplified-prompt', // Generate simplified prompt for Claude Code with Chrome extension\n // Multi-page import routes\n FETCH_SITEMAP: '/api/fetch-sitemap', // Fetch & parse sitemap.xml\n IMPORT_PAGE: '/api/import-page', // Import a single subpage\n ANALYZE_PAGE: '/api/analyze-page', // Analyze a subpage\n EXTRACT_PAGE_CONTENT: '/api/extract-page-content', // Extract content from a subpage\n GENERATE_HOMEPAGE_PROMPT: '/api/generate-homepage-prompt', // Homepage prompt with site structure\n GENERATE_PAGE_PROMPT: '/api/generate-page-prompt', // Per-page/template prompt\n LOAD_WEBSITE_IMPORT: '/api/load-website-import', // Load saved website import data from disk\n // Variables API routes\n VARIABLES_STATUS: '/api/variables-status', // Get variables config with status\n VARIABLES_CSS: '/api/variables-css', // Get generated CSS custom properties\n SAVE_VARIABLES: '/api/save-variables', // Save variables config\n // Enums API routes\n ENUMS: '/api/enums', // Get enums config\n SAVE_ENUMS: '/api/save-enums', // Save enums config\n // Component usage\n COMPONENT_USAGE: '/api/component-usage', // Get component usage across project\n // Rename component across the project (files + all references)\n RENAME_COMPONENT: '/api/rename-component',\n // Rename a page (single-locale: file rename + cascade href rewrite)\n RENAME_PAGE: '/api/rename-page',\n // Rename a page's locale-specific slug (multi-locale: meta.slugs + cascade hrefs)\n RENAME_PAGE_SLUG: '/api/rename-page-slug',\n} as const;\n\nexport const HMR_ROUTE = '/hmr';\n\nexport const FILE_PATTERNS = {\n PAGES: './pages',\n COMPONENTS: './components',\n} as const;\n\nexport const DEFAULT_TIMEOUT = 5000;\n\nexport const WEBSOCKET_STATES = {\n CONNECTING: 0,\n OPEN: 1,\n CLOSING: 2,\n CLOSED: 3,\n} as const;\n\n// Timeout constants\nexport const NOT_FOUND_TIMEOUT_MS = 300;\nexport const TAB_SWITCH_DELAY_MS = 100;\nexport const IFRAME_HIGHLIGHT_DELAY_MS = 100;\nexport const TREE_SCROLL_DELAY_MS = 200;\nexport const HOVER_HIGHLIGHT_DELAY_MS = 50; // Delay before highlighting tree item after expansion\n\n// Server configuration\nexport const MAX_PORT_ATTEMPTS = 10;\n\n// Message types for iframe-parent communication\nexport const IFRAME_MESSAGE_TYPES = {\n DELETE_ELEMENT: 'DELETE_ELEMENT',\n TOGGLE_SELECTING_MODE: 'TOGGLE_SELECTING_MODE',\n SET_TAB: 'SET_TAB',\n COPY_ELEMENT: 'COPY_ELEMENT',\n PASTE_ELEMENT: 'PASTE_ELEMENT',\n PASTE_ELEMENT_AFTER: 'PASTE_ELEMENT_AFTER',\n ARROW_UP: 'ARROW_UP',\n ARROW_DOWN: 'ARROW_DOWN',\n ARROW_LEFT: 'ARROW_LEFT',\n ARROW_RIGHT: 'ARROW_RIGHT',\n OPEN_COMMAND_PALETTE: 'OPEN_COMMAND_PALETTE',\n EDIT_COMPONENT: 'EDIT_COMPONENT',\n NAVIGATE_BACK: 'NAVIGATE_BACK',\n TOGGLE_ADDING_STYLE: 'TOGGLE_ADDING_STYLE',\n MOVE_ELEMENT_UP: 'MOVE_ELEMENT_UP',\n MOVE_ELEMENT_DOWN: 'MOVE_ELEMENT_DOWN',\n NEST_INTO_PREVIOUS_SIBLING: 'NEST_INTO_PREVIOUS_SIBLING',\n NEST_INTO_NEXT_SIBLING: 'NEST_INTO_NEXT_SIBLING',\n SELECTION_CHANGED: 'SELECTION_CHANGED',\n CMS_CONTEXT_UPDATE: 'CMS_CONTEXT_UPDATE',\n CMS_CONTEXT_REQUEST: 'CMS_CONTEXT_REQUEST',\n INTERACTIVE_CSS_UPDATE: 'INTERACTIVE_CSS_UPDATE',\n INTERACTIVE_STYLES_UPDATE: 'INTERACTIVE_STYLES_UPDATE', // Registry data from iframe to editor\n UNDO_REQUEST: 'UNDO_REQUEST',\n REDO_REQUEST: 'REDO_REQUEST',\n TOGGLE_INTERACTIVITY_EDITOR: 'TOGGLE_INTERACTIVITY_EDITOR',\n SET_BREAKPOINT: 'SET_BREAKPOINT',\n PAGE_DATA_PREVIEW: 'PAGE_DATA_PREVIEW', // Editor \u2192 Iframe for component hover preview\n PAGE_DATA_PREVIEW_REVERT: 'PAGE_DATA_PREVIEW_REVERT', // Editor \u2192 Iframe to revert preview\n PAGE_DATA_COMMITTED: 'PAGE_DATA_COMMITTED', // Editor \u2192 Iframe for committed mutations\n COMPONENT_DEFINITION_COMMITTED: 'COMPONENT_DEFINITION_COMMITTED', // Editor \u2192 Iframe for component definition updates\n CSS_VARIABLE_UPDATE: 'CSS_VARIABLE_UPDATE', // Editor \u2192 Iframe for instant CSS variable preview\n CSS_VARIABLE_SCOPED_UPDATE: 'CSS_VARIABLE_SCOPED_UPDATE', // Editor \u2192 Iframe for instant per-breakpoint CSS variable preview (scoped via @media)\n CSS_VARIABLE_SCOPED_CLEAR: 'CSS_VARIABLE_SCOPED_CLEAR', // Editor \u2192 Iframe to drop the scrub-preview <style> tag\n DUPLICATE_ELEMENT: 'DUPLICATE_ELEMENT',\n MAKE_COMPONENT: 'MAKE_COMPONENT',\n SWAP_TO_COMPONENT: 'SWAP_TO_COMPONENT',\n SMART_CONNECT: 'SMART_CONNECT',\n} as const;\n\n// Component node type constants\nexport const NODE_TYPE = {\n NODE: 'node',\n COMPONENT: 'component',\n SLOT: 'slot',\n EMBED: 'embed',\n LINK: 'link',\n LOCALE_LIST: 'locale-list',\n LIST: 'list',\n} as const;\n\nexport type NodeType = typeof NODE_TYPE[keyof typeof NODE_TYPE];\n\n// Special path identifiers for component editing\nexport const SPECIAL_PATHS = {\n COMPONENT_INTERFACE: 'component_interface',\n COMPONENT_JAVASCRIPT: 'component_javascript',\n COMPONENT_CSS: 'component_css',\n COMPONENT_LIBRARIES: 'component_libraries',\n COMPONENT_ACCEPTS_STYLES: 'component_acceptsStyles',\n STRUCTURE_STYLE: 'structure_style',\n} as const;\n\n// Component type configuration\nexport interface ComponentTypeConfig {\n id: string;\n label: string;\n color: string;\n description?: string;\n}\n\nexport const DEFAULT_COMPONENT_TYPES: ComponentTypeConfig[] = [\n { id: 'ui', label: 'UI', color: '#3b82f6' },\n { id: 'layout', label: 'Layout', color: '#10b981' },\n { id: 'content', label: 'Content', color: '#f59e0b' },\n];\n\nexport const DEFAULT_ICON_COLOR = '#6b7280';\n\n/**\n * Marker for raw HTML content that should not be escaped\n * Used by rich-text fields to signal that content should render as HTML\n */\nexport const RAW_HTML_PREFIX = '<!--MENO_RAW_HTML-->';\n\n", "/**\n * Validation Schemas\n * Zod schemas for runtime validation of JSON data structures\n * All schemas use .passthrough() to maintain backward compatibility with unknown fields\n *\n * Note: Node type definitions also define their own schemas for TypeScript type inference.\n * The schemas here are the authoritative source for VALIDATION (with proper recursive\n * ComponentNode references). Node type files use simplified schemas for type inference.\n */\n\nimport { z } from 'zod';\nimport type { StyleObject, StyleMapping, LinkMapping, HtmlMapping } from '../types/styles';\nimport { NODE_TYPE } from '../constants';\n\n/**\n * Prop type schema - validates PropType values (excluding list for base definition)\n */\nexport const BasePropTypeSchema = z.enum(['string', 'select', 'boolean', 'number', 'link', 'file', 'rich-text', 'embed']);\n\n/**\n * Full prop type schema including list\n */\nexport const PropTypeSchema = z.enum(['string', 'select', 'boolean', 'number', 'link', 'file', 'rich-text', 'embed', 'list']);\n\n/**\n * `_i18n` value object schema. Used wherever a localizable string can appear:\n * - Prop defaults (`BasePropDefinitionSchema.default`)\n * - Node `children` (text content on `type: \"node\"`, `\"link\"`, `\"component\"`,\n * and basic list nodes)\n * - Attribute values (`attributes` records on every node type)\n *\n * The runtime resolves these objects to the active locale's string at the\n * earliest dispatch point in both the SSR renderer (`renderNode`) and the\n * client builder (`ComponentBuilder.buildComponent`). The schema accepts the\n * shape so the editor's load path doesn't reject files that contain it.\n */\nexport const I18nValueObjectSchema = z.object({\n _i18n: z.literal(true),\n}).passthrough();\n\n/**\n * Base prop definition schema (for non-list props).\n * `default` accepts a literal value (string/number/boolean/link) OR an\n * `_i18n` value object \u2014 the SSR pipeline resolves the latter to the active\n * locale's string via `resolveI18nInProps` at render time, so localized prop\n * defaults are first-class. The `I18nOrStringSchema` proper is defined later\n * in this file; we inline the matching shape here to keep the validator\n * tolerant of localized defaults.\n */\nexport const BasePropDefinitionSchema = z.object({\n type: BasePropTypeSchema,\n default: z.union([\n z.string(),\n z.number(),\n z.boolean(),\n z.object({ href: z.string(), target: z.string().optional() }),\n I18nValueObjectSchema,\n ]).optional(),\n options: z.array(z.string()).readonly().optional(),\n enumName: z.string().optional(), // For 'select' type: reference to project-level enum\n accept: z.string().optional(), // For 'file' type: MIME pattern like \"image/*\", \"video/*\"\n editor: z.enum(['basic', 'extended']).optional(), // For 'rich-text' type: which editor to use\n}).passthrough();\n\n/**\n * Project-level enums configuration schema\n * Keys are enum names, values are arrays of options\n */\nexport const EnumsConfigSchema = z.record(z.string(), z.array(z.string()));\n\n/**\n * List item schema - defines structure of each item in a list prop\n */\nexport const ListItemSchemaSchema = z.record(z.string(), BasePropDefinitionSchema);\n\n/**\n * List prop definition schema\n */\nexport const ListPropDefinitionSchema = z.object({\n type: z.literal('list'),\n itemSchema: ListItemSchemaSchema,\n // List-item field values can be any primitive, a link object, an `_i18n`\n // object (resolved by the SSR pipeline), or null.\n default: z.array(z.record(z.string(), z.union([\n z.string(),\n z.number(),\n z.boolean(),\n z.object({ href: z.string(), target: z.string().optional() }),\n I18nValueObjectSchema,\n z.null(),\n ]))).optional(),\n}).passthrough();\n\n/**\n * Prop definition schema (union of base and list)\n * Validates prop definitions from component interfaces\n */\nexport const PropDefinitionSchema = z.union([\n ListPropDefinitionSchema,\n BasePropDefinitionSchema,\n]);\n\n/**\n * Style mapping schema\n */\nexport const StyleMappingSchema: z.ZodType<StyleMapping> = z.object({\n _mapping: z.literal(true),\n prop: z.string(),\n values: z.record(z.string(), z.union([z.string(), z.number()])),\n}).passthrough();\n\n/**\n * Boolean mapping schema - for conditional rendering (if property)\n * Maps component prop values to boolean results\n */\nexport const BooleanMappingSchema = z.object({\n _mapping: z.literal(true),\n prop: z.string(),\n values: z.record(z.string(), z.boolean()),\n}).passthrough();\n\n/**\n * If condition schema - can be boolean, string template, or mapping\n */\nexport const IfConditionSchema = z.union([\n z.boolean(),\n z.string(),\n BooleanMappingSchema,\n]);\n\n/**\n * Link mapping schema - for link node href mappings\n * values is optional - when missing, acts as passthrough for link-type props\n */\nexport const LinkMappingSchema: z.ZodType<LinkMapping> = z.object({\n _mapping: z.literal(true),\n prop: z.string(),\n values: z.record(z.string(), z.object({\n href: z.string(),\n target: z.string().optional(),\n })).optional(),\n}).passthrough();\n\n/**\n * HTML mapping schema - for embed node html content mappings\n * values is optional - when missing, acts as passthrough for string-type props\n */\nexport const HtmlMappingSchema: z.ZodType<HtmlMapping> = z.object({\n _mapping: z.literal(true),\n prop: z.string(),\n values: z.record(z.string(), z.string()).optional(),\n}).passthrough();\n\n/**\n * Style object schema - flat style object\n */\nexport const StyleObjectSchema: z.ZodType<StyleObject> = z.record(\n z.string(),\n z.union([\n z.string(),\n z.number(),\n StyleMappingSchema,\n ])\n);\n\n/**\n * Responsive style object schema\n */\nexport const ResponsiveStyleObjectSchema = z.object({\n base: StyleObjectSchema.optional(),\n tablet: StyleObjectSchema.optional(),\n mobile: StyleObjectSchema.optional(),\n}).passthrough();\n\n/**\n * Style value schema - can be either flat or responsive\n */\nexport const StyleValueSchema = z.union([\n StyleObjectSchema,\n ResponsiveStyleObjectSchema,\n]);\n\n/**\n * Interactive style rule schema\n * Validates prefix/postfix selector parts for interactive styles\n * CSS pattern: {prefix}.element{postfix}\n */\nexport const InteractiveStyleRuleSchema = z.object({\n name: z.string().optional(),\n prefix: z.string().optional(),\n postfix: z.string().optional(),\n style: StyleValueSchema,\n previewProp: z.string().optional(),\n});\n\n/**\n * Interactive styles schema - array of rules\n */\nexport const InteractiveStylesSchema = z.array(InteractiveStyleRuleSchema);\n\n// ============================================================================\n// Node Type Schemas (Validation)\n// These schemas handle proper recursive validation with ComponentNode references.\n// Node type files also have schemas for TypeScript type inference.\n// ============================================================================\n\n/**\n * Slot marker schema\n * default: Optional default content when instance has no children\n * Can be an array of ComponentNodes or a string\n */\nexport const SlotMarkerSchema: z.ZodType<any> = z.lazy(() => z.object({\n type: z.literal(NODE_TYPE.SLOT),\n default: z.union([\n z.array(z.union([ComponentNodeSchema, z.string(), I18nValueObjectSchema])),\n z.string(),\n I18nValueObjectSchema,\n ]).optional(),\n}).passthrough());\n\n/**\n * Component node schema - discriminated union (forward declaration)\n * Uses z.ZodType<any> because schema is more permissive than TypeScript types\n */\nlet ComponentNodeSchema: z.ZodType<any>;\n\n/**\n * HTML node schema - recursive definition\n */\nexport const HtmlNodeSchema: z.ZodType<any> = z.lazy(() => z.object({\n type: z.literal(NODE_TYPE.NODE),\n tag: z.string(),\n label: z.string().optional(),\n if: IfConditionSchema.optional(),\n style: StyleValueSchema.optional(),\n interactiveStyles: InteractiveStylesSchema.optional(),\n generateElementClass: z.boolean().optional(),\n attributes: z.record(z.string(), z.union([z.string(), z.number(), z.boolean(), I18nValueObjectSchema])).optional(),\n props: z.record(z.string(), z.any()).optional(), // Allow props for backward compatibility\n children: z.union([\n z.array(z.union([ComponentNodeSchema, z.string(), I18nValueObjectSchema])),\n z.string(),\n I18nValueObjectSchema,\n ]).optional(),\n}).passthrough());\n\n/**\n * Component instance node schema - recursive definition\n */\nexport const ComponentInstanceNodeSchema: z.ZodType<any> = z.lazy(() => z.object({\n type: z.literal(NODE_TYPE.COMPONENT),\n component: z.string(),\n label: z.string().optional(),\n if: IfConditionSchema.optional(),\n props: z.record(z.string(), z.any()).optional(),\n style: StyleValueSchema.optional(),\n interactiveStyles: InteractiveStylesSchema.optional(),\n generateElementClass: z.boolean().optional(),\n attributes: z.record(z.string(), z.union([z.string(), z.number(), z.boolean(), I18nValueObjectSchema])).optional(),\n children: z.union([\n z.array(z.union([ComponentNodeSchema, z.string(), I18nValueObjectSchema])),\n z.string(),\n I18nValueObjectSchema,\n ]).optional(),\n}).passthrough());\n\n/**\n * Embed node schema - for rendering custom HTML/SVG content\n */\nexport const EmbedNodeSchema: z.ZodType<any> = z.lazy(() => z.object({\n type: z.literal(NODE_TYPE.EMBED),\n html: z.union([z.string(), HtmlMappingSchema, I18nValueObjectSchema]),\n label: z.string().optional(),\n if: IfConditionSchema.optional(),\n style: StyleValueSchema.optional(),\n interactiveStyles: InteractiveStylesSchema.optional(),\n generateElementClass: z.boolean().optional(),\n attributes: z.record(z.string(), z.union([z.string(), z.number(), z.boolean(), I18nValueObjectSchema])).optional(),\n}).passthrough());\n\n/**\n * Link node schema - renders as div in editor, <a> in SSR\n */\nexport const LinkNodeSchema: z.ZodType<any> = z.lazy(() => z.object({\n type: z.literal(NODE_TYPE.LINK),\n href: z.union([z.string(), LinkMappingSchema, I18nValueObjectSchema]),\n label: z.string().optional(),\n if: IfConditionSchema.optional(),\n style: StyleValueSchema.optional(),\n interactiveStyles: InteractiveStylesSchema.optional(),\n generateElementClass: z.boolean().optional(),\n attributes: z.record(z.string(), z.union([z.string(), z.number(), z.boolean(), I18nValueObjectSchema])).optional(),\n children: z.union([\n z.array(z.union([ComponentNodeSchema, z.string(), I18nValueObjectSchema])),\n z.string(),\n I18nValueObjectSchema,\n ]).optional(),\n}).passthrough());\n\n/**\n * Locale list node schema - renders locale switcher links\n */\nexport const LocaleListNodeSchema: z.ZodType<any> = z.lazy(() => z.object({\n type: z.literal(NODE_TYPE.LOCALE_LIST),\n label: z.string().optional(),\n if: IfConditionSchema.optional(),\n style: StyleValueSchema.optional(),\n interactiveStyles: InteractiveStylesSchema.optional(),\n generateElementClass: z.boolean().optional(),\n itemStyle: StyleValueSchema.optional(),\n activeItemStyle: StyleValueSchema.optional(),\n separatorStyle: StyleValueSchema.optional(),\n showCurrent: z.boolean().optional(),\n showSeparator: z.boolean().optional(),\n showFlag: z.boolean().optional(),\n flagStyle: StyleValueSchema.optional(),\n attributes: z.record(z.string(), z.union([z.string(), z.number(), z.boolean(), I18nValueObjectSchema])).optional(),\n}).passthrough());\n\n/**\n * Unified List node schema (basic version for ComponentNodeSchema union)\n * Handles both prop-based lists and CMS collection-based lists.\n * Uses sourceType to distinguish: 'prop' (default) or 'collection'.\n * Also supports legacy 'cms-list' type for backward compatibility.\n */\nexport const ListNodeSchemaBasic: z.ZodType<any> = z.lazy(() => z.object({\n type: z.union([z.literal(NODE_TYPE.LIST), z.literal('cms-list')]), // Support both for migration\n sourceType: z.enum(['prop', 'collection']).optional(), // defaults to 'prop'\n source: z.string().optional(), // Source prop name or collection name\n collection: z.string().optional(), // Legacy field for cms-list migration\n label: z.string().optional(),\n if: IfConditionSchema.optional(),\n itemAs: z.string().optional(),\n // Collection-specific options\n items: z.union([z.string(), z.array(z.string())]).optional(),\n filter: z.unknown().optional(),\n sort: z.unknown().optional(),\n limit: z.number().optional(),\n offset: z.number().optional(),\n excludeCurrentItem: z.boolean().optional(),\n emitTemplate: z.boolean().optional(),\n children: z.array(z.union([ComponentNodeSchema, z.string(), I18nValueObjectSchema])).optional(),\n}).passthrough());\n\n/**\n * @deprecated Use ListNodeSchemaBasic instead.\n * Kept for backward compatibility during migration.\n */\nexport const CMSListNodeSchemaBasic = ListNodeSchemaBasic;\n\n/**\n * Component node schema - discriminated union (now defined after dependencies)\n */\nComponentNodeSchema = z.union([\n HtmlNodeSchema,\n ComponentInstanceNodeSchema,\n SlotMarkerSchema,\n EmbedNodeSchema,\n LinkNodeSchema,\n LocaleListNodeSchema,\n ListNodeSchemaBasic,\n]);\n\n// Export ComponentNodeSchema\nexport { ComponentNodeSchema };\n\n// ============================================================================\n// Library Schemas\n// ============================================================================\n\n/**\n * Script load mode schema\n */\nexport const ScriptLoadModeSchema = z.enum(['async', 'defer']);\n\n/**\n * Library position schema\n */\nexport const LibraryPositionSchema = z.enum(['head', 'body-end']);\n\n/**\n * Script type schema\n */\nexport const ScriptTypeSchema = z.enum(['classic', 'module']);\n\n/**\n * JavaScript library schema\n */\nexport const JSLibraryConfigSchema = z.object({\n url: z.string().min(1),\n mode: ScriptLoadModeSchema.optional(),\n position: LibraryPositionSchema.optional(),\n type: ScriptTypeSchema.optional(),\n}).passthrough();\n\n/**\n * CSS library schema\n */\nexport const CSSLibraryConfigSchema = z.object({\n url: z.string().min(1),\n media: z.string().optional(),\n inline: z.boolean().optional(),\n}).passthrough();\n\n/**\n * Libraries config schema\n */\nexport const LibrariesConfigSchema = z.object({\n js: z.array(JSLibraryConfigSchema).optional(),\n css: z.array(CSSLibraryConfigSchema).optional(),\n}).passthrough();\n\n/**\n * Structured component definition schema\n */\nexport const StructuredComponentDefinitionSchema = z.object({\n interface: z.record(z.string(), PropDefinitionSchema).optional(),\n structure: ComponentNodeSchema.optional(),\n javascript: z.string().optional(),\n css: z.string().optional(),\n category: z.string().optional(),\n libraries: LibrariesConfigSchema.optional(),\n acceptsStyles: z.boolean().optional(),\n}).passthrough();\n\n/**\n * Component definition schema\n * Accepts both legacy format (with type/props/children) and new format (just component)\n * New format checked first since it's more common\n */\nexport const ComponentDefinitionSchema = z.union([\n // New format: { component: {...} }\n z.object({\n component: StructuredComponentDefinitionSchema,\n }).passthrough(),\n // Legacy format: { type, props?, children?, component }\n z.object({\n type: z.string(),\n props: z.record(z.string(), z.any()).optional(),\n children: z.array(z.any()).optional(),\n component: StructuredComponentDefinitionSchema,\n }).passthrough(),\n]);\n\n/**\n * I18n value schema - accepts either a string or an i18n object\n */\nconst I18nOrStringSchema = z.union([\n z.string(),\n z.object({\n _i18n: z.literal(true),\n }).passthrough(),\n]);\n\n/**\n * Library merge mode schema\n */\nexport const LibraryMergeModeSchema = z.enum(['extend', 'replace']);\n\n/**\n * Page libraries config schema (with merge mode)\n */\nexport const PageLibrariesConfigSchema = z.object({\n js: z.array(JSLibraryConfigSchema).optional(),\n css: z.array(CSSLibraryConfigSchema).optional(),\n mode: LibraryMergeModeSchema.optional(),\n}).passthrough();\n\n/**\n * Page metadata schema (base version without CMS - used internally)\n * Note: CMS fields added via PageMetaDataWithCMSSchema after CMS schemas are defined\n */\nconst CustomCodeConfigSchema = z.object({\n head: z.string().optional(),\n bodyStart: z.string().optional(),\n bodyEnd: z.string().optional(),\n}).passthrough();\n\nconst PageMetaDataBaseSchema = z.object({\n title: I18nOrStringSchema.optional(),\n description: I18nOrStringSchema.optional(),\n keywords: I18nOrStringSchema.optional(),\n ogTitle: I18nOrStringSchema.optional(),\n ogDescription: I18nOrStringSchema.optional(),\n ogImage: z.string().optional(),\n ogType: z.string().optional(),\n slugs: z.record(z.string(), z.string()).optional(),\n draft: z.boolean().optional(),\n libraries: PageLibrariesConfigSchema.optional(),\n customCode: CustomCodeConfigSchema.optional(),\n}).passthrough();\n\n// Temporary export for backward compatibility - will be replaced with full schema below\nexport const PageMetaDataSchema = PageMetaDataBaseSchema;\n\n/**\n * Line range schema for element line number tracking\n */\nexport const LineRangeSchema = z.object({\n startLine: z.number(),\n endLine: z.number(),\n});\n\n/**\n * JSON page schema\n * Requires at least one field to prevent empty objects from matching\n */\nexport const JSONPageSchema = z.object({\n components: z.record(z.string(), ComponentDefinitionSchema).optional(),\n root: ComponentNodeSchema.optional(),\n meta: PageMetaDataSchema.optional(),\n _lineMap: z.record(z.string(), LineRangeSchema).optional(),\n}).passthrough().refine((data) => {\n // Require at least one field to be present\n return data.meta !== undefined || data.components !== undefined || data.root !== undefined;\n}, {\n message: \"JSONPage must have at least one of: meta, components, or root\"\n});\n\n/**\n * Page data with component schema\n */\nexport const PageDataWithComponentSchema = z.object({\n component: z.object({\n structure: ComponentNodeSchema.optional(),\n interface: z.record(z.string(), PropDefinitionSchema).optional(),\n javascript: z.string().optional(),\n css: z.string().optional(),\n acceptsStyles: z.boolean().optional(),\n }).passthrough(),\n}).passthrough();\n\n/**\n * Page data schema - union of JSONPage and PageDataWithComponent\n * PageDataWithComponent checked first because it's more specific\n */\nexport const PageDataSchema = z.union([\n PageDataWithComponentSchema,\n JSONPageSchema,\n]);\n\n// ============================================================================\n// CMS Schemas\n// ============================================================================\n\n/**\n * CMS field type schema\n */\nexport const CMSFieldTypeSchema = z.enum([\n 'string', 'text', 'rich-text', 'number', 'boolean', 'image', 'file', 'date', 'select', 'reference'\n]);\n\n/**\n * CMS field definition schema\n */\nexport const CMSFieldDefinitionSchema = z.object({\n type: CMSFieldTypeSchema,\n required: z.boolean().optional(),\n default: z.unknown().optional(),\n label: z.string().optional(),\n description: z.string().optional(),\n options: z.array(z.string()).optional(),\n accept: z.string().optional(),\n collection: z.string().optional(),\n multiple: z.boolean().optional(),\n}).passthrough();\n\n/**\n * CMS client data strategy schema\n */\nexport const CMSClientDataStrategySchema = z.enum(['auto', 'inline', 'static']);\n\n/**\n * CMS client data config schema\n * Configures client-side data exposure for dynamic filtering\n */\nexport const CMSClientDataConfigSchema = z.object({\n enabled: z.boolean(),\n strategy: CMSClientDataStrategySchema,\n threshold: z.number().positive().optional(),\n fields: z.array(z.string()).optional(),\n}).passthrough();\n\n/**\n * CMS schema schema (defines collection structure)\n */\nexport const CMSSchemaSchema = z.object({\n id: z.string(),\n name: z.string(),\n slugField: z.string(),\n urlPattern: z.string(),\n fields: z.record(CMSFieldDefinitionSchema),\n clientData: CMSClientDataConfigSchema.optional(),\n}).passthrough();\n\n/**\n * CMS item schema (content entry, strict \u2014 used at publish/save time).\n */\nexport const CMSItemSchema = z.object({\n _id: z.string(),\n _slug: z.string().optional(),\n _filename: z.string().optional(),\n _createdAt: z.string().optional(),\n}).passthrough();\n\n/**\n * CMS draft item schema (loose \u2014 used at draft-write time).\n *\n * Drafts can be partial work-in-progress, so even system-managed identifiers\n * are optional at this stage. Strict validation runs when promoting the draft\n * to published (see `publishDraft` in `FileSystemCMSProvider`).\n */\nexport const CMSDraftItemSchema = z.object({\n _id: z.string().optional(),\n _slug: z.string().optional(),\n _filename: z.string().optional(),\n _createdAt: z.string().optional(),\n}).passthrough();\n\n/**\n * CMS filter condition schema\n */\nexport const CMSFilterConditionSchema = z.object({\n field: z.string(),\n operator: z.enum(['eq', 'neq', 'gt', 'gte', 'lt', 'lte', 'contains', 'in']).optional(),\n value: z.unknown(),\n});\n\n/**\n * CMS sort config schema\n */\nexport const CMSSortConfigSchema = z.object({\n field: z.string(),\n order: z.enum(['asc', 'desc']).optional(),\n});\n\n/**\n * CMSList query schema\n */\nexport const CMSListQuerySchema = z.object({\n collection: z.string(),\n filter: z.union([\n CMSFilterConditionSchema,\n z.array(CMSFilterConditionSchema),\n z.record(z.unknown()),\n ]).optional(),\n sort: z.union([CMSSortConfigSchema, z.array(CMSSortConfigSchema)]).optional(),\n limit: z.number().positive().optional(),\n offset: z.number().nonnegative().optional(),\n});\n\n/**\n * CMSList node schema - special built-in node for rendering CMS item lists\n * Children are repeated for each item with named context variables:\n * - {{<itemAs>.field}} - Access CMS item fields (e.g., {{post.title}})\n * - {{<itemAs>Index}}, {{<itemAs>First}}, {{<itemAs>Last}} - Position info\n * Legacy {{item.field}}, {{itemIndex}}, etc. still supported\n */\nexport const CMSListNodeSchema = z.object({\n type: z.literal('cms-list'),\n collection: z.string(),\n if: IfConditionSchema.optional(),\n itemAs: z.string().optional(),\n items: z.union([z.string(), z.array(z.string())]).optional(),\n filter: z.union([\n CMSFilterConditionSchema,\n z.array(CMSFilterConditionSchema),\n z.record(z.unknown()),\n ]).optional(),\n sort: z.union([CMSSortConfigSchema, z.array(CMSSortConfigSchema)]).optional(),\n limit: z.number().positive().optional(),\n offset: z.number().nonnegative().optional(),\n excludeCurrentItem: z.boolean().optional(),\n children: z.array(z.unknown()).optional(),\n}).passthrough();\n\n/**\n * Page CMS config schema (embedded in page meta)\n */\nexport const PageCmsConfigSchema = z.object({\n id: z.string(),\n name: z.string(),\n slugField: z.string(),\n urlPattern: z.string(),\n fields: z.record(CMSFieldDefinitionSchema),\n}).passthrough();\n\n/**\n * Page metadata schema with CMS support\n * Extends base schema with source and cms fields\n */\nexport const PageMetaDataWithCMSSchema = z.object({\n title: z.union([z.string(), z.object({ _i18n: z.literal(true) }).passthrough()]).optional(),\n description: z.union([z.string(), z.object({ _i18n: z.literal(true) }).passthrough()]).optional(),\n keywords: z.union([z.string(), z.object({ _i18n: z.literal(true) }).passthrough()]).optional(),\n ogTitle: z.union([z.string(), z.object({ _i18n: z.literal(true) }).passthrough()]).optional(),\n ogDescription: z.union([z.string(), z.object({ _i18n: z.literal(true) }).passthrough()]).optional(),\n ogImage: z.string().optional(),\n ogType: z.string().optional(),\n slugs: z.record(z.string(), z.string()).optional(),\n source: z.enum(['static', 'cms']).optional(),\n cms: PageCmsConfigSchema.optional(),\n draft: z.boolean().optional(),\n libraries: PageLibrariesConfigSchema.optional(),\n customCode: CustomCodeConfigSchema.optional(),\n}).passthrough();\n", "/**\n * Base Component Registry\n * Abstract base class for component registries\n * Provides common functionality for client and SSR registries\n */\n\nimport type { ComponentDefinition } from '../types';\n\n/**\n * Base registry class with common functionality\n */\nexport abstract class BaseComponentRegistry {\n protected registry: Record<string, ComponentDefinition> = {};\n private listeners: Set<() => void> = new Set();\n \n /**\n * Register a component with the given name\n */\n register(name: string, definition: ComponentDefinition): void {\n this.registry[name] = definition;\n this.notify();\n }\n \n /**\n * Get a component by name\n */\n get(name: string): ComponentDefinition | undefined {\n return this.registry[name];\n }\n \n /**\n * Check if a component exists\n */\n has(name: string): boolean {\n return name in this.registry;\n }\n \n /**\n * Clear all registered components\n */\n clear(): void {\n this.registry = {};\n this.notify();\n }\n \n /**\n * Merge components into the registry\n * Existing components with the same name will be overwritten\n */\n merge(components: Record<string, ComponentDefinition>): void {\n Object.assign(this.registry, components);\n this.notify();\n }\n \n /**\n * Get all registered components\n */\n getAll(): Record<string, ComponentDefinition> {\n return { ...this.registry };\n }\n \n /**\n * Get list of registered component names\n */\n getNames(): string[] {\n return Object.keys(this.registry);\n }\n \n /**\n * Remove a component by name\n */\n remove(name: string): boolean {\n if (this.has(name)) {\n delete this.registry[name];\n this.notify();\n return true;\n }\n return false;\n }\n\n /**\n * Subscribe to registry changes. Returns an unsubscribe function.\n */\n subscribe(listener: () => void): () => void {\n this.listeners.add(listener);\n return () => {\n this.listeners.delete(listener);\n };\n }\n\n protected notify(): void {\n for (const listener of this.listeners) {\n try {\n listener();\n } catch (err) {\n }\n }\n }\n}\n\n", "/**\n * Client Component Registry\n * Extends base registry with client-specific functionality\n */\n\nimport { BaseComponentRegistry } from './ComponentRegistry';\nimport type { ComponentDefinition } from '../types';\n\nexport class ClientRegistry extends BaseComponentRegistry {\n /**\n * Client-specific methods can be added here\n * For now, it's the same as base registry\n */\n}\n\n", "/**\n * SSR Component Registry\n * Extends base registry with SSR-specific functionality\n */\n\nimport { BaseComponentRegistry } from './ComponentRegistry';\nimport type { ComponentDefinition } from '../types';\n\nexport class SSRRegistry extends BaseComponentRegistry {\n /**\n * SSR-specific methods can be added here\n * For now, it's the same as base registry\n */\n}\n\n", "/**\n * Registry Manager\n * Manages multiple component registries (client, SSR, etc.)\n */\n\nimport type { ComponentDefinition } from '../types';\nimport { ClientRegistry } from './ClientRegistry';\nimport { SSRRegistry } from './SSRRegistry';\n\nexport class RegistryManager {\n private clientRegistry: ClientRegistry;\n private ssrRegistry: SSRRegistry;\n\n constructor() {\n this.clientRegistry = new ClientRegistry();\n this.ssrRegistry = new SSRRegistry();\n }\n\n /**\n * Get the client registry\n */\n getClient(): ClientRegistry {\n return this.clientRegistry;\n }\n\n /**\n * Get the SSR registry\n */\n getSSR(): SSRRegistry {\n return this.ssrRegistry;\n }\n\n /**\n * Sync components from one registry to another\n */\n sync(from: 'client' | 'ssr', to: 'client' | 'ssr'): void {\n const source = from === 'client' ? this.clientRegistry : this.ssrRegistry;\n const target = to === 'client' ? this.clientRegistry : this.ssrRegistry;\n \n const components = source.getAll();\n target.merge(components);\n }\n\n /**\n * Register a component in all registries\n */\n registerAll(name: string, definition: ComponentDefinition): void {\n this.clientRegistry.register(name, definition);\n this.ssrRegistry.register(name, definition);\n }\n\n /**\n * Clear all registries\n */\n clearAll(): void {\n this.clientRegistry.clear();\n this.ssrRegistry.clear();\n }\n}\n\n", "/**\n * Base Node Type Registry\n * Abstract base class for node type registries\n * Provides common functionality for client and SSR registries\n */\n\nimport type { ComponentNode } from '../types/nodes';\nimport type { NodeTypeDefinition, NodeCategory, TreeIcon } from './NodeTypeDefinition';\n\n/**\n * Node label info returned by getNodeLabel\n */\nexport interface NodeLabelInfo {\n label: string;\n icon: TreeIcon;\n}\n\n/**\n * Base registry class with common functionality\n */\nexport abstract class BaseNodeTypeRegistry {\n protected registry: Map<string, NodeTypeDefinition> = new Map();\n private listeners: Set<() => void> = new Set();\n private nodeTypeCache: WeakMap<object, NodeTypeDefinition | null> = new WeakMap();\n\n /**\n * Register a node type definition\n */\n register(definition: NodeTypeDefinition): void {\n if (!definition.type) {\n throw new Error('Node type definition must have a type');\n }\n this.registry.set(definition.type, definition);\n this.nodeTypeCache = new WeakMap(); // Clear cache on registration\n this.notify();\n }\n\n /**\n * Register multiple node type definitions at once\n */\n registerAll(definitions: NodeTypeDefinition[]): void {\n for (const definition of definitions) {\n if (!definition.type) {\n throw new Error('Node type definition must have a type');\n }\n this.registry.set(definition.type, definition);\n }\n this.nodeTypeCache = new WeakMap(); // Clear cache on registration\n this.notify();\n }\n\n /**\n * Get a node type definition by type string\n */\n get(type: string): NodeTypeDefinition | undefined {\n return this.registry.get(type);\n }\n\n /**\n * Check if a node type is registered\n */\n has(type: string): boolean {\n return this.registry.has(type);\n }\n\n /**\n * Get all registered node types\n */\n getAll(): NodeTypeDefinition[] {\n return Array.from(this.registry.values());\n }\n\n /**\n * Get node types by category\n */\n getByCategory(category: NodeCategory): NodeTypeDefinition[] {\n return this.getAll().filter((def) => def.category === category);\n }\n\n /**\n * Get list of registered type names\n */\n getNames(): string[] {\n return Array.from(this.registry.keys());\n }\n\n /**\n * Find node type definition by node object using type guards\n * Uses WeakMap caching for performance\n */\n findByNode(node: ComponentNode): NodeTypeDefinition | undefined {\n if (!node || typeof node !== 'object') {\n return undefined;\n }\n\n // Check cache first\n const cached = this.nodeTypeCache.get(node);\n if (cached !== undefined) {\n return cached || undefined;\n }\n\n // Linear search through registered types\n for (const definition of this.registry.values()) {\n if (definition.typeGuard(node)) {\n this.nodeTypeCache.set(node, definition);\n return definition;\n }\n }\n\n // Cache miss result too\n this.nodeTypeCache.set(node, null);\n return undefined;\n }\n\n /**\n * Check if a node matches a specific type\n * More efficient than findByNode when you know the type\n */\n isType<T extends ComponentNode>(node: unknown, type: string): node is T {\n const definition = this.registry.get(type);\n if (!definition) {\n return false;\n }\n return definition.typeGuard(node);\n }\n\n /**\n * Get node label info for tree display\n */\n getNodeLabel(node: ComponentNode): NodeLabelInfo | undefined {\n const definition = this.findByNode(node);\n if (!definition) {\n return undefined;\n }\n return {\n label: definition.treeDisplay.getLabel(node),\n icon: definition.treeDisplay.icon,\n };\n }\n\n /**\n * Get default node for a type\n */\n createDefault(type: string): ComponentNode | undefined {\n const definition = this.registry.get(type);\n if (!definition) {\n return undefined;\n }\n return definition.defaultFactory();\n }\n\n /**\n * Remove a node type by type string\n */\n remove(type: string): boolean {\n if (this.has(type)) {\n this.registry.delete(type);\n this.nodeTypeCache = new WeakMap(); // Clear cache\n this.notify();\n return true;\n }\n return false;\n }\n\n /**\n * Clear all registered node types\n */\n clear(): void {\n this.registry.clear();\n this.nodeTypeCache = new WeakMap();\n this.notify();\n }\n\n /**\n * Subscribe to registry changes. Returns an unsubscribe function.\n */\n subscribe(listener: () => void): () => void {\n this.listeners.add(listener);\n return () => {\n this.listeners.delete(listener);\n };\n }\n\n /**\n * Get the number of registered node types\n */\n get size(): number {\n return this.registry.size;\n }\n\n protected notify(): void {\n for (const listener of this.listeners) {\n try {\n listener();\n } catch {\n // Silent fail - don't let one listener break others\n }\n }\n }\n}\n", "/**\n * Client Node Type Registry\n * Registry specialized for client-side (React) rendering\n */\n\nimport type { ReactElement } from 'react';\nimport type { ComponentNode } from '../types/nodes';\nimport { BaseNodeTypeRegistry } from './BaseNodeTypeRegistry';\nimport type { ClientRenderContext } from './NodeTypeDefinition';\n\n/**\n * Client-side node type registry\n * Extends base registry with client rendering capabilities\n */\nexport class ClientNodeTypeRegistry extends BaseNodeTypeRegistry {\n /**\n * Render a node using the registered renderer\n * Returns null if no renderer is found for the node type\n */\n renderNode(node: ComponentNode, context: ClientRenderContext): ReactElement | null {\n const definition = this.findByNode(node);\n if (!definition) {\n return null;\n }\n return definition.clientRenderer(node as any, context);\n }\n\n /**\n * Check if a node can be rendered by this registry\n */\n canRender(node: ComponentNode): boolean {\n return this.findByNode(node) !== undefined;\n }\n}\n", "/**\n * SSR Node Type Registry\n * Registry specialized for server-side rendering (HTML strings)\n */\n\nimport type { ComponentNode } from '../types/nodes';\nimport { BaseNodeTypeRegistry } from './BaseNodeTypeRegistry';\nimport type { SSRRenderContext } from './NodeTypeDefinition';\n\n/**\n * Server-side node type registry\n * Extends base registry with SSR rendering capabilities\n */\nexport class SSRNodeTypeRegistry extends BaseNodeTypeRegistry {\n /**\n * Render a node to HTML string using the registered renderer\n * Returns empty string if no renderer is found for the node type\n */\n renderNode(node: ComponentNode, context: SSRRenderContext): string {\n const definition = this.findByNode(node);\n if (!definition) {\n return '';\n }\n return definition.ssrRenderer(node as any, context);\n }\n\n /**\n * Check if a node can be rendered by this registry\n */\n canRender(node: ComponentNode): boolean {\n return this.findByNode(node) !== undefined;\n }\n}\n", "/**\n * Node Type Manager\n * Global singleton managing both client and SSR registries\n */\n\nimport { ClientNodeTypeRegistry } from './ClientNodeTypeRegistry';\nimport { SSRNodeTypeRegistry } from './SSRNodeTypeRegistry';\nimport type { NodeTypeDefinition } from './NodeTypeDefinition';\n\n/**\n * Manages both client and SSR node type registries\n * Ensures both registries stay in sync\n */\nexport class NodeTypeManager {\n private clientRegistry: ClientNodeTypeRegistry;\n private ssrRegistry: SSRNodeTypeRegistry;\n\n constructor() {\n this.clientRegistry = new ClientNodeTypeRegistry();\n this.ssrRegistry = new SSRNodeTypeRegistry();\n }\n\n /**\n * Get the client-side registry\n */\n getClient(): ClientNodeTypeRegistry {\n return this.clientRegistry;\n }\n\n /**\n * Get the SSR registry\n */\n getSSR(): SSRNodeTypeRegistry {\n return this.ssrRegistry;\n }\n\n /**\n * Register a node type in both registries\n */\n register(definition: NodeTypeDefinition): void {\n this.clientRegistry.register(definition);\n this.ssrRegistry.register(definition);\n }\n\n /**\n * Register multiple node types in both registries\n */\n registerAll(definitions: NodeTypeDefinition[]): void {\n this.clientRegistry.registerAll(definitions);\n this.ssrRegistry.registerAll(definitions);\n }\n\n /**\n * Check if a node type is registered\n */\n has(type: string): boolean {\n return this.clientRegistry.has(type);\n }\n\n /**\n * Get a node type definition\n */\n get(type: string): NodeTypeDefinition | undefined {\n return this.clientRegistry.get(type);\n }\n\n /**\n * Get all registered node types\n */\n getAll(): NodeTypeDefinition[] {\n return this.clientRegistry.getAll();\n }\n\n /**\n * Get list of registered type names\n */\n getNames(): string[] {\n return this.clientRegistry.getNames();\n }\n\n /**\n * Clear both registries\n */\n clear(): void {\n this.clientRegistry.clear();\n this.ssrRegistry.clear();\n }\n}\n\n/**\n * Global singleton node type manager\n * Use this instance throughout the application\n */\nexport const globalNodeTypeManager = new NodeTypeManager();\n", "/**\n * defineNodeType Helper\n * Type-safe helper function to create node type definitions\n */\n\nimport type { ComponentNode } from '../types/nodes';\nimport type {\n NodeTypeDefinition,\n NodeTypeDefinitionInput,\n NodeCapabilities,\n} from './NodeTypeDefinition';\n\n/**\n * Default capabilities for node types\n */\nconst DEFAULT_CAPABILITIES: NodeCapabilities = {\n canHaveChildren: true,\n canHaveStyle: true,\n canHaveAttributes: true,\n canBeNested: true,\n requiresProps: [],\n};\n\n/**\n * Create a node type definition with sensible defaults\n * Provides type safety and validation at definition time\n */\nexport function defineNodeType<TNode extends ComponentNode>(\n input: NodeTypeDefinitionInput<TNode>\n): NodeTypeDefinition<TNode> {\n // Validate required fields\n if (!input.type) {\n throw new Error('Node type definition must have a type');\n }\n if (!input.displayName) {\n throw new Error('Node type definition must have a displayName');\n }\n if (!input.schema) {\n throw new Error('Node type definition must have a schema');\n }\n if (!input.typeGuard) {\n throw new Error('Node type definition must have a typeGuard');\n }\n if (!input.clientRenderer) {\n throw new Error('Node type definition must have a clientRenderer');\n }\n if (!input.ssrRenderer) {\n throw new Error('Node type definition must have an ssrRenderer');\n }\n if (!input.treeDisplay) {\n throw new Error('Node type definition must have treeDisplay');\n }\n if (!input.defaultFactory) {\n throw new Error('Node type definition must have a defaultFactory');\n }\n\n return {\n type: input.type,\n displayName: input.displayName,\n category: input.category ?? 'core',\n schema: input.schema,\n typeGuard: input.typeGuard,\n clientRenderer: input.clientRenderer,\n ssrRenderer: input.ssrRenderer,\n treeDisplay: input.treeDisplay,\n propsEditor: input.propsEditor,\n defaultFactory: input.defaultFactory,\n capabilities: {\n ...DEFAULT_CAPABILITIES,\n ...input.capabilities,\n },\n };\n}\n", "/**\n * createNodeType Helper\n * Simplified API for creating node type definitions with auto-generated type guards\n * and inferred TypeScript types from Zod schemas\n */\n\nimport type { ReactElement } from 'react';\nimport type { ZodType, z } from 'zod';\nimport type {\n NodeTypeDefinition,\n NodeCapabilities,\n NodeCategory,\n TreeIcon,\n ClientRenderContext,\n SSRRenderContext,\n EditableField,\n} from './NodeTypeDefinition';\n\n/**\n * Default capabilities for node types\n */\nconst DEFAULT_CAPABILITIES: NodeCapabilities = {\n canHaveChildren: true,\n canHaveStyle: true,\n canHaveAttributes: true,\n canBeNested: true,\n requiresProps: [],\n};\n\n/**\n * Create a type guard function from a type string value\n * Automatically generates the type guard based on the node's type field\n */\nfunction createTypeGuard<T>(typeValue: string) {\n return (node: unknown): node is T =>\n node !== null &&\n typeof node === 'object' &&\n 'type' in node &&\n (node as { type: unknown }).type === typeValue;\n}\n\n/**\n * Input configuration for createNodeType\n * Schema is the single source of truth - TypeScript types are inferred from it\n */\nexport interface CreateNodeTypeInput<TSchema extends ZodType> {\n /** The type discriminator value (e.g., 'image', 'video') */\n type: string;\n\n /** Human-readable display name (e.g., 'Image', 'Video') */\n displayName: string;\n\n /** Category for grouping in command palette */\n category?: NodeCategory;\n\n /** Zod schema - single source of truth for validation and type inference */\n schema: TSchema;\n\n /** Default values for creating new nodes (type field is auto-added) */\n defaultValues: Omit<Partial<z.infer<TSchema>>, 'type'>;\n\n /** Tree display configuration */\n treeDisplay: {\n icon: TreeIcon;\n getLabel?: (node: z.infer<TSchema>) => string;\n };\n\n /** Client-side React renderer */\n clientRenderer: (node: z.infer<TSchema>, context: ClientRenderContext) => ReactElement | null;\n\n /** Server-side HTML string renderer */\n ssrRenderer: (node: z.infer<TSchema>, context: SSRRenderContext) => string;\n\n /** Optional capabilities override */\n capabilities?: Partial<NodeCapabilities>;\n\n /** Optional custom props editor component */\n propsEditor?: React.ComponentType<{\n node: z.infer<TSchema>;\n selectedPath: string | null;\n onPropChange?: (path: string, propName: string, newValue: unknown) => void;\n themeColors?: Record<string, string>;\n }>;\n\n /** Editable fields for auto-generated props editor UI */\n editableFields?: EditableField[];\n}\n\n/**\n * Create a complete node type definition from a simplified configuration\n *\n * Benefits over defineNodeType:\n * - Type guards are auto-generated from the type string\n * - Default factory is auto-generated from defaultValues\n * - TypeScript types are inferred from the Zod schema\n * - Less boilerplate, single source of truth\n *\n * @example\n * ```ts\n * const schema = z.object({\n * type: z.literal('image'),\n * src: z.string(),\n * alt: z.string().optional(),\n * });\n *\n * export type ImageNode = z.infer<typeof schema>;\n * export const ImageNodeSchema = schema;\n *\n * export const ImageNodeType = createNodeType({\n * type: 'image',\n * displayName: 'Image',\n * schema,\n * defaultValues: { src: '', alt: '' },\n * treeDisplay: { icon: 'IMAGE' },\n * clientRenderer: (node, ctx) => h('img', { src: node.src, alt: node.alt }),\n * ssrRenderer: (node, ctx) => `<img src=\"${node.src}\" alt=\"${node.alt || ''}\" />`,\n * });\n * ```\n */\nexport function createNodeType<TSchema extends ZodType>(\n input: CreateNodeTypeInput<TSchema>\n): NodeTypeDefinition<z.infer<TSchema>> {\n type TNode = z.infer<TSchema>;\n\n // Validate required fields\n if (!input.type) {\n throw new Error('Node type definition must have a type');\n }\n if (!input.displayName) {\n throw new Error('Node type definition must have a displayName');\n }\n if (!input.schema) {\n throw new Error('Node type definition must have a schema');\n }\n if (!input.clientRenderer) {\n throw new Error('Node type definition must have a clientRenderer');\n }\n if (!input.ssrRenderer) {\n throw new Error('Node type definition must have an ssrRenderer');\n }\n if (!input.treeDisplay) {\n throw new Error('Node type definition must have treeDisplay');\n }\n\n return {\n type: input.type,\n displayName: input.displayName,\n category: input.category ?? 'core',\n schema: input.schema as ZodType<TNode>,\n\n // Auto-generated type guard\n typeGuard: createTypeGuard<TNode>(input.type),\n\n // Auto-generated default factory\n defaultFactory: (): TNode => ({\n type: input.type,\n ...input.defaultValues,\n } as TNode),\n\n treeDisplay: {\n icon: input.treeDisplay.icon,\n getLabel: input.treeDisplay.getLabel ?? (() => input.displayName),\n },\n\n clientRenderer: input.clientRenderer,\n ssrRenderer: input.ssrRenderer,\n propsEditor: input.propsEditor,\n editableFields: input.editableFields,\n\n capabilities: {\n ...DEFAULT_CAPABILITIES,\n ...input.capabilities,\n },\n };\n}\n", "/**\n * Generic Field Type Factories for Node Types\n *\n * Configurable field factories that can be used for any property.\n * Each factory creates an EditableField with the specified configuration.\n *\n * @example\n * import { textField, urlField, imageField, booleanField, selectField } from '../fieldPresets';\n *\n * editableFields: [\n * urlField({ name: 'src', label: 'Video Source', required: true }),\n * imageField({ name: 'poster', label: 'Poster Image' }),\n * selectField({ name: 'preload', label: 'Preload', options: ['auto', 'metadata', 'none'] }),\n * booleanField({ name: 'controls', label: 'Show Controls', group: 'Playback' }),\n * ],\n */\n\nimport type { EditableField } from './NodeTypeDefinition';\n\n// ============================================\n// Field Configuration Types\n// ============================================\n\ninterface BaseFieldConfig {\n name: string;\n label: string;\n required?: boolean;\n group?: string;\n}\n\ninterface TextFieldConfig extends BaseFieldConfig {\n placeholder?: string;\n}\n\ninterface SelectFieldConfig extends BaseFieldConfig {\n options: string[];\n}\n\n// ============================================\n// Generic Field Type Factories\n// ============================================\n\n/** Text input field */\nexport const textField = (config: TextFieldConfig): EditableField => ({\n name: config.name,\n label: config.label,\n type: 'string',\n required: config.required,\n placeholder: config.placeholder,\n group: config.group,\n});\n\n/** URL input field */\nexport const urlField = (config: TextFieldConfig): EditableField => ({\n name: config.name,\n label: config.label,\n type: 'url',\n required: config.required,\n placeholder: config.placeholder ?? 'https://...',\n group: config.group,\n});\n\n/** Image URL field (can add picker UI later) */\nexport const imageField = (config: BaseFieldConfig): EditableField => ({\n name: config.name,\n label: config.label,\n type: 'url',\n required: config.required,\n placeholder: 'https://example.com/image.jpg',\n group: config.group,\n});\n\n/** Number input field */\nexport const numberField = (config: TextFieldConfig): EditableField => ({\n name: config.name,\n label: config.label,\n type: 'number',\n required: config.required,\n placeholder: config.placeholder,\n group: config.group,\n});\n\n/** Boolean toggle field */\nexport const booleanField = (config: BaseFieldConfig): EditableField => ({\n name: config.name,\n label: config.label,\n type: 'boolean',\n group: config.group,\n});\n\n/** Select dropdown field */\nexport const selectField = (config: SelectFieldConfig): EditableField => ({\n name: config.name,\n label: config.label,\n type: 'select',\n options: config.options,\n required: config.required,\n group: config.group,\n});\n\n/** Textarea field (multiline text) */\nexport const textareaField = (config: TextFieldConfig): EditableField => ({\n name: config.name,\n label: config.label,\n type: 'text',\n required: config.required,\n placeholder: config.placeholder,\n group: config.group,\n});\n", "/**\n * HTML Node Type Definition\n * HTML element nodes (div, span, header, etc.)\n */\n\nimport { z } from 'zod';\nimport { createElement as h } from 'react';\nimport { StyleValueSchema, InteractiveStylesSchema, IfConditionSchema } from '../../validation/schemas';\nimport { createNodeType } from '../createNodeType';\n\n// Forward reference for ComponentNode schema (recursive)\nconst ComponentNodeSchemaRef: z.ZodType<any> = z.lazy(() => z.any());\n\n// Schema is the SINGLE source of truth\nconst HtmlNodeSchemaInternal = z.object({\n type: z.literal('node'),\n tag: z.string(),\n label: z.string().optional(), // Custom label displayed in structure tree\n if: IfConditionSchema.optional(), // Conditional rendering - skip node when false\n style: StyleValueSchema.optional(),\n interactiveStyles: InteractiveStylesSchema.optional(), // Interactive CSS rules (hover, active, etc.)\n generateElementClass: z.boolean().optional(), // Generate element class without styles (for custom CSS)\n attributes: z.record(z.string(), z.union([z.string(), z.number(), z.boolean()])).optional(),\n props: z.record(z.string(), z.any()).optional(), // Backward compatibility\n children: z.union([\n z.array(z.union([ComponentNodeSchemaRef, z.string()])),\n z.string(),\n ]).optional(),\n}).passthrough();\n\n// TypeScript type inferred from schema\nexport type HtmlNode = z.infer<typeof HtmlNodeSchemaInternal>;\n\n// Export schema for validation/schemas.ts\nexport const HtmlNodeSchema = HtmlNodeSchemaInternal;\n\nexport const HtmlNodeType = createNodeType({\n type: 'node',\n displayName: 'HTML Element',\n category: 'core',\n schema: HtmlNodeSchemaInternal,\n\n defaultValues: {\n tag: 'div',\n style: { base: {} },\n children: [],\n },\n\n treeDisplay: {\n icon: 'HTML_ELEMENT',\n getLabel: (node) => node.tag,\n },\n\n clientRenderer: (node, context) => {\n const props: Record<string, any> = { key: context.key };\n\n // Prevent form submission in editor\n if (node.tag === 'form') {\n props.onSubmit = (e: React.FormEvent) => e.preventDefault();\n }\n\n // Void elements cannot have children\n const voidElements = ['img', 'br', 'hr', 'input', 'meta', 'link', 'area', 'base', 'col', 'embed', 'param', 'source', 'track', 'wbr'];\n if (voidElements.includes(node.tag.toLowerCase())) {\n return h(node.tag, props);\n }\n\n const children = context.buildChildren(\n node.children as any,\n context.elementPath,\n context.parentComponentName,\n context.componentContext\n );\n\n return h(node.tag, props, children);\n },\n\n ssrRenderer: (node, context) => {\n const childrenHTML = context.renderChildren(node.children as any, context);\n // Void elements don't have closing tags\n const voidElements = ['img', 'br', 'hr', 'input', 'meta', 'link', 'area', 'base', 'col', 'embed', 'param', 'source', 'track', 'wbr'];\n if (voidElements.includes(node.tag.toLowerCase())) {\n return `<${node.tag} />`;\n }\n return `<${node.tag}>${childrenHTML}</${node.tag}>`;\n },\n\n capabilities: {\n canHaveChildren: true,\n requiresProps: ['tag'],\n },\n});\n", "/**\n * Component Instance Node Type Definition\n * Instances of registered components\n */\n\nimport { z } from 'zod';\nimport { createElement as h } from 'react';\nimport { StyleValueSchema, InteractiveStylesSchema, IfConditionSchema } from '../../validation/schemas';\nimport { createNodeType } from '../createNodeType';\n\n// Forward reference for ComponentNode schema (recursive)\nconst ComponentNodeSchemaRef: z.ZodType<any> = z.lazy(() => z.any());\n\n// Schema is the SINGLE source of truth\nconst ComponentInstanceNodeSchemaInternal = z.object({\n type: z.literal('component'),\n component: z.string(),\n label: z.string().optional(), // Custom label displayed in structure tree\n if: IfConditionSchema.optional(), // Conditional rendering - skip node when false\n props: z.record(z.string(), z.any()).optional(),\n style: StyleValueSchema.optional(),\n interactiveStyles: InteractiveStylesSchema.optional(), // Interactive CSS rules (hover, active, etc.)\n generateElementClass: z.boolean().optional(), // Generate element class without styles (for custom CSS)\n attributes: z.record(z.string(), z.union([z.string(), z.number(), z.boolean()])).optional(),\n children: z.union([\n z.array(z.union([ComponentNodeSchemaRef, z.string()])),\n z.string(),\n ]).optional(),\n}).passthrough();\n\n// TypeScript type inferred from schema\nexport type ComponentInstanceNode = z.infer<typeof ComponentInstanceNodeSchemaInternal>;\n\n// Export schema for validation/schemas.ts\nexport const ComponentInstanceNodeSchema = ComponentInstanceNodeSchemaInternal;\n\nexport const ComponentInstanceNodeType = createNodeType({\n type: 'component',\n displayName: 'Component',\n category: 'core',\n schema: ComponentInstanceNodeSchemaInternal,\n\n defaultValues: {\n component: '',\n props: {},\n style: { base: {} },\n children: [],\n },\n\n treeDisplay: {\n icon: 'COMPONENT',\n getLabel: (node) => node.component,\n },\n\n clientRenderer: (node, context) => {\n const definition = context.getComponentDefinition(node.component);\n if (!definition) {\n return h('div', { key: context.key }, `[Unknown component: ${node.component}]`);\n }\n return h('div', { key: context.key }, `[Component: ${node.component}]`);\n },\n\n ssrRenderer: (node, context) => {\n const definition = context.getComponentDefinition(node.component);\n if (!definition) {\n return `<!-- Unknown component: ${context.escapeHtml(node.component)} -->`;\n }\n return `<!-- Component: ${context.escapeHtml(node.component)} -->`;\n },\n\n capabilities: {\n canHaveChildren: true,\n requiresProps: ['component'],\n },\n});\n", "/**\n * Slot Marker Node Type Definition\n * Indicates where instance children should be placed in a component\n */\n\nimport { z } from 'zod';\nimport { createNodeType } from '../createNodeType';\n\n// Schema is the SINGLE source of truth\n// Note: default uses z.any() to avoid circular reference with ComponentNodeSchema\n// Full validation is done via the schema in validation/schemas.ts\nconst SlotMarkerSchemaInternal = z.object({\n type: z.literal('slot'),\n default: z.union([\n z.array(z.any()),\n z.string(),\n ]).optional(),\n}).passthrough();\n\n// TypeScript type inferred from schema\nexport type SlotMarker = z.infer<typeof SlotMarkerSchemaInternal>;\n\n// Export schema for validation/schemas.ts\nexport const SlotMarkerSchema = SlotMarkerSchemaInternal;\n\nexport const SlotMarkerType = createNodeType({\n type: 'slot',\n displayName: 'Slot',\n category: 'special',\n schema: SlotMarkerSchemaInternal,\n\n defaultValues: {},\n\n treeDisplay: {\n icon: 'SLOT_MARKER',\n getLabel: () => 'slot',\n },\n\n clientRenderer: (_node, _context) => {\n // Slot markers are replaced with instance children during component rendering\n return null;\n },\n\n ssrRenderer: (_node, _context) => {\n // Slot markers are replaced with instance children during component rendering\n return '';\n },\n\n capabilities: {\n canHaveChildren: false,\n canHaveStyle: false,\n canHaveAttributes: false,\n requiresProps: [],\n },\n});\n", "/**\n * Embed Node Type Definition\n * Renders custom HTML/SVG content\n */\n\nimport { z } from 'zod';\nimport { createElement as h } from 'react';\nimport { StyleValueSchema, InteractiveStylesSchema, IfConditionSchema, HtmlMappingSchema } from '../../validation/schemas';\nimport { createNodeType } from '../createNodeType';\nimport { textareaField } from '../fieldPresets';\n\n// Schema is the SINGLE source of truth\nconst EmbedNodeSchemaInternal = z.object({\n type: z.literal('embed'),\n html: z.union([z.string(), HtmlMappingSchema]),\n label: z.string().optional(), // Custom label displayed in structure tree\n if: IfConditionSchema.optional(), // Conditional rendering - skip node when false\n style: StyleValueSchema.optional(),\n interactiveStyles: InteractiveStylesSchema.optional(), // Interactive CSS rules (hover, active, etc.)\n generateElementClass: z.boolean().optional(), // Generate element class without styles (for custom CSS)\n attributes: z.record(z.string(), z.union([z.string(), z.number(), z.boolean()])).optional(),\n}).passthrough();\n\n// TypeScript type inferred from schema\nexport type EmbedNode = z.infer<typeof EmbedNodeSchemaInternal>;\n\n// Export schema for validation/schemas.ts\nexport const EmbedNodeSchema = EmbedNodeSchemaInternal;\n\nexport const EmbedNodeType = createNodeType({\n type: 'embed',\n displayName: 'Embed',\n category: 'content',\n schema: EmbedNodeSchemaInternal,\n\n defaultValues: {\n html: '',\n style: { base: {} },\n },\n\n treeDisplay: {\n icon: 'HTML_ELEMENT',\n getLabel: () => 'Embed',\n },\n\n editableFields: [\n textareaField({ name: 'html', label: 'HTML Content', required: true, placeholder: '<svg>...</svg>' }),\n ],\n\n clientRenderer: (node, context) => {\n const htmlContent = typeof node.html === 'string' ? node.html : '';\n return h('div', {\n key: context.key,\n dangerouslySetInnerHTML: { __html: htmlContent },\n });\n },\n\n ssrRenderer: (node, _context) => {\n const htmlContent = typeof node.html === 'string' ? node.html : '';\n return `<div>${htmlContent}</div>`;\n },\n\n capabilities: {\n canHaveChildren: false,\n requiresProps: ['html'],\n },\n});\n", "/**\n * Link Node Type Definition\n * Renders as div in editor, <a> tag in SSR\n */\n\nimport { z } from 'zod';\nimport { createElement as h } from 'react';\nimport { StyleValueSchema, InteractiveStylesSchema, LinkMappingSchema, IfConditionSchema } from '../../validation/schemas';\nimport { createNodeType } from '../createNodeType';\nimport { urlField } from '../fieldPresets';\n\n// Forward reference for ComponentNode schema (recursive)\n// This will be resolved when schemas.ts imports this and builds the union\nconst ComponentNodeSchemaRef: z.ZodType<any> = z.lazy(() => z.any());\n\n// Schema is the SINGLE source of truth\nconst LinkNodeSchemaInternal = z.object({\n type: z.literal('link'),\n href: z.union([z.string(), LinkMappingSchema]),\n label: z.string().optional(), // Custom label displayed in structure tree\n if: IfConditionSchema.optional(), // Conditional rendering - skip node when false\n style: StyleValueSchema.optional(),\n interactiveStyles: InteractiveStylesSchema.optional(), // Interactive CSS rules (hover, active, etc.)\n generateElementClass: z.boolean().optional(), // Generate element class without styles (for custom CSS)\n attributes: z.record(z.string(), z.union([z.string(), z.number(), z.boolean()])).optional(),\n children: z.union([\n z.array(z.union([ComponentNodeSchemaRef, z.string()])),\n z.string(),\n ]).optional(),\n}).passthrough();\n\n// TypeScript type inferred from schema\nexport type LinkNode = z.infer<typeof LinkNodeSchemaInternal>;\n\n// Export schema for validation/schemas.ts\nexport const LinkNodeSchema = LinkNodeSchemaInternal;\n\nexport const LinkNodeType = createNodeType({\n type: 'link',\n displayName: 'Link',\n category: 'content',\n schema: LinkNodeSchemaInternal,\n\n defaultValues: {\n href: '#',\n style: { base: {} },\n children: [],\n },\n\n treeDisplay: {\n icon: 'LINK',\n getLabel: () => 'Link',\n },\n\n editableFields: [\n urlField({ name: 'href', label: 'Link URL', required: true }),\n ],\n\n clientRenderer: (node, context) => {\n const children = context.buildChildren(\n node.children as any,\n context.elementPath,\n context.parentComponentName,\n context.componentContext\n );\n return h('div', { key: context.key }, children);\n },\n\n ssrRenderer: (node, context) => {\n const href = typeof node.href === 'string' ? node.href : '#';\n const childrenHTML = context.renderChildren(node.children as any, context);\n return `<a href=\"${context.escapeHtml(href)}\" class=\"olink\">${childrenHTML}</a>`;\n },\n\n capabilities: {\n canHaveChildren: true,\n requiresProps: ['href'],\n },\n});\n", "/**\n * Locale List Node Type Definition\n * Renders locale switcher links\n */\n\nimport { z } from 'zod';\nimport { createElement as h } from 'react';\nimport { StyleValueSchema, InteractiveStylesSchema, IfConditionSchema } from '../../validation/schemas';\nimport { createNodeType } from '../createNodeType';\n\n// Schema is the SINGLE source of truth\nconst LocaleListNodeSchemaInternal = z.object({\n type: z.literal('locale-list'),\n label: z.string().optional(), // Custom label displayed in structure tree\n if: IfConditionSchema.optional(), // Conditional rendering - skip node when false\n style: StyleValueSchema.optional(),\n itemStyle: StyleValueSchema.optional(),\n activeItemStyle: StyleValueSchema.optional(),\n separatorStyle: StyleValueSchema.optional(),\n showCurrent: z.boolean().optional(),\n showSeparator: z.boolean().optional(),\n showFlag: z.boolean().optional(),\n flagStyle: StyleValueSchema.optional(),\n interactiveStyles: InteractiveStylesSchema.optional(), // Interactive CSS rules (hover, active, etc.)\n generateElementClass: z.boolean().optional(), // Generate element class without styles (for custom CSS)\n displayType: z.enum(['code', 'name', 'nativeName']).optional(), // How to display locale text\n attributes: z.record(z.string(), z.union([z.string(), z.number(), z.boolean()])).optional(),\n}).passthrough();\n\n// TypeScript type inferred from schema\nexport type LocaleListNode = z.infer<typeof LocaleListNodeSchemaInternal>;\n\n// Export schema for validation/schemas.ts\nexport const LocaleListNodeSchema = LocaleListNodeSchemaInternal;\n\nexport const LocaleListNodeType = createNodeType({\n type: 'locale-list',\n displayName: 'LocaleList',\n category: 'special',\n schema: LocaleListNodeSchemaInternal,\n\n defaultValues: {\n style: { base: {} },\n showCurrent: true,\n showSeparator: true,\n showFlag: true,\n displayType: 'nativeName',\n },\n\n treeDisplay: {\n icon: 'HTML_ELEMENT',\n getLabel: () => 'LocaleList',\n },\n\n clientRenderer: (_node, context) => {\n // In editor, shows placeholder\n return h('div', {\n key: context.key,\n 'data-locale-list': 'true',\n }, '[Locale List]');\n },\n\n ssrRenderer: (_node, _context) => {\n // Placeholder - full implementation renders actual locale links\n return '<div class=\"locale-list\">[Locale List]</div>';\n },\n\n capabilities: {\n canHaveChildren: false,\n requiresProps: [],\n },\n});\n", "/**\n * Unified List Node Type Definition\n * Renders children for each item from either component props or CMS collections.\n *\n * Replaces both the original 'list' and 'cms-list' node types with a unified\n * implementation that uses sourceType to determine data source.\n */\n\nimport { z } from 'zod';\nimport { createElement as h } from 'react';\nimport { IfConditionSchema } from '../../validation/schemas';\nimport { createNodeType } from '../createNodeType';\nimport { NODE_TYPE } from '../../constants';\n\n// Filter condition schema (shared with CMS list queries)\nconst CMSFilterConditionSchema = z.object({\n field: z.string(),\n operator: z.enum(['eq', 'neq', 'gt', 'gte', 'lt', 'lte', 'contains', 'in']).optional(),\n value: z.unknown(),\n});\n\n// Sort configuration schema\nconst CMSSortConfigSchema = z.union([\n z.object({\n field: z.string(),\n order: z.enum(['asc', 'desc']).optional(),\n }),\n z.array(z.object({\n field: z.string(),\n order: z.enum(['asc', 'desc']).optional(),\n })),\n]);\n\n// Schema is the SINGLE source of truth\nconst ListNodeSchemaInternal = z.object({\n type: z.literal('list'),\n /**\n * Data source type:\n * - 'prop': Read items from component props (default)\n * - 'collection': Query items from CMS collection\n */\n sourceType: z.enum(['prop', 'collection']).default('prop'),\n /**\n * Source identifier:\n * - For sourceType 'prop': Prop name (e.g., \"items\") or template expression (e.g., \"{{category.items}}\")\n * - For sourceType 'collection': Collection name (e.g., \"posts\", \"authors\")\n */\n source: z.string(),\n label: z.string().optional(), // Custom label displayed in structure tree\n if: IfConditionSchema.optional(), // Conditional rendering - skip node when false\n /**\n * Variable name for item in templates.\n * - For sourceType 'prop': defaults to 'item'\n * - For sourceType 'collection': defaults to singularized collection name\n */\n itemAs: z.string().optional(),\n\n // Collection-only options (ignored when sourceType: 'prop')\n /** Direct item IDs or template expression for referenced items (e.g., \"{{post.authorId}}\") */\n items: z.union([z.string(), z.array(z.string())]).optional(),\n /** Filter conditions */\n filter: z.union([\n CMSFilterConditionSchema,\n z.array(CMSFilterConditionSchema),\n z.record(z.unknown()),\n ]).optional(),\n /** Sort configuration */\n sort: CMSSortConfigSchema.optional(),\n /** Exclude the current CMS item from the list (useful for \"related items\" sections) */\n excludeCurrentItem: z.boolean().optional(),\n /**\n * Emit item template for dynamic client-side rendering.\n * When true, SSR emits a `<template data-meno-item>` element with unprocessed\n * {{item.field}} placeholders. MenoFilter uses this to render items beyond\n * the SSR'd limit dynamically.\n */\n emitTemplate: z.boolean().optional(),\n\n // Shared options\n /** Maximum number of items to return */\n limit: z.number().optional(),\n /** Number of items to skip */\n offset: z.number().optional(),\n /** Children are repeated for each item */\n children: z.array(z.unknown()).optional(),\n /** @deprecated Legacy property - use source + sourceType instead */\n collection: z.union([z.string(), z.array(z.any())]).optional(),\n}).passthrough();\n\n// TypeScript type inferred from schema\nexport type ListNode = z.infer<typeof ListNodeSchemaInternal>;\n\n// Export schema for validation/schemas.ts\nexport const ListNodeSchema = ListNodeSchemaInternal;\n\nexport const ListNodeType = createNodeType({\n type: NODE_TYPE.LIST,\n displayName: 'List',\n category: 'special',\n schema: ListNodeSchemaInternal,\n\n defaultValues: {\n sourceType: 'prop',\n source: '{{items}}',\n itemAs: 'item',\n children: [],\n },\n\n treeDisplay: {\n icon: 'ARRAY',\n getLabel: (node) => {\n const listNode = node as ListNode;\n const sourceType = listNode.sourceType || 'prop';\n const prefix = sourceType === 'collection' ? 'CMS List' : 'List';\n return listNode.source ? `${prefix}: ${listNode.source}` : prefix;\n },\n },\n\n clientRenderer: (node, context) => {\n const listNode = node as ListNode;\n const sourceType = listNode.sourceType || 'prop';\n const isCollection = sourceType === 'collection';\n // Different styling for collection vs prop lists\n const bgColor = isCollection ? 'rgba(139, 92, 246, 0.1)' : 'rgba(59, 130, 246, 0.1)';\n const borderColor = isCollection ? 'rgba(139, 92, 246, 0.5)' : 'rgba(59, 130, 246, 0.5)';\n const textColor = isCollection ? '#8b5cf6' : '#3b82f6';\n const label = isCollection ? 'CMS List' : 'List';\n\n return h('div', {\n key: context.key,\n 'data-list': 'true',\n 'data-source-type': sourceType,\n 'data-source': listNode.source,\n style: {\n padding: '8px 12px',\n background: bgColor,\n border: `1px dashed ${borderColor}`,\n borderRadius: '4px',\n color: textColor,\n fontSize: '12px',\n },\n }, `[${label}: ${listNode.source || 'No source'}]`);\n },\n\n ssrRenderer: (_node, _context) => {\n // Placeholder - actual SSR is handled by processList in ssrRenderer.ts\n return '<!-- list rendered by processList -->';\n },\n\n capabilities: {\n canHaveChildren: true,\n requiresProps: ['source'],\n },\n\n editableFields: [\n {\n name: 'sourceType',\n label: 'Source Type',\n type: 'select',\n required: false,\n options: ['prop', 'collection'],\n },\n {\n name: 'source',\n label: 'Source',\n type: 'string',\n required: true,\n placeholder: 'e.g., items or posts'\n },\n {\n name: 'itemAs',\n label: 'Item Variable',\n type: 'string',\n required: false,\n placeholder: 'default: item (prop) or singular (collection)'\n }\n ],\n});\n", "/**\n * Node Types Index\n * Exports all built-in node type definitions, schemas, and types\n *\n * This is the single source of truth for node type definitions.\n * Types are inferred from Zod schemas, eliminating duplication.\n */\n\nimport { globalNodeTypeManager } from '../NodeTypeManager';\nimport type { NodeTypeDefinition } from '../NodeTypeDefinition';\n\n// Import all node type definitions (each file exports type, schema, and definition)\nimport { HtmlNodeType, HtmlNodeSchema, type HtmlNode } from './HtmlNodeType';\nimport { ComponentInstanceNodeType, ComponentInstanceNodeSchema, type ComponentInstanceNode } from './ComponentInstanceNodeType';\nimport { SlotMarkerType, SlotMarkerSchema, type SlotMarker } from './SlotMarkerType';\nimport { EmbedNodeType, EmbedNodeSchema, type EmbedNode } from './EmbedNodeType';\nimport { LinkNodeType, LinkNodeSchema, type LinkNode } from './LinkNodeType';\nimport { LocaleListNodeType, LocaleListNodeSchema, type LocaleListNode } from './LocaleListNodeType';\nimport { ListNodeType, ListNodeSchema, type ListNode } from './ListNodeType';\n\n/**\n * All built-in node type definitions\n * Type assertion needed because TypeScript sees each as a specific generic type\n */\nexport const builtInNodeTypes: NodeTypeDefinition[] = [\n HtmlNodeType as NodeTypeDefinition,\n ComponentInstanceNodeType as NodeTypeDefinition,\n SlotMarkerType as NodeTypeDefinition,\n EmbedNodeType as NodeTypeDefinition,\n LinkNodeType as NodeTypeDefinition,\n LocaleListNodeType as NodeTypeDefinition,\n ListNodeType as NodeTypeDefinition,\n];\n\n/**\n * Export all schemas for use in validation/schemas.ts\n */\nexport const nodeSchemas = {\n html: HtmlNodeSchema,\n component: ComponentInstanceNodeSchema,\n slot: SlotMarkerSchema,\n embed: EmbedNodeSchema,\n link: LinkNodeSchema,\n localeList: LocaleListNodeSchema,\n list: ListNodeSchema,\n};\n\n/**\n * Register all built-in node types with the global manager\n * Call this early in app lifecycle (client and server entry points)\n */\nexport function registerBuiltInNodeTypes(): void {\n globalNodeTypeManager.registerAll(builtInNodeTypes);\n}\n\n// Re-export individual node types for direct access\nexport { HtmlNodeType, HtmlNodeSchema, type HtmlNode } from './HtmlNodeType';\nexport { ComponentInstanceNodeType, ComponentInstanceNodeSchema, type ComponentInstanceNode } from './ComponentInstanceNodeType';\nexport { SlotMarkerType, SlotMarkerSchema, type SlotMarker } from './SlotMarkerType';\nexport { EmbedNodeType, EmbedNodeSchema, type EmbedNode } from './EmbedNodeType';\nexport { LinkNodeType, LinkNodeSchema, type LinkNode } from './LinkNodeType';\nexport { LocaleListNodeType, LocaleListNodeSchema, type LocaleListNode } from './LocaleListNodeType';\nexport { ListNodeType, ListNodeSchema, type ListNode } from './ListNodeType';\n\n/**\n * Discriminated union of all component node types\n * This is the single source of truth for ComponentNode type\n */\nexport type ComponentNode =\n | HtmlNode\n | ComponentInstanceNode\n | SlotMarker\n | EmbedNode\n | LinkNode\n | LocaleListNode\n | ListNode;\n", "/**\n * Component Registry System\n * Unified registry system for client and SSR\n */\n\n// Component registries\nexport { BaseComponentRegistry } from './ComponentRegistry';\nexport { ClientRegistry } from './ClientRegistry';\nexport { SSRRegistry } from './SSRRegistry';\nexport { RegistryManager } from './RegistryManager';\n\n// Node type registries\nexport { BaseNodeTypeRegistry } from './BaseNodeTypeRegistry';\nexport type { NodeLabelInfo } from './BaseNodeTypeRegistry';\nexport { ClientNodeTypeRegistry } from './ClientNodeTypeRegistry';\nexport { SSRNodeTypeRegistry } from './SSRNodeTypeRegistry';\nexport { NodeTypeManager, globalNodeTypeManager } from './NodeTypeManager';\nexport { defineNodeType } from './defineNodeType';\nexport { createNodeType } from './createNodeType';\nexport type { CreateNodeTypeInput } from './createNodeType';\nexport type {\n NodeTypeDefinition,\n NodeTypeDefinitionInput,\n TreeIcon,\n NodeCategory,\n TreeDisplayConfig,\n NodeCapabilities,\n ClientRenderContext,\n SSRRenderContext,\n ClientNodeRenderer,\n SSRNodeRenderer,\n PropsEditorProps,\n EditableField,\n EditableFieldType,\n} from './NodeTypeDefinition';\n\n// Field presets for node types\nexport * from './fieldPresets';\n\n// Built-in node types\nexport {\n registerBuiltInNodeTypes,\n builtInNodeTypes,\n HtmlNodeType,\n ComponentInstanceNodeType,\n SlotMarkerType,\n EmbedNodeType,\n LinkNodeType,\n LocaleListNodeType,\n} from './nodeTypes';\n\n", "/**\n * Internationalization (i18n) utilities\n * Handles inline translation resolution for component props\n */\n\nimport type { I18nValue, I18nConfig, LocaleConfig } from './types/components';\n\n/**\n * Default i18n configuration\n */\nexport const DEFAULT_I18N_CONFIG: I18nConfig = {\n defaultLocale: 'en',\n locales: [\n { code: 'en', name: 'English', nativeName: 'English', langTag: 'en-US' }\n ],\n};\n\n// ============================================\n// Locale helper functions\n// ============================================\n\n/**\n * Get array of locale codes from config\n */\nexport function getLocaleCodes(config: I18nConfig): string[] {\n return config.locales.map(loc => loc.code);\n}\n\n/**\n * Find a locale config by its code\n */\nexport function findLocaleByCode(config: I18nConfig, code: string): LocaleConfig | undefined {\n return config.locales.find(loc => loc.code === code);\n}\n\n/**\n * Check if a locale code is valid/exists in config\n */\nexport function isValidLocaleCode(config: I18nConfig, code: string): boolean {\n return config.locales.some(loc => loc.code === code);\n}\n\n// ============================================\n// Config Migration (old string[] -> new LocaleConfig[])\n// ============================================\n\n/**\n * Convert old locale format (string) to new format (LocaleConfig)\n */\nfunction migrateLocaleString(code: string): LocaleConfig {\n const upperCode = code.toUpperCase();\n return {\n code: code.toLowerCase(),\n name: upperCode,\n nativeName: upperCode,\n langTag: `${code.toLowerCase()}-${upperCode}`,\n };\n}\n\n/**\n * Check if locales array is in old string format\n */\nfunction isOldLocaleFormat(locales: unknown): locales is string[] {\n return Array.isArray(locales) && locales.length > 0 && typeof locales[0] === 'string';\n}\n\n/**\n * Migrate i18n config from old format to new format\n * Old: { defaultLocale: \"en\", locales: [\"en\", \"pl\"] }\n * New: { defaultLocale: \"en\", locales: [{ code: \"en\", name: \"EN\", ... }] }\n */\nexport function migrateI18nConfig(i18n: unknown): I18nConfig {\n if (!i18n || typeof i18n !== 'object') {\n return DEFAULT_I18N_CONFIG;\n }\n\n const config = i18n as Record<string, unknown>;\n const defaultLocale = (config.defaultLocale as string) || 'en';\n const locales = config.locales;\n\n if (!locales || !Array.isArray(locales)) {\n return DEFAULT_I18N_CONFIG;\n }\n\n // Migrate old string[] format\n if (isOldLocaleFormat(locales)) {\n return {\n defaultLocale,\n locales: locales.map(migrateLocaleString),\n };\n }\n\n // Already in new format\n return {\n defaultLocale,\n locales: locales as LocaleConfig[],\n };\n}\n\n/**\n * Type guard to check if a value is an I18nValue object\n */\nexport function isI18nValue(value: unknown): value is I18nValue {\n if (typeof value !== 'object' || value === null || Array.isArray(value)) {\n return false;\n }\n return '_i18n' in value && (value as Record<string, unknown>)._i18n === true;\n}\n\n/**\n * Resolve a single translation value for the given locale\n * Fallback order: exact locale -> default locale -> first available -> empty\n * Works with any value type (strings, arrays for list props, etc.)\n */\nexport function resolveTranslation(\n value: I18nValue,\n locale: string,\n config: I18nConfig\n): unknown {\n // Try exact locale match (any type - string, array, etc.)\n if (locale in value && value[locale] !== undefined && locale !== '_i18n') {\n return value[locale];\n }\n\n // Try default locale\n if (config.defaultLocale in value && value[config.defaultLocale] !== undefined) {\n return value[config.defaultLocale];\n }\n\n // Get first available value (skip _i18n marker)\n for (const key of Object.keys(value)) {\n if (key !== '_i18n' && value[key] !== undefined) {\n return value[key];\n }\n }\n\n // Return empty string for string i18n, empty array for list i18n\n // Check if any value is an array to determine the type\n const hasArrayValue = Object.entries(value).some(\n ([k, v]) => k !== '_i18n' && Array.isArray(v)\n );\n return hasArrayValue ? [] : '';\n}\n\n/**\n * Resolve a value that might be an I18nValue or a regular value\n * Returns the original value if not an I18nValue\n */\nexport function resolveI18nValue(\n value: unknown,\n locale: string,\n config: I18nConfig\n): unknown {\n if (isI18nValue(value)) {\n return resolveTranslation(value, locale, config);\n }\n return value;\n}\n\n/**\n * Recursively resolve all I18nValue objects in a props object\n */\nexport function resolveI18nInProps(\n props: Record<string, unknown>,\n locale: string,\n config: I18nConfig\n): Record<string, unknown> {\n const resolved: Record<string, unknown> = {};\n\n for (const [key, value] of Object.entries(props)) {\n if (isI18nValue(value)) {\n resolved[key] = resolveTranslation(value, locale, config);\n } else if (Array.isArray(value)) {\n resolved[key] = value.map((item) =>\n isI18nValue(item) ? resolveTranslation(item, locale, config) : item\n );\n } else if (typeof value === 'object' && value !== null) {\n // Recursively resolve nested objects (but not I18nValue which is already handled)\n resolved[key] = resolveI18nInProps(\n value as Record<string, unknown>,\n locale,\n config\n );\n } else {\n resolved[key] = value;\n }\n }\n\n return resolved;\n}\n\n/**\n * Extract locale from URL path prefix\n * e.g., '/en/about' -> 'en', '/pl/' -> 'pl', '/about' -> null\n */\nexport function extractLocaleFromPath(\n path: string,\n config: I18nConfig\n): { locale: string | null; pathWithoutLocale: string } {\n // Remove leading slash and split\n const cleanPath = path.startsWith('/') ? path.slice(1) : path;\n const segments = cleanPath.split('/');\n\n if (segments.length > 0 && isValidLocaleCode(config, segments[0])) {\n const locale = segments[0];\n const pathWithoutLocale = '/' + segments.slice(1).join('/');\n return { locale, pathWithoutLocale: pathWithoutLocale || '/' };\n }\n\n return { locale: null, pathWithoutLocale: path };\n}\n\n/**\n * Build a localized path\n * e.g., ('/about', 'pl') -> '/pl/about'\n */\nexport function buildLocalizedPath(path: string, locale: string): string {\n const cleanPath = path.startsWith('/') ? path : '/' + path;\n return `/${locale}${cleanPath === '/' ? '' : cleanPath}`;\n}\n\n/**\n * Locale context containing resolved locale info\n */\nexport interface LocaleContext {\n /** The effective locale (never null) */\n locale: string;\n /** Path with locale prefix removed */\n pathWithoutLocale: string;\n /** Whether the current locale is the default */\n isDefaultLocale: boolean;\n}\n\n/**\n * Parse locale from path and return full context with effective locale\n * Combines extractLocaleFromPath + defaultLocale resolution in one call\n */\nexport function parseLocaleFromPath(\n path: string,\n config: I18nConfig\n): LocaleContext {\n const { locale, pathWithoutLocale } = extractLocaleFromPath(path, config);\n const effectiveLocale = locale || config.defaultLocale;\n\n return {\n locale: effectiveLocale,\n pathWithoutLocale,\n isDefaultLocale: effectiveLocale === config.defaultLocale\n };\n}\n\n// ============================================\n// Client-side locale persistence utilities\n// ============================================\n\nconst LOCALE_STORAGE_KEY = 'meno_locale_preference';\nconst OLD_LOCALE_STORAGE_KEY = 'uplo_locale_preference';\n\n/**\n * Migrate locale storage key from old to new (one-time migration)\n */\nfunction migrateLocaleStorageKey(): void {\n if (typeof window === 'undefined') return;\n try {\n const oldValue = localStorage.getItem(OLD_LOCALE_STORAGE_KEY);\n const newValue = localStorage.getItem(LOCALE_STORAGE_KEY);\n if (oldValue && !newValue) {\n localStorage.setItem(LOCALE_STORAGE_KEY, oldValue);\n localStorage.removeItem(OLD_LOCALE_STORAGE_KEY);\n }\n } catch {\n // Storage not available\n }\n}\n\n/**\n * Get stored locale preference from localStorage (client-side only)\n */\nexport function getStoredLocale(): string | null {\n if (typeof window === 'undefined') return null;\n try {\n // Migrate from old key if needed\n migrateLocaleStorageKey();\n return localStorage.getItem(LOCALE_STORAGE_KEY);\n } catch {\n return null;\n }\n}\n\n/**\n * Store locale preference to localStorage (client-side only)\n */\nexport function setStoredLocale(locale: string): void {\n if (typeof window === 'undefined') return;\n try {\n localStorage.setItem(LOCALE_STORAGE_KEY, locale);\n } catch {\n // Storage not available\n }\n}\n\n/**\n * Clear stored locale preference (client-side only)\n */\nexport function clearStoredLocale(): void {\n if (typeof window === 'undefined') return;\n try {\n localStorage.removeItem(LOCALE_STORAGE_KEY);\n } catch {\n // Storage not available\n }\n}\n", "/**\n * CMS Query Parser\n * Utilities for parsing and serializing sort/filter expressions for CMS List nodes.\n *\n * Sort Expression Syntax:\n * field [asc|desc]\n * Multiple fields separated by comma: date desc, title asc\n *\n * Filter Expression Syntax:\n * field operator value\n * Operators: =, ==, !=, <>, >, >=, <, <=, contains, ~, in\n * Multiple conditions on separate lines or semicolon-separated\n * Supports template values: category = {{cms.category}}\n */\n\nimport type { CMSFilterCondition, CMSSortConfig, CMSFilterOperator } from './types/cms';\n\n/**\n * Parse sort expression: \"date desc, title asc\"\n * Note: \"asc\" is the default and can be omitted. The serializer outputs \"date\" for ascending.\n */\nexport function parseSortExpression(expr: string): CMSSortConfig | CMSSortConfig[] | undefined {\n if (!expr.trim()) return undefined;\n\n const parts = expr.split(',').map(p => p.trim()).filter(Boolean);\n const sorts: CMSSortConfig[] = parts.map(part => {\n const tokens = part.split(/\\s+/);\n const field = tokens[0];\n const order = tokens[1]?.toLowerCase() === 'desc' ? 'desc' : 'asc';\n return { field, order };\n });\n\n return sorts.length === 1 ? sorts[0] : sorts;\n}\n\n/**\n * Serialize sort config back to expression\n */\nexport function serializeSortExpression(sort: CMSSortConfig | CMSSortConfig[] | undefined): string {\n if (!sort) return '';\n const sorts = Array.isArray(sort) ? sort : [sort];\n return sorts.map(s => `${s.field}${s.order === 'desc' ? ' desc' : ''}`).join(', ');\n}\n\n/**\n * Parse filter expression: \"featured = true; price > 100\"\n */\nexport function parseFilterExpression(\n expr: string\n): CMSFilterCondition | CMSFilterCondition[] | Record<string, unknown> | undefined {\n if (!expr.trim()) return undefined;\n\n // Split by newline or semicolon\n const lines = expr.split(/[;\\n]/).map(l => l.trim()).filter(Boolean);\n const conditions: CMSFilterCondition[] = [];\n\n for (const line of lines) {\n const condition = parseFilterLine(line);\n if (condition) conditions.push(condition);\n }\n\n if (conditions.length === 0) return undefined;\n\n // Single simple equality can use shorthand: { field: value }\n if (conditions.length === 1 && (!conditions[0].operator || conditions[0].operator === 'eq')) {\n return { [conditions[0].field]: conditions[0].value };\n }\n\n return conditions.length === 1 ? conditions[0] : conditions;\n}\n\nfunction parseFilterLine(line: string): CMSFilterCondition | null {\n // Match: field operator value\n // Operators listed longest-first to avoid partial matches (e.g., gte before gt)\n const match = line.match(/^(\\w+)\\s*(==|!=|<>|>=|<=|=|>|<|contains|~|in|gte|lte|neq|gt|lt|eq)\\s*(.+)$/i);\n if (!match) return null;\n\n const [, field, op, rawValue] = match;\n const operator = normalizeOperator(op);\n const value = parseValue(rawValue.trim(), operator);\n\n // For simple equality, we can omit operator\n if (operator === 'eq') {\n return { field, value };\n }\n\n return { field, operator, value };\n}\n\nfunction normalizeOperator(op: string): CMSFilterOperator {\n const normalized = op.toLowerCase();\n const map: Record<string, CMSFilterOperator> = {\n '=': 'eq', '==': 'eq', 'eq': 'eq',\n '!=': 'neq', '<>': 'neq', 'neq': 'neq',\n '>': 'gt', 'gt': 'gt',\n '>=': 'gte', 'gte': 'gte',\n '<': 'lt', 'lt': 'lt',\n '<=': 'lte', 'lte': 'lte',\n 'contains': 'contains', '~': 'contains',\n 'in': 'in'\n };\n return map[normalized] || 'eq';\n}\n\nfunction parseValue(raw: string, operator: CMSFilterOperator): unknown {\n // Template expression - keep as string\n if (raw.startsWith('{{') && raw.endsWith('}}')) {\n return raw;\n }\n\n // Handle 'in' operator - comma separated list\n if (operator === 'in') {\n return raw.split(',').map(v => parseScalarValue(v.trim()));\n }\n\n return parseScalarValue(raw);\n}\n\nfunction parseScalarValue(raw: string): unknown {\n // Boolean\n if (raw.toLowerCase() === 'true') return true;\n if (raw.toLowerCase() === 'false') return false;\n\n // Number\n const num = Number(raw);\n if (!isNaN(num) && raw !== '') return num;\n\n // String (strip quotes if present)\n if ((raw.startsWith('\"') && raw.endsWith('\"')) || (raw.startsWith(\"'\") && raw.endsWith(\"'\"))) {\n return raw.slice(1, -1);\n }\n\n return raw;\n}\n\n/**\n * Serialize filter config back to expression\n */\nexport function serializeFilterExpression(\n filter: CMSFilterCondition | CMSFilterCondition[] | Record<string, unknown> | undefined\n): string {\n if (!filter) return '';\n\n // Simple object filter: { featured: true }\n if (!Array.isArray(filter) && !isFilterCondition(filter)) {\n return Object.entries(filter)\n .map(([field, value]) => `${field} = ${serializeValue(value)}`)\n .join('\\n');\n }\n\n // Array or single condition\n const conditions = Array.isArray(filter) ? filter : [filter as CMSFilterCondition];\n return conditions.map(c => {\n const op = c.operator || 'eq';\n const opStr = operatorToString(op);\n const valStr = op === 'in' && Array.isArray(c.value)\n ? c.value.map(v => serializeValue(v)).join(', ')\n : serializeValue(c.value);\n return `${c.field} ${opStr} ${valStr}`;\n }).join('\\n');\n}\n\nfunction operatorToString(op: CMSFilterOperator): string {\n const map: Record<CMSFilterOperator, string> = {\n 'eq': '=',\n 'neq': '!=',\n 'gt': '>',\n 'gte': '>=',\n 'lt': '<',\n 'lte': '<=',\n 'contains': 'contains',\n 'in': 'in'\n };\n return map[op] || '=';\n}\n\nfunction isFilterCondition(obj: unknown): obj is CMSFilterCondition {\n return typeof obj === 'object' && obj !== null && 'field' in obj;\n}\n\nfunction serializeValue(value: unknown): string {\n if (typeof value === 'string') {\n // Template or simple alphanumeric - no quotes needed\n if (value.startsWith('{{') || /^[\\w-]+$/.test(value)) return value;\n return `\"${value}\"`;\n }\n return String(value);\n}\n", "/**\n * meno-core shared exports\n * Re-exports all types, constants, and utilities from shared modules\n */\n\n// Types\nexport * from './types';\n\n// Constants\nexport * from './constants';\n\n// Path utilities\nexport * from './pathArrayUtils';\nexport * from './treePathUtils';\nexport * from './paths';\n\n// Node utilities\nexport * from './nodeUtils';\n\n// Style utilities\nexport * from './breakpoints';\nexport * from './styleUtils';\nexport * from './cssProperties';\nexport * from './cssGeneration';\nexport * from './viewportUnits';\nexport * from './colorProperties';\nexport * from './cssNamedColors';\nexport * from './utilityClassMapper';\nexport * from './elementClassName';\nexport * from './styleValueRegistry';\n\n// i18n utilities\nexport * from './i18n';\n\n// Slugify utilities\nexport * from './slugify';\n\n// Tree utilities\nexport * from './tree/PathBuilder';\n\n// Validation - use explicit exports to avoid ValidationError conflict with types/errors.ts\nexport {\n // Schemas\n StyleMappingSchema,\n StyleObjectSchema,\n ResponsiveStyleObjectSchema,\n StyleValueSchema,\n InteractiveStyleRuleSchema,\n InteractiveStylesSchema,\n PageDataSchema,\n PageDataWithComponentSchema,\n PropDefinitionSchema,\n ComponentNodeSchema,\n ComponentDefinitionSchema,\n StructuredComponentDefinitionSchema,\n PageMetaDataSchema,\n CMSClientDataStrategySchema,\n CMSClientDataConfigSchema,\n CMSSchemaSchema,\n CMSItemSchema,\n // Validators\n type ValidationResult,\n validatePropDefinition,\n validateComponentNode,\n validateComponentDefinition,\n validateStructuredComponentDefinition,\n validatePageData,\n validatePageDataWithComponent,\n validatePageMetaData,\n validateCMSSchema,\n validateCMSItem,\n // Prop validator\n type PropValidationError,\n type PropValidationResult,\n validateComponentProps,\n // CMS validators\n isValidCollectionId,\n validateCollectionId,\n CMS_COLLECTION_ID_REGEX,\n CMSCollectionIdSchema,\n // Comment validators\n CommentSchema,\n CommentStatusSchema,\n CommentAnchorSchema,\n CommentAuthorSchema,\n CommentThreadEntrySchema,\n CommentNodeIdentitySchema,\n validateComment,\n} from './validation';\n\n// Utils\nexport * from './utils';\n\n// Registry\nexport * from './registry';\n\n// Theme defaults\nexport * from './themeDefaults';\n\n// Color variable utilities\nexport * from './colorVariableUtils';\n\n// Responsive style utilities\nexport * from './responsiveStyleUtils';\n\n// Responsive scaling utilities\nexport * from './responsiveScaling';\n\n// Item template utilities (for CMS List)\nexport * from './itemTemplateUtils';\n\n// Path security utilities\nexport * from './pathSecurity';\n\n// Interactive style mapping utilities\nexport * from './interactiveStyleMappings';\n\n// Rich text utilities (Tiptap)\nexport * from './richtext';\n\n// Error handling\nexport * from './errors';\nexport * from './friendlyError';\nexport { logRuntimeError, logNetworkError, setErrorHandler } from './errorLogger';\n\n// Global template context\nexport * from './globalTemplateContext';\n\n// Link utilities\nexport * from './linkUtils';\n\n// Color conversion utilities\nexport * from './colorConversions';\n\n// Gradient utilities\nexport * from './gradientUtils';\n\n// CMS query parsing utilities\nexport * from './cmsQueryParser';\n\n// Prop resolution utilities\nexport { resolvePropsFromDefinition, isRichTextMarker, richTextMarkerToHtml } from './propResolver';\n\n// Component reference utilities (shared by rename API on server + editor sync on client)\nexport * from './componentRefs';\n\n// Href reference utilities (shared by page-rename/slug-rename API cascade)\nexport * from './hrefRefs';\n\n// Slug translation utilities (URL builder + slug index)\nexport {\n buildPageUrlForLocale,\n buildSlugIndex,\n findPageBySlug,\n getLocaleLinks,\n resolveSlugToPageId,\n translatePath,\n} from './slugTranslator';\nexport type { LocaleLink, SlugMap } from './slugTranslator';\n", "/**\n * Node type utilities and type guards\n * Provides helper functions for working with ComponentNode types\n */\n\nimport type { ComponentNode, ComponentInstanceNode, HtmlNode, SlotMarker, EmbedNode, LinkNode, LocaleListNode, ComponentDefinition, StructuredComponentDefinition } from './types';\nimport type { ListNode } from './registry/nodeTypes/ListNodeType';\n\n// For backward compatibility during migration\ntype CMSListNode = ListNode;\nimport { NODE_TYPE } from './constants';\n\n/**\n * Set of HTML void elements that cannot have children.\n * These are self-closing tags like <img />, <br />, <input />, etc.\n */\nexport const VOID_ELEMENTS = new Set([\n 'area', 'base', 'br', 'col', 'embed', 'hr', 'img', 'input',\n 'link', 'meta', 'param', 'source', 'track', 'wbr'\n]);\n\n/**\n * Check if an HTML tag is a void element (self-closing, cannot have children)\n */\nexport function isVoidElement(tag: string): boolean {\n return VOID_ELEMENTS.has(tag.toLowerCase());\n}\n\n/**\n * Check if a node is an empty container that can accept children.\n * Returns true for HTML nodes (non-void) and component instances\n * that have no children (undefined or empty array).\n * Returns false for void elements, slot markers, embed nodes, list nodes,\n * null/undefined, and nodes that already have children.\n */\nexport function isEmptyContainer(node: ComponentNode | null | undefined): boolean {\n if (!node) return false;\n\n // HTML node: must be non-void and have no children\n if (isHtmlNode(node)) {\n if (isVoidElement(node.tag)) return false;\n const children = node.children;\n return children === undefined || (Array.isArray(children) && children.length === 0);\n }\n\n // Component instance: must have no children\n if (isComponentNode(node)) {\n const children = node.children;\n return children === undefined || (Array.isArray(children) && children.length === 0);\n }\n\n // All other node types (slot, embed, list, link, etc.) are not containers\n return false;\n}\n\n/**\n * Type guard to check if a node is a component instance\n */\nexport function isComponentNode(node: ComponentNode | null | undefined): node is ComponentInstanceNode {\n return node?.type === NODE_TYPE.COMPONENT;\n}\n\n/**\n * Type guard to check if a node is an HTML element\n */\nexport function isHtmlNode(node: ComponentNode | null | undefined): node is HtmlNode {\n return node?.type === NODE_TYPE.NODE;\n}\n\n/**\n * Get the component name from a ComponentNode (for component instances)\n */\nexport function getComponentName(node: ComponentNode): string | undefined {\n return isComponentNode(node) ? node.component : undefined;\n}\n\n/**\n * Get the tag name from a ComponentNode (for HTML nodes)\n */\nexport function getTagName(node: ComponentNode): string | undefined {\n return isHtmlNode(node) ? node.tag : undefined;\n}\n\n/**\n * Get the display name (tag or component name) from a ComponentNode\n * Uses registry for automatic display name resolution\n */\nexport function getDisplayName(node: ComponentNode): string {\n // Dynamic names for component/html nodes\n if (isComponentNode(node)) {\n return node.component;\n }\n if (isHtmlNode(node)) {\n return node.tag;\n }\n\n // Use registry for all other node types\n const { globalNodeTypeManager } = require('./registry');\n const definition = globalNodeTypeManager.getClient().findByNode(node);\n return definition?.displayName || 'Unknown';\n}\n\n/**\n * Extract node properties (tag/component, props) based on node type\n * Returns an object with tag, componentName, and props\n */\nexport function extractNodeProperties(node: ComponentNode): {\n tag?: string;\n componentName?: string;\n props: Record<string, unknown>;\n} {\n if (isComponentNode(node)) {\n return {\n componentName: node.component,\n props: node.props || {}\n };\n }\n if (isHtmlNode(node)) {\n return {\n tag: node.tag,\n props: {}\n };\n }\n return { props: {} };\n}\n\n/**\n * Check if a tag name is likely a component (as opposed to HTML element)\n * This is a heuristic based on naming conventions:\n * - Components typically start with uppercase (e.g., \"Card\", \"Button\")\n * - HTML elements are lowercase (e.g., \"div\", \"span\")\n * \n * Note: This is not foolproof, but works for most cases.\n * For accurate detection, use component registry lookup.\n */\nexport function isLikelyComponentTag(tag: string): boolean {\n if (!tag) return false;\n // Components typically start with uppercase letter\n return tag.length > 0 && tag[0] === tag[0].toUpperCase() && tag[0] !== tag[0].toLowerCase();\n}\n\n/**\n * Type guard to check if a node is a slot marker\n */\nexport function isSlotMarker(node: ComponentNode | null | undefined): node is SlotMarker {\n return node?.type === NODE_TYPE.SLOT;\n}\n\n/**\n * Check whether a component definition's structure contains any slot marker.\n *\n * Used by callers that decide whether to preserve a component instance's\n * `children` (e.g. the Figma paste swap) \u2014 there is no point passing children\n * to a component whose template will never render them.\n */\nexport function componentHasSlot(def: ComponentDefinition | undefined | null): boolean {\n const structure = def?.component?.structure;\n if (!structure) return false;\n return structureContainsSlot(structure);\n}\n\nfunction structureContainsSlot(node: unknown): boolean {\n if (node == null) return false;\n if (Array.isArray(node)) {\n for (const item of node) {\n if (structureContainsSlot(item)) return true;\n }\n return false;\n }\n if (typeof node !== 'object') return false;\n const obj = node as Record<string, unknown>;\n if (obj.type === NODE_TYPE.SLOT) return true;\n if (obj.children !== undefined) return structureContainsSlot(obj.children);\n return false;\n}\n\n/**\n * Type guard to check if a node is an embed node\n */\nexport function isEmbedNode(node: ComponentNode | null | undefined): node is EmbedNode {\n return node?.type === NODE_TYPE.EMBED;\n}\n\n/**\n * Type guard to check if a node is a link node\n */\nexport function isLinkNode(node: ComponentNode | null | undefined): node is LinkNode {\n return node?.type === NODE_TYPE.LINK;\n}\n\n/**\n * Type guard to check if a node is a locale list node\n */\nexport function isLocaleListNode(node: ComponentNode | null | undefined): node is LocaleListNode {\n return node?.type === NODE_TYPE.LOCALE_LIST;\n}\n\n/**\n * Type guard to check if a node is a CMS list node\n * @deprecated Use isListNode() and check sourceType === 'collection' instead.\n * Kept for backward compatibility during migration.\n */\nexport function isCMSListNode(node: unknown): node is ListNode {\n if (node === null || typeof node !== 'object') return false;\n const n = node as Record<string, unknown>;\n // Support both old cms-list type and new list with sourceType: 'collection'\n return n.type === 'cms-list' || (n.type === NODE_TYPE.LIST && n.sourceType === 'collection');\n}\n\n/**\n * Type guard to check if a node is a list node (unified type)\n */\nexport function isListNode(node: unknown): node is ListNode {\n if (node === null || typeof node !== 'object') return false;\n const n = node as Record<string, unknown>;\n // Support both old cms-list type (for migration) and new list type\n return n.type === NODE_TYPE.LIST || n.type === 'cms-list';\n}\n\n/**\n * Validate that a node type is valid\n */\nexport function isValidNodeType(type: string): type is typeof NODE_TYPE[keyof typeof NODE_TYPE] {\n return type === NODE_TYPE.NODE || type === NODE_TYPE.COMPONENT || type === NODE_TYPE.SLOT ||\n type === NODE_TYPE.EMBED || type === NODE_TYPE.LINK || type === NODE_TYPE.LOCALE_LIST ||\n type === NODE_TYPE.LIST || type === 'cms-list'; // 'cms-list' supported for migration\n}\n\n/**\n * Check if a node can have children property (excludes SlotMarker)\n */\nexport function canHaveChildren(node: ComponentNode | null | undefined): node is Exclude<ComponentNode, SlotMarker> {\n return node !== null && node !== undefined && !isSlotMarker(node);\n}\n\n/**\n * Check if a node can have style property (excludes SlotMarker)\n */\nexport function canHaveStyle(node: ComponentNode | null | undefined): node is Exclude<ComponentNode, SlotMarker> {\n return node !== null && node !== undefined && !isSlotMarker(node);\n}\n\n/**\n * Type guard: node has a children array\n */\nexport function hasChildren(node: unknown): node is { children: (ComponentNode | string)[] } {\n return node != null && typeof node === 'object' && 'children' in node && Array.isArray(node.children);\n}\n\n/**\n * Type guard: node has an if condition\n */\nexport function hasIf(node: ComponentNode): node is ComponentNode & { if: IfCondition } {\n return 'if' in node && node.if !== undefined;\n}\n\n/**\n * Check if a node is marked as slot content\n */\nexport function isSlotContent(node: unknown): boolean {\n return node != null && typeof node === 'object' && '_isSlotContent' in node && (node as Record<string, unknown>)._isSlotContent === true;\n}\n\n/**\n * Type guard to check if a value is a StructuredComponentDefinition\n */\nexport function isStructuredComponentDefinition(comp: unknown): comp is StructuredComponentDefinition {\n if (!comp || typeof comp !== 'object') {\n return false;\n }\n // Check for required structure properties (interface, structure are optional but structure should be an object if present)\n const obj = comp as Record<string, unknown>;\n // Must have at least one of: interface, structure, javascript, css\n return (\n ('interface' in obj || 'structure' in obj || 'javascript' in obj || 'css' in obj) &&\n (obj.structure === undefined || (typeof obj.structure === 'object' && obj.structure !== null))\n );\n}\n\n/**\n * Check if a ComponentDefinition has a structure property\n */\nexport function hasComponentStructure(comp: ComponentDefinition): boolean {\n return comp.component?.structure !== undefined;\n}\n\n/**\n * Check if a ComponentDefinition has a css property\n */\nexport function hasComponentCss(comp: ComponentDefinition): boolean {\n return comp.component?.css !== undefined && typeof comp.component.css === 'string';\n}\n\n/**\n * Get the node type definition from the registry\n * This is a convenience function that uses the global node type registry\n * to find the type definition for a node.\n *\n * @param node - The node to get the type definition for\n * @returns The node type definition, or undefined if not found\n *\n * @example\n * const node = { type: 'image', src: 'test.jpg' };\n * const definition = getNodeTypeDefinition(node);\n * if (definition) {\n * console.log(definition.displayName); // \"Image\"\n * }\n */\nexport function getNodeTypeDefinition(node: ComponentNode | null | undefined) {\n if (!node) return undefined;\n // Import dynamically to avoid circular dependencies\n // The globalNodeTypeManager will be initialized by the app entry point\n const { globalNodeTypeManager } = require('./registry');\n return globalNodeTypeManager.getClient().findByNode(node);\n}\n\n/**\n * Check if a node matches a specific type using the registry\n * This is an alternative to the individual type guards that uses\n * the centralized node type registry.\n *\n * @param node - The node to check\n * @param nodeType - The node type constant (e.g., NODE_TYPE.EMBED)\n * @returns true if the node matches the type\n *\n * @example\n * import { NODE_TYPE } from './constants';\n * const node = { type: 'embed', html: '<div>test</div>' };\n * if (isNodeType(node, NODE_TYPE.EMBED)) {\n * // node is an EmbedNode\n * }\n */\nexport function isNodeType(node: ComponentNode | null | undefined, nodeType: string): boolean {\n if (!node) return false;\n // Import dynamically to avoid circular dependencies\n const { globalNodeTypeManager } = require('./registry');\n return globalNodeTypeManager.getClient().isType(node, nodeType);\n}\n\n/**\n * Boolean mapping type for conditional rendering\n */\nexport interface BooleanMapping {\n _mapping: true;\n prop: string;\n values: Record<string, boolean>;\n}\n\n/**\n * If condition type - can be boolean, string template, or mapping\n */\nexport type IfCondition = boolean | string | BooleanMapping;\n\n/**\n * Check if a value is a boolean mapping\n */\nexport function isBooleanMapping(value: unknown): value is BooleanMapping {\n return (\n value !== null &&\n typeof value === 'object' &&\n '_mapping' in value &&\n (value as BooleanMapping)._mapping === true &&\n 'prop' in value &&\n typeof (value as BooleanMapping).prop === 'string' &&\n 'values' in value &&\n typeof (value as BooleanMapping).values === 'object'\n );\n}\n\n/**\n * Evaluate the if condition on a node to determine if it should be rendered.\n * Returns true if the node should be rendered, false if it should be skipped.\n *\n * @param node - The node to evaluate\n * @param props - Optional component props for resolving mappings\n * @returns true if the node should be rendered, false otherwise\n *\n * @example\n * // No if property = render\n * evaluateNodeIf({ type: 'node', tag: 'div' }) // true\n *\n * // Boolean value\n * evaluateNodeIf({ type: 'node', tag: 'div', if: true }) // true\n * evaluateNodeIf({ type: 'node', tag: 'div', if: false }) // false\n *\n * // Mapping value\n * evaluateNodeIf(\n * { type: 'node', tag: 'div', if: { _mapping: true, prop: 'visible', values: { true: true, false: false } } },\n * { visible: 'true' }\n * ) // true\n */\nexport function evaluateNodeIf(\n node: ComponentNode,\n props?: Record<string, unknown>\n): boolean {\n const ifValue = hasIf(node) ? node.if : undefined;\n\n // No if property = render (default true)\n if (ifValue === undefined) {\n return true;\n }\n\n // Boolean value\n if (typeof ifValue === 'boolean') {\n return ifValue;\n }\n\n // Mapping value - resolve using component props\n if (isBooleanMapping(ifValue)) {\n if (!props) {\n // No props available, default to true\n return true;\n }\n const propValue = props[ifValue.prop];\n const mappedValue = ifValue.values[String(propValue)];\n // If no mapping found for this prop value, default to true\n return mappedValue !== undefined ? Boolean(mappedValue) : true;\n }\n\n // String template - needs context to resolve, default to true here\n // (actual template resolution happens in the rendering context)\n if (typeof ifValue === 'string') {\n return true;\n }\n\n // Unknown type, default to true\n return true;\n}\n\n/**\n * Mark a node and all descendants as slot content.\n * Used to distinguish page-defined children (passed to component slots)\n * from component-defined structure.\n *\n * When a page contains <Stack><Text>Hello</Text></Stack>, the <Text> element\n * is page content that happens to be rendered inside the Stack component's slot.\n * For interactive styles, these elements should use the page context (p_pagename_xxx)\n * not the component context (c_stack_xxx).\n *\n * @param node - The node to mark (can be array, single node, string, number, or null)\n * @returns The same node with _isSlotContent: true added to all object nodes\n */\nexport function markAsSlotContent<T extends ComponentNode | ComponentNode[] | string | number | null | undefined>(\n node: T\n): T {\n if (!node || typeof node !== 'object') return node;\n\n if (Array.isArray(node)) {\n return node.map(markAsSlotContent) as T;\n }\n\n // Mark this node\n (node as Record<string, unknown>)._isSlotContent = true;\n\n // Recursively mark children\n if ('children' in node && node.children) {\n if (Array.isArray(node.children)) {\n node.children = node.children.map(child =>\n typeof child === 'object' && child !== null ? markAsSlotContent(child) : child\n ) as typeof node.children;\n } else if (typeof node.children === 'object') {\n markAsSlotContent(node.children as ComponentNode);\n }\n }\n\n return node;\n}\n\n", "/**\n * Shared Breakpoint Configuration\n * Defines breakpoints for responsive design\n * Supports dynamic breakpoints from project.config.json\n */\n\n/**\n * Extended breakpoint entry with separate CSS threshold and editor preview width\n * - breakpoint: The CSS media query threshold (max-width value)\n * - previewPoint: The width used in editor preview mode (defaults to breakpoint if not specified)\n * - label: Optional display label for UI (e.g., \"Tablet Landscape\", \"Phone\")\n */\nexport interface BreakpointEntry {\n breakpoint: number;\n previewPoint: number;\n label?: string;\n}\n\n/**\n * Input format for breakpoint config - supports both legacy (number) and new (object) format\n * Legacy: { tablet: 1024 }\n * New: { tablet: { breakpoint: 1024, previewPoint: 768 } }\n */\nexport type BreakpointConfigInput = Record<string, number | BreakpointEntry>;\n\n/**\n * Normalized breakpoint config - always uses object format\n */\nexport type BreakpointConfig = Record<string, BreakpointEntry>;\n\n/**\n * Legacy format for backward compatibility (simple number values)\n */\nexport type LegacyBreakpointConfig = Record<string, number>;\n\n// BreakpointName is now a string to support dynamic breakpoints\nexport type BreakpointName = string;\n\nexport const DEFAULT_BREAKPOINTS: BreakpointConfig = {\n tablet: { breakpoint: 1024, previewPoint: 768 },\n mobile: { breakpoint: 540, previewPoint: 375 },\n} as const;\n\n/**\n * Normalize a breakpoint config input to the full object format\n * Converts legacy number format to object format\n * If previewPoint is not specified, defaults to breakpoint value\n */\nexport function normalizeBreakpointConfig(\n input: BreakpointConfigInput | LegacyBreakpointConfig\n): BreakpointConfig {\n const result: BreakpointConfig = {};\n\n for (const [name, value] of Object.entries(input)) {\n if (typeof value === 'number') {\n // Legacy format: number -> { breakpoint: value, previewPoint: value }\n result[name] = { breakpoint: value, previewPoint: value };\n } else if (typeof value === 'object' && value !== null) {\n // New format: ensure both values exist, preserve label if present\n result[name] = {\n breakpoint: value.breakpoint,\n previewPoint: value.previewPoint ?? value.breakpoint,\n ...(value.label !== undefined && { label: value.label }),\n };\n }\n }\n\n return result;\n}\n\n/**\n * Get just the breakpoint values for CSS generation (media queries)\n * Returns Record<string, number> with breakpoint values\n */\nexport function getBreakpointValues(config: BreakpointConfig): LegacyBreakpointConfig {\n const result: LegacyBreakpointConfig = {};\n for (const [name, entry] of Object.entries(config)) {\n result[name] = entry.breakpoint;\n }\n return result;\n}\n\n/**\n * Get just the preview point values for editor preview\n * Returns Record<string, number> with previewPoint values\n */\nexport function getPreviewPointValues(config: BreakpointConfig): LegacyBreakpointConfig {\n const result: LegacyBreakpointConfig = {};\n for (const [name, entry] of Object.entries(config)) {\n result[name] = entry.previewPoint;\n }\n return result;\n}\n\n/**\n * Get all breakpoint names from the breakpoint configuration\n * Always includes 'base' plus all keys from the config\n * Order: base (desktop) -> breakpoints sorted by value descending (largest to smallest viewport)\n */\nexport function getAllBreakpointNames(\n breakpoints: BreakpointConfig = DEFAULT_BREAKPOINTS\n): BreakpointName[] {\n // Base is always included first\n const names: BreakpointName[] = ['base'];\n\n // Get all breakpoint names from config and sort by breakpoint value (descending)\n // This ensures proper order: largest viewport first\n const breakpointEntries = Object.entries(breakpoints);\n breakpointEntries.sort((a, b) => b[1].breakpoint - a[1].breakpoint); // Sort descending by breakpoint value\n\n // Add breakpoint names in sorted order\n for (const [name] of breakpointEntries) {\n names.push(name);\n }\n\n return names;\n}\n\n/**\n * Get active breakpoint name based on viewport width\n * Returns the smallest breakpoint that the viewport width is less than or equal to\n * If viewport is larger than all breakpoints, returns 'base'\n * Uses .breakpoint value for comparison (CSS threshold)\n */\nexport function getBreakpointName(\n viewportWidth: number,\n breakpoints: BreakpointConfig = DEFAULT_BREAKPOINTS\n): BreakpointName {\n // Sort breakpoints by breakpoint value (ascending) to find the smallest one that matches\n const breakpointEntries = Object.entries(breakpoints);\n breakpointEntries.sort((a, b) => a[1].breakpoint - b[1].breakpoint); // Sort ascending by breakpoint value\n\n // Find the smallest breakpoint that viewport width is <= to\n for (const [name, entry] of breakpointEntries) {\n if (viewportWidth <= entry.breakpoint) {\n return name;\n }\n }\n\n // If viewport is larger than all breakpoints, return 'base'\n return 'base';\n}\n\n/**\n * Get display label for a breakpoint\n * Priority:\n * 1. Label from config (if set)\n * 2. \"Desktop\" for 'base'\n * 3. Auto-capitalized name (camelCase -> Title Case)\n */\nexport function getBreakpointLabel(\n name: BreakpointName,\n breakpoints: BreakpointConfig = DEFAULT_BREAKPOINTS\n): string {\n // Base always returns \"Desktop\"\n if (name === 'base') {\n return 'Desktop';\n }\n\n // Check for custom label in config\n const entry = breakpoints[name];\n if (entry?.label) {\n return entry.label;\n }\n\n // Auto-format: camelCase -> Title Case\n // e.g., \"tabletLandscape\" -> \"Tablet Landscape\"\n return name\n .replace(/([A-Z])/g, ' $1')\n .replace(/^./, (str) => str.toUpperCase())\n .trim();\n}\n", "/**\n * CSS Property Definition structure\n */\ninterface CSSPropertyDefinition {\n values?: readonly string[];\n type?: 'string' | 'select' | 'boolean' | 'number';\n}\n\n/**\n * CSS Properties with their valid values and metadata\n * Used for autocomplete suggestions for both property names and values\n */\nexport const CSS_PROPERTIES_DEFINITION: Record<string, CSSPropertyDefinition> = {\n // Display & Layout\n display: {\n values: ['block', 'flex', 'grid', 'inline', 'inline-block', 'inline-flex', 'inline-grid', 'none'],\n type: 'select',\n },\n position: {\n values: ['static', 'relative', 'absolute', 'fixed', 'sticky'],\n type: 'select',\n },\n top: { type: 'string' },\n right: { type: 'string' },\n bottom: { type: 'string' },\n left: { type: 'string' },\n inset: { type: 'string' },\n zIndex: { type: 'number' },\n\n // Dimensions\n width: { type: 'string' },\n height: { type: 'string' },\n minWidth: { type: 'string' },\n maxWidth: { type: 'string' },\n minHeight: { type: 'string' },\n maxHeight: { type: 'string' },\n aspectRatio: { type: 'string' },\n\n // Spacing\n margin: { type: 'string' },\n marginTop: { type: 'string' },\n marginRight: { type: 'string' },\n marginBottom: { type: 'string' },\n marginLeft: { type: 'string' },\n padding: { type: 'string' },\n paddingTop: { type: 'string' },\n paddingRight: { type: 'string' },\n paddingBottom: { type: 'string' },\n paddingLeft: { type: 'string' },\n gap: { type: 'string' },\n rowGap: { type: 'string' },\n columnGap: { type: 'string' },\n\n // Borders\n border: { type: 'string' },\n borderWidth: { type: 'string' },\n borderStyle: {\n values: ['solid', 'dashed', 'dotted', 'double', 'groove', 'ridge', 'inset', 'outset', 'none'],\n type: 'select',\n },\n borderColor: { type: 'string' },\n borderTop: { type: 'string' },\n borderRight: { type: 'string' },\n borderBottom: { type: 'string' },\n borderLeft: { type: 'string' },\n borderRadius: { type: 'string' },\n borderTopLeftRadius: { type: 'string' },\n borderTopRightRadius: { type: 'string' },\n borderBottomLeftRadius: { type: 'string' },\n borderBottomRightRadius: { type: 'string' },\n\n // Background & Colors\n background: { type: 'string' },\n backgroundColor: { type: 'string' },\n backgroundImage: { type: 'string' },\n backgroundSize: {\n values: ['auto', 'cover', 'contain'],\n type: 'select',\n },\n backgroundPosition: {\n values: ['top', 'bottom', 'left', 'right', 'center'],\n type: 'select',\n },\n backgroundRepeat: {\n values: ['repeat', 'repeat-x', 'repeat-y', 'no-repeat'],\n type: 'select',\n },\n backgroundAttachment: {\n values: ['scroll', 'fixed', 'local'],\n type: 'select',\n },\n backgroundOrigin: {\n values: ['border-box', 'padding-box', 'content-box'],\n type: 'select',\n },\n backgroundBlendMode: {\n values: ['normal', 'multiply', 'screen', 'overlay', 'darken', 'lighten', 'color-dodge', 'color-burn', 'hard-light', 'soft-light', 'difference', 'exclusion', 'hue', 'saturation', 'color', 'luminosity'],\n type: 'select',\n },\n // Gradient-text recipe (`background: linear-gradient(...); background-clip:\n // text; -webkit-background-clip: text; -webkit-text-fill-color: transparent`).\n // The `Webkit*` capitalization is intentional \u2014 utilityClassMapper's\n // camel\u2192kebab emitter only prepends `-` when the first letter is uppercase,\n // so `WebkitBackgroundClip` round-trips back to `-webkit-background-clip`.\n backgroundClip: {\n values: ['border-box', 'padding-box', 'content-box', 'text'],\n type: 'select',\n },\n WebkitBackgroundClip: {\n values: ['border-box', 'padding-box', 'content-box', 'text'],\n type: 'select',\n },\n WebkitTextFillColor: { type: 'string' },\n WebkitTextStroke: { type: 'string' },\n WebkitTextStrokeWidth: { type: 'string' },\n WebkitTextStrokeColor: { type: 'string' },\n color: { type: 'string' },\n opacity: { type: 'number' },\n\n // Flexbox\n flex: { type: 'string' },\n flexDirection: {\n values: ['row', 'column', 'row-reverse', 'column-reverse'],\n type: 'select',\n },\n flexWrap: {\n values: ['nowrap', 'wrap', 'wrap-reverse'],\n type: 'select',\n },\n flexFlow: { type: 'string' },\n justifyContent: {\n values: ['flex-start', 'flex-end', 'center', 'space-between', 'space-around', 'space-evenly'],\n type: 'select',\n },\n alignItems: {\n values: ['flex-start', 'flex-end', 'center', 'stretch', 'baseline'],\n type: 'select',\n },\n alignContent: {\n values: ['flex-start', 'flex-end', 'center', 'space-between', 'space-around', 'stretch'],\n type: 'select',\n },\n alignSelf: {\n values: ['auto', 'flex-start', 'flex-end', 'center', 'stretch', 'baseline'],\n type: 'select',\n },\n flexGrow: { type: 'number' },\n flexShrink: { type: 'number' },\n flexBasis: { type: 'string' },\n order: { type: 'number' },\n\n // Grid\n grid: { type: 'string' },\n gridTemplateColumns: { type: 'string' },\n gridTemplateRows: { type: 'string' },\n gridTemplateAreas: { type: 'string' },\n gridGap: { type: 'string' },\n gridColumn: { type: 'string' },\n gridRow: { type: 'string' },\n gridArea: { type: 'string' },\n gridAutoFlow: {\n values: ['row', 'column', 'row dense', 'column dense'],\n type: 'select',\n },\n gridAutoColumns: { type: 'string' },\n gridAutoRows: { type: 'string' },\n justifyItems: {\n values: ['start', 'end', 'center', 'stretch'],\n type: 'select',\n },\n justifySelf: {\n values: ['auto', 'start', 'end', 'center', 'stretch'],\n type: 'select',\n },\n placeContent: { type: 'string' },\n placeItems: { type: 'string' },\n placeSelf: { type: 'string' },\n\n // Text & Font\n fontSize: { type: 'string' },\n fontWeight: {\n values: ['100', '200', '300', '400', '500', '600', '700', '800', '900', 'normal', 'bold'],\n type: 'select',\n },\n fontFamily: { type: 'string' },\n fontStyle: {\n values: ['normal', 'italic', 'oblique'],\n type: 'select',\n },\n lineHeight: { type: 'string' },\n textAlign: {\n values: ['left', 'right', 'center', 'justify', 'start', 'end'],\n type: 'select',\n },\n textDecoration: {\n values: ['none', 'underline', 'overline', 'line-through'],\n type: 'select',\n },\n textDecorationLine: {\n values: ['none', 'underline', 'overline', 'line-through'],\n type: 'select',\n },\n textDecorationStyle: {\n values: ['solid', 'double', 'dotted', 'dashed', 'wavy'],\n type: 'select',\n },\n textDecorationColor: { type: 'string' },\n textDecorationThickness: { type: 'string' },\n textUnderlineOffset: { type: 'string' },\n textUnderlinePosition: { type: 'string' },\n textTransform: {\n values: ['none', 'capitalize', 'uppercase', 'lowercase'],\n type: 'select',\n },\n textRendering: {\n values: ['auto', 'optimizeSpeed', 'optimizeLegibility', 'geometricPrecision'],\n type: 'select',\n },\n fontVariant: { type: 'string' },\n fontStretch: { type: 'string' },\n fontFeatureSettings: { type: 'string' },\n fontVariationSettings: { type: 'string' },\n fontKerning: {\n values: ['auto', 'normal', 'none'],\n type: 'select',\n },\n WebkitFontSmoothing: {\n values: ['auto', 'none', 'antialiased', 'subpixel-antialiased'],\n type: 'select',\n },\n MozOsxFontSmoothing: {\n values: ['auto', 'grayscale'],\n type: 'select',\n },\n hyphens: {\n values: ['none', 'manual', 'auto'],\n type: 'select',\n },\n WebkitHyphens: {\n values: ['none', 'manual', 'auto'],\n type: 'select',\n },\n writingMode: {\n values: ['horizontal-tb', 'vertical-rl', 'vertical-lr'],\n type: 'select',\n },\n direction: {\n values: ['ltr', 'rtl'],\n type: 'select',\n },\n tabSize: { type: 'string' },\n wordWrap: {\n values: ['normal', 'break-word'],\n type: 'select',\n },\n letterSpacing: { type: 'string' },\n wordSpacing: { type: 'string' },\n wordBreak: {\n values: ['normal', 'break-all', 'keep-all', 'break-word'],\n type: 'select',\n },\n overflowWrap: {\n values: ['normal', 'break-word', 'anywhere'],\n type: 'select',\n },\n textWrap: {\n values: ['wrap', 'nowrap', 'balance', 'pretty', 'stable'],\n type: 'select',\n },\n textIndent: { type: 'string' },\n verticalAlign: {\n values: ['baseline', 'top', 'middle', 'bottom', 'text-top', 'text-bottom', 'sub', 'super'],\n type: 'select',\n },\n\n // Box Shadow & Effects\n boxShadow: { type: 'string' },\n textShadow: { type: 'string' },\n filter: { type: 'string' },\n backdropFilter: { type: 'string' },\n WebkitBackdropFilter: { type: 'string' },\n transform: { type: 'string' },\n transformOrigin: { type: 'string' },\n transformStyle: {\n values: ['flat', 'preserve-3d'],\n type: 'select',\n },\n perspective: { type: 'string' },\n perspectiveOrigin: { type: 'string' },\n transition: { type: 'string' },\n transitionProperty: { type: 'string' },\n transitionDuration: { type: 'string' },\n transitionTimingFunction: { type: 'string' },\n transitionDelay: { type: 'string' },\n animation: { type: 'string' },\n backfaceVisibility: {\n values: ['visible', 'hidden'],\n type: 'select',\n },\n mixBlendMode: {\n values: ['normal', 'multiply', 'screen', 'overlay', 'darken', 'lighten', 'color-dodge', 'color-burn', 'hard-light', 'soft-light', 'difference', 'exclusion', 'hue', 'saturation', 'color', 'luminosity'],\n type: 'select',\n },\n isolation: {\n values: ['auto', 'isolate'],\n type: 'select',\n },\n willChange: { type: 'string' },\n imageRendering: {\n values: ['auto', 'crisp-edges', 'pixelated', 'smooth'],\n type: 'select',\n },\n clipPath: { type: 'string' },\n WebkitClipPath: { type: 'string' },\n // Mask family \u2014 gradient/SVG masks. Emit both the standard and `-webkit-`\n // form because Safari still needs the prefix.\n maskImage: { type: 'string' },\n WebkitMaskImage: { type: 'string' },\n maskSize: { type: 'string' },\n WebkitMaskSize: { type: 'string' },\n maskPosition: { type: 'string' },\n WebkitMaskPosition: { type: 'string' },\n maskRepeat: { type: 'string' },\n WebkitMaskRepeat: { type: 'string' },\n maskOrigin: { type: 'string' },\n WebkitMaskOrigin: { type: 'string' },\n maskClip: { type: 'string' },\n WebkitMaskClip: { type: 'string' },\n maskComposite: { type: 'string' },\n WebkitMaskComposite: { type: 'string' },\n maskMode: { type: 'string' },\n maskType: {\n values: ['luminance', 'alpha'],\n type: 'select',\n },\n\n // Overflow & Content\n overflow: {\n values: ['visible', 'hidden', 'scroll', 'auto'],\n type: 'select',\n },\n overflowX: {\n values: ['visible', 'hidden', 'scroll', 'auto'],\n type: 'select',\n },\n overflowY: {\n values: ['visible', 'hidden', 'scroll', 'auto'],\n type: 'select',\n },\n whiteSpace: {\n values: ['normal', 'nowrap', 'pre', 'pre-wrap', 'pre-line'],\n type: 'select',\n },\n textOverflow: {\n values: ['clip', 'ellipsis'],\n type: 'select',\n },\n visibility: {\n values: ['visible', 'hidden', 'collapse'],\n type: 'select',\n },\n content: { type: 'string' },\n\n // Cursor & Interaction\n cursor: {\n values: ['auto', 'default', 'pointer', 'wait', 'text', 'move', 'not-allowed', 'help'],\n type: 'select',\n },\n pointerEvents: {\n values: ['auto', 'none'],\n type: 'select',\n },\n userSelect: {\n values: ['auto', 'none', 'text', 'all'],\n type: 'select',\n },\n WebkitUserSelect: {\n values: ['auto', 'none', 'text', 'all'],\n type: 'select',\n },\n MozUserSelect: {\n values: ['auto', 'none', 'text', 'all'],\n type: 'select',\n },\n caretColor: { type: 'string' },\n appearance: {\n values: ['none', 'auto', 'menulist-button', 'textfield'],\n type: 'select',\n },\n WebkitAppearance: {\n values: ['none', 'auto', 'menulist-button', 'textfield'],\n type: 'select',\n },\n MozAppearance: {\n values: ['none', 'auto', 'menulist-button', 'textfield'],\n type: 'select',\n },\n\n // Outline\n outline: { type: 'string' },\n outlineWidth: { type: 'string' },\n outlineStyle: {\n values: ['none', 'solid', 'dashed', 'dotted', 'double', 'groove', 'ridge', 'inset', 'outset'],\n type: 'select',\n },\n outlineColor: { type: 'string' },\n outlineOffset: { type: 'string' },\n\n // Lists\n listStyle: { type: 'string' },\n listStyleType: {\n values: ['none', 'disc', 'circle', 'square', 'decimal', 'decimal-leading-zero', 'lower-roman', 'upper-roman', 'lower-alpha', 'upper-alpha'],\n type: 'select',\n },\n listStylePosition: {\n values: ['inside', 'outside'],\n type: 'select',\n },\n\n // Miscellaneous\n float: {\n values: ['left', 'right', 'none'],\n type: 'select',\n },\n clear: {\n values: ['left', 'right', 'both', 'none'],\n type: 'select',\n },\n boxSizing: {\n values: ['content-box', 'border-box'],\n type: 'select',\n },\n objectFit: {\n values: ['fill', 'contain', 'cover', 'scale-down'],\n type: 'select',\n },\n objectPosition: {\n values: ['top', 'bottom', 'left', 'right', 'center'],\n type: 'select',\n },\n resize: {\n values: ['none', 'both', 'horizontal', 'vertical'],\n type: 'select',\n },\n scrollBehavior: {\n values: ['auto', 'smooth'],\n type: 'select',\n },\n scrollSnapType: { type: 'string' },\n scrollSnapAlign: {\n values: ['none', 'start', 'end', 'center'],\n type: 'select',\n },\n scrollSnapStop: {\n values: ['normal', 'always'],\n type: 'select',\n },\n scrollMarginTop: { type: 'string' },\n scrollMarginRight: { type: 'string' },\n scrollMarginBottom: { type: 'string' },\n scrollMarginLeft: { type: 'string' },\n scrollPaddingTop: { type: 'string' },\n scrollPaddingRight: { type: 'string' },\n scrollPaddingBottom: { type: 'string' },\n scrollPaddingLeft: { type: 'string' },\n overscrollBehavior: {\n values: ['auto', 'contain', 'none'],\n type: 'select',\n },\n overscrollBehaviorX: {\n values: ['auto', 'contain', 'none'],\n type: 'select',\n },\n overscrollBehaviorY: {\n values: ['auto', 'contain', 'none'],\n type: 'select',\n },\n // CSS Containment \u2014 container queries depend on these.\n containerType: {\n values: ['normal', 'size', 'inline-size'],\n type: 'select',\n },\n containerName: { type: 'string' },\n accentColor: { type: 'string' },\n\n // SVG\n stroke: { type: 'string' },\n strokeWidth: { type: 'string' },\n strokeDasharray: { type: 'string' },\n strokeDashoffset: { type: 'string' },\n strokeLinecap: {\n values: ['butt', 'round', 'square'],\n type: 'select',\n },\n strokeLinejoin: {\n values: ['miter', 'round', 'bevel'],\n type: 'select',\n },\n strokeOpacity: { type: 'number' },\n fill: { type: 'string' },\n fillOpacity: { type: 'number' },\n fillRule: {\n values: ['nonzero', 'evenodd'],\n type: 'select',\n },\n};\n\n/**\n * Common CSS properties for autocomplete suggestions (camelCase for React/JS)\n * Derived from CSS_PROPERTIES_DEFINITION keys\n */\nexport const CSS_PROPERTIES = Object.keys(CSS_PROPERTIES_DEFINITION);\n\n/**\n * Popularity tiers for CSS properties (lower = more common).\n * Properties not listed default to tier 3.\n * Used to sort autocomplete suggestions within each match group.\n */\nconst CSS_PROPERTY_PRIORITY: Record<string, number> = {\n // Tier 1: Most commonly used\n display: 1,\n position: 1,\n width: 1,\n height: 1,\n margin: 1,\n padding: 1,\n color: 1,\n backgroundColor: 1,\n fontSize: 1,\n fontWeight: 1,\n border: 1,\n borderRadius: 1,\n flex: 1,\n flexDirection: 1,\n justifyContent: 1,\n alignItems: 1,\n gap: 1,\n opacity: 1,\n overflow: 1,\n zIndex: 1,\n top: 1,\n right: 1,\n bottom: 1,\n left: 1,\n cursor: 1,\n background: 1,\n boxShadow: 1,\n transition: 1,\n transform: 1,\n lineHeight: 1,\n textAlign: 1,\n\n // Tier 2: Common but less frequent\n maxWidth: 2,\n maxHeight: 2,\n minWidth: 3,\n minHeight: 3,\n marginTop: 2,\n marginBottom: 2,\n marginLeft: 2,\n marginRight: 2,\n paddingTop: 2,\n paddingBottom: 2,\n paddingLeft: 2,\n paddingRight: 2,\n fontFamily: 2,\n fontStyle: 2,\n textDecoration: 2,\n textTransform: 2,\n letterSpacing: 2,\n borderWidth: 2,\n borderStyle: 2,\n borderColor: 2,\n borderBottom: 2,\n borderTop: 2,\n flexWrap: 2,\n flexGrow: 2,\n flexShrink: 2,\n flexBasis: 2,\n alignSelf: 2,\n gridTemplateColumns: 2,\n gridTemplateRows: 2,\n backgroundImage: 2,\n backgroundSize: 2,\n backgroundPosition: 2,\n whiteSpace: 2,\n textOverflow: 2,\n visibility: 2,\n pointerEvents: 2,\n userSelect: 2,\n boxSizing: 2,\n objectFit: 2,\n filter: 2,\n animation: 2,\n outline: 2,\n inset: 2,\n};\n\nfunction getPropertyPriority(property: string): number {\n return CSS_PROPERTY_PRIORITY[property] ?? 3;\n}\n\n/**\n * CSS Property Groups for organizing styles in the editor\n * Order determines display order in the UI\n */\nexport const CSS_PROPERTY_GROUPS: Record<string, string[]> = {\n 'Layout': ['display'],\n 'Spacing': ['margin', 'marginTop', 'marginRight', 'marginBottom', 'marginLeft', 'padding', 'paddingTop', 'paddingRight', 'paddingBottom', 'paddingLeft'],\n 'Size': ['width', 'height', 'minWidth', 'maxWidth', 'minHeight', 'maxHeight', 'aspectRatio'],\n 'Position': ['position', 'top', 'right', 'bottom', 'left', 'inset', 'zIndex'],\n 'Flexbox': ['flex', 'flexDirection', 'flexWrap', 'flexFlow', 'justifyContent', 'alignItems', 'alignContent', 'gap', 'rowGap', 'columnGap', 'alignSelf', 'flexGrow', 'flexShrink', 'flexBasis', 'order'],\n 'Grid': ['grid', 'gridTemplateColumns', 'gridTemplateRows', 'gridTemplateAreas', 'gridGap', 'gridColumn', 'gridRow', 'gridArea', 'gridAutoFlow', 'gridAutoColumns', 'gridAutoRows', 'justifyItems', 'justifySelf', 'placeContent', 'placeItems', 'placeSelf'],\n 'Typography': ['fontWeight', 'fontSize', 'fontFamily', 'fontStyle', 'lineHeight', 'color', 'textAlign', 'textDecoration', 'textTransform', 'letterSpacing', 'wordSpacing', 'wordBreak', 'overflowWrap', 'textIndent', 'verticalAlign'],\n 'Background': ['background', 'backgroundColor', 'backgroundImage', 'backgroundSize', 'backgroundPosition', 'backgroundRepeat', 'opacity'],\n 'Borders': ['borderRadius', 'borderTopLeftRadius', 'borderTopRightRadius', 'borderBottomLeftRadius', 'borderBottomRightRadius', 'border', 'borderWidth', 'borderStyle', 'borderColor', 'borderTop', 'borderRight', 'borderBottom', 'borderLeft'],\n 'Outline': ['outline', 'outlineWidth', 'outlineStyle', 'outlineColor', 'outlineOffset'],\n 'Effects': ['boxShadow', 'textShadow', 'filter', 'backdropFilter', 'transform', 'transformOrigin', 'transition', 'animation', 'backfaceVisibility', 'mixBlendMode', 'clipPath'],\n 'Overflow': ['overflow', 'overflowX', 'overflowY', 'whiteSpace', 'textOverflow', 'visibility', 'content'],\n 'Interaction': ['cursor', 'pointerEvents', 'userSelect'],\n 'Lists': ['listStyle', 'listStyleType', 'listStylePosition'],\n 'Other': ['float', 'clear', 'boxSizing', 'objectFit', 'objectPosition', 'resize', 'scrollBehavior', 'accentColor'],\n 'SVG': ['stroke', 'strokeWidth', 'strokeDasharray', 'strokeDashoffset', 'strokeLinecap', 'strokeLinejoin', 'strokeOpacity', 'fill', 'fillOpacity', 'fillRule'],\n};\n\n/**\n * Get the group name for a CSS property\n * @param propertyName - The CSS property name\n * @returns The group name or 'Other' if not found\n */\nexport function getPropertyGroup(propertyName: string): string {\n for (const [groupName, properties] of Object.entries(CSS_PROPERTY_GROUPS)) {\n if (properties.includes(propertyName)) {\n return groupName;\n }\n }\n return 'Other';\n}\n\n/**\n * Subset of CSS properties shown as \"always-visible\" rows in the visual style\n * editor mode (Webflow-like). Each property here renders even when unset, so\n * the user can see at a glance which properties are available and click an\n * empty row to start typing a value.\n *\n * Keys must be group names from CSS_PROPERTY_GROUPS so the visual editor can\n * reuse the same group headers as list mode.\n */\nexport const VISUAL_MODE_PROPERTIES: Record<string, string[]> = {\n 'Layout': ['display'],\n 'Grid': ['gridTemplateColumns'],\n 'Flexbox': ['flexDirection', 'flexWrap', 'justifyContent', 'alignItems', 'gap', 'flexGrow', 'flexShrink', 'flexBasis'],\n 'Spacing': ['margin', 'marginTop', 'marginRight', 'marginBottom', 'marginLeft', 'padding', 'paddingTop', 'paddingRight', 'paddingBottom', 'paddingLeft'],\n 'Size': ['width', 'height', 'minWidth', 'minHeight', 'maxWidth', 'maxHeight'],\n 'Position': ['position', 'top', 'right', 'bottom', 'left', 'zIndex'],\n 'Typography': ['fontFamily', 'fontWeight', 'fontSize', 'lineHeight', 'color', 'letterSpacing', 'textAlign', 'textTransform', 'textDecoration'],\n 'Background': ['backgroundColor', 'backgroundImage', 'backgroundSize', 'backgroundPosition', 'backgroundRepeat', 'opacity'],\n 'Borders': ['borderRadius', 'borderWidth', 'borderStyle', 'borderColor'],\n 'Effects': ['boxShadow', 'transform', 'transition', 'filter'],\n 'Overflow': ['overflow', 'whiteSpace'],\n 'Interaction': ['cursor', 'pointerEvents'],\n};\n\nconst VISUAL_MODE_PROPERTIES_SET = new Set(\n Object.values(VISUAL_MODE_PROPERTIES).flat()\n);\n\n/**\n * True if `prop` belongs to the always-visible visual-mode list.\n */\nexport function isVisualModeProperty(prop: string): boolean {\n return VISUAL_MODE_PROPERTIES_SET.has(prop);\n}\n\n/**\n * Context used by visual-mode visibility rules. Captures everything a rule\n * needs to decide whether a property row is meaningful for the currently\n * selected element. Built once per render in `StyleEditor`.\n */\nexport interface VisualModeRuleContext {\n /** Effective `display` of the selected element \u2014 getComputedStyle().display\n * with declared (instance/inherited/effective) merge as fallback when the\n * iframe hasn't loaded yet. Defaults to 'block'. */\n display: string;\n /** Effective `display` of the DOM parent \u2014 used for flex/grid item props\n * whose applicability depends on the parent's layout mode. '' when no\n * parent is reachable (root element, iframe missing). */\n parentDisplay: string;\n /** Effective `position` of the selected element. Defaults to 'static'. */\n position: string;\n /** Lowercase HTML tag name of the selected element ('div', 'img', 'ul'\u2026). */\n tagName: string;\n /** True if any of paddingTop / paddingRight / paddingBottom / paddingLeft\n * is set anywhere in the cascade (instance + inherited + effective).\n * When true, the panel shows the four longhand rows and hides `padding`. */\n hasPaddingLonghand: boolean;\n /** Same as `hasPaddingLonghand` for the four `margin*` longhands. */\n hasMarginLonghand: boolean;\n /** True if `backgroundImage` (or the `background` shorthand) is set anywhere\n * in the cascade. Drives visibility of background-image-only properties\n * like `backgroundPosition` / `backgroundSize` / `backgroundRepeat`. */\n hasBackgroundImage: boolean;\n}\n\nexport type VisualModeRule = (ctx: VisualModeRuleContext) => boolean;\n\nconst isFlexDisplay = (d: string) => d === 'flex' || d === 'inline-flex';\nconst isGridDisplay = (d: string) => d === 'grid' || d === 'inline-grid';\nconst isListTag = (t: string) => t === 'ul' || t === 'ol' || t === 'li';\nconst isMediaTag = (t: string) => t === 'img' || t === 'video';\n\n/**\n * Visibility rules for the visual-mode style panel. Each entry is a predicate\n * that returns true when the row should be rendered for the current element\n * context. Properties without an entry are always visible. Properties that\n * are *explicitly set* on the element bypass these rules (the explicit-value\n * override is enforced by the caller, not here).\n */\nexport const VISUAL_MODE_RULES: Record<string, VisualModeRule> = {\n // Flex/Grid CONTAINER props \u2014 own display must be flex/grid.\n flexDirection: ctx => isFlexDisplay(ctx.display),\n flexWrap: ctx => isFlexDisplay(ctx.display),\n justifyContent: ctx => isFlexDisplay(ctx.display) || isGridDisplay(ctx.display),\n alignItems: ctx => isFlexDisplay(ctx.display) || isGridDisplay(ctx.display),\n alignContent: ctx => isFlexDisplay(ctx.display) || isGridDisplay(ctx.display),\n gap: ctx => isFlexDisplay(ctx.display) || isGridDisplay(ctx.display),\n rowGap: ctx => isFlexDisplay(ctx.display) || isGridDisplay(ctx.display),\n columnGap: ctx => isFlexDisplay(ctx.display) || isGridDisplay(ctx.display),\n gridTemplateColumns: ctx => isGridDisplay(ctx.display),\n gridTemplateRows: ctx => isGridDisplay(ctx.display),\n gridTemplateAreas: ctx => isGridDisplay(ctx.display),\n gridGap: ctx => isGridDisplay(ctx.display),\n gridAutoFlow: ctx => isGridDisplay(ctx.display),\n gridAutoColumns: ctx => isGridDisplay(ctx.display),\n gridAutoRows: ctx => isGridDisplay(ctx.display),\n justifyItems: ctx => isGridDisplay(ctx.display),\n placeItems: ctx => isGridDisplay(ctx.display),\n placeContent: ctx => isGridDisplay(ctx.display),\n\n // Flex/Grid ITEM props \u2014 PARENT display must be flex/grid.\n flex: ctx => isFlexDisplay(ctx.parentDisplay),\n flexFlow: ctx => isFlexDisplay(ctx.parentDisplay),\n flexGrow: ctx => isFlexDisplay(ctx.parentDisplay),\n flexShrink: ctx => isFlexDisplay(ctx.parentDisplay),\n flexBasis: ctx => isFlexDisplay(ctx.parentDisplay),\n alignSelf: ctx => isFlexDisplay(ctx.parentDisplay) || isGridDisplay(ctx.parentDisplay),\n justifySelf: ctx => isGridDisplay(ctx.parentDisplay),\n placeSelf: ctx => isGridDisplay(ctx.parentDisplay),\n order: ctx => isFlexDisplay(ctx.parentDisplay) || isGridDisplay(ctx.parentDisplay),\n gridArea: ctx => isGridDisplay(ctx.parentDisplay),\n gridColumn: ctx => isGridDisplay(ctx.parentDisplay),\n gridRow: ctx => isGridDisplay(ctx.parentDisplay),\n\n // Position-dependent inset properties.\n top: ctx => ctx.position !== 'static',\n right: ctx => ctx.position !== 'static',\n bottom: ctx => ctx.position !== 'static',\n left: ctx => ctx.position !== 'static',\n inset: ctx => ctx.position !== 'static',\n zIndex: ctx => ctx.position !== 'static',\n\n // Tag-based.\n objectFit: ctx => isMediaTag(ctx.tagName),\n objectPosition: ctx => isMediaTag(ctx.tagName),\n listStyle: ctx => isListTag(ctx.tagName),\n listStyleType: ctx => isListTag(ctx.tagName),\n listStylePosition: ctx => isListTag(ctx.tagName),\n\n // Padding/margin shorthand-vs-longhand auto-toggle.\n // When ANY longhand is set, hide shorthand; otherwise hide longhands.\n padding: ctx => !ctx.hasPaddingLonghand,\n paddingTop: ctx => ctx.hasPaddingLonghand,\n paddingRight: ctx => ctx.hasPaddingLonghand,\n paddingBottom: ctx => ctx.hasPaddingLonghand,\n paddingLeft: ctx => ctx.hasPaddingLonghand,\n margin: ctx => !ctx.hasMarginLonghand,\n marginTop: ctx => ctx.hasMarginLonghand,\n marginRight: ctx => ctx.hasMarginLonghand,\n marginBottom: ctx => ctx.hasMarginLonghand,\n marginLeft: ctx => ctx.hasMarginLonghand,\n\n // Background-image-only props \u2014 meaningless without a background image.\n backgroundPosition: ctx => ctx.hasBackgroundImage,\n backgroundSize: ctx => ctx.hasBackgroundImage,\n backgroundRepeat: ctx => ctx.hasBackgroundImage,\n};\n\n/**\n * True if `prop` should be visible in the visual-mode panel given `ctx`.\n * Properties without an entry in `VISUAL_MODE_RULES` default to visible.\n * Callers are responsible for the explicit-value override (a property that\n * the user has set must remain visible regardless of the rule outcome).\n */\nexport function isVisualModeRowVisible(prop: string, ctx: VisualModeRuleContext): boolean {\n const rule = VISUAL_MODE_RULES[prop];\n return rule ? rule(ctx) : true;\n}\n\n/**\n * Check if property matches the abbreviation pattern\n * For example, \"bC\" matches \"backgroundColor\" (b\u2192b, C\u2192C capital letter)\n */\nfunction matchesAbbreviation(property: string, input: string): boolean {\n if (!input) return false;\n\n let propertyIndex = 0;\n\n for (let inputIndex = 0; inputIndex < input.length; inputIndex++) {\n const inputChar = input[inputIndex];\n let found = false;\n\n // Search from current position to end of property for a match at a word boundary\n while (propertyIndex < property.length) {\n const propChar = property[propertyIndex];\n // Word boundary = first character OR capital letter\n const isWordBoundary = propertyIndex === 0 ||\n (propChar === propChar.toUpperCase() && propChar !== propChar.toLowerCase());\n\n if (isWordBoundary && inputChar.toLowerCase() === propChar.toLowerCase()) {\n // Match found at word boundary\n found = true;\n propertyIndex++; // Move past this character for next search\n break;\n }\n\n propertyIndex++;\n }\n\n if (!found) {\n return false; // Couldn't find this input character at a word boundary\n }\n }\n\n return true;\n}\n\n/**\n * Direction-abbreviation shortcuts. When the user types one of these exact\n * inputs, the mapped property is forced to the top of the suggestions list\n * (ahead of startsWith matches like `placeContent` for \"pl\"). \"u\" stands for\n * \"up\" \u2014 a natural mnemonic for `Top`.\n */\nconst PROPERTY_SHORTCUTS: Record<string, string> = {\n pl: 'paddingLeft',\n pr: 'paddingRight',\n pt: 'paddingTop',\n pu: 'paddingTop',\n pb: 'paddingBottom',\n ml: 'marginLeft',\n mr: 'marginRight',\n mt: 'marginTop',\n mu: 'marginTop',\n mb: 'marginBottom',\n};\n\n/**\n * Filter CSS properties based on input value\n * Supports both startsWith matching and camelCase abbreviation matching\n */\nexport function filterCSSProperties(input: string): string[] {\n const normalizedInput = (input ?? '').trim();\n if (!normalizedInput) {\n return CSS_PROPERTIES.slice(0, 15); // Show first 15 by default\n }\n\n // First, try startsWith matching (exact prefix match)\n const startsWithMatches = CSS_PROPERTIES.filter(prop =>\n prop.toLowerCase().startsWith(normalizedInput.toLowerCase())\n );\n\n // Then, try abbreviation/fuzzy matching\n const abbreviationMatches = CSS_PROPERTIES.filter(prop =>\n matchesAbbreviation(prop, normalizedInput) &&\n !startsWithMatches.includes(prop) // Don't duplicate startsWith matches\n );\n\n // Sort each group by popularity, then combine: exact matches first, then fuzzy matches\n const byPriority = (a: string, b: string) =>\n getPropertyPriority(a) - getPropertyPriority(b);\n\n const combined = [\n ...startsWithMatches.sort(byPriority),\n ...abbreviationMatches.sort(byPriority),\n ];\n\n const shortcut = PROPERTY_SHORTCUTS[normalizedInput.toLowerCase()];\n if (shortcut) {\n return [shortcut, ...combined.filter(prop => prop !== shortcut)];\n }\n\n return combined;\n}\n\n/**\n * Get available values for a specific CSS property\n * @param propertyName - The CSS property name (e.g., 'flexDirection')\n * @returns Array of valid values for the property, or empty array if property has no predefined values\n */\nexport function getPropertyValues(propertyName: string): string[] {\n const values = CSS_PROPERTIES_DEFINITION[propertyName]?.values;\n return values ? Array.from(values) : [];\n}\n\n/**\n * Filter values for a specific CSS property based on input\n * Supports substring matching and returns values that contain the input\n * @param propertyName - The CSS property name (e.g., 'flexDirection')\n * @param input - The user input to filter values by\n * @returns Filtered array of valid values for the property\n */\nexport function filterPropertyValues(propertyName: string, input: string): string[] {\n const values = getPropertyValues(propertyName);\n if (!values.length) {\n return []; // No predefined values for this property\n }\n\n const normalizedInput = (input ?? '').trim().toLowerCase();\n if (!normalizedInput) {\n return values; // Return all values if no input\n }\n\n // Filter values that contain the input (substring match)\n return values.filter(value =>\n value.toLowerCase().includes(normalizedInput)\n );\n}\n\n/**\n * Get the property type for a CSS property\n * @param propertyName - The CSS property name\n * @returns The property type ('string' | 'select' | 'boolean' | 'number') or undefined\n */\nexport function getPropertyType(propertyName: string): 'string' | 'select' | 'boolean' | 'number' | undefined {\n return CSS_PROPERTIES_DEFINITION[propertyName]?.type;\n}\n\n/**\n * CSS properties whose numeric values are unitless by spec \u2014 `font-weight: 400`,\n * `line-height: 1.5`, `opacity: 0.8`, `z-index: 10`, etc. The auto-px commit\n * normalizer must NOT append `px` to bare numbers for these.\n */\nexport const UNITLESS_PROPERTIES: ReadonlySet<string> = new Set([\n 'fontWeight', 'lineHeight',\n 'opacity', 'fillOpacity', 'strokeOpacity', 'stopOpacity',\n 'zIndex', 'order',\n 'flexGrow', 'flexShrink', 'flex',\n 'columnCount', 'columns', 'tabSize', 'orphans', 'widows',\n 'gridRow', 'gridColumn', 'gridRowStart', 'gridRowEnd',\n 'gridColumnStart', 'gridColumnEnd',\n 'animationIterationCount',\n 'aspectRatio',\n 'scale',\n]);\n\n/**\n * Whether bare numeric values for `propertyName` should be treated as pixels at\n * commit time (e.g. typing `52` for `width` becomes `52px`). Unitless props,\n * `select`/`boolean` keyword props, and existing `number`-typed entries return false.\n */\nexport function appendsPxByDefault(propertyName: string): boolean {\n if (UNITLESS_PROPERTIES.has(propertyName)) return false;\n const def = CSS_PROPERTIES_DEFINITION[propertyName];\n if (def?.type === 'select' || def?.type === 'boolean' || def?.type === 'number') return false;\n return true;\n}\n", "/**\n * Centralized configuration for utility class mappings\n * Single source of truth for property-to-prefix and CSS generation\n */\n\n// Mapping of CSS properties to utility class prefixes\nexport const propertyMap: Record<string, string> = {\n // Padding\n padding: 'p',\n paddingTop: 'pt',\n paddingRight: 'pr',\n paddingBottom: 'pb',\n paddingLeft: 'pl',\n paddingInline: 'px',\n paddingBlock: 'py',\n\n // Margin\n margin: 'm',\n marginTop: 'mt',\n marginRight: 'mr',\n marginBottom: 'mb',\n marginLeft: 'ml',\n marginInline: 'mx',\n marginBlock: 'my',\n\n // Display & Layout\n display: 'd',\n flexDirection: 'fd',\n justifyContent: 'jc',\n alignItems: 'ai',\n alignContent: 'ac',\n flex: 'flex',\n flexWrap: 'fw',\n gap: 'g',\n rowGap: 'rg',\n columnGap: 'cg',\n\n // Sizing\n width: 'w',\n height: 'h',\n maxWidth: 'mw',\n maxHeight: 'mh',\n minWidth: 'miw',\n minHeight: 'mih',\n aspectRatio: 'ar',\n\n // Colors & Background\n backgroundColor: 'bgc',\n background: 'bg',\n backgroundImage: 'bgi',\n color: 'c',\n\n // Borders & Radius\n border: 'b',\n borderRadius: 'br',\n borderTop: 'bt',\n borderRight: 'border-r',\n borderBottom: 'bb',\n borderLeft: 'bl',\n borderTopLeftRadius: 'brtl',\n borderTopRightRadius: 'brtr',\n borderBottomLeftRadius: 'brbl',\n borderBottomRightRadius: 'brbr',\n borderColor: 'bc',\n\n // Text\n fontSize: 'fs',\n fontWeight: 'fe',\n fontFamily: 'ff',\n textAlign: 'ta',\n textDecoration: 'td',\n textTransform: 'tt',\n lineHeight: 'lh',\n letterSpacing: 'ls',\n wordBreak: 'wb',\n overflowWrap: 'ow',\n textIndent: 'ti',\n verticalAlign: 'va',\n whiteSpace: 'whs',\n\n // Lists\n listStyle: 'lst',\n listStyleType: 'lstt',\n listStylePosition: 'lstp',\n\n // Transform & Effects\n opacity: 'o',\n transform: 'tm',\n transformOrigin: 'tmo',\n boxShadow: 'bsh',\n textShadow: 'ts',\n filter: 'flt',\n backdropFilter: 'bdf',\n backfaceVisibility: 'bfv',\n mixBlendMode: 'mbm',\n clipPath: 'cp',\n\n // Positioning\n position: 'pos',\n top: 'top',\n right: 'r',\n bottom: 'bo',\n left: 'l',\n inset: 'ins',\n zIndex: 'z',\n\n // Grid Layout\n gridTemplateColumns: 'gtc',\n gridTemplateRows: 'gtr',\n gridTemplateAreas: 'gta',\n gridGap: 'gg',\n gridAutoFlow: 'gaf',\n gridColumn: 'gc',\n gridRow: 'gr',\n gridArea: 'ga',\n gridAutoRows: 'gar',\n gridAutoColumns: 'gac',\n justifyItems: 'ji',\n justifySelf: 'jse',\n placeContent: 'plc',\n placeItems: 'pli',\n placeSelf: 'pls',\n\n // Flexbox extras\n flexGrow: 'fg',\n flexShrink: 'fsh',\n flexBasis: 'fb',\n order: 'ord',\n alignSelf: 'as',\n\n // Outline\n outline: 'ol',\n outlineWidth: 'olw',\n outlineStyle: 'ols',\n outlineColor: 'olc',\n outlineOffset: 'olo',\n\n // Other\n overflow: 'ov',\n overflowX: 'ovx',\n overflowY: 'ovy',\n cursor: 'cu',\n pointerEvents: 'pe',\n userSelect: 'us',\n transition: 'tn',\n objectFit: 'objf',\n objectPosition: 'objp',\n boxSizing: 'bsz',\n visibility: 'vis',\n resize: 'rsz',\n scrollBehavior: 'scb',\n accentColor: 'acc',\n};\n\n// Mapping of prefixes to CSS property names for dynamic rule generation\nexport const prefixToCSSProperty: Record<string, string> = {\n // Spacing\n p: 'padding',\n pt: 'padding-top',\n pr: 'padding-right',\n pb: 'padding-bottom',\n pl: 'padding-left',\n px: 'padding',\n py: 'padding',\n m: 'margin',\n mt: 'margin-top',\n mr: 'margin-right',\n mb: 'margin-bottom',\n ml: 'margin-left',\n mx: 'margin',\n my: 'margin',\n g: 'gap',\n rg: 'row-gap',\n cg: 'column-gap',\n\n // Sizing\n w: 'width',\n h: 'height',\n mw: 'max-width',\n mh: 'max-height',\n miw: 'min-width',\n mih: 'min-height',\n ar: 'aspect-ratio',\n\n // Colors & Background\n bgc: 'background-color',\n bg: 'background',\n bgi: 'background-image',\n c: 'color',\n bc: 'border-color',\n\n // Borders\n b: 'border',\n br: 'border-radius',\n brtl: 'border-top-left-radius',\n brtr: 'border-top-right-radius',\n brbl: 'border-bottom-left-radius',\n brbr: 'border-bottom-right-radius',\n bt: 'border-top',\n bb: 'border-bottom',\n bl: 'border-left',\n 'border-r': 'border-right',\n\n // Text\n fs: 'font-size',\n fe: 'font-weight',\n ff: 'font-family',\n ta: 'text-align',\n td: 'text-decoration',\n tt: 'text-transform',\n lh: 'line-height',\n ls: 'letter-spacing',\n wb: 'word-break',\n ow: 'overflow-wrap',\n ti: 'text-indent',\n va: 'vertical-align',\n whs: 'white-space',\n\n // Lists\n lst: 'list-style',\n lstt: 'list-style-type',\n lstp: 'list-style-position',\n\n // Display\n d: 'display',\n\n // Flexbox\n fd: 'flex-direction',\n jc: 'justify-content',\n ai: 'align-items',\n ac: 'align-content',\n as: 'align-self',\n flex: 'flex',\n fw: 'flex-wrap',\n fg: 'flex-grow',\n fsh: 'flex-shrink',\n fb: 'flex-basis',\n ord: 'order',\n\n // Grid\n gtc: 'grid-template-columns',\n gtr: 'grid-template-rows',\n gta: 'grid-template-areas',\n gg: 'grid-gap',\n gaf: 'grid-auto-flow',\n gc: 'grid-column',\n gr: 'grid-row',\n ga: 'grid-area',\n gar: 'grid-auto-rows',\n gac: 'grid-auto-columns',\n ji: 'justify-items',\n jse: 'justify-self',\n plc: 'place-content',\n pli: 'place-items',\n pls: 'place-self',\n\n // Effects\n o: 'opacity',\n tm: 'transform',\n tmo: 'transform-origin',\n bsh: 'box-shadow',\n ts: 'text-shadow',\n flt: 'filter',\n bdf: 'backdrop-filter',\n bfv: 'backface-visibility',\n mbm: 'mix-blend-mode',\n cp: 'clip-path',\n\n // Positioning\n pos: 'position',\n top: 'top',\n r: 'right',\n bo: 'bottom',\n l: 'left',\n ins: 'inset',\n z: 'z-index',\n\n // Outline\n ol: 'outline',\n olw: 'outline-width',\n ols: 'outline-style',\n olc: 'outline-color',\n olo: 'outline-offset',\n\n // Other\n ov: 'overflow',\n ovx: 'overflow-x',\n ovy: 'overflow-y',\n cu: 'cursor',\n pe: 'pointer-events',\n us: 'user-select',\n tn: 'transition',\n objf: 'object-fit',\n objp: 'object-position',\n bsz: 'box-sizing',\n vis: 'visibility',\n rsz: 'resize',\n scb: 'scroll-behavior',\n acc: 'accent-color',\n};\n\n// Special value mappings for specific properties\nexport const specialValueMappings: Record<string, Record<string, string>> = {\n display: {\n flex: 'f',\n grid: 'g',\n block: 'b',\n inline: 'i',\n 'inline-block': 'ib',\n none: 'h',\n 'inline-flex': 'if',\n 'inline-grid': 'ig',\n },\n flexDirection: {\n column: 'fd-col',\n row: 'fd-row',\n },\n justifyContent: {\n center: 'jc-c',\n 'flex-start': 'jc-s',\n 'flex-end': 'jc-e',\n 'space-between': 'jc-b',\n 'space-around': 'jc-a',\n 'space-evenly': 'jc-ev',\n },\n alignItems: {\n center: 'ai-c',\n 'flex-start': 'ai-s',\n 'flex-end': 'ai-e',\n stretch: 'ai-st',\n baseline: 'ai-b',\n },\n overflow: {\n hidden: 'o-h',\n auto: 'o-a',\n scroll: 'o-s',\n visible: 'o-v',\n },\n cursor: {\n pointer: 'cursor-pointer',\n default: 'cursor-default',\n },\n pointerEvents: {\n none: 'pe-none',\n auto: 'pe-auto',\n },\n userSelect: {\n none: 'us-none',\n auto: 'us-auto',\n text: 'us-text',\n all: 'us-all',\n },\n whiteSpace: {\n normal: 'whs-normal',\n nowrap: 'whs-nowrap',\n pre: 'whs-pre',\n 'pre-wrap': 'whs-pre-wrap',\n 'pre-line': 'whs-pre-line',\n },\n // Note: CSS functions (blur, translateY, scale, rotate, repeat) are now handled\n // dynamically in utilityClassMapper.ts - no need to hardcode specific values here\n};\n\n// Reverse mapping for class-to-style conversion\nexport const classToStyleSpecialCases: Record<string, { prop: string; value: string }> = {\n f: { prop: 'display', value: 'flex' },\n 'fd-col': { prop: 'flexDirection', value: 'column' },\n 'fd-row': { prop: 'flexDirection', value: 'row' },\n g: { prop: 'display', value: 'grid' },\n b: { prop: 'display', value: 'block' },\n i: { prop: 'display', value: 'inline' },\n ib: { prop: 'display', value: 'inline-block' },\n h: { prop: 'display', value: 'none' },\n 'if': { prop: 'display', value: 'inline-flex' },\n ig: { prop: 'display', value: 'inline-grid' },\n 'jc-c': { prop: 'justifyContent', value: 'center' },\n 'jc-s': { prop: 'justifyContent', value: 'flex-start' },\n 'jc-e': { prop: 'justifyContent', value: 'flex-end' },\n 'jc-b': { prop: 'justifyContent', value: 'space-between' },\n 'jc-a': { prop: 'justifyContent', value: 'space-around' },\n 'jc-ev': { prop: 'justifyContent', value: 'space-evenly' },\n 'ai-c': { prop: 'alignItems', value: 'center' },\n 'ai-s': { prop: 'alignItems', value: 'flex-start' },\n 'ai-e': { prop: 'alignItems', value: 'flex-end' },\n 'ai-st': { prop: 'alignItems', value: 'stretch' },\n 'ai-b': { prop: 'alignItems', value: 'baseline' },\n 'o-h': { prop: 'overflow', value: 'hidden' },\n 'o-a': { prop: 'overflow', value: 'auto' },\n 'o-s': { prop: 'overflow', value: 'scroll' },\n 'o-v': { prop: 'overflow', value: 'visible' },\n 'cursor-pointer': { prop: 'cursor', value: 'pointer' },\n 'cursor-default': { prop: 'cursor', value: 'default' },\n 'pe-none': { prop: 'pointerEvents', value: 'none' },\n 'pe-auto': { prop: 'pointerEvents', value: 'auto' },\n 'us-none': { prop: 'userSelect', value: 'none' },\n 'us-auto': { prop: 'userSelect', value: 'auto' },\n 'us-text': { prop: 'userSelect', value: 'text' },\n 'us-all': { prop: 'userSelect', value: 'all' },\n 'whs-normal': { prop: 'whiteSpace', value: 'normal' },\n 'whs-nowrap': { prop: 'whiteSpace', value: 'nowrap' },\n 'whs-pre': { prop: 'whiteSpace', value: 'pre' },\n 'whs-pre-wrap': { prop: 'whiteSpace', value: 'pre-wrap' },\n 'whs-pre-line': { prop: 'whiteSpace', value: 'pre-line' },\n // Grid template columns\n 'gtc-2': { prop: 'gridTemplateColumns', value: 'repeat(2, 1fr)' },\n 'gtc-3': { prop: 'gridTemplateColumns', value: 'repeat(3, 1fr)' },\n 'gtc-4': { prop: 'gridTemplateColumns', value: 'repeat(4, 1fr)' },\n 'gtc-5': { prop: 'gridTemplateColumns', value: 'repeat(5, 1fr)' },\n 'gtc-6': { prop: 'gridTemplateColumns', value: 'repeat(6, 1fr)' },\n // Backdrop filter\n 'bdf-blur-4': { prop: 'backdropFilter', value: 'blur(4px)' },\n 'bdf-blur-8': { prop: 'backdropFilter', value: 'blur(8px)' },\n 'bdf-blur-10': { prop: 'backdropFilter', value: 'blur(10px)' },\n // Transform\n 'tm-ty-0': { prop: 'transform', value: 'translateY(0)' },\n 'tm-ty-n10': { prop: 'transform', value: 'translateY(-10px)' },\n 'tm-ty-n50p': { prop: 'transform', value: 'translateY(-50%)' },\n // Filter\n 'flt-blur-1': { prop: 'filter', value: 'blur(1px)' },\n // Shadow presets (reverse mapping)\n 'sh-0': { prop: 'boxShadow', value: 'none' },\n 'sh-1': { prop: 'boxShadow', value: '0 1px 2px rgba(0, 0, 0, 0.05)' },\n 'sh-2': { prop: 'boxShadow', value: '0 4px 12px rgba(0, 0, 0, 0.1)' },\n 'sh-3': { prop: 'boxShadow', value: '0 8px 24px rgba(0, 0, 0, 0.15)' },\n 'sh-4': { prop: 'boxShadow', value: '0 12px 32px rgba(0, 0, 0, 0.2)' },\n // Gradient presets (reverse mapping)\n 'gr-1': { prop: 'background', value: 'linear-gradient(90deg, rgba(10,22,40,0.85) 0%, rgba(10,22,40,0.2) 100%)' },\n 'gr-2': { prop: 'background', value: 'linear-gradient(0deg, #a9e8fd, #00aee8 25%, #0f1335 72%)' },\n // Border presets (reverse mapping)\n 'bd-0': { prop: 'border', value: '1px solid var(--border)' },\n 'bd-1': { prop: 'border', value: '1px solid var(--border-light)' },\n};\n\n// ============================================================================\n// STYLE PRESETS\n// Predefined values for complex CSS properties (shadows, gradients, borders)\n// Usage: boxShadow: \"2\" \u2192 class \"sh-2\" \u2192 \"box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1)\"\n// ============================================================================\n\n// Shadow presets: sh-0, sh-1, sh-2, sh-3, sh-4\nexport const shadowPresets: Record<string, string> = {\n '0': 'none',\n '1': '0 1px 2px rgba(0, 0, 0, 0.05)',\n '2': '0 4px 12px rgba(0, 0, 0, 0.1)',\n '3': '0 8px 24px rgba(0, 0, 0, 0.15)',\n '4': '0 12px 32px rgba(0, 0, 0, 0.2)',\n};\n\n// Gradient presets: gr-1, gr-2\nexport const gradientPresets: Record<string, string> = {\n '1': 'linear-gradient(90deg, rgba(10,22,40,0.85) 0%, rgba(10,22,40,0.2) 100%)',\n '2': 'linear-gradient(0deg, #a9e8fd, #00aee8 25%, #0f1335 72%)',\n};\n\n// Border presets: bd-0, bd-1\nexport const borderPresets: Record<string, string> = {\n '0': '1px solid var(--border)',\n '1': '1px solid var(--border-light)',\n};\n", "/**\n * Responsive Scaling Calculator\n * Automatically calculates responsive values for different breakpoints\n * using configured scale multipliers\n */\n\n/**\n * Scale configuration for a CSS property category\n * Keys are breakpoint names (e.g., 'tablet', 'mobile', 'small')\n * Values are scale multipliers (e.g., 0.88, 0.75)\n */\nexport type BreakpointScales = Record<string, number>;\n\nexport type ResponsiveMode = 'breakpoints' | 'fluid';\n\nexport interface FluidRange {\n /** Lower viewport bound in pixels (e.g. 320) */\n min: number;\n /** Upper viewport bound in pixels (e.g. 1440) */\n max: number;\n}\n\nexport interface SiteMarginConfig {\n /** Lower bound of the side margin at smallest viewport (px). */\n min: number;\n /** Upper bound of the side margin at largest viewport (px). */\n max: number;\n}\n\nexport interface ResponsiveScales {\n enabled: boolean;\n /** Scaling strategy. Missing \u2192 'breakpoints' (back-compat with old configs). */\n mode?: ResponsiveMode;\n baseReference: number;\n /** Viewport bounds used when `mode === 'fluid'`. Defaults to 320 / 1440 px. */\n fluidRange?: FluidRange;\n /**\n * Container side margin range, in fluid mode emitted as a CSS variable\n * `--site-margin: clamp(min, \u2026, max)` on `:root`. Lets users write\n * `width: calc(100% - var(--site-margin) * 2)` for the container pattern.\n */\n siteMargin?: SiteMarginConfig;\n fontSize?: BreakpointScales;\n padding?: BreakpointScales;\n margin?: BreakpointScales;\n gap?: BreakpointScales;\n borderRadius?: BreakpointScales;\n size?: BreakpointScales;\n [key: string]: boolean | number | string | BreakpointScales | FluidRange | SiteMarginConfig | undefined;\n}\n\nexport const DEFAULT_FLUID_RANGE: FluidRange = { min: 320, max: 1440 };\nexport const DEFAULT_SITE_MARGIN: SiteMarginConfig = { min: 16, max: 32 };\n\nexport type CSSPropertyType = 'fontSize' | 'padding' | 'margin' | 'gap' | 'paddingTop' | 'paddingRight' | 'paddingBottom' | 'paddingLeft' | 'marginTop' | 'marginRight' | 'marginBottom' | 'marginLeft' | 'rowGap' | 'columnGap' | 'borderRadius' | 'borderTopLeftRadius' | 'borderTopRightRadius' | 'borderBottomLeftRadius' | 'borderBottomRightRadius' | 'width' | 'height' | 'maxWidth' | 'maxHeight' | 'minWidth' | 'minHeight';\n\n/**\n * Map CSS property to its scale category\n * e.g., paddingTop -> padding, marginRight -> margin\n */\nfunction getScaleCategory(property: CSSPropertyType): keyof ResponsiveScales | null {\n const propertyStr = property as string;\n if (property === 'fontSize') return 'fontSize';\n if (propertyStr.startsWith('padding')) return 'padding';\n if (propertyStr.startsWith('margin')) return 'margin';\n if (property === 'gap' || property === 'rowGap' || property === 'columnGap') return 'gap';\n if (propertyStr === 'borderRadius' || (propertyStr.startsWith('border') && propertyStr.includes('Radius'))) return 'borderRadius';\n if (property === 'width' || property === 'height' || property === 'maxWidth' || property === 'maxHeight' || property === 'minWidth' || property === 'minHeight') return 'size';\n return null;\n}\n\n/**\n * Extract numeric value and unit from a CSS value string\n * e.g., \"67px\" -> { value: 67, unit: \"px\" }\n */\nexport function parseValue(valueStr: string): { value: number; unit: string } | null {\n const match = valueStr.trim().match(/^(-?[\\d.]+)(px|rem|em|%|pt)$/);\n if (!match) return null;\n return {\n value: parseFloat(match[1]),\n unit: match[2],\n };\n}\n\n/**\n * CSS properties that get fluid `clamp()` / breakpoint scaling. Mirrors the\n * `AUTO_RESPONSIVE_TYPE_MAP` keys in `cssGeneration.ts`; centralized here so\n * `utilityClassMapper.ts` can consult it without a cross-module import cycle.\n */\nexport const SCALABLE_CSS_PROPERTIES: ReadonlySet<string> = new Set([\n 'padding',\n 'padding-left',\n 'padding-right',\n 'padding-top',\n 'padding-bottom',\n 'paddingLeft',\n 'paddingRight',\n 'paddingTop',\n 'paddingBottom',\n 'margin',\n 'margin-left',\n 'margin-right',\n 'margin-top',\n 'margin-bottom',\n 'marginLeft',\n 'marginRight',\n 'marginTop',\n 'marginBottom',\n 'font-size',\n 'fontSize',\n 'gap',\n 'row-gap',\n 'column-gap',\n 'rowGap',\n 'columnGap',\n 'border-radius',\n 'borderRadius',\n 'border-top-left-radius',\n 'border-top-right-radius',\n 'border-bottom-left-radius',\n 'border-bottom-right-radius',\n 'borderTopLeftRadius',\n 'borderTopRightRadius',\n 'borderBottomLeftRadius',\n 'borderBottomRightRadius',\n 'width',\n 'height',\n 'max-width',\n 'max-height',\n 'min-width',\n 'min-height',\n 'maxWidth',\n 'maxHeight',\n 'minWidth',\n 'minHeight',\n]);\n\n/**\n * Calculate responsive value using the formula:\n * responsive_value = base_value + (base_value - base_reference) * (scale - 1)\n */\nexport function calculateResponsiveValue(\n baseValue: number,\n baseReference: number,\n scale: number\n): number {\n // Values at or below baseReference stay unchanged\n if (Math.abs(baseValue) <= baseReference) {\n return Math.round(baseValue);\n }\n const scaled = baseValue + (baseValue - baseReference) * (scale - 1);\n return Math.round(scaled);\n}\n\n/**\n * Get the scale multiplier for a specific property and breakpoint\n * @param scales - The responsive scales configuration\n * @param property - The CSS property type (e.g., 'fontSize', 'padding')\n * @param breakpoint - The breakpoint name (e.g., 'tablet', 'mobile', 'small')\n */\nexport function getScaleMultiplier(\n scales: ResponsiveScales,\n property: CSSPropertyType,\n breakpoint: string\n): number | null {\n const category = getScaleCategory(property);\n if (!category || !scales[category]) return null;\n\n const scaleConfig = scales[category] as BreakpointScales | undefined;\n return scaleConfig?.[breakpoint] ?? null;\n}\n\n/**\n * Parse multi-value CSS property (e.g., \"20px 40px\" for padding)\n * Handles both space-separated (\"20px 40px\") and hyphen-separated (\"20px-40px\") formats\n * Returns array of individual values\n */\nexport function parseMultiValue(valueStr: string): string[] {\n // First, convert hyphen separators to spaces (for class names like \"p-0-80px\" \u2192 \"0-80px\")\n // But only convert hyphens between values (digit/px followed by hyphen followed by digit/px)\n const normalized = valueStr.replace(/(?<=\\w)-(?=\\d|auto|inherit|initial|unset)/g, ' ');\n return normalized.trim().split(/\\s+/).filter(v => v.length > 0);\n}\n\n/**\n * Scale a single CSS value using the responsive scale\n * Returns null if the value cannot be parsed (no unit)\n */\nexport function scaleValue(\n valueStr: string,\n baseReference: number,\n scale: number\n): string | null {\n const parsed = parseValue(valueStr);\n if (!parsed) return null;\n\n // `%` and `em` are already relative to their rendering context\n // (container / local font-size), so they should not be rescaled.\n if (parsed.unit === '%' || parsed.unit === 'em') {\n return valueStr.trim();\n }\n\n const scaledValue = calculateResponsiveValue(parsed.value, baseReference, scale);\n return `${scaledValue}${parsed.unit}`;\n}\n\n/**\n * Scale a potentially multi-value CSS property\n * e.g., \"20px 40px\" -> \"18px 36px\" (both values scaled independently)\n * Unitless values (0, auto, inherit) are kept as-is\n */\nexport function scalePropertyValue(\n valueStr: string,\n baseReference: number,\n scale: number\n): string | null {\n const parts = parseMultiValue(valueStr);\n if (parts.length === 0) return null;\n\n const scaledParts = parts.map(part => {\n // Try to scale the value\n const scaled = scaleValue(part, baseReference, scale);\n if (scaled !== null) {\n return scaled;\n }\n // If it can't be scaled, keep it as-is (for unitless values like 0, auto, inherit)\n return part;\n });\n\n return scaledParts.join(' ');\n}\n\n/**\n * Get responsive values for all breakpoints\n * Returns object with calculated values for each breakpoint\n *\n * @param baseValue - The base CSS value (e.g., '67px')\n * @param property - The CSS property type (e.g., 'fontSize')\n * @param scales - The responsive scales configuration\n * @param breakpointNames - Optional array of breakpoint names to calculate values for.\n * If not provided, defaults to ['tablet', 'mobile'] for backward compatibility.\n */\nexport function getResponsiveValues(\n baseValue: string,\n property: CSSPropertyType,\n scales: ResponsiveScales,\n breakpointNames?: string[]\n): Record<string, string | null> {\n if (!scales.enabled) {\n return { base: baseValue };\n }\n\n const result: Record<string, string | null> = {\n base: baseValue,\n };\n\n const baseRef = scales.baseReference || 16;\n\n // Use provided breakpoint names or default to tablet/mobile for backward compatibility\n const breakpoints = breakpointNames ?? ['tablet', 'mobile'];\n\n // Calculate value for each breakpoint\n for (const breakpointName of breakpoints) {\n const scale = getScaleMultiplier(scales, property, breakpointName);\n if (scale !== null) {\n result[breakpointName] = scalePropertyValue(baseValue, baseRef, scale);\n }\n }\n\n return result;\n}\n\n/**\n * Resolve the effective value of a CSS variable at a given breakpoint.\n *\n * Precedence (mirrors generateVariablesCSS in cssGenerator.ts so the editor\n * widget stays in sync with what the browser will render):\n * 1. `breakpoint === 'base'` \u2192 variable.value\n * 2. explicit per-variable override \u2192 variable.scales[breakpoint]\n * 3. globally-scaled value (ResponsiveScales multiplier for variable.type)\n * 4. fallback \u2192 variable.value\n */\nexport function resolveVariableValueAtBreakpoint(\n variable: { value: string; type: string; scales?: Record<string, string> },\n breakpoint: string,\n responsiveScales?: ResponsiveScales | null\n): string {\n if (breakpoint === 'base') return variable.value;\n\n const override = variable.scales?.[breakpoint];\n if (override !== undefined) return override;\n\n if (responsiveScales?.enabled && variable.type !== 'none') {\n const scale = getScaleMultiplier(\n responsiveScales,\n variable.type as CSSPropertyType,\n breakpoint\n );\n if (scale !== null) {\n const baseRef = responsiveScales.baseReference || 16;\n const scaled = scalePropertyValue(variable.value, baseRef, scale);\n if (scaled !== null) return scaled;\n }\n }\n\n return variable.value;\n}\n\n/**\n * Pick the smallest (most restrictive) breakpoint name from a config object,\n * by `breakpoint` field. Used in fluid mode to choose which scale multiplier\n * defines the MIN of the clamp.\n *\n * Returns null if there are no entries.\n */\nexport function getSmallestBreakpointName(\n breakpoints: Record<string, { breakpoint: number }> | undefined | null\n): string | null {\n if (!breakpoints) return null;\n const entries = Object.entries(breakpoints);\n if (entries.length === 0) return null;\n let smallestName = entries[0][0];\n let smallestWidth = entries[0][1].breakpoint;\n for (const [name, cfg] of entries) {\n if (cfg.breakpoint < smallestWidth) {\n smallestWidth = cfg.breakpoint;\n smallestName = name;\n }\n }\n return smallestName;\n}\n\n/**\n * Build a `clamp(MIN, intercept + slope*100vw, MAX)` expression that interpolates\n * linearly between (vpMin, MIN) and (vpMax, MAX).\n *\n * - `baseValue` is the desktop/MAX value in CSS units.\n * - `unit` is the CSS unit (\"px\", \"rem\", etc.) used for both bounds.\n * - `scale` is the multiplier applied at the small end (mobile). Reuses\n * `calculateResponsiveValue` so the same multipliers used in 'breakpoints'\n * mode produce the same MIN endpoint in 'fluid' mode.\n * - `vpMin` / `vpMax` are viewport widths in pixels.\n *\n * If MIN === MAX (e.g. value at or below baseReference, or scale === 1),\n * returns a plain `${baseValue}${unit}` \u2014 no clamp emitted.\n */\nexport function buildFluidClamp(\n baseValue: number,\n unit: string,\n scale: number,\n vpMin: number,\n vpMax: number,\n baseReference = 16\n): string {\n const max = baseValue;\n const min = calculateResponsiveValue(baseValue, baseReference, scale);\n\n if (min === max || vpMax === vpMin) {\n return `${formatNumber(max)}${unit}`;\n }\n\n // Convert viewport bounds into the same unit as the value, so the\n // intercept term stays in `unit`. For px / rem we keep px throughout vw maths\n // but emit the intercept in the value's unit by converting (1rem = 16px).\n const unitToPx = unit === 'rem' ? 16 : 1;\n const minPx = min * unitToPx;\n const maxPx = max * unitToPx;\n const slopePx = (maxPx - minPx) / (vpMax - vpMin); // px per px-of-viewport\n const interceptPx = minPx - slopePx * vpMin; // px\n const interceptInUnit = interceptPx / unitToPx;\n const slopeVw = slopePx * 100; // because 1vw = viewport_width / 100 px\n\n return `clamp(${formatNumber(min)}${unit}, ${formatNumber(interceptInUnit)}${unit} + ${formatNumber(slopeVw)}vw, ${formatNumber(max)}${unit})`;\n}\n\n/**\n * Build a `clamp(MIN, intercept + slope*100vw, MAX)` expression where MIN is\n * supplied directly (e.g. from an authored mobile override) rather than\n * derived from `responsiveScales` \u00D7 `baseReference`.\n *\n * Used when a node has both `style.base.<prop>` and `style.mobile.<prop>` in\n * fluid mode \u2014 the mobile value is consumed as the clamp's small end so the\n * smooth interpolation lands exactly on the authored mobile value at the\n * narrow viewport, avoiding the jump that a separate @media override would\n * create.\n *\n * Same units / vw math as `buildFluidClamp`. Returns plain `${max}${unit}`\n * when MIN === MAX or the viewport range degenerates.\n */\nexport function buildFluidClampWithExplicitMin(\n minValue: number,\n maxValue: number,\n unit: string,\n vpMin: number,\n vpMax: number\n): string {\n if (minValue === maxValue || vpMax === vpMin) {\n return `${formatNumber(maxValue)}${unit}`;\n }\n\n const unitToPx = unit === 'rem' ? 16 : 1;\n const minPx = minValue * unitToPx;\n const maxPx = maxValue * unitToPx;\n const slopePx = (maxPx - minPx) / (vpMax - vpMin);\n const interceptPx = minPx - slopePx * vpMin;\n const interceptInUnit = interceptPx / unitToPx;\n const slopeVw = slopePx * 100;\n\n return `clamp(${formatNumber(minValue)}${unit}, ${formatNumber(interceptInUnit)}${unit} + ${formatNumber(slopeVw)}vw, ${formatNumber(maxValue)}${unit})`;\n}\n\n/**\n * Trim noisy floating-point output (e.g. 21.81818181818182 \u2192 21.8182).\n */\nfunction formatNumber(n: number): string {\n if (Number.isInteger(n)) return String(n);\n return Number(n.toFixed(4)).toString();\n}\n\n/**\n * Build the CSS value for the `--site-margin` variable in fluid mode.\n * Always emits a clamp() going from `siteMargin.min` to `siteMargin.max` (px),\n * interpolated linearly across `fluidRange.min`..`fluidRange.max`.\n *\n * If `min === max` the function returns the plain value (no clamp).\n */\nexport function buildSiteMarginClamp(\n siteMargin: SiteMarginConfig,\n fluidRange: FluidRange\n): string {\n const { min, max } = siteMargin;\n const { min: vpMin, max: vpMax } = fluidRange;\n\n if (min === max || vpMax === vpMin) {\n return `${formatNumber(max)}px`;\n }\n\n const slopePx = (max - min) / (vpMax - vpMin);\n const interceptPx = min - slopePx * vpMin;\n const slopeVw = slopePx * 100;\n\n return `clamp(${formatNumber(min)}px, ${formatNumber(interceptPx)}px + ${formatNumber(slopeVw)}vw, ${formatNumber(max)}px)`;\n}\n\n/**\n * Build a fluid clamp() value for a CSS string value (e.g. \"32px\", \"2rem\").\n * Multi-value strings (\"20px 40px\") are scaled per-token, like\n * `scalePropertyValue` does for breakpoint mode. Tokens without a unit\n * (`0`, `auto`, `inherit`) are kept verbatim.\n *\n * Returns null if no token is scalable.\n */\nexport function buildFluidPropertyValue(\n valueStr: string,\n scale: number,\n vpMin: number,\n vpMax: number,\n baseReference = 16\n): string | null {\n const parts = parseMultiValue(valueStr);\n if (parts.length === 0) return null;\n\n let anyScaled = false;\n const out = parts.map(part => {\n const parsed = parseValue(part);\n if (!parsed) return part;\n if (parsed.unit === '%' || parsed.unit === 'em') return part;\n anyScaled = true;\n return buildFluidClamp(parsed.value, parsed.unit, scale, vpMin, vpMax, baseReference);\n });\n\n return anyScaled ? out.join(' ') : null;\n}\n\n/**\n * Default responsive scales configuration\n */\nexport const DEFAULT_RESPONSIVE_SCALES: ResponsiveScales = {\n enabled: false,\n mode: 'breakpoints',\n baseReference: 16,\n fluidRange: { ...DEFAULT_FLUID_RANGE },\n siteMargin: { ...DEFAULT_SITE_MARGIN },\n fontSize: {\n tablet: 0.88,\n mobile: 0.75,\n },\n padding: {\n tablet: 0.75,\n mobile: 0.5,\n },\n margin: {\n tablet: 0.7,\n mobile: 0.45,\n },\n gap: {\n tablet: 0.65,\n mobile: 0.4,\n },\n borderRadius: {\n tablet: 0.85,\n mobile: 0.7,\n },\n size: {\n tablet: 0.9,\n mobile: 0.75,\n },\n};\n", "export interface RemConversionConfig {\n enabled: boolean;\n baseFontSize: number;\n}\n\nexport const DEFAULT_REM_CONFIG: RemConversionConfig = {\n enabled: false,\n baseFontSize: 16,\n};\n\nconst PX_REGEX = /(-?\\d*\\.?\\d+)px/g;\n\n/**\n * Convert all px values in a CSS value string to rem.\n * Handles multi-value shorthands like \"16px 32px\" -> \"1rem 2rem\".\n * 0px becomes \"0\" (unitless).\n */\nexport function convertPxToRem(cssValue: string, baseFontSize: number): string {\n return cssValue.replace(PX_REGEX, (_, num) => {\n const px = parseFloat(num);\n if (px === 0) return '0';\n const rem = px / baseFontSize;\n // Round to 4 decimal places, strip trailing zeros\n const rounded = parseFloat(rem.toFixed(4));\n return `${rounded}rem`;\n });\n}\n\n/**\n * CSS properties that should keep px values (thin borders, shadows).\n */\nconst PX_KEEP_PROPERTIES = new Set([\n 'border-width',\n 'border-top-width',\n 'border-right-width',\n 'border-bottom-width',\n 'border-left-width',\n 'outline-width',\n 'outline-offset',\n 'border',\n 'box-shadow',\n 'text-shadow',\n]);\n\nexport function shouldConvertProperty(cssProperty: string): boolean {\n return !PX_KEEP_PROPERTIES.has(cssProperty);\n}\n\n/**\n * Apply rem conversion to a CSS declarations string (e.g. \"padding: 16px; font-size: 18px\").\n * Checks each property against the exclusion list before converting.\n */\nexport function applyRemConversion(\n declarations: string,\n remConfig?: RemConversionConfig\n): string {\n if (!remConfig?.enabled) return declarations;\n\n return declarations\n .split(';')\n .map(decl => {\n const trimmed = decl.trim();\n if (!trimmed) return '';\n const colonIndex = trimmed.indexOf(':');\n if (colonIndex === -1) return trimmed;\n\n const property = trimmed.substring(0, colonIndex).trim();\n const value = trimmed.substring(colonIndex + 1).trim();\n\n if (shouldConvertProperty(property)) {\n return `${property}: ${convertPxToRem(value, remConfig.baseFontSize)}`;\n }\n return trimmed;\n })\n .filter(Boolean)\n .join('; ');\n}\n", "/**\n * Shared CSS Generation Module\n * Unified CSS generation logic for both editor and static render systems\n * Used by both client and server to ensure consistent CSS output\n */\n\nimport { prefixToCSSProperty, propertyMap } from './utilityClassConfig';\nimport { getStyleValue, getDynamicStyle, isDynamicClass } from './styleValueRegistry';\nimport { isCssNamedColor } from './cssNamedColors';\nimport type { BreakpointConfig, LegacyBreakpointConfig } from './breakpoints';\nimport { DEFAULT_BREAKPOINTS, getBreakpointValues } from './breakpoints';\nimport type { ResponsiveScales, CSSPropertyType, ResponsiveMode } from './responsiveScaling';\nimport {\n scalePropertyValue,\n getScaleMultiplier,\n buildFluidPropertyValue,\n getSmallestBreakpointName,\n DEFAULT_FLUID_RANGE,\n} from './responsiveScaling';\nimport type { InteractiveStyles, StyleObject, ResponsiveStyleObject, StyleValue } from './types/styles';\nimport type { RemConversionConfig } from './pxToRem';\nimport { applyRemConversion, convertPxToRem, shouldConvertProperty } from './pxToRem';\n\n/** Sorted prefix list (longest first) \u2014 cached at module level to avoid re-sorting per call */\nconst SORTED_PREFIXES: readonly string[] = Object.keys(prefixToCSSProperty)\n .sort((a, b) => b.length - a.length);\n\n/**\n * Map from CSS property (kebab-case) to its index in propertyMap.\n * Shorthands like 'border' have lower indices than longhands like 'border-color',\n * so sorting by this index ensures shorthand CSS rules appear before longhand rules.\n */\nconst cssPropertyOrderMap: Map<string, number> = (() => {\n const map = new Map<string, number>();\n const props = Object.keys(propertyMap);\n for (let i = 0; i < props.length; i++) {\n // Convert camelCase key to kebab-case CSS property\n const kebab = props[i].replace(/([A-Z])/g, '-$1').toLowerCase();\n map.set(kebab, i);\n }\n return map;\n})();\n\n/**\n * Get the property-order index for a utility class name.\n * Returns the position of the class's CSS property in propertyMap,\n * or Infinity for unknown classes (placed last).\n */\nfunction getClassPropertyOrder(className: string): number {\n // Try dynamic prefix-based lookup\n const extracted = extractPropertyAndValue(className);\n if (extracted) {\n const idx = cssPropertyOrderMap.get(extracted.property);\n if (idx !== undefined) return idx;\n }\n\n // Try predefined rules (e.g. 'f' \u2192 display: flex)\n const rule = utilityClassRules[className];\n if (rule) {\n const propMatch = rule.match(/^([a-z-]+):/);\n if (propMatch) {\n const idx = cssPropertyOrderMap.get(propMatch[1]);\n if (idx !== undefined) return idx;\n }\n }\n\n return Infinity;\n}\n\n/**\n * Sort utility class names by CSS property precedence.\n * Ensures shorthands (border) appear before longhands (border-color) in CSS output.\n */\nexport function sortClassesByPropertyOrder(classes: Iterable<string>): string[] {\n return Array.from(classes).sort((a, b) => getClassPropertyOrder(a) - getClassPropertyOrder(b));\n}\n\n/**\n * Pick the active responsive mode. Defaults to 'breakpoints' when missing,\n * preserving behavior for projects saved before the 'fluid' option existed.\n */\nfunction getResponsiveMode(scales: ResponsiveScales | undefined | null): ResponsiveMode {\n return (scales?.mode as ResponsiveMode | undefined) ?? 'breakpoints';\n}\n\n/** CSS property \u2192 responsive scale category mapping (used by generateUtilityCSS and generateSingleClassCSS) */\nconst AUTO_RESPONSIVE_TYPE_MAP: Record<string, string> = {\n 'padding': 'padding',\n 'padding-left': 'padding',\n 'padding-right': 'padding',\n 'padding-top': 'padding',\n 'padding-bottom': 'padding',\n 'margin': 'margin',\n 'margin-left': 'margin',\n 'margin-right': 'margin',\n 'margin-top': 'margin',\n 'margin-bottom': 'margin',\n 'font-size': 'fontSize',\n 'gap': 'gap',\n 'row-gap': 'gap',\n 'column-gap': 'gap',\n 'border-radius': 'borderRadius',\n 'border-top-left-radius': 'borderRadius',\n 'border-top-right-radius': 'borderRadius',\n 'border-bottom-left-radius': 'borderRadius',\n 'border-bottom-right-radius': 'borderRadius',\n 'width': 'size',\n 'height': 'size',\n 'max-width': 'size',\n 'max-height': 'size',\n 'min-width': 'size',\n 'min-height': 'size',\n};\n\n/**\n * Escape special characters in CSS class names using backslash notation\n * Characters that have special meaning in CSS selectors need to be escaped\n */\nfunction escapeCSSClassName(className: string): string {\n // Escape special characters with backslash\n // This includes: . # [ ] ( ) { } ; : , > + ~ % etc.\n return className.replace(/[.#[\\](){};<>+~:,%\\/\\s]/g, '\\\\$&');\n}\n\n// Define all possible utility class rules\nconst utilityClassRules: Record<string, string> = {\n // Display utilities (short forms from specialValueMappings)\n f: 'display: flex;',\n 'fd-col': 'flex-direction: column;',\n 'fd-row': 'flex-direction: row;',\n g: 'display: grid;',\n b: 'display: block;',\n i: 'display: inline;',\n ib: 'display: inline-block;',\n h: 'display: none;',\n 'if': 'display: inline-flex;',\n ig: 'display: inline-grid;',\n\n // Justify Content (short forms)\n 'jc-c': 'justify-content: center;',\n 'jc-s': 'justify-content: flex-start;',\n 'jc-e': 'justify-content: flex-end;',\n 'jc-b': 'justify-content: space-between;',\n 'jc-a': 'justify-content: space-around;',\n 'jc-ev': 'justify-content: space-evenly;',\n\n // Align Items (short forms)\n 'ai-c': 'align-items: center;',\n 'ai-s': 'align-items: flex-start;',\n 'ai-e': 'align-items: flex-end;',\n 'ai-st': 'align-items: stretch;',\n 'ai-b': 'align-items: baseline;',\n\n // Overflow (short forms)\n 'o-h': 'overflow: hidden;',\n 'o-a': 'overflow: auto;',\n 'o-s': 'overflow: scroll;',\n 'o-v': 'overflow: visible;',\n\n // Cursor (full forms)\n 'cursor-pointer': 'cursor: pointer;',\n 'cursor-default': 'cursor: default;',\n\n // Pointer events\n 'pe-none': 'pointer-events: none;',\n 'pe-auto': 'pointer-events: auto;',\n\n // User select\n 'us-none': 'user-select: none;',\n 'us-auto': 'user-select: auto;',\n 'us-text': 'user-select: text;',\n 'us-all': 'user-select: all;',\n\n // White space\n 'whs-normal': 'white-space: normal;',\n 'whs-nowrap': 'white-space: nowrap;',\n 'whs-pre': 'white-space: pre;',\n 'whs-pre-wrap': 'white-space: pre-wrap;',\n 'whs-pre-line': 'white-space: pre-line;',\n\n // Shadow presets\n 'sh-0': 'box-shadow: none;',\n 'sh-1': 'box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);',\n 'sh-2': 'box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);',\n 'sh-3': 'box-shadow: 0 8px 24px rgba(0, 0, 0, 0.15);',\n 'sh-4': 'box-shadow: 0 12px 32px rgba(0, 0, 0, 0.2);',\n\n // Gradient presets\n 'gr-1': 'background: linear-gradient(90deg, rgba(10,22,40,0.85) 0%, rgba(10,22,40,0.2) 100%);',\n 'gr-2': 'background: linear-gradient(0deg, #a9e8fd, #00aee8 25%, #0f1335 72%);',\n\n // Border presets\n 'bd-0': 'border: 1px solid var(--border);',\n 'bd-1': 'border: 1px solid var(--border-light);',\n\n // Note: CSS functions (blur, translateY, scale, rotate, repeat) are now handled\n // dynamically via the styleValueRegistry - no need to hardcode specific values here\n};\n\n/**\n * Extract CSS property and value from a utility class\n * Returns { property: CSS property name, value: CSS value } or null if not a dynamic class\n */\nfunction extractPropertyAndValue(className: string): { property: string; value: string } | null {\n // Parse prefix-value pattern (e.g., \"p-10px\", \"fs-48px\")\n for (const knownPrefix of SORTED_PREFIXES) {\n if (className.startsWith(knownPrefix + '-')) {\n const classValue = className.substring(knownPrefix.length + 1);\n const cssProp = prefixToCSSProperty[knownPrefix];\n if (cssProp) {\n // Hash-fallback class (e.g. `pt-h1y9pr6i`): the part after the\n // prefix is a hash, not a real CSS value. Returning `value: 'h1y9pr6i'`\n // would make auto-responsive scaling and other downstream consumers\n // emit broken rules like `padding-top: h1y9pr6i;`. The class IS\n // resolvable via the style-value registry \u2014 `generateRuleForClass`\n // handles it directly. Skip the dynamic-extraction path here.\n if (/^h[0-9a-z]+$/.test(classValue)) {\n return null;\n }\n return { property: cssProp, value: classValue };\n }\n }\n }\n\n return null;\n}\n\n/**\n * Resolve `{ property, value }` for a utility class, consulting the style-value\n * registry for hash-fallback classes (e.g. `fs-h1glej9a` for `222.3px`).\n *\n * Used by the auto-responsive scaling path so hashed classes don't silently\n * bypass `clamp()` / `@media` rewriting. `extractPropertyAndValue` itself\n * intentionally returns null for hashed classes because its other consumers\n * would emit broken `${prop}: ${hash};` rules.\n *\n * Returns the registered value as-is (no parsing). Downstream helpers\n * (`buildFluidPropertyValue`, `scalePropertyValue`) already null out\n * unparseable / `%` / `em` / `var()` / clamp-blob inputs, so a Webflow-style\n * already-clamped value will pass through untouched via the existing\n * `if (!fluidValue) return rule;` guards.\n */\nfunction resolveScalablePropertyValue(className: string): { property: string; value: string } | null {\n const direct = extractPropertyAndValue(className);\n if (direct) return direct;\n\n for (const knownPrefix of SORTED_PREFIXES) {\n if (!className.startsWith(knownPrefix + '-')) continue;\n const classValue = className.substring(knownPrefix.length + 1);\n if (!/^h[0-9a-z]+$/.test(classValue)) continue;\n const cssProp = prefixToCSSProperty[knownPrefix];\n if (!cssProp) continue;\n const registered = getStyleValue(className);\n if (registered == null || registered === '') continue;\n return { property: cssProp, value: String(registered) };\n }\n\n return null;\n}\n\n/**\n * Generate CSS rule for a utility class\n * Handles dynamic classes like p-10px, m-20px, fs-48px, etc.\n */\nexport function generateRuleForClass(className: string): string | null {\n // Check if it's a predefined rule\n if (utilityClassRules[className]) {\n return utilityClassRules[className];\n }\n\n // Parse prefix-value pattern (e.g., \"p-10px\", \"fs-48px\", \"p-92px-0\", \"bgc-background-light\")\n // Try to match known prefixes first by checking longest prefixes first\n let prefix = '';\n let classValue = '';\n\n for (const knownPrefix of SORTED_PREFIXES) {\n if (className.startsWith(knownPrefix + '-')) {\n prefix = knownPrefix;\n classValue = className.substring(knownPrefix.length + 1); // +1 for the hyphen\n break;\n }\n }\n\n if (!prefix || !classValue) {\n // Check dynamic registry for classes with unknown prefixes\n const dynamicStyle = getDynamicStyle(className);\n if (dynamicStyle) {\n return `${dynamicStyle.property}: ${dynamicStyle.value};`;\n }\n return null;\n }\n\n // Look up the CSS property from prefix\n const cssProp = prefixToCSSProperty[prefix];\n if (!cssProp) {\n // Check dynamic registry for classes with unknown prefixes\n const dynamicStyle = getDynamicStyle(className);\n if (dynamicStyle) {\n return `${dynamicStyle.property}: ${dynamicStyle.value};`;\n }\n return null;\n }\n\n // Handle border-side classes (bt-, bb-, bl-, border-r-) with special syntax FIRST\n // Generate ONLY width and style, NOT color - allows bc- to control color independently\n // e.g., bt-1px-solid \u2192 \"border-top-width: 1px; border-top-style: solid;\"\n // This must come BEFORE registry check to ensure consistent output\n const borderSideMap: Record<string, string> = {\n 'bt': 'border-top',\n 'bb': 'border-bottom',\n 'bl': 'border-left',\n 'border-r': 'border-right',\n };\n if (borderSideMap[prefix] && classValue.includes('-')) {\n const parts = classValue.split('-');\n const width = parts[0];\n const borderStyle = parts[1] || 'solid';\n const side = borderSideMap[prefix];\n return `${side}-width: ${width}; ${side}-style: ${borderStyle};`;\n }\n\n // Check registry for original value first (avoids lossy reverse-engineering)\n const originalValue = getStyleValue(className);\n if (originalValue !== undefined) {\n return `${cssProp}: ${originalValue};`;\n }\n\n // FALLBACK: Reverse-engineer value from class name for backward compatibility\n // (for classes extracted from HTML that weren't registered)\n\n // Handle border with special syntax BEFORE hyphen conversion (e.g., b-1px-solid-text)\n // This needs the original hyphenated format to parse correctly\n if (prefix === 'b' && classValue.includes('-')) {\n const parts = classValue.split('-');\n const width = parts[0];\n const borderStyle = parts[1] || 'solid';\n const borderColor = parts[2] ? `var(--${parts[2]})` : 'currentColor';\n return `border: ${width} ${borderStyle} ${borderColor};`;\n }\n\n // Handle border-radius with CSS variables (e.g., br-background)\n if (prefix === 'br' && classValue.includes('-') && !classValue.match(/^\\d+px$/)) {\n return `border-radius: var(--${classValue});`;\n }\n\n // Convert hyphenated values back to spaces, but preserve negative numbers\n // Handle cases like:\n // - \"92px-0\" \u2192 \"92px 0\" (space between values)\n // - \"-0.015\" \u2192 \"-0.015\" (negative number)\n // - \"0-5px\" \u2192 \"0 5px\" (space between values)\n // - \"1px-solid\" \u2192 \"1px solid\" (border shorthand)\n // - \"translateY(-100vh)\" \u2192 \"translateY(-100vh)\" (preserve negatives in functions)\n let value = classValue;\n\n // Pattern to match CSS values that should be preceded by a space instead of hyphen\n // Includes: digits, auto, inherit, initial, unset, border style keywords, and CSS function names\n const valuePattern = /\\d|auto|inherit|initial|unset|solid|dashed|dotted|double|groove|ridge|inset|outset|none|hidden|minmax|repeat|clamp|calc|min|max|fit-content|var/;\n\n // Only convert hyphens that are NOT inside parentheses (function arguments)\n // This preserves negative values like translateY(-100vh) while still handling\n // multi-value shorthand like \"10px-20px\" \u2192 \"10px 20px\"\n const hasParentheses = value.includes('(');\n\n if (hasParentheses) {\n // Convert hyphens to spaces, handling both inside and outside parentheses\n // Inside parentheses: convert hyphens after commas (they were space separators)\n // - \"repeat(3,-1fr)\" \u2192 \"repeat(3, 1fr)\" (single hyphen = space)\n // - \"clamp(-10px,--5px,-10px)\" \u2192 \"clamp(-10px, -5px, 10px)\" (double hyphen = space + negative)\n let result = '';\n let depth = 0;\n let afterComma = false;\n for (let i = 0; i < value.length; i++) {\n const char = value[i];\n if (char === '(') {\n depth++;\n result += char;\n afterComma = false;\n } else if (char === ')') {\n depth--;\n result += char;\n afterComma = false;\n } else if (char === ',') {\n result += char;\n afterComma = true;\n } else if (char === '-' && afterComma && depth > 0) {\n // Hyphen after comma inside parentheses - convert to space\n // Check if next char is also hyphen (indicating actual negative number)\n if (value[i + 1] === '-') {\n // Double hyphen: \",--\" means \", -\" (space followed by negative)\n result += ' ';\n // Don't skip the next hyphen - let it be added normally\n } else {\n // Single hyphen: \",-\" means \", \" (just a space separator)\n result += ' ';\n }\n afterComma = false;\n } else if (char === '-' && depth > 0 && i > 0) {\n // Hyphens inside parentheses (not after comma) - convert if followed by digit/value\n // This handles cases like \"#0f1442-94%\" \u2192 \"#0f1442 94%\"\n const rest = value.substring(i + 1);\n if (valuePattern.test(rest[0] || '')) {\n result += ' ';\n } else {\n result += char;\n }\n afterComma = false;\n } else if (char === '-' && depth === 0 && i > 0) {\n // Hyphens outside parentheses - convert if followed by value pattern\n const rest = value.substring(i + 1);\n if (valuePattern.test(rest[0] || '')) {\n result += ' ';\n } else {\n result += char;\n }\n afterComma = false;\n } else {\n result += char;\n afterComma = false;\n }\n }\n value = result;\n } else if (value.startsWith('-')) {\n // For negative values, only replace hyphens that come after the first character\n // This way \"-0.015\" stays as is, but \"-10px-5px\" becomes \"-10px 5px\"\n value = value[0] + value.substring(1).replace(new RegExp(`-(?=${valuePattern.source})`, 'g'), ' ');\n } else {\n // For positive values, replace hyphens normally\n value = value.replace(new RegExp(`-(?=${valuePattern.source})`, 'g'), ' ');\n }\n\n // Convert 'p' suffix to '%' for percentage values (e.g., \"50p\" \u2192 \"50%\")\n value = value.replace(/(\\d+)p(?!\\w)/g, '$1%');\n\n // Handle special multi-property prefixes\n if (prefix === 'px') {\n // padding-left and padding-right\n return `padding-left: ${value}; padding-right: ${value};`;\n }\n if (prefix === 'py') {\n // padding-top and padding-bottom\n return `padding-top: ${value}; padding-bottom: ${value};`;\n }\n if (prefix === 'mx') {\n // margin-left and margin-right\n return `margin-left: ${value}; margin-right: ${value};`;\n }\n if (prefix === 'my') {\n // margin-top and margin-bottom\n return `margin-top: ${value}; margin-bottom: ${value};`;\n }\n\n // Handle CSS variables for color properties\n // For color (c), background-color (bgc), and border-color (bc), treat as CSS variables\n // unless it's a hex color (#...) or RGB value\n if ((prefix === 'bgc' || prefix === 'bg' || prefix === 'c' || prefix === 'bc')) {\n // If it's not a hex color, RGB value, or pixel value, treat it as a CSS variable name\n // Unless it's a CSS named color (red, blue, transparent, etc.) \u2014 use directly\n if (!value.startsWith('#') && !value.includes('rgb') && !value.includes('px')) {\n if (isCssNamedColor(value)) {\n return `${cssProp}: ${value};`;\n }\n return `${cssProp}: var(--${value});`;\n }\n }\n\n // Standard case: prefix-value (e.g., p-10px, fs-48px, ta-center)\n return `${cssProp}: ${value};`;\n}\n\n/**\n * In fluid mode, return a CSS declaration string with the value replaced by\n * `clamp(...)` when the property is auto-responsive AND has a small-end scale.\n * Otherwise returns the original `rule` unchanged.\n *\n * The MIN of the clamp comes from the smallest configured breakpoint's\n * multiplier, matching the user-confirmed mapping (mobile multiplier \u21D2 MIN,\n * base value \u21D2 MAX, tablet ignored in fluid mode).\n */\nfunction applyFluidToUtilityRule(\n rule: string,\n className: string,\n responsiveScales: ResponsiveScales,\n breakpoints: BreakpointConfig\n): string {\n const propValue = resolveScalablePropertyValue(className);\n if (!propValue) return rule;\n\n const category = AUTO_RESPONSIVE_TYPE_MAP[propValue.property];\n if (!category) return rule;\n\n const scaleConfig = responsiveScales[category as keyof ResponsiveScales] as\n | Record<string, number>\n | undefined;\n if (!scaleConfig) return rule;\n\n const smallest = getSmallestBreakpointName(breakpoints);\n if (!smallest) return rule;\n\n const scale = scaleConfig[smallest];\n if (scale == null || scale === 1) return rule;\n\n const range = responsiveScales.fluidRange ?? DEFAULT_FLUID_RANGE;\n const baseRef = responsiveScales.baseReference ?? 16;\n const fluidValue = buildFluidPropertyValue(\n propValue.value,\n scale,\n range.min,\n range.max,\n baseRef\n );\n if (!fluidValue) return rule;\n\n return `${propValue.property}: ${fluidValue};`;\n}\n\n/**\n * In fluid mode, transform a flat StyleObject by replacing each scalable\n * property's value with a `clamp(...)` expression. Properties without a\n * matching scale category pass through unchanged.\n */\nfunction applyFluidToStyle(\n style: StyleObject,\n responsiveScales: ResponsiveScales,\n breakpoints: BreakpointConfig\n): StyleObject {\n const range = responsiveScales.fluidRange ?? DEFAULT_FLUID_RANGE;\n const baseRef = responsiveScales.baseReference ?? 16;\n const smallest = getSmallestBreakpointName(breakpoints);\n if (!smallest) return style;\n\n const out: StyleObject = {};\n for (const [prop, value] of Object.entries(style)) {\n if (typeof value === 'object' && value !== null && '_mapping' in value) {\n out[prop] = value;\n continue;\n }\n if (value == null || value === '') {\n out[prop] = value;\n continue;\n }\n\n const scale = getScaleMultiplier(\n responsiveScales,\n prop as CSSPropertyType,\n smallest\n );\n if (scale == null || scale === 1) {\n out[prop] = value;\n continue;\n }\n\n const fluidValue = buildFluidPropertyValue(\n String(value),\n scale,\n range.min,\n range.max,\n baseRef\n );\n out[prop] = fluidValue ?? value;\n }\n return out;\n}\n\n/** Values that don't make sense in a fluid container pattern. */\nconst CONTAINER_RESERVED_VALUES = new Set(['auto', 'inherit', 'initial', 'unset', '']);\n\n/**\n * Detect \"container intent\" on a flat StyleObject and rewrite it into the\n * fluid container pattern. Trigger: `width === maxWidth` (both set, equal).\n *\n * Transformation:\n * { width: '1200px', maxWidth: '1200px' }\n * \u2192 { width: 'calc(100% - var(--site-margin) * 2)', maxWidth: '1200px',\n * marginLeft: 'auto', marginRight: 'auto' }\n *\n * No-op when fluid mode is inactive (`fluidActive === false`) \u2014 the\n * `--site-margin` CSS variable is only emitted in fluid mode, so emitting the\n * calc() in breakpoints mode would reference an undefined variable.\n *\n * Margins are ALWAYS overwritten with `auto` (per user spec), even if the\n * caller had set explicit values.\n */\nexport function applyContainerPattern(\n style: StyleObject,\n fluidActive: boolean\n): StyleObject {\n if (!fluidActive) return style;\n const w = style.width;\n const mw = style.maxWidth;\n if (w == null || mw == null) return style;\n if (typeof w !== 'string' || typeof mw !== 'string') return style;\n if (w !== mw) return style;\n if (CONTAINER_RESERVED_VALUES.has(w.trim())) return style;\n\n return {\n ...style,\n width: 'calc(100% - var(--site-margin) * 2)',\n marginLeft: 'auto',\n marginRight: 'auto',\n };\n}\n\n/**\n * Generate CSS for all utility classes used in the application\n * Scans through all classes and generates the necessary CSS rules\n * Optionally applies responsive scaling based on configuration\n */\nexport function generateUtilityCSS(\n usedClasses: Set<string>,\n breakpoints: BreakpointConfig = DEFAULT_BREAKPOINTS,\n responsiveScales?: ResponsiveScales,\n remConfig?: RemConversionConfig\n): string {\n const css: string[] = [];\n const baseClasses = new Set<string>();\n const autoResponsiveClasses = new Set<string>(); // Classes that should get auto-scaling\n\n // Extract breakpoint values for CSS media queries\n const breakpointValues = getBreakpointValues(breakpoints);\n\n // Create a map for responsive breakpoint classes\n // Map from prefix (e.g., 't', 'm') to the class name and breakpoint info\n type BreakpointClassMap = Record<string, { classes: Set<string>; breakpointName: string; value: number }>;\n const responsiveClasses: BreakpointClassMap = {};\n\n // Initialize responsive class sets for each breakpoint\n for (const [breakpointName, breakpointValue] of Object.entries(breakpointValues)) {\n // Generate prefix from breakpoint name, avoiding conflicts with property prefixes\n // For 'mobile', use 'mob' to avoid conflict with 'margin' (m-), etc.\n let prefix = breakpointName.charAt(0).toLowerCase();\n if (breakpointName.toLowerCase() === 'mobile') {\n prefix = 'mob'; // Use 'mob' instead of 'm' to avoid margin conflict\n }\n\n responsiveClasses[prefix] = {\n classes: new Set<string>(),\n breakpointName,\n value: breakpointValue\n };\n }\n\n // Separate classes by breakpoint\n for (const className of usedClasses) {\n let matched = false;\n\n // Try to match against any responsive breakpoint prefix\n for (const prefix of Object.keys(responsiveClasses)) {\n if (className.startsWith(`${prefix}-`) && className.length > prefix.length + 1) {\n const potentialClass = className.substring(prefix.length + 1);\n const rule = generateRuleForClass(potentialClass);\n\n // If it generates a valid rule and doesn't look like a margin value, treat as breakpoint class\n // Margin values are typically: auto, 0, or pixel/percentage values (like 10px, 92px, 50p)\n if (rule && !potentialClass.match(/^(auto|0|[\\d.]+px|[\\d.]+p)$/)) {\n responsiveClasses[prefix].classes.add(potentialClass);\n matched = true;\n break;\n }\n }\n }\n\n if (!matched) {\n baseClasses.add(className);\n\n // Check if this class should get auto-responsive scaling\n if (responsiveScales?.enabled) {\n const propValue = resolveScalablePropertyValue(className);\n if (propValue) {\n const category = AUTO_RESPONSIVE_TYPE_MAP[propValue.property];\n if (category && responsiveScales[category as keyof ResponsiveScales]) {\n autoResponsiveClasses.add(className);\n }\n }\n }\n }\n }\n\n const mode = getResponsiveMode(responsiveScales);\n const fluidActive = responsiveScales?.enabled === true && mode === 'fluid';\n\n // Generate base rules \u2014 sorted so shorthands (border) appear before longhands (border-color)\n for (const className of sortClassesByPropertyOrder(baseClasses)) {\n let rule = generateRuleForClass(className);\n if (rule) {\n // In fluid mode, replace auto-responsive raw values with clamp() expressions.\n if (fluidActive && autoResponsiveClasses.has(className)) {\n rule = applyFluidToUtilityRule(rule, className, responsiveScales!, breakpoints);\n }\n // Escape special characters in class name for CSS selector\n const escapedClassName = escapeCSSClassName(className);\n const finalRule = applyRemConversion(rule, remConfig);\n css.push(`.${escapedClassName} { ${finalRule} }`);\n }\n }\n\n // Map to collect auto-responsive media queries by breakpoint\n type MediaQueryMap = Record<string, { classes: Array<{ className: string; rule: string }>; value: number }>;\n const autoResponsiveMediaQueries: MediaQueryMap = {};\n\n // Generate auto-responsive rules for classes with enabled scaling.\n // In fluid mode the base rule already encodes scaling via clamp(), so skip @media.\n if (responsiveScales?.enabled && !fluidActive) {\n for (const className of autoResponsiveClasses) {\n const propValue = resolveScalablePropertyValue(className);\n if (!propValue) continue;\n\n const category = AUTO_RESPONSIVE_TYPE_MAP[propValue.property];\n if (!category) continue;\n\n const scaleConfig = responsiveScales[category as keyof ResponsiveScales] as any;\n if (!scaleConfig) continue;\n\n const baseRef = responsiveScales.baseReference || 16;\n const escapedClassName = escapeCSSClassName(className);\n\n // Generate scaled rules for each breakpoint\n for (const [breakpointName, breakpointValue] of Object.entries(breakpointValues)) {\n // Use the actual breakpoint name to look up the scale\n // This allows custom breakpoints like 'small', 'large', etc. to have their own scales\n const scale = scaleConfig[breakpointName];\n if (!scale) continue;\n\n const scaledValue = scalePropertyValue(propValue.value, baseRef, scale);\n if (!scaledValue) continue;\n\n // Initialize media query entry if not exists\n if (!autoResponsiveMediaQueries[breakpointName]) {\n autoResponsiveMediaQueries[breakpointName] = {\n classes: [],\n value: breakpointValue\n };\n }\n\n const finalScaledValue = (remConfig?.enabled && shouldConvertProperty(propValue.property))\n ? convertPxToRem(scaledValue, remConfig.baseFontSize)\n : scaledValue;\n autoResponsiveMediaQueries[breakpointName].classes.push({\n className: escapedClassName,\n rule: `${propValue.property}: ${finalScaledValue};`\n });\n }\n }\n }\n\n // Generate media queries in two separate sections:\n // 1. Auto-responsive classes FIRST (baseline responsive behavior)\n // 2. Manual breakpoint classes AFTER (explicit overrides)\n // This ensures manual t-, mob- classes always override auto-responsive rules\n\n // Sort auto-responsive media queries by breakpoint value (descending)\n const sortedAutoResponsive = Object.entries(autoResponsiveMediaQueries)\n .sort(([, a], [, b]) => b.value - a.value);\n\n // Generate auto-responsive media queries first\n for (const [breakpointName, mq] of sortedAutoResponsive) {\n if (mq.classes.length === 0) continue;\n\n css.push(`@media (max-width: ${mq.value}px) {`);\n for (const { className, rule } of mq.classes) {\n css.push(` .${className} { ${rule} }`);\n }\n css.push('}');\n }\n\n // Sort manual responsive classes by breakpoint value (descending)\n const sortedManualResponsive = Object.entries(responsiveClasses)\n .filter(([, info]) => info.classes.size > 0)\n .sort(([, a], [, b]) => b.value - a.value);\n\n // Generate manual breakpoint media queries after\n for (const [prefix, breakpointInfo] of sortedManualResponsive) {\n const rules: string[] = [];\n\n for (const className of breakpointInfo.classes) {\n const rule = generateRuleForClass(className);\n if (rule) {\n const escapedClassName = escapeCSSClassName(className);\n const finalRule = applyRemConversion(rule, remConfig);\n rules.push(` .${prefix}-${escapedClassName} { ${finalRule} }`);\n }\n }\n\n if (rules.length > 0) {\n css.push(`@media (max-width: ${breakpointInfo.value}px) {`);\n css.push(...rules);\n css.push('}');\n }\n }\n\n return css.join('\\n');\n}\n\n/**\n * Generate complete CSS for a single utility class.\n * Returns the base rule (optionally wrapped in @media for responsive-prefixed classes)\n * plus auto-responsive scaling rules if enabled.\n *\n * Used by the client-side StyleInjector for per-class incremental injection,\n * avoiding the batch overhead of generateUtilityCSS.\n */\nexport function generateSingleClassCSS(\n className: string,\n breakpoints: BreakpointConfig = DEFAULT_BREAKPOINTS,\n responsiveScales?: ResponsiveScales,\n remConfig?: RemConversionConfig\n): string {\n const breakpointValues = getBreakpointValues(breakpoints);\n const css: string[] = [];\n\n // Build responsive prefix map: prefix \u2192 { breakpointName, value }\n const responsivePrefixes: Record<string, { breakpointName: string; value: number }> = {};\n for (const [breakpointName, breakpointValue] of Object.entries(breakpointValues)) {\n let prefix = breakpointName.charAt(0).toLowerCase();\n if (breakpointName.toLowerCase() === 'mobile') {\n prefix = 'mob';\n }\n responsivePrefixes[prefix] = { breakpointName, value: breakpointValue };\n }\n\n // Check if class has a responsive prefix (e.g. \"t-fs-16px\", \"mob-p-10px\")\n let matched = false;\n for (const prefix of Object.keys(responsivePrefixes)) {\n if (className.startsWith(`${prefix}-`) && className.length > prefix.length + 1) {\n const potentialClass = className.substring(prefix.length + 1);\n const rule = generateRuleForClass(potentialClass);\n\n // Only treat as responsive if it generates a valid rule and isn't a margin value\n if (rule && !potentialClass.match(/^(auto|0|[\\d.]+px|[\\d.]+p)$/)) {\n const escapedClassName = escapeCSSClassName(className);\n const escapedInnerClass = escapeCSSClassName(potentialClass);\n const bpValue = responsivePrefixes[prefix].value;\n const finalRule = applyRemConversion(rule, remConfig);\n css.push(`@media (max-width: ${bpValue}px) {\\n .${prefix}-${escapedInnerClass} { ${finalRule} }\\n}`);\n matched = true;\n break;\n }\n }\n }\n\n if (!matched) {\n // Base (non-responsive) class\n let rule = generateRuleForClass(className);\n if (!rule) return '';\n\n const mode = getResponsiveMode(responsiveScales);\n const fluidActive = responsiveScales?.enabled === true && mode === 'fluid';\n\n // In fluid mode, replace auto-responsive raw values with clamp().\n if (fluidActive) {\n const propValue = resolveScalablePropertyValue(className);\n if (propValue && AUTO_RESPONSIVE_TYPE_MAP[propValue.property]) {\n rule = applyFluidToUtilityRule(rule, className, responsiveScales!, breakpoints);\n }\n }\n\n const escapedClassName = escapeCSSClassName(className);\n const finalRule = applyRemConversion(rule, remConfig);\n css.push(`.${escapedClassName} { ${finalRule} }`);\n\n // Auto-responsive scaling via @media \u2014 only in 'breakpoints' mode.\n if (responsiveScales?.enabled && !fluidActive) {\n const propValue = resolveScalablePropertyValue(className);\n if (propValue) {\n const category = AUTO_RESPONSIVE_TYPE_MAP[propValue.property];\n if (category) {\n const scaleConfig = responsiveScales[category as keyof ResponsiveScales] as Record<string, number> | undefined;\n if (scaleConfig) {\n const baseRef = responsiveScales.baseReference || 16;\n\n // Sort breakpoints descending (largest first) for proper cascade\n const sortedBps = Object.entries(breakpointValues)\n .sort(([, a], [, b]) => b - a);\n\n for (const [breakpointName, breakpointValue] of sortedBps) {\n const scale = scaleConfig[breakpointName];\n if (!scale) continue;\n\n const scaledValue = scalePropertyValue(propValue.value, baseRef, scale);\n if (!scaledValue) continue;\n\n const finalScaledValue = (remConfig?.enabled && shouldConvertProperty(propValue.property))\n ? convertPxToRem(scaledValue, remConfig.baseFontSize)\n : scaledValue;\n css.push(`@media (max-width: ${breakpointValue}px) {\\n .${escapedClassName} { ${propValue.property}: ${finalScaledValue}; }\\n}`);\n }\n }\n }\n }\n }\n }\n\n return css.join('\\n');\n}\n\n/**\n * Extract all utility classes from a rendered HTML string\n * Identifies utility classes by checking against known prefixes from propertyMap\n */\nexport function extractUtilityClassesFromHTML(html: string): Set<string> {\n const classes = new Set<string>();\n const classRegex = /class=\"([^\"]*)\"/g;\n let match;\n\n // Get all known utility prefixes from propertyMap\n const knownPrefixes = new Set(Object.values(propertyMap));\n // Also include special/short form prefixes from utilityClassRules\n const specialPrefixes = new Set([\n // Display short forms\n 'f', 'fd-col', 'fd-row', 'g', 'b', 'i', 'ib', 'h', 'if', 'ig',\n // Justify content\n 'jc-c', 'jc-s', 'jc-e', 'jc-b', 'jc-a',\n // Align items\n 'ai-c', 'ai-s', 'ai-e', 'ai-b',\n // Overflow\n 'o-h', 'o-a', 'o-s', 'o-v',\n // Cursor\n 'cursor-pointer', 'cursor-default',\n // White space\n 'whs-normal', 'whs-nowrap', 'whs-pre', 'whs-pre-wrap', 'whs-pre-line',\n ]);\n\n while ((match = classRegex.exec(html)) !== null) {\n const classString = match[1];\n const classList = classString.split(/\\s+/);\n\n for (const className of classList) {\n // Skip empty class names\n if (!className || className.length === 0) continue;\n\n // Check if it's a special/short form class\n if (specialPrefixes.has(className)) {\n classes.add(className);\n continue;\n }\n\n // Check for responsive prefix (like 't-', 'mob-', 's-', etc.) and process accordingly\n let classToCheck = className;\n let hasResponsivePrefix = false;\n\n // Extract responsive prefix if present\n // Check for multi-letter prefix first (e.g., 'mob-' for mobile)\n if (className.startsWith('mob-') && className.length > 4) {\n classToCheck = className.substring(4); // Remove 'mob-' prefix\n hasResponsivePrefix = true;\n }\n // Then check for single-letter prefixes (t-, s-, l-, x-, u-)\n else if (className.length > 2 && className.charAt(1) === '-' && className.match(/^[a-z]-/)) {\n const firstChar = className.charAt(0);\n // Only treat as responsive prefix if it looks like a breakpoint indicator\n // Common breakpoint prefixes: t (tablet), s (small), x (extra), u (ultra)\n // NOTE: We exclude 'm' because it conflicts with margin prefix - use 'mob' instead\n // NOTE: We exclude 'l' because it conflicts with left property prefix - use 'lg' instead\n if (['t', 's', 'x', 'u'].includes(firstChar)) {\n classToCheck = className.substring(2); // Remove responsive prefix\n hasResponsivePrefix = true;\n }\n }\n\n // Check if it starts with a known prefix\n // Handle both single-letter (like 'p-', 'w-') and multi-letter (like 'jc-', 'ai-')\n for (const prefix of knownPrefixes) {\n if (classToCheck === prefix) {\n // Exact match (like 'f' for flex, 'g' for grid)\n classes.add(className);\n break;\n } else if (classToCheck.startsWith(prefix + '-')) {\n // Prefix with hyphen separator (like 'p-10px', 'fs-16px', or 't-p-10px')\n classes.add(className);\n break;\n }\n }\n\n // Also check special prefixes for responsive classes\n if (hasResponsivePrefix && !classes.has(className)) {\n for (const specialPrefix of specialPrefixes) {\n if (classToCheck === specialPrefix) {\n classes.add(className);\n break;\n } else if (classToCheck.startsWith(specialPrefix + '-')) {\n classes.add(className);\n break;\n }\n }\n }\n\n // Check if it's a dynamic class (registered in the dynamic registry)\n // This handles classes for properties not in propertyMap\n if (!classes.has(className) && isDynamicClass(className)) {\n classes.add(className);\n }\n }\n }\n\n return classes;\n}\n\n// ============================================================================\n// Interactive Styles CSS Generation\n// ============================================================================\n\n/**\n * Check if a style object is responsive (has base/breakpoint structure)\n */\nfunction isResponsiveStyle(style: StyleValue): style is ResponsiveStyleObject {\n return (\n typeof style === 'object' &&\n style !== null &&\n ('base' in style || 'tablet' in style || 'mobile' in style)\n );\n}\n\n/**\n * Convert a flat style object to CSS property declarations\n * Returns string like \"padding: 10px; background-color: var(--primary);\"\n */\nfunction styleObjectToCSS(style: StyleObject): string {\n const declarations: string[] = [];\n\n for (const [prop, value] of Object.entries(style)) {\n // Skip mapping objects\n if (typeof value === 'object' && value !== null && '_mapping' in value) {\n continue;\n }\n\n // Convert camelCase to kebab-case\n const cssProperty = prop.replace(/([A-Z])/g, '-$1').toLowerCase();\n\n // Handle CSS variable references for color properties\n let cssValue = String(value);\n if (\n (prop === 'backgroundColor' || prop === 'color' || prop === 'borderColor') &&\n !cssValue.startsWith('#') &&\n !cssValue.startsWith('rgb') &&\n !cssValue.startsWith('var(') &&\n !cssValue.includes('(')\n ) {\n cssValue = `var(--${cssValue})`;\n }\n\n declarations.push(`${cssProperty}: ${cssValue}`);\n }\n\n return declarations.join('; ');\n}\n\n/**\n * Generate CSS rules for interactive styles\n *\n * @param elementClass - The element's unique class (e.g., 'c_navigation_hamburger')\n * @param interactiveStyles - Array of selector-style rules\n * @param breakpoints - Breakpoint config for responsive styles\n * @returns CSS string with all interactive rules\n *\n * Example output:\n * ```css\n * #menu-toggle:checked ~ .c_navigation_hamburger { transform: rotate(45deg); }\n * .c_navigation_hamburger:hover { background-color: var(--primary); }\n * @media (max-width: 1024px) {\n * .c_navigation_hamburger:hover { padding: 24px; }\n * }\n * ```\n */\nexport function generateInteractiveCSS(\n elementClass: string,\n interactiveStyles: InteractiveStyles,\n breakpoints: BreakpointConfig = DEFAULT_BREAKPOINTS,\n remConfig?: RemConversionConfig,\n responsiveScales?: ResponsiveScales\n): string {\n const css: string[] = [];\n\n // Extract breakpoint values for CSS media queries\n const breakpointValues = getBreakpointValues(breakpoints);\n const scalingEnabled = responsiveScales?.enabled === true;\n const mode = getResponsiveMode(responsiveScales);\n const fluidActive = scalingEnabled && mode === 'fluid';\n\n for (const rule of interactiveStyles) {\n const { prefix, postfix, style } = rule;\n\n // Build full selector: {prefix}.element{postfix}\n const fullSelector = `${prefix || ''}.${elementClass}${postfix || ''}`;\n\n // Breakpoint styles (sorted by value descending)\n const sortedBreakpoints = Object.entries(breakpointValues).sort(\n ([, a], [, b]) => b - a\n );\n\n if (isResponsiveStyle(style)) {\n // Generate responsive rules\n const responsive = style as ResponsiveStyleObject;\n\n // Base styles \u2014 in fluid mode rewrite scalable values to clamp()\n // and rewrite width===maxWidth into the container pattern.\n if (responsive.base && Object.keys(responsive.base).length > 0) {\n let baseStyle = responsive.base;\n if (fluidActive) {\n baseStyle = applyContainerPattern(baseStyle, true);\n baseStyle = applyFluidToStyle(baseStyle, responsiveScales!, breakpoints);\n }\n const properties = applyRemConversion(styleObjectToCSS(baseStyle), remConfig);\n if (properties) {\n css.push(`${fullSelector} { ${properties}; }`);\n }\n }\n\n for (const [breakpointName, breakpointValue] of sortedBreakpoints) {\n const explicit = responsive[breakpointName];\n\n // Merge explicit breakpoint styles with auto-scaled values derived\n // from the base, skipping any property the author explicitly set.\n // In fluid mode skip the auto-scaled portion \u2014 base already has clamp().\n let merged: StyleObject | null = null;\n if (explicit && Object.keys(explicit).length > 0) {\n merged = fluidActive ? applyContainerPattern({ ...explicit }, true) : { ...explicit };\n }\n\n if (scalingEnabled && !fluidActive && responsive.base) {\n const scaled = scaleStyleForBreakpoint(\n responsive.base,\n responsiveScales!,\n breakpointName,\n new Set(Object.keys(explicit ?? {}))\n );\n if (Object.keys(scaled).length > 0) {\n merged = { ...(merged ?? {}), ...scaled };\n }\n }\n\n if (merged && Object.keys(merged).length > 0) {\n const properties = applyRemConversion(styleObjectToCSS(merged), remConfig);\n if (properties) {\n css.push(\n `@media (max-width: ${breakpointValue}px) { ${fullSelector} { ${properties}; } }`\n );\n }\n }\n }\n } else {\n // Flat style object\n const flatStyle = style as StyleObject;\n if (Object.keys(flatStyle).length > 0) {\n let baseFlat = flatStyle;\n if (fluidActive) {\n baseFlat = applyContainerPattern(baseFlat, true);\n baseFlat = applyFluidToStyle(baseFlat, responsiveScales!, breakpoints);\n }\n const properties = applyRemConversion(styleObjectToCSS(baseFlat), remConfig);\n if (properties) {\n css.push(`${fullSelector} { ${properties}; }`);\n }\n\n // Auto-scale the flat style into each enabled breakpoint \u2014 breakpoints mode only.\n if (scalingEnabled && !fluidActive) {\n for (const [breakpointName, breakpointValue] of sortedBreakpoints) {\n const scaled = scaleStyleForBreakpoint(\n flatStyle,\n responsiveScales!,\n breakpointName,\n new Set()\n );\n if (Object.keys(scaled).length === 0) continue;\n const scaledProps = applyRemConversion(styleObjectToCSS(scaled), remConfig);\n if (!scaledProps) continue;\n css.push(\n `@media (max-width: ${breakpointValue}px) { ${fullSelector} { ${scaledProps}; } }`\n );\n }\n }\n }\n }\n }\n\n return css.join('\\n');\n}\n\n/**\n * Build a new style object containing auto-scaled values for every property\n * in a given base style that falls into a scale category at `breakpointName`.\n * Properties listed in `skipProperties` are left out (the author has set an\n * explicit override at that breakpoint).\n */\nfunction scaleStyleForBreakpoint(\n baseStyle: StyleObject,\n responsiveScales: ResponsiveScales,\n breakpointName: string,\n skipProperties: Set<string>\n): StyleObject {\n const result: StyleObject = {};\n const baseRef = responsiveScales.baseReference ?? 16;\n\n for (const [property, value] of Object.entries(baseStyle)) {\n if (skipProperties.has(property)) continue;\n if (typeof value === 'object' && value !== null && '_mapping' in value) continue;\n if (value == null) continue;\n\n const strValue = String(value);\n if (strValue === '') continue;\n\n const scale = getScaleMultiplier(\n responsiveScales,\n property as CSSPropertyType,\n breakpointName\n );\n if (scale == null) continue;\n\n const scaledValue = scalePropertyValue(strValue, baseRef, scale);\n if (scaledValue == null || scaledValue === strValue) continue;\n\n result[property] = scaledValue;\n }\n\n return result;\n}\n\n/**\n * Collect and generate CSS for all interactive styles in a page/component\n *\n * @param interactiveStylesMap - Map of element class to interactive styles\n * @param breakpoints - Breakpoint config\n * @returns Combined CSS string\n */\nexport function generateAllInteractiveCSS(\n interactiveStylesMap: Map<string, InteractiveStyles>,\n breakpoints: BreakpointConfig = DEFAULT_BREAKPOINTS,\n remConfig?: RemConversionConfig,\n responsiveScales?: ResponsiveScales\n): string {\n const cssBlocks: string[] = [];\n\n for (const [elementClass, styles] of interactiveStylesMap) {\n const css = generateInteractiveCSS(elementClass, styles, breakpoints, remConfig, responsiveScales);\n if (css) {\n cssBlocks.push(css);\n }\n }\n\n return cssBlocks.join('\\n\\n');\n}\n", "/**\n * Maps CSS property values to utility class names\n * Example: { padding: \"10px\", display: \"flex\" } \u2192 [\"p-10px\", \"flex\"]\n * Uses centralized configuration from utilityClassConfig.ts\n */\n\nimport type { ResponsiveStyleObject, StyleObject, StyleMapping } from './types';\nimport {\n propertyMap,\n specialValueMappings,\n classToStyleSpecialCases,\n shadowPresets,\n gradientPresets,\n borderPresets,\n} from './utilityClassConfig';\nimport { registerStyleValue, registerDynamicStyle, getStyleValue } from './styleValueRegistry';\nimport {\n SCALABLE_CSS_PROPERTIES,\n buildFluidClampWithExplicitMin,\n parseValue,\n DEFAULT_FLUID_RANGE,\n type ResponsiveScales,\n} from './responsiveScaling';\n\n// Function name abbreviations for shorter class names\nconst functionAbbreviations: Record<string, string> = {\n blur: 'bl',\n translateY: 'ty',\n translateX: 'tx',\n translate: 't',\n scale: 'sc',\n scaleX: 'scx',\n scaleY: 'scy',\n rotate: 'ro',\n skew: 'sk',\n skewX: 'skx',\n skewY: 'sky',\n repeat: 're',\n minmax: 'mm',\n calc: 'ca',\n};\n\n/**\n * Check if a value is a StyleMapping object\n */\nfunction isStyleMapping(value: unknown): value is StyleMapping {\n return typeof value === 'object' && value !== null && '_mapping' in value && (value as StyleMapping)._mapping === true;\n}\n\n/**\n * Sanitize a value for use in a CSS class name\n * Replaces special characters with safe alternatives\n */\nfunction sanitizeClassValue(value: string): string {\n return value\n .replace(/\\s+/g, '-') // spaces to hyphens\n .replace(/[()]/g, '') // remove parentheses\n .replace(/,/g, '_') // commas to underscores\n .replace(/%/g, 'p') // percent to 'p'\n .replace(/\\./g, 'd') // dots to 'd' (for decimals)\n .replace(/[^\\w-]/g, ''); // remove other special chars\n}\n\n/**\n * 32-bit FNV-1a hash, encoded as base36 (6-7 chars). Deterministic \u2014 same\n * input always produces the same hash, so duplicate complex values across\n * elements share a single class definition.\n */\nfunction shortHash(input: string): string {\n let hash = 0x811c9dc5;\n for (let i = 0; i < input.length; i++) {\n hash ^= input.charCodeAt(i);\n hash = Math.imul(hash, 0x01000193);\n }\n return (hash >>> 0).toString(36);\n}\n\n/**\n * True if a class name contains characters illegal in CSS selectors. We\n * generate dynamic class names from CSS values; complex values (especially\n * Webflow `clamp(2*1rem, ((..2)/(90 - 20)*20)*1rem + ..*100vw, 4*1rem)`)\n * end up with `*`, `(`, `)`, `+`, `,` baked into the class name, none of\n * which are valid in CSS selectors. Browser silently drops the rule and\n * the styled property reverts to UA defaults. Hash-fallback gives us a\n * short, valid-CSS class name, with the actual value resolved via the\n * style-value registry at CSS generation time.\n */\nfunction hasIllegalClassChars(className: string): boolean {\n return /[^\\w-]/.test(className);\n}\n\n/**\n * Converts a CSS property value to a utility class name\n * Example: { prop: \"padding\", value: \"10px\" } \u2192 \"p-10px\"\n *\n * For properties not in propertyMap, generates a dynamic class using\n * a shortened property name prefix (e.g., \"textOverflow\" \u2192 \"txov-ellipsis\")\n */\nfunction propertyValueToClass(prop: string, value: string | number): string | null {\n const prefix = propertyMap[prop];\n\n // For properties not in propertyMap, generate a dynamic fallback class\n if (!prefix) {\n const stringValue = String(value);\n // Generate a short prefix from the property name (first 2-4 chars of each word)\n // e.g., \"textOverflow\" \u2192 \"txov\", \"WebkitBackgroundClip\" \u2192 \"wbbg\"\n const dynamicPrefix = prop\n .replace(/([A-Z])/g, '-$1') // camelCase to kebab\n .toLowerCase()\n .split('-')\n .filter(Boolean)\n .map(word => word.slice(0, 2)) // first 2 chars of each word\n .join('');\n\n // Sanitize value for class name\n const sanitizedValue = sanitizeClassValue(stringValue);\n const className = `${dynamicPrefix}-${sanitizedValue}`;\n\n // Convert camelCase to kebab-case for CSS property\n const cssProperty = prop.replace(/([A-Z])/g, '-$1').toLowerCase();\n\n // Register in dynamic registry with property info\n registerDynamicStyle(className, cssProperty, value);\n return className;\n }\n\n let stringValue = String(value);\n\n // Strip outer quotes from fontFamily values (e.g. \"Space Grotesk\" \u2192 Space Grotesk)\n if (prop === 'fontFamily') {\n stringValue = stringValue.split(',').map(font => {\n const trimmed = font.trim();\n if ((trimmed.startsWith('\"') && trimmed.endsWith('\"')) ||\n (trimmed.startsWith(\"'\") && trimmed.endsWith(\"'\"))) {\n return trimmed.slice(1, -1);\n }\n return trimmed;\n }).join(', ');\n }\n\n let className: string | null = null;\n\n // Check for special value mappings first\n if (specialValueMappings[prop]) {\n const mapping = specialValueMappings[prop];\n if (mapping[stringValue]) {\n className = mapping[stringValue];\n }\n }\n\n // Check for preset values (e.g., boxShadow: \"2\" \u2192 sh-2)\n if (!className && prop === 'boxShadow' && shadowPresets[stringValue]) {\n className = `sh-${stringValue}`;\n }\n if (!className && (prop === 'background' || prop === 'backgroundImage') && gradientPresets[stringValue]) {\n className = `gr-${stringValue}`;\n }\n if (!className && prop === 'border' && borderPresets[stringValue]) {\n className = `bd-${stringValue}`;\n }\n\n // Handle CSS function values: blur(), translateY(), rotate(), scale(), repeat(), etc.\n // Uses abbreviations for shorter class names: blur(8px) \u2192 bl8, translateY(-15px) \u2192 tyn15\n if (!className && stringValue.includes('(') && stringValue.includes(')')) {\n const funcMatch = stringValue.match(/^([a-zA-Z]+)\\((.+)\\)$/);\n if (funcMatch) {\n const [, funcName, args] = funcMatch;\n const abbrev = functionAbbreviations[funcName] || funcName.slice(0, 2);\n const argNormalized = args\n .replace(/,\\s*/g, '-') // \"3, 1fr\" \u2192 \"3-1fr\"\n .replace(/\\s+/g, '') // Remove spaces\n .replace(/-(\\d)/g, 'n$1') // \"-15px\" \u2192 \"n15px\"\n .replace(/px$/i, '') // Remove trailing px for brevity\n .replace(/%$/, 'p'); // \"50%\" \u2192 \"50p\"\n className = `${prefix}-${abbrev}${argNormalized}`;\n }\n }\n\n // CSS variables (e.g., var(--background))\n if (!className && stringValue.includes('var(')) {\n const varMatch = stringValue.match(/var\\((--[\\w-]+)\\)/);\n if (varMatch) {\n const varName = varMatch[1].replace('--', '');\n className = `${prefix}-${varName}`;\n }\n }\n\n // Detect variable names for color/background properties (e.g., color: \"text\" \u2192 c-text)\n // These are stored as plain names without var() wrapper and should be treated as variables\n if (!className &&\n (prop === 'color' || prop === 'backgroundColor' || prop === 'borderColor') &&\n !stringValue.match(/^\\d/) && !stringValue.includes('#') && !stringValue.includes('rgb')) {\n className = `${prefix}-${stringValue}`;\n }\n\n // Direct values (with units)\n if (!className && (stringValue.match(/^\\d+px$/) || stringValue.match(/^\\d+em$/))) {\n className = `${prefix}-${stringValue}`;\n }\n\n // Percentage values - convert % to p (e.g., \"50%\" \u2192 \"50p\")\n if (!className && stringValue.match(/^\\d+%$/)) {\n const percentValue = stringValue.replace('%', 'p');\n className = `${prefix}-${percentValue}`;\n }\n\n // Handle values with spaces by replacing spaces with hyphens (e.g., \"92px 0\" \u2192 \"p-92px-0\")\n if (!className && stringValue.includes(' ')) {\n const spacedValue = stringValue.replace(/\\s+/g, '-');\n className = `${prefix}-${spacedValue}`;\n }\n\n // Special handling for margin/padding \"auto\"\n if (!className && stringValue === 'auto') {\n className = `${prefix}-auto`;\n }\n\n // Handle values with slash (e.g., aspectRatio \"1/1\" \u2192 \"ar-1s1\")\n if (!className && stringValue.includes('/')) {\n const slashValue = stringValue.replace(/\\//g, 's');\n className = `${prefix}-${slashValue}`;\n }\n\n // For other cases, append the value\n if (!className) {\n className = `${prefix}-${stringValue}`;\n }\n\n // Hash-fallback for class names with illegal CSS selector chars. Webflow's\n // fluid `clamp(2*1rem, ((2 - .5)/70*20)*1rem + ..*100vw, 4*1rem)` would\n // otherwise produce `pt-cl2*1rem-((2-.5)/70*20)*1rem+..*100vw-4*1rem`,\n // with `*`, `(`, `)`, `+`, `,` \u2014 none of which are valid in CSS selectors.\n // Browser drops the rule, the styled element reverts to defaults\n // (paddings collapse to 0, etc.). Short FNV-1a hash + style-value\n // registry preserves the original value for the CSS generator without\n // baking it into the selector.\n if (hasIllegalClassChars(className)) {\n className = `${prefix}-h${shortHash(stringValue)}`;\n }\n\n // Register original value for CSS generation (single registration point)\n registerStyleValue(className, value);\n return className;\n}\n\n// Get property order from propertyMap for consistent class ordering\nconst propertyOrder = Object.keys(propertyMap);\n\n/**\n * Convert a style object to an array of utility classes\n * Example: { padding: \"10px\", display: \"flex\" } \u2192 [\"p-10px\", \"flex\"]\n *\n * Properties are sorted according to propertyMap order to ensure\n * dependent properties (like borderColor) come after their base (border)\n *\n * StyleMapping values are filtered out - they are handled at render time\n */\nexport function stylesToClasses(\n styles: StyleObject | Record<string, string | number> | null | undefined\n): string[] {\n if (!styles) return [];\n\n // Sort properties by their order in propertyMap\n // This ensures border comes before borderColor, etc.\n const sortedProps = Object.keys(styles).sort((a, b) => {\n const indexA = propertyOrder.indexOf(a);\n const indexB = propertyOrder.indexOf(b);\n // Unknown properties go to the end\n const orderA = indexA === -1 ? Infinity : indexA;\n const orderB = indexB === -1 ? Infinity : indexB;\n return orderA - orderB;\n });\n\n const classes: string[] = [];\n for (const prop of sortedProps) {\n const value = styles[prop];\n // Skip StyleMapping values - they are resolved at render time, not converted to classes\n if (isStyleMapping(value)) continue;\n const className = propertyValueToClass(prop, value);\n if (className) {\n classes.push(className);\n }\n }\n return classes;\n}\n\n/**\n * Convert a responsive style object to utility classes with responsive prefixes\n * Example: { base: { padding: \"10px\" }, tablet: { padding: \"24px\" } }\n * \u2192 [\"p-10px\", \"t-p-24px\"]\n *\n * Also handles flat merged style objects:\n * Example: { padding: \"10px\", display: \"flex\" } \u2192 [\"p-10px\", \"flex\"]\n */\n/** Values that don't make sense in a fluid container pattern. Mirrors cssGeneration.ts. */\nconst CONTAINER_RESERVED_VALUES = new Set(['auto', 'inherit', 'initial', 'unset', '']);\n\n/**\n * Detect \"container intent\" (width === maxWidth) on a flat StyleObject and\n * rewrite into the fluid container pattern. Used by `responsiveStylesToClasses`\n * when its caller signals fluid mode is active.\n *\n * Mirrors `applyContainerPattern` in cssGeneration.ts \u2014 kept as a private\n * helper here to avoid a cross-module import in this hot path.\n */\nfunction transformContainerIntent(style: StyleObject): StyleObject {\n const w = style.width;\n const mw = style.maxWidth;\n if (w == null || mw == null) return style;\n if (typeof w !== 'string' || typeof mw !== 'string') return style;\n if (w !== mw) return style;\n if (CONTAINER_RESERVED_VALUES.has(w.trim())) return style;\n return {\n ...style,\n width: 'calc(100% - var(--site-margin) * 2)',\n marginLeft: 'auto',\n marginRight: 'auto',\n };\n}\n\n/**\n * In fluid mode, consume per-node mobile overrides for scalable properties\n * into the base's `clamp()` value. The mobile value becomes the clamp's MIN\n * (small-viewport endpoint), the base stays as MAX. The mobile property is\n * then stripped from the mobile slice so no `.mob-*` @media rule is emitted\n * for it \u2014 avoiding the jump at the mobile breakpoint that a hard override\n * would create.\n *\n * Non-scalable mobile properties (display, flex-direction, etc.) are left\n * alone. Tablet is also untouched \u2014 explicit per-tablet overrides keep their\n * @media behavior for now.\n *\n * Bails out when units mismatch, parsing fails, or the registered values\n * aren't plain numeric+unit strings \u2014 those cases fall back to today's\n * behavior (mobile emits its own .mob-* rule).\n */\nfunction consumeMobileIntoBaseClamp(\n base: StyleObject,\n mobile: StyleObject,\n responsiveScales: ResponsiveScales\n): { patchedBase: StyleObject; patchedMobile: StyleObject } {\n const fluidRange = responsiveScales.fluidRange ?? DEFAULT_FLUID_RANGE;\n const patchedBase: StyleObject = { ...base };\n const patchedMobile: StyleObject = { ...mobile };\n\n for (const prop of Object.keys(base)) {\n if (!SCALABLE_CSS_PROPERTIES.has(prop)) continue;\n const mobileRaw = mobile[prop];\n if (mobileRaw == null || mobileRaw === '') continue;\n\n const baseRaw = base[prop];\n if (baseRaw == null || baseRaw === '') continue;\n if (typeof baseRaw !== 'string' && typeof baseRaw !== 'number') continue;\n if (typeof mobileRaw !== 'string' && typeof mobileRaw !== 'number') continue;\n\n const baseParsed = parseValue(String(baseRaw));\n const mobileParsed = parseValue(String(mobileRaw));\n if (!baseParsed || !mobileParsed) continue;\n if (baseParsed.unit !== mobileParsed.unit) continue;\n if (baseParsed.unit === '%' || baseParsed.unit === 'em') continue;\n\n const clampValue = buildFluidClampWithExplicitMin(\n mobileParsed.value,\n baseParsed.value,\n baseParsed.unit,\n fluidRange.min,\n fluidRange.max\n );\n\n patchedBase[prop] = clampValue;\n delete patchedMobile[prop];\n }\n\n return { patchedBase, patchedMobile };\n}\n\nexport function responsiveStylesToClasses(\n styles: StyleObject | ResponsiveStyleObject | null | undefined,\n options?: { fluidActive?: boolean; responsiveScales?: ResponsiveScales }\n): string[] {\n if (!styles) return [];\n const fluidActive = options?.fluidActive === true;\n const responsiveScales = options?.responsiveScales;\n\n const classes: string[] = [];\n\n // Check if this is a responsive style object (has base/tablet/mobile properties)\n if ('base' in styles || 'tablet' in styles || 'mobile' in styles) {\n const responsiveStyles = styles as ResponsiveStyleObject;\n\n // In fluid mode, fold per-node scalable mobile overrides into the base's\n // clamp() so they become the small-viewport endpoint instead of a hard\n // @media jump. Falls back to original base/mobile when prerequisites\n // aren't met.\n let baseSource = responsiveStyles.base;\n let mobileSource = responsiveStyles.mobile;\n if (fluidActive && responsiveScales?.enabled === true && baseSource && mobileSource) {\n const { patchedBase, patchedMobile } = consumeMobileIntoBaseClamp(\n baseSource,\n mobileSource,\n responsiveScales\n );\n baseSource = patchedBase;\n mobileSource = patchedMobile;\n }\n\n // Base styles (no prefix)\n if (baseSource) {\n const base = fluidActive\n ? transformContainerIntent(baseSource)\n : baseSource;\n classes.push(...stylesToClasses(base));\n }\n\n // Tablet styles (t- prefix)\n if (responsiveStyles.tablet) {\n const tablet = fluidActive\n ? transformContainerIntent(responsiveStyles.tablet)\n : responsiveStyles.tablet;\n const tabletClasses = stylesToClasses(tablet);\n classes.push(...tabletClasses.map((cls) => `t-${cls}`));\n }\n\n // Mobile styles (mob- prefix to avoid conflict with margin)\n if (mobileSource && Object.keys(mobileSource).length > 0) {\n const mobile = fluidActive\n ? transformContainerIntent(mobileSource)\n : mobileSource;\n const mobileClasses = stylesToClasses(mobile);\n classes.push(...mobileClasses.map((cls) => `mob-${cls}`));\n }\n } else {\n // Flat style object - treat all as base classes\n const flat = fluidActive\n ? transformContainerIntent(styles as StyleObject)\n : (styles as StyleObject);\n classes.push(...stylesToClasses(flat));\n }\n\n return classes;\n}\n\n/**\n * Parse a utility class back to CSS property and value\n * Example: \"p-10px\" \u2192 { padding: \"10px\" }\n */\nexport function classToStyle(className: string): { prop: string; value: string } | null {\n // Remove responsive prefixes for parsing\n let cleanClass = className;\n let responsivePrefix = '';\n\n if (className.startsWith('t-')) {\n responsivePrefix = 't';\n cleanClass = className.slice(2);\n } else if (className.startsWith('mob-')) {\n responsivePrefix = 'mob';\n cleanClass = className.slice(4);\n }\n\n // Check special cases from config\n if (classToStyleSpecialCases[cleanClass]) {\n return classToStyleSpecialCases[cleanClass];\n }\n\n // Parse prefix-value pattern (e.g., \"p-10px\", \"m-20px\")\n const match = cleanClass.match(/^([a-z-]+)-(.*?)$/);\n if (!match) return null;\n\n const [, prefix, value] = match;\n\n // Find the property from the prefix\n let prop = '';\n for (const [key, val] of Object.entries(propertyMap)) {\n if (val === prefix) {\n prop = key;\n break;\n }\n }\n\n if (!prop) return null;\n\n // Hash-fallback class \u2014 value is `h<base36>`, the real CSS value lives in\n // the style-value registry (set when the class was minted from a complex\n // `clamp()` / `calc()` value that wouldn't fit in a CSS selector). Pull\n // the real value back out so editor reads see the original expression.\n if (/^h[0-9a-z]+$/.test(value)) {\n const registered = getStyleValue(cleanClass);\n if (registered != null) {\n return { prop, value: String(registered) };\n }\n }\n\n // Handle CSS variables\n if (value.includes('background') || value.includes('text') || value.includes('border')) {\n return { prop, value: `var(--${value})` };\n }\n\n return { prop, value };\n}\n\n/**\n * Convert utility classes back to a style object\n * Example: [\"p-10px\", \"t-p-24px\"] \u2192 { base: { padding: \"10px\" }, tablet: { padding: \"24px\" } }\n */\nexport function classesToStyles(classes: string[]): ResponsiveStyleObject | null {\n const styles: ResponsiveStyleObject = { base: {}, tablet: {}, mobile: {} };\n\n for (const className of classes) {\n let breakpoint: 'base' | 'tablet' | 'mobile' = 'base';\n let cleanClass = className;\n\n if (className.startsWith('t-')) {\n breakpoint = 'tablet';\n cleanClass = className.slice(2);\n } else if (className.startsWith('mob-')) {\n breakpoint = 'mobile';\n cleanClass = className.slice(4);\n }\n\n const styleEntry = classToStyle(cleanClass);\n if (styleEntry) {\n if (!styles[breakpoint]) {\n styles[breakpoint] = {};\n }\n styles[breakpoint]![styleEntry.prop] = styleEntry.value;\n }\n }\n\n // Clean up empty breakpoints\n if (Object.keys(styles.tablet || {}).length === 0) delete styles.tablet;\n if (Object.keys(styles.mobile || {}).length === 0) delete styles.mobile;\n\n return Object.keys(styles.base || {}).length > 0 ? styles : null;\n}\n", "/**\n * Element Class Name Generation\n * Generates unique, stable CSS class names for elements based on their context\n *\n * Format:\n * - Components: c_<componentName>_<elementName|hash>\n * - Pages: p_<pageName>_<elementName|hash>\n *\n * Examples:\n * - c_navigation_hamburger (component \"Navigation\", element named \"Hamburger\")\n * - p_about_grid5 (page \"about\", element named \"Grid5\")\n * - c_navigation_a42e3 (component \"Navigation\", unnamed element with path hash)\n */\n\nimport type { Path } from './paths';\nimport { pathToString } from './paths';\n\n/**\n * Context for generating element class names\n */\nexport interface ElementClassContext {\n /** Type of file: 'component' or 'page' */\n fileType: 'component' | 'page';\n /** Name of the component or page (without extension) */\n fileName: string;\n /** Element's label if set */\n label?: string;\n /** Element's path in the tree */\n path: Path;\n}\n\n/**\n * Simple djb2 hash function that works in browser and server\n * Returns a short alphanumeric string\n */\nexport function shortHash(input: string): string {\n let hash = 5381;\n for (let i = 0; i < input.length; i++) {\n hash = ((hash << 5) + hash) ^ input.charCodeAt(i);\n }\n // Take the LAST 5 base36 chars: the low-order digits change with every\n // input byte, so sibling paths that share a long prefix and differ only\n // in their final index still produce distinct hashes. Slicing from the\n // start kept the high-order digits, which barely move when only the\n // last char of the input changes \u2014 every set of siblings collided.\n return Math.abs(hash).toString(36).slice(-5);\n}\n\n/**\n * Sanitize a name to be a valid CSS class name\n * - Lowercase\n * - Replace non-alphanumeric with underscore\n * - Remove leading/trailing underscores\n * - Collapse multiple underscores\n */\nfunction sanitizeName(name: string): string {\n return name\n .toLowerCase()\n .replace(/[^a-z0-9_-]/g, '_')\n .replace(/_+/g, '_')\n .replace(/^_|_$/g, '');\n}\n\n/**\n * Generate a unique CSS class name for an element\n *\n * @param ctx - Context containing file type, name, and element info\n * @returns CSS class name like \"c_navigation_hamburger\" or \"p_about_a42e3\"\n */\nexport function generateElementClassName(ctx: ElementClassContext): string {\n const prefix = ctx.fileType === 'component' ? 'c' : 'p';\n const sanitizedFileName = sanitizeName(ctx.fileName);\n\n if (ctx.label) {\n return `${prefix}_${sanitizedFileName}_${sanitizeName(ctx.label)}`;\n }\n\n // Generate hash from file name + path for unnamed elements\n const pathString = pathToString(ctx.path);\n const hash = shortHash(`${ctx.fileName}:${pathString}`);\n return `${prefix}_${sanitizedFileName}_${hash}`;\n}\n\n/**\n * Check if a class name is an element-specific class (c_ or p_ prefix)\n */\nexport function isElementClassName(className: string): boolean {\n return /^[cp]_[a-z0-9_-]+_[a-z0-9_-]+$/.test(className);\n}\n\n/**\n * Parse an element class name into its components\n * Returns null if not a valid element class name\n */\nexport function parseElementClassName(\n className: string\n): { fileType: 'component' | 'page'; fileName: string; elementName: string } | null {\n const match = className.match(/^([cp])_([a-z0-9_-]+)_([a-z0-9_-]+)$/);\n if (!match) return null;\n\n return {\n fileType: match[1] === 'c' ? 'component' : 'page',\n fileName: match[2],\n elementName: match[3],\n };\n}\n", "/**\n * Validation exports\n */\n\nexport * from './schemas';\nexport * from './validators';\nexport * from './propValidator';\nexport * from './cmsValidators';\nexport * from './commentValidators';\n", "/**\n * Validation Utilities\n * Runtime validation functions using zod schemas\n * All validators return ValidationResult<T> with detailed error information\n */\n\nimport type { ZodError, ZodType } from 'zod';\nimport type { PropDefinition, ComponentDefinition, StructuredComponentDefinition, PageData, PageDataWithComponent } from '../types/components';\nimport type { ComponentNode } from '../types/nodes';\nimport type { PageMetaData } from '../types/api';\nimport type { CMSSchema, CMSItem } from '../types/cms';\nimport {\n PropDefinitionSchema,\n ComponentNodeSchema,\n ComponentDefinitionSchema,\n StructuredComponentDefinitionSchema,\n PageDataSchema,\n PageDataWithComponentSchema,\n PageMetaDataSchema,\n CMSSchemaSchema,\n CMSItemSchema,\n CMSDraftItemSchema,\n} from './schemas';\n\n/**\n * Structured validation error with path and code\n */\nexport interface ValidationError {\n path: string;\n message: string;\n code?: 'INVALID_TYPE' | 'MISSING_REQUIRED' | 'INVALID_VALUE' | 'UNKNOWN';\n}\n\n/**\n * Validation result type - always includes error details on failure\n */\nexport type ValidationResult<T> =\n | { valid: true; data: T }\n | { valid: false; errors: ValidationError[] };\n\n/**\n * Convert Zod errors to ValidationError format\n */\nfunction zodToValidationErrors(zodError: ZodError): ValidationError[] {\n return zodError.errors.map(err => ({\n path: err.path.join('.') || 'root',\n message: err.message,\n code: 'INVALID_TYPE' as const,\n }));\n}\n\n/**\n * Validate and throw on failure - convenience helper\n */\nexport function validateOrThrow<T>(\n data: unknown,\n validator: (data: unknown) => ValidationResult<T>,\n errorMessage?: string\n): T {\n const result = validator(data);\n if (!result.valid) {\n const details = result.errors.map(e => `${e.path}: ${e.message}`).join('; ');\n throw new Error(errorMessage ? `${errorMessage}: ${details}` : details);\n }\n return result.data;\n}\n\n/**\n * Validate a prop definition\n * @returns ValidationResult with error details on failure\n */\nexport function validatePropDefinition(propDef: unknown): ValidationResult<PropDefinition> {\n try {\n const result = PropDefinitionSchema.safeParse(propDef);\n if (result.success) {\n return { valid: true, data: result.data as PropDefinition };\n }\n return { valid: false, errors: zodToValidationErrors(result.error) };\n } catch (error) {\n return {\n valid: false,\n errors: [{\n path: 'root',\n message: error instanceof Error ? error.message : 'Unknown validation error',\n code: 'UNKNOWN',\n }],\n };\n }\n}\n\n/**\n * Validate a component node\n * @returns ValidationResult with error details on failure\n */\nexport function validateComponentNode(node: unknown): ValidationResult<ComponentNode> {\n try {\n const result = ComponentNodeSchema.safeParse(node);\n if (result.success) {\n return { valid: true, data: result.data as ComponentNode };\n }\n return { valid: false, errors: zodToValidationErrors(result.error) };\n } catch (error) {\n return {\n valid: false,\n errors: [{\n path: 'root',\n message: error instanceof Error ? error.message : 'Unknown validation error',\n code: 'UNKNOWN',\n }],\n };\n }\n}\n\n/**\n * Validate a structured component definition\n * @returns ValidationResult with error details on failure\n */\nexport function validateStructuredComponentDefinition(def: unknown): ValidationResult<StructuredComponentDefinition> {\n try {\n const result = StructuredComponentDefinitionSchema.safeParse(def);\n if (result.success) {\n return { valid: true, data: result.data as StructuredComponentDefinition };\n }\n return { valid: false, errors: zodToValidationErrors(result.error) };\n } catch (error) {\n return {\n valid: false,\n errors: [{\n path: 'root',\n message: error instanceof Error ? error.message : 'Unknown validation error',\n code: 'UNKNOWN',\n }],\n };\n }\n}\n\n/**\n * Validate a component definition\n * @returns ValidationResult with error details on failure\n */\nexport function validateComponentDefinition(def: unknown): ValidationResult<ComponentDefinition> {\n try {\n const result = ComponentDefinitionSchema.safeParse(def);\n if (result.success) {\n return { valid: true, data: result.data as ComponentDefinition };\n }\n return { valid: false, errors: zodToValidationErrors(result.error) };\n } catch (error) {\n return {\n valid: false,\n errors: [{\n path: 'root',\n message: error instanceof Error ? error.message : 'Unknown validation error',\n code: 'UNKNOWN',\n }],\n };\n }\n}\n\n/**\n * Validate page data\n * @returns ValidationResult with error details on failure\n */\nexport function validatePageData(data: unknown): ValidationResult<PageData> {\n try {\n const result = PageDataSchema.safeParse(data);\n if (result.success) {\n return { valid: true, data: result.data as PageData };\n }\n return { valid: false, errors: zodToValidationErrors(result.error) };\n } catch (error) {\n return {\n valid: false,\n errors: [{\n path: 'root',\n message: error instanceof Error ? error.message : 'Unknown validation error',\n code: 'UNKNOWN',\n }],\n };\n }\n}\n\n/**\n * Validate page data with component structure\n * @returns ValidationResult with error details on failure\n */\nexport function validatePageDataWithComponent(data: unknown): ValidationResult<PageDataWithComponent> {\n try {\n const result = PageDataWithComponentSchema.safeParse(data);\n if (result.success) {\n return { valid: true, data: result.data as PageDataWithComponent };\n }\n return { valid: false, errors: zodToValidationErrors(result.error) };\n } catch (error) {\n return {\n valid: false,\n errors: [{\n path: 'root',\n message: error instanceof Error ? error.message : 'Unknown validation error',\n code: 'UNKNOWN',\n }],\n };\n }\n}\n\n/**\n * Validate page metadata\n * @returns ValidationResult with error details on failure\n */\nexport function validatePageMetaData(data: unknown): ValidationResult<PageMetaData> {\n try {\n const result = PageMetaDataSchema.safeParse(data);\n if (result.success) {\n return { valid: true, data: result.data as PageMetaData };\n }\n return { valid: false, errors: zodToValidationErrors(result.error) };\n } catch (error) {\n return {\n valid: false,\n errors: [{\n path: 'root',\n message: error instanceof Error ? error.message : 'Unknown validation error',\n code: 'UNKNOWN',\n }],\n };\n }\n}\n\n/**\n * Validate with detailed error information using a custom schema\n * @returns ValidationResult with error details on failure\n */\nexport function validateWithDetails<T>(\n data: unknown,\n schema: ZodType<T>\n): ValidationResult<T> {\n try {\n const result = schema.safeParse(data);\n if (result.success) {\n return { valid: true, data: result.data };\n }\n return { valid: false, errors: zodToValidationErrors(result.error) };\n } catch (error) {\n return {\n valid: false,\n errors: [{\n path: 'root',\n message: error instanceof Error ? error.message : 'Unknown validation error',\n code: 'UNKNOWN',\n }],\n };\n }\n}\n\n// ============================================================================\n// CMS Validators\n// ============================================================================\n\n/**\n * Validate a CMS schema\n * @returns ValidationResult with error details on failure\n */\nexport function validateCMSSchema(data: unknown): ValidationResult<CMSSchema> {\n try {\n const result = CMSSchemaSchema.safeParse(data);\n if (result.success) {\n return { valid: true, data: result.data as CMSSchema };\n }\n return { valid: false, errors: zodToValidationErrors(result.error) };\n } catch (error) {\n return {\n valid: false,\n errors: [{\n path: 'root',\n message: error instanceof Error ? error.message : 'Unknown validation error',\n code: 'UNKNOWN',\n }],\n };\n }\n}\n\n/**\n * Validate a CMS item (strict \u2014 used for published items and at publish time)\n * @returns ValidationResult with error details on failure\n */\nexport function validateCMSItem(data: unknown): ValidationResult<CMSItem> {\n try {\n const result = CMSItemSchema.safeParse(data);\n if (result.success) {\n return { valid: true, data: result.data as CMSItem };\n }\n return { valid: false, errors: zodToValidationErrors(result.error) };\n } catch (error) {\n return {\n valid: false,\n errors: [{\n path: 'root',\n message: error instanceof Error ? error.message : 'Unknown validation error',\n code: 'UNKNOWN',\n }],\n };\n }\n}\n\n/**\n * Validate a CMS draft item (loose \u2014 used at draft-write time).\n * Drafts may be partial; even system identifiers are optional. Strict\n * validation re-runs on Publish.\n */\nexport function validateCMSDraftItem(data: unknown): ValidationResult<CMSItem> {\n try {\n const result = CMSDraftItemSchema.safeParse(data);\n if (result.success) {\n return { valid: true, data: result.data as CMSItem };\n }\n return { valid: false, errors: zodToValidationErrors(result.error) };\n } catch (error) {\n return {\n valid: false,\n errors: [{\n path: 'root',\n message: error instanceof Error ? error.message : 'Unknown validation error',\n code: 'UNKNOWN',\n }],\n };\n }\n}\n\n\n", "/**\n * CMS Validation Utilities\n * Centralized validation for CMS-specific fields to ensure consistency\n */\n\nimport { z } from 'zod';\n\n/**\n * Regex pattern for valid CMS collection IDs\n * Allows alphanumeric characters, underscores, and hyphens\n */\nexport const CMS_COLLECTION_ID_REGEX = /^[a-zA-Z0-9_-]+$/;\n\n/**\n * Zod schema for CMS collection ID validation\n */\nexport const CMSCollectionIdSchema = z.string()\n .min(1, 'Collection ID is required')\n .regex(CMS_COLLECTION_ID_REGEX, 'Collection ID must contain only letters, numbers, underscores, and hyphens');\n\n/**\n * Validate a CMS collection ID\n * @returns Object with valid boolean and optional error message\n */\nexport function validateCollectionId(id: string): { valid: boolean; error?: string } {\n const result = CMSCollectionIdSchema.safeParse(id);\n if (result.success) {\n return { valid: true };\n }\n return { valid: false, error: result.error.errors[0]?.message };\n}\n\n/**\n * Check if a string is a valid CMS collection ID (simple boolean check)\n */\nexport function isValidCollectionId(id: string): boolean {\n return CMS_COLLECTION_ID_REGEX.test(id);\n}\n", "/**\n * Comment Validators\n * Zod schema + validator for pinned comments.\n */\n\nimport { z } from 'zod';\nimport type { ZodError } from 'zod';\nimport type { Comment } from '../types/comment';\nimport { COMMENT_STATUSES } from '../types/comment';\nimport type { ValidationResult, ValidationError } from './validators';\n\nexport const CommentStatusSchema = z.enum(COMMENT_STATUSES as unknown as [string, ...string[]]);\n\nexport const CommentAuthorSchema = z.object({\n login: z.string().min(1),\n name: z.string().optional(),\n avatarUrl: z.string().optional(),\n});\n\nexport const CommentNodeIdentitySchema = z.object({\n kind: z.enum(['component', 'node']),\n name: z.string().min(1),\n label: z.string().optional(),\n});\n\nexport const CommentAnchorSchema = z.object({\n nodePath: z.array(z.number().int().nonnegative()),\n nodeIdentity: CommentNodeIdentitySchema,\n offsetXPercent: z.number().min(0).max(1),\n offsetYPercent: z.number().min(0).max(1),\n breakpoint: z.string().optional(),\n});\n\nexport const CommentThreadEntrySchema = z.object({\n id: z.string().min(1),\n author: CommentAuthorSchema,\n createdAt: z.string().min(1),\n text: z.string(),\n statusChange: CommentStatusSchema.nullable(),\n});\n\nexport const CommentSchema = z.object({\n _id: z.string().min(1),\n _filename: z.string().min(1),\n _pagePath: z.string().min(1),\n _seq: z.number().int().nonnegative(),\n _createdAt: z.string().min(1),\n _updatedAt: z.string().min(1),\n _commitSha: z.string().nullable(),\n anchor: CommentAnchorSchema,\n status: CommentStatusSchema,\n thread: z.array(CommentThreadEntrySchema).min(1),\n});\n\nfunction zodToValidationErrors(zodError: ZodError): ValidationError[] {\n return zodError.errors.map(err => ({\n path: err.path.join('.') || 'root',\n message: err.message,\n code: 'INVALID_TYPE' as const,\n }));\n}\n\nexport function validateComment(data: unknown): ValidationResult<Comment> {\n const result = CommentSchema.safeParse(data);\n if (result.success) {\n return { valid: true, data: result.data as Comment };\n }\n return { valid: false, errors: zodToValidationErrors(result.error) };\n}\n", "/**\n * Safe Expression Evaluator\n * Evaluates template expressions using jsep parser\n *\n * Security: Uses jsep for safe expression parsing instead of eval/new Function()\n * Supports: ternary, binary, logical, unary operators, member access, arrays\n */\n\nimport jsep from 'jsep';\nimport type { Expression } from 'jsep';\n\n/**\n * Safely evaluates a jsep AST node against a context object\n * Only supports whitelisted node types for security\n */\nfunction evaluateNode(node: Expression, context: Record<string, unknown>): unknown {\n switch (node.type) {\n case 'Identifier':\n // Simple variable lookup\n return context[(node as jsep.Identifier).name];\n\n case 'Literal':\n // String, number, boolean literals\n return (node as jsep.Literal).value;\n\n case 'MemberExpression': {\n // Property access: obj.prop or obj[expr]\n const memberNode = node as jsep.MemberExpression;\n const obj = evaluateNode(memberNode.object, context);\n if (obj === null || obj === undefined) return undefined;\n\n let key: string | number;\n if (memberNode.computed) {\n // Bracket notation: obj[expr]\n const keyValue = evaluateNode(memberNode.property, context);\n if (typeof keyValue !== 'string' && typeof keyValue !== 'number') {\n return undefined;\n }\n key = keyValue;\n } else {\n // Dot notation: obj.prop\n key = (memberNode.property as jsep.Identifier).name;\n }\n\n if (typeof obj !== 'object') return undefined;\n return (obj as Record<string | number, unknown>)[key];\n }\n\n case 'BinaryExpression':\n case 'LogicalExpression': {\n // Operators: +, -, *, /, %, ===, !==, ==, !=, <, >, <=, >=, &&, ||\n // Note: jsep classifies && and || as BinaryExpression by default\n const binaryNode = node as jsep.BinaryExpression;\n\n // Handle logical operators with short-circuit evaluation\n if (binaryNode.operator === '&&') {\n const left = evaluateNode(binaryNode.left, context);\n return left ? evaluateNode(binaryNode.right, context) : left;\n }\n if (binaryNode.operator === '||') {\n const left = evaluateNode(binaryNode.left, context);\n return left ? left : evaluateNode(binaryNode.right, context);\n }\n\n // Evaluate both sides for non-logical operators\n const left = evaluateNode(binaryNode.left, context);\n const right = evaluateNode(binaryNode.right, context);\n\n switch (binaryNode.operator) {\n case '+':\n // String concatenation or addition\n if (typeof left === 'string' || typeof right === 'string') {\n return String(left ?? '') + String(right ?? '');\n }\n return (left as number) + (right as number);\n case '-': return (left as number) - (right as number);\n case '*': return (left as number) * (right as number);\n case '/': return (left as number) / (right as number);\n case '%': return (left as number) % (right as number);\n case '===': return left === right;\n case '!==': return left !== right;\n case '==': return left == right;\n case '!=': return left != right;\n case '<': return (left as number) < (right as number);\n case '>': return (left as number) > (right as number);\n case '<=': return (left as number) <= (right as number);\n case '>=': return (left as number) >= (right as number);\n default:\n throw new Error(`Unsupported operator: ${binaryNode.operator}`);\n }\n }\n\n case 'ConditionalExpression': {\n // Ternary: condition ? consequent : alternate\n const condNode = node as jsep.ConditionalExpression;\n const test = evaluateNode(condNode.test, context);\n return test\n ? evaluateNode(condNode.consequent, context)\n : evaluateNode(condNode.alternate, context);\n }\n\n case 'UnaryExpression': {\n // Unary operators: !, -, +\n const unaryNode = node as jsep.UnaryExpression;\n const arg = evaluateNode(unaryNode.argument, context);\n\n switch (unaryNode.operator) {\n case '!': return !arg;\n case '-': return -(arg as number);\n case '+': return +(arg as number);\n default:\n throw new Error(`Unsupported unary operator: ${unaryNode.operator}`);\n }\n }\n\n case 'ArrayExpression': {\n // Array literals: [1, 2, 3]\n const arrayNode = node as jsep.ArrayExpression;\n return arrayNode.elements.map(el =>\n el ? evaluateNode(el, context) : undefined\n );\n }\n\n case 'CallExpression': {\n // Function calls - only allow safe built-in methods\n // For security, we don't allow arbitrary function calls\n throw new Error('Function calls are not supported in template expressions');\n }\n\n case 'Compound':\n // Multiple expressions - not supported for security\n throw new Error('Compound expressions are not supported');\n\n default:\n throw new Error(`Unsupported expression type: ${node.type}`);\n }\n}\n\n/**\n * Safely evaluates a template expression using jsep\n * Returns undefined for parse errors or evaluation failures\n */\nexport function safeEvaluate(expression: string, context: Record<string, unknown>): unknown {\n try {\n const ast = jsep(expression);\n return evaluateNode(ast, context);\n } catch {\n // Return undefined for parse errors (e.g., undefined variables)\n return undefined;\n }\n}\n\n/**\n * Check if an expression contains operators (needs evaluation vs simple field access)\n * Used to determine whether to use the expression evaluator or simple field lookup\n */\nexport function isComplexExpression(expression: string): boolean {\n // Check for operators that require evaluation\n // Excludes dots (.) which are used for simple field access\n return /[?:+\\-*/%<>=!&|]/.test(expression);\n}\n", "/**\n * Global Template Context\n * Provides global variables available in all template expressions.\n *\n * Used for environment-level variables like isEditorMode that need\n * to be accessible across all components without prop drilling.\n */\n\n/**\n * Global template variables available in all {{expression}} evaluations\n */\nexport interface GlobalTemplateVariables {\n /** True when running in editor mode (disables autoplay, etc.) */\n isEditorMode: boolean;\n}\n\nconst defaultValues: GlobalTemplateVariables = {\n isEditorMode: false,\n};\n\nlet globalContext: GlobalTemplateVariables = { ...defaultValues };\n\n/**\n * Set global template variables\n * Called during client initialization to set environment-level values\n */\nexport function setGlobalTemplateContext(values: Partial<GlobalTemplateVariables>): void {\n globalContext = { ...globalContext, ...values };\n}\n\n/**\n * Get current global template variables\n * Used by template evaluation to merge with props context\n */\nexport function getGlobalTemplateContext(): GlobalTemplateVariables {\n return globalContext;\n}\n\n/**\n * Reset global template context to defaults\n * Useful for testing\n */\nexport function resetGlobalTemplateContext(): void {\n globalContext = { ...defaultValues };\n}\n", "/**\n * Interactive Style Mappings Utilities\n *\n * Extracts StyleMappings from interactive styles and replaces them with CSS variable references.\n * This enables component instances to have different hover/focus/etc. styles based on props\n * while sharing the same CSS rules.\n *\n * @example\n * const { resolvedStyles, mappings } = extractInteractiveStyleMappings([\n * { selector: ':hover', style: { base: { backgroundColor: { _mapping: true, prop: 'variant', values: { primary: '#0070f3' } } } } }\n * ]);\n * // resolvedStyles[0].style.base.backgroundColor === 'var(--is-0)'\n */\n\nimport type {\n InteractiveStyles,\n InteractiveStyleRule,\n StyleMapping,\n StyleObject,\n ResponsiveStyleObject,\n} from './types/styles';\nimport type { PropDefinition } from './types/components';\n\n/**\n * Type guard to check if a value is a StyleMapping\n */\nexport function isStyleMapping(value: unknown): value is StyleMapping {\n return (\n typeof value === 'object' &&\n value !== null &&\n '_mapping' in value &&\n (value as StyleMapping)._mapping === true\n );\n}\n\n/**\n * Extracted mapping information\n */\nexport interface ExtractedMapping {\n /** Index of the rule in the interactiveStyles array */\n ruleIndex: number;\n /** Breakpoint name (null for flat styles, 'base'/'tablet'/'mobile' for responsive) */\n breakpoint: string | null;\n /** CSS property name */\n property: string;\n /** The original StyleMapping object */\n mapping: StyleMapping;\n /** Flat index for variable naming: 0, 1, 2, 3... */\n variableIndex: number;\n}\n\n/**\n * Result of extracting mappings from interactive styles\n */\nexport interface ExtractionResult {\n /** Interactive styles with mappings replaced by var() references */\n resolvedStyles: InteractiveStyles;\n /** Extracted mappings with generated variable names */\n mappings: ExtractedMapping[];\n}\n\n/**\n * Generate CSS variable name from index\n * Variable names are: --is-0, --is-1, --is-2, etc.\n */\nexport function getVariableName(index: number): string {\n return `--is-${index}`;\n}\n\n/**\n * Check if a style object (flat or responsive) contains any mappings\n */\nfunction hasAnyMappings(style: StyleObject | ResponsiveStyleObject): boolean {\n // Check if it's a responsive style (has 'base' or known breakpoint keys)\n const isResponsive = 'base' in style || Object.keys(style).some(key =>\n key === 'base' || key === 'tablet' || key === 'mobile'\n );\n\n if (isResponsive) {\n const responsive = style as ResponsiveStyleObject;\n for (const breakpointStyle of Object.values(responsive)) {\n if (breakpointStyle) {\n for (const value of Object.values(breakpointStyle)) {\n if (isStyleMapping(value)) return true;\n }\n }\n }\n } else {\n const flat = style as StyleObject;\n for (const value of Object.values(flat)) {\n if (isStyleMapping(value)) return true;\n }\n }\n\n return false;\n}\n\n/**\n * Check if interactive styles contain any mappings\n */\nexport function hasInteractiveStyleMappings(interactiveStyles: InteractiveStyles): boolean {\n for (const rule of interactiveStyles) {\n if (hasAnyMappings(rule.style)) return true;\n }\n return false;\n}\n\n/**\n * Extract mappings from interactive styles and replace with CSS variable references\n *\n * @param interactiveStyles - Array of interactive style rules\n * @returns Object with resolved styles (var() references) and extracted mappings\n */\nexport function extractInteractiveStyleMappings(\n interactiveStyles: InteractiveStyles\n): ExtractionResult {\n const mappings: ExtractedMapping[] = [];\n let variableIndex = 0;\n\n const resolvedStyles: InteractiveStyles = interactiveStyles.map((rule, ruleIndex) => {\n const style = rule.style;\n\n // Check if it's a responsive style\n const isResponsive = 'base' in style || Object.keys(style).some(key =>\n key === 'base' || key === 'tablet' || key === 'mobile'\n );\n\n if (isResponsive) {\n const responsive = style as ResponsiveStyleObject;\n const resolvedResponsive: ResponsiveStyleObject = {};\n\n for (const [breakpointName, breakpointStyle] of Object.entries(responsive)) {\n if (!breakpointStyle) continue;\n\n const resolvedBreakpointStyle: StyleObject = {};\n\n for (const [prop, value] of Object.entries(breakpointStyle)) {\n if (isStyleMapping(value)) {\n // Extract the mapping\n mappings.push({\n ruleIndex,\n breakpoint: breakpointName,\n property: prop,\n mapping: value,\n variableIndex,\n });\n\n // Replace with var() reference\n resolvedBreakpointStyle[prop] = `var(${getVariableName(variableIndex)})`;\n variableIndex++;\n } else {\n resolvedBreakpointStyle[prop] = value;\n }\n }\n\n resolvedResponsive[breakpointName] = resolvedBreakpointStyle;\n }\n\n return {\n ...rule,\n style: resolvedResponsive,\n };\n } else {\n // Flat style object\n const flat = style as StyleObject;\n const resolvedFlat: StyleObject = {};\n\n for (const [prop, value] of Object.entries(flat)) {\n if (isStyleMapping(value)) {\n // Extract the mapping\n mappings.push({\n ruleIndex,\n breakpoint: null,\n property: prop,\n mapping: value,\n variableIndex,\n });\n\n // Replace with var() reference\n resolvedFlat[prop] = `var(${getVariableName(variableIndex)})`;\n variableIndex++;\n } else {\n resolvedFlat[prop] = value;\n }\n }\n\n return {\n ...rule,\n style: resolvedFlat,\n };\n }\n });\n\n return { resolvedStyles, mappings };\n}\n\n/**\n * Resolve extracted mappings to CSS variable values based on component props\n *\n * @param mappings - Extracted mappings from extractInteractiveStyleMappings\n * @param props - Component props to resolve against\n * @returns Object mapping variable names to resolved values: { '--is-0': '#0070f3', '--is-1': '#0055cc' }\n */\nexport function resolveExtractedMappings(\n mappings: ExtractedMapping[],\n props: Record<string, unknown>\n): Record<string, string> {\n const cssVariables: Record<string, string> = {};\n\n for (const extracted of mappings) {\n const { mapping, variableIndex } = extracted;\n const propValue = props[mapping.prop];\n\n // Skip if prop value is undefined or null\n if (propValue === undefined || propValue === null) {\n continue;\n }\n\n // Convert prop value to string for lookup\n const propValueStr = String(propValue);\n\n // Look up the resolved style value\n const resolvedValue = mapping.values[propValueStr];\n\n // Skip if prop value not in mapping (e.g., variant='purple' with only 'primary'/'secondary' defined)\n if (resolvedValue === undefined) {\n continue;\n }\n\n const variableName = getVariableName(variableIndex);\n cssVariables[variableName] = String(resolvedValue);\n }\n\n return cssVariables;\n}\n\n/**\n * Create a StyleMapping from component prop definitions\n *\n * @param componentPropDefs - Component prop definitions\n * @param currentValue - Current style value to use as default for first option\n * @returns StyleMapping object or null if no props available\n *\n * @example\n * const mapping = createStyleMappingFromProps(\n * { variant: { type: 'select', options: ['primary', 'secondary'] } },\n * '#0070f3'\n * );\n * // Returns: { _mapping: true, prop: 'variant', values: { primary: '#0070f3', secondary: '' } }\n */\nexport function createStyleMappingFromProps(\n componentPropDefs: Record<string, PropDefinition>,\n currentValue: string | number\n): StyleMapping | null {\n // Find a prop to map to (prefer 'variant' if it exists, otherwise use first prop)\n const propToMap = componentPropDefs.variant ? 'variant' : Object.keys(componentPropDefs)[0];\n\n if (!propToMap) {\n return null;\n }\n\n // Get options for the prop if it's a select type\n const propDef = componentPropDefs[propToMap];\n const options = propDef?.type === 'select' && Array.isArray(propDef.options) ? propDef.options : [];\n\n // Create mapping with current value as default for first option\n const mappingValues: Record<string, string | number> = {};\n if (options.length > 0) {\n mappingValues[options[0]] = currentValue;\n // Add other options with empty/default values\n options.slice(1).forEach((opt: string) => {\n mappingValues[opt] = '';\n });\n } else {\n // No options, create a default mapping\n mappingValues['default'] = currentValue;\n }\n\n return {\n _mapping: true,\n prop: propToMap,\n values: mappingValues\n };\n}\n", "/**\n * meno-astro/server \u2014 `loadI18nConfig`.\n *\n * Reads a converted project's `project.config.json`, pulls its `.i18n` block, and runs it\n * through meno-core's `migrateI18nConfig` so both the modern `LocaleConfig[]` shape and the\n * legacy `string[]` locales shape resolve to a canonical {@link I18nConfig}. Any failure\n * (missing file, unparseable JSON, absent/empty `.i18n`) degrades to\n * `DEFAULT_I18N_CONFIG` rather than throwing \u2014 a project should always render in *some*\n * locale, even one that predates i18n config.\n *\n * This is the single source of truth the locale middleware (and, by extension, every\n * `i18n()` call) reads its config from. It is server/build-only (touches the filesystem)\n * and reuses meno-core wholesale \u2014 no migration logic is reinvented here.\n */\n\nimport { existsSync, readFileSync } from 'fs';\nimport { join } from 'path';\nimport { migrateI18nConfig, DEFAULT_I18N_CONFIG } from 'meno-core/shared';\nimport type { I18nConfig } from 'meno-core/shared/types';\n\n/**\n * Load the i18n config for the project rooted at `projectRoot`.\n *\n * Resolution:\n * 1. Read `<projectRoot>/project.config.json`. Missing/unreadable \u2192 `DEFAULT_I18N_CONFIG`.\n * 2. Take its `.i18n` value and run `migrateI18nConfig` (handles modern + legacy shapes,\n * and itself falls back to `DEFAULT_I18N_CONFIG` for anything it can't interpret).\n *\n * Never throws: every failure path returns `DEFAULT_I18N_CONFIG`.\n */\nexport function loadI18nConfig(projectRoot: string): I18nConfig {\n try {\n const cfgPath = join(projectRoot, 'project.config.json');\n if (!existsSync(cfgPath)) return DEFAULT_I18N_CONFIG;\n const raw = readFileSync(cfgPath, 'utf8');\n const parsed = JSON.parse(raw) as { i18n?: unknown };\n // migrateI18nConfig itself returns DEFAULT_I18N_CONFIG for undefined/empty/invalid.\n return migrateI18nConfig(parsed.i18n);\n } catch {\n return DEFAULT_I18N_CONFIG;\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["z", "z", "h", "ComponentNodeSchemaRef", "z", "z", "h", "z", "h", "ComponentNodeSchemaRef", "z", "h", "z", "h", "CMSFilterConditionSchema", "CMSSortConfigSchema", "parseValue", "parseValue", "parseValue", "z", "z", "z"]
|
|
7
|
+
}
|