@mirror-physics/fractal-ui 0.2.0-next.1 → 0.2.0-next.10
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/dist/index.cjs +155 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.css +278 -7
- package/dist/index.css.map +1 -1
- package/dist/index.d.cts +33 -2
- package/dist/index.d.ts +33 -2
- package/dist/index.js +152 -3
- package/dist/index.js.map +1 -1
- package/dist/tokens.css +4 -4
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -180,8 +180,10 @@ interface SortableTableProps<T> {
|
|
|
180
180
|
sortDirection?: SortDirection;
|
|
181
181
|
onSortChange?: (key: string | null, direction: SortDirection) => void;
|
|
182
182
|
highlightRow?: (row: T, index: number) => boolean;
|
|
183
|
+
/** Invoked when a row is selected. Enables pointer and keyboard row activation. */
|
|
184
|
+
onRowClick?: (row: T, index: number) => void;
|
|
183
185
|
}
|
|
184
|
-
declare function SortableTable<T>({ columns, data, emptyMessage, header, size, className, defaultSortKey, defaultSortDirection, sortKey: controlledKey, sortDirection: controlledDirection, onSortChange, highlightRow, }: SortableTableProps<T>): React.JSX.Element;
|
|
186
|
+
declare function SortableTable<T>({ columns, data, emptyMessage, header, size, className, defaultSortKey, defaultSortDirection, sortKey: controlledKey, sortDirection: controlledDirection, onSortChange, highlightRow, onRowClick, }: SortableTableProps<T>): React.JSX.Element;
|
|
185
187
|
|
|
186
188
|
interface TabItem {
|
|
187
189
|
id: string;
|
|
@@ -231,6 +233,35 @@ interface SidebarNavItemProps extends React.ButtonHTMLAttributes<HTMLButtonEleme
|
|
|
231
233
|
declare const SidebarNavItem: React.ForwardRefExoticComponent<SidebarNavItemProps & React.RefAttributes<HTMLButtonElement>>;
|
|
232
234
|
declare const SidebarFooter: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLDivElement> & React.RefAttributes<HTMLDivElement>>;
|
|
233
235
|
|
|
236
|
+
interface SidePanelProps {
|
|
237
|
+
open: boolean;
|
|
238
|
+
onClose: () => void;
|
|
239
|
+
title: React.ReactNode;
|
|
240
|
+
description?: React.ReactNode;
|
|
241
|
+
children: React.ReactNode;
|
|
242
|
+
footer?: React.ReactNode;
|
|
243
|
+
/** Panel width: sm (420px), md (540px), or lg (680px). */
|
|
244
|
+
size?: 'sm' | 'md' | 'lg';
|
|
245
|
+
className?: string;
|
|
246
|
+
}
|
|
247
|
+
declare function SidePanel({ open, onClose, title, description, children, footer, size, className }: SidePanelProps): React.ReactPortal | null;
|
|
248
|
+
|
|
249
|
+
interface TextareaProps extends React.TextareaHTMLAttributes<HTMLTextAreaElement> {
|
|
250
|
+
}
|
|
251
|
+
declare const Textarea: React.ForwardRefExoticComponent<TextareaProps & React.RefAttributes<HTMLTextAreaElement>>;
|
|
252
|
+
|
|
253
|
+
interface FileDropzoneProps {
|
|
254
|
+
files: File[];
|
|
255
|
+
onFilesChange: (files: File[]) => void;
|
|
256
|
+
accept?: string;
|
|
257
|
+
multiple?: boolean;
|
|
258
|
+
disabled?: boolean;
|
|
259
|
+
title?: React.ReactNode;
|
|
260
|
+
description?: React.ReactNode;
|
|
261
|
+
className?: string;
|
|
262
|
+
}
|
|
263
|
+
declare function FileDropzone({ files, onFilesChange, accept, multiple, disabled, title, description, className, }: FileDropzoneProps): React.JSX.Element;
|
|
264
|
+
|
|
234
265
|
/**
|
|
235
266
|
* Register an Escape-key dismiss handler with the global priority stack.
|
|
236
267
|
*
|
|
@@ -242,4 +273,4 @@ declare function useEscapeDismiss(priority: number, handler: () => void, enabled
|
|
|
242
273
|
|
|
243
274
|
declare function cn(...inputs: ClassValue[]): string;
|
|
244
275
|
|
|
245
|
-
export { Alert, AlertDescription, AlertTitle, Button, type ButtonColor, type ButtonProps, type ButtonSize, type ButtonType, Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, Chip, type ChipProps, type ChipTone, DataTable, type DataTableColumn, type DataTableProps, Disclosure, type DisclosureProps, Dropdown, type DropdownItem, type DropdownProps, FeatureCard, type FeatureCardProps, FolderCard, type FolderCardProps, Input, type InputProps, Label, type LabelProps, Link, type LinkProps, type LinkSize, type LinkTheme, Modal, type ModalProps, PromptCard, type PromptCardProps, type PromptCardTone, PromptGrid, type PromptGridProps, Sidebar, SidebarBrand, SidebarFooter, SidebarHeader, SidebarNav, SidebarNavItem, type SidebarNavItemProps, type SidebarProps, SidebarSection, type SortDirection, SortableTable, type SortableTableColumn, type SortableTableProps, type TabItem, Tabs, type TabsProps, Toggle, type ToggleProps, cn, useEscapeDismiss };
|
|
276
|
+
export { Alert, AlertDescription, AlertTitle, Button, type ButtonColor, type ButtonProps, type ButtonSize, type ButtonType, Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, Chip, type ChipProps, type ChipTone, DataTable, type DataTableColumn, type DataTableProps, Disclosure, type DisclosureProps, Dropdown, type DropdownItem, type DropdownProps, FeatureCard, type FeatureCardProps, FileDropzone, type FileDropzoneProps, FolderCard, type FolderCardProps, Input, type InputProps, Label, type LabelProps, Link, type LinkProps, type LinkSize, type LinkTheme, Modal, type ModalProps, PromptCard, type PromptCardProps, type PromptCardTone, PromptGrid, type PromptGridProps, SidePanel, type SidePanelProps, Sidebar, SidebarBrand, SidebarFooter, SidebarHeader, SidebarNav, SidebarNavItem, type SidebarNavItemProps, type SidebarProps, SidebarSection, type SortDirection, SortableTable, type SortableTableColumn, type SortableTableProps, type TabItem, Tabs, type TabsProps, Textarea, type TextareaProps, Toggle, type ToggleProps, cn, useEscapeDismiss };
|
package/dist/index.js
CHANGED
|
@@ -50,7 +50,7 @@ var colorPalette = {
|
|
|
50
50
|
var sizeConfig = {
|
|
51
51
|
xs: { height: "28px", padding: "4px 8px", iconOnly: "28px", fontSize: "0.75rem" },
|
|
52
52
|
sm: { height: "32px", padding: "6px 12px", iconOnly: "32px", fontSize: "0.75rem" },
|
|
53
|
-
md: { height: "
|
|
53
|
+
md: { height: "40px", padding: "8px 16px", iconOnly: "40px", fontSize: "0.875rem" },
|
|
54
54
|
lg: { height: "44px", padding: "10px 20px", iconOnly: "44px", fontSize: "1rem" },
|
|
55
55
|
xl: { height: "56px", padding: "14px 28px", iconOnly: "56px", fontSize: "1rem" }
|
|
56
56
|
};
|
|
@@ -680,7 +680,8 @@ function SortableTable({
|
|
|
680
680
|
sortKey: controlledKey,
|
|
681
681
|
sortDirection: controlledDirection,
|
|
682
682
|
onSortChange,
|
|
683
|
-
highlightRow
|
|
683
|
+
highlightRow,
|
|
684
|
+
onRowClick
|
|
684
685
|
}) {
|
|
685
686
|
const [internalKey, setInternalKey] = useState3(defaultSortKey ?? null);
|
|
686
687
|
const [internalDirection, setInternalDirection] = useState3(defaultSortDirection);
|
|
@@ -781,8 +782,18 @@ function SortableTable({
|
|
|
781
782
|
{
|
|
782
783
|
className: cn(
|
|
783
784
|
"fractal-sortable-table-row",
|
|
784
|
-
highlighted && "fractal-sortable-table-row--highlighted"
|
|
785
|
+
highlighted && "fractal-sortable-table-row--highlighted",
|
|
786
|
+
onRowClick && "fractal-sortable-table-row--interactive"
|
|
785
787
|
),
|
|
788
|
+
onClick: onRowClick ? () => onRowClick(row, rowIndex) : void 0,
|
|
789
|
+
onKeyDown: onRowClick ? (event) => {
|
|
790
|
+
if (event.key === "Enter" || event.key === " ") {
|
|
791
|
+
event.preventDefault();
|
|
792
|
+
onRowClick(row, rowIndex);
|
|
793
|
+
}
|
|
794
|
+
} : void 0,
|
|
795
|
+
role: onRowClick ? "button" : void 0,
|
|
796
|
+
tabIndex: onRowClick ? 0 : void 0,
|
|
786
797
|
children: columns.map((col) => /* @__PURE__ */ jsx12(
|
|
787
798
|
"td",
|
|
788
799
|
{
|
|
@@ -1027,6 +1038,141 @@ var SidebarFooter = React10.forwardRef(
|
|
|
1027
1038
|
({ className, ...props }, ref) => /* @__PURE__ */ jsx15("div", { ref, className: cn("fractal-sidebar__footer", className), ...props })
|
|
1028
1039
|
);
|
|
1029
1040
|
SidebarFooter.displayName = "SidebarFooter";
|
|
1041
|
+
|
|
1042
|
+
// src/components/SidePanel/SidePanel.tsx
|
|
1043
|
+
import { createPortal as createPortal2 } from "react-dom";
|
|
1044
|
+
import { Close } from "@mirror-physics/fractal-icons";
|
|
1045
|
+
import { jsx as jsx16, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
1046
|
+
function SidePanel({ open, onClose, title, description, children, footer, size = "md", className }) {
|
|
1047
|
+
useEscapeDismiss(80, onClose, open);
|
|
1048
|
+
if (!open) return null;
|
|
1049
|
+
return createPortal2(
|
|
1050
|
+
/* @__PURE__ */ jsx16("div", { className: "fractal-side-panel-overlay", onMouseDown: onClose, children: /* @__PURE__ */ jsxs13(
|
|
1051
|
+
"aside",
|
|
1052
|
+
{
|
|
1053
|
+
className: cn("fractal-side-panel", `fractal-side-panel--${size}`, className),
|
|
1054
|
+
"aria-modal": "true",
|
|
1055
|
+
"aria-label": typeof title === "string" ? title : "Side panel",
|
|
1056
|
+
role: "dialog",
|
|
1057
|
+
onMouseDown: (event) => event.stopPropagation(),
|
|
1058
|
+
children: [
|
|
1059
|
+
/* @__PURE__ */ jsxs13("header", { className: "fractal-side-panel__header", children: [
|
|
1060
|
+
/* @__PURE__ */ jsxs13("div", { className: "fractal-side-panel__heading", children: [
|
|
1061
|
+
/* @__PURE__ */ jsx16("h2", { className: "fractal-side-panel__title", children: title }),
|
|
1062
|
+
description && /* @__PURE__ */ jsx16("p", { className: "fractal-side-panel__description", children: description })
|
|
1063
|
+
] }),
|
|
1064
|
+
/* @__PURE__ */ jsx16("button", { type: "button", className: "fractal-side-panel__close", "aria-label": "Close panel", onClick: onClose, children: /* @__PURE__ */ jsx16(Close, { size: 18 }) })
|
|
1065
|
+
] }),
|
|
1066
|
+
/* @__PURE__ */ jsx16("div", { className: "fractal-side-panel__body", children }),
|
|
1067
|
+
footer && /* @__PURE__ */ jsx16("footer", { className: "fractal-side-panel__footer", children: footer })
|
|
1068
|
+
]
|
|
1069
|
+
}
|
|
1070
|
+
) }),
|
|
1071
|
+
document.body
|
|
1072
|
+
);
|
|
1073
|
+
}
|
|
1074
|
+
|
|
1075
|
+
// src/components/Textarea/Textarea.tsx
|
|
1076
|
+
import * as React11 from "react";
|
|
1077
|
+
import { jsx as jsx17 } from "react/jsx-runtime";
|
|
1078
|
+
var Textarea = React11.forwardRef(
|
|
1079
|
+
({ className, ...props }, ref) => /* @__PURE__ */ jsx17("textarea", { ref, className: cn("fractal-textarea", className), ...props })
|
|
1080
|
+
);
|
|
1081
|
+
Textarea.displayName = "Textarea";
|
|
1082
|
+
|
|
1083
|
+
// src/components/FileDropzone/FileDropzone.tsx
|
|
1084
|
+
import * as React12 from "react";
|
|
1085
|
+
import { Close as Close2, FileArrowUp } from "@mirror-physics/fractal-icons";
|
|
1086
|
+
import { jsx as jsx18, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
1087
|
+
function FileDropzone({
|
|
1088
|
+
files,
|
|
1089
|
+
onFilesChange,
|
|
1090
|
+
accept,
|
|
1091
|
+
multiple = true,
|
|
1092
|
+
disabled = false,
|
|
1093
|
+
title = "Drop files here or click to browse",
|
|
1094
|
+
description = "Files stay attached to this record.",
|
|
1095
|
+
className
|
|
1096
|
+
}) {
|
|
1097
|
+
const inputId = React12.useId();
|
|
1098
|
+
const inputRef = React12.useRef(null);
|
|
1099
|
+
const [isDragging, setIsDragging] = React12.useState(false);
|
|
1100
|
+
const addFiles = (nextFiles) => {
|
|
1101
|
+
if (disabled) return;
|
|
1102
|
+
const additions = Array.from(nextFiles);
|
|
1103
|
+
if (additions.length === 0) return;
|
|
1104
|
+
onFilesChange(multiple ? [...files, ...additions] : additions.slice(0, 1));
|
|
1105
|
+
};
|
|
1106
|
+
return /* @__PURE__ */ jsxs14("div", { className: cn("fractal-file-dropzone", className), children: [
|
|
1107
|
+
/* @__PURE__ */ jsx18(
|
|
1108
|
+
"input",
|
|
1109
|
+
{
|
|
1110
|
+
ref: inputRef,
|
|
1111
|
+
id: inputId,
|
|
1112
|
+
className: "fractal-file-dropzone__input",
|
|
1113
|
+
type: "file",
|
|
1114
|
+
accept,
|
|
1115
|
+
multiple,
|
|
1116
|
+
disabled,
|
|
1117
|
+
onChange: (event) => {
|
|
1118
|
+
if (event.target.files) addFiles(event.target.files);
|
|
1119
|
+
event.target.value = "";
|
|
1120
|
+
}
|
|
1121
|
+
}
|
|
1122
|
+
),
|
|
1123
|
+
/* @__PURE__ */ jsxs14(
|
|
1124
|
+
"button",
|
|
1125
|
+
{
|
|
1126
|
+
className: "fractal-file-dropzone__target",
|
|
1127
|
+
"data-dragging": isDragging || void 0,
|
|
1128
|
+
type: "button",
|
|
1129
|
+
disabled,
|
|
1130
|
+
onClick: () => inputRef.current?.click(),
|
|
1131
|
+
onDragEnter: (event) => {
|
|
1132
|
+
event.preventDefault();
|
|
1133
|
+
if (!disabled) setIsDragging(true);
|
|
1134
|
+
},
|
|
1135
|
+
onDragOver: (event) => event.preventDefault(),
|
|
1136
|
+
onDragLeave: (event) => {
|
|
1137
|
+
event.preventDefault();
|
|
1138
|
+
setIsDragging(false);
|
|
1139
|
+
},
|
|
1140
|
+
onDrop: (event) => {
|
|
1141
|
+
event.preventDefault();
|
|
1142
|
+
setIsDragging(false);
|
|
1143
|
+
addFiles(event.dataTransfer.files);
|
|
1144
|
+
},
|
|
1145
|
+
children: [
|
|
1146
|
+
/* @__PURE__ */ jsx18(FileArrowUp, { "aria-hidden": "true", size: 20 }),
|
|
1147
|
+
/* @__PURE__ */ jsxs14("span", { className: "fractal-file-dropzone__copy", children: [
|
|
1148
|
+
/* @__PURE__ */ jsx18("span", { className: "fractal-file-dropzone__title", children: title }),
|
|
1149
|
+
description && /* @__PURE__ */ jsx18("span", { className: "fractal-file-dropzone__description", children: description })
|
|
1150
|
+
] })
|
|
1151
|
+
]
|
|
1152
|
+
}
|
|
1153
|
+
),
|
|
1154
|
+
files.length > 0 && /* @__PURE__ */ jsx18("ul", { className: "fractal-file-dropzone__files", "aria-label": "Attached files", children: files.map((file, index) => /* @__PURE__ */ jsxs14("li", { className: "fractal-file-dropzone__file", children: [
|
|
1155
|
+
/* @__PURE__ */ jsx18("span", { className: "fractal-file-dropzone__file-name", children: file.name }),
|
|
1156
|
+
/* @__PURE__ */ jsx18("span", { className: "fractal-file-dropzone__file-meta", children: formatFileSize(file.size) }),
|
|
1157
|
+
/* @__PURE__ */ jsx18(
|
|
1158
|
+
"button",
|
|
1159
|
+
{
|
|
1160
|
+
className: "fractal-file-dropzone__remove",
|
|
1161
|
+
type: "button",
|
|
1162
|
+
"aria-label": `Remove ${file.name}`,
|
|
1163
|
+
disabled,
|
|
1164
|
+
onClick: () => onFilesChange(files.filter((_, fileIndex) => fileIndex !== index)),
|
|
1165
|
+
children: /* @__PURE__ */ jsx18(Close2, { "aria-hidden": "true", size: 14 })
|
|
1166
|
+
}
|
|
1167
|
+
)
|
|
1168
|
+
] }, `${file.name}-${file.size}-${index}`)) })
|
|
1169
|
+
] });
|
|
1170
|
+
}
|
|
1171
|
+
function formatFileSize(bytes) {
|
|
1172
|
+
if (bytes < 1024) return `${bytes} B`;
|
|
1173
|
+
if (bytes < 1024 * 1024) return `${Math.round(bytes / 1024)} KB`;
|
|
1174
|
+
return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
|
|
1175
|
+
}
|
|
1030
1176
|
export {
|
|
1031
1177
|
Alert,
|
|
1032
1178
|
AlertDescription,
|
|
@@ -1043,6 +1189,7 @@ export {
|
|
|
1043
1189
|
Disclosure,
|
|
1044
1190
|
Dropdown,
|
|
1045
1191
|
FeatureCard,
|
|
1192
|
+
FileDropzone,
|
|
1046
1193
|
FolderCard,
|
|
1047
1194
|
Input,
|
|
1048
1195
|
Label,
|
|
@@ -1050,6 +1197,7 @@ export {
|
|
|
1050
1197
|
Modal,
|
|
1051
1198
|
PromptCard,
|
|
1052
1199
|
PromptGrid,
|
|
1200
|
+
SidePanel,
|
|
1053
1201
|
Sidebar,
|
|
1054
1202
|
SidebarBrand,
|
|
1055
1203
|
SidebarFooter,
|
|
@@ -1059,6 +1207,7 @@ export {
|
|
|
1059
1207
|
SidebarSection,
|
|
1060
1208
|
SortableTable,
|
|
1061
1209
|
Tabs,
|
|
1210
|
+
Textarea,
|
|
1062
1211
|
Toggle,
|
|
1063
1212
|
cn,
|
|
1064
1213
|
useEscapeDismiss
|