@keboola/design 16.1.0 → 17.1.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 (190) hide show
  1. package/CHANGELOG.md +54 -0
  2. package/dist/{AIKit-Cf5plya2.js → AIKit-DyysN1kS.js} +35 -45
  3. package/dist/AIKit-DyysN1kS.js.map +1 -0
  4. package/dist/{Alert-DziS8n1H.js → Alert-BQB-og_I.js} +2 -2
  5. package/dist/{Alert-DziS8n1H.js.map → Alert-BQB-og_I.js.map} +1 -1
  6. package/dist/{AlertModal-De04fFoy.js → AlertModal-BkmyEvsR.js} +2 -2
  7. package/dist/{AlertModal-De04fFoy.js.map → AlertModal-BkmyEvsR.js.map} +1 -1
  8. package/dist/{AppShell-BUa3U7-e.js → AppShell-CDbecT-t.js} +2 -2
  9. package/dist/{AppShell-BUa3U7-e.js.map → AppShell-CDbecT-t.js.map} +1 -1
  10. package/dist/{BrandEditor-hiLBX7az.js → BrandEditor-BHE6nsob.js} +6 -6
  11. package/dist/{BrandEditor-hiLBX7az.js.map → BrandEditor-BHE6nsob.js.map} +1 -1
  12. package/dist/{BrandLogo-Dn7hhp2c.js → BrandLogo-n4Qhi1tI.js} +2 -2
  13. package/dist/{BrandLogo-Dn7hhp2c.js.map → BrandLogo-n4Qhi1tI.js.map} +1 -1
  14. package/dist/{Breadcrumb-uGFEIjFF.js → Breadcrumb-BAwQTo0c.js} +3 -3
  15. package/dist/{Breadcrumb-uGFEIjFF.js.map → Breadcrumb-BAwQTo0c.js.map} +1 -1
  16. package/dist/{Button-DbvGzEDb.js → Button-BAMX1iuI.js} +2 -2
  17. package/dist/{Button-DbvGzEDb.js.map → Button-BAMX1iuI.js.map} +1 -1
  18. package/dist/{Checkbox-B2jLlyaO.js → Checkbox-CfjpwIcg.js} +2 -2
  19. package/dist/{Checkbox-B2jLlyaO.js.map → Checkbox-CfjpwIcg.js.map} +1 -1
  20. package/dist/{Clipboard-fAkDdpEu.js → Clipboard-BaU3cDi5.js} +7 -5
  21. package/dist/Clipboard-BaU3cDi5.js.map +1 -0
  22. package/dist/{ClipboardButton-71Ugbl8c.js → ClipboardButton-BWeaQEM2.js} +5 -4
  23. package/dist/ClipboardButton-BWeaQEM2.js.map +1 -0
  24. package/dist/{CodeEditor-D_b-ZCng.js → CodeEditor-BdTxkPD4.js} +4 -4
  25. package/dist/{CodeEditor-D_b-ZCng.js.map → CodeEditor-BdTxkPD4.js.map} +1 -1
  26. package/dist/{ColorInput-Cjr1jkvy.js → ColorInput-BoVdBxJ7.js} +3 -3
  27. package/dist/{ColorInput-Cjr1jkvy.js.map → ColorInput-BoVdBxJ7.js.map} +1 -1
  28. package/dist/{ColorModeSwitch-CuPYnJ2V.js → ColorModeSwitch-BDkdmHYl.js} +2 -2
  29. package/dist/{ColorModeSwitch-CuPYnJ2V.js.map → ColorModeSwitch-BDkdmHYl.js.map} +1 -1
  30. package/dist/{Combobox-DYjvYgl3.js → Combobox-RZ0i3w8u.js} +4 -4
  31. package/dist/{Combobox-DYjvYgl3.js.map → Combobox-RZ0i3w8u.js.map} +1 -1
  32. package/dist/{Command-BcTb6GsR.js → Command-D6XYzzJf.js} +2 -2
  33. package/dist/{Command-BcTb6GsR.js.map → Command-D6XYzzJf.js.map} +1 -1
  34. package/dist/{CopyField-CnwAvQz9.js → CopyField-9WBU8thS.js} +2 -2
  35. package/dist/{CopyField-CnwAvQz9.js.map → CopyField-9WBU8thS.js.map} +1 -1
  36. package/dist/{DateInput-DJNX7Vdx.js → DateInput-CCYG0AtT.js} +3 -3
  37. package/dist/{DateInput-DJNX7Vdx.js.map → DateInput-CCYG0AtT.js.map} +1 -1
  38. package/dist/{DateRangeInput-B3g8cyS0.js → DateRangeInput-CpZK1IFp.js} +3 -3
  39. package/dist/{DateRangeInput-B3g8cyS0.js.map → DateRangeInput-CpZK1IFp.js.map} +1 -1
  40. package/dist/{DateRangePicker-48yOB2qV.js → DateRangePicker-B2AUKX7u.js} +2 -2
  41. package/dist/{DateRangePicker-48yOB2qV.js.map → DateRangePicker-B2AUKX7u.js.map} +1 -1
  42. package/dist/{FieldItem-D7eCMfMB.js → FieldItem-eM7IHBt5.js} +3 -3
  43. package/dist/{FieldItem-D7eCMfMB.js.map → FieldItem-eM7IHBt5.js.map} +1 -1
  44. package/dist/{FileUpload-DskvxhAr.js → FileUpload-d-hNPfPV.js} +2 -2
  45. package/dist/{FileUpload-DskvxhAr.js.map → FileUpload-d-hNPfPV.js.map} +1 -1
  46. package/dist/{Form-BUNW7nlt.js → Form-B_9sNehB.js} +7 -7
  47. package/dist/{Form-BUNW7nlt.js.map → Form-B_9sNehB.js.map} +1 -1
  48. package/dist/{FormGroup-QJB21LKp.js → FormGroup-D7ahkK1q.js} +3 -3
  49. package/dist/{FormGroup-QJB21LKp.js.map → FormGroup-D7ahkK1q.js.map} +1 -1
  50. package/dist/{FullScreenModal-RzY5XxiG.js → FullScreenModal-CiRKNsls.js} +2 -2
  51. package/dist/{FullScreenModal-RzY5XxiG.js.map → FullScreenModal-CiRKNsls.js.map} +1 -1
  52. package/dist/{InlineEdit-CXL0ZslO.js → InlineEdit-BzOox46S.js} +4 -4
  53. package/dist/{InlineEdit-CXL0ZslO.js.map → InlineEdit-BzOox46S.js.map} +1 -1
  54. package/dist/{InputGroup-BWeanEo7.js → InputGroup-DnGP9-ZQ.js} +2 -2
  55. package/dist/{InputGroup-BWeanEo7.js.map → InputGroup-DnGP9-ZQ.js.map} +1 -1
  56. package/dist/{Kbd-BprYCICe.js → Kbd-6velz9J-.js} +2 -2
  57. package/dist/{Kbd-BprYCICe.js.map → Kbd-6velz9J-.js.map} +1 -1
  58. package/dist/{MermaidDiagram-E3azndPk.js → MermaidDiagram-l83gco3r.js} +2 -2
  59. package/dist/{MermaidDiagram-E3azndPk.js.map → MermaidDiagram-l83gco3r.js.map} +1 -1
  60. package/dist/{Modal-Cf_kPEBW.js → Modal-CLu6Eg5p.js} +2 -2
  61. package/dist/{Modal-Cf_kPEBW.js.map → Modal-CLu6Eg5p.js.map} +1 -1
  62. package/dist/{MultiActionButtonGroup-8WQwL4UQ.js → MultiActionButtonGroup-B3-wNw7w.js} +3 -3
  63. package/dist/{MultiActionButtonGroup-8WQwL4UQ.js.map → MultiActionButtonGroup-B3-wNw7w.js.map} +1 -1
  64. package/dist/{Navbar-CRjxVboE.js → Navbar-BEc-Pqo5.js} +2 -2
  65. package/dist/{Navbar-CRjxVboE.js.map → Navbar-BEc-Pqo5.js.map} +1 -1
  66. package/dist/{PageLayout-LcvJccOW.js → PageLayout-kY31oUix.js} +2 -2
  67. package/dist/{PageLayout-LcvJccOW.js.map → PageLayout-kY31oUix.js.map} +1 -1
  68. package/dist/{PageToolbar-By2HznxO.js → PageToolbar-NmiausP7.js} +2 -2
  69. package/dist/{PageToolbar-By2HznxO.js.map → PageToolbar-NmiausP7.js.map} +1 -1
  70. package/dist/{Pagination-DrXTrvfD.js → Pagination-DidOPSPB.js} +2 -2
  71. package/dist/{Pagination-DrXTrvfD.js.map → Pagination-DidOPSPB.js.map} +1 -1
  72. package/dist/{Popconfirm-BJuDOHdv.js → Popconfirm-C4ryoeGP.js} +2 -2
  73. package/dist/{Popconfirm-BJuDOHdv.js.map → Popconfirm-C4ryoeGP.js.map} +1 -1
  74. package/dist/{RadioGroup-B9oC8P15.js → RadioGroup-BIElT-nH.js} +2 -2
  75. package/dist/{RadioGroup-B9oC8P15.js.map → RadioGroup-BIElT-nH.js.map} +1 -1
  76. package/dist/{Search-OgaNjqQM.js → Search-xDWaQ2z3.js} +2 -2
  77. package/dist/{Search-OgaNjqQM.js.map → Search-xDWaQ2z3.js.map} +1 -1
  78. package/dist/{SearchInput-eLS-uvOn.js → SearchInput-BwlJ77mV.js} +3 -3
  79. package/dist/{SearchInput-eLS-uvOn.js.map → SearchInput-BwlJ77mV.js.map} +1 -1
  80. package/dist/{SectionNav-L81iJBo3.js → SectionNav-DV3Hwj-5.js} +14 -8
  81. package/dist/SectionNav-DV3Hwj-5.js.map +1 -0
  82. package/dist/{Select-DRdkdzBp.js → Select-C3Q_Xk_Z.js} +2 -2
  83. package/dist/{Select-DRdkdzBp.js.map → Select-C3Q_Xk_Z.js.map} +1 -1
  84. package/dist/{Sheet-DVb4XoJ5.js → Sheet-D7NnOyud.js} +2 -2
  85. package/dist/{Sheet-DVb4XoJ5.js.map → Sheet-D7NnOyud.js.map} +1 -1
  86. package/dist/{Sidebar-DYvodJWN.js → Sidebar-DaUDM8jm.js} +5 -5
  87. package/dist/{Sidebar-DYvodJWN.js.map → Sidebar-DaUDM8jm.js.map} +1 -1
  88. package/dist/{Slider-B9IskDxf.js → Slider-Cdl8FOvI.js} +3 -3
  89. package/dist/{Slider-B9IskDxf.js.map → Slider-Cdl8FOvI.js.map} +1 -1
  90. package/dist/{Table-BwgBm3hJ.js → Table-DtLrXt4i.js} +39 -7
  91. package/dist/Table-DtLrXt4i.js.map +1 -0
  92. package/dist/{Tabs-DmJB4l_N.js → Tabs-DUOUQKh7.js} +2 -2
  93. package/dist/{Tabs-DmJB4l_N.js.map → Tabs-DUOUQKh7.js.map} +1 -1
  94. package/dist/{TextInput--1CfZybC.js → TextInput-BAL-zOAN.js} +3 -3
  95. package/dist/{TextInput--1CfZybC.js.map → TextInput-BAL-zOAN.js.map} +1 -1
  96. package/dist/{ThemeProvider-BCHllN7d.js → ThemeProvider-MzVbTDBj.js} +2 -2
  97. package/dist/{ThemeProvider-BCHllN7d.js.map → ThemeProvider-MzVbTDBj.js.map} +1 -1
  98. package/dist/{ToggleAllTooltip-BFmA6TXf.js → ToggleAllTooltip-DQE5Lw6w.js} +2 -2
  99. package/dist/{ToggleAllTooltip-BFmA6TXf.js.map → ToggleAllTooltip-DQE5Lw6w.js.map} +1 -1
  100. package/dist/{ZoomableSvg-BRPGgaWJ.js → ZoomableSvg-CIOqAYpd.js} +4 -4
  101. package/dist/{ZoomableSvg-BRPGgaWJ.js.map → ZoomableSvg-CIOqAYpd.js.map} +1 -1
  102. package/dist/editors.js +3 -3
  103. package/dist/flint.js +1 -1
  104. package/dist/index.d.ts +409 -365
  105. package/dist/index.js +52 -50
  106. package/dist/internal/blocks/AIKit.js +1 -1
  107. package/dist/internal/blocks/AppShell.js +1 -1
  108. package/dist/internal/blocks/AuthLayout.js +1 -1
  109. package/dist/internal/blocks/BrandEditor.js +1 -1
  110. package/dist/internal/blocks/BulkActionsBar.js +55 -0
  111. package/dist/internal/blocks/BulkActionsBar.js.map +1 -0
  112. package/dist/internal/blocks/ChipEditor.js +2 -2
  113. package/dist/internal/blocks/ClipboardButton.js +1 -1
  114. package/dist/internal/blocks/ColorInput.js +1 -1
  115. package/dist/internal/blocks/ColorModeSwitch.js +1 -1
  116. package/dist/internal/blocks/Command.js +1 -1
  117. package/dist/internal/blocks/CopyField.js +1 -1
  118. package/dist/internal/blocks/DateInput.js +1 -1
  119. package/dist/internal/blocks/DateRangeInput.js +1 -1
  120. package/dist/internal/blocks/EmptyState.js +7 -2
  121. package/dist/internal/blocks/EmptyState.js.map +1 -1
  122. package/dist/internal/blocks/ExportMenu.js +2 -2
  123. package/dist/internal/blocks/Form/connectors/ComboboxField.js +2 -2
  124. package/dist/internal/blocks/Form/connectors/MultiComboboxField.js +1 -1
  125. package/dist/internal/blocks/Form.js +2 -2
  126. package/dist/internal/blocks/FormGroup.js +1 -1
  127. package/dist/internal/blocks/InlineEdit.js +1 -1
  128. package/dist/internal/blocks/MultiActionButtonGroup.js +1 -1
  129. package/dist/internal/blocks/MultiCombobox.js +3 -3
  130. package/dist/internal/blocks/NumberInput.js +1 -1
  131. package/dist/internal/blocks/PageLayout.js +1 -1
  132. package/dist/internal/blocks/PageSection.js +31 -0
  133. package/dist/internal/blocks/PageSection.js.map +1 -0
  134. package/dist/internal/blocks/PageToolbar.js +1 -1
  135. package/dist/internal/blocks/PasswordInput.js +2 -2
  136. package/dist/internal/blocks/SearchInput.js +1 -1
  137. package/dist/internal/blocks/SearchInputWithNavigation.js +3 -3
  138. package/dist/internal/blocks/SectionNav.js +1 -1
  139. package/dist/internal/blocks/SplitButton.js +1 -1
  140. package/dist/internal/blocks/TextInput.js +1 -1
  141. package/dist/internal/blocks/Textarea.js +1 -1
  142. package/dist/internal/blocks/TimeInput.js +2 -2
  143. package/dist/internal/components/Alert.js +1 -1
  144. package/dist/internal/components/AlertModal.js +1 -1
  145. package/dist/internal/components/Avatar.js +1 -1
  146. package/dist/internal/components/BrandLogo.js +1 -1
  147. package/dist/internal/components/Breadcrumb.js +1 -1
  148. package/dist/internal/components/Button.js +1 -1
  149. package/dist/internal/components/Checkbox.js +1 -1
  150. package/dist/internal/components/Clipboard.js +1 -1
  151. package/dist/internal/components/CollapsiblePanel.js +1 -1
  152. package/dist/internal/components/Combobox.js +1 -1
  153. package/dist/internal/components/DateRangePicker.js +1 -1
  154. package/dist/internal/components/FileUpload.js +1 -1
  155. package/dist/internal/components/FullScreenModal.js +1 -1
  156. package/dist/internal/components/InputGroup.js +1 -1
  157. package/dist/internal/components/Kbd.js +1 -1
  158. package/dist/internal/components/Modal.js +1 -1
  159. package/dist/internal/components/Navbar.js +1 -1
  160. package/dist/internal/components/Pagination.js +1 -1
  161. package/dist/internal/components/Popconfirm.js +1 -1
  162. package/dist/internal/components/RadioGroup.js +1 -1
  163. package/dist/internal/components/Search.js +1 -1
  164. package/dist/internal/components/Select.js +1 -1
  165. package/dist/internal/components/Sheet.js +1 -1
  166. package/dist/internal/components/Sidebar.js +1 -1
  167. package/dist/internal/components/Slider.js +1 -1
  168. package/dist/internal/components/Table.js +1 -1
  169. package/dist/internal/components/Tabs.js +1 -1
  170. package/dist/internal/components/ThemeProvider.js +1 -1
  171. package/dist/internal/components/Tooltip.js +1 -1
  172. package/dist/internal/components/Truncated.js +1 -1
  173. package/dist/internal/components/ZoomableSvg.js +1 -1
  174. package/dist/internal/utils.js +1 -1
  175. package/dist/markdown-editor.js +6 -6
  176. package/dist/mermaid.js +1 -1
  177. package/dist/rjsf.js +11 -11
  178. package/dist/rjsf.js.map +1 -1
  179. package/dist/styles.css +1 -1
  180. package/dist/testing.js +1 -1
  181. package/dist/{utils-DjFceY3H.js → utils-BxEJOnFD.js} +2 -2
  182. package/dist/{utils-DjFceY3H.js.map → utils-BxEJOnFD.js.map} +1 -1
  183. package/package.json +3 -3
  184. package/src/styles.css +50 -0
  185. package/src/theme.css +10 -8
  186. package/dist/AIKit-Cf5plya2.js.map +0 -1
  187. package/dist/Clipboard-fAkDdpEu.js.map +0 -1
  188. package/dist/ClipboardButton-71Ugbl8c.js.map +0 -1
  189. package/dist/SectionNav-L81iJBo3.js.map +0 -1
  190. package/dist/Table-BwgBm3hJ.js.map +0 -1
package/dist/testing.js CHANGED
@@ -1,4 +1,4 @@
1
- import { ThemeProvider } from "./ThemeProvider-BCHllN7d.js";
1
+ import { ThemeProvider } from "./ThemeProvider-MzVbTDBj.js";
2
2
  import { jsx } from "react/jsx-runtime";
3
3
  import { keboola } from "@keboola/brand-registry";
4
4
  import { render } from "@testing-library/react";
@@ -265,7 +265,7 @@ const debounce = (fn, delay) => {
265
265
  const getIsMac = () => {
266
266
  if (typeof navigator !== "undefined" && "userAgentData" in navigator) {
267
267
  const platform = navigator.userAgentData.platform;
268
- if (typeof platform === "string") return platform.toLowerCase() === "macos";
268
+ if (typeof platform === "string" && platform !== "") return platform.toLowerCase() === "macos";
269
269
  }
270
270
  if (typeof navigator !== "undefined" && typeof navigator.platform === "string") return navigator.platform.toUpperCase().indexOf("MAC") >= 0;
271
271
  return false;
@@ -314,4 +314,4 @@ const splitEntry = (entry, separator) => {
314
314
  };
315
315
  export { DEFAULT_ENTRY_SEPARATOR, HINT_UNDERLINE_CLASS_NAME, Tooltip, TooltipContent, TooltipProvider, TooltipRoot, TooltipTrigger, copyToClipboard, createChangeInputEvent, createPrefixedString, debounce, isMac, keyCodes, noop, splitEntry, useSHA256, withHiddenFullscreen, withTooltipProvider, withVisualSettle };
316
316
 
317
- //# sourceMappingURL=utils-DjFceY3H.js.map
317
+ //# sourceMappingURL=utils-BxEJOnFD.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"utils-DjFceY3H.js","names":["Root"],"sources":["../src/utils/copyToClipboard.ts","../src/utils/createChangeInputEvent.ts","../src/constants/keyCodes.ts","../src/components/Tooltip/TooltipContent.tsx","../src/components/Tooltip/TooltipRoot.tsx","../src/components/Tooltip/TooltipTitle.tsx","../src/components/Tooltip/TooltipTrigger.tsx","../src/components/Tooltip/Tooltip.tsx","../src/utils/decorators.tsx","../src/utils/createPrefixedString.ts","../src/utils/noop.ts","../src/utils/debounce.ts","../src/utils/isMac.ts","../src/utils/useSHA256.ts","../src/utils/splitEntry.ts"],"sourcesContent":["/**\n * The async Clipboard API requires the document to be focused and rejects with\n * `NotAllowedError: Document is not focused` otherwise — which is the normal state\n * for a page inside an iframe that has not taken focus, such as Storybook's canvas\n * or an embedded preview. `execCommand` has no such requirement because it copies\n * the selection of a node we focus ourselves, so it covers that gap.\n */\nconst copyViaSelection = (text: string) => {\n const node = document.createElement('textarea');\n node.value = text;\n node.setAttribute('readonly', '');\n node.style.cssText = 'position:fixed;top:0;left:0;opacity:0';\n document.body.append(node);\n node.select();\n\n try {\n return document.execCommand('copy');\n } finally {\n node.remove();\n }\n};\n\nexport const copyToClipboard = async (text: string) => {\n try {\n await navigator.clipboard.writeText(text);\n } catch (error) {\n if (!copyViaSelection(text)) throw error;\n }\n};\n","import type { ChangeEvent } from 'react';\n\nexport const createChangeInputEvent = (input: HTMLInputElement) => {\n const changeEvent: ChangeEvent<HTMLInputElement> = {\n target: input,\n currentTarget: input,\n type: 'change',\n nativeEvent: new Event('change', { bubbles: true }),\n bubbles: true,\n cancelable: false,\n defaultPrevented: false,\n eventPhase: 2, // AT_TARGET\n isTrusted: false,\n preventDefault: () => {},\n isDefaultPrevented: () => false,\n stopPropagation: () => {},\n isPropagationStopped: () => false,\n persist: () => {},\n timeStamp: Date.now(),\n };\n\n Object.defineProperty(changeEvent, 'target', {\n value: input,\n writable: false,\n });\n\n return changeEvent;\n};\n","export const keyCodes = {\n ENTER: 'Enter',\n ESCAPE: 'Escape',\n SPACE: ' ',\n};\n","import type { ComponentProps } from 'react';\nimport { Content, Portal } from '@radix-ui/react-tooltip';\nimport type { VariantProps } from 'class-variance-authority';\nimport { cva } from 'class-variance-authority';\n\nconst tooltipVariants = cva(\n [\n 'tailwindcss-preflight',\n 'tw:inline-block',\n 'tw:wrap-anywhere',\n 'tw:max-h-96',\n 'tw:overflow-y-auto',\n // Above `z-overlay` — every modal, menu and popup.\n 'tw:z-[1060]',\n\n // rich content\n 'tw:[&_hr]:my-3',\n 'tw:[&_hr]:border-current/20',\n 'tw:[&_p:last-of-type]:mb-0',\n\n // chrome\n 'tw:rounded-popover',\n 'tw:border',\n 'tw:border-solid',\n 'tw:border-border',\n 'tw:bg-popover',\n 'tw:text-popover-foreground',\n 'tw:shadow-md',\n\n // open animation\n 'tw:data-[state=delayed-open]:animate-in',\n 'tw:data-[state=instant-open]:animate-in',\n 'tw:data-[state=delayed-open]:fade-in-0',\n 'tw:data-[state=instant-open]:fade-in-0',\n 'tw:data-[state=delayed-open]:zoom-in-95',\n 'tw:data-[state=instant-open]:zoom-in-95',\n\n // closed animation\n 'tw:data-[state=closed]:animate-out',\n 'tw:data-[state=closed]:fade-out-0',\n 'tw:data-[state=closed]:zoom-out-95',\n\n // position animation\n 'tw:data-[side=bottom]:slide-in-from-top-2',\n 'tw:data-[side=left]:slide-in-from-right-2',\n 'tw:data-[side=right]:slide-in-from-left-2',\n 'tw:data-[side=top]:slide-in-from-bottom-2',\n ],\n {\n defaultVariants: {\n variant: 'action',\n },\n variants: {\n variant: {\n action: [\n 'tw:max-w-fit',\n 'tw:px-3',\n 'tw:py-2',\n\n 'tw:text-center',\n 'tw:text-xs',\n 'tw:font-medium',\n ],\n explanatory: [\n 'tw:max-w-80',\n 'tw:px-4',\n 'tw:py-3',\n 'tw:text-left',\n\n 'tw:text-sm',\n 'tw:font-normal',\n ],\n },\n },\n },\n);\n\ntype Props = {\n keepOpenOnPointerDownOutside?: boolean;\n placement?: ComponentProps<typeof Content>['side'];\n} & Omit<ComponentProps<typeof Content>, 'side'> &\n VariantProps<typeof tooltipVariants>;\n\nexport const TooltipContent = ({\n className,\n variant,\n keepOpenOnPointerDownOutside = false,\n children,\n onPointerDownOutside,\n sideOffset = 8,\n collisionPadding = 8,\n hideWhenDetached = true,\n placement = 'right',\n ...rest\n}: Props) => {\n const handlePointerDownOutside: ComponentProps<typeof Content>['onPointerDownOutside'] = (\n event,\n ) => {\n if (keepOpenOnPointerDownOutside) event.preventDefault();\n onPointerDownOutside?.(event);\n };\n\n return (\n <Portal>\n <Content\n {...rest}\n sideOffset={sideOffset}\n collisionPadding={collisionPadding}\n onPointerDownOutside={handlePointerDownOutside}\n className={tooltipVariants({ className, variant })}\n hideWhenDetached={hideWhenDetached}\n side={placement}\n >\n {children}\n </Content>\n </Portal>\n );\n};\n","import type { ComponentProps } from 'react';\nimport { Root } from '@radix-ui/react-tooltip';\n\ntype Props = ComponentProps<typeof Root>;\n\nconst DELAY_SHOW_TOOLTIP = 300;\n\nexport const TooltipRoot = ({ children, delayDuration = DELAY_SHOW_TOOLTIP, ...rest }: Props) => (\n <Root {...rest} delayDuration={delayDuration}>\n {children}\n </Root>\n);\n","import type { ComponentProps } from 'react';\n\nimport { cn } from '../../utils';\n\n/**\n * Small uppercase heading above a rich tooltip's body copy, in the tooltip's text colour.\n */\nexport const TooltipTitle = ({ className, ...rest }: ComponentProps<'div'>) => (\n <div\n className={cn('tw:mb-2 tw:text-xs tw:leading-5 tw:font-semibold tw:uppercase', className)}\n {...rest}\n />\n);\n","import type { ComponentProps } from 'react';\nimport { Slot } from '@radix-ui/react-slot';\nimport { Trigger } from '@radix-ui/react-tooltip';\n\nimport { cn } from '../../utils';\n\n/**\n * Radix stamps the tooltip's own open/closed `data-state` onto the trigger. Merged onto an\n * `asChild` child that keeps a `data-state` of its own — `ToggleGroup.Item`, `Switch`, a `Tabs`\n * trigger — it wins, because those primitives spread incoming props *after* their own attribute.\n * The child then silently loses every `data-[state=…]` style it has, which is usually the only\n * thing marking it as selected.\n *\n * The tooltip's trigger state is styled nowhere, so it is dropped before it reaches the child.\n */\nconst WithoutTooltipState = ({\n children,\n ...props\n // `Slot`'s own props, plus the one attribute this exists to remove: React's types declare no\n // `data-*`, so it has to be named to be destructured away.\n}: ComponentProps<typeof Slot> & { 'data-state'?: string }) => {\n const { 'data-state': _tooltipState, ...rest } = props;\n\n return <Slot {...rest}>{children}</Slot>;\n};\n\ntype Props = {\n keepOpenOnClick?: boolean;\n} & ComponentProps<typeof Trigger>;\n\nexport const TooltipTrigger = ({\n ref,\n children,\n className,\n keepOpenOnClick = false,\n onClick,\n onPointerDown,\n asChild,\n ...rest\n}: Props) => {\n const handleClick: ComponentProps<typeof Trigger>['onClick'] = (event) => {\n if (keepOpenOnClick) event.preventDefault();\n onClick?.(event);\n };\n\n const handlePointerDown: ComponentProps<typeof Trigger>['onPointerDown'] = (event) => {\n if (keepOpenOnClick) event.preventDefault();\n onPointerDown?.(event);\n };\n\n return (\n <Trigger\n {...rest}\n asChild\n ref={ref}\n className={cn('tailwindcss-preflight', className)}\n onClick={handleClick}\n onPointerDown={handlePointerDown}\n >\n {asChild ? (\n <WithoutTooltipState>{children}</WithoutTooltipState>\n ) : (\n // Default-mode trigger wraps children in a span so Radix has a\n // single DOM element to attach handlers to. `tailwindcss-preflight`\n // (merged in via Slot) activates Tailwind's preflight inside the\n // span, which sets `svg { display: block }` — without an inline-flex\n // container that would stack any bare Lucide icon onto its own\n // line. `tw:inline-flex tw:items-center` keeps icon + text aligned.\n <span className=\"tw:inline-flex tw:items-center\">{children}</span>\n )}\n </Trigger>\n );\n};\n","import { useState } from 'react';\nimport type { ComponentProps, ReactNode } from 'react';\nimport type { Content, Trigger } from '@radix-ui/react-tooltip';\nimport { Provider } from '@radix-ui/react-tooltip';\n\nimport { keyCodes } from '../../constants/keyCodes';\n\nimport { TooltipContent } from './TooltipContent';\nimport { TooltipRoot } from './TooltipRoot';\nimport { TooltipTitle } from './TooltipTitle';\nimport { TooltipTrigger } from './TooltipTrigger';\n\nconst ACTION_TOOLTIP_LIMIT = 30;\n\nexport const HINT_UNDERLINE_CLASS_NAME =\n 'tw:cursor-help tw:underline tw:decoration-dashed tw:decoration-muted-foreground/50 tw:underline-offset-2';\n\ntype TriggerProps = {\n triggerAsChild?: boolean;\n};\n\nexport type Props = {\n /** Stays open on trigger click (click-to-copy feedback). */\n keepOpenOnTriggerClick?: boolean;\n /** Plain text only — interactive content belongs in `HoverCard` / `Popover`. */\n tooltip: ReactNode;\n children: ReactNode;\n placement?: ComponentProps<typeof Content>['side'];\n /** Hides it regardless of hover. */\n forceHide?: boolean;\n /** Shows it regardless of hover (e.g. guided tours). */\n forceShow?: boolean;\n /** In ms; defaults to the shared 300ms. */\n delayDuration?: number;\n /** Dashed-underline hover hint on the trigger. */\n hintUnderline?: boolean;\n className?: string;\n} & TriggerProps &\n Pick<ComponentProps<typeof TooltipContent>, 'variant' | 'className'>;\n\n/** Mount once at the app root so tooltips share delay state. */\nexport const TooltipProvider = Provider;\n\n/**\n * Short plain-text label on hover or focus.\n *\n * - Use for icon-only buttons, disabled controls, truncated values.\n * - Rich content → `HoverCard`; links or buttons → `Popover` (they break a11y here).\n * - `variant` defaults to `\"explanatory\"` for strings over 30 chars, else `\"action\"`.\n * - A disabled `Button` takes `disabledReason` instead.\n */\nexport const Tooltip = ({\n tooltip,\n children,\n className,\n keepOpenOnTriggerClick = false,\n variant,\n placement = 'right',\n forceHide = false,\n forceShow = false,\n delayDuration,\n triggerAsChild = false,\n hintUnderline = false,\n}: Props) => {\n const [open, setOpen] = useState(false);\n\n const resolvedVariant = (() => {\n if (!!variant) return variant;\n if (typeof tooltip === 'string' && tooltip.length > ACTION_TOOLTIP_LIMIT) return 'explanatory';\n\n return 'action';\n })();\n\n const isActionVariant = resolvedVariant === 'action';\n\n const handleKeyUp: ComponentProps<typeof Trigger>['onKeyUp'] = (event) => {\n if (![keyCodes.ENTER, keyCodes.SPACE].includes(event.key)) return;\n event.stopPropagation();\n };\n\n return (\n <TooltipRoot\n open={!!tooltip && (open || forceShow) && !forceHide}\n onOpenChange={setOpen}\n delayDuration={delayDuration}\n disableHoverableContent={isActionVariant}\n >\n <TooltipTrigger\n asChild={triggerAsChild}\n keepOpenOnClick={keepOpenOnTriggerClick}\n onKeyUp={handleKeyUp}\n className={hintUnderline ? HINT_UNDERLINE_CLASS_NAME : undefined}\n >\n {children}\n </TooltipTrigger>\n\n <TooltipContent\n className={className}\n variant={resolvedVariant}\n placement={placement}\n keepOpenOnPointerDownOutside={keepOpenOnTriggerClick}\n >\n {tooltip}\n </TooltipContent>\n </TooltipRoot>\n );\n};\n\nTooltip.Root = TooltipRoot;\nTooltip.Content = TooltipContent;\nTooltip.Trigger = TooltipTrigger;\nTooltip.Title = TooltipTitle;\n","import type { ComponentType } from 'react';\n\nimport { TooltipProvider } from '../components/Tooltip';\n\nexport const withTooltipProvider = (Story: ComponentType) => (\n <TooltipProvider>\n <Story />\n </TooltipProvider>\n);\n\n// Marks a story whose final render arrives asynchronously (lazy chunk, debounced\n// parse). The visual suite waits for every `[data-skeleton]` inside this box to\n// unmount before capturing, so the baseline is the settled content, never the\n// placeholder it briefly shows.\nexport const withVisualSettle = (Story: ComponentType) => (\n <div data-visual-settle>\n <Story />\n </div>\n);\n\n// position:fixed only fills the Storybook iframe, not the browser window.\nexport const withHiddenFullscreen = (Story: ComponentType) => (\n <div className=\"tw:[&_[aria-label=Fullscreen]]:hidden\">\n <Story />\n </div>\n);\n","export const createPrefixedString = (prefix: string) => (literals: TemplateStringsArray) =>\n literals.reduce((acc, literal) => acc + literal, `${prefix}-`);\n","export const noop = () => void 0;\n","type DebouncedFn<T extends (...args: any[]) => void> = {\n (...args: Parameters<T>): void;\n cancel: () => void;\n};\n\nexport const debounce = <T extends (...args: any[]) => void>(\n fn: T,\n delay: number,\n): DebouncedFn<T> => {\n let timeoutId: ReturnType<typeof setTimeout>;\n const debounced = (...args: Parameters<T>) => {\n clearTimeout(timeoutId);\n timeoutId = setTimeout(() => fn(...args), delay);\n };\n debounced.cancel = () => clearTimeout(timeoutId);\n return debounced;\n};\n","// Platform detection\ntype NavigatorUAData = {\n platform: string;\n brands: { brand: string; version: string }[];\n mobile: boolean;\n};\n\nconst getIsMac = (): boolean => {\n // Modern approach using navigator.userAgentData\n if (typeof navigator !== 'undefined' && 'userAgentData' in navigator) {\n const platform = (navigator.userAgentData as NavigatorUAData).platform;\n\n if (typeof platform === 'string') {\n return platform.toLowerCase() === 'macos';\n }\n }\n\n if (typeof navigator !== 'undefined' && typeof navigator.platform === 'string') {\n return navigator.platform.toUpperCase().indexOf('MAC') >= 0;\n }\n\n // Server-side rendering fallback\n return false;\n};\n\nexport const isMac = getIsMac();\n","import { useEffect, useState } from 'react';\n\n// https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/digest#converting_a_digest_to_a_hex_string\nconst sha256 = async (text: string) => {\n const msgUint8 = new TextEncoder().encode(text);\n const hashBuffer = await crypto.subtle.digest('SHA-256', msgUint8);\n const hashArray = Array.from(new Uint8Array(hashBuffer));\n return hashArray.map((b) => b.toString(16).padStart(2, '0')).join('');\n};\n\nexport const useSHA256 = (text?: string) => {\n const [hash, setHash] = useState('');\n\n useEffect(() => {\n if (!text) return;\n let cancelled = false;\n sha256(text).then((h) => {\n if (!cancelled) setHash(h);\n });\n return () => {\n cancelled = true;\n };\n }, [text]);\n\n // Empty input has no hash — derive it during render instead of syncing state\n // in the effect (avoids the extra render and a stale-value frame).\n return text ? hash : '';\n};\n","/** The separator a typed entry is split on when the caller names none. */\nexport const DEFAULT_ENTRY_SEPARATOR = ',';\n\n/**\n * The strings one typed entry stands for.\n *\n * - Parts are trimmed; blanks dropped.\n * - Repeats collapse case-insensitively, matching the combobox's display-string matching.\n * - A `null` separator returns the entry verbatim, untrimmed — the caller must reject blank text.\n */\nexport const splitEntry = (entry: string, separator: string | RegExp | null): string[] => {\n if (separator === null) return [entry];\n\n const seen = new Set<string>();\n return entry\n .split(separator)\n .map((part) => part.trim())\n .filter((part) => {\n if (part === '') return false;\n const key = part.toLowerCase();\n if (seen.has(key)) return false;\n seen.add(key);\n return true;\n });\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"utils-BxEJOnFD.js","names":["Root"],"sources":["../src/utils/copyToClipboard.ts","../src/utils/createChangeInputEvent.ts","../src/constants/keyCodes.ts","../src/components/Tooltip/TooltipContent.tsx","../src/components/Tooltip/TooltipRoot.tsx","../src/components/Tooltip/TooltipTitle.tsx","../src/components/Tooltip/TooltipTrigger.tsx","../src/components/Tooltip/Tooltip.tsx","../src/utils/decorators.tsx","../src/utils/createPrefixedString.ts","../src/utils/noop.ts","../src/utils/debounce.ts","../src/utils/isMac.ts","../src/utils/useSHA256.ts","../src/utils/splitEntry.ts"],"sourcesContent":["/**\n * The async Clipboard API requires the document to be focused and rejects with\n * `NotAllowedError: Document is not focused` otherwise — which is the normal state\n * for a page inside an iframe that has not taken focus, such as Storybook's canvas\n * or an embedded preview. `execCommand` has no such requirement because it copies\n * the selection of a node we focus ourselves, so it covers that gap.\n */\nconst copyViaSelection = (text: string) => {\n const node = document.createElement('textarea');\n node.value = text;\n node.setAttribute('readonly', '');\n node.style.cssText = 'position:fixed;top:0;left:0;opacity:0';\n document.body.append(node);\n node.select();\n\n try {\n return document.execCommand('copy');\n } finally {\n node.remove();\n }\n};\n\nexport const copyToClipboard = async (text: string) => {\n try {\n await navigator.clipboard.writeText(text);\n } catch (error) {\n if (!copyViaSelection(text)) throw error;\n }\n};\n","import type { ChangeEvent } from 'react';\n\nexport const createChangeInputEvent = (input: HTMLInputElement) => {\n const changeEvent: ChangeEvent<HTMLInputElement> = {\n target: input,\n currentTarget: input,\n type: 'change',\n nativeEvent: new Event('change', { bubbles: true }),\n bubbles: true,\n cancelable: false,\n defaultPrevented: false,\n eventPhase: 2, // AT_TARGET\n isTrusted: false,\n preventDefault: () => {},\n isDefaultPrevented: () => false,\n stopPropagation: () => {},\n isPropagationStopped: () => false,\n persist: () => {},\n timeStamp: Date.now(),\n };\n\n Object.defineProperty(changeEvent, 'target', {\n value: input,\n writable: false,\n });\n\n return changeEvent;\n};\n","export const keyCodes = {\n ENTER: 'Enter',\n ESCAPE: 'Escape',\n SPACE: ' ',\n};\n","import type { ComponentProps } from 'react';\nimport { Content, Portal } from '@radix-ui/react-tooltip';\nimport type { VariantProps } from 'class-variance-authority';\nimport { cva } from 'class-variance-authority';\n\nconst tooltipVariants = cva(\n [\n 'tailwindcss-preflight',\n 'tw:inline-block',\n 'tw:wrap-anywhere',\n 'tw:max-h-96',\n 'tw:overflow-y-auto',\n // Above `z-overlay` — every modal, menu and popup.\n 'tw:z-[1060]',\n\n // rich content\n 'tw:[&_hr]:my-3',\n 'tw:[&_hr]:border-current/20',\n 'tw:[&_p:last-of-type]:mb-0',\n\n // chrome\n 'tw:rounded-popover',\n 'tw:border',\n 'tw:border-solid',\n 'tw:border-border',\n 'tw:bg-popover',\n 'tw:text-popover-foreground',\n 'tw:shadow-md',\n\n // open animation\n 'tw:data-[state=delayed-open]:animate-in',\n 'tw:data-[state=instant-open]:animate-in',\n 'tw:data-[state=delayed-open]:fade-in-0',\n 'tw:data-[state=instant-open]:fade-in-0',\n 'tw:data-[state=delayed-open]:zoom-in-95',\n 'tw:data-[state=instant-open]:zoom-in-95',\n\n // closed animation\n 'tw:data-[state=closed]:animate-out',\n 'tw:data-[state=closed]:fade-out-0',\n 'tw:data-[state=closed]:zoom-out-95',\n\n // position animation\n 'tw:data-[side=bottom]:slide-in-from-top-2',\n 'tw:data-[side=left]:slide-in-from-right-2',\n 'tw:data-[side=right]:slide-in-from-left-2',\n 'tw:data-[side=top]:slide-in-from-bottom-2',\n ],\n {\n defaultVariants: {\n variant: 'action',\n },\n variants: {\n variant: {\n action: [\n 'tw:max-w-fit',\n 'tw:px-3',\n 'tw:py-2',\n\n 'tw:text-center',\n 'tw:text-xs',\n 'tw:font-medium',\n ],\n explanatory: [\n 'tw:max-w-80',\n 'tw:px-4',\n 'tw:py-3',\n 'tw:text-left',\n\n 'tw:text-sm',\n 'tw:font-normal',\n ],\n },\n },\n },\n);\n\ntype Props = {\n keepOpenOnPointerDownOutside?: boolean;\n placement?: ComponentProps<typeof Content>['side'];\n} & Omit<ComponentProps<typeof Content>, 'side'> &\n VariantProps<typeof tooltipVariants>;\n\nexport const TooltipContent = ({\n className,\n variant,\n keepOpenOnPointerDownOutside = false,\n children,\n onPointerDownOutside,\n sideOffset = 8,\n collisionPadding = 8,\n hideWhenDetached = true,\n placement = 'right',\n ...rest\n}: Props) => {\n const handlePointerDownOutside: ComponentProps<typeof Content>['onPointerDownOutside'] = (\n event,\n ) => {\n if (keepOpenOnPointerDownOutside) event.preventDefault();\n onPointerDownOutside?.(event);\n };\n\n return (\n <Portal>\n <Content\n {...rest}\n sideOffset={sideOffset}\n collisionPadding={collisionPadding}\n onPointerDownOutside={handlePointerDownOutside}\n className={tooltipVariants({ className, variant })}\n hideWhenDetached={hideWhenDetached}\n side={placement}\n >\n {children}\n </Content>\n </Portal>\n );\n};\n","import type { ComponentProps } from 'react';\nimport { Root } from '@radix-ui/react-tooltip';\n\ntype Props = ComponentProps<typeof Root>;\n\nconst DELAY_SHOW_TOOLTIP = 300;\n\nexport const TooltipRoot = ({ children, delayDuration = DELAY_SHOW_TOOLTIP, ...rest }: Props) => (\n <Root {...rest} delayDuration={delayDuration}>\n {children}\n </Root>\n);\n","import type { ComponentProps } from 'react';\n\nimport { cn } from '../../utils';\n\n/**\n * Small uppercase heading above a rich tooltip's body copy, in the tooltip's text colour.\n */\nexport const TooltipTitle = ({ className, ...rest }: ComponentProps<'div'>) => (\n <div\n className={cn('tw:mb-2 tw:text-xs tw:leading-5 tw:font-semibold tw:uppercase', className)}\n {...rest}\n />\n);\n","import type { ComponentProps } from 'react';\nimport { Slot } from '@radix-ui/react-slot';\nimport { Trigger } from '@radix-ui/react-tooltip';\n\nimport { cn } from '../../utils';\n\n/**\n * Radix stamps the tooltip's own open/closed `data-state` onto the trigger. Merged onto an\n * `asChild` child that keeps a `data-state` of its own — `ToggleGroup.Item`, `Switch`, a `Tabs`\n * trigger — it wins, because those primitives spread incoming props *after* their own attribute.\n * The child then silently loses every `data-[state=…]` style it has, which is usually the only\n * thing marking it as selected.\n *\n * The tooltip's trigger state is styled nowhere, so it is dropped before it reaches the child.\n */\nconst WithoutTooltipState = ({\n children,\n ...props\n // `Slot`'s own props, plus the one attribute this exists to remove: React's types declare no\n // `data-*`, so it has to be named to be destructured away.\n}: ComponentProps<typeof Slot> & { 'data-state'?: string }) => {\n const { 'data-state': _tooltipState, ...rest } = props;\n\n return <Slot {...rest}>{children}</Slot>;\n};\n\ntype Props = {\n keepOpenOnClick?: boolean;\n} & ComponentProps<typeof Trigger>;\n\nexport const TooltipTrigger = ({\n ref,\n children,\n className,\n keepOpenOnClick = false,\n onClick,\n onPointerDown,\n asChild,\n ...rest\n}: Props) => {\n const handleClick: ComponentProps<typeof Trigger>['onClick'] = (event) => {\n if (keepOpenOnClick) event.preventDefault();\n onClick?.(event);\n };\n\n const handlePointerDown: ComponentProps<typeof Trigger>['onPointerDown'] = (event) => {\n if (keepOpenOnClick) event.preventDefault();\n onPointerDown?.(event);\n };\n\n return (\n <Trigger\n {...rest}\n asChild\n ref={ref}\n className={cn('tailwindcss-preflight', className)}\n onClick={handleClick}\n onPointerDown={handlePointerDown}\n >\n {asChild ? (\n <WithoutTooltipState>{children}</WithoutTooltipState>\n ) : (\n // Default-mode trigger wraps children in a span so Radix has a\n // single DOM element to attach handlers to. `tailwindcss-preflight`\n // (merged in via Slot) activates Tailwind's preflight inside the\n // span, which sets `svg { display: block }` — without an inline-flex\n // container that would stack any bare Lucide icon onto its own\n // line. `tw:inline-flex tw:items-center` keeps icon + text aligned.\n <span className=\"tw:inline-flex tw:items-center\">{children}</span>\n )}\n </Trigger>\n );\n};\n","import { useState } from 'react';\nimport type { ComponentProps, ReactNode } from 'react';\nimport type { Content, Trigger } from '@radix-ui/react-tooltip';\nimport { Provider } from '@radix-ui/react-tooltip';\n\nimport { keyCodes } from '../../constants/keyCodes';\n\nimport { TooltipContent } from './TooltipContent';\nimport { TooltipRoot } from './TooltipRoot';\nimport { TooltipTitle } from './TooltipTitle';\nimport { TooltipTrigger } from './TooltipTrigger';\n\nconst ACTION_TOOLTIP_LIMIT = 30;\n\nexport const HINT_UNDERLINE_CLASS_NAME =\n 'tw:cursor-help tw:underline tw:decoration-dashed tw:decoration-muted-foreground/50 tw:underline-offset-2';\n\ntype TriggerProps = {\n triggerAsChild?: boolean;\n};\n\nexport type Props = {\n /** Stays open on trigger click (click-to-copy feedback). */\n keepOpenOnTriggerClick?: boolean;\n /** Plain text only — interactive content belongs in `HoverCard` / `Popover`. */\n tooltip: ReactNode;\n children: ReactNode;\n placement?: ComponentProps<typeof Content>['side'];\n /** Hides it regardless of hover. */\n forceHide?: boolean;\n /** Shows it regardless of hover (e.g. guided tours). */\n forceShow?: boolean;\n /** In ms; defaults to the shared 300ms. */\n delayDuration?: number;\n /** Dashed-underline hover hint on the trigger. */\n hintUnderline?: boolean;\n className?: string;\n} & TriggerProps &\n Pick<ComponentProps<typeof TooltipContent>, 'variant' | 'className'>;\n\n/** Mount once at the app root so tooltips share delay state. */\nexport const TooltipProvider = Provider;\n\n/**\n * Short plain-text label on hover or focus.\n *\n * - Use for icon-only buttons, disabled controls, truncated values.\n * - Rich content → `HoverCard`; links or buttons → `Popover` (they break a11y here).\n * - `variant` defaults to `\"explanatory\"` for strings over 30 chars, else `\"action\"`.\n * - A disabled `Button` takes `disabledReason` instead.\n */\nexport const Tooltip = ({\n tooltip,\n children,\n className,\n keepOpenOnTriggerClick = false,\n variant,\n placement = 'right',\n forceHide = false,\n forceShow = false,\n delayDuration,\n triggerAsChild = false,\n hintUnderline = false,\n}: Props) => {\n const [open, setOpen] = useState(false);\n\n const resolvedVariant = (() => {\n if (!!variant) return variant;\n if (typeof tooltip === 'string' && tooltip.length > ACTION_TOOLTIP_LIMIT) return 'explanatory';\n\n return 'action';\n })();\n\n const isActionVariant = resolvedVariant === 'action';\n\n const handleKeyUp: ComponentProps<typeof Trigger>['onKeyUp'] = (event) => {\n if (![keyCodes.ENTER, keyCodes.SPACE].includes(event.key)) return;\n event.stopPropagation();\n };\n\n return (\n <TooltipRoot\n open={!!tooltip && (open || forceShow) && !forceHide}\n onOpenChange={setOpen}\n delayDuration={delayDuration}\n disableHoverableContent={isActionVariant}\n >\n <TooltipTrigger\n asChild={triggerAsChild}\n keepOpenOnClick={keepOpenOnTriggerClick}\n onKeyUp={handleKeyUp}\n className={hintUnderline ? HINT_UNDERLINE_CLASS_NAME : undefined}\n >\n {children}\n </TooltipTrigger>\n\n <TooltipContent\n className={className}\n variant={resolvedVariant}\n placement={placement}\n keepOpenOnPointerDownOutside={keepOpenOnTriggerClick}\n >\n {tooltip}\n </TooltipContent>\n </TooltipRoot>\n );\n};\n\nTooltip.Root = TooltipRoot;\nTooltip.Content = TooltipContent;\nTooltip.Trigger = TooltipTrigger;\nTooltip.Title = TooltipTitle;\n","import type { ComponentType } from 'react';\n\nimport { TooltipProvider } from '../components/Tooltip';\n\nexport const withTooltipProvider = (Story: ComponentType) => (\n <TooltipProvider>\n <Story />\n </TooltipProvider>\n);\n\n// Marks a story whose final render arrives asynchronously (lazy chunk, debounced\n// parse). The visual suite waits for every `[data-skeleton]` inside this box to\n// unmount before capturing, so the baseline is the settled content, never the\n// placeholder it briefly shows.\nexport const withVisualSettle = (Story: ComponentType) => (\n <div data-visual-settle>\n <Story />\n </div>\n);\n\n// position:fixed only fills the Storybook iframe, not the browser window.\nexport const withHiddenFullscreen = (Story: ComponentType) => (\n <div className=\"tw:[&_[aria-label=Fullscreen]]:hidden\">\n <Story />\n </div>\n);\n","export const createPrefixedString = (prefix: string) => (literals: TemplateStringsArray) =>\n literals.reduce((acc, literal) => acc + literal, `${prefix}-`);\n","export const noop = () => void 0;\n","type DebouncedFn<T extends (...args: any[]) => void> = {\n (...args: Parameters<T>): void;\n cancel: () => void;\n};\n\nexport const debounce = <T extends (...args: any[]) => void>(\n fn: T,\n delay: number,\n): DebouncedFn<T> => {\n let timeoutId: ReturnType<typeof setTimeout>;\n const debounced = (...args: Parameters<T>) => {\n clearTimeout(timeoutId);\n timeoutId = setTimeout(() => fn(...args), delay);\n };\n debounced.cancel = () => clearTimeout(timeoutId);\n return debounced;\n};\n","// Platform detection\ntype NavigatorUAData = {\n platform: string;\n brands: { brand: string; version: string }[];\n mobile: boolean;\n};\n\nconst getIsMac = (): boolean => {\n // Modern approach using navigator.userAgentData\n if (typeof navigator !== 'undefined' && 'userAgentData' in navigator) {\n const platform = (navigator.userAgentData as NavigatorUAData).platform;\n\n // An empty hint (a user-agent override, DevTools emulation) falls back to `navigator.platform`.\n if (typeof platform === 'string' && platform !== '') {\n return platform.toLowerCase() === 'macos';\n }\n }\n\n if (typeof navigator !== 'undefined' && typeof navigator.platform === 'string') {\n return navigator.platform.toUpperCase().indexOf('MAC') >= 0;\n }\n\n // Server-side rendering fallback\n return false;\n};\n\nexport const isMac = getIsMac();\n","import { useEffect, useState } from 'react';\n\n// https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/digest#converting_a_digest_to_a_hex_string\nconst sha256 = async (text: string) => {\n const msgUint8 = new TextEncoder().encode(text);\n const hashBuffer = await crypto.subtle.digest('SHA-256', msgUint8);\n const hashArray = Array.from(new Uint8Array(hashBuffer));\n return hashArray.map((b) => b.toString(16).padStart(2, '0')).join('');\n};\n\nexport const useSHA256 = (text?: string) => {\n const [hash, setHash] = useState('');\n\n useEffect(() => {\n if (!text) return;\n let cancelled = false;\n sha256(text).then((h) => {\n if (!cancelled) setHash(h);\n });\n return () => {\n cancelled = true;\n };\n }, [text]);\n\n // Empty input has no hash — derive it during render instead of syncing state\n // in the effect (avoids the extra render and a stale-value frame).\n return text ? hash : '';\n};\n","/** The separator a typed entry is split on when the caller names none. */\nexport const DEFAULT_ENTRY_SEPARATOR = ',';\n\n/**\n * The strings one typed entry stands for.\n *\n * - Parts are trimmed; blanks dropped.\n * - Repeats collapse case-insensitively, matching the combobox's display-string matching.\n * - A `null` separator returns the entry verbatim, untrimmed — the caller must reject blank text.\n */\nexport const splitEntry = (entry: string, separator: string | RegExp | null): string[] => {\n if (separator === null) return [entry];\n\n const seen = new Set<string>();\n return entry\n .split(separator)\n .map((part) => part.trim())\n .filter((part) => {\n if (part === '') return false;\n const key = part.toLowerCase();\n if (seen.has(key)) return false;\n seen.add(key);\n return true;\n });\n};\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@keboola/design",
3
- "version": "16.1.0",
3
+ "version": "17.1.0",
4
4
  "description": "Keboola UI platform design system — shadcn-aligned React primitives, Keboola-branded blocks, and the form bindings built on TanStack Form.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -122,7 +122,7 @@
122
122
  "@arethetypeswrong/cli": "^0.18.2",
123
123
  "@google/design.md": "0.2.0",
124
124
  "@keboola/agent-vocabulary": "^0.2.0",
125
- "@keboola/eslint-plugin-design": "^0.6.0",
125
+ "@keboola/eslint-plugin-design": "^0.7.0",
126
126
  "@keboola/oxlint-config": "^10.2.0",
127
127
  "@keboola/tsconfig": "^0.2.1",
128
128
  "@keboola/vitest-config": "^1.0.0",
@@ -196,7 +196,7 @@
196
196
  "@iconify-json/lucide": "^1.2.118",
197
197
  "@keboola/brand-registry": "^3.1.0",
198
198
  "@keboola/codemirror-lang-sql": "^0.7.4",
199
- "@keboola/tailwind-config": "^1.2.0",
199
+ "@keboola/tailwind-config": "^1.2.1",
200
200
  "@lexical/code": "^0.42.0",
201
201
  "@lexical/link": "^0.42.0",
202
202
  "@lexical/list": "^0.42.0",
package/src/styles.css CHANGED
@@ -213,6 +213,7 @@
213
213
  --font-display: var(
214
214
  --font-sans,
215
215
  'Inter',
216
+ 'Inter Fallback',
216
217
  system-ui,
217
218
  -apple-system,
218
219
  'Segoe UI',
@@ -415,6 +416,54 @@
415
416
  format('woff2');
416
417
  }
417
418
 
419
+ /* `Inter Fallback` — Arial scaled to Inter's metrics, painted until Inter arrives.
420
+ - Listed right after `Inter` in every Inter stack, so the swap reflows no text.
421
+ - `size-adjust` matches Inter's average advance width per weight.
422
+ - The overrides are Inter's ascent (96.9%) and descent (24.1%) divided by `size-adjust`.
423
+ - Liberation Sans shares Arial's metrics.
424
+ - `unicode-range` is the Inter subset's coverage; a glyph Inter lacks (`→`) comes from system-ui. */
425
+ @font-face {
426
+ font-family: 'Inter Fallback';
427
+ font-style: normal;
428
+ font-weight: 400;
429
+ src: local('Arial'), local('Liberation Sans');
430
+ unicode-range:
431
+ U+0020-024F, U+0259, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+1E00-1EFF, U+2002-2044, U+2074,
432
+ U+20A0-20BF, U+2113, U+2122, U+2191, U+2193, U+2212, U+2C7C, U+2C7F, U+A7FF, U+FEFF;
433
+ size-adjust: 106.37%;
434
+ ascent-override: 91.1%;
435
+ descent-override: 22.66%;
436
+ line-gap-override: 0%;
437
+ }
438
+
439
+ @font-face {
440
+ font-family: 'Inter Fallback';
441
+ font-style: normal;
442
+ font-weight: 500;
443
+ src: local('Arial'), local('Liberation Sans');
444
+ unicode-range:
445
+ U+0020-024F, U+0259, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+1E00-1EFF, U+2002-2044, U+2074,
446
+ U+20A0-20BF, U+2113, U+2122, U+2191, U+2193, U+2212, U+2C7C, U+2C7F, U+A7FF, U+FEFF;
447
+ size-adjust: 107.5%;
448
+ ascent-override: 90.14%;
449
+ descent-override: 22.42%;
450
+ line-gap-override: 0%;
451
+ }
452
+
453
+ @font-face {
454
+ font-family: 'Inter Fallback';
455
+ font-style: normal;
456
+ font-weight: 600;
457
+ src: local('Arial Bold'), local('Liberation Sans Bold');
458
+ unicode-range:
459
+ U+0020-024F, U+0259, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+1E00-1EFF, U+2002-2044, U+2074,
460
+ U+20A0-20BF, U+2113, U+2122, U+2191, U+2193, U+2212, U+2C7C, U+2C7F, U+A7FF, U+FEFF;
461
+ size-adjust: 101.29%;
462
+ ascent-override: 95.67%;
463
+ descent-override: 23.79%;
464
+ line-gap-override: 0%;
465
+ }
466
+
418
467
  html {
419
468
  /* Brand font opt-in: a brand's `typography.fontFamily` is injected as
420
469
  `--font-sans` by ThemeProvider and inherited from `html`; absent a brand
@@ -425,6 +474,7 @@
425
474
  font-family: var(
426
475
  --font-sans,
427
476
  'Inter',
477
+ 'Inter Fallback',
428
478
  system-ui,
429
479
  -apple-system,
430
480
  'Segoe UI',
package/src/theme.css CHANGED
@@ -21,9 +21,9 @@
21
21
  * name is prefixed (`--tw-font-sans`) and so cannot cycle with the runtime var it
22
22
  * reads — unlike `font-display`, which must stay an @utility. */
23
23
  --font-sans:
24
- var(--font-sans, Inter), system-ui, -apple-system, 'Segoe UI', Roboto, 'Helvetica Neue', Arial,
25
- 'Noto Sans', 'Liberation Sans', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji',
26
- 'Segoe UI Symbol', 'Noto Color Emoji';
24
+ var(--font-sans, Inter, 'Inter Fallback'), system-ui, -apple-system, 'Segoe UI', Roboto,
25
+ 'Helvetica Neue', Arial, 'Noto Sans', 'Liberation Sans', sans-serif, 'Apple Color Emoji',
26
+ 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji';
27
27
 
28
28
  /* Legacy Bootstrap-era breakpoints (screens). */
29
29
  --breakpoint-sm-legacy: 992px;
@@ -566,7 +566,7 @@
566
566
  /* Scroll-container edge fade — `scroll-fade` (= `scroll-fade-y`) and `scroll-fade-x`.
567
567
  * - A mask driven by scroll-driven animations; each edge holds 1 (solid) until there is overflow past it.
568
568
  * - `--tw-scroll-fade-size` sets the depth; `--tw-scroll-fade-size-start` overrides the leading edge.
569
- * - Browsers without scroll timelines show a static fade on both edges. */
569
+ * - Browsers without scroll timelines show no fade: the reveal animations are off, both edges solid. */
570
570
  @property --tw-scroll-fade-start {
571
571
  syntax: '<number>';
572
572
  inherits: false;
@@ -613,8 +613,9 @@
613
613
  calc(100% - var(--tw-scroll-fade-size)) 100%;
614
614
 
615
615
  @supports not (animation-timeline: scroll()) {
616
- --tw-scroll-fade-start: 0;
617
- --tw-scroll-fade-end: 0;
616
+ animation: none;
617
+ --tw-scroll-fade-start: 1;
618
+ --tw-scroll-fade-end: 1;
618
619
  }
619
620
  }
620
621
  @utility scroll-fade {
@@ -640,7 +641,8 @@
640
641
  calc(100% - var(--tw-scroll-fade-size)) 100%;
641
642
 
642
643
  @supports not (animation-timeline: scroll()) {
643
- --tw-scroll-fade-start: 0;
644
- --tw-scroll-fade-end: 0;
644
+ animation: none;
645
+ --tw-scroll-fade-start: 1;
646
+ --tw-scroll-fade-end: 1;
645
647
  }
646
648
  }