@inshorts/glint-ui 0.5.3 → 0.6.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 (341) hide show
  1. package/LICENSE +13 -0
  2. package/README.md +3 -9
  3. package/dist/alert.cjs +96 -0
  4. package/dist/alert.cjs.map +1 -0
  5. package/dist/alert.d.cts +29 -0
  6. package/dist/alert.d.ts +29 -0
  7. package/dist/alert.js +10 -0
  8. package/dist/alert.js.map +1 -0
  9. package/dist/autocomplete.cjs +578 -0
  10. package/dist/autocomplete.cjs.map +1 -0
  11. package/dist/autocomplete.d.cts +56 -0
  12. package/dist/autocomplete.d.ts +56 -0
  13. package/dist/autocomplete.js +11 -0
  14. package/dist/autocomplete.js.map +1 -0
  15. package/dist/badge.cjs +89 -0
  16. package/dist/badge.cjs.map +1 -0
  17. package/dist/badge.d.cts +25 -0
  18. package/dist/badge.d.ts +25 -0
  19. package/dist/badge.js +10 -0
  20. package/dist/badge.js.map +1 -0
  21. package/dist/breadcrumb.cjs +88 -0
  22. package/dist/breadcrumb.cjs.map +1 -0
  23. package/dist/breadcrumb.d.cts +14 -0
  24. package/dist/breadcrumb.d.ts +14 -0
  25. package/dist/breadcrumb.js +8 -0
  26. package/dist/breadcrumb.js.map +1 -0
  27. package/dist/button.cjs +143 -0
  28. package/dist/button.cjs.map +1 -0
  29. package/dist/button.d.cts +34 -0
  30. package/dist/button.d.ts +34 -0
  31. package/dist/button.js +9 -0
  32. package/dist/button.js.map +1 -0
  33. package/dist/card.cjs +111 -0
  34. package/dist/card.cjs.map +1 -0
  35. package/dist/card.d.cts +15 -0
  36. package/dist/card.d.ts +15 -0
  37. package/dist/card.js +18 -0
  38. package/dist/card.js.map +1 -0
  39. package/dist/checkbox.cjs +66 -0
  40. package/dist/checkbox.cjs.map +1 -0
  41. package/{src/checkbox.tsx → dist/checkbox.d.cts} +5 -22
  42. package/dist/checkbox.d.ts +25 -0
  43. package/dist/checkbox.js +10 -0
  44. package/dist/checkbox.js.map +1 -0
  45. package/dist/chunk-43ZUFY63.js +85 -0
  46. package/dist/chunk-43ZUFY63.js.map +1 -0
  47. package/dist/chunk-67ACNS42.js +29 -0
  48. package/dist/chunk-67ACNS42.js.map +1 -0
  49. package/dist/chunk-6URKHMCF.js +76 -0
  50. package/dist/chunk-6URKHMCF.js.map +1 -0
  51. package/dist/chunk-ASU6CUTZ.js +85 -0
  52. package/dist/chunk-ASU6CUTZ.js.map +1 -0
  53. package/dist/chunk-EWSBFU54.js +53 -0
  54. package/dist/chunk-EWSBFU54.js.map +1 -0
  55. package/dist/chunk-G4ZQUSAJ.js +38 -0
  56. package/dist/chunk-G4ZQUSAJ.js.map +1 -0
  57. package/dist/chunk-GMCUXEFI.js +67 -0
  58. package/dist/chunk-GMCUXEFI.js.map +1 -0
  59. package/dist/chunk-HBBOR43A.js +85 -0
  60. package/dist/chunk-HBBOR43A.js.map +1 -0
  61. package/dist/chunk-HCA5ODCD.js +11 -0
  62. package/dist/chunk-HCA5ODCD.js.map +1 -0
  63. package/dist/chunk-HYRJYUPI.js +26 -0
  64. package/dist/chunk-HYRJYUPI.js.map +1 -0
  65. package/dist/chunk-IRCTGJQB.js +26 -0
  66. package/dist/chunk-IRCTGJQB.js.map +1 -0
  67. package/dist/chunk-JDE5XYPT.js +30 -0
  68. package/dist/chunk-JDE5XYPT.js.map +1 -0
  69. package/dist/chunk-JSJEEKR3.js +59 -0
  70. package/dist/chunk-JSJEEKR3.js.map +1 -0
  71. package/dist/chunk-KR3BCFP7.js +85 -0
  72. package/dist/chunk-KR3BCFP7.js.map +1 -0
  73. package/dist/chunk-MQT5RAQV.js +202 -0
  74. package/dist/chunk-MQT5RAQV.js.map +1 -0
  75. package/dist/chunk-MUPW2TFJ.js +102 -0
  76. package/dist/chunk-MUPW2TFJ.js.map +1 -0
  77. package/dist/chunk-PM2VE7DJ.js +100 -0
  78. package/dist/chunk-PM2VE7DJ.js.map +1 -0
  79. package/dist/chunk-PPYR3O3L.js +44 -0
  80. package/dist/chunk-PPYR3O3L.js.map +1 -0
  81. package/dist/chunk-PUTC52SI.js +98 -0
  82. package/dist/chunk-PUTC52SI.js.map +1 -0
  83. package/dist/chunk-PVK4WQJZ.js +513 -0
  84. package/dist/chunk-PVK4WQJZ.js.map +1 -0
  85. package/dist/chunk-PWAKTEXF.js +18 -0
  86. package/dist/chunk-PWAKTEXF.js.map +1 -0
  87. package/dist/chunk-QTFWORA7.js +26 -0
  88. package/dist/chunk-QTFWORA7.js.map +1 -0
  89. package/dist/chunk-RUPL2H6V.js +49 -0
  90. package/dist/chunk-RUPL2H6V.js.map +1 -0
  91. package/dist/chunk-S7PVZAPL.js +28 -0
  92. package/dist/chunk-S7PVZAPL.js.map +1 -0
  93. package/dist/chunk-SQDV2AKJ.js +49 -0
  94. package/dist/chunk-SQDV2AKJ.js.map +1 -0
  95. package/dist/chunk-T2KXVH3O.js +297 -0
  96. package/dist/chunk-T2KXVH3O.js.map +1 -0
  97. package/dist/chunk-T4WCCHJQ.js +29 -0
  98. package/dist/chunk-T4WCCHJQ.js.map +1 -0
  99. package/dist/chunk-UC3ZIQPE.js +93 -0
  100. package/dist/chunk-UC3ZIQPE.js.map +1 -0
  101. package/dist/chunk-UE7JY7VR.js +28 -0
  102. package/dist/chunk-UE7JY7VR.js.map +1 -0
  103. package/dist/chunk-WVNRFO5F.js +70 -0
  104. package/dist/chunk-WVNRFO5F.js.map +1 -0
  105. package/dist/chunk-Y5WCT6XN.js +93 -0
  106. package/dist/chunk-Y5WCT6XN.js.map +1 -0
  107. package/dist/chunk-YDICVETX.js +151 -0
  108. package/dist/chunk-YDICVETX.js.map +1 -0
  109. package/dist/chunk-YSU4VWRD.js +90 -0
  110. package/dist/chunk-YSU4VWRD.js.map +1 -0
  111. package/dist/chunk-ZFSQVMLJ.js +126 -0
  112. package/dist/chunk-ZFSQVMLJ.js.map +1 -0
  113. package/dist/chunk-ZHATD73Y.js +46 -0
  114. package/dist/chunk-ZHATD73Y.js.map +1 -0
  115. package/dist/chunk-ZLAA4DGG.js +111 -0
  116. package/dist/chunk-ZLAA4DGG.js.map +1 -0
  117. package/dist/chunk-ZP252OJZ.js +56 -0
  118. package/dist/chunk-ZP252OJZ.js.map +1 -0
  119. package/dist/clipboard.cjs +125 -0
  120. package/dist/clipboard.cjs.map +1 -0
  121. package/dist/clipboard.d.cts +52 -0
  122. package/dist/clipboard.d.ts +52 -0
  123. package/dist/clipboard.js +23 -0
  124. package/dist/clipboard.js.map +1 -0
  125. package/dist/collapsible.cjs +94 -0
  126. package/dist/collapsible.cjs.map +1 -0
  127. package/dist/collapsible.d.cts +21 -0
  128. package/dist/collapsible.d.ts +21 -0
  129. package/dist/collapsible.js +9 -0
  130. package/dist/collapsible.js.map +1 -0
  131. package/dist/confirm-dialog.cjs +369 -0
  132. package/dist/confirm-dialog.cjs.map +1 -0
  133. package/dist/confirm-dialog.d.cts +16 -0
  134. package/dist/confirm-dialog.d.ts +16 -0
  135. package/dist/confirm-dialog.js +13 -0
  136. package/dist/confirm-dialog.js.map +1 -0
  137. package/dist/copy-button.cjs +102 -0
  138. package/dist/copy-button.cjs.map +1 -0
  139. package/dist/copy-button.d.cts +18 -0
  140. package/dist/copy-button.d.ts +18 -0
  141. package/dist/copy-button.js +10 -0
  142. package/dist/copy-button.js.map +1 -0
  143. package/dist/data-table.cjs +140 -0
  144. package/dist/data-table.cjs.map +1 -0
  145. package/dist/data-table.d.cts +81 -0
  146. package/dist/data-table.d.ts +81 -0
  147. package/dist/data-table.js +8 -0
  148. package/dist/data-table.js.map +1 -0
  149. package/dist/date-range-picker/dateRange.cjs +138 -0
  150. package/dist/date-range-picker/dateRange.cjs.map +1 -0
  151. package/dist/date-range-picker/dateRange.d.cts +57 -0
  152. package/dist/date-range-picker/dateRange.d.ts +57 -0
  153. package/dist/date-range-picker/dateRange.js +31 -0
  154. package/dist/date-range-picker/dateRange.js.map +1 -0
  155. package/dist/date-range-picker/index.cjs +375 -0
  156. package/dist/date-range-picker/index.cjs.map +1 -0
  157. package/dist/date-range-picker/index.d.cts +18 -0
  158. package/dist/date-range-picker/index.d.ts +18 -0
  159. package/dist/date-range-picker/index.js +10 -0
  160. package/dist/date-range-picker/index.js.map +1 -0
  161. package/dist/dialogLayer.cjs +121 -0
  162. package/dist/dialogLayer.cjs.map +1 -0
  163. package/dist/dialogLayer.d.cts +11 -0
  164. package/dist/dialogLayer.d.ts +11 -0
  165. package/dist/dialogLayer.js +8 -0
  166. package/dist/dialogLayer.js.map +1 -0
  167. package/dist/feature-access-gate.cjs +160 -0
  168. package/dist/feature-access-gate.cjs.map +1 -0
  169. package/dist/feature-access-gate.d.cts +14 -0
  170. package/dist/feature-access-gate.d.ts +14 -0
  171. package/dist/feature-access-gate.js +11 -0
  172. package/dist/feature-access-gate.js.map +1 -0
  173. package/dist/field.cjs +58 -0
  174. package/dist/field.cjs.map +1 -0
  175. package/dist/field.d.cts +23 -0
  176. package/dist/field.d.ts +23 -0
  177. package/dist/field.js +8 -0
  178. package/dist/field.js.map +1 -0
  179. package/dist/image-uploader.cjs +293 -0
  180. package/dist/image-uploader.cjs.map +1 -0
  181. package/dist/image-uploader.d.cts +34 -0
  182. package/dist/image-uploader.d.ts +34 -0
  183. package/dist/image-uploader.js +12 -0
  184. package/dist/image-uploader.js.map +1 -0
  185. package/dist/index.cjs +3012 -0
  186. package/dist/index.cjs.map +1 -0
  187. package/dist/index.d.cts +41 -0
  188. package/dist/index.d.ts +41 -0
  189. package/dist/index.js +232 -0
  190. package/dist/index.js.map +1 -0
  191. package/dist/input.cjs +58 -0
  192. package/dist/input.cjs.map +1 -0
  193. package/dist/input.d.cts +7 -0
  194. package/dist/input.d.ts +7 -0
  195. package/dist/input.js +10 -0
  196. package/dist/input.js.map +1 -0
  197. package/dist/label.cjs +67 -0
  198. package/dist/label.cjs.map +1 -0
  199. package/dist/label.d.cts +7 -0
  200. package/dist/label.d.ts +7 -0
  201. package/dist/label.js +9 -0
  202. package/dist/label.js.map +1 -0
  203. package/dist/modal.cjs +212 -0
  204. package/dist/modal.cjs.map +1 -0
  205. package/dist/modal.d.cts +39 -0
  206. package/dist/modal.d.ts +39 -0
  207. package/dist/modal.js +12 -0
  208. package/dist/modal.js.map +1 -0
  209. package/dist/page-header.cjs +78 -0
  210. package/dist/page-header.cjs.map +1 -0
  211. package/dist/page-header.d.cts +35 -0
  212. package/dist/page-header.d.ts +35 -0
  213. package/dist/page-header.js +8 -0
  214. package/dist/page-header.js.map +1 -0
  215. package/dist/pagination.cjs +237 -0
  216. package/dist/pagination.cjs.map +1 -0
  217. package/dist/pagination.d.cts +15 -0
  218. package/dist/pagination.d.ts +15 -0
  219. package/dist/pagination.js +11 -0
  220. package/dist/pagination.js.map +1 -0
  221. package/dist/panel-brand-mark.cjs +59 -0
  222. package/dist/panel-brand-mark.cjs.map +1 -0
  223. package/dist/panel-brand-mark.d.cts +13 -0
  224. package/dist/panel-brand-mark.d.ts +13 -0
  225. package/dist/panel-brand-mark.js +8 -0
  226. package/dist/panel-brand-mark.js.map +1 -0
  227. package/dist/panel-sign-in.cjs +256 -0
  228. package/dist/panel-sign-in.cjs.map +1 -0
  229. package/dist/panel-sign-in.d.cts +31 -0
  230. package/dist/panel-sign-in.d.ts +31 -0
  231. package/dist/panel-sign-in.js +14 -0
  232. package/dist/panel-sign-in.js.map +1 -0
  233. package/dist/segmented-control.cjs +126 -0
  234. package/dist/segmented-control.cjs.map +1 -0
  235. package/dist/segmented-control.d.cts +60 -0
  236. package/dist/segmented-control.d.ts +60 -0
  237. package/dist/segmented-control.js +9 -0
  238. package/dist/segmented-control.js.map +1 -0
  239. package/dist/select.cjs +648 -0
  240. package/dist/select.cjs.map +1 -0
  241. package/dist/select.d.cts +30 -0
  242. package/dist/select.d.ts +30 -0
  243. package/dist/select.js +12 -0
  244. package/dist/select.js.map +1 -0
  245. package/dist/separator.cjs +70 -0
  246. package/dist/separator.cjs.map +1 -0
  247. package/dist/separator.d.cts +13 -0
  248. package/dist/separator.d.ts +13 -0
  249. package/dist/separator.js +9 -0
  250. package/dist/separator.js.map +1 -0
  251. package/dist/side-drawer.cjs +321 -0
  252. package/dist/side-drawer.cjs.map +1 -0
  253. package/dist/side-drawer.d.cts +21 -0
  254. package/dist/side-drawer.d.ts +21 -0
  255. package/dist/side-drawer.js +13 -0
  256. package/dist/side-drawer.js.map +1 -0
  257. package/dist/spinner.cjs +57 -0
  258. package/dist/spinner.cjs.map +1 -0
  259. package/{src/spinner.tsx → dist/spinner.d.cts} +11 -22
  260. package/dist/spinner.d.ts +27 -0
  261. package/dist/spinner.js +8 -0
  262. package/dist/spinner.js.map +1 -0
  263. package/dist/spreadsheet-grid.cjs +238 -0
  264. package/dist/spreadsheet-grid.cjs.map +1 -0
  265. package/dist/spreadsheet-grid.d.cts +48 -0
  266. package/dist/spreadsheet-grid.d.ts +48 -0
  267. package/dist/spreadsheet-grid.js +8 -0
  268. package/dist/spreadsheet-grid.js.map +1 -0
  269. package/dist/state-panel.cjs +86 -0
  270. package/dist/state-panel.cjs.map +1 -0
  271. package/dist/state-panel.d.cts +23 -0
  272. package/dist/state-panel.d.ts +23 -0
  273. package/dist/state-panel.js +9 -0
  274. package/dist/state-panel.js.map +1 -0
  275. package/dist/switch.cjs +87 -0
  276. package/dist/switch.cjs.map +1 -0
  277. package/dist/switch.d.cts +13 -0
  278. package/dist/switch.d.ts +13 -0
  279. package/dist/switch.js +9 -0
  280. package/dist/switch.js.map +1 -0
  281. package/dist/table.cjs +139 -0
  282. package/dist/table.cjs.map +1 -0
  283. package/dist/table.d.cts +16 -0
  284. package/dist/table.d.ts +16 -0
  285. package/dist/table.js +22 -0
  286. package/dist/table.js.map +1 -0
  287. package/dist/tabs.cjs +168 -0
  288. package/dist/tabs.cjs.map +1 -0
  289. package/dist/tabs.d.cts +59 -0
  290. package/dist/tabs.d.ts +59 -0
  291. package/dist/tabs.js +11 -0
  292. package/dist/tabs.js.map +1 -0
  293. package/dist/textarea.cjs +66 -0
  294. package/dist/textarea.cjs.map +1 -0
  295. package/dist/textarea.d.cts +18 -0
  296. package/dist/textarea.d.ts +18 -0
  297. package/dist/textarea.js +10 -0
  298. package/dist/textarea.js.map +1 -0
  299. package/dist/utils.cjs +35 -0
  300. package/dist/utils.cjs.map +1 -0
  301. package/dist/utils.d.cts +5 -0
  302. package/dist/utils.d.ts +5 -0
  303. package/dist/utils.js +7 -0
  304. package/dist/utils.js.map +1 -0
  305. package/package.json +395 -19
  306. package/src/alert.tsx +0 -74
  307. package/src/autocomplete.tsx +0 -666
  308. package/src/badge.tsx +0 -60
  309. package/src/breadcrumb.tsx +0 -71
  310. package/src/button.tsx +0 -113
  311. package/src/card.tsx +0 -79
  312. package/src/clipboard.ts +0 -144
  313. package/src/collapsible.tsx +0 -63
  314. package/src/confirm-dialog.tsx +0 -84
  315. package/src/copy-button.tsx +0 -58
  316. package/src/data-table.tsx +0 -190
  317. package/src/date-range-picker/dateRange.ts +0 -142
  318. package/src/date-range-picker/index.tsx +0 -366
  319. package/src/dialogLayer.ts +0 -142
  320. package/src/feature-access-gate.tsx +0 -38
  321. package/src/field.tsx +0 -56
  322. package/src/image-uploader.tsx +0 -181
  323. package/src/index.ts +0 -37
  324. package/src/input.tsx +0 -16
  325. package/src/label.tsx +0 -23
  326. package/src/modal.tsx +0 -117
  327. package/src/page-header.tsx +0 -75
  328. package/src/pagination.tsx +0 -116
  329. package/src/panel-brand-mark.tsx +0 -32
  330. package/src/panel-sign-in.tsx +0 -134
  331. package/src/segmented-control.tsx +0 -155
  332. package/src/select.tsx +0 -105
  333. package/src/separator.tsx +0 -32
  334. package/src/side-drawer.tsx +0 -87
  335. package/src/spreadsheet-grid.tsx +0 -264
  336. package/src/state-panel.tsx +0 -46
  337. package/src/switch.tsx +0 -46
  338. package/src/table.tsx +0 -110
  339. package/src/tabs.tsx +0 -201
  340. package/src/textarea.tsx +0 -32
  341. package/src/utils.ts +0 -6
@@ -0,0 +1,13 @@
1
+ import * as React from 'react';
2
+
3
+ type PanelBrandMarkProps = React.HTMLAttributes<HTMLDivElement> & {
4
+ /** Icon inside the mark (lucide, etc.). */
5
+ children: React.ReactNode;
6
+ size?: "sm" | "md";
7
+ };
8
+ /**
9
+ * Quiet brand tile for sidebar / sign-in — solid primary, no decorative gradients.
10
+ */
11
+ declare function PanelBrandMark({ children, size, className, ...props }: PanelBrandMarkProps): React.JSX.Element;
12
+
13
+ export { PanelBrandMark, type PanelBrandMarkProps };
@@ -0,0 +1,8 @@
1
+ import {
2
+ PanelBrandMark
3
+ } from "./chunk-JDE5XYPT.js";
4
+ import "./chunk-HCA5ODCD.js";
5
+ export {
6
+ PanelBrandMark
7
+ };
8
+ //# sourceMappingURL=panel-brand-mark.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -0,0 +1,256 @@
1
+ "use client";
2
+ "use strict";
3
+ "use client";
4
+ var __create = Object.create;
5
+ var __defProp = Object.defineProperty;
6
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
7
+ var __getOwnPropNames = Object.getOwnPropertyNames;
8
+ var __getProtoOf = Object.getPrototypeOf;
9
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
10
+ var __export = (target, all) => {
11
+ for (var name in all)
12
+ __defProp(target, name, { get: all[name], enumerable: true });
13
+ };
14
+ var __copyProps = (to, from, except, desc) => {
15
+ if (from && typeof from === "object" || typeof from === "function") {
16
+ for (let key of __getOwnPropNames(from))
17
+ if (!__hasOwnProp.call(to, key) && key !== except)
18
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
19
+ }
20
+ return to;
21
+ };
22
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
23
+ // If the importer is in node compatibility mode or this is not an ESM
24
+ // file that has been converted to a CommonJS file using a Babel-
25
+ // compatible transform (i.e. "__esModule" has not been set), then set
26
+ // "default" to the CommonJS "module.exports" for node compatibility.
27
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
28
+ mod
29
+ ));
30
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
31
+
32
+ // src/panel-sign-in.tsx
33
+ var panel_sign_in_exports = {};
34
+ __export(panel_sign_in_exports, {
35
+ PanelSignIn: () => PanelSignIn,
36
+ PanelSignInSkeleton: () => PanelSignInSkeleton
37
+ });
38
+ module.exports = __toCommonJS(panel_sign_in_exports);
39
+ var import_lucide_react2 = require("lucide-react");
40
+
41
+ // src/button.tsx
42
+ var React = __toESM(require("react"), 1);
43
+ var import_class_variance_authority = require("class-variance-authority");
44
+ var import_react_slot = require("@radix-ui/react-slot");
45
+
46
+ // src/spinner.tsx
47
+ var import_lucide_react = require("lucide-react");
48
+
49
+ // src/utils.ts
50
+ var import_clsx = require("clsx");
51
+ var import_tailwind_merge = require("tailwind-merge");
52
+ function cn(...inputs) {
53
+ return (0, import_tailwind_merge.twMerge)((0, import_clsx.clsx)(inputs));
54
+ }
55
+
56
+ // src/spinner.tsx
57
+ var import_jsx_runtime = require("react/jsx-runtime");
58
+ var SIZES = {
59
+ sm: "size-3.5",
60
+ md: "size-4",
61
+ lg: "size-5",
62
+ xl: "size-10 border-2"
63
+ };
64
+ function Spinner({ size = "md", className, ...props }) {
65
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
66
+ import_lucide_react.Loader2,
67
+ {
68
+ "aria-hidden": true,
69
+ className: cn("animate-spin", SIZES[size], className),
70
+ ...props
71
+ }
72
+ );
73
+ }
74
+
75
+ // src/button.tsx
76
+ var import_jsx_runtime2 = require("react/jsx-runtime");
77
+ var buttonVariants = (0, import_class_variance_authority.cva)(
78
+ "inline-flex h-9 cursor-pointer items-center justify-center gap-2 whitespace-nowrap rounded-md px-3 text-sm font-medium transition duration-200 active:scale-[0.98] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50",
79
+ {
80
+ variants: {
81
+ variant: {
82
+ default: "bg-primary text-primary-foreground hover:bg-primary/90",
83
+ secondary: "bg-muted text-foreground hover:bg-muted/80",
84
+ ghost: "hover:bg-muted",
85
+ destructive: "bg-destructive text-destructive-foreground hover:bg-destructive/90",
86
+ outline: "border border-border bg-background hover:bg-muted"
87
+ },
88
+ size: {
89
+ sm: "h-8 px-2.5",
90
+ md: "h-9 px-3",
91
+ lg: "h-10 px-4",
92
+ icon: "h-9 w-9 px-0",
93
+ // Square, matching `sm`'s height — for an icon-only control sitting in
94
+ // a table row or beside `sm` buttons, where `icon` is a row taller.
95
+ "icon-sm": "h-8 w-8 px-0"
96
+ }
97
+ },
98
+ defaultVariants: {
99
+ variant: "default",
100
+ size: "md"
101
+ }
102
+ }
103
+ );
104
+ var ICON_SIZES = /* @__PURE__ */ new Set(["icon", "icon-sm"]);
105
+ var Button = React.forwardRef(
106
+ ({
107
+ className,
108
+ variant,
109
+ size,
110
+ asChild = false,
111
+ loading,
112
+ disabled,
113
+ children,
114
+ ...props
115
+ }, ref) => {
116
+ const Comp = asChild ? import_react_slot.Slot : "button";
117
+ if (asChild) {
118
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
119
+ Comp,
120
+ {
121
+ ref,
122
+ className: cn(buttonVariants({ variant, size }), className),
123
+ ...props,
124
+ children
125
+ }
126
+ );
127
+ }
128
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
129
+ "button",
130
+ {
131
+ ref,
132
+ disabled: disabled || loading,
133
+ "aria-busy": loading || void 0,
134
+ className: cn(buttonVariants({ variant, size }), className),
135
+ ...props,
136
+ children: [
137
+ loading ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Spinner, { size: "sm" }) : null,
138
+ loading && size != null && ICON_SIZES.has(size) ? null : children
139
+ ]
140
+ }
141
+ );
142
+ }
143
+ );
144
+ Button.displayName = "Button";
145
+
146
+ // src/panel-brand-mark.tsx
147
+ var import_jsx_runtime3 = require("react/jsx-runtime");
148
+ function PanelBrandMark({
149
+ children,
150
+ size = "md",
151
+ className,
152
+ ...props
153
+ }) {
154
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
155
+ "div",
156
+ {
157
+ className: cn(
158
+ "bg-primary text-primary-foreground grid shrink-0 place-items-center rounded-lg",
159
+ size === "sm" ? "h-9 w-9" : "h-10 w-10",
160
+ className
161
+ ),
162
+ ...props,
163
+ children
164
+ }
165
+ );
166
+ }
167
+
168
+ // src/panel-sign-in.tsx
169
+ var import_jsx_runtime4 = require("react/jsx-runtime");
170
+ function PanelSignIn({
171
+ appName,
172
+ eyebrow = "Secure Google sign-in",
173
+ description = "Use your work Google account to continue.",
174
+ features,
175
+ brandIcon,
176
+ error,
177
+ refused = false,
178
+ refusedTitle = "Access denied",
179
+ refusedMessage = "This Google account is signed in, but it is not provisioned for this panel.",
180
+ isSessionLoading = false,
181
+ isSigningIn = false,
182
+ onSignIn,
183
+ signInLabel = "Continue with Google",
184
+ className
185
+ }) {
186
+ const busy = isSessionLoading || isSigningIn;
187
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
188
+ "main",
189
+ {
190
+ className: cn(
191
+ "bg-background text-foreground grid min-h-screen place-items-center p-4 sm:p-8",
192
+ className
193
+ ),
194
+ children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("section", { className: "border-border bg-card w-full max-w-md space-y-6 rounded-lg border p-8 shadow-sm", children: [
195
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "flex items-center gap-3", children: [
196
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(PanelBrandMark, { children: brandIcon ?? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "text-sm font-semibold", "aria-hidden": true, children: appName.slice(0, 1).toUpperCase() }) }),
197
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "min-w-0", children: [
198
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "text-title truncate font-semibold", children: appName }),
199
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "text-muted-foreground text-meta", children: eyebrow })
200
+ ] })
201
+ ] }),
202
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "space-y-2", children: [
203
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("h1", { className: "text-display font-semibold tracking-tight", children: refused ? refusedTitle : "Sign in" }),
204
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "text-muted-foreground text-body", children: refused ? refusedMessage : description })
205
+ ] }),
206
+ features && features.length > 0 && !refused ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("ul", { className: "text-muted-foreground text-body space-y-1.5", children: features.slice(0, 3).map((feature) => /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("li", { className: "flex gap-2", children: [
207
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "text-foreground mt-1.5 h-1 w-1 shrink-0 rounded-full bg-current" }),
208
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { children: feature })
209
+ ] }, feature)) }) : null,
210
+ error ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
211
+ "p",
212
+ {
213
+ role: "alert",
214
+ className: "border-destructive/30 bg-destructive/5 text-destructive rounded-md border px-3 py-2 text-sm",
215
+ children: error
216
+ }
217
+ ) : null,
218
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
219
+ Button,
220
+ {
221
+ className: "w-full",
222
+ disabled: busy,
223
+ onClick: onSignIn,
224
+ "aria-busy": busy,
225
+ children: [
226
+ busy ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_lucide_react2.Loader2, { className: "mr-2 h-4 w-4 animate-spin", "aria-hidden": true }) : null,
227
+ isSigningIn ? "Redirecting\u2026" : signInLabel
228
+ ]
229
+ }
230
+ )
231
+ ] })
232
+ }
233
+ );
234
+ }
235
+ function PanelSignInSkeleton({ className }) {
236
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
237
+ "main",
238
+ {
239
+ className: cn(
240
+ "bg-background grid min-h-screen place-items-center p-4 sm:p-8",
241
+ className
242
+ ),
243
+ children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "border-border bg-card w-full max-w-md space-y-4 rounded-lg border p-8 shadow-sm", children: [
244
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "bg-muted h-3 w-24 animate-pulse rounded" }),
245
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "bg-muted h-8 w-48 animate-pulse rounded" }),
246
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "bg-muted mt-7 h-10 w-full animate-pulse rounded-md" })
247
+ ] })
248
+ }
249
+ );
250
+ }
251
+ // Annotate the CommonJS export names for ESM import in node:
252
+ 0 && (module.exports = {
253
+ PanelSignIn,
254
+ PanelSignInSkeleton
255
+ });
256
+ //# sourceMappingURL=panel-sign-in.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/panel-sign-in.tsx","../src/button.tsx","../src/spinner.tsx","../src/utils.ts","../src/panel-brand-mark.tsx"],"sourcesContent":["\"use client\";\n\nimport { Loader2 } from \"lucide-react\";\nimport * as React from \"react\";\n\nimport { Button } from \"./button\";\nimport { PanelBrandMark } from \"./panel-brand-mark\";\nimport { cn } from \"./utils\";\n\nexport type PanelSignInProps = {\n appName: string;\n /** Short line under the brand (e.g. \"Secure Google sign-in\"). */\n eyebrow?: string;\n /** One supporting sentence under the headline. */\n description?: string;\n /** Optional feature bullets — keep to ≤3; DESIGN.md: one job per surface. */\n features?: string[];\n brandIcon?: React.ReactNode;\n error?: string | null;\n /** Google signed in but panel access refused. */\n refused?: boolean;\n refusedTitle?: string;\n refusedMessage?: string;\n isSessionLoading?: boolean;\n isSigningIn?: boolean;\n onSignIn: () => void;\n signInLabel?: string;\n className?: string;\n};\n\n/**\n * DESIGN.md-compliant panel login: brand-first, ink neutrals, no purple glow.\n */\nexport function PanelSignIn({\n appName,\n eyebrow = \"Secure Google sign-in\",\n description = \"Use your work Google account to continue.\",\n features,\n brandIcon,\n error,\n refused = false,\n refusedTitle = \"Access denied\",\n refusedMessage = \"This Google account is signed in, but it is not provisioned for this panel.\",\n isSessionLoading = false,\n isSigningIn = false,\n onSignIn,\n signInLabel = \"Continue with Google\",\n className,\n}: PanelSignInProps) {\n const busy = isSessionLoading || isSigningIn;\n\n return (\n <main\n className={cn(\n \"bg-background text-foreground grid min-h-screen place-items-center p-4 sm:p-8\",\n className,\n )}\n >\n <section className=\"border-border bg-card w-full max-w-md space-y-6 rounded-lg border p-8 shadow-sm\">\n <div className=\"flex items-center gap-3\">\n <PanelBrandMark>\n {brandIcon ?? (\n <span className=\"text-sm font-semibold\" aria-hidden>\n {appName.slice(0, 1).toUpperCase()}\n </span>\n )}\n </PanelBrandMark>\n <div className=\"min-w-0\">\n <p className=\"text-title truncate font-semibold\">{appName}</p>\n <p className=\"text-muted-foreground text-meta\">{eyebrow}</p>\n </div>\n </div>\n\n <div className=\"space-y-2\">\n <h1 className=\"text-display font-semibold tracking-tight\">\n {refused ? refusedTitle : \"Sign in\"}\n </h1>\n <p className=\"text-muted-foreground text-body\">\n {refused ? refusedMessage : description}\n </p>\n </div>\n\n {features && features.length > 0 && !refused ? (\n <ul className=\"text-muted-foreground text-body space-y-1.5\">\n {features.slice(0, 3).map((feature) => (\n <li key={feature} className=\"flex gap-2\">\n <span className=\"text-foreground mt-1.5 h-1 w-1 shrink-0 rounded-full bg-current\" />\n <span>{feature}</span>\n </li>\n ))}\n </ul>\n ) : null}\n\n {error ? (\n <p\n role=\"alert\"\n className=\"border-destructive/30 bg-destructive/5 text-destructive rounded-md border px-3 py-2 text-sm\"\n >\n {error}\n </p>\n ) : null}\n\n <Button\n className=\"w-full\"\n disabled={busy}\n onClick={onSignIn}\n aria-busy={busy}\n >\n {busy ? (\n <Loader2 className=\"mr-2 h-4 w-4 animate-spin\" aria-hidden />\n ) : null}\n {isSigningIn ? \"Redirecting…\" : signInLabel}\n </Button>\n </section>\n </main>\n );\n}\n\nexport function PanelSignInSkeleton({ className }: { className?: string }) {\n return (\n <main\n className={cn(\n \"bg-background grid min-h-screen place-items-center p-4 sm:p-8\",\n className,\n )}\n >\n <div className=\"border-border bg-card w-full max-w-md space-y-4 rounded-lg border p-8 shadow-sm\">\n <div className=\"bg-muted h-3 w-24 animate-pulse rounded\" />\n <div className=\"bg-muted h-8 w-48 animate-pulse rounded\" />\n <div className=\"bg-muted mt-7 h-10 w-full animate-pulse rounded-md\" />\n </div>\n </main>\n );\n}\n","import * as React from \"react\";\nimport { cva, type VariantProps } from \"class-variance-authority\";\nimport { Slot } from \"@radix-ui/react-slot\";\n\nimport { Spinner } from \"./spinner\";\nimport { cn } from \"./utils\";\n\nconst buttonVariants = cva(\n \"inline-flex h-9 cursor-pointer items-center justify-center gap-2 whitespace-nowrap rounded-md px-3 text-sm font-medium transition duration-200 active:scale-[0.98] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50\",\n {\n variants: {\n variant: {\n default: \"bg-primary text-primary-foreground hover:bg-primary/90\",\n secondary: \"bg-muted text-foreground hover:bg-muted/80\",\n ghost: \"hover:bg-muted\",\n destructive:\n \"bg-destructive text-destructive-foreground hover:bg-destructive/90\",\n outline: \"border border-border bg-background hover:bg-muted\",\n },\n size: {\n sm: \"h-8 px-2.5\",\n md: \"h-9 px-3\",\n lg: \"h-10 px-4\",\n icon: \"h-9 w-9 px-0\",\n // Square, matching `sm`'s height — for an icon-only control sitting in\n // a table row or beside `sm` buttons, where `icon` is a row taller.\n \"icon-sm\": \"h-8 w-8 px-0\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n size: \"md\",\n },\n },\n);\n\nexport interface ButtonProps\n extends\n React.ButtonHTMLAttributes<HTMLButtonElement>,\n VariantProps<typeof buttonVariants> {\n asChild?: boolean;\n /**\n * Work is in flight: shows a spinner, disables the button, and sets\n * `aria-busy`.\n *\n * This exists because the panel had 272 disabled buttons and only 22 that\n * said anything about why — the rest went dead on click with no spinner and\n * no label change, which reads as a broken button rather than a busy one.\n * Making the feedback part of `disabled` rather than something each caller\n * remembers separately is the only way that ratio stays fixed.\n *\n * The label is kept rather than swapped. \"Saving…\" loses which button you\n * pressed, and the spinner already says it is working. An icon-only button\n * is the exception — there is no room beside the glyph, so the spinner takes\n * its place; the `aria-label` is what names the button either way.\n *\n * \"Icon-only\" means an icon `size`. A square button that grew a spinner\n * beside its glyph would not just look wrong, it would resize mid-request\n * and shove whatever sits next to it sideways.\n */\n loading?: boolean;\n}\n\n/** Sizes with no room for a spinner beside the glyph. */\nconst ICON_SIZES = new Set<string>([\"icon\", \"icon-sm\"]);\n\nexport const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(\n (\n {\n className,\n variant,\n size,\n asChild = false,\n loading,\n disabled,\n children,\n ...props\n },\n ref,\n ) => {\n const Comp = asChild ? Slot : \"button\";\n\n // `asChild` renders someone else's element, which may not take a spinner or\n // a disabled attribute — so the busy treatment is only applied to a real\n // button, and passing both is a mistake worth not papering over.\n if (asChild) {\n return (\n <Comp\n ref={ref}\n className={cn(buttonVariants({ variant, size }), className)}\n {...props}\n >\n {children}\n </Comp>\n );\n }\n\n return (\n <button\n ref={ref}\n disabled={disabled || loading}\n aria-busy={loading || undefined}\n className={cn(buttonVariants({ variant, size }), className)}\n {...props}\n >\n {loading ? <Spinner size=\"sm\" /> : null}\n {loading && size != null && ICON_SIZES.has(size) ? null : children}\n </button>\n );\n },\n);\n\nButton.displayName = \"Button\";\n","import * as React from \"react\";\nimport { Loader2 } from \"lucide-react\";\n\nimport { cn } from \"./utils\";\n\n/**\n * The one spinner.\n *\n * There were five spellings of `animate-spin` across twelve files — `h-4 w-4`,\n * `h-5 w-5`, `size-4`, bare, and a hand-drawn ring in `ProtectedRoute` — so the\n * same \"working\" signal came out a different size depending on which panel you\n * were on.\n *\n * It is `aria-hidden` on purpose. A spinner is decoration; what a screen reader\n * needs is the surrounding control's `aria-busy` or the panel's status text,\n * and announcing \"loading\" twice is worse than once. `Button` and `StatePanel`\n * both supply that.\n */\nconst SIZES = {\n sm: \"size-3.5\",\n md: \"size-4\",\n lg: \"size-5\",\n xl: \"size-10 border-2\",\n} as const;\n\nexport interface SpinnerProps extends React.SVGProps<SVGSVGElement> {\n size?: keyof typeof SIZES;\n}\n\nexport function Spinner({ size = \"md\", className, ...props }: SpinnerProps) {\n return (\n <Loader2\n aria-hidden\n className={cn(\"animate-spin\", SIZES[size], className)}\n {...props}\n />\n );\n}\n","import { type ClassValue, clsx } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs));\n}\n","import * as React from \"react\";\n\nimport { cn } from \"./utils\";\n\nexport type PanelBrandMarkProps = React.HTMLAttributes<HTMLDivElement> & {\n /** Icon inside the mark (lucide, etc.). */\n children: React.ReactNode;\n size?: \"sm\" | \"md\";\n};\n\n/**\n * Quiet brand tile for sidebar / sign-in — solid primary, no decorative gradients.\n */\nexport function PanelBrandMark({\n children,\n size = \"md\",\n className,\n ...props\n}: PanelBrandMarkProps) {\n return (\n <div\n className={cn(\n \"bg-primary text-primary-foreground grid shrink-0 place-items-center rounded-lg\",\n size === \"sm\" ? \"h-9 w-9\" : \"h-10 w-10\",\n className,\n )}\n {...props}\n >\n {children}\n </div>\n );\n}\n"],"mappings":"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","names":["import_lucide_react","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime"]}
@@ -0,0 +1,31 @@
1
+ import * as React from 'react';
2
+
3
+ type PanelSignInProps = {
4
+ appName: string;
5
+ /** Short line under the brand (e.g. "Secure Google sign-in"). */
6
+ eyebrow?: string;
7
+ /** One supporting sentence under the headline. */
8
+ description?: string;
9
+ /** Optional feature bullets — keep to ≤3; DESIGN.md: one job per surface. */
10
+ features?: string[];
11
+ brandIcon?: React.ReactNode;
12
+ error?: string | null;
13
+ /** Google signed in but panel access refused. */
14
+ refused?: boolean;
15
+ refusedTitle?: string;
16
+ refusedMessage?: string;
17
+ isSessionLoading?: boolean;
18
+ isSigningIn?: boolean;
19
+ onSignIn: () => void;
20
+ signInLabel?: string;
21
+ className?: string;
22
+ };
23
+ /**
24
+ * DESIGN.md-compliant panel login: brand-first, ink neutrals, no purple glow.
25
+ */
26
+ declare function PanelSignIn({ appName, eyebrow, description, features, brandIcon, error, refused, refusedTitle, refusedMessage, isSessionLoading, isSigningIn, onSignIn, signInLabel, className, }: PanelSignInProps): React.JSX.Element;
27
+ declare function PanelSignInSkeleton({ className }: {
28
+ className?: string;
29
+ }): React.JSX.Element;
30
+
31
+ export { PanelSignIn, type PanelSignInProps, PanelSignInSkeleton };
@@ -0,0 +1,31 @@
1
+ import * as React from 'react';
2
+
3
+ type PanelSignInProps = {
4
+ appName: string;
5
+ /** Short line under the brand (e.g. "Secure Google sign-in"). */
6
+ eyebrow?: string;
7
+ /** One supporting sentence under the headline. */
8
+ description?: string;
9
+ /** Optional feature bullets — keep to ≤3; DESIGN.md: one job per surface. */
10
+ features?: string[];
11
+ brandIcon?: React.ReactNode;
12
+ error?: string | null;
13
+ /** Google signed in but panel access refused. */
14
+ refused?: boolean;
15
+ refusedTitle?: string;
16
+ refusedMessage?: string;
17
+ isSessionLoading?: boolean;
18
+ isSigningIn?: boolean;
19
+ onSignIn: () => void;
20
+ signInLabel?: string;
21
+ className?: string;
22
+ };
23
+ /**
24
+ * DESIGN.md-compliant panel login: brand-first, ink neutrals, no purple glow.
25
+ */
26
+ declare function PanelSignIn({ appName, eyebrow, description, features, brandIcon, error, refused, refusedTitle, refusedMessage, isSessionLoading, isSigningIn, onSignIn, signInLabel, className, }: PanelSignInProps): React.JSX.Element;
27
+ declare function PanelSignInSkeleton({ className }: {
28
+ className?: string;
29
+ }): React.JSX.Element;
30
+
31
+ export { PanelSignIn, type PanelSignInProps, PanelSignInSkeleton };
@@ -0,0 +1,14 @@
1
+ "use client";
2
+ import {
3
+ PanelSignIn,
4
+ PanelSignInSkeleton
5
+ } from "./chunk-PM2VE7DJ.js";
6
+ import "./chunk-JDE5XYPT.js";
7
+ import "./chunk-KR3BCFP7.js";
8
+ import "./chunk-UE7JY7VR.js";
9
+ import "./chunk-HCA5ODCD.js";
10
+ export {
11
+ PanelSignIn,
12
+ PanelSignInSkeleton
13
+ };
14
+ //# sourceMappingURL=panel-sign-in.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -0,0 +1,126 @@
1
+ "use client";
2
+ "use strict";
3
+ "use client";
4
+ var __create = Object.create;
5
+ var __defProp = Object.defineProperty;
6
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
7
+ var __getOwnPropNames = Object.getOwnPropertyNames;
8
+ var __getProtoOf = Object.getPrototypeOf;
9
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
10
+ var __export = (target, all) => {
11
+ for (var name in all)
12
+ __defProp(target, name, { get: all[name], enumerable: true });
13
+ };
14
+ var __copyProps = (to, from, except, desc) => {
15
+ if (from && typeof from === "object" || typeof from === "function") {
16
+ for (let key of __getOwnPropNames(from))
17
+ if (!__hasOwnProp.call(to, key) && key !== except)
18
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
19
+ }
20
+ return to;
21
+ };
22
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
23
+ // If the importer is in node compatibility mode or this is not an ESM
24
+ // file that has been converted to a CommonJS file using a Babel-
25
+ // compatible transform (i.e. "__esModule" has not been set), then set
26
+ // "default" to the CommonJS "module.exports" for node compatibility.
27
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
28
+ mod
29
+ ));
30
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
31
+
32
+ // src/segmented-control.tsx
33
+ var segmented_control_exports = {};
34
+ __export(segmented_control_exports, {
35
+ SegmentedControl: () => SegmentedControl
36
+ });
37
+ module.exports = __toCommonJS(segmented_control_exports);
38
+ var React = __toESM(require("react"), 1);
39
+
40
+ // src/utils.ts
41
+ var import_clsx = require("clsx");
42
+ var import_tailwind_merge = require("tailwind-merge");
43
+ function cn(...inputs) {
44
+ return (0, import_tailwind_merge.twMerge)((0, import_clsx.clsx)(inputs));
45
+ }
46
+
47
+ // src/segmented-control.tsx
48
+ var import_jsx_runtime = require("react/jsx-runtime");
49
+ var TONES = {
50
+ emphasis: {
51
+ on: "bg-slate-950 text-white dark:bg-white dark:text-slate-950",
52
+ off: "text-muted-foreground hover:bg-muted"
53
+ },
54
+ primary: {
55
+ on: "bg-primary text-primary-foreground",
56
+ off: "text-muted-foreground hover:bg-muted"
57
+ }
58
+ };
59
+ var TRACKS = {
60
+ contained: "border-border inline-flex rounded-md border p-0.5",
61
+ loose: "flex flex-wrap gap-2"
62
+ };
63
+ function SegmentedControl({
64
+ options,
65
+ value,
66
+ onChange,
67
+ ariaLabel,
68
+ variant = "contained",
69
+ tone = "emphasis",
70
+ fill = false,
71
+ className
72
+ }) {
73
+ const refs = React.useRef(/* @__PURE__ */ new Map());
74
+ function onKeyDown(event) {
75
+ const step = event.key === "ArrowRight" || event.key === "ArrowDown" ? 1 : event.key === "ArrowLeft" || event.key === "ArrowUp" ? -1 : 0;
76
+ if (step === 0) return;
77
+ const selectable = options.filter((option) => !option.disabled);
78
+ if (selectable.length < 2) return;
79
+ const current = selectable.findIndex((option) => option.value === value);
80
+ const next = selectable[(current + step + selectable.length) % selectable.length];
81
+ event.preventDefault();
82
+ onChange(next.value);
83
+ refs.current.get(next.value)?.focus();
84
+ }
85
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
86
+ "div",
87
+ {
88
+ role: "radiogroup",
89
+ "aria-label": ariaLabel,
90
+ onKeyDown,
91
+ className: cn(TRACKS[variant], className),
92
+ children: options.map((option) => {
93
+ const checked = option.value === value;
94
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
95
+ "button",
96
+ {
97
+ ref: (node) => {
98
+ refs.current.set(option.value, node);
99
+ },
100
+ type: "button",
101
+ role: "radio",
102
+ "aria-checked": checked,
103
+ disabled: option.disabled,
104
+ title: option.title,
105
+ tabIndex: checked ? 0 : -1,
106
+ onClick: () => onChange(option.value),
107
+ className: cn(
108
+ "cursor-pointer rounded px-3 py-1 text-sm font-medium transition",
109
+ "focus-visible:ring-ring focus-visible:ring-2 focus-visible:outline-none",
110
+ "disabled:cursor-not-allowed disabled:opacity-50",
111
+ fill && "flex-1",
112
+ checked ? TONES[tone].on : TONES[tone].off
113
+ ),
114
+ children: option.label
115
+ },
116
+ option.value
117
+ );
118
+ })
119
+ }
120
+ );
121
+ }
122
+ // Annotate the CommonJS export names for ESM import in node:
123
+ 0 && (module.exports = {
124
+ SegmentedControl
125
+ });
126
+ //# sourceMappingURL=segmented-control.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/segmented-control.tsx","../src/utils.ts"],"sourcesContent":["\"use client\";\n\nimport * as React from \"react\";\n\nimport { cn } from \"./utils\";\n\n/**\n * The one-of-N picker seven panels were each drawing by hand.\n *\n * Not `Tabs`, which is a bottom-bordered strip sitting above the content it\n * switches. This is the inline version — a bordered track with the selected\n * option filled in — used for a filter or a setting that sits among other\n * controls rather than heading a panel.\n *\n * **Roles are the reason to use this.** The seven copies had three different\n * ideas about what they were: one said `tablist`/`tab`, one said\n * `group`/`aria-pressed`, and the other five said nothing at all — so on five\n * of seven a screen reader heard a row of unlabelled buttons with no\n * indication which one was active. None of the three was right. `tablist`\n * without a `tabpanel` is a promise the markup does not keep, and\n * `aria-pressed` describes independent toggles, not a choice of one. Picking a\n * value out of a fixed set is a radio group, so that is what this is, with the\n * roving tabindex and arrow keys that come with the role.\n *\n * `tone` keeps both active colours the panels had drifted into: `emphasis` is\n * the near-black/near-white fill five of them used, `primary` the violet\n * accent the other two did. They are genuinely different colours rather than\n * one spelled two ways, so collapsing them is a visual change to two panels\n * and belongs in its own reviewable diff — the same call `DataTable` makes\n * about its two header variants.\n */\nexport interface SegmentedOption<Value extends string> {\n value: Value;\n label: React.ReactNode;\n disabled?: boolean;\n /**\n * Hover text. Worth setting on a disabled option — \"Everyone\" going grey\n * says nothing about which permission would bring it back.\n */\n title?: string;\n}\n\nexport interface SegmentedControlProps<Value extends string> {\n options: ReadonlyArray<SegmentedOption<Value>>;\n value: Value;\n onChange: (value: Value) => void;\n /**\n * Required: the group never has a visible label — the options name the\n * choice between them, which tells you nothing about what is being chosen.\n */\n ariaLabel: string;\n /**\n * `contained` — one bordered track around the options (five panels).\n * `loose` — free-standing pills with a gap between them (two panels).\n */\n variant?: \"contained\" | \"loose\";\n /** See the note above: two real colours, not one spelled twice. */\n tone?: \"emphasis\" | \"primary\";\n /** Options share the width equally, for a control that fills its column. */\n fill?: boolean;\n className?: string;\n}\n\nconst TONES = {\n emphasis: {\n on: \"bg-slate-950 text-white dark:bg-white dark:text-slate-950\",\n off: \"text-muted-foreground hover:bg-muted\",\n },\n primary: {\n on: \"bg-primary text-primary-foreground\",\n off: \"text-muted-foreground hover:bg-muted\",\n },\n} as const;\n\nconst TRACKS = {\n contained: \"border-border inline-flex rounded-md border p-0.5\",\n loose: \"flex flex-wrap gap-2\",\n} as const;\n\nexport function SegmentedControl<Value extends string>({\n options,\n value,\n onChange,\n ariaLabel,\n variant = \"contained\",\n tone = \"emphasis\",\n fill = false,\n className,\n}: SegmentedControlProps<Value>) {\n const refs = React.useRef(new Map<Value, HTMLButtonElement | null>());\n\n function onKeyDown(event: React.KeyboardEvent<HTMLDivElement>) {\n const step =\n event.key === \"ArrowRight\" || event.key === \"ArrowDown\"\n ? 1\n : event.key === \"ArrowLeft\" || event.key === \"ArrowUp\"\n ? -1\n : 0;\n if (step === 0) return;\n\n const selectable = options.filter((option) => !option.disabled);\n if (selectable.length < 2) return;\n\n const current = selectable.findIndex((option) => option.value === value);\n // Wraps, which is what a radio group is expected to do.\n const next =\n selectable[(current + step + selectable.length) % selectable.length];\n\n event.preventDefault();\n onChange(next.value);\n // The newly checked option has to take focus, or the next arrow press is\n // still measured from the old one.\n refs.current.get(next.value)?.focus();\n }\n\n return (\n <div\n role=\"radiogroup\"\n aria-label={ariaLabel}\n onKeyDown={onKeyDown}\n className={cn(TRACKS[variant], className)}\n >\n {options.map((option) => {\n const checked = option.value === value;\n return (\n <button\n key={option.value}\n ref={(node) => {\n refs.current.set(option.value, node);\n }}\n type=\"button\"\n role=\"radio\"\n aria-checked={checked}\n disabled={option.disabled}\n title={option.title}\n // Only the checked option is reachable by Tab; arrows move within\n // the group. Without this a keyboard user pages through every\n // option to get past the control.\n tabIndex={checked ? 0 : -1}\n onClick={() => onChange(option.value)}\n className={cn(\n \"cursor-pointer rounded px-3 py-1 text-sm font-medium transition\",\n \"focus-visible:ring-ring focus-visible:ring-2 focus-visible:outline-none\",\n \"disabled:cursor-not-allowed disabled:opacity-50\",\n fill && \"flex-1\",\n checked ? TONES[tone].on : TONES[tone].off,\n )}\n >\n {option.label}\n </button>\n );\n })}\n </div>\n );\n}\n","import { type ClassValue, clsx } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs));\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAEA,YAAuB;;;ACFvB,kBAAsC;AACtC,4BAAwB;AAEjB,SAAS,MAAM,QAAsB;AAC1C,aAAO,mCAAQ,kBAAK,MAAM,CAAC;AAC7B;;;ADwHU;AA9DV,IAAM,QAAQ;AAAA,EACZ,UAAU;AAAA,IACR,IAAI;AAAA,IACJ,KAAK;AAAA,EACP;AAAA,EACA,SAAS;AAAA,IACP,IAAI;AAAA,IACJ,KAAK;AAAA,EACP;AACF;AAEA,IAAM,SAAS;AAAA,EACb,WAAW;AAAA,EACX,OAAO;AACT;AAEO,SAAS,iBAAuC;AAAA,EACrD;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,UAAU;AAAA,EACV,OAAO;AAAA,EACP,OAAO;AAAA,EACP;AACF,GAAiC;AAC/B,QAAM,OAAa,aAAO,oBAAI,IAAqC,CAAC;AAEpE,WAAS,UAAU,OAA4C;AAC7D,UAAM,OACJ,MAAM,QAAQ,gBAAgB,MAAM,QAAQ,cACxC,IACA,MAAM,QAAQ,eAAe,MAAM,QAAQ,YACzC,KACA;AACR,QAAI,SAAS,EAAG;AAEhB,UAAM,aAAa,QAAQ,OAAO,CAAC,WAAW,CAAC,OAAO,QAAQ;AAC9D,QAAI,WAAW,SAAS,EAAG;AAE3B,UAAM,UAAU,WAAW,UAAU,CAAC,WAAW,OAAO,UAAU,KAAK;AAEvE,UAAM,OACJ,YAAY,UAAU,OAAO,WAAW,UAAU,WAAW,MAAM;AAErE,UAAM,eAAe;AACrB,aAAS,KAAK,KAAK;AAGnB,SAAK,QAAQ,IAAI,KAAK,KAAK,GAAG,MAAM;AAAA,EACtC;AAEA,SACE;AAAA,IAAC;AAAA;AAAA,MACC,MAAK;AAAA,MACL,cAAY;AAAA,MACZ;AAAA,MACA,WAAW,GAAG,OAAO,OAAO,GAAG,SAAS;AAAA,MAEvC,kBAAQ,IAAI,CAAC,WAAW;AACvB,cAAM,UAAU,OAAO,UAAU;AACjC,eACE;AAAA,UAAC;AAAA;AAAA,YAEC,KAAK,CAAC,SAAS;AACb,mBAAK,QAAQ,IAAI,OAAO,OAAO,IAAI;AAAA,YACrC;AAAA,YACA,MAAK;AAAA,YACL,MAAK;AAAA,YACL,gBAAc;AAAA,YACd,UAAU,OAAO;AAAA,YACjB,OAAO,OAAO;AAAA,YAId,UAAU,UAAU,IAAI;AAAA,YACxB,SAAS,MAAM,SAAS,OAAO,KAAK;AAAA,YACpC,WAAW;AAAA,cACT;AAAA,cACA;AAAA,cACA;AAAA,cACA,QAAQ;AAAA,cACR,UAAU,MAAM,IAAI,EAAE,KAAK,MAAM,IAAI,EAAE;AAAA,YACzC;AAAA,YAEC,iBAAO;AAAA;AAAA,UAtBH,OAAO;AAAA,QAuBd;AAAA,MAEJ,CAAC;AAAA;AAAA,EACH;AAEJ;","names":[]}
@@ -0,0 +1,60 @@
1
+ import * as React from 'react';
2
+
3
+ /**
4
+ * The one-of-N picker seven panels were each drawing by hand.
5
+ *
6
+ * Not `Tabs`, which is a bottom-bordered strip sitting above the content it
7
+ * switches. This is the inline version — a bordered track with the selected
8
+ * option filled in — used for a filter or a setting that sits among other
9
+ * controls rather than heading a panel.
10
+ *
11
+ * **Roles are the reason to use this.** The seven copies had three different
12
+ * ideas about what they were: one said `tablist`/`tab`, one said
13
+ * `group`/`aria-pressed`, and the other five said nothing at all — so on five
14
+ * of seven a screen reader heard a row of unlabelled buttons with no
15
+ * indication which one was active. None of the three was right. `tablist`
16
+ * without a `tabpanel` is a promise the markup does not keep, and
17
+ * `aria-pressed` describes independent toggles, not a choice of one. Picking a
18
+ * value out of a fixed set is a radio group, so that is what this is, with the
19
+ * roving tabindex and arrow keys that come with the role.
20
+ *
21
+ * `tone` keeps both active colours the panels had drifted into: `emphasis` is
22
+ * the near-black/near-white fill five of them used, `primary` the violet
23
+ * accent the other two did. They are genuinely different colours rather than
24
+ * one spelled two ways, so collapsing them is a visual change to two panels
25
+ * and belongs in its own reviewable diff — the same call `DataTable` makes
26
+ * about its two header variants.
27
+ */
28
+ interface SegmentedOption<Value extends string> {
29
+ value: Value;
30
+ label: React.ReactNode;
31
+ disabled?: boolean;
32
+ /**
33
+ * Hover text. Worth setting on a disabled option — "Everyone" going grey
34
+ * says nothing about which permission would bring it back.
35
+ */
36
+ title?: string;
37
+ }
38
+ interface SegmentedControlProps<Value extends string> {
39
+ options: ReadonlyArray<SegmentedOption<Value>>;
40
+ value: Value;
41
+ onChange: (value: Value) => void;
42
+ /**
43
+ * Required: the group never has a visible label — the options name the
44
+ * choice between them, which tells you nothing about what is being chosen.
45
+ */
46
+ ariaLabel: string;
47
+ /**
48
+ * `contained` — one bordered track around the options (five panels).
49
+ * `loose` — free-standing pills with a gap between them (two panels).
50
+ */
51
+ variant?: "contained" | "loose";
52
+ /** See the note above: two real colours, not one spelled twice. */
53
+ tone?: "emphasis" | "primary";
54
+ /** Options share the width equally, for a control that fills its column. */
55
+ fill?: boolean;
56
+ className?: string;
57
+ }
58
+ declare function SegmentedControl<Value extends string>({ options, value, onChange, ariaLabel, variant, tone, fill, className, }: SegmentedControlProps<Value>): React.JSX.Element;
59
+
60
+ export { SegmentedControl, type SegmentedControlProps, type SegmentedOption };