@enadhq/enad-react-sdk 1.1.0 → 1.3.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 (232) hide show
  1. package/dist/client/cart/components/cart-drawer.mjs +3 -3
  2. package/dist/client/cart/components/cart-drawer.mjs.map +1 -1
  3. package/dist/client/cart/components/cart-trigger.mjs +1 -1
  4. package/dist/client/cart/components/cart-trigger.mjs.map +1 -1
  5. package/dist/client/storefront/blocks/card-video.mjs +1 -1
  6. package/dist/client/storefront/blocks/card-video.mjs.map +1 -1
  7. package/dist/client/storefront/blocks/gallery-with-link-blocks.d.ts.map +1 -1
  8. package/dist/client/storefront/blocks/gallery-with-link-blocks.mjs +13 -5
  9. package/dist/client/storefront/blocks/gallery-with-link-blocks.mjs.map +1 -1
  10. package/dist/client/storefront/blocks/gallery.d.ts +10 -1
  11. package/dist/client/storefront/blocks/gallery.d.ts.map +1 -1
  12. package/dist/client/storefront/blocks/gallery.mjs +51 -27
  13. package/dist/client/storefront/blocks/gallery.mjs.map +1 -1
  14. package/dist/client/storefront/blocks/hero.d.ts +12 -1
  15. package/dist/client/storefront/blocks/hero.d.ts.map +1 -1
  16. package/dist/client/storefront/blocks/hero.mjs +143 -145
  17. package/dist/client/storefront/blocks/hero.mjs.map +1 -1
  18. package/dist/client/storefront/blocks/link-block-small.d.ts.map +1 -1
  19. package/dist/client/storefront/blocks/link-block-small.mjs +1 -1
  20. package/dist/client/storefront/blocks/link-block-small.mjs.map +1 -1
  21. package/dist/client/storefront/blocks/link-block.d.ts.map +1 -1
  22. package/dist/client/storefront/blocks/link-block.mjs +4 -4
  23. package/dist/client/storefront/blocks/link-block.mjs.map +1 -1
  24. package/dist/client/storefront/blocks/product-card-parts.d.ts +1 -1
  25. package/dist/client/storefront/blocks/product-card-parts.d.ts.map +1 -1
  26. package/dist/client/storefront/blocks/product-card-parts.mjs +2 -2
  27. package/dist/client/storefront/blocks/product-card-parts.mjs.map +1 -1
  28. package/dist/client/storefront/blocks/product-card.d.ts +10 -1
  29. package/dist/client/storefront/blocks/product-card.d.ts.map +1 -1
  30. package/dist/client/storefront/blocks/product-card.mjs +122 -116
  31. package/dist/client/storefront/blocks/product-card.mjs.map +1 -1
  32. package/dist/client/storefront/blocks/product-image.mjs +2 -2
  33. package/dist/client/storefront/blocks/product-image.mjs.map +1 -1
  34. package/dist/client/storefront/blocks/text-content-with-image.d.ts +14 -1
  35. package/dist/client/storefront/blocks/text-content-with-image.d.ts.map +1 -1
  36. package/dist/client/storefront/blocks/text-content-with-image.mjs +141 -164
  37. package/dist/client/storefront/blocks/text-content-with-image.mjs.map +1 -1
  38. package/dist/client/storefront/carousel/swipeable-carousel.d.ts +5 -1
  39. package/dist/client/storefront/carousel/swipeable-carousel.d.ts.map +1 -1
  40. package/dist/client/storefront/carousel/swipeable-carousel.mjs +2 -1
  41. package/dist/client/storefront/carousel/swipeable-carousel.mjs.map +1 -1
  42. package/dist/client/storefront/checkout/cart-summary.mjs +1 -1
  43. package/dist/client/storefront/checkout/cart-summary.mjs.map +1 -1
  44. package/dist/client/storefront/components/language-selector.d.ts.map +1 -1
  45. package/dist/client/storefront/components/language-selector.mjs +1 -1
  46. package/dist/client/storefront/components/language-selector.mjs.map +1 -1
  47. package/dist/client/storefront/components/product-recommendations.d.ts.map +1 -1
  48. package/dist/client/storefront/components/product-recommendations.mjs +29 -37
  49. package/dist/client/storefront/components/product-recommendations.mjs.map +1 -1
  50. package/dist/client/storefront/filters/filter-chip.d.ts +5 -2
  51. package/dist/client/storefront/filters/filter-chip.d.ts.map +1 -1
  52. package/dist/client/storefront/filters/filter-chip.mjs +6 -4
  53. package/dist/client/storefront/filters/filter-chip.mjs.map +1 -1
  54. package/dist/client/storefront/filters/filter-panel.mjs +2 -2
  55. package/dist/client/storefront/filters/filter-panel.mjs.map +1 -1
  56. package/dist/client/storefront/filters/toggle-list-view.mjs +1 -1
  57. package/dist/client/storefront/filters/toggle-list-view.mjs.map +1 -1
  58. package/dist/client/storefront/index.d.ts +12 -1
  59. package/dist/client/storefront/index.mjs +12 -1
  60. package/dist/client/storefront/layout/header.d.ts.map +1 -1
  61. package/dist/client/storefront/layout/header.mjs +1 -1
  62. package/dist/client/storefront/layout/header.mjs.map +1 -1
  63. package/dist/client/storefront/layout/mobile-menu-drawer.mjs +1 -1
  64. package/dist/client/storefront/layout/promotion-bar.d.ts.map +1 -1
  65. package/dist/client/storefront/layout/promotion-bar.mjs +3 -3
  66. package/dist/client/storefront/layout/promotion-bar.mjs.map +1 -1
  67. package/dist/client/storefront/primitives/block-heading.d.ts +40 -0
  68. package/dist/client/storefront/primitives/block-heading.d.ts.map +1 -0
  69. package/dist/client/storefront/primitives/block-heading.mjs +43 -0
  70. package/dist/client/storefront/primitives/block-heading.mjs.map +1 -0
  71. package/dist/client/storefront/primitives/button.d.ts +2 -2
  72. package/dist/client/storefront/primitives/button.d.ts.map +1 -1
  73. package/dist/client/storefront/primitives/button.mjs +4 -4
  74. package/dist/client/storefront/primitives/button.mjs.map +1 -1
  75. package/dist/client/storefront/primitives/cta-group.d.ts +25 -0
  76. package/dist/client/storefront/primitives/cta-group.d.ts.map +1 -0
  77. package/dist/client/storefront/primitives/cta-group.mjs +27 -0
  78. package/dist/client/storefront/primitives/cta-group.mjs.map +1 -0
  79. package/dist/client/storefront/primitives/image-with-hover.d.ts +18 -0
  80. package/dist/client/storefront/primitives/image-with-hover.d.ts.map +1 -0
  81. package/dist/client/storefront/primitives/image-with-hover.mjs +16 -0
  82. package/dist/client/storefront/primitives/image-with-hover.mjs.map +1 -0
  83. package/dist/client/storefront/primitives/index.d.ts +4 -1
  84. package/dist/client/storefront/primitives/index.mjs +4 -1
  85. package/dist/client/storefront/primitives/input.d.ts +1 -1
  86. package/dist/client/storefront/primitives/input.mjs.map +1 -1
  87. package/dist/client/storefront/primitives/pagination.mjs +2 -2
  88. package/dist/client/storefront/primitives/pagination.mjs.map +1 -1
  89. package/dist/client/storefront/product/quantity-picker.mjs +2 -2
  90. package/dist/client/storefront/product/quantity-picker.mjs.map +1 -1
  91. package/dist/client/storefront/types.d.ts +1 -1
  92. package/dist/client/storefront/types.d.ts.map +1 -1
  93. package/dist/client/storefront/types.mjs.map +1 -1
  94. package/dist/client/theme/apply.d.ts +1 -1
  95. package/dist/client/theme/apply.d.ts.map +1 -1
  96. package/dist/client/theme/apply.mjs +0 -12
  97. package/dist/client/theme/apply.mjs.map +1 -1
  98. package/dist/client/theme/cli.mjs +0 -16
  99. package/dist/client/theme/cli.mjs.map +1 -1
  100. package/dist/client/theme/codec.d.ts.map +1 -1
  101. package/dist/client/theme/codec.mjs +0 -2
  102. package/dist/client/theme/codec.mjs.map +1 -1
  103. package/dist/client/theme/defaults.d.ts +0 -2
  104. package/dist/client/theme/defaults.mjs +0 -2
  105. package/dist/client/theme/defaults.mjs.map +1 -1
  106. package/dist/client/ui/accordion.d.ts +12 -1
  107. package/dist/client/ui/accordion.d.ts.map +1 -1
  108. package/dist/client/ui/accordion.mjs +23 -5
  109. package/dist/client/ui/accordion.mjs.map +1 -1
  110. package/dist/client/ui/alert.d.ts +16 -7
  111. package/dist/client/ui/alert.d.ts.map +1 -1
  112. package/dist/client/ui/alert.mjs +21 -8
  113. package/dist/client/ui/alert.mjs.map +1 -1
  114. package/dist/client/ui/avatar.d.ts +10 -1
  115. package/dist/client/ui/avatar.d.ts.map +1 -1
  116. package/dist/client/ui/avatar.mjs +18 -4
  117. package/dist/client/ui/avatar.mjs.map +1 -1
  118. package/dist/client/ui/breadcrumb.d.ts +13 -1
  119. package/dist/client/ui/breadcrumb.d.ts.map +1 -1
  120. package/dist/client/ui/breadcrumb.mjs +27 -7
  121. package/dist/client/ui/breadcrumb.mjs.map +1 -1
  122. package/dist/client/ui/button.d.ts +28 -10
  123. package/dist/client/ui/button.d.ts.map +1 -1
  124. package/dist/client/ui/button.mjs +45 -20
  125. package/dist/client/ui/button.mjs.map +1 -1
  126. package/dist/client/ui/card.d.ts +20 -1
  127. package/dist/client/ui/card.d.ts.map +1 -1
  128. package/dist/client/ui/card.mjs +36 -8
  129. package/dist/client/ui/card.mjs.map +1 -1
  130. package/dist/client/ui/carousel.d.ts +9 -1
  131. package/dist/client/ui/carousel.d.ts.map +1 -1
  132. package/dist/client/ui/carousel.mjs +20 -4
  133. package/dist/client/ui/carousel.mjs.map +1 -1
  134. package/dist/client/ui/checkbox.d.ts +9 -1
  135. package/dist/client/ui/checkbox.d.ts.map +1 -1
  136. package/dist/client/ui/checkbox.mjs +12 -3
  137. package/dist/client/ui/checkbox.mjs.map +1 -1
  138. package/dist/client/ui/dialog.d.ts +13 -1
  139. package/dist/client/ui/dialog.d.ts.map +1 -1
  140. package/dist/client/ui/dialog.mjs +27 -7
  141. package/dist/client/ui/dialog.mjs.map +1 -1
  142. package/dist/client/ui/hover-card.d.ts +6 -1
  143. package/dist/client/ui/hover-card.d.ts.map +1 -1
  144. package/dist/client/ui/hover-card.mjs +4 -2
  145. package/dist/client/ui/hover-card.mjs.map +1 -1
  146. package/dist/client/ui/input.d.ts +20 -7
  147. package/dist/client/ui/input.d.ts.map +1 -1
  148. package/dist/client/ui/input.mjs +33 -9
  149. package/dist/client/ui/input.mjs.map +1 -1
  150. package/dist/client/ui/label.d.ts +6 -1
  151. package/dist/client/ui/label.d.ts.map +1 -1
  152. package/dist/client/ui/label.mjs +4 -2
  153. package/dist/client/ui/label.mjs.map +1 -1
  154. package/dist/client/ui/navigation-menu.d.ts +20 -3
  155. package/dist/client/ui/navigation-menu.d.ts.map +1 -1
  156. package/dist/client/ui/navigation-menu.mjs +34 -12
  157. package/dist/client/ui/navigation-menu.mjs.map +1 -1
  158. package/dist/client/ui/pagination.d.ts.map +1 -1
  159. package/dist/client/ui/pagination.mjs +3 -3
  160. package/dist/client/ui/pagination.mjs.map +1 -1
  161. package/dist/client/ui/popover.d.ts +11 -1
  162. package/dist/client/ui/popover.d.ts.map +1 -1
  163. package/dist/client/ui/popover.mjs +21 -5
  164. package/dist/client/ui/popover.mjs.map +1 -1
  165. package/dist/client/ui/progress.d.ts +9 -1
  166. package/dist/client/ui/progress.d.ts.map +1 -1
  167. package/dist/client/ui/progress.mjs +12 -3
  168. package/dist/client/ui/progress.mjs.map +1 -1
  169. package/dist/client/ui/select.d.ts +14 -2
  170. package/dist/client/ui/select.d.ts.map +1 -1
  171. package/dist/client/ui/select.mjs +35 -9
  172. package/dist/client/ui/select.mjs.map +1 -1
  173. package/dist/client/ui/separator.d.ts +6 -1
  174. package/dist/client/ui/separator.d.ts.map +1 -1
  175. package/dist/client/ui/separator.mjs +4 -2
  176. package/dist/client/ui/separator.mjs.map +1 -1
  177. package/dist/client/ui/sheet.d.ts +13 -1
  178. package/dist/client/ui/sheet.d.ts.map +1 -1
  179. package/dist/client/ui/sheet.mjs +35 -7
  180. package/dist/client/ui/sheet.mjs.map +1 -1
  181. package/dist/client/ui/slot-wrapper.d.ts +28 -0
  182. package/dist/client/ui/slot-wrapper.d.ts.map +1 -0
  183. package/dist/client/ui/slot-wrapper.mjs +38 -0
  184. package/dist/client/ui/slot-wrapper.mjs.map +1 -0
  185. package/dist/client/ui/tabs.d.ts +11 -1
  186. package/dist/client/ui/tabs.d.ts.map +1 -1
  187. package/dist/client/ui/tabs.mjs +21 -5
  188. package/dist/client/ui/tabs.mjs.map +1 -1
  189. package/dist/client/ui/toggle-group.d.ts +7 -4
  190. package/dist/client/ui/toggle-group.d.ts.map +1 -1
  191. package/dist/client/ui/toggle-group.mjs +4 -4
  192. package/dist/client/ui/toggle-group.mjs.map +1 -1
  193. package/dist/client/ui/toggle.d.ts +17 -8
  194. package/dist/client/ui/toggle.d.ts.map +1 -1
  195. package/dist/client/ui/toggle.mjs +11 -9
  196. package/dist/client/ui/toggle.mjs.map +1 -1
  197. package/dist/client/ui/tooltip.d.ts +6 -1
  198. package/dist/client/ui/tooltip.d.ts.map +1 -1
  199. package/dist/client/ui/tooltip.mjs +4 -2
  200. package/dist/client/ui/tooltip.mjs.map +1 -1
  201. package/dist/client/ui-resolver/button.d.ts +3 -4
  202. package/dist/client/ui-resolver/button.d.ts.map +1 -1
  203. package/dist/client/ui-resolver/button.mjs +2 -2
  204. package/dist/client/ui-resolver/button.mjs.map +1 -1
  205. package/dist/client/ui-resolver/card.d.ts +14 -1
  206. package/dist/client/ui-resolver/card.d.ts.map +1 -1
  207. package/dist/client/ui-resolver/card.mjs +3 -2
  208. package/dist/client/ui-resolver/card.mjs.map +1 -1
  209. package/dist/client/ui-resolver/context.mjs +1 -1
  210. package/dist/client/ui-resolver/context.mjs.map +1 -1
  211. package/dist/client/ui-resolver/index.d.ts +7 -4
  212. package/dist/client/ui-resolver/index.mjs +8 -6
  213. package/dist/client/ui-resolver/input.d.ts +3 -4
  214. package/dist/client/ui-resolver/input.d.ts.map +1 -1
  215. package/dist/client/ui-resolver/input.mjs +2 -2
  216. package/dist/client/ui-resolver/input.mjs.map +1 -1
  217. package/dist/client/ui-resolver/navigation-menu.d.ts +1 -2
  218. package/dist/client/ui-resolver/navigation-menu.d.ts.map +1 -1
  219. package/dist/client/ui-resolver/recipe.d.ts +95 -0
  220. package/dist/client/ui-resolver/recipe.d.ts.map +1 -0
  221. package/dist/client/ui-resolver/recipe.mjs +134 -0
  222. package/dist/client/ui-resolver/recipe.mjs.map +1 -0
  223. package/dist/client/ui-resolver/toggle.d.ts +2 -2
  224. package/dist/client/ui-resolver/toggle.mjs +2 -2
  225. package/dist/client/ui-resolver/toggle.mjs.map +1 -1
  226. package/dist/client/ui-resolver/types.d.ts +14 -0
  227. package/dist/client/ui-resolver/types.d.ts.map +1 -0
  228. package/dist/client/ui-resolver/types.mjs +1 -0
  229. package/dist/client/wishlist/wishlist-drawer.mjs +4 -4
  230. package/dist/client/wishlist/wishlist-drawer.mjs.map +1 -1
  231. package/dist/styles.css +1 -1
  232. package/package.json +4 -3
@@ -1 +1 @@
1
- {"version":3,"file":"cli.mjs","names":["msgpackDecode"],"sources":["../../../src/client/theme/codec.ts","../../../src/client/theme/defaults.ts","../../../src/client/theme/apply.ts","../../../src/client/theme/scan.ts","../../../src/client/theme/cli.ts"],"sourcesContent":["import { decode as msgpackDecode, encode as msgpackEncode } from \"@msgpack/msgpack\";\n\n/**\n * Loose bag of theme values. The decoder returns whatever keys are present;\n * the consumer merges onto its own defaults. This keeps the format\n * forward/backward compatible: new keys are silently ignored by old decoders,\n * and removed keys are filled from defaults by the consumer.\n */\nexport type ThemeHash = Record<string, unknown>;\n\n// Current format version. Prepended as a single ASCII char before the base64url payload.\nconst FORMAT_VERSION = \"1\";\n\n// ---------------------------------------------------------------------------\n// Short key mapping\n// ---------------------------------------------------------------------------\n\n/** Short key -> full key */\nexport const KEY_MAP: Record<string, string> = {\n c: \"colorize\",\n i: \"intensity\",\n d: \"delight\",\n r: \"radius\",\n bf: \"fontBody\",\n hf: \"fontHeading\",\n ic: \"iconSet\",\n cs: \"colorSpace\",\n dm: \"darkMode\",\n lc: \"lightColors\",\n dc: \"darkColors\",\n br: \"buttonRadius\",\n cr: \"cardRadius\",\n ir: \"inputRadius\",\n mr: \"imageRadius\",\n sp: \"shadowPreset\",\n sc: \"shadowColor\",\n hw: \"headingWeight\",\n ht: \"headingTracking\",\n bw: \"bodyWeight\",\n hx: \"headingTransform\",\n bdr: \"borderWidth\",\n oc: \"overlayColor\",\n of: \"overlayFromOpacity\",\n ot: \"overlayToOpacity\",\n hs: \"imageHoverScale\",\n hd: \"imageHoverDuration\",\n v: \"variants\",\n xs: \"componentSet\",\n};\n\n/** Full key -> short key (inverse of KEY_MAP) */\nexport const KEY_MAP_REVERSE: Record<string, string> = Object.fromEntries(\n Object.entries(KEY_MAP).map(([short, full]) => [full, short]),\n);\n\n// ---------------------------------------------------------------------------\n// Base64url helpers (RFC 4648 §5, no padding)\n// ---------------------------------------------------------------------------\n\nfunction toBase64url(buf: Uint8Array): string {\n let binary = \"\";\n for (let i = 0; i < buf.length; i++) {\n binary += String.fromCharCode(buf[i]!);\n }\n return btoa(binary).replace(/\\+/g, \"-\").replace(/\\//g, \"_\").replace(/=+$/, \"\");\n}\n\nfunction fromBase64url(str: string): Uint8Array {\n const base64 = str.replace(/-/g, \"+\").replace(/_/g, \"/\");\n const padded = base64 + \"=\".repeat((4 - (base64.length % 4)) % 4);\n const binary = atob(padded);\n const bytes = new Uint8Array(binary.length);\n for (let i = 0; i < binary.length; i++) {\n bytes[i] = binary.charCodeAt(i);\n }\n return bytes;\n}\n\n// ---------------------------------------------------------------------------\n// Encode / Decode\n// ---------------------------------------------------------------------------\n\n/**\n * Encode a theme state diff into a portable hash string.\n *\n * The input should only contain non-default values. The encoder maps\n * full keys to short keys, packs with MessagePack, and encodes as\n * `<version><base64url>`.\n */\nexport function encodeThemeHash(diff: ThemeHash): string {\n const compact: Record<string, unknown> = {};\n for (const [fullKey, value] of Object.entries(diff)) {\n const shortKey = KEY_MAP_REVERSE[fullKey] ?? fullKey;\n compact[shortKey] = value;\n }\n const packed = msgpackEncode(compact);\n return FORMAT_VERSION + toBase64url(packed);\n}\n\n/**\n * Decode a hash string back into a key-value bag with full key names.\n *\n * Returns partial data -- the consumer is responsible for merging onto\n * its own defaults. Unknown keys are preserved for forward compatibility.\n * Returns an empty object on invalid input (never throws).\n */\nexport function decodeThemeHash(hash: string): ThemeHash {\n try {\n if (!hash || hash.length < 2) return {};\n\n const version = hash[0];\n if (version !== FORMAT_VERSION) return {};\n\n const payload = hash.slice(1);\n const bytes = fromBase64url(payload);\n const compact = msgpackDecode(bytes) as Record<string, unknown>;\n\n if (typeof compact !== \"object\" || compact === null) return {};\n\n const result: ThemeHash = {};\n for (const [key, value] of Object.entries(compact)) {\n const fullKey = KEY_MAP[key] ?? key;\n result[fullKey] = value;\n }\n return result;\n } catch {\n return {};\n }\n}\n","/**\n * SDK default color tokens. These are the canonical defaults used by\n * the theme codec to compute diffs (only non-default values are encoded).\n */\nexport const SDK_DEFAULTS = {\n light: {\n \"--background\": \"#ffffff\",\n \"--foreground\": \"#111827\",\n \"--card\": \"#ffffff\",\n \"--card-foreground\": \"#111827\",\n \"--popover\": \"#ffffff\",\n \"--popover-foreground\": \"#111827\",\n \"--primary\": \"#2563eb\",\n \"--primary-foreground\": \"#ffffff\",\n \"--secondary\": \"#f1f5f9\",\n \"--secondary-foreground\": \"#0f172a\",\n \"--muted\": \"#f3f4f6\",\n \"--muted-foreground\": \"#636b78\",\n \"--accent\": \"#dbeafe\",\n \"--accent-foreground\": \"#1e3a8a\",\n \"--accent-muted\": \"#eff6ff\",\n \"--accent-muted-foreground\": \"#1e40af\",\n \"--destructive\": \"#dc2626\",\n \"--destructive-foreground\": \"#ffffff\",\n \"--border\": \"#e5e7eb\",\n \"--input\": \"#e5e7eb\",\n \"--ring\": \"#2563eb\",\n } as Record<string, string>,\n dark: {\n \"--background\": \"#111827\",\n \"--foreground\": \"#f9fafb\",\n \"--card\": \"#1f2937\",\n \"--card-foreground\": \"#f9fafb\",\n \"--popover\": \"#1f2937\",\n \"--popover-foreground\": \"#f9fafb\",\n \"--primary\": \"#2563eb\",\n \"--primary-foreground\": \"#ffffff\",\n \"--secondary\": \"#1e293b\",\n \"--secondary-foreground\": \"#e2e8f0\",\n \"--muted\": \"#374151\",\n \"--muted-foreground\": \"#b0b8c4\",\n \"--accent\": \"#1e3a5f\",\n \"--accent-foreground\": \"#bfdbfe\",\n \"--accent-muted\": \"#172554\",\n \"--accent-muted-foreground\": \"#93c5fd\",\n \"--destructive\": \"#dc2626\",\n \"--destructive-foreground\": \"#ffffff\",\n \"--border\": \"#374151\",\n \"--input\": \"#374151\",\n \"--ring\": \"#2563eb\",\n } as Record<string, string>,\n};\n\n/** Default values for design tokens (non-color). */\nexport const TOKEN_DEFAULTS = {\n colorize: 50,\n intensity: 50,\n delight: 50,\n radius: 0.75,\n fontBody: \"Inter\",\n fontHeading: \"Inter\",\n iconSet: \"Phosphor\",\n colorSpace: \"hsl\",\n darkMode: false,\n componentSet: \"default\" as const,\n\n // Shape\n buttonRadius: \"9999px\",\n cardRadius: \"var(--radius)\",\n inputRadius: \"var(--radius)\",\n imageRadius: \"0px\",\n\n // Depth\n shadowPreset: \"none\",\n shadowColor: \"oklch(0 0 0 / 0.1)\",\n\n // Typography\n headingWeight: \"600\",\n headingTracking: \"0em\",\n bodyWeight: \"400\",\n headingTransform: \"none\",\n\n // Border\n borderWidth: \"1px\",\n\n // Overlay\n overlayColor: \"black\",\n overlayFromOpacity: \"0.5\",\n overlayToOpacity: \"0\",\n\n // Motion\n imageHoverScale: \"1.05\",\n imageHoverDuration: \"300ms\",\n\n // Variants\n variants: {\n hero: \"overlay\",\n linkBlock: \"overlay\",\n productCard: \"gallery\",\n contentWithImage: \"side-by-side\",\n gallery: \"grid\",\n textContent: \"default\",\n },\n} as const;\n","import type { ThemeHash } from './codec';\nimport { SDK_DEFAULTS, TOKEN_DEFAULTS } from './defaults';\n\nexport interface GenerateOptions {\n colorSpace?: 'hsl' | 'oklch';\n}\n\nfunction buildLightColorDiffs(hash: ThemeHash): string[] {\n const lightOverrides = (hash.lightColors ?? {}) as Record<string, string>;\n const diffs: string[] = [];\n for (const [token, value] of Object.entries(lightOverrides)) {\n if (value !== SDK_DEFAULTS.light[token]) {\n diffs.push(` ${token}: ${value};`);\n }\n }\n return diffs;\n}\n\nfunction buildBaseTokenDiffs(hash: ThemeHash): string[] {\n const diffs: string[] = [];\n\n const radius = hash.radius as number | undefined;\n if (radius != null && radius !== 0.75) {\n diffs.push(` --radius: ${radius}rem;`);\n }\n\n const fontBody = hash.fontBody as string | undefined;\n if (fontBody && fontBody !== 'Inter') {\n diffs.push(` --font-sans: \"${fontBody}\", sans-serif;`);\n }\n\n const fontHeading = hash.fontHeading as string | undefined;\n if (fontHeading && fontHeading !== fontBody && fontHeading !== 'Inter') {\n diffs.push(` --font-heading: \"${fontHeading}\", sans-serif;`);\n }\n\n return diffs;\n}\n\nfunction buildDarkColorDiffs(hash: ThemeHash): string[] {\n const darkOverrides = (hash.darkColors ?? {}) as Record<string, string>;\n const diffs: string[] = [];\n for (const [token, value] of Object.entries(darkOverrides)) {\n if (value !== SDK_DEFAULTS.dark[token]) {\n diffs.push(` ${token}: ${value};`);\n }\n }\n return diffs;\n}\n\nfunction buildTokenSections(hash: ThemeHash): string[] {\n const lines: string[] = [];\n\n const tokenSections: Array<{ comment: string; entries: Array<[string, string, string]> }> = [\n {\n comment: 'Shape',\n entries: [\n ['--enad-button-radius', hash.buttonRadius as string, TOKEN_DEFAULTS.buttonRadius],\n ['--enad-card-radius', hash.cardRadius as string, TOKEN_DEFAULTS.cardRadius],\n ['--enad-input-radius', hash.inputRadius as string, TOKEN_DEFAULTS.inputRadius],\n ['--enad-image-radius', hash.imageRadius as string, TOKEN_DEFAULTS.imageRadius],\n ],\n },\n {\n comment: 'Depth',\n entries: [\n ['--enad-shadow-color', hash.shadowColor as string, TOKEN_DEFAULTS.shadowColor],\n ],\n },\n {\n comment: 'Typography',\n entries: [\n ['--enad-heading-weight', hash.headingWeight as string, TOKEN_DEFAULTS.headingWeight],\n ['--enad-heading-tracking', hash.headingTracking as string, TOKEN_DEFAULTS.headingTracking],\n ['--enad-body-weight', hash.bodyWeight as string, TOKEN_DEFAULTS.bodyWeight],\n ['--enad-heading-transform', hash.headingTransform as string, TOKEN_DEFAULTS.headingTransform],\n ],\n },\n {\n comment: 'Borders',\n entries: [\n ['--enad-border-width', hash.borderWidth as string, TOKEN_DEFAULTS.borderWidth],\n ],\n },\n {\n comment: 'Overlay',\n entries: [\n ['--enad-overlay-color', hash.overlayColor as string, TOKEN_DEFAULTS.overlayColor],\n ['--enad-overlay-from-opacity', hash.overlayFromOpacity as string, TOKEN_DEFAULTS.overlayFromOpacity],\n ['--enad-overlay-to-opacity', hash.overlayToOpacity as string, TOKEN_DEFAULTS.overlayToOpacity],\n ],\n },\n {\n comment: 'Motion',\n entries: [\n ['--enad-image-hover-scale', hash.imageHoverScale as string, TOKEN_DEFAULTS.imageHoverScale],\n ['--enad-image-hover-duration', hash.imageHoverDuration as string, TOKEN_DEFAULTS.imageHoverDuration],\n ],\n },\n ];\n\n for (const section of tokenSections) {\n const sectionLines: string[] = [];\n for (const [varName, value, defaultValue] of section.entries) {\n if (value != null && value !== defaultValue) {\n sectionLines.push(` ${varName}: ${value};`);\n }\n }\n if (sectionLines.length > 0) {\n lines.push('', `/* ${section.comment} */`, ':root {', ...sectionLines, '}');\n }\n }\n\n return lines;\n}\n\n/**\n * Generate CSS variable declarations from a decoded theme hash.\n * Merges the hash onto SDK defaults and only emits values that differ.\n */\n// eslint-disable-next-line @typescript-eslint/no-unused-vars\nexport function generateThemeCSS(hash: ThemeHash, _options: GenerateOptions = {}): string {\n const lines: string[] = ['/* Generated by enad-theme */'];\n\n // --- Light color diffs + base tokens ---\n const lightDiffs = [...buildLightColorDiffs(hash), ...buildBaseTokenDiffs(hash)];\n if (lightDiffs.length > 0) {\n lines.push('', ':root {', ...lightDiffs, '}');\n }\n\n // --- Dark color diffs ---\n const darkDiffs = buildDarkColorDiffs(hash);\n if (darkDiffs.length > 0) {\n lines.push('', '.dark {', ...darkDiffs, '}');\n }\n\n // --- Token sections ---\n lines.push(...buildTokenSections(hash));\n\n return lines.join('\\n');\n}\n\n// Sentinel markers for idempotent file writes\nexport const MARKER_START = '/* === enad-theme:start === */';\nexport const MARKER_END = '/* === enad-theme:end === */';\n\n/**\n * Insert or replace a theme block in a CSS file's content.\n * Returns the updated file content.\n */\nexport function applyThemeBlock(fileContent: string, cssBlock: string): string {\n const startIdx = fileContent.indexOf(MARKER_START);\n const endIdx = fileContent.indexOf(MARKER_END);\n\n const block = `${MARKER_START}\\n${cssBlock}\\n${MARKER_END}`;\n\n if (startIdx !== -1 && endIdx !== -1) {\n return fileContent.slice(0, startIdx) + block + fileContent.slice(endIdx + MARKER_END.length);\n }\n\n // Append with a blank line separator\n const separator = fileContent.length > 0 && !fileContent.endsWith('\\n') ? '\\n' : '';\n return fileContent + separator + '\\n' + block + '\\n';\n}\n","export interface ConflictWarning {\n file: string;\n line: number;\n variable: string;\n existingValue: string;\n}\n\n/**\n * Scan CSS file contents for existing declarations of the given custom properties.\n * Uses simple regex matching -- no CSS parser needed since custom property\n * declarations have unambiguous syntax.\n */\nexport function scanConflicts(\n files: Array<{ path: string; content: string }>,\n variables: string[],\n): ConflictWarning[] {\n if (variables.length === 0) return [];\n\n const warnings: ConflictWarning[] = [];\n // Match lines like ` --variable-name: value;` or `--variable-name: value`\n const varSet = new Set(variables);\n\n for (const file of files) {\n const lines = file.content.split('\\n');\n for (let i = 0; i < lines.length; i++) {\n const line = lines[i]!;\n const match = line.match(/^\\s*(--[\\w-]+)\\s*:\\s*(.+?)\\s*;?\\s*$/);\n if (match && varSet.has(match[1]!)) {\n warnings.push({\n file: file.path,\n line: i + 1,\n variable: match[1]!,\n existingValue: match[2]!,\n });\n }\n }\n }\n\n return warnings;\n}\n","import { readFileSync, writeFileSync, readdirSync, statSync } from 'node:fs';\nimport { resolve, join } from 'node:path';\nimport { argv, exit, stderr, stdout } from 'node:process';\n\nimport { decodeThemeHash } from './codec';\nimport { applyThemeBlock, generateThemeCSS, MARKER_START } from './apply';\nimport { scanConflicts } from './scan';\n\ninterface ParsedArgs {\n command: string;\n hash: string;\n target: string;\n colorSpace: 'hsl' | 'oklch';\n scanDir: string;\n dryRun: boolean;\n}\n\nfunction printUsage() {\n stderr.write(`\nUsage: enad-theme apply <hash> [options]\n\nOptions:\n --target <file> Target CSS file (default: src/globals.css)\n --color-space <cs> Color space: hsl | oklch (default: hsl)\n --scan <dir> Directory to scan for conflicts (default: src)\n --dry-run Print CSS to stdout without writing\n --help Show this help message\n\nExamples:\n enad-theme apply 1k5YWJj...\n enad-theme apply 1k5YWJj... --target app/globals.css --color-space oklch\n enad-theme apply 1k5YWJj... --dry-run\n`);\n}\n\nfunction parseArgs(args: string[]): ParsedArgs | null {\n if (args.length === 0 || args.includes('--help')) {\n printUsage();\n exit(0);\n }\n\n const command = args[0]!;\n if (command !== 'apply') {\n stderr.write(`Unknown command: ${command}\\nRun enad-theme --help for usage.\\n`);\n exit(1);\n }\n\n const hash = args[1];\n if (!hash) {\n stderr.write('Error: missing theme hash argument.\\n');\n exit(1);\n }\n\n let target = 'src/globals.css';\n let colorSpace: 'hsl' | 'oklch' = 'hsl';\n let scanDir = 'src';\n let dryRun = false;\n\n for (let i = 2; i < args.length; i++) {\n switch (args[i]) {\n case '--target':\n target = args[++i] ?? target;\n break;\n case '--color-space':\n colorSpace = (args[++i] as 'hsl' | 'oklch') ?? colorSpace;\n break;\n case '--scan':\n scanDir = args[++i] ?? scanDir;\n break;\n case '--dry-run':\n dryRun = true;\n break;\n }\n }\n\n return { command, hash, target, colorSpace, scanDir, dryRun };\n}\n\nfunction readExistingFile(targetPath: string): string {\n try {\n return readFileSync(targetPath, 'utf-8');\n } catch {\n // File doesn't exist yet, we'll create it\n return '';\n }\n}\n\nfunction writeOutput(targetPath: string, target: string, existing: string, css: string) {\n const updated = applyThemeBlock(existing, css);\n writeFileSync(targetPath, updated, 'utf-8');\n\n const isUpdate = existing.includes(MARKER_START);\n stderr.write(\n isUpdate\n ? `Updated theme block in ${target}\\n`\n : `Wrote theme block to ${target}\\n`,\n );\n}\n\nfunction scanForConflicts(scanDir: string, targetPath: string, css: string) {\n // Extract variable names from the generated CSS\n const varPattern = /^\\s*(--[\\w-]+)\\s*:/gm;\n const variables: string[] = [];\n let match: RegExpExecArray | null;\n while ((match = varPattern.exec(css)) !== null) {\n variables.push(match[1]!);\n }\n\n if (variables.length === 0) return;\n\n // Simple recursive CSS file scan\n const cssFiles: Array<{ path: string; content: string }> = [];\n\n function walk(dir: string) {\n try {\n for (const entry of readdirSync(dir)) {\n const full = join(dir, entry);\n try {\n const stat = statSync(full);\n if (stat.isDirectory() && !entry.startsWith('.') && entry !== 'node_modules') {\n walk(full);\n } else if (stat.isFile() && full.endsWith('.css') && resolve(full) !== targetPath) {\n cssFiles.push({ path: full, content: readFileSync(full, 'utf-8') });\n }\n } catch {\n // Skip inaccessible files\n }\n }\n } catch {\n // Skip inaccessible directories\n }\n }\n\n walk(resolve(scanDir));\n\n const warnings = scanConflicts(cssFiles, variables);\n if (warnings.length > 0) {\n stderr.write(`\\nConflicting declarations found:\\n`);\n for (const w of warnings) {\n stderr.write(` ${w.file}:${w.line} ${w.variable}: ${w.existingValue}\\n`);\n }\n stderr.write(`\\nThese existing declarations may override or conflict with the theme.\\n`);\n }\n}\n\nfunction main() {\n const parsed = parseArgs(argv.slice(2));\n if (!parsed) return;\n\n const { hash, target, colorSpace, scanDir, dryRun } = parsed;\n\n // Decode\n const decoded = decodeThemeHash(hash);\n if (Object.keys(decoded).length === 0) {\n stderr.write('Error: failed to decode theme hash. Check that the hash is valid.\\n');\n exit(1);\n }\n\n // Generate CSS\n const css = generateThemeCSS(decoded, { colorSpace });\n\n if (dryRun) {\n stdout.write(css + '\\n');\n exit(0);\n }\n\n // Write to target file\n const targetPath = resolve(target);\n const existing = readExistingFile(targetPath);\n writeOutput(targetPath, target, existing, css);\n\n scanForConflicts(scanDir, targetPath, css);\n}\n\nmain();\n"],"mappings":"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"}
1
+ {"version":3,"file":"cli.mjs","names":["msgpackDecode"],"sources":["../../../src/client/theme/codec.ts","../../../src/client/theme/defaults.ts","../../../src/client/theme/apply.ts","../../../src/client/theme/scan.ts","../../../src/client/theme/cli.ts"],"sourcesContent":["import { decode as msgpackDecode, encode as msgpackEncode } from \"@msgpack/msgpack\";\n\n/**\n * Loose bag of theme values. The decoder returns whatever keys are present;\n * the consumer merges onto its own defaults. This keeps the format\n * forward/backward compatible: new keys are silently ignored by old decoders,\n * and removed keys are filled from defaults by the consumer.\n */\nexport type ThemeHash = Record<string, unknown>;\n\n// Current format version. Prepended as a single ASCII char before the base64url payload.\nconst FORMAT_VERSION = \"1\";\n\n// ---------------------------------------------------------------------------\n// Short key mapping\n// ---------------------------------------------------------------------------\n\n/** Short key -> full key */\nexport const KEY_MAP: Record<string, string> = {\n c: \"colorize\",\n i: \"intensity\",\n d: \"delight\",\n r: \"radius\",\n bf: \"fontBody\",\n hf: \"fontHeading\",\n ic: \"iconSet\",\n cs: \"colorSpace\",\n dm: \"darkMode\",\n lc: \"lightColors\",\n dc: \"darkColors\",\n br: \"buttonRadius\",\n cr: \"cardRadius\",\n ir: \"inputRadius\",\n mr: \"imageRadius\",\n sp: \"shadowPreset\",\n sc: \"shadowColor\",\n hw: \"headingWeight\",\n ht: \"headingTracking\",\n bw: \"bodyWeight\",\n hx: \"headingTransform\",\n bdr: \"borderWidth\",\n oc: \"overlayColor\",\n of: \"overlayFromOpacity\",\n ot: \"overlayToOpacity\",\n v: \"variants\",\n xs: \"componentSet\",\n};\n\n/** Full key -> short key (inverse of KEY_MAP) */\nexport const KEY_MAP_REVERSE: Record<string, string> = Object.fromEntries(\n Object.entries(KEY_MAP).map(([short, full]) => [full, short]),\n);\n\n// ---------------------------------------------------------------------------\n// Base64url helpers (RFC 4648 §5, no padding)\n// ---------------------------------------------------------------------------\n\nfunction toBase64url(buf: Uint8Array): string {\n let binary = \"\";\n for (let i = 0; i < buf.length; i++) {\n binary += String.fromCharCode(buf[i]!);\n }\n return btoa(binary).replace(/\\+/g, \"-\").replace(/\\//g, \"_\").replace(/=+$/, \"\");\n}\n\nfunction fromBase64url(str: string): Uint8Array {\n const base64 = str.replace(/-/g, \"+\").replace(/_/g, \"/\");\n const padded = base64 + \"=\".repeat((4 - (base64.length % 4)) % 4);\n const binary = atob(padded);\n const bytes = new Uint8Array(binary.length);\n for (let i = 0; i < binary.length; i++) {\n bytes[i] = binary.charCodeAt(i);\n }\n return bytes;\n}\n\n// ---------------------------------------------------------------------------\n// Encode / Decode\n// ---------------------------------------------------------------------------\n\n/**\n * Encode a theme state diff into a portable hash string.\n *\n * The input should only contain non-default values. The encoder maps\n * full keys to short keys, packs with MessagePack, and encodes as\n * `<version><base64url>`.\n */\nexport function encodeThemeHash(diff: ThemeHash): string {\n const compact: Record<string, unknown> = {};\n for (const [fullKey, value] of Object.entries(diff)) {\n const shortKey = KEY_MAP_REVERSE[fullKey] ?? fullKey;\n compact[shortKey] = value;\n }\n const packed = msgpackEncode(compact);\n return FORMAT_VERSION + toBase64url(packed);\n}\n\n/**\n * Decode a hash string back into a key-value bag with full key names.\n *\n * Returns partial data -- the consumer is responsible for merging onto\n * its own defaults. Unknown keys are preserved for forward compatibility.\n * Returns an empty object on invalid input (never throws).\n */\nexport function decodeThemeHash(hash: string): ThemeHash {\n try {\n if (!hash || hash.length < 2) return {};\n\n const version = hash[0];\n if (version !== FORMAT_VERSION) return {};\n\n const payload = hash.slice(1);\n const bytes = fromBase64url(payload);\n const compact = msgpackDecode(bytes) as Record<string, unknown>;\n\n if (typeof compact !== \"object\" || compact === null) return {};\n\n const result: ThemeHash = {};\n for (const [key, value] of Object.entries(compact)) {\n const fullKey = KEY_MAP[key] ?? key;\n result[fullKey] = value;\n }\n return result;\n } catch {\n return {};\n }\n}\n","/**\n * SDK default color tokens. These are the canonical defaults used by\n * the theme codec to compute diffs (only non-default values are encoded).\n */\nexport const SDK_DEFAULTS = {\n light: {\n \"--background\": \"#ffffff\",\n \"--foreground\": \"#111827\",\n \"--card\": \"#ffffff\",\n \"--card-foreground\": \"#111827\",\n \"--popover\": \"#ffffff\",\n \"--popover-foreground\": \"#111827\",\n \"--primary\": \"#2563eb\",\n \"--primary-foreground\": \"#ffffff\",\n \"--secondary\": \"#f1f5f9\",\n \"--secondary-foreground\": \"#0f172a\",\n \"--muted\": \"#f3f4f6\",\n \"--muted-foreground\": \"#636b78\",\n \"--accent\": \"#dbeafe\",\n \"--accent-foreground\": \"#1e3a8a\",\n \"--accent-muted\": \"#eff6ff\",\n \"--accent-muted-foreground\": \"#1e40af\",\n \"--destructive\": \"#dc2626\",\n \"--destructive-foreground\": \"#ffffff\",\n \"--border\": \"#e5e7eb\",\n \"--input\": \"#e5e7eb\",\n \"--ring\": \"#2563eb\",\n } as Record<string, string>,\n dark: {\n \"--background\": \"#111827\",\n \"--foreground\": \"#f9fafb\",\n \"--card\": \"#1f2937\",\n \"--card-foreground\": \"#f9fafb\",\n \"--popover\": \"#1f2937\",\n \"--popover-foreground\": \"#f9fafb\",\n \"--primary\": \"#2563eb\",\n \"--primary-foreground\": \"#ffffff\",\n \"--secondary\": \"#1e293b\",\n \"--secondary-foreground\": \"#e2e8f0\",\n \"--muted\": \"#374151\",\n \"--muted-foreground\": \"#b0b8c4\",\n \"--accent\": \"#1e3a5f\",\n \"--accent-foreground\": \"#bfdbfe\",\n \"--accent-muted\": \"#172554\",\n \"--accent-muted-foreground\": \"#93c5fd\",\n \"--destructive\": \"#dc2626\",\n \"--destructive-foreground\": \"#ffffff\",\n \"--border\": \"#374151\",\n \"--input\": \"#374151\",\n \"--ring\": \"#2563eb\",\n } as Record<string, string>,\n};\n\n/** Default values for design tokens (non-color). */\nexport const TOKEN_DEFAULTS = {\n colorize: 50,\n intensity: 50,\n delight: 50,\n radius: 0.75,\n fontBody: \"Inter\",\n fontHeading: \"Inter\",\n iconSet: \"Phosphor\",\n colorSpace: \"hsl\",\n darkMode: false,\n componentSet: \"default\" as const,\n\n // Shape\n buttonRadius: \"9999px\",\n cardRadius: \"var(--radius)\",\n inputRadius: \"var(--radius)\",\n imageRadius: \"0px\",\n\n // Depth\n shadowPreset: \"none\",\n shadowColor: \"oklch(0 0 0 / 0.1)\",\n\n // Typography\n headingWeight: \"600\",\n headingTracking: \"0em\",\n bodyWeight: \"400\",\n headingTransform: \"none\",\n\n // Border\n borderWidth: \"1px\",\n\n // Overlay\n overlayColor: \"black\",\n overlayFromOpacity: \"0.5\",\n overlayToOpacity: \"0\",\n\n // Variants\n variants: {\n hero: \"overlay\",\n linkBlock: \"overlay\",\n productCard: \"gallery\",\n contentWithImage: \"side-by-side\",\n gallery: \"grid\",\n textContent: \"default\",\n },\n} as const;\n","import type { ThemeHash } from \"./codec\";\nimport { SDK_DEFAULTS, TOKEN_DEFAULTS } from \"./defaults\";\n\nexport interface GenerateOptions {\n colorSpace?: \"hsl\" | \"oklch\";\n}\n\nfunction buildLightColorDiffs(hash: ThemeHash): string[] {\n const lightOverrides = (hash.lightColors ?? {}) as Record<string, string>;\n const diffs: string[] = [];\n for (const [token, value] of Object.entries(lightOverrides)) {\n if (value !== SDK_DEFAULTS.light[token]) {\n diffs.push(` ${token}: ${value};`);\n }\n }\n return diffs;\n}\n\nfunction buildBaseTokenDiffs(hash: ThemeHash): string[] {\n const diffs: string[] = [];\n\n const radius = hash.radius as number | undefined;\n if (radius != null && radius !== 0.75) {\n diffs.push(` --radius: ${radius}rem;`);\n }\n\n const fontBody = hash.fontBody as string | undefined;\n if (fontBody && fontBody !== \"Inter\") {\n diffs.push(` --font-sans: \"${fontBody}\", sans-serif;`);\n }\n\n const fontHeading = hash.fontHeading as string | undefined;\n if (fontHeading && fontHeading !== fontBody && fontHeading !== \"Inter\") {\n diffs.push(` --font-heading: \"${fontHeading}\", sans-serif;`);\n }\n\n return diffs;\n}\n\nfunction buildDarkColorDiffs(hash: ThemeHash): string[] {\n const darkOverrides = (hash.darkColors ?? {}) as Record<string, string>;\n const diffs: string[] = [];\n for (const [token, value] of Object.entries(darkOverrides)) {\n if (value !== SDK_DEFAULTS.dark[token]) {\n diffs.push(` ${token}: ${value};`);\n }\n }\n return diffs;\n}\n\nfunction buildTokenSections(hash: ThemeHash): string[] {\n const lines: string[] = [];\n\n const tokenSections: Array<{ comment: string; entries: Array<[string, string, string]> }> = [\n {\n comment: \"Shape\",\n entries: [\n [\"--enad-button-radius\", hash.buttonRadius as string, TOKEN_DEFAULTS.buttonRadius],\n [\"--enad-card-radius\", hash.cardRadius as string, TOKEN_DEFAULTS.cardRadius],\n [\"--enad-input-radius\", hash.inputRadius as string, TOKEN_DEFAULTS.inputRadius],\n [\"--enad-image-radius\", hash.imageRadius as string, TOKEN_DEFAULTS.imageRadius],\n ],\n },\n {\n comment: \"Depth\",\n entries: [[\"--enad-shadow-color\", hash.shadowColor as string, TOKEN_DEFAULTS.shadowColor]],\n },\n {\n comment: \"Typography\",\n entries: [\n [\"--enad-heading-weight\", hash.headingWeight as string, TOKEN_DEFAULTS.headingWeight],\n [\"--enad-heading-tracking\", hash.headingTracking as string, TOKEN_DEFAULTS.headingTracking],\n [\"--enad-body-weight\", hash.bodyWeight as string, TOKEN_DEFAULTS.bodyWeight],\n [\n \"--enad-heading-transform\",\n hash.headingTransform as string,\n TOKEN_DEFAULTS.headingTransform,\n ],\n ],\n },\n {\n comment: \"Borders\",\n entries: [[\"--enad-border-width\", hash.borderWidth as string, TOKEN_DEFAULTS.borderWidth]],\n },\n {\n comment: \"Overlay\",\n entries: [\n [\"--enad-overlay-color\", hash.overlayColor as string, TOKEN_DEFAULTS.overlayColor],\n [\n \"--enad-overlay-from-opacity\",\n hash.overlayFromOpacity as string,\n TOKEN_DEFAULTS.overlayFromOpacity,\n ],\n [\n \"--enad-overlay-to-opacity\",\n hash.overlayToOpacity as string,\n TOKEN_DEFAULTS.overlayToOpacity,\n ],\n ],\n },\n ];\n\n for (const section of tokenSections) {\n const sectionLines: string[] = [];\n for (const [varName, value, defaultValue] of section.entries) {\n if (value != null && value !== defaultValue) {\n sectionLines.push(` ${varName}: ${value};`);\n }\n }\n if (sectionLines.length > 0) {\n lines.push(\"\", `/* ${section.comment} */`, \":root {\", ...sectionLines, \"}\");\n }\n }\n\n return lines;\n}\n\n/**\n * Generate CSS variable declarations from a decoded theme hash.\n * Merges the hash onto SDK defaults and only emits values that differ.\n */\n// eslint-disable-next-line @typescript-eslint/no-unused-vars\nexport function generateThemeCSS(hash: ThemeHash, _options: GenerateOptions = {}): string {\n const lines: string[] = [\"/* Generated by enad-theme */\"];\n\n // --- Light color diffs + base tokens ---\n const lightDiffs = [...buildLightColorDiffs(hash), ...buildBaseTokenDiffs(hash)];\n if (lightDiffs.length > 0) {\n lines.push(\"\", \":root {\", ...lightDiffs, \"}\");\n }\n\n // --- Dark color diffs ---\n const darkDiffs = buildDarkColorDiffs(hash);\n if (darkDiffs.length > 0) {\n lines.push(\"\", \".dark {\", ...darkDiffs, \"}\");\n }\n\n // --- Token sections ---\n lines.push(...buildTokenSections(hash));\n\n return lines.join(\"\\n\");\n}\n\n// Sentinel markers for idempotent file writes\nexport const MARKER_START = \"/* === enad-theme:start === */\";\nexport const MARKER_END = \"/* === enad-theme:end === */\";\n\n/**\n * Insert or replace a theme block in a CSS file's content.\n * Returns the updated file content.\n */\nexport function applyThemeBlock(fileContent: string, cssBlock: string): string {\n const startIdx = fileContent.indexOf(MARKER_START);\n const endIdx = fileContent.indexOf(MARKER_END);\n\n const block = `${MARKER_START}\\n${cssBlock}\\n${MARKER_END}`;\n\n if (startIdx !== -1 && endIdx !== -1) {\n return fileContent.slice(0, startIdx) + block + fileContent.slice(endIdx + MARKER_END.length);\n }\n\n // Append with a blank line separator\n const separator = fileContent.length > 0 && !fileContent.endsWith(\"\\n\") ? \"\\n\" : \"\";\n return fileContent + separator + \"\\n\" + block + \"\\n\";\n}\n","export interface ConflictWarning {\n file: string;\n line: number;\n variable: string;\n existingValue: string;\n}\n\n/**\n * Scan CSS file contents for existing declarations of the given custom properties.\n * Uses simple regex matching -- no CSS parser needed since custom property\n * declarations have unambiguous syntax.\n */\nexport function scanConflicts(\n files: Array<{ path: string; content: string }>,\n variables: string[],\n): ConflictWarning[] {\n if (variables.length === 0) return [];\n\n const warnings: ConflictWarning[] = [];\n // Match lines like ` --variable-name: value;` or `--variable-name: value`\n const varSet = new Set(variables);\n\n for (const file of files) {\n const lines = file.content.split('\\n');\n for (let i = 0; i < lines.length; i++) {\n const line = lines[i]!;\n const match = line.match(/^\\s*(--[\\w-]+)\\s*:\\s*(.+?)\\s*;?\\s*$/);\n if (match && varSet.has(match[1]!)) {\n warnings.push({\n file: file.path,\n line: i + 1,\n variable: match[1]!,\n existingValue: match[2]!,\n });\n }\n }\n }\n\n return warnings;\n}\n","import { readFileSync, writeFileSync, readdirSync, statSync } from 'node:fs';\nimport { resolve, join } from 'node:path';\nimport { argv, exit, stderr, stdout } from 'node:process';\n\nimport { decodeThemeHash } from './codec';\nimport { applyThemeBlock, generateThemeCSS, MARKER_START } from './apply';\nimport { scanConflicts } from './scan';\n\ninterface ParsedArgs {\n command: string;\n hash: string;\n target: string;\n colorSpace: 'hsl' | 'oklch';\n scanDir: string;\n dryRun: boolean;\n}\n\nfunction printUsage() {\n stderr.write(`\nUsage: enad-theme apply <hash> [options]\n\nOptions:\n --target <file> Target CSS file (default: src/globals.css)\n --color-space <cs> Color space: hsl | oklch (default: hsl)\n --scan <dir> Directory to scan for conflicts (default: src)\n --dry-run Print CSS to stdout without writing\n --help Show this help message\n\nExamples:\n enad-theme apply 1k5YWJj...\n enad-theme apply 1k5YWJj... --target app/globals.css --color-space oklch\n enad-theme apply 1k5YWJj... --dry-run\n`);\n}\n\nfunction parseArgs(args: string[]): ParsedArgs | null {\n if (args.length === 0 || args.includes('--help')) {\n printUsage();\n exit(0);\n }\n\n const command = args[0]!;\n if (command !== 'apply') {\n stderr.write(`Unknown command: ${command}\\nRun enad-theme --help for usage.\\n`);\n exit(1);\n }\n\n const hash = args[1];\n if (!hash) {\n stderr.write('Error: missing theme hash argument.\\n');\n exit(1);\n }\n\n let target = 'src/globals.css';\n let colorSpace: 'hsl' | 'oklch' = 'hsl';\n let scanDir = 'src';\n let dryRun = false;\n\n for (let i = 2; i < args.length; i++) {\n switch (args[i]) {\n case '--target':\n target = args[++i] ?? target;\n break;\n case '--color-space':\n colorSpace = (args[++i] as 'hsl' | 'oklch') ?? colorSpace;\n break;\n case '--scan':\n scanDir = args[++i] ?? scanDir;\n break;\n case '--dry-run':\n dryRun = true;\n break;\n }\n }\n\n return { command, hash, target, colorSpace, scanDir, dryRun };\n}\n\nfunction readExistingFile(targetPath: string): string {\n try {\n return readFileSync(targetPath, 'utf-8');\n } catch {\n // File doesn't exist yet, we'll create it\n return '';\n }\n}\n\nfunction writeOutput(targetPath: string, target: string, existing: string, css: string) {\n const updated = applyThemeBlock(existing, css);\n writeFileSync(targetPath, updated, 'utf-8');\n\n const isUpdate = existing.includes(MARKER_START);\n stderr.write(\n isUpdate\n ? `Updated theme block in ${target}\\n`\n : `Wrote theme block to ${target}\\n`,\n );\n}\n\nfunction scanForConflicts(scanDir: string, targetPath: string, css: string) {\n // Extract variable names from the generated CSS\n const varPattern = /^\\s*(--[\\w-]+)\\s*:/gm;\n const variables: string[] = [];\n let match: RegExpExecArray | null;\n while ((match = varPattern.exec(css)) !== null) {\n variables.push(match[1]!);\n }\n\n if (variables.length === 0) return;\n\n // Simple recursive CSS file scan\n const cssFiles: Array<{ path: string; content: string }> = [];\n\n function walk(dir: string) {\n try {\n for (const entry of readdirSync(dir)) {\n const full = join(dir, entry);\n try {\n const stat = statSync(full);\n if (stat.isDirectory() && !entry.startsWith('.') && entry !== 'node_modules') {\n walk(full);\n } else if (stat.isFile() && full.endsWith('.css') && resolve(full) !== targetPath) {\n cssFiles.push({ path: full, content: readFileSync(full, 'utf-8') });\n }\n } catch {\n // Skip inaccessible files\n }\n }\n } catch {\n // Skip inaccessible directories\n }\n }\n\n walk(resolve(scanDir));\n\n const warnings = scanConflicts(cssFiles, variables);\n if (warnings.length > 0) {\n stderr.write(`\\nConflicting declarations found:\\n`);\n for (const w of warnings) {\n stderr.write(` ${w.file}:${w.line} ${w.variable}: ${w.existingValue}\\n`);\n }\n stderr.write(`\\nThese existing declarations may override or conflict with the theme.\\n`);\n }\n}\n\nfunction main() {\n const parsed = parseArgs(argv.slice(2));\n if (!parsed) return;\n\n const { hash, target, colorSpace, scanDir, dryRun } = parsed;\n\n // Decode\n const decoded = decodeThemeHash(hash);\n if (Object.keys(decoded).length === 0) {\n stderr.write('Error: failed to decode theme hash. Check that the hash is valid.\\n');\n exit(1);\n }\n\n // Generate CSS\n const css = generateThemeCSS(decoded, { colorSpace });\n\n if (dryRun) {\n stdout.write(css + '\\n');\n exit(0);\n }\n\n // Write to target file\n const targetPath = resolve(target);\n const existing = readExistingFile(targetPath);\n writeOutput(targetPath, target, existing, css);\n\n scanForConflicts(scanDir, targetPath, css);\n}\n\nmain();\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"codec.d.ts","names":[],"sources":["../../../src/client/theme/codec.ts"],"mappings":";;AAQA;;;;;KAAY,SAAA,GAAY,MAAA;;cAUX,OAAA,EAAS,MAAA;;cAiCT,eAAA,EAAiB,MAAA;AAA9B;;;;;AAsCA;;AAtCA,iBAsCgB,eAAA,CAAgB,IAAA,EAAM,SAAA;;;AAiBtC;;;;;iBAAgB,eAAA,CAAgB,IAAA,WAAe,SAAA"}
1
+ {"version":3,"file":"codec.d.ts","names":[],"sources":["../../../src/client/theme/codec.ts"],"mappings":";;AAQA;;;;;KAAY,SAAA,GAAY,MAAA;;cAUX,OAAA,EAAS,MAAA;;cA+BT,eAAA,EAAiB,MAAA;AAA9B;;;;;AAsCA;;AAtCA,iBAsCgB,eAAA,CAAgB,IAAA,EAAM,SAAA;;;AAiBtC;;;;;iBAAgB,eAAA,CAAgB,IAAA,WAAe,SAAA"}
@@ -28,8 +28,6 @@ const KEY_MAP = {
28
28
  oc: "overlayColor",
29
29
  of: "overlayFromOpacity",
30
30
  ot: "overlayToOpacity",
31
- hs: "imageHoverScale",
32
- hd: "imageHoverDuration",
33
31
  v: "variants",
34
32
  xs: "componentSet"
35
33
  };
@@ -1 +1 @@
1
- {"version":3,"file":"codec.mjs","names":["msgpackEncode","msgpackDecode"],"sources":["../../../src/client/theme/codec.ts"],"sourcesContent":["import { decode as msgpackDecode, encode as msgpackEncode } from \"@msgpack/msgpack\";\n\n/**\n * Loose bag of theme values. The decoder returns whatever keys are present;\n * the consumer merges onto its own defaults. This keeps the format\n * forward/backward compatible: new keys are silently ignored by old decoders,\n * and removed keys are filled from defaults by the consumer.\n */\nexport type ThemeHash = Record<string, unknown>;\n\n// Current format version. Prepended as a single ASCII char before the base64url payload.\nconst FORMAT_VERSION = \"1\";\n\n// ---------------------------------------------------------------------------\n// Short key mapping\n// ---------------------------------------------------------------------------\n\n/** Short key -> full key */\nexport const KEY_MAP: Record<string, string> = {\n c: \"colorize\",\n i: \"intensity\",\n d: \"delight\",\n r: \"radius\",\n bf: \"fontBody\",\n hf: \"fontHeading\",\n ic: \"iconSet\",\n cs: \"colorSpace\",\n dm: \"darkMode\",\n lc: \"lightColors\",\n dc: \"darkColors\",\n br: \"buttonRadius\",\n cr: \"cardRadius\",\n ir: \"inputRadius\",\n mr: \"imageRadius\",\n sp: \"shadowPreset\",\n sc: \"shadowColor\",\n hw: \"headingWeight\",\n ht: \"headingTracking\",\n bw: \"bodyWeight\",\n hx: \"headingTransform\",\n bdr: \"borderWidth\",\n oc: \"overlayColor\",\n of: \"overlayFromOpacity\",\n ot: \"overlayToOpacity\",\n hs: \"imageHoverScale\",\n hd: \"imageHoverDuration\",\n v: \"variants\",\n xs: \"componentSet\",\n};\n\n/** Full key -> short key (inverse of KEY_MAP) */\nexport const KEY_MAP_REVERSE: Record<string, string> = Object.fromEntries(\n Object.entries(KEY_MAP).map(([short, full]) => [full, short]),\n);\n\n// ---------------------------------------------------------------------------\n// Base64url helpers (RFC 4648 §5, no padding)\n// ---------------------------------------------------------------------------\n\nfunction toBase64url(buf: Uint8Array): string {\n let binary = \"\";\n for (let i = 0; i < buf.length; i++) {\n binary += String.fromCharCode(buf[i]!);\n }\n return btoa(binary).replace(/\\+/g, \"-\").replace(/\\//g, \"_\").replace(/=+$/, \"\");\n}\n\nfunction fromBase64url(str: string): Uint8Array {\n const base64 = str.replace(/-/g, \"+\").replace(/_/g, \"/\");\n const padded = base64 + \"=\".repeat((4 - (base64.length % 4)) % 4);\n const binary = atob(padded);\n const bytes = new Uint8Array(binary.length);\n for (let i = 0; i < binary.length; i++) {\n bytes[i] = binary.charCodeAt(i);\n }\n return bytes;\n}\n\n// ---------------------------------------------------------------------------\n// Encode / Decode\n// ---------------------------------------------------------------------------\n\n/**\n * Encode a theme state diff into a portable hash string.\n *\n * The input should only contain non-default values. The encoder maps\n * full keys to short keys, packs with MessagePack, and encodes as\n * `<version><base64url>`.\n */\nexport function encodeThemeHash(diff: ThemeHash): string {\n const compact: Record<string, unknown> = {};\n for (const [fullKey, value] of Object.entries(diff)) {\n const shortKey = KEY_MAP_REVERSE[fullKey] ?? fullKey;\n compact[shortKey] = value;\n }\n const packed = msgpackEncode(compact);\n return FORMAT_VERSION + toBase64url(packed);\n}\n\n/**\n * Decode a hash string back into a key-value bag with full key names.\n *\n * Returns partial data -- the consumer is responsible for merging onto\n * its own defaults. Unknown keys are preserved for forward compatibility.\n * Returns an empty object on invalid input (never throws).\n */\nexport function decodeThemeHash(hash: string): ThemeHash {\n try {\n if (!hash || hash.length < 2) return {};\n\n const version = hash[0];\n if (version !== FORMAT_VERSION) return {};\n\n const payload = hash.slice(1);\n const bytes = fromBase64url(payload);\n const compact = msgpackDecode(bytes) as Record<string, unknown>;\n\n if (typeof compact !== \"object\" || compact === null) return {};\n\n const result: ThemeHash = {};\n for (const [key, value] of Object.entries(compact)) {\n const fullKey = KEY_MAP[key] ?? key;\n result[fullKey] = value;\n }\n return result;\n } catch {\n return {};\n }\n}\n"],"mappings":";;AAWA,MAAM,iBAAiB;;AAOvB,MAAa,UAAkC;CAC7C,GAAG;CACH,GAAG;CACH,GAAG;CACH,GAAG;CACH,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,KAAK;CACL,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,GAAG;CACH,IAAI;CACL;;AAGD,MAAa,kBAA0C,OAAO,YAC5D,OAAO,QAAQ,QAAQ,CAAC,KAAK,CAAC,OAAO,UAAU,CAAC,MAAM,MAAM,CAAC,CAC9D;AAMD,SAAS,YAAY,KAAyB;CAC5C,IAAI,SAAS;AACb,MAAK,IAAI,IAAI,GAAG,IAAI,IAAI,QAAQ,IAC9B,WAAU,OAAO,aAAa,IAAI,GAAI;AAExC,QAAO,KAAK,OAAO,CAAC,QAAQ,OAAO,IAAI,CAAC,QAAQ,OAAO,IAAI,CAAC,QAAQ,OAAO,GAAG;;AAGhF,SAAS,cAAc,KAAyB;CAC9C,MAAM,SAAS,IAAI,QAAQ,MAAM,IAAI,CAAC,QAAQ,MAAM,IAAI;CACxD,MAAM,SAAS,SAAS,IAAI,QAAQ,IAAK,OAAO,SAAS,KAAM,EAAE;CACjE,MAAM,SAAS,KAAK,OAAO;CAC3B,MAAM,QAAQ,IAAI,WAAW,OAAO,OAAO;AAC3C,MAAK,IAAI,IAAI,GAAG,IAAI,OAAO,QAAQ,IACjC,OAAM,KAAK,OAAO,WAAW,EAAE;AAEjC,QAAO;;;;;;;;;AAcT,SAAgB,gBAAgB,MAAyB;CACvD,MAAM,UAAmC,EAAE;AAC3C,MAAK,MAAM,CAAC,SAAS,UAAU,OAAO,QAAQ,KAAK,EAAE;EACnD,MAAM,WAAW,gBAAgB,YAAY;AAC7C,UAAQ,YAAY;;AAGtB,QAAO,iBAAiB,YADTA,OAAc,QAAQ,CACM;;;;;;;;;AAU7C,SAAgB,gBAAgB,MAAyB;AACvD,KAAI;AACF,MAAI,CAAC,QAAQ,KAAK,SAAS,EAAG,QAAO,EAAE;AAGvC,MADgB,KAAK,OACL,eAAgB,QAAO,EAAE;EAIzC,MAAM,UAAUC,OADF,cADE,KAAK,MAAM,EAAE,CACO,CACA;AAEpC,MAAI,OAAO,YAAY,YAAY,YAAY,KAAM,QAAO,EAAE;EAE9D,MAAM,SAAoB,EAAE;AAC5B,OAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,QAAQ,EAAE;GAClD,MAAM,UAAU,QAAQ,QAAQ;AAChC,UAAO,WAAW;;AAEpB,SAAO;SACD;AACN,SAAO,EAAE"}
1
+ {"version":3,"file":"codec.mjs","names":["msgpackEncode","msgpackDecode"],"sources":["../../../src/client/theme/codec.ts"],"sourcesContent":["import { decode as msgpackDecode, encode as msgpackEncode } from \"@msgpack/msgpack\";\n\n/**\n * Loose bag of theme values. The decoder returns whatever keys are present;\n * the consumer merges onto its own defaults. This keeps the format\n * forward/backward compatible: new keys are silently ignored by old decoders,\n * and removed keys are filled from defaults by the consumer.\n */\nexport type ThemeHash = Record<string, unknown>;\n\n// Current format version. Prepended as a single ASCII char before the base64url payload.\nconst FORMAT_VERSION = \"1\";\n\n// ---------------------------------------------------------------------------\n// Short key mapping\n// ---------------------------------------------------------------------------\n\n/** Short key -> full key */\nexport const KEY_MAP: Record<string, string> = {\n c: \"colorize\",\n i: \"intensity\",\n d: \"delight\",\n r: \"radius\",\n bf: \"fontBody\",\n hf: \"fontHeading\",\n ic: \"iconSet\",\n cs: \"colorSpace\",\n dm: \"darkMode\",\n lc: \"lightColors\",\n dc: \"darkColors\",\n br: \"buttonRadius\",\n cr: \"cardRadius\",\n ir: \"inputRadius\",\n mr: \"imageRadius\",\n sp: \"shadowPreset\",\n sc: \"shadowColor\",\n hw: \"headingWeight\",\n ht: \"headingTracking\",\n bw: \"bodyWeight\",\n hx: \"headingTransform\",\n bdr: \"borderWidth\",\n oc: \"overlayColor\",\n of: \"overlayFromOpacity\",\n ot: \"overlayToOpacity\",\n v: \"variants\",\n xs: \"componentSet\",\n};\n\n/** Full key -> short key (inverse of KEY_MAP) */\nexport const KEY_MAP_REVERSE: Record<string, string> = Object.fromEntries(\n Object.entries(KEY_MAP).map(([short, full]) => [full, short]),\n);\n\n// ---------------------------------------------------------------------------\n// Base64url helpers (RFC 4648 §5, no padding)\n// ---------------------------------------------------------------------------\n\nfunction toBase64url(buf: Uint8Array): string {\n let binary = \"\";\n for (let i = 0; i < buf.length; i++) {\n binary += String.fromCharCode(buf[i]!);\n }\n return btoa(binary).replace(/\\+/g, \"-\").replace(/\\//g, \"_\").replace(/=+$/, \"\");\n}\n\nfunction fromBase64url(str: string): Uint8Array {\n const base64 = str.replace(/-/g, \"+\").replace(/_/g, \"/\");\n const padded = base64 + \"=\".repeat((4 - (base64.length % 4)) % 4);\n const binary = atob(padded);\n const bytes = new Uint8Array(binary.length);\n for (let i = 0; i < binary.length; i++) {\n bytes[i] = binary.charCodeAt(i);\n }\n return bytes;\n}\n\n// ---------------------------------------------------------------------------\n// Encode / Decode\n// ---------------------------------------------------------------------------\n\n/**\n * Encode a theme state diff into a portable hash string.\n *\n * The input should only contain non-default values. The encoder maps\n * full keys to short keys, packs with MessagePack, and encodes as\n * `<version><base64url>`.\n */\nexport function encodeThemeHash(diff: ThemeHash): string {\n const compact: Record<string, unknown> = {};\n for (const [fullKey, value] of Object.entries(diff)) {\n const shortKey = KEY_MAP_REVERSE[fullKey] ?? fullKey;\n compact[shortKey] = value;\n }\n const packed = msgpackEncode(compact);\n return FORMAT_VERSION + toBase64url(packed);\n}\n\n/**\n * Decode a hash string back into a key-value bag with full key names.\n *\n * Returns partial data -- the consumer is responsible for merging onto\n * its own defaults. Unknown keys are preserved for forward compatibility.\n * Returns an empty object on invalid input (never throws).\n */\nexport function decodeThemeHash(hash: string): ThemeHash {\n try {\n if (!hash || hash.length < 2) return {};\n\n const version = hash[0];\n if (version !== FORMAT_VERSION) return {};\n\n const payload = hash.slice(1);\n const bytes = fromBase64url(payload);\n const compact = msgpackDecode(bytes) as Record<string, unknown>;\n\n if (typeof compact !== \"object\" || compact === null) return {};\n\n const result: ThemeHash = {};\n for (const [key, value] of Object.entries(compact)) {\n const fullKey = KEY_MAP[key] ?? key;\n result[fullKey] = value;\n }\n return result;\n } catch {\n return {};\n }\n}\n"],"mappings":";;AAWA,MAAM,iBAAiB;;AAOvB,MAAa,UAAkC;CAC7C,GAAG;CACH,GAAG;CACH,GAAG;CACH,GAAG;CACH,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,KAAK;CACL,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,GAAG;CACH,IAAI;CACL;;AAGD,MAAa,kBAA0C,OAAO,YAC5D,OAAO,QAAQ,QAAQ,CAAC,KAAK,CAAC,OAAO,UAAU,CAAC,MAAM,MAAM,CAAC,CAC9D;AAMD,SAAS,YAAY,KAAyB;CAC5C,IAAI,SAAS;AACb,MAAK,IAAI,IAAI,GAAG,IAAI,IAAI,QAAQ,IAC9B,WAAU,OAAO,aAAa,IAAI,GAAI;AAExC,QAAO,KAAK,OAAO,CAAC,QAAQ,OAAO,IAAI,CAAC,QAAQ,OAAO,IAAI,CAAC,QAAQ,OAAO,GAAG;;AAGhF,SAAS,cAAc,KAAyB;CAC9C,MAAM,SAAS,IAAI,QAAQ,MAAM,IAAI,CAAC,QAAQ,MAAM,IAAI;CACxD,MAAM,SAAS,SAAS,IAAI,QAAQ,IAAK,OAAO,SAAS,KAAM,EAAE;CACjE,MAAM,SAAS,KAAK,OAAO;CAC3B,MAAM,QAAQ,IAAI,WAAW,OAAO,OAAO;AAC3C,MAAK,IAAI,IAAI,GAAG,IAAI,OAAO,QAAQ,IACjC,OAAM,KAAK,OAAO,WAAW,EAAE;AAEjC,QAAO;;;;;;;;;AAcT,SAAgB,gBAAgB,MAAyB;CACvD,MAAM,UAAmC,EAAE;AAC3C,MAAK,MAAM,CAAC,SAAS,UAAU,OAAO,QAAQ,KAAK,EAAE;EACnD,MAAM,WAAW,gBAAgB,YAAY;AAC7C,UAAQ,YAAY;;AAGtB,QAAO,iBAAiB,YADTA,OAAc,QAAQ,CACM;;;;;;;;;AAU7C,SAAgB,gBAAgB,MAAyB;AACvD,KAAI;AACF,MAAI,CAAC,QAAQ,KAAK,SAAS,EAAG,QAAO,EAAE;AAGvC,MADgB,KAAK,OACL,eAAgB,QAAO,EAAE;EAIzC,MAAM,UAAUC,OADF,cADE,KAAK,MAAM,EAAE,CACO,CACA;AAEpC,MAAI,OAAO,YAAY,YAAY,YAAY,KAAM,QAAO,EAAE;EAE9D,MAAM,SAAoB,EAAE;AAC5B,OAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,QAAQ,EAAE;GAClD,MAAM,UAAU,QAAQ,QAAQ;AAChC,UAAO,WAAW;;AAEpB,SAAO;SACD;AACN,SAAO,EAAE"}
@@ -33,8 +33,6 @@ declare const TOKEN_DEFAULTS: {
33
33
  readonly overlayColor: "black";
34
34
  readonly overlayFromOpacity: "0.5";
35
35
  readonly overlayToOpacity: "0";
36
- readonly imageHoverScale: "1.05";
37
- readonly imageHoverDuration: "300ms";
38
36
  readonly variants: {
39
37
  readonly hero: "overlay";
40
38
  readonly linkBlock: "overlay";
@@ -77,8 +77,6 @@ const TOKEN_DEFAULTS = {
77
77
  overlayColor: "black",
78
78
  overlayFromOpacity: "0.5",
79
79
  overlayToOpacity: "0",
80
- imageHoverScale: "1.05",
81
- imageHoverDuration: "300ms",
82
80
  variants: {
83
81
  hero: "overlay",
84
82
  linkBlock: "overlay",
@@ -1 +1 @@
1
- {"version":3,"file":"defaults.mjs","names":[],"sources":["../../../src/client/theme/defaults.ts"],"sourcesContent":["/**\n * SDK default color tokens. These are the canonical defaults used by\n * the theme codec to compute diffs (only non-default values are encoded).\n */\nexport const SDK_DEFAULTS = {\n light: {\n \"--background\": \"#ffffff\",\n \"--foreground\": \"#111827\",\n \"--card\": \"#ffffff\",\n \"--card-foreground\": \"#111827\",\n \"--popover\": \"#ffffff\",\n \"--popover-foreground\": \"#111827\",\n \"--primary\": \"#2563eb\",\n \"--primary-foreground\": \"#ffffff\",\n \"--secondary\": \"#f1f5f9\",\n \"--secondary-foreground\": \"#0f172a\",\n \"--muted\": \"#f3f4f6\",\n \"--muted-foreground\": \"#636b78\",\n \"--accent\": \"#dbeafe\",\n \"--accent-foreground\": \"#1e3a8a\",\n \"--accent-muted\": \"#eff6ff\",\n \"--accent-muted-foreground\": \"#1e40af\",\n \"--destructive\": \"#dc2626\",\n \"--destructive-foreground\": \"#ffffff\",\n \"--border\": \"#e5e7eb\",\n \"--input\": \"#e5e7eb\",\n \"--ring\": \"#2563eb\",\n } as Record<string, string>,\n dark: {\n \"--background\": \"#111827\",\n \"--foreground\": \"#f9fafb\",\n \"--card\": \"#1f2937\",\n \"--card-foreground\": \"#f9fafb\",\n \"--popover\": \"#1f2937\",\n \"--popover-foreground\": \"#f9fafb\",\n \"--primary\": \"#2563eb\",\n \"--primary-foreground\": \"#ffffff\",\n \"--secondary\": \"#1e293b\",\n \"--secondary-foreground\": \"#e2e8f0\",\n \"--muted\": \"#374151\",\n \"--muted-foreground\": \"#b0b8c4\",\n \"--accent\": \"#1e3a5f\",\n \"--accent-foreground\": \"#bfdbfe\",\n \"--accent-muted\": \"#172554\",\n \"--accent-muted-foreground\": \"#93c5fd\",\n \"--destructive\": \"#dc2626\",\n \"--destructive-foreground\": \"#ffffff\",\n \"--border\": \"#374151\",\n \"--input\": \"#374151\",\n \"--ring\": \"#2563eb\",\n } as Record<string, string>,\n};\n\n/** Default values for design tokens (non-color). */\nexport const TOKEN_DEFAULTS = {\n colorize: 50,\n intensity: 50,\n delight: 50,\n radius: 0.75,\n fontBody: \"Inter\",\n fontHeading: \"Inter\",\n iconSet: \"Phosphor\",\n colorSpace: \"hsl\",\n darkMode: false,\n componentSet: \"default\" as const,\n\n // Shape\n buttonRadius: \"9999px\",\n cardRadius: \"var(--radius)\",\n inputRadius: \"var(--radius)\",\n imageRadius: \"0px\",\n\n // Depth\n shadowPreset: \"none\",\n shadowColor: \"oklch(0 0 0 / 0.1)\",\n\n // Typography\n headingWeight: \"600\",\n headingTracking: \"0em\",\n bodyWeight: \"400\",\n headingTransform: \"none\",\n\n // Border\n borderWidth: \"1px\",\n\n // Overlay\n overlayColor: \"black\",\n overlayFromOpacity: \"0.5\",\n overlayToOpacity: \"0\",\n\n // Motion\n imageHoverScale: \"1.05\",\n imageHoverDuration: \"300ms\",\n\n // Variants\n variants: {\n hero: \"overlay\",\n linkBlock: \"overlay\",\n productCard: \"gallery\",\n contentWithImage: \"side-by-side\",\n gallery: \"grid\",\n textContent: \"default\",\n },\n} as const;\n"],"mappings":";;;;;AAIA,MAAa,eAAe;CAC1B,OAAO;EACL,gBAAgB;EAChB,gBAAgB;EAChB,UAAU;EACV,qBAAqB;EACrB,aAAa;EACb,wBAAwB;EACxB,aAAa;EACb,wBAAwB;EACxB,eAAe;EACf,0BAA0B;EAC1B,WAAW;EACX,sBAAsB;EACtB,YAAY;EACZ,uBAAuB;EACvB,kBAAkB;EAClB,6BAA6B;EAC7B,iBAAiB;EACjB,4BAA4B;EAC5B,YAAY;EACZ,WAAW;EACX,UAAU;EACX;CACD,MAAM;EACJ,gBAAgB;EAChB,gBAAgB;EAChB,UAAU;EACV,qBAAqB;EACrB,aAAa;EACb,wBAAwB;EACxB,aAAa;EACb,wBAAwB;EACxB,eAAe;EACf,0BAA0B;EAC1B,WAAW;EACX,sBAAsB;EACtB,YAAY;EACZ,uBAAuB;EACvB,kBAAkB;EAClB,6BAA6B;EAC7B,iBAAiB;EACjB,4BAA4B;EAC5B,YAAY;EACZ,WAAW;EACX,UAAU;EACX;CACF;;AAGD,MAAa,iBAAiB;CAC5B,UAAU;CACV,WAAW;CACX,SAAS;CACT,QAAQ;CACR,UAAU;CACV,aAAa;CACb,SAAS;CACT,YAAY;CACZ,UAAU;CACV,cAAc;CAGd,cAAc;CACd,YAAY;CACZ,aAAa;CACb,aAAa;CAGb,cAAc;CACd,aAAa;CAGb,eAAe;CACf,iBAAiB;CACjB,YAAY;CACZ,kBAAkB;CAGlB,aAAa;CAGb,cAAc;CACd,oBAAoB;CACpB,kBAAkB;CAGlB,iBAAiB;CACjB,oBAAoB;CAGpB,UAAU;EACR,MAAM;EACN,WAAW;EACX,aAAa;EACb,kBAAkB;EAClB,SAAS;EACT,aAAa;EACd;CACF"}
1
+ {"version":3,"file":"defaults.mjs","names":[],"sources":["../../../src/client/theme/defaults.ts"],"sourcesContent":["/**\n * SDK default color tokens. These are the canonical defaults used by\n * the theme codec to compute diffs (only non-default values are encoded).\n */\nexport const SDK_DEFAULTS = {\n light: {\n \"--background\": \"#ffffff\",\n \"--foreground\": \"#111827\",\n \"--card\": \"#ffffff\",\n \"--card-foreground\": \"#111827\",\n \"--popover\": \"#ffffff\",\n \"--popover-foreground\": \"#111827\",\n \"--primary\": \"#2563eb\",\n \"--primary-foreground\": \"#ffffff\",\n \"--secondary\": \"#f1f5f9\",\n \"--secondary-foreground\": \"#0f172a\",\n \"--muted\": \"#f3f4f6\",\n \"--muted-foreground\": \"#636b78\",\n \"--accent\": \"#dbeafe\",\n \"--accent-foreground\": \"#1e3a8a\",\n \"--accent-muted\": \"#eff6ff\",\n \"--accent-muted-foreground\": \"#1e40af\",\n \"--destructive\": \"#dc2626\",\n \"--destructive-foreground\": \"#ffffff\",\n \"--border\": \"#e5e7eb\",\n \"--input\": \"#e5e7eb\",\n \"--ring\": \"#2563eb\",\n } as Record<string, string>,\n dark: {\n \"--background\": \"#111827\",\n \"--foreground\": \"#f9fafb\",\n \"--card\": \"#1f2937\",\n \"--card-foreground\": \"#f9fafb\",\n \"--popover\": \"#1f2937\",\n \"--popover-foreground\": \"#f9fafb\",\n \"--primary\": \"#2563eb\",\n \"--primary-foreground\": \"#ffffff\",\n \"--secondary\": \"#1e293b\",\n \"--secondary-foreground\": \"#e2e8f0\",\n \"--muted\": \"#374151\",\n \"--muted-foreground\": \"#b0b8c4\",\n \"--accent\": \"#1e3a5f\",\n \"--accent-foreground\": \"#bfdbfe\",\n \"--accent-muted\": \"#172554\",\n \"--accent-muted-foreground\": \"#93c5fd\",\n \"--destructive\": \"#dc2626\",\n \"--destructive-foreground\": \"#ffffff\",\n \"--border\": \"#374151\",\n \"--input\": \"#374151\",\n \"--ring\": \"#2563eb\",\n } as Record<string, string>,\n};\n\n/** Default values for design tokens (non-color). */\nexport const TOKEN_DEFAULTS = {\n colorize: 50,\n intensity: 50,\n delight: 50,\n radius: 0.75,\n fontBody: \"Inter\",\n fontHeading: \"Inter\",\n iconSet: \"Phosphor\",\n colorSpace: \"hsl\",\n darkMode: false,\n componentSet: \"default\" as const,\n\n // Shape\n buttonRadius: \"9999px\",\n cardRadius: \"var(--radius)\",\n inputRadius: \"var(--radius)\",\n imageRadius: \"0px\",\n\n // Depth\n shadowPreset: \"none\",\n shadowColor: \"oklch(0 0 0 / 0.1)\",\n\n // Typography\n headingWeight: \"600\",\n headingTracking: \"0em\",\n bodyWeight: \"400\",\n headingTransform: \"none\",\n\n // Border\n borderWidth: \"1px\",\n\n // Overlay\n overlayColor: \"black\",\n overlayFromOpacity: \"0.5\",\n overlayToOpacity: \"0\",\n\n // Variants\n variants: {\n hero: \"overlay\",\n linkBlock: \"overlay\",\n productCard: \"gallery\",\n contentWithImage: \"side-by-side\",\n gallery: \"grid\",\n textContent: \"default\",\n },\n} as const;\n"],"mappings":";;;;;AAIA,MAAa,eAAe;CAC1B,OAAO;EACL,gBAAgB;EAChB,gBAAgB;EAChB,UAAU;EACV,qBAAqB;EACrB,aAAa;EACb,wBAAwB;EACxB,aAAa;EACb,wBAAwB;EACxB,eAAe;EACf,0BAA0B;EAC1B,WAAW;EACX,sBAAsB;EACtB,YAAY;EACZ,uBAAuB;EACvB,kBAAkB;EAClB,6BAA6B;EAC7B,iBAAiB;EACjB,4BAA4B;EAC5B,YAAY;EACZ,WAAW;EACX,UAAU;EACX;CACD,MAAM;EACJ,gBAAgB;EAChB,gBAAgB;EAChB,UAAU;EACV,qBAAqB;EACrB,aAAa;EACb,wBAAwB;EACxB,aAAa;EACb,wBAAwB;EACxB,eAAe;EACf,0BAA0B;EAC1B,WAAW;EACX,sBAAsB;EACtB,YAAY;EACZ,uBAAuB;EACvB,kBAAkB;EAClB,6BAA6B;EAC7B,iBAAiB;EACjB,4BAA4B;EAC5B,YAAY;EACZ,WAAW;EACX,UAAU;EACX;CACF;;AAGD,MAAa,iBAAiB;CAC5B,UAAU;CACV,WAAW;CACX,SAAS;CACT,QAAQ;CACR,UAAU;CACV,aAAa;CACb,SAAS;CACT,YAAY;CACZ,UAAU;CACV,cAAc;CAGd,cAAc;CACd,YAAY;CACZ,aAAa;CACb,aAAa;CAGb,cAAc;CACd,aAAa;CAGb,eAAe;CACf,iBAAiB;CACjB,YAAY;CACZ,kBAAkB;CAGlB,aAAa;CAGb,cAAc;CACd,oBAAoB;CACpB,kBAAkB;CAGlB,UAAU;EACR,MAAM;EACN,WAAW;EACX,aAAa;EACb,kBAAkB;EAClB,SAAS;EACT,aAAa;EACd;CACF"}
@@ -3,6 +3,17 @@ import * as react_jsx_runtime0 from "react/jsx-runtime";
3
3
  import { Accordion as Accordion$1 } from "radix-ui";
4
4
 
5
5
  //#region src/client/ui/accordion.d.ts
6
+ declare const accordionRecipe: (props?: ({
7
+ [x: string]: string | undefined;
8
+ } & {
9
+ className?: Partial<Record<"root" | "group" | "item" | "trigger" | "content", string>> | undefined;
10
+ }) | undefined) => {
11
+ root: string;
12
+ group: string;
13
+ item: string;
14
+ trigger: string;
15
+ content: string;
16
+ };
6
17
  declare function Accordion({
7
18
  ...props
8
19
  }: React$1.ComponentProps<typeof Accordion$1.Root>): react_jsx_runtime0.JSX.Element;
@@ -25,5 +36,5 @@ declare function AccordionContent({
25
36
  ...props
26
37
  }: React$1.ComponentProps<typeof Accordion$1.Content>): react_jsx_runtime0.JSX.Element;
27
38
  //#endregion
28
- export { Accordion, AccordionContent, AccordionGroup, AccordionItem, AccordionTrigger };
39
+ export { Accordion, AccordionContent, AccordionGroup, AccordionItem, AccordionTrigger, accordionRecipe };
29
40
  //# sourceMappingURL=accordion.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"accordion.d.ts","names":[],"sources":["../../../src/client/ui/accordion.tsx"],"mappings":";;;;;iBAMS,SAAA,CAAA;EAAA,GAAe;AAAA,GAAS,OAAA,CAAM,cAAA,QAAsB,WAAA,CAAmB,IAAA,IAAK,kBAAA,CAAA,GAAA,CAAA,OAAA;AAAA,iBAI5E,cAAA,CAAA;EACP,SAAA;EAAA,GACG;AAAA,GACF,OAAA,CAAM,cAAA,QAAsB,WAAA,CAAmB,IAAA,IAAK,kBAAA,CAAA,GAAA,CAAA,OAAA;AAAA,iBAa9C,aAAA,CAAA;EACP,SAAA;EAAA,GACG;AAAA,GACF,OAAA,CAAM,cAAA,QAAsB,WAAA,CAAmB,IAAA,IAAK,kBAAA,CAAA,GAAA,CAAA,OAAA;AAAA,iBAU9C,gBAAA,CAAA;EACP,SAAA;EACA,QAAA;EAAA,GACG;AAAA,GACF,OAAA,CAAM,cAAA,QAAsB,WAAA,CAAmB,OAAA,IAAQ,kBAAA,CAAA,GAAA,CAAA,OAAA;AAAA,iBAoBjD,gBAAA,CAAA;EACP,SAAA;EACA,QAAA;EAAA,GACG;AAAA,GACF,OAAA,CAAM,cAAA,QAAsB,WAAA,CAAmB,OAAA,IAAQ,kBAAA,CAAA,GAAA,CAAA,OAAA"}
1
+ {"version":3,"file":"accordion.d.ts","names":[],"sources":["../../../src/client/ui/accordion.tsx"],"mappings":";;;;;cAOM,eAAA,GAAe,KAAA;EAAA;;cAWnB,OAAA,CAAA,MAAA;AAAA;;;;;;;iBAIO,SAAA,CAAA;EAAA,GAAe;AAAA,GAAS,OAAA,CAAM,cAAA,QAAsB,WAAA,CAAmB,IAAA,IAAK,kBAAA,CAAA,GAAA,CAAA,OAAA;AAAA,iBAI5E,cAAA,CAAA;EACP,SAAA;EAAA,GACG;AAAA,GACF,OAAA,CAAM,cAAA,QAAsB,WAAA,CAAmB,IAAA,IAAK,kBAAA,CAAA,GAAA,CAAA,OAAA;AAAA,iBAU9C,aAAA,CAAA;EACP,SAAA;EAAA,GACG;AAAA,GACF,OAAA,CAAM,cAAA,QAAsB,WAAA,CAAmB,IAAA,IAAK,kBAAA,CAAA,GAAA,CAAA,OAAA;AAAA,iBAU9C,gBAAA,CAAA;EACP,SAAA;EACA,QAAA;EAAA,GACG;AAAA,GACF,OAAA,CAAM,cAAA,QAAsB,WAAA,CAAmB,OAAA,IAAQ,kBAAA,CAAA,GAAA,CAAA,OAAA;AAAA,iBAiBjD,gBAAA,CAAA;EACP,SAAA;EACA,QAAA;EAAA,GACG;AAAA,GACF,OAAA,CAAM,cAAA,QAAsB,WAAA,CAAmB,OAAA,IAAQ,kBAAA,CAAA,GAAA,CAAA,OAAA"}
@@ -1,9 +1,27 @@
1
1
  import { useIcon } from "../icons/icon-context.mjs";
2
2
  import { cn } from "./utils.mjs";
3
+ import { defineSlotRecipe } from "../ui-resolver/recipe.mjs";
3
4
  import "react";
4
5
  import { jsx, jsxs } from "react/jsx-runtime";
5
6
  import { Accordion as Accordion$1 } from "radix-ui";
6
7
  //#region src/client/ui/accordion.tsx
8
+ const accordionRecipe = defineSlotRecipe({
9
+ slots: [
10
+ "root",
11
+ "group",
12
+ "item",
13
+ "trigger",
14
+ "content"
15
+ ],
16
+ base: {
17
+ root: "",
18
+ group: "flex w-full flex-col overflow-hidden rounded-xl border bg-card text-card-foreground",
19
+ item: "border-b last:border-b-0",
20
+ trigger: "flex flex-1 items-start justify-between gap-4 rounded-md py-4 text-left text-sm font-medium transition-all outline-none hover:underline focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:pointer-events-none disabled:opacity-50 [&[data-state=open]>svg]:rotate-180",
21
+ content: "overflow-hidden text-sm data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down"
22
+ }
23
+ });
24
+ const defaultClasses = accordionRecipe();
7
25
  function Accordion({ ...props }) {
8
26
  return /* @__PURE__ */ jsx(Accordion$1.Root, {
9
27
  "data-slot": "accordion",
@@ -13,14 +31,14 @@ function Accordion({ ...props }) {
13
31
  function AccordionGroup({ className, ...props }) {
14
32
  return /* @__PURE__ */ jsx(Accordion$1.Root, {
15
33
  "data-slot": "accordion",
16
- className: cn("flex w-full flex-col overflow-hidden rounded-xl border bg-card text-card-foreground", className),
34
+ className: cn(defaultClasses.group, className),
17
35
  ...props
18
36
  });
19
37
  }
20
38
  function AccordionItem({ className, ...props }) {
21
39
  return /* @__PURE__ */ jsx(Accordion$1.Item, {
22
40
  "data-slot": "accordion-item",
23
- className: cn("border-b last:border-b-0", className),
41
+ className: cn(defaultClasses.item, className),
24
42
  ...props
25
43
  });
26
44
  }
@@ -30,7 +48,7 @@ function AccordionTrigger({ className, children, ...props }) {
30
48
  className: "flex",
31
49
  children: /* @__PURE__ */ jsxs(Accordion$1.Trigger, {
32
50
  "data-slot": "accordion-trigger",
33
- className: cn("flex flex-1 items-start justify-between gap-4 rounded-md py-4 text-left text-sm font-medium transition-all outline-none hover:underline focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:pointer-events-none disabled:opacity-50 [&[data-state=open]>svg]:rotate-180", className),
51
+ className: cn(defaultClasses.trigger, className),
34
52
  ...props,
35
53
  children: [children, /* @__PURE__ */ jsx(ChevronDownIcon, { className: "pointer-events-none size-4 shrink-0 translate-y-0.5 text-muted-foreground transition-transform duration-200" })]
36
54
  })
@@ -39,7 +57,7 @@ function AccordionTrigger({ className, children, ...props }) {
39
57
  function AccordionContent({ className, children, ...props }) {
40
58
  return /* @__PURE__ */ jsx(Accordion$1.Content, {
41
59
  "data-slot": "accordion-content",
42
- className: "overflow-hidden text-sm data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down",
60
+ className: defaultClasses.content,
43
61
  ...props,
44
62
  children: /* @__PURE__ */ jsx("div", {
45
63
  className: cn("pt-0 pb-4", className),
@@ -48,6 +66,6 @@ function AccordionContent({ className, children, ...props }) {
48
66
  });
49
67
  }
50
68
  //#endregion
51
- export { Accordion, AccordionContent, AccordionGroup, AccordionItem, AccordionTrigger };
69
+ export { Accordion, AccordionContent, AccordionGroup, AccordionItem, AccordionTrigger, accordionRecipe };
52
70
 
53
71
  //# sourceMappingURL=accordion.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"accordion.mjs","names":["AccordionPrimitive"],"sources":["../../../src/client/ui/accordion.tsx"],"sourcesContent":["import * as React from \"react\";\nimport { useIcon } from \"../icons/icon-context\";\nimport { Accordion as AccordionPrimitive } from \"radix-ui\";\n\nimport { cn } from \"./utils\";\n\nfunction Accordion({ ...props }: React.ComponentProps<typeof AccordionPrimitive.Root>) {\n return <AccordionPrimitive.Root data-slot=\"accordion\" {...props} />;\n}\n\nfunction AccordionGroup({\n className,\n ...props\n}: React.ComponentProps<typeof AccordionPrimitive.Root>) {\n return (\n <AccordionPrimitive.Root\n data-slot=\"accordion\"\n className={cn(\n \"flex w-full flex-col overflow-hidden rounded-xl border bg-card text-card-foreground\",\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction AccordionItem({\n className,\n ...props\n}: React.ComponentProps<typeof AccordionPrimitive.Item>) {\n return (\n <AccordionPrimitive.Item\n data-slot=\"accordion-item\"\n className={cn(\"border-b last:border-b-0\", className)}\n {...props}\n />\n );\n}\n\nfunction AccordionTrigger({\n className,\n children,\n ...props\n}: React.ComponentProps<typeof AccordionPrimitive.Trigger>) {\n const ChevronDownIcon = useIcon(\"chevronDown\");\n\n return (\n <AccordionPrimitive.Header className=\"flex\">\n <AccordionPrimitive.Trigger\n data-slot=\"accordion-trigger\"\n className={cn(\n \"flex flex-1 items-start justify-between gap-4 rounded-md py-4 text-left text-sm font-medium transition-all outline-none hover:underline focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:pointer-events-none disabled:opacity-50 [&[data-state=open]>svg]:rotate-180\",\n className,\n )}\n {...props}\n >\n {children}\n <ChevronDownIcon className=\"pointer-events-none size-4 shrink-0 translate-y-0.5 text-muted-foreground transition-transform duration-200\" />\n </AccordionPrimitive.Trigger>\n </AccordionPrimitive.Header>\n );\n}\n\nfunction AccordionContent({\n className,\n children,\n ...props\n}: React.ComponentProps<typeof AccordionPrimitive.Content>) {\n return (\n <AccordionPrimitive.Content\n data-slot=\"accordion-content\"\n className=\"overflow-hidden text-sm data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down\"\n {...props}\n >\n <div className={cn(\"pt-0 pb-4\", className)}>{children}</div>\n </AccordionPrimitive.Content>\n );\n}\n\nexport { Accordion, AccordionGroup, AccordionItem, AccordionTrigger, AccordionContent };\n"],"mappings":";;;;;;AAMA,SAAS,UAAU,EAAE,GAAG,SAA+D;AACrF,QAAO,oBAACA,YAAmB,MAApB;EAAyB,aAAU;EAAY,GAAI;EAAS,CAAA;;AAGrE,SAAS,eAAe,EACtB,WACA,GAAG,SACoD;AACvD,QACE,oBAACA,YAAmB,MAApB;EACE,aAAU;EACV,WAAW,GACT,uFACA,UACD;EACD,GAAI;EACJ,CAAA;;AAIN,SAAS,cAAc,EACrB,WACA,GAAG,SACoD;AACvD,QACE,oBAACA,YAAmB,MAApB;EACE,aAAU;EACV,WAAW,GAAG,4BAA4B,UAAU;EACpD,GAAI;EACJ,CAAA;;AAIN,SAAS,iBAAiB,EACxB,WACA,UACA,GAAG,SACuD;CAC1D,MAAM,kBAAkB,QAAQ,cAAc;AAE9C,QACE,oBAACA,YAAmB,QAApB;EAA2B,WAAU;YACnC,qBAACA,YAAmB,SAApB;GACE,aAAU;GACV,WAAW,GACT,8SACA,UACD;GACD,GAAI;aANN,CAQG,UACD,oBAAC,iBAAD,EAAiB,WAAU,+GAAgH,CAAA,CAChH;;EACH,CAAA;;AAIhC,SAAS,iBAAiB,EACxB,WACA,UACA,GAAG,SACuD;AAC1D,QACE,oBAACA,YAAmB,SAApB;EACE,aAAU;EACV,WAAU;EACV,GAAI;YAEJ,oBAAC,OAAD;GAAK,WAAW,GAAG,aAAa,UAAU;GAAG;GAAe,CAAA;EACjC,CAAA"}
1
+ {"version":3,"file":"accordion.mjs","names":["AccordionPrimitive"],"sources":["../../../src/client/ui/accordion.tsx"],"sourcesContent":["import * as React from \"react\";\nimport { useIcon } from \"../icons/icon-context\";\nimport { Accordion as AccordionPrimitive } from \"radix-ui\";\n\nimport { defineSlotRecipe } from \"../ui-resolver/recipe\";\nimport { cn } from \"./utils\";\n\nconst accordionRecipe = defineSlotRecipe({\n slots: [\"root\", \"group\", \"item\", \"trigger\", \"content\"] as const,\n base: {\n root: \"\",\n group: \"flex w-full flex-col overflow-hidden rounded-xl border bg-card text-card-foreground\",\n item: \"border-b last:border-b-0\",\n trigger:\n \"flex flex-1 items-start justify-between gap-4 rounded-md py-4 text-left text-sm font-medium transition-all outline-none hover:underline focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:pointer-events-none disabled:opacity-50 [&[data-state=open]>svg]:rotate-180\",\n content:\n \"overflow-hidden text-sm data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down\",\n },\n});\n\nconst defaultClasses = accordionRecipe();\n\nfunction Accordion({ ...props }: React.ComponentProps<typeof AccordionPrimitive.Root>) {\n return <AccordionPrimitive.Root data-slot=\"accordion\" {...props} />;\n}\n\nfunction AccordionGroup({\n className,\n ...props\n}: React.ComponentProps<typeof AccordionPrimitive.Root>) {\n return (\n <AccordionPrimitive.Root\n data-slot=\"accordion\"\n className={cn(defaultClasses.group, className)}\n {...props}\n />\n );\n}\n\nfunction AccordionItem({\n className,\n ...props\n}: React.ComponentProps<typeof AccordionPrimitive.Item>) {\n return (\n <AccordionPrimitive.Item\n data-slot=\"accordion-item\"\n className={cn(defaultClasses.item, className)}\n {...props}\n />\n );\n}\n\nfunction AccordionTrigger({\n className,\n children,\n ...props\n}: React.ComponentProps<typeof AccordionPrimitive.Trigger>) {\n const ChevronDownIcon = useIcon(\"chevronDown\");\n\n return (\n <AccordionPrimitive.Header className=\"flex\">\n <AccordionPrimitive.Trigger\n data-slot=\"accordion-trigger\"\n className={cn(defaultClasses.trigger, className)}\n {...props}\n >\n {children}\n <ChevronDownIcon className=\"pointer-events-none size-4 shrink-0 translate-y-0.5 text-muted-foreground transition-transform duration-200\" />\n </AccordionPrimitive.Trigger>\n </AccordionPrimitive.Header>\n );\n}\n\nfunction AccordionContent({\n className,\n children,\n ...props\n}: React.ComponentProps<typeof AccordionPrimitive.Content>) {\n return (\n <AccordionPrimitive.Content\n data-slot=\"accordion-content\"\n className={defaultClasses.content}\n {...props}\n >\n <div className={cn(\"pt-0 pb-4\", className)}>{children}</div>\n </AccordionPrimitive.Content>\n );\n}\n\nexport {\n Accordion,\n AccordionGroup,\n AccordionItem,\n AccordionTrigger,\n AccordionContent,\n accordionRecipe,\n};\n"],"mappings":";;;;;;;AAOA,MAAM,kBAAkB,iBAAiB;CACvC,OAAO;EAAC;EAAQ;EAAS;EAAQ;EAAW;EAAU;CACtD,MAAM;EACJ,MAAM;EACN,OAAO;EACP,MAAM;EACN,SACE;EACF,SACE;EACH;CACF,CAAC;AAEF,MAAM,iBAAiB,iBAAiB;AAExC,SAAS,UAAU,EAAE,GAAG,SAA+D;AACrF,QAAO,oBAACA,YAAmB,MAApB;EAAyB,aAAU;EAAY,GAAI;EAAS,CAAA;;AAGrE,SAAS,eAAe,EACtB,WACA,GAAG,SACoD;AACvD,QACE,oBAACA,YAAmB,MAApB;EACE,aAAU;EACV,WAAW,GAAG,eAAe,OAAO,UAAU;EAC9C,GAAI;EACJ,CAAA;;AAIN,SAAS,cAAc,EACrB,WACA,GAAG,SACoD;AACvD,QACE,oBAACA,YAAmB,MAApB;EACE,aAAU;EACV,WAAW,GAAG,eAAe,MAAM,UAAU;EAC7C,GAAI;EACJ,CAAA;;AAIN,SAAS,iBAAiB,EACxB,WACA,UACA,GAAG,SACuD;CAC1D,MAAM,kBAAkB,QAAQ,cAAc;AAE9C,QACE,oBAACA,YAAmB,QAApB;EAA2B,WAAU;YACnC,qBAACA,YAAmB,SAApB;GACE,aAAU;GACV,WAAW,GAAG,eAAe,SAAS,UAAU;GAChD,GAAI;aAHN,CAKG,UACD,oBAAC,iBAAD,EAAiB,WAAU,+GAAgH,CAAA,CAChH;;EACH,CAAA;;AAIhC,SAAS,iBAAiB,EACxB,WACA,UACA,GAAG,SACuD;AAC1D,QACE,oBAACA,YAAmB,SAApB;EACE,aAAU;EACV,WAAW,eAAe;EAC1B,GAAI;YAEJ,oBAAC,OAAD;GAAK,WAAW,GAAG,aAAa,UAAU;GAAG;GAAe,CAAA;EACjC,CAAA"}
@@ -1,17 +1,23 @@
1
1
  import * as React$1 from "react";
2
2
  import * as react_jsx_runtime0 from "react/jsx-runtime";
3
- import { VariantProps } from "class-variance-authority";
4
- import * as class_variance_authority_types0 from "class-variance-authority/types";
5
3
 
6
4
  //#region src/client/ui/alert.d.ts
7
- declare const alertVariants: (props?: ({
8
- variant?: "default" | "destructive" | null | undefined;
9
- } & class_variance_authority_types0.ClassProp) | undefined) => string;
5
+ declare const alertRecipe: (props?: ({
6
+ variant?: "default" | "destructive" | undefined;
7
+ } & {
8
+ className?: Partial<Record<"root" | "title" | "description", string>> | undefined;
9
+ }) | undefined) => {
10
+ root: string;
11
+ title: string;
12
+ description: string;
13
+ };
10
14
  declare function Alert({
11
15
  className,
12
16
  variant,
13
17
  ...props
14
- }: React$1.ComponentProps<"div"> & VariantProps<typeof alertVariants>): react_jsx_runtime0.JSX.Element;
18
+ }: React$1.ComponentProps<"div"> & {
19
+ variant?: "default" | "destructive";
20
+ }): react_jsx_runtime0.JSX.Element;
15
21
  declare function AlertTitle({
16
22
  className,
17
23
  ...props
@@ -20,6 +26,9 @@ declare function AlertDescription({
20
26
  className,
21
27
  ...props
22
28
  }: React$1.ComponentProps<"div">): react_jsx_runtime0.JSX.Element;
29
+ declare const alertVariants: (props: {
30
+ variant?: "default" | "destructive";
31
+ }) => string;
23
32
  //#endregion
24
- export { Alert, AlertDescription, AlertTitle, alertVariants };
33
+ export { Alert, AlertDescription, AlertTitle, alertRecipe, alertVariants };
25
34
  //# sourceMappingURL=alert.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"alert.d.ts","names":[],"sources":["../../../src/client/ui/alert.tsx"],"mappings":";;;;;;cAOM,aAAA,GAAa,KAAA;;IAclB,+BAAA,CAAA,SAAA;AAAA,iBAEQ,KAAA,CAAA;EACP,SAAA;EACA,OAAA;EAAA,GACG;AAAA,GACF,OAAA,CAAM,cAAA,UAAwB,YAAA,QAAoB,aAAA,IAAc,kBAAA,CAAA,GAAA,CAAA,OAAA;AAAA,iBAW1D,UAAA,CAAA;EAAa,SAAA;EAAA,GAAc;AAAA,GAAS,OAAA,CAAM,cAAA,SAAoB,kBAAA,CAAA,GAAA,CAAA,OAAA;AAAA,iBAU9D,gBAAA,CAAA;EAAmB,SAAA;EAAA,GAAc;AAAA,GAAS,OAAA,CAAM,cAAA,UAAqB,kBAAA,CAAA,GAAA,CAAA,OAAA"}
1
+ {"version":3,"file":"alert.d.ts","names":[],"sources":["../../../src/client/ui/alert.tsx"],"mappings":";;;;cAOM,WAAA,GAAW,KAAA;;;cAkBf,OAAA,CAAA,MAAA;AAAA;;;;;iBAIO,KAAA,CAAA;EACP,SAAA;EACA,OAAA;EAAA,GACG;AAAA,GACF,OAAA,CAAM,cAAA;EAA0B,OAAA;AAAA,IAAqC,kBAAA,CAAA,GAAA,CAAA,OAAA;AAAA,iBAM/D,UAAA,CAAA;EAAa,SAAA;EAAA,GAAc;AAAA,GAAS,OAAA,CAAM,cAAA,SAAoB,kBAAA,CAAA,GAAA,CAAA,OAAA;AAAA,iBAI9D,gBAAA,CAAA;EAAmB,SAAA;EAAA,GAAc;AAAA,GAAS,OAAA,CAAM,cAAA,UAAqB,kBAAA,CAAA,GAAA,CAAA,OAAA;AAAA,cAaxE,aAAA,GAAiB,KAAA;EAAS,OAAA;AAAA"}
@@ -1,39 +1,52 @@
1
1
  "use client";
2
2
  import { cn } from "./utils.mjs";
3
+ import { defineSlotRecipe } from "../ui-resolver/recipe.mjs";
3
4
  import "react";
4
5
  import { jsx } from "react/jsx-runtime";
5
- import { cva } from "class-variance-authority";
6
6
  //#region src/client/ui/alert.tsx
7
- const alertVariants = cva("relative w-full rounded-[var(--enad-card-radius)] border p-4 text-sm [&>svg+div]:translate-y-[-3px] [&>svg]:absolute [&>svg]:top-4 [&>svg]:left-4 [&>svg]:text-foreground [&>svg~*]:pl-7", {
7
+ const alertRecipe = defineSlotRecipe({
8
+ slots: [
9
+ "root",
10
+ "title",
11
+ "description"
12
+ ],
13
+ base: {
14
+ root: "relative w-full rounded-[var(--enad-card-radius)] border p-4 text-sm [&>svg+div]:translate-y-[-3px] [&>svg]:absolute [&>svg]:top-4 [&>svg]:left-4 [&>svg]:text-foreground [&>svg~*]:pl-7",
15
+ title: "mb-1 font-medium leading-none tracking-tight",
16
+ description: "text-sm [&_p]:leading-relaxed"
17
+ },
8
18
  variants: { variant: {
9
- default: "bg-background text-foreground",
10
- destructive: "border-destructive/50 text-destructive dark:border-destructive [&>svg]:text-destructive"
19
+ default: { root: "bg-background text-foreground" },
20
+ destructive: { root: "border-destructive/50 text-destructive dark:border-destructive [&>svg]:text-destructive" }
11
21
  } },
12
22
  defaultVariants: { variant: "default" }
13
23
  });
24
+ const defaultClasses = alertRecipe();
14
25
  function Alert({ className, variant, ...props }) {
26
+ const classes = alertRecipe({ variant });
15
27
  return /* @__PURE__ */ jsx("div", {
16
28
  "data-slot": "alert",
17
29
  role: "alert",
18
- className: cn(alertVariants({ variant }), className),
30
+ className: cn(classes.root, className),
19
31
  ...props
20
32
  });
21
33
  }
22
34
  function AlertTitle({ className, ...props }) {
23
35
  return /* @__PURE__ */ jsx("h5", {
24
36
  "data-slot": "alert-title",
25
- className: cn("mb-1 font-medium leading-none tracking-tight", className),
37
+ className: cn(defaultClasses.title, className),
26
38
  ...props
27
39
  });
28
40
  }
29
41
  function AlertDescription({ className, ...props }) {
30
42
  return /* @__PURE__ */ jsx("div", {
31
43
  "data-slot": "alert-description",
32
- className: cn("text-sm [&_p]:leading-relaxed", className),
44
+ className: cn(defaultClasses.description, className),
33
45
  ...props
34
46
  });
35
47
  }
48
+ const alertVariants = (props) => alertRecipe(props).root;
36
49
  //#endregion
37
- export { Alert, AlertDescription, AlertTitle, alertVariants };
50
+ export { Alert, AlertDescription, AlertTitle, alertRecipe, alertVariants };
38
51
 
39
52
  //# sourceMappingURL=alert.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"alert.mjs","names":[],"sources":["../../../src/client/ui/alert.tsx"],"sourcesContent":["\"use client\";\n\nimport * as React from \"react\";\nimport { cva, type VariantProps } from \"class-variance-authority\";\n\nimport { cn } from \"./utils\";\n\nconst alertVariants = cva(\n \"relative w-full rounded-[var(--enad-card-radius)] border p-4 text-sm [&>svg+div]:translate-y-[-3px] [&>svg]:absolute [&>svg]:top-4 [&>svg]:left-4 [&>svg]:text-foreground [&>svg~*]:pl-7\",\n {\n variants: {\n variant: {\n default: \"bg-background text-foreground\",\n destructive:\n \"border-destructive/50 text-destructive dark:border-destructive [&>svg]:text-destructive\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n },\n },\n);\n\nfunction Alert({\n className,\n variant,\n ...props\n}: React.ComponentProps<\"div\"> & VariantProps<typeof alertVariants>) {\n return (\n <div\n data-slot=\"alert\"\n role=\"alert\"\n className={cn(alertVariants({ variant }), className)}\n {...props}\n />\n );\n}\n\nfunction AlertTitle({ className, ...props }: React.ComponentProps<\"h5\">) {\n return (\n <h5\n data-slot=\"alert-title\"\n className={cn(\"mb-1 font-medium leading-none tracking-tight\", className)}\n {...props}\n />\n );\n}\n\nfunction AlertDescription({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"alert-description\"\n className={cn(\"text-sm [&_p]:leading-relaxed\", className)}\n {...props}\n />\n );\n}\n\nexport { Alert, AlertTitle, AlertDescription, alertVariants };\n"],"mappings":";;;;;;AAOA,MAAM,gBAAgB,IACpB,4LACA;CACE,UAAU,EACR,SAAS;EACP,SAAS;EACT,aACE;EACH,EACF;CACD,iBAAiB,EACf,SAAS,WACV;CACF,CACF;AAED,SAAS,MAAM,EACb,WACA,SACA,GAAG,SACgE;AACnE,QACE,oBAAC,OAAD;EACE,aAAU;EACV,MAAK;EACL,WAAW,GAAG,cAAc,EAAE,SAAS,CAAC,EAAE,UAAU;EACpD,GAAI;EACJ,CAAA;;AAIN,SAAS,WAAW,EAAE,WAAW,GAAG,SAAqC;AACvE,QACE,oBAAC,MAAD;EACE,aAAU;EACV,WAAW,GAAG,gDAAgD,UAAU;EACxE,GAAI;EACJ,CAAA;;AAIN,SAAS,iBAAiB,EAAE,WAAW,GAAG,SAAsC;AAC9E,QACE,oBAAC,OAAD;EACE,aAAU;EACV,WAAW,GAAG,iCAAiC,UAAU;EACzD,GAAI;EACJ,CAAA"}
1
+ {"version":3,"file":"alert.mjs","names":[],"sources":["../../../src/client/ui/alert.tsx"],"sourcesContent":["\"use client\";\n\nimport * as React from \"react\";\n\nimport { defineSlotRecipe } from \"../ui-resolver/recipe\";\nimport { cn } from \"./utils\";\n\nconst alertRecipe = defineSlotRecipe({\n slots: [\"root\", \"title\", \"description\"] as const,\n base: {\n root: \"relative w-full rounded-[var(--enad-card-radius)] border p-4 text-sm [&>svg+div]:translate-y-[-3px] [&>svg]:absolute [&>svg]:top-4 [&>svg]:left-4 [&>svg]:text-foreground [&>svg~*]:pl-7\",\n title: \"mb-1 font-medium leading-none tracking-tight\",\n description: \"text-sm [&_p]:leading-relaxed\",\n },\n variants: {\n variant: {\n default: { root: \"bg-background text-foreground\" },\n destructive: {\n root: \"border-destructive/50 text-destructive dark:border-destructive [&>svg]:text-destructive\",\n },\n },\n },\n defaultVariants: {\n variant: \"default\",\n },\n});\n\nconst defaultClasses = alertRecipe();\n\nfunction Alert({\n className,\n variant,\n ...props\n}: React.ComponentProps<\"div\"> & { variant?: \"default\" | \"destructive\" }) {\n const classes = alertRecipe({ variant });\n\n return <div data-slot=\"alert\" role=\"alert\" className={cn(classes.root, className)} {...props} />;\n}\n\nfunction AlertTitle({ className, ...props }: React.ComponentProps<\"h5\">) {\n return <h5 data-slot=\"alert-title\" className={cn(defaultClasses.title, className)} {...props} />;\n}\n\nfunction AlertDescription({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"alert-description\"\n className={cn(defaultClasses.description, className)}\n {...props}\n />\n );\n}\n\nexport { Alert, AlertTitle, AlertDescription, alertRecipe };\n\n// Backward compat\nconst alertVariants = (props: { variant?: \"default\" | \"destructive\" }) => alertRecipe(props).root;\nexport { alertVariants };\n"],"mappings":";;;;;;AAOA,MAAM,cAAc,iBAAiB;CACnC,OAAO;EAAC;EAAQ;EAAS;EAAc;CACvC,MAAM;EACJ,MAAM;EACN,OAAO;EACP,aAAa;EACd;CACD,UAAU,EACR,SAAS;EACP,SAAS,EAAE,MAAM,iCAAiC;EAClD,aAAa,EACX,MAAM,2FACP;EACF,EACF;CACD,iBAAiB,EACf,SAAS,WACV;CACF,CAAC;AAEF,MAAM,iBAAiB,aAAa;AAEpC,SAAS,MAAM,EACb,WACA,SACA,GAAG,SACqE;CACxE,MAAM,UAAU,YAAY,EAAE,SAAS,CAAC;AAExC,QAAO,oBAAC,OAAD;EAAK,aAAU;EAAQ,MAAK;EAAQ,WAAW,GAAG,QAAQ,MAAM,UAAU;EAAE,GAAI;EAAS,CAAA;;AAGlG,SAAS,WAAW,EAAE,WAAW,GAAG,SAAqC;AACvE,QAAO,oBAAC,MAAD;EAAI,aAAU;EAAc,WAAW,GAAG,eAAe,OAAO,UAAU;EAAE,GAAI;EAAS,CAAA;;AAGlG,SAAS,iBAAiB,EAAE,WAAW,GAAG,SAAsC;AAC9E,QACE,oBAAC,OAAD;EACE,aAAU;EACV,WAAW,GAAG,eAAe,aAAa,UAAU;EACpD,GAAI;EACJ,CAAA;;AAON,MAAM,iBAAiB,UAAmD,YAAY,MAAM,CAAC"}
@@ -3,6 +3,15 @@ import * as react_jsx_runtime0 from "react/jsx-runtime";
3
3
  import { Avatar as Avatar$1 } from "radix-ui";
4
4
 
5
5
  //#region src/client/ui/avatar.d.ts
6
+ declare const avatarRecipe: (props?: ({
7
+ [x: string]: string | undefined;
8
+ } & {
9
+ className?: Partial<Record<"root" | "image" | "fallback", string>> | undefined;
10
+ }) | undefined) => {
11
+ root: string;
12
+ image: string;
13
+ fallback: string;
14
+ };
6
15
  declare function Avatar({
7
16
  className,
8
17
  ...props
@@ -16,5 +25,5 @@ declare function AvatarFallback({
16
25
  ...props
17
26
  }: React$1.ComponentProps<typeof Avatar$1.Fallback>): react_jsx_runtime0.JSX.Element;
18
27
  //#endregion
19
- export { Avatar, AvatarFallback, AvatarImage };
28
+ export { Avatar, AvatarFallback, AvatarImage, avatarRecipe };
20
29
  //# sourceMappingURL=avatar.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"avatar.d.ts","names":[],"sources":["../../../src/client/ui/avatar.tsx"],"mappings":";;;;;iBAOS,MAAA,CAAA;EAAS,SAAA;EAAA,GAAc;AAAA,GAAS,OAAA,CAAM,cAAA,QAAsB,QAAA,CAAgB,IAAA,IAAK,kBAAA,CAAA,GAAA,CAAA,OAAA;AAAA,iBAUjF,WAAA,CAAA;EAAc,SAAA;EAAA,GAAc;AAAA,GAAS,OAAA,CAAM,cAAA,QAAsB,QAAA,CAAgB,KAAA,IAAM,kBAAA,CAAA,GAAA,CAAA,OAAA;AAAA,iBAUvF,cAAA,CAAA;EACP,SAAA;EAAA,GACG;AAAA,GACF,OAAA,CAAM,cAAA,QAAsB,QAAA,CAAgB,QAAA,IAAS,kBAAA,CAAA,GAAA,CAAA,OAAA"}
1
+ {"version":3,"file":"avatar.d.ts","names":[],"sources":["../../../src/client/ui/avatar.tsx"],"mappings":";;;;;cAQM,YAAA,GAAY,KAAA;EAAA;;cAQhB,OAAA,CAAA,MAAA;AAAA;;;;;iBAIO,MAAA,CAAA;EAAS,SAAA;EAAA,GAAc;AAAA,GAAS,OAAA,CAAM,cAAA,QAAsB,QAAA,CAAgB,IAAA,IAAK,kBAAA,CAAA,GAAA,CAAA,OAAA;AAAA,iBAUjF,WAAA,CAAA;EAAc,SAAA;EAAA,GAAc;AAAA,GAAS,OAAA,CAAM,cAAA,QAAsB,QAAA,CAAgB,KAAA,IAAM,kBAAA,CAAA,GAAA,CAAA,OAAA;AAAA,iBAUvF,cAAA,CAAA;EACP,SAAA;EAAA,GACG;AAAA,GACF,OAAA,CAAM,cAAA,QAAsB,QAAA,CAAgB,QAAA,IAAS,kBAAA,CAAA,GAAA,CAAA,OAAA"}
@@ -1,31 +1,45 @@
1
1
  "use client";
2
2
  import { cn } from "./utils.mjs";
3
+ import { defineSlotRecipe } from "../ui-resolver/recipe.mjs";
3
4
  import "react";
4
5
  import { jsx } from "react/jsx-runtime";
5
6
  import { Avatar as Avatar$1 } from "radix-ui";
6
7
  //#region src/client/ui/avatar.tsx
8
+ const avatarRecipe = defineSlotRecipe({
9
+ slots: [
10
+ "root",
11
+ "image",
12
+ "fallback"
13
+ ],
14
+ base: {
15
+ root: "relative flex size-8 shrink-0 overflow-hidden rounded-full",
16
+ image: "aspect-square size-full",
17
+ fallback: "flex size-full items-center justify-center rounded-full bg-muted text-xs font-medium"
18
+ }
19
+ });
20
+ const defaultClasses = avatarRecipe();
7
21
  function Avatar({ className, ...props }) {
8
22
  return /* @__PURE__ */ jsx(Avatar$1.Root, {
9
23
  "data-slot": "avatar",
10
- className: cn("relative flex size-8 shrink-0 overflow-hidden rounded-full", className),
24
+ className: cn(defaultClasses.root, className),
11
25
  ...props
12
26
  });
13
27
  }
14
28
  function AvatarImage({ className, ...props }) {
15
29
  return /* @__PURE__ */ jsx(Avatar$1.Image, {
16
30
  "data-slot": "avatar-image",
17
- className: cn("aspect-square size-full", className),
31
+ className: cn(defaultClasses.image, className),
18
32
  ...props
19
33
  });
20
34
  }
21
35
  function AvatarFallback({ className, ...props }) {
22
36
  return /* @__PURE__ */ jsx(Avatar$1.Fallback, {
23
37
  "data-slot": "avatar-fallback",
24
- className: cn("flex size-full items-center justify-center rounded-full bg-muted text-xs font-medium", className),
38
+ className: cn(defaultClasses.fallback, className),
25
39
  ...props
26
40
  });
27
41
  }
28
42
  //#endregion
29
- export { Avatar, AvatarFallback, AvatarImage };
43
+ export { Avatar, AvatarFallback, AvatarImage, avatarRecipe };
30
44
 
31
45
  //# sourceMappingURL=avatar.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"avatar.mjs","names":["AvatarPrimitive"],"sources":["../../../src/client/ui/avatar.tsx"],"sourcesContent":["\"use client\";\n\nimport * as React from \"react\";\nimport { Avatar as AvatarPrimitive } from \"radix-ui\";\n\nimport { cn } from \"./utils\";\n\nfunction Avatar({ className, ...props }: React.ComponentProps<typeof AvatarPrimitive.Root>) {\n return (\n <AvatarPrimitive.Root\n data-slot=\"avatar\"\n className={cn(\"relative flex size-8 shrink-0 overflow-hidden rounded-full\", className)}\n {...props}\n />\n );\n}\n\nfunction AvatarImage({ className, ...props }: React.ComponentProps<typeof AvatarPrimitive.Image>) {\n return (\n <AvatarPrimitive.Image\n data-slot=\"avatar-image\"\n className={cn(\"aspect-square size-full\", className)}\n {...props}\n />\n );\n}\n\nfunction AvatarFallback({\n className,\n ...props\n}: React.ComponentProps<typeof AvatarPrimitive.Fallback>) {\n return (\n <AvatarPrimitive.Fallback\n data-slot=\"avatar-fallback\"\n className={cn(\n \"flex size-full items-center justify-center rounded-full bg-muted text-xs font-medium\",\n className,\n )}\n {...props}\n />\n );\n}\n\nexport { Avatar, AvatarImage, AvatarFallback };\n"],"mappings":";;;;;;AAOA,SAAS,OAAO,EAAE,WAAW,GAAG,SAA4D;AAC1F,QACE,oBAACA,SAAgB,MAAjB;EACE,aAAU;EACV,WAAW,GAAG,8DAA8D,UAAU;EACtF,GAAI;EACJ,CAAA;;AAIN,SAAS,YAAY,EAAE,WAAW,GAAG,SAA6D;AAChG,QACE,oBAACA,SAAgB,OAAjB;EACE,aAAU;EACV,WAAW,GAAG,2BAA2B,UAAU;EACnD,GAAI;EACJ,CAAA;;AAIN,SAAS,eAAe,EACtB,WACA,GAAG,SACqD;AACxD,QACE,oBAACA,SAAgB,UAAjB;EACE,aAAU;EACV,WAAW,GACT,wFACA,UACD;EACD,GAAI;EACJ,CAAA"}
1
+ {"version":3,"file":"avatar.mjs","names":["AvatarPrimitive"],"sources":["../../../src/client/ui/avatar.tsx"],"sourcesContent":["\"use client\";\n\nimport * as React from \"react\";\nimport { Avatar as AvatarPrimitive } from \"radix-ui\";\n\nimport { defineSlotRecipe } from \"../ui-resolver/recipe\";\nimport { cn } from \"./utils\";\n\nconst avatarRecipe = defineSlotRecipe({\n slots: [\"root\", \"image\", \"fallback\"] as const,\n base: {\n root: \"relative flex size-8 shrink-0 overflow-hidden rounded-full\",\n image: \"aspect-square size-full\",\n fallback:\n \"flex size-full items-center justify-center rounded-full bg-muted text-xs font-medium\",\n },\n});\n\nconst defaultClasses = avatarRecipe();\n\nfunction Avatar({ className, ...props }: React.ComponentProps<typeof AvatarPrimitive.Root>) {\n return (\n <AvatarPrimitive.Root\n data-slot=\"avatar\"\n className={cn(defaultClasses.root, className)}\n {...props}\n />\n );\n}\n\nfunction AvatarImage({ className, ...props }: React.ComponentProps<typeof AvatarPrimitive.Image>) {\n return (\n <AvatarPrimitive.Image\n data-slot=\"avatar-image\"\n className={cn(defaultClasses.image, className)}\n {...props}\n />\n );\n}\n\nfunction AvatarFallback({\n className,\n ...props\n}: React.ComponentProps<typeof AvatarPrimitive.Fallback>) {\n return (\n <AvatarPrimitive.Fallback\n data-slot=\"avatar-fallback\"\n className={cn(defaultClasses.fallback, className)}\n {...props}\n />\n );\n}\n\nexport { Avatar, AvatarImage, AvatarFallback, avatarRecipe };\n"],"mappings":";;;;;;;AAQA,MAAM,eAAe,iBAAiB;CACpC,OAAO;EAAC;EAAQ;EAAS;EAAW;CACpC,MAAM;EACJ,MAAM;EACN,OAAO;EACP,UACE;EACH;CACF,CAAC;AAEF,MAAM,iBAAiB,cAAc;AAErC,SAAS,OAAO,EAAE,WAAW,GAAG,SAA4D;AAC1F,QACE,oBAACA,SAAgB,MAAjB;EACE,aAAU;EACV,WAAW,GAAG,eAAe,MAAM,UAAU;EAC7C,GAAI;EACJ,CAAA;;AAIN,SAAS,YAAY,EAAE,WAAW,GAAG,SAA6D;AAChG,QACE,oBAACA,SAAgB,OAAjB;EACE,aAAU;EACV,WAAW,GAAG,eAAe,OAAO,UAAU;EAC9C,GAAI;EACJ,CAAA;;AAIN,SAAS,eAAe,EACtB,WACA,GAAG,SACqD;AACxD,QACE,oBAACA,SAAgB,UAAjB;EACE,aAAU;EACV,WAAW,GAAG,eAAe,UAAU,UAAU;EACjD,GAAI;EACJ,CAAA"}
@@ -2,6 +2,18 @@ import * as React$1 from "react";
2
2
  import * as react_jsx_runtime0 from "react/jsx-runtime";
3
3
 
4
4
  //#region src/client/ui/breadcrumb.d.ts
5
+ declare const breadcrumbRecipe: (props?: ({
6
+ [x: string]: string | undefined;
7
+ } & {
8
+ className?: Partial<Record<"item" | "list" | "link" | "page" | "separator" | "ellipsis", string>> | undefined;
9
+ }) | undefined) => {
10
+ item: string;
11
+ list: string;
12
+ link: string;
13
+ page: string;
14
+ separator: string;
15
+ ellipsis: string;
16
+ };
5
17
  declare function Breadcrumb({
6
18
  ...props
7
19
  }: React$1.ComponentProps<"nav">): react_jsx_runtime0.JSX.Element;
@@ -34,5 +46,5 @@ declare function BreadcrumbEllipsis({
34
46
  ...props
35
47
  }: React$1.ComponentProps<"span">): react_jsx_runtime0.JSX.Element;
36
48
  //#endregion
37
- export { Breadcrumb, BreadcrumbEllipsis, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbPage, BreadcrumbSeparator };
49
+ export { Breadcrumb, BreadcrumbEllipsis, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbPage, BreadcrumbSeparator, breadcrumbRecipe };
38
50
  //# sourceMappingURL=breadcrumb.d.ts.map