@maizzle/framework 6.0.0-rc.2 → 6.0.0-rc.20

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 (542) hide show
  1. package/README.md +3 -3
  2. package/bin/maizzle.mjs +1 -1
  3. package/dist/build.d.ts +20 -0
  4. package/dist/build.d.ts.map +1 -0
  5. package/dist/{build.mjs → build.js} +33 -19
  6. package/dist/build.js.map +1 -0
  7. package/dist/components/Body.vue +128 -0
  8. package/dist/components/Button.vue +148 -52
  9. package/dist/components/CodeBlock.vue +69 -0
  10. package/dist/components/CodeInline.vue +49 -0
  11. package/dist/components/Column.vue +108 -0
  12. package/dist/components/Container.vue +123 -0
  13. package/dist/components/Font.vue +96 -0
  14. package/dist/components/Head.vue +30 -0
  15. package/dist/components/Heading.vue +28 -0
  16. package/dist/components/Hr.vue +33 -0
  17. package/dist/components/Html.vue +137 -0
  18. package/dist/components/Img.vue +70 -0
  19. package/dist/components/Layout.vue +143 -0
  20. package/dist/components/Link.vue +26 -0
  21. package/dist/components/Markdown.vue +89 -0
  22. package/dist/components/MarkdownLayout.vue +39 -0
  23. package/dist/components/NotPlaintext.vue +14 -0
  24. package/dist/components/Outlook.vue +74 -11
  25. package/dist/components/OutlookBg.vue +241 -0
  26. package/dist/components/Overlap.vue +156 -0
  27. package/dist/components/Plaintext.vue +14 -0
  28. package/dist/components/Preheader.vue +15 -0
  29. package/dist/components/QrCode.vue +157 -0
  30. package/dist/components/Raw.vue +28 -0
  31. package/dist/components/Row.vue +184 -0
  32. package/dist/components/Section.vue +124 -0
  33. package/dist/components/Spacer.vue +70 -21
  34. package/dist/components/Tailwind.vue +43 -0
  35. package/dist/components/Text.vue +29 -0
  36. package/dist/components/utils.d.ts +28 -0
  37. package/dist/components/utils.d.ts.map +1 -0
  38. package/dist/components/utils.js +50 -0
  39. package/dist/components/utils.js.map +1 -0
  40. package/dist/components/utils.ts +51 -0
  41. package/dist/composables/{defineConfig.d.mts → defineConfig.d.ts} +2 -2
  42. package/dist/composables/defineConfig.d.ts.map +1 -0
  43. package/dist/composables/{defineConfig.mjs → defineConfig.js} +4 -5
  44. package/dist/composables/defineConfig.js.map +1 -0
  45. package/dist/composables/renderContext.d.ts +37 -0
  46. package/dist/composables/renderContext.d.ts.map +1 -0
  47. package/dist/composables/{renderContext.mjs → renderContext.js} +2 -2
  48. package/dist/composables/renderContext.js.map +1 -0
  49. package/dist/composables/useBaseUrl.d.ts +19 -0
  50. package/dist/composables/useBaseUrl.d.ts.map +1 -0
  51. package/dist/composables/useBaseUrl.js +26 -0
  52. package/dist/composables/useBaseUrl.js.map +1 -0
  53. package/dist/composables/{useConfig.d.mts → useConfig.d.ts} +2 -2
  54. package/dist/composables/useConfig.d.ts.map +1 -0
  55. package/dist/composables/{useConfig.mjs → useConfig.js} +2 -3
  56. package/dist/composables/useConfig.js.map +1 -0
  57. package/dist/composables/{useDoctype.d.mts → useDoctype.d.ts} +1 -1
  58. package/dist/composables/useDoctype.d.ts.map +1 -0
  59. package/dist/composables/{useDoctype.mjs → useDoctype.js} +3 -4
  60. package/dist/composables/useDoctype.js.map +1 -0
  61. package/dist/composables/{useEvent.d.mts → useEvent.d.ts} +2 -2
  62. package/dist/composables/useEvent.d.ts.map +1 -0
  63. package/dist/composables/{useEvent.mjs → useEvent.js} +3 -4
  64. package/dist/composables/useEvent.js.map +1 -0
  65. package/dist/composables/useFont.d.ts +50 -0
  66. package/dist/composables/useFont.d.ts.map +1 -0
  67. package/dist/composables/useFont.js +92 -0
  68. package/dist/composables/useFont.js.map +1 -0
  69. package/dist/composables/useOutlookFallback.d.ts +21 -0
  70. package/dist/composables/useOutlookFallback.d.ts.map +1 -0
  71. package/dist/composables/useOutlookFallback.js +29 -0
  72. package/dist/composables/useOutlookFallback.js.map +1 -0
  73. package/dist/composables/{usePlaintext.d.mts → usePlaintext.d.ts} +3 -1
  74. package/dist/composables/usePlaintext.d.ts.map +1 -0
  75. package/dist/composables/{usePlaintext.mjs → usePlaintext.js} +4 -4
  76. package/dist/composables/usePlaintext.js.map +1 -0
  77. package/dist/composables/usePreheader.d.ts +24 -0
  78. package/dist/composables/usePreheader.d.ts.map +1 -0
  79. package/dist/composables/usePreheader.js +28 -0
  80. package/dist/composables/usePreheader.js.map +1 -0
  81. package/dist/composables/useTransformers.d.ts +34 -0
  82. package/dist/composables/useTransformers.d.ts.map +1 -0
  83. package/dist/composables/useTransformers.js +48 -0
  84. package/dist/composables/useTransformers.js.map +1 -0
  85. package/dist/composables/useUrlQuery.d.ts +19 -0
  86. package/dist/composables/useUrlQuery.d.ts.map +1 -0
  87. package/dist/composables/useUrlQuery.js +26 -0
  88. package/dist/composables/useUrlQuery.js.map +1 -0
  89. package/dist/config/{defaults.d.mts → defaults.d.ts} +2 -2
  90. package/dist/config/defaults.d.ts.map +1 -0
  91. package/dist/config/{defaults.mjs → defaults.js} +10 -6
  92. package/dist/config/defaults.js.map +1 -0
  93. package/dist/config/{index.d.mts → index.d.ts} +4 -4
  94. package/dist/config/index.d.ts.map +1 -0
  95. package/dist/config/{index.mjs → index.js} +12 -10
  96. package/dist/config/index.js.map +1 -0
  97. package/dist/events/{index.d.mts → index.d.ts} +10 -4
  98. package/dist/events/index.d.ts.map +1 -0
  99. package/dist/events/{index.mjs → index.js} +21 -5
  100. package/dist/events/index.js.map +1 -0
  101. package/dist/index.d.ts +38 -0
  102. package/dist/index.js +37 -0
  103. package/dist/{plaintext.d.mts → plaintext.d.ts} +1 -1
  104. package/dist/plaintext.d.ts.map +1 -0
  105. package/dist/{plaintext.mjs → plaintext.js} +4 -5
  106. package/dist/plaintext.js.map +1 -0
  107. package/dist/{plugin.d.mts → plugin.d.ts} +2 -2
  108. package/dist/plugin.d.ts.map +1 -0
  109. package/dist/plugin.js +57 -0
  110. package/dist/plugin.js.map +1 -0
  111. package/dist/plugins/postcss/{mergeMediaQueries.d.mts → mergeMediaQueries.d.ts} +2 -2
  112. package/dist/plugins/postcss/mergeMediaQueries.d.ts.map +1 -0
  113. package/dist/plugins/postcss/{mergeMediaQueries.mjs → mergeMediaQueries.js} +2 -3
  114. package/dist/plugins/postcss/mergeMediaQueries.js.map +1 -0
  115. package/dist/plugins/postcss/{pruneVars.d.mts → pruneVars.d.ts} +1 -1
  116. package/dist/plugins/postcss/pruneVars.d.ts.map +1 -0
  117. package/dist/plugins/postcss/{pruneVars.mjs → pruneVars.js} +2 -2
  118. package/dist/plugins/postcss/pruneVars.js.map +1 -0
  119. package/dist/plugins/postcss/quoteFontFamilies.d.ts +13 -0
  120. package/dist/plugins/postcss/quoteFontFamilies.d.ts.map +1 -0
  121. package/dist/plugins/postcss/quoteFontFamilies.js +84 -0
  122. package/dist/plugins/postcss/quoteFontFamilies.js.map +1 -0
  123. package/dist/plugins/postcss/{removeDeclarations.d.mts → removeDeclarations.d.ts} +1 -1
  124. package/dist/plugins/postcss/removeDeclarations.d.ts.map +1 -0
  125. package/dist/plugins/postcss/{removeDeclarations.mjs → removeDeclarations.js} +2 -2
  126. package/dist/plugins/postcss/removeDeclarations.js.map +1 -0
  127. package/dist/plugins/postcss/resolveMaizzleImports.d.ts +16 -0
  128. package/dist/plugins/postcss/resolveMaizzleImports.d.ts.map +1 -0
  129. package/dist/plugins/postcss/resolveMaizzleImports.js +39 -0
  130. package/dist/plugins/postcss/resolveMaizzleImports.js.map +1 -0
  131. package/dist/plugins/postcss/resolveProps.d.ts +8 -0
  132. package/dist/plugins/postcss/resolveProps.d.ts.map +1 -0
  133. package/dist/plugins/postcss/resolveProps.js +144 -0
  134. package/dist/plugins/postcss/resolveProps.js.map +1 -0
  135. package/dist/plugins/postcss/{tailwindCleanup.d.mts → tailwindCleanup.d.ts} +2 -2
  136. package/dist/plugins/postcss/tailwindCleanup.d.ts.map +1 -0
  137. package/dist/plugins/postcss/tailwindCleanup.js +68 -0
  138. package/dist/plugins/postcss/tailwindCleanup.js.map +1 -0
  139. package/dist/prepare.d.ts +17 -0
  140. package/dist/prepare.d.ts.map +1 -0
  141. package/dist/prepare.js +44 -0
  142. package/dist/prepare.js.map +1 -0
  143. package/dist/render/active.d.ts +8 -0
  144. package/dist/render/active.d.ts.map +1 -0
  145. package/dist/render/active.js +12 -0
  146. package/dist/render/active.js.map +1 -0
  147. package/dist/render/{createRenderer.d.mts → createRenderer.d.ts} +15 -7
  148. package/dist/render/createRenderer.d.ts.map +1 -0
  149. package/dist/render/createRenderer.js +319 -0
  150. package/dist/render/createRenderer.js.map +1 -0
  151. package/dist/render/index.d.ts +18 -0
  152. package/dist/render/index.d.ts.map +1 -0
  153. package/dist/render/index.js +53 -0
  154. package/dist/render/index.js.map +1 -0
  155. package/dist/render/injectFonts.d.ts +15 -0
  156. package/dist/render/injectFonts.d.ts.map +1 -0
  157. package/dist/render/injectFonts.js +45 -0
  158. package/dist/render/injectFonts.js.map +1 -0
  159. package/dist/render/plugins/codeBlockExtract.d.ts +14 -0
  160. package/dist/render/plugins/codeBlockExtract.d.ts.map +1 -0
  161. package/dist/render/plugins/codeBlockExtract.js +34 -0
  162. package/dist/render/plugins/codeBlockExtract.js.map +1 -0
  163. package/dist/render/plugins/markdownExtract.d.ts +12 -0
  164. package/dist/render/plugins/markdownExtract.d.ts.map +1 -0
  165. package/dist/render/plugins/markdownExtract.js +49 -0
  166. package/dist/render/plugins/markdownExtract.js.map +1 -0
  167. package/dist/render/plugins/rawExtract.d.ts +14 -0
  168. package/dist/render/plugins/rawExtract.d.ts.map +1 -0
  169. package/dist/render/plugins/rawExtract.js +34 -0
  170. package/dist/render/plugins/rawExtract.js.map +1 -0
  171. package/dist/render/plugins/rowSourceLocation.d.ts +18 -0
  172. package/dist/render/plugins/rowSourceLocation.d.ts.map +1 -0
  173. package/dist/render/plugins/rowSourceLocation.js +45 -0
  174. package/dist/render/plugins/rowSourceLocation.js.map +1 -0
  175. package/dist/{serve.d.mts → serve.d.ts} +4 -2
  176. package/dist/serve.d.ts.map +1 -0
  177. package/dist/{serve.mjs → serve.js} +203 -79
  178. package/dist/serve.js.map +1 -0
  179. package/dist/server/compatibility.d.ts +59 -0
  180. package/dist/server/compatibility.d.ts.map +1 -0
  181. package/dist/server/compatibility.js +911 -0
  182. package/dist/server/compatibility.js.map +1 -0
  183. package/dist/server/email.d.ts +17 -0
  184. package/dist/server/email.d.ts.map +1 -0
  185. package/dist/server/email.js +40 -0
  186. package/dist/server/email.js.map +1 -0
  187. package/dist/server/linter.d.ts +20 -0
  188. package/dist/server/linter.d.ts.map +1 -0
  189. package/dist/server/linter.js +339 -0
  190. package/dist/server/linter.js.map +1 -0
  191. package/dist/server/sfc-utils.d.ts +21 -0
  192. package/dist/server/sfc-utils.d.ts.map +1 -0
  193. package/dist/server/sfc-utils.js +198 -0
  194. package/dist/server/sfc-utils.js.map +1 -0
  195. package/dist/server/ui/App.vue +253 -77
  196. package/dist/server/ui/components/SidebarClose.vue +12 -0
  197. package/dist/server/ui/components/ui/checkbox/Checkbox.vue +35 -0
  198. package/dist/server/ui/components/ui/checkbox/index.ts +1 -0
  199. package/dist/server/ui/components/ui/command/Command.vue +5 -1
  200. package/dist/server/ui/components/ui/command/CommandDialog.vue +1 -1
  201. package/dist/server/ui/components/ui/command/CommandInput.vue +19 -1
  202. package/dist/server/ui/components/ui/command/CommandItem.vue +1 -1
  203. package/dist/server/ui/components/ui/command/CommandList.vue +1 -1
  204. package/dist/server/ui/components/ui/command/CommandShortcut.vue +1 -1
  205. package/dist/server/ui/components/ui/dialog/DialogOverlay.vue +9 -1
  206. package/dist/server/ui/components/ui/dropdown-menu/DropdownMenuItem.vue +1 -1
  207. package/dist/server/ui/components/ui/input/Input.vue +1 -1
  208. package/dist/server/ui/components/ui/scroll-area/ScrollBar.vue +1 -1
  209. package/dist/server/ui/components/ui/sheet/SheetContent.vue +1 -1
  210. package/dist/server/ui/components/ui/sheet/SheetOverlay.vue +9 -1
  211. package/dist/server/ui/components/ui/sidebar/Sidebar.vue +8 -1
  212. package/dist/server/ui/components/ui/sidebar/SidebarProvider.vue +1 -1
  213. package/dist/server/ui/components/ui/sidebar/SidebarTrigger.vue +5 -4
  214. package/dist/server/ui/components/ui/tags-input/TagsInput.vue +26 -0
  215. package/dist/server/ui/components/ui/tags-input/TagsInputInput.vue +17 -0
  216. package/dist/server/ui/components/ui/tags-input/TagsInputItem.vue +19 -0
  217. package/dist/server/ui/components/ui/tags-input/TagsInputItemDelete.vue +22 -0
  218. package/dist/server/ui/components/ui/tags-input/TagsInputItemText.vue +17 -0
  219. package/dist/server/ui/components/ui/tags-input/index.ts +5 -0
  220. package/dist/server/ui/components/ui/toggle/index.ts +3 -3
  221. package/dist/server/ui/components/ui/toggle-group/ToggleGroup.vue +1 -1
  222. package/dist/server/ui/components/ui/toggle-group/ToggleGroupItem.vue +2 -2
  223. package/dist/server/ui/lib/emulated-dark-mode.ts +131 -0
  224. package/dist/server/ui/main.css +20 -20
  225. package/dist/server/ui/pages/Home.vue +12 -5
  226. package/dist/server/ui/pages/Preview.vue +716 -276
  227. package/dist/tests/render/_helpers.d.ts +6 -0
  228. package/dist/tests/render/_helpers.d.ts.map +1 -0
  229. package/dist/tests/render/_helpers.js +16 -0
  230. package/dist/tests/render/_helpers.js.map +1 -0
  231. package/dist/transformers/{addAttributes.d.mts → addAttributes.d.ts} +2 -2
  232. package/dist/transformers/addAttributes.d.ts.map +1 -0
  233. package/dist/transformers/{addAttributes.mjs → addAttributes.js} +16 -13
  234. package/dist/transformers/addAttributes.js.map +1 -0
  235. package/dist/transformers/attributeToStyle.d.ts +38 -0
  236. package/dist/transformers/attributeToStyle.d.ts.map +1 -0
  237. package/dist/transformers/attributeToStyle.js +94 -0
  238. package/dist/transformers/attributeToStyle.js.map +1 -0
  239. package/dist/transformers/base.d.ts +71 -0
  240. package/dist/transformers/base.d.ts.map +1 -0
  241. package/dist/transformers/{base.mjs → base.js} +56 -30
  242. package/dist/transformers/base.js.map +1 -0
  243. package/dist/transformers/columnWidth.d.ts +31 -0
  244. package/dist/transformers/columnWidth.d.ts.map +1 -0
  245. package/dist/transformers/columnWidth.js +546 -0
  246. package/dist/transformers/columnWidth.js.map +1 -0
  247. package/dist/transformers/entities.d.ts +37 -0
  248. package/dist/transformers/entities.d.ts.map +1 -0
  249. package/dist/transformers/entities.js +73 -0
  250. package/dist/transformers/entities.js.map +1 -0
  251. package/dist/transformers/filters/defaults.d.ts +6 -0
  252. package/dist/transformers/filters/defaults.d.ts.map +1 -0
  253. package/dist/transformers/filters/defaults.js +78 -0
  254. package/dist/transformers/filters/defaults.js.map +1 -0
  255. package/dist/transformers/filters/index.d.ts +43 -0
  256. package/dist/transformers/filters/index.d.ts.map +1 -0
  257. package/dist/transformers/filters/index.js +89 -0
  258. package/dist/transformers/filters/index.js.map +1 -0
  259. package/dist/transformers/format.d.ts +22 -0
  260. package/dist/transformers/format.d.ts.map +1 -0
  261. package/dist/transformers/format.js +30 -0
  262. package/dist/transformers/format.js.map +1 -0
  263. package/dist/transformers/{index.d.mts → index.d.ts} +14 -11
  264. package/dist/transformers/index.d.ts.map +1 -0
  265. package/dist/transformers/index.js +133 -0
  266. package/dist/transformers/index.js.map +1 -0
  267. package/dist/transformers/inlineCss.d.ts +84 -0
  268. package/dist/transformers/inlineCss.d.ts.map +1 -0
  269. package/dist/transformers/inlineCss.js +91 -0
  270. package/dist/transformers/inlineCss.js.map +1 -0
  271. package/dist/transformers/inlineLink.d.ts +35 -0
  272. package/dist/transformers/inlineLink.d.ts.map +1 -0
  273. package/dist/transformers/{inlineLink.mjs → inlineLink.js} +34 -10
  274. package/dist/transformers/inlineLink.js.map +1 -0
  275. package/dist/transformers/minify.d.ts +21 -0
  276. package/dist/transformers/minify.d.ts.map +1 -0
  277. package/dist/transformers/minify.js +25 -0
  278. package/dist/transformers/minify.js.map +1 -0
  279. package/dist/transformers/msoPlaceholders.d.ts +28 -0
  280. package/dist/transformers/msoPlaceholders.d.ts.map +1 -0
  281. package/dist/transformers/msoPlaceholders.js +88 -0
  282. package/dist/transformers/msoPlaceholders.js.map +1 -0
  283. package/dist/transformers/purgeCss.d.ts +43 -0
  284. package/dist/transformers/purgeCss.d.ts.map +1 -0
  285. package/dist/transformers/purgeCss.js +181 -0
  286. package/dist/transformers/purgeCss.js.map +1 -0
  287. package/dist/transformers/removeAttributes.d.ts +54 -0
  288. package/dist/transformers/removeAttributes.d.ts.map +1 -0
  289. package/dist/transformers/removeAttributes.js +70 -0
  290. package/dist/transformers/removeAttributes.js.map +1 -0
  291. package/dist/transformers/{replaceStrings.d.mts → replaceStrings.d.ts} +2 -2
  292. package/dist/transformers/replaceStrings.d.ts.map +1 -0
  293. package/dist/transformers/{replaceStrings.mjs → replaceStrings.js} +2 -2
  294. package/dist/transformers/replaceStrings.js.map +1 -0
  295. package/dist/transformers/{safeClassNames.d.mts → safeClassNames.d.ts} +2 -2
  296. package/dist/transformers/safeClassNames.d.ts.map +1 -0
  297. package/dist/transformers/{safeClassNames.mjs → safeClassNames.js} +4 -5
  298. package/dist/transformers/safeClassNames.js.map +1 -0
  299. package/dist/transformers/shorthandCss.d.ts +47 -0
  300. package/dist/transformers/shorthandCss.d.ts.map +1 -0
  301. package/dist/transformers/shorthandCss.js +61 -0
  302. package/dist/transformers/shorthandCss.js.map +1 -0
  303. package/dist/transformers/sixHex.d.ts +25 -0
  304. package/dist/transformers/sixHex.d.ts.map +1 -0
  305. package/dist/transformers/sixHex.js +42 -0
  306. package/dist/transformers/sixHex.js.map +1 -0
  307. package/dist/transformers/tailwindComponent.d.ts +16 -0
  308. package/dist/transformers/tailwindComponent.d.ts.map +1 -0
  309. package/dist/transformers/tailwindComponent.js +92 -0
  310. package/dist/transformers/tailwindComponent.js.map +1 -0
  311. package/dist/transformers/{tailwindcss.d.mts → tailwindcss.d.ts} +8 -4
  312. package/dist/transformers/tailwindcss.d.ts.map +1 -0
  313. package/dist/transformers/tailwindcss.js +97 -0
  314. package/dist/transformers/tailwindcss.js.map +1 -0
  315. package/dist/transformers/urlQuery.d.ts +36 -0
  316. package/dist/transformers/urlQuery.d.ts.map +1 -0
  317. package/dist/transformers/urlQuery.js +77 -0
  318. package/dist/transformers/urlQuery.js.map +1 -0
  319. package/dist/types/config.d.ts +727 -0
  320. package/dist/types/config.d.ts.map +1 -0
  321. package/dist/types/config.js +1 -0
  322. package/dist/types/index.d.ts +2 -0
  323. package/dist/types/index.js +1 -0
  324. package/dist/utils/ast/index.d.ts +4 -0
  325. package/dist/utils/ast/index.js +4 -0
  326. package/dist/utils/ast/{parser.d.mts → parser.d.ts} +1 -1
  327. package/dist/utils/ast/parser.d.ts.map +1 -0
  328. package/dist/utils/ast/{parser.mjs → parser.js} +2 -3
  329. package/dist/utils/ast/parser.js.map +1 -0
  330. package/dist/utils/ast/serializer.d.ts +8 -0
  331. package/dist/utils/ast/serializer.d.ts.map +1 -0
  332. package/dist/utils/ast/serializer.js +36 -0
  333. package/dist/utils/ast/serializer.js.map +1 -0
  334. package/dist/utils/ast/{walker.d.mts → walker.d.ts} +1 -1
  335. package/dist/utils/ast/walker.d.ts.map +1 -0
  336. package/dist/utils/ast/{walker.mjs → walker.js} +2 -2
  337. package/dist/utils/ast/walker.js.map +1 -0
  338. package/dist/utils/compileTailwindCss.d.ts +16 -0
  339. package/dist/utils/compileTailwindCss.d.ts.map +1 -0
  340. package/dist/utils/compileTailwindCss.js +54 -0
  341. package/dist/utils/compileTailwindCss.js.map +1 -0
  342. package/dist/utils/componentSources.d.ts +50 -0
  343. package/dist/utils/componentSources.d.ts.map +1 -0
  344. package/dist/utils/componentSources.js +50 -0
  345. package/dist/utils/componentSources.js.map +1 -0
  346. package/dist/utils/decodeStyleEntities.d.ts +15 -0
  347. package/dist/utils/decodeStyleEntities.d.ts.map +1 -0
  348. package/dist/utils/decodeStyleEntities.js +18 -0
  349. package/dist/utils/decodeStyleEntities.js.map +1 -0
  350. package/dist/utils/detect.d.ts +5 -0
  351. package/dist/utils/detect.d.ts.map +1 -0
  352. package/dist/utils/detect.js +10 -0
  353. package/dist/utils/detect.js.map +1 -0
  354. package/dist/utils/output-markers.d.ts +29 -0
  355. package/dist/utils/output-markers.d.ts.map +1 -0
  356. package/dist/utils/output-markers.js +68 -0
  357. package/dist/utils/output-markers.js.map +1 -0
  358. package/dist/utils/{url.d.mts → url.d.ts} +1 -1
  359. package/dist/utils/url.d.ts.map +1 -0
  360. package/dist/utils/{url.mjs → url.js} +2 -3
  361. package/dist/utils/url.js.map +1 -0
  362. package/node_modules/@clack/core/CHANGELOG.md +8 -0
  363. package/node_modules/@clack/core/dist/index.d.mts +18 -4
  364. package/node_modules/@clack/core/dist/index.mjs +16 -10
  365. package/node_modules/@clack/core/dist/index.mjs.map +1 -1
  366. package/node_modules/@clack/core/package.json +5 -2
  367. package/node_modules/@clack/prompts/CHANGELOG.md +15 -0
  368. package/node_modules/@clack/prompts/README.md +107 -2
  369. package/node_modules/@clack/prompts/dist/index.d.mts +16 -11
  370. package/node_modules/@clack/prompts/dist/index.mjs +114 -107
  371. package/node_modules/@clack/prompts/dist/index.mjs.map +1 -1
  372. package/node_modules/@clack/prompts/package.json +7 -4
  373. package/node_modules/fast-string-truncated-width/dist/index.js +36 -96
  374. package/node_modules/fast-string-truncated-width/dist/types.d.ts +0 -3
  375. package/node_modules/fast-string-truncated-width/dist/utils.d.ts +3 -3
  376. package/node_modules/fast-string-truncated-width/dist/utils.js +14 -9
  377. package/node_modules/fast-string-truncated-width/package.json +1 -1
  378. package/node_modules/fast-string-truncated-width/readme.md +2 -3
  379. package/node_modules/fast-string-width/package.json +2 -2
  380. package/node_modules/fast-string-width/readme.md +0 -3
  381. package/node_modules/fast-wrap-ansi/lib/main.js +4 -1
  382. package/node_modules/fast-wrap-ansi/lib/main.js.map +1 -1
  383. package/node_modules/fast-wrap-ansi/package.json +2 -2
  384. package/node_modules/maizzle/README.md +24 -0
  385. package/node_modules/maizzle/dist/commands/make/component.mjs +1 -1
  386. package/node_modules/maizzle/dist/commands/make/config.mjs +1 -1
  387. package/node_modules/maizzle/dist/commands/make/layout.mjs +3 -3
  388. package/node_modules/maizzle/dist/commands/make/scaffold.mjs +1 -1
  389. package/node_modules/maizzle/dist/commands/make/stubs/Layout.vue +146 -0
  390. package/node_modules/maizzle/dist/commands/make/stubs/component.vue +2 -4
  391. package/node_modules/maizzle/dist/commands/make/stubs/config.ts +1 -5
  392. package/node_modules/maizzle/dist/commands/make/template.mjs +1 -1
  393. package/node_modules/maizzle/dist/commands/new.mjs +32 -52
  394. package/node_modules/maizzle/dist/index.d.mts +1 -0
  395. package/node_modules/maizzle/dist/index.mjs +30 -7
  396. package/node_modules/maizzle/package.json +4 -3
  397. package/node_modules/nypm/dist/cli.mjs +28 -5
  398. package/node_modules/nypm/dist/index.d.mts +0 -8
  399. package/node_modules/nypm/dist/index.mjs +27 -4
  400. package/node_modules/nypm/package.json +12 -12
  401. package/node_modules/tinyexec/README.md +1 -1
  402. package/node_modules/tinyexec/dist/main.d.mts +6 -6
  403. package/node_modules/tinyexec/dist/main.mjs +126 -134
  404. package/node_modules/tinyexec/package.json +9 -9
  405. package/package.json +31 -21
  406. package/dist/build.d.mts +0 -19
  407. package/dist/build.d.mts.map +0 -1
  408. package/dist/build.mjs.map +0 -1
  409. package/dist/components/Divider.vue +0 -105
  410. package/dist/components/Vml.vue +0 -89
  411. package/dist/components/utils.d.mts +0 -5
  412. package/dist/components/utils.d.mts.map +0 -1
  413. package/dist/components/utils.mjs +0 -9
  414. package/dist/components/utils.mjs.map +0 -1
  415. package/dist/composables/defineConfig.d.mts.map +0 -1
  416. package/dist/composables/defineConfig.mjs.map +0 -1
  417. package/dist/composables/renderContext.d.mts +0 -19
  418. package/dist/composables/renderContext.d.mts.map +0 -1
  419. package/dist/composables/renderContext.mjs.map +0 -1
  420. package/dist/composables/useConfig.d.mts.map +0 -1
  421. package/dist/composables/useConfig.mjs.map +0 -1
  422. package/dist/composables/useDoctype.d.mts.map +0 -1
  423. package/dist/composables/useDoctype.mjs.map +0 -1
  424. package/dist/composables/useEvent.d.mts.map +0 -1
  425. package/dist/composables/useEvent.mjs.map +0 -1
  426. package/dist/composables/usePlaintext.d.mts.map +0 -1
  427. package/dist/composables/usePlaintext.mjs.map +0 -1
  428. package/dist/config/defaults.d.mts.map +0 -1
  429. package/dist/config/defaults.mjs.map +0 -1
  430. package/dist/config/index.d.mts.map +0 -1
  431. package/dist/config/index.mjs.map +0 -1
  432. package/dist/events/index.d.mts.map +0 -1
  433. package/dist/events/index.mjs.map +0 -1
  434. package/dist/index.d.mts +0 -29
  435. package/dist/index.mjs +0 -29
  436. package/dist/plaintext.d.mts.map +0 -1
  437. package/dist/plaintext.mjs.map +0 -1
  438. package/dist/plugin.d.mts.map +0 -1
  439. package/dist/plugin.mjs +0 -41
  440. package/dist/plugin.mjs.map +0 -1
  441. package/dist/plugins/postcss/mergeMediaQueries.d.mts.map +0 -1
  442. package/dist/plugins/postcss/mergeMediaQueries.mjs.map +0 -1
  443. package/dist/plugins/postcss/pruneVars.d.mts.map +0 -1
  444. package/dist/plugins/postcss/pruneVars.mjs.map +0 -1
  445. package/dist/plugins/postcss/removeDeclarations.d.mts.map +0 -1
  446. package/dist/plugins/postcss/removeDeclarations.mjs.map +0 -1
  447. package/dist/plugins/postcss/tailwindCleanup.d.mts.map +0 -1
  448. package/dist/plugins/postcss/tailwindCleanup.mjs +0 -35
  449. package/dist/plugins/postcss/tailwindCleanup.mjs.map +0 -1
  450. package/dist/render/createRenderer.d.mts.map +0 -1
  451. package/dist/render/createRenderer.mjs +0 -155
  452. package/dist/render/createRenderer.mjs.map +0 -1
  453. package/dist/render/index.d.mts +0 -26
  454. package/dist/render/index.d.mts.map +0 -1
  455. package/dist/render/index.mjs +0 -44
  456. package/dist/render/index.mjs.map +0 -1
  457. package/dist/serve.d.mts.map +0 -1
  458. package/dist/serve.mjs.map +0 -1
  459. package/dist/server/compatibility.d.mts +0 -6
  460. package/dist/server/compatibility.d.mts.map +0 -1
  461. package/dist/server/compatibility.mjs +0 -83
  462. package/dist/server/compatibility.mjs.map +0 -1
  463. package/dist/server/linter.d.mts +0 -6
  464. package/dist/server/linter.d.mts.map +0 -1
  465. package/dist/server/linter.mjs +0 -200
  466. package/dist/server/linter.mjs.map +0 -1
  467. package/dist/server/ui/components/ui/resizable/ResizableHandle.vue +0 -30
  468. package/dist/server/ui/components/ui/resizable/ResizablePanel.vue +0 -21
  469. package/dist/server/ui/components/ui/resizable/ResizablePanelGroup.vue +0 -25
  470. package/dist/server/ui/components/ui/resizable/index.ts +0 -3
  471. package/dist/transformers/addAttributes.d.mts.map +0 -1
  472. package/dist/transformers/addAttributes.mjs.map +0 -1
  473. package/dist/transformers/attributeToStyle.d.mts +0 -25
  474. package/dist/transformers/attributeToStyle.d.mts.map +0 -1
  475. package/dist/transformers/attributeToStyle.mjs +0 -80
  476. package/dist/transformers/attributeToStyle.mjs.map +0 -1
  477. package/dist/transformers/base.d.mts +0 -8
  478. package/dist/transformers/base.d.mts.map +0 -1
  479. package/dist/transformers/base.mjs.map +0 -1
  480. package/dist/transformers/entities.d.mts +0 -8
  481. package/dist/transformers/entities.d.mts.map +0 -1
  482. package/dist/transformers/entities.mjs +0 -38
  483. package/dist/transformers/entities.mjs.map +0 -1
  484. package/dist/transformers/format.d.mts +0 -15
  485. package/dist/transformers/format.d.mts.map +0 -1
  486. package/dist/transformers/format.mjs +0 -26
  487. package/dist/transformers/format.mjs.map +0 -1
  488. package/dist/transformers/index.d.mts.map +0 -1
  489. package/dist/transformers/index.mjs +0 -73
  490. package/dist/transformers/index.mjs.map +0 -1
  491. package/dist/transformers/inlineCSS.d.mts +0 -30
  492. package/dist/transformers/inlineCSS.d.mts.map +0 -1
  493. package/dist/transformers/inlineCSS.mjs +0 -79
  494. package/dist/transformers/inlineCSS.mjs.map +0 -1
  495. package/dist/transformers/inlineLink.d.mts +0 -14
  496. package/dist/transformers/inlineLink.d.mts.map +0 -1
  497. package/dist/transformers/inlineLink.mjs.map +0 -1
  498. package/dist/transformers/minify.d.mts +0 -17
  499. package/dist/transformers/minify.d.mts.map +0 -1
  500. package/dist/transformers/minify.mjs +0 -24
  501. package/dist/transformers/minify.mjs.map +0 -1
  502. package/dist/transformers/purgeCSS.d.mts +0 -23
  503. package/dist/transformers/purgeCSS.d.mts.map +0 -1
  504. package/dist/transformers/purgeCSS.mjs +0 -66
  505. package/dist/transformers/purgeCSS.mjs.map +0 -1
  506. package/dist/transformers/removeAttributes.d.mts +0 -31
  507. package/dist/transformers/removeAttributes.d.mts.map +0 -1
  508. package/dist/transformers/removeAttributes.mjs +0 -63
  509. package/dist/transformers/removeAttributes.mjs.map +0 -1
  510. package/dist/transformers/replaceStrings.d.mts.map +0 -1
  511. package/dist/transformers/replaceStrings.mjs.map +0 -1
  512. package/dist/transformers/safeClassNames.d.mts.map +0 -1
  513. package/dist/transformers/safeClassNames.mjs.map +0 -1
  514. package/dist/transformers/shorthandCSS.d.mts +0 -24
  515. package/dist/transformers/shorthandCSS.d.mts.map +0 -1
  516. package/dist/transformers/shorthandCSS.mjs +0 -48
  517. package/dist/transformers/shorthandCSS.mjs.map +0 -1
  518. package/dist/transformers/tailwindcss.d.mts.map +0 -1
  519. package/dist/transformers/tailwindcss.mjs +0 -136
  520. package/dist/transformers/tailwindcss.mjs.map +0 -1
  521. package/dist/transformers/urlQuery.d.mts +0 -24
  522. package/dist/transformers/urlQuery.d.mts.map +0 -1
  523. package/dist/transformers/urlQuery.mjs +0 -65
  524. package/dist/transformers/urlQuery.mjs.map +0 -1
  525. package/dist/types/config.d.mts +0 -149
  526. package/dist/types/config.d.mts.map +0 -1
  527. package/dist/types/config.mjs +0 -1
  528. package/dist/types/index.d.mts +0 -2
  529. package/dist/types/index.mjs +0 -1
  530. package/dist/utils/ast/index.d.mts +0 -4
  531. package/dist/utils/ast/index.mjs +0 -5
  532. package/dist/utils/ast/parser.d.mts.map +0 -1
  533. package/dist/utils/ast/parser.mjs.map +0 -1
  534. package/dist/utils/ast/serializer.d.mts +0 -7
  535. package/dist/utils/ast/serializer.d.mts.map +0 -1
  536. package/dist/utils/ast/serializer.mjs +0 -13
  537. package/dist/utils/ast/serializer.mjs.map +0 -1
  538. package/dist/utils/ast/walker.d.mts.map +0 -1
  539. package/dist/utils/ast/walker.mjs.map +0 -1
  540. package/dist/utils/url.d.mts.map +0 -1
  541. package/dist/utils/url.mjs.map +0 -1
  542. package/node_modules/maizzle/dist/commands/make/stubs/layout.vue +0 -39
@@ -1,7 +1,8 @@
1
1
  <script setup lang="ts">
2
2
  import { ref, computed, onMounted, onUnmounted, watch, watchEffect } from 'vue'
3
3
  import { RouterLink, RouterView, useRoute, useRouter } from 'vue-router'
4
- import { Monitor, CodeXml, Smartphone, ChevronDown, ArrowUp, ArrowDown, CornerDownLeft, Check, X } from 'lucide-vue-next'
4
+ import { Monitor, CodeXml, Smartphone, ChevronDown, ArrowUp, ArrowDown, CornerDownLeft, Check, Search, FileCode, FileText, Code, BookText, MailQuestion, Moon, Sun } from 'lucide-vue-next'
5
+ import SidebarClose from '@/components/SidebarClose.vue'
5
6
  import logoUrl from '@/logo.svg'
6
7
  import logoGradientUrl from '@/logo-gradient.svg'
7
8
  import { Kbd } from '@/components/ui/kbd'
@@ -21,7 +22,9 @@ import {
21
22
  CommandInput,
22
23
  CommandItem,
23
24
  CommandList,
25
+ CommandShortcut,
24
26
  } from '@/components/ui/command'
27
+ import { useFilter } from 'reka-ui'
25
28
  import {
26
29
  Sidebar,
27
30
  SidebarContent,
@@ -36,7 +39,6 @@ import {
36
39
  SidebarMenuButton,
37
40
  SidebarProvider,
38
41
  SidebarTrigger,
39
- SidebarInput,
40
42
  } from '@/components/ui/sidebar'
41
43
 
42
44
 
@@ -54,7 +56,6 @@ watchEffect(() => {
54
56
  })
55
57
 
56
58
  const templates = ref<Template[]>([])
57
- const search = ref('')
58
59
  const loading = ref(true)
59
60
  const viewMode = ref<'preview' | 'source'>('preview')
60
61
  const sidebarOpen = ref(localStorage.getItem('maizzle:sidebar') !== 'closed')
@@ -76,8 +77,14 @@ const devicePresets: DevicePreset[] = [
76
77
  ]
77
78
 
78
79
  const selectedDevice = ref<DevicePreset | null>(null)
80
+ const deviceMenuOpen = ref(false)
81
+ const darkMode = ref(false)
79
82
  const panelWidth = ref(0)
80
83
  const panelHeight = ref(0)
84
+ const iframeWidth = ref<number | null>(null)
85
+ const iframeHeight = ref<number | null>(null)
86
+ const maxIframeWidth = ref(0)
87
+ const maxIframeHeight = ref(0)
81
88
  const isDragging = ref(false)
82
89
  const isFullSize = ref(true)
83
90
  const resetKey = ref(0)
@@ -87,6 +94,31 @@ function selectDevice(device: DevicePreset) {
87
94
  viewMode.value = 'preview'
88
95
  }
89
96
 
97
+ /**
98
+ * Writable proxies for the toolbar's size-indicator inputs. Display falls back
99
+ * to the measured panel size when the iframe dimension is null (the axis
100
+ * hasn't been explicitly set yet — e.g. user only dragged one axis).
101
+ * Setter rejects non-finite/non-positive values and clamps to
102
+ * [200, maxIframeWidth] / [100, maxIframeHeight] so users
103
+ * can't push the drag handles off-screen via the input.
104
+ */
105
+ const widthInput = computed<number>({
106
+ get: () => Math.round(iframeWidth.value ?? panelWidth.value),
107
+ set: (v) => {
108
+ if (typeof v !== 'number' || !Number.isFinite(v) || v <= 0) return
109
+ const max = maxIframeWidth.value || v
110
+ iframeWidth.value = Math.max(200, Math.min(max, Math.round(v)))
111
+ },
112
+ })
113
+ const heightInput = computed<number>({
114
+ get: () => Math.round(iframeHeight.value ?? panelHeight.value),
115
+ set: (v) => {
116
+ if (typeof v !== 'number' || !Number.isFinite(v) || v <= 0) return
117
+ const max = maxIframeHeight.value || v
118
+ iframeHeight.value = Math.max(100, Math.min(max, Math.round(v)))
119
+ },
120
+ })
121
+
90
122
  watch(sidebarOpen, (open) => {
91
123
  localStorage.setItem('maizzle:sidebar', open ? 'open' : 'closed')
92
124
  })
@@ -104,14 +136,9 @@ if ((import.meta as any).hot) {
104
136
  }
105
137
 
106
138
  const grouped = computed(() => {
107
- const filtered = templates.value.filter(t =>
108
- t.name.toLowerCase().includes(search.value.toLowerCase())
109
- || t.path.toLowerCase().includes(search.value.toLowerCase())
110
- )
111
-
112
139
  const groups: Record<string, Template[]> = {}
113
140
 
114
- for (const t of filtered) {
141
+ for (const t of templates.value) {
115
142
  const parts = t.path.split('/')
116
143
  const dir = parts.length > 1 ? parts.slice(0, -1).join('/') : '.'
117
144
  if (!groups[dir]) groups[dir] = []
@@ -131,7 +158,42 @@ const isPreviewRoute = computed(() => route.path !== '/')
131
158
 
132
159
  // Command palette
133
160
  const router = useRouter()
161
+ const isMac = typeof navigator !== 'undefined' && /Mac|iPhone|iPad/.test(navigator.userAgent)
162
+ const modKey = isMac ? '⌘' : 'Ctrl'
134
163
  const commandOpen = ref(false)
164
+ const commandSearch = ref('')
165
+
166
+ watch(commandOpen, (open) => {
167
+ if (!open) commandSearch.value = ''
168
+ })
169
+
170
+
171
+ async function copyHtml() {
172
+ commandOpen.value = false
173
+ const slug = route.params.template as string
174
+ if (!slug) return
175
+ const res = await fetch(`/__maizzle/render/${slug}`)
176
+ await navigator.clipboard.writeText(await res.text())
177
+ }
178
+
179
+ async function copyPlaintext() {
180
+ commandOpen.value = false
181
+ const slug = route.params.template as string
182
+ if (!slug) return
183
+ const res = await fetch(`/__maizzle/plaintext/${slug}`)
184
+ await navigator.clipboard.writeText(await res.text())
185
+ }
186
+
187
+ async function copySource() {
188
+ commandOpen.value = false
189
+ const slug = route.params.template as string
190
+ if (!slug) return
191
+ const res = await fetch(`/__maizzle/vue-source/${slug}`)
192
+ const html = await res.text()
193
+ const el = document.createElement('div')
194
+ el.innerHTML = html
195
+ await navigator.clipboard.writeText(el.textContent || '')
196
+ }
135
197
 
136
198
  const commandGrouped = computed(() => {
137
199
  const groups: Record<string, Template[]> = {}
@@ -146,6 +208,20 @@ const commandGrouped = computed(() => {
146
208
  return groups
147
209
  })
148
210
 
211
+ const { contains } = useFilter({ sensitivity: 'base' })
212
+
213
+ const filteredTemplatesCount = computed(() => {
214
+ const tokens = commandSearch.value.split(/\s+/).filter(Boolean)
215
+ if (tokens.length === 0) return 0
216
+ let count = 0
217
+ for (const t of templates.value) {
218
+ const haystack = `${getFileName(t.path)} ${t.path.split('/').join(' ')}`
219
+ if (tokens.every(token => contains(haystack, token))) count++
220
+ }
221
+ return count
222
+ })
223
+
224
+
149
225
  function getFileName(path: string) {
150
226
  return path.split('/').pop() || path
151
227
  }
@@ -155,6 +231,11 @@ function onCommandSelect(href: string) {
155
231
  router.push(href)
156
232
  }
157
233
 
234
+ function openExternal(url: string) {
235
+ commandOpen.value = false
236
+ window.open(url, '_blank', 'noopener')
237
+ }
238
+
158
239
  function onKeydown(e: KeyboardEvent) {
159
240
  if ((e.metaKey || e.ctrlKey) && e.key === 'k') {
160
241
  e.preventDefault()
@@ -162,15 +243,28 @@ function onKeydown(e: KeyboardEvent) {
162
243
  return
163
244
  }
164
245
 
165
- if ((e.metaKey || e.ctrlKey) && e.key === 'b') {
246
+ if (e.key === '/' && !isInputFocused()) {
166
247
  e.preventDefault()
167
- sidebarOpen.value = !sidebarOpen.value
248
+ commandOpen.value = true
168
249
  return
169
250
  }
170
251
 
171
- if (e.key === '/' && !isInputFocused()) {
172
- e.preventDefault()
173
- commandOpen.value = true
252
+ // Copy shortcuts (Cmd on Mac, Alt on Win/Linux)
253
+ if ((isMac ? e.metaKey : e.altKey) && !e.shiftKey && isPreviewRoute.value) {
254
+ switch (e.key.toLowerCase()) {
255
+ case 'c':
256
+ e.preventDefault()
257
+ copyHtml()
258
+ return
259
+ case 'p':
260
+ e.preventDefault()
261
+ copyPlaintext()
262
+ return
263
+ case 'u':
264
+ e.preventDefault()
265
+ copySource()
266
+ return
267
+ }
174
268
  }
175
269
  }
176
270
 
@@ -181,8 +275,23 @@ function isInputFocused() {
181
275
  return tag === 'input' || tag === 'textarea' || (el as HTMLElement).isContentEditable
182
276
  }
183
277
 
184
- onMounted(() => document.addEventListener('keydown', onKeydown))
185
- onUnmounted(() => document.removeEventListener('keydown', onKeydown))
278
+ function onWindowBlur() {
279
+ deviceMenuOpen.value = false
280
+ }
281
+
282
+ function toggleDarkMode() {
283
+ commandOpen.value = false
284
+ darkMode.value = !darkMode.value
285
+ }
286
+
287
+ onMounted(() => {
288
+ document.addEventListener('keydown', onKeydown)
289
+ window.addEventListener('blur', onWindowBlur)
290
+ })
291
+ onUnmounted(() => {
292
+ document.removeEventListener('keydown', onKeydown)
293
+ window.removeEventListener('blur', onWindowBlur)
294
+ })
186
295
  </script>
187
296
 
188
297
  <template>
@@ -193,27 +302,16 @@ onUnmounted(() => document.removeEventListener('keydown', onKeydown))
193
302
  <img :src="logoUrl" alt="Maizzle" class="h-4 dark:hidden">
194
303
  <img :src="logoGradientUrl" alt="Maizzle" class="hidden h-4 dark:block">
195
304
  </RouterLink>
196
- <SidebarTrigger class="-mr-1" />
305
+ <button class="hidden md:inline-flex items-center gap-1.5 text-gray-400 hover:text-gray-600 dark:hover:text-gray-300" @click="commandOpen = true">
306
+ <Search class="size-3.5" />
307
+ <kbd class="flex items-center gap-0.5 text-[10px] font-sans">
308
+ <span>{{ modKey }}</span>
309
+ <span class="text-gray-300 dark:text-gray-600">K</span>
310
+ </kbd>
311
+ </button>
312
+ <SidebarClose />
197
313
  </SidebarHeader>
198
314
 
199
- <div class="px-3 pt-3 pb-1">
200
- <div class="relative flex items-center">
201
- <SidebarInput
202
- v-model="search"
203
- placeholder="Search emails..."
204
- class="text-xs! pr-7"
205
- @keydown.esc="search && (search = '')"
206
- />
207
- <button
208
- v-if="search"
209
- class="absolute right-2 text-gray-400 hover:text-gray-600 dark:hover:text-gray-300"
210
- @click="search = ''"
211
- >
212
- <X class="size-3.5" />
213
- </button>
214
- </div>
215
- </div>
216
-
217
315
  <SidebarContent>
218
316
  <ScrollArea class="flex-1">
219
317
  <SidebarGroup v-if="loading">
@@ -257,24 +355,17 @@ onUnmounted(() => document.removeEventListener('keydown', onKeydown))
257
355
  <SidebarInset>
258
356
  <!-- Header toolbar -->
259
357
  <header class="grid h-12 grid-cols-[1fr_auto_1fr] items-center border-b px-4">
260
- <div>
261
- <Transition
262
- enter-from-class="opacity-0"
263
- enter-active-class="transition-opacity duration-150 delay-200"
264
- leave-active-class="transition-opacity duration-0"
265
- leave-to-class="opacity-0"
266
- >
267
- <SidebarTrigger v-show="!sidebarOpen" />
268
- </Transition>
358
+ <div class="flex items-center">
359
+ <SidebarTrigger />
269
360
  </div>
270
361
 
271
362
  <!-- View mode toggles (centered) -->
272
363
  <ToggleGroup v-if="isPreviewRoute" v-model="viewMode" type="single" variant="outline" size="sm">
273
364
  <ToggleGroupItem value="preview">
274
- <Monitor class="size-4" />
365
+ <Monitor class="size-4 dark:text-gray-400" :stroke-width="1" />
275
366
  </ToggleGroupItem>
276
367
  <ToggleGroupItem value="source">
277
- <CodeXml class="size-4" />
368
+ <CodeXml class="size-4 dark:text-gray-400" :stroke-width="1" />
278
369
  </ToggleGroupItem>
279
370
  </ToggleGroup>
280
371
  <div v-else />
@@ -282,65 +373,147 @@ onUnmounted(() => document.removeEventListener('keydown', onKeydown))
282
373
  <div class="flex items-center justify-end gap-3">
283
374
  <span
284
375
  v-if="isPreviewRoute && (!isFullSize || selectedDevice) && panelWidth"
285
- class="text-xs font-medium tabular-nums text-gray-500 dark:text-gray-400 select-none"
376
+ class="hidden min-[430px]:inline text-xs font-medium tabular-nums text-gray-500 dark:text-gray-400 select-none"
286
377
  >
287
- {{ panelWidth }} &times; {{ panelHeight }}
378
+ <input
379
+ v-model.number="widthInput"
380
+ type="number"
381
+ min="200"
382
+ :max="maxIframeWidth || undefined"
383
+ aria-label="Preview width"
384
+ class="bg-transparent border-0 outline-none p-0 m-0 text-inherit font-inherit text-center tabular-nums w-[4.5ch] focus:outline-none focus:ring-0 [appearance:textfield] [&::-webkit-inner-spin-button]:appearance-none [&::-webkit-outer-spin-button]:appearance-none"
385
+ >
386
+ <button class="hover:text-gray-700 dark:hover:text-gray-300" @click="selectedDevice = null; isFullSize = true; viewMode = 'preview'; resetKey++">&times;</button>
387
+ <input
388
+ v-model.number="heightInput"
389
+ type="number"
390
+ min="100"
391
+ :max="maxIframeHeight || undefined"
392
+ aria-label="Preview height"
393
+ class="bg-transparent border-0 outline-none p-0 m-0 text-inherit font-inherit text-center tabular-nums w-[4.5ch] focus:outline-none focus:ring-0 [appearance:textfield] [&::-webkit-inner-spin-button]:appearance-none [&::-webkit-outer-spin-button]:appearance-none"
394
+ >
288
395
  </span>
289
- <DropdownMenu v-if="isPreviewRoute">
396
+ <div v-if="isPreviewRoute" class="flex items-center gap-1">
397
+ <DropdownMenu v-model:open="deviceMenuOpen" :modal="false">
290
398
  <DropdownMenuTrigger as-child>
291
- <Button variant="outline" size="sm" class="gap-1.5">
292
- <Smartphone class="size-4" />
399
+ <Button variant="ghost" size="sm" class="hidden min-[430px]:inline-flex gap-1.5 shadow-none border-none hover:bg-transparent">
400
+ <Smartphone class="size-4 dark:text-gray-400" :stroke-width="1" />
293
401
  <span v-if="selectedDevice" class="text-xs">{{ selectedDevice.name }}</span>
294
- <ChevronDown class="size-3 opacity-50" />
402
+ <ChevronDown class="size-3 opacity-50" :stroke-width="1" />
295
403
  </Button>
296
404
  </DropdownMenuTrigger>
297
- <DropdownMenuContent align="end">
298
- <DropdownMenuItem @click="selectedDevice = null; viewMode = 'preview'; resetKey++">
299
- <Check v-if="!selectedDevice" class="size-3.5" />
300
- <span :class="!selectedDevice ? '' : 'pl-5.5'">Responsive</span>
405
+ <DropdownMenuContent align="end" class="min-w-52 bg-white/80 dark:bg-gray-900/80 backdrop-blur-md dark:border-white/10">
406
+ <DropdownMenuItem class="text-xs font-medium text-gray-600 dark:text-gray-400 focus:text-gray-900 dark:focus:text-gray-200" @click="selectedDevice = null; isFullSize = true; viewMode = 'preview'; resetKey++">
407
+ <Check v-if="!selectedDevice && isFullSize" class="size-3 text-gray-900 dark:text-gray-200" />
408
+ <span :class="[!selectedDevice && isFullSize ? 'text-gray-900 dark:text-gray-200' : 'pl-5']">Full size</span>
301
409
  </DropdownMenuItem>
302
410
  <DropdownMenuItem
303
411
  v-for="device in devicePresets"
304
412
  :key="device.name"
413
+ class="text-xs font-medium text-gray-600 dark:text-gray-400 focus:text-gray-900 dark:focus:text-gray-200"
305
414
  @click="selectDevice(device)"
306
415
  >
307
- <Check v-if="selectedDevice?.name === device.name" class="size-3.5" />
308
- <span :class="selectedDevice?.name === device.name ? '' : 'pl-5.5'">{{ device.name }}</span>
309
- <span class="ml-auto text-xs text-gray-500 dark:text-gray-400 tabular-nums">{{ device.width }}&times;{{ device.height }}</span>
416
+ <Check v-if="selectedDevice?.name === device.name" class="size-3 text-gray-900 dark:text-gray-200" />
417
+ <span :class="[selectedDevice?.name === device.name ? 'text-gray-900 dark:text-gray-200' : 'pl-5']">{{ device.name }}</span>
418
+ <span class="ml-auto text-[11px] text-gray-400 dark:text-gray-500 tabular-nums tracking-tight">{{ device.width }}&times;{{ device.height }}</span>
310
419
  </DropdownMenuItem>
311
420
  </DropdownMenuContent>
312
- </DropdownMenu>
421
+ </DropdownMenu>
422
+ </div>
313
423
  </div>
314
424
  </header>
315
425
 
316
426
  <!-- Main content -->
317
427
  <div class="flex-1 overflow-hidden">
318
428
  <RouterView v-slot="{ Component }">
319
- <component :is="Component" v-model:view-mode="viewMode" :device="selectedDevice" :reset-key="resetKey" v-model:panel-width="panelWidth" v-model:panel-height="panelHeight" v-model:is-dragging="isDragging" v-model:is-full-size="isFullSize" @clear-device="selectedDevice = null" />
429
+ <component :is="Component" v-model:view-mode="viewMode" :device="selectedDevice" :reset-key="resetKey" :templates="templates" v-model:panel-width="panelWidth" v-model:panel-height="panelHeight" v-model:iframe-width="iframeWidth" v-model:iframe-height="iframeHeight" v-model:max-iframe-width="maxIframeWidth" v-model:max-iframe-height="maxIframeHeight" v-model:is-dragging="isDragging" v-model:is-full-size="isFullSize" v-model:dark-mode="darkMode" @clear-device="selectedDevice = null; isFullSize = false" />
320
430
  </RouterView>
321
431
  </div>
322
432
  </SidebarInset>
323
433
 
324
- <CommandDialog v-model:open="commandOpen" title="Search emails" description="Search and navigate to an email">
325
- <CommandInput placeholder="Search emails..." />
326
- <CommandList>
327
- <CommandEmpty>No emails found.</CommandEmpty>
328
- <CommandGroup v-for="(items, dir) in commandGrouped" :key="dir" :heading="String(dir)">
434
+ <CommandDialog v-model:open="commandOpen" title="Command palette" description="Run commands or search emails">
435
+ <CommandInput v-model="commandSearch" placeholder="Type a command or find an email..." />
436
+ <CommandList class="max-h-[400px]">
437
+ <CommandEmpty>No results found.</CommandEmpty>
438
+
439
+ <!-- Preview commands -->
440
+ <CommandGroup v-if="isPreviewRoute && viewMode === 'preview'" heading="Preview">
441
+ <CommandItem
442
+ :value="darkMode ? 'Disable dark mode' : 'Emulate dark mode'"
443
+ @select="toggleDarkMode"
444
+ >
445
+ <Sun v-if="darkMode" class="size-3 shrink-0 opacity-50" />
446
+ <Moon v-else class="size-3 shrink-0 opacity-50" />
447
+ <span>{{ darkMode ? 'Disable dark mode' : 'Emulate dark mode' }}</span>
448
+ </CommandItem>
449
+ </CommandGroup>
450
+
451
+ <!-- Copy to clipboard commands -->
452
+ <CommandGroup v-if="isPreviewRoute" heading="Copy to clipboard">
329
453
  <CommandItem
330
- v-for="t in items"
331
- :key="t.path"
332
- :value="t.path"
333
- @select="onCommandSelect(t.href)"
454
+ value="HTML"
455
+ @select="copyHtml"
334
456
  >
335
- <svg class="size-3 shrink-0 opacity-50" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
336
- <path d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z" />
337
- <path d="M14 2v4a2 2 0 0 0 2 2h4" />
338
- </svg>
339
- <span>{{ getFileName(t.path) }}</span>
457
+ <FileCode class="size-3 shrink-0 opacity-50" />
458
+ <span>HTML</span>
459
+ <CommandShortcut>{{ isMac ? '⌘' : 'ALT+' }}C</CommandShortcut>
460
+ </CommandItem>
461
+ <CommandItem
462
+ value="Plaintext"
463
+ @select="copyPlaintext"
464
+ >
465
+ <FileText class="size-3 shrink-0 opacity-50" />
466
+ <span>Plaintext</span>
467
+ <CommandShortcut>{{ isMac ? '⌘' : 'ALT+' }}P</CommandShortcut>
468
+ </CommandItem>
469
+ <CommandItem
470
+ value="Vue source"
471
+ @select="copySource"
472
+ >
473
+ <Code class="size-3 shrink-0 opacity-50" />
474
+ <span>Vue source</span>
475
+ <CommandShortcut>{{ isMac ? '⌘' : 'ALT+' }}U</CommandShortcut>
476
+ </CommandItem>
477
+ </CommandGroup>
478
+
479
+ <!-- Resources -->
480
+ <CommandGroup heading="Resources">
481
+ <CommandItem
482
+ value="Documentation"
483
+ @select="openExternal('https://maizzle.com')"
484
+ >
485
+ <BookText class="size-3 shrink-0 opacity-50" />
486
+ <span>Documentation</span>
487
+ </CommandItem>
488
+ <CommandItem
489
+ value="Can I Email"
490
+ @select="openExternal('https://www.caniemail.com')"
491
+ >
492
+ <MailQuestion class="size-3 shrink-0 opacity-50" />
493
+ <span>Can I Email</span>
340
494
  </CommandItem>
341
495
  </CommandGroup>
496
+
497
+ <!-- Templates -->
498
+ <template v-if="commandSearch">
499
+ <CommandGroup v-for="(items, dir) in commandGrouped" :key="dir" :heading="String(dir)">
500
+ <CommandItem
501
+ v-for="t in items"
502
+ :key="t.path"
503
+ :value="t.path"
504
+ @select="onCommandSelect(t.href)"
505
+ >
506
+ <svg class="size-3 shrink-0 opacity-50" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
507
+ <path d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z" />
508
+ <path d="M14 2v4a2 2 0 0 0 2 2h4" />
509
+ </svg>
510
+ <span>{{ getFileName(t.path) }}</span>
511
+ <span class="sr-only">{{ ' ' + t.path.split('/').join(' ') }}</span>
512
+ </CommandItem>
513
+ </CommandGroup>
514
+ </template>
342
515
  </CommandList>
343
- <div class="flex items-center gap-4 border-t px-3 py-2 text-xs text-gray-500 dark:text-gray-400">
516
+ <div class="flex items-center gap-4 border-t px-3 py-2 text-xs text-gray-500 dark:text-gray-400 cursor-default select-none">
344
517
  <span class="inline-flex items-center gap-1">
345
518
  <Kbd><ArrowUp class="size-3" /></Kbd>
346
519
  <Kbd><ArrowDown class="size-3" /></Kbd>
@@ -348,12 +521,15 @@ onUnmounted(() => document.removeEventListener('keydown', onKeydown))
348
521
  </span>
349
522
  <span class="inline-flex items-center gap-1">
350
523
  <Kbd><CornerDownLeft class="size-3" /></Kbd>
351
- Open
524
+ {{ commandSearch ? 'View' : 'Run' }}
352
525
  </span>
353
526
  <span class="inline-flex items-center gap-1">
354
527
  <Kbd>Esc</Kbd>
355
528
  Close
356
529
  </span>
530
+ <span v-if="commandSearch" class="ml-auto">
531
+ {{ filteredTemplatesCount }} {{ filteredTemplatesCount === 1 ? 'result' : 'results' }}
532
+ </span>
357
533
  </div>
358
534
  </CommandDialog>
359
535
  </SidebarProvider>
@@ -0,0 +1,12 @@
1
+ <script setup lang="ts">
2
+ import { PanelRightOpen } from 'lucide-vue-next'
3
+ import { useSidebar } from '@/components/ui/sidebar'
4
+
5
+ const { setOpenMobile } = useSidebar()
6
+ </script>
7
+
8
+ <template>
9
+ <button class="md:hidden text-gray-400 hover:text-gray-600 dark:hover:text-gray-300" @click="setOpenMobile(false)">
10
+ <PanelRightOpen class="size-4" :stroke-width="1" />
11
+ </button>
12
+ </template>
@@ -0,0 +1,35 @@
1
+ <script setup lang="ts">
2
+ import type { CheckboxRootEmits, CheckboxRootProps } from "reka-ui"
3
+ import type { HTMLAttributes } from "vue"
4
+ import { reactiveOmit } from "@vueuse/core"
5
+ import { Check } from "lucide-vue-next"
6
+ import { CheckboxIndicator, CheckboxRoot, useForwardPropsEmits } from "reka-ui"
7
+ import { cn } from "@/lib/utils"
8
+
9
+ const props = defineProps<CheckboxRootProps & { class?: HTMLAttributes["class"] }>()
10
+ const emits = defineEmits<CheckboxRootEmits>()
11
+
12
+ const delegatedProps = reactiveOmit(props, "class")
13
+
14
+ const forwarded = useForwardPropsEmits(delegatedProps, emits)
15
+ </script>
16
+
17
+ <template>
18
+ <CheckboxRoot
19
+ v-slot="slotProps"
20
+ data-slot="checkbox"
21
+ v-bind="forwarded"
22
+ :class="
23
+ cn('peer border-input data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground data-[state=checked]:border-primary focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive size-4 shrink-0 rounded-[4px] border shadow-xs transition-shadow outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50',
24
+ props.class)"
25
+ >
26
+ <CheckboxIndicator
27
+ data-slot="checkbox-indicator"
28
+ class="grid place-content-center text-current transition-none"
29
+ >
30
+ <slot v-bind="slotProps">
31
+ <Check class="size-3.5" />
32
+ </slot>
33
+ </CheckboxIndicator>
34
+ </CheckboxRoot>
35
+ </template>
@@ -0,0 +1 @@
1
+ export { default as Checkbox } from "./Checkbox.vue"
@@ -44,9 +44,12 @@ function filterItems() {
44
44
  filterState.filtered.groups = new Set()
45
45
  let itemCount = 0
46
46
 
47
+ // Tokenize the search by whitespace so segments match in any order
48
+ const tokens = filterState.search.split(/\s+/).filter(Boolean)
49
+
47
50
  // Check which items should be included
48
51
  for (const [id, value] of allItems.value) {
49
- const score = contains(value, filterState.search)
52
+ const score = tokens.every(token => contains(value, token))
50
53
  filterState.filtered.items.set(id, score ? 1 : 0)
51
54
  if (score)
52
55
  itemCount++
@@ -80,6 +83,7 @@ provideCommandContext({
80
83
  <ListboxRoot
81
84
  data-slot="command"
82
85
  v-bind="forwarded"
86
+ highlight-on-hover
83
87
  :class="cn('bg-popover text-popover-foreground flex h-full w-full flex-col overflow-hidden rounded-md', props.class)"
84
88
  >
85
89
  <slot />
@@ -18,7 +18,7 @@ const forwarded = useForwardPropsEmits(props, emits)
18
18
 
19
19
  <template>
20
20
  <Dialog v-slot="slotProps" v-bind="forwarded">
21
- <DialogContent class="overflow-hidden p-0 ">
21
+ <DialogContent class="overflow-hidden p-0 shadow-2xl shadow-black/10 dark:shadow-black/40" :show-close-button="false">
22
22
  <DialogHeader class="sr-only">
23
23
  <DialogTitle>{{ title }}</DialogTitle>
24
24
  <DialogDescription>{{ description }}</DialogDescription>
@@ -1,6 +1,7 @@
1
1
  <script setup lang="ts">
2
2
  import type { ListboxFilterProps } from "reka-ui"
3
3
  import type { HTMLAttributes } from "vue"
4
+ import { watch } from "vue"
4
5
  import { reactiveOmit } from "@vueuse/core"
5
6
  import { Search } from "lucide-vue-next"
6
7
  import { ListboxFilter, useForwardProps } from "reka-ui"
@@ -13,13 +14,30 @@ defineOptions({
13
14
 
14
15
  const props = defineProps<ListboxFilterProps & {
15
16
  class?: HTMLAttributes["class"]
17
+ modelValue?: string
16
18
  }>()
17
19
 
18
- const delegatedProps = reactiveOmit(props, "class")
20
+ const emit = defineEmits<{
21
+ (e: "update:modelValue", value: string): void
22
+ }>()
23
+
24
+ const delegatedProps = reactiveOmit(props, "class", "modelValue")
19
25
 
20
26
  const forwardedProps = useForwardProps(delegatedProps)
21
27
 
22
28
  const { filterState } = useCommand()
29
+
30
+ // Sync external v-model → internal filter
31
+ watch(() => props.modelValue, (val) => {
32
+ if (val !== undefined && val !== filterState.search) {
33
+ filterState.search = val
34
+ }
35
+ })
36
+
37
+ // Sync internal filter → external v-model
38
+ watch(() => filterState.search, (val) => {
39
+ emit("update:modelValue", val)
40
+ })
23
41
  </script>
24
42
 
25
43
  <template>
@@ -66,7 +66,7 @@ onUnmounted(() => {
66
66
  :id="id"
67
67
  ref="itemRef"
68
68
  data-slot="command-item"
69
- :class="cn('data-[highlighted]:bg-accent data-[highlighted]:text-accent-foreground [&_svg:not([class*=\'text-\'])]:text-muted-foreground relative flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*=\'size-\'])]:size-4', props.class)"
69
+ :class="cn('data-[highlighted]:bg-accent data-[highlighted]:text-accent-foreground [&_svg:not([class*=\'text-\'])]:text-muted-foreground relative flex cursor-default items-center gap-2 rounded-sm px-2.5 py-1.5 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*=\'size-\'])]:size-4', props.class)"
70
70
  @select="() => {
71
71
  filterState.search = ''
72
72
  }"
@@ -16,7 +16,7 @@ const forwarded = useForwardProps(delegatedProps)
16
16
  <ListboxContent
17
17
  data-slot="command-list"
18
18
  v-bind="forwarded"
19
- :class="cn('max-h-[300px] scroll-py-1 overflow-x-hidden overflow-y-auto', props.class)"
19
+ :class="cn('max-h-[300px] scroll-py-1 overflow-x-hidden overflow-y-auto p-2', props.class)"
20
20
  >
21
21
  <div role="presentation">
22
22
  <slot />
@@ -10,7 +10,7 @@ const props = defineProps<{
10
10
  <template>
11
11
  <span
12
12
  data-slot="command-shortcut"
13
- :class="cn('text-muted-foreground ml-auto text-xs tracking-widest', props.class)"
13
+ :class="cn('ml-auto text-[10px] tracking-widest text-gray-400 dark:text-gray-500', props.class)"
14
14
  >
15
15
  <slot />
16
16
  </span>