@memelabui/ui 0.7.0 → 0.8.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/README.md +429 -429
- package/dist/index.cjs +113 -56
- package/dist/index.d.cts +29 -3
- package/dist/index.d.ts +29 -3
- package/dist/index.js +112 -58
- package/dist/styles/index.css +2496 -2490
- package/package.json +118 -120
package/dist/index.cjs
CHANGED
|
@@ -139,10 +139,12 @@ function matchModifiers(e, mods) {
|
|
|
139
139
|
}
|
|
140
140
|
function useHotkeys(bindings, options = {}) {
|
|
141
141
|
const { enabled = true } = options;
|
|
142
|
+
const bindingsRef = React.useRef(bindings);
|
|
143
|
+
bindingsRef.current = bindings;
|
|
142
144
|
React.useEffect(() => {
|
|
143
145
|
if (!enabled) return;
|
|
144
146
|
const onKeyDown = (e) => {
|
|
145
|
-
for (const binding of
|
|
147
|
+
for (const binding of bindingsRef.current) {
|
|
146
148
|
if (e.key === binding.key && matchModifiers(e, binding.modifiers)) {
|
|
147
149
|
binding.handler(e);
|
|
148
150
|
}
|
|
@@ -150,7 +152,7 @@ function useHotkeys(bindings, options = {}) {
|
|
|
150
152
|
};
|
|
151
153
|
document.addEventListener("keydown", onKeyDown);
|
|
152
154
|
return () => document.removeEventListener("keydown", onKeyDown);
|
|
153
|
-
}, [enabled
|
|
155
|
+
}, [enabled]);
|
|
154
156
|
}
|
|
155
157
|
function useIntersectionObserver(options = {}) {
|
|
156
158
|
const { root = null, rootMargin = "0px", threshold = 0, enabled = true } = options;
|
|
@@ -206,6 +208,30 @@ function useSharedNow(options = {}) {
|
|
|
206
208
|
}, [interval, untilMs, enabled]);
|
|
207
209
|
return now;
|
|
208
210
|
}
|
|
211
|
+
var lockCount = 0;
|
|
212
|
+
var savedOverflow = "";
|
|
213
|
+
function lockScroll() {
|
|
214
|
+
if (typeof document === "undefined") return;
|
|
215
|
+
if (lockCount === 0) {
|
|
216
|
+
savedOverflow = document.body.style.overflow;
|
|
217
|
+
document.body.style.overflow = "hidden";
|
|
218
|
+
}
|
|
219
|
+
lockCount++;
|
|
220
|
+
}
|
|
221
|
+
function unlockScroll() {
|
|
222
|
+
if (typeof document === "undefined") return;
|
|
223
|
+
lockCount = Math.max(0, lockCount - 1);
|
|
224
|
+
if (lockCount === 0) {
|
|
225
|
+
document.body.style.overflow = savedOverflow;
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
function useScrollLock(active) {
|
|
229
|
+
React.useEffect(() => {
|
|
230
|
+
if (!active) return;
|
|
231
|
+
lockScroll();
|
|
232
|
+
return () => unlockScroll();
|
|
233
|
+
}, [active]);
|
|
234
|
+
}
|
|
209
235
|
|
|
210
236
|
// src/tokens/colors.ts
|
|
211
237
|
var colors = {
|
|
@@ -1257,23 +1283,6 @@ var Card = React.forwardRef(function Card2({ hoverable, variant = "surface", pad
|
|
|
1257
1283
|
}
|
|
1258
1284
|
);
|
|
1259
1285
|
});
|
|
1260
|
-
var scrollLockCount = 0;
|
|
1261
|
-
var savedOverflow = "";
|
|
1262
|
-
function lockScroll() {
|
|
1263
|
-
if (typeof document === "undefined") return;
|
|
1264
|
-
if (scrollLockCount === 0) {
|
|
1265
|
-
savedOverflow = document.body.style.overflow;
|
|
1266
|
-
document.body.style.overflow = "hidden";
|
|
1267
|
-
}
|
|
1268
|
-
scrollLockCount++;
|
|
1269
|
-
}
|
|
1270
|
-
function unlockScroll() {
|
|
1271
|
-
if (typeof document === "undefined") return;
|
|
1272
|
-
scrollLockCount = Math.max(0, scrollLockCount - 1);
|
|
1273
|
-
if (scrollLockCount === 0) {
|
|
1274
|
-
document.body.style.overflow = savedOverflow;
|
|
1275
|
-
}
|
|
1276
|
-
}
|
|
1277
1286
|
function Modal({
|
|
1278
1287
|
isOpen,
|
|
1279
1288
|
onClose,
|
|
@@ -1305,11 +1314,7 @@ function Modal({
|
|
|
1305
1314
|
if (lastActive?.isConnected) focusSafely(lastActive);
|
|
1306
1315
|
};
|
|
1307
1316
|
}, [isOpen]);
|
|
1308
|
-
|
|
1309
|
-
if (!isOpen) return;
|
|
1310
|
-
lockScroll();
|
|
1311
|
-
return () => unlockScroll();
|
|
1312
|
-
}, [isOpen]);
|
|
1317
|
+
useScrollLock(isOpen);
|
|
1313
1318
|
if (!isOpen) return null;
|
|
1314
1319
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
1315
1320
|
"div",
|
|
@@ -1458,17 +1463,32 @@ function Tooltip({ content, delayMs = 500, placement = "top", className, childre
|
|
|
1458
1463
|
const el = anchorRef.current;
|
|
1459
1464
|
if (!el) return;
|
|
1460
1465
|
const r = el.getBoundingClientRect();
|
|
1466
|
+
const vw = window.innerWidth;
|
|
1461
1467
|
const centerX = r.left + r.width / 2;
|
|
1462
|
-
const
|
|
1468
|
+
const centerY = r.top + r.height / 2;
|
|
1463
1469
|
const topY = r.top - 10;
|
|
1464
1470
|
const bottomY = r.bottom + 10;
|
|
1465
|
-
const
|
|
1466
|
-
const
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
placement:
|
|
1471
|
-
|
|
1471
|
+
const leftX = r.left - 10;
|
|
1472
|
+
const rightX = r.right + 10;
|
|
1473
|
+
let effPlacement = placement;
|
|
1474
|
+
if (placement === "top" || placement === "bottom") {
|
|
1475
|
+
const canTop = topY > 8;
|
|
1476
|
+
effPlacement = placement === "top" ? canTop ? "top" : "bottom" : "bottom";
|
|
1477
|
+
setPos({
|
|
1478
|
+
left: Math.round(centerX),
|
|
1479
|
+
top: Math.round(effPlacement === "top" ? topY : bottomY),
|
|
1480
|
+
placement: effPlacement
|
|
1481
|
+
});
|
|
1482
|
+
} else {
|
|
1483
|
+
const canLeft = leftX > 8;
|
|
1484
|
+
const canRight = rightX < vw - 8;
|
|
1485
|
+
effPlacement = placement === "left" ? canLeft ? "left" : "right" : canRight ? "right" : "left";
|
|
1486
|
+
setPos({
|
|
1487
|
+
left: Math.round(effPlacement === "left" ? leftX : rightX),
|
|
1488
|
+
top: Math.round(centerY),
|
|
1489
|
+
placement: effPlacement
|
|
1490
|
+
});
|
|
1491
|
+
}
|
|
1472
1492
|
}, [placement]);
|
|
1473
1493
|
const scheduleOpen = React.useCallback(() => {
|
|
1474
1494
|
clearTimer();
|
|
@@ -1542,7 +1562,7 @@ function Tooltip({ content, delayMs = 500, placement = "top", className, childre
|
|
|
1542
1562
|
style: pos ? {
|
|
1543
1563
|
left: pos.left,
|
|
1544
1564
|
top: pos.top,
|
|
1545
|
-
transform: pos.placement === "top" ? "translate(-50%, -100%)" : "translate(-50%, 0%)"
|
|
1565
|
+
transform: pos.placement === "top" ? "translate(-50%, -100%)" : pos.placement === "bottom" ? "translate(-50%, 0%)" : pos.placement === "left" ? "translate(-100%, -50%)" : "translate(0%, -50%)"
|
|
1546
1566
|
} : { left: 0, top: 0, transform: "translate(-9999px, -9999px)" },
|
|
1547
1567
|
children: content
|
|
1548
1568
|
}
|
|
@@ -2085,7 +2105,7 @@ function StatCard({ value, label, icon, trend, className }) {
|
|
|
2085
2105
|
"div",
|
|
2086
2106
|
{
|
|
2087
2107
|
className: cn(
|
|
2088
|
-
"
|
|
2108
|
+
"glass rounded-xl p-4 flex items-start gap-3",
|
|
2089
2109
|
className
|
|
2090
2110
|
),
|
|
2091
2111
|
children: [
|
|
@@ -3818,23 +3838,6 @@ function Popover({
|
|
|
3818
3838
|
) : null
|
|
3819
3839
|
] });
|
|
3820
3840
|
}
|
|
3821
|
-
var scrollLockCount2 = 0;
|
|
3822
|
-
var savedOverflow2 = "";
|
|
3823
|
-
function lockScroll2() {
|
|
3824
|
-
if (typeof document === "undefined") return;
|
|
3825
|
-
if (scrollLockCount2 === 0) {
|
|
3826
|
-
savedOverflow2 = document.body.style.overflow;
|
|
3827
|
-
document.body.style.overflow = "hidden";
|
|
3828
|
-
}
|
|
3829
|
-
scrollLockCount2++;
|
|
3830
|
-
}
|
|
3831
|
-
function unlockScroll2() {
|
|
3832
|
-
if (typeof document === "undefined") return;
|
|
3833
|
-
scrollLockCount2 = Math.max(0, scrollLockCount2 - 1);
|
|
3834
|
-
if (scrollLockCount2 === 0) {
|
|
3835
|
-
document.body.style.overflow = savedOverflow2;
|
|
3836
|
-
}
|
|
3837
|
-
}
|
|
3838
3841
|
var sizeClass8 = {
|
|
3839
3842
|
left: { sm: "w-64", md: "w-80", lg: "w-96", full: "w-screen" },
|
|
3840
3843
|
right: { sm: "w-64", md: "w-80", lg: "w-96", full: "w-screen" },
|
|
@@ -3884,11 +3887,7 @@ function Drawer({
|
|
|
3884
3887
|
if (lastActive?.isConnected) focusSafely(lastActive);
|
|
3885
3888
|
};
|
|
3886
3889
|
}, [isOpen]);
|
|
3887
|
-
|
|
3888
|
-
if (!isOpen) return;
|
|
3889
|
-
lockScroll2();
|
|
3890
|
-
return () => unlockScroll2();
|
|
3891
|
-
}, [isOpen]);
|
|
3890
|
+
useScrollLock(isOpen);
|
|
3892
3891
|
if (!isOpen) return null;
|
|
3893
3892
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "fixed inset-0 z-50", role: "presentation", children: [
|
|
3894
3893
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -4271,6 +4270,61 @@ function VisuallyHidden({ children, as: Tag = "span", style, ...props }) {
|
|
|
4271
4270
|
}
|
|
4272
4271
|
);
|
|
4273
4272
|
}
|
|
4273
|
+
var ErrorBoundary = class extends React.Component {
|
|
4274
|
+
constructor() {
|
|
4275
|
+
super(...arguments);
|
|
4276
|
+
this.state = { error: null };
|
|
4277
|
+
this.reset = () => {
|
|
4278
|
+
this.setState({ error: null });
|
|
4279
|
+
};
|
|
4280
|
+
}
|
|
4281
|
+
static getDerivedStateFromError(error) {
|
|
4282
|
+
return { error };
|
|
4283
|
+
}
|
|
4284
|
+
componentDidCatch(error, errorInfo) {
|
|
4285
|
+
this.props.onError?.(error, errorInfo);
|
|
4286
|
+
}
|
|
4287
|
+
render() {
|
|
4288
|
+
const { error } = this.state;
|
|
4289
|
+
if (!error) return this.props.children;
|
|
4290
|
+
const { fallback } = this.props;
|
|
4291
|
+
if (typeof fallback === "function") {
|
|
4292
|
+
return fallback(error, this.reset);
|
|
4293
|
+
}
|
|
4294
|
+
if (fallback !== void 0) {
|
|
4295
|
+
return fallback;
|
|
4296
|
+
}
|
|
4297
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { role: "alert", className: cn("glass rounded-xl p-6 text-center"), children: [
|
|
4298
|
+
/* @__PURE__ */ jsxRuntime.jsx("h2", { className: "text-lg font-semibold text-white mb-2", children: "Something went wrong" }),
|
|
4299
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-white/60 mb-4", children: error.message }),
|
|
4300
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4301
|
+
"button",
|
|
4302
|
+
{
|
|
4303
|
+
type: "button",
|
|
4304
|
+
onClick: this.reset,
|
|
4305
|
+
className: "inline-flex items-center justify-center gap-2 rounded-xl font-semibold leading-none px-3.5 py-2.5 text-sm bg-gradient-to-r from-violet-600 to-purple-600 text-white shadow-glow hover:shadow-glow-lg hover:scale-[1.02] transition-[transform,background-color,box-shadow,opacity] active:translate-y-[0.5px]",
|
|
4306
|
+
children: "Try again"
|
|
4307
|
+
}
|
|
4308
|
+
)
|
|
4309
|
+
] });
|
|
4310
|
+
}
|
|
4311
|
+
};
|
|
4312
|
+
function LoadingScreen({ message, size = "lg", className }) {
|
|
4313
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
4314
|
+
"div",
|
|
4315
|
+
{
|
|
4316
|
+
role: "status",
|
|
4317
|
+
className: cn(
|
|
4318
|
+
"flex flex-col items-center justify-center min-h-screen bg-ml-bg gap-4",
|
|
4319
|
+
className
|
|
4320
|
+
),
|
|
4321
|
+
children: [
|
|
4322
|
+
/* @__PURE__ */ jsxRuntime.jsx(Spinner, { size }),
|
|
4323
|
+
message && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-white/60", children: message })
|
|
4324
|
+
]
|
|
4325
|
+
}
|
|
4326
|
+
);
|
|
4327
|
+
}
|
|
4274
4328
|
|
|
4275
4329
|
exports.ActiveFilterPills = ActiveFilterPills;
|
|
4276
4330
|
exports.Alert = Alert;
|
|
@@ -4297,10 +4351,12 @@ exports.DropdownMenu = DropdownMenu;
|
|
|
4297
4351
|
exports.DropdownSeparator = DropdownSeparator;
|
|
4298
4352
|
exports.DropdownTrigger = DropdownTrigger;
|
|
4299
4353
|
exports.EmptyState = EmptyState;
|
|
4354
|
+
exports.ErrorBoundary = ErrorBoundary;
|
|
4300
4355
|
exports.FormField = FormField;
|
|
4301
4356
|
exports.Heading = Heading;
|
|
4302
4357
|
exports.IconButton = IconButton;
|
|
4303
4358
|
exports.Input = Input;
|
|
4359
|
+
exports.LoadingScreen = LoadingScreen;
|
|
4304
4360
|
exports.Modal = Modal;
|
|
4305
4361
|
exports.MutationOverlay = MutationOverlay;
|
|
4306
4362
|
exports.Navbar = Navbar;
|
|
@@ -4353,5 +4409,6 @@ exports.useDisclosure = useDisclosure;
|
|
|
4353
4409
|
exports.useHotkeys = useHotkeys;
|
|
4354
4410
|
exports.useIntersectionObserver = useIntersectionObserver;
|
|
4355
4411
|
exports.useMediaQuery = useMediaQuery;
|
|
4412
|
+
exports.useScrollLock = useScrollLock;
|
|
4356
4413
|
exports.useSharedNow = useSharedNow;
|
|
4357
4414
|
exports.useToast = useToast;
|
package/dist/index.d.cts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export { MemelabColors, colors } from './tokens/index.cjs';
|
|
2
2
|
import * as react from 'react';
|
|
3
|
-
import { ButtonHTMLAttributes, ReactNode, InputHTMLAttributes, SelectHTMLAttributes, TextareaHTMLAttributes, HTMLAttributes, ReactElement, ComponentType } from 'react';
|
|
3
|
+
import { ButtonHTMLAttributes, ReactNode, InputHTMLAttributes, SelectHTMLAttributes, TextareaHTMLAttributes, HTMLAttributes, ReactElement, ComponentType, Component, ErrorInfo } from 'react';
|
|
4
4
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
5
5
|
|
|
6
6
|
type ClassValue = string | number | null | undefined | boolean | Record<string, boolean | null | undefined> | ClassValue[];
|
|
@@ -95,6 +95,9 @@ type UseSharedNowOptions = {
|
|
|
95
95
|
*/
|
|
96
96
|
declare function useSharedNow(options?: UseSharedNowOptions): number;
|
|
97
97
|
|
|
98
|
+
/** Ref-counted body scroll lock. Safe for nested overlays (Modal + Drawer). */
|
|
99
|
+
declare function useScrollLock(active: boolean): void;
|
|
100
|
+
|
|
98
101
|
type Size = 'sm' | 'md' | 'lg';
|
|
99
102
|
|
|
100
103
|
type AvatarSize = 'sm' | 'md' | 'lg' | 'xl';
|
|
@@ -376,7 +379,7 @@ type ConfirmDialogProps = {
|
|
|
376
379
|
};
|
|
377
380
|
declare function ConfirmDialog({ isOpen, onClose, onConfirm, title, message, confirmText, cancelText, loadingText, variant, isLoading, }: ConfirmDialogProps): react_jsx_runtime.JSX.Element;
|
|
378
381
|
|
|
379
|
-
type TooltipPlacement = 'top' | 'bottom';
|
|
382
|
+
type TooltipPlacement = 'top' | 'bottom' | 'left' | 'right';
|
|
380
383
|
type TooltipProps = {
|
|
381
384
|
content: ReactNode;
|
|
382
385
|
delayMs?: number;
|
|
@@ -919,4 +922,27 @@ type VisuallyHiddenProps = HTMLAttributes<HTMLSpanElement> & {
|
|
|
919
922
|
*/
|
|
920
923
|
declare function VisuallyHidden({ children, as: Tag, style, ...props }: VisuallyHiddenProps): react_jsx_runtime.JSX.Element;
|
|
921
924
|
|
|
922
|
-
|
|
925
|
+
type ErrorBoundaryProps = {
|
|
926
|
+
children: ReactNode;
|
|
927
|
+
fallback?: ReactNode | ((error: Error, reset: () => void) => ReactNode);
|
|
928
|
+
onError?: (error: Error, errorInfo: ErrorInfo) => void;
|
|
929
|
+
};
|
|
930
|
+
type State = {
|
|
931
|
+
error: Error | null;
|
|
932
|
+
};
|
|
933
|
+
declare class ErrorBoundary extends Component<ErrorBoundaryProps, State> {
|
|
934
|
+
state: State;
|
|
935
|
+
static getDerivedStateFromError(error: Error): State;
|
|
936
|
+
componentDidCatch(error: Error, errorInfo: ErrorInfo): void;
|
|
937
|
+
private reset;
|
|
938
|
+
render(): string | number | boolean | react_jsx_runtime.JSX.Element | Iterable<ReactNode> | null | undefined;
|
|
939
|
+
}
|
|
940
|
+
|
|
941
|
+
type LoadingScreenProps = {
|
|
942
|
+
message?: string;
|
|
943
|
+
size?: SpinnerSize;
|
|
944
|
+
className?: string;
|
|
945
|
+
};
|
|
946
|
+
declare function LoadingScreen({ message, size, className }: LoadingScreenProps): react_jsx_runtime.JSX.Element;
|
|
947
|
+
|
|
948
|
+
export { ActiveFilterPills, type ActiveFilterPillsProps, Alert, type AlertProps, type AlertVariant, Avatar, type AvatarProps, type AvatarSize, Badge, type BadgeProps, type BadgeSize, type BadgeVariant, type BreadcrumbItem, Breadcrumbs, type BreadcrumbsProps, Button, type ButtonProps, type ButtonSize, type ButtonVariant, Card, type CardPadding, type CardProps, type CardVariant, Checkbox, type CheckboxProps, CollapsibleSection, type CollapsibleSectionProps, ColorInput, type ColorInputProps, Combobox, type ComboboxOption, type ComboboxProps, ConfirmDialog, type ConfirmDialogProps, type ConfirmDialogVariant, CooldownRing, type CooldownRingProps, type CooldownRingSize, CopyField, type CopyFieldProps, DashboardLayout, type DashboardLayoutProps, Divider, type DividerProps, DotIndicator, type DotIndicatorProps, Drawer, type DrawerProps, type DrawerSide, type DrawerSize, DropZone, type DropZoneProps, Dropdown, DropdownItem, type DropdownItemProps, DropdownMenu, type DropdownMenuProps, type DropdownProps, DropdownSeparator, type DropdownSeparatorProps, DropdownTrigger, type DropdownTriggerProps, EmptyState, type EmptyStateProps, ErrorBoundary, type ErrorBoundaryProps, type FilterPill, FormField, type FormFieldProps, Heading, type HeadingLevel, type HeadingProps, type HotkeyBinding, type HotkeyModifiers, IconButton, type IconButtonProps, Input, type InputProps, LoadingScreen, type LoadingScreenProps, Modal, type ModalProps, MutationOverlay, type MutationOverlayProps, type MutationOverlayStatus, Navbar, type NavbarProps, NotificationBell, type NotificationBellProps, PageShell, type PageShellProps, type PageShellVariant, Pagination, type PaginationProps, Pill, Popover, type PopoverPlacement, type PopoverProps, ProgressBar, type ProgressBarProps, type ProgressBarVariant, ProgressButton, type ProgressButtonProps, RadioGroup, type RadioGroupProps, RadioItem, type RadioItemProps, ScrollArea, type ScrollAreaProps, SearchInput, type SearchInputProps, SectionCard, type SectionCardProps, Select, type SelectProps, Sidebar, type SidebarProps, type Size, Skeleton, type SkeletonProps, Slider, type SliderProps, Spinner, type SpinnerProps, type SpinnerSize, Stack, type StackProps, StageProgress, type StageProgressProps, StatCard, type StatCardProps, type StatCardTrend, type Step, Stepper, type StepperProps, Tab, TabList, type TabListProps, TabPanel, type TabPanelProps, type TabProps, Table, TableBody, type TableBodyProps, TableCell, type TableCellProps, TableHead, type TableHeadProps, TableHeader, type TableHeaderProps, type TableProps, TableRow, type TableRowProps, Tabs, type TabsProps, type TabsVariant, TagInput, type TagInputProps, Text, type TextColor, type TextProps, type TextSize, Textarea, type TextareaProps, type ToastData, type ToastPosition, ToastProvider, type ToastProviderProps, type ToastVariant, Toggle, type ToggleProps, type ToggleSize, Tooltip, type TooltipPlacement, type TooltipProps, Transition, type TransitionPreset, type TransitionProps, type UseClipboardReturn, type UseDisclosureReturn, type UseHotkeysOptions, type UseIntersectionObserverOptions, type UseIntersectionObserverReturn, type UseSharedNowOptions, VisuallyHidden, type VisuallyHiddenProps, cn, focusSafely, getFocusableElements, useClipboard, useDebounce, useDisclosure, useHotkeys, useIntersectionObserver, useMediaQuery, useScrollLock, useSharedNow, useToast };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export { MemelabColors, colors } from './tokens/index.js';
|
|
2
2
|
import * as react from 'react';
|
|
3
|
-
import { ButtonHTMLAttributes, ReactNode, InputHTMLAttributes, SelectHTMLAttributes, TextareaHTMLAttributes, HTMLAttributes, ReactElement, ComponentType } from 'react';
|
|
3
|
+
import { ButtonHTMLAttributes, ReactNode, InputHTMLAttributes, SelectHTMLAttributes, TextareaHTMLAttributes, HTMLAttributes, ReactElement, ComponentType, Component, ErrorInfo } from 'react';
|
|
4
4
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
5
5
|
|
|
6
6
|
type ClassValue = string | number | null | undefined | boolean | Record<string, boolean | null | undefined> | ClassValue[];
|
|
@@ -95,6 +95,9 @@ type UseSharedNowOptions = {
|
|
|
95
95
|
*/
|
|
96
96
|
declare function useSharedNow(options?: UseSharedNowOptions): number;
|
|
97
97
|
|
|
98
|
+
/** Ref-counted body scroll lock. Safe for nested overlays (Modal + Drawer). */
|
|
99
|
+
declare function useScrollLock(active: boolean): void;
|
|
100
|
+
|
|
98
101
|
type Size = 'sm' | 'md' | 'lg';
|
|
99
102
|
|
|
100
103
|
type AvatarSize = 'sm' | 'md' | 'lg' | 'xl';
|
|
@@ -376,7 +379,7 @@ type ConfirmDialogProps = {
|
|
|
376
379
|
};
|
|
377
380
|
declare function ConfirmDialog({ isOpen, onClose, onConfirm, title, message, confirmText, cancelText, loadingText, variant, isLoading, }: ConfirmDialogProps): react_jsx_runtime.JSX.Element;
|
|
378
381
|
|
|
379
|
-
type TooltipPlacement = 'top' | 'bottom';
|
|
382
|
+
type TooltipPlacement = 'top' | 'bottom' | 'left' | 'right';
|
|
380
383
|
type TooltipProps = {
|
|
381
384
|
content: ReactNode;
|
|
382
385
|
delayMs?: number;
|
|
@@ -919,4 +922,27 @@ type VisuallyHiddenProps = HTMLAttributes<HTMLSpanElement> & {
|
|
|
919
922
|
*/
|
|
920
923
|
declare function VisuallyHidden({ children, as: Tag, style, ...props }: VisuallyHiddenProps): react_jsx_runtime.JSX.Element;
|
|
921
924
|
|
|
922
|
-
|
|
925
|
+
type ErrorBoundaryProps = {
|
|
926
|
+
children: ReactNode;
|
|
927
|
+
fallback?: ReactNode | ((error: Error, reset: () => void) => ReactNode);
|
|
928
|
+
onError?: (error: Error, errorInfo: ErrorInfo) => void;
|
|
929
|
+
};
|
|
930
|
+
type State = {
|
|
931
|
+
error: Error | null;
|
|
932
|
+
};
|
|
933
|
+
declare class ErrorBoundary extends Component<ErrorBoundaryProps, State> {
|
|
934
|
+
state: State;
|
|
935
|
+
static getDerivedStateFromError(error: Error): State;
|
|
936
|
+
componentDidCatch(error: Error, errorInfo: ErrorInfo): void;
|
|
937
|
+
private reset;
|
|
938
|
+
render(): string | number | boolean | react_jsx_runtime.JSX.Element | Iterable<ReactNode> | null | undefined;
|
|
939
|
+
}
|
|
940
|
+
|
|
941
|
+
type LoadingScreenProps = {
|
|
942
|
+
message?: string;
|
|
943
|
+
size?: SpinnerSize;
|
|
944
|
+
className?: string;
|
|
945
|
+
};
|
|
946
|
+
declare function LoadingScreen({ message, size, className }: LoadingScreenProps): react_jsx_runtime.JSX.Element;
|
|
947
|
+
|
|
948
|
+
export { ActiveFilterPills, type ActiveFilterPillsProps, Alert, type AlertProps, type AlertVariant, Avatar, type AvatarProps, type AvatarSize, Badge, type BadgeProps, type BadgeSize, type BadgeVariant, type BreadcrumbItem, Breadcrumbs, type BreadcrumbsProps, Button, type ButtonProps, type ButtonSize, type ButtonVariant, Card, type CardPadding, type CardProps, type CardVariant, Checkbox, type CheckboxProps, CollapsibleSection, type CollapsibleSectionProps, ColorInput, type ColorInputProps, Combobox, type ComboboxOption, type ComboboxProps, ConfirmDialog, type ConfirmDialogProps, type ConfirmDialogVariant, CooldownRing, type CooldownRingProps, type CooldownRingSize, CopyField, type CopyFieldProps, DashboardLayout, type DashboardLayoutProps, Divider, type DividerProps, DotIndicator, type DotIndicatorProps, Drawer, type DrawerProps, type DrawerSide, type DrawerSize, DropZone, type DropZoneProps, Dropdown, DropdownItem, type DropdownItemProps, DropdownMenu, type DropdownMenuProps, type DropdownProps, DropdownSeparator, type DropdownSeparatorProps, DropdownTrigger, type DropdownTriggerProps, EmptyState, type EmptyStateProps, ErrorBoundary, type ErrorBoundaryProps, type FilterPill, FormField, type FormFieldProps, Heading, type HeadingLevel, type HeadingProps, type HotkeyBinding, type HotkeyModifiers, IconButton, type IconButtonProps, Input, type InputProps, LoadingScreen, type LoadingScreenProps, Modal, type ModalProps, MutationOverlay, type MutationOverlayProps, type MutationOverlayStatus, Navbar, type NavbarProps, NotificationBell, type NotificationBellProps, PageShell, type PageShellProps, type PageShellVariant, Pagination, type PaginationProps, Pill, Popover, type PopoverPlacement, type PopoverProps, ProgressBar, type ProgressBarProps, type ProgressBarVariant, ProgressButton, type ProgressButtonProps, RadioGroup, type RadioGroupProps, RadioItem, type RadioItemProps, ScrollArea, type ScrollAreaProps, SearchInput, type SearchInputProps, SectionCard, type SectionCardProps, Select, type SelectProps, Sidebar, type SidebarProps, type Size, Skeleton, type SkeletonProps, Slider, type SliderProps, Spinner, type SpinnerProps, type SpinnerSize, Stack, type StackProps, StageProgress, type StageProgressProps, StatCard, type StatCardProps, type StatCardTrend, type Step, Stepper, type StepperProps, Tab, TabList, type TabListProps, TabPanel, type TabPanelProps, type TabProps, Table, TableBody, type TableBodyProps, TableCell, type TableCellProps, TableHead, type TableHeadProps, TableHeader, type TableHeaderProps, type TableProps, TableRow, type TableRowProps, Tabs, type TabsProps, type TabsVariant, TagInput, type TagInputProps, Text, type TextColor, type TextProps, type TextSize, Textarea, type TextareaProps, type ToastData, type ToastPosition, ToastProvider, type ToastProviderProps, type ToastVariant, Toggle, type ToggleProps, type ToggleSize, Tooltip, type TooltipPlacement, type TooltipProps, Transition, type TransitionPreset, type TransitionProps, type UseClipboardReturn, type UseDisclosureReturn, type UseHotkeysOptions, type UseIntersectionObserverOptions, type UseIntersectionObserverReturn, type UseSharedNowOptions, VisuallyHidden, type VisuallyHiddenProps, cn, focusSafely, getFocusableElements, useClipboard, useDebounce, useDisclosure, useHotkeys, useIntersectionObserver, useMediaQuery, useScrollLock, useSharedNow, useToast };
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { forwardRef, useState, useId, useMemo, useRef, useEffect, createContext, useCallback, isValidElement, cloneElement, useReducer, useContext } from 'react';
|
|
1
|
+
import React, { forwardRef, useState, useId, useMemo, useRef, useEffect, createContext, useCallback, isValidElement, cloneElement, useReducer, useContext, Component } from 'react';
|
|
2
2
|
import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
|
|
3
3
|
import { createPortal } from 'react-dom';
|
|
4
4
|
|
|
@@ -133,10 +133,12 @@ function matchModifiers(e, mods) {
|
|
|
133
133
|
}
|
|
134
134
|
function useHotkeys(bindings, options = {}) {
|
|
135
135
|
const { enabled = true } = options;
|
|
136
|
+
const bindingsRef = useRef(bindings);
|
|
137
|
+
bindingsRef.current = bindings;
|
|
136
138
|
useEffect(() => {
|
|
137
139
|
if (!enabled) return;
|
|
138
140
|
const onKeyDown = (e) => {
|
|
139
|
-
for (const binding of
|
|
141
|
+
for (const binding of bindingsRef.current) {
|
|
140
142
|
if (e.key === binding.key && matchModifiers(e, binding.modifiers)) {
|
|
141
143
|
binding.handler(e);
|
|
142
144
|
}
|
|
@@ -144,7 +146,7 @@ function useHotkeys(bindings, options = {}) {
|
|
|
144
146
|
};
|
|
145
147
|
document.addEventListener("keydown", onKeyDown);
|
|
146
148
|
return () => document.removeEventListener("keydown", onKeyDown);
|
|
147
|
-
}, [enabled
|
|
149
|
+
}, [enabled]);
|
|
148
150
|
}
|
|
149
151
|
function useIntersectionObserver(options = {}) {
|
|
150
152
|
const { root = null, rootMargin = "0px", threshold = 0, enabled = true } = options;
|
|
@@ -200,6 +202,30 @@ function useSharedNow(options = {}) {
|
|
|
200
202
|
}, [interval, untilMs, enabled]);
|
|
201
203
|
return now;
|
|
202
204
|
}
|
|
205
|
+
var lockCount = 0;
|
|
206
|
+
var savedOverflow = "";
|
|
207
|
+
function lockScroll() {
|
|
208
|
+
if (typeof document === "undefined") return;
|
|
209
|
+
if (lockCount === 0) {
|
|
210
|
+
savedOverflow = document.body.style.overflow;
|
|
211
|
+
document.body.style.overflow = "hidden";
|
|
212
|
+
}
|
|
213
|
+
lockCount++;
|
|
214
|
+
}
|
|
215
|
+
function unlockScroll() {
|
|
216
|
+
if (typeof document === "undefined") return;
|
|
217
|
+
lockCount = Math.max(0, lockCount - 1);
|
|
218
|
+
if (lockCount === 0) {
|
|
219
|
+
document.body.style.overflow = savedOverflow;
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
function useScrollLock(active) {
|
|
223
|
+
useEffect(() => {
|
|
224
|
+
if (!active) return;
|
|
225
|
+
lockScroll();
|
|
226
|
+
return () => unlockScroll();
|
|
227
|
+
}, [active]);
|
|
228
|
+
}
|
|
203
229
|
|
|
204
230
|
// src/tokens/colors.ts
|
|
205
231
|
var colors = {
|
|
@@ -1251,23 +1277,6 @@ var Card = forwardRef(function Card2({ hoverable, variant = "surface", padding =
|
|
|
1251
1277
|
}
|
|
1252
1278
|
);
|
|
1253
1279
|
});
|
|
1254
|
-
var scrollLockCount = 0;
|
|
1255
|
-
var savedOverflow = "";
|
|
1256
|
-
function lockScroll() {
|
|
1257
|
-
if (typeof document === "undefined") return;
|
|
1258
|
-
if (scrollLockCount === 0) {
|
|
1259
|
-
savedOverflow = document.body.style.overflow;
|
|
1260
|
-
document.body.style.overflow = "hidden";
|
|
1261
|
-
}
|
|
1262
|
-
scrollLockCount++;
|
|
1263
|
-
}
|
|
1264
|
-
function unlockScroll() {
|
|
1265
|
-
if (typeof document === "undefined") return;
|
|
1266
|
-
scrollLockCount = Math.max(0, scrollLockCount - 1);
|
|
1267
|
-
if (scrollLockCount === 0) {
|
|
1268
|
-
document.body.style.overflow = savedOverflow;
|
|
1269
|
-
}
|
|
1270
|
-
}
|
|
1271
1280
|
function Modal({
|
|
1272
1281
|
isOpen,
|
|
1273
1282
|
onClose,
|
|
@@ -1299,11 +1308,7 @@ function Modal({
|
|
|
1299
1308
|
if (lastActive?.isConnected) focusSafely(lastActive);
|
|
1300
1309
|
};
|
|
1301
1310
|
}, [isOpen]);
|
|
1302
|
-
|
|
1303
|
-
if (!isOpen) return;
|
|
1304
|
-
lockScroll();
|
|
1305
|
-
return () => unlockScroll();
|
|
1306
|
-
}, [isOpen]);
|
|
1311
|
+
useScrollLock(isOpen);
|
|
1307
1312
|
if (!isOpen) return null;
|
|
1308
1313
|
return /* @__PURE__ */ jsx(
|
|
1309
1314
|
"div",
|
|
@@ -1452,17 +1457,32 @@ function Tooltip({ content, delayMs = 500, placement = "top", className, childre
|
|
|
1452
1457
|
const el = anchorRef.current;
|
|
1453
1458
|
if (!el) return;
|
|
1454
1459
|
const r = el.getBoundingClientRect();
|
|
1460
|
+
const vw = window.innerWidth;
|
|
1455
1461
|
const centerX = r.left + r.width / 2;
|
|
1456
|
-
const
|
|
1462
|
+
const centerY = r.top + r.height / 2;
|
|
1457
1463
|
const topY = r.top - 10;
|
|
1458
1464
|
const bottomY = r.bottom + 10;
|
|
1459
|
-
const
|
|
1460
|
-
const
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
placement:
|
|
1465
|
-
|
|
1465
|
+
const leftX = r.left - 10;
|
|
1466
|
+
const rightX = r.right + 10;
|
|
1467
|
+
let effPlacement = placement;
|
|
1468
|
+
if (placement === "top" || placement === "bottom") {
|
|
1469
|
+
const canTop = topY > 8;
|
|
1470
|
+
effPlacement = placement === "top" ? canTop ? "top" : "bottom" : "bottom";
|
|
1471
|
+
setPos({
|
|
1472
|
+
left: Math.round(centerX),
|
|
1473
|
+
top: Math.round(effPlacement === "top" ? topY : bottomY),
|
|
1474
|
+
placement: effPlacement
|
|
1475
|
+
});
|
|
1476
|
+
} else {
|
|
1477
|
+
const canLeft = leftX > 8;
|
|
1478
|
+
const canRight = rightX < vw - 8;
|
|
1479
|
+
effPlacement = placement === "left" ? canLeft ? "left" : "right" : canRight ? "right" : "left";
|
|
1480
|
+
setPos({
|
|
1481
|
+
left: Math.round(effPlacement === "left" ? leftX : rightX),
|
|
1482
|
+
top: Math.round(centerY),
|
|
1483
|
+
placement: effPlacement
|
|
1484
|
+
});
|
|
1485
|
+
}
|
|
1466
1486
|
}, [placement]);
|
|
1467
1487
|
const scheduleOpen = useCallback(() => {
|
|
1468
1488
|
clearTimer();
|
|
@@ -1536,7 +1556,7 @@ function Tooltip({ content, delayMs = 500, placement = "top", className, childre
|
|
|
1536
1556
|
style: pos ? {
|
|
1537
1557
|
left: pos.left,
|
|
1538
1558
|
top: pos.top,
|
|
1539
|
-
transform: pos.placement === "top" ? "translate(-50%, -100%)" : "translate(-50%, 0%)"
|
|
1559
|
+
transform: pos.placement === "top" ? "translate(-50%, -100%)" : pos.placement === "bottom" ? "translate(-50%, 0%)" : pos.placement === "left" ? "translate(-100%, -50%)" : "translate(0%, -50%)"
|
|
1540
1560
|
} : { left: 0, top: 0, transform: "translate(-9999px, -9999px)" },
|
|
1541
1561
|
children: content
|
|
1542
1562
|
}
|
|
@@ -2079,7 +2099,7 @@ function StatCard({ value, label, icon, trend, className }) {
|
|
|
2079
2099
|
"div",
|
|
2080
2100
|
{
|
|
2081
2101
|
className: cn(
|
|
2082
|
-
"
|
|
2102
|
+
"glass rounded-xl p-4 flex items-start gap-3",
|
|
2083
2103
|
className
|
|
2084
2104
|
),
|
|
2085
2105
|
children: [
|
|
@@ -3812,23 +3832,6 @@ function Popover({
|
|
|
3812
3832
|
) : null
|
|
3813
3833
|
] });
|
|
3814
3834
|
}
|
|
3815
|
-
var scrollLockCount2 = 0;
|
|
3816
|
-
var savedOverflow2 = "";
|
|
3817
|
-
function lockScroll2() {
|
|
3818
|
-
if (typeof document === "undefined") return;
|
|
3819
|
-
if (scrollLockCount2 === 0) {
|
|
3820
|
-
savedOverflow2 = document.body.style.overflow;
|
|
3821
|
-
document.body.style.overflow = "hidden";
|
|
3822
|
-
}
|
|
3823
|
-
scrollLockCount2++;
|
|
3824
|
-
}
|
|
3825
|
-
function unlockScroll2() {
|
|
3826
|
-
if (typeof document === "undefined") return;
|
|
3827
|
-
scrollLockCount2 = Math.max(0, scrollLockCount2 - 1);
|
|
3828
|
-
if (scrollLockCount2 === 0) {
|
|
3829
|
-
document.body.style.overflow = savedOverflow2;
|
|
3830
|
-
}
|
|
3831
|
-
}
|
|
3832
3835
|
var sizeClass8 = {
|
|
3833
3836
|
left: { sm: "w-64", md: "w-80", lg: "w-96", full: "w-screen" },
|
|
3834
3837
|
right: { sm: "w-64", md: "w-80", lg: "w-96", full: "w-screen" },
|
|
@@ -3878,11 +3881,7 @@ function Drawer({
|
|
|
3878
3881
|
if (lastActive?.isConnected) focusSafely(lastActive);
|
|
3879
3882
|
};
|
|
3880
3883
|
}, [isOpen]);
|
|
3881
|
-
|
|
3882
|
-
if (!isOpen) return;
|
|
3883
|
-
lockScroll2();
|
|
3884
|
-
return () => unlockScroll2();
|
|
3885
|
-
}, [isOpen]);
|
|
3884
|
+
useScrollLock(isOpen);
|
|
3886
3885
|
if (!isOpen) return null;
|
|
3887
3886
|
return /* @__PURE__ */ jsxs("div", { className: "fixed inset-0 z-50", role: "presentation", children: [
|
|
3888
3887
|
/* @__PURE__ */ jsx(
|
|
@@ -4265,5 +4264,60 @@ function VisuallyHidden({ children, as: Tag = "span", style, ...props }) {
|
|
|
4265
4264
|
}
|
|
4266
4265
|
);
|
|
4267
4266
|
}
|
|
4267
|
+
var ErrorBoundary = class extends Component {
|
|
4268
|
+
constructor() {
|
|
4269
|
+
super(...arguments);
|
|
4270
|
+
this.state = { error: null };
|
|
4271
|
+
this.reset = () => {
|
|
4272
|
+
this.setState({ error: null });
|
|
4273
|
+
};
|
|
4274
|
+
}
|
|
4275
|
+
static getDerivedStateFromError(error) {
|
|
4276
|
+
return { error };
|
|
4277
|
+
}
|
|
4278
|
+
componentDidCatch(error, errorInfo) {
|
|
4279
|
+
this.props.onError?.(error, errorInfo);
|
|
4280
|
+
}
|
|
4281
|
+
render() {
|
|
4282
|
+
const { error } = this.state;
|
|
4283
|
+
if (!error) return this.props.children;
|
|
4284
|
+
const { fallback } = this.props;
|
|
4285
|
+
if (typeof fallback === "function") {
|
|
4286
|
+
return fallback(error, this.reset);
|
|
4287
|
+
}
|
|
4288
|
+
if (fallback !== void 0) {
|
|
4289
|
+
return fallback;
|
|
4290
|
+
}
|
|
4291
|
+
return /* @__PURE__ */ jsxs("div", { role: "alert", className: cn("glass rounded-xl p-6 text-center"), children: [
|
|
4292
|
+
/* @__PURE__ */ jsx("h2", { className: "text-lg font-semibold text-white mb-2", children: "Something went wrong" }),
|
|
4293
|
+
/* @__PURE__ */ jsx("p", { className: "text-sm text-white/60 mb-4", children: error.message }),
|
|
4294
|
+
/* @__PURE__ */ jsx(
|
|
4295
|
+
"button",
|
|
4296
|
+
{
|
|
4297
|
+
type: "button",
|
|
4298
|
+
onClick: this.reset,
|
|
4299
|
+
className: "inline-flex items-center justify-center gap-2 rounded-xl font-semibold leading-none px-3.5 py-2.5 text-sm bg-gradient-to-r from-violet-600 to-purple-600 text-white shadow-glow hover:shadow-glow-lg hover:scale-[1.02] transition-[transform,background-color,box-shadow,opacity] active:translate-y-[0.5px]",
|
|
4300
|
+
children: "Try again"
|
|
4301
|
+
}
|
|
4302
|
+
)
|
|
4303
|
+
] });
|
|
4304
|
+
}
|
|
4305
|
+
};
|
|
4306
|
+
function LoadingScreen({ message, size = "lg", className }) {
|
|
4307
|
+
return /* @__PURE__ */ jsxs(
|
|
4308
|
+
"div",
|
|
4309
|
+
{
|
|
4310
|
+
role: "status",
|
|
4311
|
+
className: cn(
|
|
4312
|
+
"flex flex-col items-center justify-center min-h-screen bg-ml-bg gap-4",
|
|
4313
|
+
className
|
|
4314
|
+
),
|
|
4315
|
+
children: [
|
|
4316
|
+
/* @__PURE__ */ jsx(Spinner, { size }),
|
|
4317
|
+
message && /* @__PURE__ */ jsx("p", { className: "text-sm text-white/60", children: message })
|
|
4318
|
+
]
|
|
4319
|
+
}
|
|
4320
|
+
);
|
|
4321
|
+
}
|
|
4268
4322
|
|
|
4269
|
-
export { ActiveFilterPills, Alert, Avatar, Badge, Breadcrumbs, Button, Card, Checkbox, CollapsibleSection, ColorInput, Combobox, ConfirmDialog, CooldownRing, CopyField, DashboardLayout, Divider, DotIndicator, Drawer, DropZone, Dropdown, DropdownItem, DropdownMenu, DropdownSeparator, DropdownTrigger, EmptyState, FormField, Heading, IconButton, Input, Modal, MutationOverlay, Navbar, NotificationBell, PageShell, Pagination, Pill, Popover, ProgressBar, ProgressButton, RadioGroup, RadioItem, ScrollArea, SearchInput, SectionCard, Select, Sidebar, Skeleton, Slider, Spinner, Stack, StageProgress, StatCard, Stepper, Tab, TabList, TabPanel, Table, TableBody, TableCell, TableHead, TableHeader, TableRow, Tabs, TagInput, Text, Textarea, ToastProvider, Toggle, Tooltip, Transition, VisuallyHidden, cn, colors, focusSafely, getFocusableElements, useClipboard, useDebounce, useDisclosure, useHotkeys, useIntersectionObserver, useMediaQuery, useSharedNow, useToast };
|
|
4323
|
+
export { ActiveFilterPills, Alert, Avatar, Badge, Breadcrumbs, Button, Card, Checkbox, CollapsibleSection, ColorInput, Combobox, ConfirmDialog, CooldownRing, CopyField, DashboardLayout, Divider, DotIndicator, Drawer, DropZone, Dropdown, DropdownItem, DropdownMenu, DropdownSeparator, DropdownTrigger, EmptyState, ErrorBoundary, FormField, Heading, IconButton, Input, LoadingScreen, Modal, MutationOverlay, Navbar, NotificationBell, PageShell, Pagination, Pill, Popover, ProgressBar, ProgressButton, RadioGroup, RadioItem, ScrollArea, SearchInput, SectionCard, Select, Sidebar, Skeleton, Slider, Spinner, Stack, StageProgress, StatCard, Stepper, Tab, TabList, TabPanel, Table, TableBody, TableCell, TableHead, TableHeader, TableRow, Tabs, TagInput, Text, Textarea, ToastProvider, Toggle, Tooltip, Transition, VisuallyHidden, cn, colors, focusSafely, getFocusableElements, useClipboard, useDebounce, useDisclosure, useHotkeys, useIntersectionObserver, useMediaQuery, useScrollLock, useSharedNow, useToast };
|