@cube-dev/ui-kit 0.0.0-canary-63be1e5 → 0.0.0-canary-dec6fb1

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 (568) hide show
  1. package/es/_internal/hooks/index.js +1 -1
  2. package/es/_internal/hooks/use-chained-callback.js +1 -1
  3. package/es/_internal/hooks/use-debounced-value.js +1 -1
  4. package/es/_internal/hooks/use-deprecation-warning.js +1 -1
  5. package/es/_internal/hooks/use-effect-once.js +1 -1
  6. package/es/_internal/hooks/use-event.js +1 -1
  7. package/es/_internal/hooks/use-is-first-render.js +1 -1
  8. package/es/_internal/hooks/use-sync-ref.js +1 -1
  9. package/es/_internal/hooks/use-timer/index.js +1 -1
  10. package/es/_internal/hooks/use-timer/timer.js +1 -1
  11. package/es/_internal/hooks/use-timer/use-timer.js +1 -1
  12. package/es/_internal/hooks/use-update-effect.js +1 -1
  13. package/es/_internal/hooks/use-warn.js +1 -1
  14. package/es/_internal/index.js +1 -1
  15. package/es/components/Block.js +1 -1
  16. package/es/components/CollectionItem.js +1 -1
  17. package/es/components/GlobalStyles.js +1 -1
  18. package/es/components/GridProvider.js +1 -1
  19. package/es/components/HiddenInput.js +1 -1
  20. package/es/components/OpenTrasition.js +1 -1
  21. package/es/components/Root.js +1 -1
  22. package/es/components/actions/Action/Action.js +1 -1
  23. package/es/components/actions/Button/Button.js +1 -1
  24. package/es/components/actions/Button/index.js +1 -1
  25. package/es/components/actions/ButtonGroup/ButtonGroup.js +1 -1
  26. package/es/components/actions/CommandMenu/CommandMenu.js +1 -1
  27. package/es/components/actions/CommandMenu/index.js +1 -1
  28. package/es/components/actions/CommandMenu/styled.js +1 -1
  29. package/es/components/actions/ItemAction/ItemAction.js +1 -1
  30. package/es/components/actions/ItemAction/index.js +1 -1
  31. package/es/components/actions/ItemActionContext.js +1 -1
  32. package/es/components/actions/ItemButton/ItemButton.js +1 -1
  33. package/es/components/actions/ItemButton/index.js +1 -1
  34. package/es/components/actions/Link/Link.js +1 -1
  35. package/es/components/actions/Menu/Menu.js +1 -1
  36. package/es/components/actions/Menu/MenuItem.js +1 -1
  37. package/es/components/actions/Menu/MenuSection.js +1 -1
  38. package/es/components/actions/Menu/MenuTrigger.js +1 -1
  39. package/es/components/actions/Menu/SubMenuTrigger.js +1 -1
  40. package/es/components/actions/Menu/SubmenuTriggerContext.js +1 -1
  41. package/es/components/actions/Menu/context.js +1 -1
  42. package/es/components/actions/Menu/index.js +1 -1
  43. package/es/components/actions/Menu/styled.js +1 -1
  44. package/es/components/actions/index.js +1 -1
  45. package/es/components/actions/use-action.js +1 -1
  46. package/es/components/actions/use-anchored-menu.js +1 -1
  47. package/es/components/actions/use-context-menu.js +1 -1
  48. package/es/components/content/ActiveZone/ActiveZone.js +1 -1
  49. package/es/components/content/Alert/Alert.js +1 -1
  50. package/es/components/content/Alert/index.js +1 -1
  51. package/es/components/content/Alert/types.js +1 -1
  52. package/es/components/content/Alert/use-alert.js +1 -1
  53. package/es/components/content/Avatar/Avatar.js +1 -1
  54. package/es/components/content/Badge/Badge.js +1 -1
  55. package/es/components/content/Card/Card.js +1 -1
  56. package/es/components/content/Content.js +1 -1
  57. package/es/components/content/CopyPasteBlock/CopyPasteBlock.js +1 -1
  58. package/es/components/content/CopyPasteBlock/index.js +1 -1
  59. package/es/components/content/CopySnippet/CopySnippet.js +1 -1
  60. package/es/components/content/CopySnippet/index.js +1 -1
  61. package/es/components/content/Disclosure/Disclosure.js +1 -1
  62. package/es/components/content/Disclosure/index.js +1 -1
  63. package/es/components/content/Divider.js +1 -1
  64. package/es/components/content/Footer.js +1 -1
  65. package/es/components/content/Header.js +1 -1
  66. package/es/components/content/HotKeys/HotKeys.js +1 -1
  67. package/es/components/content/HotKeys/index.js +1 -1
  68. package/es/components/content/Item/Item.js +1 -1
  69. package/es/components/content/Item/index.js +1 -1
  70. package/es/components/content/ItemBadge/ItemBadge.js +1 -1
  71. package/es/components/content/ItemBadge/index.js +1 -1
  72. package/es/components/content/Layout/GridLayout.js +1 -1
  73. package/es/components/content/Layout/Layout.js +1 -1
  74. package/es/components/content/Layout/LayoutBlock.js +1 -1
  75. package/es/components/content/Layout/LayoutCenter.js +1 -1
  76. package/es/components/content/Layout/LayoutContainer.js +1 -1
  77. package/es/components/content/Layout/LayoutContent.js +1 -1
  78. package/es/components/content/Layout/LayoutContext.js +1 -1
  79. package/es/components/content/Layout/LayoutFlex.js +1 -1
  80. package/es/components/content/Layout/LayoutFooter.js +1 -1
  81. package/es/components/content/Layout/LayoutGrid.js +1 -1
  82. package/es/components/content/Layout/LayoutHeader.js +1 -1
  83. package/es/components/content/Layout/LayoutPane.js +1 -1
  84. package/es/components/content/Layout/LayoutPanel.js +1 -1
  85. package/es/components/content/Layout/LayoutPanelHeader.js +1 -1
  86. package/es/components/content/Layout/LayoutToolbar.js +1 -1
  87. package/es/components/content/Layout/hooks/useTinyScrollbar.js +1 -1
  88. package/es/components/content/Layout/index.js +1 -1
  89. package/es/components/content/Layout/utils.js +1 -1
  90. package/es/components/content/List/SectionHeading.js +1 -1
  91. package/es/components/content/List/index.js +1 -1
  92. package/es/components/content/Paragraph.js +1 -1
  93. package/es/components/content/Placeholder/Placeholder.js +1 -1
  94. package/es/components/content/PrismCode/PrismCode.js +1 -1
  95. package/es/components/content/PrismCode/prismSetup.js +1 -1
  96. package/es/components/content/PrismDiffCode/PrismDiffCode.js +1 -1
  97. package/es/components/content/Result/Result.js +1 -1
  98. package/es/components/content/Skeleton/Skeleton.js +1 -1
  99. package/es/components/content/Tag/Tag.js +1 -1
  100. package/es/components/content/Text.js +1 -1
  101. package/es/components/content/TextItem/TextItem.js +1 -1
  102. package/es/components/content/TextItem/index.js +1 -1
  103. package/es/components/content/Title.js +1 -1
  104. package/es/components/content/highlightText.js +1 -1
  105. package/es/components/content/use-auto-tooltip.js +1 -1
  106. package/es/components/fields/Checkbox/Checkbox.js +1 -1
  107. package/es/components/fields/Checkbox/CheckboxGroup.js +1 -1
  108. package/es/components/fields/Checkbox/context.js +1 -1
  109. package/es/components/fields/Checkbox/index.js +1 -1
  110. package/es/components/fields/ComboBox/ComboBox.js +1 -1
  111. package/es/components/fields/ComboBox/index.js +1 -1
  112. package/es/components/fields/DatePicker/DateInput.js +1 -1
  113. package/es/components/fields/DatePicker/DateInputBase.js +1 -1
  114. package/es/components/fields/DatePicker/DatePicker.js +1 -1
  115. package/es/components/fields/DatePicker/DatePickerButton.js +1 -1
  116. package/es/components/fields/DatePicker/DatePickerElement.js +1 -1
  117. package/es/components/fields/DatePicker/DatePickerInput.js +1 -1
  118. package/es/components/fields/DatePicker/DatePickerSegment.js +1 -1
  119. package/es/components/fields/DatePicker/DateRangePicker.js +1 -1
  120. package/es/components/fields/DatePicker/DateRangeSeparatedPicker.js +1 -1
  121. package/es/components/fields/DatePicker/TimeInput.js +1 -1
  122. package/es/components/fields/DatePicker/index.js +1 -1
  123. package/es/components/fields/DatePicker/intl.js +1 -1
  124. package/es/components/fields/DatePicker/parseDate.js +1 -1
  125. package/es/components/fields/DatePicker/props.js +1 -1
  126. package/es/components/fields/DatePicker/types.js +1 -1
  127. package/es/components/fields/DatePicker/utils.js +1 -1
  128. package/es/components/fields/FileInput/FileInput.js +1 -1
  129. package/es/components/fields/FilterListBox/FilterListBox.js +1 -1
  130. package/es/components/fields/FilterListBox/index.js +1 -1
  131. package/es/components/fields/FilterPicker/FilterPicker.js +1 -1
  132. package/es/components/fields/FilterPicker/index.js +1 -1
  133. package/es/components/fields/Input/Input.js +1 -1
  134. package/es/components/fields/Input/index.js +1 -1
  135. package/es/components/fields/ListBox/ListBox.js +1 -1
  136. package/es/components/fields/ListBox/index.js +1 -1
  137. package/es/components/fields/NumberInput/NumberInput.js +1 -1
  138. package/es/components/fields/NumberInput/StepButton.js +1 -1
  139. package/es/components/fields/PasswordInput/PasswordInput.js +1 -1
  140. package/es/components/fields/Picker/Picker.js +1 -1
  141. package/es/components/fields/Picker/index.js +1 -1
  142. package/es/components/fields/RadioGroup/Radio.js +1 -1
  143. package/es/components/fields/RadioGroup/RadioGroup.js +1 -1
  144. package/es/components/fields/RadioGroup/context.js +1 -1
  145. package/es/components/fields/RadioGroup/index.js +1 -1
  146. package/es/components/fields/SearchInput/SearchInput.js +1 -1
  147. package/es/components/fields/SearchInput/index.js +1 -1
  148. package/es/components/fields/Select/Select.js +1 -1
  149. package/es/components/fields/Select/index.js +1 -1
  150. package/es/components/fields/Slider/Gradation.js +1 -1
  151. package/es/components/fields/Slider/Header.js +1 -1
  152. package/es/components/fields/Slider/RangeSlider.js +1 -1
  153. package/es/components/fields/Slider/Slider.js +1 -1
  154. package/es/components/fields/Slider/SliderBase.js +1 -1
  155. package/es/components/fields/Slider/SliderInput.js +1 -1
  156. package/es/components/fields/Slider/SliderThumb.js +1 -1
  157. package/es/components/fields/Slider/SliderTrack.js +1 -1
  158. package/es/components/fields/Slider/elements.js +1 -1
  159. package/es/components/fields/Slider/index.js +1 -1
  160. package/es/components/fields/Slider/types.js +1 -1
  161. package/es/components/fields/Switch/Switch.js +1 -1
  162. package/es/components/fields/Switch/index.js +1 -1
  163. package/es/components/fields/TextArea/TextArea.js +1 -1
  164. package/es/components/fields/TextArea/index.js +1 -1
  165. package/es/components/fields/TextInput/TextInput.js +1 -1
  166. package/es/components/fields/TextInput/TextInputBase.js +1 -1
  167. package/es/components/fields/TextInput/index.js +1 -1
  168. package/es/components/fields/TextInputMapper/TextInputMapper.js +1 -1
  169. package/es/components/fields/TextInputMapper/index.js +1 -1
  170. package/es/components/fields/index.js +1 -1
  171. package/es/components/form/FieldWrapper/FieldWrapper.js +1 -1
  172. package/es/components/form/FieldWrapper/extract-field-wrapper-props.js +1 -1
  173. package/es/components/form/FieldWrapper/index.js +1 -1
  174. package/es/components/form/FieldWrapper/types.js +1 -1
  175. package/es/components/form/Form/Field.js +1 -1
  176. package/es/components/form/Form/Form.js +1 -1
  177. package/es/components/form/Form/ResetButton/ResetButton.js +1 -1
  178. package/es/components/form/Form/ResetButton/index.js +1 -1
  179. package/es/components/form/Form/SubmitButton/SubmitButton.js +1 -1
  180. package/es/components/form/Form/SubmitButton/index.js +1 -1
  181. package/es/components/form/Form/SubmitError.js +1 -1
  182. package/es/components/form/Form/index.js +1 -1
  183. package/es/components/form/Form/types.js +1 -1
  184. package/es/components/form/Form/use-field/index.js +1 -1
  185. package/es/components/form/Form/use-field/types.js +1 -1
  186. package/es/components/form/Form/use-field/use-field-props.js +1 -1
  187. package/es/components/form/Form/use-field/use-field.js +1 -1
  188. package/es/components/form/Form/use-form.js +1 -1
  189. package/es/components/form/Form/validation.js +1 -1
  190. package/es/components/form/Label.js +1 -1
  191. package/es/components/form/index.js +1 -1
  192. package/es/components/form/wrapper.js +1 -1
  193. package/es/components/helpers/DisplayTransition/DisplayTransition.js +1 -1
  194. package/es/components/helpers/DisplayTransition/index.js +1 -1
  195. package/es/components/helpers/IconSwitch/IconSwitch.js +1 -1
  196. package/es/components/helpers/index.js +1 -1
  197. package/es/components/layout/Flex.js +1 -1
  198. package/es/components/layout/Flow.js +1 -1
  199. package/es/components/layout/Grid.js +1 -1
  200. package/es/components/layout/Panel.js +1 -1
  201. package/es/components/layout/Prefix.js +1 -1
  202. package/es/components/layout/ResizablePanel.js +1 -1
  203. package/es/components/layout/Space.js +1 -1
  204. package/es/components/layout/Suffix.js +1 -1
  205. package/es/components/navigation/LegacyTabs/LegacyTabs.js +1 -1
  206. package/es/components/organisms/FileTabs/FileTabs.js +1 -1
  207. package/es/components/organisms/StatsCard/StatsCard.js +1 -1
  208. package/es/components/other/Base64Upload/Base64Upload.js +1 -1
  209. package/es/components/other/Calendar/Calendar.js +1 -1
  210. package/es/components/other/Calendar/CalendarCell.js +1 -1
  211. package/es/components/other/Calendar/CalendarGrid.js +1 -1
  212. package/es/components/other/Calendar/RangeCalendar.js +1 -1
  213. package/es/components/other/CloudLogo/CloudLogo.js +1 -1
  214. package/es/components/overlays/AlertDialog/AlertDialog.js +1 -1
  215. package/es/components/overlays/AlertDialog/AlertDialogApiProvider.js +1 -1
  216. package/es/components/overlays/AlertDialog/AlertDialogZone.js +1 -1
  217. package/es/components/overlays/AlertDialog/index.js +1 -1
  218. package/es/components/overlays/AlertDialog/types.js +1 -1
  219. package/es/components/overlays/Dialog/Dialog.js +1 -1
  220. package/es/components/overlays/Dialog/DialogContainer.js +1 -1
  221. package/es/components/overlays/Dialog/DialogForm.js +1 -1
  222. package/es/components/overlays/Dialog/DialogTrigger.js +1 -1
  223. package/es/components/overlays/Dialog/context.js +1 -1
  224. package/es/components/overlays/Dialog/index.js +1 -1
  225. package/es/components/overlays/Dialog/use-dialog-container.js +1 -1
  226. package/es/components/overlays/Modal/Modal.js +1 -1
  227. package/es/components/overlays/Modal/OpenTransition.js +1 -1
  228. package/es/components/overlays/Modal/Overlay.js +1 -1
  229. package/es/components/overlays/Modal/Popover.js +1 -1
  230. package/es/components/overlays/Modal/Tray.js +1 -1
  231. package/es/components/overlays/Modal/Underlay.js +1 -1
  232. package/es/components/overlays/Modal/index.js +1 -1
  233. package/es/components/overlays/Modal/types.js +1 -1
  234. package/es/components/overlays/NewNotifications/Bar/FloatingNotification.js +1 -1
  235. package/es/components/overlays/NewNotifications/Bar/NotificationsBar.js +1 -1
  236. package/es/components/overlays/NewNotifications/Bar/TransitionComponent.js +1 -1
  237. package/es/components/overlays/NewNotifications/Bar/index.js +1 -1
  238. package/es/components/overlays/NewNotifications/Dialog/NotificationsDialogContext.js +1 -1
  239. package/es/components/overlays/NewNotifications/Dialog/NotificationsDialogTrigger.js +1 -1
  240. package/es/components/overlays/NewNotifications/Dialog/index.js +1 -1
  241. package/es/components/overlays/NewNotifications/Notification.js +1 -1
  242. package/es/components/overlays/NewNotifications/NotificationView/NotificationAction.js +1 -1
  243. package/es/components/overlays/NewNotifications/NotificationView/NotificationCloseButton.js +1 -1
  244. package/es/components/overlays/NewNotifications/NotificationView/NotificationDescription.js +1 -1
  245. package/es/components/overlays/NewNotifications/NotificationView/NotificationFooter.js +1 -1
  246. package/es/components/overlays/NewNotifications/NotificationView/NotificationHeader.js +1 -1
  247. package/es/components/overlays/NewNotifications/NotificationView/NotificationIcon.js +1 -1
  248. package/es/components/overlays/NewNotifications/NotificationView/NotificationProvider.js +1 -1
  249. package/es/components/overlays/NewNotifications/NotificationView/NotificationView.js +1 -1
  250. package/es/components/overlays/NewNotifications/NotificationView/index.js +1 -1
  251. package/es/components/overlays/NewNotifications/NotificationView/types.js +1 -1
  252. package/es/components/overlays/NewNotifications/NotificationsContext/NotificationsContext.js +1 -1
  253. package/es/components/overlays/NewNotifications/NotificationsContext/NotificationsProvider.js +1 -1
  254. package/es/components/overlays/NewNotifications/NotificationsContext/index.js +1 -1
  255. package/es/components/overlays/NewNotifications/NotificationsContext/use-notifications.js +1 -1
  256. package/es/components/overlays/NewNotifications/NotificationsList/NotificationsList.js +1 -1
  257. package/es/components/overlays/NewNotifications/NotificationsList/NotificationsListItem.js +1 -1
  258. package/es/components/overlays/NewNotifications/NotificationsList/index.js +1 -1
  259. package/es/components/overlays/NewNotifications/NotificationsList/types.js +1 -1
  260. package/es/components/overlays/NewNotifications/hooks/index.js +1 -1
  261. package/es/components/overlays/NewNotifications/hooks/types.js +1 -1
  262. package/es/components/overlays/NewNotifications/hooks/use-notification-list-item.js +1 -1
  263. package/es/components/overlays/NewNotifications/hooks/use-notifications-api.js +1 -1
  264. package/es/components/overlays/NewNotifications/hooks/use-notifications-list.js +1 -1
  265. package/es/components/overlays/NewNotifications/hooks/use-notifications-observer.js +1 -1
  266. package/es/components/overlays/NewNotifications/index.js +1 -1
  267. package/es/components/overlays/NewNotifications/types.js +1 -1
  268. package/es/components/overlays/Notification/Notification.js +1 -1
  269. package/es/components/overlays/OverlayWrapper.js +1 -1
  270. package/es/components/overlays/Toasts/Toast.js +1 -1
  271. package/es/components/overlays/Toasts/index.js +1 -1
  272. package/es/components/overlays/Toasts/types.js +1 -1
  273. package/es/components/overlays/Toasts/use-toasts-api.js +1 -1
  274. package/es/components/overlays/Tooltip/Tooltip.js +1 -1
  275. package/es/components/overlays/Tooltip/TooltipProvider.js +1 -1
  276. package/es/components/overlays/Tooltip/TooltipTrigger.js +1 -1
  277. package/es/components/overlays/Tooltip/context.js +1 -1
  278. package/es/components/overlays/Tooltip/index.js +1 -1
  279. package/es/components/portal/Portal.js +1 -1
  280. package/es/components/portal/PortalProvider.js +1 -1
  281. package/es/components/portal/index.js +1 -1
  282. package/es/components/portal/types.js +1 -1
  283. package/es/components/portal/usePortal.js +1 -1
  284. package/es/components/shared/InvalidIcon.js +1 -1
  285. package/es/components/shared/ValidIcon.js +1 -1
  286. package/es/components/status/LoadingAnimation/LoadingAnimation.js +1 -1
  287. package/es/components/status/LoadingAnimation/index.js +1 -1
  288. package/es/components/status/Spin/Cube.js +1 -1
  289. package/es/components/status/Spin/InternalSpinner.js +1 -1
  290. package/es/components/status/Spin/Spin.js +1 -1
  291. package/es/components/status/Spin/SpinsContainer.js +1 -1
  292. package/es/components/status/Spin/index.js +1 -1
  293. package/es/components/status/Spin/types.js +1 -1
  294. package/es/components/status/index.js +1 -1
  295. package/es/data/item-themes.js +1 -1
  296. package/es/data/themes.js +1 -1
  297. package/es/icons/AdjustmentsHorizontalIcon.js +1 -1
  298. package/es/icons/AdjustmentsIcon.js +1 -1
  299. package/es/icons/AiIcon.js +1 -1
  300. package/es/icons/AreaChartIcon.js +1 -1
  301. package/es/icons/BackwardIcon.js +1 -1
  302. package/es/icons/BarChartIcon.js +1 -1
  303. package/es/icons/BellFilledIcon.js +1 -1
  304. package/es/icons/BellIcon.js +1 -1
  305. package/es/icons/BooleanIcon.js +1 -1
  306. package/es/icons/CalendarEditIcon.js +1 -1
  307. package/es/icons/CalendarIcon.js +1 -1
  308. package/es/icons/CaretDownIcon.js +1 -1
  309. package/es/icons/CaretUpIcon.js +1 -1
  310. package/es/icons/ChartAreaStackedIcon.js +1 -1
  311. package/es/icons/ChartAreaStackedPercentageIcon.js +1 -1
  312. package/es/icons/ChartBarGroupedHorizontalIcon.js +1 -1
  313. package/es/icons/ChartBarGroupedIcon.js +1 -1
  314. package/es/icons/ChartBarHorizontalIcon.js +1 -1
  315. package/es/icons/ChartBarLineIcon.js +1 -1
  316. package/es/icons/ChartBarStackedHorizontalIcon.js +1 -1
  317. package/es/icons/ChartBarStackedIcon.js +1 -1
  318. package/es/icons/ChartBarStackedPercentageHorizontalIcon.js +1 -1
  319. package/es/icons/ChartBarStackedPercentageIcon.js +1 -1
  320. package/es/icons/ChartBoxPlot2Icon.js +1 -1
  321. package/es/icons/ChartBoxPlotIcon.js +1 -1
  322. package/es/icons/ChartBubbleIcon.js +1 -1
  323. package/es/icons/ChartDonut2Icon.js +1 -1
  324. package/es/icons/ChartFunnelIcon.js +1 -1
  325. package/es/icons/ChartHeatmapIcon.js +1 -1
  326. package/es/icons/ChartKPIIcon.js +1 -1
  327. package/es/icons/ChartPie2Icon.js +1 -1
  328. package/es/icons/ChartScatterIcon.js +1 -1
  329. package/es/icons/CheckCircleFilledIcon.js +1 -1
  330. package/es/icons/CheckCircleIcon.js +1 -1
  331. package/es/icons/CheckIcon.js +1 -1
  332. package/es/icons/CircleFilledIcon.js +1 -1
  333. package/es/icons/ClearIcon.js +1 -1
  334. package/es/icons/CloseCircleFilledIcon.js +1 -1
  335. package/es/icons/CloseCircleIcon.js +1 -1
  336. package/es/icons/CloseIcon.js +1 -1
  337. package/es/icons/CodeIcon.js +1 -1
  338. package/es/icons/ColumnTotalIcon.js +1 -1
  339. package/es/icons/CopyIcon.js +1 -1
  340. package/es/icons/CountIcon.js +1 -1
  341. package/es/icons/CubeIcon.js +1 -1
  342. package/es/icons/CubePauseIcon.js +1 -1
  343. package/es/icons/CubePlayIcon.js +1 -1
  344. package/es/icons/CurrencyDollarIcon.js +1 -1
  345. package/es/icons/DangerIcon.js +1 -1
  346. package/es/icons/DashboardIcon.js +1 -1
  347. package/es/icons/DatabaseIcon.js +1 -1
  348. package/es/icons/DecimalDecreaseIcon.js +1 -1
  349. package/es/icons/DecimalIncreaseIcon.js +1 -1
  350. package/es/icons/DirectionIcon.js +1 -1
  351. package/es/icons/DonutIcon.js +1 -1
  352. package/es/icons/DownIcon.js +1 -1
  353. package/es/icons/EditIcon.js +1 -1
  354. package/es/icons/ExclamationCircleFilledIcon.js +1 -1
  355. package/es/icons/ExclamationCircleIcon.js +1 -1
  356. package/es/icons/ExclamationIcon.js +1 -1
  357. package/es/icons/EyeIcon.js +1 -1
  358. package/es/icons/EyeInvisibleIcon.js +1 -1
  359. package/es/icons/FilterIcon.js +1 -1
  360. package/es/icons/FolderFilledIcon.js +1 -1
  361. package/es/icons/FolderIcon.js +1 -1
  362. package/es/icons/FolderOpenFilledIcon.js +1 -1
  363. package/es/icons/FolderOpenIcon.js +1 -1
  364. package/es/icons/ForwardIcon.js +1 -1
  365. package/es/icons/HierarchyIcon.js +1 -1
  366. package/es/icons/HierarchyOpenIcon.js +1 -1
  367. package/es/icons/Icon.js +1 -1
  368. package/es/icons/InfoCircleIcon.js +1 -1
  369. package/es/icons/InfoIcon.js +1 -1
  370. package/es/icons/KeyIcon.js +1 -1
  371. package/es/icons/LeftIcon.js +1 -1
  372. package/es/icons/LineChartIcon.js +1 -1
  373. package/es/icons/LoadingIcon.js +1 -1
  374. package/es/icons/LockFilledIcon.js +1 -1
  375. package/es/icons/LockIcon.js +1 -1
  376. package/es/icons/MoreIcon.js +1 -1
  377. package/es/icons/NotAllowedIcon.js +1 -1
  378. package/es/icons/Number123Icon.js +1 -1
  379. package/es/icons/NumberIcon.js +1 -1
  380. package/es/icons/PauseCircleFilledIcon.js +1 -1
  381. package/es/icons/PauseCircleIcon.js +1 -1
  382. package/es/icons/PauseIcon.js +1 -1
  383. package/es/icons/PercentageIcon.js +1 -1
  384. package/es/icons/PieChartIcon.js +1 -1
  385. package/es/icons/PlayCircleIcon.js +1 -1
  386. package/es/icons/PlayIcon.js +1 -1
  387. package/es/icons/PlusIcon.js +1 -1
  388. package/es/icons/ProgressBarIcon.js +1 -1
  389. package/es/icons/ReloadIcon.js +1 -1
  390. package/es/icons/ReportIcon.js +1 -1
  391. package/es/icons/ReturnIcon.js +1 -1
  392. package/es/icons/RightIcon.js +1 -1
  393. package/es/icons/RowTotalsIcon.js +1 -1
  394. package/es/icons/SchemeIcon.js +1 -1
  395. package/es/icons/SearchIcon.js +1 -1
  396. package/es/icons/SettingsIcon.js +1 -1
  397. package/es/icons/ShieldFilledIcon.js +1 -1
  398. package/es/icons/ShieldIcon.js +1 -1
  399. package/es/icons/SlashIcon.js +1 -1
  400. package/es/icons/SparklesIcon.js +1 -1
  401. package/es/icons/SqlIcon.js +1 -1
  402. package/es/icons/StatsIcon.js +1 -1
  403. package/es/icons/StopIcon.js +1 -1
  404. package/es/icons/StringIcon.js +1 -1
  405. package/es/icons/SubtotalsIcon.js +1 -1
  406. package/es/icons/SwitchIcon.js +1 -1
  407. package/es/icons/TableIcon.js +1 -1
  408. package/es/icons/ThumbsDownIcon.js +1 -1
  409. package/es/icons/ThumbsUpIcon.js +1 -1
  410. package/es/icons/ThunderboltCrossedIcon.js +1 -1
  411. package/es/icons/ThunderboltFilledIcon.js +1 -1
  412. package/es/icons/ThunderboltIcon.js +1 -1
  413. package/es/icons/TimeIcon.js +1 -1
  414. package/es/icons/TrashIcon.js +1 -1
  415. package/es/icons/UnlockIcon.js +1 -1
  416. package/es/icons/UpIcon.js +1 -1
  417. package/es/icons/UserGroupIcon.js +1 -1
  418. package/es/icons/UserIcon.js +1 -1
  419. package/es/icons/UserLockIcon.js +1 -1
  420. package/es/icons/ViewIcon.js +1 -1
  421. package/es/icons/WarningFilledIcon.js +1 -1
  422. package/es/icons/WarningIcon.js +1 -1
  423. package/es/icons/add-new-icon.js +1 -1
  424. package/es/icons/index.js +1 -1
  425. package/es/icons/wrap-icon.js +1 -1
  426. package/es/index.js +1 -1
  427. package/es/provider.js +1 -1
  428. package/es/providers/TrackingProvider.js +1 -1
  429. package/es/providers/navigation.types.js +1 -1
  430. package/es/providers/navigationAdapter.default.js +1 -1
  431. package/es/services/notification.js +1 -1
  432. package/es/shared/form.js +1 -1
  433. package/es/shared/index.js +1 -1
  434. package/es/stories/Form.legacy-stories.js +1 -1
  435. package/es/stories/FormFieldArgs.js +1 -1
  436. package/es/stories/SimpleLayout.stories.js +1 -1
  437. package/es/stories/Tasty.stories.js +1 -1
  438. package/es/stories/components/ConfirmDeletionDialogForm.js +1 -1
  439. package/es/stories/components/DialogFormApp.js +1 -1
  440. package/es/stories/components/StyledButton.js +1 -1
  441. package/es/stories/lists/baseProps.js +1 -1
  442. package/es/tasty/chunks/cacheKey.js +1 -1
  443. package/es/tasty/chunks/definitions.js +1 -1
  444. package/es/tasty/chunks/index.js +1 -1
  445. package/es/tasty/chunks/renderChunk.js +23 -1
  446. package/es/tasty/debug.js +1 -1
  447. package/es/tasty/hooks/index.js +1 -1
  448. package/es/tasty/hooks/useGlobalStyles.js +10 -2
  449. package/es/tasty/hooks/useStyles.js +1 -1
  450. package/es/tasty/index.js +1 -1
  451. package/es/tasty/injector/index.js +1 -1
  452. package/es/tasty/injector/injector.js +1 -1
  453. package/es/tasty/injector/sheet-manager.js +1 -1
  454. package/es/tasty/injector/types.js +1 -1
  455. package/es/tasty/parser/classify.js +1 -1
  456. package/es/tasty/parser/const.js +1 -1
  457. package/es/tasty/parser/lru.js +1 -1
  458. package/es/tasty/parser/parser.js +1 -1
  459. package/es/tasty/parser/tokenizer.js +1 -1
  460. package/es/tasty/parser/types.js +1 -1
  461. package/es/tasty/pipeline/conditions.js +1 -1
  462. package/es/tasty/pipeline/exclusive.js +85 -2
  463. package/es/tasty/pipeline/index.js +10 -5
  464. package/es/tasty/pipeline/materialize.js +109 -9
  465. package/es/tasty/pipeline/parseStateKey.js +12 -2
  466. package/es/tasty/pipeline/simplify.js +1 -1
  467. package/es/tasty/states/index.js +5 -10
  468. package/es/tasty/styles/align.js +1 -1
  469. package/es/tasty/styles/border.js +1 -1
  470. package/es/tasty/styles/boxShadow.combinator.js +1 -1
  471. package/es/tasty/styles/color.js +1 -1
  472. package/es/tasty/styles/createStyle.js +1 -1
  473. package/es/tasty/styles/dimension.js +1 -1
  474. package/es/tasty/styles/display.js +1 -1
  475. package/es/tasty/styles/fade.js +1 -1
  476. package/es/tasty/styles/fill.js +1 -1
  477. package/es/tasty/styles/flow.js +1 -1
  478. package/es/tasty/styles/font.js +1 -1
  479. package/es/tasty/styles/fontStyle.js +1 -1
  480. package/es/tasty/styles/gap.js +1 -1
  481. package/es/tasty/styles/groupRadius.js +1 -1
  482. package/es/tasty/styles/height.js +1 -1
  483. package/es/tasty/styles/index.js +1 -1
  484. package/es/tasty/styles/inset.js +1 -1
  485. package/es/tasty/styles/justify.js +1 -1
  486. package/es/tasty/styles/list.js +1 -1
  487. package/es/tasty/styles/margin.js +1 -1
  488. package/es/tasty/styles/outline.js +1 -1
  489. package/es/tasty/styles/padding.js +1 -1
  490. package/es/tasty/styles/place.js +1 -1
  491. package/es/tasty/styles/predefined.js +1 -1
  492. package/es/tasty/styles/preset.js +1 -1
  493. package/es/tasty/styles/radius.js +1 -1
  494. package/es/tasty/styles/reset.js +1 -1
  495. package/es/tasty/styles/scrollbar.js +1 -1
  496. package/es/tasty/styles/shadow.js +1 -1
  497. package/es/tasty/styles/styledScrollbar.js +1 -1
  498. package/es/tasty/styles/transition.js +1 -1
  499. package/es/tasty/styles/types.js +1 -1
  500. package/es/tasty/styles/width.js +1 -1
  501. package/es/tasty/tasty.js +1 -1
  502. package/es/tasty/types.js +1 -1
  503. package/es/tasty/utils/cache-wrapper.js +1 -1
  504. package/es/tasty/utils/case-converter.js +1 -1
  505. package/es/tasty/utils/colors.js +1 -1
  506. package/es/tasty/utils/dotize.js +1 -1
  507. package/es/tasty/utils/filterBaseProps.js +1 -1
  508. package/es/tasty/utils/getDisplayName.js +1 -1
  509. package/es/tasty/utils/isDevEnv.js +1 -1
  510. package/es/tasty/utils/mergeStyles.js +2 -2
  511. package/es/tasty/utils/modAttrs.js +1 -1
  512. package/es/tasty/utils/processTokens.js +1 -1
  513. package/es/tasty/utils/string.js +1 -1
  514. package/es/tasty/utils/styles.js +1 -1
  515. package/es/tasty/utils/warnings.js +1 -1
  516. package/es/tokens.js +1 -1
  517. package/es/utils/ResizeSensor.js +1 -1
  518. package/es/utils/index.js +1 -1
  519. package/es/utils/modules.js +1 -1
  520. package/es/utils/promise.js +1 -1
  521. package/es/utils/raf.js +1 -1
  522. package/es/utils/random.js +1 -1
  523. package/es/utils/range.js +1 -1
  524. package/es/utils/react/RenderCache.js +1 -1
  525. package/es/utils/react/Slots.js +1 -1
  526. package/es/utils/react/chain.js +1 -1
  527. package/es/utils/react/forwardRefWithGenerics.js +1 -1
  528. package/es/utils/react/index.js +1 -1
  529. package/es/utils/react/interactions.js +1 -1
  530. package/es/utils/react/isTextOnly.js +1 -1
  531. package/es/utils/react/mapProps.js +1 -1
  532. package/es/utils/react/mergeProps.js +1 -1
  533. package/es/utils/react/nullableValue.js +1 -1
  534. package/es/utils/react/resolveIcon.js +1 -1
  535. package/es/utils/react/sharedStore.js +1 -1
  536. package/es/utils/react/useCombinedRefs.js +1 -1
  537. package/es/utils/react/useControlledFocusVisible.js +1 -1
  538. package/es/utils/react/useEventBus.js +1 -1
  539. package/es/utils/react/useId.js +1 -1
  540. package/es/utils/react/useIsDarwin.js +1 -1
  541. package/es/utils/react/useKeySymbols.js +1 -1
  542. package/es/utils/react/useLayoutEffect.js +1 -1
  543. package/es/utils/react/useLocalStorage.js +1 -1
  544. package/es/utils/react/useQaProps.js +1 -1
  545. package/es/utils/react/useViewportSize.js +1 -1
  546. package/es/utils/react/wrapNodeIfPlain.js +1 -1
  547. package/es/utils/tree.js +1 -1
  548. package/es/utils/warnings.js +1 -1
  549. package/es/version.js +2 -2
  550. package/package.json +1 -1
  551. package/types/components/HiddenInput.d.ts +1 -1
  552. package/types/components/actions/CommandMenu/styled.d.ts +5 -5
  553. package/types/components/actions/Menu/styled.d.ts +8 -8
  554. package/types/components/content/List/SectionHeading.d.ts +1 -1
  555. package/types/components/content/Text.d.ts +7 -7
  556. package/types/components/fields/DatePicker/DatePickerElement.d.ts +1 -1
  557. package/types/components/fields/Select/Select.d.ts +1 -1
  558. package/types/components/fields/Slider/elements.d.ts +6 -6
  559. package/types/tasty/chunks/renderChunk.d.ts +5 -0
  560. package/types/tasty/injector/types.d.ts +1 -1
  561. package/types/tasty/pipeline/exclusive.d.ts +15 -0
  562. package/types/tasty/tasty.d.ts +1 -1
  563. package/es/tasty/utils/getModCombinations.js +0 -38
  564. package/es/tasty/utils/mediaRangeOptimizer.js +0 -338
  565. package/es/tasty/utils/renderStyles.js +0 -1624
  566. package/types/tasty/utils/getModCombinations.d.ts +0 -9
  567. package/types/tasty/utils/mediaRangeOptimizer.d.ts +0 -88
  568. package/types/tasty/utils/renderStyles.d.ts +0 -47
@@ -1,1624 +0,0 @@
1
- /**
2
- * @license MIT
3
- * author: Cube Dev Team
4
- * @cube-dev/ui-kit v0.0.0-canary-63be1e5
5
- * Released under the MIT license.
6
- */
7
-
8
- /**
9
- * @deprecated This file is superseded by src/tasty/pipeline/index.ts
10
- * It is kept for reference during the transition period.
11
- * All imports should use the new pipeline instead.
12
- *
13
- * Original description:
14
- * Style rendering that works with structured style objects.
15
- * Eliminates CSS string parsing for better performance.
16
- *
17
- * Key optimizations:
18
- * - Early exit checks (hasSameAttributeConflicts) handle common cases without overhead
19
- * - Logical rule caching (logicalRulesCache) memoizes expensive style processing
20
- * - Conflict detection prevents invalid CSS selector combinations
21
- * - Not-selector optimization reduces CSS size
22
- * - Priority-based filtering handles mod precedence correctly
23
- * - Consolidated mod processing eliminates code duplication
24
- */
25
- import { Lru } from '../parser/lru';
26
- import { createStyle, STYLE_HANDLER_MAP } from '../styles';
27
- import { getModCombinationsIterative } from './getModCombinations';
28
- import { computeNonOverlappingRanges, parseMediaCondition, rangeToMediaCondition, } from './mediaRangeOptimizer';
29
- import { computeState, getModSelector, stringifyStyles, styleStateMapToStyleStateDataList, } from './styles';
30
- // Cache logical rules per styles+breakpoints to avoid recomputation across identical calls
31
- const logicalRulesCache = new Lru(5000);
32
- // Normalize selector suffixes coming from `$` in style handler results.
33
- // Some legacy handlers return suffixes starting with `&` (e.g. '& > *').
34
- // The renderer expects suffixes without the ampersand because it adds
35
- // the parent selector during materialization.
36
- function normalizeDollarSelectorSuffix(suffix) {
37
- if (!suffix)
38
- return '';
39
- return suffix.startsWith('&') ? suffix.slice(1) : suffix;
40
- }
41
- /**
42
- * Check if a key represents a CSS selector
43
- */
44
- export function isSelector(key) {
45
- return (key.startsWith('&') || key.startsWith('.') || key.match(/^[A-Z]/) !== null);
46
- }
47
- /**
48
- * Transform selector affix by converting capitalized words to sub-element selectors.
49
- * Returns a selector prefix with leading and trailing spaces.
50
- *
51
- * Examples:
52
- * '> Body > Row' -> ' > [data-element="Body"] > [data-element="Row"] '
53
- * '> Body > Row >' -> ' > [data-element="Body"] > [data-element="Row"] > '
54
- * '>' -> ' > '
55
- */
56
- function transformSelectorAffix(affix) {
57
- const trimmed = affix.trim();
58
- if (!trimmed)
59
- return ' ';
60
- // Validate that combinators have spaces around them
61
- // Check for capitalized words adjacent to combinators without spaces
62
- const invalidPattern = /[A-Z][a-z]*[>+~]|[>+~][A-Z][a-z]*/;
63
- if (invalidPattern.test(trimmed)) {
64
- console.error(`[Tasty] Invalid selector affix ($) syntax: "${affix}"\n` +
65
- `Combinators (>, +, ~) must have spaces around them when used with element names.\n` +
66
- `Example: Use "$: '> Body > Row'" instead of "$: '>Body>Row'"\n` +
67
- `This is a design choice: the parser uses simple whitespace splitting for performance.`);
68
- }
69
- const tokens = trimmed.split(/\s+/);
70
- const transformed = tokens.map((token) => /^[A-Z]/.test(token) ? `[data-element="${token}"]` : token);
71
- return ` ${transformed.join(' ')} `;
72
- }
73
- /**
74
- * Get the selector suffix for a key
75
- */
76
- function getSelector(key, styles) {
77
- if (key.startsWith('&')) {
78
- return key.slice(1);
79
- }
80
- if (key.startsWith('.')) {
81
- return ` ${key}`;
82
- }
83
- if (key.match(/^[A-Z]/)) {
84
- const affix = styles?.$;
85
- if (affix !== undefined) {
86
- const prefix = transformSelectorAffix(String(affix));
87
- return `${prefix}[data-element="${key}"]`;
88
- }
89
- return ` [data-element="${key}"]`;
90
- }
91
- return null;
92
- }
93
- /**
94
- * Parse attribute selector into its components.
95
- * Simple regex parsing - JS engines optimize repeated patterns internally.
96
- */
97
- function parseAttributeSelector(selector) {
98
- // Match patterns like [data-size="medium"] or [data-selected]
99
- const match = selector.match(/^\[([^=\]]+)(?:="([^"]+)")?\]$/);
100
- return match
101
- ? {
102
- attribute: match[1],
103
- value: match[2] || 'true', // Handle boolean attributes
104
- fullSelector: selector,
105
- }
106
- : null;
107
- }
108
- function hasConflictingAttributeSelectors(mods, parsedMods) {
109
- const attributeValues = new Map();
110
- const attributeBooleans = new Set();
111
- for (const mod of mods) {
112
- const parsed = parsedMods?.get(mod) ?? parseAttributeSelector(mod);
113
- if (!parsed)
114
- continue;
115
- if (parsed.value === 'true') {
116
- // Boolean attribute
117
- attributeBooleans.add(parsed.attribute);
118
- }
119
- else {
120
- // Value attribute
121
- if (!attributeValues.has(parsed.attribute)) {
122
- attributeValues.set(parsed.attribute, []);
123
- }
124
- attributeValues.get(parsed.attribute).push(parsed.value);
125
- }
126
- }
127
- // Check for multiple different values for the same attribute
128
- for (const values of attributeValues.values()) {
129
- if (values.length > 1)
130
- return true;
131
- }
132
- return false;
133
- }
134
- /**
135
- * Create a conflict checker function that uses precomputed attribute maps
136
- * for efficient conflict detection during combination generation
137
- */
138
- function createAttributeConflictChecker(parsedMods) {
139
- return (combination) => hasConflictingAttributeSelectors(combination, parsedMods);
140
- }
141
- // Build precomputed attribute maps for efficient not selector optimization
142
- function buildAttributeMaps(currentMods, allMods, parsedModsCache) {
143
- const allAttributes = new Map();
144
- const currentAttributes = new Map();
145
- const parsedMods = parsedModsCache || new Map();
146
- // Parse all mods once and cache results (only if cache not provided)
147
- if (!parsedModsCache) {
148
- const allModsSet = new Set([...currentMods, ...allMods]);
149
- for (const mod of allModsSet) {
150
- if (!parsedMods.has(mod)) {
151
- parsedMods.set(mod, parseAttributeSelector(mod));
152
- }
153
- }
154
- }
155
- // Build map of all possible values for each attribute
156
- for (const mod of allMods) {
157
- const parsed = parsedMods.get(mod);
158
- if (parsed && parsed.value !== 'true') {
159
- if (!allAttributes.has(parsed.attribute)) {
160
- allAttributes.set(parsed.attribute, new Set());
161
- }
162
- allAttributes.get(parsed.attribute).add(parsed.value);
163
- }
164
- }
165
- // Build map of current mod attribute values
166
- for (const mod of currentMods) {
167
- const parsed = parsedMods.get(mod);
168
- if (parsed && parsed.value !== 'true') {
169
- currentAttributes.set(parsed.attribute, parsed.value);
170
- }
171
- }
172
- return { allAttributes, currentAttributes, parsedMods };
173
- }
174
- /**
175
- * Check if a combination of positive and negative selectors creates a contradiction
176
- * Returns true if the combination is INVALID and should be pruned
177
- */
178
- function hasContradiction(currentMods, notMods, parsedMods) {
179
- // Build maps of positive selector states
180
- const positiveAttributes = new Map();
181
- const positiveBooleans = new Set();
182
- for (const mod of currentMods) {
183
- const parsed = parsedMods.get(mod);
184
- if (parsed) {
185
- if (parsed.value === 'true') {
186
- // Boolean attribute (e.g., [data-theme])
187
- positiveBooleans.add(parsed.attribute);
188
- }
189
- else {
190
- // Value attribute (e.g., [data-theme="danger"])
191
- if (!positiveAttributes.has(parsed.attribute)) {
192
- positiveAttributes.set(parsed.attribute, []);
193
- }
194
- positiveAttributes.get(parsed.attribute).push(parsed.value);
195
- }
196
- }
197
- }
198
- // Check negative selectors for contradictions
199
- for (const mod of notMods) {
200
- const parsed = parsedMods.get(mod);
201
- if (parsed) {
202
- if (parsed.value === 'true') {
203
- // Negative boolean: !([data-theme])
204
- // Case 6: Value positive + attribute negative = CONTRADICTION
205
- if (positiveAttributes.has(parsed.attribute) ||
206
- positiveBooleans.has(parsed.attribute)) {
207
- return true; // INVALID: can't have value without attribute
208
- }
209
- }
210
- else {
211
- // Negative value: !([data-theme="danger"])
212
- // No contradiction - this is valid
213
- }
214
- }
215
- }
216
- return false;
217
- }
218
- function optimizeNotSelectors(currentMods, allMods, precomputedMaps) {
219
- const maps = precomputedMaps || buildAttributeMaps(currentMods, allMods);
220
- const notMods = allMods.filter((mod) => !currentMods.includes(mod));
221
- const optimizedNotMods = [];
222
- // Precompute presence of negative boolean attributes to avoid repeated scans
223
- const negativeBooleanByAttr = new Set();
224
- for (const mod of notMods) {
225
- const p = maps.parsedMods.get(mod);
226
- if (p && p.value === 'true') {
227
- negativeBooleanByAttr.add(p.attribute);
228
- }
229
- }
230
- // Build maps of positive selector states for subsumption optimization
231
- const positiveAttributes = new Map();
232
- const positiveBooleans = new Set();
233
- for (const mod of currentMods) {
234
- const parsed = maps.parsedMods.get(mod);
235
- if (parsed) {
236
- if (parsed.value === 'true') {
237
- positiveBooleans.add(parsed.attribute);
238
- }
239
- else {
240
- if (!positiveAttributes.has(parsed.attribute)) {
241
- positiveAttributes.set(parsed.attribute, []);
242
- }
243
- positiveAttributes.get(parsed.attribute).push(parsed.value);
244
- }
245
- }
246
- }
247
- for (const mod of notMods) {
248
- const parsed = maps.parsedMods.get(mod);
249
- if (parsed && parsed.value !== 'true') {
250
- // Negative value selector
251
- // If we already have a value for this attribute, skip this not selector
252
- // because it's already mutually exclusive (optimization)
253
- if (maps.currentAttributes.has(parsed.attribute)) {
254
- continue;
255
- }
256
- }
257
- // If we have a positive value for this attribute, skip the negative boolean
258
- // This avoids producing selectors like [data-attr="x"]:not([data-attr])
259
- if (parsed && parsed.value === 'true') {
260
- if (maps.currentAttributes.has(parsed.attribute)) {
261
- continue;
262
- }
263
- }
264
- // Case 4 subsumption: If we have a value positive and boolean positive for same attribute
265
- // The value implies the boolean, so we can skip the boolean from positive mods
266
- // (This is handled elsewhere - the value selector is more specific)
267
- // Case 7 subsumption: If we have a value negative and boolean negative for same attribute
268
- // The boolean negative implies value negative, so skip the value negative
269
- if (parsed && parsed.value !== 'true') {
270
- // If we also have the boolean attribute in negative mods, skip the value negative
271
- if (negativeBooleanByAttr.has(parsed.attribute)) {
272
- continue;
273
- }
274
- }
275
- optimizedNotMods.push(mod);
276
- }
277
- return optimizedNotMods;
278
- }
279
- /**
280
- * Quick check if there are any same-attribute conflicts (boolean vs value for same attribute).
281
- * Returns true if conflicts exist, false if filtering can be skipped.
282
- * This early exit optimization handles the common case efficiently.
283
- */
284
- function hasSameAttributeConflicts(allMods, parsedModsCache) {
285
- const attributeCounts = new Map();
286
- for (const mod of allMods) {
287
- const parsed = parsedModsCache.get(mod);
288
- if (!parsed)
289
- continue;
290
- const isBool = parsed.value === 'true';
291
- const existing = attributeCounts.get(parsed.attribute);
292
- if (existing) {
293
- // Already have both types for this attribute - conflict exists!
294
- if ((isBool && existing.hasValue) || (!isBool && existing.hasBool)) {
295
- return true;
296
- }
297
- // Update the types we've seen
298
- if (isBool)
299
- existing.hasBool = true;
300
- else
301
- existing.hasValue = true;
302
- }
303
- else {
304
- attributeCounts.set(parsed.attribute, {
305
- hasBool: isBool,
306
- hasValue: !isBool,
307
- });
308
- }
309
- }
310
- return false;
311
- }
312
- /**
313
- * Filter mods based on priority order for same-attribute conflicts.
314
- * If a boolean selector has higher priority than value selectors for the same attribute,
315
- * remove the value selectors (they would be shadowed by the boolean).
316
- *
317
- * Priority is determined by order in the styleStates (after reversal - earlier = higher priority)
318
- */
319
- function filterModsByPriority(allMods, styleStates, lookupStyles, parsedModsCache) {
320
- // Early exit: if no same-attribute conflicts exist, skip all the expensive work
321
- // This handles the common case efficiently without any cache overhead
322
- if (!hasSameAttributeConflicts(allMods, parsedModsCache)) {
323
- return allMods;
324
- }
325
- // Build priority map: for each mod, find its earliest appearance in any state list
326
- const modPriorities = new Map();
327
- for (const style of lookupStyles) {
328
- const states = styleStates[style];
329
- if (!states || states.length === 0)
330
- continue; // Skip empty states
331
- // states are already reversed (higher priority = lower index)
332
- for (let index = 0; index < states.length; index++) {
333
- const state = states[index];
334
- if (!state.mods || state.mods.length === 0)
335
- continue; // Skip empty mods
336
- for (const mod of state.mods) {
337
- const currentPriority = modPriorities.get(mod);
338
- if (currentPriority === undefined || index < currentPriority) {
339
- modPriorities.set(mod, index);
340
- }
341
- }
342
- }
343
- }
344
- // Group mods by attribute
345
- const attributeGroups = new Map();
346
- for (const mod of allMods) {
347
- const parsed = parsedModsCache.get(mod);
348
- if (!parsed)
349
- continue;
350
- const priority = modPriorities.get(mod);
351
- if (priority === undefined)
352
- continue;
353
- const isBool = parsed.value === 'true';
354
- let group = attributeGroups.get(parsed.attribute);
355
- if (!group) {
356
- group = [];
357
- attributeGroups.set(parsed.attribute, group);
358
- }
359
- group.push({
360
- mod,
361
- isBool,
362
- priority,
363
- });
364
- }
365
- // Filter: for each attribute, if boolean has higher priority than any value, remove values
366
- const modsToRemove = new Set();
367
- for (const [attribute, group] of attributeGroups.entries()) {
368
- // Only process attributes with more than one mod
369
- if (group.length <= 1)
370
- continue;
371
- const boolMods = group.filter((m) => m.isBool);
372
- const valueMods = group.filter((m) => !m.isBool);
373
- // Only check if we have both types
374
- if (boolMods.length === 0 || valueMods.length === 0)
375
- continue;
376
- // Check if any boolean has higher priority (lower index) than all values
377
- for (const boolMod of boolMods) {
378
- const hasHigherPriorityThanAllValues = valueMods.every((valueMod) => boolMod.priority < valueMod.priority);
379
- if (hasHigherPriorityThanAllValues) {
380
- // This boolean shadows all value mods for this attribute
381
- valueMods.forEach((valueMod) => modsToRemove.add(valueMod.mod));
382
- }
383
- }
384
- }
385
- return allMods.filter((mod) => !modsToRemove.has(mod));
386
- }
387
- /**
388
- * Explode a style handler result into logical rules with proper mapping
389
- * Phase 1: Handler fan-out ($ selectors)
390
- * Phase 2: Rule materialization
391
- */
392
- function explodeHandlerResult(result, selectorSuffix = '', atRuleContext, ownMods, negatedOwnMods) {
393
- if (!result)
394
- return [];
395
- // Phase 1: Handler fan-out - normalize to array
396
- const resultArray = Array.isArray(result) ? result : [result];
397
- const logicalRules = [];
398
- for (const item of resultArray) {
399
- if (!item || typeof item !== 'object')
400
- continue;
401
- const { $, ...styleProps } = item;
402
- // Build declarations from style props
403
- const declarations = {};
404
- for (const [prop, value] of Object.entries(styleProps)) {
405
- if (value != null && value !== '') {
406
- declarations[prop] = String(value);
407
- }
408
- }
409
- if (Object.keys(declarations).length === 0)
410
- continue;
411
- // Phase 2: Selector fan-out - handle $ suffixes
412
- // IMPORTANT: If we are already in a pseudo-element context (contains '::'),
413
- // CSS does not allow further descendant/child selectors (e.g., '>*') after
414
- // a pseudo-element. In such cases we must ignore the `$`-derived selectors.
415
- const inPseudoElementContext = selectorSuffix.includes('::');
416
- if (inPseudoElementContext && $) {
417
- // Skip this item entirely to avoid producing invalid selectors like
418
- // `.t0::before>*`.
419
- continue;
420
- }
421
- const suffixes = $
422
- ? (Array.isArray($) ? $ : [$]).map((s) => selectorSuffix + normalizeDollarSelectorSuffix(String(s)))
423
- : [selectorSuffix];
424
- // Create logical rules for each suffix
425
- for (const suffix of suffixes) {
426
- const rule = {
427
- selectorSuffix: suffix,
428
- declarations: { ...declarations },
429
- };
430
- if (atRuleContext) {
431
- rule.atRuleContext = atRuleContext;
432
- }
433
- if (ownMods?.length) {
434
- rule.ownMods = ownMods;
435
- }
436
- if (negatedOwnMods?.length) {
437
- rule.negatedOwnMods = negatedOwnMods;
438
- }
439
- logicalRules.push(rule);
440
- }
441
- }
442
- return logicalRules;
443
- }
444
- /**
445
- * Convert handler result (CSSMap) to CSS string for global injection
446
- */
447
- function convertHandlerResultToCSS(result, selectorSuffix = '') {
448
- if (!result)
449
- return '';
450
- if (Array.isArray(result)) {
451
- const fragments = [];
452
- for (const item of result) {
453
- const itemCSS = convertHandlerResultToCSS(item, selectorSuffix);
454
- if (itemCSS) {
455
- fragments.push(itemCSS);
456
- }
457
- }
458
- return fragments.join('');
459
- }
460
- const { $, css, ...styleProps } = result;
461
- const styleFragments = [];
462
- // Process style properties using array accumulation
463
- for (const [styleName, value] of Object.entries(styleProps)) {
464
- if (Array.isArray(value)) {
465
- // Handle array values
466
- for (const val of value) {
467
- if (val) {
468
- styleFragments.push(`${styleName}: ${val};\n`);
469
- }
470
- }
471
- }
472
- else if (value) {
473
- // Handle single values
474
- styleFragments.push(`${styleName}: ${value};\n`);
475
- }
476
- }
477
- let renderedStyles = styleFragments.join('');
478
- if (css) {
479
- renderedStyles = css + '\n' + renderedStyles;
480
- }
481
- if (!renderedStyles) {
482
- return '';
483
- }
484
- const finalSelectorSuffix = selectorSuffix || '';
485
- if (Array.isArray($)) {
486
- const ruleFragments = [];
487
- for (const suffix of $) {
488
- const normalized = suffix
489
- ? normalizeDollarSelectorSuffix(String(suffix))
490
- : '';
491
- ruleFragments.push(`&${finalSelectorSuffix}${normalized}{\n${renderedStyles}}\n`);
492
- }
493
- return ruleFragments.join('');
494
- }
495
- const normalizedSingle = $ ? normalizeDollarSelectorSuffix(String($)) : '';
496
- return `&${finalSelectorSuffix}${normalizedSingle}{\n${renderedStyles}}\n`;
497
- }
498
- /**
499
- * Process state maps with mod combinations and generate logical rules.
500
- * This consolidates the common logic for handling mod combinations, priority filtering,
501
- * contradiction checking, and selector optimization.
502
- *
503
- * Enhanced to support advanced states (media queries, container queries, etc.)
504
- */
505
- function processStateMapsWithModCombinations(styleStates, lookupStyles, handler, parentSuffix, allLogicalRules) {
506
- // Collect all mods and check for advanced states
507
- const allMods = [];
508
- const seenMods = new Set();
509
- let hasAdvancedStates = false;
510
- // Collect all unique at-rule contexts from states
511
- const atRuleContextsByKey = new Map();
512
- for (const style of lookupStyles) {
513
- const states = styleStates[style];
514
- if (!states)
515
- continue;
516
- for (const state of states) {
517
- if (state.mods) {
518
- for (const mod of state.mods) {
519
- if (!seenMods.has(mod)) {
520
- seenMods.add(mod);
521
- allMods.push(mod);
522
- }
523
- }
524
- }
525
- // Check for any advanced state context (atRuleContext or ownMods)
526
- if (state.atRuleContext ||
527
- state.ownMods?.length ||
528
- state.negatedOwnMods?.length) {
529
- hasAdvancedStates = true;
530
- if (state.atRuleContext) {
531
- // Create a key for this context to deduplicate
532
- const ctxKey = JSON.stringify(state.atRuleContext);
533
- if (!atRuleContextsByKey.has(ctxKey)) {
534
- atRuleContextsByKey.set(ctxKey, state.atRuleContext);
535
- }
536
- }
537
- }
538
- }
539
- }
540
- // Handle case with no mods but possibly advanced states
541
- if (allMods.length === 0) {
542
- if (!hasAdvancedStates) {
543
- // No mods, no advanced states - just call handler with default state values
544
- const stateProps = {};
545
- lookupStyles.forEach((style) => {
546
- const states = styleStates[style];
547
- if (states && states.length > 0) {
548
- stateProps[style] = states[0].value;
549
- }
550
- });
551
- const result = handler(stateProps);
552
- if (!result)
553
- return;
554
- const logicalRules = explodeHandlerResult(result, parentSuffix);
555
- allLogicalRules.push(...logicalRules);
556
- return;
557
- }
558
- // Has advanced states but no mods - generate rules for each at-rule context
559
- processAdvancedStatesOnly(styleStates, lookupStyles, handler, parentSuffix, allLogicalRules);
560
- return;
561
- }
562
- // Parse all mods once and share the cache across all operations
563
- const parsedModsCache = new Map();
564
- for (const mod of allMods) {
565
- parsedModsCache.set(mod, parseAttributeSelector(getModSelector(mod)));
566
- }
567
- // Apply priority-based filtering for same-attribute boolean vs value conflicts
568
- const filteredMods = filterModsByPriority(allMods, styleStates, lookupStyles, parsedModsCache);
569
- // Precompute attribute maps once for all combinations
570
- const attributeMaps = buildAttributeMaps([], filteredMods, parsedModsCache);
571
- // Generate combinations with conflict-aware pruning
572
- const conflictChecker = createAttributeConflictChecker(attributeMaps.parsedMods);
573
- const combinations = getModCombinationsIterative(filteredMods, true, conflictChecker);
574
- // Process each mod combination
575
- combinations.forEach((modCombination) => {
576
- const stateProps = {};
577
- // Find matching state for each style
578
- lookupStyles.forEach((style) => {
579
- const states = styleStates[style];
580
- const matchingState = states.find((state) => computeState(state.model, (mod) => modCombination.includes(mod)));
581
- if (matchingState) {
582
- stateProps[style] = matchingState.value;
583
- }
584
- });
585
- // Use precomputed maps for efficient not selector optimization
586
- const currentMaps = buildAttributeMaps(modCombination, filteredMods, parsedModsCache);
587
- // Compute raw NOTs for contradiction check (before optimization)
588
- const rawNotMods = filteredMods.filter((mod) => !modCombination.includes(mod));
589
- // Check for contradictions between positive and negative selectors
590
- if (hasContradiction(modCombination, rawNotMods, currentMaps.parsedMods)) {
591
- return; // Skip this invalid combination
592
- }
593
- // Optimize NOT selectors afterwards (pure simplification)
594
- const optimizedNotMods = optimizeNotSelectors(modCombination, filteredMods, currentMaps);
595
- // Build the mod selector string
596
- const modsSelectors = `${modCombination
597
- .map(getModSelector)
598
- .join('')}${optimizedNotMods
599
- .map((mod) => {
600
- const sel = getModSelector(mod);
601
- return sel.startsWith(':not(') ? sel.slice(5, -1) : `:not(${sel})`;
602
- })
603
- .join('')}`;
604
- // Simple non-responsive state values
605
- const result = handler(stateProps);
606
- if (!result)
607
- return;
608
- const logical = explodeHandlerResult(result, `${modsSelectors}${parentSuffix}`);
609
- allLogicalRules.push(...logical);
610
- });
611
- }
612
- function processAdvancedStatesOnly(styleStates, lookupStyles, handler, parentSuffix, allLogicalRules) {
613
- // Group states by their at-rule context AND ownMods
614
- const contextGroups = new Map();
615
- for (const style of lookupStyles) {
616
- const states = styleStates[style];
617
- if (!states)
618
- continue;
619
- for (const state of states) {
620
- // Create a key that includes both atRuleContext and ownMods
621
- const ctxKey = state.atRuleContext
622
- ? JSON.stringify(state.atRuleContext)
623
- : '';
624
- const ownModsKey = state.ownMods?.join(',') || '';
625
- const negatedOwnModsKey = state.negatedOwnMods?.join(',') || '';
626
- const groupKey = `${ctxKey}||${ownModsKey}||${negatedOwnModsKey}`;
627
- if (!contextGroups.has(groupKey)) {
628
- contextGroups.set(groupKey, {
629
- context: state.atRuleContext,
630
- ownMods: state.ownMods,
631
- negatedOwnMods: state.negatedOwnMods,
632
- states: [],
633
- });
634
- }
635
- contextGroups.get(groupKey).states.push({ style, state });
636
- }
637
- }
638
- // Generate rules for each context group
639
- for (const [, group] of contextGroups) {
640
- const stateProps = {};
641
- // For each style, find the value for this context
642
- for (const { style, state } of group.states) {
643
- stateProps[style] = state.value;
644
- }
645
- // Fill in missing styles with their default values
646
- for (const style of lookupStyles) {
647
- if (!(style in stateProps)) {
648
- const states = styleStates[style];
649
- if (states && states.length > 0) {
650
- // Use the first state without at-rule context, or the last state
651
- const defaultState = states.find((s) => !s.atRuleContext) ||
652
- states[states.length - 1];
653
- stateProps[style] = defaultState.value;
654
- }
655
- }
656
- }
657
- const result = handler(stateProps);
658
- if (!result)
659
- continue;
660
- const logical = explodeHandlerResult(result, parentSuffix, group.context, group.ownMods, group.negatedOwnMods);
661
- allLogicalRules.push(...logical);
662
- }
663
- }
664
- /**
665
- * Convert logical rules to final StyleResult format
666
- */
667
- function materializeRules(logicalRules, className) {
668
- return logicalRules.map((rule) => {
669
- // Generate base selector
670
- let selector = `.${className}${rule.selectorSuffix}`;
671
- // Increase specificity for tasty class selectors by duplicating the class
672
- if (/^t\d+$/.test(className)) {
673
- selector = `.${className}${selector}`;
674
- }
675
- // Handle @own mods by appending to the selector (after sub-element)
676
- if (rule.ownMods?.length || rule.negatedOwnMods?.length) {
677
- // Build own mod selectors
678
- const ownModSelectors = [];
679
- for (const mod of rule.ownMods || []) {
680
- ownModSelectors.push(getModSelector(mod));
681
- }
682
- for (const mod of rule.negatedOwnMods || []) {
683
- ownModSelectors.push(`:not(${getModSelector(mod)})`);
684
- }
685
- selector = selector + ownModSelectors.join('');
686
- }
687
- // Handle root states by prefixing selector
688
- if (rule.atRuleContext?.rootStates?.length) {
689
- const rootPrefix = rule.atRuleContext.rootStates
690
- .map((rs) => `:root${rs}`)
691
- .join('');
692
- selector = `${rootPrefix} ${selector}`;
693
- }
694
- else if (rule.atRuleContext?.negatedRootStates?.length) {
695
- // Handle negated root states (for non-overlapping default rules)
696
- const negatedPrefix = `:root${rule.atRuleContext.negatedRootStates.join('')}`;
697
- selector = `${negatedPrefix} ${selector}`;
698
- }
699
- const declarations = Object.entries(rule.declarations)
700
- .map(([prop, value]) => `${prop}: ${value};`)
701
- .join(' ');
702
- const result = {
703
- selector,
704
- declarations,
705
- };
706
- // Convert atRuleContext to atRules array for the injector
707
- const atRules = buildAtRulesArray(rule.atRuleContext);
708
- if (atRules.length > 0) {
709
- result.atRules = atRules;
710
- }
711
- return result;
712
- });
713
- }
714
- /**
715
- * Build an array of at-rule strings from AtRuleContext
716
- */
717
- function buildAtRulesArray(ctx) {
718
- if (!ctx)
719
- return [];
720
- const atRules = [];
721
- // Add media queries (combined with 'and')
722
- if (ctx.media?.length) {
723
- const mediaConditions = ctx.media.join(' and ');
724
- atRules.push(`@media ${mediaConditions}`);
725
- }
726
- // Add container queries (nested)
727
- if (ctx.container?.length) {
728
- for (const c of ctx.container) {
729
- const name = c.name ? `${c.name} ` : '';
730
- // Don't double-wrap with parentheses if condition already has them
731
- const condition = c.condition.startsWith('(') && c.condition.endsWith(')')
732
- ? c.condition
733
- : `(${c.condition})`;
734
- atRules.push(`@container ${name}${condition}`);
735
- }
736
- }
737
- // Add starting style
738
- if (ctx.startingStyle) {
739
- atRules.push('@starting-style');
740
- }
741
- return atRules;
742
- }
743
- /**
744
- * Core style processing logic that generates logical rules
745
- * Used by the unified renderStyles function
746
- */
747
- function generateLogicalRules(styles, parentSuffix = '') {
748
- const allLogicalRules = [];
749
- // Process styles recursively, preserving mod selectors and combining with nested selector suffixes
750
- function processStyles(currentStyles, parentSuffix = '') {
751
- const keys = Object.keys(currentStyles || {});
752
- const selectorKeys = keys.filter((key) => isSelector(key));
753
- // Recurse into nested selectors first to compute proper suffix chaining
754
- for (const key of selectorKeys) {
755
- const suffix = getSelector(key, currentStyles[key]);
756
- if (suffix && currentStyles[key]) {
757
- // Remove $ key to prevent it from being processed as a style property
758
- const { $: _omit, ...cleanedStyles } = currentStyles[key];
759
- processStyles(cleanedStyles, `${parentSuffix}${suffix}`);
760
- }
761
- }
762
- // Build handler queue for style properties at this level
763
- const handlerQueue = [];
764
- const seenHandlers = new Set();
765
- keys.forEach((styleName) => {
766
- if (isSelector(styleName))
767
- return;
768
- let handlers = STYLE_HANDLER_MAP[styleName];
769
- if (!handlers) {
770
- handlers = STYLE_HANDLER_MAP[styleName] = [createStyle(styleName)];
771
- }
772
- handlers.forEach((handler) => {
773
- if (seenHandlers.has(handler)) {
774
- return;
775
- }
776
- seenHandlers.add(handler);
777
- const lookupStyles = handler.__lookupStyles;
778
- const filteredStyleMap = lookupStyles.reduce((map, name) => {
779
- const value = currentStyles?.[name];
780
- if (value !== undefined) {
781
- map[name] = value;
782
- }
783
- return map;
784
- }, {});
785
- handlerQueue.push({
786
- handler,
787
- styleMap: filteredStyleMap,
788
- });
789
- });
790
- });
791
- // Process handlers
792
- handlerQueue.forEach(({ handler, styleMap }) => {
793
- const lookupStyles = handler.__lookupStyles;
794
- // Check if any values have state maps
795
- const hasStateMaps = lookupStyles.some((style) => {
796
- const value = styleMap[style];
797
- return value && typeof value === 'object' && !Array.isArray(value);
798
- });
799
- if (hasStateMaps) {
800
- // Build styleStates from styleMap
801
- const styleStates = {};
802
- lookupStyles.forEach((style) => {
803
- const value = styleMap[style];
804
- if (value && typeof value === 'object' && !Array.isArray(value)) {
805
- const { states } = styleStateMapToStyleStateDataList(value);
806
- styleStates[style] = states;
807
- }
808
- else {
809
- // Simple value, create a single state
810
- styleStates[style] = [{ mods: [], notMods: [], value }];
811
- }
812
- });
813
- // Use the consolidated helper for mod combination processing
814
- processStateMapsWithModCombinations(styleStates, lookupStyles, handler, parentSuffix, allLogicalRules);
815
- }
816
- else {
817
- // Simple case: no state maps, call handler directly
818
- const result = handler(styleMap);
819
- if (result) {
820
- const logical = explodeHandlerResult(result, parentSuffix);
821
- allLogicalRules.push(...logical);
822
- }
823
- }
824
- });
825
- }
826
- // Kick off processing from the root styles with empty suffix
827
- processStyles(styles, parentSuffix);
828
- return allLogicalRules;
829
- }
830
- /**
831
- * Optimize media ranges in logical rules to generate non-overlapping CSS rules.
832
- * Groups rules by selector suffix and applies range optimization to media-only rules.
833
- */
834
- function optimizeMediaRangesInRules(rules) {
835
- // Group rules by selector suffix (ignoring atRuleContext)
836
- const groups = new Map();
837
- for (const rule of rules) {
838
- const key = rule.selectorSuffix;
839
- if (!groups.has(key)) {
840
- groups.set(key, []);
841
- }
842
- groups.get(key).push(rule);
843
- }
844
- const result = [];
845
- for (const [, groupRules] of groups) {
846
- // Separate media-only rules from others
847
- const mediaOnlyRules = [];
848
- const otherRules = [];
849
- for (const rule of groupRules) {
850
- const ctx = rule.atRuleContext;
851
- // Check if this is a media-only rule (no container, no root states, no starting style)
852
- if (ctx?.media?.length &&
853
- !ctx.container?.length &&
854
- !ctx.rootStates?.length &&
855
- !ctx.startingStyle) {
856
- mediaOnlyRules.push(rule);
857
- }
858
- else if (!ctx?.media?.length &&
859
- !ctx?.container?.length &&
860
- !ctx?.rootStates?.length &&
861
- !ctx?.startingStyle) {
862
- // Default rule (no at-rules) - treat as "remaining" media range
863
- otherRules.push(rule);
864
- }
865
- else {
866
- // Other rules with mixed at-rule contexts
867
- result.push(rule);
868
- }
869
- }
870
- // If we have media rules, try to optimize them
871
- if (mediaOnlyRules.length > 0) {
872
- const defaultRule = otherRules.length > 0 ? otherRules[0] : undefined;
873
- const optimized = tryOptimizeMediaGroup(mediaOnlyRules, defaultRule);
874
- result.push(...optimized);
875
- }
876
- else {
877
- // No media rules to optimize, just pass through
878
- result.push(...otherRules);
879
- }
880
- }
881
- return result;
882
- }
883
- /**
884
- * Optimize container ranges in logical rules to generate non-overlapping CSS rules.
885
- * Similar to media query optimization but for @container queries.
886
- */
887
- function optimizeContainerRangesInRules(rules) {
888
- // Group rules by selector suffix (ignoring atRuleContext)
889
- const groups = new Map();
890
- for (const rule of rules) {
891
- const key = rule.selectorSuffix;
892
- if (!groups.has(key)) {
893
- groups.set(key, []);
894
- }
895
- groups.get(key).push(rule);
896
- }
897
- const result = [];
898
- for (const [, groupRules] of groups) {
899
- // Separate container-only rules from others
900
- const containerOnlyRules = [];
901
- const otherRules = [];
902
- for (const rule of groupRules) {
903
- const ctx = rule.atRuleContext;
904
- // Check if this is a container-only rule (no media, no root states, no starting style)
905
- if (ctx?.container?.length &&
906
- !ctx.media?.length &&
907
- !ctx.rootStates?.length &&
908
- !ctx.startingStyle) {
909
- containerOnlyRules.push(rule);
910
- }
911
- else if (!ctx?.media?.length &&
912
- !ctx?.container?.length &&
913
- !ctx?.rootStates?.length &&
914
- !ctx?.startingStyle) {
915
- // Default rule (no at-rules) - treat as "remaining" range
916
- otherRules.push(rule);
917
- }
918
- else {
919
- // Other rules with mixed at-rule contexts
920
- result.push(rule);
921
- }
922
- }
923
- // If we have container rules, try to optimize them
924
- if (containerOnlyRules.length > 0) {
925
- const defaultRule = otherRules.length > 0 ? otherRules[0] : undefined;
926
- const optimized = tryOptimizeContainerGroup(containerOnlyRules, defaultRule);
927
- result.push(...optimized);
928
- }
929
- else {
930
- // No container rules to optimize, just pass through
931
- result.push(...otherRules);
932
- }
933
- }
934
- return result;
935
- }
936
- /**
937
- * Check if a set of container conditions together cover all possible values.
938
- * Similar to checkIfConditionsCoverAllRanges but for container queries.
939
- */
940
- function checkIfContainerConditionsCoverAllRanges(containerRules) {
941
- let hasUnboundedLower = false;
942
- let hasUnboundedUpper = false;
943
- let conditionCount = 0;
944
- for (const rule of containerRules) {
945
- const container = rule.atRuleContext?.container?.[0];
946
- if (!container)
947
- continue;
948
- let conditionStr = container.condition;
949
- // Strip surrounding parentheses
950
- if (conditionStr.startsWith('(') && conditionStr.endsWith(')')) {
951
- conditionStr = conditionStr.slice(1, -1);
952
- }
953
- const parsed = parseMediaCondition(conditionStr);
954
- if (!parsed)
955
- continue;
956
- conditionCount++;
957
- if (parsed.type === 'simple') {
958
- const cond = parsed.condition;
959
- if ((cond.operator === '<' || cond.operator === '<=') &&
960
- cond.valueNumeric !== null) {
961
- hasUnboundedLower = true;
962
- }
963
- else if ((cond.operator === '>' || cond.operator === '>=') &&
964
- cond.valueNumeric !== null) {
965
- hasUnboundedUpper = true;
966
- }
967
- }
968
- else if (parsed.type === 'range') {
969
- // Range conditions don't contribute to unbounded ends
970
- // but do count towards condition count
971
- }
972
- }
973
- // If we have both ends covered and enough conditions, assume full coverage
974
- if (hasUnboundedLower && hasUnboundedUpper && conditionCount >= 3) {
975
- return true;
976
- }
977
- return false;
978
- }
979
- /**
980
- * Try to optimize a group of container-only rules with an optional default rule.
981
- * Returns optimized rules with non-overlapping container queries.
982
- */
983
- function tryOptimizeContainerGroup(containerRules, defaultRule) {
984
- // Parse container conditions and separate by type
985
- const parsedSimple = [];
986
- const otherRules = [];
987
- for (const rule of containerRules) {
988
- const container = rule.atRuleContext?.container?.[0];
989
- if (!container) {
990
- otherRules.push(rule);
991
- continue;
992
- }
993
- let conditionStr = container.condition;
994
- // Strip surrounding parentheses if present
995
- if (conditionStr.startsWith('(') && conditionStr.endsWith(')')) {
996
- conditionStr = conditionStr.slice(1, -1);
997
- }
998
- const parsed = parseMediaCondition(conditionStr);
999
- if (parsed && parsed.type === 'simple') {
1000
- parsedSimple.push({
1001
- rule,
1002
- condition: parsed.condition,
1003
- containerName: container.name,
1004
- });
1005
- }
1006
- else {
1007
- // Range or unparseable - pass through
1008
- otherRules.push(rule);
1009
- }
1010
- }
1011
- // Check if all simple conditions are on the same dimension and same container name
1012
- // AND there are no other rules (ranges)
1013
- if (parsedSimple.length > 0 && otherRules.length === 0) {
1014
- const dimension = parsedSimple[0].condition.dimension;
1015
- const containerName = parsedSimple[0].containerName;
1016
- const allSameDimensionAndName = parsedSimple.every((c) => c.condition.dimension === dimension &&
1017
- c.containerName === containerName);
1018
- if (allSameDimensionAndName) {
1019
- // All conditions are simple conditions on the same dimension
1020
- // Build a map for computeNonOverlappingRanges
1021
- const mediaConditionsMap = new Map();
1022
- const rulesByKey = new Map();
1023
- for (let i = 0; i < parsedSimple.length; i++) {
1024
- const key = `rule_${i}`;
1025
- mediaConditionsMap.set(key, parsedSimple[i].condition);
1026
- rulesByKey.set(key, parsedSimple[i].rule);
1027
- }
1028
- // Compute non-overlapping ranges
1029
- const defaultKey = defaultRule ? 'default' : null;
1030
- const optimizedRanges = computeNonOverlappingRanges(mediaConditionsMap, defaultKey);
1031
- // If optimization succeeded
1032
- if (optimizedRanges.length > 0) {
1033
- const result = [];
1034
- for (const range of optimizedRanges) {
1035
- const rangeCondition = rangeToMediaCondition(range, dimension);
1036
- const sourceRule = range.stateKey === 'default'
1037
- ? defaultRule
1038
- : rulesByKey.get(range.stateKey);
1039
- if (sourceRule) {
1040
- result.push({
1041
- selectorSuffix: sourceRule.selectorSuffix,
1042
- declarations: { ...sourceRule.declarations },
1043
- ownMods: sourceRule.ownMods,
1044
- negatedOwnMods: sourceRule.negatedOwnMods,
1045
- atRuleContext: {
1046
- container: [{ name: containerName, condition: rangeCondition }],
1047
- },
1048
- });
1049
- }
1050
- }
1051
- return result;
1052
- }
1053
- }
1054
- }
1055
- // For non-optimizable conditions, use NOT negation for the default
1056
- // But first check if the explicit conditions already cover all ranges
1057
- if (containerRules.length > 0 && defaultRule) {
1058
- // Check if explicit conditions cover all possible ranges
1059
- const coversAllRanges = checkIfContainerConditionsCoverAllRanges(containerRules);
1060
- if (coversAllRanges) {
1061
- // No need for default rule - explicit conditions cover everything
1062
- return [...containerRules];
1063
- }
1064
- const result = [...containerRules];
1065
- // Create negated conditions for the default rule
1066
- const negations = [];
1067
- for (const rule of containerRules) {
1068
- const container = rule.atRuleContext?.container?.[0];
1069
- if (!container)
1070
- continue;
1071
- // Use 'not (...)' for all conditions
1072
- const cond = container.condition;
1073
- negations.push(`not (${cond})`);
1074
- }
1075
- const combinedNegation = negations.filter(Boolean).join(' and ');
1076
- if (combinedNegation) {
1077
- // Get the container name from the first rule (they should all be the same)
1078
- const containerName = containerRules[0].atRuleContext?.container?.[0]?.name;
1079
- result.push({
1080
- ...defaultRule,
1081
- atRuleContext: {
1082
- container: [{ name: containerName, condition: combinedNegation }],
1083
- },
1084
- });
1085
- }
1086
- return result;
1087
- }
1088
- // No optimization possible, return as-is
1089
- return [
1090
- ...containerRules,
1091
- ...otherRules,
1092
- ...(defaultRule ? [defaultRule] : []),
1093
- ];
1094
- }
1095
- /**
1096
- * Check if a set of media conditions together cover all possible values.
1097
- * If so, there's no need to generate a default rule.
1098
- */
1099
- function checkIfConditionsCoverAllRanges(mediaRules) {
1100
- // Parse all conditions
1101
- const conditions = [];
1102
- let hasUnboundedLower = false; // e.g., width < 768px (covers 0 to 768)
1103
- let hasUnboundedUpper = false; // e.g., width >= 1024px (covers 1024 to ∞)
1104
- for (const rule of mediaRules) {
1105
- let mediaStr = rule.atRuleContext?.media?.[0];
1106
- if (!mediaStr)
1107
- continue;
1108
- // Strip surrounding parentheses
1109
- if (mediaStr.startsWith('(') && mediaStr.endsWith(')')) {
1110
- mediaStr = mediaStr.slice(1, -1);
1111
- }
1112
- const parsed = parseMediaCondition(mediaStr);
1113
- if (!parsed)
1114
- continue;
1115
- if (parsed.type === 'simple') {
1116
- const cond = parsed.condition;
1117
- if ((cond.operator === '<' || cond.operator === '<=') &&
1118
- cond.valueNumeric !== null) {
1119
- // Upper bound only: width < 768px covers 0 to 768
1120
- hasUnboundedLower = true;
1121
- conditions.push({
1122
- hasLowerBound: false,
1123
- hasUpperBound: true,
1124
- upperValue: cond.valueNumeric,
1125
- });
1126
- }
1127
- else if ((cond.operator === '>' || cond.operator === '>=') &&
1128
- cond.valueNumeric !== null) {
1129
- // Lower bound only: width >= 1024px covers 1024 to ∞
1130
- hasUnboundedUpper = true;
1131
- conditions.push({
1132
- hasLowerBound: true,
1133
- hasUpperBound: false,
1134
- lowerValue: cond.valueNumeric,
1135
- });
1136
- }
1137
- }
1138
- else if (parsed.type === 'range') {
1139
- const cond = parsed.condition;
1140
- if (cond.lower.valueNumeric !== null &&
1141
- cond.upper.valueNumeric !== null) {
1142
- conditions.push({
1143
- hasLowerBound: true,
1144
- hasUpperBound: true,
1145
- lowerValue: cond.lower.valueNumeric,
1146
- upperValue: cond.upper.valueNumeric,
1147
- });
1148
- }
1149
- }
1150
- }
1151
- // If we have both an unbounded lower (covers 0 to X) and unbounded upper (covers Y to ∞),
1152
- // and intermediate ranges fill the gap, then all values are covered.
1153
- if (hasUnboundedLower && hasUnboundedUpper && conditions.length >= 2) {
1154
- // Simple heuristic: if we have 3+ conditions with both unbounded ends,
1155
- // assume they cover all values
1156
- // A more rigorous check would verify no gaps exist
1157
- return conditions.length >= 3;
1158
- }
1159
- return false;
1160
- }
1161
- /**
1162
- * Try to optimize a group of media-only rules with an optional default rule.
1163
- * Returns optimized rules with non-overlapping media queries.
1164
- */
1165
- function tryOptimizeMediaGroup(mediaRules, defaultRule) {
1166
- // Parse media conditions and separate by type
1167
- const parsedSimple = [];
1168
- const otherRules = [];
1169
- for (const rule of mediaRules) {
1170
- let mediaStr = rule.atRuleContext?.media?.[0];
1171
- if (!mediaStr) {
1172
- otherRules.push(rule);
1173
- continue;
1174
- }
1175
- // Strip surrounding parentheses if present (buildAtRuleContext adds them)
1176
- if (mediaStr.startsWith('(') && mediaStr.endsWith(')')) {
1177
- mediaStr = mediaStr.slice(1, -1);
1178
- }
1179
- const parsed = parseMediaCondition(mediaStr);
1180
- if (parsed && parsed.type === 'simple') {
1181
- parsedSimple.push({ rule, condition: parsed.condition });
1182
- }
1183
- else {
1184
- // Range or unparseable - pass through
1185
- otherRules.push(rule);
1186
- }
1187
- }
1188
- // Check if all simple conditions are on the same dimension AND there are no other rules (ranges)
1189
- // We can only use the range optimizer when ALL conditions are simple (no pre-existing ranges)
1190
- if (parsedSimple.length > 0 && otherRules.length === 0) {
1191
- const dimension = parsedSimple[0].condition.dimension;
1192
- const allSameDimension = parsedSimple.every((c) => c.condition.dimension === dimension);
1193
- if (allSameDimension) {
1194
- // All conditions are simple conditions on the same dimension
1195
- // Build a map for computeNonOverlappingRanges
1196
- const mediaConditionsMap = new Map();
1197
- const rulesByKey = new Map();
1198
- for (let i = 0; i < parsedSimple.length; i++) {
1199
- const key = `rule_${i}`;
1200
- mediaConditionsMap.set(key, parsedSimple[i].condition);
1201
- rulesByKey.set(key, parsedSimple[i].rule);
1202
- }
1203
- // Compute non-overlapping ranges
1204
- const defaultKey = defaultRule ? 'default' : null;
1205
- const optimizedRanges = computeNonOverlappingRanges(mediaConditionsMap, defaultKey);
1206
- // If optimization succeeded
1207
- if (optimizedRanges.length > 0) {
1208
- const result = [];
1209
- for (const range of optimizedRanges) {
1210
- const mediaCondition = rangeToMediaCondition(range, dimension);
1211
- const isFromDefault = range.stateKey === 'default';
1212
- const sourceRule = isFromDefault
1213
- ? defaultRule
1214
- : rulesByKey.get(range.stateKey);
1215
- if (sourceRule) {
1216
- result.push({
1217
- selectorSuffix: sourceRule.selectorSuffix,
1218
- declarations: { ...sourceRule.declarations },
1219
- ownMods: sourceRule.ownMods,
1220
- negatedOwnMods: sourceRule.negatedOwnMods,
1221
- atRuleContext: { media: [mediaCondition] },
1222
- // Mark explicit media rules (not from default) - they should not be split by root states
1223
- isExplicitMedia: !isFromDefault,
1224
- });
1225
- }
1226
- }
1227
- return result;
1228
- }
1229
- }
1230
- }
1231
- // For non-optimizable conditions, use NOT negation for the default
1232
- // But first check if the explicit conditions already cover all ranges
1233
- if (mediaRules.length > 0 && defaultRule) {
1234
- // Check if explicit conditions cover all possible ranges
1235
- const coversAllRanges = checkIfConditionsCoverAllRanges(mediaRules);
1236
- // Mark all explicit media rules
1237
- const markedMediaRules = mediaRules.map((rule) => ({
1238
- ...rule,
1239
- isExplicitMedia: true,
1240
- }));
1241
- if (coversAllRanges) {
1242
- // No need for default rule - explicit conditions cover everything
1243
- return markedMediaRules;
1244
- }
1245
- const result = [...markedMediaRules];
1246
- // Create negated conditions for the default rule
1247
- const negations = [];
1248
- for (const rule of mediaRules) {
1249
- const cond = rule.atRuleContext?.media?.[0];
1250
- if (!cond)
1251
- continue;
1252
- // Use 'not (...)' for all conditions
1253
- negations.push(`not (${cond})`);
1254
- }
1255
- const combinedNegation = negations.filter(Boolean).join(' and ');
1256
- if (combinedNegation) {
1257
- result.push({
1258
- ...defaultRule,
1259
- atRuleContext: { media: [combinedNegation] },
1260
- // Default-derived rule, can be split by root states
1261
- isExplicitMedia: false,
1262
- });
1263
- }
1264
- return result;
1265
- }
1266
- // No optimization possible, return as-is
1267
- // Mark media rules as explicit
1268
- const markedMediaRules = mediaRules.map((rule) => ({
1269
- ...rule,
1270
- isExplicitMedia: true,
1271
- }));
1272
- return [
1273
- ...markedMediaRules,
1274
- ...otherRules,
1275
- ...(defaultRule ? [defaultRule] : []),
1276
- ];
1277
- }
1278
- /**
1279
- * Optimize root states in logical rules to generate non-overlapping CSS rules.
1280
- * For default rules, adds negated root states to make them non-overlapping with explicit root rules.
1281
- */
1282
- function optimizeRootStatesInRules(rules) {
1283
- // Group rules by selector suffix and media context
1284
- const groups = new Map();
1285
- for (const rule of rules) {
1286
- const mediaKey = rule.atRuleContext?.media?.join(',') || '';
1287
- const key = `${rule.selectorSuffix}||${mediaKey}`;
1288
- if (!groups.has(key)) {
1289
- groups.set(key, []);
1290
- }
1291
- groups.get(key).push(rule);
1292
- }
1293
- const result = [];
1294
- for (const [, groupRules] of groups) {
1295
- // Separate root state rules from default rules
1296
- const rootStateRules = [];
1297
- const defaultRules = [];
1298
- for (const rule of groupRules) {
1299
- if (rule.atRuleContext?.rootStates?.length) {
1300
- rootStateRules.push(rule);
1301
- }
1302
- else if (!rule.atRuleContext?.container?.length &&
1303
- !rule.atRuleContext?.startingStyle) {
1304
- // Default rule (may have media but no root/container/starting)
1305
- defaultRules.push(rule);
1306
- }
1307
- else {
1308
- result.push(rule);
1309
- }
1310
- }
1311
- // Collect all unique root state selectors
1312
- const allRootSelectors = new Set();
1313
- for (const rule of rootStateRules) {
1314
- for (const rs of rule.atRuleContext?.rootStates || []) {
1315
- allRootSelectors.add(rs);
1316
- }
1317
- }
1318
- // Add root state rules as-is
1319
- result.push(...rootStateRules);
1320
- // For default rules, add negated root states
1321
- for (const defaultRule of defaultRules) {
1322
- if (allRootSelectors.size > 0) {
1323
- const negatedRootStates = Array.from(allRootSelectors).map((rs) => `:not(${rs})`);
1324
- result.push({
1325
- ...defaultRule,
1326
- atRuleContext: {
1327
- ...defaultRule.atRuleContext,
1328
- negatedRootStates,
1329
- },
1330
- });
1331
- }
1332
- else {
1333
- result.push(defaultRule);
1334
- }
1335
- }
1336
- }
1337
- return result;
1338
- }
1339
- /**
1340
- * Cross-multiply media queries with root states to avoid overlapping.
1341
- * When we have both:
1342
- * - Media rules: @media (width < 600px) { ... }
1343
- * - Root rules: :root[data-theme="dark"] { ... }
1344
- * They overlap! This function wraps root-only rules with the same media ranges
1345
- * to make them non-overlapping.
1346
- *
1347
- * IMPORTANT: Only default-derived media rules (isExplicitMedia=false) should be
1348
- * split by root states. Explicit @media() rules apply to all themes.
1349
- */
1350
- function crossMultiplyMediaAndRootStates(rules) {
1351
- // Group rules by selectorSuffix
1352
- const groups = new Map();
1353
- for (const rule of rules) {
1354
- const key = rule.selectorSuffix;
1355
- if (!groups.has(key)) {
1356
- groups.set(key, []);
1357
- }
1358
- groups.get(key).push(rule);
1359
- }
1360
- const result = [];
1361
- for (const [, groupRules] of groups) {
1362
- // Categorize rules
1363
- const explicitMediaRules = []; // Explicit @media rules - apply to all themes
1364
- const defaultDerivedMediaRules = []; // Default-derived media rules - can be split by root
1365
- const rootOnlyRules = []; // Has root, no media
1366
- const combinedRules = []; // Has both
1367
- const otherRules = []; // Neither (or has container/starting)
1368
- for (const rule of groupRules) {
1369
- const hasMedia = !!rule.atRuleContext?.media?.length;
1370
- const hasRoot = !!rule.atRuleContext?.rootStates?.length;
1371
- const hasContainer = !!rule.atRuleContext?.container?.length;
1372
- const hasStarting = !!rule.atRuleContext?.startingStyle;
1373
- if (hasContainer || hasStarting) {
1374
- // Don't touch container or starting rules
1375
- otherRules.push(rule);
1376
- }
1377
- else if (hasMedia && hasRoot) {
1378
- combinedRules.push(rule);
1379
- }
1380
- else if (hasMedia && !hasRoot) {
1381
- // Separate explicit vs default-derived media rules
1382
- if (rule.isExplicitMedia) {
1383
- explicitMediaRules.push(rule);
1384
- }
1385
- else {
1386
- defaultDerivedMediaRules.push(rule);
1387
- }
1388
- }
1389
- else if (hasRoot && !hasMedia) {
1390
- rootOnlyRules.push(rule);
1391
- }
1392
- else {
1393
- otherRules.push(rule);
1394
- }
1395
- }
1396
- // Explicit media rules go straight through - they apply to ALL themes
1397
- result.push(...explicitMediaRules);
1398
- // If we have both default-derived media rules and root-only rules, cross-multiply
1399
- if (defaultDerivedMediaRules.length > 0 && rootOnlyRules.length > 0) {
1400
- // Collect all unique media conditions from DEFAULT-DERIVED rules only
1401
- const defaultDerivedMediaConditions = new Set();
1402
- for (const rule of defaultDerivedMediaRules) {
1403
- for (const mc of rule.atRuleContext?.media || []) {
1404
- defaultDerivedMediaConditions.add(mc);
1405
- }
1406
- }
1407
- // For each root-only rule, create copies for each DEFAULT-DERIVED media range
1408
- for (const rootRule of rootOnlyRules) {
1409
- for (const mediaCondition of defaultDerivedMediaConditions) {
1410
- result.push({
1411
- ...rootRule,
1412
- atRuleContext: {
1413
- ...rootRule.atRuleContext,
1414
- media: [mediaCondition],
1415
- },
1416
- });
1417
- }
1418
- }
1419
- // Keep default-derived media rules - they will get root negation in the next step
1420
- result.push(...defaultDerivedMediaRules);
1421
- }
1422
- else {
1423
- // No cross-multiplication needed, pass through
1424
- result.push(...defaultDerivedMediaRules);
1425
- result.push(...rootOnlyRules);
1426
- }
1427
- // Pass through combined and other rules
1428
- result.push(...combinedRules);
1429
- result.push(...otherRules);
1430
- }
1431
- return result;
1432
- }
1433
- /**
1434
- * Optimize @own mods in logical rules.
1435
- * For default rules with no ownMods, adds negated ownMods to make them non-overlapping.
1436
- */
1437
- function optimizeOwnModsInRules(rules) {
1438
- // Group rules by selector suffix (for sub-element context)
1439
- const groups = new Map();
1440
- for (const rule of rules) {
1441
- const key = `${rule.selectorSuffix}||${JSON.stringify(rule.atRuleContext || {})}`;
1442
- if (!groups.has(key)) {
1443
- groups.set(key, []);
1444
- }
1445
- groups.get(key).push(rule);
1446
- }
1447
- const result = [];
1448
- for (const [, groupRules] of groups) {
1449
- // Separate rules with ownMods from default rules
1450
- const ownModRules = [];
1451
- const defaultRules = [];
1452
- for (const rule of groupRules) {
1453
- if (rule.ownMods?.length) {
1454
- ownModRules.push(rule);
1455
- }
1456
- else if (!rule.negatedOwnMods?.length) {
1457
- defaultRules.push(rule);
1458
- }
1459
- else {
1460
- result.push(rule);
1461
- }
1462
- }
1463
- // Collect all unique ownMods
1464
- const allOwnMods = new Set();
1465
- for (const rule of ownModRules) {
1466
- for (const mod of rule.ownMods || []) {
1467
- allOwnMods.add(mod);
1468
- }
1469
- }
1470
- // Add ownMod rules as-is
1471
- result.push(...ownModRules);
1472
- // For default rules, add negated ownMods
1473
- for (const defaultRule of defaultRules) {
1474
- if (allOwnMods.size > 0) {
1475
- result.push({
1476
- ...defaultRule,
1477
- negatedOwnMods: Array.from(allOwnMods),
1478
- });
1479
- }
1480
- else {
1481
- result.push(defaultRule);
1482
- }
1483
- }
1484
- }
1485
- return result;
1486
- }
1487
- export function renderStyles(styles, classNameOrSelector) {
1488
- const directSelector = !!classNameOrSelector;
1489
- if (!styles) {
1490
- return directSelector ? [] : { rules: [] };
1491
- }
1492
- // Generate logical rules using shared pipeline (memoized per styles)
1493
- const stylesKey = stringifyStyles(styles);
1494
- let allLogicalRules = logicalRulesCache.get(stylesKey);
1495
- if (!allLogicalRules) {
1496
- let rules = generateLogicalRules(styles);
1497
- // Apply optimizations in order: media ranges -> container ranges -> cross-multiply -> root states -> own mods
1498
- rules = optimizeMediaRangesInRules(rules);
1499
- rules = optimizeContainerRangesInRules(rules);
1500
- rules = crossMultiplyMediaAndRootStates(rules);
1501
- rules = optimizeRootStatesInRules(rules);
1502
- rules = optimizeOwnModsInRules(rules);
1503
- allLogicalRules = rules;
1504
- logicalRulesCache.set(stylesKey, allLogicalRules);
1505
- }
1506
- if (directSelector) {
1507
- // Direct selector mode: convert logical rules directly to StyleResult format
1508
- if (!classNameOrSelector) {
1509
- throw new Error('directSelector mode requires classNameOrSelector');
1510
- }
1511
- return allLogicalRules.map((rule) => {
1512
- // Replace & with the actual selector or append suffix to selector
1513
- let finalSelector = rule.selectorSuffix
1514
- ? `${classNameOrSelector}${rule.selectorSuffix}`
1515
- : classNameOrSelector;
1516
- // Increase specificity for tasty class selectors by duplicating the class
1517
- if (finalSelector.startsWith('.') && /^\.t\d+/.test(finalSelector)) {
1518
- const classMatch = finalSelector.match(/^\.t\d+/);
1519
- if (classMatch) {
1520
- const baseClass = classMatch[0];
1521
- finalSelector = baseClass + finalSelector;
1522
- }
1523
- }
1524
- const declarations = Object.entries(rule.declarations)
1525
- .map(([prop, value]) => `${prop}: ${value};`)
1526
- .join(' ');
1527
- return {
1528
- selector: finalSelector,
1529
- declarations,
1530
- };
1531
- });
1532
- }
1533
- // Standard mode: use accumulation and materialization with className
1534
- const accumulatedRules = new Map();
1535
- for (const rule of allLogicalRules) {
1536
- // Create a key based on selectorSuffix AND atRuleContext (to avoid merging rules with different at-rules)
1537
- const atRuleKey = rule.atRuleContext
1538
- ? JSON.stringify(rule.atRuleContext)
1539
- : '';
1540
- const ownModsKey = rule.ownMods?.join(',') || '';
1541
- const negatedOwnModsKey = rule.negatedOwnMods?.join(',') || '';
1542
- const ruleKey = `${rule.selectorSuffix}||${atRuleKey}||${ownModsKey}||${negatedOwnModsKey}`;
1543
- const existing = accumulatedRules.get(ruleKey);
1544
- if (existing) {
1545
- // Merge declarations from this rule into the existing one
1546
- Object.assign(existing.declarations, rule.declarations);
1547
- }
1548
- else {
1549
- // Create a new accumulated rule - preserve atRuleContext, ownMods, negatedOwnMods
1550
- accumulatedRules.set(ruleKey, {
1551
- selectorSuffix: rule.selectorSuffix,
1552
- declarations: { ...rule.declarations },
1553
- atRuleContext: rule.atRuleContext,
1554
- ownMods: rule.ownMods,
1555
- negatedOwnMods: rule.negatedOwnMods,
1556
- });
1557
- }
1558
- }
1559
- // If no className provided, return rules with needsClassName flag
1560
- if (!classNameOrSelector) {
1561
- const materializedRules = Array.from(accumulatedRules.values()).map((rule) => {
1562
- const declarations = Object.entries(rule.declarations)
1563
- .map(([prop, value]) => `${prop}: ${value};`)
1564
- .join(' ');
1565
- // Build selector with @own mods if present
1566
- let selector = rule.selectorSuffix || '';
1567
- if (rule.ownMods?.length || rule.negatedOwnMods?.length) {
1568
- const ownModSelectors = [];
1569
- for (const mod of rule.ownMods || []) {
1570
- ownModSelectors.push(getModSelector(mod));
1571
- }
1572
- for (const mod of rule.negatedOwnMods || []) {
1573
- ownModSelectors.push(`:not(${getModSelector(mod)})`);
1574
- }
1575
- selector = selector + ownModSelectors.join('');
1576
- }
1577
- // Compute rootPrefix for root states
1578
- let rootPrefix;
1579
- if (rule.atRuleContext?.rootStates?.length) {
1580
- rootPrefix = rule.atRuleContext.rootStates
1581
- .map((rs) => `:root${rs}`)
1582
- .join('');
1583
- }
1584
- else if (rule.atRuleContext?.negatedRootStates?.length) {
1585
- rootPrefix = `:root${rule.atRuleContext.negatedRootStates.join('')}`;
1586
- }
1587
- // Build at-rules array
1588
- const atRules = buildAtRulesArray(rule.atRuleContext);
1589
- const result = {
1590
- selector,
1591
- declarations,
1592
- needsClassName: true, // Flag for injector to prepend className
1593
- };
1594
- if (rootPrefix) {
1595
- result.rootPrefix = rootPrefix;
1596
- }
1597
- if (atRules.length > 0) {
1598
- result.atRules = atRules;
1599
- }
1600
- return result;
1601
- });
1602
- return {
1603
- rules: materializedRules,
1604
- };
1605
- }
1606
- // Materialize the accumulated logical rules into final format
1607
- const finalRulesRaw = materializeRules(Array.from(accumulatedRules.values()), classNameOrSelector);
1608
- // Simplified deduplication (should be much less work now)
1609
- const seen = new Set();
1610
- const finalRules = finalRulesRaw.filter((rule) => {
1611
- const at = rule.atRules && rule.atRules.length ? `@${rule.atRules.join('|')}` : '';
1612
- const key = `${rule.selector}|${rule.declarations}|${at}`;
1613
- if (seen.has(key))
1614
- return false;
1615
- seen.add(key);
1616
- return true;
1617
- });
1618
- return {
1619
- rules: finalRules,
1620
- className: classNameOrSelector,
1621
- };
1622
- }
1623
-
1624
-