@devalok/shilp-sutra 0.38.0 → 0.40.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 (361) hide show
  1. package/AGENTS.md +151 -0
  2. package/MIGRATION.md +255 -0
  3. package/README.md +3 -0
  4. package/dist/_chunks/badge-group.js +76 -75
  5. package/dist/_chunks/badge-group.js.map +1 -1
  6. package/dist/_chunks/chart-container.js +50 -0
  7. package/dist/_chunks/chart-container.js.map +1 -0
  8. package/dist/_chunks/chat.js +236 -228
  9. package/dist/_chunks/chat.js.map +1 -1
  10. package/dist/_chunks/colors.js +30 -0
  11. package/dist/_chunks/colors.js.map +1 -0
  12. package/dist/_chunks/document-preview.js +2 -2
  13. package/dist/_chunks/document-preview.js.map +1 -1
  14. package/dist/_chunks/emoji-data.js +45 -0
  15. package/dist/_chunks/emoji-data.js.map +1 -0
  16. package/dist/_chunks/grid-lines.js +72 -0
  17. package/dist/_chunks/grid-lines.js.map +1 -0
  18. package/dist/_chunks/image-preview.js +2 -2
  19. package/dist/_chunks/image-preview.js.map +1 -1
  20. package/dist/_chunks/mention-suggestion.js +35 -263
  21. package/dist/_chunks/mention-suggestion.js.map +1 -1
  22. package/dist/_chunks/normalize-icon.js +18 -0
  23. package/dist/_chunks/normalize-icon.js.map +1 -0
  24. package/dist/_chunks/oauth-button.js +227 -0
  25. package/dist/_chunks/oauth-button.js.map +1 -0
  26. package/dist/_chunks/popover.js +3 -3
  27. package/dist/_chunks/popover.js.map +1 -1
  28. package/dist/_chunks/primitives.js +107 -107
  29. package/dist/_chunks/primitives.js.map +1 -1
  30. package/dist/_chunks/shared.js +5 -5
  31. package/dist/_chunks/shared.js.map +1 -1
  32. package/dist/_chunks/{text.js → success.js} +26 -63
  33. package/dist/_chunks/success.js.map +1 -0
  34. package/dist/_chunks/tiptap.js +1952 -1949
  35. package/dist/_chunks/tiptap.js.map +1 -1
  36. package/dist/_chunks/tooltip.js +58 -0
  37. package/dist/_chunks/tooltip.js.map +1 -0
  38. package/dist/_chunks/tree-view.js +101 -96
  39. package/dist/_chunks/tree-view.js.map +1 -1
  40. package/dist/_chunks/use-calendar.js +5 -5
  41. package/dist/_chunks/use-calendar.js.map +1 -1
  42. package/dist/ai/ai-command-provider.d.ts +3 -2
  43. package/dist/ai/ai-command-provider.d.ts.map +1 -1
  44. package/dist/ai/ai-command-provider.js.map +1 -1
  45. package/dist/ai/block-renderer.js +11 -9
  46. package/dist/ai/block-renderer.js.map +1 -1
  47. package/dist/ai/blocks/error.js +31 -0
  48. package/dist/ai/blocks/error.js.map +1 -0
  49. package/dist/ai/blocks/index.d.ts +0 -2
  50. package/dist/ai/blocks/index.d.ts.map +1 -1
  51. package/dist/ai/blocks/index.js +2 -2
  52. package/dist/ai/blocks/text.js +19 -0
  53. package/dist/ai/blocks/text.js.map +1 -0
  54. package/dist/ai/command-bar.d.ts.map +1 -1
  55. package/dist/ai/command-bar.js +198 -193
  56. package/dist/ai/command-bar.js.map +1 -1
  57. package/dist/ai/conversation.d.ts +2 -1
  58. package/dist/ai/conversation.d.ts.map +1 -1
  59. package/dist/ai/conversation.js +92 -87
  60. package/dist/ai/conversation.js.map +1 -1
  61. package/dist/ai/index.d.ts +0 -4
  62. package/dist/ai/index.d.ts.map +1 -1
  63. package/dist/ai/index.js +45 -46
  64. package/dist/ai/index.js.map +1 -1
  65. package/dist/composed/activity-feed.d.ts +2 -1
  66. package/dist/composed/activity-feed.d.ts.map +1 -1
  67. package/dist/composed/activity-feed.js +5 -5
  68. package/dist/composed/activity-feed.js.map +1 -1
  69. package/dist/composed/avatar-group.js +4 -4
  70. package/dist/composed/avatar-group.js.map +1 -1
  71. package/dist/composed/bulk-action-bar.d.ts +2 -2
  72. package/dist/composed/bulk-action-bar.d.ts.map +1 -1
  73. package/dist/composed/bulk-action-bar.js +12 -12
  74. package/dist/composed/bulk-action-bar.js.map +1 -1
  75. package/dist/composed/command-palette.d.ts +2 -1
  76. package/dist/composed/command-palette.d.ts.map +1 -1
  77. package/dist/composed/command-palette.js +106 -101
  78. package/dist/composed/command-palette.js.map +1 -1
  79. package/dist/composed/content-card.js +1 -1
  80. package/dist/composed/content-card.js.map +1 -1
  81. package/dist/composed/date-picker/index.js +747 -3
  82. package/dist/composed/date-picker/index.js.map +1 -0
  83. package/dist/composed/emoji-picker.js +4 -4
  84. package/dist/composed/emoji-picker.js.map +1 -1
  85. package/dist/composed/empty-state.d.ts +3 -3
  86. package/dist/composed/empty-state.d.ts.map +1 -1
  87. package/dist/composed/empty-state.js +40 -31
  88. package/dist/composed/empty-state.js.map +1 -1
  89. package/dist/composed/error-boundary.js +3 -3
  90. package/dist/composed/error-boundary.js.map +1 -1
  91. package/dist/composed/extensions/emoji-node.js +81 -0
  92. package/dist/composed/extensions/emoji-node.js.map +1 -0
  93. package/dist/composed/extensions/emoji-suggestion.js +117 -0
  94. package/dist/composed/extensions/emoji-suggestion.js.map +1 -0
  95. package/dist/composed/file-preview.js +498 -2
  96. package/dist/composed/file-preview.js.map +1 -0
  97. package/dist/composed/filter-bar.js +1 -1
  98. package/dist/composed/filter-bar.js.map +1 -1
  99. package/dist/composed/index.d.ts +0 -15
  100. package/dist/composed/index.d.ts.map +1 -1
  101. package/dist/composed/index.js +16 -24
  102. package/dist/composed/inline-edit.js +1 -1
  103. package/dist/composed/inline-edit.js.map +1 -1
  104. package/dist/composed/loading-skeleton.js +9 -9
  105. package/dist/composed/loading-skeleton.js.map +1 -1
  106. package/dist/composed/markdown-viewer.js +3 -3
  107. package/dist/composed/markdown-viewer.js.map +1 -1
  108. package/dist/composed/multi-select-popover.js +1 -1
  109. package/dist/composed/multi-select-popover.js.map +1 -1
  110. package/dist/composed/page-header.js +1 -1
  111. package/dist/composed/page-header.js.map +1 -1
  112. package/dist/composed/page-skeletons.js +15 -15
  113. package/dist/composed/page-skeletons.js.map +1 -1
  114. package/dist/composed/priority-indicator.js +3 -3
  115. package/dist/composed/priority-indicator.js.map +1 -1
  116. package/dist/composed/rich-chat-input.js +2073 -2
  117. package/dist/composed/rich-chat-input.js.map +1 -0
  118. package/dist/composed/rich-text-editor.js +75 -72
  119. package/dist/composed/rich-text-editor.js.map +1 -1
  120. package/dist/composed/schedule-view.js +3 -3
  121. package/dist/composed/schedule-view.js.map +1 -1
  122. package/dist/composed/status-badge.d.ts +3 -2
  123. package/dist/composed/status-badge.d.ts.map +1 -1
  124. package/dist/composed/status-badge.js +58 -53
  125. package/dist/composed/status-badge.js.map +1 -1
  126. package/dist/shell/app-command-palette.d.ts +2 -1
  127. package/dist/shell/app-command-palette.d.ts.map +1 -1
  128. package/dist/shell/app-command-palette.js.map +1 -1
  129. package/dist/shell/bottom-navbar.d.ts +3 -1
  130. package/dist/shell/bottom-navbar.d.ts.map +1 -1
  131. package/dist/shell/bottom-navbar.js +94 -86
  132. package/dist/shell/bottom-navbar.js.map +1 -1
  133. package/dist/shell/command-registry.d.ts +2 -1
  134. package/dist/shell/command-registry.d.ts.map +1 -1
  135. package/dist/shell/command-registry.js.map +1 -1
  136. package/dist/shell/notification-center.js +8 -8
  137. package/dist/shell/notification-center.js.map +1 -1
  138. package/dist/shell/notification-preferences.js +1 -1
  139. package/dist/shell/notification-preferences.js.map +1 -1
  140. package/dist/shell/sidebar.d.ts +7 -4
  141. package/dist/shell/sidebar.d.ts.map +1 -1
  142. package/dist/shell/sidebar.js +148 -134
  143. package/dist/shell/sidebar.js.map +1 -1
  144. package/dist/shell/top-bar.d.ts +4 -3
  145. package/dist/shell/top-bar.d.ts.map +1 -1
  146. package/dist/shell/top-bar.js +116 -108
  147. package/dist/shell/top-bar.js.map +1 -1
  148. package/dist/tokens/semantic.css +82 -9
  149. package/dist/ui/accordion.js +1 -1
  150. package/dist/ui/accordion.js.map +1 -1
  151. package/dist/ui/alert-dialog.js +3 -3
  152. package/dist/ui/alert-dialog.js.map +1 -1
  153. package/dist/ui/alert.js +2 -2
  154. package/dist/ui/alert.js.map +1 -1
  155. package/dist/ui/autocomplete.js +2 -2
  156. package/dist/ui/autocomplete.js.map +1 -1
  157. package/dist/ui/avatar.js +11 -11
  158. package/dist/ui/avatar.js.map +1 -1
  159. package/dist/ui/badge-indicator.js +1 -1
  160. package/dist/ui/badge-indicator.js.map +1 -1
  161. package/dist/ui/badge.d.ts +3 -2
  162. package/dist/ui/badge.d.ts.map +1 -1
  163. package/dist/ui/banner.js +1 -1
  164. package/dist/ui/banner.js.map +1 -1
  165. package/dist/ui/breadcrumb.js +1 -1
  166. package/dist/ui/breadcrumb.js.map +1 -1
  167. package/dist/ui/button.d.ts +5 -4
  168. package/dist/ui/button.d.ts.map +1 -1
  169. package/dist/ui/button.js +66 -65
  170. package/dist/ui/button.js.map +1 -1
  171. package/dist/ui/card.js +5 -5
  172. package/dist/ui/card.js.map +1 -1
  173. package/dist/ui/charts/area-chart.js +177 -0
  174. package/dist/ui/charts/area-chart.js.map +1 -0
  175. package/dist/ui/charts/bar-chart.js +127 -0
  176. package/dist/ui/charts/bar-chart.js.map +1 -0
  177. package/dist/ui/charts/chart-container.js +3 -0
  178. package/dist/ui/charts/gauge-chart.js +72 -0
  179. package/dist/ui/charts/gauge-chart.js.map +1 -0
  180. package/dist/ui/charts/index.js +10 -1035
  181. package/dist/ui/charts/line-chart.js +135 -0
  182. package/dist/ui/charts/line-chart.js.map +1 -0
  183. package/dist/ui/charts/pie-chart.js +111 -0
  184. package/dist/ui/charts/pie-chart.js.map +1 -0
  185. package/dist/ui/charts/radar-chart.js +170 -0
  186. package/dist/ui/charts/radar-chart.js.map +1 -0
  187. package/dist/ui/charts/sparkline.js +119 -0
  188. package/dist/ui/charts/sparkline.js.map +1 -0
  189. package/dist/ui/chat/message.d.ts +3 -3
  190. package/dist/ui/chat/message.d.ts.map +1 -1
  191. package/dist/ui/chat/system-message.d.ts +2 -1
  192. package/dist/ui/chat/system-message.d.ts.map +1 -1
  193. package/dist/ui/checkbox.js +1 -1
  194. package/dist/ui/checkbox.js.map +1 -1
  195. package/dist/ui/code.js +2 -2
  196. package/dist/ui/code.js.map +1 -1
  197. package/dist/ui/color-input.js +10 -10
  198. package/dist/ui/color-input.js.map +1 -1
  199. package/dist/ui/color-swatch.js +3 -3
  200. package/dist/ui/color-swatch.js.map +1 -1
  201. package/dist/ui/combobox.d.ts +2 -1
  202. package/dist/ui/combobox.d.ts.map +1 -1
  203. package/dist/ui/combobox.js +100 -95
  204. package/dist/ui/combobox.js.map +1 -1
  205. package/dist/ui/container.d.ts +6 -1
  206. package/dist/ui/container.d.ts.map +1 -1
  207. package/dist/ui/container.js +2 -1
  208. package/dist/ui/container.js.map +1 -1
  209. package/dist/ui/context-menu.js +6 -6
  210. package/dist/ui/context-menu.js.map +1 -1
  211. package/dist/ui/data-table-body.js +1 -1
  212. package/dist/ui/data-table-body.js.map +1 -1
  213. package/dist/ui/data-table-bulk-actions.js +2 -2
  214. package/dist/ui/data-table-bulk-actions.js.map +1 -1
  215. package/dist/ui/data-table-card.js +2 -2
  216. package/dist/ui/data-table-card.js.map +1 -1
  217. package/dist/ui/data-table-header.js +2 -2
  218. package/dist/ui/data-table-header.js.map +1 -1
  219. package/dist/ui/data-table-pagination.js +3 -3
  220. package/dist/ui/data-table-pagination.js.map +1 -1
  221. package/dist/ui/data-table-toolbar.js +1 -1
  222. package/dist/ui/data-table-toolbar.js.map +1 -1
  223. package/dist/ui/data-table.js +1 -1
  224. package/dist/ui/data-table.js.map +1 -1
  225. package/dist/ui/devalok-grain.d.ts +1 -1
  226. package/dist/ui/devalok-grain.js.map +1 -1
  227. package/dist/ui/dialog.js +2 -2
  228. package/dist/ui/dialog.js.map +1 -1
  229. package/dist/ui/dropdown-menu.js +6 -6
  230. package/dist/ui/dropdown-menu.js.map +1 -1
  231. package/dist/ui/file-upload.js +4 -4
  232. package/dist/ui/file-upload.js.map +1 -1
  233. package/dist/ui/hover-card.js +1 -1
  234. package/dist/ui/hover-card.js.map +1 -1
  235. package/dist/ui/icon-button.d.ts +9 -2
  236. package/dist/ui/icon-button.d.ts.map +1 -1
  237. package/dist/ui/icon-button.js +14 -13
  238. package/dist/ui/icon-button.js.map +1 -1
  239. package/dist/ui/index.d.ts +1 -3
  240. package/dist/ui/index.d.ts.map +1 -1
  241. package/dist/ui/index.js +31 -33
  242. package/dist/ui/index.js.map +1 -1
  243. package/dist/ui/input-otp.js +1 -1
  244. package/dist/ui/input-otp.js.map +1 -1
  245. package/dist/ui/input.js +2 -2
  246. package/dist/ui/input.js.map +1 -1
  247. package/dist/ui/lib/icon-input.d.ts +42 -0
  248. package/dist/ui/lib/icon-input.d.ts.map +1 -0
  249. package/dist/ui/lib/normalize-icon.d.ts +39 -0
  250. package/dist/ui/lib/normalize-icon.d.ts.map +1 -0
  251. package/dist/ui/link.js +1 -1
  252. package/dist/ui/link.js.map +1 -1
  253. package/dist/ui/menubar.js +8 -8
  254. package/dist/ui/menubar.js.map +1 -1
  255. package/dist/ui/navigation-menu.js +3 -3
  256. package/dist/ui/navigation-menu.js.map +1 -1
  257. package/dist/ui/number-input.js +3 -3
  258. package/dist/ui/number-input.js.map +1 -1
  259. package/dist/ui/oauth-button/index.d.ts +3 -0
  260. package/dist/ui/oauth-button/index.d.ts.map +1 -0
  261. package/dist/ui/oauth-button/index.js +3 -0
  262. package/dist/ui/oauth-button/oauth-button.d.ts +208 -0
  263. package/dist/ui/oauth-button/oauth-button.d.ts.map +1 -0
  264. package/dist/ui/pagination.js +1 -1
  265. package/dist/ui/pagination.js.map +1 -1
  266. package/dist/ui/progress.js +2 -2
  267. package/dist/ui/progress.js.map +1 -1
  268. package/dist/ui/radio.js +1 -1
  269. package/dist/ui/radio.js.map +1 -1
  270. package/dist/ui/segmented-control.d.ts +3 -4
  271. package/dist/ui/segmented-control.d.ts.map +1 -1
  272. package/dist/ui/segmented-control.js +53 -45
  273. package/dist/ui/segmented-control.js.map +1 -1
  274. package/dist/ui/select.js +3 -3
  275. package/dist/ui/select.js.map +1 -1
  276. package/dist/ui/sheet.js +2 -2
  277. package/dist/ui/sheet.js.map +1 -1
  278. package/dist/ui/sidebar.js +11 -11
  279. package/dist/ui/sidebar.js.map +1 -1
  280. package/dist/ui/skeleton.js +9 -9
  281. package/dist/ui/skeleton.js.map +1 -1
  282. package/dist/ui/slider.js +2 -2
  283. package/dist/ui/slider.js.map +1 -1
  284. package/dist/ui/split-button.js +7 -7
  285. package/dist/ui/split-button.js.map +1 -1
  286. package/dist/ui/stack.d.ts +6 -1
  287. package/dist/ui/stack.d.ts.map +1 -1
  288. package/dist/ui/stack.js +2 -1
  289. package/dist/ui/stack.js.map +1 -1
  290. package/dist/ui/stat-card.d.ts +2 -3
  291. package/dist/ui/stat-card.d.ts.map +1 -1
  292. package/dist/ui/stat-card.js +118 -116
  293. package/dist/ui/stat-card.js.map +1 -1
  294. package/dist/ui/status-dot.js +2 -2
  295. package/dist/ui/status-dot.js.map +1 -1
  296. package/dist/ui/stepper.d.ts +2 -1
  297. package/dist/ui/stepper.d.ts.map +1 -1
  298. package/dist/ui/stepper.js +74 -69
  299. package/dist/ui/stepper.js.map +1 -1
  300. package/dist/ui/switch.js +2 -2
  301. package/dist/ui/switch.js.map +1 -1
  302. package/dist/ui/tabs.js +3 -3
  303. package/dist/ui/tabs.js.map +1 -1
  304. package/dist/ui/text.d.ts +7 -2
  305. package/dist/ui/text.d.ts.map +1 -1
  306. package/dist/ui/text.js +2 -1
  307. package/dist/ui/text.js.map +1 -1
  308. package/dist/ui/textarea.js +1 -1
  309. package/dist/ui/textarea.js.map +1 -1
  310. package/dist/ui/toast.js +8 -8
  311. package/dist/ui/toast.js.map +1 -1
  312. package/dist/ui/toaster.d.ts +11 -2
  313. package/dist/ui/toaster.d.ts.map +1 -1
  314. package/dist/ui/toaster.js.map +1 -1
  315. package/dist/ui/toggle.js +1 -1
  316. package/dist/ui/toggle.js.map +1 -1
  317. package/dist/ui/tooltip.js +12 -12
  318. package/dist/ui/tooltip.js.map +1 -1
  319. package/dist/ui/tree-view/tree-item.d.ts +3 -2
  320. package/dist/ui/tree-view/tree-item.d.ts.map +1 -1
  321. package/dist/ui/tree-view/use-tree.d.ts +2 -1
  322. package/dist/ui/tree-view/use-tree.d.ts.map +1 -1
  323. package/docs/components/_header.md +90 -1
  324. package/docs/components/ui/oauth-button.md +86 -0
  325. package/docs/recipes/customize-brand.md +100 -4
  326. package/docs/recipes/index.md +5 -1
  327. package/docs/recipes/install-astro.md +15 -0
  328. package/docs/recipes/install-next-app-router.md +21 -5
  329. package/docs/recipes/install-next-pages.md +2 -0
  330. package/docs/recipes/install-remix.md +15 -0
  331. package/docs/recipes/install-tanstack-start.md +15 -0
  332. package/docs/recipes/install-vite.md +15 -0
  333. package/docs/recipes/troubleshoot.md +22 -0
  334. package/llms-full.txt +177 -2
  335. package/llms-quick.txt +247 -0
  336. package/llms.txt +116 -3
  337. package/package.json +80 -2
  338. package/scripts/welcome.mjs +219 -0
  339. package/skill/README.md +99 -0
  340. package/skill/SKILL.md +163 -0
  341. package/skill/install.sh +59 -0
  342. package/skill/references/components-full.md +7083 -0
  343. package/skill/references/components.md +778 -0
  344. package/skill/references/customize-brand.md +314 -0
  345. package/skill/references/server-components.md +211 -0
  346. package/skill/references/setup-astro.md +195 -0
  347. package/skill/references/setup-next-app-router.md +248 -0
  348. package/skill/references/setup-next-pages.md +127 -0
  349. package/skill/references/setup-remix.md +188 -0
  350. package/skill/references/setup-tanstack-start.md +160 -0
  351. package/skill/references/setup-vite.md +187 -0
  352. package/skill/references/troubleshoot.md +241 -0
  353. package/dist/_chunks/date-picker.js +0 -748
  354. package/dist/_chunks/date-picker.js.map +0 -1
  355. package/dist/_chunks/file-preview.js +0 -499
  356. package/dist/_chunks/file-preview.js.map +0 -1
  357. package/dist/_chunks/rich-chat-input.js +0 -2071
  358. package/dist/_chunks/rich-chat-input.js.map +0 -1
  359. package/dist/_chunks/text.js.map +0 -1
  360. package/dist/ui/charts/index.js.map +0 -1
  361. /package/{LICENSE → skill/LICENSE} +0 -0
@@ -1,272 +1,44 @@
1
1
  "use client";
2
2
  import { cn as e } from "../ui/lib/utils.js";
3
3
  import { Icon as t } from "../ui/icon.js";
4
- import { emojiDataLoaders as n } from "../composed/emoji-picker.js";
5
- import { _ as r, f as i, g as a, p as o, u as s, v as c, y as l } from "./tiptap.js";
6
- import * as u from "react";
7
- import { jsx as d, jsxs as f } from "react/jsx-runtime";
8
- import { IconDownload as p, IconFile as m } from "@tabler/icons-react";
9
- import { createRoot as h } from "react-dom/client";
10
- //#region src/composed/extensions/emoji-data.ts
11
- var g = (e) => `https://cdn.jsdelivr.net/npm/emoji-datasource-${e}@15.0.1/img/${e}/sheets-256/64.png`, _ = null, v = null;
12
- async function y(e) {
13
- if (_ === e && v) return v;
14
- let t = await (n[e] ?? n.native)();
15
- return v = t.default ?? t, _ = e, v;
16
- }
17
- function b(e, t) {
18
- let n = e.emojis[t];
19
- if (!n) return null;
20
- let r = n.skins[0];
21
- return r ? {
22
- id: n.id,
23
- name: n.name,
24
- native: r.native,
25
- x: r.x ?? 0,
26
- y: r.y ?? 0
27
- } : null;
28
- }
29
- function x(e, t, n = 8) {
30
- let r = Object.values(e.emojis);
31
- if (!t) return r.slice(0, n).map((e) => ({
32
- id: e.id,
33
- name: e.name,
34
- native: e.skins[0]?.native ?? "",
35
- x: e.skins[0]?.x ?? 0,
36
- y: e.skins[0]?.y ?? 0
37
- }));
38
- let i = t.toLowerCase(), a = [];
39
- for (let e of r) {
40
- if (a.length >= n) break;
41
- (e.id.includes(i) || e.name.toLowerCase().includes(i) || e.keywords?.some((e) => e.includes(i))) && a.push({
42
- id: e.id,
43
- name: e.name,
44
- native: e.skins[0]?.native ?? "",
45
- x: e.skins[0]?.x ?? 0,
46
- y: e.skins[0]?.y ?? 0
47
- });
48
- }
49
- return a;
50
- }
51
- //#endregion
52
- //#region src/composed/extensions/emoji-node.tsx
53
- function S({ node: e }) {
54
- let { native: t, set: n, x: r, y: a } = e.attrs;
55
- if (n === "native") return /* @__PURE__ */ d(i, {
56
- as: "span",
57
- className: "inline",
58
- children: /* @__PURE__ */ d("span", { children: t })
59
- });
60
- let o = `${100 / 60 * r}% ${100 / 60 * a}%`;
61
- return /* @__PURE__ */ d(i, {
62
- as: "span",
63
- className: "inline",
64
- children: /* @__PURE__ */ d("span", {
65
- role: "img",
66
- "aria-label": t,
67
- className: "inline-block h-[1.2em] w-[1.2em] align-text-bottom",
68
- style: {
69
- backgroundImage: `url(${g(n)})`,
70
- backgroundSize: "6100% 6100%",
71
- backgroundPosition: o
72
- }
73
- })
74
- });
75
- }
76
- var C = r.create({
77
- name: "emojiNode",
78
- group: "inline",
79
- inline: !0,
80
- atom: !0,
81
- selectable: !1,
82
- addAttributes() {
83
- return {
84
- id: { default: null },
85
- native: { default: null },
86
- set: { default: "native" },
87
- x: { default: 0 },
88
- y: { default: 0 }
89
- };
90
- },
91
- renderText({ node: e }) {
92
- return e.attrs.native ?? "";
93
- },
94
- parseHTML() {
95
- return [{
96
- tag: "span[data-emoji-id]",
97
- getAttrs: (e) => {
98
- let t = e;
99
- return {
100
- id: t.getAttribute("data-emoji-id"),
101
- set: t.getAttribute("data-emoji-set") ?? "native",
102
- x: parseInt(t.getAttribute("data-emoji-x") ?? "0", 10),
103
- y: parseInt(t.getAttribute("data-emoji-y") ?? "0", 10),
104
- native: t.textContent ?? ""
105
- };
106
- }
107
- }];
108
- },
109
- renderHTML({ node: e }) {
110
- return [
111
- "span",
112
- {
113
- "data-emoji-id": e.attrs.id,
114
- "data-emoji-set": e.attrs.set,
115
- "data-emoji-x": e.attrs.x,
116
- "data-emoji-y": e.attrs.y,
117
- role: "img",
118
- "aria-label": e.attrs.native
119
- },
120
- e.attrs.native ?? ""
121
- ];
122
- },
123
- addNodeView() {
124
- return o(S);
125
- }
126
- });
127
- //#endregion
128
- //#region src/composed/extensions/emoji-suggestion.tsx
129
- function w({ emoji: e, set: t, size: n = "1.2em" }) {
130
- return t === "native" ? /* @__PURE__ */ d("span", {
131
- style: { fontSize: n },
132
- children: e.native
133
- }) : /* @__PURE__ */ d("span", {
134
- role: "img",
135
- "aria-label": e.native,
136
- className: "inline-block",
137
- style: {
138
- width: n,
139
- height: n,
140
- backgroundImage: `url(${g(t)})`,
141
- backgroundSize: "6100% 6100%",
142
- backgroundPosition: `${100 / 60 * e.x}% ${100 / 60 * e.y}%`
143
- }
144
- });
145
- }
146
- var T = u.forwardRef(({ items: t, set: n, command: r }, i) => {
147
- let [a, o] = u.useState(0);
148
- return u.useEffect(() => o(0), [t]), u.useImperativeHandle(i, () => ({ onKeyDown: ({ event: e }) => e.key === "ArrowUp" ? (o((e) => (e + t.length - 1) % t.length), !0) : e.key === "ArrowDown" ? (o((e) => (e + 1) % t.length), !0) : e.key === "Enter" ? (t[a] && r(t[a]), !0) : !1 })), t.length ? /* @__PURE__ */ d("div", {
149
- role: "listbox",
150
- "aria-label": "Emoji suggestions",
151
- className: "z-popover max-h-[200px] overflow-x-hidden overflow-y-auto rounded-ds-md border border-surface-border-strong bg-surface-overlay shadow-raised-hover",
152
- children: t.map((t, i) => /* @__PURE__ */ f("button", {
153
- type: "button",
154
- role: "option",
155
- "aria-selected": i === a,
156
- onClick: () => r(t),
157
- className: e("flex w-full items-center gap-ds-03 px-ds-04 py-ds-02b text-left text-ds-sm", i === a ? "bg-surface-raised text-surface-fg" : "text-surface-fg-muted hover:bg-surface-raised"),
158
- children: [/* @__PURE__ */ d(w, {
159
- emoji: t,
160
- set: n,
161
- size: "1.25em"
162
- }), /* @__PURE__ */ f("span", {
163
- className: "truncate",
164
- children: [
165
- ":",
166
- t.id,
167
- ":"
168
- ]
169
- })]
170
- }, t.id))
171
- }) : null;
172
- });
173
- T.displayName = "EmojiList";
174
- function E(e) {
175
- return () => {
176
- let t = null, n = null, r = null;
177
- return {
178
- onStart: (i) => {
179
- n = document.createElement("div"), n.style.position = "absolute", n.style.zIndex = "1400";
180
- let a = i.clientRect?.();
181
- a && (n.style.left = `${a.left}px`, n.style.top = `${a.bottom + 4}px`), document.body.appendChild(n), t = h(n), t.render(/* @__PURE__ */ d(T, {
182
- ref: (e) => {
183
- r = e;
184
- },
185
- items: i.items,
186
- set: e,
187
- command: (e) => i.command(e)
188
- }));
189
- },
190
- onUpdate: (i) => {
191
- if (!t || !n) return;
192
- let a = i.clientRect?.();
193
- a && (n.style.left = `${a.left}px`, n.style.top = `${a.bottom + 4}px`), t.render(/* @__PURE__ */ d(T, {
194
- ref: (e) => {
195
- r = e;
196
- },
197
- items: i.items,
198
- set: e,
199
- command: (e) => i.command(e)
200
- }));
201
- },
202
- onKeyDown: (e) => e.event.key === "Escape" ? (n && (t?.unmount(), n.remove(), n = null, t = null), !0) : r?.onKeyDown(e) ?? !1,
203
- onExit: () => {
204
- n && (t?.unmount(), n.remove(), n = null, t = null);
205
- }
206
- };
207
- };
208
- }
209
- function D(e = "native") {
210
- return a.create({
211
- name: "emojiSuggestion",
212
- addProseMirrorPlugins() {
213
- return [s({
214
- pluginKey: new l("emojiSuggestion"),
215
- editor: this.editor,
216
- char: ":",
217
- items: async ({ query: t }) => x(await y(e), t, 8),
218
- command: ({ editor: t, range: n, props: r }) => {
219
- let i = r;
220
- t.chain().focus().deleteRange(n).insertContent({
221
- type: "emojiNode",
222
- attrs: {
223
- id: i.id,
224
- native: i.native,
225
- set: e,
226
- x: i.x,
227
- y: i.y
228
- }
229
- }).run();
230
- },
231
- render: E(e)
232
- })];
233
- }
234
- });
235
- }
236
- //#endregion
4
+ import { _ as n, o as r, s as i, v as a } from "./tiptap.js";
5
+ import * as o from "react";
6
+ import { jsx as s, jsxs as c } from "react/jsx-runtime";
7
+ import { IconDownload as l, IconFile as u } from "@tabler/icons-react";
8
+ import { createRoot as d } from "react-dom/client";
237
9
  //#region src/composed/extensions/file-attachment.tsx
238
- function O(e) {
10
+ function f(e) {
239
11
  return e < 1024 ? `${e} B` : e < 1024 * 1024 ? `${(e / 1024).toFixed(1)} KB` : `${(e / (1024 * 1024)).toFixed(1)} MB`;
240
12
  }
241
- function k({ node: e }) {
242
- return /* @__PURE__ */ d(i, {
13
+ function p({ node: e }) {
14
+ return /* @__PURE__ */ s(r, {
243
15
  className: "my-ds-02",
244
- children: /* @__PURE__ */ f("a", {
16
+ children: /* @__PURE__ */ c("a", {
245
17
  href: /^https?:\/\//.test(e.attrs.url) ? e.attrs.url : "#",
246
18
  target: "_blank",
247
19
  rel: "noopener noreferrer",
248
- className: "inline-flex items-center gap-ds-03 rounded-ds-md border border-surface-border-strong bg-surface-raised px-ds-04 py-ds-03 text-ds-sm text-surface-fg transition-colors hover:border-surface-border-strong hover:bg-surface-raised-hover",
20
+ className: "inline-flex items-center gap-ds-03 rounded-control border border-surface-border-strong bg-surface-raised px-ds-04 py-ds-03 text-ds-sm text-surface-fg transition-colors hover:border-surface-border-strong hover:bg-surface-raised-hover",
249
21
  contentEditable: !1,
250
22
  children: [
251
- /* @__PURE__ */ d(t, {
252
- icon: m,
23
+ /* @__PURE__ */ s(t, {
24
+ icon: u,
253
25
  size: "sm",
254
26
  className: "shrink-0 text-surface-fg-subtle"
255
27
  }),
256
- /* @__PURE__ */ d("span", {
28
+ /* @__PURE__ */ s("span", {
257
29
  className: "truncate",
258
30
  children: e.attrs.name
259
31
  }),
260
- /* @__PURE__ */ f("span", {
32
+ /* @__PURE__ */ c("span", {
261
33
  className: "shrink-0 text-surface-fg-subtle",
262
34
  children: [
263
35
  "(",
264
- O(e.attrs.size),
36
+ f(e.attrs.size),
265
37
  ")"
266
38
  ]
267
39
  }),
268
- /* @__PURE__ */ d(t, {
269
- icon: p,
40
+ /* @__PURE__ */ s(t, {
41
+ icon: l,
270
42
  size: "sm",
271
43
  className: "shrink-0 text-surface-fg-subtle"
272
44
  })
@@ -274,7 +46,7 @@ function k({ node: e }) {
274
46
  })
275
47
  });
276
48
  }
277
- var A = r.create({
49
+ var m = n.create({
278
50
  name: "fileAttachment",
279
51
  group: "block",
280
52
  atom: !0,
@@ -289,43 +61,43 @@ var A = r.create({
289
61
  return [{ tag: "div[data-file-attachment]" }];
290
62
  },
291
63
  renderHTML({ HTMLAttributes: e }) {
292
- return ["div", c({ "data-file-attachment": "" }, e)];
64
+ return ["div", a({ "data-file-attachment": "" }, e)];
293
65
  },
294
66
  addNodeView() {
295
- return o(k);
67
+ return i(p);
296
68
  }
297
- }), j = u.forwardRef(({ items: t, command: n }, r) => {
298
- let [i, a] = u.useState(0);
299
- return u.useEffect(() => a(0), [t]), u.useImperativeHandle(r, () => ({ onKeyDown: ({ event: e }) => e.key === "ArrowUp" ? (a((e) => (e + t.length - 1) % t.length), !0) : e.key === "ArrowDown" ? (a((e) => (e + 1) % t.length), !0) : e.key === "Enter" ? (t[i] && n(t[i]), !0) : !1 })), t.length ? /* @__PURE__ */ d("div", {
69
+ }), h = o.forwardRef(({ items: t, command: n }, r) => {
70
+ let [i, a] = o.useState(0);
71
+ return o.useEffect(() => a(0), [t]), o.useImperativeHandle(r, () => ({ onKeyDown: ({ event: e }) => e.key === "ArrowUp" ? (a((e) => (e + t.length - 1) % t.length), !0) : e.key === "ArrowDown" ? (a((e) => (e + 1) % t.length), !0) : e.key === "Enter" ? (t[i] && n(t[i]), !0) : !1 })), t.length ? /* @__PURE__ */ s("div", {
300
72
  role: "listbox",
301
73
  "aria-label": "Mention suggestions",
302
- className: "z-popover overflow-hidden rounded-ds-md border border-surface-border-strong bg-surface-overlay shadow-raised-hover",
303
- children: t.map((t, r) => /* @__PURE__ */ f("button", {
74
+ className: "z-popover overflow-hidden rounded-control border border-surface-border-strong bg-surface-overlay shadow-raised-hover",
75
+ children: t.map((t, r) => /* @__PURE__ */ c("button", {
304
76
  type: "button",
305
77
  role: "option",
306
78
  "aria-selected": r === i,
307
79
  onClick: () => n(t),
308
80
  className: e("flex w-full items-center gap-ds-03 px-ds-04 py-ds-02b text-left text-ds-sm", r === i ? "bg-surface-raised text-surface-fg" : "text-surface-fg-muted hover:bg-surface-raised"),
309
- children: [t.avatar ? /* @__PURE__ */ d("img", {
81
+ children: [t.avatar ? /* @__PURE__ */ s("img", {
310
82
  src: t.avatar,
311
83
  alt: "",
312
- className: "h-ico-md w-ico-md rounded-ds-full object-cover"
313
- }) : /* @__PURE__ */ d("span", {
314
- className: "flex h-ico-md w-ico-md items-center justify-center rounded-ds-full bg-accent-2 text-[10px] font-semibold text-accent-11",
84
+ className: "h-ico-md w-ico-md rounded-pill object-cover"
85
+ }) : /* @__PURE__ */ s("span", {
86
+ className: "flex h-ico-md w-ico-md items-center justify-center rounded-pill bg-accent-2 text-[10px] font-semibold text-accent-11",
315
87
  children: t.label.charAt(0).toUpperCase()
316
- }), /* @__PURE__ */ d("span", { children: t.label })]
88
+ }), /* @__PURE__ */ s("span", { children: t.label })]
317
89
  }, t.id))
318
90
  }) : null;
319
91
  });
320
- j.displayName = "MentionList";
321
- function M(e) {
92
+ h.displayName = "MentionList";
93
+ function g(e) {
322
94
  return () => {
323
95
  let t = null, n = null, r = null;
324
96
  return {
325
97
  onStart: (i) => {
326
98
  n = document.createElement("div"), n.style.position = "absolute", n.style.zIndex = "1400";
327
99
  let a = i.clientRect?.();
328
- a && (n.style.left = `${a.left}px`, n.style.top = `${a.bottom + 4}px`), document.body.appendChild(n), t = h(n), t.render(/* @__PURE__ */ d(j, {
100
+ a && (n.style.left = `${a.left}px`, n.style.top = `${a.bottom + 4}px`), document.body.appendChild(n), t = d(n), t.render(/* @__PURE__ */ s(h, {
329
101
  ref: (e) => {
330
102
  r = e;
331
103
  },
@@ -341,7 +113,7 @@ function M(e) {
341
113
  onUpdate: (i) => {
342
114
  if (!t || !n) return;
343
115
  let a = i.clientRect?.();
344
- a && (n.style.left = `${a.left}px`, n.style.top = `${a.bottom + 4}px`), t.render(/* @__PURE__ */ d(j, {
116
+ a && (n.style.left = `${a.left}px`, n.style.top = `${a.bottom + 4}px`), t.render(/* @__PURE__ */ s(h, {
345
117
  ref: (e) => {
346
118
  r = e;
347
119
  },
@@ -362,4 +134,4 @@ function M(e) {
362
134
  };
363
135
  }
364
136
  //#endregion
365
- export { y as a, C as i, A as n, b as o, D as r, M as t };
137
+ export { m as n, g as t };
@@ -1 +1 @@
1
- {"version":3,"file":"mention-suggestion.js","names":[],"sources":["../../src/composed/extensions/emoji-data.ts","../../src/composed/extensions/emoji-node.tsx","../../src/composed/extensions/emoji-suggestion.tsx","../../src/composed/extensions/file-attachment.tsx","../../src/composed/extensions/mention-suggestion.tsx"],"sourcesContent":["import { emojiDataLoaders } from '../emoji-picker'\n\n// Spritesheet constants — must match emoji-mart's rendering (emoji-datasource v15.0.1)\nexport const SPRITESHEET_URL = (set: string) =>\n `https://cdn.jsdelivr.net/npm/emoji-datasource-${set}@15.0.1/img/${set}/sheets-256/64.png`\nexport const SHEET_COLS = 61\nexport const SHEET_ROWS = 61\n\ninterface EmojiSkin {\n unified: string\n native: string\n x?: number\n y?: number\n}\n\ninterface EmojiEntry {\n id: string\n name: string\n keywords?: string[]\n skins: EmojiSkin[]\n}\n\nexport interface EmojiDataset {\n emojis: Record<string, EmojiEntry>\n sheet?: { cols: number; rows: number }\n}\n\nexport interface ResolvedEmoji {\n id: string\n name: string\n native: string\n x: number\n y: number\n}\n\nlet cachedSet: string | null = null\nlet cachedData: EmojiDataset | null = null\n\nexport async function loadEmojiData(set: string): Promise<EmojiDataset> {\n if (cachedSet === set && cachedData) return cachedData\n const loader = emojiDataLoaders[set] ?? emojiDataLoaders.native\n const mod = await loader()\n cachedData = (mod.default ?? mod) as EmojiDataset\n cachedSet = set\n return cachedData\n}\n\nexport function lookupEmoji(data: EmojiDataset, id: string): ResolvedEmoji | null {\n const entry = data.emojis[id]\n if (!entry) return null\n const skin = entry.skins[0]\n if (!skin) return null\n return {\n id: entry.id,\n name: entry.name,\n native: skin.native,\n x: skin.x ?? 0,\n y: skin.y ?? 0,\n }\n}\n\nexport function searchEmoji(data: EmojiDataset, query: string, limit = 8): ResolvedEmoji[] {\n const entries = Object.values(data.emojis)\n if (!query) {\n return entries.slice(0, limit).map((e) => ({\n id: e.id,\n name: e.name,\n native: e.skins[0]?.native ?? '',\n x: e.skins[0]?.x ?? 0,\n y: e.skins[0]?.y ?? 0,\n }))\n }\n const q = query.toLowerCase()\n const results: ResolvedEmoji[] = []\n for (const e of entries) {\n if (results.length >= limit) break\n if (\n e.id.includes(q) ||\n e.name.toLowerCase().includes(q) ||\n e.keywords?.some((k) => k.includes(q))\n ) {\n results.push({\n id: e.id,\n name: e.name,\n native: e.skins[0]?.native ?? '',\n x: e.skins[0]?.x ?? 0,\n y: e.skins[0]?.y ?? 0,\n })\n }\n }\n return results\n}\n","import { Node } from '@tiptap/core'\nimport { type NodeViewProps,NodeViewWrapper, ReactNodeViewRenderer } from '@tiptap/react'\n\nimport { SHEET_COLS, SHEET_ROWS,SPRITESHEET_URL } from './emoji-data'\n\nexport interface EmojiNodeAttrs {\n id: string\n native: string\n set: string\n x: number\n y: number\n}\n\nfunction EmojiNodeView({ node }: NodeViewProps) {\n const { native, set, x, y } = node.attrs as EmojiNodeAttrs\n\n if (set === 'native') {\n return (\n <NodeViewWrapper as=\"span\" className=\"inline\">\n <span>{native}</span>\n </NodeViewWrapper>\n )\n }\n\n const bgSize = `${100 * SHEET_COLS}% ${100 * SHEET_ROWS}%`\n const bgPos = `${(100 / (SHEET_COLS - 1)) * x}% ${(100 / (SHEET_ROWS - 1)) * y}%`\n\n return (\n <NodeViewWrapper as=\"span\" className=\"inline\">\n <span\n role=\"img\"\n aria-label={native}\n className=\"inline-block h-[1.2em] w-[1.2em] align-text-bottom\"\n style={{\n backgroundImage: `url(${SPRITESHEET_URL(set)})`,\n backgroundSize: bgSize,\n backgroundPosition: bgPos,\n }}\n />\n </NodeViewWrapper>\n )\n}\n\nexport const EmojiNode = Node.create({\n name: 'emojiNode',\n group: 'inline',\n inline: true,\n atom: true,\n selectable: false,\n\n addAttributes() {\n return {\n id: { default: null },\n native: { default: null },\n set: { default: 'native' },\n x: { default: 0 },\n y: { default: 0 },\n }\n },\n\n renderText({ node }) {\n return node.attrs.native ?? ''\n },\n\n parseHTML() {\n return [{\n tag: 'span[data-emoji-id]',\n getAttrs: (el) => {\n const dom = el as HTMLElement\n return {\n id: dom.getAttribute('data-emoji-id'),\n set: dom.getAttribute('data-emoji-set') ?? 'native',\n x: parseInt(dom.getAttribute('data-emoji-x') ?? '0', 10),\n y: parseInt(dom.getAttribute('data-emoji-y') ?? '0', 10),\n native: dom.textContent ?? '',\n }\n },\n }]\n },\n\n renderHTML({ node }) {\n return ['span', {\n 'data-emoji-id': node.attrs.id,\n 'data-emoji-set': node.attrs.set,\n 'data-emoji-x': node.attrs.x,\n 'data-emoji-y': node.attrs.y,\n 'role': 'img',\n 'aria-label': node.attrs.native,\n }, node.attrs.native ?? '']\n },\n\n addNodeView() {\n return ReactNodeViewRenderer(EmojiNodeView)\n },\n})\n","import { Extension } from '@tiptap/core'\nimport Suggestion, { type SuggestionKeyDownProps,type SuggestionProps } from '@tiptap/suggestion'\nimport { PluginKey } from 'prosemirror-state'\nimport * as React from 'react'\nimport { createRoot, type Root } from 'react-dom/client'\n\nimport { cn } from '../../ui/lib/utils'\nimport { loadEmojiData, type ResolvedEmoji, searchEmoji, SHEET_COLS, SHEET_ROWS,SPRITESHEET_URL } from './emoji-data'\n\n// Re-export for external consumers\nexport type { ResolvedEmoji as EmojiSuggestionItem }\n\nfunction EmojiImage({ emoji, set, size = '1.2em' }: { emoji: ResolvedEmoji; set: string; size?: string }) {\n if (set === 'native') {\n return <span style={{ fontSize: size }}>{emoji.native}</span>\n }\n return (\n <span\n role=\"img\"\n aria-label={emoji.native}\n className=\"inline-block\"\n style={{\n width: size,\n height: size,\n backgroundImage: `url(${SPRITESHEET_URL(set)})`,\n backgroundSize: `${100 * SHEET_COLS}% ${100 * SHEET_ROWS}%`,\n backgroundPosition: `${(100 / (SHEET_COLS - 1)) * emoji.x}% ${(100 / (SHEET_ROWS - 1)) * emoji.y}%`,\n }}\n />\n )\n}\n\ninterface EmojiListRef {\n onKeyDown: (props: SuggestionKeyDownProps) => boolean\n}\n\ninterface EmojiListProps {\n items: ResolvedEmoji[]\n set: string\n command: (item: ResolvedEmoji) => void\n}\n\nconst EmojiList = React.forwardRef<EmojiListRef, EmojiListProps>(\n ({ items, set, command }, ref) => {\n const [selectedIndex, setSelectedIndex] = React.useState(0)\n\n React.useEffect(() => setSelectedIndex(0), [items])\n\n React.useImperativeHandle(ref, () => ({\n onKeyDown: ({ event }: SuggestionKeyDownProps) => {\n if (event.key === 'ArrowUp') {\n setSelectedIndex((i) => (i + items.length - 1) % items.length)\n return true\n }\n if (event.key === 'ArrowDown') {\n setSelectedIndex((i) => (i + 1) % items.length)\n return true\n }\n if (event.key === 'Enter') {\n if (items[selectedIndex]) command(items[selectedIndex])\n return true\n }\n return false\n },\n }))\n\n if (!items.length) return null\n\n return (\n <div role=\"listbox\" aria-label=\"Emoji suggestions\" className=\"z-popover max-h-[200px] overflow-x-hidden overflow-y-auto rounded-ds-md border border-surface-border-strong bg-surface-overlay shadow-raised-hover\">\n {items.map((item, index) => (\n <button\n key={item.id}\n type=\"button\"\n role=\"option\"\n aria-selected={index === selectedIndex}\n onClick={() => command(item)}\n className={cn(\n 'flex w-full items-center gap-ds-03 px-ds-04 py-ds-02b text-left text-ds-sm',\n index === selectedIndex ? 'bg-surface-raised text-surface-fg' : 'text-surface-fg-muted hover:bg-surface-raised',\n )}\n >\n <EmojiImage emoji={item} set={set} size=\"1.25em\" />\n <span className=\"truncate\">:{item.id}:</span>\n </button>\n ))}\n </div>\n )\n },\n)\nEmojiList.displayName = 'EmojiList'\n\nfunction createEmojiSuggestionRenderer(set: string) {\n return () => {\n let root: Root | null = null\n let container: HTMLDivElement | null = null\n let componentRef: EmojiListRef | null = null\n\n return {\n onStart: (props: SuggestionProps<ResolvedEmoji>) => {\n container = document.createElement('div')\n container.style.position = 'absolute'\n container.style.zIndex = '1400'\n const rect = props.clientRect?.()\n if (rect) {\n container.style.left = `${rect.left}px`\n container.style.top = `${rect.bottom + 4}px`\n }\n document.body.appendChild(container)\n root = createRoot(container)\n root.render(\n <EmojiList\n ref={(r) => { componentRef = r }}\n items={props.items as ResolvedEmoji[]}\n set={set}\n command={(item) => props.command(item)}\n />,\n )\n },\n\n onUpdate: (props: SuggestionProps<ResolvedEmoji>) => {\n if (!root || !container) return\n const rect = props.clientRect?.()\n if (rect) {\n container.style.left = `${rect.left}px`\n container.style.top = `${rect.bottom + 4}px`\n }\n root.render(\n <EmojiList\n ref={(r) => { componentRef = r }}\n items={props.items as ResolvedEmoji[]}\n set={set}\n command={(item) => props.command(item)}\n />,\n )\n },\n\n onKeyDown: (props: SuggestionKeyDownProps) => {\n if (props.event.key === 'Escape') {\n if (container) {\n root?.unmount()\n container.remove()\n container = null\n root = null\n }\n return true\n }\n return componentRef?.onKeyDown(props) ?? false\n },\n\n onExit: () => {\n if (container) {\n root?.unmount()\n container.remove()\n container = null\n root = null\n }\n },\n }\n }\n}\n\n/** Factory: call with the emoji set to get a configured extension. */\nexport function createEmojiSuggestion(set = 'native') {\n return Extension.create({\n name: 'emojiSuggestion',\n\n addProseMirrorPlugins() {\n return [\n Suggestion({\n pluginKey: new PluginKey('emojiSuggestion'),\n editor: this.editor,\n char: ':',\n items: async ({ query }) => {\n const data = await loadEmojiData(set)\n return searchEmoji(data, query, 8)\n },\n command: ({ editor, range, props: item }) => {\n const emoji = item as ResolvedEmoji\n editor\n .chain()\n .focus()\n .deleteRange(range)\n .insertContent({\n type: 'emojiNode',\n attrs: { id: emoji.id, native: emoji.native, set, x: emoji.x, y: emoji.y },\n })\n .run()\n },\n render: createEmojiSuggestionRenderer(set),\n }),\n ]\n },\n })\n}\n","import { IconDownload,IconFile } from '@tabler/icons-react'\nimport { mergeAttributes,Node } from '@tiptap/core'\nimport { type NodeViewProps,NodeViewWrapper, ReactNodeViewRenderer } from '@tiptap/react'\n\nimport { Icon } from '../../ui/icon'\n\nfunction formatFileSize(bytes: number): string {\n if (bytes < 1024) return `${bytes} B`\n if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`\n return `${(bytes / (1024 * 1024)).toFixed(1)} MB`\n}\n\nfunction FileAttachmentView({ node }: NodeViewProps) {\n const safeUrl = /^https?:\\/\\//.test(node.attrs.url) ? node.attrs.url : '#'\n return (\n <NodeViewWrapper className=\"my-ds-02\">\n <a\n href={safeUrl}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"inline-flex items-center gap-ds-03 rounded-ds-md border border-surface-border-strong bg-surface-raised px-ds-04 py-ds-03 text-ds-sm text-surface-fg transition-colors hover:border-surface-border-strong hover:bg-surface-raised-hover\"\n contentEditable={false}\n >\n <Icon icon={IconFile} size=\"sm\" className=\"shrink-0 text-surface-fg-subtle\" />\n <span className=\"truncate\">{node.attrs.name}</span>\n <span className=\"shrink-0 text-surface-fg-subtle\">({formatFileSize(node.attrs.size)})</span>\n <Icon icon={IconDownload} size=\"sm\" className=\"shrink-0 text-surface-fg-subtle\" />\n </a>\n </NodeViewWrapper>\n )\n}\n\nexport const FileAttachment = Node.create({\n name: 'fileAttachment',\n group: 'block',\n atom: true,\n\n addAttributes() {\n return {\n url: { default: null },\n name: { default: 'Untitled' },\n size: { default: 0 },\n }\n },\n\n parseHTML() {\n return [{ tag: 'div[data-file-attachment]' }]\n },\n\n renderHTML({ HTMLAttributes }) {\n return ['div', mergeAttributes({ 'data-file-attachment': '' }, HTMLAttributes)]\n },\n\n addNodeView() {\n return ReactNodeViewRenderer(FileAttachmentView)\n },\n})\n","import type { SuggestionKeyDownProps,SuggestionProps } from '@tiptap/suggestion'\nimport * as React from 'react'\nimport { createRoot, type Root } from 'react-dom/client'\n\nimport { cn } from '../../ui/lib/utils'\nimport type { MentionItem } from '../rich-text-editor'\n\ninterface MentionListRef {\n onKeyDown: (props: SuggestionKeyDownProps) => boolean\n}\n\ninterface MentionListProps {\n items: MentionItem[]\n command: (item: MentionItem) => void\n}\n\nconst MentionList = React.forwardRef<MentionListRef, MentionListProps>(\n ({ items, command }, ref) => {\n const [selectedIndex, setSelectedIndex] = React.useState(0)\n\n React.useEffect(() => setSelectedIndex(0), [items])\n\n React.useImperativeHandle(ref, () => ({\n onKeyDown: ({ event }: SuggestionKeyDownProps) => {\n if (event.key === 'ArrowUp') {\n setSelectedIndex((i) => (i + items.length - 1) % items.length)\n return true\n }\n if (event.key === 'ArrowDown') {\n setSelectedIndex((i) => (i + 1) % items.length)\n return true\n }\n if (event.key === 'Enter') {\n if (items[selectedIndex]) command(items[selectedIndex])\n return true\n }\n return false\n },\n }))\n\n if (!items.length) return null\n\n return (\n <div role=\"listbox\" aria-label=\"Mention suggestions\" className=\"z-popover overflow-hidden rounded-ds-md border border-surface-border-strong bg-surface-overlay shadow-raised-hover\">\n {items.map((item, index) => (\n <button\n key={item.id}\n type=\"button\"\n role=\"option\"\n aria-selected={index === selectedIndex}\n onClick={() => command(item)}\n className={cn(\n 'flex w-full items-center gap-ds-03 px-ds-04 py-ds-02b text-left text-ds-sm',\n index === selectedIndex ? 'bg-surface-raised text-surface-fg' : 'text-surface-fg-muted hover:bg-surface-raised',\n )}\n >\n {item.avatar ? (\n <img src={item.avatar} alt=\"\" className=\"h-ico-md w-ico-md rounded-ds-full object-cover\" />\n ) : (\n <span className=\"flex h-ico-md w-ico-md items-center justify-center rounded-ds-full bg-accent-2 text-[10px] font-semibold text-accent-11\">\n {item.label.charAt(0).toUpperCase()}\n </span>\n )}\n <span>{item.label}</span>\n </button>\n ))}\n </div>\n )\n },\n)\nMentionList.displayName = 'MentionList'\n\nexport function createSuggestionRenderer(onMentionSelect?: (item: MentionItem) => void) {\n return () => {\n let root: Root | null = null\n let container: HTMLDivElement | null = null\n let componentRef: MentionListRef | null = null\n\n return {\n onStart: (props: SuggestionProps<MentionItem>) => {\n container = document.createElement('div')\n container.style.position = 'absolute'\n container.style.zIndex = '1400' // z-popover\n\n const rect = props.clientRect?.()\n if (rect) {\n container.style.left = `${rect.left}px`\n container.style.top = `${rect.bottom + 4}px`\n }\n document.body.appendChild(container)\n\n root = createRoot(container)\n root.render(\n <MentionList\n ref={(r) => { componentRef = r }}\n items={props.items as MentionItem[]}\n command={(item) => {\n props.command({ id: item.id, label: item.label })\n onMentionSelect?.(item)\n }}\n />,\n )\n },\n\n onUpdate: (props: SuggestionProps<MentionItem>) => {\n if (!root || !container) return\n\n const rect = props.clientRect?.()\n if (rect) {\n container.style.left = `${rect.left}px`\n container.style.top = `${rect.bottom + 4}px`\n }\n\n root.render(\n <MentionList\n ref={(r) => { componentRef = r }}\n items={props.items as MentionItem[]}\n command={(item) => {\n props.command({ id: item.id, label: item.label })\n onMentionSelect?.(item)\n }}\n />,\n )\n },\n\n onKeyDown: (props: SuggestionKeyDownProps) => {\n if (props.event.key === 'Escape') {\n if (container) {\n root?.unmount()\n container.remove()\n container = null\n root = null\n }\n return true\n }\n return componentRef?.onKeyDown(props) ?? false\n },\n\n onExit: () => {\n if (container) {\n root?.unmount()\n container.remove()\n container = null\n root = null\n }\n },\n }\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"mention-suggestion.js","names":[],"sources":["../../src/composed/extensions/file-attachment.tsx","../../src/composed/extensions/mention-suggestion.tsx"],"sourcesContent":["import { IconDownload,IconFile } from '@tabler/icons-react'\nimport { mergeAttributes,Node } from '@tiptap/core'\nimport { type NodeViewProps,NodeViewWrapper, ReactNodeViewRenderer } from '@tiptap/react'\n\nimport { Icon } from '../../ui/icon'\n\nfunction formatFileSize(bytes: number): string {\n if (bytes < 1024) return `${bytes} B`\n if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`\n return `${(bytes / (1024 * 1024)).toFixed(1)} MB`\n}\n\nfunction FileAttachmentView({ node }: NodeViewProps) {\n const safeUrl = /^https?:\\/\\//.test(node.attrs.url) ? node.attrs.url : '#'\n return (\n <NodeViewWrapper className=\"my-ds-02\">\n <a\n href={safeUrl}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"inline-flex items-center gap-ds-03 rounded-control border border-surface-border-strong bg-surface-raised px-ds-04 py-ds-03 text-ds-sm text-surface-fg transition-colors hover:border-surface-border-strong hover:bg-surface-raised-hover\"\n contentEditable={false}\n >\n <Icon icon={IconFile} size=\"sm\" className=\"shrink-0 text-surface-fg-subtle\" />\n <span className=\"truncate\">{node.attrs.name}</span>\n <span className=\"shrink-0 text-surface-fg-subtle\">({formatFileSize(node.attrs.size)})</span>\n <Icon icon={IconDownload} size=\"sm\" className=\"shrink-0 text-surface-fg-subtle\" />\n </a>\n </NodeViewWrapper>\n )\n}\n\nexport const FileAttachment = Node.create({\n name: 'fileAttachment',\n group: 'block',\n atom: true,\n\n addAttributes() {\n return {\n url: { default: null },\n name: { default: 'Untitled' },\n size: { default: 0 },\n }\n },\n\n parseHTML() {\n return [{ tag: 'div[data-file-attachment]' }]\n },\n\n renderHTML({ HTMLAttributes }) {\n return ['div', mergeAttributes({ 'data-file-attachment': '' }, HTMLAttributes)]\n },\n\n addNodeView() {\n return ReactNodeViewRenderer(FileAttachmentView)\n },\n})\n","import type { SuggestionKeyDownProps,SuggestionProps } from '@tiptap/suggestion'\nimport * as React from 'react'\nimport { createRoot, type Root } from 'react-dom/client'\n\nimport { cn } from '../../ui/lib/utils'\nimport type { MentionItem } from '../rich-text-editor'\n\ninterface MentionListRef {\n onKeyDown: (props: SuggestionKeyDownProps) => boolean\n}\n\ninterface MentionListProps {\n items: MentionItem[]\n command: (item: MentionItem) => void\n}\n\nconst MentionList = React.forwardRef<MentionListRef, MentionListProps>(\n ({ items, command }, ref) => {\n const [selectedIndex, setSelectedIndex] = React.useState(0)\n\n React.useEffect(() => setSelectedIndex(0), [items])\n\n React.useImperativeHandle(ref, () => ({\n onKeyDown: ({ event }: SuggestionKeyDownProps) => {\n if (event.key === 'ArrowUp') {\n setSelectedIndex((i) => (i + items.length - 1) % items.length)\n return true\n }\n if (event.key === 'ArrowDown') {\n setSelectedIndex((i) => (i + 1) % items.length)\n return true\n }\n if (event.key === 'Enter') {\n if (items[selectedIndex]) command(items[selectedIndex])\n return true\n }\n return false\n },\n }))\n\n if (!items.length) return null\n\n return (\n <div role=\"listbox\" aria-label=\"Mention suggestions\" className=\"z-popover overflow-hidden rounded-control border border-surface-border-strong bg-surface-overlay shadow-raised-hover\">\n {items.map((item, index) => (\n <button\n key={item.id}\n type=\"button\"\n role=\"option\"\n aria-selected={index === selectedIndex}\n onClick={() => command(item)}\n className={cn(\n 'flex w-full items-center gap-ds-03 px-ds-04 py-ds-02b text-left text-ds-sm',\n index === selectedIndex ? 'bg-surface-raised text-surface-fg' : 'text-surface-fg-muted hover:bg-surface-raised',\n )}\n >\n {item.avatar ? (\n <img src={item.avatar} alt=\"\" className=\"h-ico-md w-ico-md rounded-pill object-cover\" />\n ) : (\n <span className=\"flex h-ico-md w-ico-md items-center justify-center rounded-pill bg-accent-2 text-[10px] font-semibold text-accent-11\">\n {item.label.charAt(0).toUpperCase()}\n </span>\n )}\n <span>{item.label}</span>\n </button>\n ))}\n </div>\n )\n },\n)\nMentionList.displayName = 'MentionList'\n\nexport function createSuggestionRenderer(onMentionSelect?: (item: MentionItem) => void) {\n return () => {\n let root: Root | null = null\n let container: HTMLDivElement | null = null\n let componentRef: MentionListRef | null = null\n\n return {\n onStart: (props: SuggestionProps<MentionItem>) => {\n container = document.createElement('div')\n container.style.position = 'absolute'\n container.style.zIndex = '1400' // z-popover\n\n const rect = props.clientRect?.()\n if (rect) {\n container.style.left = `${rect.left}px`\n container.style.top = `${rect.bottom + 4}px`\n }\n document.body.appendChild(container)\n\n root = createRoot(container)\n root.render(\n <MentionList\n ref={(r) => { componentRef = r }}\n items={props.items as MentionItem[]}\n command={(item) => {\n props.command({ id: item.id, label: item.label })\n onMentionSelect?.(item)\n }}\n />,\n )\n },\n\n onUpdate: (props: SuggestionProps<MentionItem>) => {\n if (!root || !container) return\n\n const rect = props.clientRect?.()\n if (rect) {\n container.style.left = `${rect.left}px`\n container.style.top = `${rect.bottom + 4}px`\n }\n\n root.render(\n <MentionList\n ref={(r) => { componentRef = r }}\n items={props.items as MentionItem[]}\n command={(item) => {\n props.command({ id: item.id, label: item.label })\n onMentionSelect?.(item)\n }}\n />,\n )\n },\n\n onKeyDown: (props: SuggestionKeyDownProps) => {\n if (props.event.key === 'Escape') {\n if (container) {\n root?.unmount()\n container.remove()\n container = null\n root = null\n }\n return true\n }\n return componentRef?.onKeyDown(props) ?? false\n },\n\n onExit: () => {\n if (container) {\n root?.unmount()\n container.remove()\n container = null\n root = null\n }\n },\n }\n }\n}\n"],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ "use client";
2
+ import { Icon as e } from "../ui/icon.js";
3
+ import * as t from "react";
4
+ import { jsx as n } from "react/jsx-runtime";
5
+ //#region src/ui/lib/normalize-icon.tsx
6
+ function r(r, a) {
7
+ return r == null ? null : t.isValidElement(r) ? r : i(r) ? /* @__PURE__ */ n(e, {
8
+ icon: r,
9
+ size: a
10
+ }) : typeof r == "function" ? /* @__PURE__ */ n(r, {}) : null;
11
+ }
12
+ function i(e) {
13
+ if (typeof e != "object" || !e) return !1;
14
+ let t = e;
15
+ return typeof t.$$typeof == "symbol" && typeof t.render == "function";
16
+ }
17
+ //#endregion
18
+ export { r as t };
@@ -0,0 +1 @@
1
+ {"version":3,"file":"normalize-icon.js","names":[],"sources":["../../src/ui/lib/normalize-icon.tsx"],"sourcesContent":["// @server-safe\nimport * as React from 'react'\n\nimport { Icon } from '../icon'\nimport type { IconSize } from '../icon-context'\nimport type { IconInput } from './icon-input'\n\n/**\n * Normalize any IconInput shape into a renderable React node.\n *\n * - Component refs (`IconPlus`) → wrap in `<Icon icon={IconPlus} />` (context-aware).\n * - Already-instantiated elements (`<IconPlus />`, `<Icon …/>`, `<span>$</span>`) →\n * passed through. If inside an `<IconProvider>`, any nested `<Icon>` element\n * picks up the size + stroke from context automatically.\n * - `null` / `undefined` → returns `null`.\n *\n * Components calling this should also wrap their icon slot in\n * `<IconProvider size={defaultSize}>` so the size context propagates to\n * nested `<Icon>` elements. Example:\n *\n * ```tsx\n * import { IconProvider } from './icon-context'\n * import { normalizeIcon } from './lib/normalize-icon'\n *\n * function MyComponent({ icon, size = 'md' }: { icon?: IconInput; size?: 'sm' | 'md' | 'lg' }) {\n * return (\n * <div>\n * <IconProvider size={iconSizeMap[size]}>\n * {normalizeIcon(icon)}\n * </IconProvider>\n * </div>\n * )\n * }\n * ```\n *\n * @param input Anything matching `IconInput`.\n * @param fallbackSize Optional explicit size to apply if the input is a\n * raw component ref AND no IconProvider context is set. In practice you\n * should use IconProvider for size control; this fallback is for unusual\n * cases where the consumer can't be wrapped (e.g. portal-rendered icons).\n */\nexport function normalizeIcon(\n input: IconInput,\n fallbackSize?: IconSize,\n): React.ReactNode {\n if (input == null) return null\n\n // Already an instantiated React element — pass through. If it's our\n // `<Icon>`, the IconProvider above will populate any unset size/stroke.\n // If it's a raw Tabler element (`<IconPlus />`) or any custom node, it\n // renders as-is.\n if (React.isValidElement(input)) return input\n\n // ForwardRef component (Tabler icons + anything built with React.forwardRef).\n // Wrap in <Icon /> so it participates in IconContext (size + stroke flow\n // from any surrounding IconProvider).\n if (isForwardRefComponent(input)) {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return <Icon icon={input as any} size={fallbackSize} />\n }\n\n // Plain function/class component — render directly. The component is\n // responsible for its own sizing; we don't force <Icon> wrapping because\n // <Icon>'s type expects a ForwardRef shape and passing arbitrary props\n // would generate React warnings.\n if (typeof input === 'function') {\n const Component = input as React.ComponentType<{\n className?: string\n size?: number | string\n }>\n return <Component />\n }\n\n return null\n}\n\n/**\n * True only for `React.forwardRef`-shaped components (Tabler icons fit\n * this). React tags forwardRef objects with `$$typeof` (a symbol) and a\n * `render` function.\n */\nfunction isForwardRefComponent(value: unknown): boolean {\n if (value == null) return false\n if (typeof value !== 'object') return false\n const v = value as { $$typeof?: symbol; render?: unknown }\n return typeof v.$$typeof === 'symbol' && typeof v.render === 'function'\n}\n"],"mappings":";;;;AAyCA,SAAgB,EACd,GACA,GACiB;AA6BjB,QA5BI,KAAS,OAAa,OAMtB,EAAM,eAAe,EAAM,GAAS,IAKpC,EAAsB,EAAM,GAEvB,kBAAC,GAAD;EAAM,MAAM;EAAc,MAAM;EAAgB,CAAA,GAOrD,OAAO,KAAU,aAKZ,kBAJW,GAIX,EAAa,CAAA,GAGf;;AAQT,SAAS,EAAsB,GAAyB;AAEtD,KAAI,OAAO,KAAU,aADjB,EAC2B,QAAO;CACtC,IAAM,IAAI;AACV,QAAO,OAAO,EAAE,YAAa,YAAY,OAAO,EAAE,UAAW"}