@braedonsaunders/appkit-ui 0.2.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 (300) hide show
  1. package/LICENSE +661 -0
  2. package/README.md +11 -0
  3. package/account-menu.d.ts +49 -0
  4. package/account-menu.d.ts.map +1 -0
  5. package/account-menu.js +66 -0
  6. package/account-menu.js.map +1 -0
  7. package/alert.d.ts +13 -0
  8. package/alert.d.ts.map +1 -0
  9. package/alert.js +22 -0
  10. package/alert.js.map +1 -0
  11. package/animated-number.d.ts +13 -0
  12. package/animated-number.d.ts.map +1 -0
  13. package/animated-number.js +53 -0
  14. package/animated-number.js.map +1 -0
  15. package/api-reference.d.ts +44 -0
  16. package/api-reference.d.ts.map +1 -0
  17. package/api-reference.js +82 -0
  18. package/api-reference.js.map +1 -0
  19. package/app-shell.d.ts +39 -0
  20. package/app-shell.d.ts.map +1 -0
  21. package/app-shell.js +21 -0
  22. package/app-shell.js.map +1 -0
  23. package/app-sidebar.d.ts +22 -0
  24. package/app-sidebar.d.ts.map +1 -0
  25. package/app-sidebar.js +30 -0
  26. package/app-sidebar.js.map +1 -0
  27. package/avatar.d.ts +9 -0
  28. package/avatar.d.ts.map +1 -0
  29. package/avatar.js +18 -0
  30. package/avatar.js.map +1 -0
  31. package/badge.d.ts +9 -0
  32. package/badge.d.ts.map +1 -0
  33. package/badge.js +23 -0
  34. package/badge.js.map +1 -0
  35. package/button.d.ts +24 -0
  36. package/button.d.ts.map +1 -0
  37. package/button.js +50 -0
  38. package/button.js.map +1 -0
  39. package/card.d.ts +21 -0
  40. package/card.d.ts.map +1 -0
  41. package/card.js +36 -0
  42. package/card.js.map +1 -0
  43. package/checkbox.d.ts +4 -0
  44. package/checkbox.d.ts.map +1 -0
  45. package/checkbox.js +6 -0
  46. package/checkbox.js.map +1 -0
  47. package/confirm-dialog.d.ts +23 -0
  48. package/confirm-dialog.d.ts.map +1 -0
  49. package/confirm-dialog.js +67 -0
  50. package/confirm-dialog.js.map +1 -0
  51. package/context-menu.d.ts +47 -0
  52. package/context-menu.d.ts.map +1 -0
  53. package/context-menu.js +90 -0
  54. package/context-menu.js.map +1 -0
  55. package/dialog.d.ts +25 -0
  56. package/dialog.d.ts.map +1 -0
  57. package/dialog.js +89 -0
  58. package/dialog.js.map +1 -0
  59. package/document-title.d.ts +11 -0
  60. package/document-title.d.ts.map +1 -0
  61. package/document-title.js +17 -0
  62. package/document-title.js.map +1 -0
  63. package/drawer.d.ts +63 -0
  64. package/drawer.d.ts.map +1 -0
  65. package/drawer.js +188 -0
  66. package/drawer.js.map +1 -0
  67. package/empty-state.d.ts +10 -0
  68. package/empty-state.d.ts.map +1 -0
  69. package/empty-state.js +7 -0
  70. package/empty-state.js.map +1 -0
  71. package/file-uploader.d.ts +67 -0
  72. package/file-uploader.d.ts.map +1 -0
  73. package/file-uploader.js +156 -0
  74. package/file-uploader.js.map +1 -0
  75. package/filter-chips.d.ts +47 -0
  76. package/filter-chips.d.ts.map +1 -0
  77. package/filter-chips.js +62 -0
  78. package/filter-chips.js.map +1 -0
  79. package/global-search.d.ts +41 -0
  80. package/global-search.d.ts.map +1 -0
  81. package/global-search.js +116 -0
  82. package/global-search.js.map +1 -0
  83. package/index.d.ts +70 -0
  84. package/index.d.ts.map +1 -0
  85. package/index.js +70 -0
  86. package/index.js.map +1 -0
  87. package/input.d.ts +9 -0
  88. package/input.d.ts.map +1 -0
  89. package/input.js +11 -0
  90. package/input.js.map +1 -0
  91. package/label.d.ts +3 -0
  92. package/label.d.ts.map +1 -0
  93. package/label.js +6 -0
  94. package/label.js.map +1 -0
  95. package/line-grid.d.ts +48 -0
  96. package/line-grid.d.ts.map +1 -0
  97. package/line-grid.js +155 -0
  98. package/line-grid.js.map +1 -0
  99. package/link-context.d.ts +44 -0
  100. package/link-context.d.ts.map +1 -0
  101. package/link-context.js +32 -0
  102. package/link-context.js.map +1 -0
  103. package/list-nav.d.ts +28 -0
  104. package/list-nav.d.ts.map +1 -0
  105. package/list-nav.js +41 -0
  106. package/list-nav.js.map +1 -0
  107. package/list-pagination.d.ts +27 -0
  108. package/list-pagination.d.ts.map +1 -0
  109. package/list-pagination.js +43 -0
  110. package/list-pagination.js.map +1 -0
  111. package/list-params.d.ts +41 -0
  112. package/list-params.d.ts.map +1 -0
  113. package/list-params.js +84 -0
  114. package/list-params.js.map +1 -0
  115. package/list-search-input-state.d.ts +13 -0
  116. package/list-search-input-state.d.ts.map +1 -0
  117. package/list-search-input-state.js +27 -0
  118. package/list-search-input-state.js.map +1 -0
  119. package/list-search-input.d.ts +16 -0
  120. package/list-search-input.d.ts.map +1 -0
  121. package/list-search-input.js +51 -0
  122. package/list-search-input.js.map +1 -0
  123. package/mobile-tab-bar.d.ts +14 -0
  124. package/mobile-tab-bar.d.ts.map +1 -0
  125. package/mobile-tab-bar.js +25 -0
  126. package/mobile-tab-bar.js.map +1 -0
  127. package/multi-select.d.ts +32 -0
  128. package/multi-select.d.ts.map +1 -0
  129. package/multi-select.js +52 -0
  130. package/multi-select.js.map +1 -0
  131. package/nav-overflow.d.ts +12 -0
  132. package/nav-overflow.d.ts.map +1 -0
  133. package/nav-overflow.js +30 -0
  134. package/nav-overflow.js.map +1 -0
  135. package/navigation-config-editor.d.ts +26 -0
  136. package/navigation-config-editor.d.ts.map +1 -0
  137. package/navigation-config-editor.js +57 -0
  138. package/navigation-config-editor.js.map +1 -0
  139. package/navigation-config.d.ts +48 -0
  140. package/navigation-config.d.ts.map +1 -0
  141. package/navigation-config.js +75 -0
  142. package/navigation-config.js.map +1 -0
  143. package/navigation-mode.d.ts +16 -0
  144. package/navigation-mode.d.ts.map +1 -0
  145. package/navigation-mode.js +30 -0
  146. package/navigation-mode.js.map +1 -0
  147. package/notifications-bell.d.ts +22 -0
  148. package/notifications-bell.d.ts.map +1 -0
  149. package/notifications-bell.js +30 -0
  150. package/notifications-bell.js.map +1 -0
  151. package/org-chart.d.ts +85 -0
  152. package/org-chart.d.ts.map +1 -0
  153. package/org-chart.js +193 -0
  154. package/org-chart.js.map +1 -0
  155. package/package.json +61 -0
  156. package/page-header.d.ts +32 -0
  157. package/page-header.d.ts.map +1 -0
  158. package/page-header.js +14 -0
  159. package/page-header.js.map +1 -0
  160. package/page-layout.d.ts +29 -0
  161. package/page-layout.d.ts.map +1 -0
  162. package/page-layout.js +23 -0
  163. package/page-layout.js.map +1 -0
  164. package/page-transition.d.ts +13 -0
  165. package/page-transition.d.ts.map +1 -0
  166. package/page-transition.js +14 -0
  167. package/page-transition.js.map +1 -0
  168. package/paged-table.d.ts +54 -0
  169. package/paged-table.d.ts.map +1 -0
  170. package/paged-table.js +74 -0
  171. package/paged-table.js.map +1 -0
  172. package/popover.d.ts +16 -0
  173. package/popover.d.ts.map +1 -0
  174. package/popover.js +99 -0
  175. package/popover.js.map +1 -0
  176. package/progress.d.ts +7 -0
  177. package/progress.d.ts.map +1 -0
  178. package/progress.js +8 -0
  179. package/progress.js.map +1 -0
  180. package/prompt-dialog.d.ts +21 -0
  181. package/prompt-dialog.d.ts.map +1 -0
  182. package/prompt-dialog.js +109 -0
  183. package/prompt-dialog.js.map +1 -0
  184. package/record-list.d.ts +76 -0
  185. package/record-list.d.ts.map +1 -0
  186. package/record-list.js +51 -0
  187. package/record-list.js.map +1 -0
  188. package/search-select.d.ts +42 -0
  189. package/search-select.d.ts.map +1 -0
  190. package/search-select.js +194 -0
  191. package/search-select.js.map +1 -0
  192. package/select-options.d.ts +16 -0
  193. package/select-options.d.ts.map +1 -0
  194. package/select-options.js +119 -0
  195. package/select-options.js.map +1 -0
  196. package/select.d.ts +24 -0
  197. package/select.d.ts.map +1 -0
  198. package/select.js +65 -0
  199. package/select.js.map +1 -0
  200. package/separator.d.ts +6 -0
  201. package/separator.d.ts.map +1 -0
  202. package/separator.js +7 -0
  203. package/separator.js.map +1 -0
  204. package/settings-layout.d.ts +79 -0
  205. package/settings-layout.d.ts.map +1 -0
  206. package/settings-layout.js +74 -0
  207. package/settings-layout.js.map +1 -0
  208. package/sidebar-nav.d.ts +67 -0
  209. package/sidebar-nav.d.ts.map +1 -0
  210. package/sidebar-nav.js +291 -0
  211. package/sidebar-nav.js.map +1 -0
  212. package/signature-pad.d.ts +16 -0
  213. package/signature-pad.d.ts.map +1 -0
  214. package/signature-pad.js +355 -0
  215. package/signature-pad.js.map +1 -0
  216. package/skeleton.d.ts +9 -0
  217. package/skeleton.d.ts.map +1 -0
  218. package/skeleton.js +12 -0
  219. package/skeleton.js.map +1 -0
  220. package/slider.d.ts +13 -0
  221. package/slider.d.ts.map +1 -0
  222. package/slider.js +15 -0
  223. package/slider.js.map +1 -0
  224. package/sortable-th.d.ts +28 -0
  225. package/sortable-th.d.ts.map +1 -0
  226. package/sortable-th.js +35 -0
  227. package/sortable-th.js.map +1 -0
  228. package/sparkline.d.ts +16 -0
  229. package/sparkline.d.ts.map +1 -0
  230. package/sparkline.js +46 -0
  231. package/sparkline.js.map +1 -0
  232. package/spinner.d.ts +11 -0
  233. package/spinner.d.ts.map +1 -0
  234. package/spinner.js +11 -0
  235. package/spinner.js.map +1 -0
  236. package/styles.css +166 -0
  237. package/subtab-nav.d.ts +17 -0
  238. package/subtab-nav.d.ts.map +1 -0
  239. package/subtab-nav.js +11 -0
  240. package/subtab-nav.js.map +1 -0
  241. package/switch.d.ts +9 -0
  242. package/switch.d.ts.map +1 -0
  243. package/switch.js +11 -0
  244. package/switch.js.map +1 -0
  245. package/tab-content.d.ts +24 -0
  246. package/tab-content.d.ts.map +1 -0
  247. package/tab-content.js +26 -0
  248. package/tab-content.js.map +1 -0
  249. package/table.d.ts +28 -0
  250. package/table.d.ts.map +1 -0
  251. package/table.js +21 -0
  252. package/table.js.map +1 -0
  253. package/tabs.d.ts +18 -0
  254. package/tabs.d.ts.map +1 -0
  255. package/tabs.js +18 -0
  256. package/tabs.js.map +1 -0
  257. package/text-context.d.ts +9 -0
  258. package/text-context.d.ts.map +1 -0
  259. package/text-context.js +12 -0
  260. package/text-context.js.map +1 -0
  261. package/textarea.d.ts +4 -0
  262. package/textarea.d.ts.map +1 -0
  263. package/textarea.js +6 -0
  264. package/textarea.js.map +1 -0
  265. package/theme-script.d.ts +3 -0
  266. package/theme-script.d.ts.map +1 -0
  267. package/theme-script.js +6 -0
  268. package/theme-script.js.map +1 -0
  269. package/theme.d.ts +28 -0
  270. package/theme.d.ts.map +1 -0
  271. package/theme.js +92 -0
  272. package/theme.js.map +1 -0
  273. package/toast.d.ts +52 -0
  274. package/toast.d.ts.map +1 -0
  275. package/toast.js +178 -0
  276. package/toast.js.map +1 -0
  277. package/tooltip.d.ts +12 -0
  278. package/tooltip.d.ts.map +1 -0
  279. package/tooltip.js +14 -0
  280. package/tooltip.js.map +1 -0
  281. package/top-nav.d.ts +18 -0
  282. package/top-nav.d.ts.map +1 -0
  283. package/top-nav.js +160 -0
  284. package/top-nav.js.map +1 -0
  285. package/upload-limits.d.ts +4 -0
  286. package/upload-limits.d.ts.map +1 -0
  287. package/upload-limits.js +21 -0
  288. package/upload-limits.js.map +1 -0
  289. package/use-element-size.d.ts +7 -0
  290. package/use-element-size.d.ts.map +1 -0
  291. package/use-element-size.js +21 -0
  292. package/use-element-size.js.map +1 -0
  293. package/utils.d.ts +4 -0
  294. package/utils.d.ts.map +1 -0
  295. package/utils.js +7 -0
  296. package/utils.js.map +1 -0
  297. package/workspace-launcher.d.ts +50 -0
  298. package/workspace-launcher.d.ts.map +1 -0
  299. package/workspace-launcher.js +127 -0
  300. package/workspace-launcher.js.map +1 -0
@@ -0,0 +1,22 @@
1
+ import * as React from 'react';
2
+ import { type SidebarNavGroup } from './sidebar-nav.js';
3
+ import type { LinkRender } from './settings-layout.js';
4
+ /**
5
+ * The desktop nav rail: brand + collapse toggle (persisted to a cookie so the
6
+ * server can render the right width next load), the grouped nav, and a footer
7
+ * slot (theme toggle, version, etc.). Hidden below `lg` — pair with AppShell's
8
+ * built-in mobile nav.
9
+ */
10
+ export declare function AppSidebar({ groups, pathname, brand, footer, collapsedFooter, defaultCollapsed, collapsible, linkRender, expandLabel, collapseLabel, }: {
11
+ groups: SidebarNavGroup[];
12
+ pathname: string;
13
+ brand?: React.ReactNode;
14
+ footer?: React.ReactNode;
15
+ collapsedFooter?: React.ReactNode;
16
+ defaultCollapsed?: boolean;
17
+ collapsible?: boolean;
18
+ linkRender?: LinkRender;
19
+ expandLabel?: string;
20
+ collapseLabel?: string;
21
+ }): React.JSX.Element;
22
+ //# sourceMappingURL=app-sidebar.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"app-sidebar.d.ts","sourceRoot":"","sources":["../src/app-sidebar.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAE9B,OAAO,EAAc,KAAK,eAAe,EAAE,MAAM,eAAe,CAAA;AAChE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAA;AAKnD;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,EACzB,MAAM,EACN,QAAQ,EACR,KAAK,EACL,MAAM,EACN,eAAe,EACf,gBAAwB,EACxB,WAAkB,EAClB,UAAU,EACV,WAA8B,EAC9B,aAAkC,GACnC,EAAE;IACD,MAAM,EAAE,eAAe,EAAE,CAAA;IACzB,QAAQ,EAAE,MAAM,CAAA;IAChB,KAAK,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IACvB,MAAM,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IACxB,eAAe,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IACjC,gBAAgB,CAAC,EAAE,OAAO,CAAA;IAC1B,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,UAAU,CAAC,EAAE,UAAU,CAAA;IACvB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,aAAa,CAAC,EAAE,MAAM,CAAA;CACvB,qBA8CA"}
package/app-sidebar.js ADDED
@@ -0,0 +1,30 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import * as React from 'react';
4
+ import { PanelLeftClose, PanelLeftOpen } from 'lucide-react';
5
+ import { SidebarNav } from './sidebar-nav.js';
6
+ import { cn } from './utils.js';
7
+ const COOKIE = 'appkit_sidebar_collapsed';
8
+ /**
9
+ * The desktop nav rail: brand + collapse toggle (persisted to a cookie so the
10
+ * server can render the right width next load), the grouped nav, and a footer
11
+ * slot (theme toggle, version, etc.). Hidden below `lg` — pair with AppShell's
12
+ * built-in mobile nav.
13
+ */
14
+ export function AppSidebar({ groups, pathname, brand, footer, collapsedFooter, defaultCollapsed = false, collapsible = true, linkRender, expandLabel = 'Expand sidebar', collapseLabel = 'Collapse sidebar', }) {
15
+ const [collapsed, setCollapsed] = React.useState(defaultCollapsed);
16
+ const toggle = React.useCallback(() => {
17
+ setCollapsed((c) => {
18
+ const next = !c;
19
+ try {
20
+ document.cookie = `${COOKIE}=${next ? '1' : '0'};path=/;max-age=31536000;samesite=lax`;
21
+ }
22
+ catch {
23
+ // Cookie persistence can be unavailable; local interaction still works.
24
+ }
25
+ return next;
26
+ });
27
+ }, []);
28
+ return (_jsxs("aside", { className: cn('hidden shrink-0 flex-col border-r border-border bg-surface transition-[width] duration-200 ease-out lg:flex', collapsed ? 'w-[4.25rem]' : 'w-60'), children: [_jsxs("div", { className: cn('flex h-14 items-center border-b border-border px-3', collapsed ? 'justify-center' : 'gap-2'), children: [collapsed ? null : _jsx("div", { className: "min-w-0 flex-1 truncate", children: brand }), collapsible ? (_jsx("button", { type: "button", onClick: toggle, "aria-label": collapsed ? expandLabel : collapseLabel, title: collapsed ? expandLabel : collapseLabel, className: cn('grid size-8 place-items-center rounded-md text-fg-subtle transition-colors hover:bg-surface-hover hover:text-fg', collapsed ? '' : 'ml-auto'), children: collapsed ? _jsx(PanelLeftOpen, { size: 17 }) : _jsx(PanelLeftClose, { size: 17 }) })) : null] }), _jsx(SidebarNav, { groups: groups, pathname: pathname, collapsed: collapsed, linkRender: linkRender }), footer || collapsedFooter ? (_jsx("div", { className: "border-t border-border p-3", children: collapsed ? collapsedFooter : footer })) : null] }));
29
+ }
30
+ //# sourceMappingURL=app-sidebar.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"app-sidebar.js","sourceRoot":"","sources":["../src/app-sidebar.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAA;;AAEZ,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AAC5D,OAAO,EAAE,UAAU,EAAwB,MAAM,eAAe,CAAA;AAEhE,OAAO,EAAE,EAAE,EAAE,MAAM,SAAS,CAAA;AAE5B,MAAM,MAAM,GAAG,0BAA0B,CAAA;AAEzC;;;;;GAKG;AACH,MAAM,UAAU,UAAU,CAAC,EACzB,MAAM,EACN,QAAQ,EACR,KAAK,EACL,MAAM,EACN,eAAe,EACf,gBAAgB,GAAG,KAAK,EACxB,WAAW,GAAG,IAAI,EAClB,UAAU,EACV,WAAW,GAAG,gBAAgB,EAC9B,aAAa,GAAG,kBAAkB,GAYnC;IACC,MAAM,CAAC,SAAS,EAAE,YAAY,CAAC,GAAG,KAAK,CAAC,QAAQ,CAAC,gBAAgB,CAAC,CAAA;IAClE,MAAM,MAAM,GAAG,KAAK,CAAC,WAAW,CAAC,GAAG,EAAE;QACpC,YAAY,CAAC,CAAC,CAAC,EAAE,EAAE;YACjB,MAAM,IAAI,GAAG,CAAC,CAAC,CAAA;YACf,IAAI,CAAC;gBACH,QAAQ,CAAC,MAAM,GAAG,GAAG,MAAM,IAAI,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,uCAAuC,CAAA;YACxF,CAAC;YAAC,MAAM,CAAC;gBACP,wEAAwE;YAC1E,CAAC;YACD,OAAO,IAAI,CAAA;QACb,CAAC,CAAC,CAAA;IACJ,CAAC,EAAE,EAAE,CAAC,CAAA;IAEN,OAAO,CACL,iBACE,SAAS,EAAE,EAAE,CACX,6GAA6G,EAC7G,SAAS,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,MAAM,CACnC,aAED,eAAK,SAAS,EAAE,EAAE,CAAC,oDAAoD,EAAE,SAAS,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,OAAO,CAAC,aAC7G,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,cAAK,SAAS,EAAC,yBAAyB,YAAE,KAAK,GAAO,EACzE,WAAW,CAAC,CAAC,CAAC,CACb,iBACE,IAAI,EAAC,QAAQ,EACb,OAAO,EAAE,MAAM,gBACH,SAAS,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,aAAa,EACnD,KAAK,EAAE,SAAS,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,aAAa,EAC9C,SAAS,EAAE,EAAE,CACX,iHAAiH,EACjH,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,CAC3B,YAEA,SAAS,CAAC,CAAC,CAAC,KAAC,aAAa,IAAC,IAAI,EAAE,EAAE,GAAI,CAAC,CAAC,CAAC,KAAC,cAAc,IAAC,IAAI,EAAE,EAAE,GAAI,GAChE,CACV,CAAC,CAAC,CAAC,IAAI,IACJ,EAEN,KAAC,UAAU,IAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,SAAS,EAAE,SAAS,EAAE,UAAU,EAAE,UAAU,GAAI,EAE/F,MAAM,IAAI,eAAe,CAAC,CAAC,CAAC,CAC3B,cAAK,SAAS,EAAC,4BAA4B,YAAE,SAAS,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,MAAM,GAAO,CACzF,CAAC,CAAC,CAAC,IAAI,IACF,CACT,CAAA;AACH,CAAC","sourcesContent":["'use client'\n\nimport * as React from 'react'\nimport { PanelLeftClose, PanelLeftOpen } from 'lucide-react'\nimport { SidebarNav, type SidebarNavGroup } from './sidebar-nav'\nimport type { LinkRender } from './settings-layout'\nimport { cn } from './utils'\n\nconst COOKIE = 'appkit_sidebar_collapsed'\n\n/**\n * The desktop nav rail: brand + collapse toggle (persisted to a cookie so the\n * server can render the right width next load), the grouped nav, and a footer\n * slot (theme toggle, version, etc.). Hidden below `lg` — pair with AppShell's\n * built-in mobile nav.\n */\nexport function AppSidebar({\n groups,\n pathname,\n brand,\n footer,\n collapsedFooter,\n defaultCollapsed = false,\n collapsible = true,\n linkRender,\n expandLabel = 'Expand sidebar',\n collapseLabel = 'Collapse sidebar',\n}: {\n groups: SidebarNavGroup[]\n pathname: string\n brand?: React.ReactNode\n footer?: React.ReactNode\n collapsedFooter?: React.ReactNode\n defaultCollapsed?: boolean\n collapsible?: boolean\n linkRender?: LinkRender\n expandLabel?: string\n collapseLabel?: string\n}) {\n const [collapsed, setCollapsed] = React.useState(defaultCollapsed)\n const toggle = React.useCallback(() => {\n setCollapsed((c) => {\n const next = !c\n try {\n document.cookie = `${COOKIE}=${next ? '1' : '0'};path=/;max-age=31536000;samesite=lax`\n } catch {\n // Cookie persistence can be unavailable; local interaction still works.\n }\n return next\n })\n }, [])\n\n return (\n <aside\n className={cn(\n 'hidden shrink-0 flex-col border-r border-border bg-surface transition-[width] duration-200 ease-out lg:flex',\n collapsed ? 'w-[4.25rem]' : 'w-60',\n )}\n >\n <div className={cn('flex h-14 items-center border-b border-border px-3', collapsed ? 'justify-center' : 'gap-2')}>\n {collapsed ? null : <div className=\"min-w-0 flex-1 truncate\">{brand}</div>}\n {collapsible ? (\n <button\n type=\"button\"\n onClick={toggle}\n aria-label={collapsed ? expandLabel : collapseLabel}\n title={collapsed ? expandLabel : collapseLabel}\n className={cn(\n 'grid size-8 place-items-center rounded-md text-fg-subtle transition-colors hover:bg-surface-hover hover:text-fg',\n collapsed ? '' : 'ml-auto',\n )}\n >\n {collapsed ? <PanelLeftOpen size={17} /> : <PanelLeftClose size={17} />}\n </button>\n ) : null}\n </div>\n\n <SidebarNav groups={groups} pathname={pathname} collapsed={collapsed} linkRender={linkRender} />\n\n {footer || collapsedFooter ? (\n <div className=\"border-t border-border p-3\">{collapsed ? collapsedFooter : footer}</div>\n ) : null}\n </aside>\n )\n}\n"]}
package/avatar.d.ts ADDED
@@ -0,0 +1,9 @@
1
+ import * as React from 'react';
2
+ export type AvatarProps = {
3
+ src?: string;
4
+ name?: string;
5
+ size?: number;
6
+ className?: string;
7
+ };
8
+ export declare function Avatar({ src, name, size, className }: AvatarProps): React.JSX.Element;
9
+ //# sourceMappingURL=avatar.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"avatar.d.ts","sourceRoot":"","sources":["../src/avatar.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAG9B,MAAM,MAAM,WAAW,GAAG;IACxB,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB,CAAA;AAUD,wBAAgB,MAAM,CAAC,EAAE,GAAG,EAAE,IAAI,EAAE,IAAS,EAAE,SAAS,EAAE,EAAE,WAAW,qBAyBtE"}
package/avatar.js ADDED
@@ -0,0 +1,18 @@
1
+ 'use client';
2
+ import { jsx as _jsx } from "react/jsx-runtime";
3
+ import * as React from 'react';
4
+ import { cn } from './utils.js';
5
+ function initials(name) {
6
+ if (!name)
7
+ return '?';
8
+ const parts = name.trim().split(/\s+/);
9
+ const first = parts[0]?.[0] ?? '';
10
+ const last = parts.length > 1 ? parts[parts.length - 1]?.[0] ?? '' : '';
11
+ return (first + last).toUpperCase() || '?';
12
+ }
13
+ export function Avatar({ src, name, size = 40, className }) {
14
+ const [failed, setFailed] = React.useState(false);
15
+ const showImage = src && !failed;
16
+ return (_jsx("span", { className: cn('inline-flex shrink-0 items-center justify-center overflow-hidden rounded-full bg-primary-subtle font-medium text-primary select-none', className), style: { width: size, height: size, fontSize: Math.round(size * 0.38) }, "aria-label": name, role: "img", children: showImage ? (_jsx("img", { src: src, alt: name ?? '', className: "size-full object-cover", onError: () => setFailed(true) })) : (initials(name)) }));
17
+ }
18
+ //# sourceMappingURL=avatar.js.map
package/avatar.js.map ADDED
@@ -0,0 +1 @@
1
+ {"version":3,"file":"avatar.js","sourceRoot":"","sources":["../src/avatar.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAA;;AAEZ,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,EAAE,EAAE,EAAE,MAAM,SAAS,CAAA;AAS5B,SAAS,QAAQ,CAAC,IAAa;IAC7B,IAAI,CAAC,IAAI;QAAE,OAAO,GAAG,CAAA;IACrB,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,CAAA;IACtC,MAAM,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAA;IACjC,MAAM,IAAI,GAAG,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAA;IACvE,OAAO,CAAC,KAAK,GAAG,IAAI,CAAC,CAAC,WAAW,EAAE,IAAI,GAAG,CAAA;AAC5C,CAAC;AAED,MAAM,UAAU,MAAM,CAAC,EAAE,GAAG,EAAE,IAAI,EAAE,IAAI,GAAG,EAAE,EAAE,SAAS,EAAe;IACrE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAA;IACjD,MAAM,SAAS,GAAG,GAAG,IAAI,CAAC,MAAM,CAAA;IAChC,OAAO,CACL,eACE,SAAS,EAAE,EAAE,CACX,sIAAsI,EACtI,SAAS,CACV,EACD,KAAK,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,GAAG,IAAI,CAAC,EAAE,gBAC3D,IAAI,EAChB,IAAI,EAAC,KAAK,YAET,SAAS,CAAC,CAAC,CAAC,CACX,cACE,GAAG,EAAE,GAAG,EACR,GAAG,EAAE,IAAI,IAAI,EAAE,EACf,SAAS,EAAC,wBAAwB,EAClC,OAAO,EAAE,GAAG,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,GAC9B,CACH,CAAC,CAAC,CAAC,CACF,QAAQ,CAAC,IAAI,CAAC,CACf,GACI,CACR,CAAA;AACH,CAAC","sourcesContent":["'use client'\n\nimport * as React from 'react'\nimport { cn } from './utils'\n\nexport type AvatarProps = {\n src?: string\n name?: string\n size?: number\n className?: string\n}\n\nfunction initials(name?: string): string {\n if (!name) return '?'\n const parts = name.trim().split(/\\s+/)\n const first = parts[0]?.[0] ?? ''\n const last = parts.length > 1 ? parts[parts.length - 1]?.[0] ?? '' : ''\n return (first + last).toUpperCase() || '?'\n}\n\nexport function Avatar({ src, name, size = 40, className }: AvatarProps) {\n const [failed, setFailed] = React.useState(false)\n const showImage = src && !failed\n return (\n <span\n className={cn(\n 'inline-flex shrink-0 items-center justify-center overflow-hidden rounded-full bg-primary-subtle font-medium text-primary select-none',\n className,\n )}\n style={{ width: size, height: size, fontSize: Math.round(size * 0.38) }}\n aria-label={name}\n role=\"img\"\n >\n {showImage ? (\n <img\n src={src}\n alt={name ?? ''}\n className=\"size-full object-cover\"\n onError={() => setFailed(true)}\n />\n ) : (\n initials(name)\n )}\n </span>\n )\n}\n"]}
package/badge.d.ts ADDED
@@ -0,0 +1,9 @@
1
+ import * as React from 'react';
2
+ import { type VariantProps } from 'class-variance-authority';
3
+ declare const badgeVariants: (props?: ({
4
+ variant?: "default" | "secondary" | "outline" | "destructive" | "warning" | "success" | "info" | null | undefined;
5
+ } & import("class-variance-authority/types").ClassProp) | undefined) => string;
6
+ export type BadgeProps = React.HTMLAttributes<HTMLSpanElement> & VariantProps<typeof badgeVariants>;
7
+ export declare function Badge({ className, variant, ...props }: BadgeProps): React.JSX.Element;
8
+ export { badgeVariants };
9
+ //# sourceMappingURL=badge.d.ts.map
package/badge.d.ts.map ADDED
@@ -0,0 +1 @@
1
+ {"version":3,"file":"badge.d.ts","sourceRoot":"","sources":["../src/badge.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,EAAO,KAAK,YAAY,EAAE,MAAM,0BAA0B,CAAA;AAGjE,QAAA,MAAM,aAAa;;8EAgBlB,CAAA;AAED,MAAM,MAAM,UAAU,GAAG,KAAK,CAAC,cAAc,CAAC,eAAe,CAAC,GAC5D,YAAY,CAAC,OAAO,aAAa,CAAC,CAAA;AAEpC,wBAAgB,KAAK,CAAC,EAAE,SAAS,EAAE,OAAO,EAAE,GAAG,KAAK,EAAE,EAAE,UAAU,qBAEjE;AAED,OAAO,EAAE,aAAa,EAAE,CAAA"}
package/badge.js ADDED
@@ -0,0 +1,23 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import * as React from 'react';
3
+ import { cva } from 'class-variance-authority';
4
+ import { cn } from './utils.js';
5
+ const badgeVariants = cva('inline-flex items-center gap-1 rounded-full border px-2.5 py-0.5 text-xs font-semibold leading-tight transition-colors', {
6
+ variants: {
7
+ variant: {
8
+ default: 'border-primary/20 bg-primary-subtle text-primary',
9
+ secondary: 'border-border bg-bg-subtle text-fg-muted',
10
+ outline: 'border-border-strong bg-surface text-fg-muted',
11
+ destructive: 'border-danger/25 bg-danger-subtle text-danger',
12
+ warning: 'border-warning/25 bg-warning-subtle text-warning',
13
+ success: 'border-success/25 bg-success-subtle text-success',
14
+ info: 'border-info/25 bg-info-subtle text-info',
15
+ },
16
+ },
17
+ defaultVariants: { variant: 'default' },
18
+ });
19
+ export function Badge({ className, variant, ...props }) {
20
+ return _jsx("span", { className: cn(badgeVariants({ variant }), className), ...props });
21
+ }
22
+ export { badgeVariants };
23
+ //# sourceMappingURL=badge.js.map
package/badge.js.map ADDED
@@ -0,0 +1 @@
1
+ {"version":3,"file":"badge.js","sourceRoot":"","sources":["../src/badge.tsx"],"names":[],"mappings":";AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,EAAE,GAAG,EAAqB,MAAM,0BAA0B,CAAA;AACjE,OAAO,EAAE,EAAE,EAAE,MAAM,SAAS,CAAA;AAE5B,MAAM,aAAa,GAAG,GAAG,CACvB,wHAAwH,EACxH;IACE,QAAQ,EAAE;QACR,OAAO,EAAE;YACP,OAAO,EAAE,kDAAkD;YAC3D,SAAS,EAAE,0CAA0C;YACrD,OAAO,EAAE,+CAA+C;YACxD,WAAW,EAAE,+CAA+C;YAC5D,OAAO,EAAE,kDAAkD;YAC3D,OAAO,EAAE,kDAAkD;YAC3D,IAAI,EAAE,yCAAyC;SAChD;KACF;IACD,eAAe,EAAE,EAAE,OAAO,EAAE,SAAS,EAAE;CACxC,CACF,CAAA;AAKD,MAAM,UAAU,KAAK,CAAC,EAAE,SAAS,EAAE,OAAO,EAAE,GAAG,KAAK,EAAc;IAChE,OAAO,eAAM,SAAS,EAAE,EAAE,CAAC,aAAa,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,SAAS,CAAC,KAAM,KAAK,GAAI,CAAA;AAClF,CAAC;AAED,OAAO,EAAE,aAAa,EAAE,CAAA","sourcesContent":["import * as React from 'react'\nimport { cva, type VariantProps } from 'class-variance-authority'\nimport { cn } from './utils'\n\nconst badgeVariants = cva(\n 'inline-flex items-center gap-1 rounded-full border px-2.5 py-0.5 text-xs font-semibold leading-tight transition-colors',\n {\n variants: {\n variant: {\n default: 'border-primary/20 bg-primary-subtle text-primary',\n secondary: 'border-border bg-bg-subtle text-fg-muted',\n outline: 'border-border-strong bg-surface text-fg-muted',\n destructive: 'border-danger/25 bg-danger-subtle text-danger',\n warning: 'border-warning/25 bg-warning-subtle text-warning',\n success: 'border-success/25 bg-success-subtle text-success',\n info: 'border-info/25 bg-info-subtle text-info',\n },\n },\n defaultVariants: { variant: 'default' },\n },\n)\n\nexport type BadgeProps = React.HTMLAttributes<HTMLSpanElement> &\n VariantProps<typeof badgeVariants>\n\nexport function Badge({ className, variant, ...props }: BadgeProps) {\n return <span className={cn(badgeVariants({ variant }), className)} {...props} />\n}\n\nexport { badgeVariants }\n"]}
package/button.d.ts ADDED
@@ -0,0 +1,24 @@
1
+ import * as React from 'react';
2
+ import { type VariantProps } from 'class-variance-authority';
3
+ /**
4
+ * Button — the ecosystem's primary action. Every color is a semantic token, so
5
+ * it rebrands and dark-modes for free. The press micro-interaction (scale) and
6
+ * hover shadow reference the shared motion feel and honor reduced-motion.
7
+ */
8
+ declare const buttonVariants: (props?: ({
9
+ variant?: "link" | "default" | "secondary" | "outline" | "destructive" | "ghost" | "subtle" | null | undefined;
10
+ size?: "icon" | "sm" | "md" | "lg" | null | undefined;
11
+ } & import("class-variance-authority/types").ClassProp) | undefined) => string;
12
+ export type ButtonProps = React.ButtonHTMLAttributes<HTMLButtonElement> & VariantProps<typeof buttonVariants> & {
13
+ /** Render onto the single child element instead of a <button>. */
14
+ asChild?: boolean;
15
+ };
16
+ export declare const Button: React.ForwardRefExoticComponent<React.ButtonHTMLAttributes<HTMLButtonElement> & VariantProps<(props?: ({
17
+ variant?: "link" | "default" | "secondary" | "outline" | "destructive" | "ghost" | "subtle" | null | undefined;
18
+ size?: "icon" | "sm" | "md" | "lg" | null | undefined;
19
+ } & import("class-variance-authority/types").ClassProp) | undefined) => string> & {
20
+ /** Render onto the single child element instead of a <button>. */
21
+ asChild?: boolean;
22
+ } & React.RefAttributes<HTMLButtonElement>>;
23
+ export { buttonVariants };
24
+ //# sourceMappingURL=button.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"button.d.ts","sourceRoot":"","sources":["../src/button.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,EAAO,KAAK,YAAY,EAAE,MAAM,0BAA0B,CAAA;AAGjE;;;;GAIG;AACH,QAAA,MAAM,cAAc;;;8EA+BnB,CAAA;AAED,MAAM,MAAM,WAAW,GAAG,KAAK,CAAC,oBAAoB,CAAC,iBAAiB,CAAC,GACrE,YAAY,CAAC,OAAO,cAAc,CAAC,GAAG;IACpC,kEAAkE;IAClE,OAAO,CAAC,EAAE,OAAO,CAAA;CAClB,CAAA;AAEH,eAAO,MAAM,MAAM;;;;IAJf,kEAAkE;cACxD,OAAO;2CAyBpB,CAAA;AAGD,OAAO,EAAE,cAAc,EAAE,CAAA"}
package/button.js ADDED
@@ -0,0 +1,50 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import * as React from 'react';
3
+ import { cva } from 'class-variance-authority';
4
+ import { cn } from './utils.js';
5
+ /**
6
+ * Button — the ecosystem's primary action. Every color is a semantic token, so
7
+ * it rebrands and dark-modes for free. The press micro-interaction (scale) and
8
+ * hover shadow reference the shared motion feel and honor reduced-motion.
9
+ */
10
+ const buttonVariants = cva([
11
+ 'inline-flex select-none items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium',
12
+ 'transition-[background-color,box-shadow,border-color,transform,color] duration-150 ease-out',
13
+ 'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring/60 focus-visible:ring-offset-2 focus-visible:ring-offset-bg',
14
+ 'active:scale-[0.98] motion-reduce:transition-none motion-reduce:active:scale-100',
15
+ 'disabled:pointer-events-none disabled:opacity-50',
16
+ ].join(' '), {
17
+ variants: {
18
+ variant: {
19
+ default: 'bg-primary text-primary-fg shadow-sm hover:bg-primary-hover hover:shadow active:bg-primary-active',
20
+ outline: 'border border-border bg-surface text-fg shadow-sm hover:border-border-strong hover:bg-surface-hover active:bg-surface-hover',
21
+ ghost: 'text-fg hover:bg-surface-hover active:bg-bg-subtle',
22
+ subtle: 'bg-primary-subtle text-primary hover:bg-primary-subtle/70 active:bg-primary-subtle/60',
23
+ secondary: 'bg-bg-subtle text-fg hover:bg-surface-hover active:bg-border-subtle',
24
+ destructive: 'bg-danger text-danger-fg shadow-sm hover:bg-danger/90 active:bg-danger/80',
25
+ link: 'text-primary underline-offset-4 hover:underline focus-visible:ring-offset-0',
26
+ },
27
+ size: {
28
+ sm: 'h-8 px-3',
29
+ md: 'h-10 px-4 py-2',
30
+ lg: 'h-11 px-6 text-[0.9375rem]',
31
+ icon: 'h-10 w-10',
32
+ },
33
+ },
34
+ defaultVariants: { variant: 'default', size: 'md' },
35
+ });
36
+ export const Button = React.forwardRef(({ className, variant, size, asChild = false, children, ...props }, ref) => {
37
+ const classes = cn(buttonVariants({ variant, size }), className);
38
+ if (asChild && React.isValidElement(children)) {
39
+ const child = children;
40
+ return React.cloneElement(child, {
41
+ ...props,
42
+ ref: ref,
43
+ className: cn(classes, child.props.className),
44
+ });
45
+ }
46
+ return (_jsx("button", { ref: ref, className: classes, ...props, children: children }));
47
+ });
48
+ Button.displayName = 'Button';
49
+ export { buttonVariants };
50
+ //# sourceMappingURL=button.js.map
package/button.js.map ADDED
@@ -0,0 +1 @@
1
+ {"version":3,"file":"button.js","sourceRoot":"","sources":["../src/button.tsx"],"names":[],"mappings":";AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,EAAE,GAAG,EAAqB,MAAM,0BAA0B,CAAA;AACjE,OAAO,EAAE,EAAE,EAAE,MAAM,SAAS,CAAA;AAE5B;;;;GAIG;AACH,MAAM,cAAc,GAAG,GAAG,CACxB;IACE,4GAA4G;IAC5G,6FAA6F;IAC7F,qIAAqI;IACrI,kFAAkF;IAClF,kDAAkD;CACnD,CAAC,IAAI,CAAC,GAAG,CAAC,EACX;IACE,QAAQ,EAAE;QACR,OAAO,EAAE;YACP,OAAO,EACL,mGAAmG;YACrG,OAAO,EACL,6HAA6H;YAC/H,KAAK,EAAE,oDAAoD;YAC3D,MAAM,EAAE,uFAAuF;YAC/F,SAAS,EAAE,qEAAqE;YAChF,WAAW,EACT,2EAA2E;YAC7E,IAAI,EAAE,6EAA6E;SACpF;QACD,IAAI,EAAE;YACJ,EAAE,EAAE,UAAU;YACd,EAAE,EAAE,gBAAgB;YACpB,EAAE,EAAE,4BAA4B;YAChC,IAAI,EAAE,WAAW;SAClB;KACF;IACD,eAAe,EAAE,EAAE,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE;CACpD,CACF,CAAA;AAQD,MAAM,CAAC,MAAM,MAAM,GAAG,KAAK,CAAC,UAAU,CACpC,CAAC,EAAE,SAAS,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,GAAG,KAAK,EAAE,QAAQ,EAAE,GAAG,KAAK,EAAE,EAAE,GAAG,EAAE,EAAE;IACzE,MAAM,OAAO,GAAG,EAAE,CAAC,cAAc,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,EAAE,SAAS,CAAC,CAAA;IAEhE,IAAI,OAAO,IAAI,KAAK,CAAC,cAAc,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC9C,MAAM,KAAK,GAAG,QAGZ,CAAA;QACF,OAAO,KAAK,CAAC,YAAY,CAAC,KAAK,EAAE;YAC/B,GAAG,KAAK;YACR,GAAG,EAAE,GAA6B;YAClC,SAAS,EAAE,EAAE,CAAC,OAAO,EAAE,KAAK,CAAC,KAAK,CAAC,SAAS,CAAC;SAC9C,CAAC,CAAA;IACJ,CAAC;IAED,OAAO,CACL,iBAAQ,GAAG,EAAE,GAAG,EAAE,SAAS,EAAE,OAAO,KAAM,KAAK,YAC5C,QAAQ,GACF,CACV,CAAA;AACH,CAAC,CACF,CAAA;AACD,MAAM,CAAC,WAAW,GAAG,QAAQ,CAAA;AAE7B,OAAO,EAAE,cAAc,EAAE,CAAA","sourcesContent":["import * as React from 'react'\nimport { cva, type VariantProps } from 'class-variance-authority'\nimport { cn } from './utils'\n\n/**\n * Button — the ecosystem's primary action. Every color is a semantic token, so\n * it rebrands and dark-modes for free. The press micro-interaction (scale) and\n * hover shadow reference the shared motion feel and honor reduced-motion.\n */\nconst buttonVariants = cva(\n [\n 'inline-flex select-none items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium',\n 'transition-[background-color,box-shadow,border-color,transform,color] duration-150 ease-out',\n 'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring/60 focus-visible:ring-offset-2 focus-visible:ring-offset-bg',\n 'active:scale-[0.98] motion-reduce:transition-none motion-reduce:active:scale-100',\n 'disabled:pointer-events-none disabled:opacity-50',\n ].join(' '),\n {\n variants: {\n variant: {\n default:\n 'bg-primary text-primary-fg shadow-sm hover:bg-primary-hover hover:shadow active:bg-primary-active',\n outline:\n 'border border-border bg-surface text-fg shadow-sm hover:border-border-strong hover:bg-surface-hover active:bg-surface-hover',\n ghost: 'text-fg hover:bg-surface-hover active:bg-bg-subtle',\n subtle: 'bg-primary-subtle text-primary hover:bg-primary-subtle/70 active:bg-primary-subtle/60',\n secondary: 'bg-bg-subtle text-fg hover:bg-surface-hover active:bg-border-subtle',\n destructive:\n 'bg-danger text-danger-fg shadow-sm hover:bg-danger/90 active:bg-danger/80',\n link: 'text-primary underline-offset-4 hover:underline focus-visible:ring-offset-0',\n },\n size: {\n sm: 'h-8 px-3',\n md: 'h-10 px-4 py-2',\n lg: 'h-11 px-6 text-[0.9375rem]',\n icon: 'h-10 w-10',\n },\n },\n defaultVariants: { variant: 'default', size: 'md' },\n },\n)\n\nexport type ButtonProps = React.ButtonHTMLAttributes<HTMLButtonElement> &\n VariantProps<typeof buttonVariants> & {\n /** Render onto the single child element instead of a <button>. */\n asChild?: boolean\n }\n\nexport const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(\n ({ className, variant, size, asChild = false, children, ...props }, ref) => {\n const classes = cn(buttonVariants({ variant, size }), className)\n\n if (asChild && React.isValidElement(children)) {\n const child = children as React.ReactElement<{\n className?: string\n ref?: React.Ref<HTMLElement>\n }>\n return React.cloneElement(child, {\n ...props,\n ref: ref as React.Ref<HTMLElement>,\n className: cn(classes, child.props.className),\n })\n }\n\n return (\n <button ref={ref} className={classes} {...props}>\n {children}\n </button>\n )\n },\n)\nButton.displayName = 'Button'\n\nexport { buttonVariants }\n"]}
package/card.d.ts ADDED
@@ -0,0 +1,21 @@
1
+ import * as React from 'react';
2
+ export type CardProps = React.HTMLAttributes<HTMLDivElement> & {
3
+ /** Adds a hover lift + shadow. Auto-enabled when an onClick is present. */
4
+ interactive?: boolean;
5
+ };
6
+ /**
7
+ * Card — the default surface. No 'use client': stays server-renderable, and
8
+ * only attaches keyboard handling when the caller actually made it clickable
9
+ * (an unconditional handler would make every server-rendered Card
10
+ * unserializable).
11
+ */
12
+ export declare const Card: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLDivElement> & {
13
+ /** Adds a hover lift + shadow. Auto-enabled when an onClick is present. */
14
+ interactive?: boolean;
15
+ } & React.RefAttributes<HTMLDivElement>>;
16
+ export declare const CardHeader: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLDivElement> & React.RefAttributes<HTMLDivElement>>;
17
+ export declare const CardTitle: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLHeadingElement> & React.RefAttributes<HTMLHeadingElement>>;
18
+ export declare const CardDescription: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLParagraphElement> & React.RefAttributes<HTMLParagraphElement>>;
19
+ export declare const CardContent: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLDivElement> & React.RefAttributes<HTMLDivElement>>;
20
+ export declare const CardFooter: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLDivElement> & React.RefAttributes<HTMLDivElement>>;
21
+ //# sourceMappingURL=card.d.ts.map
package/card.d.ts.map ADDED
@@ -0,0 +1 @@
1
+ {"version":3,"file":"card.d.ts","sourceRoot":"","sources":["../src/card.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAG9B,MAAM,MAAM,SAAS,GAAG,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC,GAAG;IAC7D,2EAA2E;IAC3E,WAAW,CAAC,EAAE,OAAO,CAAA;CACtB,CAAA;AAED;;;;;GAKG;AACH,eAAO,MAAM,IAAI;IAVf,2EAA2E;kBAC7D,OAAO;wCAwCtB,CAAA;AAGD,eAAO,MAAM,UAAU,6GAItB,CAAA;AAGD,eAAO,MAAM,SAAS,qHAKpB,CAAA;AAGF,eAAO,MAAM,eAAe,yHAK1B,CAAA;AAGF,eAAO,MAAM,WAAW,6GAIvB,CAAA;AAGD,eAAO,MAAM,UAAU,6GAItB,CAAA"}
package/card.js ADDED
@@ -0,0 +1,36 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import * as React from 'react';
3
+ import { cn } from './utils.js';
4
+ /**
5
+ * Card — the default surface. No 'use client': stays server-renderable, and
6
+ * only attaches keyboard handling when the caller actually made it clickable
7
+ * (an unconditional handler would make every server-rendered Card
8
+ * unserializable).
9
+ */
10
+ export const Card = React.forwardRef(({ className, interactive, onClick, onKeyDown, ...props }, ref) => {
11
+ const isInteractive = interactive ?? typeof onClick === 'function';
12
+ const clickable = isInteractive && typeof onClick === 'function';
13
+ const handleKeyDown = clickable || onKeyDown
14
+ ? (e) => {
15
+ if (clickable && (e.key === 'Enter' || e.key === ' ')) {
16
+ e.preventDefault();
17
+ onClick?.(e);
18
+ }
19
+ onKeyDown?.(e);
20
+ }
21
+ : undefined;
22
+ return (_jsx("div", { ref: ref, onClick: onClick, role: clickable ? 'button' : undefined, tabIndex: clickable ? 0 : undefined, onKeyDown: handleKeyDown, className: cn('rounded-lg border border-border bg-surface shadow-sm', isInteractive &&
23
+ 'cursor-pointer transition-all duration-200 ease-out hover:-translate-y-0.5 hover:border-border-strong hover:shadow-md focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring/40 motion-reduce:transition-none motion-reduce:hover:translate-y-0', className), ...props }));
24
+ });
25
+ Card.displayName = 'Card';
26
+ export const CardHeader = React.forwardRef(({ className, ...props }, ref) => (_jsx("div", { ref: ref, className: cn('flex flex-col gap-1 p-6', className), ...props })));
27
+ CardHeader.displayName = 'CardHeader';
28
+ export const CardTitle = React.forwardRef(({ className, ...props }, ref) => (_jsx("h3", { ref: ref, className: cn('text-lg font-semibold text-fg', className), ...props })));
29
+ CardTitle.displayName = 'CardTitle';
30
+ export const CardDescription = React.forwardRef(({ className, ...props }, ref) => (_jsx("p", { ref: ref, className: cn('text-sm text-fg-muted', className), ...props })));
31
+ CardDescription.displayName = 'CardDescription';
32
+ export const CardContent = React.forwardRef(({ className, ...props }, ref) => (_jsx("div", { ref: ref, className: cn('p-6 pt-0', className), ...props })));
33
+ CardContent.displayName = 'CardContent';
34
+ export const CardFooter = React.forwardRef(({ className, ...props }, ref) => (_jsx("div", { ref: ref, className: cn('flex items-center gap-2 p-6 pt-0', className), ...props })));
35
+ CardFooter.displayName = 'CardFooter';
36
+ //# sourceMappingURL=card.js.map
package/card.js.map ADDED
@@ -0,0 +1 @@
1
+ {"version":3,"file":"card.js","sourceRoot":"","sources":["../src/card.tsx"],"names":[],"mappings":";AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,EAAE,EAAE,EAAE,MAAM,SAAS,CAAA;AAO5B;;;;;GAKG;AACH,MAAM,CAAC,MAAM,IAAI,GAAG,KAAK,CAAC,UAAU,CAClC,CAAC,EAAE,SAAS,EAAE,WAAW,EAAE,OAAO,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,GAAG,EAAE,EAAE;IAChE,MAAM,aAAa,GAAG,WAAW,IAAI,OAAO,OAAO,KAAK,UAAU,CAAA;IAClE,MAAM,SAAS,GAAG,aAAa,IAAI,OAAO,OAAO,KAAK,UAAU,CAAA;IAChE,MAAM,aAAa,GACjB,SAAS,IAAI,SAAS;QACpB,CAAC,CAAC,CAAC,CAAsC,EAAE,EAAE;YACzC,IAAI,SAAS,IAAI,CAAC,CAAC,CAAC,GAAG,KAAK,OAAO,IAAI,CAAC,CAAC,GAAG,KAAK,GAAG,CAAC,EAAE,CAAC;gBACtD,CAAC,CAAC,cAAc,EAAE,CAAA;gBAClB,OAAO,EAAE,CAAC,CAAgD,CAAC,CAAA;YAC7D,CAAC;YACD,SAAS,EAAE,CAAC,CAAC,CAAC,CAAA;QAChB,CAAC;QACH,CAAC,CAAC,SAAS,CAAA;IACf,OAAO,CACL,cACE,GAAG,EAAE,GAAG,EACR,OAAO,EAAE,OAAO,EAChB,IAAI,EAAE,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS,EACtC,QAAQ,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,EACnC,SAAS,EAAE,aAAa,EACxB,SAAS,EAAE,EAAE,CACX,sDAAsD,EACtD,aAAa;YACX,kQAAkQ,EACpQ,SAAS,CACV,KACG,KAAK,GACT,CACH,CAAA;AACH,CAAC,CACF,CAAA;AACD,IAAI,CAAC,WAAW,GAAG,MAAM,CAAA;AAEzB,MAAM,CAAC,MAAM,UAAU,GAAG,KAAK,CAAC,UAAU,CACxC,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,GAAG,EAAE,EAAE,CAAC,CAChC,cAAK,GAAG,EAAE,GAAG,EAAE,SAAS,EAAE,EAAE,CAAC,yBAAyB,EAAE,SAAS,CAAC,KAAM,KAAK,GAAI,CAClF,CACF,CAAA;AACD,UAAU,CAAC,WAAW,GAAG,YAAY,CAAA;AAErC,MAAM,CAAC,MAAM,SAAS,GAAG,KAAK,CAAC,UAAU,CAGvC,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,GAAG,EAAE,EAAE,CAAC,CAClC,aAAI,GAAG,EAAE,GAAG,EAAE,SAAS,EAAE,EAAE,CAAC,+BAA+B,EAAE,SAAS,CAAC,KAAM,KAAK,GAAI,CACvF,CAAC,CAAA;AACF,SAAS,CAAC,WAAW,GAAG,WAAW,CAAA;AAEnC,MAAM,CAAC,MAAM,eAAe,GAAG,KAAK,CAAC,UAAU,CAG7C,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,GAAG,EAAE,EAAE,CAAC,CAClC,YAAG,GAAG,EAAE,GAAG,EAAE,SAAS,EAAE,EAAE,CAAC,uBAAuB,EAAE,SAAS,CAAC,KAAM,KAAK,GAAI,CAC9E,CAAC,CAAA;AACF,eAAe,CAAC,WAAW,GAAG,iBAAiB,CAAA;AAE/C,MAAM,CAAC,MAAM,WAAW,GAAG,KAAK,CAAC,UAAU,CACzC,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,GAAG,EAAE,EAAE,CAAC,CAChC,cAAK,GAAG,EAAE,GAAG,EAAE,SAAS,EAAE,EAAE,CAAC,UAAU,EAAE,SAAS,CAAC,KAAM,KAAK,GAAI,CACnE,CACF,CAAA;AACD,WAAW,CAAC,WAAW,GAAG,aAAa,CAAA;AAEvC,MAAM,CAAC,MAAM,UAAU,GAAG,KAAK,CAAC,UAAU,CACxC,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,GAAG,EAAE,EAAE,CAAC,CAChC,cAAK,GAAG,EAAE,GAAG,EAAE,SAAS,EAAE,EAAE,CAAC,kCAAkC,EAAE,SAAS,CAAC,KAAM,KAAK,GAAI,CAC3F,CACF,CAAA;AACD,UAAU,CAAC,WAAW,GAAG,YAAY,CAAA","sourcesContent":["import * as React from 'react'\nimport { cn } from './utils'\n\nexport type CardProps = React.HTMLAttributes<HTMLDivElement> & {\n /** Adds a hover lift + shadow. Auto-enabled when an onClick is present. */\n interactive?: boolean\n}\n\n/**\n * Card — the default surface. No 'use client': stays server-renderable, and\n * only attaches keyboard handling when the caller actually made it clickable\n * (an unconditional handler would make every server-rendered Card\n * unserializable).\n */\nexport const Card = React.forwardRef<HTMLDivElement, CardProps>(\n ({ className, interactive, onClick, onKeyDown, ...props }, ref) => {\n const isInteractive = interactive ?? typeof onClick === 'function'\n const clickable = isInteractive && typeof onClick === 'function'\n const handleKeyDown =\n clickable || onKeyDown\n ? (e: React.KeyboardEvent<HTMLDivElement>) => {\n if (clickable && (e.key === 'Enter' || e.key === ' ')) {\n e.preventDefault()\n onClick?.(e as unknown as React.MouseEvent<HTMLDivElement>)\n }\n onKeyDown?.(e)\n }\n : undefined\n return (\n <div\n ref={ref}\n onClick={onClick}\n role={clickable ? 'button' : undefined}\n tabIndex={clickable ? 0 : undefined}\n onKeyDown={handleKeyDown}\n className={cn(\n 'rounded-lg border border-border bg-surface shadow-sm',\n isInteractive &&\n 'cursor-pointer transition-all duration-200 ease-out hover:-translate-y-0.5 hover:border-border-strong hover:shadow-md focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring/40 motion-reduce:transition-none motion-reduce:hover:translate-y-0',\n className,\n )}\n {...props}\n />\n )\n },\n)\nCard.displayName = 'Card'\n\nexport const CardHeader = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(\n ({ className, ...props }, ref) => (\n <div ref={ref} className={cn('flex flex-col gap-1 p-6', className)} {...props} />\n ),\n)\nCardHeader.displayName = 'CardHeader'\n\nexport const CardTitle = React.forwardRef<\n HTMLHeadingElement,\n React.HTMLAttributes<HTMLHeadingElement>\n>(({ className, ...props }, ref) => (\n <h3 ref={ref} className={cn('text-lg font-semibold text-fg', className)} {...props} />\n))\nCardTitle.displayName = 'CardTitle'\n\nexport const CardDescription = React.forwardRef<\n HTMLParagraphElement,\n React.HTMLAttributes<HTMLParagraphElement>\n>(({ className, ...props }, ref) => (\n <p ref={ref} className={cn('text-sm text-fg-muted', className)} {...props} />\n))\nCardDescription.displayName = 'CardDescription'\n\nexport const CardContent = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(\n ({ className, ...props }, ref) => (\n <div ref={ref} className={cn('p-6 pt-0', className)} {...props} />\n ),\n)\nCardContent.displayName = 'CardContent'\n\nexport const CardFooter = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(\n ({ className, ...props }, ref) => (\n <div ref={ref} className={cn('flex items-center gap-2 p-6 pt-0', className)} {...props} />\n ),\n)\nCardFooter.displayName = 'CardFooter'\n"]}
package/checkbox.d.ts ADDED
@@ -0,0 +1,4 @@
1
+ import * as React from 'react';
2
+ export type CheckboxProps = React.InputHTMLAttributes<HTMLInputElement>;
3
+ export declare const Checkbox: React.ForwardRefExoticComponent<CheckboxProps & React.RefAttributes<HTMLInputElement>>;
4
+ //# sourceMappingURL=checkbox.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"checkbox.d.ts","sourceRoot":"","sources":["../src/checkbox.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAG9B,MAAM,MAAM,aAAa,GAAG,KAAK,CAAC,mBAAmB,CAAC,gBAAgB,CAAC,CAAA;AAEvE,eAAO,MAAM,QAAQ,wFAcpB,CAAA"}
package/checkbox.js ADDED
@@ -0,0 +1,6 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import * as React from 'react';
3
+ import { cn } from './utils.js';
4
+ export const Checkbox = React.forwardRef(({ className, ...props }, ref) => (_jsx("input", { ref: ref, type: "checkbox", className: cn('size-4 shrink-0 rounded border-border accent-primary', 'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring/50 focus-visible:ring-offset-2 focus-visible:ring-offset-bg', 'disabled:cursor-not-allowed disabled:opacity-50', className), ...props })));
5
+ Checkbox.displayName = 'Checkbox';
6
+ //# sourceMappingURL=checkbox.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"checkbox.js","sourceRoot":"","sources":["../src/checkbox.tsx"],"names":[],"mappings":";AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,EAAE,EAAE,EAAE,MAAM,SAAS,CAAA;AAI5B,MAAM,CAAC,MAAM,QAAQ,GAAG,KAAK,CAAC,UAAU,CACtC,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,GAAG,EAAE,EAAE,CAAC,CAChC,gBACE,GAAG,EAAE,GAAG,EACR,IAAI,EAAC,UAAU,EACf,SAAS,EAAE,EAAE,CACX,sDAAsD,EACtD,qIAAqI,EACrI,iDAAiD,EACjD,SAAS,CACV,KACG,KAAK,GACT,CACH,CACF,CAAA;AACD,QAAQ,CAAC,WAAW,GAAG,UAAU,CAAA","sourcesContent":["import * as React from 'react'\nimport { cn } from './utils'\n\nexport type CheckboxProps = React.InputHTMLAttributes<HTMLInputElement>\n\nexport const Checkbox = React.forwardRef<HTMLInputElement, CheckboxProps>(\n ({ className, ...props }, ref) => (\n <input\n ref={ref}\n type=\"checkbox\"\n className={cn(\n 'size-4 shrink-0 rounded border-border accent-primary',\n 'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring/50 focus-visible:ring-offset-2 focus-visible:ring-offset-bg',\n 'disabled:cursor-not-allowed disabled:opacity-50',\n className,\n )}\n {...props}\n />\n ),\n)\nCheckbox.displayName = 'Checkbox'\n"]}
@@ -0,0 +1,23 @@
1
+ import * as React from 'react';
2
+ export type ConfirmTone = 'default' | 'danger';
3
+ export type ConfirmDialogOptions = {
4
+ title?: string;
5
+ message: React.ReactNode;
6
+ confirmLabel?: string;
7
+ cancelLabel?: string;
8
+ tone?: ConfirmTone;
9
+ };
10
+ /** Promise-based, application-wide replacement for `window.confirm()`. */
11
+ export declare function confirmDialog(options: string | ConfirmDialogOptions): Promise<boolean>;
12
+ export declare function cancelConfirmDialog(): void;
13
+ export type ConfirmRootProps = {
14
+ labels?: {
15
+ defaultTitle?: string;
16
+ dangerTitle?: string;
17
+ confirm?: string;
18
+ cancel?: string;
19
+ };
20
+ };
21
+ /** Mount once near the root of an application that calls `confirmDialog`. */
22
+ export declare function ConfirmRoot({ labels }: ConfirmRootProps): React.ReactPortal | null;
23
+ //# sourceMappingURL=confirm-dialog.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"confirm-dialog.d.ts","sourceRoot":"","sources":["../src/confirm-dialog.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAM9B,MAAM,MAAM,WAAW,GAAG,SAAS,GAAG,QAAQ,CAAA;AAE9C,MAAM,MAAM,oBAAoB,GAAG;IACjC,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,OAAO,EAAE,KAAK,CAAC,SAAS,CAAA;IACxB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,IAAI,CAAC,EAAE,WAAW,CAAA;CACnB,CAAA;AAYD,0EAA0E;AAC1E,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,oBAAoB,GAAG,OAAO,CAAC,OAAO,CAAC,CAOtF;AAED,wBAAgB,mBAAmB,SAElC;AAcD,MAAM,MAAM,gBAAgB,GAAG;IAC7B,MAAM,CAAC,EAAE;QACP,YAAY,CAAC,EAAE,MAAM,CAAA;QACrB,WAAW,CAAC,EAAE,MAAM,CAAA;QACpB,OAAO,CAAC,EAAE,MAAM,CAAA;QAChB,MAAM,CAAC,EAAE,MAAM,CAAA;KAChB,CAAA;CACF,CAAA;AAED,6EAA6E;AAC7E,wBAAgB,WAAW,CAAC,EAAE,MAAW,EAAE,EAAE,gBAAgB,4BAgE5D"}
@@ -0,0 +1,67 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import * as React from 'react';
4
+ import { createPortal } from 'react-dom';
5
+ import { AnimatePresence, motion } from 'framer-motion';
6
+ import { AlertTriangle, HelpCircle } from 'lucide-react';
7
+ import { Button } from './button.js';
8
+ let current = null;
9
+ let counter = 0;
10
+ const listeners = new Set();
11
+ function emit() {
12
+ for (const listener of listeners)
13
+ listener();
14
+ }
15
+ /** Promise-based, application-wide replacement for `window.confirm()`. */
16
+ export function confirmDialog(options) {
17
+ const request = typeof options === 'string' ? { message: options } : options;
18
+ return new Promise((resolve) => {
19
+ if (current)
20
+ current.resolve(false);
21
+ current = { ...request, id: ++counter, resolve };
22
+ emit();
23
+ });
24
+ }
25
+ export function cancelConfirmDialog() {
26
+ settle(false);
27
+ }
28
+ function settle(confirmed) {
29
+ if (!current)
30
+ return;
31
+ current.resolve(confirmed);
32
+ current = null;
33
+ emit();
34
+ }
35
+ function subscribe(listener) {
36
+ listeners.add(listener);
37
+ return () => listeners.delete(listener);
38
+ }
39
+ /** Mount once near the root of an application that calls `confirmDialog`. */
40
+ export function ConfirmRoot({ labels = {} }) {
41
+ const request = React.useSyncExternalStore(subscribe, () => current, () => null);
42
+ React.useEffect(() => {
43
+ if (!request)
44
+ return;
45
+ function onKey(event) {
46
+ if (event.key === 'Escape')
47
+ settle(false);
48
+ if (event.key === 'Enter')
49
+ settle(true);
50
+ }
51
+ document.addEventListener('keydown', onKey);
52
+ const previousOverflow = document.body.style.overflow;
53
+ document.body.style.overflow = 'hidden';
54
+ return () => {
55
+ document.removeEventListener('keydown', onKey);
56
+ document.body.style.overflow = previousOverflow;
57
+ };
58
+ }, [request]);
59
+ if (typeof document === 'undefined')
60
+ return null;
61
+ const danger = request?.tone === 'danger';
62
+ const title = request?.title ?? (danger ? labels.dangerTitle ?? 'Are you sure?' : labels.defaultTitle ?? 'Confirm');
63
+ const confirmLabel = request?.confirmLabel ?? labels.confirm ?? 'Confirm';
64
+ const cancelLabel = request?.cancelLabel ?? labels.cancel ?? 'Cancel';
65
+ return createPortal(_jsx(AnimatePresence, { children: request ? (_jsxs("div", { className: "fixed inset-0 z-[60] flex items-center justify-center p-4", role: "dialog", "aria-modal": "true", "aria-labelledby": "appkit-confirm-title", children: [_jsx(motion.div, { initial: { opacity: 0 }, animate: { opacity: 1 }, exit: { opacity: 0 }, transition: { duration: 0.15 }, className: "absolute inset-0 bg-overlay backdrop-blur-[2px]", onClick: () => settle(false), "aria-hidden": "true" }), _jsxs(motion.div, { initial: { opacity: 0, scale: 0.96, y: 8 }, animate: { opacity: 1, scale: 1, y: 0 }, exit: { opacity: 0, scale: 0.96, y: 8 }, transition: { type: 'spring', damping: 26, stiffness: 340, mass: 0.7 }, className: "relative w-full max-w-md overflow-hidden rounded-xl border border-border bg-surface shadow-xl", children: [_jsxs("div", { className: "flex items-start gap-4 p-6", children: [_jsx("div", { className: danger ? 'flex size-10 shrink-0 items-center justify-center rounded-full bg-danger-subtle text-danger' : 'flex size-10 shrink-0 items-center justify-center rounded-full bg-info-subtle text-info', children: danger ? _jsx(AlertTriangle, { size: 20 }) : _jsx(HelpCircle, { size: 20 }) }), _jsxs("div", { className: "min-w-0 space-y-1.5 pt-0.5", children: [_jsx("h2", { id: "appkit-confirm-title", className: "text-base font-semibold text-fg", children: title }), _jsx("div", { className: "text-sm leading-relaxed text-fg-muted", children: request.message })] })] }), _jsxs("div", { className: "flex justify-end gap-2 border-t border-border bg-bg-subtle px-6 py-4", children: [_jsx(Button, { variant: "outline", onClick: () => settle(false), children: cancelLabel }), _jsx(Button, { autoFocus: true, variant: danger ? 'destructive' : 'default', onClick: () => settle(true), children: confirmLabel })] })] })] }, request.id)) : null }), document.body);
66
+ }
67
+ //# sourceMappingURL=confirm-dialog.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"confirm-dialog.js","sourceRoot":"","sources":["../src/confirm-dialog.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAA;;AAEZ,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAA;AACxC,OAAO,EAAE,eAAe,EAAE,MAAM,EAAE,MAAM,eAAe,CAAA;AACvD,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AACxD,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAA;AAcjC,IAAI,OAAO,GAAmB,IAAI,CAAA;AAClC,IAAI,OAAO,GAAG,CAAC,CAAA;AACf,MAAM,SAAS,GAAG,IAAI,GAAG,EAAc,CAAA;AAEvC,SAAS,IAAI;IACX,KAAK,MAAM,QAAQ,IAAI,SAAS;QAAE,QAAQ,EAAE,CAAA;AAC9C,CAAC;AAED,0EAA0E;AAC1E,MAAM,UAAU,aAAa,CAAC,OAAsC;IAClE,MAAM,OAAO,GAAG,OAAO,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,OAAO,CAAA;IAC5E,OAAO,IAAI,OAAO,CAAU,CAAC,OAAO,EAAE,EAAE;QACtC,IAAI,OAAO;YAAE,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,CAAA;QACnC,OAAO,GAAG,EAAE,GAAG,OAAO,EAAE,EAAE,EAAE,EAAE,OAAO,EAAE,OAAO,EAAE,CAAA;QAChD,IAAI,EAAE,CAAA;IACR,CAAC,CAAC,CAAA;AACJ,CAAC;AAED,MAAM,UAAU,mBAAmB;IACjC,MAAM,CAAC,KAAK,CAAC,CAAA;AACf,CAAC;AAED,SAAS,MAAM,CAAC,SAAkB;IAChC,IAAI,CAAC,OAAO;QAAE,OAAM;IACpB,OAAO,CAAC,OAAO,CAAC,SAAS,CAAC,CAAA;IAC1B,OAAO,GAAG,IAAI,CAAA;IACd,IAAI,EAAE,CAAA;AACR,CAAC;AAED,SAAS,SAAS,CAAC,QAAoB;IACrC,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAA;IACvB,OAAO,GAAG,EAAE,CAAC,SAAS,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAA;AACzC,CAAC;AAWD,6EAA6E;AAC7E,MAAM,UAAU,WAAW,CAAC,EAAE,MAAM,GAAG,EAAE,EAAoB;IAC3D,MAAM,OAAO,GAAG,KAAK,CAAC,oBAAoB,CAAC,SAAS,EAAE,GAAG,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,CAAA;IAEhF,KAAK,CAAC,SAAS,CAAC,GAAG,EAAE;QACnB,IAAI,CAAC,OAAO;YAAE,OAAM;QACpB,SAAS,KAAK,CAAC,KAAoB;YACjC,IAAI,KAAK,CAAC,GAAG,KAAK,QAAQ;gBAAE,MAAM,CAAC,KAAK,CAAC,CAAA;YACzC,IAAI,KAAK,CAAC,GAAG,KAAK,OAAO;gBAAE,MAAM,CAAC,IAAI,CAAC,CAAA;QACzC,CAAC;QACD,QAAQ,CAAC,gBAAgB,CAAC,SAAS,EAAE,KAAK,CAAC,CAAA;QAC3C,MAAM,gBAAgB,GAAG,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAA;QACrD,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,GAAG,QAAQ,CAAA;QACvC,OAAO,GAAG,EAAE;YACV,QAAQ,CAAC,mBAAmB,CAAC,SAAS,EAAE,KAAK,CAAC,CAAA;YAC9C,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,GAAG,gBAAgB,CAAA;QACjD,CAAC,CAAA;IACH,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC,CAAA;IAEb,IAAI,OAAO,QAAQ,KAAK,WAAW;QAAE,OAAO,IAAI,CAAA;IAEhD,MAAM,MAAM,GAAG,OAAO,EAAE,IAAI,KAAK,QAAQ,CAAA;IACzC,MAAM,KAAK,GAAG,OAAO,EAAE,KAAK,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,WAAW,IAAI,eAAe,CAAC,CAAC,CAAC,MAAM,CAAC,YAAY,IAAI,SAAS,CAAC,CAAA;IACnH,MAAM,YAAY,GAAG,OAAO,EAAE,YAAY,IAAI,MAAM,CAAC,OAAO,IAAI,SAAS,CAAA;IACzE,MAAM,WAAW,GAAG,OAAO,EAAE,WAAW,IAAI,MAAM,CAAC,MAAM,IAAI,QAAQ,CAAA;IAErE,OAAO,YAAY,CACjB,KAAC,eAAe,cACb,OAAO,CAAC,CAAC,CAAC,CACT,eAAsB,SAAS,EAAC,2DAA2D,EAAC,IAAI,EAAC,QAAQ,gBAAY,MAAM,qBAAiB,sBAAsB,aAChK,KAAC,MAAM,CAAC,GAAG,IACT,OAAO,EAAE,EAAE,OAAO,EAAE,CAAC,EAAE,EACvB,OAAO,EAAE,EAAE,OAAO,EAAE,CAAC,EAAE,EACvB,IAAI,EAAE,EAAE,OAAO,EAAE,CAAC,EAAE,EACpB,UAAU,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,EAC9B,SAAS,EAAC,iDAAiD,EAC3D,OAAO,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,iBAChB,MAAM,GAClB,EACF,MAAC,MAAM,CAAC,GAAG,IACT,OAAO,EAAE,EAAE,OAAO,EAAE,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC,EAAE,EAC1C,OAAO,EAAE,EAAE,OAAO,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,EACvC,IAAI,EAAE,EAAE,OAAO,EAAE,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC,EAAE,EACvC,UAAU,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,EAAE,EAAE,SAAS,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,EAAE,EACtE,SAAS,EAAC,+FAA+F,aAEzG,eAAK,SAAS,EAAC,4BAA4B,aACzC,cAAK,SAAS,EAAE,MAAM,CAAC,CAAC,CAAC,6FAA6F,CAAC,CAAC,CAAC,yFAAyF,YAC/M,MAAM,CAAC,CAAC,CAAC,KAAC,aAAa,IAAC,IAAI,EAAE,EAAE,GAAI,CAAC,CAAC,CAAC,KAAC,UAAU,IAAC,IAAI,EAAE,EAAE,GAAI,GAC5D,EACN,eAAK,SAAS,EAAC,4BAA4B,aACzC,aAAI,EAAE,EAAC,sBAAsB,EAAC,SAAS,EAAC,iCAAiC,YAAE,KAAK,GAAM,EACtF,cAAK,SAAS,EAAC,uCAAuC,YAAE,OAAO,CAAC,OAAO,GAAO,IAC1E,IACF,EACN,eAAK,SAAS,EAAC,sEAAsE,aACnF,KAAC,MAAM,IAAC,OAAO,EAAC,SAAS,EAAC,OAAO,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,YAAG,WAAW,GAAU,EAC9E,KAAC,MAAM,IAAC,SAAS,QAAC,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,SAAS,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,YAAG,YAAY,GAAU,IAC/G,IACK,KA9BL,OAAO,CAAC,EAAE,CA+Bd,CACP,CAAC,CAAC,CAAC,IAAI,GACQ,EAClB,QAAQ,CAAC,IAAI,CACd,CAAA;AACH,CAAC","sourcesContent":["'use client'\n\nimport * as React from 'react'\nimport { createPortal } from 'react-dom'\nimport { AnimatePresence, motion } from 'framer-motion'\nimport { AlertTriangle, HelpCircle } from 'lucide-react'\nimport { Button } from './button'\n\nexport type ConfirmTone = 'default' | 'danger'\n\nexport type ConfirmDialogOptions = {\n title?: string\n message: React.ReactNode\n confirmLabel?: string\n cancelLabel?: string\n tone?: ConfirmTone\n}\n\ntype Request = ConfirmDialogOptions & { id: number; resolve: (confirmed: boolean) => void }\n\nlet current: Request | null = null\nlet counter = 0\nconst listeners = new Set<() => void>()\n\nfunction emit() {\n for (const listener of listeners) listener()\n}\n\n/** Promise-based, application-wide replacement for `window.confirm()`. */\nexport function confirmDialog(options: string | ConfirmDialogOptions): Promise<boolean> {\n const request = typeof options === 'string' ? { message: options } : options\n return new Promise<boolean>((resolve) => {\n if (current) current.resolve(false)\n current = { ...request, id: ++counter, resolve }\n emit()\n })\n}\n\nexport function cancelConfirmDialog() {\n settle(false)\n}\n\nfunction settle(confirmed: boolean) {\n if (!current) return\n current.resolve(confirmed)\n current = null\n emit()\n}\n\nfunction subscribe(listener: () => void) {\n listeners.add(listener)\n return () => listeners.delete(listener)\n}\n\nexport type ConfirmRootProps = {\n labels?: {\n defaultTitle?: string\n dangerTitle?: string\n confirm?: string\n cancel?: string\n }\n}\n\n/** Mount once near the root of an application that calls `confirmDialog`. */\nexport function ConfirmRoot({ labels = {} }: ConfirmRootProps) {\n const request = React.useSyncExternalStore(subscribe, () => current, () => null)\n\n React.useEffect(() => {\n if (!request) return\n function onKey(event: KeyboardEvent) {\n if (event.key === 'Escape') settle(false)\n if (event.key === 'Enter') settle(true)\n }\n document.addEventListener('keydown', onKey)\n const previousOverflow = document.body.style.overflow\n document.body.style.overflow = 'hidden'\n return () => {\n document.removeEventListener('keydown', onKey)\n document.body.style.overflow = previousOverflow\n }\n }, [request])\n\n if (typeof document === 'undefined') return null\n\n const danger = request?.tone === 'danger'\n const title = request?.title ?? (danger ? labels.dangerTitle ?? 'Are you sure?' : labels.defaultTitle ?? 'Confirm')\n const confirmLabel = request?.confirmLabel ?? labels.confirm ?? 'Confirm'\n const cancelLabel = request?.cancelLabel ?? labels.cancel ?? 'Cancel'\n\n return createPortal(\n <AnimatePresence>\n {request ? (\n <div key={request.id} className=\"fixed inset-0 z-[60] flex items-center justify-center p-4\" role=\"dialog\" aria-modal=\"true\" aria-labelledby=\"appkit-confirm-title\">\n <motion.div\n initial={{ opacity: 0 }}\n animate={{ opacity: 1 }}\n exit={{ opacity: 0 }}\n transition={{ duration: 0.15 }}\n className=\"absolute inset-0 bg-overlay backdrop-blur-[2px]\"\n onClick={() => settle(false)}\n aria-hidden=\"true\"\n />\n <motion.div\n initial={{ opacity: 0, scale: 0.96, y: 8 }}\n animate={{ opacity: 1, scale: 1, y: 0 }}\n exit={{ opacity: 0, scale: 0.96, y: 8 }}\n transition={{ type: 'spring', damping: 26, stiffness: 340, mass: 0.7 }}\n className=\"relative w-full max-w-md overflow-hidden rounded-xl border border-border bg-surface shadow-xl\"\n >\n <div className=\"flex items-start gap-4 p-6\">\n <div className={danger ? 'flex size-10 shrink-0 items-center justify-center rounded-full bg-danger-subtle text-danger' : 'flex size-10 shrink-0 items-center justify-center rounded-full bg-info-subtle text-info'}>\n {danger ? <AlertTriangle size={20} /> : <HelpCircle size={20} />}\n </div>\n <div className=\"min-w-0 space-y-1.5 pt-0.5\">\n <h2 id=\"appkit-confirm-title\" className=\"text-base font-semibold text-fg\">{title}</h2>\n <div className=\"text-sm leading-relaxed text-fg-muted\">{request.message}</div>\n </div>\n </div>\n <div className=\"flex justify-end gap-2 border-t border-border bg-bg-subtle px-6 py-4\">\n <Button variant=\"outline\" onClick={() => settle(false)}>{cancelLabel}</Button>\n <Button autoFocus variant={danger ? 'destructive' : 'default'} onClick={() => settle(true)}>{confirmLabel}</Button>\n </div>\n </motion.div>\n </div>\n ) : null}\n </AnimatePresence>,\n document.body,\n )\n}\n"]}
@@ -0,0 +1,47 @@
1
+ import * as React from 'react';
2
+ /**
3
+ * Universal context menu — a floating list of actions opened at a point.
4
+ * Trigger it via {@link useContextMenu}, either from a right-click
5
+ * (`onContextMenu={menu.onContextMenu}`) or a kebab button
6
+ * (`onClick={(e) => menu.openBelow(e.currentTarget)}`). The panel portals to
7
+ * <body>, clamps inside the viewport, and closes on outside-click / Esc /
8
+ * scroll. Items carry an icon, label, and handler; `danger` tints destructive
9
+ * actions and `{ separator: true }` draws a divider.
10
+ */
11
+ export interface ContextMenuItem {
12
+ key: string;
13
+ label: string;
14
+ icon?: React.ComponentType<{
15
+ className?: string;
16
+ }>;
17
+ onSelect: () => void;
18
+ disabled?: boolean;
19
+ danger?: boolean;
20
+ }
21
+ export type ContextMenuEntry = ContextMenuItem | {
22
+ key: string;
23
+ separator: true;
24
+ };
25
+ export interface ContextMenuController {
26
+ open: boolean;
27
+ position: {
28
+ x: number;
29
+ y: number;
30
+ } | null;
31
+ openAt: (x: number, y: number) => void;
32
+ onContextMenu: (e: React.MouseEvent) => void;
33
+ openBelow: (el: HTMLElement) => void;
34
+ close: () => void;
35
+ }
36
+ export declare function useContextMenu(): ContextMenuController;
37
+ export declare function ContextMenu({ open, position, items, onClose, className, }: {
38
+ open: boolean;
39
+ position: {
40
+ x: number;
41
+ y: number;
42
+ } | null;
43
+ items: ContextMenuEntry[];
44
+ onClose: () => void;
45
+ className?: string;
46
+ }): React.ReactPortal | null;
47
+ //# sourceMappingURL=context-menu.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context-menu.d.ts","sourceRoot":"","sources":["../src/context-menu.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAK9B;;;;;;;;GAQG;AACH,MAAM,WAAW,eAAe;IAC9B,GAAG,EAAE,MAAM,CAAA;IACX,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;QAAE,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;IAClD,QAAQ,EAAE,MAAM,IAAI,CAAA;IACpB,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,MAAM,CAAC,EAAE,OAAO,CAAA;CACjB;AAED,MAAM,MAAM,gBAAgB,GAAG,eAAe,GAAG;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,IAAI,CAAA;CAAE,CAAA;AAEjF,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,OAAO,CAAA;IACb,QAAQ,EAAE;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAA;IACzC,MAAM,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,KAAK,IAAI,CAAA;IACtC,aAAa,EAAE,CAAC,CAAC,EAAE,KAAK,CAAC,UAAU,KAAK,IAAI,CAAA;IAC5C,SAAS,EAAE,CAAC,EAAE,EAAE,WAAW,KAAK,IAAI,CAAA;IACpC,KAAK,EAAE,MAAM,IAAI,CAAA;CAClB;AAED,wBAAgB,cAAc,IAAI,qBAAqB,CActD;AAED,wBAAgB,WAAW,CAAC,EAC1B,IAAI,EACJ,QAAQ,EACR,KAAK,EACL,OAAO,EACP,SAAS,GACV,EAAE;IACD,IAAI,EAAE,OAAO,CAAA;IACb,QAAQ,EAAE;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAA;IACzC,KAAK,EAAE,gBAAgB,EAAE,CAAA;IACzB,OAAO,EAAE,MAAM,IAAI,CAAA;IACnB,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB,4BA2GA"}