semajsx 0.1.1 → 0.2.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.
Files changed (103) hide show
  1. package/dist/{computed-BpjqvQu1.mjs → computed-BidG06Lt.mjs} +2 -2
  2. package/dist/{computed-BpjqvQu1.mjs.map → computed-BidG06Lt.mjs.map} +1 -1
  3. package/dist/{document-OGuk9jhK.mjs → document-BOJDaiBc.mjs} +19 -4
  4. package/dist/document-BOJDaiBc.mjs.map +1 -0
  5. package/dist/{document-DFsOtfef.mjs → document-CwHVG_PJ.mjs} +2 -2
  6. package/dist/dom/index.d.mts +68 -3
  7. package/dist/dom/index.d.mts.map +1 -1
  8. package/dist/dom/index.mjs +4 -4
  9. package/dist/dom/jsx-dev-runtime.d.mts +4 -4
  10. package/dist/dom/jsx-dev-runtime.mjs +1 -1
  11. package/dist/dom/jsx-runtime.d.mts +4 -4
  12. package/dist/dom/jsx-runtime.mjs +2 -2
  13. package/dist/{helpers-DrifjCXb.d.mts → helpers-CfRDJgcP.d.mts} +3 -3
  14. package/dist/{helpers-DrifjCXb.d.mts.map → helpers-CfRDJgcP.d.mts.map} +1 -1
  15. package/dist/{index-DS5X3Pvb.d.mts → index-B1pjI-Su.d.mts} +2 -2
  16. package/dist/{index-DS5X3Pvb.d.mts.map → index-B1pjI-Su.d.mts.map} +1 -1
  17. package/dist/index-Ch9GwToI.d.mts +81 -0
  18. package/dist/index-Ch9GwToI.d.mts.map +1 -0
  19. package/dist/index.d.mts +7 -7
  20. package/dist/index.mjs +5 -5
  21. package/dist/{island-marker-hZdmHMvx.d.mts → island-marker-BJIO07Vj.d.mts} +1 -1
  22. package/dist/island-marker-BJIO07Vj.d.mts.map +1 -0
  23. package/dist/{jsx-CGW4OyqA.d.mts → jsx-fNlLjLou.d.mts} +2 -2
  24. package/dist/{jsx-CGW4OyqA.d.mts.map → jsx-fNlLjLou.d.mts.map} +1 -1
  25. package/dist/{jsx-runtime-DU8DRISG.d.mts → jsx-runtime-BFuFPDzn.d.mts} +3 -3
  26. package/dist/{jsx-runtime-DU8DRISG.d.mts.map → jsx-runtime-BFuFPDzn.d.mts.map} +1 -1
  27. package/dist/jsx-runtime-D9ZNjMJ2.mjs.map +1 -1
  28. package/dist/{jsx-runtime-mBpL8czJ.d.mts → jsx-runtime-DZx2Yv-t.d.mts} +28 -6
  29. package/dist/{jsx-runtime-mBpL8czJ.d.mts.map → jsx-runtime-DZx2Yv-t.d.mts.map} +1 -1
  30. package/dist/lucide-CVtHepGM.mjs +126 -0
  31. package/dist/lucide-CVtHepGM.mjs.map +1 -0
  32. package/dist/{resource-B1IudM8_.d.mts → resource-BQI6AeJ0.d.mts} +23 -3
  33. package/dist/resource-BQI6AeJ0.d.mts.map +1 -0
  34. package/dist/{resource-BjsDAkbG.mjs → resource-DSlXDZZi.mjs} +2 -2
  35. package/dist/{resource-BjsDAkbG.mjs.map → resource-DSlXDZZi.mjs.map} +1 -1
  36. package/dist/signal/index.d.mts +2 -2
  37. package/dist/signal/index.mjs +3 -3
  38. package/dist/{signal-4PgGfydw.mjs → signal-BN8vHXDb.mjs} +1 -1
  39. package/dist/{signal-4PgGfydw.mjs.map → signal-BN8vHXDb.mjs.map} +1 -1
  40. package/dist/{signal-CLsaPA7c.d.mts → signal-BwxUlXKs.d.mts} +1 -1
  41. package/dist/{signal-CLsaPA7c.d.mts.map → signal-BwxUlXKs.d.mts.map} +1 -1
  42. package/dist/{src-CRi0xsNK.mjs → src-BqX3sryB.mjs} +68 -5
  43. package/dist/src-BqX3sryB.mjs.map +1 -0
  44. package/dist/{src-DEoBG1zB.mjs → src-DUpFNNM_.mjs} +4 -4
  45. package/dist/{src-DEoBG1zB.mjs.map → src-DUpFNNM_.mjs.map} +1 -1
  46. package/dist/{src-BlS3Hc-L.mjs → src-DW3tIczg.mjs} +75 -5
  47. package/dist/src-DW3tIczg.mjs.map +1 -0
  48. package/dist/{src-Jbt_w0hc.mjs → src-Ds9vl42d.mjs} +37 -35
  49. package/dist/src-Ds9vl42d.mjs.map +1 -0
  50. package/dist/{src-iC-NFwTy.mjs → src-DuSN6go_.mjs} +79 -22
  51. package/dist/src-DuSN6go_.mjs.map +1 -0
  52. package/dist/src-L88LbwEv.mjs +868 -0
  53. package/dist/src-L88LbwEv.mjs.map +1 -0
  54. package/dist/ssg/index.d.mts +4 -182
  55. package/dist/ssg/index.d.mts.map +1 -1
  56. package/dist/ssg/index.mjs +7 -756
  57. package/dist/ssg/index.mjs.map +1 -1
  58. package/dist/ssg/plugins/docs-theme.d.mts +218 -0
  59. package/dist/ssg/plugins/docs-theme.d.mts.map +1 -0
  60. package/dist/ssg/plugins/docs-theme.mjs +2252 -0
  61. package/dist/ssg/plugins/docs-theme.mjs.map +1 -0
  62. package/dist/ssg/plugins/lucide.d.mts +3 -0
  63. package/dist/ssg/plugins/lucide.mjs +7 -0
  64. package/dist/ssr/client.d.mts +3 -3
  65. package/dist/ssr/client.mjs +5 -5
  66. package/dist/ssr/index.d.mts +3 -3
  67. package/dist/ssr/index.d.mts.map +1 -1
  68. package/dist/ssr/index.mjs +6 -5
  69. package/dist/style/index.d.mts +2 -2
  70. package/dist/style/index.d.mts.map +1 -1
  71. package/dist/style/index.mjs +1 -1
  72. package/dist/style/react.d.mts +2 -2
  73. package/dist/style/react.mjs +2 -2
  74. package/dist/style/vue.d.mts +2 -2
  75. package/dist/style/vue.mjs +2 -2
  76. package/dist/terminal/index.d.mts +4 -4
  77. package/dist/terminal/index.mjs +2 -2
  78. package/dist/terminal/jsx-dev-runtime.d.mts +4 -4
  79. package/dist/terminal/jsx-dev-runtime.mjs +1 -1
  80. package/dist/terminal/jsx-runtime.d.mts +4 -4
  81. package/dist/terminal/jsx-runtime.mjs +1 -1
  82. package/dist/{types-DlNR9ZaJ.d.mts → types-BlaUrkq0.d.mts} +2 -2
  83. package/dist/{types-DlNR9ZaJ.d.mts.map → types-BlaUrkq0.d.mts.map} +1 -1
  84. package/dist/types-C9fiRu6l.d.mts +220 -0
  85. package/dist/types-C9fiRu6l.d.mts.map +1 -0
  86. package/dist/{types-Dgj6n-EE.d.mts → types-CZMcXQTW.d.mts} +9 -4
  87. package/dist/types-CZMcXQTW.d.mts.map +1 -0
  88. package/dist/{types-Bjx1Pp14.d.mts → types-D0jRO840.d.mts} +1 -1
  89. package/dist/{types-Bjx1Pp14.d.mts.map → types-D0jRO840.d.mts.map} +1 -1
  90. package/dist/{types-DEi0apQO.d.mts → types-DucvOZQ2.d.mts} +2 -2
  91. package/dist/{types-DEi0apQO.d.mts.map → types-DucvOZQ2.d.mts.map} +1 -1
  92. package/dist/{utils-BrGmTgfG.mjs → utils-DbTAs943.mjs} +1 -1
  93. package/dist/{utils-BrGmTgfG.mjs.map → utils-DbTAs943.mjs.map} +1 -1
  94. package/package.json +30 -2
  95. package/dist/document-OGuk9jhK.mjs.map +0 -1
  96. package/dist/island-marker-hZdmHMvx.d.mts.map +0 -1
  97. package/dist/jsx-runtime-D2B2BK8X.mjs +0 -4
  98. package/dist/resource-B1IudM8_.d.mts.map +0 -1
  99. package/dist/src-BlS3Hc-L.mjs.map +0 -1
  100. package/dist/src-CRi0xsNK.mjs.map +0 -1
  101. package/dist/src-Jbt_w0hc.mjs.map +0 -1
  102. package/dist/src-iC-NFwTy.mjs.map +0 -1
  103. package/dist/types-Dgj6n-EE.d.mts.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"src-DEoBG1zB.mjs","names":[],"sources":["../../terminal/src/utils/colors.ts","../../terminal/src/rendering/box.ts","../../terminal/src/operations.ts","../../terminal/src/rendering/text.ts","../../terminal/src/renderer.ts","../../terminal/src/properties.ts","../../terminal/src/components/ExitHint.tsx","../../terminal/src/render.ts","../../terminal/src/components/BlankLine.tsx"],"sourcesContent":["import chalk, { type ChalkInstance } from \"chalk\";\n\n/**\n * Get a chalk color function by name\n */\nexport function getChalkColor(colorName: string): ChalkInstance {\n const colors: Record<string, ChalkInstance> = {\n black: chalk.black,\n red: chalk.red,\n green: chalk.green,\n yellow: chalk.yellow,\n blue: chalk.blue,\n magenta: chalk.magenta,\n cyan: chalk.cyan,\n white: chalk.white,\n gray: chalk.gray,\n grey: chalk.grey,\n blackBright: chalk.blackBright,\n redBright: chalk.redBright,\n greenBright: chalk.greenBright,\n yellowBright: chalk.yellowBright,\n blueBright: chalk.blueBright,\n magentaBright: chalk.magentaBright,\n cyanBright: chalk.cyanBright,\n whiteBright: chalk.whiteBright,\n };\n return colors[colorName] || chalk;\n}\n\n/**\n * Get a chalk background color function by name\n */\nexport function getChalkBgColor(colorName: string): ChalkInstance {\n const bgColors: Record<string, ChalkInstance> = {\n black: chalk.bgBlack,\n red: chalk.bgRed,\n green: chalk.bgGreen,\n yellow: chalk.bgYellow,\n blue: chalk.bgBlue,\n magenta: chalk.bgMagenta,\n cyan: chalk.bgCyan,\n white: chalk.bgWhite,\n gray: chalk.bgGray,\n grey: chalk.bgGrey,\n blackBright: chalk.bgBlackBright,\n redBright: chalk.bgRedBright,\n greenBright: chalk.bgGreenBright,\n yellowBright: chalk.bgYellowBright,\n blueBright: chalk.bgBlueBright,\n magentaBright: chalk.bgMagentaBright,\n cyanBright: chalk.bgCyanBright,\n whiteBright: chalk.bgWhiteBright,\n };\n return bgColors[colorName] || chalk;\n}\n","import chalk from \"chalk\";\nimport cliBoxes from \"cli-boxes\";\nimport type { TerminalElement } from \"../types\";\nimport { getChalkColor, getChalkBgColor } from \"../utils/colors\";\n\n/**\n * Render a border around an element\n */\nexport function renderBorder(\n node: TerminalElement,\n writeAt: (x: number, y: number, text: string) => void,\n): void {\n const { style, x = 0, y = 0, width = 0, height = 0 } = node;\n const boxStyle = style.border || \"single\";\n\n if (boxStyle === \"none\") return;\n\n const box = cliBoxes[boxStyle] || cliBoxes.single;\n let borderChar = chalk;\n\n if (style.borderColor) {\n borderChar = getChalkColor(style.borderColor);\n }\n\n // Top border\n const topLine = borderChar(box.topLeft + box.top.repeat(Math.max(0, width - 2)) + box.topRight);\n writeAt(x, y, topLine);\n\n // Side borders with spacing\n for (let i = 1; i < height - 1; i++) {\n // Render left border, middle spaces, and right border as a single line\n const middleSpaces = \" \".repeat(Math.max(0, width - 2));\n const sideLine = borderChar(box.left) + middleSpaces + borderChar(box.right);\n writeAt(x, y + i, sideLine);\n }\n\n // Bottom border\n if (height > 1) {\n const bottomLine = borderChar(\n box.bottomLeft + box.bottom.repeat(Math.max(0, width - 2)) + box.bottomRight,\n );\n writeAt(x, y + height - 1, bottomLine);\n }\n}\n\n/**\n * Render background color\n */\nexport function renderBackground(\n node: TerminalElement,\n writeAt: (x: number, y: number, text: string) => void,\n): void {\n const { style, x = 0, y = 0, width = 0, height = 0 } = node;\n\n if (!style.backgroundColor) return;\n\n const bg = getChalkBgColor(style.backgroundColor);\n\n for (let i = 0; i < height; i++) {\n const line = bg(\" \".repeat(width));\n writeAt(x, y + i, line);\n }\n}\n","import Yoga from \"yoga-layout-prebuilt\";\nimport stringWidth from \"string-width\";\nimport wrapAnsi from \"wrap-ansi\";\nimport type { TerminalNode, TerminalElement, TerminalText, TerminalStyle } from \"./types\";\n\n/**\n * Create a terminal element\n */\nexport function createElement(tagName: string): TerminalElement {\n const yogaNode = Yoga.Node.create();\n\n const element: TerminalElement = {\n type: \"element\",\n tagName,\n style: {},\n props: {},\n yogaNode,\n parent: null,\n children: [],\n };\n\n // Set measure function for text containers\n // Text elements need to measure their text content\n if (tagName === \"text\") {\n yogaNode.setMeasureFunc(measureTextNode.bind(null, element));\n }\n\n return element;\n}\n\n/**\n * Create a terminal text node\n * Text nodes don't have yoga nodes - they are pure data containers\n */\nexport function createTextNode(text: string): TerminalText {\n return {\n type: \"text\",\n content: text,\n yogaNode: undefined,\n parent: null,\n children: [],\n };\n}\n\n/**\n * Create a comment (no-op in terminal, returns text node)\n */\nexport function createComment(_text: string): TerminalText {\n return createTextNode(\"\");\n}\n\n/**\n * Append a child to a parent node\n */\nexport function appendChild(parent: TerminalNode, child: TerminalNode): void {\n if (child.parent) {\n removeChild(child);\n }\n\n child.parent = parent;\n parent.children.push(child);\n\n if (parent.yogaNode && child.yogaNode) {\n parent.yogaNode.insertChild(child.yogaNode, parent.yogaNode.getChildCount());\n }\n}\n\n/**\n * Remove a child from its parent\n */\nexport function removeChild(node: TerminalNode): void {\n if (!node.parent) return;\n\n const parent = node.parent;\n const index = parent.children.indexOf(node);\n\n if (index !== -1) {\n parent.children.splice(index, 1);\n\n if (parent.yogaNode && node.yogaNode) {\n parent.yogaNode.removeChild(node.yogaNode);\n }\n }\n\n node.parent = null;\n}\n\n/**\n * Insert a node before another node\n */\nexport function insertBefore(\n parent: TerminalNode,\n newNode: TerminalNode,\n refNode: TerminalNode | null,\n): void {\n if (newNode.parent) {\n removeChild(newNode);\n }\n\n newNode.parent = parent;\n\n if (!refNode) {\n appendChild(parent, newNode);\n return;\n }\n\n const index = parent.children.indexOf(refNode);\n if (index !== -1) {\n parent.children.splice(index, 0, newNode);\n\n if (parent.yogaNode && newNode.yogaNode) {\n parent.yogaNode.insertChild(newNode.yogaNode, index);\n }\n }\n}\n\n/**\n * Replace a node with another node\n */\nexport function replaceNode(oldNode: TerminalNode, newNode: TerminalNode): void {\n const parent = oldNode.parent;\n if (!parent) return;\n\n insertBefore(parent, newNode, oldNode);\n removeChild(oldNode);\n}\n\n/**\n * Set text content of a text node\n */\nexport function setText(node: TerminalNode, text: string): void {\n if (node.type === \"text\") {\n if (node.content === text) {\n return;\n }\n\n node.content = text;\n\n // Text nodes don't have yoga nodes, mark parent as dirty\n if (node.parent) {\n markNodeAsDirty(node.parent);\n }\n }\n}\n\n/**\n * Apply yoga layout styles\n */\nexport function applyStyle(element: TerminalElement, style: Partial<TerminalStyle>): void {\n const { yogaNode } = element;\n if (!yogaNode) return;\n\n element.style = { ...element.style, ...style };\n\n // Flexbox\n if (style.flexDirection) {\n const direction = {\n row: Yoga.FLEX_DIRECTION_ROW,\n column: Yoga.FLEX_DIRECTION_COLUMN,\n \"row-reverse\": Yoga.FLEX_DIRECTION_ROW_REVERSE,\n \"column-reverse\": Yoga.FLEX_DIRECTION_COLUMN_REVERSE,\n }[style.flexDirection];\n yogaNode.setFlexDirection(direction);\n }\n\n if (style.justifyContent) {\n const justify = {\n \"flex-start\": Yoga.JUSTIFY_FLEX_START,\n center: Yoga.JUSTIFY_CENTER,\n \"flex-end\": Yoga.JUSTIFY_FLEX_END,\n \"space-between\": Yoga.JUSTIFY_SPACE_BETWEEN,\n \"space-around\": Yoga.JUSTIFY_SPACE_AROUND,\n }[style.justifyContent];\n yogaNode.setJustifyContent(justify);\n }\n\n if (style.alignItems) {\n const align = {\n \"flex-start\": Yoga.ALIGN_FLEX_START,\n center: Yoga.ALIGN_CENTER,\n \"flex-end\": Yoga.ALIGN_FLEX_END,\n stretch: Yoga.ALIGN_STRETCH,\n }[style.alignItems];\n yogaNode.setAlignItems(align);\n }\n\n // Flex grow/shrink\n if (style.flexGrow !== undefined) {\n yogaNode.setFlexGrow(style.flexGrow);\n }\n if (style.flexShrink !== undefined) {\n yogaNode.setFlexShrink(style.flexShrink);\n }\n\n // Dimensions\n if (style.width !== undefined) {\n if (typeof style.width === \"number\") {\n yogaNode.setWidth(style.width);\n } else if (style.width === \"auto\") {\n yogaNode.setWidthAuto();\n } else if (style.width.endsWith(\"%\")) {\n yogaNode.setWidthPercent(parseFloat(style.width));\n }\n }\n\n if (style.height !== undefined) {\n if (typeof style.height === \"number\") {\n yogaNode.setHeight(style.height);\n } else if (style.height === \"auto\") {\n yogaNode.setHeightAuto();\n } else if (style.height.endsWith(\"%\")) {\n yogaNode.setHeightPercent(parseFloat(style.height));\n }\n }\n\n // Min/Max dimensions\n if (style.minWidth !== undefined) yogaNode.setMinWidth(style.minWidth);\n if (style.minHeight !== undefined) yogaNode.setMinHeight(style.minHeight);\n if (style.maxWidth !== undefined) yogaNode.setMaxWidth(style.maxWidth);\n if (style.maxHeight !== undefined) yogaNode.setMaxHeight(style.maxHeight);\n\n // Margin\n if (style.margin !== undefined) {\n yogaNode.setMargin(Yoga.EDGE_ALL, style.margin);\n }\n // Logical properties (applied before specific edges so they can be overridden)\n if (style.marginInline !== undefined) {\n yogaNode.setMargin(Yoga.EDGE_LEFT, style.marginInline);\n yogaNode.setMargin(Yoga.EDGE_RIGHT, style.marginInline);\n }\n if (style.marginBlock !== undefined) {\n yogaNode.setMargin(Yoga.EDGE_TOP, style.marginBlock);\n yogaNode.setMargin(Yoga.EDGE_BOTTOM, style.marginBlock);\n }\n // Specific edges (override logical properties)\n if (style.marginLeft !== undefined) {\n yogaNode.setMargin(Yoga.EDGE_LEFT, style.marginLeft);\n }\n if (style.marginRight !== undefined) {\n yogaNode.setMargin(Yoga.EDGE_RIGHT, style.marginRight);\n }\n if (style.marginTop !== undefined) {\n yogaNode.setMargin(Yoga.EDGE_TOP, style.marginTop);\n }\n if (style.marginBottom !== undefined) {\n yogaNode.setMargin(Yoga.EDGE_BOTTOM, style.marginBottom);\n }\n\n // Padding\n if (style.padding !== undefined) {\n yogaNode.setPadding(Yoga.EDGE_ALL, style.padding);\n }\n // Logical properties (applied before specific edges so they can be overridden)\n if (style.paddingInline !== undefined) {\n yogaNode.setPadding(Yoga.EDGE_LEFT, style.paddingInline);\n yogaNode.setPadding(Yoga.EDGE_RIGHT, style.paddingInline);\n }\n if (style.paddingBlock !== undefined) {\n yogaNode.setPadding(Yoga.EDGE_TOP, style.paddingBlock);\n yogaNode.setPadding(Yoga.EDGE_BOTTOM, style.paddingBlock);\n }\n // Specific edges (override logical properties)\n if (style.paddingLeft !== undefined) {\n yogaNode.setPadding(Yoga.EDGE_LEFT, style.paddingLeft);\n }\n if (style.paddingRight !== undefined) {\n yogaNode.setPadding(Yoga.EDGE_RIGHT, style.paddingRight);\n }\n if (style.paddingTop !== undefined) {\n yogaNode.setPadding(Yoga.EDGE_TOP, style.paddingTop);\n }\n if (style.paddingBottom !== undefined) {\n yogaNode.setPadding(Yoga.EDGE_BOTTOM, style.paddingBottom);\n }\n}\n\n/**\n * Recursively collect all text content from a node's children\n * Similar to Ink's squashTextNodes\n */\nexport function collectText(node: TerminalNode): string {\n if (node.type === \"text\") {\n return node.content;\n }\n\n let text = \"\";\n for (const child of node.children) {\n text += collectText(child);\n }\n\n return text;\n}\n\n/**\n * Measure text node for Yoga layout\n * This is called by Yoga when calculating layout\n */\nfunction measureTextNode(node: TerminalElement, width: number): { width: number; height: number } {\n // Collect all text from children\n const text = collectText(node);\n\n if (text.length === 0) {\n return { width: 0, height: 0 };\n }\n\n const textWidth = stringWidth(text);\n const lines = text.split(\"\\n\");\n const height = lines.length;\n\n // Text fits within width, no wrapping needed\n if (textWidth <= width) {\n return { width: textWidth, height };\n }\n\n // Edge case: Yoga asking if we can fit in <1px\n if (textWidth >= 1 && width > 0 && width < 1) {\n return { width: textWidth, height };\n }\n\n // Wrap text if it exceeds width\n const wrappedText = wrapAnsi(text, Math.floor(width), {\n hard: true,\n trim: false,\n });\n const wrappedLines = wrappedText.split(\"\\n\");\n const wrappedWidth = Math.max(...wrappedLines.map((line) => stringWidth(line)));\n\n return { width: wrappedWidth, height: wrappedLines.length };\n}\n\n/**\n * Mark a node and its ancestors as dirty for relayout\n */\nexport function markNodeAsDirty(node: TerminalNode): void {\n if (node.yogaNode) {\n node.yogaNode.markDirty();\n return;\n }\n\n // Walk up to find a yoga node\n if (node.parent) {\n markNodeAsDirty(node.parent);\n }\n}\n\n/**\n * Get the parent node of a node\n */\nexport function getParent(node: TerminalNode): TerminalNode | null {\n return node.parent;\n}\n\n/**\n * Get the next sibling of a node\n */\nexport function getNextSibling(node: TerminalNode): TerminalNode | null {\n const parent = node.parent;\n if (!parent) return null;\n\n const index = parent.children.indexOf(node);\n if (index === -1 || index === parent.children.length - 1) {\n return null;\n }\n\n return parent.children[index + 1] || null;\n}\n","import chalk from \"chalk\";\nimport stringWidth from \"string-width\";\nimport sliceAnsi from \"slice-ansi\";\nimport type { TerminalElement, TerminalText } from \"../types\";\nimport { collectText } from \"../operations\";\nimport { getChalkColor } from \"../utils/colors\";\n\n/**\n * Render a text node\n */\nexport function renderTextNode(\n node: TerminalText,\n writeAt: (x: number, y: number, text: string) => void,\n terminalWidth: number,\n): void {\n const { content, x = 0, y = 0, width = 0 } = node;\n\n let text = content;\n const maxWidth = width || terminalWidth - x;\n\n // Truncate if needed\n if (stringWidth(text) > maxWidth) {\n text = sliceAnsi(text, 0, maxWidth);\n }\n\n // Write to buffer at position\n writeAt(x, y, text);\n}\n\n/**\n * Render a text element (collects and styles all text content)\n */\nexport function renderTextElement(\n node: TerminalElement,\n writeAt: (x: number, y: number, text: string) => void,\n): void {\n const { style, x = 0, y = 0 } = node;\n\n const text = collectText(node);\n if (!text) return;\n\n // Apply text styling\n let styledText = text;\n if (style.color) {\n styledText = getChalkColor(style.color)(styledText);\n }\n if (style.bold) {\n styledText = chalk.bold(styledText);\n }\n if (style.italic) {\n styledText = chalk.italic(styledText);\n }\n if (style.underline) {\n styledText = chalk.underline(styledText);\n }\n if (style.strikethrough) {\n styledText = chalk.strikethrough(styledText);\n }\n if (style.dim) {\n styledText = chalk.dim(styledText);\n }\n\n writeAt(x, y, styledText);\n}\n","import Yoga from \"yoga-layout-prebuilt\";\nimport ansiEscapes from \"ansi-escapes\";\nimport stringWidth from \"string-width\";\nimport sliceAnsi from \"slice-ansi\";\nimport type { TerminalNode, TerminalElement, TerminalText, TerminalRoot } from \"./types\";\nimport { renderBorder, renderBackground, renderTextNode, renderTextElement } from \"./rendering\";\n\n/**\n * Terminal renderer instance\n */\nexport class TerminalRenderer {\n private root: TerminalRoot;\n private buffer: string[] = [];\n private previousOutput: string = \"\";\n private lastOutputHeight: number = 0;\n private wasRawMode: boolean = false;\n\n constructor(stream: NodeJS.WriteStream = process.stdout) {\n this.root = {\n type: \"root\",\n stream,\n parent: null,\n children: [],\n yogaNode: Yoga.Node.create(),\n };\n\n // Set root dimensions to terminal size\n const { columns, rows } = stream;\n if (this.root.yogaNode) {\n this.root.yogaNode.setWidth(columns || 80);\n this.root.yogaNode.setHeight(rows || 24);\n // Set default flexbox properties to prevent children from stretching\n this.root.yogaNode.setFlexDirection(Yoga.FLEX_DIRECTION_COLUMN);\n this.root.yogaNode.setAlignItems(Yoga.ALIGN_FLEX_START);\n }\n\n // Enable raw mode to prevent ^C from being displayed\n // Save the previous state so we can restore it\n if (process.stdin.isTTY && process.stdin.setRawMode) {\n this.wasRawMode = process.stdin.isRaw || false;\n if (!this.wasRawMode) {\n process.stdin.setRawMode(true);\n }\n }\n\n // Hide cursor for cleaner rendering\n this.root.stream.write(ansiEscapes.cursorHide);\n }\n\n /**\n * Get the root node\n */\n getRoot(): TerminalRoot {\n return this.root;\n }\n\n /**\n * Render the tree to terminal\n */\n render(): void {\n // Calculate layout\n if (this.root.yogaNode) {\n this.root.yogaNode.calculateLayout(\n this.root.stream.columns || 80,\n this.root.stream.rows || 24,\n Yoga.DIRECTION_LTR,\n );\n }\n\n // Update positions\n this.updatePositions(this.root, 0, 0);\n\n // Render to buffer\n this.buffer = [];\n const height = this.root.stream.rows || 24;\n for (let i = 0; i < height; i++) {\n this.buffer[i] = \"\";\n }\n\n // Render children\n for (const child of this.root.children) {\n this.renderNode(child);\n }\n\n // Output to terminal\n this.output();\n }\n\n /**\n * Update positions of nodes based on yoga layout\n */\n private updatePositions(node: TerminalNode, parentX: number, parentY: number): void {\n if (node.yogaNode) {\n node.x = Math.round(parentX + node.yogaNode.getComputedLeft());\n node.y = Math.round(parentY + node.yogaNode.getComputedTop());\n node.width = Math.round(node.yogaNode.getComputedWidth());\n node.height = Math.round(node.yogaNode.getComputedHeight());\n\n // If this element has a border, add border size to width/height\n // and offset children by 1 to account for border thickness\n let childOffsetX = node.x || 0;\n let childOffsetY = node.y || 0;\n\n if (node.type === \"element\" && node.style.border && node.style.border !== \"none\") {\n // Expand width and height to include border (1 char on each side)\n node.width += 2;\n node.height += 2;\n // Offset children by 1 to leave room for border\n childOffsetX += 1;\n childOffsetY += 1;\n }\n\n for (const child of node.children) {\n this.updatePositions(child, childOffsetX, childOffsetY);\n }\n } else {\n // Text nodes don't have yoga nodes - inherit parent position\n node.x = parentX;\n node.y = parentY;\n\n for (const child of node.children) {\n this.updatePositions(child, parentX, parentY);\n }\n }\n }\n\n /**\n * Render a single node\n */\n private renderNode(node: TerminalNode): void {\n if (node.type === \"text\") {\n this.renderText(node);\n } else if (node.type === \"element\") {\n this.renderElement(node);\n }\n }\n\n /**\n * Render a text node\n */\n private renderText(node: TerminalText): void {\n const { y = 0, x = 0 } = node;\n\n if (y >= this.buffer.length || x < 0) return;\n\n renderTextNode(node, this.writeAt.bind(this), this.root.stream.columns || 80);\n }\n\n /**\n * Render an element node\n */\n private renderElement(node: TerminalElement): void {\n const { style, tagName } = node;\n\n // Render border if specified\n if (style.border && style.border !== \"none\") {\n renderBorder(node, this.writeAt.bind(this));\n }\n\n // Render background\n if (style.backgroundColor) {\n renderBackground(node, this.writeAt.bind(this));\n }\n\n // For text elements, collect and render all text content at once\n if (tagName === \"text\") {\n renderTextElement(node, this.writeAt.bind(this));\n } else {\n // For other elements, render children normally\n for (const child of node.children) {\n this.renderNode(child);\n }\n }\n }\n\n /**\n * Write text at a specific position in the buffer\n */\n private writeAt(x: number, y: number, text: string): void {\n if (y < 0 || y >= this.buffer.length) return;\n\n const row = this.buffer[y] || \"\";\n const width = stringWidth(text);\n const rowWidth = stringWidth(row);\n\n // Pad row if needed\n if (rowWidth < x) {\n this.buffer[y] = row + \" \".repeat(x - rowWidth) + text;\n } else {\n // Replace characters at position\n this.buffer[y] = sliceAnsi(row, 0, x) + text + sliceAnsi(row, x + width);\n }\n }\n\n /**\n * Output the buffer to terminal\n */\n private output(): void {\n // Remove trailing empty lines from buffer (only output actual content)\n let lastNonEmptyIndex = -1;\n for (let i = this.buffer.length - 1; i >= 0; i--) {\n const line = this.buffer[i];\n if (line && line.trim() !== \"\") {\n lastNonEmptyIndex = i;\n break;\n }\n }\n\n // Get only the lines with content\n const contentLines = lastNonEmptyIndex >= 0 ? this.buffer.slice(0, lastNonEmptyIndex + 1) : [];\n const output = contentLines.join(\"\\n\");\n\n // Only update if changed\n if (output !== this.previousOutput) {\n // Erase previous output if there was any\n // eraseLines moves cursor up and erases, so we're ready to write at the start position\n if (this.lastOutputHeight > 0) {\n this.root.stream.write(ansiEscapes.eraseLines(this.lastOutputHeight));\n }\n\n // Write new output (cursor is already at the right position after eraseLines)\n this.root.stream.write(output);\n\n // Calculate and store output height (number of actual lines rendered)\n this.lastOutputHeight = contentLines.length;\n this.previousOutput = output;\n }\n }\n\n /**\n * Clear the rendered output\n */\n clear(): void {\n if (this.lastOutputHeight > 0) {\n this.root.stream.write(ansiEscapes.eraseLines(this.lastOutputHeight));\n this.lastOutputHeight = 0;\n }\n this.previousOutput = \"\";\n }\n\n /**\n * Cleanup\n */\n destroy(): void {\n // Final render to ensure latest state is shown\n this.render();\n\n // Move cursor to line after output\n this.root.stream.write(\"\\n\");\n\n // Show cursor again on cleanup\n this.root.stream.write(ansiEscapes.cursorShow);\n\n // Restore raw mode to previous state\n if (process.stdin.isTTY && process.stdin.setRawMode && !this.wasRawMode) {\n process.stdin.setRawMode(false);\n }\n\n // Free yoga layout\n if (this.root.yogaNode) {\n this.root.yogaNode.freeRecursive();\n }\n }\n}\n","import type { Signal } from \"@semajsx/signal\";\nimport type { TerminalNode, TerminalStyle } from \"./types\";\nimport { applyStyle } from \"./operations\";\n\n/**\n * Set a property on a terminal node\n */\nexport function setProperty(node: TerminalNode, key: string, value: unknown): void {\n if (node.type !== \"element\") return;\n\n // Handle style properties\n if (isStyleProperty(key)) {\n const styleUpdate: Partial<TerminalStyle> = { [key]: value };\n applyStyle(node, styleUpdate);\n return;\n }\n\n // Store other props\n node.props[key] = value;\n}\n\n/**\n * Set a signal property on a terminal node\n */\nexport function setSignalProperty<T = unknown>(\n node: TerminalNode,\n key: string,\n signal: Signal<T>,\n): () => void {\n // Set initial value\n setProperty(node, key, signal.value);\n\n // Subscribe to changes\n return signal.subscribe((value: T) => {\n setProperty(node, key, value);\n });\n}\n\n/**\n * Check if a property is a style property\n */\nfunction isStyleProperty(key: string): boolean {\n const styleProps = new Set([\n \"flexDirection\",\n \"justifyContent\",\n \"alignItems\",\n \"flexGrow\",\n \"flexShrink\",\n \"flexBasis\",\n \"width\",\n \"height\",\n \"minWidth\",\n \"minHeight\",\n \"maxWidth\",\n \"maxHeight\",\n \"margin\",\n \"marginLeft\",\n \"marginRight\",\n \"marginTop\",\n \"marginBottom\",\n \"marginInline\",\n \"marginBlock\",\n \"padding\",\n \"paddingLeft\",\n \"paddingRight\",\n \"paddingTop\",\n \"paddingBottom\",\n \"paddingInline\",\n \"paddingBlock\",\n \"border\",\n \"borderColor\",\n \"color\",\n \"backgroundColor\",\n \"bold\",\n \"italic\",\n \"underline\",\n \"strikethrough\",\n \"dim\",\n ]);\n\n return styleProps.has(key);\n}\n","/** @jsxImportSource @semajsx/terminal */\nimport { computed, signal, type WritableSignal } from \"@semajsx/signal\";\nimport { when, type JSXNode } from \"@semajsx/core\";\n\n/**\n * Global exiting signal for terminal rendering\n * Set to true during unmount to hide exit hints in final render\n */\nconst globalExitingSignal = signal(false);\n\n/**\n * Get the global exiting signal\n * Used internally by render() to coordinate with ExitHint component\n */\nexport function getExitingSignal(): WritableSignal<boolean> {\n return globalExitingSignal;\n}\n\n/**\n * Reset the exiting signal (useful for testing or multiple render cycles)\n */\nexport function resetExitingSignal(): void {\n globalExitingSignal.value = false;\n}\n\nexport interface ExitHintProps {\n /**\n * Content to show during normal rendering, hidden during exit\n * After normalization: single VNode, array of VNodes, or undefined\n */\n children?: JSXNode;\n}\n\n/**\n * ExitHint component - hides its children during the final render before exit\n *\n * This is useful for hiding \"Press Ctrl+C to exit\" messages in the final\n * terminal output, keeping only the actual content visible.\n *\n * The component automatically detects when unmount() is called and reactively\n * hides its children during the final render using signal-based reactivity.\n *\n * @example\n * ```tsx\n * render(\n * <box flexDirection=\"column\" padding={1}>\n * <text bold>Counter: {count}</text>\n *\n * <ExitHint>\n * <text dim marginTop={1} color=\"yellow\">\n * Press Ctrl+C or ESC to exit\n * </text>\n * </ExitHint>\n * </box>\n * );\n * ```\n *\n * Result after exit:\n * - The counter remains visible\n * - The exit hint is hidden from final output\n */\nexport function ExitHint({ children }: ExitHintProps): JSXNode {\n // Create inverted signal: show when NOT exiting\n const shouldShow = computed(globalExitingSignal, (isExiting) => !isExiting);\n\n // Return signal directly - renderComponent now handles Signal<VNode>\n return when(shouldShow, children);\n}\n","import type { VNode } from \"@semajsx/core\";\nimport { setProperty, setSignalProperty } from \"./properties\";\nimport {\n appendChild,\n createElement,\n createTextNode,\n createComment,\n removeChild,\n replaceNode,\n insertBefore,\n getParent,\n getNextSibling,\n} from \"./operations\";\nimport { TerminalRenderer } from \"./renderer\";\nimport type { TerminalNode } from \"./types\";\nimport { getExitingSignal, resetExitingSignal } from \"./components/ExitHint\";\nimport { type ContextMap } from \"@semajsx/core\";\nimport { createRenderer, type RenderStrategy } from \"@semajsx/core\";\n\n/**\n * Terminal-specific render strategy (no reuse optimization needed)\n */\nconst terminalStrategy: RenderStrategy<TerminalNode> = {\n createTextNode,\n createComment,\n createElement,\n getParent,\n getNextSibling,\n insertBefore,\n appendChild,\n removeChild,\n replaceNode,\n setProperty,\n setSignalProperty,\n // Terminal doesn't need tryReuseNode optimization\n};\n\n// Create terminal renderer\nconst { renderNode, cleanupSubscriptions } = createRenderer(terminalStrategy);\n\n/**\n * Options for terminal rendering\n */\nexport interface RenderOptions {\n /**\n * Custom renderer instance. If not provided, one will be created automatically.\n */\n renderer?: TerminalRenderer;\n /**\n * Whether to automatically re-render on signal changes.\n * @default true\n */\n autoRender?: boolean;\n /**\n * Target frames per second for auto-rendering.\n * @default 60\n */\n fps?: number;\n /**\n * Output stream to render to. Only used if renderer is not provided.\n * @default process.stdout\n */\n stream?: NodeJS.WriteStream;\n}\n\n/**\n * Return type for render function\n */\nexport interface RenderResult {\n /**\n * Re-render the tree (useful for manual updates)\n */\n rerender: () => void;\n /**\n * Unmount and cleanup\n */\n unmount: () => void;\n /**\n * Wait for all pending async operations\n */\n waitUntilExit: () => Promise<void>;\n}\n\n/**\n * Options for print function\n */\nexport interface PrintOptions {\n /**\n * Output stream to print to.\n * @default process.stdout\n */\n stream?: NodeJS.WriteStream;\n}\n\n/**\n * Render a VNode tree to the terminal\n * Supports sync VNodes, async VNodes (Promise), and streaming VNodes (AsyncIterableIterator)\n *\n * @example\n * // Simple usage (ink-style)\n * const { unmount } = render(<App />);\n *\n * @example\n * // With custom stream\n * render(<App />, { stream: process.stderr });\n *\n * @example\n * // Disable auto-rendering\n * const { rerender } = render(<App />, { autoRender: false });\n * setInterval(rerender, 100);\n *\n * @example\n * // With custom renderer\n * const renderer = new TerminalRenderer(process.stderr);\n * render(<App />, { renderer });\n *\n * @example\n * // Custom FPS\n * render(<App />, { fps: 30 });\n */\nexport function render(element: VNode, options: RenderOptions = {}): RenderResult {\n const { renderer, autoRender = true, fps = 60, stream: outputStream = process.stdout } = options;\n\n // Reset exiting signal for new render\n resetExitingSignal();\n\n // Auto-create renderer if not provided (ink-style API)\n const autoCreated = !renderer;\n const actualRenderer = renderer || new TerminalRenderer(outputStream);\n\n const root = actualRenderer.getRoot();\n\n // Initialize empty context map for root render\n const initialContext: ContextMap = new Map();\n\n const rendered = renderNode(element, initialContext);\n\n if (rendered.node) {\n appendChild(root, rendered.node);\n } else if (rendered.children.length > 0) {\n // Fragment case - append all fragment children\n for (const child of rendered.children) {\n if (child.node) {\n appendChild(root, child.node);\n }\n }\n }\n\n // Initial render\n actualRenderer.render();\n\n // Rendering lock to prevent overlapping renders (race condition fix)\n let isRendering = false;\n const safeRender = () => {\n if (isRendering) return;\n isRendering = true;\n try {\n actualRenderer.render();\n } finally {\n isRendering = false;\n }\n };\n\n // Auto re-render on signal changes (like ink)\n let renderInterval: NodeJS.Timeout | null = null;\n if (autoRender) {\n const interval = Math.floor(1000 / fps);\n renderInterval = setInterval(() => {\n safeRender();\n }, interval);\n }\n\n // Promise that resolves on exit\n let exitResolver: (() => void) | null = null;\n const exitPromise = new Promise<void>((resolve) => {\n exitResolver = resolve;\n });\n\n // Track original terminal state for cleanup\n const originalRawMode = process.stdin.isTTY && process.stdin.isRaw;\n let handleExit: (() => void) | null = null;\n let handleKeypress: ((data: Buffer) => void) | null = null;\n\n // Cleanup function to restore terminal state\n const cleanup = () => {\n // Stop auto-rendering\n if (renderInterval) {\n clearInterval(renderInterval);\n renderInterval = null;\n }\n\n // Remove event listeners\n if (handleExit) {\n process.removeListener(\"SIGINT\", handleExit);\n process.removeListener(\"SIGTERM\", handleExit);\n }\n if (handleKeypress) {\n process.stdin.removeListener(\"data\", handleKeypress);\n }\n\n // Restore original terminal state\n if (process.stdin.isTTY && process.stdin.setRawMode) {\n try {\n process.stdin.setRawMode(originalRawMode || false);\n } catch {\n // Terminal may already be closed, ignore error\n }\n }\n\n // Clean up subscriptions only (preserve output on exit)\n cleanupSubscriptions(rendered);\n actualRenderer.destroy();\n\n if (exitResolver) {\n exitResolver();\n }\n };\n\n // Unmount function\n const unmount = () => {\n // Mark as exiting to hide ExitHint components\n getExitingSignal().value = true;\n\n // Trigger one final render to apply ExitHint changes\n // This removes exit prompts from the final output\n actualRenderer.render();\n\n cleanup();\n };\n\n // Handle Ctrl+C if auto-created\n if (autoCreated) {\n handleExit = () => {\n unmount();\n process.exit(0);\n };\n\n // Install signal handlers with error recovery\n try {\n process.on(\"SIGINT\", handleExit);\n process.on(\"SIGTERM\", handleExit);\n\n // Enable stdin for keyboard input\n if (process.stdin.isTTY) {\n process.stdin.setRawMode(true);\n process.stdin.resume();\n\n handleKeypress = (data: Buffer) => {\n const key = data.toString();\n // Ctrl+C or ESC to exit\n if (key === \"\\u0003\" || key === \"\\u001b\") {\n if (handleExit) {\n handleExit();\n }\n }\n };\n\n process.stdin.on(\"data\", handleKeypress);\n }\n } catch (err) {\n // If setup fails, clean up and rethrow\n cleanup();\n throw err;\n }\n }\n\n return {\n rerender: safeRender,\n unmount,\n waitUntilExit: () => exitPromise,\n };\n}\n\n/**\n * Print a VNode tree to the terminal once (no auto-rendering).\n * Supports sync VNodes, async VNodes (Promise), and streaming VNodes (AsyncIterableIterator)\n *\n * This is a convenience function for one-time rendering scenarios like:\n * - Server startup messages\n * - CLI output\n * - Static terminal displays\n *\n * Unlike `render()`, this function:\n * - Does not subscribe to signal changes\n * - Does not auto-render on updates\n * - Immediately outputs and cleans up\n * - Does not capture keyboard input\n *\n * @example\n * // Simple server output\n * print(\n * <box border=\"round\" borderColor=\"green\" padding={1}>\n * <text bold color=\"green\">Server started!</text>\n * <text>URL: http://localhost:3000</text>\n * </box>\n * );\n *\n * @example\n * // Print to stderr\n * print(<text color=\"red\">Error occurred</text>, { stream: process.stderr });\n *\n * @example\n * // Print a blank line\n * print();\n */\nexport function print(element?: VNode, options: PrintOptions = {}): void {\n const { stream: outputStream = process.stdout } = options;\n\n // If no element provided, just print a blank line\n if (element === undefined) {\n outputStream.write(\"\\n\");\n return;\n }\n\n // Save raw mode state\n const wasRawMode = process.stdin.isTTY && process.stdin.isRaw;\n\n // Create renderer\n const renderer = new TerminalRenderer(outputStream);\n const root = renderer.getRoot();\n\n // Initialize empty context map for root render\n const initialContext: ContextMap = new Map();\n\n // Render the element\n const rendered = renderNode(element, initialContext);\n\n if (rendered.node) {\n appendChild(root, rendered.node);\n } else if (rendered.children.length > 0) {\n // Fragment case - append all fragment children\n for (const child of rendered.children) {\n if (child.node) {\n appendChild(root, child.node);\n }\n }\n }\n\n // Render once\n renderer.render();\n\n // Clean up subscriptions only (don't remove nodes from tree)\n // This keeps the output visible after destroy\n cleanupSubscriptions(rendered);\n\n // Destroy renderer (outputs final result and shows cursor)\n renderer.destroy();\n\n // Restore raw mode if it was enabled\n if (process.stdin.isTTY && process.stdin.setRawMode && wasRawMode) {\n process.stdin.setRawMode(true);\n }\n}\n","/** @jsxImportSource @semajsx/terminal */\nimport type { JSXNode } from \"@semajsx/core\";\n\nexport interface BlankLineProps {\n /**\n * Number of blank lines to render\n * @default 1\n */\n count?: number;\n}\n\n/**\n * BlankLine component - renders one or more empty lines\n *\n * Useful for adding vertical spacing between terminal UI elements.\n *\n * @example\n * ```tsx\n * <box flexDirection=\"column\">\n * <text>First line</text>\n * <BlankLine />\n * <text>After one blank line</text>\n * <BlankLine count={2} />\n * <text>After two blank lines</text>\n * </box>\n * ```\n */\nexport function BlankLine({ count = 1 }: BlankLineProps): JSXNode {\n const lines = Array.from({ length: count }, (_, i) => <text key={i}> </text>);\n\n return <>{lines}</>;\n}\n"],"mappings":";;;;;;;;;;;;;;;AAKA,SAAgB,cAAc,WAAkC;AAqB9D,QApB8C;EAC5C,OAAO,MAAM;EACb,KAAK,MAAM;EACX,OAAO,MAAM;EACb,QAAQ,MAAM;EACd,MAAM,MAAM;EACZ,SAAS,MAAM;EACf,MAAM,MAAM;EACZ,OAAO,MAAM;EACb,MAAM,MAAM;EACZ,MAAM,MAAM;EACZ,aAAa,MAAM;EACnB,WAAW,MAAM;EACjB,aAAa,MAAM;EACnB,cAAc,MAAM;EACpB,YAAY,MAAM;EAClB,eAAe,MAAM;EACrB,YAAY,MAAM;EAClB,aAAa,MAAM;EACpB,CACa,cAAc;;;;;AAM9B,SAAgB,gBAAgB,WAAkC;AAqBhE,QApBgD;EAC9C,OAAO,MAAM;EACb,KAAK,MAAM;EACX,OAAO,MAAM;EACb,QAAQ,MAAM;EACd,MAAM,MAAM;EACZ,SAAS,MAAM;EACf,MAAM,MAAM;EACZ,OAAO,MAAM;EACb,MAAM,MAAM;EACZ,MAAM,MAAM;EACZ,aAAa,MAAM;EACnB,WAAW,MAAM;EACjB,aAAa,MAAM;EACnB,cAAc,MAAM;EACpB,YAAY,MAAM;EAClB,eAAe,MAAM;EACrB,YAAY,MAAM;EAClB,aAAa,MAAM;EACpB,CACe,cAAc;;;;;;;;AC7ChC,SAAgB,aACd,MACA,SACM;CACN,MAAM,EAAE,OAAO,IAAI,GAAG,IAAI,GAAG,QAAQ,GAAG,SAAS,MAAM;CACvD,MAAM,WAAW,MAAM,UAAU;AAEjC,KAAI,aAAa,OAAQ;CAEzB,MAAM,MAAM,SAAS,aAAa,SAAS;CAC3C,IAAI,aAAa;AAEjB,KAAI,MAAM,YACR,cAAa,cAAc,MAAM,YAAY;AAK/C,SAAQ,GAAG,GADK,WAAW,IAAI,UAAU,IAAI,IAAI,OAAO,KAAK,IAAI,GAAG,QAAQ,EAAE,CAAC,GAAG,IAAI,SAAS,CACzE;AAGtB,MAAK,IAAI,IAAI,GAAG,IAAI,SAAS,GAAG,KAAK;EAEnC,MAAM,eAAe,IAAI,OAAO,KAAK,IAAI,GAAG,QAAQ,EAAE,CAAC;EACvD,MAAM,WAAW,WAAW,IAAI,KAAK,GAAG,eAAe,WAAW,IAAI,MAAM;AAC5E,UAAQ,GAAG,IAAI,GAAG,SAAS;;AAI7B,KAAI,SAAS,GAAG;EACd,MAAM,aAAa,WACjB,IAAI,aAAa,IAAI,OAAO,OAAO,KAAK,IAAI,GAAG,QAAQ,EAAE,CAAC,GAAG,IAAI,YAClE;AACD,UAAQ,GAAG,IAAI,SAAS,GAAG,WAAW;;;;;;AAO1C,SAAgB,iBACd,MACA,SACM;CACN,MAAM,EAAE,OAAO,IAAI,GAAG,IAAI,GAAG,QAAQ,GAAG,SAAS,MAAM;AAEvD,KAAI,CAAC,MAAM,gBAAiB;CAE5B,MAAM,KAAK,gBAAgB,MAAM,gBAAgB;AAEjD,MAAK,IAAI,IAAI,GAAG,IAAI,QAAQ,KAAK;EAC/B,MAAM,OAAO,GAAG,IAAI,OAAO,MAAM,CAAC;AAClC,UAAQ,GAAG,IAAI,GAAG,KAAK;;;;;;;;;ACpD3B,SAAgB,cAAc,SAAkC;CAC9D,MAAM,WAAW,KAAK,KAAK,QAAQ;CAEnC,MAAM,UAA2B;EAC/B,MAAM;EACN;EACA,OAAO,EAAE;EACT,OAAO,EAAE;EACT;EACA,QAAQ;EACR,UAAU,EAAE;EACb;AAID,KAAI,YAAY,OACd,UAAS,eAAe,gBAAgB,KAAK,MAAM,QAAQ,CAAC;AAG9D,QAAO;;;;;;AAOT,SAAgB,eAAe,MAA4B;AACzD,QAAO;EACL,MAAM;EACN,SAAS;EACT,UAAU;EACV,QAAQ;EACR,UAAU,EAAE;EACb;;;;;AAMH,SAAgB,cAAc,OAA6B;AACzD,QAAO,eAAe,GAAG;;;;;AAM3B,SAAgB,YAAY,QAAsB,OAA2B;AAC3E,KAAI,MAAM,OACR,aAAY,MAAM;AAGpB,OAAM,SAAS;AACf,QAAO,SAAS,KAAK,MAAM;AAE3B,KAAI,OAAO,YAAY,MAAM,SAC3B,QAAO,SAAS,YAAY,MAAM,UAAU,OAAO,SAAS,eAAe,CAAC;;;;;AAOhF,SAAgB,YAAY,MAA0B;AACpD,KAAI,CAAC,KAAK,OAAQ;CAElB,MAAM,SAAS,KAAK;CACpB,MAAM,QAAQ,OAAO,SAAS,QAAQ,KAAK;AAE3C,KAAI,UAAU,IAAI;AAChB,SAAO,SAAS,OAAO,OAAO,EAAE;AAEhC,MAAI,OAAO,YAAY,KAAK,SAC1B,QAAO,SAAS,YAAY,KAAK,SAAS;;AAI9C,MAAK,SAAS;;;;;AAMhB,SAAgB,aACd,QACA,SACA,SACM;AACN,KAAI,QAAQ,OACV,aAAY,QAAQ;AAGtB,SAAQ,SAAS;AAEjB,KAAI,CAAC,SAAS;AACZ,cAAY,QAAQ,QAAQ;AAC5B;;CAGF,MAAM,QAAQ,OAAO,SAAS,QAAQ,QAAQ;AAC9C,KAAI,UAAU,IAAI;AAChB,SAAO,SAAS,OAAO,OAAO,GAAG,QAAQ;AAEzC,MAAI,OAAO,YAAY,QAAQ,SAC7B,QAAO,SAAS,YAAY,QAAQ,UAAU,MAAM;;;;;;AAQ1D,SAAgB,YAAY,SAAuB,SAA6B;CAC9E,MAAM,SAAS,QAAQ;AACvB,KAAI,CAAC,OAAQ;AAEb,cAAa,QAAQ,SAAS,QAAQ;AACtC,aAAY,QAAQ;;;;;AAMtB,SAAgB,QAAQ,MAAoB,MAAoB;AAC9D,KAAI,KAAK,SAAS,QAAQ;AACxB,MAAI,KAAK,YAAY,KACnB;AAGF,OAAK,UAAU;AAGf,MAAI,KAAK,OACP,iBAAgB,KAAK,OAAO;;;;;;AAQlC,SAAgB,WAAW,SAA0B,OAAqC;CACxF,MAAM,EAAE,aAAa;AACrB,KAAI,CAAC,SAAU;AAEf,SAAQ,QAAQ;EAAE,GAAG,QAAQ;EAAO,GAAG;EAAO;AAG9C,KAAI,MAAM,eAAe;EACvB,MAAM,YAAY;GAChB,KAAK,KAAK;GACV,QAAQ,KAAK;GACb,eAAe,KAAK;GACpB,kBAAkB,KAAK;GACxB,CAAC,MAAM;AACR,WAAS,iBAAiB,UAAU;;AAGtC,KAAI,MAAM,gBAAgB;EACxB,MAAM,UAAU;GACd,cAAc,KAAK;GACnB,QAAQ,KAAK;GACb,YAAY,KAAK;GACjB,iBAAiB,KAAK;GACtB,gBAAgB,KAAK;GACtB,CAAC,MAAM;AACR,WAAS,kBAAkB,QAAQ;;AAGrC,KAAI,MAAM,YAAY;EACpB,MAAM,QAAQ;GACZ,cAAc,KAAK;GACnB,QAAQ,KAAK;GACb,YAAY,KAAK;GACjB,SAAS,KAAK;GACf,CAAC,MAAM;AACR,WAAS,cAAc,MAAM;;AAI/B,KAAI,MAAM,aAAa,OACrB,UAAS,YAAY,MAAM,SAAS;AAEtC,KAAI,MAAM,eAAe,OACvB,UAAS,cAAc,MAAM,WAAW;AAI1C,KAAI,MAAM,UAAU,QAClB;MAAI,OAAO,MAAM,UAAU,SACzB,UAAS,SAAS,MAAM,MAAM;WACrB,MAAM,UAAU,OACzB,UAAS,cAAc;WACd,MAAM,MAAM,SAAS,IAAI,CAClC,UAAS,gBAAgB,WAAW,MAAM,MAAM,CAAC;;AAIrD,KAAI,MAAM,WAAW,QACnB;MAAI,OAAO,MAAM,WAAW,SAC1B,UAAS,UAAU,MAAM,OAAO;WACvB,MAAM,WAAW,OAC1B,UAAS,eAAe;WACf,MAAM,OAAO,SAAS,IAAI,CACnC,UAAS,iBAAiB,WAAW,MAAM,OAAO,CAAC;;AAKvD,KAAI,MAAM,aAAa,OAAW,UAAS,YAAY,MAAM,SAAS;AACtE,KAAI,MAAM,cAAc,OAAW,UAAS,aAAa,MAAM,UAAU;AACzE,KAAI,MAAM,aAAa,OAAW,UAAS,YAAY,MAAM,SAAS;AACtE,KAAI,MAAM,cAAc,OAAW,UAAS,aAAa,MAAM,UAAU;AAGzE,KAAI,MAAM,WAAW,OACnB,UAAS,UAAU,KAAK,UAAU,MAAM,OAAO;AAGjD,KAAI,MAAM,iBAAiB,QAAW;AACpC,WAAS,UAAU,KAAK,WAAW,MAAM,aAAa;AACtD,WAAS,UAAU,KAAK,YAAY,MAAM,aAAa;;AAEzD,KAAI,MAAM,gBAAgB,QAAW;AACnC,WAAS,UAAU,KAAK,UAAU,MAAM,YAAY;AACpD,WAAS,UAAU,KAAK,aAAa,MAAM,YAAY;;AAGzD,KAAI,MAAM,eAAe,OACvB,UAAS,UAAU,KAAK,WAAW,MAAM,WAAW;AAEtD,KAAI,MAAM,gBAAgB,OACxB,UAAS,UAAU,KAAK,YAAY,MAAM,YAAY;AAExD,KAAI,MAAM,cAAc,OACtB,UAAS,UAAU,KAAK,UAAU,MAAM,UAAU;AAEpD,KAAI,MAAM,iBAAiB,OACzB,UAAS,UAAU,KAAK,aAAa,MAAM,aAAa;AAI1D,KAAI,MAAM,YAAY,OACpB,UAAS,WAAW,KAAK,UAAU,MAAM,QAAQ;AAGnD,KAAI,MAAM,kBAAkB,QAAW;AACrC,WAAS,WAAW,KAAK,WAAW,MAAM,cAAc;AACxD,WAAS,WAAW,KAAK,YAAY,MAAM,cAAc;;AAE3D,KAAI,MAAM,iBAAiB,QAAW;AACpC,WAAS,WAAW,KAAK,UAAU,MAAM,aAAa;AACtD,WAAS,WAAW,KAAK,aAAa,MAAM,aAAa;;AAG3D,KAAI,MAAM,gBAAgB,OACxB,UAAS,WAAW,KAAK,WAAW,MAAM,YAAY;AAExD,KAAI,MAAM,iBAAiB,OACzB,UAAS,WAAW,KAAK,YAAY,MAAM,aAAa;AAE1D,KAAI,MAAM,eAAe,OACvB,UAAS,WAAW,KAAK,UAAU,MAAM,WAAW;AAEtD,KAAI,MAAM,kBAAkB,OAC1B,UAAS,WAAW,KAAK,aAAa,MAAM,cAAc;;;;;;AAQ9D,SAAgB,YAAY,MAA4B;AACtD,KAAI,KAAK,SAAS,OAChB,QAAO,KAAK;CAGd,IAAI,OAAO;AACX,MAAK,MAAM,SAAS,KAAK,SACvB,SAAQ,YAAY,MAAM;AAG5B,QAAO;;;;;;AAOT,SAAS,gBAAgB,MAAuB,OAAkD;CAEhG,MAAM,OAAO,YAAY,KAAK;AAE9B,KAAI,KAAK,WAAW,EAClB,QAAO;EAAE,OAAO;EAAG,QAAQ;EAAG;CAGhC,MAAM,YAAY,YAAY,KAAK;CAEnC,MAAM,SADQ,KAAK,MAAM,KAAK,CACT;AAGrB,KAAI,aAAa,MACf,QAAO;EAAE,OAAO;EAAW;EAAQ;AAIrC,KAAI,aAAa,KAAK,QAAQ,KAAK,QAAQ,EACzC,QAAO;EAAE,OAAO;EAAW;EAAQ;CAQrC,MAAM,eAJc,SAAS,MAAM,KAAK,MAAM,MAAM,EAAE;EACpD,MAAM;EACN,MAAM;EACP,CAAC,CAC+B,MAAM,KAAK;AAG5C,QAAO;EAAE,OAFY,KAAK,IAAI,GAAG,aAAa,KAAK,SAAS,YAAY,KAAK,CAAC,CAAC;EAEjD,QAAQ,aAAa;EAAQ;;;;;AAM7D,SAAgB,gBAAgB,MAA0B;AACxD,KAAI,KAAK,UAAU;AACjB,OAAK,SAAS,WAAW;AACzB;;AAIF,KAAI,KAAK,OACP,iBAAgB,KAAK,OAAO;;;;;AAOhC,SAAgB,UAAU,MAAyC;AACjE,QAAO,KAAK;;;;;AAMd,SAAgB,eAAe,MAAyC;CACtE,MAAM,SAAS,KAAK;AACpB,KAAI,CAAC,OAAQ,QAAO;CAEpB,MAAM,QAAQ,OAAO,SAAS,QAAQ,KAAK;AAC3C,KAAI,UAAU,MAAM,UAAU,OAAO,SAAS,SAAS,EACrD,QAAO;AAGT,QAAO,OAAO,SAAS,QAAQ,MAAM;;;;;;;;AClWvC,SAAgB,eACd,MACA,SACA,eACM;CACN,MAAM,EAAE,SAAS,IAAI,GAAG,IAAI,GAAG,QAAQ,MAAM;CAE7C,IAAI,OAAO;CACX,MAAM,WAAW,SAAS,gBAAgB;AAG1C,KAAI,YAAY,KAAK,GAAG,SACtB,QAAO,UAAU,MAAM,GAAG,SAAS;AAIrC,SAAQ,GAAG,GAAG,KAAK;;;;;AAMrB,SAAgB,kBACd,MACA,SACM;CACN,MAAM,EAAE,OAAO,IAAI,GAAG,IAAI,MAAM;CAEhC,MAAM,OAAO,YAAY,KAAK;AAC9B,KAAI,CAAC,KAAM;CAGX,IAAI,aAAa;AACjB,KAAI,MAAM,MACR,cAAa,cAAc,MAAM,MAAM,CAAC,WAAW;AAErD,KAAI,MAAM,KACR,cAAa,MAAM,KAAK,WAAW;AAErC,KAAI,MAAM,OACR,cAAa,MAAM,OAAO,WAAW;AAEvC,KAAI,MAAM,UACR,cAAa,MAAM,UAAU,WAAW;AAE1C,KAAI,MAAM,cACR,cAAa,MAAM,cAAc,WAAW;AAE9C,KAAI,MAAM,IACR,cAAa,MAAM,IAAI,WAAW;AAGpC,SAAQ,GAAG,GAAG,WAAW;;;;;;;;ACpD3B,IAAa,mBAAb,MAA8B;CAO5B,YAAY,SAA6B,QAAQ,QAAQ;gBAL9B,EAAE;wBACI;0BACE;oBACL;AAG5B,OAAK,OAAO;GACV,MAAM;GACN;GACA,QAAQ;GACR,UAAU,EAAE;GACZ,UAAU,KAAK,KAAK,QAAQ;GAC7B;EAGD,MAAM,EAAE,SAAS,SAAS;AAC1B,MAAI,KAAK,KAAK,UAAU;AACtB,QAAK,KAAK,SAAS,SAAS,WAAW,GAAG;AAC1C,QAAK,KAAK,SAAS,UAAU,QAAQ,GAAG;AAExC,QAAK,KAAK,SAAS,iBAAiB,KAAK,sBAAsB;AAC/D,QAAK,KAAK,SAAS,cAAc,KAAK,iBAAiB;;AAKzD,MAAI,QAAQ,MAAM,SAAS,QAAQ,MAAM,YAAY;AACnD,QAAK,aAAa,QAAQ,MAAM,SAAS;AACzC,OAAI,CAAC,KAAK,WACR,SAAQ,MAAM,WAAW,KAAK;;AAKlC,OAAK,KAAK,OAAO,MAAM,YAAY,WAAW;;;;;CAMhD,UAAwB;AACtB,SAAO,KAAK;;;;;CAMd,SAAe;AAEb,MAAI,KAAK,KAAK,SACZ,MAAK,KAAK,SAAS,gBACjB,KAAK,KAAK,OAAO,WAAW,IAC5B,KAAK,KAAK,OAAO,QAAQ,IACzB,KAAK,cACN;AAIH,OAAK,gBAAgB,KAAK,MAAM,GAAG,EAAE;AAGrC,OAAK,SAAS,EAAE;EAChB,MAAM,SAAS,KAAK,KAAK,OAAO,QAAQ;AACxC,OAAK,IAAI,IAAI,GAAG,IAAI,QAAQ,IAC1B,MAAK,OAAO,KAAK;AAInB,OAAK,MAAM,SAAS,KAAK,KAAK,SAC5B,MAAK,WAAW,MAAM;AAIxB,OAAK,QAAQ;;;;;CAMf,AAAQ,gBAAgB,MAAoB,SAAiB,SAAuB;AAClF,MAAI,KAAK,UAAU;AACjB,QAAK,IAAI,KAAK,MAAM,UAAU,KAAK,SAAS,iBAAiB,CAAC;AAC9D,QAAK,IAAI,KAAK,MAAM,UAAU,KAAK,SAAS,gBAAgB,CAAC;AAC7D,QAAK,QAAQ,KAAK,MAAM,KAAK,SAAS,kBAAkB,CAAC;AACzD,QAAK,SAAS,KAAK,MAAM,KAAK,SAAS,mBAAmB,CAAC;GAI3D,IAAI,eAAe,KAAK,KAAK;GAC7B,IAAI,eAAe,KAAK,KAAK;AAE7B,OAAI,KAAK,SAAS,aAAa,KAAK,MAAM,UAAU,KAAK,MAAM,WAAW,QAAQ;AAEhF,SAAK,SAAS;AACd,SAAK,UAAU;AAEf,oBAAgB;AAChB,oBAAgB;;AAGlB,QAAK,MAAM,SAAS,KAAK,SACvB,MAAK,gBAAgB,OAAO,cAAc,aAAa;SAEpD;AAEL,QAAK,IAAI;AACT,QAAK,IAAI;AAET,QAAK,MAAM,SAAS,KAAK,SACvB,MAAK,gBAAgB,OAAO,SAAS,QAAQ;;;;;;CAQnD,AAAQ,WAAW,MAA0B;AAC3C,MAAI,KAAK,SAAS,OAChB,MAAK,WAAW,KAAK;WACZ,KAAK,SAAS,UACvB,MAAK,cAAc,KAAK;;;;;CAO5B,AAAQ,WAAW,MAA0B;EAC3C,MAAM,EAAE,IAAI,GAAG,IAAI,MAAM;AAEzB,MAAI,KAAK,KAAK,OAAO,UAAU,IAAI,EAAG;AAEtC,iBAAe,MAAM,KAAK,QAAQ,KAAK,KAAK,EAAE,KAAK,KAAK,OAAO,WAAW,GAAG;;;;;CAM/E,AAAQ,cAAc,MAA6B;EACjD,MAAM,EAAE,OAAO,YAAY;AAG3B,MAAI,MAAM,UAAU,MAAM,WAAW,OACnC,cAAa,MAAM,KAAK,QAAQ,KAAK,KAAK,CAAC;AAI7C,MAAI,MAAM,gBACR,kBAAiB,MAAM,KAAK,QAAQ,KAAK,KAAK,CAAC;AAIjD,MAAI,YAAY,OACd,mBAAkB,MAAM,KAAK,QAAQ,KAAK,KAAK,CAAC;MAGhD,MAAK,MAAM,SAAS,KAAK,SACvB,MAAK,WAAW,MAAM;;;;;CAQ5B,AAAQ,QAAQ,GAAW,GAAW,MAAoB;AACxD,MAAI,IAAI,KAAK,KAAK,KAAK,OAAO,OAAQ;EAEtC,MAAM,MAAM,KAAK,OAAO,MAAM;EAC9B,MAAM,QAAQ,YAAY,KAAK;EAC/B,MAAM,WAAW,YAAY,IAAI;AAGjC,MAAI,WAAW,EACb,MAAK,OAAO,KAAK,MAAM,IAAI,OAAO,IAAI,SAAS,GAAG;MAGlD,MAAK,OAAO,KAAK,UAAU,KAAK,GAAG,EAAE,GAAG,OAAO,UAAU,KAAK,IAAI,MAAM;;;;;CAO5E,AAAQ,SAAe;EAErB,IAAI,oBAAoB;AACxB,OAAK,IAAI,IAAI,KAAK,OAAO,SAAS,GAAG,KAAK,GAAG,KAAK;GAChD,MAAM,OAAO,KAAK,OAAO;AACzB,OAAI,QAAQ,KAAK,MAAM,KAAK,IAAI;AAC9B,wBAAoB;AACpB;;;EAKJ,MAAM,eAAe,qBAAqB,IAAI,KAAK,OAAO,MAAM,GAAG,oBAAoB,EAAE,GAAG,EAAE;EAC9F,MAAM,SAAS,aAAa,KAAK,KAAK;AAGtC,MAAI,WAAW,KAAK,gBAAgB;AAGlC,OAAI,KAAK,mBAAmB,EAC1B,MAAK,KAAK,OAAO,MAAM,YAAY,WAAW,KAAK,iBAAiB,CAAC;AAIvE,QAAK,KAAK,OAAO,MAAM,OAAO;AAG9B,QAAK,mBAAmB,aAAa;AACrC,QAAK,iBAAiB;;;;;;CAO1B,QAAc;AACZ,MAAI,KAAK,mBAAmB,GAAG;AAC7B,QAAK,KAAK,OAAO,MAAM,YAAY,WAAW,KAAK,iBAAiB,CAAC;AACrE,QAAK,mBAAmB;;AAE1B,OAAK,iBAAiB;;;;;CAMxB,UAAgB;AAEd,OAAK,QAAQ;AAGb,OAAK,KAAK,OAAO,MAAM,KAAK;AAG5B,OAAK,KAAK,OAAO,MAAM,YAAY,WAAW;AAG9C,MAAI,QAAQ,MAAM,SAAS,QAAQ,MAAM,cAAc,CAAC,KAAK,WAC3D,SAAQ,MAAM,WAAW,MAAM;AAIjC,MAAI,KAAK,KAAK,SACZ,MAAK,KAAK,SAAS,eAAe;;;;;;;;;AC7PxC,SAAgB,YAAY,MAAoB,KAAa,OAAsB;AACjF,KAAI,KAAK,SAAS,UAAW;AAG7B,KAAI,gBAAgB,IAAI,EAAE;AAExB,aAAW,MADiC,GAAG,MAAM,OAAO,CAC/B;AAC7B;;AAIF,MAAK,MAAM,OAAO;;;;;AAMpB,SAAgB,kBACd,MACA,KACA,QACY;AAEZ,aAAY,MAAM,KAAK,OAAO,MAAM;AAGpC,QAAO,OAAO,WAAW,UAAa;AACpC,cAAY,MAAM,KAAK,MAAM;GAC7B;;;;;AAMJ,SAAS,gBAAgB,KAAsB;AAuC7C,QAtCmB,IAAI,IAAI;EACzB;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACD,CAAC,CAEgB,IAAI,IAAI;;;;;;;;;;ACxE5B,MAAM,sBAAsB,OAAO,MAAM;;;;;AAMzC,SAAgB,mBAA4C;AAC1D,QAAO;;;;;AAMT,SAAgB,qBAA2B;AACzC,qBAAoB,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAuC9B,SAAgB,SAAS,EAAE,YAAoC;AAK7D,QAAO,KAHY,SAAS,sBAAsB,cAAc,CAAC,UAAU,EAGnD,SAAS;;;;;AC5BnC,MAAM,EAAE,YAAY,yBAAyB,eAhBU;CACrD;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CAED,CAG4E;;;;;;;;;;;;;;;;;;;;;;;;;;;AAkF7E,SAAgB,OAAO,SAAgB,UAAyB,EAAE,EAAgB;CAChF,MAAM,EAAE,UAAU,aAAa,MAAM,MAAM,IAAI,QAAQ,eAAe,QAAQ,WAAW;AAGzF,qBAAoB;CAGpB,MAAM,cAAc,CAAC;CACrB,MAAM,iBAAiB,YAAY,IAAI,iBAAiB,aAAa;CAErE,MAAM,OAAO,eAAe,SAAS;CAKrC,MAAM,WAAW,WAAW,yBAFO,IAAI,KAAK,CAEQ;AAEpD,KAAI,SAAS,KACX,aAAY,MAAM,SAAS,KAAK;UACvB,SAAS,SAAS,SAAS,GAEpC;OAAK,MAAM,SAAS,SAAS,SAC3B,KAAI,MAAM,KACR,aAAY,MAAM,MAAM,KAAK;;AAMnC,gBAAe,QAAQ;CAGvB,IAAI,cAAc;CAClB,MAAM,mBAAmB;AACvB,MAAI,YAAa;AACjB,gBAAc;AACd,MAAI;AACF,kBAAe,QAAQ;YACf;AACR,iBAAc;;;CAKlB,IAAI,iBAAwC;AAC5C,KAAI,YAAY;EACd,MAAM,WAAW,KAAK,MAAM,MAAO,IAAI;AACvC,mBAAiB,kBAAkB;AACjC,eAAY;KACX,SAAS;;CAId,IAAI,eAAoC;CACxC,MAAM,cAAc,IAAI,SAAe,YAAY;AACjD,iBAAe;GACf;CAGF,MAAM,kBAAkB,QAAQ,MAAM,SAAS,QAAQ,MAAM;CAC7D,IAAI,aAAkC;CACtC,IAAI,iBAAkD;CAGtD,MAAM,gBAAgB;AAEpB,MAAI,gBAAgB;AAClB,iBAAc,eAAe;AAC7B,oBAAiB;;AAInB,MAAI,YAAY;AACd,WAAQ,eAAe,UAAU,WAAW;AAC5C,WAAQ,eAAe,WAAW,WAAW;;AAE/C,MAAI,eACF,SAAQ,MAAM,eAAe,QAAQ,eAAe;AAItD,MAAI,QAAQ,MAAM,SAAS,QAAQ,MAAM,WACvC,KAAI;AACF,WAAQ,MAAM,WAAW,mBAAmB,MAAM;UAC5C;AAMV,uBAAqB,SAAS;AAC9B,iBAAe,SAAS;AAExB,MAAI,aACF,eAAc;;CAKlB,MAAM,gBAAgB;AAEpB,oBAAkB,CAAC,QAAQ;AAI3B,iBAAe,QAAQ;AAEvB,WAAS;;AAIX,KAAI,aAAa;AACf,qBAAmB;AACjB,YAAS;AACT,WAAQ,KAAK,EAAE;;AAIjB,MAAI;AACF,WAAQ,GAAG,UAAU,WAAW;AAChC,WAAQ,GAAG,WAAW,WAAW;AAGjC,OAAI,QAAQ,MAAM,OAAO;AACvB,YAAQ,MAAM,WAAW,KAAK;AAC9B,YAAQ,MAAM,QAAQ;AAEtB,sBAAkB,SAAiB;KACjC,MAAM,MAAM,KAAK,UAAU;AAE3B,SAAI,QAAQ,OAAY,QAAQ,QAC9B;UAAI,WACF,aAAY;;;AAKlB,YAAQ,MAAM,GAAG,QAAQ,eAAe;;WAEnC,KAAK;AAEZ,YAAS;AACT,SAAM;;;AAIV,QAAO;EACL,UAAU;EACV;EACA,qBAAqB;EACtB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAmCH,SAAgB,MAAM,SAAiB,UAAwB,EAAE,EAAQ;CACvE,MAAM,EAAE,QAAQ,eAAe,QAAQ,WAAW;AAGlD,KAAI,YAAY,QAAW;AACzB,eAAa,MAAM,KAAK;AACxB;;CAIF,MAAM,aAAa,QAAQ,MAAM,SAAS,QAAQ,MAAM;CAGxD,MAAM,WAAW,IAAI,iBAAiB,aAAa;CACnD,MAAM,OAAO,SAAS,SAAS;CAM/B,MAAM,WAAW,WAAW,yBAHO,IAAI,KAAK,CAGQ;AAEpD,KAAI,SAAS,KACX,aAAY,MAAM,SAAS,KAAK;UACvB,SAAS,SAAS,SAAS,GAEpC;OAAK,MAAM,SAAS,SAAS,SAC3B,KAAI,MAAM,KACR,aAAY,MAAM,MAAM,KAAK;;AAMnC,UAAS,QAAQ;AAIjB,sBAAqB,SAAS;AAG9B,UAAS,SAAS;AAGlB,KAAI,QAAQ,MAAM,SAAS,QAAQ,MAAM,cAAc,WACrD,SAAQ,MAAM,WAAW,KAAK;;;;;;;;;;;;;;;;;;;;;ACnUlC,SAAgB,UAAU,EAAE,QAAQ,KAA8B;AAGhE,QAAO,0CAFO,MAAM,KAAK,EAAE,QAAQ,OAAO,GAAG,GAAG,MAAM,oBAAC,oBAAa,OAAH,EAAW,CAAC,GAE1D"}
1
+ {"version":3,"file":"src-DUpFNNM_.mjs","names":[],"sources":["../../terminal/src/utils/colors.ts","../../terminal/src/rendering/box.ts","../../terminal/src/operations.ts","../../terminal/src/rendering/text.ts","../../terminal/src/renderer.ts","../../terminal/src/properties.ts","../../terminal/src/components/ExitHint.tsx","../../terminal/src/render.ts","../../terminal/src/components/BlankLine.tsx"],"sourcesContent":["import chalk, { type ChalkInstance } from \"chalk\";\n\n/**\n * Get a chalk color function by name\n */\nexport function getChalkColor(colorName: string): ChalkInstance {\n const colors: Record<string, ChalkInstance> = {\n black: chalk.black,\n red: chalk.red,\n green: chalk.green,\n yellow: chalk.yellow,\n blue: chalk.blue,\n magenta: chalk.magenta,\n cyan: chalk.cyan,\n white: chalk.white,\n gray: chalk.gray,\n grey: chalk.grey,\n blackBright: chalk.blackBright,\n redBright: chalk.redBright,\n greenBright: chalk.greenBright,\n yellowBright: chalk.yellowBright,\n blueBright: chalk.blueBright,\n magentaBright: chalk.magentaBright,\n cyanBright: chalk.cyanBright,\n whiteBright: chalk.whiteBright,\n };\n return colors[colorName] || chalk;\n}\n\n/**\n * Get a chalk background color function by name\n */\nexport function getChalkBgColor(colorName: string): ChalkInstance {\n const bgColors: Record<string, ChalkInstance> = {\n black: chalk.bgBlack,\n red: chalk.bgRed,\n green: chalk.bgGreen,\n yellow: chalk.bgYellow,\n blue: chalk.bgBlue,\n magenta: chalk.bgMagenta,\n cyan: chalk.bgCyan,\n white: chalk.bgWhite,\n gray: chalk.bgGray,\n grey: chalk.bgGrey,\n blackBright: chalk.bgBlackBright,\n redBright: chalk.bgRedBright,\n greenBright: chalk.bgGreenBright,\n yellowBright: chalk.bgYellowBright,\n blueBright: chalk.bgBlueBright,\n magentaBright: chalk.bgMagentaBright,\n cyanBright: chalk.bgCyanBright,\n whiteBright: chalk.bgWhiteBright,\n };\n return bgColors[colorName] || chalk;\n}\n","import chalk from \"chalk\";\nimport cliBoxes from \"cli-boxes\";\nimport type { TerminalElement } from \"../types\";\nimport { getChalkColor, getChalkBgColor } from \"../utils/colors\";\n\n/**\n * Render a border around an element\n */\nexport function renderBorder(\n node: TerminalElement,\n writeAt: (x: number, y: number, text: string) => void,\n): void {\n const { style, x = 0, y = 0, width = 0, height = 0 } = node;\n const boxStyle = style.border || \"single\";\n\n if (boxStyle === \"none\") return;\n\n const box = cliBoxes[boxStyle] || cliBoxes.single;\n let borderChar = chalk;\n\n if (style.borderColor) {\n borderChar = getChalkColor(style.borderColor);\n }\n\n // Top border\n const topLine = borderChar(box.topLeft + box.top.repeat(Math.max(0, width - 2)) + box.topRight);\n writeAt(x, y, topLine);\n\n // Side borders with spacing\n for (let i = 1; i < height - 1; i++) {\n // Render left border, middle spaces, and right border as a single line\n const middleSpaces = \" \".repeat(Math.max(0, width - 2));\n const sideLine = borderChar(box.left) + middleSpaces + borderChar(box.right);\n writeAt(x, y + i, sideLine);\n }\n\n // Bottom border\n if (height > 1) {\n const bottomLine = borderChar(\n box.bottomLeft + box.bottom.repeat(Math.max(0, width - 2)) + box.bottomRight,\n );\n writeAt(x, y + height - 1, bottomLine);\n }\n}\n\n/**\n * Render background color\n */\nexport function renderBackground(\n node: TerminalElement,\n writeAt: (x: number, y: number, text: string) => void,\n): void {\n const { style, x = 0, y = 0, width = 0, height = 0 } = node;\n\n if (!style.backgroundColor) return;\n\n const bg = getChalkBgColor(style.backgroundColor);\n\n for (let i = 0; i < height; i++) {\n const line = bg(\" \".repeat(width));\n writeAt(x, y + i, line);\n }\n}\n","import Yoga from \"yoga-layout-prebuilt\";\nimport stringWidth from \"string-width\";\nimport wrapAnsi from \"wrap-ansi\";\nimport type { TerminalNode, TerminalElement, TerminalText, TerminalStyle } from \"./types\";\n\n/**\n * Create a terminal element\n */\nexport function createElement(tagName: string): TerminalElement {\n const yogaNode = Yoga.Node.create();\n\n const element: TerminalElement = {\n type: \"element\",\n tagName,\n style: {},\n props: {},\n yogaNode,\n parent: null,\n children: [],\n };\n\n // Set measure function for text containers\n // Text elements need to measure their text content\n if (tagName === \"text\") {\n yogaNode.setMeasureFunc(measureTextNode.bind(null, element));\n }\n\n return element;\n}\n\n/**\n * Create a terminal text node\n * Text nodes don't have yoga nodes - they are pure data containers\n */\nexport function createTextNode(text: string): TerminalText {\n return {\n type: \"text\",\n content: text,\n yogaNode: undefined,\n parent: null,\n children: [],\n };\n}\n\n/**\n * Create a comment (no-op in terminal, returns text node)\n */\nexport function createComment(_text: string): TerminalText {\n return createTextNode(\"\");\n}\n\n/**\n * Append a child to a parent node\n */\nexport function appendChild(parent: TerminalNode, child: TerminalNode): void {\n if (child.parent) {\n removeChild(child);\n }\n\n child.parent = parent;\n parent.children.push(child);\n\n if (parent.yogaNode && child.yogaNode) {\n parent.yogaNode.insertChild(child.yogaNode, parent.yogaNode.getChildCount());\n }\n}\n\n/**\n * Remove a child from its parent\n */\nexport function removeChild(node: TerminalNode): void {\n if (!node.parent) return;\n\n const parent = node.parent;\n const index = parent.children.indexOf(node);\n\n if (index !== -1) {\n parent.children.splice(index, 1);\n\n if (parent.yogaNode && node.yogaNode) {\n parent.yogaNode.removeChild(node.yogaNode);\n }\n }\n\n node.parent = null;\n}\n\n/**\n * Insert a node before another node\n */\nexport function insertBefore(\n parent: TerminalNode,\n newNode: TerminalNode,\n refNode: TerminalNode | null,\n): void {\n if (newNode.parent) {\n removeChild(newNode);\n }\n\n newNode.parent = parent;\n\n if (!refNode) {\n appendChild(parent, newNode);\n return;\n }\n\n const index = parent.children.indexOf(refNode);\n if (index !== -1) {\n parent.children.splice(index, 0, newNode);\n\n if (parent.yogaNode && newNode.yogaNode) {\n parent.yogaNode.insertChild(newNode.yogaNode, index);\n }\n }\n}\n\n/**\n * Replace a node with another node\n */\nexport function replaceNode(oldNode: TerminalNode, newNode: TerminalNode): void {\n const parent = oldNode.parent;\n if (!parent) return;\n\n insertBefore(parent, newNode, oldNode);\n removeChild(oldNode);\n}\n\n/**\n * Set text content of a text node\n */\nexport function setText(node: TerminalNode, text: string): void {\n if (node.type === \"text\") {\n if (node.content === text) {\n return;\n }\n\n node.content = text;\n\n // Text nodes don't have yoga nodes, mark parent as dirty\n if (node.parent) {\n markNodeAsDirty(node.parent);\n }\n }\n}\n\n/**\n * Apply yoga layout styles\n */\nexport function applyStyle(element: TerminalElement, style: Partial<TerminalStyle>): void {\n const { yogaNode } = element;\n if (!yogaNode) return;\n\n element.style = { ...element.style, ...style };\n\n // Flexbox\n if (style.flexDirection) {\n const direction = {\n row: Yoga.FLEX_DIRECTION_ROW,\n column: Yoga.FLEX_DIRECTION_COLUMN,\n \"row-reverse\": Yoga.FLEX_DIRECTION_ROW_REVERSE,\n \"column-reverse\": Yoga.FLEX_DIRECTION_COLUMN_REVERSE,\n }[style.flexDirection];\n yogaNode.setFlexDirection(direction);\n }\n\n if (style.justifyContent) {\n const justify = {\n \"flex-start\": Yoga.JUSTIFY_FLEX_START,\n center: Yoga.JUSTIFY_CENTER,\n \"flex-end\": Yoga.JUSTIFY_FLEX_END,\n \"space-between\": Yoga.JUSTIFY_SPACE_BETWEEN,\n \"space-around\": Yoga.JUSTIFY_SPACE_AROUND,\n }[style.justifyContent];\n yogaNode.setJustifyContent(justify);\n }\n\n if (style.alignItems) {\n const align = {\n \"flex-start\": Yoga.ALIGN_FLEX_START,\n center: Yoga.ALIGN_CENTER,\n \"flex-end\": Yoga.ALIGN_FLEX_END,\n stretch: Yoga.ALIGN_STRETCH,\n }[style.alignItems];\n yogaNode.setAlignItems(align);\n }\n\n // Flex grow/shrink\n if (style.flexGrow !== undefined) {\n yogaNode.setFlexGrow(style.flexGrow);\n }\n if (style.flexShrink !== undefined) {\n yogaNode.setFlexShrink(style.flexShrink);\n }\n\n // Dimensions\n if (style.width !== undefined) {\n if (typeof style.width === \"number\") {\n yogaNode.setWidth(style.width);\n } else if (style.width === \"auto\") {\n yogaNode.setWidthAuto();\n } else if (style.width.endsWith(\"%\")) {\n yogaNode.setWidthPercent(parseFloat(style.width));\n }\n }\n\n if (style.height !== undefined) {\n if (typeof style.height === \"number\") {\n yogaNode.setHeight(style.height);\n } else if (style.height === \"auto\") {\n yogaNode.setHeightAuto();\n } else if (style.height.endsWith(\"%\")) {\n yogaNode.setHeightPercent(parseFloat(style.height));\n }\n }\n\n // Min/Max dimensions\n if (style.minWidth !== undefined) yogaNode.setMinWidth(style.minWidth);\n if (style.minHeight !== undefined) yogaNode.setMinHeight(style.minHeight);\n if (style.maxWidth !== undefined) yogaNode.setMaxWidth(style.maxWidth);\n if (style.maxHeight !== undefined) yogaNode.setMaxHeight(style.maxHeight);\n\n // Margin\n if (style.margin !== undefined) {\n yogaNode.setMargin(Yoga.EDGE_ALL, style.margin);\n }\n // Logical properties (applied before specific edges so they can be overridden)\n if (style.marginInline !== undefined) {\n yogaNode.setMargin(Yoga.EDGE_LEFT, style.marginInline);\n yogaNode.setMargin(Yoga.EDGE_RIGHT, style.marginInline);\n }\n if (style.marginBlock !== undefined) {\n yogaNode.setMargin(Yoga.EDGE_TOP, style.marginBlock);\n yogaNode.setMargin(Yoga.EDGE_BOTTOM, style.marginBlock);\n }\n // Specific edges (override logical properties)\n if (style.marginLeft !== undefined) {\n yogaNode.setMargin(Yoga.EDGE_LEFT, style.marginLeft);\n }\n if (style.marginRight !== undefined) {\n yogaNode.setMargin(Yoga.EDGE_RIGHT, style.marginRight);\n }\n if (style.marginTop !== undefined) {\n yogaNode.setMargin(Yoga.EDGE_TOP, style.marginTop);\n }\n if (style.marginBottom !== undefined) {\n yogaNode.setMargin(Yoga.EDGE_BOTTOM, style.marginBottom);\n }\n\n // Padding\n if (style.padding !== undefined) {\n yogaNode.setPadding(Yoga.EDGE_ALL, style.padding);\n }\n // Logical properties (applied before specific edges so they can be overridden)\n if (style.paddingInline !== undefined) {\n yogaNode.setPadding(Yoga.EDGE_LEFT, style.paddingInline);\n yogaNode.setPadding(Yoga.EDGE_RIGHT, style.paddingInline);\n }\n if (style.paddingBlock !== undefined) {\n yogaNode.setPadding(Yoga.EDGE_TOP, style.paddingBlock);\n yogaNode.setPadding(Yoga.EDGE_BOTTOM, style.paddingBlock);\n }\n // Specific edges (override logical properties)\n if (style.paddingLeft !== undefined) {\n yogaNode.setPadding(Yoga.EDGE_LEFT, style.paddingLeft);\n }\n if (style.paddingRight !== undefined) {\n yogaNode.setPadding(Yoga.EDGE_RIGHT, style.paddingRight);\n }\n if (style.paddingTop !== undefined) {\n yogaNode.setPadding(Yoga.EDGE_TOP, style.paddingTop);\n }\n if (style.paddingBottom !== undefined) {\n yogaNode.setPadding(Yoga.EDGE_BOTTOM, style.paddingBottom);\n }\n}\n\n/**\n * Recursively collect all text content from a node's children\n * Similar to Ink's squashTextNodes\n */\nexport function collectText(node: TerminalNode): string {\n if (node.type === \"text\") {\n return node.content;\n }\n\n let text = \"\";\n for (const child of node.children) {\n text += collectText(child);\n }\n\n return text;\n}\n\n/**\n * Measure text node for Yoga layout\n * This is called by Yoga when calculating layout\n */\nfunction measureTextNode(node: TerminalElement, width: number): { width: number; height: number } {\n // Collect all text from children\n const text = collectText(node);\n\n if (text.length === 0) {\n return { width: 0, height: 0 };\n }\n\n const textWidth = stringWidth(text);\n const lines = text.split(\"\\n\");\n const height = lines.length;\n\n // Text fits within width, no wrapping needed\n if (textWidth <= width) {\n return { width: textWidth, height };\n }\n\n // Edge case: Yoga asking if we can fit in <1px\n if (textWidth >= 1 && width > 0 && width < 1) {\n return { width: textWidth, height };\n }\n\n // Wrap text if it exceeds width\n const wrappedText = wrapAnsi(text, Math.floor(width), {\n hard: true,\n trim: false,\n });\n const wrappedLines = wrappedText.split(\"\\n\");\n const wrappedWidth = Math.max(...wrappedLines.map((line) => stringWidth(line)));\n\n return { width: wrappedWidth, height: wrappedLines.length };\n}\n\n/**\n * Mark a node and its ancestors as dirty for relayout\n */\nexport function markNodeAsDirty(node: TerminalNode): void {\n if (node.yogaNode) {\n node.yogaNode.markDirty();\n return;\n }\n\n // Walk up to find a yoga node\n if (node.parent) {\n markNodeAsDirty(node.parent);\n }\n}\n\n/**\n * Get the parent node of a node\n */\nexport function getParent(node: TerminalNode): TerminalNode | null {\n return node.parent;\n}\n\n/**\n * Get the next sibling of a node\n */\nexport function getNextSibling(node: TerminalNode): TerminalNode | null {\n const parent = node.parent;\n if (!parent) return null;\n\n const index = parent.children.indexOf(node);\n if (index === -1 || index === parent.children.length - 1) {\n return null;\n }\n\n return parent.children[index + 1] || null;\n}\n","import chalk from \"chalk\";\nimport stringWidth from \"string-width\";\nimport sliceAnsi from \"slice-ansi\";\nimport type { TerminalElement, TerminalText } from \"../types\";\nimport { collectText } from \"../operations\";\nimport { getChalkColor } from \"../utils/colors\";\n\n/**\n * Render a text node\n */\nexport function renderTextNode(\n node: TerminalText,\n writeAt: (x: number, y: number, text: string) => void,\n terminalWidth: number,\n): void {\n const { content, x = 0, y = 0, width = 0 } = node;\n\n let text = content;\n const maxWidth = width || terminalWidth - x;\n\n // Truncate if needed\n if (stringWidth(text) > maxWidth) {\n text = sliceAnsi(text, 0, maxWidth);\n }\n\n // Write to buffer at position\n writeAt(x, y, text);\n}\n\n/**\n * Render a text element (collects and styles all text content)\n */\nexport function renderTextElement(\n node: TerminalElement,\n writeAt: (x: number, y: number, text: string) => void,\n): void {\n const { style, x = 0, y = 0 } = node;\n\n const text = collectText(node);\n if (!text) return;\n\n // Apply text styling\n let styledText = text;\n if (style.color) {\n styledText = getChalkColor(style.color)(styledText);\n }\n if (style.bold) {\n styledText = chalk.bold(styledText);\n }\n if (style.italic) {\n styledText = chalk.italic(styledText);\n }\n if (style.underline) {\n styledText = chalk.underline(styledText);\n }\n if (style.strikethrough) {\n styledText = chalk.strikethrough(styledText);\n }\n if (style.dim) {\n styledText = chalk.dim(styledText);\n }\n\n writeAt(x, y, styledText);\n}\n","import Yoga from \"yoga-layout-prebuilt\";\nimport ansiEscapes from \"ansi-escapes\";\nimport stringWidth from \"string-width\";\nimport sliceAnsi from \"slice-ansi\";\nimport type { TerminalNode, TerminalElement, TerminalText, TerminalRoot } from \"./types\";\nimport { renderBorder, renderBackground, renderTextNode, renderTextElement } from \"./rendering\";\n\n/**\n * Terminal renderer instance\n */\nexport class TerminalRenderer {\n private root: TerminalRoot;\n private buffer: string[] = [];\n private previousOutput: string = \"\";\n private lastOutputHeight: number = 0;\n private wasRawMode: boolean = false;\n\n constructor(stream: NodeJS.WriteStream = process.stdout) {\n this.root = {\n type: \"root\",\n stream,\n parent: null,\n children: [],\n yogaNode: Yoga.Node.create(),\n };\n\n // Set root dimensions to terminal size\n const { columns, rows } = stream;\n if (this.root.yogaNode) {\n this.root.yogaNode.setWidth(columns || 80);\n this.root.yogaNode.setHeight(rows || 24);\n // Set default flexbox properties to prevent children from stretching\n this.root.yogaNode.setFlexDirection(Yoga.FLEX_DIRECTION_COLUMN);\n this.root.yogaNode.setAlignItems(Yoga.ALIGN_FLEX_START);\n }\n\n // Enable raw mode to prevent ^C from being displayed\n // Save the previous state so we can restore it\n if (process.stdin.isTTY && process.stdin.setRawMode) {\n this.wasRawMode = process.stdin.isRaw || false;\n if (!this.wasRawMode) {\n process.stdin.setRawMode(true);\n }\n }\n\n // Hide cursor for cleaner rendering\n this.root.stream.write(ansiEscapes.cursorHide);\n }\n\n /**\n * Get the root node\n */\n getRoot(): TerminalRoot {\n return this.root;\n }\n\n /**\n * Render the tree to terminal\n */\n render(): void {\n // Calculate layout\n if (this.root.yogaNode) {\n this.root.yogaNode.calculateLayout(\n this.root.stream.columns || 80,\n this.root.stream.rows || 24,\n Yoga.DIRECTION_LTR,\n );\n }\n\n // Update positions\n this.updatePositions(this.root, 0, 0);\n\n // Render to buffer\n this.buffer = [];\n const height = this.root.stream.rows || 24;\n for (let i = 0; i < height; i++) {\n this.buffer[i] = \"\";\n }\n\n // Render children\n for (const child of this.root.children) {\n this.renderNode(child);\n }\n\n // Output to terminal\n this.output();\n }\n\n /**\n * Update positions of nodes based on yoga layout\n */\n private updatePositions(node: TerminalNode, parentX: number, parentY: number): void {\n if (node.yogaNode) {\n node.x = Math.round(parentX + node.yogaNode.getComputedLeft());\n node.y = Math.round(parentY + node.yogaNode.getComputedTop());\n node.width = Math.round(node.yogaNode.getComputedWidth());\n node.height = Math.round(node.yogaNode.getComputedHeight());\n\n // If this element has a border, add border size to width/height\n // and offset children by 1 to account for border thickness\n let childOffsetX = node.x || 0;\n let childOffsetY = node.y || 0;\n\n if (node.type === \"element\" && node.style.border && node.style.border !== \"none\") {\n // Expand width and height to include border (1 char on each side)\n node.width += 2;\n node.height += 2;\n // Offset children by 1 to leave room for border\n childOffsetX += 1;\n childOffsetY += 1;\n }\n\n for (const child of node.children) {\n this.updatePositions(child, childOffsetX, childOffsetY);\n }\n } else {\n // Text nodes don't have yoga nodes - inherit parent position\n node.x = parentX;\n node.y = parentY;\n\n for (const child of node.children) {\n this.updatePositions(child, parentX, parentY);\n }\n }\n }\n\n /**\n * Render a single node\n */\n private renderNode(node: TerminalNode): void {\n if (node.type === \"text\") {\n this.renderText(node);\n } else if (node.type === \"element\") {\n this.renderElement(node);\n }\n }\n\n /**\n * Render a text node\n */\n private renderText(node: TerminalText): void {\n const { y = 0, x = 0 } = node;\n\n if (y >= this.buffer.length || x < 0) return;\n\n renderTextNode(node, this.writeAt.bind(this), this.root.stream.columns || 80);\n }\n\n /**\n * Render an element node\n */\n private renderElement(node: TerminalElement): void {\n const { style, tagName } = node;\n\n // Render border if specified\n if (style.border && style.border !== \"none\") {\n renderBorder(node, this.writeAt.bind(this));\n }\n\n // Render background\n if (style.backgroundColor) {\n renderBackground(node, this.writeAt.bind(this));\n }\n\n // For text elements, collect and render all text content at once\n if (tagName === \"text\") {\n renderTextElement(node, this.writeAt.bind(this));\n } else {\n // For other elements, render children normally\n for (const child of node.children) {\n this.renderNode(child);\n }\n }\n }\n\n /**\n * Write text at a specific position in the buffer\n */\n private writeAt(x: number, y: number, text: string): void {\n if (y < 0 || y >= this.buffer.length) return;\n\n const row = this.buffer[y] || \"\";\n const width = stringWidth(text);\n const rowWidth = stringWidth(row);\n\n // Pad row if needed\n if (rowWidth < x) {\n this.buffer[y] = row + \" \".repeat(x - rowWidth) + text;\n } else {\n // Replace characters at position\n this.buffer[y] = sliceAnsi(row, 0, x) + text + sliceAnsi(row, x + width);\n }\n }\n\n /**\n * Output the buffer to terminal\n */\n private output(): void {\n // Remove trailing empty lines from buffer (only output actual content)\n let lastNonEmptyIndex = -1;\n for (let i = this.buffer.length - 1; i >= 0; i--) {\n const line = this.buffer[i];\n if (line && line.trim() !== \"\") {\n lastNonEmptyIndex = i;\n break;\n }\n }\n\n // Get only the lines with content\n const contentLines = lastNonEmptyIndex >= 0 ? this.buffer.slice(0, lastNonEmptyIndex + 1) : [];\n const output = contentLines.join(\"\\n\");\n\n // Only update if changed\n if (output !== this.previousOutput) {\n // Erase previous output if there was any\n // eraseLines moves cursor up and erases, so we're ready to write at the start position\n if (this.lastOutputHeight > 0) {\n this.root.stream.write(ansiEscapes.eraseLines(this.lastOutputHeight));\n }\n\n // Write new output (cursor is already at the right position after eraseLines)\n this.root.stream.write(output);\n\n // Calculate and store output height (number of actual lines rendered)\n this.lastOutputHeight = contentLines.length;\n this.previousOutput = output;\n }\n }\n\n /**\n * Clear the rendered output\n */\n clear(): void {\n if (this.lastOutputHeight > 0) {\n this.root.stream.write(ansiEscapes.eraseLines(this.lastOutputHeight));\n this.lastOutputHeight = 0;\n }\n this.previousOutput = \"\";\n }\n\n /**\n * Cleanup\n */\n destroy(): void {\n // Final render to ensure latest state is shown\n this.render();\n\n // Move cursor to line after output\n this.root.stream.write(\"\\n\");\n\n // Show cursor again on cleanup\n this.root.stream.write(ansiEscapes.cursorShow);\n\n // Restore raw mode to previous state\n if (process.stdin.isTTY && process.stdin.setRawMode && !this.wasRawMode) {\n process.stdin.setRawMode(false);\n }\n\n // Free yoga layout\n if (this.root.yogaNode) {\n this.root.yogaNode.freeRecursive();\n }\n }\n}\n","import type { Signal } from \"@semajsx/signal\";\nimport type { TerminalNode, TerminalStyle } from \"./types\";\nimport { applyStyle } from \"./operations\";\n\n/**\n * Set a property on a terminal node\n */\nexport function setProperty(node: TerminalNode, key: string, value: unknown): void {\n if (node.type !== \"element\") return;\n\n // Handle style properties\n if (isStyleProperty(key)) {\n const styleUpdate: Partial<TerminalStyle> = { [key]: value };\n applyStyle(node, styleUpdate);\n return;\n }\n\n // Store other props\n node.props[key] = value;\n}\n\n/**\n * Set a signal property on a terminal node\n */\nexport function setSignalProperty<T = unknown>(\n node: TerminalNode,\n key: string,\n signal: Signal<T>,\n): () => void {\n // Set initial value\n setProperty(node, key, signal.value);\n\n // Subscribe to changes\n return signal.subscribe((value: T) => {\n setProperty(node, key, value);\n });\n}\n\n/**\n * Check if a property is a style property\n */\nfunction isStyleProperty(key: string): boolean {\n const styleProps = new Set([\n \"flexDirection\",\n \"justifyContent\",\n \"alignItems\",\n \"flexGrow\",\n \"flexShrink\",\n \"flexBasis\",\n \"width\",\n \"height\",\n \"minWidth\",\n \"minHeight\",\n \"maxWidth\",\n \"maxHeight\",\n \"margin\",\n \"marginLeft\",\n \"marginRight\",\n \"marginTop\",\n \"marginBottom\",\n \"marginInline\",\n \"marginBlock\",\n \"padding\",\n \"paddingLeft\",\n \"paddingRight\",\n \"paddingTop\",\n \"paddingBottom\",\n \"paddingInline\",\n \"paddingBlock\",\n \"border\",\n \"borderColor\",\n \"color\",\n \"backgroundColor\",\n \"bold\",\n \"italic\",\n \"underline\",\n \"strikethrough\",\n \"dim\",\n ]);\n\n return styleProps.has(key);\n}\n","/** @jsxImportSource @semajsx/terminal */\nimport { computed, signal, type WritableSignal } from \"@semajsx/signal\";\nimport { when, type JSXNode } from \"@semajsx/core\";\n\n/**\n * Global exiting signal for terminal rendering\n * Set to true during unmount to hide exit hints in final render\n */\nconst globalExitingSignal = signal(false);\n\n/**\n * Get the global exiting signal\n * Used internally by render() to coordinate with ExitHint component\n */\nexport function getExitingSignal(): WritableSignal<boolean> {\n return globalExitingSignal;\n}\n\n/**\n * Reset the exiting signal (useful for testing or multiple render cycles)\n */\nexport function resetExitingSignal(): void {\n globalExitingSignal.value = false;\n}\n\nexport interface ExitHintProps {\n /**\n * Content to show during normal rendering, hidden during exit\n * After normalization: single VNode, array of VNodes, or undefined\n */\n children?: JSXNode;\n}\n\n/**\n * ExitHint component - hides its children during the final render before exit\n *\n * This is useful for hiding \"Press Ctrl+C to exit\" messages in the final\n * terminal output, keeping only the actual content visible.\n *\n * The component automatically detects when unmount() is called and reactively\n * hides its children during the final render using signal-based reactivity.\n *\n * @example\n * ```tsx\n * render(\n * <box flexDirection=\"column\" padding={1}>\n * <text bold>Counter: {count}</text>\n *\n * <ExitHint>\n * <text dim marginTop={1} color=\"yellow\">\n * Press Ctrl+C or ESC to exit\n * </text>\n * </ExitHint>\n * </box>\n * );\n * ```\n *\n * Result after exit:\n * - The counter remains visible\n * - The exit hint is hidden from final output\n */\nexport function ExitHint({ children }: ExitHintProps): JSXNode {\n // Create inverted signal: show when NOT exiting\n const shouldShow = computed(globalExitingSignal, (isExiting) => !isExiting);\n\n // Return signal directly - renderComponent now handles Signal<VNode>\n return when(shouldShow, children);\n}\n","import type { VNode } from \"@semajsx/core\";\nimport { setProperty, setSignalProperty } from \"./properties\";\nimport {\n appendChild,\n createElement,\n createTextNode,\n createComment,\n removeChild,\n replaceNode,\n insertBefore,\n getParent,\n getNextSibling,\n} from \"./operations\";\nimport { TerminalRenderer } from \"./renderer\";\nimport type { TerminalNode } from \"./types\";\nimport { getExitingSignal, resetExitingSignal } from \"./components/ExitHint\";\nimport { type ContextMap } from \"@semajsx/core\";\nimport { createRenderer, type RenderStrategy } from \"@semajsx/core\";\n\n/**\n * Terminal-specific render strategy (no reuse optimization needed)\n */\nconst terminalStrategy: RenderStrategy<TerminalNode> = {\n createTextNode,\n createComment,\n createElement,\n getParent,\n getNextSibling,\n insertBefore,\n appendChild,\n removeChild,\n replaceNode,\n setProperty,\n setSignalProperty,\n // Terminal doesn't need tryReuseNode optimization\n};\n\n// Create terminal renderer\nconst { renderNode, cleanupSubscriptions } = createRenderer(terminalStrategy);\n\n/**\n * Options for terminal rendering\n */\nexport interface RenderOptions {\n /**\n * Custom renderer instance. If not provided, one will be created automatically.\n */\n renderer?: TerminalRenderer;\n /**\n * Whether to automatically re-render on signal changes.\n * @default true\n */\n autoRender?: boolean;\n /**\n * Target frames per second for auto-rendering.\n * @default 60\n */\n fps?: number;\n /**\n * Output stream to render to. Only used if renderer is not provided.\n * @default process.stdout\n */\n stream?: NodeJS.WriteStream;\n}\n\n/**\n * Return type for render function\n */\nexport interface RenderResult {\n /**\n * Re-render the tree (useful for manual updates)\n */\n rerender: () => void;\n /**\n * Unmount and cleanup\n */\n unmount: () => void;\n /**\n * Wait for all pending async operations\n */\n waitUntilExit: () => Promise<void>;\n}\n\n/**\n * Options for print function\n */\nexport interface PrintOptions {\n /**\n * Output stream to print to.\n * @default process.stdout\n */\n stream?: NodeJS.WriteStream;\n}\n\n/**\n * Render a VNode tree to the terminal\n * Supports sync VNodes, async VNodes (Promise), and streaming VNodes (AsyncIterableIterator)\n *\n * @example\n * // Simple usage (ink-style)\n * const { unmount } = render(<App />);\n *\n * @example\n * // With custom stream\n * render(<App />, { stream: process.stderr });\n *\n * @example\n * // Disable auto-rendering\n * const { rerender } = render(<App />, { autoRender: false });\n * setInterval(rerender, 100);\n *\n * @example\n * // With custom renderer\n * const renderer = new TerminalRenderer(process.stderr);\n * render(<App />, { renderer });\n *\n * @example\n * // Custom FPS\n * render(<App />, { fps: 30 });\n */\nexport function render(element: VNode, options: RenderOptions = {}): RenderResult {\n const { renderer, autoRender = true, fps = 60, stream: outputStream = process.stdout } = options;\n\n // Reset exiting signal for new render\n resetExitingSignal();\n\n // Auto-create renderer if not provided (ink-style API)\n const autoCreated = !renderer;\n const actualRenderer = renderer || new TerminalRenderer(outputStream);\n\n const root = actualRenderer.getRoot();\n\n // Initialize empty context map for root render\n const initialContext: ContextMap = new Map();\n\n const rendered = renderNode(element, initialContext);\n\n if (rendered.node) {\n appendChild(root, rendered.node);\n } else if (rendered.children.length > 0) {\n // Fragment case - append all fragment children\n for (const child of rendered.children) {\n if (child.node) {\n appendChild(root, child.node);\n }\n }\n }\n\n // Initial render\n actualRenderer.render();\n\n // Rendering lock to prevent overlapping renders (race condition fix)\n let isRendering = false;\n const safeRender = () => {\n if (isRendering) return;\n isRendering = true;\n try {\n actualRenderer.render();\n } finally {\n isRendering = false;\n }\n };\n\n // Auto re-render on signal changes (like ink)\n let renderInterval: NodeJS.Timeout | null = null;\n if (autoRender) {\n const interval = Math.floor(1000 / fps);\n renderInterval = setInterval(() => {\n safeRender();\n }, interval);\n }\n\n // Promise that resolves on exit\n let exitResolver: (() => void) | null = null;\n const exitPromise = new Promise<void>((resolve) => {\n exitResolver = resolve;\n });\n\n // Track original terminal state for cleanup\n const originalRawMode = process.stdin.isTTY && process.stdin.isRaw;\n let handleExit: (() => void) | null = null;\n let handleKeypress: ((data: Buffer) => void) | null = null;\n\n // Cleanup function to restore terminal state\n const cleanup = () => {\n // Stop auto-rendering\n if (renderInterval) {\n clearInterval(renderInterval);\n renderInterval = null;\n }\n\n // Remove event listeners\n if (handleExit) {\n process.removeListener(\"SIGINT\", handleExit);\n process.removeListener(\"SIGTERM\", handleExit);\n }\n if (handleKeypress) {\n process.stdin.removeListener(\"data\", handleKeypress);\n }\n\n // Restore original terminal state\n if (process.stdin.isTTY && process.stdin.setRawMode) {\n try {\n process.stdin.setRawMode(originalRawMode || false);\n } catch {\n // Terminal may already be closed, ignore error\n }\n }\n\n // Clean up subscriptions only (preserve output on exit)\n cleanupSubscriptions(rendered);\n actualRenderer.destroy();\n\n if (exitResolver) {\n exitResolver();\n }\n };\n\n // Unmount function\n const unmount = () => {\n // Mark as exiting to hide ExitHint components\n getExitingSignal().value = true;\n\n // Trigger one final render to apply ExitHint changes\n // This removes exit prompts from the final output\n actualRenderer.render();\n\n cleanup();\n };\n\n // Handle Ctrl+C if auto-created\n if (autoCreated) {\n handleExit = () => {\n unmount();\n process.exit(0);\n };\n\n // Install signal handlers with error recovery\n try {\n process.on(\"SIGINT\", handleExit);\n process.on(\"SIGTERM\", handleExit);\n\n // Enable stdin for keyboard input\n if (process.stdin.isTTY) {\n process.stdin.setRawMode(true);\n process.stdin.resume();\n\n handleKeypress = (data: Buffer) => {\n const key = data.toString();\n // Ctrl+C or ESC to exit\n if (key === \"\\u0003\" || key === \"\\u001b\") {\n if (handleExit) {\n handleExit();\n }\n }\n };\n\n process.stdin.on(\"data\", handleKeypress);\n }\n } catch (err) {\n // If setup fails, clean up and rethrow\n cleanup();\n throw err;\n }\n }\n\n return {\n rerender: safeRender,\n unmount,\n waitUntilExit: () => exitPromise,\n };\n}\n\n/**\n * Print a VNode tree to the terminal once (no auto-rendering).\n * Supports sync VNodes, async VNodes (Promise), and streaming VNodes (AsyncIterableIterator)\n *\n * This is a convenience function for one-time rendering scenarios like:\n * - Server startup messages\n * - CLI output\n * - Static terminal displays\n *\n * Unlike `render()`, this function:\n * - Does not subscribe to signal changes\n * - Does not auto-render on updates\n * - Immediately outputs and cleans up\n * - Does not capture keyboard input\n *\n * @example\n * // Simple server output\n * print(\n * <box border=\"round\" borderColor=\"green\" padding={1}>\n * <text bold color=\"green\">Server started!</text>\n * <text>URL: http://localhost:3000</text>\n * </box>\n * );\n *\n * @example\n * // Print to stderr\n * print(<text color=\"red\">Error occurred</text>, { stream: process.stderr });\n *\n * @example\n * // Print a blank line\n * print();\n */\nexport function print(element?: VNode, options: PrintOptions = {}): void {\n const { stream: outputStream = process.stdout } = options;\n\n // If no element provided, just print a blank line\n if (element === undefined) {\n outputStream.write(\"\\n\");\n return;\n }\n\n // Save raw mode state\n const wasRawMode = process.stdin.isTTY && process.stdin.isRaw;\n\n // Create renderer\n const renderer = new TerminalRenderer(outputStream);\n const root = renderer.getRoot();\n\n // Initialize empty context map for root render\n const initialContext: ContextMap = new Map();\n\n // Render the element\n const rendered = renderNode(element, initialContext);\n\n if (rendered.node) {\n appendChild(root, rendered.node);\n } else if (rendered.children.length > 0) {\n // Fragment case - append all fragment children\n for (const child of rendered.children) {\n if (child.node) {\n appendChild(root, child.node);\n }\n }\n }\n\n // Render once\n renderer.render();\n\n // Clean up subscriptions only (don't remove nodes from tree)\n // This keeps the output visible after destroy\n cleanupSubscriptions(rendered);\n\n // Destroy renderer (outputs final result and shows cursor)\n renderer.destroy();\n\n // Restore raw mode if it was enabled\n if (process.stdin.isTTY && process.stdin.setRawMode && wasRawMode) {\n process.stdin.setRawMode(true);\n }\n}\n","/** @jsxImportSource @semajsx/terminal */\nimport type { JSXNode } from \"@semajsx/core\";\n\nexport interface BlankLineProps {\n /**\n * Number of blank lines to render\n * @default 1\n */\n count?: number;\n}\n\n/**\n * BlankLine component - renders one or more empty lines\n *\n * Useful for adding vertical spacing between terminal UI elements.\n *\n * @example\n * ```tsx\n * <box flexDirection=\"column\">\n * <text>First line</text>\n * <BlankLine />\n * <text>After one blank line</text>\n * <BlankLine count={2} />\n * <text>After two blank lines</text>\n * </box>\n * ```\n */\nexport function BlankLine({ count = 1 }: BlankLineProps): JSXNode {\n const lines = Array.from({ length: count }, (_, i) => <text key={i}> </text>);\n\n return <>{lines}</>;\n}\n"],"mappings":";;;;;;;;;;;;;;;AAKA,SAAgB,cAAc,WAAkC;AAqB9D,QApB8C;EAC5C,OAAO,MAAM;EACb,KAAK,MAAM;EACX,OAAO,MAAM;EACb,QAAQ,MAAM;EACd,MAAM,MAAM;EACZ,SAAS,MAAM;EACf,MAAM,MAAM;EACZ,OAAO,MAAM;EACb,MAAM,MAAM;EACZ,MAAM,MAAM;EACZ,aAAa,MAAM;EACnB,WAAW,MAAM;EACjB,aAAa,MAAM;EACnB,cAAc,MAAM;EACpB,YAAY,MAAM;EAClB,eAAe,MAAM;EACrB,YAAY,MAAM;EAClB,aAAa,MAAM;EACpB,CACa,cAAc;;;;;AAM9B,SAAgB,gBAAgB,WAAkC;AAqBhE,QApBgD;EAC9C,OAAO,MAAM;EACb,KAAK,MAAM;EACX,OAAO,MAAM;EACb,QAAQ,MAAM;EACd,MAAM,MAAM;EACZ,SAAS,MAAM;EACf,MAAM,MAAM;EACZ,OAAO,MAAM;EACb,MAAM,MAAM;EACZ,MAAM,MAAM;EACZ,aAAa,MAAM;EACnB,WAAW,MAAM;EACjB,aAAa,MAAM;EACnB,cAAc,MAAM;EACpB,YAAY,MAAM;EAClB,eAAe,MAAM;EACrB,YAAY,MAAM;EAClB,aAAa,MAAM;EACpB,CACe,cAAc;;;;;;;;AC7ChC,SAAgB,aACd,MACA,SACM;CACN,MAAM,EAAE,OAAO,IAAI,GAAG,IAAI,GAAG,QAAQ,GAAG,SAAS,MAAM;CACvD,MAAM,WAAW,MAAM,UAAU;AAEjC,KAAI,aAAa,OAAQ;CAEzB,MAAM,MAAM,SAAS,aAAa,SAAS;CAC3C,IAAI,aAAa;AAEjB,KAAI,MAAM,YACR,cAAa,cAAc,MAAM,YAAY;AAK/C,SAAQ,GAAG,GADK,WAAW,IAAI,UAAU,IAAI,IAAI,OAAO,KAAK,IAAI,GAAG,QAAQ,EAAE,CAAC,GAAG,IAAI,SAAS,CACzE;AAGtB,MAAK,IAAI,IAAI,GAAG,IAAI,SAAS,GAAG,KAAK;EAEnC,MAAM,eAAe,IAAI,OAAO,KAAK,IAAI,GAAG,QAAQ,EAAE,CAAC;EACvD,MAAM,WAAW,WAAW,IAAI,KAAK,GAAG,eAAe,WAAW,IAAI,MAAM;AAC5E,UAAQ,GAAG,IAAI,GAAG,SAAS;;AAI7B,KAAI,SAAS,GAAG;EACd,MAAM,aAAa,WACjB,IAAI,aAAa,IAAI,OAAO,OAAO,KAAK,IAAI,GAAG,QAAQ,EAAE,CAAC,GAAG,IAAI,YAClE;AACD,UAAQ,GAAG,IAAI,SAAS,GAAG,WAAW;;;;;;AAO1C,SAAgB,iBACd,MACA,SACM;CACN,MAAM,EAAE,OAAO,IAAI,GAAG,IAAI,GAAG,QAAQ,GAAG,SAAS,MAAM;AAEvD,KAAI,CAAC,MAAM,gBAAiB;CAE5B,MAAM,KAAK,gBAAgB,MAAM,gBAAgB;AAEjD,MAAK,IAAI,IAAI,GAAG,IAAI,QAAQ,KAAK;EAC/B,MAAM,OAAO,GAAG,IAAI,OAAO,MAAM,CAAC;AAClC,UAAQ,GAAG,IAAI,GAAG,KAAK;;;;;;;;;ACpD3B,SAAgB,cAAc,SAAkC;CAC9D,MAAM,WAAW,KAAK,KAAK,QAAQ;CAEnC,MAAM,UAA2B;EAC/B,MAAM;EACN;EACA,OAAO,EAAE;EACT,OAAO,EAAE;EACT;EACA,QAAQ;EACR,UAAU,EAAE;EACb;AAID,KAAI,YAAY,OACd,UAAS,eAAe,gBAAgB,KAAK,MAAM,QAAQ,CAAC;AAG9D,QAAO;;;;;;AAOT,SAAgB,eAAe,MAA4B;AACzD,QAAO;EACL,MAAM;EACN,SAAS;EACT,UAAU;EACV,QAAQ;EACR,UAAU,EAAE;EACb;;;;;AAMH,SAAgB,cAAc,OAA6B;AACzD,QAAO,eAAe,GAAG;;;;;AAM3B,SAAgB,YAAY,QAAsB,OAA2B;AAC3E,KAAI,MAAM,OACR,aAAY,MAAM;AAGpB,OAAM,SAAS;AACf,QAAO,SAAS,KAAK,MAAM;AAE3B,KAAI,OAAO,YAAY,MAAM,SAC3B,QAAO,SAAS,YAAY,MAAM,UAAU,OAAO,SAAS,eAAe,CAAC;;;;;AAOhF,SAAgB,YAAY,MAA0B;AACpD,KAAI,CAAC,KAAK,OAAQ;CAElB,MAAM,SAAS,KAAK;CACpB,MAAM,QAAQ,OAAO,SAAS,QAAQ,KAAK;AAE3C,KAAI,UAAU,IAAI;AAChB,SAAO,SAAS,OAAO,OAAO,EAAE;AAEhC,MAAI,OAAO,YAAY,KAAK,SAC1B,QAAO,SAAS,YAAY,KAAK,SAAS;;AAI9C,MAAK,SAAS;;;;;AAMhB,SAAgB,aACd,QACA,SACA,SACM;AACN,KAAI,QAAQ,OACV,aAAY,QAAQ;AAGtB,SAAQ,SAAS;AAEjB,KAAI,CAAC,SAAS;AACZ,cAAY,QAAQ,QAAQ;AAC5B;;CAGF,MAAM,QAAQ,OAAO,SAAS,QAAQ,QAAQ;AAC9C,KAAI,UAAU,IAAI;AAChB,SAAO,SAAS,OAAO,OAAO,GAAG,QAAQ;AAEzC,MAAI,OAAO,YAAY,QAAQ,SAC7B,QAAO,SAAS,YAAY,QAAQ,UAAU,MAAM;;;;;;AAQ1D,SAAgB,YAAY,SAAuB,SAA6B;CAC9E,MAAM,SAAS,QAAQ;AACvB,KAAI,CAAC,OAAQ;AAEb,cAAa,QAAQ,SAAS,QAAQ;AACtC,aAAY,QAAQ;;;;;AAMtB,SAAgB,QAAQ,MAAoB,MAAoB;AAC9D,KAAI,KAAK,SAAS,QAAQ;AACxB,MAAI,KAAK,YAAY,KACnB;AAGF,OAAK,UAAU;AAGf,MAAI,KAAK,OACP,iBAAgB,KAAK,OAAO;;;;;;AAQlC,SAAgB,WAAW,SAA0B,OAAqC;CACxF,MAAM,EAAE,aAAa;AACrB,KAAI,CAAC,SAAU;AAEf,SAAQ,QAAQ;EAAE,GAAG,QAAQ;EAAO,GAAG;EAAO;AAG9C,KAAI,MAAM,eAAe;EACvB,MAAM,YAAY;GAChB,KAAK,KAAK;GACV,QAAQ,KAAK;GACb,eAAe,KAAK;GACpB,kBAAkB,KAAK;GACxB,CAAC,MAAM;AACR,WAAS,iBAAiB,UAAU;;AAGtC,KAAI,MAAM,gBAAgB;EACxB,MAAM,UAAU;GACd,cAAc,KAAK;GACnB,QAAQ,KAAK;GACb,YAAY,KAAK;GACjB,iBAAiB,KAAK;GACtB,gBAAgB,KAAK;GACtB,CAAC,MAAM;AACR,WAAS,kBAAkB,QAAQ;;AAGrC,KAAI,MAAM,YAAY;EACpB,MAAM,QAAQ;GACZ,cAAc,KAAK;GACnB,QAAQ,KAAK;GACb,YAAY,KAAK;GACjB,SAAS,KAAK;GACf,CAAC,MAAM;AACR,WAAS,cAAc,MAAM;;AAI/B,KAAI,MAAM,aAAa,OACrB,UAAS,YAAY,MAAM,SAAS;AAEtC,KAAI,MAAM,eAAe,OACvB,UAAS,cAAc,MAAM,WAAW;AAI1C,KAAI,MAAM,UAAU,QAClB;MAAI,OAAO,MAAM,UAAU,SACzB,UAAS,SAAS,MAAM,MAAM;WACrB,MAAM,UAAU,OACzB,UAAS,cAAc;WACd,MAAM,MAAM,SAAS,IAAI,CAClC,UAAS,gBAAgB,WAAW,MAAM,MAAM,CAAC;;AAIrD,KAAI,MAAM,WAAW,QACnB;MAAI,OAAO,MAAM,WAAW,SAC1B,UAAS,UAAU,MAAM,OAAO;WACvB,MAAM,WAAW,OAC1B,UAAS,eAAe;WACf,MAAM,OAAO,SAAS,IAAI,CACnC,UAAS,iBAAiB,WAAW,MAAM,OAAO,CAAC;;AAKvD,KAAI,MAAM,aAAa,OAAW,UAAS,YAAY,MAAM,SAAS;AACtE,KAAI,MAAM,cAAc,OAAW,UAAS,aAAa,MAAM,UAAU;AACzE,KAAI,MAAM,aAAa,OAAW,UAAS,YAAY,MAAM,SAAS;AACtE,KAAI,MAAM,cAAc,OAAW,UAAS,aAAa,MAAM,UAAU;AAGzE,KAAI,MAAM,WAAW,OACnB,UAAS,UAAU,KAAK,UAAU,MAAM,OAAO;AAGjD,KAAI,MAAM,iBAAiB,QAAW;AACpC,WAAS,UAAU,KAAK,WAAW,MAAM,aAAa;AACtD,WAAS,UAAU,KAAK,YAAY,MAAM,aAAa;;AAEzD,KAAI,MAAM,gBAAgB,QAAW;AACnC,WAAS,UAAU,KAAK,UAAU,MAAM,YAAY;AACpD,WAAS,UAAU,KAAK,aAAa,MAAM,YAAY;;AAGzD,KAAI,MAAM,eAAe,OACvB,UAAS,UAAU,KAAK,WAAW,MAAM,WAAW;AAEtD,KAAI,MAAM,gBAAgB,OACxB,UAAS,UAAU,KAAK,YAAY,MAAM,YAAY;AAExD,KAAI,MAAM,cAAc,OACtB,UAAS,UAAU,KAAK,UAAU,MAAM,UAAU;AAEpD,KAAI,MAAM,iBAAiB,OACzB,UAAS,UAAU,KAAK,aAAa,MAAM,aAAa;AAI1D,KAAI,MAAM,YAAY,OACpB,UAAS,WAAW,KAAK,UAAU,MAAM,QAAQ;AAGnD,KAAI,MAAM,kBAAkB,QAAW;AACrC,WAAS,WAAW,KAAK,WAAW,MAAM,cAAc;AACxD,WAAS,WAAW,KAAK,YAAY,MAAM,cAAc;;AAE3D,KAAI,MAAM,iBAAiB,QAAW;AACpC,WAAS,WAAW,KAAK,UAAU,MAAM,aAAa;AACtD,WAAS,WAAW,KAAK,aAAa,MAAM,aAAa;;AAG3D,KAAI,MAAM,gBAAgB,OACxB,UAAS,WAAW,KAAK,WAAW,MAAM,YAAY;AAExD,KAAI,MAAM,iBAAiB,OACzB,UAAS,WAAW,KAAK,YAAY,MAAM,aAAa;AAE1D,KAAI,MAAM,eAAe,OACvB,UAAS,WAAW,KAAK,UAAU,MAAM,WAAW;AAEtD,KAAI,MAAM,kBAAkB,OAC1B,UAAS,WAAW,KAAK,aAAa,MAAM,cAAc;;;;;;AAQ9D,SAAgB,YAAY,MAA4B;AACtD,KAAI,KAAK,SAAS,OAChB,QAAO,KAAK;CAGd,IAAI,OAAO;AACX,MAAK,MAAM,SAAS,KAAK,SACvB,SAAQ,YAAY,MAAM;AAG5B,QAAO;;;;;;AAOT,SAAS,gBAAgB,MAAuB,OAAkD;CAEhG,MAAM,OAAO,YAAY,KAAK;AAE9B,KAAI,KAAK,WAAW,EAClB,QAAO;EAAE,OAAO;EAAG,QAAQ;EAAG;CAGhC,MAAM,YAAY,YAAY,KAAK;CAEnC,MAAM,SADQ,KAAK,MAAM,KAAK,CACT;AAGrB,KAAI,aAAa,MACf,QAAO;EAAE,OAAO;EAAW;EAAQ;AAIrC,KAAI,aAAa,KAAK,QAAQ,KAAK,QAAQ,EACzC,QAAO;EAAE,OAAO;EAAW;EAAQ;CAQrC,MAAM,eAJc,SAAS,MAAM,KAAK,MAAM,MAAM,EAAE;EACpD,MAAM;EACN,MAAM;EACP,CAAC,CAC+B,MAAM,KAAK;AAG5C,QAAO;EAAE,OAFY,KAAK,IAAI,GAAG,aAAa,KAAK,SAAS,YAAY,KAAK,CAAC,CAAC;EAEjD,QAAQ,aAAa;EAAQ;;;;;AAM7D,SAAgB,gBAAgB,MAA0B;AACxD,KAAI,KAAK,UAAU;AACjB,OAAK,SAAS,WAAW;AACzB;;AAIF,KAAI,KAAK,OACP,iBAAgB,KAAK,OAAO;;;;;AAOhC,SAAgB,UAAU,MAAyC;AACjE,QAAO,KAAK;;;;;AAMd,SAAgB,eAAe,MAAyC;CACtE,MAAM,SAAS,KAAK;AACpB,KAAI,CAAC,OAAQ,QAAO;CAEpB,MAAM,QAAQ,OAAO,SAAS,QAAQ,KAAK;AAC3C,KAAI,UAAU,MAAM,UAAU,OAAO,SAAS,SAAS,EACrD,QAAO;AAGT,QAAO,OAAO,SAAS,QAAQ,MAAM;;;;;;;;AClWvC,SAAgB,eACd,MACA,SACA,eACM;CACN,MAAM,EAAE,SAAS,IAAI,GAAG,IAAI,GAAG,QAAQ,MAAM;CAE7C,IAAI,OAAO;CACX,MAAM,WAAW,SAAS,gBAAgB;AAG1C,KAAI,YAAY,KAAK,GAAG,SACtB,QAAO,UAAU,MAAM,GAAG,SAAS;AAIrC,SAAQ,GAAG,GAAG,KAAK;;;;;AAMrB,SAAgB,kBACd,MACA,SACM;CACN,MAAM,EAAE,OAAO,IAAI,GAAG,IAAI,MAAM;CAEhC,MAAM,OAAO,YAAY,KAAK;AAC9B,KAAI,CAAC,KAAM;CAGX,IAAI,aAAa;AACjB,KAAI,MAAM,MACR,cAAa,cAAc,MAAM,MAAM,CAAC,WAAW;AAErD,KAAI,MAAM,KACR,cAAa,MAAM,KAAK,WAAW;AAErC,KAAI,MAAM,OACR,cAAa,MAAM,OAAO,WAAW;AAEvC,KAAI,MAAM,UACR,cAAa,MAAM,UAAU,WAAW;AAE1C,KAAI,MAAM,cACR,cAAa,MAAM,cAAc,WAAW;AAE9C,KAAI,MAAM,IACR,cAAa,MAAM,IAAI,WAAW;AAGpC,SAAQ,GAAG,GAAG,WAAW;;;;;;;;ACpD3B,IAAa,mBAAb,MAA8B;CAO5B,YAAY,SAA6B,QAAQ,QAAQ;gBAL9B,EAAE;wBACI;0BACE;oBACL;AAG5B,OAAK,OAAO;GACV,MAAM;GACN;GACA,QAAQ;GACR,UAAU,EAAE;GACZ,UAAU,KAAK,KAAK,QAAQ;GAC7B;EAGD,MAAM,EAAE,SAAS,SAAS;AAC1B,MAAI,KAAK,KAAK,UAAU;AACtB,QAAK,KAAK,SAAS,SAAS,WAAW,GAAG;AAC1C,QAAK,KAAK,SAAS,UAAU,QAAQ,GAAG;AAExC,QAAK,KAAK,SAAS,iBAAiB,KAAK,sBAAsB;AAC/D,QAAK,KAAK,SAAS,cAAc,KAAK,iBAAiB;;AAKzD,MAAI,QAAQ,MAAM,SAAS,QAAQ,MAAM,YAAY;AACnD,QAAK,aAAa,QAAQ,MAAM,SAAS;AACzC,OAAI,CAAC,KAAK,WACR,SAAQ,MAAM,WAAW,KAAK;;AAKlC,OAAK,KAAK,OAAO,MAAM,YAAY,WAAW;;;;;CAMhD,UAAwB;AACtB,SAAO,KAAK;;;;;CAMd,SAAe;AAEb,MAAI,KAAK,KAAK,SACZ,MAAK,KAAK,SAAS,gBACjB,KAAK,KAAK,OAAO,WAAW,IAC5B,KAAK,KAAK,OAAO,QAAQ,IACzB,KAAK,cACN;AAIH,OAAK,gBAAgB,KAAK,MAAM,GAAG,EAAE;AAGrC,OAAK,SAAS,EAAE;EAChB,MAAM,SAAS,KAAK,KAAK,OAAO,QAAQ;AACxC,OAAK,IAAI,IAAI,GAAG,IAAI,QAAQ,IAC1B,MAAK,OAAO,KAAK;AAInB,OAAK,MAAM,SAAS,KAAK,KAAK,SAC5B,MAAK,WAAW,MAAM;AAIxB,OAAK,QAAQ;;;;;CAMf,AAAQ,gBAAgB,MAAoB,SAAiB,SAAuB;AAClF,MAAI,KAAK,UAAU;AACjB,QAAK,IAAI,KAAK,MAAM,UAAU,KAAK,SAAS,iBAAiB,CAAC;AAC9D,QAAK,IAAI,KAAK,MAAM,UAAU,KAAK,SAAS,gBAAgB,CAAC;AAC7D,QAAK,QAAQ,KAAK,MAAM,KAAK,SAAS,kBAAkB,CAAC;AACzD,QAAK,SAAS,KAAK,MAAM,KAAK,SAAS,mBAAmB,CAAC;GAI3D,IAAI,eAAe,KAAK,KAAK;GAC7B,IAAI,eAAe,KAAK,KAAK;AAE7B,OAAI,KAAK,SAAS,aAAa,KAAK,MAAM,UAAU,KAAK,MAAM,WAAW,QAAQ;AAEhF,SAAK,SAAS;AACd,SAAK,UAAU;AAEf,oBAAgB;AAChB,oBAAgB;;AAGlB,QAAK,MAAM,SAAS,KAAK,SACvB,MAAK,gBAAgB,OAAO,cAAc,aAAa;SAEpD;AAEL,QAAK,IAAI;AACT,QAAK,IAAI;AAET,QAAK,MAAM,SAAS,KAAK,SACvB,MAAK,gBAAgB,OAAO,SAAS,QAAQ;;;;;;CAQnD,AAAQ,WAAW,MAA0B;AAC3C,MAAI,KAAK,SAAS,OAChB,MAAK,WAAW,KAAK;WACZ,KAAK,SAAS,UACvB,MAAK,cAAc,KAAK;;;;;CAO5B,AAAQ,WAAW,MAA0B;EAC3C,MAAM,EAAE,IAAI,GAAG,IAAI,MAAM;AAEzB,MAAI,KAAK,KAAK,OAAO,UAAU,IAAI,EAAG;AAEtC,iBAAe,MAAM,KAAK,QAAQ,KAAK,KAAK,EAAE,KAAK,KAAK,OAAO,WAAW,GAAG;;;;;CAM/E,AAAQ,cAAc,MAA6B;EACjD,MAAM,EAAE,OAAO,YAAY;AAG3B,MAAI,MAAM,UAAU,MAAM,WAAW,OACnC,cAAa,MAAM,KAAK,QAAQ,KAAK,KAAK,CAAC;AAI7C,MAAI,MAAM,gBACR,kBAAiB,MAAM,KAAK,QAAQ,KAAK,KAAK,CAAC;AAIjD,MAAI,YAAY,OACd,mBAAkB,MAAM,KAAK,QAAQ,KAAK,KAAK,CAAC;MAGhD,MAAK,MAAM,SAAS,KAAK,SACvB,MAAK,WAAW,MAAM;;;;;CAQ5B,AAAQ,QAAQ,GAAW,GAAW,MAAoB;AACxD,MAAI,IAAI,KAAK,KAAK,KAAK,OAAO,OAAQ;EAEtC,MAAM,MAAM,KAAK,OAAO,MAAM;EAC9B,MAAM,QAAQ,YAAY,KAAK;EAC/B,MAAM,WAAW,YAAY,IAAI;AAGjC,MAAI,WAAW,EACb,MAAK,OAAO,KAAK,MAAM,IAAI,OAAO,IAAI,SAAS,GAAG;MAGlD,MAAK,OAAO,KAAK,UAAU,KAAK,GAAG,EAAE,GAAG,OAAO,UAAU,KAAK,IAAI,MAAM;;;;;CAO5E,AAAQ,SAAe;EAErB,IAAI,oBAAoB;AACxB,OAAK,IAAI,IAAI,KAAK,OAAO,SAAS,GAAG,KAAK,GAAG,KAAK;GAChD,MAAM,OAAO,KAAK,OAAO;AACzB,OAAI,QAAQ,KAAK,MAAM,KAAK,IAAI;AAC9B,wBAAoB;AACpB;;;EAKJ,MAAM,eAAe,qBAAqB,IAAI,KAAK,OAAO,MAAM,GAAG,oBAAoB,EAAE,GAAG,EAAE;EAC9F,MAAM,SAAS,aAAa,KAAK,KAAK;AAGtC,MAAI,WAAW,KAAK,gBAAgB;AAGlC,OAAI,KAAK,mBAAmB,EAC1B,MAAK,KAAK,OAAO,MAAM,YAAY,WAAW,KAAK,iBAAiB,CAAC;AAIvE,QAAK,KAAK,OAAO,MAAM,OAAO;AAG9B,QAAK,mBAAmB,aAAa;AACrC,QAAK,iBAAiB;;;;;;CAO1B,QAAc;AACZ,MAAI,KAAK,mBAAmB,GAAG;AAC7B,QAAK,KAAK,OAAO,MAAM,YAAY,WAAW,KAAK,iBAAiB,CAAC;AACrE,QAAK,mBAAmB;;AAE1B,OAAK,iBAAiB;;;;;CAMxB,UAAgB;AAEd,OAAK,QAAQ;AAGb,OAAK,KAAK,OAAO,MAAM,KAAK;AAG5B,OAAK,KAAK,OAAO,MAAM,YAAY,WAAW;AAG9C,MAAI,QAAQ,MAAM,SAAS,QAAQ,MAAM,cAAc,CAAC,KAAK,WAC3D,SAAQ,MAAM,WAAW,MAAM;AAIjC,MAAI,KAAK,KAAK,SACZ,MAAK,KAAK,SAAS,eAAe;;;;;;;;;AC7PxC,SAAgB,YAAY,MAAoB,KAAa,OAAsB;AACjF,KAAI,KAAK,SAAS,UAAW;AAG7B,KAAI,gBAAgB,IAAI,EAAE;AAExB,aAAW,MADiC,GAAG,MAAM,OAAO,CAC/B;AAC7B;;AAIF,MAAK,MAAM,OAAO;;;;;AAMpB,SAAgB,kBACd,MACA,KACA,QACY;AAEZ,aAAY,MAAM,KAAK,OAAO,MAAM;AAGpC,QAAO,OAAO,WAAW,UAAa;AACpC,cAAY,MAAM,KAAK,MAAM;GAC7B;;;;;AAMJ,SAAS,gBAAgB,KAAsB;AAuC7C,QAtCmB,IAAI,IAAI;EACzB;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACD,CAAC,CAEgB,IAAI,IAAI;;;;;;;;;;ACxE5B,MAAM,sBAAsB,OAAO,MAAM;;;;;AAMzC,SAAgB,mBAA4C;AAC1D,QAAO;;;;;AAMT,SAAgB,qBAA2B;AACzC,qBAAoB,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAuC9B,SAAgB,SAAS,EAAE,YAAoC;AAK7D,QAAO,KAHY,SAAS,sBAAsB,cAAc,CAAC,UAAU,EAGnD,SAAS;;;;;AC5BnC,MAAM,EAAE,YAAY,yBAAyB,eAhBU;CACrD;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CAED,CAG4E;;;;;;;;;;;;;;;;;;;;;;;;;;;AAkF7E,SAAgB,OAAO,SAAgB,UAAyB,EAAE,EAAgB;CAChF,MAAM,EAAE,UAAU,aAAa,MAAM,MAAM,IAAI,QAAQ,eAAe,QAAQ,WAAW;AAGzF,qBAAoB;CAGpB,MAAM,cAAc,CAAC;CACrB,MAAM,iBAAiB,YAAY,IAAI,iBAAiB,aAAa;CAErE,MAAM,OAAO,eAAe,SAAS;CAKrC,MAAM,WAAW,WAAW,yBAFO,IAAI,KAAK,CAEQ;AAEpD,KAAI,SAAS,KACX,aAAY,MAAM,SAAS,KAAK;UACvB,SAAS,SAAS,SAAS,GAEpC;OAAK,MAAM,SAAS,SAAS,SAC3B,KAAI,MAAM,KACR,aAAY,MAAM,MAAM,KAAK;;AAMnC,gBAAe,QAAQ;CAGvB,IAAI,cAAc;CAClB,MAAM,mBAAmB;AACvB,MAAI,YAAa;AACjB,gBAAc;AACd,MAAI;AACF,kBAAe,QAAQ;YACf;AACR,iBAAc;;;CAKlB,IAAI,iBAAwC;AAC5C,KAAI,YAAY;EACd,MAAM,WAAW,KAAK,MAAM,MAAO,IAAI;AACvC,mBAAiB,kBAAkB;AACjC,eAAY;KACX,SAAS;;CAId,IAAI,eAAoC;CACxC,MAAM,cAAc,IAAI,SAAe,YAAY;AACjD,iBAAe;GACf;CAGF,MAAM,kBAAkB,QAAQ,MAAM,SAAS,QAAQ,MAAM;CAC7D,IAAI,aAAkC;CACtC,IAAI,iBAAkD;CAGtD,MAAM,gBAAgB;AAEpB,MAAI,gBAAgB;AAClB,iBAAc,eAAe;AAC7B,oBAAiB;;AAInB,MAAI,YAAY;AACd,WAAQ,eAAe,UAAU,WAAW;AAC5C,WAAQ,eAAe,WAAW,WAAW;;AAE/C,MAAI,eACF,SAAQ,MAAM,eAAe,QAAQ,eAAe;AAItD,MAAI,QAAQ,MAAM,SAAS,QAAQ,MAAM,WACvC,KAAI;AACF,WAAQ,MAAM,WAAW,mBAAmB,MAAM;UAC5C;AAMV,uBAAqB,SAAS;AAC9B,iBAAe,SAAS;AAExB,MAAI,aACF,eAAc;;CAKlB,MAAM,gBAAgB;AAEpB,oBAAkB,CAAC,QAAQ;AAI3B,iBAAe,QAAQ;AAEvB,WAAS;;AAIX,KAAI,aAAa;AACf,qBAAmB;AACjB,YAAS;AACT,WAAQ,KAAK,EAAE;;AAIjB,MAAI;AACF,WAAQ,GAAG,UAAU,WAAW;AAChC,WAAQ,GAAG,WAAW,WAAW;AAGjC,OAAI,QAAQ,MAAM,OAAO;AACvB,YAAQ,MAAM,WAAW,KAAK;AAC9B,YAAQ,MAAM,QAAQ;AAEtB,sBAAkB,SAAiB;KACjC,MAAM,MAAM,KAAK,UAAU;AAE3B,SAAI,QAAQ,OAAY,QAAQ,QAC9B;UAAI,WACF,aAAY;;;AAKlB,YAAQ,MAAM,GAAG,QAAQ,eAAe;;WAEnC,KAAK;AAEZ,YAAS;AACT,SAAM;;;AAIV,QAAO;EACL,UAAU;EACV;EACA,qBAAqB;EACtB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAmCH,SAAgB,MAAM,SAAiB,UAAwB,EAAE,EAAQ;CACvE,MAAM,EAAE,QAAQ,eAAe,QAAQ,WAAW;AAGlD,KAAI,YAAY,QAAW;AACzB,eAAa,MAAM,KAAK;AACxB;;CAIF,MAAM,aAAa,QAAQ,MAAM,SAAS,QAAQ,MAAM;CAGxD,MAAM,WAAW,IAAI,iBAAiB,aAAa;CACnD,MAAM,OAAO,SAAS,SAAS;CAM/B,MAAM,WAAW,WAAW,yBAHO,IAAI,KAAK,CAGQ;AAEpD,KAAI,SAAS,KACX,aAAY,MAAM,SAAS,KAAK;UACvB,SAAS,SAAS,SAAS,GAEpC;OAAK,MAAM,SAAS,SAAS,SAC3B,KAAI,MAAM,KACR,aAAY,MAAM,MAAM,KAAK;;AAMnC,UAAS,QAAQ;AAIjB,sBAAqB,SAAS;AAG9B,UAAS,SAAS;AAGlB,KAAI,QAAQ,MAAM,SAAS,QAAQ,MAAM,cAAc,WACrD,SAAQ,MAAM,WAAW,KAAK;;;;;;;;;;;;;;;;;;;;;ACnUlC,SAAgB,UAAU,EAAE,QAAQ,KAA8B;AAGhE,QAAO,0CAFO,MAAM,KAAK,EAAE,QAAQ,OAAO,GAAG,GAAG,MAAM,oBAAC,oBAAa,OAAH,EAAW,CAAC,GAE1D"}
@@ -1,6 +1,6 @@
1
- import { t as signal } from "./signal-4PgGfydw.mjs";
2
- import { t as computed } from "./computed-BpjqvQu1.mjs";
3
- import { t as isSignal } from "./utils-BrGmTgfG.mjs";
1
+ import { t as signal } from "./signal-BN8vHXDb.mjs";
2
+ import { t as computed } from "./computed-BidG06Lt.mjs";
3
+ import { t as isSignal } from "./utils-DbTAs943.mjs";
4
4
 
5
5
  //#region ../core/src/types.ts
6
6
  /**
@@ -11,6 +11,11 @@ const Fragment = Symbol.for("semajsx.fragment");
11
11
  * Special VNode type for portal support
12
12
  */
13
13
  const Portal = Symbol.for("semajsx.portal");
14
+ /**
15
+ * Special VNode type for forward support
16
+ * Forward merges its props onto its single child element without producing a DOM node
17
+ */
18
+ const Forward = Symbol.for("semajsx.forward");
14
19
 
15
20
  //#endregion
16
21
  //#region ../core/src/vnode.ts
@@ -335,6 +340,8 @@ function createRenderer(strategy) {
335
340
  if (type === "#signal") return renderSignalNode(vnode, parentContext);
336
341
  if (type === Fragment) return renderFragment(vnode, parentContext);
337
342
  if (type === Portal) return renderPortal(vnode, parentContext);
343
+ if (type === Forward) return renderForward(vnode, parentContext);
344
+ if (type === "#native") return renderNativeNode(vnode);
338
345
  if (typeof type === "function") return renderComponent(vnode, parentContext);
339
346
  if (typeof type === "string") return renderElement(vnode, parentContext);
340
347
  throw new Error(`Unknown VNode type: ${String(type)}`);
@@ -443,6 +450,69 @@ function createRenderer(strategy) {
443
450
  };
444
451
  }
445
452
  /**
453
+ * Merge Forward's props into the child's props
454
+ * - class/className: concatenated (array)
455
+ * - style: merged objects (Forward overrides per-property)
456
+ * - on* events: chained (both handlers run)
457
+ * - other props: Forward overrides child
458
+ */
459
+ function mergeForwardProps(childProps, forwardProps) {
460
+ const merged = { ...childProps };
461
+ for (const [key, value] of Object.entries(forwardProps)) {
462
+ if (key === "key" || key === "children") continue;
463
+ if ((key === "class" || key === "className") && merged[key] != null) merged[key] = [merged[key], value];
464
+ else if (key === "style" && typeof merged[key] === "object" && typeof value === "object") merged[key] = {
465
+ ...merged[key],
466
+ ...value
467
+ };
468
+ else if (key.startsWith("on") && typeof value === "function" && typeof merged[key] === "function") {
469
+ const existing = merged[key];
470
+ merged[key] = (...args) => {
471
+ value(...args);
472
+ existing(...args);
473
+ };
474
+ } else merged[key] = value;
475
+ }
476
+ return merged;
477
+ }
478
+ /**
479
+ * Render a Forward node
480
+ * Forward merges its props onto its single child and renders it directly
481
+ */
482
+ function renderForward(vnode, parentContext) {
483
+ const child = vnode.children[0];
484
+ if (!child || vnode.children.length !== 1) throw new Error("Forward must have exactly one child element");
485
+ const forwardProps = vnode.props || {};
486
+ return renderNode({
487
+ ...child,
488
+ props: mergeForwardProps(child.props || {}, forwardProps)
489
+ }, parentContext);
490
+ }
491
+ /**
492
+ * Render a native node (pre-created element from external libraries)
493
+ * The element is used directly without creating a new one.
494
+ * Additional props are applied via the strategy's setProperty/setSignalProperty.
495
+ */
496
+ function renderNativeNode(vnode) {
497
+ const nativeNode = vnode.props?.__nativeNode;
498
+ if (!nativeNode) throw new Error("Native VNode must have an __nativeNode prop");
499
+ const subscriptions = [];
500
+ const props = vnode.props || {};
501
+ for (const [key, value] of Object.entries(props)) {
502
+ if (key === "__nativeNode" || key === "key" || key === "children") continue;
503
+ if (isSignal(value)) {
504
+ const unsub = strategy.setSignalProperty(nativeNode, key, value);
505
+ subscriptions.push(unsub);
506
+ } else strategy.setProperty(nativeNode, key, value);
507
+ }
508
+ return {
509
+ vnode,
510
+ node: nativeNode,
511
+ subscriptions,
512
+ children: []
513
+ };
514
+ }
515
+ /**
446
516
  * Render a component
447
517
  */
448
518
  function renderComponent(vnode, parentContext) {
@@ -583,5 +653,5 @@ function createRenderer(strategy) {
583
653
  }
584
654
 
585
655
  //#endregion
586
- export { Fragment as _, jsxs as a, when as c, createComponentAPI as d, ISLAND_MARKER as f, isVNode as g, h, jsx as i, Context as l, createTextVNode as m, isAsyncIterator as n, resource as o, createFragment as p, isPromise as r, stream as s, createRenderer as t, context as u, Portal as v };
587
- //# sourceMappingURL=src-BlS3Hc-L.mjs.map
656
+ export { Forward as _, jsxs as a, when as c, createComponentAPI as d, ISLAND_MARKER as f, isVNode as g, h, jsx as i, Context as l, createTextVNode as m, isAsyncIterator as n, resource as o, createFragment as p, isPromise as r, stream as s, createRenderer as t, context as u, Fragment as v, Portal as y };
657
+ //# sourceMappingURL=src-DW3tIczg.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"src-DW3tIczg.mjs","names":[],"sources":["../../core/src/types.ts","../../core/src/vnode.ts","../../core/src/shared/island-marker.ts","../../core/src/context.ts","../../core/src/helpers.ts","../../core/src/jsx.ts","../../core/src/component.ts","../../core/src/render-core.ts"],"sourcesContent":["import type { ReadableSignal, WritableSignal } from \"./signal\";\n\n/**\n * Special VNode type for fragment support\n */\nexport const Fragment: symbol = Symbol.for(\"semajsx.fragment\");\n\n/**\n * Special VNode type for portal support\n */\nexport const Portal: symbol = Symbol.for(\"semajsx.portal\");\n\n/**\n * Special VNode type for forward support\n * Forward merges its props onto its single child element without producing a DOM node\n */\nexport const Forward: symbol = Symbol.for(\"semajsx.forward\");\n\n/**\n * VNode types\n * - The runtime VNode tree always resolves to these `type` values\n */\nexport type VNodeType = string | Component<any> | typeof Fragment | typeof Portal | typeof Forward;\n\n/**\n * VNode: The basic unit of the runtime render tree\n * - `type`: the element/component type\n * - `props`: attributes or props passed to the node (may be null)\n * - `children`: resolved child nodes (always normalized to VNode[] at render time)\n */\nexport interface VNode {\n type: VNodeType;\n props: Record<string, any> | null;\n children: VNode[];\n key?: string | number | null;\n}\n\n/**\n * Primitive values allowed in JSX\n * - These are normalized during VNode construction\n */\nexport type JSXPrimitive = string | number | boolean | null | undefined;\n\n/**\n * A JSXNode represents any valid \"JSX expression result\"\n * - Could be a raw VNode/primitive, or wrapped in a reactive/async container\n */\nexport type JSXNode =\n | VNode\n | JSXPrimitive\n | Iterable<JSXNode>\n | ReadableSignal<JSXNode>\n | Promise<JSXNode>\n | AsyncIterableIterator<JSXNode>;\n\n/**\n * Component type\n * - Optional `ctx` parameter allows passing in custom API/runtime helpers\n */\nexport type Component<P = any> = (props: P, ctx?: ComponentAPI) => JSXNode;\n\n/**\n * ComponentAPI - Runtime API available to components via second parameter\n */\nexport interface ComponentAPI {\n /**\n * Inject a context value\n * @param context - The context to inject\n * @returns The current value of the context, or undefined if not provided\n */\n inject<T>(context: Context<T>): T | undefined;\n}\n\n/**\n * Ref types\n */\n\n/**\n * Ref - can be a WritableSignal or a callback function\n * This allows both reactive refs and imperative refs\n */\nexport type Ref<T> = WritableSignal<T | null> | ((instance: T | null) => void);\n\n/**\n * Context types\n */\n\n/**\n * Context - a typed Symbol for identifying context\n */\nexport type Context<T> = symbol & { __type?: T };\n\n/**\n * Context provide entry: [Context, value]\n */\nexport type ContextProvide<T = any> = [Context<T>, T];\n\n/**\n * Context component props - supports single or multiple context provides\n */\nexport interface ContextProps {\n // Single context: [ThemeContext, theme]\n // Multiple contexts: [[ThemeContext, theme], [UserContext, user]]\n provide: ContextProvide | ContextProvide[];\n children?: JSXNode;\n}\n\n/**\n * Helper type to allow Signal values for any attribute\n */\nexport type SignalOr<T> = T | ReadableSignal<T>;\n\n/**\n * Makes all properties in T accept Signal values\n * Excludes event handlers (functions) and children\n */\nexport type WithSignals<T> = {\n [K in keyof T]: K extends `on${string}`\n ? T[K] // Event handlers don't need Signal wrapper\n : K extends \"children\"\n ? T[K] // Children handled separately\n : T[K] extends (...args: any[]) => any\n ? T[K] // Other functions don't need Signal wrapper\n : SignalOr<T[K]>;\n};\n\n/**\n * Adds key property to element attributes for list reconciliation\n */\nexport type WithKey<T> = T & {\n key?: string | number;\n};\n","import type { JSXNode, VNode, VNodeType } from \"./types\";\nimport type { Signal } from \"@semajsx/signal\";\nimport { Fragment } from \"./types\";\nimport { isSignal } from \"@semajsx/signal\";\n\n/**\n * Create a VNode (Virtual Node)\n */\nexport function h(\n type: VNodeType,\n props: Record<string, any> | null,\n ...children: JSXNode[]\n): VNode {\n return {\n type,\n props: props || {},\n children: normalizeChildren(children),\n key: props?.key,\n };\n}\n\n/**\n * Create a text VNode\n */\nexport function createTextVNode(text: string | number): VNode {\n return {\n type: \"#text\",\n props: { nodeValue: String(text) },\n children: [],\n };\n}\n\n/**\n * Create a signal VNode wrapper\n */\nexport function createSignalVNode(signal: Signal<unknown>): VNode {\n return {\n type: \"#signal\",\n props: { signal },\n children: [],\n };\n}\n\n/**\n * Normalize children into an array of VNodes\n */\nfunction normalizeChildren(children: JSXNode[]): VNode[] {\n const result: VNode[] = [];\n\n for (const child of children) {\n if (child == null || typeof child === \"boolean\") {\n // Skip nullish and boolean values\n continue;\n }\n\n if (Array.isArray(child)) {\n // Recursively flatten arrays\n result.push(...normalizeChildren(child));\n } else if (typeof child === \"string\" || typeof child === \"number\") {\n // Convert primitives to text nodes\n result.push(createTextVNode(child));\n } else if (isSignal(child)) {\n // Wrap signals in special signal nodes\n result.push(createSignalVNode(child));\n } else if (isVNode(child)) {\n // Already a VNode\n result.push(child);\n } else {\n // Unknown type, skip\n console.warn(\"Unknown child type:\", typeof child);\n }\n }\n\n return result;\n}\n\n/**\n * Check if a value is a VNode\n */\nexport function isVNode(value: unknown): value is VNode {\n return (\n value != null &&\n typeof value === \"object\" &&\n \"type\" in value &&\n \"props\" in value &&\n \"children\" in value\n );\n}\n\n/**\n * Create a Fragment\n */\nexport function createFragment(children: JSXNode[]): VNode {\n return h(Fragment, null, ...children);\n}\n","/**\n * Unique symbol to mark Island components\n * This symbol is used to identify components that should be hydrated on the client\n */\nexport const ISLAND_MARKER: symbol = Symbol.for(\"semajsx.island\");\n","/**\n * Context API implementation\n */\n\nimport { h } from \"./vnode\";\nimport { Fragment } from \"./types\";\nimport type { ComponentAPI, Context as ContextType, ContextProps, VNode } from \"./types\";\n\n// Context map type - stores context values for current render environment\nexport type ContextMap = Map<symbol, any>;\n\n/**\n * Create a new Context (returns a typed Symbol)\n *\n * @param name - Optional name for debugging (defaults to \"anonymous\")\n * @returns Context symbol\n *\n * @example\n * ```typescript\n * const ThemeContext = context<Theme>();\n * const UserContext = context<User>('user'); // With debug name\n *\n * <Context provide={[ThemeContext, theme]}>\n * <App />\n * </Context>\n * ```\n */\nexport function context<T>(name?: string): ContextType<T> {\n const debugName = name || \"anonymous\";\n return Symbol(debugName) as ContextType<T>;\n}\n\n/**\n * Context component - provides context values to child components\n *\n * @example\n * ```typescript\n * // Single context\n * <Context provide={[ThemeContext, theme]}>\n * <App />\n * </Context>\n *\n * // Multiple contexts\n * <Context provide={[\n * [ThemeContext, theme],\n * [UserContext, user]\n * ]}>\n * <App />\n * </Context>\n * ```\n */\nexport function Context(props: ContextProps): VNode {\n const children = props.children\n ? Array.isArray(props.children)\n ? props.children\n : [props.children]\n : [];\n return h(Fragment, null, ...children);\n}\n\n// Mark as special context provider component\n(Context as any).__isContextProvider = true;\n\n/**\n * Create ComponentAPI instance for a component\n *\n * @param contextMap - The context map for current render environment\n * @returns ComponentAPI instance\n */\nexport function createComponentAPI(contextMap: ContextMap): ComponentAPI {\n return {\n inject<T>(context: ContextType<T>): T | undefined {\n return contextMap.get(context);\n },\n };\n}\n","import type { JSXNode } from \"./types\";\nimport type { Signal } from \"@semajsx/signal\";\nimport { computed, signal } from \"@semajsx/signal\";\n\n/**\n * Conditional rendering helper\n *\n * Renders content when condition signal is true, nothing when false.\n *\n * @example\n * // With VNode\n * const hint = when(showHint, <text>Press Ctrl+C to exit</text>);\n *\n * @example\n * // With function (lazy evaluation)\n * const hint = when(showHint, () => <text>Press Ctrl+C to exit</text>);\n */\nexport function when(\n condition: Signal<boolean>,\n content: JSXNode | (() => JSXNode),\n): Signal<JSXNode | null> {\n return computed([condition], (show) => {\n if (!show) return null;\n return typeof content === \"function\" ? content() : content;\n });\n}\n\n/**\n * Async resource helper for Promise<VNode>\n *\n * Renders pending content (or null) while the promise is pending, then renders\n * the resolved VNode. Handle errors in the promise itself using .catch().\n *\n * @example\n * // Handle everything in the promise\n * const content = resource(\n * fetchData()\n * .then(data => <text>{data}</text>)\n * .catch(err => <text color=\"red\">Error: {err.message}</text>)\n * );\n *\n * @example\n * // With optional pending content\n * const content = resource(\n * fetchData().then(data => <text>{data}</text>),\n * <text>Loading...</text>\n * );\n */\nexport function resource(promise: Promise<JSXNode>, pending?: JSXNode): Signal<JSXNode | null> {\n const content = signal<JSXNode | null>(pending || null);\n\n promise\n .then((result) => {\n content.value = result;\n })\n .catch((err) => {\n console.error(\"Unhandled promise rejection in resource():\", err);\n });\n\n return content;\n}\n\n/**\n * Async stream helper for AsyncIterable<VNode>\n *\n * Renders each yielded VNode from the async iterator, replacing the previous\n * content with each new value.\n *\n * @example\n * async function* generateContent() {\n * yield <text>Loading...</text>;\n * const data = await fetchData();\n * yield <text>Data: {data}</text>;\n * }\n *\n * const content = stream(generateContent());\n */\nexport function stream(\n iterator: AsyncIterable<JSXNode>,\n pending?: JSXNode,\n): Signal<JSXNode | null> {\n const content = signal<JSXNode | null>(pending || null);\n\n (async () => {\n try {\n for await (const vnode of iterator) {\n content.value = vnode;\n }\n } catch (err) {\n console.error(\"Error in stream():\", err);\n }\n })();\n\n return content;\n}\n","import { VNode, VNodeType } from \"./types\";\nimport { h } from \"./vnode\";\n\nexport function jsx(type: VNodeType, props: any, key?: any): VNode {\n const { children, ...restProps } = props || {};\n\n if (key !== undefined) {\n restProps.key = key;\n }\n\n if (children !== undefined) {\n return h(type, restProps, children);\n }\n\n return h(type, restProps);\n}\n\nexport function jsxs(type: VNodeType, props: any, key?: any): VNode {\n const { children, ...restProps } = props || {};\n\n if (key !== undefined) {\n restProps.key = key;\n }\n\n if (children !== undefined) {\n const childArray = Array.isArray(children) ? children : [children];\n return h(type, restProps, ...childArray);\n }\n\n return h(type, restProps);\n}\n","import type { JSXNode, JSXPrimitive, VNode } from \"./types\";\nimport { Fragment } from \"./types\";\nimport { isSignal } from \"@semajsx/signal\";\nimport { createSignalVNode, createTextVNode, isVNode } from \"./vnode\";\n\n/**\n * Normalize the `children` prop passed to components so it mirrors React semantics.\n * - 0 children => undefined\n * - 1 child => the child itself\n * - >1 children => array\n */\nexport function normalizeChildrenProp(children: VNode[]): VNode | VNode[] | undefined {\n if (children.length === 0) {\n return undefined;\n }\n if (children.length === 1) {\n return children[0];\n }\n return children;\n}\n\n/**\n * Normalize any JSXNode result from a component into a concrete VNode.\n */\nexport function normalizeComponentResult(result: VNode | JSXPrimitive | Iterable<JSXNode>): VNode {\n if (isVNode(result)) {\n return result;\n }\n\n if (typeof result === \"string\" || typeof result === \"number\") {\n return createTextVNode(result);\n }\n\n if (result == null || typeof result === \"boolean\") {\n return createTextVNode(\"\");\n }\n\n if (Array.isArray(result) || isIterable(result)) {\n const normalizedChildren = normalizeIterableChildren(result);\n return {\n type: Fragment,\n props: {},\n children: normalizedChildren,\n };\n }\n\n throw new Error(`Invalid component return type: ${typeof result}`);\n}\n\nfunction normalizeIterableChildren(children: Iterable<JSXNode>): VNode[] {\n const normalized: VNode[] = [];\n\n for (const child of children) {\n if (child == null || typeof child === \"boolean\") {\n continue;\n }\n\n if (Array.isArray(child) || isIterable(child)) {\n normalized.push(...normalizeIterableChildren(child as Iterable<JSXNode>));\n continue;\n }\n\n if (typeof child === \"string\" || typeof child === \"number\") {\n normalized.push(createTextVNode(child));\n continue;\n }\n\n if (isSignal(child)) {\n normalized.push(createSignalVNode(child));\n continue;\n }\n\n if (isVNode(child)) {\n normalized.push(child);\n continue;\n }\n\n throw new Error(`Invalid child in iterable: ${typeof child}`);\n }\n\n return normalized;\n}\n\nfunction isIterable(value: unknown): value is Iterable<unknown> {\n return value != null && typeof (value as any)[Symbol.iterator] === \"function\";\n}\n","import type { VNode, Ref } from \"./types\";\nimport { Fragment, Forward, Portal } from \"./types\";\nimport { isSignal } from \"@semajsx/signal\";\nimport { isVNode } from \"./vnode\";\nimport { resource, stream } from \"./helpers\";\nimport { type ContextMap, createComponentAPI } from \"./context\";\nimport { normalizeChildrenProp, normalizeComponentResult } from \"./component\";\n\n/**\n * Generic rendered node structure\n */\nexport interface RenderedNode<TNode> {\n vnode: VNode;\n node: TNode | null;\n subscriptions: Array<() => void>;\n children: RenderedNode<TNode>[];\n}\n\n/**\n * Operations strategy for different rendering targets\n */\nexport interface RenderStrategy<TNode> {\n /**\n * Create a text node\n */\n createTextNode(text: string): TNode;\n\n /**\n * Create a comment node (used for markers)\n */\n createComment(text: string): TNode;\n\n /**\n * Create an element node\n */\n createElement(type: string): TNode;\n\n /**\n * Get the parent node of a node\n */\n getParent(node: TNode): TNode | null;\n\n /**\n * Get the next sibling of a node\n */\n getNextSibling(node: TNode): TNode | null;\n\n /**\n * Insert a node before another node\n */\n insertBefore(parent: TNode, newNode: TNode, beforeNode: TNode | null): void;\n\n /**\n * Append child to parent\n */\n appendChild(parent: TNode, child: TNode): void;\n\n /**\n * Remove child from its parent\n */\n removeChild(node: TNode): void;\n\n /**\n * Replace old node with new node\n */\n replaceNode(oldNode: TNode, newNode: TNode): void;\n\n /**\n * Set a property on a node\n */\n setProperty(node: TNode, key: string, value: unknown): void;\n\n /**\n * Set a signal property on a node (returns unsubscribe function)\n */\n setSignalProperty(node: TNode, key: string, signal: any): () => void;\n\n /**\n * Optional: Set a ref on a node (returns cleanup function)\n * This is only used for DOM rendering\n */\n setRef?(node: TNode, ref: Ref<TNode>): () => void;\n\n /**\n * Optional: Try to reuse an existing node instead of replacing it\n * Returns true if the node was successfully reused\n * This is used for DOM optimization but not needed for terminal\n */\n tryReuseNode?(\n oldNode: TNode,\n newNode: TNode,\n oldRendered: RenderedNode<TNode>,\n newRendered: RenderedNode<TNode>,\n ): boolean;\n}\n\n/**\n * Check if a value is a Promise\n */\nexport function isPromise<T>(value: any): value is Promise<T> {\n return value && typeof value.then === \"function\";\n}\n\n/**\n * Check if a value is an AsyncIterator\n */\nexport function isAsyncIterator<T>(value: any): value is AsyncIterableIterator<T> {\n return value && typeof value[Symbol.asyncIterator] === \"function\";\n}\n\n/**\n * Core rendering logic - works for both DOM and Terminal\n */\nexport function createRenderer<TNode>(strategy: RenderStrategy<TNode>): {\n renderNode: (vnode: VNode, parentContext: ContextMap) => RenderedNode<TNode>;\n unmount: (node: RenderedNode<TNode>) => void;\n cleanupSubscriptions: (node: RenderedNode<TNode>) => void;\n} {\n /**\n * Helper to recursively collect all actual DOM nodes from a rendered node\n * Handles fragments and signal nodes that may not have their own DOM node\n */\n function collectNodes(rendered: RenderedNode<TNode>): TNode[] {\n const nodes: TNode[] = [];\n\n // Fragment: no node, only children\n if (rendered.vnode.type === Fragment) {\n for (const child of rendered.children) {\n nodes.push(...collectNodes(child));\n }\n return nodes;\n }\n\n // Portal: children are rendered into a different container,\n // so they should not be collected in the parent tree\n if (rendered.vnode.type === Portal) {\n return nodes;\n }\n\n // Signal marker: include marker node + content children\n if (rendered.vnode.type === \"#signal\") {\n if (rendered.node) {\n nodes.push(rendered.node); // marker\n }\n // Collect content children (after marker)\n for (const child of rendered.children) {\n nodes.push(...collectNodes(child));\n }\n return nodes;\n }\n\n // Regular elements and text nodes: just the node itself\n // Children are already attached to the node\n if (rendered.node) {\n nodes.push(rendered.node);\n }\n\n return nodes;\n }\n\n /**\n * Render a single VNode\n */\n function renderNode(vnode: VNode, parentContext: ContextMap): RenderedNode<TNode> {\n const { type } = vnode;\n\n // Text node\n if (type === \"#text\") {\n return renderTextNode(vnode);\n }\n\n // Signal VNode\n if (type === \"#signal\") {\n return renderSignalNode(vnode, parentContext);\n }\n\n // Fragment\n if (type === Fragment) {\n return renderFragment(vnode, parentContext);\n }\n\n // Portal\n if (type === Portal) {\n return renderPortal(vnode, parentContext);\n }\n\n // Forward\n if (type === Forward) {\n return renderForward(vnode, parentContext);\n }\n\n // Native node (pre-created element from external libraries)\n if (type === \"#native\") {\n return renderNativeNode(vnode);\n }\n\n // Component\n if (typeof type === \"function\") {\n return renderComponent(vnode, parentContext);\n }\n\n // Element\n if (typeof type === \"string\") {\n return renderElement(vnode, parentContext);\n }\n\n throw new Error(`Unknown VNode type: ${String(type)}`);\n }\n\n /**\n * Render a text node\n */\n function renderTextNode(vnode: VNode): RenderedNode<TNode> {\n const text = vnode.props?.nodeValue || \"\";\n const node = strategy.createTextNode(text);\n\n return {\n vnode,\n node,\n subscriptions: [],\n children: [],\n };\n }\n\n /**\n * Render a signal VNode\n */\n function renderSignalNode(vnode: VNode, parentContext: ContextMap): RenderedNode<TNode> {\n const signal = vnode.props?.signal;\n // Use captured context if available (for async components), otherwise parent context\n const contextForSignal = vnode.props?.context || parentContext;\n\n if (!isSignal(signal)) {\n throw new Error(\"Signal VNode must have a signal prop\");\n }\n\n // Create a comment node as a marker to track the signal's position in the DOM\n // This is necessary because signal content might be a Fragment (no direct node)\n // or might be empty initially\n const marker = strategy.createComment(\"signal\");\n\n // Get initial value and render it\n const initialValue = signal.value;\n let currentRendered = renderValueToNode(initialValue, contextForSignal);\n\n const subscriptions: Array<() => void> = [];\n\n // Subscribe to signal changes\n const unsubscribe = signal.subscribe((value) => {\n const newRendered = renderValueToNode(value, contextForSignal);\n\n // Collect actual DOM nodes from old and new rendered trees\n const oldContentNodes = collectNodes(currentRendered);\n const newContentNodes = collectNodes(newRendered);\n\n // Get the parent from the marker\n const parent = strategy.getParent(marker);\n if (!parent) {\n console.warn(\"[Signal] Marker not in DOM, cannot update\");\n return;\n }\n\n // Remove all old content nodes\n for (const node of oldContentNodes) {\n strategy.removeChild(node);\n }\n\n // Insert new content nodes after the marker\n let insertAfter = strategy.getNextSibling(marker);\n for (const node of newContentNodes) {\n strategy.insertBefore(parent, node, insertAfter);\n // Update insertAfter to maintain order (insert at the position after the last inserted)\n insertAfter = strategy.getNextSibling(node);\n }\n\n // Unmount old rendered tree: cleans up subscriptions AND removes\n // portal children from their containers (cleanupSubscriptions alone\n // would leave portal content orphaned in the portal container)\n unmount(currentRendered);\n\n currentRendered = newRendered;\n });\n\n subscriptions.push(unsubscribe);\n\n return {\n vnode,\n node: marker,\n subscriptions,\n children: currentRendered ? [currentRendered] : [],\n };\n }\n\n /**\n * Helper to convert a signal value to a rendered node\n */\n function renderValueToNode(value: unknown, context: ContextMap): RenderedNode<TNode> {\n let newVNode: VNode;\n\n // Convert value to VNode\n if (isVNode(value)) {\n newVNode = value;\n } else if (Array.isArray(value)) {\n // Support arrays - wrap in Fragment automatically\n // This allows: computed(todos, list => list.map(...))\n // Without requiring manual Fragment wrapping\n newVNode = {\n type: Fragment,\n props: {},\n children: value.filter(isVNode), // Filter out non-VNodes\n };\n } else if (typeof value === \"string\" || typeof value === \"number\") {\n newVNode = {\n type: \"#text\",\n props: { nodeValue: String(value) },\n children: [],\n };\n } else if (value == null || typeof value === \"boolean\") {\n // Render empty text for null/undefined/boolean\n // This works for both DOM and terminal\n newVNode = {\n type: \"#text\",\n props: { nodeValue: \"\" },\n children: [],\n };\n } else {\n throw new Error(`Invalid signal value type: ${typeof value}`);\n }\n\n return renderNode(newVNode, context);\n }\n\n /**\n * Render a fragment\n */\n function renderFragment(vnode: VNode, parentContext: ContextMap): RenderedNode<TNode> {\n const children = vnode.children.map((child) => renderNode(child, parentContext));\n\n // Fragment has no node of its own\n return {\n vnode,\n node: null,\n subscriptions: [],\n children,\n };\n }\n\n /**\n * Render a portal\n * Portal renders its children into a different container\n */\n function renderPortal(vnode: VNode, parentContext: ContextMap): RenderedNode<TNode> {\n const container = vnode.props?.container;\n\n if (!container) {\n throw new Error(\"Portal must have a container prop\");\n }\n\n // Render children with same context\n const children = vnode.children.map((child) => renderNode(child, parentContext));\n\n // Append all child nodes to the portal container (recursively handles fragments)\n for (const child of children) {\n const nodes = collectNodes(child);\n for (const node of nodes) {\n strategy.appendChild(container, node);\n }\n }\n\n // Portal has no node in the parent tree\n return {\n vnode,\n node: null,\n subscriptions: [],\n children,\n };\n }\n\n /**\n * Merge Forward's props into the child's props\n * - class/className: concatenated (array)\n * - style: merged objects (Forward overrides per-property)\n * - on* events: chained (both handlers run)\n * - other props: Forward overrides child\n */\n function mergeForwardProps(\n childProps: Record<string, any>,\n forwardProps: Record<string, any>,\n ): Record<string, any> {\n const merged = { ...childProps };\n\n for (const [key, value] of Object.entries(forwardProps)) {\n if (key === \"key\" || key === \"children\") continue;\n\n if ((key === \"class\" || key === \"className\") && merged[key] != null) {\n // Concatenate class values as array — renderers resolve arrays\n merged[key] = [merged[key], value];\n } else if (key === \"style\" && typeof merged[key] === \"object\" && typeof value === \"object\") {\n // Merge style objects (Forward properties override)\n merged[key] = { ...merged[key], ...value };\n } else if (\n key.startsWith(\"on\") &&\n typeof value === \"function\" &&\n typeof merged[key] === \"function\"\n ) {\n // Chain event handlers: Forward's runs first, then child's\n const existing = merged[key];\n merged[key] = (...args: unknown[]) => {\n value(...args);\n existing(...args);\n };\n } else {\n merged[key] = value;\n }\n }\n\n return merged;\n }\n\n /**\n * Render a Forward node\n * Forward merges its props onto its single child and renders it directly\n */\n function renderForward(vnode: VNode, parentContext: ContextMap): RenderedNode<TNode> {\n const child = vnode.children[0];\n\n if (!child || vnode.children.length !== 1) {\n throw new Error(\"Forward must have exactly one child element\");\n }\n\n const forwardProps = vnode.props || {};\n\n // Create a new VNode with merged props\n const mergedChild: VNode = {\n ...child,\n props: mergeForwardProps(child.props || {}, forwardProps),\n };\n\n // Render the merged child directly — Forward is completely transparent\n return renderNode(mergedChild, parentContext);\n }\n\n /**\n * Render a native node (pre-created element from external libraries)\n * The element is used directly without creating a new one.\n * Additional props are applied via the strategy's setProperty/setSignalProperty.\n */\n function renderNativeNode(vnode: VNode): RenderedNode<TNode> {\n const nativeNode = vnode.props?.__nativeNode as TNode;\n\n if (!nativeNode) {\n throw new Error(\"Native VNode must have an __nativeNode prop\");\n }\n\n const subscriptions: Array<() => void> = [];\n\n // Apply additional props to the native node\n const props = vnode.props || {};\n for (const [key, value] of Object.entries(props)) {\n if (key === \"__nativeNode\" || key === \"key\" || key === \"children\") continue;\n\n if (isSignal(value)) {\n const unsub = strategy.setSignalProperty(nativeNode, key, value);\n subscriptions.push(unsub);\n } else {\n strategy.setProperty(nativeNode, key, value);\n }\n }\n\n return {\n vnode,\n node: nativeNode,\n subscriptions,\n children: [],\n };\n }\n\n /**\n * Render a component\n */\n function renderComponent(vnode: VNode, parentContext: ContextMap): RenderedNode<TNode> {\n if (typeof vnode.type !== \"function\") {\n throw new Error(\"Component vnode must have a function type\");\n }\n\n const Component = vnode.type;\n const props = {\n ...vnode.props,\n children: normalizeChildrenProp(vnode.children),\n };\n\n // Prepare current component's context\n let currentContext = parentContext;\n\n // Check if this is a Context Provider\n const isContextProvider = (Component as any).__isContextProvider;\n\n if (isContextProvider) {\n // Context Provider: create new context map with provided values\n currentContext = new Map(parentContext);\n const provide = (props as any).provide;\n\n if (provide) {\n // Check if it's a single provide [Context, value] or multiple [[Context, value], ...]\n const isSingle = provide.length === 2 && typeof provide[0] === \"symbol\";\n\n if (isSingle) {\n // Single: [Context, value]\n const [context, value] = provide;\n currentContext.set(context, value);\n } else {\n // Multiple: [[Context, value], ...]\n for (const [context, value] of provide) {\n currentContext.set(context, value);\n }\n }\n }\n }\n\n // Create ComponentAPI\n const ctx = createComponentAPI(currentContext);\n\n // Call component function with props and ctx\n const result = Component(props, ctx);\n\n // Handle async component (Promise<VNode>)\n if (isPromise(result)) {\n const pending: VNode = {\n type: \"#text\",\n props: { nodeValue: \"\" },\n children: [],\n };\n const resultSignal = resource(result, pending);\n const signalVNode: VNode = {\n type: \"#signal\",\n props: { signal: resultSignal, context: currentContext },\n children: [],\n };\n const rendered = renderNode(signalVNode, currentContext);\n return {\n vnode,\n node: rendered.node,\n subscriptions: rendered.subscriptions,\n children: [rendered],\n };\n }\n\n // Handle async generator component (AsyncIterableIterator<VNode>)\n if (isAsyncIterator(result)) {\n const pending: VNode = {\n type: \"#text\",\n props: { nodeValue: \"\" },\n children: [],\n };\n const resultSignal = stream(result, pending);\n const signalVNode: VNode = {\n type: \"#signal\",\n props: { signal: resultSignal, context: currentContext },\n children: [],\n };\n const rendered = renderNode(signalVNode, currentContext);\n return {\n vnode,\n node: rendered.node,\n subscriptions: rendered.subscriptions,\n children: [rendered],\n };\n }\n\n // Handle signal component (Signal<VNode>)\n if (isSignal(result)) {\n const signalVNode: VNode = {\n type: \"#signal\",\n props: { signal: result, context: currentContext },\n children: [],\n };\n const rendered = renderNode(signalVNode, currentContext);\n return {\n vnode,\n node: rendered.node,\n subscriptions: rendered.subscriptions,\n children: [rendered],\n };\n }\n\n // Handle normal sync component (VNode)\n const normalizedResult = normalizeComponentResult(result);\n const rendered = renderNode(normalizedResult, currentContext);\n\n return {\n vnode,\n node: rendered.node,\n subscriptions: rendered.subscriptions,\n children: [rendered],\n };\n }\n\n /**\n * Render an element\n */\n function renderElement(vnode: VNode, parentContext: ContextMap): RenderedNode<TNode> {\n if (typeof vnode.type !== \"string\") {\n throw new Error(\"Element vnode must have a string type\");\n }\n\n const element = strategy.createElement(vnode.type);\n const subscriptions: Array<() => void> = [];\n\n // Apply props\n const props = vnode.props || {};\n for (const [key, value] of Object.entries(props)) {\n if (key === \"key\" || key === \"children\") continue;\n\n // Handle ref separately\n if (key === \"ref\") {\n if (strategy.setRef && value != null) {\n const cleanup = strategy.setRef(element, value as Ref<TNode>);\n subscriptions.push(cleanup);\n }\n continue;\n }\n\n if (isSignal(value)) {\n const unsub = strategy.setSignalProperty(element, key, value);\n subscriptions.push(unsub);\n } else {\n strategy.setProperty(element, key, value);\n }\n }\n\n // Render children with same context\n const children = vnode.children.map((child) => renderNode(child, parentContext));\n\n // Append all child nodes (recursively handles fragments and signal wrappers)\n for (const child of children) {\n const nodes = collectNodes(child);\n for (const node of nodes) {\n strategy.appendChild(element, node);\n }\n }\n\n return {\n vnode,\n node: element,\n subscriptions,\n children,\n };\n }\n\n /**\n * Unmount a rendered node\n */\n function unmount(node: RenderedNode<TNode>): void {\n // Cleanup subscriptions\n for (const unsub of node.subscriptions) {\n unsub();\n }\n\n // Recursively unmount children\n for (const child of node.children) {\n unmount(child);\n }\n\n // Remove from tree\n if (node.node) {\n strategy.removeChild(node.node);\n }\n }\n\n /**\n * Clean up subscriptions without removing nodes from tree\n */\n function cleanupSubscriptions(node: RenderedNode<TNode>): void {\n // Cleanup subscriptions\n for (const unsub of node.subscriptions) {\n unsub();\n }\n\n // Recursively cleanup children\n for (const child of node.children) {\n cleanupSubscriptions(child);\n }\n }\n\n return {\n renderNode: renderNode,\n unmount: unmount,\n cleanupSubscriptions: cleanupSubscriptions,\n };\n}\n"],"mappings":"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"}
@@ -1,42 +1,16 @@
1
- import { t as isSignal } from "./utils-BrGmTgfG.mjs";
1
+ import { t as isSignal } from "./utils-DbTAs943.mjs";
2
2
 
3
- //#region ../style/src/hash.ts
4
- /**
5
- * Hash utilities for generating unique class names
6
- *
7
- * Uses a simple but effective hash algorithm that produces short,
8
- * deterministic strings suitable for class names.
9
- */
10
- /**
11
- * Generate a short hash from a string
12
- *
13
- * Uses djb2 algorithm for fast, deterministic hashing
14
- */
15
- function hashString(str) {
16
- let hash = 5381;
17
- for (let i = 0; i < str.length; i++) hash = (hash << 5) + hash ^ str.charCodeAt(i);
18
- return Math.abs(hash).toString(36).slice(-5);
19
- }
20
- /**
21
- * Generate a unique ID using a counter + random suffix
22
- *
23
- * Used for runtime-generated class names where determinism isn't required
24
- */
25
- let counter = 0;
26
- function uniqueId() {
27
- return (++counter).toString(36) + Math.random().toString(36).slice(2, 5);
28
- }
29
-
30
- //#endregion
31
3
  //#region ../style/src/classes.ts
32
4
  /**
33
- * Class name generation for @semajsx/style
34
- */
35
- /**
36
5
  * Symbol used to identify ClassRef objects
37
6
  */
38
7
  const CLASS_REF_BRAND = Symbol.for("@semajsx/style/classRef");
39
8
  /**
9
+ * Monotonic counter to ensure unique class names even when classes() is called
10
+ * multiple times in the same millisecond (e.g., multiple component modules).
11
+ */
12
+ let classCounter = 0;
13
+ /**
40
14
  * Create class name references with hashed values
41
15
  *
42
16
  * @example
@@ -50,7 +24,7 @@ const CLASS_REF_BRAND = Symbol.for("@semajsx/style/classRef");
50
24
  function classes(names) {
51
25
  const result = {};
52
26
  for (const name of names) {
53
- const className = `${name}-${hashString(name + Date.now().toString(36))}`;
27
+ const className = `${name}-${(++classCounter).toString(36)}`;
54
28
  const ref = {
55
29
  id: Symbol(className),
56
30
  toString() {
@@ -304,6 +278,34 @@ function preload(...styles) {
304
278
  for (const style of styles) inject(style);
305
279
  }
306
280
 
281
+ //#endregion
282
+ //#region ../style/src/hash.ts
283
+ /**
284
+ * Hash utilities for generating unique class names
285
+ *
286
+ * Uses a simple but effective hash algorithm that produces short,
287
+ * deterministic strings suitable for class names.
288
+ */
289
+ /**
290
+ * Generate a short hash from a string
291
+ *
292
+ * Uses djb2 algorithm for fast, deterministic hashing
293
+ */
294
+ function hashString(str) {
295
+ let hash = 5381;
296
+ for (let i = 0; i < str.length; i++) hash = (hash << 5) + hash ^ str.charCodeAt(i);
297
+ return Math.abs(hash).toString(36).slice(-5);
298
+ }
299
+ /**
300
+ * Generate a unique ID using a counter + random suffix
301
+ *
302
+ * Used for runtime-generated class names where determinism isn't required
303
+ */
304
+ let counter = 0;
305
+ function uniqueId() {
306
+ return (++counter).toString(36) + Math.random().toString(36).slice(2, 5);
307
+ }
308
+
307
309
  //#endregion
308
310
  //#region ../style/src/registry.ts
309
311
  /**
@@ -1001,5 +1003,5 @@ function container(query, ...tokens) {
1001
1003
  }
1002
1004
 
1003
1005
  //#endregion
1004
- export { keyframes as A, preload as B, slideRight as C, spin as D, slideUpKf as E, StyleRegistry as F, isClassRef as G, rule as H, createCx as I, hashString as K, createRegistry as L, createTheme as M, defineTokens as N, spinKf as O, isTokenRef as P, inject as R, slideLeftKf as S, slideUp as T, rules as U, isStyleToken as V, classes as W, scaleOut as _, bounce as a, slideDownKf as b, fadeInKf as c, ping as d, pingKf as f, scaleInKf as g, scaleIn as h, media as i, keyframesToken as j, isKeyframeRef as k, fadeOut as l, pulseKf as m, container as n, bounceKf as o, pulse as p, uniqueId as q, defineBreakpoints as r, fadeIn as s, breakpoints as t, fadeOutKf as u, scaleOutKf as v, slideRightKf as w, slideLeft as x, slideDown as y, injectStyles as z };
1005
- //# sourceMappingURL=src-Jbt_w0hc.mjs.map
1006
+ export { keyframes as A, inject as B, slideRight as C, spin as D, slideUpKf as E, StyleRegistry as F, rules as G, preload as H, createCx as I, classes as K, createRegistry as L, createTheme as M, defineTokens as N, spinKf as O, isTokenRef as P, hashString as R, slideLeftKf as S, slideUp as T, isStyleToken as U, injectStyles as V, rule as W, scaleOut as _, bounce as a, slideDownKf as b, fadeInKf as c, ping as d, pingKf as f, scaleInKf as g, scaleIn as h, media as i, keyframesToken as j, isKeyframeRef as k, fadeOut as l, pulseKf as m, container as n, bounceKf as o, pulse as p, isClassRef as q, defineBreakpoints as r, fadeIn as s, breakpoints as t, fadeOutKf as u, scaleOutKf as v, slideRightKf as w, slideLeft as x, slideDown as y, uniqueId as z };
1007
+ //# sourceMappingURL=src-Ds9vl42d.mjs.map