beez-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/CHANGELOG.md +21 -3
- package/README.md +290 -274
- package/dist/components/account-menu.d.ts +53 -0
- package/dist/components/account-menu.js +405 -0
- package/dist/components/animated-collapse.d.ts +19 -0
- package/dist/components/animated-collapse.js +81 -0
- package/dist/components/animated-count.d.ts +13 -0
- package/dist/components/animated-count.js +105 -0
- package/dist/components/animated-list-item.d.ts +25 -0
- package/dist/components/animated-list-item.js +132 -0
- package/dist/components/bouncing-dots-loader.d.ts +19 -0
- package/dist/components/bouncing-dots-loader.js +47 -0
- package/dist/components/confirm-delete-button.d.ts +29 -0
- package/dist/components/confirm-delete-button.js +254 -0
- package/dist/components/empty-state.d.ts +24 -0
- package/dist/components/empty-state.js +37 -0
- package/dist/components/error-state.d.ts +20 -0
- package/dist/components/error-state.js +145 -0
- package/dist/components/external-browser-handoff.d.ts +27 -0
- package/dist/components/external-browser-handoff.js +306 -0
- package/dist/components/file-upload.d.ts +78 -0
- package/dist/components/file-upload.js +678 -0
- package/dist/components/info-popover.d.ts +23 -0
- package/dist/components/info-popover.js +158 -0
- package/dist/components/month-calendar-header.d.ts +65 -0
- package/dist/components/month-calendar-header.js +337 -0
- package/dist/components/month-grid.d.ts +59 -0
- package/dist/components/month-grid.js +301 -0
- package/dist/components/notification-bell.d.ts +50 -0
- package/dist/components/notification-bell.js +338 -0
- package/dist/components/notification-panel.d.ts +56 -0
- package/dist/components/notification-panel.js +281 -0
- package/dist/components/open-in-browser-cta.d.ts +22 -0
- package/dist/components/open-in-browser-cta.js +61 -0
- package/dist/components/presence-swap.d.ts +22 -0
- package/dist/components/presence-swap.js +162 -0
- package/dist/components/progress-ring.d.ts +20 -0
- package/dist/components/progress-ring.js +53 -0
- package/dist/components/pwa-update-control.d.ts +18 -0
- package/dist/components/pwa-update-control.js +119 -0
- package/dist/components/reaction-button.d.ts +26 -0
- package/dist/components/reaction-button.js +114 -0
- package/dist/components/rich-link-editor.d.ts +25 -0
- package/dist/components/rich-link-editor.js +320 -0
- package/dist/components/rich-markdown-content.d.ts +10 -0
- package/dist/components/rich-markdown-content.js +56 -0
- package/dist/components/rich-text-content.d.ts +19 -0
- package/dist/components/rich-text-content.js +26 -0
- package/dist/emoji-picker.d.ts +27 -0
- package/dist/emoji-picker.js +283 -0
- package/dist/hooks/use-horizontal-swipe.d.ts +23 -0
- package/dist/hooks/use-horizontal-swipe.js +80 -0
- package/dist/hooks/use-is-hydrated.d.ts +6 -0
- package/dist/hooks/use-is-hydrated.js +20 -0
- package/dist/hooks/use-minute-clock.d.ts +23 -0
- package/dist/hooks/use-minute-clock.js +147 -0
- package/dist/hooks/use-month-transition-direction.d.ts +21 -0
- package/dist/hooks/use-month-transition-direction.js +110 -0
- package/dist/hooks/use-rich-link-editor.d.ts +55 -0
- package/dist/hooks/use-rich-link-editor.js +515 -0
- package/dist/hooks/use-viewer-time-zone.d.ts +6 -0
- package/dist/hooks/use-viewer-time-zone.js +20 -0
- package/dist/index.d.ts +44 -0
- package/dist/index.js +43 -0
- package/dist/lib/browser-clipboard.d.ts +13 -0
- package/dist/lib/browser-clipboard.js +48 -0
- package/dist/lib/browser-navigation.d.ts +21 -0
- package/dist/lib/browser-navigation.js +42 -0
- package/dist/lib/file-acceptance.d.ts +43 -0
- package/dist/lib/file-acceptance.js +107 -0
- package/dist/lib/format-file-size.d.ts +16 -0
- package/dist/lib/format-file-size.js +34 -0
- package/dist/lib/fuzzy-search.d.ts +17 -0
- package/dist/lib/fuzzy-search.js +183 -0
- package/dist/lib/horizontal-swipe.d.ts +23 -0
- package/dist/lib/horizontal-swipe.js +29 -0
- package/dist/lib/in-app-browser.d.ts +35 -0
- package/dist/lib/in-app-browser.js +80 -0
- package/dist/lib/month-grid.d.ts +42 -0
- package/dist/lib/month-grid.js +74 -0
- package/dist/lib/name-initials.d.ts +7 -0
- package/dist/lib/name-initials.js +11 -0
- package/dist/lib/rich-text/link-markdown-constants.d.ts +147 -0
- package/dist/lib/rich-text/link-markdown-constants.js +458 -0
- package/dist/lib/rich-text/link-markdown-types.d.ts +53 -0
- package/dist/lib/rich-text/link-markdown-types.js +1 -0
- package/dist/lib/rich-text/link-markdown.d.ts +193 -0
- package/dist/lib/rich-text/link-markdown.js +592 -0
- package/dist/lib/rich-text/rich-markdown.d.ts +41 -0
- package/dist/lib/rich-text/rich-markdown.js +105 -0
- package/dist/lib/rich-text/rich-text-editor-dom.d.ts +26 -0
- package/dist/lib/rich-text/rich-text-editor-dom.js +79 -0
- package/dist/motion/tokens.d.ts +17 -1
- package/dist/motion/tokens.js +17 -1
- package/dist/styles.css +1 -1
- package/package.json +211 -1
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { c as _c } from "react/compiler-runtime";
|
|
3
|
+
import { motion, useIsPresent } from "motion/react";
|
|
4
|
+
import { usePrefersReducedMotion } from "../hooks/use-prefers-reduced-motion.js";
|
|
5
|
+
import { cn } from "../lib/utils.js";
|
|
6
|
+
import { MOTION_EASE, MOTION_ITEM_ENTER_SCALE, MOTION_LIST_ITEM_DISTANCE, MOTION_TIMING, SPRING_LAYOUT } from "../motion/tokens.js";
|
|
7
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
8
|
+
const ANIMATED_LIST_ITEM_ELEMENTS = {
|
|
9
|
+
li: motion.li,
|
|
10
|
+
div: motion.div,
|
|
11
|
+
article: motion.article
|
|
12
|
+
};
|
|
13
|
+
const LIST_ITEM_TRANSITION = {
|
|
14
|
+
duration: MOTION_TIMING.panel,
|
|
15
|
+
ease: MOTION_EASE,
|
|
16
|
+
layout: SPRING_LAYOUT
|
|
17
|
+
};
|
|
18
|
+
const LIST_ITEM_EXIT_TRANSITION = {
|
|
19
|
+
duration: MOTION_TIMING.exit,
|
|
20
|
+
ease: MOTION_EASE
|
|
21
|
+
};
|
|
22
|
+
/** Reduced motion keeps enter/exit semantics (inert while leaving) but without travel or delay. */
|
|
23
|
+
const INSTANT_TRANSITION = { duration: 0 };
|
|
24
|
+
/**
|
|
25
|
+
* Wrap the list in `<AnimatePresence initial={false}>` so only items added after the
|
|
26
|
+
* first render animate in, and removed items animate out before leaving the DOM.
|
|
27
|
+
* A leaving item turns inert and hidden from assistive technology, so it can no
|
|
28
|
+
* longer be focused, clicked or announced during its exit.
|
|
29
|
+
* @param props - Native attributes, element type and content.
|
|
30
|
+
* @returns The animated item.
|
|
31
|
+
*/
|
|
32
|
+
export function AnimatedListItem(t0) {
|
|
33
|
+
const $ = _c(22);
|
|
34
|
+
let children;
|
|
35
|
+
let className;
|
|
36
|
+
let elementProps;
|
|
37
|
+
let t1;
|
|
38
|
+
let t2;
|
|
39
|
+
if ($[0] !== t0) {
|
|
40
|
+
({children, as: t1, layout: t2, className, ...elementProps} = t0);
|
|
41
|
+
$[0] = t0;
|
|
42
|
+
$[1] = children;
|
|
43
|
+
$[2] = className;
|
|
44
|
+
$[3] = elementProps;
|
|
45
|
+
$[4] = t1;
|
|
46
|
+
$[5] = t2;
|
|
47
|
+
} else {
|
|
48
|
+
children = $[1];
|
|
49
|
+
className = $[2];
|
|
50
|
+
elementProps = $[3];
|
|
51
|
+
t1 = $[4];
|
|
52
|
+
t2 = $[5];
|
|
53
|
+
}
|
|
54
|
+
const as = t1 === undefined ? "li" : t1;
|
|
55
|
+
const layout = t2 === undefined ? true : t2;
|
|
56
|
+
const MotionElement = ANIMATED_LIST_ITEM_ELEMENTS[as];
|
|
57
|
+
const isPresent = useIsPresent();
|
|
58
|
+
const shouldReduceMotion = usePrefersReducedMotion();
|
|
59
|
+
const t3 = isPresent ? elementProps["aria-hidden"] : true;
|
|
60
|
+
const t4 = !isPresent || undefined;
|
|
61
|
+
let t5;
|
|
62
|
+
if ($[6] !== className) {
|
|
63
|
+
t5 = cn("min-w-0", className);
|
|
64
|
+
$[6] = className;
|
|
65
|
+
$[7] = t5;
|
|
66
|
+
} else {
|
|
67
|
+
t5 = $[7];
|
|
68
|
+
}
|
|
69
|
+
const t6 = layout && !shouldReduceMotion ? "position" : false;
|
|
70
|
+
let t7;
|
|
71
|
+
let t8;
|
|
72
|
+
if ($[8] === Symbol.for("react.memo_cache_sentinel")) {
|
|
73
|
+
t7 = {
|
|
74
|
+
opacity: 0,
|
|
75
|
+
y: MOTION_LIST_ITEM_DISTANCE,
|
|
76
|
+
scale: MOTION_ITEM_ENTER_SCALE
|
|
77
|
+
};
|
|
78
|
+
t8 = {
|
|
79
|
+
opacity: 1,
|
|
80
|
+
y: 0,
|
|
81
|
+
scale: 1
|
|
82
|
+
};
|
|
83
|
+
$[8] = t7;
|
|
84
|
+
$[9] = t8;
|
|
85
|
+
} else {
|
|
86
|
+
t7 = $[8];
|
|
87
|
+
t8 = $[9];
|
|
88
|
+
}
|
|
89
|
+
const t9 = shouldReduceMotion ? INSTANT_TRANSITION : LIST_ITEM_EXIT_TRANSITION;
|
|
90
|
+
let t10;
|
|
91
|
+
if ($[10] !== t9) {
|
|
92
|
+
t10 = {
|
|
93
|
+
opacity: 0,
|
|
94
|
+
scale: MOTION_ITEM_ENTER_SCALE,
|
|
95
|
+
transition: t9
|
|
96
|
+
};
|
|
97
|
+
$[10] = t9;
|
|
98
|
+
$[11] = t10;
|
|
99
|
+
} else {
|
|
100
|
+
t10 = $[11];
|
|
101
|
+
}
|
|
102
|
+
const t11 = shouldReduceMotion ? INSTANT_TRANSITION : LIST_ITEM_TRANSITION;
|
|
103
|
+
let t12;
|
|
104
|
+
if ($[12] !== MotionElement || $[13] !== children || $[14] !== elementProps || $[15] !== t10 || $[16] !== t11 || $[17] !== t3 || $[18] !== t4 || $[19] !== t5 || $[20] !== t6) {
|
|
105
|
+
t12 = /* @__PURE__ */ _jsx(MotionElement, {
|
|
106
|
+
"data-slot": "animated-list-item",
|
|
107
|
+
...elementProps,
|
|
108
|
+
"aria-hidden": t3,
|
|
109
|
+
inert: t4,
|
|
110
|
+
className: t5,
|
|
111
|
+
layout: t6,
|
|
112
|
+
initial: t7,
|
|
113
|
+
animate: t8,
|
|
114
|
+
exit: t10,
|
|
115
|
+
transition: t11,
|
|
116
|
+
children
|
|
117
|
+
});
|
|
118
|
+
$[12] = MotionElement;
|
|
119
|
+
$[13] = children;
|
|
120
|
+
$[14] = elementProps;
|
|
121
|
+
$[15] = t10;
|
|
122
|
+
$[16] = t11;
|
|
123
|
+
$[17] = t3;
|
|
124
|
+
$[18] = t4;
|
|
125
|
+
$[19] = t5;
|
|
126
|
+
$[20] = t6;
|
|
127
|
+
$[21] = t12;
|
|
128
|
+
} else {
|
|
129
|
+
t12 = $[21];
|
|
130
|
+
}
|
|
131
|
+
return t12;
|
|
132
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/** Animated three-dot bouncing loader with synchronized floor shadows. */
|
|
2
|
+
import type { HTMLAttributes } from "react";
|
|
3
|
+
export type BouncingDotsLoaderSize = "sm" | "md";
|
|
4
|
+
export type BouncingDotsLoaderProps = Omit<HTMLAttributes<HTMLDivElement>, "aria-label" | "role"> & {
|
|
5
|
+
/**
|
|
6
|
+
* Accessible label announced by assistive technologies. Also rendered as visually hidden text
|
|
7
|
+
* so screen readers can read it independently of the `aria-label`.
|
|
8
|
+
*/
|
|
9
|
+
label?: string;
|
|
10
|
+
/** Use `"sm"` for inline or compact contexts and `"md"` (default) for standalone loading panels. */
|
|
11
|
+
size?: BouncingDotsLoaderSize;
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* Renders the loader as a `role="status"` region. It fades in after a short delay, so loads that
|
|
15
|
+
* finish quickly never flash it. Reduced motion stops the bounce through the shared fallback.
|
|
16
|
+
* @param props - Label, size and native attributes.
|
|
17
|
+
* @returns The loader.
|
|
18
|
+
*/
|
|
19
|
+
export declare function BouncingDotsLoader({ label, size, className, ...rest }: BouncingDotsLoaderProps): import("react").JSX.Element;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { cn } from "../lib/utils.js";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
const DEFAULT_LOADING_LABEL = "Cargando...";
|
|
4
|
+
/** Stage, dot and shadow geometry per size; the keyframes in `keyframes.css` match these values. */
|
|
5
|
+
const LOADER_SIZE_CLASS_NAMES = {
|
|
6
|
+
md: {
|
|
7
|
+
stage: "h-[3.75rem] w-[12.5rem]",
|
|
8
|
+
dot: "size-5 animate-[beez-bouncing-dot-md_0.5s_ease_infinite_alternate]",
|
|
9
|
+
shadow: "top-[3.875rem] h-1 w-5"
|
|
10
|
+
},
|
|
11
|
+
sm: {
|
|
12
|
+
stage: "h-[1.875rem] w-[6.5rem]",
|
|
13
|
+
dot: "size-2.5 animate-[beez-bouncing-dot-sm_0.5s_ease_infinite_alternate]",
|
|
14
|
+
shadow: "top-[1.9375rem] h-[0.1875rem] w-2.5"
|
|
15
|
+
}
|
|
16
|
+
};
|
|
17
|
+
/** Horizontal slot and phase of each dot: the middle and right dots trail the left one. */
|
|
18
|
+
const DOT_POSITION_CLASS_NAMES = [
|
|
19
|
+
"left-[15%]",
|
|
20
|
+
"left-[45%] delay-200",
|
|
21
|
+
"right-[15%] delay-300"
|
|
22
|
+
];
|
|
23
|
+
/**
|
|
24
|
+
* Renders the loader as a `role="status"` region. It fades in after a short delay, so loads that
|
|
25
|
+
* finish quickly never flash it. Reduced motion stops the bounce through the shared fallback.
|
|
26
|
+
* @param props - Label, size and native attributes.
|
|
27
|
+
* @returns The loader.
|
|
28
|
+
*/
|
|
29
|
+
export function BouncingDotsLoader({ label = DEFAULT_LOADING_LABEL, size = "md", className, ...rest }) {
|
|
30
|
+
const sizeClassNames = LOADER_SIZE_CLASS_NAMES[size];
|
|
31
|
+
return /* @__PURE__ */ _jsxs("div", {
|
|
32
|
+
"data-slot": "bouncing-dots-loader",
|
|
33
|
+
"data-size": size,
|
|
34
|
+
...rest,
|
|
35
|
+
"aria-label": label,
|
|
36
|
+
role: "status",
|
|
37
|
+
className: cn("flex w-full items-center justify-center animate-in fade-in fill-mode-both delay-120 duration-300", className),
|
|
38
|
+
children: [/* @__PURE__ */ _jsxs("div", {
|
|
39
|
+
"aria-hidden": "true",
|
|
40
|
+
className: cn("relative z-[1]", sizeClassNames.stage),
|
|
41
|
+
children: [DOT_POSITION_CLASS_NAMES.map((positionClassName) => /* @__PURE__ */ _jsx("span", { className: cn("absolute top-0 origin-bottom rounded-full bg-foreground", sizeClassNames.dot, positionClassName) }, `dot-${positionClassName}`)), DOT_POSITION_CLASS_NAMES.map((positionClassName) => /* @__PURE__ */ _jsx("span", { className: cn("absolute -z-[1] rounded-full bg-foreground/35 blur-[1px] animate-[beez-bouncing-dot-shadow_0.5s_ease_infinite_alternate]", sizeClassNames.shadow, positionClassName) }, `shadow-${positionClassName}`))]
|
|
42
|
+
}), /* @__PURE__ */ _jsx("span", {
|
|
43
|
+
className: "sr-only",
|
|
44
|
+
children: label
|
|
45
|
+
})]
|
|
46
|
+
});
|
|
47
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/** Row action menu whose destructive item asks for an inline confirmation before running. */
|
|
2
|
+
import { type ReactNode } from "react";
|
|
3
|
+
export interface ConfirmDeleteButtonLabels {
|
|
4
|
+
/** Dismisses the confirmation. */
|
|
5
|
+
cancel?: string;
|
|
6
|
+
/** Runs `onConfirm`. */
|
|
7
|
+
confirm?: string;
|
|
8
|
+
/** Destructive menu item that opens the confirmation. */
|
|
9
|
+
delete?: string;
|
|
10
|
+
/** Accessible name of the icon-only menu trigger. */
|
|
11
|
+
menu?: string;
|
|
12
|
+
}
|
|
13
|
+
export interface ConfirmDeleteButtonProps {
|
|
14
|
+
/** Question shown in the confirmation, also used as its accessible name. */
|
|
15
|
+
message: string;
|
|
16
|
+
onConfirm: () => void;
|
|
17
|
+
/** Extra menu items (for example Edit), rendered before the delete item. */
|
|
18
|
+
extraMenuItems?: ReactNode;
|
|
19
|
+
labels?: ConfirmDeleteButtonLabels;
|
|
20
|
+
className?: string;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Renders an icon menu with a destructive item. Choosing it opens a confirmation anchored to
|
|
24
|
+
* the trigger; only its confirm button runs `onConfirm`. Escape, an outside click or Cancel
|
|
25
|
+
* dismiss it without side effects.
|
|
26
|
+
* @param props - Confirmation copy, callback, extra items and optional labels.
|
|
27
|
+
* @returns The menu trigger with its confirmation.
|
|
28
|
+
*/
|
|
29
|
+
export declare function ConfirmDeleteButton({ message, onConfirm, extraMenuItems, labels, className, }: ConfirmDeleteButtonProps): import("react").JSX.Element;
|
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { c as _c } from "react/compiler-runtime";
|
|
3
|
+
/** Row action menu whose destructive item asks for an inline confirmation before running. */
|
|
4
|
+
import { useId, useRef, useState } from "react";
|
|
5
|
+
import { MoreVertical, Trash2 } from "lucide-react";
|
|
6
|
+
import { cn } from "../lib/utils.js";
|
|
7
|
+
import { Button } from "./button.js";
|
|
8
|
+
import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from "./dropdown-menu.js";
|
|
9
|
+
import { Popover, PopoverAnchor, PopoverContent } from "./popover.js";
|
|
10
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
11
|
+
const CONFIRM_DELETE_DEFAULT_LABELS = {
|
|
12
|
+
cancel: "Cancelar",
|
|
13
|
+
confirm: "Confirmar",
|
|
14
|
+
delete: "Eliminar",
|
|
15
|
+
menu: "Abrir acciones"
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* Renders an icon menu with a destructive item. Choosing it opens a confirmation anchored to
|
|
19
|
+
* the trigger; only its confirm button runs `onConfirm`. Escape, an outside click or Cancel
|
|
20
|
+
* dismiss it without side effects.
|
|
21
|
+
* @param props - Confirmation copy, callback, extra items and optional labels.
|
|
22
|
+
* @returns The menu trigger with its confirmation.
|
|
23
|
+
*/
|
|
24
|
+
export function ConfirmDeleteButton(t0) {
|
|
25
|
+
const $ = _c(43);
|
|
26
|
+
const { message, onConfirm, extraMenuItems: t1, labels, className } = t0;
|
|
27
|
+
const extraMenuItems = t1 === undefined ? null : t1;
|
|
28
|
+
let t2;
|
|
29
|
+
if ($[0] !== labels) {
|
|
30
|
+
t2 = {
|
|
31
|
+
...CONFIRM_DELETE_DEFAULT_LABELS,
|
|
32
|
+
...labels
|
|
33
|
+
};
|
|
34
|
+
$[0] = labels;
|
|
35
|
+
$[1] = t2;
|
|
36
|
+
} else {
|
|
37
|
+
t2 = $[1];
|
|
38
|
+
}
|
|
39
|
+
const resolvedLabels = t2;
|
|
40
|
+
const [isConfirming, setIsConfirming] = useState(false);
|
|
41
|
+
const isOpeningConfirmationRef = useRef(false);
|
|
42
|
+
const messageId = useId();
|
|
43
|
+
let t3;
|
|
44
|
+
if ($[2] !== className) {
|
|
45
|
+
t3 = cn("inline-flex justify-end", className);
|
|
46
|
+
$[2] = className;
|
|
47
|
+
$[3] = t3;
|
|
48
|
+
} else {
|
|
49
|
+
t3 = $[3];
|
|
50
|
+
}
|
|
51
|
+
let t4;
|
|
52
|
+
if ($[4] === Symbol.for("react.memo_cache_sentinel")) {
|
|
53
|
+
t4 = /* @__PURE__ */ _jsx(MoreVertical, { "aria-hidden": "true" });
|
|
54
|
+
$[4] = t4;
|
|
55
|
+
} else {
|
|
56
|
+
t4 = $[4];
|
|
57
|
+
}
|
|
58
|
+
let t5;
|
|
59
|
+
if ($[5] !== resolvedLabels.menu) {
|
|
60
|
+
t5 = /* @__PURE__ */ _jsx(PopoverAnchor, {
|
|
61
|
+
asChild: true,
|
|
62
|
+
children: /* @__PURE__ */ _jsx(DropdownMenuTrigger, {
|
|
63
|
+
asChild: true,
|
|
64
|
+
children: /* @__PURE__ */ _jsx(Button, {
|
|
65
|
+
"aria-label": resolvedLabels.menu,
|
|
66
|
+
size: "icon-sm",
|
|
67
|
+
type: "button",
|
|
68
|
+
variant: "ghost",
|
|
69
|
+
children: t4
|
|
70
|
+
})
|
|
71
|
+
})
|
|
72
|
+
});
|
|
73
|
+
$[5] = resolvedLabels.menu;
|
|
74
|
+
$[6] = t5;
|
|
75
|
+
} else {
|
|
76
|
+
t5 = $[6];
|
|
77
|
+
}
|
|
78
|
+
let t6;
|
|
79
|
+
if ($[7] === Symbol.for("react.memo_cache_sentinel")) {
|
|
80
|
+
t6 = (event) => {
|
|
81
|
+
if (!isOpeningConfirmationRef.current) {
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
isOpeningConfirmationRef.current = false;
|
|
85
|
+
event.preventDefault();
|
|
86
|
+
};
|
|
87
|
+
$[7] = t6;
|
|
88
|
+
} else {
|
|
89
|
+
t6 = $[7];
|
|
90
|
+
}
|
|
91
|
+
let t7;
|
|
92
|
+
let t8;
|
|
93
|
+
if ($[8] === Symbol.for("react.memo_cache_sentinel")) {
|
|
94
|
+
t7 = () => {
|
|
95
|
+
isOpeningConfirmationRef.current = true;
|
|
96
|
+
setIsConfirming(true);
|
|
97
|
+
};
|
|
98
|
+
t8 = /* @__PURE__ */ _jsx(Trash2, { "aria-hidden": "true" });
|
|
99
|
+
$[8] = t7;
|
|
100
|
+
$[9] = t8;
|
|
101
|
+
} else {
|
|
102
|
+
t7 = $[8];
|
|
103
|
+
t8 = $[9];
|
|
104
|
+
}
|
|
105
|
+
let t9;
|
|
106
|
+
if ($[10] !== resolvedLabels.delete) {
|
|
107
|
+
t9 = /* @__PURE__ */ _jsxs(DropdownMenuItem, {
|
|
108
|
+
variant: "destructive",
|
|
109
|
+
onSelect: t7,
|
|
110
|
+
children: [t8, resolvedLabels.delete]
|
|
111
|
+
});
|
|
112
|
+
$[10] = resolvedLabels.delete;
|
|
113
|
+
$[11] = t9;
|
|
114
|
+
} else {
|
|
115
|
+
t9 = $[11];
|
|
116
|
+
}
|
|
117
|
+
let t10;
|
|
118
|
+
if ($[12] !== extraMenuItems || $[13] !== t9) {
|
|
119
|
+
t10 = /* @__PURE__ */ _jsxs(DropdownMenuContent, {
|
|
120
|
+
align: "end",
|
|
121
|
+
onCloseAutoFocus: t6,
|
|
122
|
+
children: [extraMenuItems, t9]
|
|
123
|
+
});
|
|
124
|
+
$[12] = extraMenuItems;
|
|
125
|
+
$[13] = t9;
|
|
126
|
+
$[14] = t10;
|
|
127
|
+
} else {
|
|
128
|
+
t10 = $[14];
|
|
129
|
+
}
|
|
130
|
+
let t11;
|
|
131
|
+
if ($[15] !== t10 || $[16] !== t5) {
|
|
132
|
+
t11 = /* @__PURE__ */ _jsxs(DropdownMenu, { children: [t5, t10] });
|
|
133
|
+
$[15] = t10;
|
|
134
|
+
$[16] = t5;
|
|
135
|
+
$[17] = t11;
|
|
136
|
+
} else {
|
|
137
|
+
t11 = $[17];
|
|
138
|
+
}
|
|
139
|
+
let t12;
|
|
140
|
+
if ($[18] !== message || $[19] !== messageId) {
|
|
141
|
+
t12 = /* @__PURE__ */ _jsx("p", {
|
|
142
|
+
id: messageId,
|
|
143
|
+
className: "m-0 text-sm text-foreground",
|
|
144
|
+
children: message
|
|
145
|
+
});
|
|
146
|
+
$[18] = message;
|
|
147
|
+
$[19] = messageId;
|
|
148
|
+
$[20] = t12;
|
|
149
|
+
} else {
|
|
150
|
+
t12 = $[20];
|
|
151
|
+
}
|
|
152
|
+
let t13;
|
|
153
|
+
if ($[21] === Symbol.for("react.memo_cache_sentinel")) {
|
|
154
|
+
t13 = () => setIsConfirming(false);
|
|
155
|
+
$[21] = t13;
|
|
156
|
+
} else {
|
|
157
|
+
t13 = $[21];
|
|
158
|
+
}
|
|
159
|
+
let t14;
|
|
160
|
+
if ($[22] !== resolvedLabels.cancel) {
|
|
161
|
+
t14 = /* @__PURE__ */ _jsx(Button, {
|
|
162
|
+
size: "sm",
|
|
163
|
+
type: "button",
|
|
164
|
+
variant: "outline",
|
|
165
|
+
onClick: t13,
|
|
166
|
+
children: resolvedLabels.cancel
|
|
167
|
+
});
|
|
168
|
+
$[22] = resolvedLabels.cancel;
|
|
169
|
+
$[23] = t14;
|
|
170
|
+
} else {
|
|
171
|
+
t14 = $[23];
|
|
172
|
+
}
|
|
173
|
+
let t15;
|
|
174
|
+
if ($[24] !== onConfirm) {
|
|
175
|
+
t15 = () => {
|
|
176
|
+
setIsConfirming(false);
|
|
177
|
+
onConfirm();
|
|
178
|
+
};
|
|
179
|
+
$[24] = onConfirm;
|
|
180
|
+
$[25] = t15;
|
|
181
|
+
} else {
|
|
182
|
+
t15 = $[25];
|
|
183
|
+
}
|
|
184
|
+
let t16;
|
|
185
|
+
if ($[26] !== resolvedLabels.confirm || $[27] !== t15) {
|
|
186
|
+
t16 = /* @__PURE__ */ _jsx(Button, {
|
|
187
|
+
size: "sm",
|
|
188
|
+
type: "button",
|
|
189
|
+
variant: "destructive",
|
|
190
|
+
onClick: t15,
|
|
191
|
+
children: resolvedLabels.confirm
|
|
192
|
+
});
|
|
193
|
+
$[26] = resolvedLabels.confirm;
|
|
194
|
+
$[27] = t15;
|
|
195
|
+
$[28] = t16;
|
|
196
|
+
} else {
|
|
197
|
+
t16 = $[28];
|
|
198
|
+
}
|
|
199
|
+
let t17;
|
|
200
|
+
if ($[29] !== t14 || $[30] !== t16) {
|
|
201
|
+
t17 = /* @__PURE__ */ _jsxs("div", {
|
|
202
|
+
className: "flex items-center gap-2",
|
|
203
|
+
children: [t14, t16]
|
|
204
|
+
});
|
|
205
|
+
$[29] = t14;
|
|
206
|
+
$[30] = t16;
|
|
207
|
+
$[31] = t17;
|
|
208
|
+
} else {
|
|
209
|
+
t17 = $[31];
|
|
210
|
+
}
|
|
211
|
+
let t18;
|
|
212
|
+
if ($[32] !== messageId || $[33] !== t12 || $[34] !== t17) {
|
|
213
|
+
t18 = /* @__PURE__ */ _jsxs(PopoverContent, {
|
|
214
|
+
align: "end",
|
|
215
|
+
"aria-labelledby": messageId,
|
|
216
|
+
className: "w-[min(18rem,calc(100vw-2rem))] gap-3 p-3.5",
|
|
217
|
+
children: [t12, t17]
|
|
218
|
+
});
|
|
219
|
+
$[32] = messageId;
|
|
220
|
+
$[33] = t12;
|
|
221
|
+
$[34] = t17;
|
|
222
|
+
$[35] = t18;
|
|
223
|
+
} else {
|
|
224
|
+
t18 = $[35];
|
|
225
|
+
}
|
|
226
|
+
let t19;
|
|
227
|
+
if ($[36] !== isConfirming || $[37] !== t11 || $[38] !== t18) {
|
|
228
|
+
t19 = /* @__PURE__ */ _jsxs(Popover, {
|
|
229
|
+
open: isConfirming,
|
|
230
|
+
onOpenChange: setIsConfirming,
|
|
231
|
+
children: [t11, t18]
|
|
232
|
+
});
|
|
233
|
+
$[36] = isConfirming;
|
|
234
|
+
$[37] = t11;
|
|
235
|
+
$[38] = t18;
|
|
236
|
+
$[39] = t19;
|
|
237
|
+
} else {
|
|
238
|
+
t19 = $[39];
|
|
239
|
+
}
|
|
240
|
+
let t20;
|
|
241
|
+
if ($[40] !== t19 || $[41] !== t3) {
|
|
242
|
+
t20 = /* @__PURE__ */ _jsx("div", {
|
|
243
|
+
"data-slot": "confirm-delete-button",
|
|
244
|
+
className: t3,
|
|
245
|
+
children: t19
|
|
246
|
+
});
|
|
247
|
+
$[40] = t19;
|
|
248
|
+
$[41] = t3;
|
|
249
|
+
$[42] = t20;
|
|
250
|
+
} else {
|
|
251
|
+
t20 = $[42];
|
|
252
|
+
}
|
|
253
|
+
return t20;
|
|
254
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/** Placeholder for regions without content yet: empty lists, sections in construction or first steps. */
|
|
2
|
+
import type { ReactNode } from "react";
|
|
3
|
+
export type EmptyStateTitleElement = "h1" | "h2" | "h3" | "p";
|
|
4
|
+
export interface EmptyStateProps {
|
|
5
|
+
title: ReactNode;
|
|
6
|
+
/** Heading level that fits the surrounding outline; a paragraph for minor regions. */
|
|
7
|
+
titleAs?: EmptyStateTitleElement;
|
|
8
|
+
/** Short uppercase label above the title, such as "Próximamente". */
|
|
9
|
+
eyebrow?: ReactNode;
|
|
10
|
+
description?: ReactNode;
|
|
11
|
+
/** Actions or extra content, such as buttons or a template list. */
|
|
12
|
+
children?: ReactNode;
|
|
13
|
+
align?: "start" | "center";
|
|
14
|
+
/** `page` uses display typography for full sections; `inline` stays compact inside panels. */
|
|
15
|
+
size?: "page" | "inline";
|
|
16
|
+
className?: string;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Renders the empty region as a labelled section. It does not add a landmark besides the
|
|
20
|
+
* section, so it composes inside an existing `main`.
|
|
21
|
+
* @param props - Title, optional eyebrow, description, actions and layout.
|
|
22
|
+
* @returns The empty state.
|
|
23
|
+
*/
|
|
24
|
+
export declare function EmptyState({ title, titleAs: TitleElement, eyebrow, description, children, align, size, className, }: EmptyStateProps): import("react").JSX.Element;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { cn } from "../lib/utils.js";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
/** Copy settles in one line after another; reduced motion drops it through the shared fallback. */
|
|
4
|
+
const ENTER_CLASS_NAME = "animate-in fade-in slide-in-from-bottom-1.5 fill-mode-both duration-300";
|
|
5
|
+
/**
|
|
6
|
+
* Renders the empty region as a labelled section. It does not add a landmark besides the
|
|
7
|
+
* section, so it composes inside an existing `main`.
|
|
8
|
+
* @param props - Title, optional eyebrow, description, actions and layout.
|
|
9
|
+
* @returns The empty state.
|
|
10
|
+
*/
|
|
11
|
+
export function EmptyState({ title, titleAs: TitleElement = "h2", eyebrow, description, children, align = "start", size = "inline", className }) {
|
|
12
|
+
const isCentered = align === "center";
|
|
13
|
+
const isPage = size === "page";
|
|
14
|
+
return /* @__PURE__ */ _jsxs("section", {
|
|
15
|
+
"data-slot": "empty-state",
|
|
16
|
+
"data-size": size,
|
|
17
|
+
className: cn("grid gap-2", isCentered ? "justify-items-center text-center" : "justify-items-start", isPage ? "max-w-2xl gap-2.5 py-6" : "py-6", className),
|
|
18
|
+
children: [
|
|
19
|
+
eyebrow ? /* @__PURE__ */ _jsx("p", {
|
|
20
|
+
className: cn("m-0 text-[0.78rem] font-bold tracking-[0.08em] text-[color-mix(in_oklab,var(--primary)_76%,var(--foreground))] uppercase", ENTER_CLASS_NAME),
|
|
21
|
+
children: eyebrow
|
|
22
|
+
}) : null,
|
|
23
|
+
/* @__PURE__ */ _jsx(TitleElement, {
|
|
24
|
+
className: cn("m-0 text-balance [overflow-wrap:anywhere]", isPage ? "font-display text-[clamp(2rem,6vw,4rem)] leading-[1.05] font-semibold" : "font-semibold", ENTER_CLASS_NAME, "delay-40"),
|
|
25
|
+
children: title
|
|
26
|
+
}),
|
|
27
|
+
description ? /* @__PURE__ */ _jsx("p", {
|
|
28
|
+
className: cn("m-0 max-w-xl text-pretty text-muted-foreground", isPage && "text-[clamp(1rem,2vw,1.15rem)] leading-relaxed", ENTER_CLASS_NAME, "delay-80"),
|
|
29
|
+
children: description
|
|
30
|
+
}) : null,
|
|
31
|
+
children ? /* @__PURE__ */ _jsx("div", {
|
|
32
|
+
className: cn("mt-2 flex w-full flex-wrap gap-2", isCentered && "justify-center", ENTER_CLASS_NAME, "delay-120"),
|
|
33
|
+
children
|
|
34
|
+
}) : null
|
|
35
|
+
]
|
|
36
|
+
});
|
|
37
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/** Full-page recovery view for route and global error boundaries: explains the failure and offers a retry. */
|
|
2
|
+
import type { ReactNode } from "react";
|
|
3
|
+
export interface ErrorStateProps {
|
|
4
|
+
eyebrow?: ReactNode;
|
|
5
|
+
title: ReactNode;
|
|
6
|
+
description: ReactNode;
|
|
7
|
+
retryLabel: string;
|
|
8
|
+
onRetry: () => void;
|
|
9
|
+
/** Destination of the secondary action. Without it, only the retry action is shown. */
|
|
10
|
+
homeHref?: string;
|
|
11
|
+
homeLabel?: string;
|
|
12
|
+
className?: string;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Renders a full-height section with the error copy, a retry button and an optional way home.
|
|
16
|
+
* The home link uses the router adapter configured in `BeezUIProvider`.
|
|
17
|
+
* @param props - Copy, retry callback and optional home destination.
|
|
18
|
+
* @returns The error view.
|
|
19
|
+
*/
|
|
20
|
+
export declare function ErrorState({ eyebrow, title, description, retryLabel, onRetry, homeHref, homeLabel, className }: ErrorStateProps): import("react").JSX.Element;
|