@askrjs/themes 0.0.19 → 0.0.21

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 (202) hide show
  1. package/README.md +24 -3
  2. package/THEMING.md +11 -4
  3. package/dist/components/_internal/block-layout.js +1 -1
  4. package/dist/components/_internal/block-layout.js.map +1 -1
  5. package/dist/components/_internal/style.js +9 -21
  6. package/dist/components/_internal/style.js.map +1 -1
  7. package/dist/components/grid/grid.js +5 -42
  8. package/dist/components/grid/grid.js.map +1 -1
  9. package/dist/components/jsx-types.d.ts +0 -3
  10. package/dist/components/theme/theme.js +11 -12
  11. package/dist/components/theme/theme.js.map +1 -1
  12. package/dist/entries/accordion.d.ts +1 -0
  13. package/dist/entries/accordion.js +1 -0
  14. package/dist/entries/alert-dialog.d.ts +1 -0
  15. package/dist/entries/alert-dialog.js +1 -0
  16. package/dist/entries/alert.d.ts +4 -0
  17. package/dist/entries/alert.js +2 -0
  18. package/dist/entries/aspect-ratio.d.ts +4 -0
  19. package/dist/entries/aspect-ratio.js +2 -0
  20. package/dist/entries/avatar.d.ts +1 -0
  21. package/dist/entries/avatar.js +1 -0
  22. package/dist/entries/badge.d.ts +4 -0
  23. package/dist/entries/badge.js +2 -0
  24. package/dist/entries/breadcrumb.d.ts +2 -0
  25. package/dist/entries/breadcrumb.js +2 -0
  26. package/dist/entries/button-group.d.ts +4 -0
  27. package/dist/entries/button-group.js +2 -0
  28. package/dist/entries/button.d.ts +1 -0
  29. package/dist/entries/button.js +1 -0
  30. package/dist/entries/calendar.d.ts +2 -0
  31. package/dist/entries/calendar.js +2 -0
  32. package/dist/entries/card.d.ts +4 -0
  33. package/dist/entries/card.js +2 -0
  34. package/dist/entries/carousel.d.ts +2 -0
  35. package/dist/entries/carousel.js +2 -0
  36. package/dist/entries/checkbox.d.ts +1 -0
  37. package/dist/entries/checkbox.js +1 -0
  38. package/dist/entries/collapsible.d.ts +1 -0
  39. package/dist/entries/collapsible.js +1 -0
  40. package/dist/entries/combobox.d.ts +2 -0
  41. package/dist/entries/combobox.js +2 -0
  42. package/dist/entries/command.d.ts +2 -0
  43. package/dist/entries/command.js +2 -0
  44. package/dist/entries/context-menu.d.ts +3 -0
  45. package/dist/entries/context-menu.js +3 -0
  46. package/dist/entries/data-table.d.ts +2 -0
  47. package/dist/entries/data-table.js +2 -0
  48. package/dist/entries/date-picker.d.ts +2 -0
  49. package/dist/entries/date-picker.js +2 -0
  50. package/dist/entries/dialog.d.ts +1 -0
  51. package/dist/entries/dialog.js +1 -0
  52. package/dist/entries/direction.d.ts +2 -0
  53. package/dist/entries/direction.js +2 -0
  54. package/dist/entries/drawer.d.ts +2 -0
  55. package/dist/entries/drawer.js +2 -0
  56. package/dist/entries/dropdown-menu.d.ts +3 -0
  57. package/dist/entries/dropdown-menu.js +3 -0
  58. package/dist/entries/empty.d.ts +2 -0
  59. package/dist/entries/empty.js +2 -0
  60. package/dist/entries/field.d.ts +4 -0
  61. package/dist/entries/field.js +2 -0
  62. package/dist/entries/form.d.ts +1 -0
  63. package/dist/entries/form.js +1 -0
  64. package/dist/entries/hover-card.d.ts +1 -0
  65. package/dist/entries/hover-card.js +1 -0
  66. package/dist/entries/input-group.d.ts +4 -0
  67. package/dist/entries/input-group.js +2 -0
  68. package/dist/entries/input-otp.d.ts +2 -0
  69. package/dist/entries/input-otp.js +2 -0
  70. package/dist/entries/input.d.ts +1 -0
  71. package/dist/entries/input.js +1 -0
  72. package/dist/entries/item.d.ts +2 -0
  73. package/dist/entries/item.js +2 -0
  74. package/dist/entries/kbd.d.ts +2 -0
  75. package/dist/entries/kbd.js +2 -0
  76. package/dist/entries/label.d.ts +1 -0
  77. package/dist/entries/label.js +1 -0
  78. package/dist/entries/menubar.d.ts +1 -0
  79. package/dist/entries/menubar.js +1 -0
  80. package/dist/entries/native-select.d.ts +2 -0
  81. package/dist/entries/native-select.js +2 -0
  82. package/dist/entries/navigation-menu.d.ts +2 -0
  83. package/dist/entries/navigation-menu.js +2 -0
  84. package/dist/entries/pagination.d.ts +2 -0
  85. package/dist/entries/pagination.js +2 -0
  86. package/dist/entries/popover.d.ts +1 -0
  87. package/dist/entries/popover.js +1 -0
  88. package/dist/entries/progress.d.ts +1 -0
  89. package/dist/entries/progress.js +1 -0
  90. package/dist/entries/radio-group.d.ts +1 -0
  91. package/dist/entries/radio-group.js +1 -0
  92. package/dist/entries/resizable.d.ts +2 -0
  93. package/dist/entries/resizable.js +2 -0
  94. package/dist/entries/scroll-area.d.ts +1 -0
  95. package/dist/entries/scroll-area.js +1 -0
  96. package/dist/entries/select.d.ts +1 -0
  97. package/dist/entries/select.js +1 -0
  98. package/dist/entries/separator.d.ts +4 -0
  99. package/dist/entries/separator.js +2 -0
  100. package/dist/entries/sheet.d.ts +3 -0
  101. package/dist/entries/sheet.js +3 -0
  102. package/dist/entries/sidebar.d.ts +4 -0
  103. package/dist/entries/sidebar.js +2 -0
  104. package/dist/entries/skeleton.d.ts +4 -0
  105. package/dist/entries/skeleton.js +2 -0
  106. package/dist/entries/slider.d.ts +1 -0
  107. package/dist/entries/slider.js +1 -0
  108. package/dist/entries/sonner.d.ts +2 -0
  109. package/dist/entries/sonner.js +2 -0
  110. package/dist/entries/spinner.d.ts +4 -0
  111. package/dist/entries/spinner.js +2 -0
  112. package/dist/entries/switch.d.ts +1 -0
  113. package/dist/entries/switch.js +1 -0
  114. package/dist/entries/table.d.ts +1 -0
  115. package/dist/entries/table.js +1 -0
  116. package/dist/entries/tabs.d.ts +4 -0
  117. package/dist/entries/tabs.js +3 -0
  118. package/dist/entries/textarea.d.ts +1 -0
  119. package/dist/entries/textarea.js +1 -0
  120. package/dist/entries/toast.d.ts +1 -0
  121. package/dist/entries/toast.js +1 -0
  122. package/dist/entries/toggle-group.d.ts +1 -0
  123. package/dist/entries/toggle-group.js +1 -0
  124. package/dist/entries/toggle.d.ts +1 -0
  125. package/dist/entries/toggle.js +1 -0
  126. package/dist/entries/tooltip.d.ts +1 -0
  127. package/dist/entries/tooltip.js +1 -0
  128. package/dist/entries/typography.d.ts +2 -0
  129. package/dist/entries/typography.js +2 -0
  130. package/dist/ssr.js +23 -11
  131. package/dist/ssr.js.map +1 -1
  132. package/dist/themes/default/index.css +1 -1
  133. package/package.json +25 -240
  134. package/src/components/_internal/block-layout.ts +2 -2
  135. package/src/components/_internal/style.ts +8 -26
  136. package/src/components/grid/grid.tsx +6 -57
  137. package/src/components/jsx-types.ts +0 -5
  138. package/src/components/theme/theme.tsx +22 -22
  139. package/src/entries/accordion.ts +1 -0
  140. package/src/entries/alert-dialog.ts +1 -0
  141. package/src/entries/alert.ts +1 -0
  142. package/src/entries/aspect-ratio.ts +1 -0
  143. package/src/entries/avatar.ts +1 -0
  144. package/src/entries/badge.ts +1 -0
  145. package/src/entries/breadcrumb.ts +9 -0
  146. package/src/entries/button-group.ts +1 -0
  147. package/src/entries/button.ts +1 -0
  148. package/src/entries/calendar.ts +14 -0
  149. package/src/entries/card.ts +1 -0
  150. package/src/entries/carousel.ts +7 -0
  151. package/src/entries/checkbox.ts +1 -0
  152. package/src/entries/collapsible.ts +1 -0
  153. package/src/entries/combobox.ts +1 -0
  154. package/src/entries/command.ts +13 -0
  155. package/src/entries/context-menu.ts +10 -0
  156. package/src/entries/data-table.ts +1 -0
  157. package/src/entries/date-picker.ts +1 -0
  158. package/src/entries/dialog.ts +1 -0
  159. package/src/entries/direction.ts +1 -0
  160. package/src/entries/drawer.ts +10 -0
  161. package/src/entries/dropdown-menu.ts +10 -0
  162. package/src/entries/empty.ts +8 -0
  163. package/src/entries/field.ts +1 -0
  164. package/src/entries/form.ts +1 -0
  165. package/src/entries/hover-card.ts +1 -0
  166. package/src/entries/input-group.ts +1 -0
  167. package/src/entries/input-otp.ts +1 -0
  168. package/src/entries/input.ts +1 -0
  169. package/src/entries/item.ts +11 -0
  170. package/src/entries/kbd.ts +1 -0
  171. package/src/entries/label.ts +1 -0
  172. package/src/entries/menubar.ts +1 -0
  173. package/src/entries/native-select.ts +1 -0
  174. package/src/entries/navigation-menu.ts +10 -0
  175. package/src/entries/pagination.ts +9 -0
  176. package/src/entries/popover.ts +1 -0
  177. package/src/entries/progress.ts +1 -0
  178. package/src/entries/radio-group.ts +1 -0
  179. package/src/entries/resizable.ts +1 -0
  180. package/src/entries/scroll-area.ts +1 -0
  181. package/src/entries/select.ts +1 -0
  182. package/src/entries/separator.ts +1 -0
  183. package/src/entries/sheet.ts +14 -0
  184. package/src/entries/sidebar.ts +1 -0
  185. package/src/entries/skeleton.ts +1 -0
  186. package/src/entries/slider.ts +1 -0
  187. package/src/entries/sonner.ts +1 -0
  188. package/src/entries/spinner.ts +1 -0
  189. package/src/entries/switch.ts +1 -0
  190. package/src/entries/table.ts +1 -0
  191. package/src/entries/tabs.ts +2 -0
  192. package/src/entries/textarea.ts +1 -0
  193. package/src/entries/toast.ts +1 -0
  194. package/src/entries/toggle-group.ts +1 -0
  195. package/src/entries/toggle.ts +1 -0
  196. package/src/entries/tooltip.ts +1 -0
  197. package/src/entries/typography.ts +12 -0
  198. package/src/parity.ts +3 -3
  199. package/src/ssr.ts +45 -20
  200. package/src/themes/default/foundations.css +6 -0
  201. package/src/themes/default/tokens.css +1 -1
  202. package/templates/theme/tokens.css +1 -1
@@ -0,0 +1,4 @@
1
+ import { Pill, Pills, Tab, Tabs } from "../components/nav/nav.js";
2
+ import "../components/nav/index.js";
3
+ import { TabsContent, TabsList, TabsTrigger } from "../components/catalog.js";
4
+ export { Pill, Pills, Tab, Tabs, TabsContent, TabsList, TabsTrigger };
@@ -0,0 +1,3 @@
1
+ import { Pill, Pills, Tab, Tabs } from "../components/nav/nav.js";
2
+ import { TabsContent, TabsList, TabsTrigger } from "../components/catalog.js";
3
+ export { Pill, Pills, Tab, Tabs, TabsContent, TabsList, TabsTrigger };
@@ -0,0 +1 @@
1
+ export * from "@askrjs/ui/textarea";
@@ -0,0 +1 @@
1
+ export * from "@askrjs/ui/textarea";
@@ -0,0 +1 @@
1
+ export * from "@askrjs/ui/toast";
@@ -0,0 +1 @@
1
+ export * from "@askrjs/ui/toast";
@@ -0,0 +1 @@
1
+ export * from "@askrjs/ui/toggle-group";
@@ -0,0 +1 @@
1
+ export * from "@askrjs/ui/toggle-group";
@@ -0,0 +1 @@
1
+ export * from "@askrjs/ui/toggle";
@@ -0,0 +1 @@
1
+ export * from "@askrjs/ui/toggle";
@@ -0,0 +1 @@
1
+ export * from "@askrjs/ui/tooltip";
@@ -0,0 +1 @@
1
+ export * from "@askrjs/ui/tooltip";
@@ -0,0 +1,2 @@
1
+ import { Typography, TypographyBlockquote, TypographyH1, TypographyH2, TypographyH3, TypographyH4, TypographyLead, TypographyList, TypographyMuted, TypographyP } from "../components/catalog.js";
2
+ export { Typography, TypographyBlockquote, TypographyH1, TypographyH2, TypographyH3, TypographyH4, TypographyLead, TypographyList, TypographyMuted, TypographyP };
@@ -0,0 +1,2 @@
1
+ import { Typography, TypographyBlockquote, TypographyH1, TypographyH2, TypographyH3, TypographyH4, TypographyLead, TypographyList, TypographyMuted, TypographyP } from "../components/catalog.js";
2
+ export { Typography, TypographyBlockquote, TypographyH1, TypographyH2, TypographyH3, TypographyH4, TypographyLead, TypographyList, TypographyMuted, TypographyP };
package/dist/ssr.js CHANGED
@@ -1,12 +1,19 @@
1
- import { styleRulesForHtml } from "./components/_internal/style.js";
2
1
  //#region src/ssr.ts
3
2
  const STYLE_REGISTRY_ATTR = "data-askr-style-registry";
3
+ const STYLE_CLASS_PREFIX = "ak-style-";
4
+ const CLASS_ATTRIBUTE_PATTERN = /\sclass=(?:"([^"]*)"|'([^']*)')/g;
5
+ const MAX_STYLE_RULES = 512;
4
6
  function escapeHtmlAttribute(value) {
5
7
  return value.replace(/&/g, "&amp;").replace(/"/g, "&quot;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
6
8
  }
7
9
  function escapeStyleRawText(value) {
8
10
  return value.replace(/<\/style/gi, "<\\/style");
9
11
  }
12
+ function generatedStyleClasses(html) {
13
+ const classes = /* @__PURE__ */ new Set();
14
+ for (const attribute of html.matchAll(CLASS_ATTRIBUTE_PATTERN)) for (const className of (attribute[1] ?? attribute[2] ?? "").split(/\s+/)) if (className.startsWith(STYLE_CLASS_PREFIX)) classes.add(className);
15
+ return classes;
16
+ }
10
17
  function findHeadEnd(html) {
11
18
  let index = 0;
12
19
  while (index < html.length) {
@@ -44,16 +51,21 @@ function withThemeStyles(documentRenderer) {
44
51
  return (args) => {
45
52
  const documentHtml = documentRenderer(args);
46
53
  const registeredStyles = args.context.styles;
47
- const rules = registeredStyles ? (() => {
48
- const styles = /* @__PURE__ */ new Map();
49
- for (const style of registeredStyles) {
50
- if (!style.id || !style.cssText) throw new TypeError("Invalid SSR theme style registration.");
51
- const existing = styles.get(style.id);
52
- if (existing !== void 0 && existing !== style.cssText) throw new RangeError(`SSR style registration collision for ${JSON.stringify(style.id)}.`);
53
- styles.set(style.id, style.cssText);
54
- }
55
- return Array.from(styles.values());
56
- })() : styleRulesForHtml(args.appHtml);
54
+ const generatedClasses = generatedStyleClasses(documentHtml);
55
+ if (registeredStyles === void 0) {
56
+ if (generatedClasses.size > 0) throw new Error("Generated theme classes require request-local SSR style registrations from @askrjs/askr.");
57
+ return documentHtml;
58
+ }
59
+ const styles = /* @__PURE__ */ new Map();
60
+ for (const style of registeredStyles) {
61
+ if (!style.id || !style.cssText) throw new TypeError("Invalid SSR theme style registration.");
62
+ const existing = styles.get(style.id);
63
+ if (existing !== void 0 && existing !== style.cssText) throw new RangeError(`SSR style registration collision for ${JSON.stringify(style.id)}.`);
64
+ styles.set(style.id, style.cssText);
65
+ if (styles.size > MAX_STYLE_RULES) throw new RangeError("Theme style registry capacity exceeded.");
66
+ }
67
+ for (const className of generatedClasses) if (!styles.has(className)) throw new Error(`Missing request-local SSR style registration for ${JSON.stringify(className)}.`);
68
+ const rules = Array.from(styles.values());
57
69
  if (rules.length === 0) return documentHtml;
58
70
  const nonce = args.context.cspNonce === void 0 ? "" : ` nonce="${escapeHtmlAttribute(args.context.cspNonce)}"`;
59
71
  return injectIntoHead(documentHtml, `<style ${STYLE_REGISTRY_ATTR}="true"${nonce}>${escapeStyleRawText(rules.join("\n"))}\n</style>`);
package/dist/ssr.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"ssr.js","names":[],"sources":["../src/ssr.ts"],"sourcesContent":["import { styleRulesForHtml } from \"./components/_internal/style\";\n\nconst STYLE_REGISTRY_ATTR = \"data-askr-style-registry\";\n\ntype DocumentRenderArgsLike = {\n appHtml: string;\n context: {\n cspNonce?: string;\n styles?: readonly { id: string; cssText: string }[];\n };\n};\n\nfunction escapeHtmlAttribute(value: string): string {\n return value\n .replace(/&/g, \"&amp;\")\n .replace(/\"/g, \"&quot;\")\n .replace(/</g, \"&lt;\")\n .replace(/>/g, \"&gt;\");\n}\n\nfunction escapeStyleRawText(value: string): string {\n return value.replace(/<\\/style/gi, \"<\\\\/style\");\n}\n\nfunction findHeadEnd(html: string): number {\n let index = 0;\n while (index < html.length) {\n if (html.startsWith(\"<!--\", index)) {\n const commentEnd = html.indexOf(\"-->\", index + 4);\n index = commentEnd < 0 ? html.length : commentEnd + 3;\n continue;\n }\n\n const rawTextStart = html.slice(index).match(/^<\\s*(script|style|title|textarea)(?:\\s|>)/i);\n if (rawTextStart) {\n const rawTextEndPattern = new RegExp(`</\\\\s*${rawTextStart[1]}\\\\s*>`, \"ig\");\n rawTextEndPattern.lastIndex = index + rawTextStart[0].length;\n const rawTextEnd = rawTextEndPattern.exec(html);\n if (!rawTextEnd) return -1;\n index = rawTextEnd.index + rawTextEnd[0].length;\n continue;\n }\n\n const headEnd = html.slice(index).match(/^<\\/\\s*head\\s*>/i);\n if (headEnd) return index;\n index += 1;\n }\n return -1;\n}\n\nfunction injectIntoHead(html: string, content: string): string {\n const headEnd = findHeadEnd(html);\n if (headEnd >= 0) {\n return `${html.slice(0, headEnd)}${content}${html.slice(headEnd)}`;\n }\n\n const bodyStart = html.search(/<body(?:\\s[^>]*)?>/i);\n if (bodyStart >= 0) {\n return `${html.slice(0, bodyStart)}<head>${content}</head>${html.slice(bodyStart)}`;\n }\n\n return `${content}${html}`;\n}\n\n/**\n * Wrap an Askr SSR/SSG document renderer so generated theme rules used by the\n * rendered app are available before hydration.\n */\nexport function withThemeStyles<TArgs extends DocumentRenderArgsLike>(\n documentRenderer: (args: TArgs) => string,\n): (args: TArgs) => string {\n return (args) => {\n const documentHtml = documentRenderer(args);\n const registeredStyles = args.context.styles;\n const rules = registeredStyles\n ? (() => {\n const styles = new Map<string, string>();\n for (const style of registeredStyles) {\n if (!style.id || !style.cssText) {\n throw new TypeError(\"Invalid SSR theme style registration.\");\n }\n const existing = styles.get(style.id);\n if (existing !== undefined && existing !== style.cssText) {\n throw new RangeError(\n `SSR style registration collision for ${JSON.stringify(style.id)}.`,\n );\n }\n styles.set(style.id, style.cssText);\n }\n return Array.from(styles.values());\n })()\n : styleRulesForHtml(args.appHtml);\n if (rules.length === 0) return documentHtml;\n\n const nonce =\n args.context.cspNonce === undefined\n ? \"\"\n : ` nonce=\"${escapeHtmlAttribute(args.context.cspNonce)}\"`;\n const registry = `<style ${STYLE_REGISTRY_ATTR}=\"true\"${nonce}>${escapeStyleRawText(rules.join(\"\\n\"))}\\n</style>`;\n return injectIntoHead(documentHtml, registry);\n };\n}\n"],"mappings":";;AAEA,MAAM,sBAAsB;AAU5B,SAAS,oBAAoB,OAAuB;CAClD,OAAO,MACJ,QAAQ,MAAM,OAAO,CAAC,CACtB,QAAQ,MAAM,QAAQ,CAAC,CACvB,QAAQ,MAAM,MAAM,CAAC,CACrB,QAAQ,MAAM,MAAM;AACzB;AAEA,SAAS,mBAAmB,OAAuB;CACjD,OAAO,MAAM,QAAQ,cAAc,WAAW;AAChD;AAEA,SAAS,YAAY,MAAsB;CACzC,IAAI,QAAQ;CACZ,OAAO,QAAQ,KAAK,QAAQ;EAC1B,IAAI,KAAK,WAAW,QAAQ,KAAK,GAAG;GAClC,MAAM,aAAa,KAAK,QAAQ,OAAO,QAAQ,CAAC;GAChD,QAAQ,aAAa,IAAI,KAAK,SAAS,aAAa;GACpD;EACF;EAEA,MAAM,eAAe,KAAK,MAAM,KAAK,CAAC,CAAC,MAAM,6CAA6C;EAC1F,IAAI,cAAc;GAChB,MAAM,oBAAoB,IAAI,OAAO,SAAS,aAAa,GAAG,QAAQ,IAAI;GAC1E,kBAAkB,YAAY,QAAQ,aAAa,EAAE,CAAC;GACtD,MAAM,aAAa,kBAAkB,KAAK,IAAI;GAC9C,IAAI,CAAC,YAAY,OAAO;GACxB,QAAQ,WAAW,QAAQ,WAAW,EAAE,CAAC;GACzC;EACF;EAGA,IADgB,KAAK,MAAM,KAAK,CAAC,CAAC,MAAM,kBAC9B,GAAG,OAAO;EACpB,SAAS;CACX;CACA,OAAO;AACT;AAEA,SAAS,eAAe,MAAc,SAAyB;CAC7D,MAAM,UAAU,YAAY,IAAI;CAChC,IAAI,WAAW,GACb,OAAO,GAAG,KAAK,MAAM,GAAG,OAAO,IAAI,UAAU,KAAK,MAAM,OAAO;CAGjE,MAAM,YAAY,KAAK,OAAO,qBAAqB;CACnD,IAAI,aAAa,GACf,OAAO,GAAG,KAAK,MAAM,GAAG,SAAS,EAAE,QAAQ,QAAQ,SAAS,KAAK,MAAM,SAAS;CAGlF,OAAO,GAAG,UAAU;AACtB;;;;;AAMA,SAAgB,gBACd,kBACyB;CACzB,QAAQ,SAAS;EACf,MAAM,eAAe,iBAAiB,IAAI;EAC1C,MAAM,mBAAmB,KAAK,QAAQ;EACtC,MAAM,QAAQ,0BACH;GACL,MAAM,yBAAS,IAAI,IAAoB;GACvC,KAAK,MAAM,SAAS,kBAAkB;IACpC,IAAI,CAAC,MAAM,MAAM,CAAC,MAAM,SACtB,MAAM,IAAI,UAAU,uCAAuC;IAE7D,MAAM,WAAW,OAAO,IAAI,MAAM,EAAE;IACpC,IAAI,aAAa,KAAA,KAAa,aAAa,MAAM,SAC/C,MAAM,IAAI,WACR,wCAAwC,KAAK,UAAU,MAAM,EAAE,EAAE,EACnE;IAEF,OAAO,IAAI,MAAM,IAAI,MAAM,OAAO;GACpC;GACA,OAAO,MAAM,KAAK,OAAO,OAAO,CAAC;EACnC,EAAA,CAAG,IACH,kBAAkB,KAAK,OAAO;EAClC,IAAI,MAAM,WAAW,GAAG,OAAO;EAE/B,MAAM,QACJ,KAAK,QAAQ,aAAa,KAAA,IACtB,KACA,WAAW,oBAAoB,KAAK,QAAQ,QAAQ,EAAE;EAE5D,OAAO,eAAe,cAAc,UADT,oBAAoB,SAAS,MAAM,GAAG,mBAAmB,MAAM,KAAK,IAAI,CAAC,EAAE,WAC1D;CAC9C;AACF"}
1
+ {"version":3,"file":"ssr.js","names":[],"sources":["../src/ssr.ts"],"sourcesContent":["const STYLE_REGISTRY_ATTR = \"data-askr-style-registry\";\nconst STYLE_CLASS_PREFIX = \"ak-style-\";\nconst CLASS_ATTRIBUTE_PATTERN = /\\sclass=(?:\"([^\"]*)\"|'([^']*)')/g;\nconst MAX_STYLE_RULES = 512;\n\ntype DocumentRenderArgsLike = {\n appHtml: string;\n context: {\n cspNonce?: string;\n styles?: readonly { id: string; cssText: string }[];\n };\n};\n\nfunction escapeHtmlAttribute(value: string): string {\n return value\n .replace(/&/g, \"&amp;\")\n .replace(/\"/g, \"&quot;\")\n .replace(/</g, \"&lt;\")\n .replace(/>/g, \"&gt;\");\n}\n\nfunction escapeStyleRawText(value: string): string {\n return value.replace(/<\\/style/gi, \"<\\\\/style\");\n}\n\nfunction generatedStyleClasses(html: string): Set<string> {\n const classes = new Set<string>();\n for (const attribute of html.matchAll(CLASS_ATTRIBUTE_PATTERN)) {\n for (const className of (attribute[1] ?? attribute[2] ?? \"\").split(/\\s+/)) {\n if (className.startsWith(STYLE_CLASS_PREFIX)) classes.add(className);\n }\n }\n return classes;\n}\n\nfunction findHeadEnd(html: string): number {\n let index = 0;\n while (index < html.length) {\n if (html.startsWith(\"<!--\", index)) {\n const commentEnd = html.indexOf(\"-->\", index + 4);\n index = commentEnd < 0 ? html.length : commentEnd + 3;\n continue;\n }\n\n const rawTextStart = html.slice(index).match(/^<\\s*(script|style|title|textarea)(?:\\s|>)/i);\n if (rawTextStart) {\n const rawTextEndPattern = new RegExp(`</\\\\s*${rawTextStart[1]}\\\\s*>`, \"ig\");\n rawTextEndPattern.lastIndex = index + rawTextStart[0].length;\n const rawTextEnd = rawTextEndPattern.exec(html);\n if (!rawTextEnd) return -1;\n index = rawTextEnd.index + rawTextEnd[0].length;\n continue;\n }\n\n const headEnd = html.slice(index).match(/^<\\/\\s*head\\s*>/i);\n if (headEnd) return index;\n index += 1;\n }\n return -1;\n}\n\nfunction injectIntoHead(html: string, content: string): string {\n const headEnd = findHeadEnd(html);\n if (headEnd >= 0) {\n return `${html.slice(0, headEnd)}${content}${html.slice(headEnd)}`;\n }\n\n const bodyStart = html.search(/<body(?:\\s[^>]*)?>/i);\n if (bodyStart >= 0) {\n return `${html.slice(0, bodyStart)}<head>${content}</head>${html.slice(bodyStart)}`;\n }\n\n return `${content}${html}`;\n}\n\n/**\n * Wrap an Askr SSR/SSG document renderer so generated theme rules used by the\n * rendered app are available before hydration.\n */\nexport function withThemeStyles<TArgs extends DocumentRenderArgsLike>(\n documentRenderer: (args: TArgs) => string,\n): (args: TArgs) => string {\n return (args) => {\n const documentHtml = documentRenderer(args);\n const registeredStyles = args.context.styles;\n const generatedClasses = generatedStyleClasses(documentHtml);\n if (registeredStyles === undefined) {\n if (generatedClasses.size > 0) {\n throw new Error(\n \"Generated theme classes require request-local SSR style registrations from @askrjs/askr.\",\n );\n }\n return documentHtml;\n }\n\n const styles = new Map<string, string>();\n for (const style of registeredStyles) {\n if (!style.id || !style.cssText) {\n throw new TypeError(\"Invalid SSR theme style registration.\");\n }\n const existing = styles.get(style.id);\n if (existing !== undefined && existing !== style.cssText) {\n throw new RangeError(`SSR style registration collision for ${JSON.stringify(style.id)}.`);\n }\n styles.set(style.id, style.cssText);\n if (styles.size > MAX_STYLE_RULES) {\n throw new RangeError(\"Theme style registry capacity exceeded.\");\n }\n }\n for (const className of generatedClasses) {\n if (!styles.has(className)) {\n throw new Error(\n `Missing request-local SSR style registration for ${JSON.stringify(className)}.`,\n );\n }\n }\n const rules = Array.from(styles.values());\n if (rules.length === 0) return documentHtml;\n\n const nonce =\n args.context.cspNonce === undefined\n ? \"\"\n : ` nonce=\"${escapeHtmlAttribute(args.context.cspNonce)}\"`;\n const registry = `<style ${STYLE_REGISTRY_ATTR}=\"true\"${nonce}>${escapeStyleRawText(rules.join(\"\\n\"))}\\n</style>`;\n return injectIntoHead(documentHtml, registry);\n };\n}\n"],"mappings":"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"}
@@ -145,7 +145,7 @@
145
145
  --ak-section-2: var(--ak-space-5);
146
146
  --ak-section-3: var(--ak-space-6);
147
147
  --ak-section-4: var(--ak-space-7);
148
- --ak-z-dropdown: 1000;
148
+ --ak-z-dropdown: 1500;
149
149
  --ak-z-index-base: auto;
150
150
  --ak-z-index-sm: 10;
151
151
  --ak-z-index-md: 100;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@askrjs/themes",
3
- "version": "0.0.19",
3
+ "version": "0.0.21",
4
4
  "description": "Default theme tokens, styles, and component presets for Askr apps.",
5
5
  "keywords": [
6
6
  "askr",
@@ -58,245 +58,29 @@
58
58
  "types": "./dist/ssr.d.ts",
59
59
  "import": "./dist/ssr.js"
60
60
  },
61
- "./accordion": {
62
- "types": "./dist/components.d.ts",
63
- "import": "./dist/components.js"
64
- },
65
- "./alert": {
66
- "types": "./dist/components.d.ts",
67
- "import": "./dist/components.js"
68
- },
69
- "./alert-dialog": {
70
- "types": "./dist/components.d.ts",
71
- "import": "./dist/components.js"
72
- },
73
- "./aspect-ratio": {
74
- "types": "./dist/components.d.ts",
75
- "import": "./dist/components.js"
76
- },
77
- "./avatar": {
78
- "types": "./dist/components.d.ts",
79
- "import": "./dist/components.js"
80
- },
81
- "./badge": {
82
- "types": "./dist/components.d.ts",
83
- "import": "./dist/components.js"
84
- },
85
- "./breadcrumb": {
86
- "types": "./dist/components.d.ts",
87
- "import": "./dist/components.js"
88
- },
89
- "./button": {
90
- "types": "./dist/components.d.ts",
91
- "import": "./dist/components.js"
92
- },
93
- "./button-group": {
94
- "types": "./dist/components.d.ts",
95
- "import": "./dist/components.js"
96
- },
97
- "./calendar": {
98
- "types": "./dist/components.d.ts",
99
- "import": "./dist/components.js"
100
- },
101
- "./card": {
102
- "types": "./dist/components.d.ts",
103
- "import": "./dist/components.js"
104
- },
105
- "./carousel": {
106
- "types": "./dist/components.d.ts",
107
- "import": "./dist/components.js"
108
- },
109
- "./checkbox": {
110
- "types": "./dist/components.d.ts",
111
- "import": "./dist/components.js"
112
- },
113
- "./collapsible": {
114
- "types": "./dist/components.d.ts",
115
- "import": "./dist/components.js"
116
- },
117
- "./combobox": {
118
- "types": "./dist/components.d.ts",
119
- "import": "./dist/components.js"
120
- },
121
- "./command": {
122
- "types": "./dist/components.d.ts",
123
- "import": "./dist/components.js"
124
- },
125
- "./context-menu": {
126
- "types": "./dist/components.d.ts",
127
- "import": "./dist/components.js"
128
- },
129
- "./data-table": {
130
- "types": "./dist/components.d.ts",
131
- "import": "./dist/components.js"
132
- },
133
- "./date-picker": {
134
- "types": "./dist/components.d.ts",
135
- "import": "./dist/components.js"
136
- },
137
- "./dialog": {
138
- "types": "./dist/components.d.ts",
139
- "import": "./dist/components.js"
140
- },
141
- "./direction": {
142
- "types": "./dist/components.d.ts",
143
- "import": "./dist/components.js"
144
- },
145
- "./drawer": {
146
- "types": "./dist/components.d.ts",
147
- "import": "./dist/components.js"
148
- },
149
- "./dropdown-menu": {
150
- "types": "./dist/components.d.ts",
151
- "import": "./dist/components.js"
152
- },
153
- "./empty": {
154
- "types": "./dist/components.d.ts",
155
- "import": "./dist/components.js"
156
- },
157
- "./field": {
158
- "types": "./dist/components.d.ts",
159
- "import": "./dist/components.js"
160
- },
161
- "./form": {
162
- "types": "./dist/components.d.ts",
163
- "import": "./dist/components.js"
164
- },
165
- "./hover-card": {
166
- "types": "./dist/components.d.ts",
167
- "import": "./dist/components.js"
168
- },
169
- "./input": {
170
- "types": "./dist/components.d.ts",
171
- "import": "./dist/components.js"
172
- },
173
- "./input-group": {
174
- "types": "./dist/components.d.ts",
175
- "import": "./dist/components.js"
176
- },
177
- "./input-otp": {
178
- "types": "./dist/components.d.ts",
179
- "import": "./dist/components.js"
180
- },
181
- "./item": {
182
- "types": "./dist/components.d.ts",
183
- "import": "./dist/components.js"
184
- },
185
- "./kbd": {
186
- "types": "./dist/components.d.ts",
187
- "import": "./dist/components.js"
188
- },
189
- "./label": {
190
- "types": "./dist/components.d.ts",
191
- "import": "./dist/components.js"
192
- },
193
- "./menubar": {
194
- "types": "./dist/components.d.ts",
195
- "import": "./dist/components.js"
196
- },
197
- "./native-select": {
198
- "types": "./dist/components.d.ts",
199
- "import": "./dist/components.js"
200
- },
201
- "./navigation-menu": {
202
- "types": "./dist/components.d.ts",
203
- "import": "./dist/components.js"
204
- },
205
- "./pagination": {
206
- "types": "./dist/components.d.ts",
207
- "import": "./dist/components.js"
208
- },
209
- "./popover": {
210
- "types": "./dist/components.d.ts",
211
- "import": "./dist/components.js"
212
- },
213
- "./progress": {
214
- "types": "./dist/components.d.ts",
215
- "import": "./dist/components.js"
216
- },
217
- "./radio-group": {
218
- "types": "./dist/components.d.ts",
219
- "import": "./dist/components.js"
220
- },
221
- "./resizable": {
222
- "types": "./dist/components.d.ts",
223
- "import": "./dist/components.js"
224
- },
225
- "./scroll-area": {
226
- "types": "./dist/components.d.ts",
227
- "import": "./dist/components.js"
228
- },
229
- "./select": {
230
- "types": "./dist/components.d.ts",
231
- "import": "./dist/components.js"
232
- },
233
- "./separator": {
234
- "types": "./dist/components.d.ts",
235
- "import": "./dist/components.js"
236
- },
237
- "./sheet": {
238
- "types": "./dist/components.d.ts",
239
- "import": "./dist/components.js"
240
- },
241
- "./sidebar": {
242
- "types": "./dist/components.d.ts",
243
- "import": "./dist/components.js"
244
- },
245
- "./skeleton": {
246
- "types": "./dist/components.d.ts",
247
- "import": "./dist/components.js"
248
- },
249
- "./slider": {
250
- "types": "./dist/components.d.ts",
251
- "import": "./dist/components.js"
252
- },
253
- "./sonner": {
254
- "types": "./dist/components.d.ts",
255
- "import": "./dist/components.js"
256
- },
257
- "./spinner": {
258
- "types": "./dist/components.d.ts",
259
- "import": "./dist/components.js"
260
- },
261
- "./switch": {
262
- "types": "./dist/components.d.ts",
263
- "import": "./dist/components.js"
264
- },
265
- "./table": {
266
- "types": "./dist/components.d.ts",
267
- "import": "./dist/components.js"
268
- },
269
- "./tabs": {
270
- "types": "./dist/components.d.ts",
271
- "import": "./dist/components.js"
61
+ "./*": {
62
+ "types": "./dist/entries/*.d.ts",
63
+ "import": "./dist/entries/*.js"
272
64
  },
273
- "./textarea": {
274
- "types": "./dist/components.d.ts",
275
- "import": "./dist/components.js"
276
- },
277
- "./toast": {
278
- "types": "./dist/components.d.ts",
279
- "import": "./dist/components.js"
280
- },
281
- "./toggle": {
282
- "types": "./dist/components.d.ts",
283
- "import": "./dist/components.js"
65
+ "./default/tokens.css": {
66
+ "types": "./src/css.d.ts",
67
+ "default": "./src/themes/default/tokens.css"
284
68
  },
285
- "./toggle-group": {
286
- "types": "./dist/components.d.ts",
287
- "import": "./dist/components.js"
69
+ "./default/foundations.css": {
70
+ "types": "./src/css.d.ts",
71
+ "default": "./src/themes/default/foundations.css"
288
72
  },
289
- "./tooltip": {
290
- "types": "./dist/components.d.ts",
291
- "import": "./dist/components.js"
73
+ "./default/input.css": {
74
+ "types": "./src/css.d.ts",
75
+ "default": "./src/themes/default/styles/forms/input.css"
292
76
  },
293
- "./typography": {
294
- "types": "./dist/components.d.ts",
295
- "import": "./dist/components.js"
77
+ "./default/label.css": {
78
+ "types": "./src/css.d.ts",
79
+ "default": "./src/themes/default/styles/forms/label.css"
296
80
  },
297
- "./default/tokens.css": {
81
+ "./default/styles/*": {
298
82
  "types": "./src/css.d.ts",
299
- "default": "./src/themes/default/tokens.css"
83
+ "default": "./src/themes/default/styles/*"
300
84
  },
301
85
  "./templates/*": {
302
86
  "types": "./src/css.d.ts",
@@ -326,14 +110,15 @@
326
110
  "typecheck": "tsc -p tsconfig.pack.json --noEmit",
327
111
  "build": "vp pack",
328
112
  "pack:check": "node tests/package-artifacts.js",
329
- "check": "npm run lint && npm run typecheck && npm test && npm run build && npm run test:installed && npm run test:publint && npm run pack:check",
113
+ "test:bundle": "node tests/granular-bundle.js",
114
+ "check": "npm run lint && npm run typecheck && npm test && npm run build && npm run test:installed && npm run test:publint && npm run pack:check && npm run test:bundle",
330
115
  "prepack": "npm run build",
331
116
  "prepublishOnly": "npm run check",
332
117
  "test:checks": "vp test run -c vitest.test.checks.config.ts"
333
118
  },
334
119
  "devDependencies": {
335
- "@askrjs/askr": ">=0.0.64 <0.1.0",
336
- "@askrjs/ui": ">=0.0.13 <0.1.0",
120
+ "@askrjs/askr": ">=0.0.85 <0.1.0",
121
+ "@askrjs/ui": ">=0.0.24 <0.1.0",
337
122
  "@askrjs/vite": ">=0.0.5 <0.1.0",
338
123
  "@tsdown/css": "0.22.8",
339
124
  "@types/node": "^26.0.0",
@@ -346,11 +131,11 @@
346
131
  "vite-plus": "^0.2.4"
347
132
  },
348
133
  "peerDependencies": {
349
- "@askrjs/askr": ">=0.0.64 <0.1.0",
350
- "@askrjs/ui": ">=0.0.13 <0.1.0"
134
+ "@askrjs/askr": ">=0.0.85 <0.1.0",
135
+ "@askrjs/ui": ">=0.0.24 <0.1.0"
351
136
  },
352
137
  "engines": {
353
- "node": ">=18"
138
+ "node": ">=24.15.0"
354
139
  },
355
140
  "packageManager": "npm@11.17.0"
356
141
  }
@@ -200,7 +200,7 @@ function resolveTokenValue(
200
200
  return tokens[trimmed] ?? trimmed;
201
201
  }
202
202
 
203
- function resolveSpaceValue(value: string | number): string | number {
203
+ export function resolveSpaceValue(value: string | number): string | number {
204
204
  return resolveTokenValue(value, SPACE_TOKEN_MAP);
205
205
  }
206
206
 
@@ -243,7 +243,7 @@ function resolveShadowValue(value: BlockShadow): string | undefined {
243
243
  return String(resolveTokenValue(value, SHADOW_TOKEN_MAP));
244
244
  }
245
245
 
246
- function setResponsiveVar<T>(
246
+ export function setResponsiveVar<T>(
247
247
  styles: Record<string, string | number>,
248
248
  property: string,
249
249
  value: ResponsiveValue<T> | undefined,
@@ -176,7 +176,7 @@ export function mergeCssVar(style: unknown, name: string, value: string): string
176
176
  const STYLE_REGISTRY_ATTR = "data-askr-style-registry";
177
177
  const STYLE_CLASS_PREFIX = "ak-style-";
178
178
  const MAX_STYLE_RULES = 512;
179
- const MAX_SSR_STYLE_CACHE = 4096;
179
+ const MAX_COLLISION_CACHE = 4096;
180
180
 
181
181
  type StyleRule = {
182
182
  className: string;
@@ -184,7 +184,7 @@ type StyleRule = {
184
184
  rule: string;
185
185
  };
186
186
 
187
- const styleRulesByClass = new Map<string, StyleRule>();
187
+ const styleCollisionCache = new Map<string, StyleRule>();
188
188
  type StyleRegistry = {
189
189
  element: HTMLStyleElement;
190
190
  ruleCount: number;
@@ -221,7 +221,7 @@ function escapeStyleRawText(value: string): string {
221
221
 
222
222
  function styleRuleFor(declarations: string): StyleRule {
223
223
  const className = styleClassName(declarations);
224
- const existing = styleRulesByClass.get(className);
224
+ const existing = styleCollisionCache.get(className);
225
225
  if (existing) {
226
226
  if (existing.declarations !== declarations) {
227
227
  throw new RangeError("Theme style class collision detected.");
@@ -238,12 +238,12 @@ function styleRuleFor(declarations: string): StyleRule {
238
238
  }
239
239
 
240
240
  function rememberStyleRule(entry: StyleRule): void {
241
- styleRulesByClass.delete(entry.className);
242
- styleRulesByClass.set(entry.className, entry);
243
- while (styleRulesByClass.size > MAX_SSR_STYLE_CACHE) {
244
- const oldest = styleRulesByClass.keys().next().value;
241
+ styleCollisionCache.delete(entry.className);
242
+ styleCollisionCache.set(entry.className, entry);
243
+ while (styleCollisionCache.size > MAX_COLLISION_CACHE) {
244
+ const oldest = styleCollisionCache.keys().next().value;
245
245
  if (oldest === undefined) break;
246
- styleRulesByClass.delete(oldest);
246
+ styleCollisionCache.delete(oldest);
247
247
  }
248
248
  }
249
249
 
@@ -327,21 +327,3 @@ export function styleDeclarationsToClass(declarations: string | undefined): stri
327
327
 
328
328
  return entry.className;
329
329
  }
330
-
331
- export function styleRulesForHtml(html: string): string[] {
332
- const rules = new Map<string, string>();
333
- const classAttributePattern = /\sclass=(?:"([^"]*)"|'([^']*)')/g;
334
-
335
- for (const attribute of html.matchAll(classAttributePattern)) {
336
- const value = attribute[1] ?? attribute[2] ?? "";
337
- for (const className of value.split(/\s+/)) {
338
- const entry = styleRulesByClass.get(className);
339
- if (entry) rules.set(className, entry.rule);
340
- if (rules.size > MAX_STYLE_RULES) {
341
- throw new RangeError("Theme style registry capacity exceeded.");
342
- }
343
- }
344
- }
345
-
346
- return Array.from(rules.values());
347
- }
@@ -1,46 +1,13 @@
1
1
  import type { JSX } from "@askrjs/askr/jsx-runtime";
2
2
  import { classes } from "../_internal/classes";
3
- import { mergeLayoutStyles } from "../_internal/block-layout";
3
+ import { mergeLayoutStyles, resolveSpaceValue, setResponsiveVar } from "../_internal/block-layout";
4
4
  import { mergeProps } from "../_internal/merge-props";
5
5
  import { intrinsicElement } from "../_internal/jsx";
6
6
  import { styleDeclarationsToClass } from "../_internal/style";
7
- import type { BlockSpace, LayoutBreakpoint, ResponsiveValue } from "../_internal/block-layout";
7
+ import type { BlockSpace } from "../_internal/block-layout";
8
8
  import type { GridAlign, GridColumns, GridElement, GridProps } from "./grid.types";
9
9
 
10
10
  const DEFAULT_ELEMENT = "div";
11
- const BREAKPOINTS: readonly LayoutBreakpoint[] = ["base", "sm", "md", "lg", "xl"];
12
-
13
- const SPACE_TOKEN_MAP: Record<BlockSpace, string> = {
14
- "0": "0",
15
- xs: "var(--ak-space-xs)",
16
- sm: "var(--ak-space-sm)",
17
- md: "var(--ak-space-md)",
18
- lg: "var(--ak-space-lg)",
19
- xl: "var(--ak-space-xl)",
20
- "2xl": "var(--ak-space-2xl)",
21
- "3xl": "var(--ak-space-3xl)",
22
- page: "var(--ak-layout-page-gutter)",
23
- };
24
-
25
- function isResponsiveValue<T>(
26
- value: ResponsiveValue<T> | undefined,
27
- ): value is Partial<Record<LayoutBreakpoint, T>> {
28
- return Boolean(
29
- value &&
30
- typeof value === "object" &&
31
- !Array.isArray(value) &&
32
- BREAKPOINTS.some((breakpoint) => breakpoint in value),
33
- );
34
- }
35
-
36
- function normalizeResponsiveValue<T>(
37
- value: ResponsiveValue<T> | undefined,
38
- ): Partial<Record<LayoutBreakpoint, T>> | undefined {
39
- if (value === undefined) return undefined;
40
- if (isResponsiveValue(value)) return value;
41
- return { base: value };
42
- }
43
-
44
11
  function resolveColumns(value: GridColumns): string {
45
12
  if (typeof value === "number") {
46
13
  return `repeat(${value}, minmax(0, 1fr))`;
@@ -51,7 +18,7 @@ function resolveColumns(value: GridColumns): string {
51
18
  }
52
19
 
53
20
  function resolveGap(value: BlockSpace): string {
54
- return SPACE_TOKEN_MAP[value] ?? value;
21
+ return String(resolveSpaceValue(value));
55
22
  }
56
23
 
57
24
  function resolveAlign(value: GridAlign): string {
@@ -60,24 +27,6 @@ function resolveAlign(value: GridAlign): string {
60
27
  return value;
61
28
  }
62
29
 
63
- function setResponsiveVar<T>(
64
- styles: Record<string, string | number>,
65
- property: string,
66
- value: ResponsiveValue<T> | undefined,
67
- resolve: (value: T) => string | number | undefined,
68
- ) {
69
- const normalized = normalizeResponsiveValue(value);
70
- if (!normalized) return;
71
-
72
- for (const breakpoint of BREAKPOINTS) {
73
- const breakpointValue = normalized[breakpoint];
74
- if (breakpointValue === undefined) continue;
75
- const resolved = resolve(breakpointValue);
76
- if (resolved === undefined || resolved === "") continue;
77
- styles[`--ak-grid-${property}-${breakpoint}`] = resolved;
78
- }
79
- }
80
-
81
30
  export function Grid<TElement extends GridElement = "div">(
82
31
  props: GridProps<TElement>,
83
32
  ): JSX.Element {
@@ -99,9 +48,9 @@ export function Grid<TElement extends GridElement = "div">(
99
48
  };
100
49
 
101
50
  const styles: Record<string, string | number> = {};
102
- setResponsiveVar(styles, "columns", columns, resolveColumns);
103
- setResponsiveVar(styles, "gap", gap, resolveGap);
104
- setResponsiveVar(styles, "align", align, resolveAlign);
51
+ setResponsiveVar(styles, "grid-columns", columns, resolveColumns);
52
+ setResponsiveVar(styles, "grid-gap", gap, resolveGap);
53
+ setResponsiveVar(styles, "grid-align", align, resolveAlign);
105
54
 
106
55
  const generatedClass = styleDeclarationsToClass(mergeLayoutStyles(styles, userStyle));
107
56
  const finalProps = mergeProps(rest, {
@@ -5,11 +5,6 @@ declare global {
5
5
  interface Element extends JSXElement {
6
6
  readonly __askrThemesJsxElementBrand?: never;
7
7
  }
8
-
9
- interface IntrinsicElements {
10
- // @ts-ignore The Askr source types already provide a compatible fallback index.
11
- [element: string]: Record<string, unknown>;
12
- }
13
8
  }
14
9
  }
15
10