@atom-learning/components 6.0.0-beta.11 → 6.0.0-beta.13

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 (211) hide show
  1. package/dist/components/accordion/AccordionContent.d.ts +2 -2
  2. package/dist/components/accordion/AccordionItem.d.ts +2 -2
  3. package/dist/components/accordion/AccordionTrigger.d.ts +3 -3
  4. package/dist/components/action-icon/ActionIcon.d.ts +2 -2
  5. package/dist/components/action-icon/ActionIcon.js +1 -1
  6. package/dist/components/action-icon/ActionIcon.js.map +1 -1
  7. package/dist/components/alert-dialog/AlertDialog.d.ts +3 -3
  8. package/dist/components/alert-dialog/AlertDialogContent.d.ts +3 -3
  9. package/dist/components/avatar/Avatar.d.ts +6 -6
  10. package/dist/components/avatar/Avatar.js +1 -1
  11. package/dist/components/avatar/Avatar.js.map +1 -1
  12. package/dist/components/badge/Badge.d.ts +11 -11
  13. package/dist/components/badge/Badge.js.map +1 -1
  14. package/dist/components/badge/BadgeText.d.ts +4 -4
  15. package/dist/components/banner/BannerContainer.d.ts +3 -3
  16. package/dist/components/banner/BannerContainer.js +1 -1
  17. package/dist/components/banner/BannerContainer.js.map +1 -1
  18. package/dist/components/banner/BannerContext.d.ts +4 -1
  19. package/dist/components/banner/BannerContext.js.map +1 -1
  20. package/dist/components/banner/banner-regular/BannerRegular.d.ts +3 -3
  21. package/dist/components/banner/banner-regular/BannerRegularContent.d.ts +2 -2
  22. package/dist/components/banner/banner-regular/BannerRegularContent.js +1 -1
  23. package/dist/components/banner/banner-regular/BannerRegularContent.js.map +1 -1
  24. package/dist/components/banner/banner-regular/BannerRegularDismiss.d.ts +3 -3
  25. package/dist/components/banner/banner-regular/BannerRegularHeading.js +1 -1
  26. package/dist/components/banner/banner-regular/BannerRegularHeading.js.map +1 -1
  27. package/dist/components/banner/banner-regular/BannerRegularImage.js +1 -1
  28. package/dist/components/banner/banner-regular/BannerRegularImage.js.map +1 -1
  29. package/dist/components/banner/banner-regular/BannerRegularText.js +1 -1
  30. package/dist/components/banner/banner-regular/BannerRegularText.js.map +1 -1
  31. package/dist/components/banner/banner-slim/BannerSlim.d.ts +4 -4
  32. package/dist/components/banner/banner-slim/BannerSlimActions.js +1 -1
  33. package/dist/components/banner/banner-slim/BannerSlimActions.js.map +1 -1
  34. package/dist/components/banner/banner-slim/BannerSlimContainer.d.ts +4 -4
  35. package/dist/components/banner/banner-slim/BannerSlimContainer.js +1 -1
  36. package/dist/components/banner/banner-slim/BannerSlimContainer.js.map +1 -1
  37. package/dist/components/banner/banner-slim/BannerSlimContent.d.ts +3 -3
  38. package/dist/components/banner/banner-slim/BannerSlimDismiss.d.ts +3 -3
  39. package/dist/components/banner/banner-slim/BannerSlimDismiss.js +1 -1
  40. package/dist/components/banner/banner-slim/BannerSlimDismiss.js.map +1 -1
  41. package/dist/components/banner/banner-slim/BannerSlimImage.js +1 -1
  42. package/dist/components/banner/banner-slim/BannerSlimImage.js.map +1 -1
  43. package/dist/components/banner/banner-slim/BannerSlimText.js +1 -1
  44. package/dist/components/banner/banner-slim/BannerSlimText.js.map +1 -1
  45. package/dist/components/box/Box.d.ts +2 -2
  46. package/dist/components/button/Button.d.ts +2 -2
  47. package/dist/components/button/Button.js +1 -1
  48. package/dist/components/button/Button.js.map +1 -1
  49. package/dist/components/calendar/Day.d.ts +5 -5
  50. package/dist/components/calendar/Day.js +1 -1
  51. package/dist/components/calendar/Day.js.map +1 -1
  52. package/dist/components/carousel/Carousel.d.ts +8 -8
  53. package/dist/components/carousel/CarouselArrows.d.ts +4 -4
  54. package/dist/components/carousel/CarouselPagination.d.ts +2 -2
  55. package/dist/components/carousel/CarouselSlider.d.ts +2 -2
  56. package/dist/components/checkbox/Checkbox.d.ts +4 -4
  57. package/dist/components/checkbox-group/CheckboxGroup.d.ts +7 -7
  58. package/dist/components/checkbox-tree/CheckboxTree.d.ts +6 -6
  59. package/dist/components/chip/Chip.d.ts +11 -11
  60. package/dist/components/chip/ChipGroup.d.ts +2 -2
  61. package/dist/components/chip-dismissible-group/ChipDismissibleGroupItem.d.ts +4 -4
  62. package/dist/components/chip-toggle-group/ChipToggleGroupItem.d.ts +4 -4
  63. package/dist/components/chip-toggle-group/ChipToggleGroupRoot.d.ts +4 -4
  64. package/dist/components/combobox/Combobox.d.ts +10 -10
  65. package/dist/components/combobox/ComboboxInput.d.ts +8 -8
  66. package/dist/components/combobox/ComboboxList.d.ts +2 -2
  67. package/dist/components/combobox/ComboboxOption.d.ts +2 -2
  68. package/dist/components/combobox/ComboboxPopover.d.ts +2 -2
  69. package/dist/components/data-table/DataTable.d.ts +32 -32
  70. package/dist/components/data-table/DataTableBulkActionsFloating.d.ts +3 -3
  71. package/dist/components/data-table/DataTableLoading.d.ts +3 -3
  72. package/dist/components/data-table/pagination/Pagination.d.ts +2 -2
  73. package/dist/components/dialog/Dialog.d.ts +5 -5
  74. package/dist/components/dialog/DialogBackground.d.ts +2 -2
  75. package/dist/components/dialog/DialogContent.d.ts +3 -3
  76. package/dist/components/divider/Divider.d.ts +6 -6
  77. package/dist/components/drawer/Drawer.d.ts +6 -6
  78. package/dist/components/drawer/DrawerContent.d.ts +4 -4
  79. package/dist/components/drawer/DrawerFooter.d.ts +2 -2
  80. package/dist/components/drawer/DrawerHeader.d.ts +2 -2
  81. package/dist/components/drawer/DrawerMain.d.ts +2 -2
  82. package/dist/components/drawer/DrawerOverlay.d.ts +2 -2
  83. package/dist/components/dropdown-menu/DropdownMenu.d.ts +8 -8
  84. package/dist/components/dropdown-menu/DropdownMenuContent.d.ts +2 -2
  85. package/dist/components/dropdown-menu/DropdownMenuItem.d.ts +2 -2
  86. package/dist/components/dropdown-menu/DropdownMenuSeparator.d.ts +2 -2
  87. package/dist/components/dropdown-menu/DropdownMenuTrigger.d.ts +2 -2
  88. package/dist/components/empty-state/EmptyState.d.ts +16 -16
  89. package/dist/components/empty-state/EmptyStateBody.d.ts +4 -4
  90. package/dist/components/empty-state/EmptyStateImage.d.ts +5 -5
  91. package/dist/components/empty-state/EmptyStateTitle.d.ts +3 -3
  92. package/dist/components/flex/Flex.d.ts +2 -2
  93. package/dist/components/flex/Flex.js +1 -1
  94. package/dist/components/flex/Flex.js.map +1 -1
  95. package/dist/components/grid/Grid.d.ts +3 -3
  96. package/dist/components/heading/Heading.d.ts +2 -2
  97. package/dist/components/heading/Heading.js +1 -1
  98. package/dist/components/heading/Heading.js.map +1 -1
  99. package/dist/components/icon/Icon.d.ts +3 -3
  100. package/dist/components/image/Image.d.ts +3 -3
  101. package/dist/components/inline-message/InlineMessage.d.ts +4 -4
  102. package/dist/components/input/Input.d.ts +10 -10
  103. package/dist/components/keyboard-shortcut/KeyboardShortcut.d.ts +3 -3
  104. package/dist/components/keyboard-shortcut/index.d.ts +3 -3
  105. package/dist/components/label/Label.d.ts +7 -7
  106. package/dist/components/link/Link.d.ts +4 -4
  107. package/dist/components/list/List.d.ts +8 -8
  108. package/dist/components/loader/Loader.js +1 -1
  109. package/dist/components/loader/Loader.js.map +1 -1
  110. package/dist/components/markdown-content/MarkdownContent.d.ts +3 -3
  111. package/dist/components/markdown-content/components/MarkdownEmphasis.d.ts +2 -2
  112. package/dist/components/navigation/NavigationMenu.d.ts +22 -22
  113. package/dist/components/navigation/NavigationMenuDropdownContent.d.ts +2 -2
  114. package/dist/components/navigation/NavigationMenuDropdownItem.d.ts +9 -9
  115. package/dist/components/navigation/NavigationMenuDropdownTrigger.d.ts +3 -3
  116. package/dist/components/navigation/NavigationMenuLink.d.ts +6 -6
  117. package/dist/components/navigation-menu-vertical/NavigationMenuVertical.d.ts +20 -20
  118. package/dist/components/navigation-menu-vertical/NavigationMenuVerticalAccordionTrigger.d.ts +3 -3
  119. package/dist/components/navigation-menu-vertical/NavigationMenuVerticalIcon.d.ts +4 -4
  120. package/dist/components/navigation-menu-vertical/NavigationMenuVerticalLink.d.ts +3 -3
  121. package/dist/components/navigation-menu-vertical/NavigationMenuVerticalList.d.ts +2 -2
  122. package/dist/components/navigation-menu-vertical/NavigationMenuVerticalText.d.ts +4 -4
  123. package/dist/components/notification-badge/NotificationBadge.js +1 -1
  124. package/dist/components/notification-badge/NotificationBadge.js.map +1 -1
  125. package/dist/components/number-input/NumberInputStepper.d.ts +4 -4
  126. package/dist/components/pagination/PaginationNextButton.d.ts +3 -3
  127. package/dist/components/pagination/PaginationPreviousButton.d.ts +3 -3
  128. package/dist/components/popover/Popover.d.ts +3 -3
  129. package/dist/components/popover/PopoverContent.d.ts +3 -3
  130. package/dist/components/progress-bar/ProgressBar.d.ts +4 -4
  131. package/dist/components/progress-bar/ProgressBar.js +1 -1
  132. package/dist/components/progress-bar/ProgressBar.js.map +1 -1
  133. package/dist/components/radio-button/RadioButton.d.ts +3 -3
  134. package/dist/components/radio-button/RadioButton.js +1 -1
  135. package/dist/components/radio-button/RadioButton.js.map +1 -1
  136. package/dist/components/radio-button/RadioButtonGroup.d.ts +3 -3
  137. package/dist/components/radio-button-field/RadioButtonField.d.ts +3 -3
  138. package/dist/components/radio-card/RadioCard.d.ts +5 -5
  139. package/dist/components/radio-card/RadioCard.js +1 -1
  140. package/dist/components/radio-card/RadioCard.js.map +1 -1
  141. package/dist/components/section-message/SectionMessage.d.ts +7 -7
  142. package/dist/components/segmented-control/SegmentedControl.d.ts +17 -17
  143. package/dist/components/segmented-control/SegmentedControlContent.d.ts +2 -2
  144. package/dist/components/segmented-control/SegmentedControlDescription.d.ts +4 -4
  145. package/dist/components/segmented-control/SegmentedControlHeading.d.ts +4 -4
  146. package/dist/components/segmented-control/SegmentedControlItem.d.ts +5 -5
  147. package/dist/components/segmented-control/SegmentedControlRoot.d.ts +4 -4
  148. package/dist/components/select/Select.d.ts +5 -5
  149. package/dist/components/side-bar/SideBar.d.ts +17 -17
  150. package/dist/components/side-bar/SideBarComponents.d.ts +14 -14
  151. package/dist/components/slider/Slider.d.ts +5 -5
  152. package/dist/components/slider/Slider.js +1 -1
  153. package/dist/components/slider/Slider.js.map +1 -1
  154. package/dist/components/sortable/Handle.d.ts +4 -4
  155. package/dist/components/spacer/Spacer.d.ts +2 -2
  156. package/dist/components/stepper/StepperStepBullet.d.ts +4 -4
  157. package/dist/components/stepper/StepperStepContainer.d.ts +7 -7
  158. package/dist/components/stepper/StepperStepLabel.d.ts +5 -5
  159. package/dist/components/switch/Switch.d.ts +3 -3
  160. package/dist/components/switch/Switch.js +1 -1
  161. package/dist/components/switch/Switch.js.map +1 -1
  162. package/dist/components/table/Table.d.ts +21 -21
  163. package/dist/components/table/TableBody.d.ts +3 -3
  164. package/dist/components/table/TableCell.d.ts +2 -2
  165. package/dist/components/table/TableFooter.d.ts +2 -2
  166. package/dist/components/table/TableFooterCell.d.ts +2 -2
  167. package/dist/components/table/TableHeader.d.ts +4 -4
  168. package/dist/components/table/TableHeaderCell.d.ts +2 -2
  169. package/dist/components/table/TableRow.d.ts +2 -2
  170. package/dist/components/tabs/Tabs.d.ts +8 -8
  171. package/dist/components/tabs/TabsContent.d.ts +2 -2
  172. package/dist/components/tabs/TabsTrigger.d.ts +2 -2
  173. package/dist/components/tabs/TabsTriggerList.d.ts +2 -2
  174. package/dist/components/text/Text.d.ts +2 -2
  175. package/dist/components/text/Text.js +1 -1
  176. package/dist/components/text/Text.js.map +1 -1
  177. package/dist/components/textarea/Textarea.d.ts +8 -8
  178. package/dist/components/tile/Tile.d.ts +5 -5
  179. package/dist/components/tile/TileGroup.d.ts +2 -2
  180. package/dist/components/tile-interactive/TileInteractive.d.ts +6 -6
  181. package/dist/components/tile-toggle-group/TileToggleGroupItem.d.ts +7 -7
  182. package/dist/components/tile-toggle-group/TileToggleGroupRoot.d.ts +5 -5
  183. package/dist/components/toast/Toast.d.ts +4 -4
  184. package/dist/components/toggle-group/ToggleGroupButton.d.ts +14 -14
  185. package/dist/components/toggle-group/ToggleGroupItem.d.ts +3 -3
  186. package/dist/components/toggle-group/ToggleGroupRoot.d.ts +13 -13
  187. package/dist/components/toggle-group/index.d.ts +17 -17
  188. package/dist/components/tooltip/Tooltip.d.ts +3 -3
  189. package/dist/components/tooltip/TooltipContent.d.ts +3 -3
  190. package/dist/components/top-bar/TopBar.d.ts +9 -9
  191. package/dist/components/top-bar/TopBar.js +1 -1
  192. package/dist/components/top-bar/TopBar.js.map +1 -1
  193. package/dist/components/top-bar/TopBarBrand.d.ts +5 -5
  194. package/dist/components/tree/Tree.d.ts +17 -17
  195. package/dist/components/tree/TreeCollapsible.d.ts +2 -2
  196. package/dist/components/tree/TreeCollapsibleContent.d.ts +2 -2
  197. package/dist/components/tree/TreeIcon.d.ts +4 -4
  198. package/dist/components/tree/TreeItemContent.d.ts +2 -2
  199. package/dist/components/tree/TreeListItem.d.ts +2 -2
  200. package/dist/docgen.json +1 -1
  201. package/dist/index.cjs.js +1 -1
  202. package/dist/index.cjs.js.map +1 -1
  203. package/dist/styled.d.ts +10 -3
  204. package/dist/styled.js +1 -1
  205. package/dist/styled.js.map +1 -1
  206. package/dist/utilities/no-overflow-wrapper/NoOverflowWrapper.d.ts +2 -2
  207. package/package.json +14 -6
  208. package/scripts/generate-responsive-variant-classes.mjs +300 -0
  209. package/scripts/vite-plugin-tailwind-responsive-variant-classes.mjs +92 -0
  210. package/src/index.css +1 -4
  211. package/src/responsive-variant-classes.css +15 -0
package/dist/styled.d.ts CHANGED
@@ -14,8 +14,10 @@ type BooleanKeys<V> = Extract<StringKeys<V>, 'true' | 'false'>;
14
14
  type HasBoolLikeKeys<V> = BooleanKeys<V> extends never ? Extract<StringKeys<V>, 'true' | 'false'> extends never ? false : true : true;
15
15
  type VariantValueType<V> = HasBoolLikeKeys<V> extends true ? boolean : [NumberKeys<V>] extends [never] ? StringKeys<V> : NumberKeys<V> | `${NumberKeys<V>}`;
16
16
  type VariantConfig = Record<string, Record<string | number, string[]>>;
17
- type VariantProps<V extends VariantConfig | undefined> = V extends VariantConfig ? {
17
+ type VariantProps<V extends VariantConfig | undefined, R extends boolean = false> = V extends VariantConfig ? R extends true ? {
18
18
  [K in keyof V]?: ResponsiveVariant<VariantValueType<V[K]>>;
19
+ } : {
20
+ [K in keyof V]?: VariantValueType<V[K]>;
19
21
  } : unknown;
20
22
  type StyledConfig<V extends VariantConfig | undefined = undefined> = {
21
23
  base?: string | string[];
@@ -29,7 +31,12 @@ type StyledConfig<V extends VariantConfig | undefined = undefined> = {
29
31
  [K in keyof V]?: VariantValueType<V[K]>;
30
32
  } : Record<string, never>;
31
33
  };
32
- export declare const styled: <TElement extends ElementType, V extends VariantConfig | undefined = undefined>(el: TElement, styles: StyledConfig<V>) => React.ForwardRefExoticComponent<React.PropsWithoutRef<Omit<React.ComponentPropsWithRef<TElement>, V extends VariantConfig ? keyof V : never> & VariantProps<V> & {
34
+ export declare function styled<TElement extends ElementType, V extends VariantConfig>(el: TElement, styles: StyledConfig<V>, options: {
35
+ enabledResponsiveVariants: true;
36
+ }): React.ForwardRefExoticComponent<Omit<React.ComponentPropsWithRef<TElement>, keyof V> & VariantProps<V, true> & {
33
37
  as?: ElementType;
34
- }> & React.RefAttributes<React.ElementRef<TElement>>>;
38
+ }>;
39
+ export declare function styled<TElement extends ElementType, V extends VariantConfig | undefined = undefined>(el: TElement, styles: StyledConfig<V>): React.ForwardRefExoticComponent<Omit<React.ComponentPropsWithRef<TElement>, V extends VariantConfig ? keyof V : never> & VariantProps<V, false> & {
40
+ as?: ElementType;
41
+ }>;
35
42
  export {};
package/dist/styled.js CHANGED
@@ -1,2 +1,2 @@
1
- import y from"clsx";import c from"react";import{tv as N}from"tailwind-variants";const O=({children:e,theme:s})=>c.createElement("div",{className:"contents",style:s},e),h=e=>Object.fromEntries(Object.values(e).flatMap(s=>Object.entries(s).map(([n,p])=>["--".concat(n),p]))),g=(e,s)=>{const n=Object.keys(s.variants||{}),p=N(s,{twMerge:!1});return c.forwardRef((a,o)=>{const d=n.map(t=>{const r=a[t],l=s.variants[t];return typeof r=="object"&&r?Object.entries(r).flatMap(([m,f])=>{const b=l&&l[f];return b?b.flatMap(j=>m==="@initial"?j:"".concat(m.replace("@",""),":").concat(j)):[]}):[]}).flat(),E=p(a),i=Object.fromEntries(Object.entries(a).filter(([t])=>!n.includes(t)&&t!=="as")),u=y(E,d).trim();if(typeof e=="string"||typeof e=="function"||e&&typeof e=="object"){const t=e;if(typeof e=="string")return c.createElement(a.as||t,{...i,ref:o,className:u});const r={...i,as:a.as,className:y(a.className,u).trim(),ref:o};return c.createElement(t,r)}if(c.isValidElement(e)){const t=e,r=t.props.className,l=i.className,m=y(r,l,u).trim(),f={...i,as:a.as||t.props.as,className:m};return o&&(f.ref=o),c.cloneElement(t,f)}throw console.log({el:e,styles:s}),Error("Something is wrong")})};export{O as Theme,h as createTheme,g as styled};
1
+ import b from"clsx";import n from"react";import{tv as O}from"tailwind-variants";const h=({children:e,theme:r})=>n.createElement("div",{className:"contents",style:r},e),w=e=>Object.fromEntries(Object.values(e).flatMap(r=>Object.entries(r).map(([o,c])=>["--".concat(o),c])));function M(e,r,o){const c=Object.keys(r.variants||{}),j=(o==null?void 0:o.enabledResponsiveVariants)===!0,E=O(r);return n.forwardRef((s,i)=>{const g=j?c.map(t=>{const a=s[t],m=r.variants[t];return typeof a=="object"&&a&&!Array.isArray(a)?Object.entries(a).flatMap(([f,p])=>{const N=String(p),u=m&&m[N];return u?u.flatMap(d=>f==="@initial"?d:"".concat(f.replace("@",""),":").concat(d)):[]}):[]}).flat():[],v=E(s),l=Object.fromEntries(Object.entries(s).filter(([t])=>!c.includes(t)&&t!=="as")),y=b(v,g).trim();if(typeof e=="string"||typeof e=="function"||e&&typeof e=="object"){const t=e;if(typeof e=="string")return n.createElement(s.as||t,{...l,ref:i,className:y});const a={...l,as:s.as,className:b(s.className,y).trim(),ref:i};return n.createElement(t,a)}if(n.isValidElement(e)){const t=e,a=t.props.className,m=l.className,f=b(a,m,y).trim(),p={...l,as:s.as||t.props.as,className:f};return i&&(p.ref=i),n.cloneElement(t,p)}throw console.log({el:e,styles:r}),Error("Something is wrong")})}export{h as Theme,w as createTheme,M as styled};
2
2
  //# sourceMappingURL=styled.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"styled.js","sources":["../src/styled.tsx"],"sourcesContent":["import clsx from 'clsx'\nimport React, { ElementType, ReactElement } from 'react'\nimport { tv } from 'tailwind-variants'\n\ntype Breakpoint = '@initial' | '@sm' | '@md' | '@lg' | '@xl'\n\nexport const Theme = ({\n children,\n theme\n}: React.PropsWithChildren<{ theme?: Record<string, string> }>) => (\n <div className=\"contents\" style={theme}>\n {children}\n </div>\n)\n\nexport const createTheme = (config: Record<string, Record<string, string>>) =>\n Object.fromEntries(\n Object.values(config).flatMap((tokens) =>\n Object.entries(tokens).map(([token, value]) => [`--${token}`, value])\n )\n )\n\n// ---------------------------------------------------------------------------\n// Local typing for styled()\n// ---------------------------------------------------------------------------\n\n// Responsive variant prop: either a single value or a per-breakpoint map\ntype ResponsiveVariant<V extends string | number | boolean> =\n | V\n | Partial<Record<Breakpoint, V>>\n\n// Helpers to derive value type from variant config keys\ntype Keys<V> = keyof V\ntype StringKeys<V> = Extract<Keys<V>, string>\ntype NumberKeys<V> = Extract<Keys<V>, number>\n// Booleans are represented as string keys \"true\"/\"false\" in our VariantConfig,\n// so we only need to detect those in StringKeys.\ntype BooleanKeys<V> = Extract<StringKeys<V>, 'true' | 'false'>\n\ntype HasBoolLikeKeys<V> =\n BooleanKeys<V> extends never\n ? Extract<StringKeys<V>, 'true' | 'false'> extends never\n ? false\n : true\n : true\n\n// If a variant's keys are boolean-like, expose the prop as boolean.\n// If it has numeric keys, allow those numbers and their string forms.\n// Otherwise use a string union of the keys.\ntype VariantValueType<V> =\n HasBoolLikeKeys<V> extends true\n ? boolean\n : [NumberKeys<V>] extends [never]\n ? StringKeys<V>\n : NumberKeys<V> | `${NumberKeys<V>}`\n\n// Shape of the `variants` section passed to styled()\ntype VariantConfig = Record<string, Record<string | number, string[]>>\n\n// Props derived from a `variants` config\ntype VariantProps<V extends VariantConfig | undefined> = V extends VariantConfig\n ? {\n [K in keyof V]?: ResponsiveVariant<VariantValueType<V[K]>>\n }\n : unknown\n\n// Typed config for our styled helper.\n// We intentionally *don't* rely on tailwind-variants' TS types here;\n// we only care about enough structure to derive props.\ntype StyledConfig<V extends VariantConfig | undefined = undefined> = {\n base?: string | string[]\n variants?: V\n compoundVariants?: Array<\n {\n class?: string | string[]\n } & (V extends VariantConfig\n ? {\n [K in keyof V]?: VariantValueType<V[K]> | VariantValueType<V[K]>[]\n }\n : Record<string, never>)\n >\n defaultVariants?: V extends VariantConfig\n ? { [K in keyof V]?: VariantValueType<V[K]> }\n : Record<string, never>\n}\n\nexport const styled = <\n TElement extends ElementType,\n V extends VariantConfig | undefined = undefined\n>(\n el: TElement,\n styles: StyledConfig<V>\n) => {\n const variantKeys = Object.keys(styles.variants || {})\n const tvFn = tv(styles as any, { twMerge: false })\n\n type VariantPropsType = VariantProps<V>\n type BaseProps = React.ComponentPropsWithRef<TElement>\n // Extract variant keys to omit from BaseProps so variant props override native HTML attributes\n type VariantKeys = V extends VariantConfig ? keyof V : never\n type StyledProps = Omit<BaseProps, VariantKeys> &\n VariantPropsType & { as?: ElementType }\n\n const Comp = React.forwardRef<React.ElementRef<TElement>, StyledProps>(\n (props, ref) => {\n const additionalStyles = variantKeys\n .map((variantKey) => {\n const responsiveVariantConfig:\n | Record<Breakpoint, string>\n | undefined = props[variantKey]\n const variantStyles: Record<string, string[]> =\n styles.variants![variantKey]\n\n if (\n typeof responsiveVariantConfig === 'object' &&\n responsiveVariantConfig\n ) {\n return Object.entries(responsiveVariantConfig).flatMap(\n ([key, val]: [Breakpoint, string]) => {\n const styleArr: string[] = variantStyles && variantStyles[val]\n\n if (styleArr) {\n return styleArr.flatMap((cls: string) => {\n if (key === '@initial') return cls\n return `${key.replace('@', '')}:${cls}`\n })\n }\n return []\n }\n )\n }\n\n return []\n })\n .flat()\n\n const cls = tvFn(props)\n\n const filteredProps = Object.fromEntries(\n Object.entries(props).filter(\n ([key]) => !variantKeys.includes(key) && key !== 'as'\n )\n )\n\n const mergedClassName = clsx(cls, additionalStyles).trim()\n\n if (\n typeof el === 'string' ||\n typeof el === 'function' ||\n (el && typeof el === 'object')\n ) {\n const elementType = el as ElementType\n\n // If el is a host string ('div', 'span', etc.) we must not pass variant props to the DOM.\n if (typeof el === 'string') {\n return React.createElement(props.as || elementType, {\n ...filteredProps,\n ref,\n className: mergedClassName\n })\n }\n\n // If el is a function component (including forwardRef), pass ALL props through\n // (the wrapped component may expect variant props), but ensure className and ref are forwarded.\n const propsForComponent = {\n ...filteredProps, // original props (includes variant keys)\n as: props.as,\n className: clsx((props as any).className, mergedClassName).trim(),\n ref\n }\n\n return React.createElement(elementType, propsForComponent)\n }\n\n if (React.isValidElement(el)) {\n const element = el as ReactElement\n // Merge existing element className, incoming filteredProps.className and our computed class\n const existingClass = (element.props as any).className\n const incomingClass = (filteredProps as any).className\n const finalClassName = clsx(\n existingClass,\n incomingClass,\n mergedClassName\n ).trim()\n\n const cloneProps: any = {\n // ...element.props,\n ...filteredProps,\n as: props.as || element.props.as,\n className: finalClassName\n }\n\n // Forward the ref if provided\n if (ref) {\n cloneProps.ref = ref\n }\n\n return React.cloneElement(element, cloneProps)\n }\n\n console.log({ el, styles })\n throw Error('Something is wrong')\n }\n )\n\n return Comp\n}\n"],"names":["Theme","children","theme","React","createTheme","config","tokens","token","value","styled","el","styles","variantKeys","tvFn","tv","props","ref","additionalStyles","variantKey","responsiveVariantConfig","variantStyles","key","val","styleArr","cls","filteredProps","mergedClassName","clsx","elementType","propsForComponent","element","existingClass","incomingClass","finalClassName","cloneProps"],"mappings":"sFAMaA,EAAQ,CAAC,CACpB,SAAAC,EACA,MAAAC,CACF,IACEC,EAAA,cAAC,MAAA,CAAI,UAAU,WAAW,MAAOD,CAC9BD,EAAAA,CACH,EAGWG,EAAeC,GAC1B,OAAO,YACL,OAAO,OAAOA,CAAM,EAAE,QAASC,GAC7B,OAAO,QAAQA,CAAM,EAAE,IAAI,CAAC,CAACC,EAAOC,CAAK,IAAM,CAAC,KAAK,OAAAD,CAASC,EAAAA,CAAK,CAAC,CACtE,CACF,EAkEWC,EAAS,CAIpBC,EACAC,IACG,CACH,MAAMC,EAAc,OAAO,KAAKD,EAAO,UAAY,CAAE,CAAA,EAC/CE,EAAOC,EAAGH,EAAe,CAAE,QAAS,EAAM,CAAC,EA+GjD,OAtGaR,EAAM,WACjB,CAACY,EAAOC,IAAQ,CACd,MAAMC,EAAmBL,EACtB,IAAKM,GAAe,CACnB,MAAMC,EAEUJ,EAAMG,CAAU,EAC1BE,EACJT,EAAO,SAAUO,CAAU,EAE7B,OACE,OAAOC,GAA4B,UACnCA,EAEO,OAAO,QAAQA,CAAuB,EAAE,QAC7C,CAAC,CAACE,EAAKC,CAAG,IAA4B,CACpC,MAAMC,EAAqBH,GAAiBA,EAAcE,CAAG,EAE7D,OAAIC,EACKA,EAAS,QAASC,GACnBH,IAAQ,WAAmBG,EACxB,GAAG,OAAAH,EAAI,QAAQ,IAAK,EAAE,EAAC,GAAA,EAAI,OAAAG,CACnC,CAAA,EAEI,CAAA,CACT,CACF,EAGK,CAAA,CACT,CAAC,EACA,KAAK,EAEFA,EAAMX,EAAKE,CAAK,EAEhBU,EAAgB,OAAO,YAC3B,OAAO,QAAQV,CAAK,EAAE,OACpB,CAAC,CAACM,CAAG,IAAM,CAACT,EAAY,SAASS,CAAG,GAAKA,IAAQ,IACnD,CACF,EAEMK,EAAkBC,EAAKH,EAAKP,CAAgB,EAAE,OAEpD,GACE,OAAOP,GAAO,UACd,OAAOA,GAAO,YACbA,GAAM,OAAOA,GAAO,SACrB,CACA,MAAMkB,EAAclB,EAGpB,GAAI,OAAOA,GAAO,SAChB,OAAOP,EAAM,cAAcY,EAAM,IAAMa,EAAa,CAClD,GAAGH,EACH,IAAAT,EACA,UAAWU,CACb,CAAC,EAKH,MAAMG,EAAoB,CACxB,GAAGJ,EACH,GAAIV,EAAM,GACV,UAAWY,EAAMZ,EAAc,UAAWW,CAAe,EAAE,KAC3D,EAAA,IAAAV,CACF,EAEA,OAAOb,EAAM,cAAcyB,EAAaC,CAAiB,CAC3D,CAEA,GAAI1B,EAAM,eAAeO,CAAE,EAAG,CAC5B,MAAMoB,EAAUpB,EAEVqB,EAAiBD,EAAQ,MAAc,UACvCE,EAAiBP,EAAsB,UACvCQ,EAAiBN,EACrBI,EACAC,EACAN,CACF,EAAE,KAAK,EAEDQ,EAAkB,CAEtB,GAAGT,EACH,GAAIV,EAAM,IAAMe,EAAQ,MAAM,GAC9B,UAAWG,CACb,EAGA,OAAIjB,IACFkB,EAAW,IAAMlB,GAGZb,EAAM,aAAa2B,EAASI,CAAU,CAC/C,CAEA,MAAQ,QAAA,IAAI,CAAE,GAAAxB,EAAI,OAAAC,CAAO,CAAC,EACpB,MAAM,oBAAoB,CAClC,CACF,CAGF"}
1
+ {"version":3,"file":"styled.js","sources":["../src/styled.tsx"],"sourcesContent":["import clsx from 'clsx'\nimport React, { ElementType, ReactElement } from 'react'\nimport { tv } from 'tailwind-variants'\n\ntype Breakpoint = '@initial' | '@sm' | '@md' | '@lg' | '@xl'\n\nexport const Theme = ({\n children,\n theme\n}: React.PropsWithChildren<{ theme?: Record<string, string> }>) => (\n <div className=\"contents\" style={theme}>\n {children}\n </div>\n)\n\nexport const createTheme = (config: Record<string, Record<string, string>>) =>\n Object.fromEntries(\n Object.values(config).flatMap((tokens) =>\n Object.entries(tokens).map(([token, value]) => [`--${token}`, value])\n )\n )\n\n// ---------------------------------------------------------------------------\n// Local typing for styled()\n// ---------------------------------------------------------------------------\n\n// Responsive variant prop: either a single value or a per-breakpoint map\n// Each breakpoint can have a different value from the union type V\ntype ResponsiveVariant<V extends string | number | boolean> =\n | V\n | Partial<Record<Breakpoint, V>>\n\n// Helpers to derive value type from variant config keys\ntype Keys<V> = keyof V\ntype StringKeys<V> = Extract<Keys<V>, string>\ntype NumberKeys<V> = Extract<Keys<V>, number>\n// Booleans are represented as string keys \"true\"/\"false\" in our VariantConfig,\n// so we only need to detect those in StringKeys.\ntype BooleanKeys<V> = Extract<StringKeys<V>, 'true' | 'false'>\n\ntype HasBoolLikeKeys<V> =\n BooleanKeys<V> extends never\n ? Extract<StringKeys<V>, 'true' | 'false'> extends never\n ? false\n : true\n : true\n\n// If a variant's keys are boolean-like, expose the prop as boolean.\n// If it has numeric keys, allow those numbers and their string forms.\n// Otherwise use a string union of the keys.\ntype VariantValueType<V> =\n HasBoolLikeKeys<V> extends true\n ? boolean\n : [NumberKeys<V>] extends [never]\n ? StringKeys<V>\n : NumberKeys<V> | `${NumberKeys<V>}`\n\n// Shape of the `variants` section passed to styled()\ntype VariantConfig = Record<string, Record<string | number, string[]>>\n\n// Options for styled() function\ntype StyledOptions = {\n enabledResponsiveVariants?: boolean\n}\n\n// Helper to check if responsive variants are enabled\ntype AreResponsiveVariantsEnabled<O> = O extends {\n enabledResponsiveVariants: true\n}\n ? true\n : false\n\n// Props derived from a `variants` config\n// If enabledResponsiveVariants is true, all variants support responsive values\n// If enabledResponsiveVariants is not provided or false, variants do not support responsive values\ntype VariantProps<\n V extends VariantConfig | undefined,\n R extends boolean = false\n> = V extends VariantConfig\n ? R extends true\n ? {\n [K in keyof V]?: ResponsiveVariant<VariantValueType<V[K]>>\n }\n : {\n [K in keyof V]?: VariantValueType<V[K]>\n }\n : unknown\n\n// Typed config for our styled helper.\n// We intentionally *don't* rely on tailwind-variants' TS types here;\n// we only care about enough structure to derive props.\ntype StyledConfig<V extends VariantConfig | undefined = undefined> = {\n base?: string | string[]\n variants?: V\n compoundVariants?: Array<\n {\n class?: string | string[]\n } & (V extends VariantConfig\n ? {\n [K in keyof V]?: VariantValueType<V[K]> | VariantValueType<V[K]>[]\n }\n : Record<string, never>)\n >\n defaultVariants?: V extends VariantConfig\n ? { [K in keyof V]?: VariantValueType<V[K]> }\n : Record<string, never>\n}\n\n// Function overloads for better type inference\nexport function styled<TElement extends ElementType, V extends VariantConfig>(\n el: TElement,\n styles: StyledConfig<V>,\n options: { enabledResponsiveVariants: true }\n): React.ForwardRefExoticComponent<\n Omit<React.ComponentPropsWithRef<TElement>, keyof V> &\n VariantProps<V, true> & { as?: ElementType }\n>\n\nexport function styled<\n TElement extends ElementType,\n V extends VariantConfig | undefined = undefined\n>(\n el: TElement,\n styles: StyledConfig<V>\n): React.ForwardRefExoticComponent<\n Omit<\n React.ComponentPropsWithRef<TElement>,\n V extends VariantConfig ? keyof V : never\n > &\n VariantProps<V, false> & { as?: ElementType }\n>\n\n// Implementation\nexport function styled<\n TElement extends ElementType,\n V extends VariantConfig | undefined = undefined,\n O extends StyledOptions | undefined = undefined\n>(el: TElement, styles: StyledConfig<V>, options?: O) {\n const variantKeys = Object.keys(styles.variants || {})\n const enabledResponsiveVariants = options?.enabledResponsiveVariants === true\n const tvFn = tv(styles as any)\n\n type ResponsiveVariantsEnabled = AreResponsiveVariantsEnabled<O>\n type VariantPropsType = VariantProps<V, ResponsiveVariantsEnabled>\n type BaseProps = React.ComponentPropsWithRef<TElement>\n // Extract variant keys to omit from BaseProps so variant props override native HTML attributes\n type VariantKeys = V extends VariantConfig ? keyof V : never\n type StyledProps = Omit<BaseProps, VariantKeys> &\n VariantPropsType & { as?: ElementType }\n\n const Comp = React.forwardRef<React.ElementRef<TElement>, StyledProps>(\n (props, ref) => {\n const additionalStyles = enabledResponsiveVariants\n ? variantKeys\n .map((variantKey) => {\n const responsiveVariantConfig:\n | Record<Breakpoint, string | number>\n | undefined = props[variantKey]\n const variantStyles: Record<string, string[]> =\n styles.variants![variantKey]\n\n if (\n typeof responsiveVariantConfig === 'object' &&\n responsiveVariantConfig &&\n !Array.isArray(responsiveVariantConfig)\n ) {\n return Object.entries(responsiveVariantConfig).flatMap(\n ([key, val]: [Breakpoint, string | number]) => {\n const valStr = String(val)\n const styleArr: string[] =\n variantStyles && variantStyles[valStr]\n\n if (styleArr) {\n return styleArr.flatMap((cls: string) => {\n if (key === '@initial') return cls\n return `${key.replace('@', '')}:${cls}`\n })\n }\n return []\n }\n )\n }\n\n return []\n })\n .flat()\n : []\n\n const cls = tvFn(props)\n\n const filteredProps = Object.fromEntries(\n Object.entries(props).filter(\n ([key]) => !variantKeys.includes(key) && key !== 'as'\n )\n )\n\n const mergedClassName = clsx(cls, additionalStyles).trim()\n\n if (\n typeof el === 'string' ||\n typeof el === 'function' ||\n (el && typeof el === 'object')\n ) {\n const elementType = el as ElementType\n\n // If el is a host string ('div', 'span', etc.) we must not pass variant props to the DOM.\n if (typeof el === 'string') {\n return React.createElement(props.as || elementType, {\n ...filteredProps,\n ref,\n className: mergedClassName\n })\n }\n\n // If el is a function component (including forwardRef), pass ALL props through\n // (the wrapped component may expect variant props), but ensure className and ref are forwarded.\n const propsForComponent = {\n ...filteredProps, // original props (includes variant keys)\n as: props.as,\n className: clsx((props as any).className, mergedClassName).trim(),\n ref\n }\n\n return React.createElement(elementType, propsForComponent)\n }\n\n if (React.isValidElement(el)) {\n const element = el as ReactElement\n // Merge existing element className, incoming filteredProps.className and our computed class\n const existingClass = (element.props as any).className\n const incomingClass = (filteredProps as any).className\n const finalClassName = clsx(\n existingClass,\n incomingClass,\n mergedClassName\n ).trim()\n\n const cloneProps: any = {\n // ...element.props,\n ...filteredProps,\n as: props.as || element.props.as,\n className: finalClassName\n }\n\n // Forward the ref if provided\n if (ref) {\n cloneProps.ref = ref\n }\n\n return React.cloneElement(element, cloneProps)\n }\n\n console.log({ el, styles })\n throw Error('Something is wrong')\n }\n )\n\n return Comp\n}\n"],"names":["Theme","children","theme","React","createTheme","config","tokens","token","value","styled","el","styles","options","variantKeys","enabledResponsiveVariants","tvFn","tv","props","ref","additionalStyles","variantKey","responsiveVariantConfig","variantStyles","key","val","valStr","styleArr","cls","filteredProps","mergedClassName","clsx","elementType","propsForComponent","element","existingClass","incomingClass","finalClassName","cloneProps"],"mappings":"gFAMO,MAAMA,EAAQ,CAAC,CACpB,SAAAC,EACA,MAAAC,CACF,IACEC,EAAA,cAAC,OAAI,UAAU,WAAW,MAAOD,CAAAA,EAC9BD,CACH,EAGWG,EAAeC,GAC1B,OAAO,YACL,OAAO,OAAOA,CAAM,EAAE,QAASC,GAC7B,OAAO,QAAQA,CAAM,EAAE,IAAI,CAAC,CAACC,EAAOC,CAAK,IAAM,CAAC,KAAK,OAAAD,GAASC,CAAK,CAAC,CACtE,CACF,EAiHc,SAAAC,EAIdC,EAAcC,EAAyBC,EAAa,CACpD,MAAMC,EAAc,OAAO,KAAKF,EAAO,UAAY,CAAA,CAAE,EAC/CG,GAA4BF,GAAA,YAAAA,EAAS,6BAA8B,GACnEG,EAAOC,EAAGL,CAAa,EAqH7B,OA3GaR,EAAM,WACjB,CAACc,EAAOC,IAAQ,CACd,MAAMC,EAAmBL,EACrBD,EACG,IAAKO,GAAe,CACnB,MAAMC,EAEUJ,EAAMG,CAAU,EAC1BE,EACJX,EAAO,SAAUS,CAAU,EAE7B,OACE,OAAOC,GAA4B,UACnCA,GACA,CAAC,MAAM,QAAQA,CAAuB,EAE/B,OAAO,QAAQA,CAAuB,EAAE,QAC7C,CAAC,CAACE,EAAKC,CAAG,IAAqC,CAC7C,MAAMC,EAAS,OAAOD,CAAG,EACnBE,EACJJ,GAAiBA,EAAcG,CAAM,EAEvC,OAAIC,EACKA,EAAS,QAASC,GACnBJ,IAAQ,WAAmBI,EACxB,GAAG,OAAAJ,EAAI,QAAQ,IAAK,EAAE,EAAC,KAAI,OAAAI,CAAAA,CACnC,EAEI,CAAA,CACT,CACF,EAGK,CACT,CAAA,CAAC,EACA,KAAK,EACR,CAAA,EAEEA,EAAMZ,EAAKE,CAAK,EAEhBW,EAAgB,OAAO,YAC3B,OAAO,QAAQX,CAAK,EAAE,OACpB,CAAC,CAACM,CAAG,IAAM,CAACV,EAAY,SAASU,CAAG,GAAKA,IAAQ,IACnD,CACF,EAEMM,EAAkBC,EAAKH,EAAKR,CAAgB,EAAE,OAEpD,GACE,OAAOT,GAAO,UACd,OAAOA,GAAO,YACbA,GAAM,OAAOA,GAAO,SACrB,CACA,MAAMqB,EAAcrB,EAGpB,GAAI,OAAOA,GAAO,SAChB,OAAOP,EAAM,cAAcc,EAAM,IAAMc,EAAa,CAClD,GAAGH,EACH,IAAAV,EACA,UAAWW,CACb,CAAC,EAKH,MAAMG,EAAoB,CACxB,GAAGJ,EACH,GAAIX,EAAM,GACV,UAAWa,EAAMb,EAAc,UAAWY,CAAe,EAAE,OAC3D,IAAAX,CACF,EAEA,OAAOf,EAAM,cAAc4B,EAAaC,CAAiB,CAC3D,CAEA,GAAI7B,EAAM,eAAeO,CAAE,EAAG,CAC5B,MAAMuB,EAAUvB,EAEVwB,EAAiBD,EAAQ,MAAc,UACvCE,EAAiBP,EAAsB,UACvCQ,EAAiBN,EACrBI,EACAC,EACAN,CACF,EAAE,KAAK,EAEDQ,EAAkB,CAEtB,GAAGT,EACH,GAAIX,EAAM,IAAMgB,EAAQ,MAAM,GAC9B,UAAWG,CACb,EAGA,OAAIlB,IACFmB,EAAW,IAAMnB,GAGZf,EAAM,aAAa8B,EAASI,CAAU,CAC/C,CAEA,MAAA,QAAQ,IAAI,CAAE,GAAA3B,EAAI,OAAAC,CAAO,CAAC,EACpB,MAAM,oBAAoB,CAClC,CACF,CAGF"}
@@ -1,5 +1,5 @@
1
- export declare const NoOverflowWrapper: import("react").ForwardRefExoticComponent<Omit<Omit<Omit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref"> & {
1
+ export declare const NoOverflowWrapper: import("react").ForwardRefExoticComponent<Omit<Omit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref"> & {
2
2
  ref?: ((instance: HTMLDivElement | null) => void) | import("react").RefObject<HTMLDivElement> | null | undefined;
3
3
  }, never> & {
4
4
  as?: import("react").ElementType;
5
- }, "ref"> & import("react").RefAttributes<HTMLDivElement>>;
5
+ }>;
package/package.json CHANGED
@@ -4,20 +4,25 @@
4
4
  "main": "dist/index.cjs.js",
5
5
  "typings": "dist/index.d.ts",
6
6
  "module": "dist/index.js",
7
- "version": "6.0.0-beta.11",
7
+ "version": "6.0.0-beta.13",
8
8
  "description": "",
9
9
  "files": [
10
10
  "dist",
11
- "src/index.css"
11
+ "src/index.css",
12
+ "src/responsive-variant-classes.css",
13
+ "scripts/vite-plugin-tailwind-responsive-variant-classes.mjs",
14
+ "scripts/generate-responsive-variant-classes.mjs"
12
15
  ],
13
16
  "exports": {
14
17
  ".": {
15
18
  "types": "./dist/index.d.ts",
16
19
  "import": "./dist/index.js",
20
+ "style": "./src/index.css",
17
21
  "require": "./dist/index.cjs.js",
18
22
  "default": "./dist/index.js"
19
23
  },
20
- "./index.css": "./src/index.css"
24
+ "./index.css": "./src/index.css",
25
+ "./vite": "./scripts/vite-plugin-tailwind-responsive-variant-classes.mjs"
21
26
  },
22
27
  "sideEffects": false,
23
28
  "scripts": {
@@ -25,9 +30,10 @@
25
30
  "build:lib": "NODE_ENV=production rollup -c",
26
31
  "build:types": "NODE_ENV=production tsc --project tsconfig.build.json --emitDeclarationOnly && tsc-alias",
27
32
  "build:proptypes": "node ./scripts/generate-component-props.mjs",
33
+ "build:responsive-variant-classes": "node ./scripts/generate-responsive-variant-classes.mjs",
28
34
  "start:sandbox": "vite -c ./sandbox/vite.config.js",
29
35
  "add-component": "node ./scripts/add-component.mjs",
30
- "prepublishOnly": "run-s clean build:lib build:types build:proptypes",
36
+ "prepublishOnly": "run-s clean build:responsive-variant-classes build:lib build:types build:proptypes",
31
37
  "clean": "del ./dist/",
32
38
  "format": "prettier 'src/**/*.{js,ts,tsx}' --write",
33
39
  "lint": "eslint 'src/**/*.{js,ts,tsx}' --fix",
@@ -69,7 +75,7 @@
69
75
  ],
70
76
  "devDependencies": {
71
77
  "@atom-learning/icons": "1.20.0",
72
- "@atom-learning/theme": "6.0.0-beta.1",
78
+ "@atom-learning/theme": "6.0.0-beta.3",
73
79
  "@commitlint/cli": "^11.0.0",
74
80
  "@commitlint/config-conventional": "^11.0.0",
75
81
  "@ianvs/prettier-plugin-sort-imports": "^4.7.0",
@@ -111,7 +117,6 @@
111
117
  "eslint-plugin-react": "^7.22.0",
112
118
  "eslint-plugin-react-hooks": "^4.2.0",
113
119
  "eslint-plugin-simple-import-sort": "^7.0.0",
114
- "glob": "^7.1.6",
115
120
  "husky": "^4.3.8",
116
121
  "jest": "^27.0.6",
117
122
  "jest-axe": "^4.1.0",
@@ -174,10 +179,12 @@
174
179
  "dayjs": "^1.10.7",
175
180
  "dayzed": "^3.2.2",
176
181
  "dlv": "^1.1.3",
182
+ "glob": "^7.1.6",
177
183
  "invariant": "^2.2.4",
178
184
  "mdast-util-directive": "1.0.1",
179
185
  "mdast-util-from-markdown": "0.8.5",
180
186
  "micromark-extension-directive": "1.4.0",
187
+ "minimatch": "^10.0.0",
181
188
  "prop-types": "^15.8.1",
182
189
  "pure-react-carousel": "^1.27.6",
183
190
  "react-aria": "^3.29.1",
@@ -189,6 +196,7 @@
189
196
  "tailwind-variants": "^3.2.2",
190
197
  "tailwindcss": "^4.1.17",
191
198
  "throttle-debounce": "^3.0.1",
199
+ "ts-morph": "^25.0.1",
192
200
  "uid": "^2.0.0",
193
201
  "use-deep-compare-effect": "^1.8.1"
194
202
  },
@@ -0,0 +1,300 @@
1
+ import fs from 'node:fs'
2
+ import path from 'node:path'
3
+ import { fileURLToPath } from 'node:url'
4
+ import g from 'glob'
5
+ import { Project, SyntaxKind } from 'ts-morph'
6
+
7
+ const { glob } = g
8
+
9
+ function extractArrayElements(node) {
10
+ if (node.getKind() !== SyntaxKind.ArrayLiteralExpression) return []
11
+
12
+ return node
13
+ .getElements()
14
+ .map((element) =>
15
+ element.getKind() === SyntaxKind.StringLiteral
16
+ ? element.getLiteralValue()
17
+ : element.getText().replace(/^['"]|['"]$/g, '')
18
+ )
19
+ .filter(Boolean)
20
+ }
21
+
22
+ function getPropertyValue(obj, propName) {
23
+ const prop = obj
24
+ .getProperties()
25
+ .find(
26
+ (p) =>
27
+ p.getKind() === SyntaxKind.PropertyAssignment &&
28
+ p
29
+ .asKindOrThrow(SyntaxKind.PropertyAssignment)
30
+ .getNameNode()
31
+ .getText()
32
+ .replace(/['"]/g, '') === propName
33
+ )
34
+ return prop?.asKindOrThrow(SyntaxKind.PropertyAssignment).getInitializer()
35
+ }
36
+
37
+ function isEnabledResponsiveVariants(args) {
38
+ if (args.length < 3) return false
39
+ const optionsArg = args[2]
40
+ if (optionsArg.getKind() !== SyntaxKind.ObjectLiteralExpression) return false
41
+
42
+ const enabledProp = getPropertyValue(
43
+ optionsArg.asKindOrThrow(SyntaxKind.ObjectLiteralExpression),
44
+ 'enabledResponsiveVariants'
45
+ )
46
+ return enabledProp?.getKind() === SyntaxKind.TrueKeyword
47
+ }
48
+
49
+ function extractClasses(optionValue) {
50
+ if (optionValue.getKind() === SyntaxKind.ArrayLiteralExpression) {
51
+ return extractArrayElements(optionValue)
52
+ }
53
+ if (optionValue.getKind() === SyntaxKind.StringLiteral) {
54
+ return [optionValue.getLiteralValue()]
55
+ }
56
+ return []
57
+ }
58
+
59
+ function extractVariantsFromAST(sourceFile) {
60
+ const variants = {}
61
+
62
+ for (const call of sourceFile.getDescendantsOfKind(
63
+ SyntaxKind.CallExpression
64
+ )) {
65
+ if (call.getExpression().getText() !== 'styled') continue
66
+
67
+ const args = call.getArguments()
68
+ if (args.length < 2) continue
69
+
70
+ const configArg = args[1]
71
+ if (configArg.getKind() !== SyntaxKind.ObjectLiteralExpression) continue
72
+
73
+ if (!isEnabledResponsiveVariants(args)) continue
74
+
75
+ const configObj = configArg.asKindOrThrow(
76
+ SyntaxKind.ObjectLiteralExpression
77
+ )
78
+ const variantsValue = getPropertyValue(configObj, 'variants')
79
+
80
+ if (
81
+ !variantsValue ||
82
+ variantsValue.getKind() !== SyntaxKind.ObjectLiteralExpression
83
+ ) {
84
+ continue
85
+ }
86
+
87
+ const variantsObj = variantsValue.asKindOrThrow(
88
+ SyntaxKind.ObjectLiteralExpression
89
+ )
90
+
91
+ for (const variantProp of variantsObj.getProperties()) {
92
+ if (variantProp.getKind() !== SyntaxKind.PropertyAssignment) continue
93
+
94
+ const variant = variantProp.asKindOrThrow(SyntaxKind.PropertyAssignment)
95
+ const variantKey = variant.getNameNode().getText().replace(/['"]/g, '')
96
+ const variantValue = variant.getInitializer()
97
+
98
+ if (
99
+ !variantValue ||
100
+ variantValue.getKind() !== SyntaxKind.ObjectLiteralExpression
101
+ ) {
102
+ continue
103
+ }
104
+
105
+ const variantOptionsObj = variantValue.asKindOrThrow(
106
+ SyntaxKind.ObjectLiteralExpression
107
+ )
108
+ const options = {}
109
+
110
+ for (const optionProp of variantOptionsObj.getProperties()) {
111
+ if (optionProp.getKind() !== SyntaxKind.PropertyAssignment) continue
112
+
113
+ const option = optionProp.asKindOrThrow(SyntaxKind.PropertyAssignment)
114
+ const optionKey = option.getNameNode().getText().replace(/['"]/g, '')
115
+ const optionValue = option.getInitializer()
116
+
117
+ if (!optionValue) continue
118
+
119
+ const classes = extractClasses(optionValue)
120
+ if (classes.length > 0) {
121
+ options[optionKey] = classes
122
+ }
123
+ }
124
+
125
+ if (Object.keys(options).length > 0) {
126
+ variants[variantKey] = options
127
+ }
128
+ }
129
+ }
130
+
131
+ return Object.keys(variants).length > 0 ? variants : null
132
+ }
133
+
134
+ function generateResponsiveVariantClasses(variants) {
135
+ const breakpoints = ['sm', 'md', 'lg', 'xl']
136
+ const classes = new Set()
137
+
138
+ for (const variantOptions of Object.values(variants)) {
139
+ for (const classList of Object.values(variantOptions)) {
140
+ if (Array.isArray(classList)) {
141
+ for (const cls of classList) {
142
+ const trimmed = typeof cls === 'string' ? cls.trim() : ''
143
+ if (trimmed) {
144
+ classes.add(trimmed)
145
+ for (const bp of breakpoints) {
146
+ classes.add(`${bp}:${trimmed}`)
147
+ }
148
+ }
149
+ }
150
+ }
151
+ }
152
+ }
153
+
154
+ return Array.from(classes).sort()
155
+ }
156
+
157
+ function extractUniqueClasses(allClasses) {
158
+ const uniqueClasses = new Set()
159
+
160
+ for (const cls of allClasses) {
161
+ const match = cls.match(/^(sm|md|lg|xl):(.+)$/)
162
+ uniqueClasses.add(match ? match[2] : cls)
163
+ }
164
+
165
+ return Array.from(uniqueClasses).sort()
166
+ }
167
+
168
+ /**
169
+ * Generate CSS file content with @source inline() patterns
170
+ */
171
+ function generateCSSFileContent(allClasses) {
172
+ const uniqueClasses = extractUniqueClasses(allClasses)
173
+ const breakpointPrefix = `{,sm:,md:,lg:,xl:}`
174
+ const classPattern = `{${uniqueClasses.join(',')}}`
175
+ const pattern = `@source inline("${breakpointPrefix}${classPattern}");`
176
+
177
+ return `/**
178
+ * Tailwind Responsive Variant Classes Safelist (CSS Format)
179
+ *
180
+ * ⚠️ AUTO-GENERATED FILE - DO NOT EDIT MANUALLY ⚠️
181
+ *
182
+ * This file is automatically generated by the build script: scripts/generate-responsive-variant-classes.mjs
183
+ * Run \`yarn build:responsive-variant-classes\` to regenerate this file.
184
+ *
185
+ * This file ensures Tailwind includes dynamically generated responsive classes
186
+ * when using responsive variants like: gap={{ '@initial': 1, '@sm': 3 }}
187
+ *
188
+ * Uses Tailwind v4's @source inline() pattern syntax for efficient class detection.
189
+ */
190
+
191
+ ${pattern}
192
+ `
193
+ }
194
+
195
+ /**
196
+ * Main function to generate responsive variant classes safelist
197
+ *
198
+ * @param {Object} options - Generation options
199
+ * @param {string} [options.cwd] - Working directory
200
+ * @param {string|string[]} [options.input] - Input glob pattern(s). Can be a string or array of strings
201
+ * @param {string} [options.outputPath] - Output file path relative to cwd
202
+ */
203
+ async function generateResponsiveVariantClassesSafelist(options = {}) {
204
+ const {
205
+ cwd = process.cwd(),
206
+ input = 'src/**/*.{ts,tsx}',
207
+ outputPath = 'src/responsive-variant-classes.css'
208
+ } = options
209
+ try {
210
+ console.log('🔍 Scanning component files for styled() variants...\n')
211
+
212
+ const project = new Project({
213
+ tsConfigFilePath: path.resolve(cwd, 'tsconfig.json'),
214
+ skipAddingFilesFromTsConfig: true
215
+ })
216
+
217
+ const patterns = Array.isArray(input) ? input : [input]
218
+ const ignorePatterns = [
219
+ '**/*.test.tsx',
220
+ '**/*.test.ts',
221
+ '**/__snapshots__/**',
222
+ '**/node_modules/**',
223
+ '**/responsive-variant-classes.css'
224
+ ]
225
+
226
+ const files = new Set()
227
+ for (const pattern of patterns) {
228
+ const matches = glob.sync(pattern, { cwd, ignore: ignorePatterns })
229
+ matches.forEach((file) => files.add(file))
230
+ }
231
+
232
+ const fileArray = Array.from(files)
233
+ console.log(`Found ${fileArray.length} component files to scan\n`)
234
+
235
+ const allVariants = {}
236
+ let processedFiles = 0
237
+
238
+ for (const filePath of fileArray) {
239
+ try {
240
+ const fullPath = path.isAbsolute(filePath)
241
+ ? filePath
242
+ : path.resolve(cwd, filePath)
243
+
244
+ if (!fs.readFileSync(fullPath, 'utf-8').includes('styled(')) continue
245
+
246
+ const sourceFile = project.addSourceFileAtPath(fullPath)
247
+ const variants = extractVariantsFromAST(sourceFile)
248
+
249
+ if (variants) {
250
+ console.log(` ✓ ${path.relative(cwd, fullPath)}`)
251
+ for (const [key, value] of Object.entries(variants)) {
252
+ allVariants[key] = allVariants[key]
253
+ ? { ...allVariants[key], ...value }
254
+ : value
255
+ }
256
+ processedFiles++
257
+ }
258
+ } catch (error) {
259
+ console.warn(` ⚠️ Error processing ${filePath}:`, error.message)
260
+ }
261
+ }
262
+
263
+ if (Object.keys(allVariants).length === 0) {
264
+ console.log('\n⚠️ No variants found in component files')
265
+ return
266
+ }
267
+
268
+ console.log(`\n📦 Extracted variants from ${processedFiles} files`)
269
+ console.log(
270
+ ` Found ${Object.keys(allVariants).length} unique variant keys\n`
271
+ )
272
+
273
+ // Generate all responsive classes
274
+ const allClasses = generateResponsiveVariantClasses(allVariants)
275
+
276
+ console.log(
277
+ `✨ Generated ${allClasses.length} responsive variant class combinations\n`
278
+ )
279
+
280
+ // Generate and write the CSS file
281
+ const cssContent = generateCSSFileContent(allClasses)
282
+ const cssOutputPath = path.resolve(cwd, outputPath)
283
+ fs.writeFileSync(cssOutputPath, cssContent, 'utf-8')
284
+
285
+ console.log(`✅ Generated ${path.relative(cwd, cssOutputPath)}`)
286
+ console.log(` Contains ${allClasses.length} variant class combinations\n`)
287
+ } catch (error) {
288
+ console.error('❌ Error generating responsive variant classes:', error)
289
+ process.exit(1)
290
+ }
291
+ }
292
+
293
+ // Export the function for use in other modules
294
+ export { generateResponsiveVariantClassesSafelist }
295
+
296
+ // Run the script if this file is executed directly (not imported)
297
+ const __filename = fileURLToPath(import.meta.url)
298
+ if (process.argv[1] === __filename) {
299
+ generateResponsiveVariantClassesSafelist()
300
+ }
@@ -0,0 +1,92 @@
1
+ import path from 'path'
2
+ import { minimatch } from 'minimatch'
3
+
4
+ import { generateResponsiveVariantClassesSafelist } from './generate-responsive-variant-classes.mjs'
5
+
6
+ /**
7
+ * Vite plugin to automatically generate responsive classes safelist
8
+ *
9
+ * @param {Object} options - Plugin options
10
+ * @param {string[]} [options.files] - Glob patterns to watch for changes. Defaults to ['src/components/**', 'sandbox/**']
11
+ */
12
+ export function tailwindResponsiveVariantClasses(options = {}) {
13
+ const {
14
+ input = 'src/**/*.{ts,tsx}',
15
+ cwd = process.cwd(),
16
+ outputPath = 'src/responsive-variant-classes.css'
17
+ } = options
18
+ let isGenerating = false
19
+ let generateTimeout = null
20
+
21
+ const matchesPattern = (filePath) => {
22
+ const relativePath = path.relative(cwd, filePath).replace(/\\/g, '/')
23
+ return minimatch(relativePath, input)
24
+ }
25
+
26
+ async function generateResponsiveClasses() {
27
+ if (isGenerating) return Promise.resolve()
28
+
29
+ isGenerating = true
30
+
31
+ try {
32
+ await generateResponsiveVariantClassesSafelist({
33
+ cwd,
34
+ input,
35
+ outputPath
36
+ })
37
+ console.log('[responsive-classes] ✓ Generated responsive variant classes')
38
+ } catch (error) {
39
+ console.error(
40
+ '[responsive-classes] Error generating classes:',
41
+ error.message
42
+ )
43
+ throw error
44
+ } finally {
45
+ isGenerating = false
46
+ }
47
+ }
48
+
49
+ function debouncedGenerate() {
50
+ if (generateTimeout) clearTimeout(generateTimeout)
51
+ generateTimeout = setTimeout(() => {
52
+ generateResponsiveClasses().catch((error) => {
53
+ console.warn('[responsive-classes] Generation failed:', error.message)
54
+ })
55
+ }, 500)
56
+ }
57
+
58
+ return {
59
+ name: 'vite-plugin-responsive-classes',
60
+ enforce: 'pre',
61
+
62
+ async configResolved() {
63
+ try {
64
+ await generateResponsiveClasses()
65
+ } catch (error) {
66
+ console.warn(
67
+ '[responsive-classes] Initial generation failed:',
68
+ error.message
69
+ )
70
+ }
71
+ },
72
+
73
+ configureServer(server) {
74
+ const handleFileChange = (file) => {
75
+ if (matchesPattern(file)) {
76
+ debouncedGenerate()
77
+ }
78
+ }
79
+
80
+ server.watcher.on('change', handleFileChange)
81
+ server.watcher.on('add', handleFileChange)
82
+ server.watcher.on('unlink', handleFileChange)
83
+ },
84
+
85
+ handleHotUpdate({ file }) {
86
+ if (matchesPattern(file)) {
87
+ debouncedGenerate()
88
+ return []
89
+ }
90
+ }
91
+ }
92
+ }
package/src/index.css CHANGED
@@ -1,8 +1,5 @@
1
1
  @import 'tailwindcss';
2
-
3
- @import '@atom-learning/theme/lib/theme-atom.css';
4
-
5
- @source '../src/';
2
+ @import './responsive-variant-classes.css';
6
3
 
7
4
  @theme {
8
5
  --default-font-family: var(--font-body);
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Tailwind Responsive Variant Classes Safelist (CSS Format)
3
+ *
4
+ * ⚠️ AUTO-GENERATED FILE - DO NOT EDIT MANUALLY ⚠️
5
+ *
6
+ * This file is automatically generated by the build script: scripts/generate-responsive-variant-classes.mjs
7
+ * Run `yarn build:responsive-variant-classes` to regenerate this file.
8
+ *
9
+ * This file ensures Tailwind includes dynamically generated responsive classes
10
+ * when using responsive variants like: gap={{ '@initial': 1, '@sm': 3 }}
11
+ *
12
+ * Uses Tailwind v4's @source inline() pattern syntax for efficient class detection.
13
+ */
14
+
15
+ @source inline("{,sm:,md:,lg:,xl:}{[--active:rgba(white,0.25)],[--active:var(--color-danger-dark)],[--active:var(--color-primary-1000)],[--active:var(--color-primary-1200)],[--active:var(--color-success-dark)],[--active:var(--color-warning-dark)],[--active:var(--color-white)],[--banner-heading-color:var(--color-foreground-7-plus)],[--banner-text-color:var(--color-grey-100)],[--base:var(--color-danger)],[--base:var(--color-primary-1000)],[--base:var(--color-primary-800)],[--base:var(--color-success)],[--base:var(--color-warning)],[--base:var(--color-white)],[--base:white],[--interact:rgba(white,0.1)],[--interact:var(--color-danger-mid)],[--interact:var(--color-primary-1100)],[--interact:var(--color-primary-900)],[--interact:var(--color-success-mid)],[--interact:var(--color-warning-mid)],[--interact:var(--color-white)],[--text:var(--color-primary-800)],[align-items:first baseline],[align-items:inherit],[align-items:initial],[align-items:last baseline],[align-items:normal],[align-items:revert-layer],[align-items:revert],[align-items:safe],[align-items:self-end],[align-items:self-start],[align-items:unsafe],[align-items:unset],[flex-wrap:inherit],[flex-wrap:initial],[flex-wrap:revert-layer],[flex-wrap:revert],[flex-wrap:unset],[justify-content:inherit],[justify-content:initial],[justify-content:left],[justify-content:revert-layer],[justify-content:revert],[justify-content:right],[justify-content:safe],[justify-content:unsafe],[justify-content:unset],absolute,after:hidden!,before:hidden!,bg-(--base),bg-(--base-1),bg-(--base-11),bg-(--base-3),bg-transparent,border,border-b,border-b-(--border-bottom),border-current,border-white,capsize-[0.2078],capsize-[0.3864],capsize-after-[0.26],capsize-after-[0.2],capsize-before-[0.16],capsize-before-[0.1],cursor-not-allowed opacity-60 pointer-events-none,direction-[inherit],direction-[initial],direction-[revert-layer],direction-[revert],direction-[unset],disabled:cursor-not-allowed,disabled:opacity-30,flex-col,flex-col-reverse,flex-no-wrap,flex-row,flex-row-reverse,flex-wrap,flex-wrap-reverse,font-body,font-display,font-medium,font-mono,font-normal,font-semibold,gap-0.5,gap-1,gap-10,gap-12,gap-16,gap-2,gap-20,gap-3,gap-4,gap-6,gap-8,h-16,h-24,items-baseline,items-center,items-end,items-start,items-stretch,justify-around,justify-between,justify-center,justify-end,justify-evenly,justify-normal,justify-start,justify-stretch,leading-[1.12],leading-[1.14],leading-none,leading-normal,max-w-full,not-disabled:active:bg-(--active),not-disabled:active:text-(--active),not-disabled:focus:bg-(--interact),not-disabled:focus:no-underline,not-disabled:focus:text-(--interact),not-disabled:focus:text-(--text,white),not-disabled:hover:bg-(--interact),not-disabled:hover:no-underline,not-disabled:hover:text-(--interact),not-disabled:hover:text-(--text,white),p-2,px-6,right-4,rounded-full,shadow-[0px_4px_4px_-2px_rgba(31,31,31,0.1)],static,supports-color-mix:backdrop-blur-sm,supports-color-mix:bg-[color-mix(in_hsl,(--base-1)_70%,transparent)],text-(--base),text-(--foreground-7-plus),text-(--text,white),text-3xl,text-4xl,text-lg,text-md,top-0,top-2,top-4,w-full,w-max,w-screen}");