@keboola/design 1.0.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 (606) hide show
  1. package/README.md +83 -0
  2. package/package.json +151 -0
  3. package/src/blocks/AIKit/AnswerSummary.stories.tsx +38 -0
  4. package/src/blocks/AIKit/AnswerSummary.tsx +63 -0
  5. package/src/blocks/AIKit/CollapsibleStepHeader.stories.tsx +53 -0
  6. package/src/blocks/AIKit/CollapsibleStepHeader.tsx +65 -0
  7. package/src/blocks/AIKit/InlineStepDetail.stories.tsx +25 -0
  8. package/src/blocks/AIKit/InlineStepDetail.tsx +13 -0
  9. package/src/blocks/AIKit/InlineStepLabel.stories.tsx +37 -0
  10. package/src/blocks/AIKit/InlineStepLabel.tsx +36 -0
  11. package/src/blocks/AIKit/MessageBubble.stories.tsx +137 -0
  12. package/src/blocks/AIKit/MessageBubble.tsx +68 -0
  13. package/src/blocks/AIKit/PlanApproval.stories.tsx +121 -0
  14. package/src/blocks/AIKit/PlanApproval.test.tsx +241 -0
  15. package/src/blocks/AIKit/PlanApproval.tsx +345 -0
  16. package/src/blocks/AIKit/PlanRewritingIndicator.test.tsx +17 -0
  17. package/src/blocks/AIKit/PlanRewritingIndicator.tsx +20 -0
  18. package/src/blocks/AIKit/PromptInput.stories.tsx +98 -0
  19. package/src/blocks/AIKit/PromptInput.tsx +218 -0
  20. package/src/blocks/AIKit/PromptInputAction.tsx +18 -0
  21. package/src/blocks/AIKit/PromptInputSubmit.tsx +55 -0
  22. package/src/blocks/AIKit/Question.stories.tsx +235 -0
  23. package/src/blocks/AIKit/Question.tsx +323 -0
  24. package/src/blocks/AIKit/QuestionBlock.stories.tsx +99 -0
  25. package/src/blocks/AIKit/QuestionBlock.tsx +83 -0
  26. package/src/blocks/AIKit/SuggestedPrompt.stories.tsx +88 -0
  27. package/src/blocks/AIKit/SuggestedPrompt.tsx +35 -0
  28. package/src/blocks/AIKit/ThinkingIndicator.stories.tsx +21 -0
  29. package/src/blocks/AIKit/ThinkingIndicator.tsx +14 -0
  30. package/src/blocks/AIKit/index.ts +12 -0
  31. package/src/blocks/AutoSaveTextarea/AutoSaveTextarea.stories.tsx +78 -0
  32. package/src/blocks/AutoSaveTextarea/AutoSaveTextarea.tsx +103 -0
  33. package/src/blocks/AutoSaveTextarea/index.ts +1 -0
  34. package/src/blocks/ClipboardButton/ClipboardButton.stories.tsx +28 -0
  35. package/src/blocks/ClipboardButton/ClipboardButton.tsx +41 -0
  36. package/src/blocks/ClipboardButton/ClipboardInline.tsx +41 -0
  37. package/src/blocks/ClipboardButton/index.ts +2 -0
  38. package/src/blocks/ColorInput/ColorInput.stories.tsx +109 -0
  39. package/src/blocks/ColorInput/ColorInput.test.tsx +163 -0
  40. package/src/blocks/ColorInput/ColorInput.tsx +169 -0
  41. package/src/blocks/ColorInput/ColorPicker.tsx +39 -0
  42. package/src/blocks/ColorInput/index.ts +1 -0
  43. package/src/blocks/ColorInput/utils.test.ts +189 -0
  44. package/src/blocks/ColorInput/utils.ts +74 -0
  45. package/src/blocks/EmptyConfigurationActionCard/EmptyConfigurationActionCard.stories.tsx +30 -0
  46. package/src/blocks/EmptyConfigurationActionCard/EmptyConfigurationActionCard.tsx +20 -0
  47. package/src/blocks/EmptyConfigurationActionCard/index.ts +1 -0
  48. package/src/blocks/EmptyState/EmptyState.stories.tsx +93 -0
  49. package/src/blocks/EmptyState/EmptyState.tsx +130 -0
  50. package/src/blocks/EmptyState/index.ts +1 -0
  51. package/src/blocks/ErrorState/ErrorState.stories.tsx +125 -0
  52. package/src/blocks/ErrorState/ErrorState.tsx +132 -0
  53. package/src/blocks/ErrorState/index.ts +1 -0
  54. package/src/blocks/Form/components/FormBody.tsx +27 -0
  55. package/src/blocks/Form/components/SubmitButton.tsx +30 -0
  56. package/src/blocks/Form/connectors/CheckboxField.tsx +34 -0
  57. package/src/blocks/Form/connectors/FieldShell.tsx +46 -0
  58. package/src/blocks/Form/connectors/NumberField.tsx +36 -0
  59. package/src/blocks/Form/connectors/PasswordField.tsx +38 -0
  60. package/src/blocks/Form/connectors/SelectField.tsx +73 -0
  61. package/src/blocks/Form/connectors/SwitchField.tsx +34 -0
  62. package/src/blocks/Form/connectors/TextAreaField.tsx +36 -0
  63. package/src/blocks/Form/connectors/TextField.tsx +36 -0
  64. package/src/blocks/Form/contexts.ts +4 -0
  65. package/src/blocks/Form/formHook.ts +30 -0
  66. package/src/blocks/Form/index.ts +2 -0
  67. package/src/blocks/Form/setServerFieldErrors.test.ts +38 -0
  68. package/src/blocks/Form/setServerFieldErrors.ts +21 -0
  69. package/src/blocks/MermaidDiagram/MermaidDiagram.stories.tsx +87 -0
  70. package/src/blocks/MermaidDiagram/MermaidDiagram.tsx +266 -0
  71. package/src/blocks/MermaidDiagram/index.ts +1 -0
  72. package/src/blocks/MultiActionButtonGroup/MultiActionButton.stories.tsx +118 -0
  73. package/src/blocks/MultiActionButtonGroup/MultiActionButton.tsx +40 -0
  74. package/src/blocks/MultiActionButtonGroup/MultiActionButtonGroup.tsx +16 -0
  75. package/src/blocks/MultiActionButtonGroup/index.ts +1 -0
  76. package/src/blocks/MultiCombobox/MultiCombobox.stories.tsx +324 -0
  77. package/src/blocks/MultiCombobox/MultiCombobox.tsx +241 -0
  78. package/src/blocks/MultiCombobox/index.ts +1 -0
  79. package/src/blocks/NumberInput/NumberInput.stories.tsx +112 -0
  80. package/src/blocks/NumberInput/NumberInput.test.tsx +148 -0
  81. package/src/blocks/NumberInput/NumberInput.tsx +89 -0
  82. package/src/blocks/NumberInput/index.ts +1 -0
  83. package/src/blocks/PageHeader/AGENTS.md +77 -0
  84. package/src/blocks/PageHeader/PageHeader.stories.tsx +272 -0
  85. package/src/blocks/PageHeader/PageHeader.tsx +7 -0
  86. package/src/blocks/PageHeader/PageHeaderDetail.tsx +62 -0
  87. package/src/blocks/PageHeader/PageHeaderIndex.tsx +56 -0
  88. package/src/blocks/PageHeader/index.ts +1 -0
  89. package/src/blocks/PageHeader/styles.ts +6 -0
  90. package/src/blocks/PageLayout/AGENTS.md +94 -0
  91. package/src/blocks/PageLayout/PageLayout.stories.tsx +143 -0
  92. package/src/blocks/PageLayout/PageLayout.tsx +130 -0
  93. package/src/blocks/PageLayout/index.ts +1 -0
  94. package/src/blocks/PasswordInput/PasswordInput.stories.tsx +114 -0
  95. package/src/blocks/PasswordInput/PasswordInput.test.tsx +219 -0
  96. package/src/blocks/PasswordInput/PasswordInput.tsx +180 -0
  97. package/src/blocks/PasswordInput/index.ts +1 -0
  98. package/src/blocks/SearchInput/SearchInput.stories.tsx +127 -0
  99. package/src/blocks/SearchInput/SearchInput.test.tsx +162 -0
  100. package/src/blocks/SearchInput/SearchInput.tsx +146 -0
  101. package/src/blocks/SearchInput/index.ts +1 -0
  102. package/src/blocks/SearchInputWithNavigation/SearchInputWithNavigation.stories.tsx +73 -0
  103. package/src/blocks/SearchInputWithNavigation/SearchInputWithNavigation.tsx +89 -0
  104. package/src/blocks/SearchInputWithNavigation/index.ts +1 -0
  105. package/src/blocks/SplitButton/SplitButton.stories.tsx +88 -0
  106. package/src/blocks/SplitButton/SplitButton.tsx +68 -0
  107. package/src/blocks/SplitButton/index.ts +1 -0
  108. package/src/blocks/Tagger/TagItem.tsx +29 -0
  109. package/src/blocks/Tagger/TagSelectPopover/TagSelectCreateItem.tsx +42 -0
  110. package/src/blocks/Tagger/TagSelectPopover/TagSelectItem.tsx +31 -0
  111. package/src/blocks/Tagger/TagSelectPopover/TagSelectList.tsx +67 -0
  112. package/src/blocks/Tagger/TagSelectPopover/TagSelectPopover.tsx +34 -0
  113. package/src/blocks/Tagger/TagSelectPopover/TagSelectValue.tsx +47 -0
  114. package/src/blocks/Tagger/TagSelectPopover/index.ts +1 -0
  115. package/src/blocks/Tagger/Tagger.stories.tsx +80 -0
  116. package/src/blocks/Tagger/Tagger.tsx +101 -0
  117. package/src/blocks/Tagger/index.ts +1 -0
  118. package/src/blocks/Tagger/types.ts +11 -0
  119. package/src/blocks/Textarea/Textarea.stories.tsx +47 -0
  120. package/src/blocks/Textarea/Textarea.tsx +50 -0
  121. package/src/blocks/Textarea/index.ts +1 -0
  122. package/src/components/Alert/Alert.stories.tsx +93 -0
  123. package/src/components/Alert/Alert.tsx +103 -0
  124. package/src/components/Alert/AlertAction.tsx +31 -0
  125. package/src/components/Alert/AlertCollapsibleIcon.tsx +26 -0
  126. package/src/components/Alert/AlertDescription.tsx +31 -0
  127. package/src/components/Alert/AlertIcon.tsx +43 -0
  128. package/src/components/Alert/AlertRoot.tsx +64 -0
  129. package/src/components/Alert/AlertTitle.tsx +25 -0
  130. package/src/components/Alert/index.ts +1 -0
  131. package/src/components/Avatar.stories.tsx +22 -0
  132. package/src/components/Avatar.tsx +88 -0
  133. package/src/components/Badge/Badge.stories.tsx +106 -0
  134. package/src/components/Badge/Badge.tsx +55 -0
  135. package/src/components/Badge/BadgeAddon.tsx +63 -0
  136. package/src/components/Badge/BadgeButton.tsx +39 -0
  137. package/src/components/Badge/BadgeLabel.tsx +37 -0
  138. package/src/components/Badge/BadgeRoot.tsx +21 -0
  139. package/src/components/Badge/index.ts +1 -0
  140. package/src/components/Badge/styles.ts +74 -0
  141. package/src/components/Breadcrumb/Breadcrumb.stories.tsx +135 -0
  142. package/src/components/Breadcrumb/Breadcrumb.tsx +23 -0
  143. package/src/components/Breadcrumb/BreadcrumbEllipsis.tsx +43 -0
  144. package/src/components/Breadcrumb/BreadcrumbItem.tsx +9 -0
  145. package/src/components/Breadcrumb/BreadcrumbLink.tsx +48 -0
  146. package/src/components/Breadcrumb/BreadcrumbList.tsx +26 -0
  147. package/src/components/Breadcrumb/BreadcrumbPage.tsx +22 -0
  148. package/src/components/Breadcrumb/BreadcrumbSeparator.tsx +28 -0
  149. package/src/components/Breadcrumb/index.ts +1 -0
  150. package/src/components/Button/Button.stories.tsx +68 -0
  151. package/src/components/Button/Button.tsx +73 -0
  152. package/src/components/Button/ButtonInline.stories.tsx +54 -0
  153. package/src/components/Button/ButtonInline.tsx +73 -0
  154. package/src/components/Button/index.ts +3 -0
  155. package/src/components/Button/styles.ts +292 -0
  156. package/src/components/ButtonGroup/ButtonGroup.stories.tsx +118 -0
  157. package/src/components/ButtonGroup/ButtonGroup.tsx +79 -0
  158. package/src/components/ButtonGroup/index.ts +1 -0
  159. package/src/components/Calendar/Calendar.stories.tsx +101 -0
  160. package/src/components/Calendar/Calendar.tsx +44 -0
  161. package/src/components/Calendar/index.ts +2 -0
  162. package/src/components/Card/Card.stories.tsx +60 -0
  163. package/src/components/Card/Card.tsx +25 -0
  164. package/src/components/Card/CardContent.tsx +5 -0
  165. package/src/components/Card/CardHeader.tsx +5 -0
  166. package/src/components/Card/CardTitle.tsx +13 -0
  167. package/src/components/Card/index.ts +1 -0
  168. package/src/components/Card/styles.ts +32 -0
  169. package/src/components/Checkbox/Checkbox.stories.tsx +210 -0
  170. package/src/components/Checkbox/Checkbox.test.tsx +140 -0
  171. package/src/components/Checkbox/Checkbox.tsx +86 -0
  172. package/src/components/Checkbox/index.ts +1 -0
  173. package/src/components/Checkbox/styles.ts +77 -0
  174. package/src/components/Clipboard/Clipboard.stories.tsx +44 -0
  175. package/src/components/Clipboard/Clipboard.tsx +89 -0
  176. package/src/components/Clipboard/index.ts +1 -0
  177. package/src/components/CodeEditor/ButtonToolbar.tsx +14 -0
  178. package/src/components/CodeEditor/CodeEditor.tsx +155 -0
  179. package/src/components/CodeEditor/SqlEditor.stories.tsx +76 -0
  180. package/src/components/CodeEditor/SqlEditor.tsx +206 -0
  181. package/src/components/CodeEditor/ToggleComponentHelp.tsx +7 -0
  182. package/src/components/CodeEditor/activeQueryHighlight.test.ts +178 -0
  183. package/src/components/CodeEditor/activeQueryHighlight.ts +245 -0
  184. package/src/components/CodeEditor/helpers.ts +100 -0
  185. package/src/components/CodeEditor/highlighting.ts +184 -0
  186. package/src/components/CodeEditor/index.ts +3 -0
  187. package/src/components/CodeEditor/search.ts +186 -0
  188. package/src/components/Collapse.stories.tsx +56 -0
  189. package/src/components/Collapse.tsx +61 -0
  190. package/src/components/Collapsible/Collapsible.stories.tsx +55 -0
  191. package/src/components/Collapsible/Collapsible.tsx +11 -0
  192. package/src/components/Collapsible/CollapsibleContent.tsx +25 -0
  193. package/src/components/Collapsible/index.ts +1 -0
  194. package/src/components/CollapsiblePanel.stories.tsx +25 -0
  195. package/src/components/CollapsiblePanel.tsx +130 -0
  196. package/src/components/Combobox/Combobox.stories.tsx +426 -0
  197. package/src/components/Combobox/Combobox.test.tsx +165 -0
  198. package/src/components/Combobox/Combobox.tsx +347 -0
  199. package/src/components/Combobox/ComboboxChips.tsx +63 -0
  200. package/src/components/Combobox/ComboboxContent.tsx +95 -0
  201. package/src/components/Combobox/ComboboxEmpty.tsx +30 -0
  202. package/src/components/Combobox/ComboboxInput.tsx +10 -0
  203. package/src/components/Combobox/ComboboxInputGroup.tsx +38 -0
  204. package/src/components/Combobox/ComboboxItem.tsx +71 -0
  205. package/src/components/Combobox/ComboboxItemIndicator.tsx +76 -0
  206. package/src/components/Combobox/ComboboxList.tsx +32 -0
  207. package/src/components/Combobox/ComboboxRoot.tsx +5 -0
  208. package/src/components/Combobox/ComboboxSeparator.tsx +20 -0
  209. package/src/components/Combobox/Group/ComboboxCollection.tsx +7 -0
  210. package/src/components/Combobox/Group/ComboboxGroup.tsx +23 -0
  211. package/src/components/Combobox/Group/ComboboxGroupLabel.tsx +38 -0
  212. package/src/components/Combobox/Group/index.ts +3 -0
  213. package/src/components/Combobox/index.ts +1 -0
  214. package/src/components/Combobox/types.ts +26 -0
  215. package/src/components/Combobox/utils.test.ts +95 -0
  216. package/src/components/Combobox/utils.ts +103 -0
  217. package/src/components/Command/Command.stories.tsx +376 -0
  218. package/src/components/Command/Command.tsx +37 -0
  219. package/src/components/Command/CommandContent.tsx +19 -0
  220. package/src/components/Command/CommandEmpty.tsx +6 -0
  221. package/src/components/Command/CommandGroup.tsx +26 -0
  222. package/src/components/Command/CommandInput.tsx +27 -0
  223. package/src/components/Command/CommandItem/CheckIndicator.tsx +74 -0
  224. package/src/components/Command/CommandItem/CommandItem.tsx +91 -0
  225. package/src/components/Command/CommandItem/index.ts +1 -0
  226. package/src/components/Command/CommandList.tsx +32 -0
  227. package/src/components/Command/CommandSeparator.tsx +13 -0
  228. package/src/components/Command/index.ts +6 -0
  229. package/src/components/DatePicker/DatePicker.tsx +37 -0
  230. package/src/components/DatePicker/index.ts +1 -0
  231. package/src/components/DiffView/DiffView.stories.tsx +80 -0
  232. package/src/components/DiffView/DiffView.tsx +131 -0
  233. package/src/components/DiffView/DiffViewMark.tsx +21 -0
  234. package/src/components/DiffView/DiffViewTd.tsx +84 -0
  235. package/src/components/DiffView/DiffViewTh.tsx +23 -0
  236. package/src/components/DiffView/index.ts +11 -0
  237. package/src/components/DiffView/util.test.ts +231 -0
  238. package/src/components/DiffView/util.ts +311 -0
  239. package/src/components/DotsLoader.tsx +22 -0
  240. package/src/components/DropdownMenu/DropdownMenu.stories.tsx +306 -0
  241. package/src/components/DropdownMenu/DropdownMenu.tsx +61 -0
  242. package/src/components/DropdownMenu/DropdownMenuCheckboxItem.tsx +52 -0
  243. package/src/components/DropdownMenu/DropdownMenuContent.tsx +52 -0
  244. package/src/components/DropdownMenu/DropdownMenuContext.tsx +13 -0
  245. package/src/components/DropdownMenu/DropdownMenuItem.tsx +74 -0
  246. package/src/components/DropdownMenu/DropdownMenuItemDescription.tsx +42 -0
  247. package/src/components/DropdownMenu/DropdownMenuItemIndicator.tsx +98 -0
  248. package/src/components/DropdownMenu/DropdownMenuLabel.tsx +21 -0
  249. package/src/components/DropdownMenu/DropdownMenuRadioGroup/DropdownMenuRadioGroup.tsx +31 -0
  250. package/src/components/DropdownMenu/DropdownMenuRadioGroup/DropdownMenuRadioItem.tsx +64 -0
  251. package/src/components/DropdownMenu/DropdownMenuRadioGroup/index.ts +2 -0
  252. package/src/components/DropdownMenu/DropdownMenuSeparator.tsx +35 -0
  253. package/src/components/DropdownMenu/DropdownMenuSub/DropdownMenuSub.tsx +3 -0
  254. package/src/components/DropdownMenu/DropdownMenuSub/DropdownMenuSubContent.tsx +21 -0
  255. package/src/components/DropdownMenu/DropdownMenuSub/DropdownMenuSubTrigger.tsx +17 -0
  256. package/src/components/DropdownMenu/DropdownMenuSub/index.ts +3 -0
  257. package/src/components/DropdownMenu/DropdownMenuTrigger.tsx +19 -0
  258. package/src/components/DropdownMenu/ItemIcon.tsx +22 -0
  259. package/src/components/DropdownMenu/index.ts +1 -0
  260. package/src/components/DropdownMenu/styles.ts +82 -0
  261. package/src/components/EmptySearchContent.stories.tsx +12 -0
  262. package/src/components/EmptySearchContent.tsx +13 -0
  263. package/src/components/FieldBox/FieldBox.stories.tsx +138 -0
  264. package/src/components/FieldBox/FieldBox.tsx +43 -0
  265. package/src/components/FieldBox/FieldBoxDescription.tsx +18 -0
  266. package/src/components/FieldBox/FieldBoxTitle.tsx +20 -0
  267. package/src/components/FieldBox/index.ts +1 -0
  268. package/src/components/FieldBox/styles.ts +37 -0
  269. package/src/components/FormGroup/FormGroup.stories.tsx +120 -0
  270. package/src/components/FormGroup/FormGroup.tsx +33 -0
  271. package/src/components/FormGroup/FormGroupColorInput.tsx +15 -0
  272. package/src/components/FormGroup/FormGroupHelp.tsx +17 -0
  273. package/src/components/FormGroup/FormGroupNumberInput.tsx +15 -0
  274. package/src/components/FormGroup/FormGroupTextInput.tsx +15 -0
  275. package/src/components/FormGroup/FormGroupTextarea.tsx +12 -0
  276. package/src/components/FormGroup/context.ts +11 -0
  277. package/src/components/FormGroup/index.ts +2 -0
  278. package/src/components/FormGroup/types.ts +5 -0
  279. package/src/components/FullScreenModal/FullScreenModal.tsx +8 -0
  280. package/src/components/FullScreenModal/FullScreenModalBody.tsx +16 -0
  281. package/src/components/FullScreenModal/FullScreenModalHeader.tsx +89 -0
  282. package/src/components/FullScreenModal/FullScreenModalRoot.tsx +79 -0
  283. package/src/components/FullScreenModal/index.ts +3 -0
  284. package/src/components/HelpBlock/HelpBlock.stories.tsx +28 -0
  285. package/src/components/HelpBlock/HelpBlock.tsx +31 -0
  286. package/src/components/HelpBlock/index.ts +1 -0
  287. package/src/components/HoverCard/HoverCard.stories.tsx +77 -0
  288. package/src/components/HoverCard/HoverCard.tsx +13 -0
  289. package/src/components/HoverCard/HoverCardContent.tsx +63 -0
  290. package/src/components/HoverCard/index.ts +1 -0
  291. package/src/components/Icon/Icon.stories.tsx +26 -0
  292. package/src/components/Icon/Icon.tsx +10 -0
  293. package/src/components/Icon/Icons.mdx +28 -0
  294. package/src/components/Icon/constants.ts +1 -0
  295. package/src/components/Icon/index.ts +27 -0
  296. package/src/components/Input/DateInput/DateInput.stories.tsx +58 -0
  297. package/src/components/Input/DateInput/DateInput.tsx +140 -0
  298. package/src/components/Input/DateInput/helpers.test.ts +102 -0
  299. package/src/components/Input/DateInput/helpers.ts +59 -0
  300. package/src/components/Input/DateInput/index.ts +1 -0
  301. package/src/components/Input/DateRangeInput/DateRangeInput.stories.tsx +66 -0
  302. package/src/components/Input/DateRangeInput/DateRangeInput.tsx +141 -0
  303. package/src/components/Input/DateRangeInput/helpers.test.ts +146 -0
  304. package/src/components/Input/DateRangeInput/helpers.ts +36 -0
  305. package/src/components/Input/DateRangeInput/index.ts +1 -0
  306. package/src/components/Input/Input.stories.tsx +93 -0
  307. package/src/components/Input/Input.test.tsx +112 -0
  308. package/src/components/Input/Input.tsx +147 -0
  309. package/src/components/Input/TextInput/TextInput.stories.tsx +68 -0
  310. package/src/components/Input/TextInput/TextInput.test.tsx +52 -0
  311. package/src/components/Input/TextInput/TextInput.tsx +57 -0
  312. package/src/components/Input/TextInput/index.ts +1 -0
  313. package/src/components/Input/TimeInput/TimeInput.stories.tsx +89 -0
  314. package/src/components/Input/TimeInput/TimeInput.tsx +103 -0
  315. package/src/components/Input/TimeInput/index.ts +1 -0
  316. package/src/components/Input/index.ts +4 -0
  317. package/src/components/Input/utils.ts +11 -0
  318. package/src/components/InputGroup/InputGroup.stories.tsx +208 -0
  319. package/src/components/InputGroup/InputGroup.tsx +228 -0
  320. package/src/components/InputGroup/InputGroupAddon.tsx +46 -0
  321. package/src/components/InputGroup/InputGroupButton.tsx +25 -0
  322. package/src/components/InputGroup/InputGroupInput.tsx +34 -0
  323. package/src/components/InputGroup/InputGroupText.tsx +21 -0
  324. package/src/components/InputGroup/InputGroupTextArea.tsx +78 -0
  325. package/src/components/InputGroup/index.ts +1 -0
  326. package/src/components/Kbd/Kbd.stories.tsx +82 -0
  327. package/src/components/Kbd/Kbd.tsx +17 -0
  328. package/src/components/Kbd/KbdGroup.tsx +35 -0
  329. package/src/components/Kbd/KbdSeparator.tsx +9 -0
  330. package/src/components/Kbd/index.ts +3 -0
  331. package/src/components/Kbd/keyboardKeys.ts +40 -0
  332. package/src/components/Kbd/styles.ts +39 -0
  333. package/src/components/Label/Label.stories.tsx +53 -0
  334. package/src/components/Label/Label.tsx +31 -0
  335. package/src/components/Label/index.ts +1 -0
  336. package/src/components/Link.stories.tsx +19 -0
  337. package/src/components/Link.tsx +37 -0
  338. package/src/components/MarkdownEditor/MarkdownEditor.stories.tsx +120 -0
  339. package/src/components/MarkdownEditor/MarkdownEditor.test.ts +171 -0
  340. package/src/components/MarkdownEditor/MarkdownEditor.tsx +155 -0
  341. package/src/components/MarkdownEditor/context.ts +10 -0
  342. package/src/components/MarkdownEditor/index.ts +1 -0
  343. package/src/components/MarkdownEditor/nodes/ImageNode.tsx +115 -0
  344. package/src/components/MarkdownEditor/nodes/ImageNodeComponent.tsx +18 -0
  345. package/src/components/MarkdownEditor/nodes/MermaidNode.tsx +72 -0
  346. package/src/components/MarkdownEditor/nodes/MermaidNodeComponent.tsx +35 -0
  347. package/src/components/MarkdownEditor/plugins/ImagePastePlugin.tsx +149 -0
  348. package/src/components/MarkdownEditor/plugins/KeyboardPlugin.tsx +37 -0
  349. package/src/components/MarkdownEditor/plugins/MarkdownSyncPlugin.tsx +56 -0
  350. package/src/components/MarkdownEditor/plugins/ToolbarPlugin.tsx +274 -0
  351. package/src/components/MarkdownEditor/plugins/toolbar/AlignmentDropdown.tsx +93 -0
  352. package/src/components/MarkdownEditor/plugins/toolbar/BlockTypeDropdown.tsx +133 -0
  353. package/src/components/MarkdownEditor/plugins/toolbar/LinkPanel.tsx +160 -0
  354. package/src/components/MarkdownEditor/plugins/toolbar/ToolbarButton.tsx +36 -0
  355. package/src/components/MarkdownEditor/plugins/toolbar/ToolbarDivider.tsx +1 -0
  356. package/src/components/MarkdownEditor/theme.ts +39 -0
  357. package/src/components/MarkdownEditor/transformers.ts +179 -0
  358. package/src/components/MarkedText/MarkedText.stories.tsx +46 -0
  359. package/src/components/MarkedText/MarkedText.tsx +36 -0
  360. package/src/components/MarkedText/index.ts +1 -0
  361. package/src/components/MarkedText/utils.test.ts +193 -0
  362. package/src/components/MarkedText/utils.ts +37 -0
  363. package/src/components/MergeEditor/AcceptControls/AcceptButton.tsx +20 -0
  364. package/src/components/MergeEditor/AcceptControls/AcceptControls.tsx +66 -0
  365. package/src/components/MergeEditor/ConflictStatus/ConflictStatusIndicator.tsx +38 -0
  366. package/src/components/MergeEditor/MergeEditor.stories.tsx +211 -0
  367. package/src/components/MergeEditor/MergeEditor.tsx +116 -0
  368. package/src/components/MergeEditor/MergePane.tsx +95 -0
  369. package/src/components/MergeEditor/PaneHeader.tsx +11 -0
  370. package/src/components/MergeEditor/constants.ts +48 -0
  371. package/src/components/MergeEditor/decorations.ts +126 -0
  372. package/src/components/MergeEditor/helpers.test.ts +172 -0
  373. package/src/components/MergeEditor/helpers.ts +118 -0
  374. package/src/components/MergeEditor/index.ts +5 -0
  375. package/src/components/MergeEditor/useMergeDiff.ts +573 -0
  376. package/src/components/MergeEditor/useScrollSync.ts +79 -0
  377. package/src/components/Modal/Modal.stories.tsx +678 -0
  378. package/src/components/Modal/Modal.tsx +23 -0
  379. package/src/components/Modal/ModalBody.tsx +23 -0
  380. package/src/components/Modal/ModalCloseIcon.tsx +32 -0
  381. package/src/components/Modal/ModalContent.tsx +87 -0
  382. package/src/components/Modal/ModalDescription.tsx +20 -0
  383. package/src/components/Modal/ModalFooter.tsx +15 -0
  384. package/src/components/Modal/ModalHeader.tsx +50 -0
  385. package/src/components/Modal/ModalIcon.tsx +83 -0
  386. package/src/components/Modal/ModalOverlay.tsx +42 -0
  387. package/src/components/Modal/ModalTitle.tsx +12 -0
  388. package/src/components/Modal/index.ts +1 -0
  389. package/src/components/Navbar/Navbar.stories.tsx +179 -0
  390. package/src/components/Navbar/Navbar.tsx +80 -0
  391. package/src/components/Navbar/NavbarContent.tsx +20 -0
  392. package/src/components/Navbar/NavbarFooter.tsx +11 -0
  393. package/src/components/Navbar/NavbarHeader.tsx +11 -0
  394. package/src/components/Navbar/NavbarMenu.tsx +30 -0
  395. package/src/components/Navbar/NavbarMenuAvatar.tsx +67 -0
  396. package/src/components/Navbar/NavbarMenuButton.tsx +134 -0
  397. package/src/components/Navbar/NavbarMenuItem.tsx +9 -0
  398. package/src/components/Navbar/NavbarMenuItemAdornment.tsx +65 -0
  399. package/src/components/Navbar/index.ts +1 -0
  400. package/src/components/Pagination/Pagination.stories.tsx +132 -0
  401. package/src/components/Pagination/Pagination.tsx +34 -0
  402. package/src/components/Pagination/PaginationButton.tsx +36 -0
  403. package/src/components/Pagination/PaginationContent.tsx +12 -0
  404. package/src/components/Pagination/PaginationEllipsis.tsx +26 -0
  405. package/src/components/Pagination/PaginationItem.tsx +9 -0
  406. package/src/components/Pagination/PaginationNext.tsx +19 -0
  407. package/src/components/Pagination/PaginationPrevious.tsx +11 -0
  408. package/src/components/Pagination/index.ts +1 -0
  409. package/src/components/PanelWithDetails.stories.tsx +28 -0
  410. package/src/components/PanelWithDetails.tsx +66 -0
  411. package/src/components/Popconfirm/Popconfirm.stories.tsx +365 -0
  412. package/src/components/Popconfirm/Popconfirm.tsx +82 -0
  413. package/src/components/Popconfirm/PopconfirmBody.tsx +5 -0
  414. package/src/components/Popconfirm/PopconfirmCancel.tsx +45 -0
  415. package/src/components/Popconfirm/PopconfirmConfirm.tsx +57 -0
  416. package/src/components/Popconfirm/PopconfirmContent.tsx +33 -0
  417. package/src/components/Popconfirm/PopconfirmFooter.tsx +9 -0
  418. package/src/components/Popconfirm/PopconfirmTrigger.tsx +22 -0
  419. package/src/components/Popconfirm/context.ts +19 -0
  420. package/src/components/Popconfirm/index.ts +1 -0
  421. package/src/components/Popover/Popover.stories.tsx +85 -0
  422. package/src/components/Popover/Popover.tsx +15 -0
  423. package/src/components/Popover/PopoverContent.tsx +99 -0
  424. package/src/components/Popover/index.ts +1 -0
  425. package/src/components/Progress/Progress.stories.tsx +67 -0
  426. package/src/components/Progress/Progress.tsx +45 -0
  427. package/src/components/Progress/index.ts +1 -0
  428. package/src/components/RadioGroup/Radio.tsx +67 -0
  429. package/src/components/RadioGroup/RadioGroup.stories.tsx +300 -0
  430. package/src/components/RadioGroup/RadioGroup.tsx +64 -0
  431. package/src/components/RadioGroup/RadioGroupItem.tsx +60 -0
  432. package/src/components/RadioGroup/RadioGroupItemButton.tsx +79 -0
  433. package/src/components/RadioGroup/RadioGroupSeparator.tsx +12 -0
  434. package/src/components/RadioGroup/context.ts +13 -0
  435. package/src/components/RadioGroup/index.ts +1 -0
  436. package/src/components/Resizable/Resizable.stories.tsx +50 -0
  437. package/src/components/Resizable/ResizableHandle.tsx +50 -0
  438. package/src/components/Resizable/ResizablePanel.tsx +12 -0
  439. package/src/components/Resizable/ResizablePanelGroup.tsx +19 -0
  440. package/src/components/Resizable/index.ts +3 -0
  441. package/src/components/ScrollArea/ScrollArea.stories.tsx +43 -0
  442. package/src/components/ScrollArea/ScrollArea.tsx +50 -0
  443. package/src/components/ScrollArea/ScrollBar.tsx +32 -0
  444. package/src/components/ScrollArea/index.ts +2 -0
  445. package/src/components/Search/ClearButton.tsx +42 -0
  446. package/src/components/Search/Search.stories.tsx +77 -0
  447. package/src/components/Search/Search.test.tsx +224 -0
  448. package/src/components/Search/Search.tsx +139 -0
  449. package/src/components/Search/SearchForm.tsx +37 -0
  450. package/src/components/Search/index.ts +2 -0
  451. package/src/components/Search/styles.ts +88 -0
  452. package/src/components/Search/utils.ts +11 -0
  453. package/src/components/Select/Select.stories.tsx +109 -0
  454. package/src/components/Select/Select.tsx +130 -0
  455. package/src/components/Select/SelectContent.tsx +101 -0
  456. package/src/components/Select/SelectGroup.tsx +10 -0
  457. package/src/components/Select/SelectItem.tsx +71 -0
  458. package/src/components/Select/SelectLabel.tsx +32 -0
  459. package/src/components/Select/SelectRoot.tsx +6 -0
  460. package/src/components/Select/SelectSeparator.tsx +13 -0
  461. package/src/components/Select/SelectTrigger.tsx +161 -0
  462. package/src/components/Select/index.ts +1 -0
  463. package/src/components/Separator/Separator.stories.tsx +41 -0
  464. package/src/components/Separator/Separator.tsx +84 -0
  465. package/src/components/Separator/index.ts +1 -0
  466. package/src/components/Sheet/Sheet.stories.tsx +63 -0
  467. package/src/components/Sheet/Sheet.tsx +21 -0
  468. package/src/components/Sheet/SheetBody.tsx +12 -0
  469. package/src/components/Sheet/SheetContent.tsx +131 -0
  470. package/src/components/Sheet/SheetFooter.tsx +9 -0
  471. package/src/components/Sheet/SheetHeader.tsx +39 -0
  472. package/src/components/Sheet/SheetOverlay.tsx +11 -0
  473. package/src/components/Sheet/SheetTitle.tsx +12 -0
  474. package/src/components/Sheet/index.ts +1 -0
  475. package/src/components/Sidebar/Sidebar.stories.tsx +812 -0
  476. package/src/components/Sidebar/Sidebar.tsx +225 -0
  477. package/src/components/Sidebar/SidebarContent.tsx +61 -0
  478. package/src/components/Sidebar/SidebarFillTrigger.tsx +25 -0
  479. package/src/components/Sidebar/SidebarFooter.tsx +13 -0
  480. package/src/components/Sidebar/SidebarGroup/SidebarGroup.tsx +23 -0
  481. package/src/components/Sidebar/SidebarGroup/SidebarGroupAction.tsx +49 -0
  482. package/src/components/Sidebar/SidebarGroup/SidebarGroupContent.tsx +20 -0
  483. package/src/components/Sidebar/SidebarGroup/SidebarGroupLabel.tsx +76 -0
  484. package/src/components/Sidebar/SidebarGroup/index.ts +4 -0
  485. package/src/components/Sidebar/SidebarHeader.tsx +20 -0
  486. package/src/components/Sidebar/SidebarInstanceContext.ts +18 -0
  487. package/src/components/Sidebar/SidebarMenu/SidebarMenu.tsx +28 -0
  488. package/src/components/Sidebar/SidebarMenu/SidebarMenuAction.tsx +69 -0
  489. package/src/components/Sidebar/SidebarMenu/SidebarMenuBadge.tsx +56 -0
  490. package/src/components/Sidebar/SidebarMenu/SidebarMenuButton.tsx +108 -0
  491. package/src/components/Sidebar/SidebarMenu/SidebarMenuCard.tsx +107 -0
  492. package/src/components/Sidebar/SidebarMenu/SidebarMenuIcon.tsx +30 -0
  493. package/src/components/Sidebar/SidebarMenu/SidebarMenuItem.tsx +9 -0
  494. package/src/components/Sidebar/SidebarMenu/SidebarMenuSub.tsx +143 -0
  495. package/src/components/Sidebar/SidebarMenu/SidebarMenuSubItem.tsx +106 -0
  496. package/src/components/Sidebar/SidebarMenu/SidebarSearchInput.tsx +90 -0
  497. package/src/components/Sidebar/SidebarMenu/index.ts +10 -0
  498. package/src/components/Sidebar/SidebarProvider/SidebarProvider.tsx +171 -0
  499. package/src/components/Sidebar/SidebarProvider/context.ts +35 -0
  500. package/src/components/Sidebar/SidebarProvider/index.ts +2 -0
  501. package/src/components/Sidebar/SidebarProvider/useHoverTracking.test.ts +199 -0
  502. package/src/components/Sidebar/SidebarProvider/useHoverTracking.ts +72 -0
  503. package/src/components/Sidebar/SidebarProvider/useSidebarState.ts +50 -0
  504. package/src/components/Sidebar/SidebarProvider/useTransitionPresence.test.ts +179 -0
  505. package/src/components/Sidebar/SidebarProvider/useTransitionPresence.ts +53 -0
  506. package/src/components/Sidebar/SidebarResizeHandle.tsx +28 -0
  507. package/src/components/Sidebar/SidebarSeparator.tsx +15 -0
  508. package/src/components/Sidebar/SidebarTrigger.tsx +40 -0
  509. package/src/components/Sidebar/index.ts +3 -0
  510. package/src/components/Sidebar/types.ts +6 -0
  511. package/src/components/Sidebar/useResizeSidebar.ts +112 -0
  512. package/src/components/Sidebar/utils.test.ts +178 -0
  513. package/src/components/Sidebar/utils.ts +70 -0
  514. package/src/components/Skeleton/Skeleton.stories.tsx +54 -0
  515. package/src/components/Skeleton/Skeleton.tsx +54 -0
  516. package/src/components/Skeleton/SkeletonList.stories.tsx +11 -0
  517. package/src/components/Skeleton/SkeletonList.tsx +65 -0
  518. package/src/components/Slider/Slider.stories.tsx +99 -0
  519. package/src/components/Slider/Slider.tsx +85 -0
  520. package/src/components/Slider/SliderThumb.tsx +57 -0
  521. package/src/components/Slider/SliderTrack.tsx +49 -0
  522. package/src/components/Slider/index.ts +1 -0
  523. package/src/components/Slider/useInteracting.test.ts +159 -0
  524. package/src/components/Slider/useInteracting.ts +64 -0
  525. package/src/components/Switch/Switch.stories.tsx +177 -0
  526. package/src/components/Switch/Switch.tsx +58 -0
  527. package/src/components/Switch/index.ts +1 -0
  528. package/src/components/Switch/styles.ts +173 -0
  529. package/src/components/Table/Table.stories.tsx +106 -0
  530. package/src/components/Table/Table.tsx +51 -0
  531. package/src/components/Table/TableBody.tsx +22 -0
  532. package/src/components/Table/TableCell.tsx +7 -0
  533. package/src/components/Table/TableFooter.tsx +15 -0
  534. package/src/components/Table/TableHead.tsx +15 -0
  535. package/src/components/Table/TableHeader.tsx +20 -0
  536. package/src/components/Table/TableRow.tsx +11 -0
  537. package/src/components/Table/index.ts +1 -0
  538. package/src/components/Tabs.stories.tsx +123 -0
  539. package/src/components/Tabs.tsx +111 -0
  540. package/src/components/ThemeProvider/AIGradientSvg.tsx +18 -0
  541. package/src/components/ThemeProvider/ThemeProvider.tsx +25 -0
  542. package/src/components/ThemeProvider/index.ts +1 -0
  543. package/src/components/TimePicker/TimePicker.tsx +95 -0
  544. package/src/components/TimePicker/TimePickerButton.tsx +39 -0
  545. package/src/components/TimePicker/index.ts +1 -0
  546. package/src/components/TimePicker/utils.ts +31 -0
  547. package/src/components/Timeline/Timeline.stories.tsx +246 -0
  548. package/src/components/Timeline/Timeline.tsx +35 -0
  549. package/src/components/Timeline/TimelineConnector.tsx +154 -0
  550. package/src/components/Timeline/TimelineContent.tsx +18 -0
  551. package/src/components/Timeline/TimelineItem.tsx +14 -0
  552. package/src/components/Timeline/index.ts +1 -0
  553. package/src/components/Timeline/useLastLineHeight.ts +36 -0
  554. package/src/components/Toast/Toast.stories.tsx +178 -0
  555. package/src/components/Toast/ToastAction.tsx +40 -0
  556. package/src/components/Toast/ToastDescription.tsx +28 -0
  557. package/src/components/Toast/ToastDismiss.tsx +36 -0
  558. package/src/components/Toast/ToastDuration.tsx +43 -0
  559. package/src/components/Toast/ToastRoot.tsx +130 -0
  560. package/src/components/Toast/ToastTitle.tsx +33 -0
  561. package/src/components/Toast/Toaster.tsx +25 -0
  562. package/src/components/Toast/index.ts +3 -0
  563. package/src/components/Toast/toast.tsx +94 -0
  564. package/src/components/Toast/useNotification.tsx +33 -0
  565. package/src/components/Toggle/Toggle.stories.tsx +67 -0
  566. package/src/components/Toggle/Toggle.tsx +197 -0
  567. package/src/components/Toggle/index.ts +1 -0
  568. package/src/components/Tooltip/Tooltip.stories.tsx +82 -0
  569. package/src/components/Tooltip/Tooltip.tsx +87 -0
  570. package/src/components/Tooltip/TooltipContent.tsx +90 -0
  571. package/src/components/Tooltip/TooltipRoot.tsx +12 -0
  572. package/src/components/Tooltip/TooltipTrigger.tsx +42 -0
  573. package/src/components/Tooltip/index.ts +1 -0
  574. package/src/components/Truncated.stories.tsx +72 -0
  575. package/src/components/Truncated.tsx +78 -0
  576. package/src/components/ZoomableSvg/ZoomableSvg.stories.tsx +53 -0
  577. package/src/components/ZoomableSvg/ZoomableSvg.tsx +198 -0
  578. package/src/components/ZoomableSvg/index.ts +1 -0
  579. package/src/constants/keyCodes.ts +5 -0
  580. package/src/docs/Colors.mdx +19 -0
  581. package/src/docs/Spacing.mdx +35 -0
  582. package/src/docs/Typography.mdx +63 -0
  583. package/src/docs/components/Typeset.tsx +35 -0
  584. package/src/hooks/useAutosizeInput.stories.tsx +142 -0
  585. package/src/hooks/useAutosizeInput.test.tsx +77 -0
  586. package/src/hooks/useAutosizeInput.tsx +107 -0
  587. package/src/hooks/useElement.ts +16 -0
  588. package/src/hooks/useScrollbarPosition.ts +68 -0
  589. package/src/icon-names.ts +20 -0
  590. package/src/index.ts +87 -0
  591. package/src/styles.css +212 -0
  592. package/src/utils/classNames.test.ts +16 -0
  593. package/src/utils/classNames.ts +27 -0
  594. package/src/utils/copyToClipboard.ts +3 -0
  595. package/src/utils/createChangeInputEvent.ts +28 -0
  596. package/src/utils/createPrefixedString.ts +2 -0
  597. package/src/utils/debounce.test.ts +63 -0
  598. package/src/utils/debounce.ts +17 -0
  599. package/src/utils/decorators.tsx +16 -0
  600. package/src/utils/escapeStringRegexp.ts +4 -0
  601. package/src/utils/index.ts +11 -0
  602. package/src/utils/isMac.ts +26 -0
  603. package/src/utils/mergeRefs.ts +23 -0
  604. package/src/utils/noop.ts +1 -0
  605. package/src/utils/useSHA256.ts +21 -0
  606. package/src/vite-env.d.ts +1 -0
@@ -0,0 +1,39 @@
1
+ import type { EditorThemeClasses } from 'lexical';
2
+
3
+ /**
4
+ * Lexical editor theme — maps node types to CSS classes.
5
+ * The editor container uses `tw-prose` so semantic elements (headings, lists, blockquotes, etc.)
6
+ * are styled by Tailwind Typography. We only need explicit classes for text formatting
7
+ * (bold, italic, etc.) because Lexical renders those as `<span>` elements.
8
+ */
9
+ export const editorTheme: EditorThemeClasses = {
10
+ link: 'tw-cursor-pointer !tw-text-secondary-500 tw-underline',
11
+ text: {
12
+ bold: 'tw-font-bold',
13
+ italic: 'tw-italic',
14
+ strikethrough: 'tw-line-through',
15
+ underline: 'tw-underline',
16
+ code: 'tw-rounded tw-bg-neutral-100 tw-px-1 tw-py-0.5 tw-font-mono tw-text-[0.85em]',
17
+ },
18
+ list: {
19
+ ol: '!tw-list-decimal',
20
+ ul: '!tw-list-disc',
21
+ checklist: '!tw-list-none !tw-pl-0',
22
+ listitemChecked: [
23
+ 'tw-relative !tw-pl-6 tw-list-none tw-outline-none tw-line-through tw-text-neutral-400',
24
+ 'before:tw-content-[""] before:tw-absolute before:tw-left-0 before:tw-top-[3px]',
25
+ 'before:tw-size-4 before:tw-rounded before:tw-border before:tw-border-solid',
26
+ 'before:tw-bg-secondary-500 before:tw-border-secondary-500 before:tw-cursor-pointer',
27
+ 'after:tw-content-[""] after:tw-absolute after:tw-left-[5.5px] after:tw-top-[5.5px]',
28
+ 'after:tw-w-1 after:tw-h-2 after:tw-border-white after:tw-border-solid',
29
+ 'after:tw-border-r-[1.5px] after:tw-border-b-[1.5px] after:tw-border-t-0 after:tw-border-l-0',
30
+ 'after:tw-rotate-45',
31
+ ].join(' '),
32
+ listitemUnchecked: [
33
+ 'tw-relative !tw-pl-6 tw-list-none tw-outline-none',
34
+ 'before:tw-content-[""] before:tw-absolute before:tw-left-0 before:tw-top-[3px]',
35
+ 'before:tw-size-4 before:tw-rounded before:tw-border before:tw-border-solid',
36
+ 'before:tw-border-neutral-200 before:tw-bg-white before:tw-cursor-pointer',
37
+ ].join(' '),
38
+ },
39
+ };
@@ -0,0 +1,179 @@
1
+ import type {
2
+ ElementTransformer,
3
+ MultilineElementTransformer,
4
+ TextMatchTransformer,
5
+ Transformer,
6
+ } from '@lexical/markdown';
7
+ import { CHECK_LIST, TRANSFORMERS } from '@lexical/markdown';
8
+ import {
9
+ $createHorizontalRuleNode,
10
+ $isHorizontalRuleNode,
11
+ HorizontalRuleNode,
12
+ } from '@lexical/react/LexicalHorizontalRuleNode';
13
+
14
+ import { $createImageNode, $isImageNode, ImageNode } from './nodes/ImageNode';
15
+ import { $createMermaidNode, $isMermaidNode, MermaidNode } from './nodes/MermaidNode';
16
+
17
+ /** Markdown image: `![alt](src)` */
18
+ const IMAGE: TextMatchTransformer = {
19
+ dependencies: [ImageNode],
20
+ export: (node) => {
21
+ if (!$isImageNode(node)) return null;
22
+ return `![${node.getAlt()}](${node.getSrc()})`;
23
+ },
24
+ importRegExp: /!\[([^\]]*)\]\(([^)]+)\)/,
25
+ regExp: /!\[([^\]]*)\]\(([^)]+)\)$/,
26
+ replace: (textNode, match) => {
27
+ const [, alt = '', src = ''] = match;
28
+ const imageNode = $createImageNode(src, alt);
29
+ textNode.replace(imageNode);
30
+ },
31
+ trigger: ')',
32
+ type: 'text-match',
33
+ };
34
+
35
+ /** Horizontal rule: `---`, `***`, or `___` */
36
+ const HORIZONTAL_RULE: ElementTransformer = {
37
+ dependencies: [HorizontalRuleNode],
38
+ export: (node) => {
39
+ return $isHorizontalRuleNode(node) ? '---' : null;
40
+ },
41
+ regExp: /^(---|\*\*\*|___)$/,
42
+ replace: (parentNode) => {
43
+ const node = $createHorizontalRuleNode();
44
+ parentNode.replace(node);
45
+ },
46
+ type: 'element',
47
+ };
48
+
49
+ /** Fenced mermaid block: ` ```mermaid ... ``` ` → MermaidNode (rendered as diagram) */
50
+ const MERMAID: MultilineElementTransformer = {
51
+ dependencies: [MermaidNode],
52
+ export: (node) => {
53
+ if (!$isMermaidNode(node)) return null;
54
+ return '```mermaid\n' + node.getCode() + '\n```';
55
+ },
56
+ regExpStart: /^[ \t]*(`{3,})mermaid(?:\s.*)?$/,
57
+ regExpEnd: {
58
+ optional: true,
59
+ regExp: /^[ \t]*`{3,}$/,
60
+ },
61
+ replace: (rootNode, _children, _startMatch, _endMatch, linesInBetween) => {
62
+ if (!linesInBetween) return;
63
+ const code = linesInBetween.join('\n').trim();
64
+ if (code) {
65
+ rootNode.append($createMermaidNode(code));
66
+ }
67
+ },
68
+ handleImportAfterStartMatch: ({
69
+ lines,
70
+ rootNode,
71
+ startLineIndex,
72
+ startMatch,
73
+ }): [boolean, number] => {
74
+ const fence = startMatch[1];
75
+ if (!fence) return [false, startLineIndex];
76
+ const fenceLength = fence.trim().length;
77
+ const endRegex = new RegExp(`^[ \\t]*\`{${fenceLength},}$`);
78
+
79
+ for (let i = startLineIndex + 1; i < lines.length; i++) {
80
+ if (endRegex.test(lines[i] ?? '')) {
81
+ const code = lines
82
+ .slice(startLineIndex + 1, i)
83
+ .join('\n')
84
+ .trim();
85
+ if (code) {
86
+ rootNode.append($createMermaidNode(code));
87
+ }
88
+ return [true, i];
89
+ }
90
+ }
91
+
92
+ // No closing fence — consume remaining lines
93
+ const code = lines
94
+ .slice(startLineIndex + 1)
95
+ .join('\n')
96
+ .trim();
97
+ if (code) {
98
+ rootNode.append($createMermaidNode(code));
99
+ }
100
+ return [true, lines.length - 1];
101
+ },
102
+ type: 'multiline-element',
103
+ };
104
+
105
+ /**
106
+ * Custom transformers = our additions + built-in Lexical transformers.
107
+ * MERMAID is placed before TRANSFORMERS so it intercepts ` ```mermaid ``` ` before the generic CODE transformer.
108
+ * IMAGE is placed before built-in LINK to prevent `![alt](url)` from being parsed as `!` + link.
109
+ */
110
+ export const CUSTOM_TRANSFORMERS: Transformer[] = [
111
+ IMAGE,
112
+ HORIZONTAL_RULE,
113
+ CHECK_LIST,
114
+ MERMAID,
115
+ ...TRANSFORMERS,
116
+ ];
117
+
118
+ // --- Table pre/post-processing ---
119
+ // GFM tables can't round-trip through Lexical's markdown (no built-in table transformer).
120
+ // We wrap them in fenced code blocks on import and unwrap on export to preserve them exactly.
121
+
122
+ const TABLE_FENCE_LANG = '__kbc_table__';
123
+
124
+ const isTableLine = (line: string): boolean => {
125
+ const trimmed = line.trim();
126
+ return trimmed.startsWith('|') && trimmed.endsWith('|');
127
+ };
128
+
129
+ const CODE_FENCE_REGEX = /^[ \t]*`{3,}/;
130
+
131
+ /** Wrap GFM tables in code fences so they survive Lexical's markdown round-trip. */
132
+ export const preprocessMarkdown = (markdown: string): string => {
133
+ const lines = markdown.split('\n');
134
+ const result: string[] = [];
135
+ let tableLines: string[] = [];
136
+ let insideCodeFence = false;
137
+
138
+ const flushTable = () => {
139
+ if (tableLines.length >= 2) {
140
+ result.push(`\`\`\`${TABLE_FENCE_LANG}`);
141
+ result.push(...tableLines);
142
+ result.push('```');
143
+ } else {
144
+ // Single pipe line isn't a table — keep as-is
145
+ result.push(...tableLines);
146
+ }
147
+ tableLines = [];
148
+ };
149
+
150
+ for (const line of lines) {
151
+ if (CODE_FENCE_REGEX.test(line)) {
152
+ if (tableLines.length > 0) flushTable();
153
+ insideCodeFence = !insideCodeFence;
154
+ result.push(line);
155
+ continue;
156
+ }
157
+
158
+ if (insideCodeFence) {
159
+ result.push(line);
160
+ continue;
161
+ }
162
+
163
+ if (isTableLine(line)) {
164
+ tableLines.push(line);
165
+ } else {
166
+ if (tableLines.length > 0) flushTable();
167
+ result.push(line);
168
+ }
169
+ }
170
+ if (tableLines.length > 0) flushTable();
171
+
172
+ return result.join('\n');
173
+ };
174
+
175
+ /** Unwrap code-fenced tables back to raw GFM table markdown. */
176
+ export const postprocessMarkdown = (markdown: string): string => {
177
+ const regex = new RegExp(`\`\`\`${TABLE_FENCE_LANG}\\n([\\s\\S]*?)\\n\`\`\``, 'g');
178
+ return markdown.replace(regex, '$1');
179
+ };
@@ -0,0 +1,46 @@
1
+ import { useState } from 'react';
2
+ import type { ComponentProps } from 'react';
3
+ import type { Meta, StoryObj } from '@storybook/react-vite';
4
+
5
+ import { TextInput } from '../Input';
6
+
7
+ import { MarkedText } from './MarkedText';
8
+
9
+ export default {
10
+ component: MarkedText,
11
+ args: {
12
+ source: 'This is a text with marked words.',
13
+ mark: 'marked',
14
+ },
15
+ } satisfies Meta<typeof MarkedText>;
16
+
17
+ type Story = StoryObj<typeof MarkedText>;
18
+
19
+ export const Default: Story = {};
20
+
21
+ const MarkedTextDemo = (props: ComponentProps<typeof MarkedText>) => {
22
+ const [search, setSearch] = useState('');
23
+ return (
24
+ <div className="tw-flex tw-flex-col tw-gap-4">
25
+ <TextInput
26
+ value={search}
27
+ placeholder="Search..."
28
+ onValueChange={setSearch}
29
+ variant="secondary"
30
+ />
31
+ <MarkedText {...props} mark={search} />
32
+ </div>
33
+ );
34
+ };
35
+
36
+ export const WithInput: Story = {
37
+ args: {
38
+ source:
39
+ 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam euismod, nisi vel consectetur interdum, nisl nunc egestas nunc, vitae tincidunt nisl nunc euismod nunc. Sed euismod, nisi vel consectetur interdum, nisl nunc egestas nunc, vitae tincidunt nisl nunc euismod nunc.\n' +
40
+ 'Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae; Donec velit neque, auctor sit amet aliquam vel, ullamcorper sit amet ligula. Proin eget tortor risus. Vivamus suscipit tortor eget felis porttitor volutpat. Praesent sapien massa, convallis a pellentesque nec, egestas non nisi.\n' +
41
+ 'Curabitur non nulla sit amet nisl tempus convallis quis ac lectus. Pellentesque in ipsum id orci porta dapibus. Cras ultricies ligula sed magna dictum porta. Nulla quis lorem ut libero malesuada feugiat. Mauris blandit aliquet elit, eget tincidunt nibh pulvinar a.\n' +
42
+ 'Sed porttitor lectus nibh. Nulla porttitor accumsan tincidunt. Vivamus magna justo, lacinia eget consectetur sed, convallis at tellus. Curabitur aliquet quam id dui posuere blandit. Nulla quis lorem ut libero malesuada feugiat.\n' +
43
+ 'Praesent sapien massa, convallis a pellentesque nec, egestas non nisi. Donec rutrum congue leo eget malesuada. Mauris blandit aliquet elit, eget tincidunt nibh pulvinar a. Nulla porttitor accumsan tincidunt. Vivamus suscipit tortor eget felis porttitor volutpat.',
44
+ },
45
+ render: MarkedTextDemo,
46
+ };
@@ -0,0 +1,36 @@
1
+ import { useMemo } from 'react';
2
+ import type { ComponentProps, ElementRef, Ref } from 'react';
3
+
4
+ import { createMarkedParts } from './utils';
5
+
6
+ type Props = {
7
+ source: string;
8
+ className?: string;
9
+ mark?: string;
10
+ isCaseSensitive?: boolean;
11
+ } & ComponentProps<'span'>;
12
+
13
+ export const MarkedText = ({
14
+ ref,
15
+ source,
16
+ mark,
17
+ isCaseSensitive = false,
18
+ ...spanProps
19
+ }: Props & { ref?: Ref<ElementRef<'span'>> }) => {
20
+ const parts = useMemo(
21
+ () =>
22
+ createMarkedParts({
23
+ mark,
24
+ source,
25
+ isCaseSensitive,
26
+ }),
27
+ [isCaseSensitive, mark, source],
28
+ );
29
+
30
+ return (
31
+ <span {...spanProps} ref={ref}>
32
+ {/* oxlint-disable-next-line react/no-array-index-key */}
33
+ {parts.map(({ isMark, part }, index) => (isMark ? <mark key={index}>{part}</mark> : part))}
34
+ </span>
35
+ );
36
+ };
@@ -0,0 +1 @@
1
+ export { MarkedText } from './MarkedText';
@@ -0,0 +1,193 @@
1
+ import { createMarkedParts } from './utils';
2
+
3
+ describe('MarkedText - utils - createMarkedParts', () => {
4
+ it('should return single unmarked part with entire source as there is no marked string', () => {
5
+ const result = createMarkedParts({
6
+ source: 'hello world',
7
+ isCaseSensitive: false,
8
+ });
9
+
10
+ expect(result).toEqual([{ isMark: false, part: 'hello world' }]);
11
+ });
12
+
13
+ it('should return empty array as there is nothing to mark', () => {
14
+ const result = createMarkedParts({
15
+ source: '',
16
+ mark: 'hello',
17
+ isCaseSensitive: false,
18
+ });
19
+
20
+ expect(result).toEqual([]);
21
+ });
22
+
23
+ it('should properly escape special regex characters', () => {
24
+ const result = createMarkedParts({
25
+ mark: '(test) [hello] $world',
26
+ source: 'this (test) has [hello] special $world chars',
27
+ isCaseSensitive: false,
28
+ });
29
+
30
+ expect(result.filter((p) => p.isMark)).toHaveLength(3);
31
+ });
32
+
33
+ it('should return original source when mark is empty', () => {
34
+ const result = createMarkedParts({
35
+ mark: '',
36
+ source: 'hello world',
37
+ isCaseSensitive: false,
38
+ });
39
+
40
+ expect(result).toEqual([{ isMark: false, part: 'hello world' }]);
41
+ });
42
+
43
+ it('should return original source when mark is whitespace only', () => {
44
+ const result = createMarkedParts({
45
+ mark: ' ',
46
+ source: 'hello world',
47
+ isCaseSensitive: false,
48
+ });
49
+
50
+ expect(result).toEqual([{ isMark: false, part: 'hello world' }]);
51
+ });
52
+
53
+ it('should split text correctly with single word match', () => {
54
+ const result = createMarkedParts({
55
+ mark: 'world',
56
+ source: 'hello world test',
57
+ isCaseSensitive: false,
58
+ });
59
+
60
+ expect(result).toEqual([
61
+ { isMark: false, part: 'hello ' },
62
+ { isMark: true, part: 'world' },
63
+ { isMark: false, part: ' test' },
64
+ ]);
65
+ });
66
+
67
+ it('should split text correctly with multiple matches', () => {
68
+ const result = createMarkedParts({
69
+ mark: 'test',
70
+ source: 'test hello test world test',
71
+ isCaseSensitive: false,
72
+ });
73
+
74
+ expect(result).toEqual([
75
+ { isMark: true, part: 'test' },
76
+ { isMark: false, part: ' hello ' },
77
+ { isMark: true, part: 'test' },
78
+ { isMark: false, part: ' world ' },
79
+ { isMark: true, part: 'test' },
80
+ ]);
81
+ });
82
+ });
83
+
84
+ describe('case sensitivity', () => {
85
+ it('should respect case insensitive matching', () => {
86
+ const result = createMarkedParts({
87
+ mark: 'Hello',
88
+ source: 'hello world Hello there',
89
+ isCaseSensitive: false,
90
+ });
91
+
92
+ expect(result).toEqual([
93
+ { isMark: true, part: 'hello' },
94
+ { isMark: false, part: ' world ' },
95
+ { isMark: true, part: 'Hello' },
96
+ { isMark: false, part: ' there' },
97
+ ]);
98
+ });
99
+
100
+ it('should respect case sensitive matching', () => {
101
+ const result = createMarkedParts({
102
+ mark: 'Hello',
103
+ source: 'hello world Hello there',
104
+ isCaseSensitive: true,
105
+ });
106
+
107
+ expect(result).toEqual([
108
+ { isMark: false, part: 'hello world ' },
109
+ { isMark: true, part: 'Hello' },
110
+ { isMark: false, part: ' there' },
111
+ ]);
112
+ });
113
+
114
+ it('should handle mixed case in source with case insensitive search', () => {
115
+ const result = createMarkedParts({
116
+ mark: 'test',
117
+ source: 'Test is a TEST for testing',
118
+ isCaseSensitive: false,
119
+ });
120
+
121
+ expect(result).toEqual([
122
+ { isMark: true, part: 'Test' },
123
+ { isMark: false, part: ' is a ' },
124
+ { isMark: true, part: 'TEST' },
125
+ { isMark: false, part: ' for ' },
126
+ { isMark: true, part: 'test' },
127
+ { isMark: false, part: 'ing' },
128
+ ]);
129
+ });
130
+ });
131
+
132
+ describe('multiple words', () => {
133
+ it('should split on multiple words with OR logic', () => {
134
+ const result = createMarkedParts({
135
+ mark: 'hello world',
136
+ source: 'hello there world peace',
137
+ isCaseSensitive: false,
138
+ });
139
+
140
+ expect(result).toEqual([
141
+ { isMark: true, part: 'hello' },
142
+ { isMark: false, part: ' there ' },
143
+ { isMark: true, part: 'world' },
144
+ { isMark: false, part: ' peace' },
145
+ ]);
146
+ });
147
+
148
+ it('should handle multiple spaces between search terms', () => {
149
+ const result = createMarkedParts({
150
+ mark: 'hello world',
151
+ source: 'hello there world peace',
152
+ isCaseSensitive: false,
153
+ });
154
+
155
+ expect(result).toEqual([
156
+ { isMark: true, part: 'hello' },
157
+ { isMark: false, part: ' there ' },
158
+ { isMark: true, part: 'world' },
159
+ { isMark: false, part: ' peace' },
160
+ ]);
161
+ });
162
+
163
+ it('should handle overlapping search terms', () => {
164
+ const result = createMarkedParts({
165
+ mark: 'test testing',
166
+ source: 'testing is test work',
167
+ isCaseSensitive: false,
168
+ });
169
+
170
+ expect(result).toEqual([
171
+ { isMark: true, part: 'test' },
172
+ { isMark: false, part: 'ing is ' },
173
+ { isMark: true, part: 'test' },
174
+ { isMark: false, part: ' work' },
175
+ ]);
176
+ });
177
+
178
+ it('should handle three or more search terms', () => {
179
+ const result = createMarkedParts({
180
+ mark: 'one two three',
181
+ source: 'one fish two fish red fish blue fish three',
182
+ isCaseSensitive: false,
183
+ });
184
+
185
+ expect(result).toEqual([
186
+ { isMark: true, part: 'one' },
187
+ { isMark: false, part: ' fish ' },
188
+ { isMark: true, part: 'two' },
189
+ { isMark: false, part: ' fish red fish blue fish ' },
190
+ { isMark: true, part: 'three' },
191
+ ]);
192
+ });
193
+ });
@@ -0,0 +1,37 @@
1
+ import { escapeStringRegexp } from '../../utils/escapeStringRegexp';
2
+
3
+ const createSearchRegex = ({
4
+ mark,
5
+ isCaseSensitive = false,
6
+ }: {
7
+ mark: string;
8
+ isCaseSensitive?: boolean;
9
+ }) => {
10
+ const pattern = escapeStringRegexp(mark).split(' ').filter(Boolean).join('|');
11
+ return new RegExp(`(${pattern})`, `g${isCaseSensitive ? '' : 'i'}`);
12
+ };
13
+
14
+ export const createMarkedParts = ({
15
+ mark,
16
+ isCaseSensitive,
17
+ source,
18
+ }: {
19
+ mark?: string;
20
+ source: string;
21
+ isCaseSensitive: boolean;
22
+ }) => {
23
+ if (!mark?.trim()) return [{ isMark: false, part: source }];
24
+
25
+ const searchRegex = createSearchRegex({
26
+ mark,
27
+ isCaseSensitive,
28
+ });
29
+
30
+ return source
31
+ .split(searchRegex)
32
+ .map((part) => ({
33
+ isMark: searchRegex.test(part),
34
+ part,
35
+ }))
36
+ .filter(({ part }) => part !== '');
37
+ };
@@ -0,0 +1,20 @@
1
+ import { Button } from '../../Button';
2
+
3
+ type Props = {
4
+ side: 'left' | 'right';
5
+ onAccept: () => void;
6
+ };
7
+
8
+ export const AcceptButton = ({ side, onAccept }: Props) => {
9
+ const label = `Accept ${side === 'left' ? 'production' : 'branch'} version`;
10
+ return (
11
+ <Button
12
+ icon={side === 'left' ? ['far', 'chevrons-right'] : ['far', 'chevrons-left']}
13
+ onClick={onAccept}
14
+ variant="outline"
15
+ size="icon"
16
+ title={label}
17
+ aria-label={label}
18
+ />
19
+ );
20
+ };
@@ -0,0 +1,66 @@
1
+ import type { RefCallback } from 'react';
2
+
3
+ import { cn } from '../../../utils';
4
+ import { Button } from '../../Button';
5
+ import { LINE_HEIGHT_PX, type MergeConflict, PANE_HEADER_HEIGHT_PX } from '../constants';
6
+
7
+ import { AcceptButton } from './AcceptButton';
8
+
9
+ type Props = {
10
+ conflicts: MergeConflict[];
11
+ side: 'left' | 'right';
12
+ onAccept: (conflict: MergeConflict) => void;
13
+ onDismiss?: (conflict: MergeConflict) => void;
14
+ contentRef?: RefCallback<HTMLDivElement>;
15
+ };
16
+
17
+ // 40px column when there are conflicts to render — wide enough to fit the
18
+ // accept chevron + dismiss icon without overflowing into the adjacent panes
19
+ // (which use `tw-overflow-hidden` and would clip absolutely-positioned
20
+ // children that crossed the boundary). Collapses to 0 when idle so empty
21
+ // merges don't reserve a sliver of layout. Inner wrapper allows horizontal
22
+ // overflow so the icon buttons' focus-visible ring (4px) stays visible past
23
+ // the column edge. Buttons stay aligned with their source-pane chunk via the
24
+ // parent's `translateY(-scrollTop)` follower applied to `contentRef`.
25
+ export const AcceptControls = ({ conflicts, side, onAccept, onDismiss, contentRef }: Props) => (
26
+ <div
27
+ className={cn(
28
+ 'tw-z-10 tw-flex tw-shrink-0 tw-flex-col tw-items-center',
29
+ conflicts.length > 0 ? 'tw-w-10' : 'tw-w-0',
30
+ )}
31
+ >
32
+ {conflicts.length > 0 && (
33
+ <>
34
+ <div className="tw-shrink-0" style={{ height: `${PANE_HEADER_HEIGHT_PX}px` }} />
35
+ <div className="tw-relative tw-w-full tw-flex-1 tw-overflow-y-clip tw-overflow-x-visible">
36
+ <div ref={contentRef} className="tw-relative tw-size-full">
37
+ {conflicts.map((conflict) => {
38
+ const topLine = side === 'left' ? conflict.oldStartLine : conflict.newStartLine;
39
+ const topOffset = (topLine - 1) * LINE_HEIGHT_PX - 2;
40
+
41
+ return (
42
+ <div
43
+ key={conflict.id}
44
+ className="tw-absolute tw-inset-x-0 tw-flex tw-flex-col tw-items-center tw-gap-0.5"
45
+ style={{ top: `${topOffset}px` }}
46
+ >
47
+ <AcceptButton side={side} onAccept={() => onAccept(conflict)} />
48
+ {onDismiss && (
49
+ <Button
50
+ icon="xmark"
51
+ onClick={() => onDismiss(conflict)}
52
+ variant="outline"
53
+ size="icon"
54
+ title="Dismiss"
55
+ aria-label={`Dismiss ${side === 'left' ? 'production' : 'branch'} change`}
56
+ />
57
+ )}
58
+ </div>
59
+ );
60
+ })}
61
+ </div>
62
+ </div>
63
+ </>
64
+ )}
65
+ </div>
66
+ );
@@ -0,0 +1,38 @@
1
+ import { cn } from '../../../utils';
2
+ import { Icon } from '../../Icon';
3
+
4
+ type Props = {
5
+ remainingConflicts: number;
6
+ remainingSafeChanges: number;
7
+ };
8
+
9
+ export const ConflictStatusIndicator = ({ remainingConflicts, remainingSafeChanges }: Props) => {
10
+ const hasConflicts = remainingConflicts > 0;
11
+ const allDone = !hasConflicts && remainingSafeChanges === 0;
12
+
13
+ const colorClass = hasConflicts
14
+ ? 'tw-text-warning-500'
15
+ : allDone
16
+ ? 'tw-text-primary-500'
17
+ : 'tw-text-neutral-400';
18
+
19
+ const parts: string[] = [];
20
+ if (hasConflicts) {
21
+ parts.push(`${remainingConflicts} conflict${remainingConflicts !== 1 ? 's' : ''}`);
22
+ }
23
+ if (remainingSafeChanges > 0) {
24
+ parts.push(`${remainingSafeChanges} change${remainingSafeChanges !== 1 ? 's' : ''}`);
25
+ }
26
+
27
+ return (
28
+ <p
29
+ className={cn(
30
+ 'tw-m-0 tw-flex tw-items-center tw-gap-1.5 tw-text-sm tw-font-medium',
31
+ colorClass,
32
+ )}
33
+ >
34
+ <Icon icon={allDone ? 'circle-check' : 'triangle-exclamation'} />
35
+ {allDone ? 'All changes resolved' : `${parts.join(', ')} remaining`}
36
+ </p>
37
+ );
38
+ };