@refraction-ui/react 0.21.0 → 0.23.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 (235) hide show
  1. package/dist/{chunk-ZF3OHCGV.js → chunk-2Q6HHFAN.js} +1 -1
  2. package/dist/chunk-2Q6HHFAN.js.map +7 -0
  3. package/dist/{chunk-533MCMSU.js → chunk-3I3DYDHR.js} +2 -2
  4. package/dist/{chunk-H54FLNAF.js → chunk-63N4PZUJ.js} +2 -2
  5. package/dist/chunk-7P7EJ56S.js +7 -0
  6. package/dist/{chunk-Y2FNNAIL.js → chunk-EGVPAMQU.js} +2 -2
  7. package/dist/chunk-EGVPAMQU.js.map +1 -0
  8. package/dist/{chunk-WK2IIUFO.js → chunk-QDMLIDYN.js} +2 -2
  9. package/dist/{chunk-BOLFYVI6.js → chunk-QPCKJ2YR.js} +2 -2
  10. package/dist/{chunk-TOZBR4GL.js → chunk-RSWOLRIC.js} +4 -4
  11. package/dist/{chunk-TOZBR4GL.js.map → chunk-RSWOLRIC.js.map} +1 -1
  12. package/dist/{chunk-UNEM2TRI.js → chunk-SDAJVXD4.js} +2 -2
  13. package/dist/{chunk-VK3EQ34F.js → chunk-V24GDHUX.js} +2 -2
  14. package/dist/{chunk-XWP763SH.js → chunk-V727VZOE.js} +4 -2
  15. package/dist/{chunk-XWP763SH.js.map → chunk-V727VZOE.js.map} +2 -2
  16. package/dist/{chunk-AMK4VCBG.js → chunk-WYKPPK3W.js} +2 -2
  17. package/dist/{chunk-ONACRMG4.js → chunk-XMFNBOPO.js} +2 -2
  18. package/dist/{chunk-NKCWOPNX.js → chunk-Z5IHYNQD.js} +12 -8
  19. package/dist/chunk-Z5IHYNQD.js.map +7 -0
  20. package/dist/faro-engine-VIUXJAPH-FSARIABU.js +3 -0
  21. package/dist/{faro-engine-47HGRAQH-JKINJPMH.js.map → faro-engine-VIUXJAPH-FSARIABU.js.map} +1 -1
  22. package/dist/form.cjs.map +1 -1
  23. package/dist/form.js +1 -1
  24. package/dist/index.cjs +1305 -302
  25. package/dist/index.cjs.map +1 -1
  26. package/dist/index.d.cts +7 -0
  27. package/dist/index.d.ts +7 -0
  28. package/dist/index.js +7 -0
  29. package/dist/internal/action-list/index.d.ts +39 -0
  30. package/dist/internal/avatar/index.d.cts +4 -1
  31. package/dist/internal/avatar/index.d.ts +4 -1
  32. package/dist/internal/button/index.d.cts +2 -2
  33. package/dist/internal/button/index.d.ts +2 -2
  34. package/dist/internal/card/index.d.cts +5 -1
  35. package/dist/internal/card/index.d.ts +5 -1
  36. package/dist/internal/data-table/index.d.cts +48 -3
  37. package/dist/internal/data-table/index.d.ts +48 -3
  38. package/dist/internal/funnel-chart/index.d.ts +60 -0
  39. package/dist/internal/line-chart/index.d.ts +124 -0
  40. package/dist/internal/native-select/index.d.ts +21 -0
  41. package/dist/internal/page-header/index.d.ts +35 -0
  42. package/dist/internal/react-action-list/index.d.ts +28 -0
  43. package/dist/internal/react-avatar/index.d.cts +4 -2
  44. package/dist/internal/react-avatar/index.d.ts +4 -2
  45. package/dist/internal/react-card/index.d.cts +10 -4
  46. package/dist/internal/react-card/index.d.ts +10 -4
  47. package/dist/internal/react-command/index.d.cts +13 -2
  48. package/dist/internal/react-command/index.d.ts +13 -2
  49. package/dist/internal/react-data-table/index.d.cts +27 -9
  50. package/dist/internal/react-data-table/index.d.ts +27 -9
  51. package/dist/internal/react-dialog/index.d.cts +5 -0
  52. package/dist/internal/react-dialog/index.d.ts +5 -0
  53. package/dist/internal/react-dropdown-menu/index.d.cts +19 -1
  54. package/dist/internal/react-dropdown-menu/index.d.ts +19 -1
  55. package/dist/internal/react-funnel-chart/index.d.ts +28 -0
  56. package/dist/internal/react-line-chart/index.d.ts +38 -0
  57. package/dist/internal/react-native-select/index.d.ts +19 -0
  58. package/dist/internal/react-page-header/index.d.ts +23 -0
  59. package/dist/internal/react-select/index.d.cts +21 -3
  60. package/dist/internal/react-select/index.d.ts +21 -3
  61. package/dist/internal/react-stat-grid/index.d.ts +22 -11
  62. package/dist/internal/react-table/index.d.ts +39 -0
  63. package/dist/internal/select/index.d.cts +14 -1
  64. package/dist/internal/select/index.d.ts +14 -1
  65. package/dist/internal/shared/index.d.cts +6 -3
  66. package/dist/internal/shared/index.d.ts +6 -3
  67. package/dist/internal/stat-grid/index.d.ts +49 -7
  68. package/dist/internal/table/index.d.ts +46 -0
  69. package/dist/internal/tabs/index.d.cts +8 -1
  70. package/dist/internal/tabs/index.d.ts +8 -1
  71. package/dist/react-accordion.js +1 -1
  72. package/dist/react-action-list.js +74 -0
  73. package/dist/react-action-list.js.map +7 -0
  74. package/dist/react-ai.js +1 -1
  75. package/dist/react-analytics.js +16 -4
  76. package/dist/react-analytics.js.map +2 -2
  77. package/dist/react-animated-text.js +1 -1
  78. package/dist/react-app-shell.js +1 -1
  79. package/dist/react-audience-feature-card.js +1 -1
  80. package/dist/react-audio-room.js +1 -1
  81. package/dist/react-auth.js +1 -1
  82. package/dist/react-avatar-group.js +1 -1
  83. package/dist/react-avatar.js +13 -9
  84. package/dist/react-avatar.js.map +2 -2
  85. package/dist/react-badge.js +2 -2
  86. package/dist/react-badge.js.map +1 -1
  87. package/dist/react-bottom-nav.js +1 -1
  88. package/dist/react-brand-network-cell.js +1 -1
  89. package/dist/react-breadcrumbs.js +1 -1
  90. package/dist/react-browser-chrome-mock.js +1 -1
  91. package/dist/react-button.js +3 -3
  92. package/dist/react-calendar.js +1 -1
  93. package/dist/react-call-controls.js +1 -1
  94. package/dist/react-callout.js +8 -3
  95. package/dist/react-callout.js.map +2 -2
  96. package/dist/react-card-grid.js +1 -1
  97. package/dist/react-card.js +5 -5
  98. package/dist/react-card.js.map +2 -2
  99. package/dist/react-carousel.js +1 -1
  100. package/dist/react-charts.js +1 -1
  101. package/dist/react-checkbox.js +1 -1
  102. package/dist/react-checklist.js +1 -1
  103. package/dist/react-code-block.js +1 -1
  104. package/dist/react-code-editor.js +1 -1
  105. package/dist/react-collapsible.js +1 -1
  106. package/dist/react-combobox.js +1 -1
  107. package/dist/react-command-input.js +1 -1
  108. package/dist/react-command.js +115 -70
  109. package/dist/react-command.js.map +3 -3
  110. package/dist/react-composer.js +3 -3
  111. package/dist/react-content-protection.js +1 -1
  112. package/dist/react-conversation.js +5 -5
  113. package/dist/react-cookie-consent.js +1 -1
  114. package/dist/react-data-table.js +125 -114
  115. package/dist/react-data-table.js.map +2 -2
  116. package/dist/react-date-picker.js +1 -1
  117. package/dist/react-device-frame.js +1 -1
  118. package/dist/react-dialog.js +33 -9
  119. package/dist/react-dialog.js.map +2 -2
  120. package/dist/react-diff-viewer.js +1 -1
  121. package/dist/react-dropdown-menu.js +61 -8
  122. package/dist/react-dropdown-menu.js.map +3 -3
  123. package/dist/react-editor-status-bar.js +1 -1
  124. package/dist/react-editor-tabs.js +1 -1
  125. package/dist/react-emoji-picker.js +2 -2
  126. package/dist/react-empty-state.js +1 -1
  127. package/dist/react-feedback-dialog.js +2 -2
  128. package/dist/react-file-tree.js +1 -1
  129. package/dist/react-file-upload.js +1 -1
  130. package/dist/react-floating-reactions.js +1 -1
  131. package/dist/react-flow-editor.js +2 -2
  132. package/dist/react-footer.js +1 -1
  133. package/dist/react-funnel-chart.js +105 -0
  134. package/dist/react-funnel-chart.js.map +7 -0
  135. package/dist/react-graph-view.js +2 -2
  136. package/dist/react-infinite-canvas.js +2 -2
  137. package/dist/react-inline-editor.js +1 -1
  138. package/dist/react-input-group.js +1 -1
  139. package/dist/react-input.js +2 -2
  140. package/dist/react-install-prompt.js +1 -1
  141. package/dist/react-kanban-board.js +1 -1
  142. package/dist/react-keyboard-shortcut.js +2 -2
  143. package/dist/react-language-selector.js +1 -1
  144. package/dist/react-line-chart.js +280 -0
  145. package/dist/react-line-chart.js.map +7 -0
  146. package/dist/react-link-card.js +1 -1
  147. package/dist/react-live-captions.js +1 -1
  148. package/dist/react-live-cursors.js +1 -1
  149. package/dist/react-live-transcript.js +1 -1
  150. package/dist/react-location-selector.js +1 -1
  151. package/dist/react-logger.js +3 -3
  152. package/dist/react-markdown-renderer.js +2 -2
  153. package/dist/react-marquee-strip.js +1 -1
  154. package/dist/react-mascot.js +1 -1
  155. package/dist/react-mastery-bar.js +1 -1
  156. package/dist/react-mini-map.js +1 -1
  157. package/dist/react-mobile-nav.js +1 -1
  158. package/dist/react-native-select.js +52 -0
  159. package/dist/react-native-select.js.map +7 -0
  160. package/dist/react-navbar.js +1 -1
  161. package/dist/react-numbered-steps.js +1 -1
  162. package/dist/react-otp-input.js +1 -1
  163. package/dist/react-page-header.js +40 -0
  164. package/dist/react-page-header.js.map +7 -0
  165. package/dist/react-pagination.js +1 -1
  166. package/dist/react-password-input.js +2 -2
  167. package/dist/react-payment.js +1 -1
  168. package/dist/react-popover.js +1 -1
  169. package/dist/react-pre-call-lobby.js +1 -1
  170. package/dist/react-presence-indicator.js +1 -1
  171. package/dist/react-pricing-card.js +1 -1
  172. package/dist/react-progress-display.js +2 -2
  173. package/dist/react-progress-display.js.map +1 -1
  174. package/dist/react-radial-gauge.js +1 -1
  175. package/dist/react-radio.js +1 -1
  176. package/dist/react-rating-scale.js +1 -1
  177. package/dist/react-reaction-bar.js +1 -1
  178. package/dist/react-resizable-layout.js +1 -1
  179. package/dist/react-search-bar.js +1 -1
  180. package/dist/react-section-head.js +1 -1
  181. package/dist/react-segmented-control.js +1 -1
  182. package/dist/react-select.js +94 -20
  183. package/dist/react-select.js.map +3 -3
  184. package/dist/react-separator.js +1 -1
  185. package/dist/react-sheet.js +1 -1
  186. package/dist/react-sidebar.js +1 -1
  187. package/dist/react-skeleton.js +1 -1
  188. package/dist/react-skip-to-content.js +1 -1
  189. package/dist/react-slide-viewer.js +1 -1
  190. package/dist/react-slider.js +1 -1
  191. package/dist/react-slot-picker.js +1 -1
  192. package/dist/react-social-auth-button.js +3 -3
  193. package/dist/react-sortable-list.js +1 -1
  194. package/dist/react-stat-grid.js +91 -22
  195. package/dist/react-stat-grid.js.map +2 -2
  196. package/dist/react-status-indicator.js +1 -1
  197. package/dist/react-steps.js +1 -1
  198. package/dist/react-sticky-note.js +1 -1
  199. package/dist/react-switch.js +1 -1
  200. package/dist/react-table-of-contents.js +1 -1
  201. package/dist/react-table.js +148 -0
  202. package/dist/react-table.js.map +7 -0
  203. package/dist/react-tabs.js +84 -7
  204. package/dist/react-tabs.js.map +2 -2
  205. package/dist/react-terminal.js +1 -1
  206. package/dist/react-test-results.js +1 -1
  207. package/dist/react-textarea.js +3 -3
  208. package/dist/react-textarea.js.map +1 -1
  209. package/dist/react-thread-view.js +2 -2
  210. package/dist/react-timeline.js +1 -1
  211. package/dist/react-toast.js +1 -1
  212. package/dist/react-tooltip.js +1 -1
  213. package/dist/react-version-selector.js +1 -1
  214. package/dist/react-video-grid.js +2 -2
  215. package/dist/react-video-player.js +1 -1
  216. package/dist/react-video-tile.js +2 -2
  217. package/dist/react-voice-pill.js +1 -1
  218. package/dist/react-waveform.js +1 -1
  219. package/dist/react-wizard.js +1 -1
  220. package/dist/theme.js +1 -1
  221. package/package.json +7 -1
  222. package/dist/chunk-NKCWOPNX.js.map +0 -7
  223. package/dist/chunk-SDZ3LROZ.js +0 -7
  224. package/dist/chunk-Y2FNNAIL.js.map +0 -1
  225. package/dist/chunk-ZF3OHCGV.js.map +0 -7
  226. package/dist/faro-engine-47HGRAQH-JKINJPMH.js +0 -3
  227. /package/dist/{chunk-533MCMSU.js.map → chunk-3I3DYDHR.js.map} +0 -0
  228. /package/dist/{chunk-H54FLNAF.js.map → chunk-63N4PZUJ.js.map} +0 -0
  229. /package/dist/{chunk-SDZ3LROZ.js.map → chunk-7P7EJ56S.js.map} +0 -0
  230. /package/dist/{chunk-WK2IIUFO.js.map → chunk-QDMLIDYN.js.map} +0 -0
  231. /package/dist/{chunk-BOLFYVI6.js.map → chunk-QPCKJ2YR.js.map} +0 -0
  232. /package/dist/{chunk-UNEM2TRI.js.map → chunk-SDAJVXD4.js.map} +0 -0
  233. /package/dist/{chunk-VK3EQ34F.js.map → chunk-V24GDHUX.js.map} +0 -0
  234. /package/dist/{chunk-AMK4VCBG.js.map → chunk-WYKPPK3W.js.map} +0 -0
  235. /package/dist/{chunk-ONACRMG4.js.map → chunk-XMFNBOPO.js.map} +0 -0
@@ -1,12 +1,21 @@
1
1
  import {
2
2
  cn,
3
3
  cva
4
- } from "./chunk-ZF3OHCGV.js";
4
+ } from "./chunk-2Q6HHFAN.js";
5
5
 
6
6
  // ../react-data-table/dist/index.js
7
7
  import * as React from "react";
8
8
 
9
9
  // ../data-table/dist/index.js
10
+ function resolveColumnAlign(col) {
11
+ return col.align ?? (col.numeric ? "end" : "start");
12
+ }
13
+ function getColumnValue(col, row) {
14
+ return col.accessor ? col.accessor(row) : void 0;
15
+ }
16
+ function resolveRowKey(row, index, getRowKey) {
17
+ return getRowKey ? getRowKey(row, index) : index;
18
+ }
10
19
  function createDataTable(props) {
11
20
  const {
12
21
  columns,
@@ -24,10 +33,10 @@ function createDataTable(props) {
24
33
  for (const [columnId, filterValue] of Object.entries(filters)) {
25
34
  if (!filterValue) continue;
26
35
  const col = columns.find((c) => c.id === columnId);
27
- if (!col) continue;
36
+ if (!col?.accessor) continue;
28
37
  const lowerFilter = filterValue.toLowerCase();
29
38
  result = result.filter((row) => {
30
- const cellValue = col.accessor(row);
39
+ const cellValue = getColumnValue(col, row);
31
40
  return String(cellValue ?? "").toLowerCase().includes(lowerFilter);
32
41
  });
33
42
  }
@@ -37,10 +46,10 @@ function createDataTable(props) {
37
46
  const filtered = getFilteredData();
38
47
  if (!sortBy) return filtered;
39
48
  const col = columns.find((c) => c.id === sortBy);
40
- if (!col) return filtered;
49
+ if (!col?.accessor) return filtered;
41
50
  return [...filtered].sort((a, b) => {
42
- const aVal = col.accessor(a);
43
- const bVal = col.accessor(b);
51
+ const aVal = getColumnValue(col, a);
52
+ const bVal = getColumnValue(col, b);
44
53
  const aStr = String(aVal ?? "");
45
54
  const bStr = String(bVal ?? "");
46
55
  const cmp = aStr.localeCompare(bStr, void 0, { numeric: true });
@@ -160,8 +169,21 @@ var rowVariants = cva({
160
169
  selected: "false"
161
170
  }
162
171
  });
172
+ var dataTableAlignClass = {
173
+ start: "text-start",
174
+ center: "text-center",
175
+ end: "text-end"
176
+ };
177
+ var dataTableNumericClass = "tabular-nums whitespace-nowrap";
178
+ var dataTableSortButtonClass = "inline-flex items-center gap-1 rounded-sm font-inherit text-inherit focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring";
179
+ var dataTableActionRowClass = "cursor-pointer focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-ring";
163
180
 
164
181
  // ../react-data-table/dist/index.js
182
+ import { jsx, jsxs } from "react/jsx-runtime";
183
+ var ACTIVATION_KEYS = /* @__PURE__ */ new Set(["Enter", " "]);
184
+ function filterLabel(header, id) {
185
+ return typeof header === "string" || typeof header === "number" ? String(header) : id;
186
+ }
165
187
  function DataTable({
166
188
  columns,
167
189
  data,
@@ -170,13 +192,21 @@ function DataTable({
170
192
  onSort,
171
193
  filters: controlledFilters,
172
194
  className,
173
- emptyMessage = "No data available"
195
+ emptyMessage = "No data available",
196
+ getRowKey,
197
+ getRowProps,
198
+ onRowClick,
199
+ caption,
200
+ wrapperClassName,
201
+ ...tableProps
174
202
  }) {
175
203
  const [sortBy, setSortBy] = React.useState(controlledSortBy ?? null);
176
204
  const [sortDir, setSortDir] = React.useState(controlledSortDir);
177
205
  const [filters, setFilters] = React.useState(controlledFilters ?? {});
178
206
  const api = React.useMemo(
179
207
  () => createDataTable({
208
+ // The core only reads id/accessor/sortable/filterable; header and cell
209
+ // are rendered here.
180
210
  columns,
181
211
  data,
182
212
  sortBy: sortBy ?? void 0,
@@ -186,119 +216,100 @@ function DataTable({
186
216
  }),
187
217
  [columns, data, sortBy, sortDir, onSort, filters]
188
218
  );
189
- const handleSort = React.useCallback(
190
- (columnId) => {
191
- const col = columns.find((c) => c.id === columnId);
192
- if (!col?.sortable) return;
193
- let newDir = "asc";
194
- if (sortBy === columnId) {
195
- newDir = sortDir === "asc" ? "desc" : "asc";
196
- }
197
- setSortBy(columnId);
198
- setSortDir(newDir);
199
- onSort?.(columnId, newDir);
200
- },
201
- [columns, sortBy, sortDir, onSort]
202
- );
203
- const handleFilter = React.useCallback(
204
- (columnId, value) => {
205
- setFilters((prev) => ({ ...prev, [columnId]: value }));
206
- },
207
- []
208
- );
209
- const sortedData = api.state.sortedData;
219
+ const handleSort = (columnId) => {
220
+ const col = columns.find((c) => c.id === columnId);
221
+ if (!col?.sortable) return;
222
+ const newDir = sortBy === columnId && sortDir === "asc" ? "desc" : "asc";
223
+ setSortBy(columnId);
224
+ setSortDir(newDir);
225
+ onSort?.(columnId, newDir);
226
+ };
227
+ const handleFilter = (columnId, value) => {
228
+ setFilters((prev) => ({ ...prev, [columnId]: value }));
229
+ };
230
+ const rows = api.state.sortedData;
210
231
  const hasFilterable = columns.some((c) => c.filterable);
211
- return React.createElement(
212
- "div",
213
- { className: "relative w-full overflow-auto" },
214
- React.createElement(
215
- "table",
216
- {
217
- className: cn(tableVariants(), className),
218
- role: "table"
232
+ const rowElementProps = (row, index) => {
233
+ const extra = getRowProps?.(row, index) ?? {};
234
+ if (!onRowClick) return extra;
235
+ return {
236
+ tabIndex: 0,
237
+ ...extra,
238
+ className: cn(dataTableActionRowClass, extra.className),
239
+ onClick: (e) => {
240
+ extra.onClick?.(e);
241
+ if (!e.defaultPrevented) onRowClick(row, index);
219
242
  },
220
- // thead
221
- React.createElement(
222
- "thead",
223
- null,
224
- // Header row
225
- React.createElement(
226
- "tr",
227
- { role: "row" },
228
- ...columns.map((col) => {
229
- const headerProps = api.getHeaderProps(col);
230
- return React.createElement(
231
- "th",
232
- {
233
- key: col.id,
234
- ...headerProps,
235
- className: headerVariants({ sortable: col.sortable ? "true" : "false" }),
236
- onClick: col.sortable ? () => handleSort(col.id) : void 0
237
- },
243
+ onKeyDown: (e) => {
244
+ extra.onKeyDown?.(e);
245
+ if (e.defaultPrevented || e.target !== e.currentTarget || !ACTIVATION_KEYS.has(e.key)) return;
246
+ e.preventDefault();
247
+ onRowClick(row, index);
248
+ }
249
+ };
250
+ };
251
+ return /* @__PURE__ */ jsx("div", { className: cn("relative w-full overflow-auto", wrapperClassName), children: /* @__PURE__ */ jsxs("table", { className: cn(tableVariants(), className), role: "table", ...tableProps, children: [
252
+ caption != null && /* @__PURE__ */ jsx("caption", { className: "mt-2 caption-bottom text-xs text-muted-foreground", children: caption }),
253
+ /* @__PURE__ */ jsxs("thead", { children: [
254
+ /* @__PURE__ */ jsx("tr", { role: "row", children: columns.map((col) => {
255
+ const headerProps = api.getHeaderProps(col);
256
+ const align = resolveColumnAlign(col);
257
+ const indicator = col.sortable && sortBy === col.id ? /* @__PURE__ */ jsx("span", { "aria-hidden": "true", children: sortDir === "asc" ? "\u2191" : "\u2193" }) : null;
258
+ return /* @__PURE__ */ jsx(
259
+ "th",
260
+ {
261
+ ...headerProps,
262
+ className: cn(
263
+ headerVariants({ sortable: col.sortable ? "true" : "false" }),
264
+ dataTableAlignClass[align],
265
+ col.headerClassName
266
+ ),
267
+ children: col.sortable ? /* @__PURE__ */ jsxs("button", { type: "button", className: dataTableSortButtonClass, onClick: () => handleSort(col.id), children: [
238
268
  col.header,
239
- col.sortable && sortBy === col.id ? React.createElement("span", { "aria-hidden": true }, sortDir === "asc" ? " \u2191" : " \u2193") : null
240
- );
241
- })
242
- ),
243
- // Filter row
244
- hasFilterable ? React.createElement(
245
- "tr",
246
- { role: "row", "data-filter-row": "true" },
247
- ...columns.map(
248
- (col) => React.createElement(
249
- "th",
250
- { key: `filter-${col.id}` },
251
- col.filterable ? React.createElement("input", {
252
- type: "text",
253
- "aria-label": `Filter ${col.header}`,
254
- value: filters[col.id] ?? "",
255
- onChange: (e) => handleFilter(col.id, e.target.value),
256
- placeholder: `Filter...`
257
- }) : null
258
- )
259
- )
260
- ) : null
261
- ),
262
- // tbody
263
- React.createElement(
264
- "tbody",
265
- null,
266
- sortedData.length === 0 ? React.createElement(
267
- "tr",
268
- { role: "row" },
269
- React.createElement(
269
+ indicator
270
+ ] }) : col.header
271
+ },
272
+ col.id
273
+ );
274
+ }) }),
275
+ hasFilterable && /* @__PURE__ */ jsx("tr", { role: "row", "data-filter-row": "true", children: columns.map((col) => /* @__PURE__ */ jsx("th", { children: col.filterable ? /* @__PURE__ */ jsx(
276
+ "input",
277
+ {
278
+ type: "text",
279
+ "aria-label": `Filter ${filterLabel(col.header, col.id)}`,
280
+ value: filters[col.id] ?? "",
281
+ onChange: (e) => handleFilter(col.id, e.target.value),
282
+ placeholder: "Filter..."
283
+ }
284
+ ) : null }, `filter-${col.id}`)) })
285
+ ] }),
286
+ /* @__PURE__ */ jsx("tbody", { children: rows.length === 0 ? /* @__PURE__ */ jsx("tr", { role: "row", children: /* @__PURE__ */ jsx("td", { colSpan: columns.length, className: "text-center p-4 text-muted-foreground", role: "cell", children: emptyMessage }) }) : rows.map((row, rowIndex) => {
287
+ const rowProps = rowElementProps(row, rowIndex);
288
+ return /* @__PURE__ */ jsx(
289
+ "tr",
290
+ {
291
+ ...api.getRowProps(row, rowIndex),
292
+ ...rowProps,
293
+ className: cn(rowVariants(), rowProps.className),
294
+ children: columns.map((col) => /* @__PURE__ */ jsx(
270
295
  "td",
271
296
  {
272
- colSpan: columns.length,
273
- className: "text-center p-4 text-muted-foreground",
274
- role: "cell"
275
- },
276
- emptyMessage
277
- )
278
- ) : sortedData.map(
279
- (row, rowIndex) => React.createElement(
280
- "tr",
281
- {
282
- key: rowIndex,
283
- ...api.getRowProps(row, rowIndex),
284
- className: rowVariants()
297
+ ...api.getCellProps(col, row),
298
+ className: cn(
299
+ cellVariants(),
300
+ dataTableAlignClass[resolveColumnAlign(col)],
301
+ col.numeric && dataTableNumericClass,
302
+ col.className
303
+ ),
304
+ children: col.cell ? col.cell(row, rowIndex) : String(getColumnValue(col, row) ?? "")
285
305
  },
286
- ...columns.map(
287
- (col) => React.createElement(
288
- "td",
289
- {
290
- key: col.id,
291
- ...api.getCellProps(col, row),
292
- className: cellVariants()
293
- },
294
- String(col.accessor(row) ?? "")
295
- )
296
- )
297
- )
298
- )
299
- )
300
- )
301
- );
306
+ col.id
307
+ ))
308
+ },
309
+ resolveRowKey(row, rowIndex, getRowKey)
310
+ );
311
+ }) })
312
+ ] }) });
302
313
  }
303
314
  export {
304
315
  DataTable,
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../data-table/src/data-table.ts", "../../data-table/src/data-table.styles.ts", "../../react-data-table/src/DataTable.tsx"],
4
- "sourcesContent": ["import type { AccessibilityProps } from '@refraction-ui/shared'\n\nexport interface ColumnDef<T = Record<string, unknown>> {\n /** Unique column identifier */\n id: string\n /** Column header text */\n header: string\n /** Accessor function to get cell value from row */\n accessor: (row: T) => unknown\n /** Whether this column is sortable */\n sortable?: boolean\n /** Whether this column is filterable */\n filterable?: boolean\n}\n\nexport type SortDirection = 'asc' | 'desc'\n\nexport interface DataTableProps<T = Record<string, unknown>> {\n /** Column definitions */\n columns: ColumnDef<T>[]\n /** Data rows */\n data: T[]\n /** Current sort column */\n sortBy?: string\n /** Current sort direction */\n sortDir?: SortDirection\n /** Callback when sort changes */\n onSort?: (columnId: string, direction: SortDirection) => void\n /** Active filters: columnId -> filter value */\n filters?: Record<string, string>\n}\n\nexport interface DataTableState<T = Record<string, unknown>> {\n sortedData: T[]\n sortBy: string | null\n sortDir: SortDirection\n filters: Record<string, string>\n}\n\nexport interface DataTableAPI<T = Record<string, unknown>> {\n /** Current table state */\n state: DataTableState<T>\n /** Toggle sort for a column */\n sort(columnId: string): void\n /** Set a filter value for a column */\n setFilter(columnId: string, value: string): void\n /** Get ARIA and role props for a header cell */\n getHeaderProps(col: ColumnDef<T>): Partial<AccessibilityProps> & Record<string, unknown>\n /** Get props for a data cell */\n getCellProps(col: ColumnDef<T>, row: T): Record<string, unknown>\n /** Get props for a data row */\n getRowProps(row: T, index: number): Record<string, unknown>\n}\n\nexport function createDataTable<T = Record<string, unknown>>(\n props: DataTableProps<T>,\n): DataTableAPI<T> {\n const {\n columns,\n data,\n sortBy: initialSortBy,\n sortDir: initialSortDir = 'asc',\n onSort,\n filters: initialFilters,\n } = props\n\n let sortBy: string | null = initialSortBy ?? null\n let sortDir: SortDirection = initialSortDir\n let filters: Record<string, string> = { ...(initialFilters ?? {}) }\n\n function getFilteredData(): T[] {\n let result = [...data]\n\n for (const [columnId, filterValue] of Object.entries(filters)) {\n if (!filterValue) continue\n const col = columns.find((c) => c.id === columnId)\n if (!col) continue\n const lowerFilter = filterValue.toLowerCase()\n result = result.filter((row) => {\n const cellValue = col.accessor(row)\n return String(cellValue ?? '').toLowerCase().includes(lowerFilter)\n })\n }\n\n return result\n }\n\n function getSortedData(): T[] {\n const filtered = getFilteredData()\n\n if (!sortBy) return filtered\n\n const col = columns.find((c) => c.id === sortBy)\n if (!col) return filtered\n\n return [...filtered].sort((a, b) => {\n const aVal = col.accessor(a)\n const bVal = col.accessor(b)\n const aStr = String(aVal ?? '')\n const bStr = String(bVal ?? '')\n\n const cmp = aStr.localeCompare(bStr, undefined, { numeric: true })\n return sortDir === 'asc' ? cmp : -cmp\n })\n }\n\n function sort(columnId: string): void {\n const col = columns.find((c) => c.id === columnId)\n if (!col?.sortable) return\n\n if (sortBy === columnId) {\n sortDir = sortDir === 'asc' ? 'desc' : 'asc'\n } else {\n sortBy = columnId\n sortDir = 'asc'\n }\n\n onSort?.(sortBy, sortDir)\n }\n\n function setFilter(columnId: string, value: string): void {\n filters = { ...filters, [columnId]: value }\n }\n\n function getHeaderProps(\n col: ColumnDef<T>,\n ): Partial<AccessibilityProps> & Record<string, unknown> {\n const props: Partial<AccessibilityProps> & Record<string, unknown> = {\n role: 'columnheader',\n }\n\n if (col.sortable) {\n if (sortBy === col.id) {\n props['aria-sort'] = sortDir === 'asc' ? 'ascending' : 'descending'\n } else {\n props['aria-sort'] = 'none'\n }\n }\n\n return props\n }\n\n function getCellProps(\n col: ColumnDef<T>,\n _row: T,\n ): Record<string, unknown> {\n return {\n role: 'cell',\n 'data-column': col.id,\n }\n }\n\n function getRowProps(_row: T, index: number): Record<string, unknown> {\n return {\n role: 'row',\n 'data-row-index': index,\n }\n }\n\n return {\n get state(): DataTableState<T> {\n return {\n get sortedData() {\n return getSortedData()\n },\n get sortBy() {\n return sortBy\n },\n get sortDir() {\n return sortDir\n },\n get filters() {\n return { ...filters }\n },\n }\n },\n sort,\n setFilter,\n getHeaderProps,\n getCellProps,\n getRowProps,\n }\n}\n", "import { cva } from '@refraction-ui/shared'\n\nexport const tableVariants = cva({\n base: 'w-full caption-bottom text-sm border-collapse',\n variants: {\n size: {\n sm: 'text-xs',\n md: 'text-sm',\n lg: 'text-base',\n },\n },\n defaultVariants: {\n size: 'md',\n },\n})\n\nexport const headerVariants = cva({\n base: 'h-10 px-2 text-left align-middle font-medium text-muted-foreground border-b',\n variants: {\n sortable: {\n true: 'cursor-pointer select-none hover:text-foreground',\n false: '',\n },\n },\n defaultVariants: {\n sortable: 'false',\n },\n})\n\nexport const cellVariants = cva({\n base: 'p-2 align-middle border-b',\n variants: {\n size: {\n sm: 'p-1',\n md: 'p-2',\n lg: 'p-3',\n },\n },\n defaultVariants: {\n size: 'md',\n },\n})\n\nexport const rowVariants = cva({\n base: 'border-b transition-colors hover:bg-muted/50',\n variants: {\n selected: {\n true: 'bg-muted',\n false: '',\n },\n },\n defaultVariants: {\n selected: 'false',\n },\n})\n", "import * as React from 'react'\nimport {\n createDataTable,\n tableVariants,\n headerVariants,\n cellVariants,\n rowVariants,\n type ColumnDef,\n type SortDirection,\n type DataTableProps as CoreProps,\n} from '@refraction-ui/data-table'\nimport { cn } from '@refraction-ui/shared'\n\n// ---------------------------------------------------------------------------\n// DataTable\n// ---------------------------------------------------------------------------\n\nexport interface DataTableProps<T = Record<string, unknown>> {\n columns: ColumnDef<T>[]\n data: T[]\n sortBy?: string\n sortDir?: SortDirection\n onSort?: (columnId: string, direction: SortDirection) => void\n filters?: Record<string, string>\n className?: string\n emptyMessage?: string\n}\n\nexport function DataTable<T = Record<string, unknown>>({\n columns,\n data,\n sortBy: controlledSortBy,\n sortDir: controlledSortDir = 'asc',\n onSort,\n filters: controlledFilters,\n className,\n emptyMessage = 'No data available',\n}: DataTableProps<T>) {\n const [sortBy, setSortBy] = React.useState<string | null>(controlledSortBy ?? null)\n const [sortDir, setSortDir] = React.useState<SortDirection>(controlledSortDir)\n const [filters, setFilters] = React.useState<Record<string, string>>(controlledFilters ?? {})\n\n const api = React.useMemo(\n () =>\n createDataTable<T>({\n columns,\n data,\n sortBy: sortBy ?? undefined,\n sortDir,\n onSort,\n filters,\n }),\n [columns, data, sortBy, sortDir, onSort, filters],\n )\n\n const handleSort = React.useCallback(\n (columnId: string) => {\n const col = columns.find((c) => c.id === columnId)\n if (!col?.sortable) return\n\n let newDir: SortDirection = 'asc'\n if (sortBy === columnId) {\n newDir = sortDir === 'asc' ? 'desc' : 'asc'\n }\n\n setSortBy(columnId)\n setSortDir(newDir)\n onSort?.(columnId, newDir)\n },\n [columns, sortBy, sortDir, onSort],\n )\n\n const handleFilter = React.useCallback(\n (columnId: string, value: string) => {\n setFilters((prev) => ({ ...prev, [columnId]: value }))\n },\n [],\n )\n\n const sortedData = api.state.sortedData\n const hasFilterable = columns.some((c) => c.filterable)\n\n return React.createElement(\n 'div',\n { className: 'relative w-full overflow-auto' },\n React.createElement(\n 'table',\n {\n className: cn(tableVariants(), className),\n role: 'table',\n },\n // thead\n React.createElement(\n 'thead',\n null,\n // Header row\n React.createElement(\n 'tr',\n { role: 'row' },\n ...columns.map((col) => {\n const headerProps = api.getHeaderProps(col)\n return React.createElement(\n 'th',\n {\n key: col.id,\n ...headerProps,\n className: headerVariants({ sortable: col.sortable ? 'true' : 'false' }),\n onClick: col.sortable ? () => handleSort(col.id) : undefined,\n },\n col.header,\n col.sortable && sortBy === col.id\n ? React.createElement('span', { 'aria-hidden': true }, sortDir === 'asc' ? ' \\u2191' : ' \\u2193')\n : null,\n )\n }),\n ),\n // Filter row\n hasFilterable\n ? React.createElement(\n 'tr',\n { role: 'row', 'data-filter-row': 'true' },\n ...columns.map((col) =>\n React.createElement(\n 'th',\n { key: `filter-${col.id}` },\n col.filterable\n ? React.createElement('input', {\n type: 'text',\n 'aria-label': `Filter ${col.header}`,\n value: filters[col.id] ?? '',\n onChange: (e: React.ChangeEvent<HTMLInputElement>) =>\n handleFilter(col.id, e.target.value),\n placeholder: `Filter...`,\n })\n : null,\n ),\n ),\n )\n : null,\n ),\n // tbody\n React.createElement(\n 'tbody',\n null,\n sortedData.length === 0\n ? React.createElement(\n 'tr',\n { role: 'row' },\n React.createElement(\n 'td',\n {\n colSpan: columns.length,\n className: 'text-center p-4 text-muted-foreground',\n role: 'cell',\n },\n emptyMessage,\n ),\n )\n : sortedData.map((row, rowIndex) =>\n React.createElement(\n 'tr',\n {\n key: rowIndex,\n ...api.getRowProps(row, rowIndex),\n className: rowVariants(),\n },\n ...columns.map((col) =>\n React.createElement(\n 'td',\n {\n key: col.id,\n ...api.getCellProps(col, row),\n className: cellVariants(),\n },\n String(col.accessor(row) ?? ''),\n ),\n ),\n ),\n ),\n ),\n )\n )\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import type { AccessibilityProps } from '@refraction-ui/shared'\n\nexport interface ColumnDef<T = Record<string, unknown>> {\n /** Unique column identifier */\n id: string\n /** Column header text */\n header: string\n /**\n * Value of this column for a row. Drives sorting, filtering and — when no\n * `cell` renderer is given — the rendered text. Optional for display-only\n * columns that set `cell`.\n */\n accessor?: (row: T) => unknown\n /**\n * Custom cell renderer. Framework adapters narrow the return type (React:\n * `ReactNode`). When omitted the cell renders `String(accessor(row))`.\n */\n cell?: (row: T, index: number) => unknown\n /** Horizontal alignment of header and cells. Defaults to `start`. */\n align?: DataTableAlign\n /** Numeric column: tabular figures, no wrapping, aligned to `end` unless `align` says otherwise. */\n numeric?: boolean\n /** Extra class for this column's data cells. */\n className?: string\n /** Extra class for this column's header cell. */\n headerClassName?: string\n /** Whether this column is sortable */\n sortable?: boolean\n /** Whether this column is filterable */\n filterable?: boolean\n}\n\nexport type SortDirection = 'asc' | 'desc'\n\n/** Horizontal alignment of a column (logical, RTL-safe). */\nexport type DataTableAlign = 'start' | 'center' | 'end'\n\n/** A column's effective alignment: explicit `align`, else `end` for numeric columns. */\nexport function resolveColumnAlign(col: { align?: DataTableAlign; numeric?: boolean }): DataTableAlign {\n return col.align ?? (col.numeric ? 'end' : 'start')\n}\n\n/** The raw value of a column for a row (`undefined` without an accessor). */\nexport function getColumnValue<T>(col: { accessor?: (row: T) => unknown }, row: T): unknown {\n return col.accessor ? col.accessor(row) : undefined\n}\n\n/**\n * Stable React/DOM key for a row: `getRowKey` when given, else the row's\n * index. Prefer a `getRowKey` — index keys break row state on sort/filter.\n */\nexport function resolveRowKey<T>(\n row: T,\n index: number,\n getRowKey?: (row: T, index: number) => string | number,\n): string | number {\n return getRowKey ? getRowKey(row, index) : index\n}\n\nexport interface DataTableProps<T = Record<string, unknown>> {\n /** Column definitions */\n columns: ColumnDef<T>[]\n /** Data rows */\n data: T[]\n /** Current sort column */\n sortBy?: string\n /** Current sort direction */\n sortDir?: SortDirection\n /** Callback when sort changes */\n onSort?: (columnId: string, direction: SortDirection) => void\n /** Active filters: columnId -> filter value */\n filters?: Record<string, string>\n}\n\nexport interface DataTableState<T = Record<string, unknown>> {\n sortedData: T[]\n sortBy: string | null\n sortDir: SortDirection\n filters: Record<string, string>\n}\n\nexport interface DataTableAPI<T = Record<string, unknown>> {\n /** Current table state */\n state: DataTableState<T>\n /** Toggle sort for a column */\n sort(columnId: string): void\n /** Set a filter value for a column */\n setFilter(columnId: string, value: string): void\n /** Get ARIA and role props for a header cell */\n getHeaderProps(col: ColumnDef<T>): Partial<AccessibilityProps> & Record<string, unknown>\n /** Get props for a data cell */\n getCellProps(col: ColumnDef<T>, row: T): Record<string, unknown>\n /** Get props for a data row */\n getRowProps(row: T, index: number): Record<string, unknown>\n}\n\nexport function createDataTable<T = Record<string, unknown>>(\n props: DataTableProps<T>,\n): DataTableAPI<T> {\n const {\n columns,\n data,\n sortBy: initialSortBy,\n sortDir: initialSortDir = 'asc',\n onSort,\n filters: initialFilters,\n } = props\n\n let sortBy: string | null = initialSortBy ?? null\n let sortDir: SortDirection = initialSortDir\n let filters: Record<string, string> = { ...(initialFilters ?? {}) }\n\n function getFilteredData(): T[] {\n let result = [...data]\n\n for (const [columnId, filterValue] of Object.entries(filters)) {\n if (!filterValue) continue\n const col = columns.find((c) => c.id === columnId)\n if (!col?.accessor) continue\n const lowerFilter = filterValue.toLowerCase()\n result = result.filter((row) => {\n const cellValue = getColumnValue(col, row)\n return String(cellValue ?? '').toLowerCase().includes(lowerFilter)\n })\n }\n\n return result\n }\n\n function getSortedData(): T[] {\n const filtered = getFilteredData()\n\n if (!sortBy) return filtered\n\n const col = columns.find((c) => c.id === sortBy)\n if (!col?.accessor) return filtered\n\n return [...filtered].sort((a, b) => {\n const aVal = getColumnValue(col, a)\n const bVal = getColumnValue(col, b)\n const aStr = String(aVal ?? '')\n const bStr = String(bVal ?? '')\n\n const cmp = aStr.localeCompare(bStr, undefined, { numeric: true })\n return sortDir === 'asc' ? cmp : -cmp\n })\n }\n\n function sort(columnId: string): void {\n const col = columns.find((c) => c.id === columnId)\n if (!col?.sortable) return\n\n if (sortBy === columnId) {\n sortDir = sortDir === 'asc' ? 'desc' : 'asc'\n } else {\n sortBy = columnId\n sortDir = 'asc'\n }\n\n onSort?.(sortBy, sortDir)\n }\n\n function setFilter(columnId: string, value: string): void {\n filters = { ...filters, [columnId]: value }\n }\n\n function getHeaderProps(\n col: ColumnDef<T>,\n ): Partial<AccessibilityProps> & Record<string, unknown> {\n const props: Partial<AccessibilityProps> & Record<string, unknown> = {\n role: 'columnheader',\n }\n\n if (col.sortable) {\n if (sortBy === col.id) {\n props['aria-sort'] = sortDir === 'asc' ? 'ascending' : 'descending'\n } else {\n props['aria-sort'] = 'none'\n }\n }\n\n return props\n }\n\n function getCellProps(\n col: ColumnDef<T>,\n _row: T,\n ): Record<string, unknown> {\n return {\n role: 'cell',\n 'data-column': col.id,\n }\n }\n\n function getRowProps(_row: T, index: number): Record<string, unknown> {\n return {\n role: 'row',\n 'data-row-index': index,\n }\n }\n\n return {\n get state(): DataTableState<T> {\n return {\n get sortedData() {\n return getSortedData()\n },\n get sortBy() {\n return sortBy\n },\n get sortDir() {\n return sortDir\n },\n get filters() {\n return { ...filters }\n },\n }\n },\n sort,\n setFilter,\n getHeaderProps,\n getCellProps,\n getRowProps,\n }\n}\n", "import { cva } from '@refraction-ui/shared'\n\nexport const tableVariants = cva({\n base: 'w-full caption-bottom text-sm border-collapse',\n variants: {\n size: {\n sm: 'text-xs',\n md: 'text-sm',\n lg: 'text-base',\n },\n },\n defaultVariants: {\n size: 'md',\n },\n})\n\nexport const headerVariants = cva({\n base: 'h-10 px-2 text-left align-middle font-medium text-muted-foreground border-b',\n variants: {\n sortable: {\n true: 'cursor-pointer select-none hover:text-foreground',\n false: '',\n },\n },\n defaultVariants: {\n sortable: 'false',\n },\n})\n\nexport const cellVariants = cva({\n base: 'p-2 align-middle border-b',\n variants: {\n size: {\n sm: 'p-1',\n md: 'p-2',\n lg: 'p-3',\n },\n },\n defaultVariants: {\n size: 'md',\n },\n})\n\nexport const rowVariants = cva({\n base: 'border-b transition-colors hover:bg-muted/50',\n variants: {\n selected: {\n true: 'bg-muted',\n false: '',\n },\n },\n defaultVariants: {\n selected: 'false',\n },\n})\n\n/** Logical text alignment per column alignment. */\nexport const dataTableAlignClass = {\n start: 'text-start',\n center: 'text-center',\n end: 'text-end',\n} as const\n\n/** Numeric cells: tabular figures, no wrapping. */\nexport const dataTableNumericClass = 'tabular-nums whitespace-nowrap'\n\n/** Button inside a sortable header: the keyboard-reachable sort control. */\nexport const dataTableSortButtonClass =\n 'inline-flex items-center gap-1 rounded-sm font-inherit text-inherit focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring'\n\n/** Rows with a row action: pointer + keyboard focus ring. */\nexport const dataTableActionRowClass =\n 'cursor-pointer focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-ring'\n", "import * as React from 'react'\nimport {\n createDataTable,\n tableVariants,\n headerVariants,\n cellVariants,\n rowVariants,\n resolveColumnAlign,\n getColumnValue,\n resolveRowKey,\n dataTableAlignClass,\n dataTableNumericClass,\n dataTableSortButtonClass,\n dataTableActionRowClass,\n type ColumnDef,\n type SortDirection,\n} from '@refraction-ui/data-table'\nimport { cn } from '@refraction-ui/shared'\n\n// ---------------------------------------------------------------------------\n// Column definition (React): header and cell may be any ReactNode\n// ---------------------------------------------------------------------------\n\nexport interface DataTableColumn<T = Record<string, unknown>>\n extends Omit<ColumnDef<T>, 'header' | 'cell'> {\n /** Header content. A string is also used for the filter input's label. */\n header: React.ReactNode\n /** Render the cell. Defaults to `String(accessor(row))`. */\n cell?: (row: T, index: number) => React.ReactNode\n}\n\n// ---------------------------------------------------------------------------\n// DataTable\n// ---------------------------------------------------------------------------\n\nexport interface DataTableProps<T = Record<string, unknown>>\n extends Omit<React.TableHTMLAttributes<HTMLTableElement>, 'children'> {\n columns: DataTableColumn<T>[]\n data: T[]\n sortBy?: string\n sortDir?: SortDirection\n onSort?: (columnId: string, direction: SortDirection) => void\n filters?: Record<string, string>\n emptyMessage?: React.ReactNode\n /** Stable key per row. Defaults to the row index — pass one when rows can reorder. */\n getRowKey?: (row: T, index: number) => string | number\n /** Extra attributes for a row (`data-*`, `aria-*`, className, handlers). */\n getRowProps?: (row: T, index: number) => React.HTMLAttributes<HTMLTableRowElement>\n /**\n * Row action. Makes each row focusable (Tab) and activatable with click,\n * Enter or Space. Keep a real link/button in the row too when the action\n * needs an accessible name beyond the row's text.\n */\n onRowClick?: (row: T, index: number) => void\n /** Table caption (rendered as `<caption>`). */\n caption?: React.ReactNode\n /** Class for the horizontal scroll wrapper. */\n wrapperClassName?: string\n}\n\nconst ACTIVATION_KEYS = new Set(['Enter', ' '])\n\nfunction filterLabel(header: React.ReactNode, id: string): string {\n return typeof header === 'string' || typeof header === 'number' ? String(header) : id\n}\n\nexport function DataTable<T = Record<string, unknown>>({\n columns,\n data,\n sortBy: controlledSortBy,\n sortDir: controlledSortDir = 'asc',\n onSort,\n filters: controlledFilters,\n className,\n emptyMessage = 'No data available',\n getRowKey,\n getRowProps,\n onRowClick,\n caption,\n wrapperClassName,\n ...tableProps\n}: DataTableProps<T>) {\n const [sortBy, setSortBy] = React.useState<string | null>(controlledSortBy ?? null)\n const [sortDir, setSortDir] = React.useState<SortDirection>(controlledSortDir)\n const [filters, setFilters] = React.useState<Record<string, string>>(controlledFilters ?? {})\n\n const api = React.useMemo(\n () =>\n createDataTable<T>({\n // The core only reads id/accessor/sortable/filterable; header and cell\n // are rendered here.\n columns: columns as unknown as ColumnDef<T>[],\n data,\n sortBy: sortBy ?? undefined,\n sortDir,\n onSort,\n filters,\n }),\n [columns, data, sortBy, sortDir, onSort, filters],\n )\n\n const handleSort = (columnId: string) => {\n const col = columns.find((c) => c.id === columnId)\n if (!col?.sortable) return\n const newDir: SortDirection = sortBy === columnId && sortDir === 'asc' ? 'desc' : 'asc'\n setSortBy(columnId)\n setSortDir(newDir)\n onSort?.(columnId, newDir)\n }\n\n const handleFilter = (columnId: string, value: string) => {\n setFilters((prev) => ({ ...prev, [columnId]: value }))\n }\n\n const rows = api.state.sortedData\n const hasFilterable = columns.some((c) => c.filterable)\n\n const rowElementProps = (row: T, index: number): React.HTMLAttributes<HTMLTableRowElement> => {\n const extra = getRowProps?.(row, index) ?? {}\n if (!onRowClick) return extra\n return {\n tabIndex: 0,\n ...extra,\n className: cn(dataTableActionRowClass, extra.className),\n onClick: (e) => {\n extra.onClick?.(e)\n if (!e.defaultPrevented) onRowClick(row, index)\n },\n onKeyDown: (e) => {\n extra.onKeyDown?.(e)\n // Only when the row itself is focused — not a control inside it.\n if (e.defaultPrevented || e.target !== e.currentTarget || !ACTIVATION_KEYS.has(e.key)) return\n e.preventDefault()\n onRowClick(row, index)\n },\n }\n }\n\n return (\n <div className={cn('relative w-full overflow-auto', wrapperClassName)}>\n <table className={cn(tableVariants(), className)} role=\"table\" {...tableProps}>\n {caption != null && <caption className=\"mt-2 caption-bottom text-xs text-muted-foreground\">{caption}</caption>}\n <thead>\n <tr role=\"row\">\n {columns.map((col) => {\n const headerProps = api.getHeaderProps(col as unknown as ColumnDef<T>)\n const align = resolveColumnAlign(col)\n const indicator =\n col.sortable && sortBy === col.id ? (\n <span aria-hidden=\"true\">{sortDir === 'asc' ? '↑' : '↓'}</span>\n ) : null\n return (\n <th\n key={col.id}\n {...headerProps}\n className={cn(\n headerVariants({ sortable: col.sortable ? 'true' : 'false' }),\n dataTableAlignClass[align],\n col.headerClassName,\n )}\n >\n {col.sortable ? (\n <button type=\"button\" className={dataTableSortButtonClass} onClick={() => handleSort(col.id)}>\n {col.header}\n {indicator}\n </button>\n ) : (\n col.header\n )}\n </th>\n )\n })}\n </tr>\n {hasFilterable && (\n <tr role=\"row\" data-filter-row=\"true\">\n {columns.map((col) => (\n <th key={`filter-${col.id}`}>\n {col.filterable ? (\n <input\n type=\"text\"\n aria-label={`Filter ${filterLabel(col.header, col.id)}`}\n value={filters[col.id] ?? ''}\n onChange={(e) => handleFilter(col.id, e.target.value)}\n placeholder=\"Filter...\"\n />\n ) : null}\n </th>\n ))}\n </tr>\n )}\n </thead>\n <tbody>\n {rows.length === 0 ? (\n <tr role=\"row\">\n <td colSpan={columns.length} className=\"text-center p-4 text-muted-foreground\" role=\"cell\">\n {emptyMessage}\n </td>\n </tr>\n ) : (\n rows.map((row, rowIndex) => {\n const rowProps = rowElementProps(row, rowIndex)\n return (\n <tr\n key={resolveRowKey(row, rowIndex, getRowKey)}\n {...api.getRowProps(row, rowIndex)}\n {...rowProps}\n className={cn(rowVariants(), rowProps.className)}\n >\n {columns.map((col) => (\n <td\n key={col.id}\n {...api.getCellProps(col as unknown as ColumnDef<T>, row)}\n className={cn(\n cellVariants(),\n dataTableAlignClass[resolveColumnAlign(col)],\n col.numeric && dataTableNumericClass,\n col.className,\n )}\n >\n {col.cell ? col.cell(row, rowIndex) : String(getColumnValue(col, row) ?? '')}\n </td>\n ))}\n </tr>\n )\n })\n )}\n </tbody>\n </table>\n </div>\n )\n}\n"],
5
+ "mappings": "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",
6
6
  "names": ["props"]
7
7
  }
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  cn,
3
3
  cva
4
- } from "./chunk-ZF3OHCGV.js";
4
+ } from "./chunk-2Q6HHFAN.js";
5
5
 
6
6
  // ../react-date-picker/dist/index.js
7
7
  import * as React from "react";
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  cn,
3
3
  cva
4
- } from "./chunk-ZF3OHCGV.js";
4
+ } from "./chunk-2Q6HHFAN.js";
5
5
 
6
6
  // ../react-device-frame/dist/index.js
7
7
  import * as React from "react";
@@ -2,12 +2,12 @@ import {
2
2
  createDialog,
3
3
  dialogContentVariants,
4
4
  overlayStyles
5
- } from "./chunk-VK3EQ34F.js";
5
+ } from "./chunk-V24GDHUX.js";
6
6
  import {
7
7
  cn,
8
8
  createKeyboardHandler,
9
9
  devWarn
10
- } from "./chunk-ZF3OHCGV.js";
10
+ } from "./chunk-2Q6HHFAN.js";
11
11
 
12
12
  // ../react-dialog/dist/index.js
13
13
  import * as React from "react";
@@ -48,6 +48,8 @@ function Dialog({
48
48
  apiRef.current = createDialog({ open, modal });
49
49
  }
50
50
  const api = apiRef.current;
51
+ const [hasTitle, setHasTitle] = React.useState(false);
52
+ const [hasDescription, setHasDescription] = React.useState(false);
51
53
  const ctx = React.useMemo(
52
54
  () => ({
53
55
  open,
@@ -55,9 +57,13 @@ function Dialog({
55
57
  modal,
56
58
  contentId: api.ids.content,
57
59
  titleId: api.ids.title,
58
- descriptionId: api.ids.description
60
+ descriptionId: api.ids.description,
61
+ hasTitle,
62
+ hasDescription,
63
+ setHasTitle,
64
+ setHasDescription
59
65
  }),
60
- [open, handleOpenChange, modal, api.ids.content, api.ids.title, api.ids.description]
66
+ [open, handleOpenChange, modal, api.ids.content, api.ids.title, api.ids.description, hasTitle, hasDescription]
61
67
  );
62
68
  return React.createElement(DialogContext.Provider, { value: ctx }, children);
63
69
  }
@@ -102,9 +108,17 @@ var DialogOverlay = React.forwardRef(
102
108
  });
103
109
  }
104
110
  );
111
+ function containsElement(node, type) {
112
+ let found = false;
113
+ React.Children.forEach(node, (child) => {
114
+ if (found || !React.isValidElement(child)) return;
115
+ found = child.type === type || containsElement(child.props.children, type);
116
+ });
117
+ return found;
118
+ }
105
119
  var DialogContent = React.forwardRef(
106
120
  function DialogContent2({ className, children, onKeyDown, ...props }, ref) {
107
- const { open, onOpenChange, modal, contentId, titleId, descriptionId } = useDialogContext();
121
+ const { open, onOpenChange, modal, contentId, titleId, descriptionId, hasTitle, hasDescription } = useDialogContext();
108
122
  React.useMemo(
109
123
  () => createDialog({ open, modal }),
110
124
  [open, modal]
@@ -126,8 +140,10 @@ var DialogContent = React.forwardRef(
126
140
  ref,
127
141
  role: "dialog",
128
142
  "aria-modal": modal,
129
- "aria-labelledby": titleId,
130
- "aria-describedby": descriptionId,
143
+ // Reference only parts that exist: an id pointing at nothing leaves the
144
+ // dialog unnamed while looking labelled.
145
+ "aria-labelledby": hasTitle || containsElement(children, DialogTitle) ? titleId : void 0,
146
+ "aria-describedby": hasDescription || containsElement(children, DialogDescription) ? descriptionId : void 0,
131
147
  id: contentId,
132
148
  className: cn(dialogContentVariants(), className),
133
149
  onKeyDown: handleKeyDown,
@@ -165,7 +181,11 @@ var DialogFooter = React.forwardRef(
165
181
  );
166
182
  var DialogTitle = React.forwardRef(
167
183
  function DialogTitle2({ className, ...props }, ref) {
168
- const { titleId } = useDialogContext();
184
+ const { titleId, setHasTitle } = useDialogContext();
185
+ React.useEffect(() => {
186
+ setHasTitle(true);
187
+ return () => setHasTitle(false);
188
+ }, [setHasTitle]);
169
189
  return React.createElement("h2", {
170
190
  ref,
171
191
  id: titleId,
@@ -175,7 +195,11 @@ var DialogTitle = React.forwardRef(
175
195
  }
176
196
  );
177
197
  var DialogDescription = React.forwardRef(function DialogDescription2({ className, ...props }, ref) {
178
- const { descriptionId } = useDialogContext();
198
+ const { descriptionId, setHasDescription } = useDialogContext();
199
+ React.useEffect(() => {
200
+ setHasDescription(true);
201
+ return () => setHasDescription(false);
202
+ }, [setHasDescription]);
179
203
  return React.createElement("p", {
180
204
  ref,
181
205
  id: descriptionId,
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../react-dialog/src/dialog.tsx"],
4
- "sourcesContent": ["import * as React from 'react'\nimport * as ReactDOM from 'react-dom'\nimport {\n createDialog,\n overlayStyles,\n dialogContentVariants,\n type DialogProps as CoreDialogProps,\n} from '@refraction-ui/dialog'\nimport { cn, createKeyboardHandler, devWarn } from '@refraction-ui/shared'\n\n// ---------------------------------------------------------------------------\n// Context\n// ---------------------------------------------------------------------------\n\ninterface DialogContextValue {\n open: boolean\n onOpenChange: (open: boolean) => void\n modal: boolean\n contentId: string\n titleId: string\n descriptionId: string\n}\n\nconst DialogContext = React.createContext<DialogContextValue | null>(null)\n\nfunction useDialogContext(): DialogContextValue {\n const ctx = React.useContext(DialogContext)\n if (!ctx) {\n devWarn(\n 'react-dialog/context-outside-provider',\n 'Dialog compound components (DialogTrigger/DialogContent/DialogTitle/etc.) must be rendered inside a <Dialog>. The missing DialogContext makes this throw.',\n )\n throw new Error('Dialog compound components must be used within <Dialog>')\n }\n return ctx\n}\n\n// ---------------------------------------------------------------------------\n// Dialog (root provider)\n// ---------------------------------------------------------------------------\n\nexport interface DialogProps {\n open?: boolean\n defaultOpen?: boolean\n onOpenChange?: (open: boolean) => void\n modal?: boolean\n children?: React.ReactNode\n}\n\nexport function Dialog({\n open: controlledOpen,\n defaultOpen = false,\n onOpenChange,\n modal = true,\n children,\n}: DialogProps) {\n const [uncontrolledOpen, setUncontrolledOpen] = React.useState(defaultOpen)\n const isControlled = controlledOpen !== undefined\n const open = isControlled ? controlledOpen : uncontrolledOpen\n\n const handleOpenChange = React.useCallback(\n (next: boolean) => {\n if (!isControlled) {\n setUncontrolledOpen(next)\n }\n onOpenChange?.(next)\n },\n [isControlled, onOpenChange],\n )\n\n // Use the headless core to get stable IDs\n const apiRef = React.useRef<ReturnType<typeof createDialog> | null>(null)\n if (apiRef.current === null) {\n apiRef.current = createDialog({ open, modal })\n }\n const api = apiRef.current\n\n const ctx = React.useMemo<DialogContextValue>(\n () => ({\n open,\n onOpenChange: handleOpenChange,\n modal,\n contentId: api.ids.content,\n titleId: api.ids.title,\n descriptionId: api.ids.description,\n }),\n [open, handleOpenChange, modal, api.ids.content, api.ids.title, api.ids.description],\n )\n\n return React.createElement(DialogContext.Provider, { value: ctx }, children)\n}\n\n// ---------------------------------------------------------------------------\n// DialogTrigger\n// ---------------------------------------------------------------------------\n\nexport interface DialogTriggerProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {\n asChild?: boolean\n}\n\nexport const DialogTrigger = React.forwardRef<HTMLButtonElement, DialogTriggerProps>(\n function DialogTrigger({ onClick, children, ...props }, ref) {\n const { open, onOpenChange, contentId } = useDialogContext()\n\n const handleClick = (e: React.MouseEvent<HTMLButtonElement>) => {\n onOpenChange(!open)\n onClick?.(e)\n }\n\n return React.createElement(\n 'button',\n {\n ref,\n type: 'button',\n 'aria-expanded': open,\n 'aria-controls': contentId,\n 'aria-haspopup': 'dialog',\n onClick: handleClick,\n ...props,\n },\n children,\n )\n },\n)\n\n// ---------------------------------------------------------------------------\n// DialogOverlay\n// ---------------------------------------------------------------------------\n\nexport interface DialogOverlayProps extends React.HTMLAttributes<HTMLDivElement> {}\n\nexport const DialogOverlay = React.forwardRef<HTMLDivElement, DialogOverlayProps>(\n function DialogOverlay({ className, onClick, ...props }, ref) {\n const { open, onOpenChange } = useDialogContext()\n\n if (!open) return null\n\n const handleClick = (e: React.MouseEvent<HTMLDivElement>) => {\n // Only close if clicking the overlay itself, not children\n if (e.target === e.currentTarget) {\n onOpenChange(false)\n }\n onClick?.(e)\n }\n\n return React.createElement('div', {\n ref,\n className: cn(overlayStyles, className),\n 'data-state': open ? 'open' : 'closed',\n onClick: handleClick,\n ...props,\n })\n },\n)\n\n// ---------------------------------------------------------------------------\n// DialogContent\n// ---------------------------------------------------------------------------\n\nexport interface DialogContentProps extends React.HTMLAttributes<HTMLDivElement> {}\n\nexport const DialogContent = React.forwardRef<HTMLDivElement, DialogContentProps>(\n function DialogContent({ className, children, onKeyDown, ...props }, ref) {\n const { open, onOpenChange, modal, contentId, titleId, descriptionId } =\n useDialogContext()\n\n const api = React.useMemo(\n () => createDialog({ open, modal }),\n [open, modal],\n )\n\n const handleKeyDown = (e: React.KeyboardEvent<HTMLDivElement>) => {\n const handler = createKeyboardHandler({\n Escape: (ev) => {\n ev.preventDefault()\n onOpenChange(false)\n },\n })\n handler(e.nativeEvent)\n onKeyDown?.(e)\n }\n\n if (!open) return null\n\n const content = React.createElement(\n 'div',\n {\n ref,\n role: 'dialog',\n 'aria-modal': modal,\n 'aria-labelledby': titleId,\n 'aria-describedby': descriptionId,\n id: contentId,\n className: cn(dialogContentVariants(), className),\n onKeyDown: handleKeyDown,\n tabIndex: -1,\n ...props,\n },\n children,\n )\n\n // Render via portal if document is available (client-side)\n if (typeof document !== 'undefined') {\n return ReactDOM.createPortal(content, document.body)\n }\n\n // SSR fallback: render inline\n return content\n },\n)\n\n// ---------------------------------------------------------------------------\n// DialogHeader\n// ---------------------------------------------------------------------------\n\nexport interface DialogHeaderProps extends React.HTMLAttributes<HTMLDivElement> {}\n\nexport const DialogHeader = React.forwardRef<HTMLDivElement, DialogHeaderProps>(\n function DialogHeader({ className, ...props }, ref) {\n return React.createElement('div', {\n ref,\n className: cn('flex flex-col space-y-1.5 text-center sm:text-left', className),\n ...props,\n })\n },\n)\n\n// ---------------------------------------------------------------------------\n// DialogFooter\n// ---------------------------------------------------------------------------\n\nexport interface DialogFooterProps extends React.HTMLAttributes<HTMLDivElement> {}\n\nexport const DialogFooter = React.forwardRef<HTMLDivElement, DialogFooterProps>(\n function DialogFooter({ className, ...props }, ref) {\n return React.createElement('div', {\n ref,\n className: cn(\n 'flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2',\n className,\n ),\n ...props,\n })\n },\n)\n\n// ---------------------------------------------------------------------------\n// DialogTitle\n// ---------------------------------------------------------------------------\n\nexport interface DialogTitleProps extends React.HTMLAttributes<HTMLHeadingElement> {}\n\nexport const DialogTitle = React.forwardRef<HTMLHeadingElement, DialogTitleProps>(\n function DialogTitle({ className, ...props }, ref) {\n const { titleId } = useDialogContext()\n\n return React.createElement('h2', {\n ref,\n id: titleId,\n className: cn('text-lg font-semibold leading-none tracking-tight', className),\n ...props,\n })\n },\n)\n\n// ---------------------------------------------------------------------------\n// DialogDescription\n// ---------------------------------------------------------------------------\n\nexport interface DialogDescriptionProps extends React.HTMLAttributes<HTMLParagraphElement> {}\n\nexport const DialogDescription = React.forwardRef<\n HTMLParagraphElement,\n DialogDescriptionProps\n>(function DialogDescription({ className, ...props }, ref) {\n const { descriptionId } = useDialogContext()\n\n return React.createElement('p', {\n ref,\n id: descriptionId,\n className: cn('text-sm text-muted-foreground', className),\n ...props,\n })\n})\n\n// ---------------------------------------------------------------------------\n// DialogClose\n// ---------------------------------------------------------------------------\n\nexport interface DialogCloseProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {}\n\nexport const DialogClose = React.forwardRef<HTMLButtonElement, DialogCloseProps>(\n function DialogClose({ onClick, children, ...props }, ref) {\n const { onOpenChange } = useDialogContext()\n\n const handleClick = (e: React.MouseEvent<HTMLButtonElement>) => {\n onOpenChange(false)\n onClick?.(e)\n }\n\n return React.createElement(\n 'button',\n {\n ref,\n type: 'button',\n onClick: handleClick,\n ...props,\n },\n children,\n )\n },\n)\n"],
5
- "mappings": ";;;;;;;;;;;;;;AAuBA,IAAM,gBAAsB,oBAAyC,IAAI;AAEzE,SAAS,mBAAuC;AAC9C,QAAM,MAAY,iBAAW,aAAa;AAC1C,MAAI,CAAC,KAAK;AACR;MACE;MACA;IAAA;AAEF,UAAM,IAAI,MAAM,yDAAyD;EAC3E;AACA,SAAO;AACT;AAcO,SAAS,OAAO;EACrB,MAAM;EACN,cAAc;EACd;EACA,QAAQ;EACR;AACF,GAAgB;AACd,QAAM,CAAC,kBAAkB,mBAAmB,IAAU,eAAS,WAAW;AAC1E,QAAM,eAAe,mBAAmB;AACxC,QAAM,OAAO,eAAe,iBAAiB;AAE7C,QAAM,mBAAyB;IAC7B,CAAC,SAAkB;AACjB,UAAI,CAAC,cAAc;AACjB,4BAAoB,IAAI;MAC1B;AACA,qBAAe,IAAI;IACrB;IACA,CAAC,cAAc,YAAY;EAAA;AAI7B,QAAM,SAAe,aAA+C,IAAI;AACxE,MAAI,OAAO,YAAY,MAAM;AAC3B,WAAO,UAAU,aAAa,EAAE,MAAM,MAAA,CAAO;EAC/C;AACA,QAAM,MAAM,OAAO;AAEnB,QAAM,MAAY;IAChB,OAAO;MACL;MACA,cAAc;MACd;MACA,WAAW,IAAI,IAAI;MACnB,SAAS,IAAI,IAAI;MACjB,eAAe,IAAI,IAAI;IAAA;IAEzB,CAAC,MAAM,kBAAkB,OAAO,IAAI,IAAI,SAAS,IAAI,IAAI,OAAO,IAAI,IAAI,WAAW;EAAA;AAGrF,SAAa,oBAAc,cAAc,UAAU,EAAE,OAAO,IAAA,GAAO,QAAQ;AAC7E;AAUO,IAAM,gBAAsB;EACjC,SAASA,eAAc,EAAE,SAAS,UAAU,GAAG,MAAA,GAAS,KAAK;AAC3D,UAAM,EAAE,MAAM,cAAc,UAAA,IAAc,iBAAA;AAE1C,UAAM,cAAc,CAAC,MAA2C;AAC9D,mBAAa,CAAC,IAAI;AAClB,gBAAU,CAAC;IACb;AAEA,WAAa;MACX;MACA;QACE;QACA,MAAM;QACN,iBAAiB;QACjB,iBAAiB;QACjB,iBAAiB;QACjB,SAAS;QACT,GAAG;MAAA;MAEL;IAAA;EAEJ;AACF;AAQO,IAAM,gBAAsB;EACjC,SAASC,eAAc,EAAE,WAAW,SAAS,GAAG,MAAA,GAAS,KAAK;AAC5D,UAAM,EAAE,MAAM,aAAA,IAAiB,iBAAA;AAE/B,QAAI,CAAC,KAAM,QAAO;AAElB,UAAM,cAAc,CAAC,MAAwC;AAE3D,UAAI,EAAE,WAAW,EAAE,eAAe;AAChC,qBAAa,KAAK;MACpB;AACA,gBAAU,CAAC;IACb;AAEA,WAAa,oBAAc,OAAO;MAChC;MACA,WAAW,GAAG,eAAe,SAAS;MACtC,cAAc,OAAO,SAAS;MAC9B,SAAS;MACT,GAAG;IAAA,CACJ;EACH;AACF;AAQO,IAAM,gBAAsB;EACjC,SAASC,eAAc,EAAE,WAAW,UAAU,WAAW,GAAG,MAAA,GAAS,KAAK;AACxE,UAAM,EAAE,MAAM,cAAc,OAAO,WAAW,SAAS,cAAA,IACrD,iBAAA;AAEgB,IAAA;MAChB,MAAM,aAAa,EAAE,MAAM,MAAA,CAAO;MAClC,CAAC,MAAM,KAAK;IAAA;AAGd,UAAM,gBAAgB,CAAC,MAA2C;AAChE,YAAM,UAAU,sBAAsB;QACpC,QAAQ,CAAC,OAAO;AACd,aAAG,eAAA;AACH,uBAAa,KAAK;QACpB;MAAA,CACD;AACD,cAAQ,EAAE,WAAW;AACrB,kBAAY,CAAC;IACf;AAEA,QAAI,CAAC,KAAM,QAAO;AAElB,UAAM,UAAgB;MACpB;MACA;QACE;QACA,MAAM;QACN,cAAc;QACd,mBAAmB;QACnB,oBAAoB;QACpB,IAAI;QACJ,WAAW,GAAG,sBAAA,GAAyB,SAAS;QAChD,WAAW;QACX,UAAU;QACV,GAAG;MAAA;MAEL;IAAA;AAIF,QAAI,OAAO,aAAa,aAAa;AACnC,aAAgB,sBAAa,SAAS,SAAS,IAAI;IACrD;AAGA,WAAO;EACT;AACF;AAQO,IAAM,eAAqB;EAChC,SAASC,cAAa,EAAE,WAAW,GAAG,MAAA,GAAS,KAAK;AAClD,WAAa,oBAAc,OAAO;MAChC;MACA,WAAW,GAAG,sDAAsD,SAAS;MAC7E,GAAG;IAAA,CACJ;EACH;AACF;AAQO,IAAM,eAAqB;EAChC,SAASC,cAAa,EAAE,WAAW,GAAG,MAAA,GAAS,KAAK;AAClD,WAAa,oBAAc,OAAO;MAChC;MACA,WAAW;QACT;QACA;MAAA;MAEF,GAAG;IAAA,CACJ;EACH;AACF;AAQO,IAAM,cAAoB;EAC/B,SAASC,aAAY,EAAE,WAAW,GAAG,MAAA,GAAS,KAAK;AACjD,UAAM,EAAE,QAAA,IAAY,iBAAA;AAEpB,WAAa,oBAAc,MAAM;MAC/B;MACA,IAAI;MACJ,WAAW,GAAG,qDAAqD,SAAS;MAC5E,GAAG;IAAA,CACJ;EACH;AACF;AAQO,IAAM,oBAA0B,iBAGrC,SAASC,mBAAkB,EAAE,WAAW,GAAG,MAAA,GAAS,KAAK;AACzD,QAAM,EAAE,cAAA,IAAkB,iBAAA;AAE1B,SAAa,oBAAc,KAAK;IAC9B;IACA,IAAI;IACJ,WAAW,GAAG,iCAAiC,SAAS;IACxD,GAAG;EAAA,CACJ;AACH,CAAC;AAQM,IAAM,cAAoB;EAC/B,SAASC,aAAY,EAAE,SAAS,UAAU,GAAG,MAAA,GAAS,KAAK;AACzD,UAAM,EAAE,aAAA,IAAiB,iBAAA;AAEzB,UAAM,cAAc,CAAC,MAA2C;AAC9D,mBAAa,KAAK;AAClB,gBAAU,CAAC;IACb;AAEA,WAAa;MACX;MACA;QACE;QACA,MAAM;QACN,SAAS;QACT,GAAG;MAAA;MAEL;IAAA;EAEJ;AACF;",
4
+ "sourcesContent": ["import * as React from 'react'\nimport * as ReactDOM from 'react-dom'\nimport {\n createDialog,\n overlayStyles,\n dialogContentVariants,\n type DialogProps as CoreDialogProps,\n} from '@refraction-ui/dialog'\nimport { cn, createKeyboardHandler, devWarn } from '@refraction-ui/shared'\n\n// ---------------------------------------------------------------------------\n// Context\n// ---------------------------------------------------------------------------\n\ninterface DialogContextValue {\n open: boolean\n onOpenChange: (open: boolean) => void\n modal: boolean\n contentId: string\n titleId: string\n descriptionId: string\n /** Whether a DialogTitle / DialogDescription is mounted — only then is it referenced. */\n hasTitle: boolean\n hasDescription: boolean\n setHasTitle: (present: boolean) => void\n setHasDescription: (present: boolean) => void\n}\n\nconst DialogContext = React.createContext<DialogContextValue | null>(null)\n\nfunction useDialogContext(): DialogContextValue {\n const ctx = React.useContext(DialogContext)\n if (!ctx) {\n devWarn(\n 'react-dialog/context-outside-provider',\n 'Dialog compound components (DialogTrigger/DialogContent/DialogTitle/etc.) must be rendered inside a <Dialog>. The missing DialogContext makes this throw.',\n )\n throw new Error('Dialog compound components must be used within <Dialog>')\n }\n return ctx\n}\n\n// ---------------------------------------------------------------------------\n// Dialog (root provider)\n// ---------------------------------------------------------------------------\n\nexport interface DialogProps {\n open?: boolean\n defaultOpen?: boolean\n onOpenChange?: (open: boolean) => void\n modal?: boolean\n children?: React.ReactNode\n}\n\nexport function Dialog({\n open: controlledOpen,\n defaultOpen = false,\n onOpenChange,\n modal = true,\n children,\n}: DialogProps) {\n const [uncontrolledOpen, setUncontrolledOpen] = React.useState(defaultOpen)\n const isControlled = controlledOpen !== undefined\n const open = isControlled ? controlledOpen : uncontrolledOpen\n\n const handleOpenChange = React.useCallback(\n (next: boolean) => {\n if (!isControlled) {\n setUncontrolledOpen(next)\n }\n onOpenChange?.(next)\n },\n [isControlled, onOpenChange],\n )\n\n // Use the headless core to get stable IDs\n const apiRef = React.useRef<ReturnType<typeof createDialog> | null>(null)\n if (apiRef.current === null) {\n apiRef.current = createDialog({ open, modal })\n }\n const api = apiRef.current\n const [hasTitle, setHasTitle] = React.useState(false)\n const [hasDescription, setHasDescription] = React.useState(false)\n\n const ctx = React.useMemo<DialogContextValue>(\n () => ({\n open,\n onOpenChange: handleOpenChange,\n modal,\n contentId: api.ids.content,\n titleId: api.ids.title,\n descriptionId: api.ids.description,\n hasTitle,\n hasDescription,\n setHasTitle,\n setHasDescription,\n }),\n [open, handleOpenChange, modal, api.ids.content, api.ids.title, api.ids.description, hasTitle, hasDescription],\n )\n\n return React.createElement(DialogContext.Provider, { value: ctx }, children)\n}\n\n// ---------------------------------------------------------------------------\n// DialogTrigger\n// ---------------------------------------------------------------------------\n\nexport interface DialogTriggerProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {\n asChild?: boolean\n}\n\nexport const DialogTrigger = React.forwardRef<HTMLButtonElement, DialogTriggerProps>(\n function DialogTrigger({ onClick, children, ...props }, ref) {\n const { open, onOpenChange, contentId } = useDialogContext()\n\n const handleClick = (e: React.MouseEvent<HTMLButtonElement>) => {\n onOpenChange(!open)\n onClick?.(e)\n }\n\n return React.createElement(\n 'button',\n {\n ref,\n type: 'button',\n 'aria-expanded': open,\n 'aria-controls': contentId,\n 'aria-haspopup': 'dialog',\n onClick: handleClick,\n ...props,\n },\n children,\n )\n },\n)\n\n// ---------------------------------------------------------------------------\n// DialogOverlay\n// ---------------------------------------------------------------------------\n\nexport interface DialogOverlayProps extends React.HTMLAttributes<HTMLDivElement> {}\n\nexport const DialogOverlay = React.forwardRef<HTMLDivElement, DialogOverlayProps>(\n function DialogOverlay({ className, onClick, ...props }, ref) {\n const { open, onOpenChange } = useDialogContext()\n\n if (!open) return null\n\n const handleClick = (e: React.MouseEvent<HTMLDivElement>) => {\n // Only close if clicking the overlay itself, not children\n if (e.target === e.currentTarget) {\n onOpenChange(false)\n }\n onClick?.(e)\n }\n\n return React.createElement('div', {\n ref,\n className: cn(overlayStyles, className),\n 'data-state': open ? 'open' : 'closed',\n onClick: handleClick,\n ...props,\n })\n },\n)\n\n// ---------------------------------------------------------------------------\n// DialogContent\n// ---------------------------------------------------------------------------\n\nexport interface DialogContentProps extends React.HTMLAttributes<HTMLDivElement> {}\n\n/**\n * Whether `type` appears in the element tree — covers the first and server\n * render, before a mounted DialogTitle/DialogDescription has registered.\n * Parts nested inside custom components are found once they mount.\n */\nfunction containsElement(node: React.ReactNode, type: React.ElementType): boolean {\n let found = false\n React.Children.forEach(node, (child) => {\n if (found || !React.isValidElement<{ children?: React.ReactNode }>(child)) return\n found = child.type === type || containsElement(child.props.children, type)\n })\n return found\n}\n\nexport const DialogContent = React.forwardRef<HTMLDivElement, DialogContentProps>(\n function DialogContent({ className, children, onKeyDown, ...props }, ref) {\n const { open, onOpenChange, modal, contentId, titleId, descriptionId, hasTitle, hasDescription } =\n useDialogContext()\n\n const api = React.useMemo(\n () => createDialog({ open, modal }),\n [open, modal],\n )\n\n const handleKeyDown = (e: React.KeyboardEvent<HTMLDivElement>) => {\n const handler = createKeyboardHandler({\n Escape: (ev) => {\n ev.preventDefault()\n onOpenChange(false)\n },\n })\n handler(e.nativeEvent)\n onKeyDown?.(e)\n }\n\n if (!open) return null\n\n const content = React.createElement(\n 'div',\n {\n ref,\n role: 'dialog',\n 'aria-modal': modal,\n // Reference only parts that exist: an id pointing at nothing leaves the\n // dialog unnamed while looking labelled.\n 'aria-labelledby': hasTitle || containsElement(children, DialogTitle) ? titleId : undefined,\n 'aria-describedby':\n hasDescription || containsElement(children, DialogDescription) ? descriptionId : undefined,\n id: contentId,\n className: cn(dialogContentVariants(), className),\n onKeyDown: handleKeyDown,\n tabIndex: -1,\n ...props,\n },\n children,\n )\n\n // Render via portal if document is available (client-side)\n if (typeof document !== 'undefined') {\n return ReactDOM.createPortal(content, document.body)\n }\n\n // SSR fallback: render inline\n return content\n },\n)\n\n// ---------------------------------------------------------------------------\n// DialogHeader\n// ---------------------------------------------------------------------------\n\nexport interface DialogHeaderProps extends React.HTMLAttributes<HTMLDivElement> {}\n\nexport const DialogHeader = React.forwardRef<HTMLDivElement, DialogHeaderProps>(\n function DialogHeader({ className, ...props }, ref) {\n return React.createElement('div', {\n ref,\n className: cn('flex flex-col space-y-1.5 text-center sm:text-left', className),\n ...props,\n })\n },\n)\n\n// ---------------------------------------------------------------------------\n// DialogFooter\n// ---------------------------------------------------------------------------\n\nexport interface DialogFooterProps extends React.HTMLAttributes<HTMLDivElement> {}\n\nexport const DialogFooter = React.forwardRef<HTMLDivElement, DialogFooterProps>(\n function DialogFooter({ className, ...props }, ref) {\n return React.createElement('div', {\n ref,\n className: cn(\n 'flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2',\n className,\n ),\n ...props,\n })\n },\n)\n\n// ---------------------------------------------------------------------------\n// DialogTitle\n// ---------------------------------------------------------------------------\n\nexport interface DialogTitleProps extends React.HTMLAttributes<HTMLHeadingElement> {}\n\nexport const DialogTitle = React.forwardRef<HTMLHeadingElement, DialogTitleProps>(\n function DialogTitle({ className, ...props }, ref) {\n const { titleId, setHasTitle } = useDialogContext()\n React.useEffect(() => {\n setHasTitle(true)\n return () => setHasTitle(false)\n }, [setHasTitle])\n\n return React.createElement('h2', {\n ref,\n id: titleId,\n className: cn('text-lg font-semibold leading-none tracking-tight', className),\n ...props,\n })\n },\n)\n\n// ---------------------------------------------------------------------------\n// DialogDescription\n// ---------------------------------------------------------------------------\n\nexport interface DialogDescriptionProps extends React.HTMLAttributes<HTMLParagraphElement> {}\n\nexport const DialogDescription = React.forwardRef<\n HTMLParagraphElement,\n DialogDescriptionProps\n>(function DialogDescription({ className, ...props }, ref) {\n const { descriptionId, setHasDescription } = useDialogContext()\n React.useEffect(() => {\n setHasDescription(true)\n return () => setHasDescription(false)\n }, [setHasDescription])\n\n return React.createElement('p', {\n ref,\n id: descriptionId,\n className: cn('text-sm text-muted-foreground', className),\n ...props,\n })\n})\n\n// ---------------------------------------------------------------------------\n// DialogClose\n// ---------------------------------------------------------------------------\n\nexport interface DialogCloseProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {}\n\nexport const DialogClose = React.forwardRef<HTMLButtonElement, DialogCloseProps>(\n function DialogClose({ onClick, children, ...props }, ref) {\n const { onOpenChange } = useDialogContext()\n\n const handleClick = (e: React.MouseEvent<HTMLButtonElement>) => {\n onOpenChange(false)\n onClick?.(e)\n }\n\n return React.createElement(\n 'button',\n {\n ref,\n type: 'button',\n onClick: handleClick,\n ...props,\n },\n children,\n )\n },\n)\n"],
5
+ "mappings": "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",
6
6
  "names": ["DialogTrigger", "DialogOverlay", "DialogContent", "DialogHeader", "DialogFooter", "DialogTitle", "DialogDescription", "DialogClose"]
7
7
  }
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  cn,
3
3
  cva
4
- } from "./chunk-ZF3OHCGV.js";
4
+ } from "./chunk-2Q6HHFAN.js";
5
5
 
6
6
  // ../react-diff-viewer/dist/index.js
7
7
  import * as React from "react";