semajsx 0.6.1 → 0.7.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 (74) hide show
  1. package/dist/{client-CButR91p.mjs → client-BrupjhG0.mjs} +4 -4
  2. package/dist/{client-CButR91p.mjs.map → client-BrupjhG0.mjs.map} +1 -1
  3. package/dist/{computed-BidG06Lt.mjs → computed-BpjqvQu1.mjs} +2 -2
  4. package/dist/{computed-BidG06Lt.mjs.map → computed-BpjqvQu1.mjs.map} +1 -1
  5. package/dist/document-DsiJO2jG.mjs +5 -0
  6. package/dist/{document-BOJDaiBc.mjs → document-XKyAs62C.mjs} +2 -2
  7. package/dist/{document-BOJDaiBc.mjs.map → document-XKyAs62C.mjs.map} +1 -1
  8. package/dist/dom/index.mjs +3 -3
  9. package/dist/dom/jsx-dev-runtime.d.mts +1 -1
  10. package/dist/dom/jsx-dev-runtime.mjs +2 -2
  11. package/dist/dom/jsx-runtime.d.mts +1 -1
  12. package/dist/dom/jsx-runtime.mjs +2 -2
  13. package/dist/{index-D_FIlSk3.d.mts → index-CmxkYOtR.d.mts} +2 -2
  14. package/dist/{index-D_FIlSk3.d.mts.map → index-CmxkYOtR.d.mts.map} +1 -1
  15. package/dist/index.mjs +4 -4
  16. package/dist/{jsx-runtime-D9ZNjMJ2.mjs → jsx-runtime-BFs1c0xz.mjs} +1 -1
  17. package/dist/jsx-runtime-BFs1c0xz.mjs.map +1 -0
  18. package/dist/{jsx-runtime-tIuFmhTh.d.mts → jsx-runtime-C-TtSL51.d.mts} +9 -4
  19. package/dist/jsx-runtime-C-TtSL51.d.mts.map +1 -0
  20. package/dist/{jsx-runtime-BjCGsceN.mjs → jsx-runtime-kv_6vBiR.mjs} +1 -1
  21. package/dist/{jsx-runtime-BjCGsceN.mjs.map → jsx-runtime-kv_6vBiR.mjs.map} +1 -1
  22. package/dist/{lucide-C5BghhSl.mjs → lucide-Ddt_N9dJ.mjs} +3 -3
  23. package/dist/{lucide-C5BghhSl.mjs.map → lucide-Ddt_N9dJ.mjs.map} +1 -1
  24. package/dist/{resource-CNwiNxJX.d.mts → resource-CX-sVeS_.d.mts} +5 -2
  25. package/dist/resource-CX-sVeS_.d.mts.map +1 -0
  26. package/dist/{resource-DSlXDZZi.mjs → resource-pm7qP-jV.mjs} +2 -2
  27. package/dist/{resource-DSlXDZZi.mjs.map → resource-pm7qP-jV.mjs.map} +1 -1
  28. package/dist/signal/index.mjs +3 -3
  29. package/dist/{signal-BN8vHXDb.mjs → signal-4PgGfydw.mjs} +1 -1
  30. package/dist/{signal-BN8vHXDb.mjs.map → signal-4PgGfydw.mjs.map} +1 -1
  31. package/dist/{src-B4VBiHa8.mjs → src-CAyv9Uf9.mjs} +24 -17
  32. package/dist/src-CAyv9Uf9.mjs.map +1 -0
  33. package/dist/{src-DUpFNNM_.mjs → src-CXY-7FC3.mjs} +4 -4
  34. package/dist/{src-DUpFNNM_.mjs.map → src-CXY-7FC3.mjs.map} +1 -1
  35. package/dist/{src-BqX3sryB.mjs → src-C_aFsFJ3.mjs} +4 -4
  36. package/dist/{src-BqX3sryB.mjs.map → src-C_aFsFJ3.mjs.map} +1 -1
  37. package/dist/{src-DW3tIczg.mjs → src-Cv4rRVzv.mjs} +4 -4
  38. package/dist/{src-DW3tIczg.mjs.map → src-Cv4rRVzv.mjs.map} +1 -1
  39. package/dist/{src-Ds9vl42d.mjs → src-DV9uwtE5.mjs} +2 -2
  40. package/dist/{src-Ds9vl42d.mjs.map → src-DV9uwtE5.mjs.map} +1 -1
  41. package/dist/{src-75qcxwT_.mjs → src-SqJ6k7Xv.mjs} +13 -29
  42. package/dist/src-SqJ6k7Xv.mjs.map +1 -0
  43. package/dist/ssg/index.d.mts +1 -1
  44. package/dist/ssg/index.d.mts.map +1 -1
  45. package/dist/ssg/index.mjs +14 -9
  46. package/dist/ssg/index.mjs.map +1 -1
  47. package/dist/ssg/plugins/docs-theme.d.mts +68 -29
  48. package/dist/ssg/plugins/docs-theme.d.mts.map +1 -1
  49. package/dist/ssg/plugins/docs-theme.mjs +2747 -380
  50. package/dist/ssg/plugins/docs-theme.mjs.map +1 -1
  51. package/dist/ssg/plugins/lucide.d.mts +2 -2
  52. package/dist/ssg/plugins/lucide.mjs +5 -5
  53. package/dist/ssr/client.d.mts +1 -1
  54. package/dist/ssr/client.mjs +5 -5
  55. package/dist/ssr/index.d.mts +1 -1
  56. package/dist/ssr/index.d.mts.map +1 -1
  57. package/dist/ssr/index.mjs +8 -8
  58. package/dist/style/index.mjs +1 -1
  59. package/dist/style/react.mjs +2 -2
  60. package/dist/style/vue.mjs +2 -2
  61. package/dist/terminal/index.mjs +3 -3
  62. package/dist/terminal/jsx-dev-runtime.mjs +2 -2
  63. package/dist/terminal/jsx-runtime.mjs +2 -2
  64. package/dist/{types-BmDIxXiP.d.mts → types-BaS-zTDX.d.mts} +3 -1
  65. package/dist/{types-BmDIxXiP.d.mts.map → types-BaS-zTDX.d.mts.map} +1 -1
  66. package/dist/{utils-DbTAs943.mjs → utils-BrGmTgfG.mjs} +1 -1
  67. package/dist/{utils-DbTAs943.mjs.map → utils-BrGmTgfG.mjs.map} +1 -1
  68. package/package.json +1 -1
  69. package/dist/document-CwHVG_PJ.mjs +0 -5
  70. package/dist/jsx-runtime-D9ZNjMJ2.mjs.map +0 -1
  71. package/dist/jsx-runtime-tIuFmhTh.d.mts.map +0 -1
  72. package/dist/resource-CNwiNxJX.d.mts.map +0 -1
  73. package/dist/src-75qcxwT_.mjs.map +0 -1
  74. package/dist/src-B4VBiHa8.mjs.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"jsx-runtime-BjCGsceN.mjs","names":[],"sources":["../../terminal/src/jsx-runtime.ts"],"sourcesContent":["/**\n * JSX automatic runtime for Terminal (production)\n * Use with: @jsxImportSource @semajsx/terminal\n */\n\nimport { Fragment } from \"@semajsx/core\";\nimport type { ComponentAPI, JSXNode, VNode, WithSignals } from \"@semajsx/core\";\nimport type { TerminalStyle } from \"./types\";\n\nexport { jsx, jsxs } from \"@semajsx/core\";\nexport { Fragment };\n\n/**\n * Base terminal element attributes (without Signal support)\n */\ninterface BaseTerminalAttributes extends TerminalStyle {\n // Special props\n key?: string | number;\n children?: JSXNode;\n}\n\n/**\n * Terminal element attributes with Signal support\n * All style properties can accept Signal values\n */\nexport type TerminalAttributes = WithSignals<BaseTerminalAttributes>;\n\n/**\n * Box element attributes\n * Used for layout containers with flexbox support\n *\n * All properties support both plain values and Signals:\n * - flexDirection, justifyContent, alignItems\n * - flexGrow, flexShrink, flexBasis\n * - width, height, minWidth, minHeight, maxWidth, maxHeight\n * - margin, marginLeft, marginRight, marginTop, marginBottom\n * - padding, paddingLeft, paddingRight, paddingTop, paddingBottom\n * - border, borderColor\n * - backgroundColor\n */\nexport type BoxAttributes = TerminalAttributes;\n\n/**\n * Text element attributes\n * Used for displaying styled text content\n *\n * All properties support both plain values and Signals:\n * - color: Text color\n * - bold: Bold text\n * - italic: Italic text\n * - underline: Underlined text\n * - strikethrough: Strikethrough text\n * - dim: Dimmed text\n * - Layout props: flexGrow, flexShrink, flexBasis, margin, etc.\n */\nexport type TextAttributes = TerminalAttributes;\n\n/**\n * JSX namespace for Terminal elements\n */\nexport namespace JSX {\n export type Element = VNode;\n\n export type ElementType =\n | keyof IntrinsicElements\n | ((props: any) => JSXNode)\n | ((props: any, ctx: ComponentAPI) => JSXNode);\n\n export interface ElementChildrenAttribute {\n children: {};\n }\n\n export interface IntrinsicAttributes {\n key?: string | number;\n }\n\n export interface IntrinsicElements {\n /**\n * Box component for layout and containers\n *\n * Supports flexbox layout with Yoga:\n * - flexDirection: 'row' | 'column' | 'row-reverse' | 'column-reverse'\n * - justifyContent: 'flex-start' | 'center' | 'flex-end' | 'space-between' | 'space-around'\n * - alignItems: 'flex-start' | 'center' | 'flex-end' | 'stretch'\n *\n * Supports sizing:\n * - width, height: number | string (e.g., '50%')\n * - minWidth, minHeight, maxWidth, maxHeight: number\n *\n * Supports spacing:\n * - margin, marginLeft, marginRight, marginTop, marginBottom: number\n * - padding, paddingLeft, paddingRight, paddingTop, paddingBottom: number\n *\n * Supports borders:\n * - border: 'single' | 'double' | 'round' | 'bold' | 'none'\n * - borderColor: string (color name or hex)\n *\n * Supports background:\n * - backgroundColor: string (color name or hex)\n *\n * @example\n * <box border=\"round\" padding={1} borderColor=\"green\">\n * <text>Content</text>\n * </box>\n */\n box: BoxAttributes;\n\n /**\n * Text component for displaying styled text\n *\n * Supports text styling:\n * - color: string (color name or hex)\n * - bold: boolean\n * - italic: boolean\n * - underline: boolean\n * - strikethrough: boolean\n * - dim: boolean\n *\n * Supports layout from parent box:\n * - flexGrow, flexShrink, flexBasis\n * - margin, marginLeft, marginRight, marginTop, marginBottom\n *\n * @example\n * <text color=\"green\" bold>\n * Success message\n * </text>\n */\n text: TextAttributes;\n }\n}\n"],"mappings":""}
1
+ {"version":3,"file":"jsx-runtime-kv_6vBiR.mjs","names":[],"sources":["../../terminal/src/jsx-runtime.ts"],"sourcesContent":["/**\n * JSX automatic runtime for Terminal (production)\n * Use with: @jsxImportSource @semajsx/terminal\n */\n\nimport { Fragment } from \"@semajsx/core\";\nimport type { ComponentAPI, JSXNode, VNode, WithSignals } from \"@semajsx/core\";\nimport type { TerminalStyle } from \"./types\";\n\nexport { jsx, jsxs } from \"@semajsx/core\";\nexport { Fragment };\n\n/**\n * Base terminal element attributes (without Signal support)\n */\ninterface BaseTerminalAttributes extends TerminalStyle {\n // Special props\n key?: string | number;\n children?: JSXNode;\n}\n\n/**\n * Terminal element attributes with Signal support\n * All style properties can accept Signal values\n */\nexport type TerminalAttributes = WithSignals<BaseTerminalAttributes>;\n\n/**\n * Box element attributes\n * Used for layout containers with flexbox support\n *\n * All properties support both plain values and Signals:\n * - flexDirection, justifyContent, alignItems\n * - flexGrow, flexShrink, flexBasis\n * - width, height, minWidth, minHeight, maxWidth, maxHeight\n * - margin, marginLeft, marginRight, marginTop, marginBottom\n * - padding, paddingLeft, paddingRight, paddingTop, paddingBottom\n * - border, borderColor\n * - backgroundColor\n */\nexport type BoxAttributes = TerminalAttributes;\n\n/**\n * Text element attributes\n * Used for displaying styled text content\n *\n * All properties support both plain values and Signals:\n * - color: Text color\n * - bold: Bold text\n * - italic: Italic text\n * - underline: Underlined text\n * - strikethrough: Strikethrough text\n * - dim: Dimmed text\n * - Layout props: flexGrow, flexShrink, flexBasis, margin, etc.\n */\nexport type TextAttributes = TerminalAttributes;\n\n/**\n * JSX namespace for Terminal elements\n */\nexport namespace JSX {\n export type Element = VNode;\n\n export type ElementType =\n | keyof IntrinsicElements\n | ((props: any) => JSXNode)\n | ((props: any, ctx: ComponentAPI) => JSXNode);\n\n export interface ElementChildrenAttribute {\n children: {};\n }\n\n export interface IntrinsicAttributes {\n key?: string | number;\n }\n\n export interface IntrinsicElements {\n /**\n * Box component for layout and containers\n *\n * Supports flexbox layout with Yoga:\n * - flexDirection: 'row' | 'column' | 'row-reverse' | 'column-reverse'\n * - justifyContent: 'flex-start' | 'center' | 'flex-end' | 'space-between' | 'space-around'\n * - alignItems: 'flex-start' | 'center' | 'flex-end' | 'stretch'\n *\n * Supports sizing:\n * - width, height: number | string (e.g., '50%')\n * - minWidth, minHeight, maxWidth, maxHeight: number\n *\n * Supports spacing:\n * - margin, marginLeft, marginRight, marginTop, marginBottom: number\n * - padding, paddingLeft, paddingRight, paddingTop, paddingBottom: number\n *\n * Supports borders:\n * - border: 'single' | 'double' | 'round' | 'bold' | 'none'\n * - borderColor: string (color name or hex)\n *\n * Supports background:\n * - backgroundColor: string (color name or hex)\n *\n * @example\n * <box border=\"round\" padding={1} borderColor=\"green\">\n * <text>Content</text>\n * </box>\n */\n box: BoxAttributes;\n\n /**\n * Text component for displaying styled text\n *\n * Supports text styling:\n * - color: string (color name or hex)\n * - bold: boolean\n * - italic: boolean\n * - underline: boolean\n * - strikethrough: boolean\n * - dim: boolean\n *\n * Supports layout from parent box:\n * - flexGrow, flexShrink, flexBasis\n * - margin, marginLeft, marginRight, marginTop, marginBottom\n *\n * @example\n * <text color=\"green\" bold>\n * Success message\n * </text>\n */\n text: TextAttributes;\n }\n}\n"],"mappings":""}
@@ -1,5 +1,5 @@
1
- import { h, i as jsx } from "./src-DW3tIczg.mjs";
2
- import { t as Native } from "./src-BqX3sryB.mjs";
1
+ import { h, i as jsx } from "./src-Cv4rRVzv.mjs";
2
+ import { t as Native } from "./src-C_aFsFJ3.mjs";
3
3
  import * as allExports from "lucide";
4
4
  import { createElement } from "lucide";
5
5
 
@@ -123,4 +123,4 @@ function lucide(options = {}) {
123
123
 
124
124
  //#endregion
125
125
  export { Icon as n, lucide as t };
126
- //# sourceMappingURL=lucide-C5BghhSl.mjs.map
126
+ //# sourceMappingURL=lucide-Ddt_N9dJ.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"lucide-C5BghhSl.mjs","names":[],"sources":["../../ssg/src/plugins/lucide/component.tsx","../../ssg/src/plugins/lucide/index.ts"],"sourcesContent":["/** @jsxImportSource @semajsx/dom */\n\nimport { h } from \"@semajsx/core\";\nimport type { VNode } from \"@semajsx/core\";\nimport { Native } from \"@semajsx/dom\";\nimport { createElement } from \"lucide\";\nimport * as allExports from \"lucide\";\n\n/**\n * lucide IconNode: array of [tag, attrs] tuples\n * e.g., [[\"path\", { d: \"M4.5 16.5...\" }], [\"circle\", { cx: \"12\", ... }]]\n */\ntype IconNode = [string, Record<string, string>][];\n\n/**\n * Convert kebab-case icon name to PascalCase for lucide lookup.\n *\n * \"arrow-right\" → \"ArrowRight\"\n * \"rocket\" → \"Rocket\"\n */\nfunction toPascalCase(name: string): string {\n return name\n .split(\"-\")\n .map((part) => part.charAt(0).toUpperCase() + part.slice(1))\n .join(\"\");\n}\n\n/**\n * Look up an icon by kebab-case name from lucide's exports.\n * Returns the IconNode data (array of [tag, attrs] tuples) or undefined.\n */\nfunction getIcon(name: string): IconNode | undefined {\n const pascalName = toPascalCase(name);\n const icon = (allExports as Record<string, unknown>)[pascalName];\n // IconNode is an array of tuples; functions (createElement, createIcons) are filtered out\n if (Array.isArray(icon)) return icon as IconNode;\n return undefined;\n}\n\nexport interface IconProps {\n /** Icon name in kebab-case (e.g., \"rocket\", \"arrow-right\", \"circle-check\") */\n name: string;\n /** Icon size in pixels (default: 24) */\n size?: number;\n /** Stroke color (default: \"currentColor\") */\n color?: string;\n /** Stroke width (default: 2) */\n strokeWidth?: number;\n /** Additional CSS class */\n class?: string;\n}\n\n/**\n * Default SVG attributes matching lucide's defaults.\n */\nconst SVG_DEFAULTS = {\n xmlns: \"http://www.w3.org/2000/svg\",\n viewBox: \"0 0 24 24\",\n fill: \"none\",\n stroke: \"currentColor\",\n \"stroke-width\": 2,\n \"stroke-linecap\": \"round\",\n \"stroke-linejoin\": \"round\",\n} as const;\n\n/**\n * Isomorphic Lucide icon component.\n *\n * - **Browser**: uses lucide's `createElement` to produce a real SVGElement,\n * embedded via `<Native>` for optimal performance.\n * - **Server (SSG/SSR)**: constructs JSX SVG from IconNode data,\n * rendered to HTML string by the SSR renderer.\n *\n * @example\n * ```mdx\n * <Icon name=\"rocket\" />\n * <Icon name=\"arrow-right\" size={20} color=\"#007aff\" />\n * ```\n */\nexport function Icon({\n name,\n size = 24,\n color = \"currentColor\",\n strokeWidth = 2,\n class: className,\n}: IconProps): VNode {\n const iconNode = getIcon(name);\n\n if (!iconNode) {\n return (\n <span class=\"lucide-icon-missing\" title={`Unknown icon: ${name}`}>\n {\"?\"}\n </span>\n );\n }\n\n const iconClass = className ? `lucide lucide-${name} ${className}` : `lucide lucide-${name}`;\n\n // Browser: use lucide's createElement + Native\n if (typeof document !== \"undefined\") {\n const element = createElement(iconNode, {\n width: size,\n height: size,\n stroke: color,\n \"stroke-width\": strokeWidth,\n class: iconClass,\n });\n return <Native element={element} />;\n }\n\n // Server: construct SVG from IconNode data\n return h(\n \"svg\",\n {\n ...SVG_DEFAULTS,\n width: size,\n height: size,\n stroke: color,\n \"stroke-width\": strokeWidth,\n class: iconClass,\n },\n ...iconNode.map(([tag, attrs]) => h(tag, attrs)),\n );\n}\n","import type { SSGPlugin } from \"../../types\";\nimport { Icon, type IconProps } from \"./component\";\n\nexport type { IconProps } from \"./component\";\nexport { Icon };\n\nexport interface LucidePluginOptions {\n /** Default icon size in pixels (default: 24) */\n size?: number;\n /** Default stroke color (default: \"currentColor\") */\n color?: string;\n /** Default stroke width (default: 2) */\n strokeWidth?: number;\n}\n\n/**\n * Lucide icon plugin for SSG.\n *\n * Registers the `<Icon>` component for use in MDX content.\n * Optionally configure default icon properties.\n *\n * @example\n * ```tsx\n * import { createSSG } from \"@semajsx/ssg\";\n * import { lucide } from \"@semajsx/ssg/plugins/lucide\";\n *\n * const ssg = createSSG({\n * plugins: [lucide()],\n * });\n * ```\n *\n * @example\n * ```tsx\n * // With custom defaults\n * const ssg = createSSG({\n * plugins: [lucide({ size: 20, color: \"#333\" })],\n * });\n * ```\n *\n * @example\n * ```mdx\n * <Icon name=\"rocket\" />\n * <Icon name=\"arrow-right\" size={16} color=\"#007aff\" />\n * ```\n */\nexport function lucide(options: LucidePluginOptions = {}): SSGPlugin {\n const { size, color, strokeWidth } = options;\n const hasDefaults = size !== undefined || color !== undefined || strokeWidth !== undefined;\n\n // Wrap Icon with custom defaults if any options are provided\n const IconComponent = hasDefaults\n ? (props: IconProps) =>\n Icon({\n ...props,\n size: props.size ?? size,\n color: props.color ?? color,\n strokeWidth: props.strokeWidth ?? strokeWidth,\n })\n : Icon;\n\n return {\n name: \"lucide\",\n config() {\n return {\n mdx: {\n components: { Icon: IconComponent },\n },\n };\n },\n };\n}\n"],"mappings":";;;;;;;;;;;;;AAoBA,SAAS,aAAa,MAAsB;AAC1C,QAAO,KACJ,MAAM,IAAI,CACV,KAAK,SAAS,KAAK,OAAO,EAAE,CAAC,aAAa,GAAG,KAAK,MAAM,EAAE,CAAC,CAC3D,KAAK,GAAG;;;;;;AAOb,SAAS,QAAQ,MAAoC;CAEnD,MAAM,OAAQ,WADK,aAAa,KAAK;AAGrC,KAAI,MAAM,QAAQ,KAAK,CAAE,QAAO;;;;;AAoBlC,MAAM,eAAe;CACnB,OAAO;CACP,SAAS;CACT,MAAM;CACN,QAAQ;CACR,gBAAgB;CAChB,kBAAkB;CAClB,mBAAmB;CACpB;;;;;;;;;;;;;;;AAgBD,SAAgB,KAAK,EACnB,MACA,OAAO,IACP,QAAQ,gBACR,cAAc,GACd,OAAO,aACY;CACnB,MAAM,WAAW,QAAQ,KAAK;AAE9B,KAAI,CAAC,SACH,QACE,oBAAC;EAAK,OAAM;EAAsB,OAAO,iBAAiB;YACvD;GACI;CAIX,MAAM,YAAY,YAAY,iBAAiB,KAAK,GAAG,cAAc,iBAAiB;AAGtF,KAAI,OAAO,aAAa,YAQtB,QAAO,oBAAC,UAAO,SAPC,cAAc,UAAU;EACtC,OAAO;EACP,QAAQ;EACR,QAAQ;EACR,gBAAgB;EAChB,OAAO;EACR,CAAC,GACiC;AAIrC,QAAO,EACL,OACA;EACE,GAAG;EACH,OAAO;EACP,QAAQ;EACR,QAAQ;EACR,gBAAgB;EAChB,OAAO;EACR,EACD,GAAG,SAAS,KAAK,CAAC,KAAK,WAAW,EAAE,KAAK,MAAM,CAAC,CACjD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AC7EH,SAAgB,OAAO,UAA+B,EAAE,EAAa;CACnE,MAAM,EAAE,MAAM,OAAO,gBAAgB;CAIrC,MAAM,gBAHc,SAAS,UAAa,UAAU,UAAa,gBAAgB,UAI5E,UACC,KAAK;EACH,GAAG;EACH,MAAM,MAAM,QAAQ;EACpB,OAAO,MAAM,SAAS;EACtB,aAAa,MAAM,eAAe;EACnC,CAAC,GACJ;AAEJ,QAAO;EACL,MAAM;EACN,SAAS;AACP,UAAO,EACL,KAAK,EACH,YAAY,EAAE,MAAM,eAAe,EACpC,EACF;;EAEJ"}
1
+ {"version":3,"file":"lucide-Ddt_N9dJ.mjs","names":[],"sources":["../../ssg/src/plugins/lucide/component.tsx","../../ssg/src/plugins/lucide/index.ts"],"sourcesContent":["/** @jsxImportSource @semajsx/dom */\n\nimport { h } from \"@semajsx/core\";\nimport type { VNode } from \"@semajsx/core\";\nimport { Native } from \"@semajsx/dom\";\nimport { createElement } from \"lucide\";\nimport * as allExports from \"lucide\";\n\n/**\n * lucide IconNode: array of [tag, attrs] tuples\n * e.g., [[\"path\", { d: \"M4.5 16.5...\" }], [\"circle\", { cx: \"12\", ... }]]\n */\ntype IconNode = [string, Record<string, string>][];\n\n/**\n * Convert kebab-case icon name to PascalCase for lucide lookup.\n *\n * \"arrow-right\" → \"ArrowRight\"\n * \"rocket\" → \"Rocket\"\n */\nfunction toPascalCase(name: string): string {\n return name\n .split(\"-\")\n .map((part) => part.charAt(0).toUpperCase() + part.slice(1))\n .join(\"\");\n}\n\n/**\n * Look up an icon by kebab-case name from lucide's exports.\n * Returns the IconNode data (array of [tag, attrs] tuples) or undefined.\n */\nfunction getIcon(name: string): IconNode | undefined {\n const pascalName = toPascalCase(name);\n const icon = (allExports as Record<string, unknown>)[pascalName];\n // IconNode is an array of tuples; functions (createElement, createIcons) are filtered out\n if (Array.isArray(icon)) return icon as IconNode;\n return undefined;\n}\n\nexport interface IconProps {\n /** Icon name in kebab-case (e.g., \"rocket\", \"arrow-right\", \"circle-check\") */\n name: string;\n /** Icon size in pixels (default: 24) */\n size?: number;\n /** Stroke color (default: \"currentColor\") */\n color?: string;\n /** Stroke width (default: 2) */\n strokeWidth?: number;\n /** Additional CSS class */\n class?: string;\n}\n\n/**\n * Default SVG attributes matching lucide's defaults.\n */\nconst SVG_DEFAULTS = {\n xmlns: \"http://www.w3.org/2000/svg\",\n viewBox: \"0 0 24 24\",\n fill: \"none\",\n stroke: \"currentColor\",\n \"stroke-width\": 2,\n \"stroke-linecap\": \"round\",\n \"stroke-linejoin\": \"round\",\n} as const;\n\n/**\n * Isomorphic Lucide icon component.\n *\n * - **Browser**: uses lucide's `createElement` to produce a real SVGElement,\n * embedded via `<Native>` for optimal performance.\n * - **Server (SSG/SSR)**: constructs JSX SVG from IconNode data,\n * rendered to HTML string by the SSR renderer.\n *\n * @example\n * ```mdx\n * <Icon name=\"rocket\" />\n * <Icon name=\"arrow-right\" size={20} color=\"#007aff\" />\n * ```\n */\nexport function Icon({\n name,\n size = 24,\n color = \"currentColor\",\n strokeWidth = 2,\n class: className,\n}: IconProps): VNode {\n const iconNode = getIcon(name);\n\n if (!iconNode) {\n return (\n <span class=\"lucide-icon-missing\" title={`Unknown icon: ${name}`}>\n {\"?\"}\n </span>\n );\n }\n\n const iconClass = className ? `lucide lucide-${name} ${className}` : `lucide lucide-${name}`;\n\n // Browser: use lucide's createElement + Native\n if (typeof document !== \"undefined\") {\n const element = createElement(iconNode, {\n width: size,\n height: size,\n stroke: color,\n \"stroke-width\": strokeWidth,\n class: iconClass,\n });\n return <Native element={element} />;\n }\n\n // Server: construct SVG from IconNode data\n return h(\n \"svg\",\n {\n ...SVG_DEFAULTS,\n width: size,\n height: size,\n stroke: color,\n \"stroke-width\": strokeWidth,\n class: iconClass,\n },\n ...iconNode.map(([tag, attrs]) => h(tag, attrs)),\n );\n}\n","import type { SSGPlugin } from \"../../types\";\nimport { Icon, type IconProps } from \"./component\";\n\nexport type { IconProps } from \"./component\";\nexport { Icon };\n\nexport interface LucidePluginOptions {\n /** Default icon size in pixels (default: 24) */\n size?: number;\n /** Default stroke color (default: \"currentColor\") */\n color?: string;\n /** Default stroke width (default: 2) */\n strokeWidth?: number;\n}\n\n/**\n * Lucide icon plugin for SSG.\n *\n * Registers the `<Icon>` component for use in MDX content.\n * Optionally configure default icon properties.\n *\n * @example\n * ```tsx\n * import { createSSG } from \"@semajsx/ssg\";\n * import { lucide } from \"@semajsx/ssg/plugins/lucide\";\n *\n * const ssg = createSSG({\n * plugins: [lucide()],\n * });\n * ```\n *\n * @example\n * ```tsx\n * // With custom defaults\n * const ssg = createSSG({\n * plugins: [lucide({ size: 20, color: \"#333\" })],\n * });\n * ```\n *\n * @example\n * ```mdx\n * <Icon name=\"rocket\" />\n * <Icon name=\"arrow-right\" size={16} color=\"#007aff\" />\n * ```\n */\nexport function lucide(options: LucidePluginOptions = {}): SSGPlugin {\n const { size, color, strokeWidth } = options;\n const hasDefaults = size !== undefined || color !== undefined || strokeWidth !== undefined;\n\n // Wrap Icon with custom defaults if any options are provided\n const IconComponent = hasDefaults\n ? (props: IconProps) =>\n Icon({\n ...props,\n size: props.size ?? size,\n color: props.color ?? color,\n strokeWidth: props.strokeWidth ?? strokeWidth,\n })\n : Icon;\n\n return {\n name: \"lucide\",\n config() {\n return {\n mdx: {\n components: { Icon: IconComponent },\n },\n };\n },\n };\n}\n"],"mappings":";;;;;;;;;;;;;AAoBA,SAAS,aAAa,MAAsB;AAC1C,QAAO,KACJ,MAAM,IAAI,CACV,KAAK,SAAS,KAAK,OAAO,EAAE,CAAC,aAAa,GAAG,KAAK,MAAM,EAAE,CAAC,CAC3D,KAAK,GAAG;;;;;;AAOb,SAAS,QAAQ,MAAoC;CAEnD,MAAM,OAAQ,WADK,aAAa,KAAK;AAGrC,KAAI,MAAM,QAAQ,KAAK,CAAE,QAAO;;;;;AAoBlC,MAAM,eAAe;CACnB,OAAO;CACP,SAAS;CACT,MAAM;CACN,QAAQ;CACR,gBAAgB;CAChB,kBAAkB;CAClB,mBAAmB;CACpB;;;;;;;;;;;;;;;AAgBD,SAAgB,KAAK,EACnB,MACA,OAAO,IACP,QAAQ,gBACR,cAAc,GACd,OAAO,aACY;CACnB,MAAM,WAAW,QAAQ,KAAK;AAE9B,KAAI,CAAC,SACH,QACE,oBAAC;EAAK,OAAM;EAAsB,OAAO,iBAAiB;YACvD;GACI;CAIX,MAAM,YAAY,YAAY,iBAAiB,KAAK,GAAG,cAAc,iBAAiB;AAGtF,KAAI,OAAO,aAAa,YAQtB,QAAO,oBAAC,UAAO,SAPC,cAAc,UAAU;EACtC,OAAO;EACP,QAAQ;EACR,QAAQ;EACR,gBAAgB;EAChB,OAAO;EACR,CAAC,GACiC;AAIrC,QAAO,EACL,OACA;EACE,GAAG;EACH,OAAO;EACP,QAAQ;EACR,QAAQ;EACR,gBAAgB;EAChB,OAAO;EACR,EACD,GAAG,SAAS,KAAK,CAAC,KAAK,WAAW,EAAE,KAAK,MAAM,CAAC,CACjD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AC7EH,SAAgB,OAAO,UAA+B,EAAE,EAAa;CACnE,MAAM,EAAE,MAAM,OAAO,gBAAgB;CAIrC,MAAM,gBAHc,SAAS,UAAa,UAAU,UAAa,gBAAgB,UAI5E,UACC,KAAK;EACH,GAAG;EACH,MAAM,MAAM,QAAQ;EACpB,OAAO,MAAM,SAAS;EACtB,aAAa,MAAM,eAAe;EACnC,CAAC,GACJ;AAEJ,QAAO;EACL,MAAM;EACN,SAAS;AACP,UAAO,EACL,KAAK,EACH,YAAY,EAAE,MAAM,eAAe,EACpC,EACF;;EAEJ"}
@@ -65,6 +65,8 @@ interface SSRResult {
65
65
  document?: string;
66
66
  /** Collected CSS file paths */
67
67
  css: string[];
68
+ /** Collected inline CSS from StyleTokens */
69
+ styles: string[];
68
70
  /** Collected asset file paths */
69
71
  assets: string[];
70
72
  }
@@ -232,7 +234,8 @@ interface BuildOptions {
232
234
  */
233
235
  renderHtml?: (opts: {
234
236
  /** Rendered page content (HTML string) */html: string; /** CSS stylesheet paths */
235
- css: string[]; /** Island script entries to include */
237
+ css: string[]; /** Inline CSS collected from StyleTokens */
238
+ styles: string[]; /** Island script entries to include */
236
239
  scripts: BuildScriptEntry[]; /** Page title */
237
240
  title: string; /** Route path */
238
241
  path: string;
@@ -386,4 +389,4 @@ declare function isLinkVNode(vnode: VNode): boolean;
386
389
  declare function isAssetVNode(vnode: VNode): boolean;
387
390
  //#endregion
388
391
  export { RouterConfig as A, IslandScriptTransformer as C, RouteContext as D, RenderToStringOptions as E, RouteHandler as O, IslandScriptContext as S, RenderResult as T, BuildScriptEntry as _, ResourceTools as a, IslandMarker as b, isAssetVNode as c, resource as d, App as f, BuildResult as g, BuildOptions as h, LinkProps as i, SSRResult as j, RouteMeta as k, isLinkVNode as l, AssetMetadata as m, AssetProps as n, STYLE_MARKER as o, AppConfig as p, LINK_MARKER as r, StyleProps as s, ASSET_MARKER as t, isStyleVNode as u, DevOptions as v, LinkMetadata as w, IslandMetadata as x, DocumentTemplate as y };
389
- //# sourceMappingURL=resource-CNwiNxJX.d.mts.map
392
+ //# sourceMappingURL=resource-CX-sVeS_.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resource-CX-sVeS_.d.mts","names":[],"sources":["../../ssr/src/shared/types.ts","../../ssr/src/client/resource.ts"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { f as ISLAND_MARKER } from "./src-DW3tIczg.mjs";
1
+ import { f as ISLAND_MARKER } from "./src-Cv4rRVzv.mjs";
2
2
 
3
3
  //#region ../ssr/src/client/island.ts
4
4
  /**
@@ -193,4 +193,4 @@ function isAssetVNode(vnode) {
193
193
 
194
194
  //#endregion
195
195
  export { isLinkVNode as a, getIslandMetadata as c, island as d, isAssetVNode as i, isIslandComponent as l, LINK_MARKER as n, isStyleVNode as o, STYLE_MARKER as r, resource as s, ASSET_MARKER as t, isIslandVNode as u };
196
- //# sourceMappingURL=resource-DSlXDZZi.mjs.map
196
+ //# sourceMappingURL=resource-pm7qP-jV.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"resource-DSlXDZZi.mjs","names":[],"sources":["../../ssr/src/client/island.ts","../../ssr/src/client/resource.ts"],"sourcesContent":["import { ISLAND_MARKER, type Component, type JSXNode, type VNode } from \"@semajsx/core\";\nimport type { IslandMarker } from \"../shared/types\";\n\n/**\n * Mark a component as an Island that should be hydrated on the client\n *\n * @param component - The component function to mark as an island\n * @param modulePath - The module path to the component file (use import.meta.url or relative path)\n * @returns A wrapped component that can be used in SSR\n *\n * @example\n * ```tsx\n * // Using import.meta.url (recommended)\n * export const Counter = island(\n * function Counter({ initial = 0 }) {\n * const count = signal(initial)\n * return <button onClick={() => count.value++}>{count}</button>\n * },\n * import.meta.url\n * )\n *\n * // Using relative path\n * export const TodoList = island(\n * TodoListComponent,\n * './components/TodoList.tsx'\n * )\n * ```\n */\nexport function island<T extends Component<any>>(component: T, modulePath: string): T {\n // Create a wrapped component that marks itself as an island\n const wrappedComponent = ((props: any): JSXNode => {\n // Create a VNode with island marker\n const vnode: VNode & { [ISLAND_MARKER]?: IslandMarker } = {\n type: component,\n props: props || {},\n children: [],\n [ISLAND_MARKER]: {\n modulePath,\n component,\n props,\n },\n };\n\n return vnode;\n }) as T;\n\n // Also mark the wrapper function itself for static analysis\n (wrappedComponent as any)[ISLAND_MARKER] = {\n modulePath,\n component,\n };\n\n // Preserve component name for debugging\n Object.defineProperty(wrappedComponent, \"name\", {\n value: component.name || \"IslandComponent\",\n configurable: true,\n });\n\n return wrappedComponent;\n}\n\n/**\n * Check if a component is marked as an Island\n */\nexport function isIslandComponent(component: any): boolean {\n return component && ISLAND_MARKER in component;\n}\n\n/**\n * Check if a VNode is an Island instance\n */\nexport function isIslandVNode(vnode: VNode): vnode is VNode & {\n [ISLAND_MARKER]: IslandMarker;\n} {\n return ISLAND_MARKER in vnode;\n}\n\n/**\n * Get island metadata from a VNode\n */\nexport function getIslandMetadata(vnode: VNode): IslandMarker | undefined {\n if (isIslandVNode(vnode)) {\n return vnode[ISLAND_MARKER];\n }\n return undefined;\n}\n","import { ISLAND_MARKER, type Component, type JSXNode, type VNode } from \"@semajsx/core\";\nimport type { IslandMarker } from \"../shared/types\";\n\n/**\n * Symbol markers for resource types\n */\nexport const STYLE_MARKER: symbol = Symbol.for(\"semajsx.style\");\nexport const LINK_MARKER: symbol = Symbol.for(\"semajsx.link\");\nexport const ASSET_MARKER: symbol = Symbol.for(\"semajsx.asset\");\n\n/**\n * Style component props\n */\nexport interface StyleProps {\n href: string;\n}\n\n/**\n * Link component props\n */\nexport interface LinkProps {\n href: string;\n rel?: string;\n as?: string;\n}\n\n/**\n * Asset component props\n */\nexport interface AssetProps {\n src: string;\n type?: \"image\" | \"font\" | \"script\";\n}\n\n/**\n * Resource tools returned by resource()\n */\nexport interface ResourceTools {\n /** CSS stylesheet declaration */\n Style: (props: StyleProps) => VNode;\n /** External resource link */\n Link: (props: LinkProps) => VNode;\n /** Static asset declaration */\n Asset: (props: AssetProps) => VNode;\n /** Resolve relative path to absolute */\n url: (path: string) => string;\n /** Create an island component */\n island: <T extends Component<any>>(component: T, name?: string) => T;\n}\n\n/**\n * Create resource tools bound to a module path\n *\n * @param baseUrl - The module URL (use import.meta.url)\n * @returns Resource tools with resolved paths\n *\n * @example\n * ```tsx\n * import { resource } from '@semajsx/ssr';\n *\n * const { Style, Link, Asset, url, island } = resource(import.meta.url);\n *\n * export default function Page() {\n * return (\n * <>\n * <Style href=\"./page.css\" />\n * <img src={url('./hero.png')} />\n * <Counter />\n * </>\n * );\n * }\n *\n * const Counter = island(function Counter({ initial = 0 }) {\n * return <button>{initial}</button>;\n * });\n * ```\n */\nexport function resource(baseUrl: string): ResourceTools {\n /**\n * Resolve a relative path against the base URL\n */\n const resolve = (href: string): string => {\n if (href.startsWith(\"./\") || href.startsWith(\"../\")) {\n const url = new URL(href, baseUrl);\n return url.pathname + url.search + url.hash;\n }\n return href;\n };\n\n return {\n Style({ href }: StyleProps): VNode {\n return {\n type: STYLE_MARKER as unknown as string,\n props: { href: resolve(href) },\n children: [],\n };\n },\n\n Link({ href, rel = \"stylesheet\", as: asType }: LinkProps): VNode {\n return {\n type: LINK_MARKER as unknown as string,\n props: { href: resolve(href), rel, as: asType },\n children: [],\n };\n },\n\n Asset({ src, type = \"image\" }: AssetProps): VNode {\n return {\n type: ASSET_MARKER as unknown as string,\n props: { src: resolve(src), type },\n children: [],\n };\n },\n\n url(path: string): string {\n return resolve(path);\n },\n\n island<T extends Component<any>>(component: T, name?: string): T {\n const componentName = name || component.name || \"Anonymous\";\n\n const wrappedComponent = ((props: Record<string, unknown>): JSXNode => {\n const vnode: VNode & { [ISLAND_MARKER]?: IslandMarker } = {\n type: component,\n props: props || {},\n children: [],\n [ISLAND_MARKER]: {\n modulePath: baseUrl,\n component,\n props,\n },\n };\n\n return vnode;\n }) as T;\n\n // Mark the wrapper function for static analysis\n (wrappedComponent as Record<symbol, unknown>)[ISLAND_MARKER] = {\n modulePath: baseUrl,\n component,\n };\n\n // Preserve component name\n Object.defineProperty(wrappedComponent, \"name\", {\n value: componentName,\n configurable: true,\n });\n\n return wrappedComponent;\n },\n };\n}\n\n/**\n * Check if a VNode is a Style resource\n */\nexport function isStyleVNode(vnode: VNode): boolean {\n return vnode.type === STYLE_MARKER;\n}\n\n/**\n * Check if a VNode is a Link resource\n */\nexport function isLinkVNode(vnode: VNode): boolean {\n return vnode.type === LINK_MARKER;\n}\n\n/**\n * Check if a VNode is an Asset resource\n */\nexport function isAssetVNode(vnode: VNode): boolean {\n return vnode.type === ASSET_MARKER;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4BA,SAAgB,OAAiC,WAAc,YAAuB;CAEpF,MAAM,qBAAqB,UAAwB;AAajD,SAX0D;GACxD,MAAM;GACN,OAAO,SAAS,EAAE;GAClB,UAAU,EAAE;IACX,gBAAgB;IACf;IACA;IACA;IACD;GACF;;AAMH,CAAC,iBAAyB,iBAAiB;EACzC;EACA;EACD;AAGD,QAAO,eAAe,kBAAkB,QAAQ;EAC9C,OAAO,UAAU,QAAQ;EACzB,cAAc;EACf,CAAC;AAEF,QAAO;;;;;AAMT,SAAgB,kBAAkB,WAAyB;AACzD,QAAO,aAAa,iBAAiB;;;;;AAMvC,SAAgB,cAAc,OAE5B;AACA,QAAO,iBAAiB;;;;;AAM1B,SAAgB,kBAAkB,OAAwC;AACxE,KAAI,cAAc,MAAM,CACtB,QAAO,MAAM;;;;;;;;AC5EjB,MAAa,eAAuB,OAAO,IAAI,gBAAgB;AAC/D,MAAa,cAAsB,OAAO,IAAI,eAAe;AAC7D,MAAa,eAAuB,OAAO,IAAI,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAqE/D,SAAgB,SAAS,SAAgC;;;;CAIvD,MAAM,WAAW,SAAyB;AACxC,MAAI,KAAK,WAAW,KAAK,IAAI,KAAK,WAAW,MAAM,EAAE;GACnD,MAAM,MAAM,IAAI,IAAI,MAAM,QAAQ;AAClC,UAAO,IAAI,WAAW,IAAI,SAAS,IAAI;;AAEzC,SAAO;;AAGT,QAAO;EACL,MAAM,EAAE,QAA2B;AACjC,UAAO;IACL,MAAM;IACN,OAAO,EAAE,MAAM,QAAQ,KAAK,EAAE;IAC9B,UAAU,EAAE;IACb;;EAGH,KAAK,EAAE,MAAM,MAAM,cAAc,IAAI,UAA4B;AAC/D,UAAO;IACL,MAAM;IACN,OAAO;KAAE,MAAM,QAAQ,KAAK;KAAE;KAAK,IAAI;KAAQ;IAC/C,UAAU,EAAE;IACb;;EAGH,MAAM,EAAE,KAAK,OAAO,WAA8B;AAChD,UAAO;IACL,MAAM;IACN,OAAO;KAAE,KAAK,QAAQ,IAAI;KAAE;KAAM;IAClC,UAAU,EAAE;IACb;;EAGH,IAAI,MAAsB;AACxB,UAAO,QAAQ,KAAK;;EAGtB,OAAiC,WAAc,MAAkB;GAC/D,MAAM,gBAAgB,QAAQ,UAAU,QAAQ;GAEhD,MAAM,qBAAqB,UAA4C;AAYrE,WAX0D;KACxD,MAAM;KACN,OAAO,SAAS,EAAE;KAClB,UAAU,EAAE;MACX,gBAAgB;MACf,YAAY;MACZ;MACA;MACD;KACF;;AAMH,GAAC,iBAA6C,iBAAiB;IAC7D,YAAY;IACZ;IACD;AAGD,UAAO,eAAe,kBAAkB,QAAQ;IAC9C,OAAO;IACP,cAAc;IACf,CAAC;AAEF,UAAO;;EAEV;;;;;AAMH,SAAgB,aAAa,OAAuB;AAClD,QAAO,MAAM,SAAS;;;;;AAMxB,SAAgB,YAAY,OAAuB;AACjD,QAAO,MAAM,SAAS;;;;;AAMxB,SAAgB,aAAa,OAAuB;AAClD,QAAO,MAAM,SAAS"}
1
+ {"version":3,"file":"resource-pm7qP-jV.mjs","names":[],"sources":["../../ssr/src/client/island.ts","../../ssr/src/client/resource.ts"],"sourcesContent":["import { ISLAND_MARKER, type Component, type JSXNode, type VNode } from \"@semajsx/core\";\nimport type { IslandMarker } from \"../shared/types\";\n\n/**\n * Mark a component as an Island that should be hydrated on the client\n *\n * @param component - The component function to mark as an island\n * @param modulePath - The module path to the component file (use import.meta.url or relative path)\n * @returns A wrapped component that can be used in SSR\n *\n * @example\n * ```tsx\n * // Using import.meta.url (recommended)\n * export const Counter = island(\n * function Counter({ initial = 0 }) {\n * const count = signal(initial)\n * return <button onClick={() => count.value++}>{count}</button>\n * },\n * import.meta.url\n * )\n *\n * // Using relative path\n * export const TodoList = island(\n * TodoListComponent,\n * './components/TodoList.tsx'\n * )\n * ```\n */\nexport function island<T extends Component<any>>(component: T, modulePath: string): T {\n // Create a wrapped component that marks itself as an island\n const wrappedComponent = ((props: any): JSXNode => {\n // Create a VNode with island marker\n const vnode: VNode & { [ISLAND_MARKER]?: IslandMarker } = {\n type: component,\n props: props || {},\n children: [],\n [ISLAND_MARKER]: {\n modulePath,\n component,\n props,\n },\n };\n\n return vnode;\n }) as T;\n\n // Also mark the wrapper function itself for static analysis\n (wrappedComponent as any)[ISLAND_MARKER] = {\n modulePath,\n component,\n };\n\n // Preserve component name for debugging\n Object.defineProperty(wrappedComponent, \"name\", {\n value: component.name || \"IslandComponent\",\n configurable: true,\n });\n\n return wrappedComponent;\n}\n\n/**\n * Check if a component is marked as an Island\n */\nexport function isIslandComponent(component: any): boolean {\n return component && ISLAND_MARKER in component;\n}\n\n/**\n * Check if a VNode is an Island instance\n */\nexport function isIslandVNode(vnode: VNode): vnode is VNode & {\n [ISLAND_MARKER]: IslandMarker;\n} {\n return ISLAND_MARKER in vnode;\n}\n\n/**\n * Get island metadata from a VNode\n */\nexport function getIslandMetadata(vnode: VNode): IslandMarker | undefined {\n if (isIslandVNode(vnode)) {\n return vnode[ISLAND_MARKER];\n }\n return undefined;\n}\n","import { ISLAND_MARKER, type Component, type JSXNode, type VNode } from \"@semajsx/core\";\nimport type { IslandMarker } from \"../shared/types\";\n\n/**\n * Symbol markers for resource types\n */\nexport const STYLE_MARKER: symbol = Symbol.for(\"semajsx.style\");\nexport const LINK_MARKER: symbol = Symbol.for(\"semajsx.link\");\nexport const ASSET_MARKER: symbol = Symbol.for(\"semajsx.asset\");\n\n/**\n * Style component props\n */\nexport interface StyleProps {\n href: string;\n}\n\n/**\n * Link component props\n */\nexport interface LinkProps {\n href: string;\n rel?: string;\n as?: string;\n}\n\n/**\n * Asset component props\n */\nexport interface AssetProps {\n src: string;\n type?: \"image\" | \"font\" | \"script\";\n}\n\n/**\n * Resource tools returned by resource()\n */\nexport interface ResourceTools {\n /** CSS stylesheet declaration */\n Style: (props: StyleProps) => VNode;\n /** External resource link */\n Link: (props: LinkProps) => VNode;\n /** Static asset declaration */\n Asset: (props: AssetProps) => VNode;\n /** Resolve relative path to absolute */\n url: (path: string) => string;\n /** Create an island component */\n island: <T extends Component<any>>(component: T, name?: string) => T;\n}\n\n/**\n * Create resource tools bound to a module path\n *\n * @param baseUrl - The module URL (use import.meta.url)\n * @returns Resource tools with resolved paths\n *\n * @example\n * ```tsx\n * import { resource } from '@semajsx/ssr';\n *\n * const { Style, Link, Asset, url, island } = resource(import.meta.url);\n *\n * export default function Page() {\n * return (\n * <>\n * <Style href=\"./page.css\" />\n * <img src={url('./hero.png')} />\n * <Counter />\n * </>\n * );\n * }\n *\n * const Counter = island(function Counter({ initial = 0 }) {\n * return <button>{initial}</button>;\n * });\n * ```\n */\nexport function resource(baseUrl: string): ResourceTools {\n /**\n * Resolve a relative path against the base URL\n */\n const resolve = (href: string): string => {\n if (href.startsWith(\"./\") || href.startsWith(\"../\")) {\n const url = new URL(href, baseUrl);\n return url.pathname + url.search + url.hash;\n }\n return href;\n };\n\n return {\n Style({ href }: StyleProps): VNode {\n return {\n type: STYLE_MARKER as unknown as string,\n props: { href: resolve(href) },\n children: [],\n };\n },\n\n Link({ href, rel = \"stylesheet\", as: asType }: LinkProps): VNode {\n return {\n type: LINK_MARKER as unknown as string,\n props: { href: resolve(href), rel, as: asType },\n children: [],\n };\n },\n\n Asset({ src, type = \"image\" }: AssetProps): VNode {\n return {\n type: ASSET_MARKER as unknown as string,\n props: { src: resolve(src), type },\n children: [],\n };\n },\n\n url(path: string): string {\n return resolve(path);\n },\n\n island<T extends Component<any>>(component: T, name?: string): T {\n const componentName = name || component.name || \"Anonymous\";\n\n const wrappedComponent = ((props: Record<string, unknown>): JSXNode => {\n const vnode: VNode & { [ISLAND_MARKER]?: IslandMarker } = {\n type: component,\n props: props || {},\n children: [],\n [ISLAND_MARKER]: {\n modulePath: baseUrl,\n component,\n props,\n },\n };\n\n return vnode;\n }) as T;\n\n // Mark the wrapper function for static analysis\n (wrappedComponent as Record<symbol, unknown>)[ISLAND_MARKER] = {\n modulePath: baseUrl,\n component,\n };\n\n // Preserve component name\n Object.defineProperty(wrappedComponent, \"name\", {\n value: componentName,\n configurable: true,\n });\n\n return wrappedComponent;\n },\n };\n}\n\n/**\n * Check if a VNode is a Style resource\n */\nexport function isStyleVNode(vnode: VNode): boolean {\n return vnode.type === STYLE_MARKER;\n}\n\n/**\n * Check if a VNode is a Link resource\n */\nexport function isLinkVNode(vnode: VNode): boolean {\n return vnode.type === LINK_MARKER;\n}\n\n/**\n * Check if a VNode is an Asset resource\n */\nexport function isAssetVNode(vnode: VNode): boolean {\n return vnode.type === ASSET_MARKER;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4BA,SAAgB,OAAiC,WAAc,YAAuB;CAEpF,MAAM,qBAAqB,UAAwB;AAajD,SAX0D;GACxD,MAAM;GACN,OAAO,SAAS,EAAE;GAClB,UAAU,EAAE;IACX,gBAAgB;IACf;IACA;IACA;IACD;GACF;;AAMH,CAAC,iBAAyB,iBAAiB;EACzC;EACA;EACD;AAGD,QAAO,eAAe,kBAAkB,QAAQ;EAC9C,OAAO,UAAU,QAAQ;EACzB,cAAc;EACf,CAAC;AAEF,QAAO;;;;;AAMT,SAAgB,kBAAkB,WAAyB;AACzD,QAAO,aAAa,iBAAiB;;;;;AAMvC,SAAgB,cAAc,OAE5B;AACA,QAAO,iBAAiB;;;;;AAM1B,SAAgB,kBAAkB,OAAwC;AACxE,KAAI,cAAc,MAAM,CACtB,QAAO,MAAM;;;;;;;;AC5EjB,MAAa,eAAuB,OAAO,IAAI,gBAAgB;AAC/D,MAAa,cAAsB,OAAO,IAAI,eAAe;AAC7D,MAAa,eAAuB,OAAO,IAAI,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAqE/D,SAAgB,SAAS,SAAgC;;;;CAIvD,MAAM,WAAW,SAAyB;AACxC,MAAI,KAAK,WAAW,KAAK,IAAI,KAAK,WAAW,MAAM,EAAE;GACnD,MAAM,MAAM,IAAI,IAAI,MAAM,QAAQ;AAClC,UAAO,IAAI,WAAW,IAAI,SAAS,IAAI;;AAEzC,SAAO;;AAGT,QAAO;EACL,MAAM,EAAE,QAA2B;AACjC,UAAO;IACL,MAAM;IACN,OAAO,EAAE,MAAM,QAAQ,KAAK,EAAE;IAC9B,UAAU,EAAE;IACb;;EAGH,KAAK,EAAE,MAAM,MAAM,cAAc,IAAI,UAA4B;AAC/D,UAAO;IACL,MAAM;IACN,OAAO;KAAE,MAAM,QAAQ,KAAK;KAAE;KAAK,IAAI;KAAQ;IAC/C,UAAU,EAAE;IACb;;EAGH,MAAM,EAAE,KAAK,OAAO,WAA8B;AAChD,UAAO;IACL,MAAM;IACN,OAAO;KAAE,KAAK,QAAQ,IAAI;KAAE;KAAM;IAClC,UAAU,EAAE;IACb;;EAGH,IAAI,MAAsB;AACxB,UAAO,QAAQ,KAAK;;EAGtB,OAAiC,WAAc,MAAkB;GAC/D,MAAM,gBAAgB,QAAQ,UAAU,QAAQ;GAEhD,MAAM,qBAAqB,UAA4C;AAYrE,WAX0D;KACxD,MAAM;KACN,OAAO,SAAS,EAAE;KAClB,UAAU,EAAE;MACX,gBAAgB;MACf,YAAY;MACZ;MACA;MACD;KACF;;AAMH,GAAC,iBAA6C,iBAAiB;IAC7D,YAAY;IACZ;IACD;AAGD,UAAO,eAAe,kBAAkB,QAAQ;IAC9C,OAAO;IACP,cAAc;IACf,CAAC;AAEF,UAAO;;EAEV;;;;;AAMH,SAAgB,aAAa,OAAuB;AAClD,QAAO,MAAM,SAAS;;;;;AAMxB,SAAgB,YAAY,OAAuB;AACjD,QAAO,MAAM,SAAS;;;;;AAMxB,SAAgB,aAAa,OAAuB;AAClD,QAAO,MAAM,SAAS"}
@@ -1,5 +1,5 @@
1
- import { n as batch, t as signal } from "../signal-BN8vHXDb.mjs";
2
- import { n as memo, t as computed } from "../computed-BidG06Lt.mjs";
3
- import { n as unwrap, t as isSignal } from "../utils-DbTAs943.mjs";
1
+ import { n as batch, t as signal } from "../signal-4PgGfydw.mjs";
2
+ import { n as memo, t as computed } from "../computed-BpjqvQu1.mjs";
3
+ import { n as unwrap, t as isSignal } from "../utils-BrGmTgfG.mjs";
4
4
 
5
5
  export { batch, computed, isSignal, memo, signal, unwrap };
@@ -91,4 +91,4 @@ function signal(initialValue) {
91
91
 
92
92
  //#endregion
93
93
  export { batch as n, scheduleUpdate as r, signal as t };
94
- //# sourceMappingURL=signal-BN8vHXDb.mjs.map
94
+ //# sourceMappingURL=signal-4PgGfydw.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"signal-BN8vHXDb.mjs","names":[],"sources":["../../signal/src/batch.ts","../../signal/src/signal.ts"],"sourcesContent":["/**\n * Batch multiple signal updates using microtask scheduling\n *\n * Updates are collected and executed in a single microtask to prevent\n * multiple synchronous DOM updates and layout thrashing.\n */\n\n// Queue of pending updates\nlet updateQueue = new Set<() => void>();\nlet isFlushScheduled = false;\nlet isBatching = false;\n\n/**\n * Schedule a notification to run in a microtask\n */\nexport function scheduleUpdate(notify: () => void): void {\n // If we're in a batch, always queue the update\n if (isBatching) {\n updateQueue.add(notify);\n return;\n }\n\n // If not batching, check if we should schedule a flush\n updateQueue.add(notify);\n\n if (!isFlushScheduled) {\n isFlushScheduled = true;\n queueMicrotask(flushUpdates);\n }\n}\n\n/**\n * Flush all pending updates\n */\nfunction flushUpdates(): void {\n isFlushScheduled = false;\n\n // Copy and clear the queue to handle updates that trigger new updates\n const updates = Array.from(updateQueue);\n updateQueue.clear();\n\n // Execute all updates\n for (const notify of updates) {\n notify();\n }\n}\n\n/**\n * Batch multiple signal updates\n * All updates inside the batch function will be deferred until the batch completes\n */\nexport function batch<T>(fn: () => T): T {\n // If already batching, just run the function\n if (isBatching) {\n return fn();\n }\n\n isBatching = true;\n\n try {\n const result = fn();\n return result;\n } finally {\n isBatching = false;\n\n // Flush all queued updates immediately after the batch\n if (updateQueue.size > 0) {\n const updates = Array.from(updateQueue);\n updateQueue.clear();\n\n for (const notify of updates) {\n notify();\n }\n }\n }\n}\n","import type { WritableSignal } from \"./types\";\nimport { scheduleUpdate } from \"./batch\";\n\n/**\n * Create a writable signal\n */\nexport function signal<T>(initialValue: T): WritableSignal<T> {\n let value = initialValue;\n const subscribers = new Set<(value: T) => void>();\n\n const sig: WritableSignal<T> = {\n get value() {\n return value;\n },\n\n set value(newValue: T) {\n if (!Object.is(value, newValue)) {\n value = newValue;\n notify();\n }\n },\n\n set(newValue: T) {\n this.value = newValue;\n },\n\n update(fn: (prev: T) => T) {\n this.value = fn(value);\n },\n\n subscribe(listener: (value: T) => void) {\n subscribers.add(listener);\n return () => {\n subscribers.delete(listener);\n };\n },\n };\n\n function notify() {\n // Schedule the notification instead of running it immediately\n // This allows batching multiple updates into a single microtask\n scheduleUpdate(() => {\n // Directly iterate over the Set - no need to copy to array\n // The Set is stable during iteration even if modified\n for (const listener of subscribers) {\n listener(value);\n }\n });\n }\n\n return sig;\n}\n"],"mappings":";;;;;;;AAQA,IAAI,8BAAc,IAAI,KAAiB;AACvC,IAAI,mBAAmB;AACvB,IAAI,aAAa;;;;AAKjB,SAAgB,eAAe,QAA0B;AAEvD,KAAI,YAAY;AACd,cAAY,IAAI,OAAO;AACvB;;AAIF,aAAY,IAAI,OAAO;AAEvB,KAAI,CAAC,kBAAkB;AACrB,qBAAmB;AACnB,iBAAe,aAAa;;;;;;AAOhC,SAAS,eAAqB;AAC5B,oBAAmB;CAGnB,MAAM,UAAU,MAAM,KAAK,YAAY;AACvC,aAAY,OAAO;AAGnB,MAAK,MAAM,UAAU,QACnB,SAAQ;;;;;;AAQZ,SAAgB,MAAS,IAAgB;AAEvC,KAAI,WACF,QAAO,IAAI;AAGb,cAAa;AAEb,KAAI;AAEF,SADe,IAAI;WAEX;AACR,eAAa;AAGb,MAAI,YAAY,OAAO,GAAG;GACxB,MAAM,UAAU,MAAM,KAAK,YAAY;AACvC,eAAY,OAAO;AAEnB,QAAK,MAAM,UAAU,QACnB,SAAQ;;;;;;;;;;ACjEhB,SAAgB,OAAU,cAAoC;CAC5D,IAAI,QAAQ;CACZ,MAAM,8BAAc,IAAI,KAAyB;CAEjD,MAAM,MAAyB;EAC7B,IAAI,QAAQ;AACV,UAAO;;EAGT,IAAI,MAAM,UAAa;AACrB,OAAI,CAAC,OAAO,GAAG,OAAO,SAAS,EAAE;AAC/B,YAAQ;AACR,YAAQ;;;EAIZ,IAAI,UAAa;AACf,QAAK,QAAQ;;EAGf,OAAO,IAAoB;AACzB,QAAK,QAAQ,GAAG,MAAM;;EAGxB,UAAU,UAA8B;AACtC,eAAY,IAAI,SAAS;AACzB,gBAAa;AACX,gBAAY,OAAO,SAAS;;;EAGjC;CAED,SAAS,SAAS;AAGhB,uBAAqB;AAGnB,QAAK,MAAM,YAAY,YACrB,UAAS,MAAM;IAEjB;;AAGJ,QAAO"}
1
+ {"version":3,"file":"signal-4PgGfydw.mjs","names":[],"sources":["../../signal/src/batch.ts","../../signal/src/signal.ts"],"sourcesContent":["/**\n * Batch multiple signal updates using microtask scheduling\n *\n * Updates are collected and executed in a single microtask to prevent\n * multiple synchronous DOM updates and layout thrashing.\n */\n\n// Queue of pending updates\nlet updateQueue = new Set<() => void>();\nlet isFlushScheduled = false;\nlet isBatching = false;\n\n/**\n * Schedule a notification to run in a microtask\n */\nexport function scheduleUpdate(notify: () => void): void {\n // If we're in a batch, always queue the update\n if (isBatching) {\n updateQueue.add(notify);\n return;\n }\n\n // If not batching, check if we should schedule a flush\n updateQueue.add(notify);\n\n if (!isFlushScheduled) {\n isFlushScheduled = true;\n queueMicrotask(flushUpdates);\n }\n}\n\n/**\n * Flush all pending updates\n */\nfunction flushUpdates(): void {\n isFlushScheduled = false;\n\n // Copy and clear the queue to handle updates that trigger new updates\n const updates = Array.from(updateQueue);\n updateQueue.clear();\n\n // Execute all updates\n for (const notify of updates) {\n notify();\n }\n}\n\n/**\n * Batch multiple signal updates\n * All updates inside the batch function will be deferred until the batch completes\n */\nexport function batch<T>(fn: () => T): T {\n // If already batching, just run the function\n if (isBatching) {\n return fn();\n }\n\n isBatching = true;\n\n try {\n const result = fn();\n return result;\n } finally {\n isBatching = false;\n\n // Flush all queued updates immediately after the batch\n if (updateQueue.size > 0) {\n const updates = Array.from(updateQueue);\n updateQueue.clear();\n\n for (const notify of updates) {\n notify();\n }\n }\n }\n}\n","import type { WritableSignal } from \"./types\";\nimport { scheduleUpdate } from \"./batch\";\n\n/**\n * Create a writable signal\n */\nexport function signal<T>(initialValue: T): WritableSignal<T> {\n let value = initialValue;\n const subscribers = new Set<(value: T) => void>();\n\n const sig: WritableSignal<T> = {\n get value() {\n return value;\n },\n\n set value(newValue: T) {\n if (!Object.is(value, newValue)) {\n value = newValue;\n notify();\n }\n },\n\n set(newValue: T) {\n this.value = newValue;\n },\n\n update(fn: (prev: T) => T) {\n this.value = fn(value);\n },\n\n subscribe(listener: (value: T) => void) {\n subscribers.add(listener);\n return () => {\n subscribers.delete(listener);\n };\n },\n };\n\n function notify() {\n // Schedule the notification instead of running it immediately\n // This allows batching multiple updates into a single microtask\n scheduleUpdate(() => {\n // Directly iterate over the Set - no need to copy to array\n // The Set is stable during iteration even if modified\n for (const listener of subscribers) {\n listener(value);\n }\n });\n }\n\n return sig;\n}\n"],"mappings":";;;;;;;AAQA,IAAI,8BAAc,IAAI,KAAiB;AACvC,IAAI,mBAAmB;AACvB,IAAI,aAAa;;;;AAKjB,SAAgB,eAAe,QAA0B;AAEvD,KAAI,YAAY;AACd,cAAY,IAAI,OAAO;AACvB;;AAIF,aAAY,IAAI,OAAO;AAEvB,KAAI,CAAC,kBAAkB;AACrB,qBAAmB;AACnB,iBAAe,aAAa;;;;;;AAOhC,SAAS,eAAqB;AAC5B,oBAAmB;CAGnB,MAAM,UAAU,MAAM,KAAK,YAAY;AACvC,aAAY,OAAO;AAGnB,MAAK,MAAM,UAAU,QACnB,SAAQ;;;;;;AAQZ,SAAgB,MAAS,IAAgB;AAEvC,KAAI,WACF,QAAO,IAAI;AAGb,cAAa;AAEb,KAAI;AAEF,SADe,IAAI;WAEX;AACR,eAAa;AAGb,MAAI,YAAY,OAAO,GAAG;GACxB,MAAM,UAAU,MAAM,KAAK,YAAY;AACvC,eAAY,OAAO;AAEnB,QAAK,MAAM,UAAU,QACnB,SAAQ;;;;;;;;;;ACjEhB,SAAgB,OAAU,cAAoC;CAC5D,IAAI,QAAQ;CACZ,MAAM,8BAAc,IAAI,KAAyB;CAEjD,MAAM,MAAyB;EAC7B,IAAI,QAAQ;AACV,UAAO;;EAGT,IAAI,MAAM,UAAa;AACrB,OAAI,CAAC,OAAO,GAAG,OAAO,SAAS,EAAE;AAC/B,YAAQ;AACR,YAAQ;;;EAIZ,IAAI,UAAa;AACf,QAAK,QAAQ;;EAGf,OAAO,IAAoB;AACzB,QAAK,QAAQ,GAAG,MAAM;;EAGxB,UAAU,UAA8B;AACtC,eAAY,IAAI,SAAS;AACzB,gBAAa;AACX,gBAAY,OAAO,SAAS;;;EAGjC;CAED,SAAS,SAAS;AAGhB,uBAAqB;AAGnB,QAAK,MAAM,YAAY,YACrB,UAAS,MAAM;IAEjB;;AAGJ,QAAO"}
@@ -1,9 +1,9 @@
1
- import { n as unwrap, t as isSignal } from "./utils-DbTAs943.mjs";
2
- import { a as jsxs, i as jsx, v as Fragment } from "./src-DW3tIczg.mjs";
3
- import { U as isStyleToken } from "./src-Ds9vl42d.mjs";
4
- import { n as print } from "./src-DUpFNNM_.mjs";
5
- import { c as getIslandMetadata, n as LINK_MARKER, r as STYLE_MARKER, t as ASSET_MARKER, u as isIslandVNode } from "./resource-DSlXDZZi.mjs";
6
- import { n as renderDocument } from "./document-BOJDaiBc.mjs";
1
+ import { n as unwrap, t as isSignal } from "./utils-BrGmTgfG.mjs";
2
+ import { a as jsxs, i as jsx, v as Fragment } from "./src-Cv4rRVzv.mjs";
3
+ import { U as isStyleToken } from "./src-DV9uwtE5.mjs";
4
+ import { n as print } from "./src-CXY-7FC3.mjs";
5
+ import { c as getIslandMetadata, n as LINK_MARKER, r as STYLE_MARKER, t as ASSET_MARKER, u as isIslandVNode } from "./resource-pm7qP-jV.mjs";
6
+ import { n as renderDocument } from "./document-XKyAs62C.mjs";
7
7
  import { build, createServer, mergeConfig } from "vite";
8
8
  import { dirname, resolve } from "path";
9
9
 
@@ -69,6 +69,7 @@ async function renderToString(vnode, options = {}) {
69
69
  enableHydration: !!transformIslandScript,
70
70
  renderCache: /* @__PURE__ */ new WeakMap(),
71
71
  css: /* @__PURE__ */ new Set(),
72
+ styles: /* @__PURE__ */ new Set(),
72
73
  assets: /* @__PURE__ */ new Set(),
73
74
  rootDir
74
75
  };
@@ -79,6 +80,7 @@ async function renderToString(vnode, options = {}) {
79
80
  islands: context.islands,
80
81
  scripts,
81
82
  css: Array.from(context.css),
83
+ styles: Array.from(context.styles),
82
84
  assets: Array.from(context.assets)
83
85
  };
84
86
  }
@@ -342,7 +344,7 @@ async function renderIsland(vnode, context) {
342
344
  async function renderElement(vnode, context) {
343
345
  const tag = vnode.type;
344
346
  const props = vnode.props || {};
345
- if (props.dangerouslySetInnerHTML?.__html != null) return `<${tag}${renderAttributes(props)}>${props.dangerouslySetInnerHTML.__html}</${tag}>`;
347
+ if (props.dangerouslySetInnerHTML?.__html != null) return `<${tag}${renderAttributes(props, context)}>${props.dangerouslySetInnerHTML.__html}</${tag}>`;
346
348
  const selfClosing = [
347
349
  "area",
348
350
  "base",
@@ -359,7 +361,7 @@ async function renderElement(vnode, context) {
359
361
  "track",
360
362
  "wbr"
361
363
  ];
362
- const attrs = renderAttributes(props);
364
+ const attrs = renderAttributes(props, context);
363
365
  if (selfClosing.includes(tag)) return `<${tag}${attrs} />`;
364
366
  if (tag === "style" || tag === "script") return `<${tag}${attrs}>${(vnode.children || []).map((child) => extractRawText(child)).join("")}</${tag}>`;
365
367
  return `<${tag}${attrs}>${(await Promise.all((vnode.children || []).map((child) => renderVNodeToHTML(child, context)))).join("")}</${tag}>`;
@@ -388,20 +390,23 @@ function extractRawText(vnode) {
388
390
  * Resolve a class value to a string for SSR output.
389
391
  *
390
392
  * Handles strings, StyleToken objects, arrays, and falsy values.
391
- * Unlike the DOM version, this does NOT call inject() since CSS is
392
- * collected statically (via componentCSS) for SSG/SSR output.
393
+ * When a StyleToken is encountered, its CSS rule is collected into
394
+ * the render context for inclusion in the output.
393
395
  */
394
- function resolveClass(value) {
396
+ function resolveClass(value, context) {
395
397
  if (!value) return "";
396
398
  if (typeof value === "string") return value;
397
- if (isStyleToken(value)) return value._ ?? "";
398
- if (Array.isArray(value)) return value.map(resolveClass).filter(Boolean).join(" ");
399
+ if (isStyleToken(value)) {
400
+ if (context && value.__cssTemplate) context.styles.add(value.__cssTemplate);
401
+ return value._ ?? "";
402
+ }
403
+ if (Array.isArray(value)) return value.map((v) => resolveClass(v, context)).filter(Boolean).join(" ");
399
404
  return String(value);
400
405
  }
401
406
  /**
402
407
  * Render element attributes
403
408
  */
404
- function renderAttributes(props) {
409
+ function renderAttributes(props, context) {
405
410
  const attrs = [];
406
411
  for (const [key, value] of Object.entries(props)) {
407
412
  if (key === "children" || key === "key" || key === "ref" || key === "dangerouslySetInnerHTML") continue;
@@ -416,7 +421,7 @@ function renderAttributes(props) {
416
421
  }
417
422
  const attrName = key === "className" ? "class" : key === "htmlFor" ? "for" : key === "charSet" ? "charset" : key === "crossOrigin" ? "crossorigin" : key === "httpEquiv" ? "http-equiv" : key;
418
423
  if (attrName === "class") {
419
- const resolved = resolveClass(attrValue);
424
+ const resolved = resolveClass(attrValue, context);
420
425
  if (resolved) attrs.push(`class="${escapeHTML(resolved)}"`);
421
426
  continue;
422
427
  }
@@ -1221,6 +1226,7 @@ var AppImpl = class {
1221
1226
  modules[htmlFileName] = customRenderHtml ? customRenderHtml({
1222
1227
  html: result.html,
1223
1228
  css: cssRefs,
1229
+ styles: result.styles,
1224
1230
  scripts: islandScriptEntries,
1225
1231
  title: pageTitle,
1226
1232
  path
@@ -1231,6 +1237,7 @@ var AppImpl = class {
1231
1237
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
1232
1238
  <title>${pageTitle}</title>
1233
1239
  ${cssRefs.map((href) => `<link rel="stylesheet" href="${href}">`).join("\n ")}
1240
+ ${result.styles.length > 0 ? `<style>${result.styles.join("\n")}</style>` : ""}
1234
1241
  </head>
1235
1242
  <body>
1236
1243
  ${result.html}
@@ -1723,7 +1730,7 @@ var ViteRouter = class {
1723
1730
  const result = await renderToString(match.handler(context), { transformIslandScript: (island) => `<script type="module" src="${island.basePath}/${island.id}.js" async><\/script>` });
1724
1731
  for (const island of result.islands) this.islandsCache.set(island.id, island);
1725
1732
  if (this.config.document) {
1726
- const { renderDocument } = await import("./document-CwHVG_PJ.mjs");
1733
+ const { renderDocument } = await import("./document-DsiJO2jG.mjs");
1727
1734
  result.document = renderDocument(this.config.document({
1728
1735
  children: {
1729
1736
  type: "template",
@@ -1921,4 +1928,4 @@ function createIslandCollector() {
1921
1928
 
1922
1929
  //#endregion
1923
1930
  export { ViteIslandBuilder as a, renderToString as c, createViteRouter as i, createIslandCollector as n, createViteIslandBuilder as o, ViteRouter as r, createApp as s, IslandCollector as t };
1924
- //# sourceMappingURL=src-B4VBiHa8.mjs.map
1931
+ //# sourceMappingURL=src-CAyv9Uf9.mjs.map