@refine-studio/ui 0.0.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +102 -2
- package/dist/components/accordion/accordion.d.ts +15 -0
- package/dist/components/accordion/accordion.js +58 -0
- package/dist/components/accordion/accordion.js.map +1 -0
- package/dist/components/alert/alert.d.ts +24 -0
- package/dist/components/alert/alert.js +98 -0
- package/dist/components/alert/alert.js.map +1 -0
- package/dist/components/alert-dialog/alert-dialog.d.ts +36 -0
- package/dist/components/alert-dialog/alert-dialog.js +112 -0
- package/dist/components/alert-dialog/alert-dialog.js.map +1 -0
- package/dist/components/app-shell/app-shell.d.ts +77 -0
- package/dist/components/app-shell/app-shell.js +224 -0
- package/dist/components/app-shell/app-shell.js.map +1 -0
- package/dist/components/avatar/avatar.d.ts +32 -0
- package/dist/components/avatar/avatar.js +83 -0
- package/dist/components/avatar/avatar.js.map +1 -0
- package/dist/components/badge/badge.d.ts +15 -0
- package/dist/components/badge/badge.js +50 -0
- package/dist/components/badge/badge.js.map +1 -0
- package/dist/components/breadcrumb/breadcrumb.d.ts +24 -0
- package/dist/components/breadcrumb/breadcrumb.js +82 -0
- package/dist/components/breadcrumb/breadcrumb.js.map +1 -0
- package/dist/components/button/button.d.ts +15 -0
- package/dist/components/button/button.js +75 -0
- package/dist/components/button/button.js.map +1 -0
- package/dist/components/card/card.d.ts +46 -0
- package/dist/components/card/card.js +124 -0
- package/dist/components/card/card.js.map +1 -0
- package/dist/components/checkbox/checkbox.d.ts +6 -0
- package/dist/components/checkbox/checkbox.js +31 -0
- package/dist/components/checkbox/checkbox.js.map +1 -0
- package/dist/components/chip/chip.d.ts +25 -0
- package/dist/components/chip/chip.js +54 -0
- package/dist/components/chip/chip.js.map +1 -0
- package/dist/components/code/code.d.ts +15 -0
- package/dist/components/code/code.js +63 -0
- package/dist/components/code/code.js.map +1 -0
- package/dist/components/collapsible/collapsible.d.ts +14 -0
- package/dist/components/collapsible/collapsible.js +55 -0
- package/dist/components/collapsible/collapsible.js.map +1 -0
- package/dist/components/combobox/combobox.d.ts +33 -0
- package/dist/components/combobox/combobox.js +244 -0
- package/dist/components/combobox/combobox.js.map +1 -0
- package/dist/components/command-menu/command-menu.d.ts +35 -0
- package/dist/components/command-menu/command-menu.js +116 -0
- package/dist/components/command-menu/command-menu.js.map +1 -0
- package/dist/components/context-menu/context-menu.d.ts +45 -0
- package/dist/components/context-menu/context-menu.js +136 -0
- package/dist/components/context-menu/context-menu.js.map +1 -0
- package/dist/components/data-table/data-table.d.ts +49 -0
- package/dist/components/data-table/data-table.js +171 -0
- package/dist/components/data-table/data-table.js.map +1 -0
- package/dist/components/data-table/sort-rows.d.ts +6 -0
- package/dist/components/data-table/sort-rows.js +33 -0
- package/dist/components/data-table/sort-rows.js.map +1 -0
- package/dist/components/dialog/dialog.d.ts +42 -0
- package/dist/components/dialog/dialog.js +118 -0
- package/dist/components/dialog/dialog.js.map +1 -0
- package/dist/components/dropdown-menu/dropdown-menu.d.ts +45 -0
- package/dist/components/dropdown-menu/dropdown-menu.js +137 -0
- package/dist/components/dropdown-menu/dropdown-menu.js.map +1 -0
- package/dist/components/dropdown-menu/menu-styles.d.ts +10 -0
- package/dist/components/dropdown-menu/menu-styles.js +34 -0
- package/dist/components/dropdown-menu/menu-styles.js.map +1 -0
- package/dist/components/empty-state/empty-state.d.ts +12 -0
- package/dist/components/empty-state/empty-state.js +46 -0
- package/dist/components/empty-state/empty-state.js.map +1 -0
- package/dist/components/eyebrow/eyebrow.d.ts +9 -0
- package/dist/components/eyebrow/eyebrow.js +25 -0
- package/dist/components/eyebrow/eyebrow.js.map +1 -0
- package/dist/components/field/field.d.ts +56 -0
- package/dist/components/field/field.js +135 -0
- package/dist/components/field/field.js.map +1 -0
- package/dist/components/glow-border/glow-border.d.ts +9 -0
- package/dist/components/glow-border/glow-border.js +39 -0
- package/dist/components/glow-border/glow-border.js.map +1 -0
- package/dist/components/hex-field/hex-field.d.ts +12 -0
- package/dist/components/hex-field/hex-field.js +86 -0
- package/dist/components/hex-field/hex-field.js.map +1 -0
- package/dist/components/input/input.d.ts +14 -0
- package/dist/components/input/input.js +52 -0
- package/dist/components/input/input.js.map +1 -0
- package/dist/components/kbd/kbd.d.ts +9 -0
- package/dist/components/kbd/kbd.js +26 -0
- package/dist/components/kbd/kbd.js.map +1 -0
- package/dist/components/label/label.d.ts +6 -0
- package/dist/components/label/label.js +17 -0
- package/dist/components/label/label.js.map +1 -0
- package/dist/components/logo/logo-paths.d.ts +5 -0
- package/dist/components/logo/logo-paths.js +20 -0
- package/dist/components/logo/logo-paths.js.map +1 -0
- package/dist/components/logo/logo.d.ts +18 -0
- package/dist/components/logo/logo.js +94 -0
- package/dist/components/logo/logo.js.map +1 -0
- package/dist/components/marquee/marquee.d.ts +15 -0
- package/dist/components/marquee/marquee.js +54 -0
- package/dist/components/marquee/marquee.js.map +1 -0
- package/dist/components/page-header/page-header.d.ts +15 -0
- package/dist/components/page-header/page-header.js +50 -0
- package/dist/components/page-header/page-header.js.map +1 -0
- package/dist/components/pagination/pagination.d.ts +28 -0
- package/dist/components/pagination/pagination.js +95 -0
- package/dist/components/pagination/pagination.js.map +1 -0
- package/dist/components/popover/popover.d.ts +14 -0
- package/dist/components/popover/popover.js +48 -0
- package/dist/components/popover/popover.js.map +1 -0
- package/dist/components/progress/progress.d.ts +14 -0
- package/dist/components/progress/progress.js +41 -0
- package/dist/components/progress/progress.js.map +1 -0
- package/dist/components/radio-group/radio-group.d.ts +10 -0
- package/dist/components/radio-group/radio-group.js +33 -0
- package/dist/components/radio-group/radio-group.js.map +1 -0
- package/dist/components/section-heading/section-heading.d.ts +18 -0
- package/dist/components/section-heading/section-heading.js +57 -0
- package/dist/components/section-heading/section-heading.js.map +1 -0
- package/dist/components/select/select.d.ts +32 -0
- package/dist/components/select/select.js +100 -0
- package/dist/components/select/select.js.map +1 -0
- package/dist/components/separator/separator.d.ts +10 -0
- package/dist/components/separator/separator.js +37 -0
- package/dist/components/separator/separator.js.map +1 -0
- package/dist/components/sheet/sheet.d.ts +29 -0
- package/dist/components/sheet/sheet.js +130 -0
- package/dist/components/sheet/sheet.js.map +1 -0
- package/dist/components/skeleton/skeleton.d.ts +5 -0
- package/dist/components/skeleton/skeleton.js +18 -0
- package/dist/components/skeleton/skeleton.js.map +1 -0
- package/dist/components/slider/slider.d.ts +10 -0
- package/dist/components/slider/slider.js +36 -0
- package/dist/components/slider/slider.js.map +1 -0
- package/dist/components/spinner/spinner.d.ts +9 -0
- package/dist/components/spinner/spinner.js +40 -0
- package/dist/components/spinner/spinner.js.map +1 -0
- package/dist/components/spotlight/spotlight.d.ts +9 -0
- package/dist/components/spotlight/spotlight.js +32 -0
- package/dist/components/spotlight/spotlight.js.map +1 -0
- package/dist/components/starfield/starfield.d.ts +11 -0
- package/dist/components/starfield/starfield.js +76 -0
- package/dist/components/starfield/starfield.js.map +1 -0
- package/dist/components/stat/stat.d.ts +28 -0
- package/dist/components/stat/stat.js +100 -0
- package/dist/components/stat/stat.js.map +1 -0
- package/dist/components/switch/switch.d.ts +13 -0
- package/dist/components/switch/switch.js +44 -0
- package/dist/components/switch/switch.js.map +1 -0
- package/dist/components/table/table.d.ts +52 -0
- package/dist/components/table/table.js +96 -0
- package/dist/components/table/table.js.map +1 -0
- package/dist/components/tabs/tabs.d.ts +24 -0
- package/dist/components/tabs/tabs.js +89 -0
- package/dist/components/tabs/tabs.js.map +1 -0
- package/dist/components/textarea/textarea.d.ts +5 -0
- package/dist/components/textarea/textarea.js +20 -0
- package/dist/components/textarea/textarea.js.map +1 -0
- package/dist/components/theme-switcher/theme-switcher.d.ts +7 -0
- package/dist/components/theme-switcher/theme-switcher.js +57 -0
- package/dist/components/theme-switcher/theme-switcher.js.map +1 -0
- package/dist/components/toaster/toaster.d.ts +7 -0
- package/dist/components/toaster/toaster.js +43 -0
- package/dist/components/toaster/toaster.js.map +1 -0
- package/dist/components/toggle-group/toggle-group.d.ts +24 -0
- package/dist/components/toggle-group/toggle-group.js +84 -0
- package/dist/components/toggle-group/toggle-group.js.map +1 -0
- package/dist/components/tooltip/tooltip.d.ts +19 -0
- package/dist/components/tooltip/tooltip.js +49 -0
- package/dist/components/tooltip/tooltip.js.map +1 -0
- package/dist/fonts/geist-cyrillic-ext-wght-normal.woff2 +0 -0
- package/dist/fonts/geist-cyrillic-wght-normal.woff2 +0 -0
- package/dist/fonts/geist-latin-ext-wght-normal.woff2 +0 -0
- package/dist/fonts/geist-latin-wght-normal.woff2 +0 -0
- package/dist/fonts/geist-mono-cyrillic-ext-wght-normal.woff2 +0 -0
- package/dist/fonts/geist-mono-cyrillic-wght-normal.woff2 +0 -0
- package/dist/fonts/geist-mono-latin-ext-wght-normal.woff2 +0 -0
- package/dist/fonts/geist-mono-latin-wght-normal.woff2 +0 -0
- package/dist/fonts/geist-mono-symbols2-wght-normal.woff2 +0 -0
- package/dist/fonts/geist-mono-vietnamese-wght-normal.woff2 +0 -0
- package/dist/fonts/geist-mono.LICENSE +93 -0
- package/dist/fonts/geist-vietnamese-wght-normal.woff2 +0 -0
- package/dist/fonts/geist.LICENSE +93 -0
- package/dist/icons/icon.d.ts +10 -0
- package/dist/icons/icon.js +13 -0
- package/dist/icons/icon.js.map +1 -0
- package/dist/icons/refine-icon-names.d.ts +5 -0
- package/dist/icons/refine-icon-names.js +16 -0
- package/dist/icons/refine-icon-names.js.map +1 -0
- package/dist/icons/refine-icons.d.ts +467 -0
- package/dist/icons/refine-icons.js +473 -0
- package/dist/icons/refine-icons.js.map +1 -0
- package/dist/icons/with-refine-weight.d.ts +11 -0
- package/dist/icons/with-refine-weight.js +25 -0
- package/dist/icons/with-refine-weight.js.map +1 -0
- package/dist/index.d.ts +61 -0
- package/dist/index.js +61 -0
- package/dist/lib/cn.d.ts +5 -0
- package/dist/lib/cn.js +49 -0
- package/dist/lib/cn.js.map +1 -0
- package/dist/lib/use-breakpoint.d.ts +16 -0
- package/dist/lib/use-breakpoint.js +52 -0
- package/dist/lib/use-breakpoint.js.map +1 -0
- package/dist/styles.css +697 -0
- package/dist/theme/theme-provider.d.ts +31 -0
- package/dist/theme/theme-provider.js +115 -0
- package/dist/theme/theme-provider.js.map +1 -0
- package/dist/theme/theme-scope.d.ts +12 -0
- package/dist/theme/theme-scope.js +22 -0
- package/dist/theme/theme-scope.js.map +1 -0
- package/dist/theme/theme.d.ts +20 -0
- package/dist/theme/theme.js +37 -0
- package/dist/theme/theme.js.map +1 -0
- package/package.json +91 -5
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { type ComponentProps, type ReactNode } from 'react';
|
|
2
|
+
import type { SortDirection, SortValue } from './sort-rows';
|
|
3
|
+
import { TableHead } from '../table/table';
|
|
4
|
+
export type { SortDirection } from './sort-rows';
|
|
5
|
+
export interface DataTableSort {
|
|
6
|
+
columnId: string;
|
|
7
|
+
direction: SortDirection;
|
|
8
|
+
}
|
|
9
|
+
export interface DataTableColumn<T> {
|
|
10
|
+
id: string;
|
|
11
|
+
header: ReactNode;
|
|
12
|
+
cell: (row: T) => ReactNode;
|
|
13
|
+
cellClassName?: string;
|
|
14
|
+
defaultSortDirection?: SortDirection;
|
|
15
|
+
headClassName?: string;
|
|
16
|
+
numeric?: boolean;
|
|
17
|
+
sortValue?: (row: T) => SortValue;
|
|
18
|
+
}
|
|
19
|
+
interface TableHeadSortableProps extends ComponentProps<typeof TableHead> {
|
|
20
|
+
direction: SortDirection | null;
|
|
21
|
+
onSort: () => void;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* A header cell whose label is a sort button; `direction` is null while another column holds the sort.
|
|
25
|
+
*/
|
|
26
|
+
export declare const TableHeadSortable: ({ children, className, direction, numeric, onSort, ...props }: TableHeadSortableProps) => import("react").JSX.Element;
|
|
27
|
+
interface DataTableProps<T> {
|
|
28
|
+
columns: DataTableColumn<T>[];
|
|
29
|
+
rows: T[];
|
|
30
|
+
getRowId: (row: T) => string;
|
|
31
|
+
'aria-label'?: string;
|
|
32
|
+
className?: string;
|
|
33
|
+
containerClassName?: string;
|
|
34
|
+
defaultExpanded?: string[];
|
|
35
|
+
defaultSort?: DataTableSort | null;
|
|
36
|
+
empty?: ReactNode;
|
|
37
|
+
expanded?: string[];
|
|
38
|
+
expandMultiple?: boolean;
|
|
39
|
+
footer?: ReactNode;
|
|
40
|
+
onExpandedChange?: (expanded: string[]) => void;
|
|
41
|
+
onSortChange?: (sort: DataTableSort) => void;
|
|
42
|
+
renderDetail?: (row: T) => ReactNode;
|
|
43
|
+
sort?: DataTableSort | null;
|
|
44
|
+
stickyHeader?: boolean;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Renders rows under sortable column headers; with `renderDetail`, each row gets a chevron that opens a full-width detail row beneath it.
|
|
48
|
+
*/
|
|
49
|
+
export declare const DataTable: <T>({ "aria-label": ariaLabel, className, columns, containerClassName, defaultExpanded, defaultSort, empty, expanded: controlledExpanded, expandMultiple, footer, getRowId, onExpandedChange, onSortChange, renderDetail, rows, sort: controlledSort, stickyHeader, }: DataTableProps<T>) => import("react").JSX.Element;
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
import { cn } from "../../lib/cn.js";
|
|
2
|
+
import { RefineIconArrowDownSM, RefineIconArrowDownUp, RefineIconArrowUpSM, RefineIconChevronDown } from "../../icons/refine-icons.js";
|
|
3
|
+
import { Table, TableBody, TableCell, TableFooter, TableHead, TableHeader, TableRow } from "../table/table.js";
|
|
4
|
+
import { sortRows } from "./sort-rows.js";
|
|
5
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
6
|
+
import { Fragment as Fragment$1, useState } from "react";
|
|
7
|
+
// src/components/data-table/data-table.tsx
|
|
8
|
+
var SORT_ICON_BY_DIRECTION = {
|
|
9
|
+
ascending: RefineIconArrowUpSM,
|
|
10
|
+
descending: RefineIconArrowDownSM
|
|
11
|
+
};
|
|
12
|
+
/**
|
|
13
|
+
* A header cell whose label is a sort button; `direction` is null while another column holds the sort.
|
|
14
|
+
*/
|
|
15
|
+
var TableHeadSortable = ({ children, className, direction, numeric, onSort, ...props }) => {
|
|
16
|
+
const Icon = direction ? SORT_ICON_BY_DIRECTION[direction] : RefineIconArrowDownUp;
|
|
17
|
+
return /* @__PURE__ */ jsx(TableHead, {
|
|
18
|
+
"aria-sort": direction ?? "none",
|
|
19
|
+
className,
|
|
20
|
+
"data-slot": "table-head-sortable",
|
|
21
|
+
numeric,
|
|
22
|
+
...props,
|
|
23
|
+
children: /* @__PURE__ */ jsxs("button", {
|
|
24
|
+
className: cn("group/sort gap-1 inline-flex items-center rounded-inner uppercase focus-ring transition-colors hover:text-foreground", direction && "text-foreground", numeric && "flex-row-reverse"),
|
|
25
|
+
onClick: onSort,
|
|
26
|
+
type: "button",
|
|
27
|
+
children: [children, /* @__PURE__ */ jsx(Icon, {
|
|
28
|
+
"aria-hidden": true,
|
|
29
|
+
className: cn("size-3.5 shrink-0 transition-opacity", !direction && "opacity-0 group-hover/sort:opacity-60 group-focus-visible/sort:opacity-60")
|
|
30
|
+
})]
|
|
31
|
+
})
|
|
32
|
+
});
|
|
33
|
+
};
|
|
34
|
+
/**
|
|
35
|
+
* Returns the direction a first click on the column sorts in: text A→Z, numbers largest first, unless the column says otherwise.
|
|
36
|
+
*/
|
|
37
|
+
var firstDirection = (column) => {
|
|
38
|
+
return column.defaultSortDirection ?? (column.numeric ? "descending" : "ascending");
|
|
39
|
+
};
|
|
40
|
+
/**
|
|
41
|
+
* Renders rows under sortable column headers; with `renderDetail`, each row gets a chevron that opens a full-width detail row beneath it.
|
|
42
|
+
*/
|
|
43
|
+
var DataTable = ({ "aria-label": ariaLabel, className, columns, containerClassName, defaultExpanded = [], defaultSort = null, empty = "Nothing to show.", expanded: controlledExpanded, expandMultiple = false, footer, getRowId, onExpandedChange, onSortChange, renderDetail, rows, sort: controlledSort, stickyHeader = false }) => {
|
|
44
|
+
const [uncontrolledSort, setUncontrolledSort] = useState(defaultSort);
|
|
45
|
+
const [uncontrolledExpanded, setUncontrolledExpanded] = useState(defaultExpanded);
|
|
46
|
+
const sort = controlledSort === void 0 ? uncontrolledSort : controlledSort;
|
|
47
|
+
const expanded = controlledExpanded ?? uncontrolledExpanded;
|
|
48
|
+
const isExpandable = !!renderDetail;
|
|
49
|
+
const columnCount = columns.length + (isExpandable ? 1 : 0);
|
|
50
|
+
const sortColumn = columns.find((column) => {
|
|
51
|
+
return column.id === sort?.columnId;
|
|
52
|
+
});
|
|
53
|
+
const sorted = sort && sortColumn?.sortValue ? sortRows(rows, sortColumn.sortValue, sort.direction) : rows;
|
|
54
|
+
/**
|
|
55
|
+
* Sorts by the column, flipping the direction when it already holds the sort.
|
|
56
|
+
*/
|
|
57
|
+
const handleSort = (column) => {
|
|
58
|
+
const isSameColumn = sort?.columnId === column.id;
|
|
59
|
+
let direction = firstDirection(column);
|
|
60
|
+
if (isSameColumn) direction = sort.direction === "ascending" ? "descending" : "ascending";
|
|
61
|
+
const next = {
|
|
62
|
+
columnId: column.id,
|
|
63
|
+
direction
|
|
64
|
+
};
|
|
65
|
+
if (controlledSort === void 0) setUncontrolledSort(next);
|
|
66
|
+
onSortChange?.(next);
|
|
67
|
+
};
|
|
68
|
+
/**
|
|
69
|
+
* Opens or closes one row; without `expandMultiple`, opening a row closes the one open before it.
|
|
70
|
+
*/
|
|
71
|
+
const handleToggle = (id) => {
|
|
72
|
+
const isOpen = expanded.includes(id);
|
|
73
|
+
let next = expandMultiple ? [...expanded, id] : [id];
|
|
74
|
+
if (isOpen) next = expanded.filter((openId) => {
|
|
75
|
+
return openId !== id;
|
|
76
|
+
});
|
|
77
|
+
if (controlledExpanded === void 0) setUncontrolledExpanded(next);
|
|
78
|
+
onExpandedChange?.(next);
|
|
79
|
+
};
|
|
80
|
+
return /* @__PURE__ */ jsxs(Table, {
|
|
81
|
+
"aria-label": ariaLabel,
|
|
82
|
+
className,
|
|
83
|
+
containerClassName,
|
|
84
|
+
"data-slot": "data-table",
|
|
85
|
+
stickyHeader,
|
|
86
|
+
children: [
|
|
87
|
+
/* @__PURE__ */ jsx(TableHeader, { children: /* @__PURE__ */ jsxs(TableRow, {
|
|
88
|
+
hoverable: false,
|
|
89
|
+
children: [isExpandable ? /* @__PURE__ */ jsx(TableHead, {
|
|
90
|
+
className: "w-0 pr-0",
|
|
91
|
+
children: /* @__PURE__ */ jsx("span", {
|
|
92
|
+
className: "sr-only",
|
|
93
|
+
children: "Details"
|
|
94
|
+
})
|
|
95
|
+
}) : null, columns.map((column) => {
|
|
96
|
+
if (!column.sortValue) return /* @__PURE__ */ jsx(TableHead, {
|
|
97
|
+
className: column.headClassName,
|
|
98
|
+
numeric: column.numeric,
|
|
99
|
+
children: column.header
|
|
100
|
+
}, column.id);
|
|
101
|
+
return /* @__PURE__ */ jsx(TableHeadSortable, {
|
|
102
|
+
className: column.headClassName,
|
|
103
|
+
direction: sort?.columnId === column.id ? sort.direction : null,
|
|
104
|
+
numeric: column.numeric,
|
|
105
|
+
onSort: () => {
|
|
106
|
+
handleSort(column);
|
|
107
|
+
},
|
|
108
|
+
children: column.header
|
|
109
|
+
}, column.id);
|
|
110
|
+
})]
|
|
111
|
+
}) }),
|
|
112
|
+
/* @__PURE__ */ jsxs(TableBody, { children: [sorted.length === 0 ? /* @__PURE__ */ jsx(TableRow, {
|
|
113
|
+
hoverable: false,
|
|
114
|
+
children: /* @__PURE__ */ jsx(TableCell, {
|
|
115
|
+
className: "h-24 text-center whitespace-normal text-muted-foreground",
|
|
116
|
+
colSpan: columnCount,
|
|
117
|
+
children: empty
|
|
118
|
+
})
|
|
119
|
+
}) : null, sorted.map((row) => {
|
|
120
|
+
const id = getRowId(row);
|
|
121
|
+
const isOpen = isExpandable && expanded.includes(id);
|
|
122
|
+
const detailId = `data-table-detail-${id}`;
|
|
123
|
+
const toggleLabel = isOpen ? "Hide details" : "Show details";
|
|
124
|
+
return /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsxs(TableRow, {
|
|
125
|
+
"data-state": isOpen ? "selected" : void 0,
|
|
126
|
+
children: [isExpandable ? /* @__PURE__ */ jsx(TableCell, {
|
|
127
|
+
className: "w-0 pr-0",
|
|
128
|
+
children: /* @__PURE__ */ jsxs("button", {
|
|
129
|
+
"aria-controls": isOpen ? detailId : void 0,
|
|
130
|
+
"aria-expanded": isOpen,
|
|
131
|
+
className: "size-6 grid place-items-center rounded-inner text-muted-foreground focus-ring hover:bg-hover hover:text-foreground",
|
|
132
|
+
"data-slot": "data-table-toggle",
|
|
133
|
+
onClick: () => {
|
|
134
|
+
handleToggle(id);
|
|
135
|
+
},
|
|
136
|
+
title: toggleLabel,
|
|
137
|
+
type: "button",
|
|
138
|
+
children: [/* @__PURE__ */ jsx(RefineIconChevronDown, {
|
|
139
|
+
"aria-hidden": true,
|
|
140
|
+
className: cn("size-4 transition-transform", !isOpen && "-rotate-90")
|
|
141
|
+
}), /* @__PURE__ */ jsx("span", {
|
|
142
|
+
className: "sr-only",
|
|
143
|
+
children: toggleLabel
|
|
144
|
+
})]
|
|
145
|
+
})
|
|
146
|
+
}) : null, columns.map((column) => {
|
|
147
|
+
return /* @__PURE__ */ jsx(TableCell, {
|
|
148
|
+
className: column.cellClassName,
|
|
149
|
+
numeric: column.numeric,
|
|
150
|
+
children: column.cell(row)
|
|
151
|
+
}, column.id);
|
|
152
|
+
})]
|
|
153
|
+
}), isOpen ? /* @__PURE__ */ jsx(TableRow, {
|
|
154
|
+
className: "[&>td]:bg-gem/5",
|
|
155
|
+
"data-slot": "data-table-detail",
|
|
156
|
+
hoverable: false,
|
|
157
|
+
id: detailId,
|
|
158
|
+
children: /* @__PURE__ */ jsx(TableCell, {
|
|
159
|
+
className: "px-3 py-4 h-auto whitespace-normal",
|
|
160
|
+
colSpan: columnCount,
|
|
161
|
+
children: renderDetail(row)
|
|
162
|
+
})
|
|
163
|
+
}) : null] }, id);
|
|
164
|
+
})] }),
|
|
165
|
+
footer ? /* @__PURE__ */ jsx(TableFooter, { children: footer }) : null
|
|
166
|
+
]
|
|
167
|
+
});
|
|
168
|
+
};
|
|
169
|
+
export { DataTable, TableHeadSortable };
|
|
170
|
+
|
|
171
|
+
//# sourceMappingURL=data-table.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"data-table.js","names":["Fragment"],"sources":["../../../src/components/data-table/data-table.tsx"],"sourcesContent":["import { type ComponentProps, Fragment, type ReactNode, useState } from 'react';\n\nimport {\n RefineIconArrowDownSM,\n RefineIconArrowDownUp,\n RefineIconArrowUpSM,\n RefineIconChevronDown,\n} from '../../icons/refine-icons';\nimport { cn } from '../../lib/cn';\nimport type { SortDirection, SortValue } from './sort-rows';\n\nimport { Table, TableBody, TableCell, TableFooter, TableHead, TableHeader, TableRow } from '../table/table';\nimport { sortRows } from './sort-rows';\n\nexport type { SortDirection } from './sort-rows';\n\nexport interface DataTableSort {\n columnId: string;\n direction: SortDirection;\n}\n\nexport interface DataTableColumn<T> {\n id: string;\n header: ReactNode;\n cell: (row: T) => ReactNode;\n cellClassName?: string;\n defaultSortDirection?: SortDirection;\n headClassName?: string;\n numeric?: boolean;\n sortValue?: (row: T) => SortValue;\n}\n\nconst SORT_ICON_BY_DIRECTION = {\n ascending: RefineIconArrowUpSM,\n descending: RefineIconArrowDownSM,\n} satisfies Record<SortDirection, unknown>;\n\ninterface TableHeadSortableProps extends ComponentProps<typeof TableHead> {\n direction: SortDirection | null;\n onSort: () => void;\n}\n\n/**\n * A header cell whose label is a sort button; `direction` is null while another column holds the sort.\n */\nexport const TableHeadSortable = ({\n children,\n className,\n direction,\n numeric,\n onSort,\n ...props\n}: TableHeadSortableProps) => {\n const Icon = direction ? SORT_ICON_BY_DIRECTION[direction] : RefineIconArrowDownUp;\n return (\n <TableHead\n aria-sort={direction ?? 'none'}\n className={className}\n data-slot=\"table-head-sortable\"\n numeric={numeric}\n {...props}\n >\n <button\n className={cn(\n 'group/sort gap-1 inline-flex items-center rounded-inner uppercase focus-ring transition-colors hover:text-foreground',\n direction && 'text-foreground',\n numeric && 'flex-row-reverse',\n )}\n onClick={onSort}\n type=\"button\"\n >\n {children}\n <Icon\n aria-hidden\n className={cn(\n 'size-3.5 shrink-0 transition-opacity',\n !direction && 'opacity-0 group-hover/sort:opacity-60 group-focus-visible/sort:opacity-60',\n )}\n />\n </button>\n </TableHead>\n );\n};\n\n/**\n * Returns the direction a first click on the column sorts in: text A→Z, numbers largest first, unless the column says otherwise.\n */\nconst firstDirection = <T,>(column: DataTableColumn<T>) => {\n return column.defaultSortDirection ?? (column.numeric ? 'descending' : 'ascending');\n};\n\ninterface DataTableProps<T> {\n columns: DataTableColumn<T>[];\n rows: T[];\n getRowId: (row: T) => string;\n 'aria-label'?: string;\n className?: string;\n containerClassName?: string;\n defaultExpanded?: string[];\n defaultSort?: DataTableSort | null;\n empty?: ReactNode;\n expanded?: string[];\n expandMultiple?: boolean;\n footer?: ReactNode;\n onExpandedChange?: (expanded: string[]) => void;\n onSortChange?: (sort: DataTableSort) => void;\n renderDetail?: (row: T) => ReactNode;\n sort?: DataTableSort | null;\n stickyHeader?: boolean;\n}\n\n/**\n * Renders rows under sortable column headers; with `renderDetail`, each row gets a chevron that opens a full-width detail row beneath it.\n */\nexport const DataTable = <T,>({\n 'aria-label': ariaLabel,\n className,\n columns,\n containerClassName,\n defaultExpanded = [],\n defaultSort = null,\n empty = 'Nothing to show.',\n expanded: controlledExpanded,\n expandMultiple = false,\n footer,\n getRowId,\n onExpandedChange,\n onSortChange,\n renderDetail,\n rows,\n sort: controlledSort,\n stickyHeader = false,\n}: DataTableProps<T>) => {\n const [uncontrolledSort, setUncontrolledSort] = useState(defaultSort);\n const [uncontrolledExpanded, setUncontrolledExpanded] = useState(defaultExpanded);\n const sort = controlledSort === undefined ? uncontrolledSort : controlledSort;\n const expanded = controlledExpanded ?? uncontrolledExpanded;\n const isExpandable = !!renderDetail;\n const columnCount = columns.length + (isExpandable ? 1 : 0);\n const sortColumn = columns.find((column) => {\n return column.id === sort?.columnId;\n });\n const sorted = sort && sortColumn?.sortValue ? sortRows(rows, sortColumn.sortValue, sort.direction) : rows;\n\n /**\n * Sorts by the column, flipping the direction when it already holds the sort.\n */\n const handleSort = (column: DataTableColumn<T>) => {\n const isSameColumn = sort?.columnId === column.id;\n let direction = firstDirection(column);\n if (isSameColumn) direction = sort.direction === 'ascending' ? 'descending' : 'ascending';\n const next = {\n columnId: column.id,\n direction,\n };\n if (controlledSort === undefined) setUncontrolledSort(next);\n onSortChange?.(next);\n };\n\n /**\n * Opens or closes one row; without `expandMultiple`, opening a row closes the one open before it.\n */\n const handleToggle = (id: string) => {\n const isOpen = expanded.includes(id);\n let next = expandMultiple ? [...expanded, id] : [id];\n if (isOpen) {\n next = expanded.filter((openId) => {\n return openId !== id;\n });\n }\n if (controlledExpanded === undefined) setUncontrolledExpanded(next);\n onExpandedChange?.(next);\n };\n\n return (\n <Table\n aria-label={ariaLabel}\n className={className}\n containerClassName={containerClassName}\n data-slot=\"data-table\"\n stickyHeader={stickyHeader}\n >\n <TableHeader>\n <TableRow hoverable={false}>\n {isExpandable ? (\n <TableHead className=\"w-0 pr-0\">\n <span className=\"sr-only\">Details</span>\n </TableHead>\n ) : null}\n {columns.map((column) => {\n if (!column.sortValue) {\n return (\n <TableHead className={column.headClassName} key={column.id} numeric={column.numeric}>\n {column.header}\n </TableHead>\n );\n }\n return (\n <TableHeadSortable\n className={column.headClassName}\n direction={sort?.columnId === column.id ? sort.direction : null}\n key={column.id}\n numeric={column.numeric}\n onSort={() => {\n handleSort(column);\n }}\n >\n {column.header}\n </TableHeadSortable>\n );\n })}\n </TableRow>\n </TableHeader>\n <TableBody>\n {sorted.length === 0 ? (\n <TableRow hoverable={false}>\n <TableCell className=\"h-24 text-center whitespace-normal text-muted-foreground\" colSpan={columnCount}>\n {empty}\n </TableCell>\n </TableRow>\n ) : null}\n {sorted.map((row) => {\n const id = getRowId(row);\n const isOpen = isExpandable && expanded.includes(id);\n const detailId = `data-table-detail-${id}`;\n const toggleLabel = isOpen ? 'Hide details' : 'Show details';\n return (\n <Fragment key={id}>\n <TableRow data-state={isOpen ? 'selected' : undefined}>\n {isExpandable ? (\n <TableCell className=\"w-0 pr-0\">\n <button\n aria-controls={isOpen ? detailId : undefined}\n aria-expanded={isOpen}\n className=\"size-6 grid place-items-center rounded-inner text-muted-foreground focus-ring hover:bg-hover hover:text-foreground\"\n data-slot=\"data-table-toggle\"\n onClick={() => {\n handleToggle(id);\n }}\n title={toggleLabel}\n type=\"button\"\n >\n <RefineIconChevronDown\n aria-hidden\n className={cn('size-4 transition-transform', !isOpen && '-rotate-90')}\n />\n <span className=\"sr-only\">{toggleLabel}</span>\n </button>\n </TableCell>\n ) : null}\n {columns.map((column) => {\n return (\n <TableCell className={column.cellClassName} key={column.id} numeric={column.numeric}>\n {column.cell(row)}\n </TableCell>\n );\n })}\n </TableRow>\n {isOpen ? (\n <TableRow className=\"[&>td]:bg-gem/5\" data-slot=\"data-table-detail\" hoverable={false} id={detailId}>\n <TableCell className=\"px-3 py-4 h-auto whitespace-normal\" colSpan={columnCount}>\n {renderDetail(row)}\n </TableCell>\n </TableRow>\n ) : null}\n </Fragment>\n );\n })}\n </TableBody>\n {footer ? <TableFooter>{footer}</TableFooter> : null}\n </Table>\n );\n};\n"],"mappings":"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"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export type SortDirection = 'ascending' | 'descending';
|
|
2
|
+
export type SortValue = Date | number | string | null | undefined;
|
|
3
|
+
/**
|
|
4
|
+
* Returns a sorted copy of the rows; empty values go last in both directions, and ties keep their input order.
|
|
5
|
+
*/
|
|
6
|
+
export declare const sortRows: <T>(rows: T[], sortValue: (row: T) => SortValue, direction: SortDirection) => T[];
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
// src/components/data-table/sort-rows.ts
|
|
2
|
+
/**
|
|
3
|
+
* Compares two sort values ascending: numbers and dates by size, text by locale with digits read as numbers.
|
|
4
|
+
*/
|
|
5
|
+
var compareValues = (a, b) => {
|
|
6
|
+
if (a instanceof Date && b instanceof Date) return a.getTime() - b.getTime();
|
|
7
|
+
if (typeof a === "number" && typeof b === "number") return a - b;
|
|
8
|
+
return String(a).localeCompare(String(b), void 0, {
|
|
9
|
+
numeric: true,
|
|
10
|
+
sensitivity: "base"
|
|
11
|
+
});
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* Returns true for a value the table treats as empty, which always sorts last.
|
|
15
|
+
*/
|
|
16
|
+
var isEmptyValue = (value) => {
|
|
17
|
+
return value === null || value === void 0 || value === "";
|
|
18
|
+
};
|
|
19
|
+
/**
|
|
20
|
+
* Returns a sorted copy of the rows; empty values go last in both directions, and ties keep their input order.
|
|
21
|
+
*/
|
|
22
|
+
var sortRows = (rows, sortValue, direction) => {
|
|
23
|
+
const sign = direction === "ascending" ? 1 : -1;
|
|
24
|
+
return [...rows].sort((rowA, rowB) => {
|
|
25
|
+
const a = sortValue(rowA);
|
|
26
|
+
const b = sortValue(rowB);
|
|
27
|
+
if (isEmptyValue(a) || isEmptyValue(b)) return Number(isEmptyValue(a)) - Number(isEmptyValue(b));
|
|
28
|
+
return compareValues(a, b) * sign;
|
|
29
|
+
});
|
|
30
|
+
};
|
|
31
|
+
export { sortRows };
|
|
32
|
+
|
|
33
|
+
//# sourceMappingURL=sort-rows.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sort-rows.js","names":[],"sources":["../../../src/components/data-table/sort-rows.ts"],"sourcesContent":["export type SortDirection = 'ascending' | 'descending';\n\nexport type SortValue = Date | number | string | null | undefined;\n\n/**\n * Compares two sort values ascending: numbers and dates by size, text by locale with digits read as numbers.\n */\nconst compareValues = (a: SortValue, b: SortValue) => {\n if (a instanceof Date && b instanceof Date) return a.getTime() - b.getTime();\n if (typeof a === 'number' && typeof b === 'number') return a - b;\n return String(a).localeCompare(String(b), undefined, {\n numeric: true,\n sensitivity: 'base',\n });\n};\n\n/**\n * Returns true for a value the table treats as empty, which always sorts last.\n */\nconst isEmptyValue = (value: SortValue) => {\n return value === null || value === undefined || value === '';\n};\n\n/**\n * Returns a sorted copy of the rows; empty values go last in both directions, and ties keep their input order.\n */\nexport const sortRows = <T>(rows: T[], sortValue: (row: T) => SortValue, direction: SortDirection) => {\n const sign = direction === 'ascending' ? 1 : -1;\n return [...rows].sort((rowA, rowB) => {\n const a = sortValue(rowA);\n const b = sortValue(rowB);\n if (isEmptyValue(a) || isEmptyValue(b)) return Number(isEmptyValue(a)) - Number(isEmptyValue(b));\n return compareValues(a, b) * sign;\n });\n};\n"],"mappings":";;;;AAOA,IAAM,iBAAiB,GAAc,MAAiB;CACpD,IAAI,aAAa,QAAQ,aAAa,MAAM,OAAO,EAAE,QAAQ,IAAI,EAAE,QAAQ;CAC3E,IAAI,OAAO,MAAM,YAAY,OAAO,MAAM,UAAU,OAAO,IAAI;CAC/D,OAAO,OAAO,CAAC,CAAC,CAAC,cAAc,OAAO,CAAC,GAAG,KAAA,GAAW;EACnD,SAAS;EACT,aAAa;CACf,CAAC;AACH;;;;AAKA,IAAM,gBAAgB,UAAqB;CACzC,OAAO,UAAU,QAAQ,UAAU,KAAA,KAAa,UAAU;AAC5D;;;;AAKA,IAAa,YAAe,MAAW,WAAkC,cAA6B;CACpG,MAAM,OAAO,cAAc,cAAc,IAAI;CAC7C,OAAO,CAAC,GAAG,IAAI,CAAC,CAAC,MAAM,MAAM,SAAS;EACpC,MAAM,IAAI,UAAU,IAAI;EACxB,MAAM,IAAI,UAAU,IAAI;EACxB,IAAI,aAAa,CAAC,KAAK,aAAa,CAAC,GAAG,OAAO,OAAO,aAAa,CAAC,CAAC,IAAI,OAAO,aAAa,CAAC,CAAC;EAC/F,OAAO,cAAc,GAAG,CAAC,IAAI;CAC/B,CAAC;AACH"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { type VariantProps } from 'class-variance-authority';
|
|
2
|
+
import { Dialog as DialogPrimitive } from 'radix-ui';
|
|
3
|
+
import type { ComponentProps } from 'react';
|
|
4
|
+
export declare const DIALOG_OVERLAY_CLASS_NAME: string;
|
|
5
|
+
export declare const DIALOG_CLOSE_CLASS_NAME: string;
|
|
6
|
+
declare const dialogContentVariants: (props?: ({
|
|
7
|
+
size?: "sm" | "md" | "lg" | "xl" | "full" | null | undefined;
|
|
8
|
+
} & import("class-variance-authority/types").ClassProp) | undefined) => string;
|
|
9
|
+
/**
|
|
10
|
+
* Holds the open state of a modal dialog.
|
|
11
|
+
*/
|
|
12
|
+
export declare const Dialog: (props: ComponentProps<typeof DialogPrimitive.Root>) => import("react").JSX.Element;
|
|
13
|
+
/**
|
|
14
|
+
* Opens the dialog; pass `asChild` to turn any button into the trigger.
|
|
15
|
+
*/
|
|
16
|
+
export declare const DialogTrigger: (props: ComponentProps<typeof DialogPrimitive.Trigger>) => import("react").JSX.Element;
|
|
17
|
+
/**
|
|
18
|
+
* Closes the dialog; pass `asChild` to turn any button into the close action.
|
|
19
|
+
*/
|
|
20
|
+
export declare const DialogClose: (props: ComponentProps<typeof DialogPrimitive.Close>) => import("react").JSX.Element;
|
|
21
|
+
interface DialogContentProps extends ComponentProps<typeof DialogPrimitive.Content>, VariantProps<typeof dialogContentVariants> {
|
|
22
|
+
showClose?: boolean;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Portals the dialog panel above a blurred scrim, with an optional corner close button.
|
|
26
|
+
*/
|
|
27
|
+
export declare const DialogContent: ({ children, className, showClose, size, ...props }: DialogContentProps) => import("react").JSX.Element;
|
|
28
|
+
/**
|
|
29
|
+
* Stacks the title and description at the top of the panel.
|
|
30
|
+
*/
|
|
31
|
+
export declare const DialogHeader: ({ className, ...props }: ComponentProps<"div">) => import("react").JSX.Element;
|
|
32
|
+
/**
|
|
33
|
+
* Scrolls the dialog's main content when it outgrows the viewport.
|
|
34
|
+
*/
|
|
35
|
+
export declare const DialogBody: ({ className, ...props }: ComponentProps<"div">) => import("react").JSX.Element;
|
|
36
|
+
/**
|
|
37
|
+
* Right-aligns the dialog's actions, stacking them on narrow screens.
|
|
38
|
+
*/
|
|
39
|
+
export declare const DialogFooter: ({ className, ...props }: ComponentProps<"div">) => import("react").JSX.Element;
|
|
40
|
+
export declare const DialogTitle: ({ className, ...props }: ComponentProps<typeof DialogPrimitive.Title>) => import("react").JSX.Element;
|
|
41
|
+
export declare const DialogDescription: ({ className, ...props }: ComponentProps<typeof DialogPrimitive.Description>) => import("react").JSX.Element;
|
|
42
|
+
export {};
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { cn } from "../../lib/cn.js";
|
|
3
|
+
import { RefineIconCloseMD } from "../../icons/refine-icons.js";
|
|
4
|
+
import { Dialog } from "radix-ui";
|
|
5
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
6
|
+
import { cva } from "class-variance-authority";
|
|
7
|
+
// src/components/dialog/dialog.tsx
|
|
8
|
+
var DIALOG_OVERLAY_CLASS_NAME = cn("fixed inset-0 z-50 bg-scrim backdrop-blur-sm", "data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:animate-in data-[state=open]:fade-in-0");
|
|
9
|
+
var DIALOG_CLOSE_CLASS_NAME = cn("absolute top-4 right-4 inline-flex size-control-sm items-center justify-center rounded-control text-muted-foreground transition-colors focus-ring", "hover:bg-hover hover:text-foreground", "active:bg-pressed", "disabled:pointer-events-none disabled:opacity-45");
|
|
10
|
+
var dialogContentVariants = cva([
|
|
11
|
+
"fixed top-1/2 left-1/2 z-50 flex max-h-[calc(100dvh-2rem)] w-[calc(100vw-2rem)] -translate-x-1/2 -translate-y-1/2 flex-col overflow-hidden",
|
|
12
|
+
"rounded-panel border bg-popover text-popover-foreground shadow-float outline-none",
|
|
13
|
+
"duration-200 ease-out-expo data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95"
|
|
14
|
+
], {
|
|
15
|
+
variants: { size: {
|
|
16
|
+
sm: "max-w-sm",
|
|
17
|
+
md: "max-w-lg",
|
|
18
|
+
lg: "max-w-2xl",
|
|
19
|
+
xl: "max-w-4xl",
|
|
20
|
+
full: "h-[calc(100dvh-2rem)] max-w-[calc(100vw-2rem)]"
|
|
21
|
+
} },
|
|
22
|
+
defaultVariants: { size: "md" }
|
|
23
|
+
});
|
|
24
|
+
/**
|
|
25
|
+
* Holds the open state of a modal dialog.
|
|
26
|
+
*/
|
|
27
|
+
var Dialog$1 = (props) => {
|
|
28
|
+
return /* @__PURE__ */ jsx(Dialog.Root, {
|
|
29
|
+
"data-slot": "dialog",
|
|
30
|
+
...props
|
|
31
|
+
});
|
|
32
|
+
};
|
|
33
|
+
/**
|
|
34
|
+
* Opens the dialog; pass `asChild` to turn any button into the trigger.
|
|
35
|
+
*/
|
|
36
|
+
var DialogTrigger = (props) => {
|
|
37
|
+
return /* @__PURE__ */ jsx(Dialog.Trigger, {
|
|
38
|
+
"data-slot": "dialog-trigger",
|
|
39
|
+
...props
|
|
40
|
+
});
|
|
41
|
+
};
|
|
42
|
+
/**
|
|
43
|
+
* Closes the dialog; pass `asChild` to turn any button into the close action.
|
|
44
|
+
*/
|
|
45
|
+
var DialogClose = (props) => {
|
|
46
|
+
return /* @__PURE__ */ jsx(Dialog.Close, {
|
|
47
|
+
"data-slot": "dialog-close",
|
|
48
|
+
...props
|
|
49
|
+
});
|
|
50
|
+
};
|
|
51
|
+
/**
|
|
52
|
+
* Portals the dialog panel above a blurred scrim, with an optional corner close button.
|
|
53
|
+
*/
|
|
54
|
+
var DialogContent = ({ children, className, showClose = true, size, ...props }) => {
|
|
55
|
+
return /* @__PURE__ */ jsxs(Dialog.Portal, { children: [/* @__PURE__ */ jsx(Dialog.Overlay, {
|
|
56
|
+
className: DIALOG_OVERLAY_CLASS_NAME,
|
|
57
|
+
"data-slot": "dialog-overlay"
|
|
58
|
+
}), /* @__PURE__ */ jsxs(Dialog.Content, {
|
|
59
|
+
className: cn(dialogContentVariants({ size }), className),
|
|
60
|
+
"data-slot": "dialog-content",
|
|
61
|
+
...props,
|
|
62
|
+
children: [children, showClose && /* @__PURE__ */ jsxs(Dialog.Close, {
|
|
63
|
+
className: DIALOG_CLOSE_CLASS_NAME,
|
|
64
|
+
title: "Close",
|
|
65
|
+
children: [/* @__PURE__ */ jsx(RefineIconCloseMD, { className: "size-4" }), /* @__PURE__ */ jsx("span", {
|
|
66
|
+
className: "sr-only",
|
|
67
|
+
children: "Close"
|
|
68
|
+
})]
|
|
69
|
+
})]
|
|
70
|
+
})] });
|
|
71
|
+
};
|
|
72
|
+
/**
|
|
73
|
+
* Stacks the title and description at the top of the panel.
|
|
74
|
+
*/
|
|
75
|
+
var DialogHeader = ({ className, ...props }) => {
|
|
76
|
+
return /* @__PURE__ */ jsx("div", {
|
|
77
|
+
className: cn("flex flex-col gap-1.5 px-6 pt-6 pr-14", className),
|
|
78
|
+
"data-slot": "dialog-header",
|
|
79
|
+
...props
|
|
80
|
+
});
|
|
81
|
+
};
|
|
82
|
+
/**
|
|
83
|
+
* Scrolls the dialog's main content when it outgrows the viewport.
|
|
84
|
+
*/
|
|
85
|
+
var DialogBody = ({ className, ...props }) => {
|
|
86
|
+
return /* @__PURE__ */ jsx("div", {
|
|
87
|
+
className: cn("min-h-0 flex-1 overflow-y-auto px-6 py-4 text-body-sm text-muted-foreground", className),
|
|
88
|
+
"data-slot": "dialog-body",
|
|
89
|
+
...props
|
|
90
|
+
});
|
|
91
|
+
};
|
|
92
|
+
/**
|
|
93
|
+
* Right-aligns the dialog's actions, stacking them on narrow screens.
|
|
94
|
+
*/
|
|
95
|
+
var DialogFooter = ({ className, ...props }) => {
|
|
96
|
+
return /* @__PURE__ */ jsx("div", {
|
|
97
|
+
className: cn("flex flex-col-reverse gap-2 border-t bg-muted/50 px-6 py-4 sm:flex-row sm:justify-end", className),
|
|
98
|
+
"data-slot": "dialog-footer",
|
|
99
|
+
...props
|
|
100
|
+
});
|
|
101
|
+
};
|
|
102
|
+
var DialogTitle = ({ className, ...props }) => {
|
|
103
|
+
return /* @__PURE__ */ jsx(Dialog.Title, {
|
|
104
|
+
className: cn("text-headline-sm text-foreground", className),
|
|
105
|
+
"data-slot": "dialog-title",
|
|
106
|
+
...props
|
|
107
|
+
});
|
|
108
|
+
};
|
|
109
|
+
var DialogDescription = ({ className, ...props }) => {
|
|
110
|
+
return /* @__PURE__ */ jsx(Dialog.Description, {
|
|
111
|
+
className: cn("text-body-sm text-muted-foreground", className),
|
|
112
|
+
"data-slot": "dialog-description",
|
|
113
|
+
...props
|
|
114
|
+
});
|
|
115
|
+
};
|
|
116
|
+
export { DIALOG_CLOSE_CLASS_NAME, DIALOG_OVERLAY_CLASS_NAME, Dialog$1 as Dialog, DialogBody, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, DialogTrigger };
|
|
117
|
+
|
|
118
|
+
//# sourceMappingURL=dialog.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dialog.js","names":["Dialog","DialogPrimitive"],"sources":["../../../src/components/dialog/dialog.tsx"],"sourcesContent":["'use client';\n\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport { Dialog as DialogPrimitive } from 'radix-ui';\nimport type { ComponentProps } from 'react';\n\nimport { cn } from '../../lib/cn';\nimport { RefineIconCloseMD } from '../../icons/refine-icons';\n\nexport const DIALOG_OVERLAY_CLASS_NAME = cn(\n // base\n 'fixed inset-0 z-50 bg-scrim backdrop-blur-sm',\n // animation\n 'data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:animate-in data-[state=open]:fade-in-0',\n);\n\nexport const DIALOG_CLOSE_CLASS_NAME = cn(\n // base\n 'absolute top-4 right-4 inline-flex size-control-sm items-center justify-center rounded-control text-muted-foreground transition-colors focus-ring',\n // hover\n 'hover:bg-hover hover:text-foreground',\n // active\n 'active:bg-pressed',\n // disabled\n 'disabled:pointer-events-none disabled:opacity-45',\n);\n\nconst dialogContentVariants = cva(\n [\n // base\n 'fixed top-1/2 left-1/2 z-50 flex max-h-[calc(100dvh-2rem)] w-[calc(100vw-2rem)] -translate-x-1/2 -translate-y-1/2 flex-col overflow-hidden',\n 'rounded-panel border bg-popover text-popover-foreground shadow-float outline-none',\n // animation\n 'duration-200 ease-out-expo data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95',\n ],\n {\n variants: {\n size: {\n sm: 'max-w-sm',\n md: 'max-w-lg',\n lg: 'max-w-2xl',\n xl: 'max-w-4xl',\n full: 'h-[calc(100dvh-2rem)] max-w-[calc(100vw-2rem)]',\n },\n },\n defaultVariants: {\n size: 'md',\n },\n },\n);\n\n/**\n * Holds the open state of a modal dialog.\n */\nexport const Dialog = (props: ComponentProps<typeof DialogPrimitive.Root>) => {\n return <DialogPrimitive.Root data-slot=\"dialog\" {...props} />;\n};\n\n/**\n * Opens the dialog; pass `asChild` to turn any button into the trigger.\n */\nexport const DialogTrigger = (props: ComponentProps<typeof DialogPrimitive.Trigger>) => {\n return <DialogPrimitive.Trigger data-slot=\"dialog-trigger\" {...props} />;\n};\n\n/**\n * Closes the dialog; pass `asChild` to turn any button into the close action.\n */\nexport const DialogClose = (props: ComponentProps<typeof DialogPrimitive.Close>) => {\n return <DialogPrimitive.Close data-slot=\"dialog-close\" {...props} />;\n};\n\ninterface DialogContentProps\n extends ComponentProps<typeof DialogPrimitive.Content>,\n VariantProps<typeof dialogContentVariants> {\n showClose?: boolean;\n}\n\n/**\n * Portals the dialog panel above a blurred scrim, with an optional corner close button.\n */\nexport const DialogContent = ({ children, className, showClose = true, size, ...props }: DialogContentProps) => {\n return (\n <DialogPrimitive.Portal>\n <DialogPrimitive.Overlay className={DIALOG_OVERLAY_CLASS_NAME} data-slot=\"dialog-overlay\" />\n <DialogPrimitive.Content\n className={cn(dialogContentVariants({ size }), className)}\n data-slot=\"dialog-content\"\n {...props}\n >\n {children}\n {showClose && (\n <DialogPrimitive.Close className={DIALOG_CLOSE_CLASS_NAME} title=\"Close\">\n <RefineIconCloseMD className=\"size-4\" />\n <span className=\"sr-only\">Close</span>\n </DialogPrimitive.Close>\n )}\n </DialogPrimitive.Content>\n </DialogPrimitive.Portal>\n );\n};\n\n/**\n * Stacks the title and description at the top of the panel.\n */\nexport const DialogHeader = ({ className, ...props }: ComponentProps<'div'>) => {\n return <div className={cn('flex flex-col gap-1.5 px-6 pt-6 pr-14', className)} data-slot=\"dialog-header\" {...props} />;\n};\n\n/**\n * Scrolls the dialog's main content when it outgrows the viewport.\n */\nexport const DialogBody = ({ className, ...props }: ComponentProps<'div'>) => {\n return (\n <div\n className={cn('min-h-0 flex-1 overflow-y-auto px-6 py-4 text-body-sm text-muted-foreground', className)}\n data-slot=\"dialog-body\"\n {...props}\n />\n );\n};\n\n/**\n * Right-aligns the dialog's actions, stacking them on narrow screens.\n */\nexport const DialogFooter = ({ className, ...props }: ComponentProps<'div'>) => {\n return (\n <div\n className={cn(\n 'flex flex-col-reverse gap-2 border-t bg-muted/50 px-6 py-4 sm:flex-row sm:justify-end',\n className,\n )}\n data-slot=\"dialog-footer\"\n {...props}\n />\n );\n};\n\nexport const DialogTitle = ({ className, ...props }: ComponentProps<typeof DialogPrimitive.Title>) => {\n return (\n <DialogPrimitive.Title\n className={cn('text-headline-sm text-foreground', className)}\n data-slot=\"dialog-title\"\n {...props}\n />\n );\n};\n\nexport const DialogDescription = ({ className, ...props }: ComponentProps<typeof DialogPrimitive.Description>) => {\n return (\n <DialogPrimitive.Description\n className={cn('text-body-sm text-muted-foreground', className)}\n data-slot=\"dialog-description\"\n {...props}\n />\n );\n};\n"],"mappings":";;;;;;;AASA,IAAa,4BAA4B,GAEvC,gDAEA,yHACF;AAEA,IAAa,0BAA0B,GAErC,qJAEA,wCAEA,qBAEA,kDACF;AAEA,IAAM,wBAAwB,IAC5B;CAEE;CACA;CAEA;AACF,GACA;CACE,UAAU,EACR,MAAM;EACJ,IAAI;EACJ,IAAI;EACJ,IAAI;EACJ,IAAI;EACJ,MAAM;CACR,EACF;CACA,iBAAiB,EACf,MAAM,KACR;AACF,CACF;;;;AAKA,IAAaA,YAAU,UAAuD;CAC5E,OAAO,oBAACC,OAAgB,MAAjB;EAAsB,aAAU;EAAS,GAAI;CAAQ,CAAA;AAC9D;;;;AAKA,IAAa,iBAAiB,UAA0D;CACtF,OAAO,oBAACA,OAAgB,SAAjB;EAAyB,aAAU;EAAiB,GAAI;CAAQ,CAAA;AACzE;;;;AAKA,IAAa,eAAe,UAAwD;CAClF,OAAO,oBAACA,OAAgB,OAAjB;EAAuB,aAAU;EAAe,GAAI;CAAQ,CAAA;AACrE;;;;AAWA,IAAa,iBAAiB,EAAE,UAAU,WAAW,YAAY,MAAM,MAAM,GAAG,YAAgC;CAC9G,OACE,qBAACA,OAAgB,QAAjB,EAAA,UAAA,CACE,oBAACA,OAAgB,SAAjB;EAAyB,WAAW;EAA2B,aAAU;CAAkB,CAAA,GAC3F,qBAACA,OAAgB,SAAjB;EACE,WAAW,GAAG,sBAAsB,EAAE,KAAK,CAAC,GAAG,SAAS;EACxD,aAAU;EACV,GAAI;EAHN,UAAA,CAKG,UACA,aACC,qBAACA,OAAgB,OAAjB;GAAuB,WAAW;GAAyB,OAAM;GAAjE,UAAA,CACE,oBAAC,mBAAD,EAAmB,WAAU,SAAU,CAAA,GACvC,oBAAC,QAAD;IAAM,WAAU;IAAU,UAAA;GAAW,CAAA,CAChB;EAEF,CAAA,CAAA;CACH,CAAA,CAAA,EAAA,CAAA;AAE5B;;;;AAKA,IAAa,gBAAgB,EAAE,WAAW,GAAG,YAAmC;CAC9E,OAAO,oBAAC,OAAD;EAAK,WAAW,GAAG,yCAAyC,SAAS;EAAG,aAAU;EAAgB,GAAI;CAAQ,CAAA;AACvH;;;;AAKA,IAAa,cAAc,EAAE,WAAW,GAAG,YAAmC;CAC5E,OACE,oBAAC,OAAD;EACE,WAAW,GAAG,+EAA+E,SAAS;EACtG,aAAU;EACV,GAAI;CACL,CAAA;AAEL;;;;AAKA,IAAa,gBAAgB,EAAE,WAAW,GAAG,YAAmC;CAC9E,OACE,oBAAC,OAAD;EACE,WAAW,GACT,yFACA,SACF;EACA,aAAU;EACV,GAAI;CACL,CAAA;AAEL;AAEA,IAAa,eAAe,EAAE,WAAW,GAAG,YAA0D;CACpG,OACE,oBAACA,OAAgB,OAAjB;EACE,WAAW,GAAG,oCAAoC,SAAS;EAC3D,aAAU;EACV,GAAI;CACL,CAAA;AAEL;AAEA,IAAa,qBAAqB,EAAE,WAAW,GAAG,YAAgE;CAChH,OACE,oBAACA,OAAgB,aAAjB;EACE,WAAW,GAAG,sCAAsC,SAAS;EAC7D,aAAU;EACV,GAAI;CACL,CAAA;AAEL"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import type { VariantProps } from 'class-variance-authority';
|
|
2
|
+
import { DropdownMenu as DropdownMenuPrimitive } from 'radix-ui';
|
|
3
|
+
import type { ComponentProps } from 'react';
|
|
4
|
+
import { menuItemVariants } from './menu-styles';
|
|
5
|
+
/**
|
|
6
|
+
* Holds the open state of a menu of actions opened from a trigger.
|
|
7
|
+
*/
|
|
8
|
+
export declare const DropdownMenu: (props: ComponentProps<typeof DropdownMenuPrimitive.Root>) => import("react").JSX.Element;
|
|
9
|
+
export declare const DropdownMenuTrigger: (props: ComponentProps<typeof DropdownMenuPrimitive.Trigger>) => import("react").JSX.Element;
|
|
10
|
+
export declare const DropdownMenuGroup: (props: ComponentProps<typeof DropdownMenuPrimitive.Group>) => import("react").JSX.Element;
|
|
11
|
+
export declare const DropdownMenuRadioGroup: (props: ComponentProps<typeof DropdownMenuPrimitive.RadioGroup>) => import("react").JSX.Element;
|
|
12
|
+
export declare const DropdownMenuSub: (props: ComponentProps<typeof DropdownMenuPrimitive.Sub>) => import("react").JSX.Element;
|
|
13
|
+
/**
|
|
14
|
+
* Portals the menu panel next to its trigger.
|
|
15
|
+
*/
|
|
16
|
+
export declare const DropdownMenuContent: ({ className, sideOffset, ...props }: ComponentProps<typeof DropdownMenuPrimitive.Content>) => import("react").JSX.Element;
|
|
17
|
+
type DropdownMenuItemProps = ComponentProps<typeof DropdownMenuPrimitive.Item> & VariantProps<typeof menuItemVariants>;
|
|
18
|
+
/**
|
|
19
|
+
* Runs an action; the `danger` variant marks destructive ones.
|
|
20
|
+
*/
|
|
21
|
+
export declare const DropdownMenuItem: ({ className, inset, variant, ...props }: DropdownMenuItemProps) => import("react").JSX.Element;
|
|
22
|
+
/**
|
|
23
|
+
* Toggles a setting and shows a check while it is on.
|
|
24
|
+
*/
|
|
25
|
+
export declare const DropdownMenuCheckboxItem: ({ children, className, ...props }: ComponentProps<typeof DropdownMenuPrimitive.CheckboxItem>) => import("react").JSX.Element;
|
|
26
|
+
/**
|
|
27
|
+
* Picks one option of its radio group and marks it with a dot.
|
|
28
|
+
*/
|
|
29
|
+
export declare const DropdownMenuRadioItem: ({ children, className, ...props }: ComponentProps<typeof DropdownMenuPrimitive.RadioItem>) => import("react").JSX.Element;
|
|
30
|
+
export declare const DropdownMenuLabel: ({ className, inset, ...props }: ComponentProps<typeof DropdownMenuPrimitive.Label> & {
|
|
31
|
+
inset?: boolean;
|
|
32
|
+
}) => import("react").JSX.Element;
|
|
33
|
+
export declare const DropdownMenuSeparator: ({ className, ...props }: ComponentProps<typeof DropdownMenuPrimitive.Separator>) => import("react").JSX.Element;
|
|
34
|
+
/**
|
|
35
|
+
* Right-aligns a keyboard shortcut hint inside an item.
|
|
36
|
+
*/
|
|
37
|
+
export declare const DropdownMenuShortcut: ({ className, ...props }: ComponentProps<"span">) => import("react").JSX.Element;
|
|
38
|
+
/**
|
|
39
|
+
* Opens a nested menu and points at it with a chevron.
|
|
40
|
+
*/
|
|
41
|
+
export declare const DropdownMenuSubTrigger: ({ children, className, inset, ...props }: ComponentProps<typeof DropdownMenuPrimitive.SubTrigger> & {
|
|
42
|
+
inset?: boolean;
|
|
43
|
+
}) => import("react").JSX.Element;
|
|
44
|
+
export declare const DropdownMenuSubContent: ({ className, ...props }: ComponentProps<typeof DropdownMenuPrimitive.SubContent>) => import("react").JSX.Element;
|
|
45
|
+
export {};
|