idml-ui 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 +102 -0
- package/dist/cli.cjs +292 -0
- package/dist/index.cjs +2434 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +599 -0
- package/dist/index.d.ts +599 -0
- package/dist/index.js +2380 -0
- package/dist/index.js.map +1 -0
- package/dist/server.cjs +1236 -0
- package/dist/server.cjs.map +1 -0
- package/dist/server.d.cts +184 -0
- package/dist/server.d.ts +184 -0
- package/dist/server.js +1195 -0
- package/dist/server.js.map +1 -0
- package/package.json +78 -0
- package/ui.config.schema.json +495 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/server.ts","../src/next-plugin/index.ts","../src/next-plugin/watcher.ts","../src/parser/idml-parser.ts"],"sourcesContent":["// Server-side only exports\n// Note: This entry point must never import from src/renderer/ or src/editor/\n\nexport { withUIConfig } from './next-plugin';\nexport { startWatcher, stopWatcher, addSSEWriter } from './next-plugin/watcher';\nexport type { UIConfigOptions } from './next-plugin';\n\n// Parser is safe to use server-side (no React dependency)\nexport { parseIdml } from './parser/idml-parser';\n","import type { NextConfig } from 'next';\nimport path from 'node:path';\n\nexport interface UIConfigOptions {\n configPath?: string;\n editorEnabled?: boolean;\n}\n\nexport function withUIConfig(\n options: UIConfigOptions = {}\n): (nextConfig: NextConfig) => NextConfig {\n const {\n configPath = './ui.config.json',\n editorEnabled = process.env.NODE_ENV === 'development',\n } = options;\n\n const resolvedConfigPath = path.resolve(process.cwd(), configPath);\n\n return function (nextConfig: NextConfig): NextConfig {\n return {\n ...nextConfig,\n\n env: {\n ...nextConfig.env,\n ISD_UI_CONFIG_PATH: resolvedConfigPath,\n ISD_UI_EDITOR_ENABLED: String(editorEnabled),\n },\n\n async rewrites() {\n const existing = await nextConfig.rewrites?.();\n const isdRewrites = editorEnabled\n ? [\n {\n source: '/_isd-editor',\n destination: '/isd/editor',\n },\n {\n source: '/_isd-editor/:path*',\n destination: '/isd/editor/:path*',\n },\n ]\n : [];\n\n if (Array.isArray(existing)) {\n return [...existing, ...isdRewrites];\n }\n\n return {\n beforeFiles: [...(existing?.beforeFiles ?? [])],\n afterFiles: [...(existing?.afterFiles ?? []), ...isdRewrites],\n fallback: [...(existing?.fallback ?? [])],\n };\n },\n };\n };\n}\n","import chokidar from 'chokidar';\n\ntype SSEWriter = WritableStreamDefaultWriter<Uint8Array>;\n\nconst writers = new Set<SSEWriter>();\nlet watcher: ReturnType<typeof chokidar.watch> | null = null;\n\nexport function startWatcher(configPath: string): void {\n if (watcher) return;\n\n watcher = chokidar.watch(configPath, {\n persistent: true,\n ignoreInitial: true,\n awaitWriteFinish: { stabilityThreshold: 150, pollInterval: 50 },\n });\n\n watcher.on('change', () => {\n broadcastConfigChange();\n });\n\n watcher.on('error', (err) => {\n console.error('[idml] Watcher error:', err);\n });\n}\n\nexport async function stopWatcher(): Promise<void> {\n if (!watcher) return;\n await watcher.close();\n watcher = null;\n}\n\nexport function addSSEWriter(writer: SSEWriter): () => void {\n writers.add(writer);\n return () => writers.delete(writer);\n}\n\nfunction broadcastConfigChange(): void {\n const encoder = new TextEncoder();\n const message = encoder.encode(`data: ${JSON.stringify({ type: 'config:change', ts: Date.now() })}\\n\\n`);\n\n for (const writer of writers) {\n writer.write(message).catch(() => {\n writers.delete(writer);\n });\n }\n}\n","import type { UIConfig, LayoutDef, ComponentDef, FlexDef, SizeDef, DataBindingDef } from '../types';\nimport type { PercentageString, DynamicSize, DynamicDim } from '../types/layout.types';\n\n// ==================== PARSED INTERMEDIATE TYPES ====================\n\n// A dimension is a static percentage number, or a `@ref` value-binding (resolved\n// per render to a dimension) so a cell can resize on state — e.g. a sidebar that\n// narrows when collapsed. A `@ref ? A : B` form picks A/B from the ref's\n// truthiness so the two sizes (the visual values) live in the .idml, not in a\n// method. (`'auto'` is gone; see parseDimension.)\ntype DimRef = { ref: string; whenTrue?: string; whenFalse?: string };\n// `'auto'` is internal-only (table expansion uses it for content-height); the\n// parser rejects it as user input. `@ref` dims come from `parseDimension`.\ntype DimValue = number | 'auto' | DimRef;\nconst isDimRef = (d: DimValue): d is DimRef => typeof d === 'object' && d !== null && 'ref' in d;\n\n/**\n * Content-sizing (\"hug\") flags. An element still declares its `[h,w]` percentage\n * tile — that tile is its MAX bound — but a hugged axis shrinks the bound\n * component to its content within the tile (instead of stretching to fill it),\n * clipping with an ellipsis if the content would overflow the tile.\n */\ninterface HugSpec {\n w: boolean;\n h: boolean;\n}\n\n// An argument value in a component call. Bare identifiers become tagged strings\n// (FN_REF_PREFIX = handler, VALUE_REF_PREFIX = reactive value binding); `null`,\n// booleans, numbers and strings are literals; a `{ }` block is a children marker.\ntype IdmlArg = string | number | boolean | null | Record<string, unknown>;\n\ninterface ParsedItem {\n name: string;\n args: IdmlArg[];\n height: DimValue;\n width: DimValue;\n anchor: string;\n children: ParsedItem[];\n style: Record<string, string>;\n className?: string;\n /** Method ids referenced as `@x` tokens inside a class block — resolved per\n * render (with the current row item) and appended to className. */\n classRefs?: string[];\n /** Conditional class blocks (`` `classes`?@ref ``) applied per render. */\n condClasses?: { classes: string; ref: string; negate: boolean }[];\n /** Optional content-sizing flags from a trailing `hug` / `hug-w` / `hug-h`\n * token in the dimension bracket. */\n hug?: HugSpec;\n /** Optional visibility condition from a `?@ref` / `?!@ref` clause after the\n * dims — the element renders only when the ref is truthy (negate flips it). */\n visibility?: VisibilityRef;\n}\n\n/** A reactive show/hide condition: render the element only when `ref` (a value\n * path like `state.open` / `item.x` / a method) is truthy; `negate` flips it. */\ninterface VisibilityRef {\n ref: string;\n negate: boolean;\n}\n\ninterface ParsedPage {\n route: string;\n scroll: boolean;\n items: ParsedItem[];\n}\n\ninterface StyleEntry {\n baseType: string;\n defaultArgs: IdmlArg[];\n style: Record<string, string>;\n /** Utility (Tailwind) classes baked into this styled variant. */\n className?: string;\n}\n\n// ==================== TOKENIZER ====================\n\ntype TokenType =\n | 'ROUTE'\n | 'IDENT'\n | 'NUMBER'\n | 'STRING'\n | 'COLOR'\n | 'COLON'\n | 'LPAREN'\n | 'RPAREN'\n | 'LBRACKET'\n | 'RBRACKET'\n | 'LBRACE'\n | 'RBRACE'\n | 'COMMA'\n | 'QUESTION'\n | 'BANG'\n | 'VALUE_REF'\n | 'MODEL_REF'\n | 'CLASS_BLOCK';\n\ninterface Token {\n type: TokenType;\n value?: string | number;\n}\n\nconst SINGLE_CHAR_TOKENS: Record<string, TokenType> = {\n '(': 'LPAREN',\n ')': 'RPAREN',\n '[': 'LBRACKET',\n ']': 'RBRACKET',\n '{': 'LBRACE',\n '}': 'RBRACE',\n ',': 'COMMA',\n ':': 'COLON',\n '?': 'QUESTION',\n '!': 'BANG',\n};\n\n// Hard maximum line width. Lines longer than this are a parse error: long lines\n// hide structure, so the DSL is kept legible at a glance.\nconst MAX_LINE_WIDTH = 80;\n\n/**\n * Source-level rules enforced before tokenizing (so they apply to the main file\n * and every imported file uniformly):\n * - no line may exceed MAX_LINE_WIDTH columns;\n * - comments (`#` lines) are only allowed in the header — a single block at the\n * top of the file, before the first line of code. A comment anywhere after\n * code has started is an error.\n * Blank lines are allowed anywhere. Inline `#rrggbb` colours are not affected:\n * only a line whose first non-whitespace character is `#` counts as a comment.\n */\nfunction validateSource(source: string): void {\n const lines = source.split('\\n');\n let codeStarted = false;\n lines.forEach((line, idx) => {\n const lineNo = idx + 1;\n if (line.length > MAX_LINE_WIDTH) {\n throw new Error(\n `[idml] line ${lineNo} is ${line.length} columns; the limit is ${MAX_LINE_WIDTH}`\n );\n }\n const trimmed = line.trim();\n if (trimmed === '') return;\n if (trimmed.startsWith('#')) {\n if (codeStarted) {\n throw new Error(\n `[idml] line ${lineNo}: comments are only allowed in the header block ` +\n `at the very top of the file, before any code`\n );\n }\n return;\n }\n codeStarted = true;\n });\n}\n\nfunction tokenize(source: string): Token[] {\n validateSource(source);\n\n // Strip whole-line comments (lines where # is the first non-whitespace char).\n // This preserves inline # such as hex colours inside style blocks.\n const stripped = source\n .split('\\n')\n .map(line => (line.trimStart().startsWith('#') ? '' : line))\n .join('\\n');\n\n const tokens: Token[] = [];\n let i = 0;\n\n while (i < stripped.length) {\n if (/\\s/.test(stripped[i])) { i++; continue; }\n\n // Route: ./segment or ./segment/segment (multi-segment routes supported)\n if (stripped[i] === '.' && stripped[i + 1] === '/') {\n let j = i + 2;\n while (j < stripped.length && /[\\w/-]/.test(stripped[j])) j++;\n tokens.push({ type: 'ROUTE', value: '/' + stripped.slice(i + 2, j) });\n i = j;\n continue;\n }\n\n // Hex color: #rrggbb or #rgb\n if (stripped[i] === '#' && /[0-9a-fA-F]/.test(stripped[i + 1] ?? '')) {\n let j = i + 1;\n while (j < stripped.length && /[0-9a-fA-F]/.test(stripped[j])) j++;\n tokens.push({ type: 'COLOR', value: stripped.slice(i, j) });\n i = j;\n continue;\n }\n\n // Reactive value reference: @methodName or @item.field or @obj.field — binds a\n // prop to a live value. A dotted path's first segment is either the reserved\n // `item` (current repeat row) or a registered method; later segments index\n // into the result. A bare identifier (no @) is a handler instead.\n if (stripped[i] === '@' && /[a-zA-Z_]/.test(stripped[i + 1] ?? '')) {\n let j = i + 1;\n while (j < stripped.length && /[\\w.-]/.test(stripped[j])) j++;\n tokens.push({ type: 'VALUE_REF', value: stripped.slice(i + 1, j) });\n i = j;\n continue;\n }\n\n // Two-way model reference: ~stateName — binds an input's value to a form-state\n // cell (read + write). Used on form inputs, e.g. Input(~email).\n if (stripped[i] === '~' && /[a-zA-Z_]/.test(stripped[i + 1] ?? '')) {\n let j = i + 1;\n while (j < stripped.length && /[\\w-]/.test(stripped[j])) j++;\n tokens.push({ type: 'MODEL_REF', value: stripped.slice(i + 1, j) });\n i = j;\n continue;\n }\n\n // Inline `<...>` style blocks are no longer supported — all styling lives in\n // named styled variants (Name:BaseType). Reject them explicitly.\n if (stripped[i] === '<') {\n throw new Error(\n '[idml] inline `<...>` style blocks are no longer supported; ' +\n 'declare a styled variant (Name:BaseType) and apply it instead'\n );\n }\n\n // CSS class block: `class names here` (backticks). Spaces allowed; flows to\n // the element's className (e.g. Tailwind utilities).\n if (stripped[i] === '`') {\n let j = i + 1;\n while (j < stripped.length && stripped[j] !== '`') j++;\n tokens.push({ type: 'CLASS_BLOCK', value: stripped.slice(i + 1, j).trim() });\n i = j + 1;\n continue;\n }\n\n // Single-char tokens\n if (stripped[i] in SINGLE_CHAR_TOKENS) {\n tokens.push({ type: SINGLE_CHAR_TOKENS[stripped[i]] });\n i++;\n continue;\n }\n\n // Quoted string\n if (stripped[i] === '\"') {\n let j = i + 1;\n while (j < stripped.length && stripped[j] !== '\"') {\n if (stripped[j] === '\\\\') j++;\n j++;\n }\n tokens.push({ type: 'STRING', value: stripped.slice(i + 1, j) });\n i = j + 1;\n continue;\n }\n\n // Number (may include decimal point)\n if (/\\d/.test(stripped[i])) {\n let j = i;\n while (j < stripped.length && /[\\d.]/.test(stripped[j])) j++;\n tokens.push({ type: 'NUMBER', value: parseFloat(stripped.slice(i, j)) });\n i = j;\n continue;\n }\n\n // Identifier (includes hyphenated keywords like top-left)\n if (/[a-zA-Z_]/.test(stripped[i])) {\n let j = i;\n while (j < stripped.length && /[\\w-]/.test(stripped[j])) j++;\n tokens.push({ type: 'IDENT', value: stripped.slice(i, j) });\n i = j;\n continue;\n }\n\n throw new Error(`[idml] Unexpected character '${stripped[i]}' at position ${i}`);\n }\n\n return tokens;\n}\n\n// ==================== STYLE PROP MAPPER ====================\n\nfunction applyStyleProp(key: string, val: string, result: Record<string, string>): void {\n switch (key) {\n case 'bg': result.backgroundColor = val; break;\n case 'fg': result.color = val; break;\n case 'size': result.fontSize = val.endsWith('vw') ? val : `${val}vw`; break;\n case 'font': result.fontFamily = val; break;\n case 'weight': result.fontWeight = val; break;\n case 'style':\n if (val === 'bold') result.fontWeight = '700';\n else if (val === 'italic') result.fontStyle = 'italic';\n break;\n case 'pad': result.padding = val.endsWith('%') ? val : `${val}%`; break;\n case 'radius': result.borderRadius = val.endsWith('px') ? val : `${val}px`; break;\n case 'gap': result.gap = val.endsWith('vw') ? val : `${val}vw`; break;\n case 'align': result.textAlign = val; break;\n case 'overflow': result.overflowY = val; break;\n case 'h': result.height = val; break;\n case 'w': result.width = val; break;\n default: result[key] = val;\n }\n}\n\n// ==================== RECURSIVE DESCENT PARSER ====================\n\n// Prefix added to bare-identifier args so callers can distinguish them from string values.\nconst FN_REF_PREFIX = '\\x00fn:';\n// Prefix for `@method` value references — a prop bound to a method's live return value.\nconst VALUE_REF_PREFIX = '\\x00val:';\n// Prefix for `~name` model references — a two-way binding to a form-state cell.\nconst MODEL_REF_PREFIX = '\\x00model:';\n\n// Names that resolve to builtins (renderer-provided) or layout primitives, so an\n// `import` of them needn't be defined in the target file. Kept here (rather than\n// importing from the renderer) to preserve the parser/renderer separation.\nconst BUILTIN_NAMES = new Set([\n 'Text', 'Heading', 'Button', 'Image', 'List', 'Card', 'Divider', 'Spacer',\n 'Icon', 'Table', 'Children', 'Row', 'Col', 'Repeat', 'Form', 'Modal', 'Column',\n 'Overlay', 'Input', 'Textarea', 'Select', 'Option', 'Checkbox', 'Radio', 'Label',\n]);\n\nclass IdmlParser {\n private tokens: Token[];\n private pos = 0;\n styleRegistry: Map<string, StyleEntry> = new Map();\n // Reusable component definitions: name -> body template (item list). A `define`\n // block registers one; using the name as an item expands the body (macro-style),\n // substituting the call's children at the `Children` marker. See convertItem.\n defRegistry: Map<string, ParsedItem[]> = new Map();\n // Parameter names per definition (e.g. `define TopBar(title)` -> ['title']).\n // At expansion the call's positional args are bound to these names and any\n // matching references inside the body are substituted. See convertItem.\n defParamRegistry: Map<string, string[]> = new Map();\n\n constructor(tokens: Token[]) {\n this.tokens = tokens;\n }\n\n private peek(offset = 0): Token | undefined { return this.tokens[this.pos + offset]; }\n\n private consume(type?: TokenType): Token {\n const t = this.tokens[this.pos++];\n if (!t) throw new Error('[idml] Unexpected end of input');\n if (type && t.type !== type) {\n throw new Error(`[idml] Expected ${type}, got ${t.type} (\"${t.value}\")`);\n }\n return t;\n }\n\n // Entry point. resolve() is called to load imported .idml files.\n parseFile(resolve?: (path: string) => string): ParsedPage[] {\n this.parseImports(resolve);\n this.parseTopDecls();\n\n const pages: ParsedPage[] = [];\n while (this.peek()) {\n const route = this.consume('ROUTE').value as string;\n\n let scroll = false;\n if (this.peek()?.type === 'LBRACKET') {\n this.consume('LBRACKET');\n const flag = this.consume('IDENT').value as string;\n if (flag === 'scroll') scroll = true;\n this.consume('RBRACKET');\n }\n\n const items: ParsedItem[] = [];\n while (this.peek() && this.peek()?.type !== 'ROUTE') {\n const t = this.peek();\n // Imports / definitions may appear anywhere in a file — including after\n // the route line (a natural \"this is the /x page, and it needs these\"\n // ordering). Process them into the shared registries and continue.\n if (t?.type === 'IDENT' && t.value === 'import') { this.parseImports(resolve); continue; }\n if (t?.type === 'IDENT' && t.value === 'define') { this.parseDefinition(); continue; }\n if (t?.type === 'IDENT' && this.peek(1)?.type === 'COLON' && this.peek(2)?.type === 'IDENT') {\n this.parseStyleDefs();\n continue;\n }\n items.push(this.parseItem());\n }\n pages.push({ route, scroll, items });\n }\n return pages;\n }\n\n // Consume import lines. Two forms:\n // import \"path\" (whole-file style/def import)\n // import Name, Name from \"path\" (named component/def import)\n // In both cases the referenced .idml file is parsed and its definitions +\n // style-defs are registered into the shared registries.\n private parseImports(resolve?: (path: string) => string): void {\n while (this.peek(0)?.type === 'IDENT' && this.peek(0)?.value === 'import') {\n const next = this.peek(1);\n\n if (next?.type === 'STRING') {\n // Whole-file form: import \"path\"\n this.pos++; // consume 'import'\n const importPath = this.consume('STRING').value as string;\n this.resolveImport(importPath, [], resolve);\n continue;\n }\n\n if (next?.type === 'IDENT') {\n // Named form: import A, B from \"path\"\n this.pos++; // consume 'import'\n const names: string[] = [this.consume('IDENT').value as string];\n while (this.peek()?.type === 'COMMA') {\n this.pos++;\n names.push(this.consume('IDENT').value as string);\n }\n const fromTok = this.consume('IDENT');\n if (fromTok.value !== 'from') {\n throw new Error(`[idml] Expected 'from' in import, got \"${fromTok.value}\"`);\n }\n const importPath = this.consume('STRING').value as string;\n this.resolveImport(importPath, names, resolve);\n continue;\n }\n\n break;\n }\n }\n\n // Resolve and parse an imported .idml file into the shared registries.\n // `names`, when non-empty, are validated against what the file actually defines.\n private resolveImport(\n importPath: string,\n names: string[],\n resolve?: (path: string) => string\n ): void {\n // Only .idml (or extension-less) imports are resolvable here. Other imports\n // (e.g. .ts/.tsx) are documentation-only at parse time.\n const afterLastSlash = importPath.slice(importPath.lastIndexOf('/') + 1);\n const dotIdx = afterLastSlash.lastIndexOf('.');\n const ext = dotIdx >= 0 ? afterLastSlash.slice(dotIdx) : '';\n if (ext !== '.idml' && ext !== '') return;\n if (!resolve) return;\n\n const src = resolve(importPath);\n const sub = new IdmlParser(tokenize(src));\n sub.styleRegistry = this.styleRegistry; // share registries\n sub.defRegistry = this.defRegistry;\n sub.defParamRegistry = this.defParamRegistry;\n sub.parseImports(resolve); // transitive imports\n sub.parseTopDecls();\n\n for (const name of names) {\n if (\n !this.defRegistry.has(name) &&\n !this.styleRegistry.has(name) &&\n !BUILTIN_NAMES.has(name)\n ) {\n console.warn(`[idml] import: \"${name}\" is not defined in ${importPath}`);\n }\n }\n }\n\n // Parse the top-of-file declarations: `define` component definitions and\n // `Name:BaseType` style-defs, in any order, until a page route or EOF.\n private parseTopDecls(): void {\n for (;;) {\n const t = this.peek();\n if (t?.type === 'IDENT' && t.value === 'define') {\n this.parseDefinition();\n continue;\n }\n if (\n t?.type === 'IDENT' &&\n this.peek(1)?.type === 'COLON' &&\n this.peek(2)?.type === 'IDENT'\n ) {\n this.parseStyleDefs();\n continue;\n }\n break;\n }\n }\n\n // Consume `define Name(params?) { ...items including Children()... }`.\n private parseDefinition(): void {\n this.pos++; // consume 'define'\n const name = this.consume('IDENT').value as string;\n\n // Parameter list: bare identifiers, bound positionally to the call args at\n // expansion time (see convertItem's definition branch + substituteParams).\n this.consume('LPAREN');\n const params: string[] = [];\n if (this.peek()?.type !== 'RPAREN') {\n params.push(this.consume('IDENT').value as string);\n while (this.peek()?.type === 'COMMA') {\n this.pos++;\n params.push(this.consume('IDENT').value as string);\n }\n }\n this.consume('RPAREN');\n\n this.consume('LBRACE');\n const body: ParsedItem[] = [];\n while (this.peek()?.type !== 'RBRACE') {\n body.push(this.parseItem());\n }\n this.consume('RBRACE');\n\n this.defRegistry.set(name, body);\n this.defParamRegistry.set(name, params);\n }\n\n // Consume `Name:BaseType(\"arg\"...) { prop: value }` definitions.\n parseStyleDefs(): void {\n while (\n this.peek(0)?.type === 'IDENT' &&\n this.peek(1)?.type === 'COLON' &&\n this.peek(2)?.type === 'IDENT'\n ) {\n const name = this.consume('IDENT').value as string;\n this.consume('COLON');\n const baseType = this.consume('IDENT').value as string;\n\n // Optional pre-set args: Name:Type(\"arg1\", \"arg2\") { ... }\n const defaultArgs: IdmlArg[] = [];\n if (this.peek()?.type === 'LPAREN') {\n this.consume('LPAREN');\n if (this.peek()?.type !== 'RPAREN') defaultArgs.push(...this.parseArgList());\n this.consume('RPAREN');\n }\n\n // Optional baked-in utility classes: Name:Type `tailwind classes`\n let className: string | undefined;\n while (this.peek()?.type === 'CLASS_BLOCK') {\n const cls = this.consume('CLASS_BLOCK').value as string;\n className = className ? `${className} ${cls}` : cls;\n }\n\n // The `{ cssProp: val }` body is optional — a styled variant may carry only\n // classes (the common case) and/or pre-set args.\n const style = this.peek()?.type === 'LBRACE' ? this.parseStyleDefBody() : {};\n\n this.styleRegistry.set(name, { baseType, defaultArgs, style, className });\n }\n }\n\n // Parse `{ prop: value ... }` body of a style definition.\n private parseStyleDefBody(): Record<string, string> {\n this.consume('LBRACE');\n const result: Record<string, string> = {};\n while (this.peek()?.type !== 'RBRACE') {\n const key = this.consume('IDENT').value as string;\n this.consume('COLON');\n const val = this.parseStyleValue();\n applyStyleProp(key, val, result);\n }\n this.consume('RBRACE');\n return result;\n }\n\n // Parse a value token inside a style def body.\n private parseStyleValue(): string {\n const t = this.peek();\n if (!t) throw new Error('[idml] Expected style value');\n\n if (t.type === 'COLOR') { this.pos++; return t.value as string; }\n\n if (t.type === 'NUMBER') {\n const n = this.consume('NUMBER').value as number;\n const next = this.peek();\n if (next?.type === 'IDENT' && ['vh', 'vw', 'px', 'rem', 'em'].includes(next.value as string)) {\n this.pos++;\n return `${n}${next.value}`;\n }\n return String(n);\n }\n\n if (t.type === 'IDENT') { this.pos++; return t.value as string; }\n\n throw new Error(`[idml] Unexpected token type ${t.type} as style value`);\n }\n\n parseItem(): ParsedItem {\n const rawName = this.consume('IDENT').value as string;\n\n const regEntry = this.styleRegistry.get(rawName);\n const name = regEntry ? regEntry.baseType : rawName;\n const baseStyle: Record<string, string> = regEntry ? { ...regEntry.style } : {};\n\n // Args are always required: Name(arg, ...) or Name()\n this.consume('LPAREN');\n const parsedArgs: IdmlArg[] = [];\n if (this.peek()?.type !== 'RPAREN') parsedArgs.push(...this.parseArgList());\n this.consume('RPAREN');\n\n // Lift any `{ ... }` children-block args out of the arg list; they become\n // part of this item's children (merged with the trailing `{ }` block below).\n const inlineChildren: ParsedItem[] = [];\n const valueArgs: IdmlArg[] = [];\n for (const a of parsedArgs) {\n if (a && typeof a === 'object' && Array.isArray((a as Record<string, unknown>).__idmlChildren)) {\n inlineChildren.push(...((a as { __idmlChildren: ParsedItem[] }).__idmlChildren));\n } else {\n valueArgs.push(a);\n }\n }\n\n // Use provided value args; fall back to style-def defaults if none given\n const args = valueArgs.length > 0 ? valueArgs : (regEntry?.defaultArgs ?? []);\n\n // Dimensions: [height%, width%, anchor]. Required on every item, and always\n // explicit numbers — the `auto` keyword is gone (see parseDimension), because\n // every element must declare exactly how much space it occupies.\n if (this.peek()?.type !== 'LBRACKET') {\n throw new Error(\n `[idml] \"${rawName}\" is missing its required [height,width,anchor] ` +\n `dimensions`\n );\n }\n this.consume('LBRACKET');\n const height = this.parseDimension();\n this.consume('COMMA');\n const width = this.parseDimension();\n this.consume('COMMA');\n const anchor = this.consume('IDENT').value as string;\n // Optional trailing sizing keyword: [h, w, anchor, hug|hug-w|hug-h]. It makes\n // the bound component hug its content within the declared tile (see HugSpec).\n let hug: HugSpec | undefined;\n if (this.peek()?.type === 'COMMA') {\n this.consume('COMMA');\n const kw = this.consume('IDENT').value as string;\n if (kw === 'hug') hug = { w: true, h: true };\n else if (kw === 'hug-w') hug = { w: true, h: false };\n else if (kw === 'hug-h') hug = { w: false, h: true };\n else\n throw new Error(\n `[idml] unknown sizing keyword \"${kw}\" for \"${rawName}\"; ` +\n `expected hug, hug-w, or hug-h`\n );\n }\n this.consume('RBRACKET');\n\n // Optional visibility clause: `?@ref` (show when truthy) or `?!@ref` (show\n // when falsy). `ref` is a value path — `@state.x`, `@item.x`, or `@method`.\n let visibility: VisibilityRef | undefined;\n if (this.peek()?.type === 'QUESTION') {\n this.consume('QUESTION');\n let negate = false;\n if (this.peek()?.type === 'BANG') { this.consume('BANG'); negate = true; }\n const ref = this.consume('VALUE_REF').value as string;\n visibility = { ref, negate };\n }\n\n // Optional `` `class names` `` block before the children. A styled variant\n // (Name:BaseType) seeds its baked-in classes here. A use-site class block may\n // contain ONLY dynamic `@method` bindings (e.g. a per-row colour) — literal\n // utility classes are not allowed at a use site; they belong in a variant.\n let className: string | undefined = regEntry?.className;\n const condClasses: { classes: string; ref: string; negate: boolean }[] = [];\n while (this.peek()?.type === 'CLASS_BLOCK') {\n const cls = this.consume('CLASS_BLOCK').value as string;\n // Optional trailing condition `?@ref` / `?!@ref`: these classes apply only\n // when the ref is truthy / falsy. A CONDITIONAL block may use literal\n // classes — it expresses a state-driven visual (e.g. a pop-up's scale/\n // opacity), which belongs in the .idml, not a method.\n if (this.peek()?.type === 'QUESTION') {\n this.consume('QUESTION');\n let negate = false;\n if (this.peek()?.type === 'BANG') { this.consume('BANG'); negate = true; }\n const ref = this.consume('VALUE_REF').value as string;\n condClasses.push({ classes: cls, ref, negate });\n continue;\n }\n // Unconditional use-site block: only `@method` bindings (no literals).\n for (const tok of cls.split(/\\s+/).filter(Boolean)) {\n if (!tok.startsWith('@')) {\n throw new Error(\n `[idml] literal class \"${tok}\" is not allowed at a use site; ` +\n `declare a styled variant (Name:BaseType) instead`\n );\n }\n }\n className = className ? `${className} ${cls}` : cls;\n }\n\n const style = { ...baseStyle };\n\n // Split the class string into static classes and `@method` references. The\n // refs are resolved per render (with the current row item) and appended to\n // className — so e.g. a role badge can colour itself from its row's role.\n const classRefs: string[] = [];\n if (className) {\n const statics: string[] = [];\n for (const tok of className.split(/\\s+/).filter(Boolean)) {\n if (tok.startsWith('@')) classRefs.push(tok.slice(1));\n else statics.push(tok);\n }\n className = statics.length ? statics.join(' ') : undefined;\n }\n\n this.consume('LBRACE');\n const children: ParsedItem[] = [...inlineChildren];\n while (this.peek()?.type !== 'RBRACE') {\n children.push(this.parseItem());\n }\n this.consume('RBRACE');\n\n return { name, args, height, width, anchor, children, style, className, classRefs, condClasses, hug, visibility };\n }\n\n private parseDimension(): DimValue {\n if (this.peek()?.type === 'IDENT' && this.peek()?.value === 'auto') {\n throw new Error(\n '[idml] the `auto` dimension is no longer supported; give an explicit ' +\n 'percentage (use a Spacer for any intentional empty space)'\n );\n }\n // `@ref` dimension — resolved per render to a percentage (reactive sizing).\n // `@ref ? A : B` resolves to A when the ref is truthy, else B (the two sizes\n // declared inline, e.g. `@state.collapsed ? 3.4vw : 13.5vw`).\n if (this.peek()?.type === 'VALUE_REF') {\n const ref = this.consume('VALUE_REF').value as string;\n if (this.peek()?.type === 'QUESTION') {\n this.consume('QUESTION');\n const whenTrue = this.parseDimLiteral();\n this.consume('COLON');\n const whenFalse = this.parseDimLiteral();\n return { ref, whenTrue, whenFalse };\n }\n return { ref };\n }\n return this.consume('NUMBER').value as number;\n }\n\n /** A literal dimension value inside a `@ref ? A : B`: a number (→ `%`) or a\n * number with a unit (`3.4vw`, `64px`). Returns the final CSS string. */\n private parseDimLiteral(): string {\n const n = this.consume('NUMBER').value as number;\n const next = this.peek();\n if (next?.type === 'IDENT' && ['vw', 'vh', 'px', 'rem', 'em'].includes(next.value as string)) {\n this.pos++;\n return `${n}${next.value}`;\n }\n return `${n}%`;\n }\n\n private parseArgList(): IdmlArg[] {\n const args: IdmlArg[] = [];\n args.push(this.parseArg());\n while (this.peek()?.type === 'COMMA') {\n this.pos++;\n if (this.peek()?.type === 'RPAREN') break;\n args.push(this.parseArg());\n }\n return args;\n }\n\n private parseArg(): IdmlArg {\n const t = this.peek();\n if (!t) throw new Error('[idml] Expected argument');\n if (t.type === 'STRING') { this.pos++; return t.value as string; }\n if (t.type === 'NUMBER') { this.pos++; return t.value as number; }\n // @method — reactive value binding (prop bound to the method's return value).\n if (t.type === 'VALUE_REF') { this.pos++; return `${VALUE_REF_PREFIX}${t.value}`; }\n // ~name — two-way model binding to a form-state cell.\n if (t.type === 'MODEL_REF') { this.pos++; return `${MODEL_REF_PREFIX}${t.value}`; }\n if (t.type === 'IDENT') {\n this.pos++;\n // Literal keywords. `null` is the explicit \"no handler / no value\" placeholder.\n if (t.value === 'null') return null;\n if (t.value === 'true') return true;\n if (t.value === 'false') return false;\n // Any other bare identifier = function reference (e.g. a Button onClick handler).\n return `${FN_REF_PREFIX}${t.value}`;\n }\n // A `{ ... }` argument is a children block — child items placed inside the\n // component (e.g. `Button(\"Save\", { Image(...) })`). Returned tagged so\n // parseItem can lift them into the item's children.\n if (t.type === 'LBRACE') {\n this.pos++; // consume '{'\n const childItems: ParsedItem[] = [];\n while (this.peek()?.type !== 'RBRACE') {\n childItems.push(this.parseItem());\n }\n this.consume('RBRACE');\n return { __idmlChildren: childItems };\n }\n throw new Error(`[idml] Unexpected token type ${t.type} as argument`);\n }\n}\n\n// ==================== CONVERTER ====================\n\nconst LAYOUT_ITEMS = new Set(['Row', 'Col']);\n\nconst ANCHOR_V: Record<string, string> = { top: 'flex-start', center: 'center', bottom: 'flex-end' };\nconst ANCHOR_H: Record<string, string> = { left: 'flex-start', center: 'center', right: 'flex-end' };\n\n/**\n * Map an anchor to absolute-position insets, used to place a child inside an\n * `Overlay` layer. The child keeps its dims (width/height %), so e.g.\n * `[10,10,bottom-right]` is a 10%×10% box pinned to the bottom-right corner with\n * the rest of the screen left empty.\n */\nfunction anchorToAbsoluteInsets(anchor: string): Record<string, string> {\n const parts = anchor.split('-');\n const v = parts.length === 1 ? parts[0] : (parts[0] ?? 'top');\n const h = parts.length === 1 ? parts[0] : (parts[1] ?? 'left');\n const css: Record<string, string> = {};\n if (v === 'bottom') css.bottom = '0';\n else if (v === 'center') css.top = '50%';\n else css.top = '0';\n if (h === 'right') css.right = '0';\n else if (h === 'center') css.left = '50%';\n else css.left = '0';\n if (v === 'center' || h === 'center') {\n css.transform = `translate(${h === 'center' ? '-50%' : '0'}, ${v === 'center' ? '-50%' : '0'})`;\n }\n return css;\n}\n\nfunction anchorToFlexProps(anchor: string, direction: 'row' | 'column') {\n const parts = anchor.split('-');\n if (parts.length === 1) {\n const val = (ANCHOR_V[parts[0]] ?? ANCHOR_H[parts[0]] ?? 'flex-start') as FlexDef['justifyContent'];\n return { justifyContent: val, alignItems: val as FlexDef['alignItems'] };\n }\n const [v = 'top', h = 'left'] = parts;\n const vVal = ANCHOR_V[v] ?? 'flex-start';\n const hVal = ANCHOR_H[h] ?? 'flex-start';\n if (direction === 'row') {\n return { justifyContent: hVal as FlexDef['justifyContent'], alignItems: vVal as FlexDef['alignItems'] };\n }\n return { justifyContent: vVal as FlexDef['justifyContent'], alignItems: hVal as FlexDef['alignItems'] };\n}\n\nfunction pct(n: number): PercentageString { return `${n}%` as PercentageString; }\n\nlet _idCounter = 0;\nfunction genId(prefix: string): string { return `${prefix}-${++_idCounter}`; }\n\ninterface ConvertCtx {\n components: ComponentDef[];\n defs: Map<string, ParsedItem[]>;\n /** Parameter names per definition (bound positionally to call args at expansion). */\n defParams: Map<string, string[]>;\n /** Call-site children to inject at a `Children` marker (set while expanding a definition). */\n slotChildren?: ParsedItem[];\n /** Definition names currently being expanded — guards against infinite recursion. */\n expanding: Set<string>;\n /** True for out-of-flow node types (Overlay/Modal/out-of-flow defs) — their\n * cells render with `display:contents` so they occupy no flow space. */\n isOutOfFlow: (name: string) => boolean;\n}\n\n/**\n * Deep-copy a definition body item, replacing any arg that references a bound\n * parameter with that parameter's value. Parameters appear in the body as bare\n * identifiers (handler refs) or `@`/`~` refs whose name matches a param; the\n * bound value is whatever the caller passed in that position (a literal, another\n * ref, etc.), so values also thread through nested definition calls.\n */\nfunction substituteParams(item: ParsedItem, bindings: Map<string, IdmlArg>): ParsedItem {\n if (bindings.size === 0) return item;\n const subArg = (a: IdmlArg): IdmlArg => {\n if (typeof a === 'string') {\n for (const prefix of [FN_REF_PREFIX, VALUE_REF_PREFIX, MODEL_REF_PREFIX]) {\n if (a.startsWith(prefix)) {\n const name = a.slice(prefix.length);\n return bindings.has(name) ? (bindings.get(name) as IdmlArg) : a;\n }\n }\n return a;\n }\n if (a && typeof a === 'object' && Array.isArray((a as { __idmlChildren?: ParsedItem[] }).__idmlChildren)) {\n return {\n __idmlChildren: (a as { __idmlChildren: ParsedItem[] }).__idmlChildren.map(c => substituteParams(c, bindings)),\n } as IdmlArg;\n }\n return a;\n };\n return {\n ...item,\n args: item.args.map(subArg),\n children: item.children.map(c => substituteParams(c, bindings)),\n };\n}\n\n// ==================== LAYOUT (TILING) VALIDATION ====================\n\n/**\n * Direction in which a node lays its children out, or `null` if the node is NOT\n * a space-tiling container. Only `Row`, `Col`, `Form` and definition calls tile\n * their children; everything else (`Overlay`, `Modal`, `Repeat`, `Table`, and\n * leaf components whose children are a slot) is exempt from the sum-to-100 rule.\n */\nfunction containerDirection(\n name: string,\n defs: Map<string, ParsedItem[]>\n): 'row' | 'column' | null {\n if (name === 'Row') return 'row';\n if (name === 'Col' || name === 'Form') return 'column';\n if (defs.has(name)) return 'column'; // a def call's slot children flow in a column\n return null;\n}\n\n/**\n * Enforce total tiling: a container's children must account for ALL of its space\n * with no implicit gaps. Along the main axis (height for a column, width for a\n * row) the children's percentages must sum to exactly 100; along the cross axis\n * each child must be exactly 100. Any intentional empty space must be an explicit\n * element (e.g. a Spacer) with a declared percentage.\n */\n/** Out-of-flow node types: portals / fixed layers. They don't occupy flow space,\n * so they neither count toward a parent's tiling sum nor must fill the cross axis. */\nconst OUT_OF_FLOW = new Set(['Overlay', 'Modal']);\n\n/**\n * A definition is itself out-of-flow when its body renders only out-of-flow\n * content (Overlay/Modal, or other out-of-flow definitions). This lets a shared\n * \"chrome\" widget — e.g. a feedback launcher that is just an Overlay + a Modal —\n * be called as a sibling without consuming any tiling space.\n */\nfunction defIsOutOfFlow(\n name: string,\n defs: Map<string, ParsedItem[]>,\n seen: Set<string> = new Set()\n): boolean {\n const body = defs.get(name);\n if (!body || seen.has(name)) return false;\n seen.add(name);\n return body.every(\n (c) => OUT_OF_FLOW.has(c.name) || (defs.has(c.name) && defIsOutOfFlow(c.name, defs, seen))\n );\n}\n\n/** Build the predicate that decides whether a node takes part in flow tiling. */\nfunction makeOutOfFlowPredicate(defs: Map<string, ParsedItem[]>): (name: string) => boolean {\n return (name: string) => OUT_OF_FLOW.has(name) || (defs.has(name) && defIsOutOfFlow(name, defs));\n}\n\nfunction validateTiling(\n children: ParsedItem[],\n direction: 'row' | 'column',\n where: string,\n isOutOfFlow: (name: string) => boolean,\n containerHug?: HugSpec\n): void {\n // Out-of-flow children (Overlay/Modal/out-of-flow defs) are positioned, not tiled.\n children = children.filter((c) => !isOutOfFlow(c.name));\n if (children.length === 0) return;\n const main = direction === 'row' ? 'width' : 'height';\n const cross = direction === 'row' ? 'height' : 'width';\n const mainKey = direction === 'row' ? 'w' : 'h';\n const crossKey = direction === 'row' ? 'h' : 'w';\n // Content-flow: when the container hugs the main axis, OR any child hugs the\n // main axis (is content-sized), the children PACK instead of tiling — so the\n // sum-to-100 rule is lifted (the leftover is explicit empty padding, exactly\n // as a hug element's unused tile space is). Strict tiling still applies to\n // every ordinary container.\n // A `@ref` (reactive) dim is resolved at render time, so its value can't be\n // summed statically — its presence on the main axis lifts the sum-to-100 rule\n // (just like hug), and on the cross axis it's exempt from the fill check. The\n // author guarantees the runtime values tile (e.g. sidebar + content widths).\n const packsMain =\n !!containerHug?.[mainKey] ||\n children.some((c) => c.hug?.[mainKey] || isDimRef(c[main]));\n let sum = 0;\n for (const c of children) {\n if (typeof c[main] === 'number') sum += c[main] as number;\n // A child that hugs the CROSS axis is content-sized there (≤100), and a\n // `@ref` cross dim is dynamic — both opt out of the fill-the-cross-axis rule.\n if (!c.hug?.[crossKey] && !isDimRef(c[cross]) && (c[cross] as number) !== 100) {\n throw new Error(\n `[idml] ${c.name} in ${where}: cross-axis ${cross} must be 100 ` +\n `(got ${c[cross]}); no vacant space is allowed`\n );\n }\n }\n if (!packsMain && sum !== 100) {\n throw new Error(\n `[idml] children of ${where} must tile to 100% along ${main}; got ${sum}. ` +\n `Add an explicit Spacer for any gap.`\n );\n }\n}\n\n/** Recursively validate tiling for a node's children, descending into all nodes. */\nfunction walkTiling(\n item: ParsedItem,\n defs: Map<string, ParsedItem[]>,\n isOutOfFlow: (name: string) => boolean\n): void {\n const dir = containerDirection(item.name, defs);\n if (dir) validateTiling(item.children, dir, `<${item.name}>`, isOutOfFlow, item.hug);\n for (const child of item.children) walkTiling(child, defs, isOutOfFlow);\n}\n\nfunction sizeOf(item: ParsedItem): SizeDef {\n const size: SizeDef = {};\n // Only static numeric dims become a fixed `%`; `@ref` dims are resolved at\n // render time (see dynSizeOf / LayoutRenderer).\n if (typeof item.height === 'number') size.height = pct(item.height);\n if (typeof item.width === 'number') size.width = pct(item.width);\n return size;\n}\n\n/** Collect the `@ref` (reactive) dimensions — resolved per render, not baked.\n * A conditional dim carries its two inline sizes (`whenTrue`/`whenFalse`). */\nfunction dynSizeOf(item: ParsedItem): DynamicSize | undefined {\n const dyn: DynamicSize = {};\n if (isDimRef(item.height)) dyn.height = dimRefToDynamic(item.height);\n if (isDimRef(item.width)) dyn.width = dimRefToDynamic(item.width);\n return dyn.width || dyn.height ? dyn : undefined;\n}\n\nfunction dimRefToDynamic(d: DimRef): DynamicDim {\n return d.whenTrue !== undefined\n ? { ref: d.ref, whenTrue: d.whenTrue, whenFalse: d.whenFalse }\n : { ref: d.ref };\n}\n\n/**\n * Inline styles that make a bound component hug its content on the requested\n * axes. `fit-content` shrinks the box to its content but never past the tile\n * (the tile is the available width/height); `nowrap` + `overflow:hidden` +\n * `text-overflow:ellipsis` truncate a too-long label with `…` instead of letting\n * it spill out of the tile. These are spread LAST into the component's style, so\n * they override the renderer's default `width/height:100%` fill.\n */\nfunction hugStyles(hug: HugSpec): Record<string, string> {\n const s: Record<string, string> = {};\n if (hug.w) {\n s.width = 'fit-content';\n s.maxWidth = '100%';\n s.minWidth = '0';\n s.overflow = 'hidden';\n s.textOverflow = 'ellipsis';\n s.whiteSpace = 'nowrap';\n }\n if (hug.h) {\n s.height = 'fit-content';\n s.maxHeight = '100%';\n }\n return s;\n}\n\n/**\n * Cell-level hug styles for a CONTAINER (Row/Col/Form): the cell shrinks to its\n * packed children on the hugged axis, capped at its tile. No overflow/ellipsis\n * (that would clip the children) — truncation is a leaf-text concern only.\n */\nfunction hugContainerStyles(hug: HugSpec): Record<string, string> {\n const s: Record<string, string> = {};\n // NB: no inline max-width/height cap. The cell shrinks to its content\n // (fit-content); a hard tile cap would override author `max-w-*` classes\n // (which the feedback launcher's hover text-reveal relies on), and the\n // surrounding flex layout already constrains the cell in practice.\n if (hug.w) s.width = 'fit-content';\n if (hug.h) s.height = 'fit-content';\n return s;\n}\n\n/** Node names that can't be hugged: they bind no component AND don't lay out\n * flow children whose packing `hug` could control. (`Table` IS huggable — it\n * expands to a Col of content-height rows, so `hug-h` gives a content-height\n * card with no dead space below the last row; handled in `expandTable`.) */\nconst HUG_INVALID_ON = new Set(['Overlay', 'Modal', 'Children']);\n\n/** Throw if `hug` is used where it has nothing to size (a portal/slot/table or\n * a definition call). Containers (Row/Col/Form) and components are fine. */\nfunction assertHuggable(item: ParsedItem, isDef: boolean): void {\n if (!item.hug) return;\n if (HUG_INVALID_ON.has(item.name) || isDef) {\n throw new Error(\n `[idml] \"${item.name}\" cannot use hug — nothing to content-size here. ` +\n `hug applies to components (e.g. Button/Text) and layout containers ` +\n `(Row/Col/Form), not definitions, slots, tables, or out-of-flow layers.`\n );\n }\n}\n\nfunction mkItem(\n name: string,\n args: IdmlArg[],\n height: DimValue,\n width: DimValue,\n anchor: string,\n children: ParsedItem[],\n style: Record<string, string> = {}\n): ParsedItem {\n return { name, args, height, width, anchor, children, style };\n}\n\n/**\n * Expand `Table(@data){ Column(\"H\"){ cell } ... }` into existing primitives: a\n * header Row of column labels, then a Repeat over `@data` whose template is a Row\n * of one cell per column. Cell templates use `@item.field` and resolve per row via\n * the Repeat's item scope. Each Column's `[h,w,anchor]` provides the column width\n * and cell alignment (height is auto so rows size to content).\n */\nfunction expandTable(item: ParsedItem, ctx: ConvertCtx): LayoutDef {\n const dataArg = item.args.find(\n (a): a is string => typeof a === 'string' && a.startsWith(VALUE_REF_PREFIX)\n );\n const columns = item.children.filter(c => c.name === 'Column');\n\n // Header: a tinted row of small, uppercase, muted column labels with generous\n // cell padding — the conventional data-table header look.\n const headerCells = columns.map(col => {\n // Font size is set in vw (not a px/rem `text-xs` class) so table headers\n // scale with the viewport like the rest of the text.\n const label = mkItem(\n 'Text', [String(col.args[0] ?? '')], 'auto', 100, col.anchor, [], { fontSize: '0.63vw' }\n );\n label.className = 'font-medium text-gray-500 uppercase tracking-wider';\n // Cell padding is vw (not px-6/py-3) so the table is zoom-invariant.\n const cell = mkItem('Col', [], 'auto', col.width, col.anchor, [label], {\n paddingLeft: '1.6vw', paddingRight: '1.6vw', paddingTop: '0.8vw', paddingBottom: '0.8vw',\n });\n return cell;\n });\n const headerRow = mkItem('Row', [], 'auto', 100, 'top-left', headerCells, {\n borderBottom: '0.07vw solid #e5e7eb',\n });\n headerRow.className = 'bg-gray-50';\n\n // Body cells carry the same horizontal padding and a comfortable vertical\n // rhythm; rows are separated by a light divider.\n const bodyCells = columns.map(col => {\n const cell = mkItem('Col', [], 'auto', col.width, col.anchor, col.children, {\n paddingLeft: '1.6vw', paddingRight: '1.6vw', paddingTop: '1vw', paddingBottom: '1vw',\n });\n cell.className = 'whitespace-nowrap';\n return cell;\n });\n const bodyRowTemplate = mkItem('Row', [], 'auto', 100, 'top-left', bodyCells, {\n borderBottom: '0.07vw solid #e5e7eb',\n });\n\n const repeat = mkItem('Repeat', dataArg ? [dataArg] : [], 'auto', 100, 'top-left', [bodyRowTemplate]);\n\n // `hug` content-sizes the card on the requested axis: an `auto` dim emits no\n // fixed size, so the Col shrinks to its rows (no dead white space below the\n // last row) instead of stretching to the declared tile height.\n const tableStyle = { ...item.style };\n if (item.hug?.w) tableStyle.width = 'fit-content';\n const tableCol = mkItem(\n 'Col', [],\n item.hug?.h ? 'auto' : item.height,\n item.hug?.w ? 'auto' : item.width,\n item.anchor, [headerRow, repeat], tableStyle\n );\n tableCol.className = item.className;\n return convertItem(tableCol, ctx);\n}\n\n/** Convert a parsed item, attaching its `?@ref` visibility condition (if any) to\n * the resulting cell. The heavy lifting is in `convertNode`. */\nfunction convertItem(item: ParsedItem, ctx: ConvertCtx): LayoutDef {\n const def = convertNode(item, ctx);\n if (item.visibility) def.visibility = item.visibility;\n const dyn = dynSizeOf(item);\n if (dyn) def.dynamicSize = dyn;\n // Dynamic `@class` refs / conditional class blocks on a CONTAINER (no bound\n // component) are resolved by the LayoutRenderer; a component's `@class` refs\n // are already wired as className value-bindings.\n if (item.classRefs?.length && !def.componentId) def.classRefs = item.classRefs;\n if (item.condClasses?.length) def.condClasses = item.condClasses;\n return def;\n}\n\nfunction convertNode(item: ParsedItem, ctx: ConvertCtx): LayoutDef {\n assertHuggable(item, ctx.defs.has(item.name));\n const size = sizeOf(item);\n const idmlStyle = Object.keys(item.style).length ? item.style : undefined;\n const colAnchor = anchorToFlexProps(item.anchor, 'column');\n // Out-of-flow nodes (Modal / out-of-flow defs) render with `display:contents`\n // so their wrapper cell occupies NO flow space (their real content is a portal\n // or fixed layer). This means authors don't have to fake a 0 height for them.\n // (Overlay has its own branch below; its layer is already position:fixed.)\n const outOfFlow = ctx.isOutOfFlow(item.name);\n const cellStyle = outOfFlow ? { ...(idmlStyle ?? {}), display: 'contents' } : idmlStyle;\n\n // `Children` slot marker — replaced by the enclosing definition's call children.\n if (item.name === 'Children') {\n const slot = ctx.slotChildren ?? [];\n // Slot content is real page content: convert it without an active slot context.\n const childCtx: ConvertCtx = { ...ctx, slotChildren: undefined };\n return {\n type: 'flex',\n direction: 'column',\n ...colAnchor,\n size,\n children: slot.map(child => convertItem(child, childCtx)),\n idmlStyle,\n };\n }\n\n // Reusable component definition — expand its body, injecting this call's\n // children at any `Children` marker inside it.\n const defBody = ctx.defs.get(item.name);\n if (defBody && !ctx.expanding.has(item.name)) {\n // Bind the definition's parameters to this call's positional args, then\n // substitute references in the body (missing args bind to '' so they render\n // empty rather than leaking the param name).\n const params = ctx.defParams.get(item.name) ?? [];\n const bindings = new Map<string, IdmlArg>();\n params.forEach((p, i) => bindings.set(p, item.args[i] ?? ''));\n const body = bindings.size ? defBody.map(t => substituteParams(t, bindings)) : defBody;\n\n const innerCtx: ConvertCtx = {\n ...ctx,\n slotChildren: item.children,\n expanding: new Set(ctx.expanding).add(item.name),\n };\n return {\n type: 'flex',\n direction: 'column',\n ...colAnchor,\n size,\n children: body.map(t => convertItem(t, innerCtx)),\n idmlStyle: cellStyle,\n };\n }\n\n // Overlay — a full-viewport, click-through layer. Each child is absolutely\n // positioned by its own anchor + dims, so it occupies exactly that box at that\n // corner and the rest of the screen stays empty and interactive (the layer\n // itself is pointer-events:none; children opt back in). No fixed/pixel classes\n // needed — placement comes entirely from dims + anchor.\n if (item.name === 'Overlay') {\n const children = item.children.map(child => {\n const layout = convertItem(child, ctx);\n // An Overlay child is positioned (not tiled), so `hug` may shrink it to\n // content on the hugged axis — its declared dim becomes the MAX bound\n // (so a docked panel grows from its corner to fit content, no dead space).\n const hugStyle: Record<string, string> = {};\n if (child.hug?.w) {\n hugStyle.width = 'fit-content';\n if (layout.size?.width) hugStyle.maxWidth = layout.size.width;\n }\n if (child.hug?.h) {\n hugStyle.height = 'fit-content';\n if (layout.size?.height) hugStyle.maxHeight = layout.size.height;\n }\n return {\n ...layout,\n idmlStyle: {\n ...(layout.idmlStyle ?? {}),\n position: 'absolute',\n pointerEvents: 'auto',\n ...anchorToAbsoluteInsets(child.anchor),\n ...hugStyle,\n },\n } as LayoutDef;\n });\n return {\n type: 'flex',\n direction: 'column',\n size: { width: '100%', height: '100%' },\n children,\n idmlStyle: {\n position: 'fixed',\n top: '0',\n left: '0',\n right: '0',\n bottom: '0',\n pointerEvents: 'none',\n outline: 'none',\n zIndex: '50',\n ...(idmlStyle ?? {}),\n },\n ...(item.className ? { className: item.className } : {}),\n };\n }\n\n // Table sugar — expands to a header row + a Repeat of row templates.\n if (item.name === 'Table') {\n return expandTable(item, ctx);\n }\n\n // Layout primitives (Row/Col).\n if (LAYOUT_ITEMS.has(item.name)) {\n const direction = item.name === 'Row' ? 'row' : 'column';\n const { justifyContent, alignItems } = anchorToFlexProps(item.anchor, direction);\n const children = item.children.map(child => convertItem(child, ctx));\n // Content-flow: a container hugged on its MAIN axis lays its children out by\n // content (they pack) instead of tiling. The container keeps its own size;\n // each child's main-axis size is dropped so it shrinks to content, and the\n // anchor's justify-content packs them, leaving the rest as explicit empty\n // space. (Cross-axis hug, if any, just content-sizes the cell itself.)\n const mainHug = direction === 'column' ? item.hug?.h : item.hug?.w;\n if (mainHug) {\n for (const ch of children) {\n if (!ch.size) continue;\n if (direction === 'column') delete ch.size.height;\n else delete ch.size.width;\n }\n }\n const crossHug = direction === 'column' ? item.hug?.w : item.hug?.h;\n const containerStyle = crossHug\n ? { ...(idmlStyle ?? {}), ...hugContainerStyles({ w: direction === 'column', h: direction === 'row' }) }\n : idmlStyle;\n return {\n type: 'flex',\n direction,\n justifyContent,\n alignItems,\n size,\n children,\n idmlStyle: containerStyle,\n ...(item.className ? { className: item.className } : {}),\n };\n }\n\n // Select sugar — `Select(~role){ Option(\"Admin\") … }`. The <option> elements\n // must be direct DOM children of <select>, but every layout child is wrapped in\n // a layout <div>, which is invalid inside a <select>. So lift Option children\n // into an `options: [{value,label}]` prop (the Select builtin renders that) and\n // emit no layout children.\n if (item.name === 'Select' && item.children.some(c => c.name === 'Option')) {\n const id = genId('select');\n const options = item.children\n .filter(c => c.name === 'Option')\n .map(c => ({ value: c.args[0] ?? '', label: c.args[1] ?? c.args[0] ?? '' }));\n const def = buildComponentDef(item, id);\n def.props = { ...def.props, options };\n ctx.components.push(def);\n return { type: 'flex', direction: 'column', ...colAnchor, size, children: [], componentId: id };\n }\n\n // Component (builtin / registered / custom). Children stay as layout nodes on\n // the bound cell; the LayoutRenderer threads them into the component as its\n // slot so containers (Card, Table, imported components) render their content.\n // slotChildren is passed through so a `Children` marker nested inside a\n // definition's component still resolves.\n const id = genId(item.name.toLowerCase());\n ctx.components.push(buildComponentDef(item, id));\n const children = item.children.map(child => convertItem(child, ctx));\n // A hugged component shrinks to its content; make its CELL content-width/height\n // too. Otherwise the cell keeps the dim's `width:100%`, which collapses to 0\n // inside a fit-content parent (e.g. the feedback launcher's hover label) and\n // is what makes a hug pill content-sized within a definite-width column.\n const hugCell: Record<string, string> = {};\n if (item.hug?.w) {\n hugCell.width = 'fit-content';\n if (typeof item.width === 'number') hugCell.maxWidth = `${item.width}%`;\n }\n if (item.hug?.h) {\n hugCell.height = 'fit-content';\n if (typeof item.height === 'number') hugCell.maxHeight = `${item.height}%`;\n }\n const cellIdml = outOfFlow\n ? { ...(cellStyle ?? {}), ...hugCell }\n : Object.keys(hugCell).length\n ? hugCell\n : undefined;\n return {\n type: 'flex', direction: 'column', ...colAnchor, size, children, componentId: id,\n ...(cellIdml ? { idmlStyle: cellIdml } : {}),\n };\n}\n\n/**\n * Derive CSS alignment properties from the item's anchor so that content\n * centres (or aligns) correctly within the component element itself.\n * Text components use textAlign; Button uses flex centering.\n */\nfunction anchorToComponentStyle(anchor: string, componentType: string): Record<string, string> {\n const parts = anchor.split('-');\n const h = parts.length === 1 ? parts[0] : parts[1] ?? parts[0];\n const v = parts.length === 1 ? parts[0] : parts[0];\n\n const css: Record<string, string> = {};\n\n if (componentType === 'Text' || componentType === 'Heading') {\n if (h === 'center') css.textAlign = 'center';\n else if (h === 'right') css.textAlign = 'right';\n }\n\n if (componentType === 'Button') {\n css.display = 'flex';\n css.justifyContent = h === 'center' ? 'center' : h === 'right' ? 'flex-end' : 'flex-start';\n css.alignItems = v === 'center' ? 'center' : v === 'bottom' ? 'flex-end' : 'flex-start';\n }\n\n return css;\n}\n\nfunction buildComponentDef(item: ParsedItem, id: string): ComponentDef {\n const anchorStyle = anchorToComponentStyle(item.anchor, item.name);\n // hug styles win over anchor defaults and variant styles so the component\n // actually shrinks to content (overriding the renderer's default fill).\n const hug = item.hug ? hugStyles(item.hug) : {};\n const merged = { ...anchorStyle, ...item.style, ...hug };\n const idmlStyle = Object.keys(merged).length ? merged : undefined;\n\n // Classify call args. `@x` -> reactive value binding; a bare identifier -> a\n // handler (onClick); a \"/...\" string -> a route href; everything else (strings,\n // numbers, booleans, null) is a positional literal.\n const valueRefs: string[] = [];\n const modelRefs: string[] = [];\n const handlerRefs: string[] = [];\n const literals: IdmlArg[] = [];\n for (const a of item.args) {\n if (typeof a === 'string' && a.startsWith(VALUE_REF_PREFIX)) valueRefs.push(a.slice(VALUE_REF_PREFIX.length));\n else if (typeof a === 'string' && a.startsWith(MODEL_REF_PREFIX)) modelRefs.push(a.slice(MODEL_REF_PREFIX.length));\n else if (typeof a === 'string' && a.startsWith(FN_REF_PREFIX)) handlerRefs.push(a.slice(FN_REF_PREFIX.length));\n else literals.push(a);\n }\n\n // The prop a leading `@value` / `~model` binds to, per component. Bound props are\n // applied after literal props in the renderer, so they win when both are present.\n const primaryProp = PRIMARY_PROP[item.name] ?? 'value';\n const bindings: DataBindingDef[] = [\n ...valueRefs.map(methodId => ({ prop: primaryProp, methodId, kind: 'value' as const })),\n ...modelRefs.map(methodId => ({ prop: primaryProp, methodId, kind: 'model' as const })),\n ...handlerRefs.map(methodId => ({ prop: 'onClick', methodId })),\n // Dynamic classes (`@method` tokens in a class block) resolve to strings that\n // are appended to className per render.\n ...(item.classRefs ?? []).map(methodId => ({ prop: 'className', methodId, kind: 'value' as const })),\n ];\n const withBindings = (def: ComponentDef): ComponentDef => {\n const withB = bindings.length ? { ...def, bindings } : def;\n return item.className ? { ...withB, className: item.className } : withB;\n };\n\n const [first, second] = literals;\n\n switch (item.name) {\n case 'Text':\n return withBindings({ id, type: 'Text', props: { text: String(first ?? '') }, idmlStyle });\n\n case 'Heading':\n return withBindings({\n id,\n type: 'Heading',\n props: { text: String(first ?? ''), level: typeof second === 'number' ? second : 1 },\n idmlStyle,\n });\n\n case 'Button': {\n // For a Button, a \"/...\" literal is a route href; the first non-route\n // literal is the label.\n const route = literals.find(a => typeof a === 'string' && a.startsWith('/')) as string | undefined;\n const label = literals.find(a => typeof a === 'string' && !a.startsWith('/'));\n const props: Record<string, unknown> = { text: String(label ?? '') };\n if (route) props.href = route;\n return withBindings({ id, type: 'Button', props, idmlStyle });\n }\n\n case 'Image':\n return withBindings({ id, type: 'Image', props: { src: String(first ?? ''), alt: String(second ?? '') }, idmlStyle });\n\n case 'Label':\n return withBindings({ id, type: 'Label', props: { text: String(first ?? '') }, idmlStyle });\n\n case 'Icon': {\n // `Icon(\"House\")` → name only; `Icon(\"House\", 24)` → name + size;\n // `Icon(\"ChatCenteredDots\", 24, \"white\")` → + colour (a numeric arg is the\n // size, a string arg the colour). Name may also be bound dynamically via\n // `@method` (PRIMARY_PROP.Icon = 'name'), e.g. a dark-mode toggle swapping\n // MoonStars/SunDim.\n const props: Record<string, unknown> = { name: String(first ?? '') };\n for (const rest of literals.slice(1)) {\n if (typeof rest === 'number') props.size = rest;\n else if (typeof rest === 'string') props.color = rest;\n }\n return withBindings({ id, type: 'Icon', props, idmlStyle });\n }\n\n case 'Option': {\n // `Option(\"Admin\")` → value & label both \"Admin\"; `Option(\"admin\", \"Administrator\")`\n // → value \"admin\", label \"Administrator\".\n const value = first ?? '';\n const label = second ?? first ?? '';\n return withBindings({ id, type: 'Option', props: { value, label }, idmlStyle });\n }\n\n case 'Input':\n case 'Textarea':\n // `Input(~model, \"Placeholder text\")` — the `~model` binds the value; the\n // first string literal is the placeholder (its text is content → .idml).\n return withBindings({\n id,\n type: item.name,\n props: first != null ? { placeholder: String(first) } : {},\n idmlStyle,\n });\n\n default:\n return withBindings({\n id,\n type: item.name,\n props: Object.fromEntries(literals.map((v, i) => [`arg${i}`, v])),\n idmlStyle,\n });\n }\n}\n\n// The prop that a leading `@value` reference binds to, per component type.\nconst PRIMARY_PROP: Record<string, string> = {\n Text: 'text',\n Heading: 'text',\n Button: 'text',\n Image: 'src',\n Input: 'value',\n Textarea: 'value',\n Select: 'value',\n Checkbox: 'checked',\n Table: 'data',\n Repeat: 'data',\n Modal: 'open',\n Icon: 'name',\n};\n\nconst DEFAULT_TOKENS: UIConfig['tokens'] = {\n colors: [\n { name: 'primary', value: '#1a56db', darkValue: '#60a5fa' },\n { name: 'surface', value: '#ffffff', darkValue: '#1e1e2e' },\n { name: 'on-surface', value: '#111827', darkValue: '#f9fafb' },\n { name: 'danger', value: '#dc2626', darkValue: '#f87171' },\n ],\n typography: [\n { name: 'heading-xl', fontSize: '2.25rem', fontWeight: 700, lineHeight: '1.25' },\n { name: 'body-md', fontSize: '1rem', fontWeight: 400, lineHeight: '1.6' },\n { name: 'label-sm', fontSize: '0.75rem', fontWeight: 500, lineHeight: '1.4' },\n ],\n spacing: [\n { name: 'gap-sm', value: '0.5rem' },\n { name: 'gap-md', value: '1rem' },\n { name: 'gap-lg', value: '2rem' },\n ],\n};\n\nexport interface ParseOptions {\n /**\n * Called when an `import \"./file.idml\"` line is encountered.\n * Should return the raw source of the imported file.\n */\n resolve?: (path: string) => string;\n}\n\nexport function parseIdml(source: string, options?: ParseOptions): UIConfig {\n _idCounter = 0;\n const parser = new IdmlParser(tokenize(source));\n const parsedPages = parser.parseFile(options?.resolve);\n\n // Total-tiling validation: every page (a column root) and every definition\n // body (also a column) must tile to 100%, as must every nested Row/Col/Form.\n const isOutOfFlow = makeOutOfFlowPredicate(parser.defRegistry);\n for (const { route, items } of parsedPages) {\n validateTiling(items, 'column', `page ${route}`, isOutOfFlow);\n items.forEach((it) => walkTiling(it, parser.defRegistry, isOutOfFlow));\n }\n for (const [name, body] of parser.defRegistry) {\n validateTiling(body, 'column', `define ${name}`, isOutOfFlow);\n body.forEach((it) => walkTiling(it, parser.defRegistry, isOutOfFlow));\n }\n\n const pages = parsedPages.map(({ route, scroll, items }) => {\n const components: ComponentDef[] = [];\n const ctx: ConvertCtx = {\n components,\n defs: parser.defRegistry,\n defParams: parser.defParamRegistry,\n expanding: new Set(),\n isOutOfFlow,\n };\n const layoutChildren = items.map(item => convertItem(item, ctx));\n const rootLayout: FlexDef = {\n type: 'flex',\n direction: 'column',\n size: { width: '100%', height: '100%' },\n children: layoutChildren,\n ...(scroll ? { idmlStyle: { overflowY: 'auto' } } : {}),\n };\n return { route, layout: rootLayout, components };\n });\n\n return { version: '1', tokens: DEFAULT_TOKENS, pages };\n}\n"],"mappings":"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","names":["path","chokidar","children","id"]}
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
import { NextConfig } from 'next';
|
|
2
|
+
|
|
3
|
+
interface UIConfigOptions {
|
|
4
|
+
configPath?: string;
|
|
5
|
+
editorEnabled?: boolean;
|
|
6
|
+
}
|
|
7
|
+
declare function withUIConfig(options?: UIConfigOptions): (nextConfig: NextConfig) => NextConfig;
|
|
8
|
+
|
|
9
|
+
type SSEWriter = WritableStreamDefaultWriter<Uint8Array>;
|
|
10
|
+
declare function startWatcher(configPath: string): void;
|
|
11
|
+
declare function stopWatcher(): Promise<void>;
|
|
12
|
+
declare function addSSEWriter(writer: SSEWriter): () => void;
|
|
13
|
+
|
|
14
|
+
interface ColorToken {
|
|
15
|
+
name: string;
|
|
16
|
+
value: string;
|
|
17
|
+
darkValue?: string;
|
|
18
|
+
}
|
|
19
|
+
interface TypographyToken {
|
|
20
|
+
name: string;
|
|
21
|
+
fontFamily?: string;
|
|
22
|
+
fontSize: string;
|
|
23
|
+
fontWeight?: number | string;
|
|
24
|
+
lineHeight?: string;
|
|
25
|
+
letterSpacing?: string;
|
|
26
|
+
}
|
|
27
|
+
interface SpacingToken {
|
|
28
|
+
name: string;
|
|
29
|
+
value: string;
|
|
30
|
+
}
|
|
31
|
+
interface TokensDef {
|
|
32
|
+
colors: ColorToken[];
|
|
33
|
+
typography: TypographyToken[];
|
|
34
|
+
spacing: SpacingToken[];
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
type PercentageString = `${number}%`;
|
|
38
|
+
interface SizeDef {
|
|
39
|
+
width?: PercentageString;
|
|
40
|
+
height?: PercentageString;
|
|
41
|
+
minWidth?: PercentageString;
|
|
42
|
+
minHeight?: PercentageString;
|
|
43
|
+
maxWidth?: PercentageString;
|
|
44
|
+
maxHeight?: PercentageString;
|
|
45
|
+
}
|
|
46
|
+
type FlexDirection = 'row' | 'column' | 'row-reverse' | 'column-reverse';
|
|
47
|
+
type FlexWrap = 'nowrap' | 'wrap' | 'wrap-reverse';
|
|
48
|
+
type JustifyContent = 'flex-start' | 'flex-end' | 'center' | 'space-between' | 'space-around' | 'space-evenly';
|
|
49
|
+
type AlignItems = 'flex-start' | 'flex-end' | 'center' | 'stretch' | 'baseline';
|
|
50
|
+
interface FlexDef {
|
|
51
|
+
type: 'flex';
|
|
52
|
+
direction: FlexDirection;
|
|
53
|
+
wrap?: FlexWrap;
|
|
54
|
+
justifyContent?: JustifyContent;
|
|
55
|
+
alignItems?: AlignItems;
|
|
56
|
+
gap?: string;
|
|
57
|
+
size?: SizeDef;
|
|
58
|
+
children: LayoutDef[];
|
|
59
|
+
componentId?: string;
|
|
60
|
+
idmlStyle?: Record<string, string>;
|
|
61
|
+
className?: string;
|
|
62
|
+
/** Dynamic `@method` class refs (resolved per render, like a component's, so a
|
|
63
|
+
* container can carry a state-driven class — e.g. a per-row colour). */
|
|
64
|
+
classRefs?: string[];
|
|
65
|
+
/** Conditional class blocks (`` `classes`?@ref ``) applied per render. */
|
|
66
|
+
condClasses?: ConditionalClass[];
|
|
67
|
+
visibility?: LayoutVisibility;
|
|
68
|
+
dynamicSize?: DynamicSize;
|
|
69
|
+
}
|
|
70
|
+
/** Reactive show/hide for a layout cell: render only when `ref` resolves truthy
|
|
71
|
+
* (a value path like `state.open`); `negate` flips the test. */
|
|
72
|
+
interface LayoutVisibility {
|
|
73
|
+
ref: string;
|
|
74
|
+
negate?: boolean;
|
|
75
|
+
}
|
|
76
|
+
/** A class block that applies only when `ref` is truthy (`negate` flips it) —
|
|
77
|
+
* i.e. `` `scale-100 opacity-100`?@state.open ``. Lets state-driven visuals (a
|
|
78
|
+
* pop-up's scale/opacity) live in the .idml rather than a method. */
|
|
79
|
+
interface ConditionalClass {
|
|
80
|
+
classes: string;
|
|
81
|
+
ref: string;
|
|
82
|
+
negate?: boolean;
|
|
83
|
+
}
|
|
84
|
+
/** Reactive width/height resolved per render (applied AFTER static `size`, so it
|
|
85
|
+
* wins — letting a cell resize on state, e.g. a collapsing sidebar). The change
|
|
86
|
+
* is animated by the renderer (Web Animations API). */
|
|
87
|
+
interface DynamicSize {
|
|
88
|
+
width?: DynamicDim;
|
|
89
|
+
height?: DynamicDim;
|
|
90
|
+
}
|
|
91
|
+
/** One reactive dimension. `ref` is a value path (`state.x` / method). With
|
|
92
|
+
* `whenTrue`/`whenFalse` it's a condition — the dim is `whenTrue` when the ref
|
|
93
|
+
* is truthy, else `whenFalse` (both inline CSS sizes from the .idml). Without
|
|
94
|
+
* them the ref's resolved value is the dim (bare number → `%`). */
|
|
95
|
+
interface DynamicDim {
|
|
96
|
+
ref: string;
|
|
97
|
+
whenTrue?: string;
|
|
98
|
+
whenFalse?: string;
|
|
99
|
+
}
|
|
100
|
+
interface GridDef {
|
|
101
|
+
type: 'grid';
|
|
102
|
+
columns: number;
|
|
103
|
+
rows?: number;
|
|
104
|
+
gap?: string;
|
|
105
|
+
size?: SizeDef;
|
|
106
|
+
children: LayoutDef[];
|
|
107
|
+
componentId?: string;
|
|
108
|
+
idmlStyle?: Record<string, string>;
|
|
109
|
+
className?: string;
|
|
110
|
+
/** Dynamic `@method` class refs (resolved per render, like a component's, so a
|
|
111
|
+
* container can carry a state-driven class — e.g. a per-row colour). */
|
|
112
|
+
classRefs?: string[];
|
|
113
|
+
/** Conditional class blocks (`` `classes`?@ref ``) applied per render. */
|
|
114
|
+
condClasses?: ConditionalClass[];
|
|
115
|
+
visibility?: LayoutVisibility;
|
|
116
|
+
dynamicSize?: DynamicSize;
|
|
117
|
+
}
|
|
118
|
+
type LayoutDef = FlexDef | GridDef;
|
|
119
|
+
|
|
120
|
+
interface DataBindingDef {
|
|
121
|
+
prop: string;
|
|
122
|
+
methodId: string;
|
|
123
|
+
/**
|
|
124
|
+
* How the binding is wired:
|
|
125
|
+
* - 'handler' (default): the method function is passed as the prop (e.g. onClick).
|
|
126
|
+
* - 'value': the method is called during render and its return value becomes the
|
|
127
|
+
* prop. If the method is a hook (e.g. wraps useQuery/useState) the component
|
|
128
|
+
* re-renders reactively when that value changes.
|
|
129
|
+
* - 'model': two-way binding to a form-state cell named by `methodId` — sets the
|
|
130
|
+
* prop to the current value AND an `onChange` that writes it back.
|
|
131
|
+
*/
|
|
132
|
+
kind?: 'handler' | 'value' | 'model';
|
|
133
|
+
}
|
|
134
|
+
interface VisibilityDef {
|
|
135
|
+
methodId: string;
|
|
136
|
+
negate?: boolean;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
type BuiltinComponentType = 'Text' | 'Heading' | 'Button' | 'Image' | 'List' | 'Card' | 'Divider' | 'Spacer' | 'Icon' | 'Table' | 'Input' | 'Textarea' | 'Select' | 'Option' | 'Checkbox' | 'Radio' | 'Label' | 'Children' | 'Repeat' | 'Form' | 'Modal';
|
|
140
|
+
interface ComponentDef {
|
|
141
|
+
id: string;
|
|
142
|
+
type: BuiltinComponentType | string;
|
|
143
|
+
props?: Record<string, unknown>;
|
|
144
|
+
tokenProps?: {
|
|
145
|
+
color?: string;
|
|
146
|
+
background?: string;
|
|
147
|
+
typography?: string;
|
|
148
|
+
padding?: string;
|
|
149
|
+
};
|
|
150
|
+
bindings?: DataBindingDef[];
|
|
151
|
+
visibility?: VisibilityDef;
|
|
152
|
+
children?: ComponentDef[];
|
|
153
|
+
idmlStyle?: Record<string, string>;
|
|
154
|
+
className?: string;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
interface PageDef {
|
|
158
|
+
route: string;
|
|
159
|
+
title?: string;
|
|
160
|
+
layout: LayoutDef;
|
|
161
|
+
components: ComponentDef[];
|
|
162
|
+
meta?: {
|
|
163
|
+
description?: string;
|
|
164
|
+
ogTitle?: string;
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
interface UIConfig {
|
|
169
|
+
version: '1';
|
|
170
|
+
tokens: TokensDef;
|
|
171
|
+
pages: PageDef[];
|
|
172
|
+
userComponents?: string[];
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
interface ParseOptions {
|
|
176
|
+
/**
|
|
177
|
+
* Called when an `import "./file.idml"` line is encountered.
|
|
178
|
+
* Should return the raw source of the imported file.
|
|
179
|
+
*/
|
|
180
|
+
resolve?: (path: string) => string;
|
|
181
|
+
}
|
|
182
|
+
declare function parseIdml(source: string, options?: ParseOptions): UIConfig;
|
|
183
|
+
|
|
184
|
+
export { type UIConfigOptions, addSSEWriter, parseIdml, startWatcher, stopWatcher, withUIConfig };
|
package/dist/server.d.ts
ADDED
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
import { NextConfig } from 'next';
|
|
2
|
+
|
|
3
|
+
interface UIConfigOptions {
|
|
4
|
+
configPath?: string;
|
|
5
|
+
editorEnabled?: boolean;
|
|
6
|
+
}
|
|
7
|
+
declare function withUIConfig(options?: UIConfigOptions): (nextConfig: NextConfig) => NextConfig;
|
|
8
|
+
|
|
9
|
+
type SSEWriter = WritableStreamDefaultWriter<Uint8Array>;
|
|
10
|
+
declare function startWatcher(configPath: string): void;
|
|
11
|
+
declare function stopWatcher(): Promise<void>;
|
|
12
|
+
declare function addSSEWriter(writer: SSEWriter): () => void;
|
|
13
|
+
|
|
14
|
+
interface ColorToken {
|
|
15
|
+
name: string;
|
|
16
|
+
value: string;
|
|
17
|
+
darkValue?: string;
|
|
18
|
+
}
|
|
19
|
+
interface TypographyToken {
|
|
20
|
+
name: string;
|
|
21
|
+
fontFamily?: string;
|
|
22
|
+
fontSize: string;
|
|
23
|
+
fontWeight?: number | string;
|
|
24
|
+
lineHeight?: string;
|
|
25
|
+
letterSpacing?: string;
|
|
26
|
+
}
|
|
27
|
+
interface SpacingToken {
|
|
28
|
+
name: string;
|
|
29
|
+
value: string;
|
|
30
|
+
}
|
|
31
|
+
interface TokensDef {
|
|
32
|
+
colors: ColorToken[];
|
|
33
|
+
typography: TypographyToken[];
|
|
34
|
+
spacing: SpacingToken[];
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
type PercentageString = `${number}%`;
|
|
38
|
+
interface SizeDef {
|
|
39
|
+
width?: PercentageString;
|
|
40
|
+
height?: PercentageString;
|
|
41
|
+
minWidth?: PercentageString;
|
|
42
|
+
minHeight?: PercentageString;
|
|
43
|
+
maxWidth?: PercentageString;
|
|
44
|
+
maxHeight?: PercentageString;
|
|
45
|
+
}
|
|
46
|
+
type FlexDirection = 'row' | 'column' | 'row-reverse' | 'column-reverse';
|
|
47
|
+
type FlexWrap = 'nowrap' | 'wrap' | 'wrap-reverse';
|
|
48
|
+
type JustifyContent = 'flex-start' | 'flex-end' | 'center' | 'space-between' | 'space-around' | 'space-evenly';
|
|
49
|
+
type AlignItems = 'flex-start' | 'flex-end' | 'center' | 'stretch' | 'baseline';
|
|
50
|
+
interface FlexDef {
|
|
51
|
+
type: 'flex';
|
|
52
|
+
direction: FlexDirection;
|
|
53
|
+
wrap?: FlexWrap;
|
|
54
|
+
justifyContent?: JustifyContent;
|
|
55
|
+
alignItems?: AlignItems;
|
|
56
|
+
gap?: string;
|
|
57
|
+
size?: SizeDef;
|
|
58
|
+
children: LayoutDef[];
|
|
59
|
+
componentId?: string;
|
|
60
|
+
idmlStyle?: Record<string, string>;
|
|
61
|
+
className?: string;
|
|
62
|
+
/** Dynamic `@method` class refs (resolved per render, like a component's, so a
|
|
63
|
+
* container can carry a state-driven class — e.g. a per-row colour). */
|
|
64
|
+
classRefs?: string[];
|
|
65
|
+
/** Conditional class blocks (`` `classes`?@ref ``) applied per render. */
|
|
66
|
+
condClasses?: ConditionalClass[];
|
|
67
|
+
visibility?: LayoutVisibility;
|
|
68
|
+
dynamicSize?: DynamicSize;
|
|
69
|
+
}
|
|
70
|
+
/** Reactive show/hide for a layout cell: render only when `ref` resolves truthy
|
|
71
|
+
* (a value path like `state.open`); `negate` flips the test. */
|
|
72
|
+
interface LayoutVisibility {
|
|
73
|
+
ref: string;
|
|
74
|
+
negate?: boolean;
|
|
75
|
+
}
|
|
76
|
+
/** A class block that applies only when `ref` is truthy (`negate` flips it) —
|
|
77
|
+
* i.e. `` `scale-100 opacity-100`?@state.open ``. Lets state-driven visuals (a
|
|
78
|
+
* pop-up's scale/opacity) live in the .idml rather than a method. */
|
|
79
|
+
interface ConditionalClass {
|
|
80
|
+
classes: string;
|
|
81
|
+
ref: string;
|
|
82
|
+
negate?: boolean;
|
|
83
|
+
}
|
|
84
|
+
/** Reactive width/height resolved per render (applied AFTER static `size`, so it
|
|
85
|
+
* wins — letting a cell resize on state, e.g. a collapsing sidebar). The change
|
|
86
|
+
* is animated by the renderer (Web Animations API). */
|
|
87
|
+
interface DynamicSize {
|
|
88
|
+
width?: DynamicDim;
|
|
89
|
+
height?: DynamicDim;
|
|
90
|
+
}
|
|
91
|
+
/** One reactive dimension. `ref` is a value path (`state.x` / method). With
|
|
92
|
+
* `whenTrue`/`whenFalse` it's a condition — the dim is `whenTrue` when the ref
|
|
93
|
+
* is truthy, else `whenFalse` (both inline CSS sizes from the .idml). Without
|
|
94
|
+
* them the ref's resolved value is the dim (bare number → `%`). */
|
|
95
|
+
interface DynamicDim {
|
|
96
|
+
ref: string;
|
|
97
|
+
whenTrue?: string;
|
|
98
|
+
whenFalse?: string;
|
|
99
|
+
}
|
|
100
|
+
interface GridDef {
|
|
101
|
+
type: 'grid';
|
|
102
|
+
columns: number;
|
|
103
|
+
rows?: number;
|
|
104
|
+
gap?: string;
|
|
105
|
+
size?: SizeDef;
|
|
106
|
+
children: LayoutDef[];
|
|
107
|
+
componentId?: string;
|
|
108
|
+
idmlStyle?: Record<string, string>;
|
|
109
|
+
className?: string;
|
|
110
|
+
/** Dynamic `@method` class refs (resolved per render, like a component's, so a
|
|
111
|
+
* container can carry a state-driven class — e.g. a per-row colour). */
|
|
112
|
+
classRefs?: string[];
|
|
113
|
+
/** Conditional class blocks (`` `classes`?@ref ``) applied per render. */
|
|
114
|
+
condClasses?: ConditionalClass[];
|
|
115
|
+
visibility?: LayoutVisibility;
|
|
116
|
+
dynamicSize?: DynamicSize;
|
|
117
|
+
}
|
|
118
|
+
type LayoutDef = FlexDef | GridDef;
|
|
119
|
+
|
|
120
|
+
interface DataBindingDef {
|
|
121
|
+
prop: string;
|
|
122
|
+
methodId: string;
|
|
123
|
+
/**
|
|
124
|
+
* How the binding is wired:
|
|
125
|
+
* - 'handler' (default): the method function is passed as the prop (e.g. onClick).
|
|
126
|
+
* - 'value': the method is called during render and its return value becomes the
|
|
127
|
+
* prop. If the method is a hook (e.g. wraps useQuery/useState) the component
|
|
128
|
+
* re-renders reactively when that value changes.
|
|
129
|
+
* - 'model': two-way binding to a form-state cell named by `methodId` — sets the
|
|
130
|
+
* prop to the current value AND an `onChange` that writes it back.
|
|
131
|
+
*/
|
|
132
|
+
kind?: 'handler' | 'value' | 'model';
|
|
133
|
+
}
|
|
134
|
+
interface VisibilityDef {
|
|
135
|
+
methodId: string;
|
|
136
|
+
negate?: boolean;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
type BuiltinComponentType = 'Text' | 'Heading' | 'Button' | 'Image' | 'List' | 'Card' | 'Divider' | 'Spacer' | 'Icon' | 'Table' | 'Input' | 'Textarea' | 'Select' | 'Option' | 'Checkbox' | 'Radio' | 'Label' | 'Children' | 'Repeat' | 'Form' | 'Modal';
|
|
140
|
+
interface ComponentDef {
|
|
141
|
+
id: string;
|
|
142
|
+
type: BuiltinComponentType | string;
|
|
143
|
+
props?: Record<string, unknown>;
|
|
144
|
+
tokenProps?: {
|
|
145
|
+
color?: string;
|
|
146
|
+
background?: string;
|
|
147
|
+
typography?: string;
|
|
148
|
+
padding?: string;
|
|
149
|
+
};
|
|
150
|
+
bindings?: DataBindingDef[];
|
|
151
|
+
visibility?: VisibilityDef;
|
|
152
|
+
children?: ComponentDef[];
|
|
153
|
+
idmlStyle?: Record<string, string>;
|
|
154
|
+
className?: string;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
interface PageDef {
|
|
158
|
+
route: string;
|
|
159
|
+
title?: string;
|
|
160
|
+
layout: LayoutDef;
|
|
161
|
+
components: ComponentDef[];
|
|
162
|
+
meta?: {
|
|
163
|
+
description?: string;
|
|
164
|
+
ogTitle?: string;
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
interface UIConfig {
|
|
169
|
+
version: '1';
|
|
170
|
+
tokens: TokensDef;
|
|
171
|
+
pages: PageDef[];
|
|
172
|
+
userComponents?: string[];
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
interface ParseOptions {
|
|
176
|
+
/**
|
|
177
|
+
* Called when an `import "./file.idml"` line is encountered.
|
|
178
|
+
* Should return the raw source of the imported file.
|
|
179
|
+
*/
|
|
180
|
+
resolve?: (path: string) => string;
|
|
181
|
+
}
|
|
182
|
+
declare function parseIdml(source: string, options?: ParseOptions): UIConfig;
|
|
183
|
+
|
|
184
|
+
export { type UIConfigOptions, addSSEWriter, parseIdml, startWatcher, stopWatcher, withUIConfig };
|