@cube-dev/ui-kit 0.154.1 → 0.155.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (522) hide show
  1. package/dist/CHANGELOG.md +35 -0
  2. package/dist/_internal/hooks/use-chained-callback.js +1 -1
  3. package/dist/_internal/hooks/use-debounced-value.js +1 -1
  4. package/dist/_internal/hooks/use-deprecation-warning.js +1 -1
  5. package/dist/_internal/hooks/use-event.js +1 -1
  6. package/dist/_internal/hooks/use-is-first-render.js +1 -1
  7. package/dist/_internal/hooks/use-sync-ref.js +1 -1
  8. package/dist/_internal/hooks/use-timer/timer.js +1 -1
  9. package/dist/_internal/hooks/use-timer/use-timer.js +1 -1
  10. package/dist/_internal/hooks/use-warn.js +1 -1
  11. package/dist/components/Block.js +1 -1
  12. package/dist/components/CollectionItem.js +1 -1
  13. package/dist/components/GlobalStyles.js +1 -1
  14. package/dist/components/GridProvider.js +1 -1
  15. package/dist/components/HiddenInput.js +1 -1
  16. package/dist/components/Root.js +1 -1
  17. package/dist/components/actions/Action/Action.js +1 -1
  18. package/dist/components/actions/Banner/Banner.js +1 -1
  19. package/dist/components/actions/Button/Button.js +1 -1
  20. package/dist/components/actions/ButtonGroup/ButtonGroup.js +1 -1
  21. package/dist/components/actions/ButtonSplit/ButtonSplit.js +1 -1
  22. package/dist/components/actions/ButtonSplit/context.js +1 -1
  23. package/dist/components/actions/CommandMenu/CommandMenu.js +1 -1
  24. package/dist/components/actions/CommandMenu/styled.js +1 -1
  25. package/dist/components/actions/ItemAction/ItemAction.js +1 -1
  26. package/dist/components/actions/ItemActionContext.js +1 -1
  27. package/dist/components/actions/ItemButton/ItemButton.js +1 -1
  28. package/dist/components/actions/Link/Link.js +1 -1
  29. package/dist/components/actions/Menu/Menu.js +1 -1
  30. package/dist/components/actions/Menu/MenuItem.js +1 -1
  31. package/dist/components/actions/Menu/MenuSection.js +1 -1
  32. package/dist/components/actions/Menu/MenuTrigger.js +1 -1
  33. package/dist/components/actions/Menu/SubMenuTrigger.js +1 -1
  34. package/dist/components/actions/Menu/SubmenuTriggerContext.js +1 -1
  35. package/dist/components/actions/Menu/context.js +1 -1
  36. package/dist/components/actions/Menu/styled.js +1 -1
  37. package/dist/components/actions/index.js +1 -1
  38. package/dist/components/actions/use-action.js +1 -1
  39. package/dist/components/actions/use-anchored-menu.js +1 -1
  40. package/dist/components/actions/use-context-menu.js +1 -1
  41. package/dist/components/content/ActiveZone/ActiveZone.js +1 -1
  42. package/dist/components/content/Alert/Alert.js +1 -1
  43. package/dist/components/content/Alert/use-alert.js +1 -1
  44. package/dist/components/content/Avatar/Avatar.js +1 -1
  45. package/dist/components/content/Badge/Badge.js +1 -1
  46. package/dist/components/content/Card/Card.js +1 -1
  47. package/dist/components/content/Content.js +1 -1
  48. package/dist/components/content/CopyPasteBlock/CopyPasteBlock.js +1 -1
  49. package/dist/components/content/CopySnippet/CopySnippet.js +1 -1
  50. package/dist/components/content/Disclosure/Disclosure.js +1 -1
  51. package/dist/components/content/Divider.js +1 -1
  52. package/dist/components/content/Footer.js +1 -1
  53. package/dist/components/content/Header.js +1 -1
  54. package/dist/components/content/HotKeys/HotKeys.js +1 -1
  55. package/dist/components/content/InfoBadge/InfoBadge.js +1 -1
  56. package/dist/components/content/InlineInput/InlineInput.js +1 -1
  57. package/dist/components/content/Item/Item.d.ts +2 -1
  58. package/dist/components/content/Item/Item.js +1 -1
  59. package/dist/components/content/Item/Item.js.map +1 -1
  60. package/dist/components/content/ItemBadge/ItemBadge.js +1 -1
  61. package/dist/components/content/ItemCard/ItemCard.js +1 -1
  62. package/dist/components/content/Layout/GridLayout.js +1 -1
  63. package/dist/components/content/Layout/Layout.js +1 -1
  64. package/dist/components/content/Layout/LayoutBlock.js +1 -1
  65. package/dist/components/content/Layout/LayoutCenter.js +1 -1
  66. package/dist/components/content/Layout/LayoutContainer.js +1 -1
  67. package/dist/components/content/Layout/LayoutContent.js +1 -1
  68. package/dist/components/content/Layout/LayoutContext.js +1 -1
  69. package/dist/components/content/Layout/LayoutFlex.js +1 -1
  70. package/dist/components/content/Layout/LayoutFooter.js +1 -1
  71. package/dist/components/content/Layout/LayoutGrid.js +1 -1
  72. package/dist/components/content/Layout/LayoutHeader.js +1 -1
  73. package/dist/components/content/Layout/LayoutPane.js +1 -1
  74. package/dist/components/content/Layout/LayoutPanel.js +1 -1
  75. package/dist/components/content/Layout/LayoutPanelHeader.js +1 -1
  76. package/dist/components/content/Layout/LayoutToolbar.js +1 -1
  77. package/dist/components/content/Layout/hooks/useTinyScrollbar.js +1 -1
  78. package/dist/components/content/Layout/index.js +1 -1
  79. package/dist/components/content/Layout/utils.js +1 -1
  80. package/dist/components/content/Paragraph.js +1 -1
  81. package/dist/components/content/Placeholder/Placeholder.js +1 -1
  82. package/dist/components/content/PrismCode/PrismCode.js +1 -1
  83. package/dist/components/content/PrismCode/prismSetup.js +1 -1
  84. package/dist/components/content/PrismDiffCode/PrismDiffCode.js +1 -1
  85. package/dist/components/content/Result/Result.js +1 -1
  86. package/dist/components/content/Skeleton/Skeleton.js +1 -1
  87. package/dist/components/content/Tag/Tag.js +1 -1
  88. package/dist/components/content/Text.d.ts +21 -42
  89. package/dist/components/content/Text.js +4 -5
  90. package/dist/components/content/Text.js.map +1 -1
  91. package/dist/components/content/TextItem/TextItem.js +1 -1
  92. package/dist/components/content/Title.js +2 -3
  93. package/dist/components/content/Title.js.map +1 -1
  94. package/dist/components/content/Tree/Tree.js +1 -1
  95. package/dist/components/content/Tree/TreeNode.js +1 -1
  96. package/dist/components/content/Tree/styled.js +1 -1
  97. package/dist/components/content/Tree/tree-index.js +1 -1
  98. package/dist/components/content/Tree/use-checkbox-tree.js +1 -1
  99. package/dist/components/content/Tree/use-load-data.js +1 -1
  100. package/dist/components/content/highlightText.js +1 -1
  101. package/dist/components/content/use-auto-tooltip.d.ts +0 -1
  102. package/dist/components/content/use-auto-tooltip.js +1 -1
  103. package/dist/components/content/use-auto-tooltip.js.map +1 -1
  104. package/dist/components/fields/Checkbox/Checkbox.js +1 -1
  105. package/dist/components/fields/Checkbox/CheckboxGroup.js +1 -1
  106. package/dist/components/fields/Checkbox/context.js +1 -1
  107. package/dist/components/fields/ComboBox/ComboBox.js +1 -1
  108. package/dist/components/fields/CommandTextArea/CommandTextArea.js +1 -1
  109. package/dist/components/fields/CommandTextArea/caretPosition.js +1 -1
  110. package/dist/components/fields/CommandTextArea/useCaretAnchor.js +1 -1
  111. package/dist/components/fields/DatePicker/DateInput.js +1 -1
  112. package/dist/components/fields/DatePicker/DateInputBase.js +1 -1
  113. package/dist/components/fields/DatePicker/DateInputBase.js.map +1 -1
  114. package/dist/components/fields/DatePicker/DatePicker.js +1 -1
  115. package/dist/components/fields/DatePicker/DatePickerButton.js +1 -1
  116. package/dist/components/fields/DatePicker/DatePickerElement.js +1 -1
  117. package/dist/components/fields/DatePicker/DatePickerInput.js +1 -1
  118. package/dist/components/fields/DatePicker/DatePickerSegment.js +1 -1
  119. package/dist/components/fields/DatePicker/DateRangePicker.js +1 -1
  120. package/dist/components/fields/DatePicker/DateRangeSeparatedPicker.js +1 -1
  121. package/dist/components/fields/DatePicker/MonthPicker.js +1 -1
  122. package/dist/components/fields/DatePicker/PeriodPicker.js +1 -1
  123. package/dist/components/fields/DatePicker/QuarterPicker.js +1 -1
  124. package/dist/components/fields/DatePicker/TimeInput.js +1 -1
  125. package/dist/components/fields/DatePicker/WeekPicker.js +1 -1
  126. package/dist/components/fields/DatePicker/YearPicker.js +1 -1
  127. package/dist/components/fields/DatePicker/parseDate.js +1 -1
  128. package/dist/components/fields/DatePicker/period.js +1 -1
  129. package/dist/components/fields/DatePicker/props.js +1 -1
  130. package/dist/components/fields/DatePicker/utils.js +1 -1
  131. package/dist/components/fields/FileInput/FileInput.d.ts +2 -1
  132. package/dist/components/fields/FileInput/FileInput.js +1 -1
  133. package/dist/components/fields/FileInput/FileInput.js.map +1 -1
  134. package/dist/components/fields/FilterListBox/FilterListBox.js +1 -1
  135. package/dist/components/fields/FilterPicker/FilterPicker.js +1 -1
  136. package/dist/components/fields/Input/Input.js +1 -1
  137. package/dist/components/fields/ListBox/DraggableListBox.js +1 -1
  138. package/dist/components/fields/ListBox/ListBox.js +1 -1
  139. package/dist/components/fields/ListBoxPopover/ListBoxPopover.js +1 -1
  140. package/dist/components/fields/ListBoxPopover/listNavigation.js +1 -1
  141. package/dist/components/fields/ListBoxPopover/useCompositeFocus.js +1 -1
  142. package/dist/components/fields/NumberInput/NumberInput.js +1 -1
  143. package/dist/components/fields/NumberInput/StepButton.js +1 -1
  144. package/dist/components/fields/PasswordInput/PasswordInput.js +1 -1
  145. package/dist/components/fields/Picker/Picker.js +1 -1
  146. package/dist/components/fields/RadioGroup/Radio.js +1 -1
  147. package/dist/components/fields/RadioGroup/RadioGroup.js +1 -1
  148. package/dist/components/fields/RadioGroup/context.js +1 -1
  149. package/dist/components/fields/SearchComboBox/SearchComboBox.js +1 -1
  150. package/dist/components/fields/SearchInput/SearchInput.js +1 -1
  151. package/dist/components/fields/Select/Select.d.ts +2 -1
  152. package/dist/components/fields/Select/Select.js +1 -1
  153. package/dist/components/fields/Select/Select.js.map +1 -1
  154. package/dist/components/fields/Slider/Gradation.js +1 -1
  155. package/dist/components/fields/Slider/HueSlider.js +1 -1
  156. package/dist/components/fields/Slider/RangeSlider.js +1 -1
  157. package/dist/components/fields/Slider/Slider.js +1 -1
  158. package/dist/components/fields/Slider/SliderBase.js +1 -1
  159. package/dist/components/fields/Slider/SliderThumb.js +1 -1
  160. package/dist/components/fields/Slider/SliderTrack.js +1 -1
  161. package/dist/components/fields/Slider/elements.js +1 -1
  162. package/dist/components/fields/Slider/index.js +1 -1
  163. package/dist/components/fields/Switch/Switch.js +1 -1
  164. package/dist/components/fields/TextArea/TextArea.js +1 -1
  165. package/dist/components/fields/TextInput/TextInput.js +1 -1
  166. package/dist/components/fields/TextInput/TextInputBase.d.ts +2 -1
  167. package/dist/components/fields/TextInput/TextInputBase.js +1 -1
  168. package/dist/components/fields/TextInput/TextInputBase.js.map +1 -1
  169. package/dist/components/fields/TextInputMapper/TextInputMapper.js +1 -1
  170. package/dist/components/form/FieldWrapper/FieldWrapper.d.ts +2 -1
  171. package/dist/components/form/FieldWrapper/FieldWrapper.js +1 -1
  172. package/dist/components/form/FieldWrapper/types.d.ts +2 -1
  173. package/dist/components/form/Form/Field.js +1 -1
  174. package/dist/components/form/Form/Form.js +1 -1
  175. package/dist/components/form/Form/ResetButton/ResetButton.js +1 -1
  176. package/dist/components/form/Form/SubmitButton/SubmitButton.js +1 -1
  177. package/dist/components/form/Form/SubmitError.js +1 -1
  178. package/dist/components/form/Form/index.js +1 -1
  179. package/dist/components/form/Form/use-field/use-field-props.js +1 -1
  180. package/dist/components/form/Form/use-field/use-field.js +1 -1
  181. package/dist/components/form/Form/use-form.js +1 -1
  182. package/dist/components/form/Form/validation.js +1 -1
  183. package/dist/components/form/Label.js +1 -1
  184. package/dist/components/form/validation/ValidationIndicator.js +1 -1
  185. package/dist/components/form/validation/resolve-validation-props.js +1 -1
  186. package/dist/components/form/validation/use-validation-props.js +1 -1
  187. package/dist/components/form/wrapper.js +1 -1
  188. package/dist/components/helpers/DisplayTransition/DisplayTransition.js +1 -1
  189. package/dist/components/helpers/IconSwitch/IconSwitch.js +1 -1
  190. package/dist/components/layout/Board/Board.js +1 -1
  191. package/dist/components/layout/Board/BoardProvider.js +1 -1
  192. package/dist/components/layout/Board/BoardResponsive.js +1 -1
  193. package/dist/components/layout/Board/Widget.js +1 -1
  194. package/dist/components/layout/Board/WidgetHost.js +1 -1
  195. package/dist/components/layout/Board/board-context.js +1 -1
  196. package/dist/components/layout/Board/board-store.js +1 -1
  197. package/dist/components/layout/Board/grid-core/calculate.js +1 -1
  198. package/dist/components/layout/Board/grid-core/collision.js +1 -1
  199. package/dist/components/layout/Board/grid-core/compactors.js +1 -1
  200. package/dist/components/layout/Board/grid-core/constraints.js +1 -1
  201. package/dist/components/layout/Board/grid-core/layout.js +1 -1
  202. package/dist/components/layout/Board/grid-core/sort.js +1 -1
  203. package/dist/components/layout/Board/index.js +1 -1
  204. package/dist/components/layout/Board/responsive-utils.js +1 -1
  205. package/dist/components/layout/Board/use-board-layout.js +1 -1
  206. package/dist/components/layout/Board/use-board-registry.js +1 -1
  207. package/dist/components/layout/Flex.js +1 -1
  208. package/dist/components/layout/Flow.js +1 -1
  209. package/dist/components/layout/Grid.js +1 -1
  210. package/dist/components/layout/Panel.js +1 -1
  211. package/dist/components/layout/Prefix.js +1 -1
  212. package/dist/components/layout/ResizablePanel.js +1 -1
  213. package/dist/components/layout/Space.js +1 -1
  214. package/dist/components/layout/Suffix.js +1 -1
  215. package/dist/components/navigation/Tabs/DraggableTabList.js +1 -1
  216. package/dist/components/navigation/Tabs/TabButton.js +1 -1
  217. package/dist/components/navigation/Tabs/TabDropIndicator.js +1 -1
  218. package/dist/components/navigation/Tabs/TabPanel.js +1 -1
  219. package/dist/components/navigation/Tabs/TabPicker.js +1 -1
  220. package/dist/components/navigation/Tabs/Tabs.js +1 -1
  221. package/dist/components/navigation/Tabs/TabsAction.js +1 -1
  222. package/dist/components/navigation/Tabs/TabsContext.js +1 -1
  223. package/dist/components/navigation/Tabs/popover-placement.js +1 -1
  224. package/dist/components/navigation/Tabs/styled.js +1 -1
  225. package/dist/components/navigation/Tabs/types.js +1 -1
  226. package/dist/components/navigation/Tabs/use-tab-editing.js +1 -1
  227. package/dist/components/navigation/Tabs/use-tab-indicator.js +1 -1
  228. package/dist/components/organisms/FileTabs/FileTabs.js +1 -1
  229. package/dist/components/organisms/StatsCard/StatsCard.js +1 -1
  230. package/dist/components/other/Calendar/Calendar.js +1 -1
  231. package/dist/components/other/Calendar/CalendarCell.js +1 -1
  232. package/dist/components/other/Calendar/CalendarGrid.js +1 -1
  233. package/dist/components/other/Calendar/PeriodCalendar.js +1 -1
  234. package/dist/components/other/Calendar/RangeCalendar.js +1 -1
  235. package/dist/components/other/CubeLogo/CubeLogo.js +1 -1
  236. package/dist/components/overlays/AlertDialog/AlertDialog.js +1 -1
  237. package/dist/components/overlays/AlertDialog/AlertDialogApiProvider.js +1 -1
  238. package/dist/components/overlays/AlertDialog/AlertDialogZone.js +1 -1
  239. package/dist/components/overlays/Dialog/Dialog.js +1 -1
  240. package/dist/components/overlays/Dialog/DialogContainer.js +1 -1
  241. package/dist/components/overlays/Dialog/DialogForm.js +1 -1
  242. package/dist/components/overlays/Dialog/DialogTrigger.js +1 -1
  243. package/dist/components/overlays/Dialog/context.js +1 -1
  244. package/dist/components/overlays/Dialog/use-dialog-container.js +1 -1
  245. package/dist/components/overlays/Modal/Modal.js +1 -1
  246. package/dist/components/overlays/Modal/Modal.js.map +1 -1
  247. package/dist/components/overlays/Modal/OpenTransitionContext.js +1 -1
  248. package/dist/components/overlays/Modal/Overlay.js +1 -1
  249. package/dist/components/overlays/Modal/Overlay.js.map +1 -1
  250. package/dist/components/overlays/Modal/Popover.js +1 -1
  251. package/dist/components/overlays/Modal/Tray.js +1 -1
  252. package/dist/components/overlays/Modal/Tray.js.map +1 -1
  253. package/dist/components/overlays/Modal/Underlay.js +1 -1
  254. package/dist/components/overlays/Notifications/Notification.js +1 -1
  255. package/dist/components/overlays/Notifications/NotificationAction.js +1 -1
  256. package/dist/components/overlays/Notifications/NotificationCard.js +1 -1
  257. package/dist/components/overlays/Notifications/NotificationContext.js +1 -1
  258. package/dist/components/overlays/Notifications/NotificationItem.js +1 -1
  259. package/dist/components/overlays/Notifications/OverlayContainer.js +1 -1
  260. package/dist/components/overlays/Notifications/OverlayProvider.js +1 -1
  261. package/dist/components/overlays/Notifications/PersistentNotificationsList.js +1 -1
  262. package/dist/components/overlays/Notifications/dismissed-storage.js +1 -1
  263. package/dist/components/overlays/Notifications/format-relative-time.js +1 -1
  264. package/dist/components/overlays/Notifications/index.js +1 -1
  265. package/dist/components/overlays/Notifications/use-notification-state.js +1 -1
  266. package/dist/components/overlays/Notifications/use-notifications.js +1 -1
  267. package/dist/components/overlays/Notifications/use-overlay-timers.js +1 -1
  268. package/dist/components/overlays/Notifications/use-persistent-notifications.js +1 -1
  269. package/dist/components/overlays/Notifications/use-persistent-state.js +1 -1
  270. package/dist/components/overlays/Notifications/use-toast-state.js +1 -1
  271. package/dist/components/overlays/Toast/ToastItem.js +1 -1
  272. package/dist/components/overlays/Toast/index.js +1 -1
  273. package/dist/components/overlays/Toast/useProgressToast.js +1 -1
  274. package/dist/components/overlays/Toast/useToast.js +1 -1
  275. package/dist/components/overlays/Tooltip/Tooltip.js +1 -1
  276. package/dist/components/overlays/Tooltip/TooltipProvider.js +1 -1
  277. package/dist/components/overlays/Tooltip/TooltipTrigger.js +1 -1
  278. package/dist/components/overlays/Tooltip/context.js +1 -1
  279. package/dist/components/overlays/Tooltip/context.js.map +1 -1
  280. package/dist/components/portal/Portal.js +1 -1
  281. package/dist/components/portal/PortalProvider.js +1 -1
  282. package/dist/components/portal/usePortal.js +1 -1
  283. package/dist/components/shared/DraggableCollection.js +1 -1
  284. package/dist/components/shared/InvalidIcon.js +1 -1
  285. package/dist/components/shared/ValidIcon.js +1 -1
  286. package/dist/components/status/LoadingAnimation/LoadingAnimation.js +1 -1
  287. package/dist/components/status/Spin/Cube.js +1 -1
  288. package/dist/components/status/Spin/InternalSpinner.js +1 -1
  289. package/dist/components/status/Spin/Spin.js +1 -1
  290. package/dist/components/status/Spin/SpinsContainer.js +1 -1
  291. package/dist/data/item-themes.js +1 -1
  292. package/dist/data/themes.js +1 -1
  293. package/dist/eslint-plugin/defaults.generated.js +1 -1
  294. package/dist/eslint-plugin/index.js +1 -1
  295. package/dist/eslint-plugin/rules/no-redundant-default-prop.js +1 -1
  296. package/dist/i18n/I18nProvider.js +1 -1
  297. package/dist/i18n/createFormatter.js +1 -1
  298. package/dist/i18n/index.js +1 -1
  299. package/dist/i18n/instance.js +1 -1
  300. package/dist/i18n/locales/de-DE/uikit.js +1 -1
  301. package/dist/i18n/locales/en-US/uikit.js +1 -1
  302. package/dist/i18n/locales/es-ES/uikit.js +1 -1
  303. package/dist/i18n/locales/es-MX/uikit.js +1 -1
  304. package/dist/i18n/locales/fr-FR/uikit.js +1 -1
  305. package/dist/i18n/locales/it-IT/uikit.js +1 -1
  306. package/dist/i18n/locales/ja-JP/uikit.js +1 -1
  307. package/dist/i18n/locales/nb-NO/uikit.js +1 -1
  308. package/dist/i18n/locales/pt-BR/uikit.js +1 -1
  309. package/dist/i18n/locales/pt-PT/uikit.js +1 -1
  310. package/dist/i18n/locales/sv-SE/uikit.js +1 -1
  311. package/dist/i18n/locales/vi-VN/uikit.js +1 -1
  312. package/dist/i18n/locales.js +1 -1
  313. package/dist/i18n/useFormatter.js +1 -1
  314. package/dist/i18n/useI18n.js +1 -1
  315. package/dist/icons/AdjustmentsHorizontalIcon.js +1 -1
  316. package/dist/icons/AdjustmentsIcon.js +1 -1
  317. package/dist/icons/AiIcon.js +1 -1
  318. package/dist/icons/AreaChartIcon.js +1 -1
  319. package/dist/icons/BackwardIcon.js +1 -1
  320. package/dist/icons/BarChartIcon.js +1 -1
  321. package/dist/icons/BellFilledIcon.js +1 -1
  322. package/dist/icons/BellIcon.js +1 -1
  323. package/dist/icons/BooleanIcon.js +1 -1
  324. package/dist/icons/CalendarEditIcon.js +1 -1
  325. package/dist/icons/CalendarIcon.js +1 -1
  326. package/dist/icons/CaretDownIcon.js +1 -1
  327. package/dist/icons/CaretUpIcon.js +1 -1
  328. package/dist/icons/ChartAreaStackedIcon.js +1 -1
  329. package/dist/icons/ChartAreaStackedPercentageIcon.js +1 -1
  330. package/dist/icons/ChartBarGroupedHorizontalIcon.js +1 -1
  331. package/dist/icons/ChartBarGroupedIcon.js +1 -1
  332. package/dist/icons/ChartBarHorizontalIcon.js +1 -1
  333. package/dist/icons/ChartBarLineIcon.js +1 -1
  334. package/dist/icons/ChartBarStackedHorizontalIcon.js +1 -1
  335. package/dist/icons/ChartBarStackedIcon.js +1 -1
  336. package/dist/icons/ChartBarStackedPercentageHorizontalIcon.js +1 -1
  337. package/dist/icons/ChartBarStackedPercentageIcon.js +1 -1
  338. package/dist/icons/ChartBoxPlot2Icon.js +1 -1
  339. package/dist/icons/ChartBoxPlotIcon.js +1 -1
  340. package/dist/icons/ChartBubbleIcon.js +1 -1
  341. package/dist/icons/ChartDonut2Icon.js +1 -1
  342. package/dist/icons/ChartFunnelIcon.js +1 -1
  343. package/dist/icons/ChartHeatmapIcon.js +1 -1
  344. package/dist/icons/ChartKPIIcon.js +1 -1
  345. package/dist/icons/ChartPie2Icon.js +1 -1
  346. package/dist/icons/ChartScatterIcon.js +1 -1
  347. package/dist/icons/CheckCircleFilledIcon.js +1 -1
  348. package/dist/icons/CheckCircleIcon.js +1 -1
  349. package/dist/icons/CheckIcon.js +1 -1
  350. package/dist/icons/CircleFilledIcon.js +1 -1
  351. package/dist/icons/ClearIcon.js +1 -1
  352. package/dist/icons/CloseCircleFilledIcon.js +1 -1
  353. package/dist/icons/CloseCircleIcon.js +1 -1
  354. package/dist/icons/CloseIcon.js +1 -1
  355. package/dist/icons/CodeIcon.js +1 -1
  356. package/dist/icons/ColumnTotalIcon.js +1 -1
  357. package/dist/icons/CopyIcon.js +1 -1
  358. package/dist/icons/CountIcon.js +1 -1
  359. package/dist/icons/CubeIcon.js +1 -1
  360. package/dist/icons/CubePauseIcon.js +1 -1
  361. package/dist/icons/CubePlayIcon.js +1 -1
  362. package/dist/icons/CurrencyDollarIcon.js +1 -1
  363. package/dist/icons/DangerIcon.js +1 -1
  364. package/dist/icons/DashboardIcon.js +1 -1
  365. package/dist/icons/DatabaseIcon.js +1 -1
  366. package/dist/icons/DecimalDecreaseIcon.js +1 -1
  367. package/dist/icons/DecimalIncreaseIcon.js +1 -1
  368. package/dist/icons/DirectionIcon.js +1 -1
  369. package/dist/icons/DonutIcon.js +1 -1
  370. package/dist/icons/DownIcon.js +1 -1
  371. package/dist/icons/EditIcon.js +1 -1
  372. package/dist/icons/ExclamationCircleFilledIcon.js +1 -1
  373. package/dist/icons/ExclamationCircleIcon.js +1 -1
  374. package/dist/icons/ExclamationIcon.js +1 -1
  375. package/dist/icons/EyeIcon.js +1 -1
  376. package/dist/icons/EyeInvisibleIcon.js +1 -1
  377. package/dist/icons/FilterIcon.js +1 -1
  378. package/dist/icons/FolderFilledIcon.js +1 -1
  379. package/dist/icons/FolderIcon.js +1 -1
  380. package/dist/icons/FolderOpenFilledIcon.js +1 -1
  381. package/dist/icons/FolderOpenIcon.js +1 -1
  382. package/dist/icons/ForwardIcon.js +1 -1
  383. package/dist/icons/GripVerticalIcon.js +1 -1
  384. package/dist/icons/HierarchyIcon.js +1 -1
  385. package/dist/icons/HierarchyOpenIcon.js +1 -1
  386. package/dist/icons/Icon.js +1 -1
  387. package/dist/icons/InfoCircleIcon.js +1 -1
  388. package/dist/icons/InfoIcon.js +1 -1
  389. package/dist/icons/KeyIcon.js +1 -1
  390. package/dist/icons/LeftIcon.js +1 -1
  391. package/dist/icons/LineChartIcon.js +1 -1
  392. package/dist/icons/LoadingIcon.js +1 -1
  393. package/dist/icons/LockFilledIcon.js +1 -1
  394. package/dist/icons/LockIcon.js +1 -1
  395. package/dist/icons/MoreIcon.js +1 -1
  396. package/dist/icons/NotAllowedIcon.js +1 -1
  397. package/dist/icons/Number123Icon.js +1 -1
  398. package/dist/icons/NumberIcon.js +1 -1
  399. package/dist/icons/PauseCircleFilledIcon.js +1 -1
  400. package/dist/icons/PauseCircleIcon.js +1 -1
  401. package/dist/icons/PauseIcon.js +1 -1
  402. package/dist/icons/PercentageIcon.js +1 -1
  403. package/dist/icons/PieChartIcon.js +1 -1
  404. package/dist/icons/PlayCircleIcon.js +1 -1
  405. package/dist/icons/PlayIcon.js +1 -1
  406. package/dist/icons/PlusIcon.js +1 -1
  407. package/dist/icons/ProgressBarIcon.js +1 -1
  408. package/dist/icons/ReloadIcon.js +1 -1
  409. package/dist/icons/ReportIcon.js +1 -1
  410. package/dist/icons/ReturnIcon.js +1 -1
  411. package/dist/icons/RightIcon.js +1 -1
  412. package/dist/icons/RowTotalsIcon.js +1 -1
  413. package/dist/icons/SchemeIcon.js +1 -1
  414. package/dist/icons/SearchIcon.js +1 -1
  415. package/dist/icons/SemanticQueryIcon.js +1 -1
  416. package/dist/icons/SettingsIcon.js +1 -1
  417. package/dist/icons/ShieldFilledIcon.js +1 -1
  418. package/dist/icons/ShieldIcon.js +1 -1
  419. package/dist/icons/SlashIcon.js +1 -1
  420. package/dist/icons/SparklesIcon.js +1 -1
  421. package/dist/icons/SqlIcon.js +1 -1
  422. package/dist/icons/StatsIcon.js +1 -1
  423. package/dist/icons/StopIcon.js +1 -1
  424. package/dist/icons/StringIcon.js +1 -1
  425. package/dist/icons/SubtotalsIcon.js +1 -1
  426. package/dist/icons/SwitchIcon.js +1 -1
  427. package/dist/icons/TableIcon.js +1 -1
  428. package/dist/icons/ThumbsDownIcon.js +1 -1
  429. package/dist/icons/ThumbsUpIcon.js +1 -1
  430. package/dist/icons/ThunderboltCrossedIcon.js +1 -1
  431. package/dist/icons/ThunderboltFilledIcon.js +1 -1
  432. package/dist/icons/ThunderboltIcon.js +1 -1
  433. package/dist/icons/TimeIcon.js +1 -1
  434. package/dist/icons/TrashIcon.js +1 -1
  435. package/dist/icons/UnlockIcon.js +1 -1
  436. package/dist/icons/UpIcon.js +1 -1
  437. package/dist/icons/UserGroupIcon.js +1 -1
  438. package/dist/icons/UserIcon.js +1 -1
  439. package/dist/icons/UserLockIcon.js +1 -1
  440. package/dist/icons/ViewIcon.js +1 -1
  441. package/dist/icons/WarningFilledIcon.js +1 -1
  442. package/dist/icons/WarningIcon.js +1 -1
  443. package/dist/icons/wrap-icon.js +1 -1
  444. package/dist/index.d.ts +2 -1
  445. package/dist/index.js +1 -1
  446. package/dist/index.js.map +1 -1
  447. package/dist/props.d.ts +13 -0
  448. package/dist/provider.d.ts +1 -1
  449. package/dist/provider.js +1 -1
  450. package/dist/provider.js.map +1 -1
  451. package/dist/providers/TrackingProvider.js +1 -1
  452. package/dist/providers/navigationAdapter.default.js +1 -1
  453. package/dist/shared/form.d.ts +2 -1
  454. package/dist/tokens/base.js +1 -1
  455. package/dist/tokens/colors.js +1 -1
  456. package/dist/tokens/index.js +1 -1
  457. package/dist/tokens/layout.js +1 -1
  458. package/dist/tokens/lazy-styles.js +1 -1
  459. package/dist/tokens/palette-config.js +1 -1
  460. package/dist/tokens/palette.js +1 -1
  461. package/dist/tokens/shadows.js +1 -1
  462. package/dist/tokens/sizes.js +1 -1
  463. package/dist/tokens/spacing.js +1 -1
  464. package/dist/tokens/typography.js +1 -1
  465. package/dist/utils/ResizeSensor.js +1 -1
  466. package/dist/utils/is-dev-env.js +1 -1
  467. package/dist/utils/modules.js +1 -1
  468. package/dist/utils/promise.js +1 -1
  469. package/dist/utils/raf.js +1 -1
  470. package/dist/utils/random.js +1 -1
  471. package/dist/utils/range.js +1 -1
  472. package/dist/utils/react/RenderCache.js +1 -1
  473. package/dist/utils/react/Slots.js +1 -1
  474. package/dist/utils/react/chain.js +1 -1
  475. package/dist/utils/react/forwardRefWithGenerics.js +1 -1
  476. package/dist/utils/react/index.js +1 -1
  477. package/dist/utils/react/interactions.js +1 -1
  478. package/dist/utils/react/isTextOnly.js +1 -1
  479. package/dist/utils/react/mapProps.js +1 -1
  480. package/dist/utils/react/mergeProps.d.ts +1 -1
  481. package/dist/utils/react/mergeProps.js +1 -1
  482. package/dist/utils/react/mergeProps.js.map +1 -1
  483. package/dist/utils/react/nullableValue.d.ts +1 -1
  484. package/dist/utils/react/nullableValue.js +1 -1
  485. package/dist/utils/react/nullableValue.js.map +1 -1
  486. package/dist/utils/react/resolveIcon.js +1 -1
  487. package/dist/utils/react/sharedStore.js +1 -1
  488. package/dist/utils/react/useCombinedRefs.js +1 -1
  489. package/dist/utils/react/useControlledFocusVisible.js +1 -1
  490. package/dist/utils/react/useEventBus.js +1 -1
  491. package/dist/utils/react/useId.js +1 -1
  492. package/dist/utils/react/useIsDarwin.js +1 -1
  493. package/dist/utils/react/useKeySymbols.js +1 -1
  494. package/dist/utils/react/useLayoutEffect.js +1 -1
  495. package/dist/utils/react/useLocalStorage.js +1 -1
  496. package/dist/utils/react/useMergeStyles.js +1 -1
  497. package/dist/utils/react/usePopoverSync.js +1 -1
  498. package/dist/utils/react/useQaProps.js +1 -1
  499. package/dist/utils/react/useViewportSize.js +1 -1
  500. package/dist/utils/react/wrapNodeIfPlain.js +1 -1
  501. package/dist/utils/selection.js +1 -1
  502. package/dist/utils/styles.js +1 -1
  503. package/dist/utils/tree.js +1 -1
  504. package/dist/utils/warnings.js +1 -1
  505. package/dist/version.js +3 -3
  506. package/docs/components/content/Text.md +1 -2
  507. package/docs/tasty/README.md +3 -1
  508. package/docs/tasty/ai-agents.md +21 -7
  509. package/docs/tasty/configuration.md +220 -30
  510. package/docs/tasty/debug.md +7 -7
  511. package/docs/tasty/design-system.md +2 -2
  512. package/docs/tasty/dsl.md +68 -8
  513. package/docs/tasty/injector.md +31 -4
  514. package/docs/tasty/methodology.md +1 -1
  515. package/docs/tasty/migration-v3.md +285 -0
  516. package/docs/tasty/pipeline.md +3 -3
  517. package/docs/tasty/plugins.md +349 -0
  518. package/docs/tasty/react-api.md +61 -1
  519. package/docs/tasty/ssr.md +41 -33
  520. package/docs/tasty/styles.md +27 -9
  521. package/docs/tasty/tasty-static.md +8 -6
  522. package/package.json +3 -3
@@ -20,13 +20,15 @@ Tasty is a styling engine for design systems that turns component state into det
20
20
  - **React components**: [React API](react-api.md)
21
21
  - **Zero-runtime / build-time extraction**: [Zero Runtime (tastyStatic)](tasty-static.md)
22
22
  - **Runtime `tasty()` with server collection and hydration**: [Server-Side Rendering](ssr.md)
23
+ - **Upgrading from v2**: [Migration Guide (v2 → v3)](migration-v3.md)
23
24
 
24
25
  ## By Task
25
26
 
26
27
  - **Learn the style language**: [Style DSL](dsl.md)
27
28
  - **Brief an AI agent (or yourself) on writing correct styles**: [Style Rules for AI Agents](ai-agents.md)
28
29
  - **Look up a property handler**: [Style Properties](styles.md)
29
- - **Define tokens, units, recipes, keyframes, or properties globally**: [Configuration](configuration.md)
30
+ - **Define tokens, units, recipes, keyframes, properties, functions, or polyfills globally**: [Configuration](configuration.md)
31
+ - **Extend Tasty with a plugin, custom handler, or custom prop**: [Plugins & Extension Points](plugins.md)
30
32
  - **Debug generated CSS or cache behavior**: [Debug Utilities](debug.md)
31
33
  - **Understand how selector generation works internally**: [Style rendering pipeline](pipeline.md)
32
34
  - **Understand runtime injection internals**: [Style Injector](injector.md)
@@ -1,6 +1,6 @@
1
1
  # Tasty Style Rules for AI Agents
2
2
 
3
- A compact ruleset for **writing correct `@tenphi/tasty` styles**. It is not an API tour — every rule here is machine-checked by [`@tenphi/eslint-plugin-tasty`](https://www.npmjs.com/package/@tenphi/eslint-plugin-tasty), so following it means clean lint output. For explanations and the complete API, see [Style DSL](dsl.md), [Style Properties](styles.md), [React API](react-api.md).
3
+ A compact ruleset for **writing correct `@tenphi/tasty` styles**. It is not an API tour — most rules here are machine-checked by [`@tenphi/eslint-plugin-tasty`](https://www.npmjs.com/package/@tenphi/eslint-plugin-tasty), so following it generally means clean lint output. The plugin ships separately and can lag a new DSL rule, so treat this page as the source of truth and the plugin as the enforcement that catches most of it. For explanations and the complete API, see [Style DSL](dsl.md), [Style Properties](styles.md), [React API](react-api.md).
4
4
 
5
5
  Notation: ❌ wrong → ✅ correct.
6
6
 
@@ -64,7 +64,8 @@ The last row goes the other way — longhands over the shorthand — because `fl
64
64
  | `#clear` / `#current` | `transparent` / `currentcolor` |
65
65
  | `$name` | custom property → `var(--name)` |
66
66
  | `(#a, #b)` | fallback chain |
67
- | `$$name` / `##name` | the property *name* — only inside `transition` |
67
+ | `$$name` / `##name` | the custom property *name* (not its value) — inside `transition` |
68
+ | `$$name(…)` | call a CSS `@function` declared via `@function`, `useFunction`, or config |
68
69
 
69
70
  - ❌ `#f5f5f5`, `rgb(0 0 0)`, `oklch(…)`, `okhsl(…)`, `red` → ✅ `#surface` (add the token to the config if it doesn't exist).
70
71
  - ❌ `var(--gap)` → ✅ `$gap` · ❌ `$accent-color` → ✅ `#accent` · ❌ `transparent` → ✅ `#clear` · ❌ `currentColor` → ✅ `#current`.
@@ -82,7 +83,7 @@ Prefer units over raw pixels: `8px` → `1x` … `64px` → `8x`; `radius: '6px'
82
83
 
83
84
  ### `true`
84
85
 
85
- `true` means "the design-system default" and is accepted **only** by: `border`, `radius`, `outline`, `shadow`, `padding`, `margin`, `gap`, `inset`, `width`, `height`, `fill`, `color`, `preset`, `font`, `scrollbar`, `hide`. Anywhere else it is an error.
86
+ `true` means "the design-system default" and is accepted **only** by: `border`, `radius`, `outline`, `shadow`, `padding`, `margin`, `gap`, `inset`, `width`, `height`, `fill`, `color`, `fade`, `preset`, `font`, `scrollbar`, `hide`. Anywhere else it is an error.
86
87
 
87
88
  ### `!important`
88
89
 
@@ -90,7 +91,7 @@ Never use it. Tasty owns specificity through doubled selectors and state orderin
90
91
 
91
92
  ### Modifiers
92
93
 
93
- A value is `[values…] [modifiers…]`, and several groups can be comma-separated (later groups override earlier ones). Only the modifiers a property knows are valid:
94
+ A value is `[values…] [modifiers…]`, and several groups can be comma-separated (later groups override earlier ones). A group that names **direction** modifiers takes a **single** value, applied to every direction it names — per-side values come from comma groups. A group naming no direction keeps plain CSS shorthand order (1–4 values). (`inset` + `dock` is the one exception: a second value insets the spanned sides.) Only the modifiers a property knows are valid:
94
95
 
95
96
  | Property | Modifiers |
96
97
  |----------|-----------|
@@ -111,6 +112,8 @@ Directional modifiers beat placeholder zeros:
111
112
  - ❌ `padding: '0 0 2x 0'` → ✅ `padding: '2x bottom'`
112
113
  - ❌ `padding: '1x 1x 2x 1x'` → ✅ `padding: '1x, 2x bottom'`
113
114
  - ❌ `border: '0 0 1bw 0'` — four tokens parse as *one* border value, so this renders no border at all → ✅ `border: '1bw bottom'`
115
+ - ❌ `padding: '2x 4x top right'` — a directional group takes one value, so `4x` is dropped → ✅ `padding: '2x top, 4x right'`
116
+ - ❌ `fade: '3x 1x top bottom'` → ✅ `fade: '3x top, 1x bottom'`
114
117
 
115
118
  Value-only properties reject both colors and modifiers: `gap`, `columnGap`, `rowGap`, `opacity`, `zIndex`, `order`, `flexGrow`, `flexShrink`, `flexBasis`, `aspectRatio`, `lineClamp`, `tabSize`, `paddingInline`, `paddingBlock`. `fill` and `color` take a color (plus `none` / `transparent`); `caretColor` and `accentColor` take a color only.
116
119
 
@@ -184,11 +187,21 @@ styles: { Title: { preset: 'h3' }, Icon: { $: '>@:last-child', color: '#accent'
184
187
  | Key | Shape |
185
188
  |-----|-------|
186
189
  | `@keyframes` | `{ name: { '0%': styles, … } }` |
187
- | `@properties` | `{ '$name': { syntax, inherits, initialValue } }` |
188
- | `@fontFace` | `{ 'Family Name': descriptors \| descriptors[] }` |
189
- | `@counterStyle` | `{ name: descriptors }` |
190
+ | `@property` | `{ '$name': { syntax, inherits, initialValue } }` |
191
+ | `@font-face` | `{ 'Family Name': descriptors \| descriptors[] }` |
192
+ | `@counter-style` | `{ name: descriptors }` |
193
+ | `@function` | `{ '$$name': { args, returns?, result, '$local'? } }` |
190
194
  | `recipe` | a **string** of configured recipe names: `'card elevated'`, `'reset input / autofill'`, `'none / disabled'` |
191
195
 
196
+ At-rule keys match the real CSS at-rule names, so they are kebab-case, not camelCase. Inside `@function`, the callable is `$$name` but its parameters and local variables are `$name`:
197
+
198
+ ```jsx
199
+ styles: {
200
+ '@function': { $$negative: { args: ['$value'], result: '(-1 * $value)' } },
201
+ marginTop: '$$negative(2x)',
202
+ }
203
+ ```
204
+
192
205
  ## 7. `tastyStatic()`
193
206
 
194
207
  The selector must be a string literal and valid CSS. Values must be static — strings, numbers, booleans, `null`, or objects/arrays of those. No variables, template literals, function calls, or spreads.
@@ -203,4 +216,5 @@ The selector must be a string literal and valid CSS. Values must be static — s
203
216
  - Modifiers valid for the property; directional shorthand instead of placeholder zeros.
204
217
  - Every state map starts with `''` (or `_`), is flat, and lives inside a property value.
205
218
  - `@own()` only inside sub-elements; sub-element keys are capitalized and hold objects.
219
+ - At-rule keys are kebab-case (`@property`, `@font-face`, `@counter-style`, `@function`); `@function` names use `$$`, their args and locals use `$`.
206
220
  - Values are static; dynamic behavior comes from `mods` / `tokens` / `styleProps`.
@@ -26,12 +26,15 @@ configure({
26
26
  custom: (n) => `${n * 10}px`, // Function-based unit
27
27
  },
28
28
 
29
- // Custom functions for the parser
30
- funcs: {
29
+ // Custom functions — a single map for both flavors, discriminated by value type:
30
+ functions: {
31
+ // Bare key + function value → parse-time function, called as `double(...)`
31
32
  double: (groups) => {
32
33
  const value = parseFloat(groups[0]?.output || '0');
33
34
  return `${value * 2}px`;
34
35
  },
36
+ // `$$name` key + object value → declarative CSS @function, called as `$$negative(...)`
37
+ $$negative: { args: ['$value'], result: '(-1 * $value)' },
35
38
  },
36
39
  });
37
40
  ```
@@ -45,23 +48,31 @@ These docs use `data-schema="dark"` in examples. If your app already standardize
45
48
  | Option | Type | Default | Description |
46
49
  |--------|------|---------|-------------|
47
50
  | `nonce` | `string` | - | CSP nonce for style elements |
51
+ | `maxRulesPerSheet` | `number` | `8192` | Maximum rules per injected stylesheet |
52
+ | `forceTextInjection` | `boolean` | auto (`true` in test envs) | Force text-node CSS injection instead of constructable stylesheets |
53
+ | `devMode` | `boolean` | auto | Enable development-mode features: performance metrics and debug info |
48
54
  | `states` | `Record<string, string>` | - | Global state aliases for advanced state mapping |
49
55
  | `parserCacheSize` | `number` | `1000` | Parser LRU cache size |
50
- | `units` | `Record<string, string \| Function>` | Built-in | Custom units (merged with built-in). See [built-in units](dsl.md#built-in-units) |
51
- | `funcs` | `Record<string, Function>` | - | Custom parser functions (merged with existing) |
52
- | `handlers` | `Record<string, StyleHandlerDefinition>` | Built-in | Custom style handlers (replace built-in) |
56
+ | `units` | `Record<string, string \| UnitHandler>` | Built-in | Custom units (merged with built-in). See [built-in units](dsl.md#built-in-units) |
57
+ | `functions` | `Record<string, FunctionDefinition \| Function>` | - | Custom functions (merged). Bare keys → parse functions; `$$name` keys → declarative CSS `@function` definitions |
58
+ | `handlers` | `Record<string, StyleHandlerDefinition>` | Built-in | Custom style handlers (replace built-in). See [Custom Style Handlers](#custom-style-handlers) |
59
+ | `propHandlers` | `Record<string, PropHandlerDefinition>` | - | Props middleware for every component — props in, props out. See [Props Middleware](#props-middleware) |
60
+ | `baseStyleProps` | `readonly string[]` | - | Style names exposed as props on **every** component. See [Base Style Props](#base-style-props) |
53
61
  | `tokens` | `Record<string, value \| stateMap>` | - | Design tokens injected as `:root` CSS custom properties |
54
- | `replaceTokens` | `Record<string, string \| number>` | - | Parse-time token substitution (inline replacement) |
62
+ | `replaceTokens` | `Record<string, string \| number \| boolean>` | - | Parse-time token substitution (inline replacement). `boolean` is allowed for `#` color tokens |
55
63
  | `keyframes` | `Record<string, KeyframesSteps>` | - | Global keyframes for animations |
56
64
  | `properties` | `Record<string, PropertyDefinition>` | - | Global CSS @property definitions |
57
- | `fontFace` | `Record<string, FontFaceInput>` | - | Global @font-face definitions |
58
- | `counterStyle` | `Record<string, CounterStyleDescriptors>` | - | Global @counter-style definitions |
65
+ | `fontFaces` | `Record<string, FontFaceInput>` | - | Global @font-face definitions |
66
+ | `counterStyles` | `Record<string, CounterStyleDescriptors>` | - | Global @counter-style definitions |
67
+ | `polyfills` | `{ functions?: boolean }` | `{}` | Opt-in polyfills for not-yet-baseline features. `functions: true` inlines `@function` calls into plain CSS at parse time |
59
68
  | `autoPropertyTypes` | `boolean` | `true` | Auto-infer and register `@property` types from values |
60
69
  | `recipes` | `Record<string, RecipeStyles>` | - | Predefined style recipes (named style bundles) |
61
70
  | `presets` | `Record<string, TypographyPreset>` | - | Typography presets — shorthand for `generateTypographyTokens()` |
62
71
  | `globalStyles` | `Record<string, Styles>` | - | Global Tasty styles keyed by CSS selector |
72
+ | `plugins` | `TastyPlugin[]` | - | Plugins that bundle any of the above (processed in order; later override earlier, and direct config wins over all). See [Plugins](plugins.md) |
73
+ | `gc` | `GCConfig` | - | Garbage-collection tuning for unused styles (`{ touchInterval, capacity }`) |
63
74
  | `colorSpace` | `'rgb' \| 'hsl' \| 'oklch'` | `'oklch'` | Color space for decomposed color token companion variables |
64
- | `namePrefix` | `string` | `'t'` (runtime) / `'ts'` (zero-runtime) | Prefix prepended to every generated identifier (class, keyframe, counter-style names). See [Name prefix](#name-prefix). |
75
+ | `namePrefix` | `string` | `'t'` (runtime) / `'ts'` (zero-runtime) | Prefix prepended to every generated identifier (class, keyframe, counter-style names). Must match `^[a-zA-Z_][a-zA-Z0-9_-]{0,31}$`. See [Name prefix](#name-prefix). |
65
76
 
66
77
  ---
67
78
 
@@ -187,7 +198,7 @@ Register custom fonts globally so every component can reference them by family n
187
198
 
188
199
  ```ts
189
200
  configure({
190
- fontFace: {
201
+ fontFaces: {
191
202
  'Brand Sans': [
192
203
  {
193
204
  src: 'url("/fonts/brand-regular.woff2") format("woff2")',
@@ -210,7 +221,7 @@ configure({
210
221
 
211
222
  Now any component can use `fontFamily: '"Brand Sans", sans-serif'` and the browser will already have the `@font-face` rules in the stylesheet.
212
223
 
213
- See [Font Face (`@fontFace`)](dsl.md#font-face-fontface) for inline usage inside component styles and the full list of supported descriptors.
224
+ See [Font Face (`@font-face`)](dsl.md#font-face-font-face) for inline usage inside component styles and the full list of supported descriptors.
214
225
 
215
226
  ---
216
227
 
@@ -220,7 +231,7 @@ Define custom list-marker algorithms globally. Rules are injected eagerly when s
220
231
 
221
232
  ```ts
222
233
  configure({
223
- counterStyle: {
234
+ counterStyles: {
224
235
  thumbs: {
225
236
  system: 'cyclic',
226
237
  symbols: '"👍"',
@@ -236,7 +247,98 @@ configure({
236
247
 
237
248
  Components can then reference `listStyleType: 'thumbs'` directly.
238
249
 
239
- See [Counter Style (`@counterStyle`)](dsl.md#counter-style-counterstyle) for inline usage inside component styles and the full list of supported descriptors.
250
+ See [Counter Style (`@counter-style`)](dsl.md#counter-style-counter-style) for inline usage inside component styles and the full list of supported descriptors.
251
+
252
+ ---
253
+
254
+ ## Functions
255
+
256
+ The single `functions` map holds both kinds of custom functions, discriminated by the value type:
257
+
258
+ - **Parse functions** — a **bare key** with a **function value** `(groups) => string`. Runs at parse time and is called as `name(...)`. Use these for computed/derived CSS that JavaScript produces (e.g. color-space conversions).
259
+ - **CSS `@function` definitions** — a **`$$name` key** with an **object value** (a [`FunctionDefinition`](https://developer.mozilla.org/en-US/docs/Web/CSS/@function)). Injected eagerly as a native `@function` rule and called as `$$name(...)` (→ `--name(...)`).
260
+
261
+ ```ts
262
+ configure({
263
+ functions: {
264
+ // Parse function — bare key, function value
265
+ double: (groups) => `calc(2 * ${groups[0]?.output ?? '0'})`,
266
+
267
+ // CSS @function — `$$` key, object value
268
+ $$negative: { args: ['$value'], result: '(-1 * $value)' },
269
+ $$shadow: {
270
+ args: { '$shadow-color': { syntax: '<color>', default: 'inherit' } },
271
+ returns: '<color>',
272
+ $offset: '2px',
273
+ result: '$offset $offset ($shadow-color, black)',
274
+ },
275
+ },
276
+ });
277
+ ```
278
+
279
+ Components then invoke parse functions as `double(...)` and CSS functions with the `$$name(...)` sugar, e.g. `marginTop: '$$negative(10px)'`.
280
+
281
+ > A key whose prefix doesn't match its value type (an object under a bare key, or a function under a `$$` key) is **ignored with a dev-mode warning**.
282
+
283
+ See [Functions (`@function`)](dsl.md#functions-function) for inline usage inside component styles, the full descriptor shape, and token conventions. `@function` is an experimental CSS feature — unsupported browsers safely ignore the native rule (see the polyfill below).
284
+
285
+ ### Custom color functions
286
+
287
+ A parse function whose output is an already-supported color (`rgb`, `hsl`, `#…`, `oklch`, …) is treated as a **color function**: it works everywhere a color is accepted — style values, `#token.alpha` opacity injection, token decomposition into the configured color space, and `parseColor` — with no extra registration. This is the same mechanism the built-in `okhsl`/`okhst` plugins use; they are ordinary plugins registered by default.
288
+
289
+ ```ts
290
+ import { configure, createColorFunc } from '@tenphi/tasty';
291
+
292
+ // A custom color space is just a `functions` entry.
293
+ const myColorPlugin = () => ({
294
+ name: 'mycolor',
295
+ functions: {
296
+ // Hand-written parse function:
297
+ mycolor: (groups) => {
298
+ const [r, g, b] = groups[0].all;
299
+ return `rgb(${r} ${g} ${b})`;
300
+ },
301
+ },
302
+ });
303
+
304
+ configure({ plugins: [myColorPlugin()] });
305
+
306
+ // Now `mycolor(...)` is a color in every context:
307
+ // fill: 'mycolor(255 0 0)'
308
+ // fill: '#brand.5' (with replaceTokens: { '#brand': 'mycolor(255 0 0)' })
309
+ ```
310
+
311
+ For HSL-style color spaces (a hue angle plus two percentages), the exported `createColorFunc(name, convert, label?)` helper handles angle/percentage parsing, clamping, alpha, and caching. `convert` returns sRGB `[r, g, b]` in 0-1; `label` is an optional string used only in dev warnings (e.g. `'H S L'`) and has no effect on output. This is exactly how `okhslPlugin`/`okhstPlugin` are implemented.
312
+
313
+ ---
314
+
315
+ ## Polyfills
316
+
317
+ `@function` only ships natively in Chromium 139+. To use CSS functions in browsers that don't support the at-rule yet (Firefox, Safari), enable the **functions polyfill**, which expands every `$$name(...)` call into plain CSS (`calc()`/`var()`/`color-mix()`) at parse time instead of emitting the native `@function` rule:
318
+
319
+ ```ts
320
+ configure({
321
+ polyfills: {
322
+ functions: true, // default: false
323
+ },
324
+ functions: {
325
+ $$negative: { args: ['$value'], result: '(-1 * $value)' },
326
+ },
327
+ });
328
+
329
+ // Now `marginTop: '$$negative(10px)'` renders `margin-top: calc(-1 * 10px)`
330
+ // — no native @function rule is emitted.
331
+ ```
332
+
333
+ This works across all rendering modes (client, SSR/RSC, and `tastyStatic`) because expansion happens in the parser. Note `polyfills.functions` (the feature toggle) is distinct from the top-level `functions` (the definitions map).
334
+
335
+ **Decided limitations when the polyfill is on:**
336
+
337
+ - **No native fallback** — functions are always inlined; we do exactly what is configured.
338
+ - **Conditional results** (`@media`/`@supports`/`if()` inside `result`) are inlined verbatim; the conditional nuance is not resolved per-element.
339
+ - **Typed params / `returns`** are dropped (inlining is purely lexical substitution).
340
+ - **Param name collisions** are avoided by fully inlining argument values (no function-internal custom properties are emitted) and by namespacing the function's own variables.
341
+ - **Recursion** — self/mutually-recursive functions are not expanded; the cycle guard bails and leaves the call untouched.
240
342
 
241
343
  ---
242
344
 
@@ -260,7 +362,7 @@ configure({
260
362
  });
261
363
  ```
262
364
 
263
- Recipe values are flat tasty styles (no sub-element keys). They may contain base styles, tokens, local states, `@keyframes`, and `@properties`. Recipes cannot reference other recipes.
365
+ Recipe values are flat tasty styles (no sub-element keys). They may contain base styles, tokens, local states, `@keyframes`, and `@property`. Recipes cannot reference other recipes.
264
366
 
265
367
  For how to apply, compose, and override recipes in components, see [Recipes](dsl.md#recipes) in the Style DSL reference.
266
368
 
@@ -349,12 +451,12 @@ Supported types:
349
451
  | `300ms`, `1s` (time units) | `<time>` |
350
452
  | `#name` tokens (by naming convention) | `<color>` |
351
453
 
352
- Auto-inferred properties use `inherits: true` (the CSS default). Use explicit `@properties` when you need different settings:
454
+ Auto-inferred properties use `inherits: true` (the CSS default). Use explicit `@property` when you need different settings:
353
455
 
354
456
  ```jsx
355
457
  // In component styles
356
458
  styles: {
357
- '@properties': {
459
+ '@property': {
358
460
  '$scale': { syntax: '<number>', inherits: false, initialValue: 1 },
359
461
  },
360
462
  }
@@ -367,7 +469,7 @@ configure({
367
469
  });
368
470
  ```
369
471
 
370
- To disable auto-inference entirely (only explicit `@properties` will be used):
472
+ To disable auto-inference entirely (only explicit `@property` will be used):
371
473
 
372
474
  ```jsx
373
475
  configure({ autoPropertyTypes: false });
@@ -385,21 +487,13 @@ Override or extend the built-in style property handlers. A handler definition ca
385
487
  | Single dep | `['styleName', handler]` | Triggered by the specified style property |
386
488
  | Multi dep | `[['dep1', 'dep2', ...], handler]` | Triggered by any of the listed properties; receives all of them |
387
489
 
388
- The multi-dep form is useful when output depends on several style properties together (e.g., `gap` needs to know `display` and `flow` to decide the CSS strategy).
490
+ The multi-dep form is useful when output depends on several style properties together (e.g., `gap` needs to know `display` and `flow` to decide the CSS strategy). Use `defineHandler` for it and the dependency types are inferred from the dependency list, so a typo in the destructure is a type error instead of a silent `undefined`.
389
491
 
390
492
  ```jsx
391
- import { configure, styleHandlers } from '@tenphi/tasty';
493
+ import { configure, defineHandler, styleHandlers } from '@tenphi/tasty';
392
494
 
393
495
  configure({
394
496
  handlers: {
395
- // Function only — overrides built-in fill handler
396
- fill: ({ fill }) => {
397
- if (fill?.startsWith('gradient:')) {
398
- return { background: fill.slice(9) };
399
- }
400
- return styleHandlers.fill({ fill });
401
- },
402
-
403
497
  // Function only — new single-prop handler
404
498
  elevation: ({ elevation }) => {
405
499
  const level = parseInt(elevation) || 1;
@@ -409,16 +503,112 @@ configure({
409
503
  };
410
504
  },
411
505
 
506
+ // Overriding a built-in: declare every style the built-in handled and pass
507
+ // them all through, or the ones you leave out stop working (see below).
508
+ fill: defineHandler(
509
+ [
510
+ 'fill', 'backgroundColor', 'image', 'backgroundImage',
511
+ 'backgroundPosition', 'backgroundSize', 'backgroundRepeat',
512
+ ],
513
+ (props) => {
514
+ if (typeof props.fill === 'string' && props.fill.startsWith('gradient:')) {
515
+ return { background: props.fill.slice(9) };
516
+ }
517
+ return styleHandlers.fill(props);
518
+ },
519
+ ),
520
+
412
521
  // Multi dep — handler reads multiple style properties
413
- gap: [['display', 'flow', 'gap'], ({ display, flow, gap }) => {
522
+ gap: defineHandler(['display', 'flow', 'gap'], ({ display, flow, gap }) => {
414
523
  if (!gap) return;
415
- const isGrid = display?.includes('grid');
524
+ const isGrid = String(display ?? '').includes('grid');
416
525
  return { gap: isGrid ? gap : `/* custom logic for ${flow} */` };
417
- }],
526
+ }),
418
527
  },
419
528
  });
420
529
  ```
421
530
 
531
+ ### Return shape
532
+
533
+ A handler returns a `CSSMap`, an array of them, or nothing:
534
+
535
+ - Keys are **kebab-case** CSS property names (`'background-color'`, not `backgroundColor`) or `--custom-property` names. A camelCase key warns in development and is emitted verbatim, which the browser ignores.
536
+ - Values are stringified, so numbers are fine (`{ '-webkit-line-clamp': 3 }`).
537
+ - The reserved `$` key is a **selector suffix**: `{ $: '& > *:not(:last-child)', 'margin-right': gap }` applies the declarations to a nested selector. It accepts an array to fan out over several.
538
+ - Return an array of maps to emit several declaration sets, each with its own `$`.
539
+
540
+ Values arrive **state-resolved but unparsed** — the raw authored DSL string (`'2x'`, `'#purple.5'`, `true`, `4`). Call the exported `parseStyle()` / `parseColor()` yourself; nothing parses them for you.
541
+
542
+ ### Replacing a built-in handler
543
+
544
+ Built-in handlers are shared across several style names. Registering a handler for one of those names unregisters the built-in from **all** of them, and the displaced names then fall back to auto-generated CSS aliases — so `hide: true` starts emitting a literal `hide: true` declaration. A development-mode warning lists exactly what was displaced.
545
+
546
+ The shared groups worth knowing:
547
+
548
+ | Registering a handler for | Also takes over |
549
+ |---|---|
550
+ | `fill` | `backgroundColor`, `image`, `backgroundImage`, `backgroundPosition`, `backgroundSize`, `backgroundRepeat` |
551
+ | `display` | `hide`, `overflow`, `whiteSpace`, `textOverflow`, `flow`, `gap` |
552
+ | `preset` | `font`, `fontSize`, `fontWeight`, `fontStyle`, `lineHeight`, `letterSpacing`, `textTransform` |
553
+ | `padding` / `margin` / `inset` | their `*Top`/`*Right`/`*Bottom`/`*Left`/`*Block`/`*Inline` longhands |
554
+
555
+ Either declare the whole group and delegate the rest to `styleHandlers.*`, or pick a name that isn't shared.
556
+
557
+ ### Chunk membership
558
+
559
+ Tasty renders and caches CSS in independent chunks, and a chunk's cache key covers only its own style values. All of a handler's dependencies must therefore live in one chunk. Custom style names are pulled into their handler's chunk automatically at registration; a handler whose dependencies span two *built-in* chunks (say `fill` and `padding`) warns, because it would be invoked once per chunk with a subset of its inputs.
560
+
561
+ `configure({ handlers })` must run before the first render, like every other config option.
562
+
563
+ ---
564
+
565
+ ## Props Middleware
566
+
567
+ `propHandlers` are middleware over a component's props — props in, props out. Where a style *handler* turns a style property into CSS declarations, a prop handler turns a **component prop** into other props, including `styles`. It is the extension point for props whose value isn't a style value.
568
+
569
+ ```jsx
570
+ import { configure, mergeStyles } from '@tenphi/tasty';
571
+
572
+ configure({
573
+ propHandlers: {
574
+ glaze: (props) => {
575
+ const { glaze, ...rest } = props;
576
+ if (!glaze) return rest;
577
+
578
+ return { ...rest, styles: mergeStyles(glazeStyles(glaze), rest.styles) };
579
+ },
580
+ },
581
+ });
582
+
583
+ <Element glaze="purple" />
584
+ ```
585
+
586
+ The map key is the handler's name and, by default, the prop that triggers it, so an absent prop costs one property check rather than a call. A tuple overrides that: `['glaze', fn]`, `[['glaze', 'tint'], fn]`, or `['*', fn]` for unconditional.
587
+
588
+ Handlers run at the very top of every component's render, before any prop is destructured, so one can rewrite `styles`, `mods`, `tokens`, `variant`, `as`, `element`, and `qa`. They run in registration order — plugins first, then direct config — each receiving the previous one's output.
589
+
590
+ Handlers must be **pure** and must not mutate their input, and should memoize the styles they build per input value: style values are cached by object identity, so mutating one in place yields stale CSS, and a reference-stable object avoids re-serializing on every render.
591
+
592
+ Injected styles occupy the `styles` slot, so they beat a component's own default styles and lose to a style prop at the call site. Prop handlers do not apply to sub-elements or to zero-runtime `tastyStatic()`, which has no props.
593
+
594
+ See [Plugins → Props middleware](plugins.md#props-middleware) for the full contract and a worked example.
595
+
596
+ ---
597
+
598
+ ## Base Style Props
599
+
600
+ `baseStyleProps` exposes style properties as props on **every** `tasty()` component, on top of the built-in base styles (`display`, `font`, `preset`, `hide`, `whiteSpace`, `opacity`, `transition`):
601
+
602
+ ```jsx
603
+ configure({ baseStyleProps: ['radius', 'shadow'] });
604
+
605
+ <Card radius="1r" shadow />
606
+ ```
607
+
608
+ `configure()` may run after your components are defined — each factory resolves its prop list lazily.
609
+
610
+ Each name costs one property check per render of every component, and the effect is app-global, so keep the list short and use a factory's own `styleProps` for anything narrower. Avoid names that collide with real DOM or component props (`width`, `size`, `color`), since every component will then swallow them as styles.
611
+
422
612
  ---
423
613
 
424
614
  ## Extending Style Types (TypeScript)
@@ -79,7 +79,7 @@ Retrieves CSS text for a given target. Logs the result with rule count and size.
79
79
  **Extra options:**
80
80
 
81
81
  ```typescript
82
- interface CssOptions extends DebugOptions {
82
+ interface CSSOptions extends DebugOptions {
83
83
  prettify?: boolean; // Format output (default: true)
84
84
  source?: boolean; // Read original CSS instead of live CSSOM (default: false, dev-mode only)
85
85
  }
@@ -111,14 +111,14 @@ Inspects a DOM element and returns detailed information about its tasty styles,
111
111
  ```typescript
112
112
  interface InspectResult {
113
113
  element?: Element | null;
114
- classes: string[]; // Tasty classes on the element
115
- chunks: ChunkInfo[]; // Chunk assignment per class
116
- css: string; // Prettified CSS
117
- size: number; // CSS size in characters
118
- rules: number; // Number of CSS rule blocks
114
+ classes: string[]; // Tasty classes on the element
115
+ chunks: DebugChunkInfo[]; // Chunk assignment per class
116
+ css: string; // Prettified CSS
117
+ size: number; // CSS size in characters
118
+ rules: number; // Number of CSS rule blocks
119
119
  }
120
120
 
121
- interface ChunkInfo {
121
+ interface DebugChunkInfo {
122
122
  className: string;
123
123
  chunkName: string | null; // e.g., 'appearance', 'font', 'dimension'
124
124
  }
@@ -117,11 +117,11 @@ Then use `preset: 'h1'` or `preset: 't2'` in any component's styles.
117
117
 
118
118
  ### Registering brand fonts
119
119
 
120
- Register your design system's custom fonts via `configure({ fontFace })` so every component can reference them:
120
+ Register your design system's custom fonts via `configure({ fontFaces })` so every component can reference them:
121
121
 
122
122
  ```ts
123
123
  configure({
124
- fontFace: {
124
+ fontFaces: {
125
125
  'Brand Sans': [
126
126
  { src: 'url("/fonts/brand-regular.woff2") format("woff2")', fontWeight: 400, fontDisplay: 'swap' },
127
127
  { src: 'url("/fonts/brand-bold.woff2") format("woff2")', fontWeight: 700, fontDisplay: 'swap' },
package/docs/tasty/dsl.md CHANGED
@@ -123,7 +123,7 @@ mods={{ hovered: true, theme: 'danger' }}
123
123
  // → data-hovered="" data-theme="danger"
124
124
  ```
125
125
 
126
- Modifiers can also be exposed as top-level component props via `modProps` — see [Runtime — Mod Props](react-api.md#mod-props).
126
+ Modifiers can also be exposed as top-level component props via `modProps` — see [React API — Mod Props](react-api.md#mod-props).
127
127
 
128
128
  ---
129
129
 
@@ -683,24 +683,24 @@ const AnimatedGradient = tasty({
683
683
 
684
684
  Here `$gradient-angle: '0deg'` is detected as `<angle>` and `#theme` as `<color>` (via the `#name` naming convention), so both transitions work without any manual `@property` declarations. Numeric types (`<number>`, `<length>`, `<percentage>`, `<angle>`, `<time>`) are inferred from values; `<color>` is inferred from `#name` tokens.
685
685
 
686
- Use explicit `@properties` when you need non-default settings like `inherits: false`:
686
+ Use explicit `@property` when you need non-default settings like `inherits: false`:
687
687
 
688
688
  ```jsx
689
- '@properties': {
689
+ '@property': {
690
690
  '$gradient-angle': { syntax: '<angle>', inherits: false, initialValue: '0deg' },
691
691
  },
692
692
  ```
693
693
 
694
694
  ---
695
695
 
696
- ## Font Face (`@fontFace`)
696
+ ## Font Face (`@font-face`)
697
697
 
698
698
  Register custom fonts directly inside a `styles` object. Keys are font-family names, values are descriptor objects (or arrays of them for multiple weights/styles).
699
699
 
700
700
  ```ts
701
701
  const Heading = tasty({
702
702
  styles: {
703
- '@fontFace': {
703
+ '@font-face': {
704
704
  'Brand Sans': {
705
705
  src: 'url("/fonts/brand-sans.woff2") format("woff2")',
706
706
  fontDisplay: 'swap',
@@ -716,7 +716,7 @@ const Heading = tasty({
716
716
  Supply an array to register several variants of the same family:
717
717
 
718
718
  ```ts
719
- '@fontFace': {
719
+ '@font-face': {
720
720
  'Brand Sans': [
721
721
  { src: 'url("/fonts/brand-regular.woff2") format("woff2")', fontWeight: 400, fontDisplay: 'swap' },
722
722
  { src: 'url("/fonts/brand-bold.woff2") format("woff2")', fontWeight: 700, fontDisplay: 'swap' },
@@ -745,7 +745,7 @@ Supply an array to register several variants of the same family:
745
745
 
746
746
  ---
747
747
 
748
- ## Counter Style (`@counterStyle`)
748
+ ## Counter Style (`@counter-style`)
749
749
 
750
750
  Define custom list markers via the CSS `@counter-style` at-rule. Keys are counter-style names, values are descriptor objects.
751
751
 
@@ -753,7 +753,7 @@ Define custom list markers via the CSS `@counter-style` at-rule. Keys are counte
753
753
  const EmojiList = tasty({
754
754
  tag: 'ol',
755
755
  styles: {
756
- '@counterStyle': {
756
+ '@counter-style': {
757
757
  thumbs: {
758
758
  system: 'cyclic',
759
759
  symbols: '"👍"',
@@ -784,6 +784,66 @@ const EmojiList = tasty({
784
784
 
785
785
  ---
786
786
 
787
+ ## Functions (`@function`)
788
+
789
+ Define reusable, parameterized CSS [custom functions](https://developer.mozilla.org/en-US/docs/Web/CSS/@function) via the CSS `@function` at-rule. A custom function takes parameters and returns a single value — like a dynamic custom property.
790
+
791
+ The token convention follows Tasty's `$` vs `$$` distinction:
792
+
793
+ - **`$$name`** — the literal callable name (`--name`). Used for the **definition key** and for **invocation** `$$name(...)`, mirroring the existing `$$gradient-angle` → `--gradient-angle` sugar. The definition key matches the call site.
794
+ - **`$name`** — a custom-property declaration/reference (`var(--name)`). Used for **parameters** and **local variables**, exactly like declaring custom props in a styles object.
795
+ - **Local variables** are declared directly as `$name` keys on the descriptor — the body reads like a mini styles object.
796
+ - `result`, local-variable values, and parameter `default` values flow through the full Tasty DSL, so units (`2x`), color tokens (`#theme`), auto-calc (`(-1 * $value)` → `calc(-1 * var(--value))`), and fallbacks (`($shadow-color, black)` → `var(--shadow-color, black)`) all work.
797
+
798
+ ```ts
799
+ const Box = tasty({
800
+ styles: {
801
+ '@function': {
802
+ // simplest: one bare param + result (auto-calc, no explicit calc())
803
+ '$$negative': { args: ['$value'], result: '(-1 * $value)' },
804
+
805
+ // typed param + default + return type + local variable
806
+ '$$shadow': {
807
+ args: { '$shadow-color': { syntax: '<color>', default: 'inherit' } },
808
+ returns: '<color>',
809
+ '$offset': '2px', // local variable
810
+ result: '$offset $offset ($shadow-color, black)',
811
+ },
812
+ },
813
+ marginTop: '$$negative(10px)', // → margin-top: --negative(10px)
814
+ boxShadow: '$$shadow(#accent)', // → box-shadow: --shadow(var(--accent-color))
815
+ },
816
+ });
817
+ ```
818
+
819
+ Generated CSS:
820
+
821
+ ```css
822
+ @function --negative(--value) { result: calc(-1 * var(--value)); }
823
+ @function --shadow(--shadow-color <color>: inherit) returns <color> {
824
+ --offset: 2px;
825
+ result: var(--offset) var(--offset) var(--shadow-color, black);
826
+ }
827
+ .t0 { margin-top: --negative(10px); box-shadow: --shadow(var(--accent-color)); }
828
+ ```
829
+
830
+ ### Descriptor shape
831
+
832
+ | Field | Type | Notes |
833
+ |---|---|---|
834
+ | `result` (required) | `string` | The `result:` value, parsed through the Tasty DSL. |
835
+ | `args` | `string[]` \| `Record<string, FunctionParameter>` | Ordered parameters. Array form lists bare names; object form maps names to type/default. |
836
+ | `returns` | `string` | Optional return type, e.g. `'<color>'`. |
837
+ | `$name` keys | `string \| number` | Any `$name` key declares a local variable `--name` (value parsed). |
838
+
839
+ A `FunctionParameter` is one of: `true` (bare param), a string CSS type shorthand (`'<length>'`), or `{ syntax?: string; default?: string | number }`.
840
+
841
+ Functions can also be registered with the [`useFunction`](react-api.md#usefunction) hook or globally via [`configure({ functions })`](configuration.md#functions) (the same map also accepts bare-key parse functions).
842
+
843
+ > `@function` is permanent — injected once and never cleaned up, like `@counter-style`. It is an experimental CSS feature ([Chrome 139+](https://developer.mozilla.org/en-US/docs/Web/CSS/@function)); unsupported browsers safely ignore the native rule, so use it as progressive enhancement — or enable the [`configure({ polyfills: { functions: true } })`](configuration.md#polyfills) inline polyfill to expand `$$name(...)` calls into plain CSS for full cross-browser support.
844
+
845
+ ---
846
+
787
847
  ## Style Properties
788
848
 
789
849
  For a complete reference of all enhanced style properties — syntax, values, modifiers, and recommendations — see **[Style Properties Reference](styles.md)**.