@emara/ui 1.1.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/components/ui/.gitkeep +0 -0
- package/components/ui/accordion.stories.tsx +231 -0
- package/components/ui/accordion.tsx +250 -0
- package/components/ui/app-shell.stories.tsx +270 -0
- package/components/ui/app-shell.tsx +491 -0
- package/components/ui/avatar.stories.tsx +174 -0
- package/components/ui/avatar.tsx +257 -0
- package/components/ui/badge.stories.tsx +127 -0
- package/components/ui/badge.tsx +146 -0
- package/components/ui/breadcrumb.stories.tsx +92 -0
- package/components/ui/breadcrumb.tsx +302 -0
- package/components/ui/button.stories.tsx +186 -0
- package/components/ui/button.tsx +128 -0
- package/components/ui/card.stories.tsx +279 -0
- package/components/ui/card.tsx +250 -0
- package/components/ui/checkbox.stories.tsx +93 -0
- package/components/ui/checkbox.tsx +131 -0
- package/components/ui/combobox.stories.tsx +489 -0
- package/components/ui/combobox.tsx +874 -0
- package/components/ui/context-menu.stories.tsx +202 -0
- package/components/ui/context-menu.tsx +309 -0
- package/components/ui/data-table.stories.tsx +227 -0
- package/components/ui/data-table.tsx +539 -0
- package/components/ui/date-picker.stories.tsx +225 -0
- package/components/ui/date-picker.tsx +597 -0
- package/components/ui/dialog.stories.tsx +193 -0
- package/components/ui/dialog.tsx +262 -0
- package/components/ui/divider.stories.tsx +84 -0
- package/components/ui/divider.tsx +135 -0
- package/components/ui/drawer.stories.tsx +218 -0
- package/components/ui/drawer.tsx +329 -0
- package/components/ui/dropdown-menu.stories.tsx +270 -0
- package/components/ui/dropdown-menu.tsx +353 -0
- package/components/ui/empty-state.stories.tsx +121 -0
- package/components/ui/empty-state.tsx +289 -0
- package/components/ui/field-group.stories.tsx +201 -0
- package/components/ui/field-group.tsx +276 -0
- package/components/ui/form.stories.tsx +219 -0
- package/components/ui/form.tsx +542 -0
- package/components/ui/input.stories.tsx +154 -0
- package/components/ui/input.tsx +208 -0
- package/components/ui/label.stories.tsx +84 -0
- package/components/ui/label.tsx +98 -0
- package/components/ui/page-header.stories.tsx +136 -0
- package/components/ui/page-header.tsx +315 -0
- package/components/ui/pagination.stories.tsx +136 -0
- package/components/ui/pagination.tsx +427 -0
- package/components/ui/popover.stories.tsx +212 -0
- package/components/ui/popover.tsx +167 -0
- package/components/ui/radio-group.stories.tsx +96 -0
- package/components/ui/radio-group.tsx +250 -0
- package/components/ui/select.stories.tsx +203 -0
- package/components/ui/select.tsx +318 -0
- package/components/ui/sidebar.stories.tsx +186 -0
- package/components/ui/sidebar.tsx +623 -0
- package/components/ui/skeleton.stories.tsx +131 -0
- package/components/ui/skeleton.tsx +311 -0
- package/components/ui/switch.stories.tsx +74 -0
- package/components/ui/switch.tsx +186 -0
- package/components/ui/table.stories.tsx +107 -0
- package/components/ui/table.tsx +285 -0
- package/components/ui/tabs.stories.tsx +222 -0
- package/components/ui/tabs.tsx +287 -0
- package/components/ui/textarea.stories.tsx +96 -0
- package/components/ui/textarea.tsx +182 -0
- package/components/ui/toast.stories.tsx +169 -0
- package/components/ui/toast.tsx +250 -0
- package/components/ui/tooltip.stories.tsx +146 -0
- package/components/ui/tooltip.tsx +156 -0
- package/components/ui/top-bar.stories.tsx +182 -0
- package/components/ui/top-bar.tsx +155 -0
- package/dist/components/ui/accordion.d.ts +45 -0
- package/dist/components/ui/accordion.d.ts.map +1 -0
- package/dist/components/ui/accordion.js +99 -0
- package/dist/components/ui/accordion.js.map +1 -0
- package/dist/components/ui/app-shell.d.ts +70 -0
- package/dist/components/ui/app-shell.d.ts.map +1 -0
- package/dist/components/ui/app-shell.js +199 -0
- package/dist/components/ui/app-shell.js.map +1 -0
- package/dist/components/ui/avatar.d.ts +41 -0
- package/dist/components/ui/avatar.d.ts.map +1 -0
- package/dist/components/ui/avatar.js +104 -0
- package/dist/components/ui/avatar.js.map +1 -0
- package/dist/components/ui/badge.d.ts +27 -0
- package/dist/components/ui/badge.d.ts.map +1 -0
- package/dist/components/ui/badge.js +65 -0
- package/dist/components/ui/badge.js.map +1 -0
- package/dist/components/ui/breadcrumb.d.ts +35 -0
- package/dist/components/ui/breadcrumb.d.ts.map +1 -0
- package/dist/components/ui/breadcrumb.js +88 -0
- package/dist/components/ui/breadcrumb.js.map +1 -0
- package/dist/components/ui/button.d.ts +26 -0
- package/dist/components/ui/button.d.ts.map +1 -0
- package/dist/components/ui/button.js +73 -0
- package/dist/components/ui/button.js.map +1 -0
- package/dist/components/ui/card.d.ts +52 -0
- package/dist/components/ui/card.d.ts.map +1 -0
- package/dist/components/ui/card.js +96 -0
- package/dist/components/ui/card.js.map +1 -0
- package/dist/components/ui/checkbox.d.ts +18 -0
- package/dist/components/ui/checkbox.d.ts.map +1 -0
- package/dist/components/ui/checkbox.js +59 -0
- package/dist/components/ui/checkbox.js.map +1 -0
- package/dist/components/ui/combobox.d.ts +194 -0
- package/dist/components/ui/combobox.d.ts.map +1 -0
- package/dist/components/ui/combobox.js +361 -0
- package/dist/components/ui/combobox.js.map +1 -0
- package/dist/components/ui/context-menu.d.ts +46 -0
- package/dist/components/ui/context-menu.d.ts.map +1 -0
- package/dist/components/ui/context-menu.js +95 -0
- package/dist/components/ui/context-menu.js.map +1 -0
- package/dist/components/ui/data-table.d.ts +53 -0
- package/dist/components/ui/data-table.d.ts.map +1 -0
- package/dist/components/ui/data-table.js +163 -0
- package/dist/components/ui/data-table.js.map +1 -0
- package/dist/components/ui/date-picker.d.ts +103 -0
- package/dist/components/ui/date-picker.d.ts.map +1 -0
- package/dist/components/ui/date-picker.js +306 -0
- package/dist/components/ui/date-picker.js.map +1 -0
- package/dist/components/ui/dialog.d.ts +40 -0
- package/dist/components/ui/dialog.d.ts.map +1 -0
- package/dist/components/ui/dialog.js +110 -0
- package/dist/components/ui/dialog.js.map +1 -0
- package/dist/components/ui/divider.d.ts +30 -0
- package/dist/components/ui/divider.d.ts.map +1 -0
- package/dist/components/ui/divider.js +62 -0
- package/dist/components/ui/divider.js.map +1 -0
- package/dist/components/ui/drawer.d.ts +56 -0
- package/dist/components/ui/drawer.d.ts.map +1 -0
- package/dist/components/ui/drawer.js +147 -0
- package/dist/components/ui/drawer.js.map +1 -0
- package/dist/components/ui/dropdown-menu.d.ts +63 -0
- package/dist/components/ui/dropdown-menu.d.ts.map +1 -0
- package/dist/components/ui/dropdown-menu.js +116 -0
- package/dist/components/ui/dropdown-menu.js.map +1 -0
- package/dist/components/ui/empty-state.d.ts +43 -0
- package/dist/components/ui/empty-state.d.ts.map +1 -0
- package/dist/components/ui/empty-state.js +128 -0
- package/dist/components/ui/empty-state.js.map +1 -0
- package/dist/components/ui/field-group.d.ts +38 -0
- package/dist/components/ui/field-group.d.ts.map +1 -0
- package/dist/components/ui/field-group.js +107 -0
- package/dist/components/ui/field-group.js.map +1 -0
- package/dist/components/ui/form.d.ts +67 -0
- package/dist/components/ui/form.d.ts.map +1 -0
- package/dist/components/ui/form.js +286 -0
- package/dist/components/ui/form.js.map +1 -0
- package/dist/components/ui/input.d.ts +36 -0
- package/dist/components/ui/input.d.ts.map +1 -0
- package/dist/components/ui/input.js +99 -0
- package/dist/components/ui/input.js.map +1 -0
- package/dist/components/ui/label.d.ts +37 -0
- package/dist/components/ui/label.d.ts.map +1 -0
- package/dist/components/ui/label.js +34 -0
- package/dist/components/ui/label.js.map +1 -0
- package/dist/components/ui/page-header.d.ts +65 -0
- package/dist/components/ui/page-header.d.ts.map +1 -0
- package/dist/components/ui/page-header.js +140 -0
- package/dist/components/ui/page-header.js.map +1 -0
- package/dist/components/ui/pagination.d.ts +67 -0
- package/dist/components/ui/pagination.d.ts.map +1 -0
- package/dist/components/ui/pagination.js +109 -0
- package/dist/components/ui/pagination.js.map +1 -0
- package/dist/components/ui/popover.d.ts +28 -0
- package/dist/components/ui/popover.d.ts.map +1 -0
- package/dist/components/ui/popover.js +85 -0
- package/dist/components/ui/popover.js.map +1 -0
- package/dist/components/ui/radio-group.d.ts +35 -0
- package/dist/components/ui/radio-group.d.ts.map +1 -0
- package/dist/components/ui/radio-group.js +103 -0
- package/dist/components/ui/radio-group.js.map +1 -0
- package/dist/components/ui/select.d.ts +42 -0
- package/dist/components/ui/select.d.ts.map +1 -0
- package/dist/components/ui/select.js +86 -0
- package/dist/components/ui/select.js.map +1 -0
- package/dist/components/ui/sidebar.d.ts +59 -0
- package/dist/components/ui/sidebar.d.ts.map +1 -0
- package/dist/components/ui/sidebar.js +189 -0
- package/dist/components/ui/sidebar.js.map +1 -0
- package/dist/components/ui/skeleton.d.ts +77 -0
- package/dist/components/ui/skeleton.d.ts.map +1 -0
- package/dist/components/ui/skeleton.js +115 -0
- package/dist/components/ui/skeleton.js.map +1 -0
- package/dist/components/ui/switch.d.ts +26 -0
- package/dist/components/ui/switch.d.ts.map +1 -0
- package/dist/components/ui/switch.js +84 -0
- package/dist/components/ui/switch.js.map +1 -0
- package/dist/components/ui/table.d.ts +52 -0
- package/dist/components/ui/table.d.ts.map +1 -0
- package/dist/components/ui/table.js +109 -0
- package/dist/components/ui/table.js.map +1 -0
- package/dist/components/ui/tabs.d.ts +42 -0
- package/dist/components/ui/tabs.d.ts.map +1 -0
- package/dist/components/ui/tabs.js +163 -0
- package/dist/components/ui/tabs.js.map +1 -0
- package/dist/components/ui/textarea.d.ts +26 -0
- package/dist/components/ui/textarea.d.ts.map +1 -0
- package/dist/components/ui/textarea.js +96 -0
- package/dist/components/ui/textarea.js.map +1 -0
- package/dist/components/ui/toast.d.ts +77 -0
- package/dist/components/ui/toast.d.ts.map +1 -0
- package/dist/components/ui/toast.js +141 -0
- package/dist/components/ui/toast.js.map +1 -0
- package/dist/components/ui/tooltip.d.ts +31 -0
- package/dist/components/ui/tooltip.d.ts.map +1 -0
- package/dist/components/ui/tooltip.js +71 -0
- package/dist/components/ui/tooltip.js.map +1 -0
- package/dist/components/ui/top-bar.d.ts +30 -0
- package/dist/components/ui/top-bar.d.ts.map +1 -0
- package/dist/components/ui/top-bar.js +64 -0
- package/dist/components/ui/top-bar.js.map +1 -0
- package/dist/lib/utils.d.ts +3 -0
- package/dist/lib/utils.d.ts.map +1 -0
- package/dist/lib/utils.js +6 -0
- package/dist/lib/utils.js.map +1 -0
- package/lib/utils.ts +6 -0
- package/package.json +112 -0
- package/styles/globals.css +685 -0
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
+
import { useEffect, useState } from "react";
|
|
4
|
+
import { RiCheckLine, RiCloseCircleLine, RiErrorWarningLine, RiInformationLine, RiLoader2Line, } from "@remixicon/react";
|
|
5
|
+
import { Toaster as SonnerToaster, toast as sonnerToast, } from "sonner";
|
|
6
|
+
import { cn } from "@/lib/utils";
|
|
7
|
+
const positionToSonner = {
|
|
8
|
+
"top-start": "top-left",
|
|
9
|
+
"top-end": "top-right",
|
|
10
|
+
"top-center": "top-center",
|
|
11
|
+
"bottom-start": "bottom-left",
|
|
12
|
+
"bottom-end": "bottom-right",
|
|
13
|
+
"bottom-center": "bottom-center",
|
|
14
|
+
};
|
|
15
|
+
/**
|
|
16
|
+
* Sonner uses `left`/`right` physical sides for positions. In RTL,
|
|
17
|
+
* `top-start` should mean visually top-right, and `top-end` should mean
|
|
18
|
+
* top-left. We resolve at runtime based on `<html dir>`.
|
|
19
|
+
*/
|
|
20
|
+
function resolveDir() {
|
|
21
|
+
if (typeof document === "undefined")
|
|
22
|
+
return "ltr";
|
|
23
|
+
return document.documentElement.dir === "rtl" ? "rtl" : "ltr";
|
|
24
|
+
}
|
|
25
|
+
function resolvePosition(p) {
|
|
26
|
+
const dir = resolveDir();
|
|
27
|
+
if (dir === "rtl") {
|
|
28
|
+
if (p === "top-start")
|
|
29
|
+
return "top-right";
|
|
30
|
+
if (p === "top-end")
|
|
31
|
+
return "top-left";
|
|
32
|
+
if (p === "bottom-start")
|
|
33
|
+
return "bottom-right";
|
|
34
|
+
if (p === "bottom-end")
|
|
35
|
+
return "bottom-left";
|
|
36
|
+
}
|
|
37
|
+
return positionToSonner[p];
|
|
38
|
+
}
|
|
39
|
+
function Toaster({ position = "bottom-end", pauseOnHover = true, closeOnClick = false, swipeToDismiss = true, maxVisible, defaultDuration = 4000, expand, gap, richColors, className, toastOptions, ...rest }) {
|
|
40
|
+
// Sonner already handles pause-on-hover, no-close-on-click, and swipe on
|
|
41
|
+
// touch natively. These props are accepted in the public API for
|
|
42
|
+
// forward-compatibility but currently have no Sonner override. The voids
|
|
43
|
+
// declare intent without leaking the props through `...rest`.
|
|
44
|
+
void pauseOnHover;
|
|
45
|
+
void closeOnClick;
|
|
46
|
+
void swipeToDismiss;
|
|
47
|
+
// Re-resolve position on dir change. Sonner's `position` is set once at
|
|
48
|
+
// mount, but consumers may flip dir at runtime — re-mount the Toaster by
|
|
49
|
+
// keying on the resolved position.
|
|
50
|
+
const [resolved, setResolved] = useState(() => resolvePosition(position));
|
|
51
|
+
useEffect(() => {
|
|
52
|
+
setResolved(resolvePosition(position));
|
|
53
|
+
if (typeof document === "undefined")
|
|
54
|
+
return;
|
|
55
|
+
const obs = new MutationObserver(() => setResolved(resolvePosition(position)));
|
|
56
|
+
obs.observe(document.documentElement, { attributes: true, attributeFilter: ["dir"] });
|
|
57
|
+
return () => obs.disconnect();
|
|
58
|
+
}, [position]);
|
|
59
|
+
// exactOptionalPropertyTypes: don't forward optional props with `undefined`.
|
|
60
|
+
const passthrough = {};
|
|
61
|
+
if (expand !== undefined)
|
|
62
|
+
passthrough.expand = expand;
|
|
63
|
+
if (gap !== undefined)
|
|
64
|
+
passthrough.gap = gap;
|
|
65
|
+
if (richColors !== undefined)
|
|
66
|
+
passthrough.richColors = richColors;
|
|
67
|
+
if (maxVisible !== undefined)
|
|
68
|
+
passthrough.visibleToasts = maxVisible;
|
|
69
|
+
return (_jsx(SonnerToaster, { position: resolved, duration: defaultDuration, closeButton: true,
|
|
70
|
+
// Anchor sonner's stack layer to the design-token --z-toast (1700) so
|
|
71
|
+
// toasts always sit above tooltips, popovers, and modals.
|
|
72
|
+
style: { zIndex: "var(--z-toast)" },
|
|
73
|
+
// Emara-tinted defaults — colors track the active theme.
|
|
74
|
+
toastOptions: {
|
|
75
|
+
...toastOptions,
|
|
76
|
+
className: cn("border border-border bg-popover text-popover-foreground shadow-md", toastOptions?.className),
|
|
77
|
+
}, className: cn(className), ...passthrough, ...rest }, resolved));
|
|
78
|
+
}
|
|
79
|
+
function variantIcon(variant) {
|
|
80
|
+
switch (variant) {
|
|
81
|
+
case "success":
|
|
82
|
+
return _jsx(RiCheckLine, { className: "text-success size-4" });
|
|
83
|
+
case "warning":
|
|
84
|
+
return _jsx(RiErrorWarningLine, { className: "text-warning size-4" });
|
|
85
|
+
case "info":
|
|
86
|
+
return _jsx(RiInformationLine, { className: "text-info size-4" });
|
|
87
|
+
case "error":
|
|
88
|
+
return _jsx(RiCloseCircleLine, { className: "text-destructive size-4" });
|
|
89
|
+
case "loading":
|
|
90
|
+
return _jsx(RiLoader2Line, { className: "size-4 animate-spin" });
|
|
91
|
+
default:
|
|
92
|
+
return undefined;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
function toSonnerOptions(options, variant) {
|
|
96
|
+
if (!options && !variant)
|
|
97
|
+
return undefined;
|
|
98
|
+
const out = {};
|
|
99
|
+
if (options?.id !== undefined)
|
|
100
|
+
out.id = options.id;
|
|
101
|
+
if (options?.description !== undefined)
|
|
102
|
+
out.description = options.description;
|
|
103
|
+
if (options?.duration !== undefined)
|
|
104
|
+
out.duration = options.duration;
|
|
105
|
+
if (options?.action)
|
|
106
|
+
out.action = options.action;
|
|
107
|
+
if (options?.cancel)
|
|
108
|
+
out.cancel = options.cancel;
|
|
109
|
+
if (options?.dismissible !== undefined)
|
|
110
|
+
out.dismissible = options.dismissible;
|
|
111
|
+
if (options?.icon !== undefined) {
|
|
112
|
+
out.icon = options.icon;
|
|
113
|
+
}
|
|
114
|
+
else if (variant && variant !== "default") {
|
|
115
|
+
out.icon = variantIcon(variant);
|
|
116
|
+
}
|
|
117
|
+
return out;
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* `toast(message, options)` and its variant-shortcut siblings. Wraps sonner's
|
|
121
|
+
* imperative API so consumers don't import sonner directly.
|
|
122
|
+
*/
|
|
123
|
+
function toastBase(message, options) {
|
|
124
|
+
return sonnerToast(message, toSonnerOptions(options, "default"));
|
|
125
|
+
}
|
|
126
|
+
const toast = Object.assign(toastBase, {
|
|
127
|
+
success: (message, options) => sonnerToast.success(message, toSonnerOptions(options, "success")),
|
|
128
|
+
warning: (message, options) => sonnerToast.warning(message, toSonnerOptions(options, "warning")),
|
|
129
|
+
info: (message, options) => sonnerToast.info(message, toSonnerOptions(options, "info")),
|
|
130
|
+
error: (message, options) => sonnerToast.error(message, toSonnerOptions(options, "error")),
|
|
131
|
+
loading: (message, options) => sonnerToast.loading(message, toSonnerOptions(options, "loading")),
|
|
132
|
+
promise: (promise, msgs) => sonnerToast.promise(promise, {
|
|
133
|
+
loading: msgs.loading,
|
|
134
|
+
success: msgs.success,
|
|
135
|
+
error: msgs.error,
|
|
136
|
+
}),
|
|
137
|
+
dismiss: (id) => sonnerToast.dismiss(id),
|
|
138
|
+
custom: sonnerToast.custom,
|
|
139
|
+
});
|
|
140
|
+
export { Toaster, toast };
|
|
141
|
+
//# sourceMappingURL=toast.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"toast.js","sourceRoot":"","sources":["../../../components/ui/toast.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import * as TooltipPrimitive from "@radix-ui/react-tooltip";
|
|
2
|
+
import { type VariantProps } from "class-variance-authority";
|
|
3
|
+
declare const TooltipProvider: import("react").FC<TooltipPrimitive.TooltipProviderProps>;
|
|
4
|
+
declare const Tooltip: import("react").FC<TooltipPrimitive.TooltipProps>;
|
|
5
|
+
declare const TooltipTrigger: import("react").ForwardRefExoticComponent<TooltipPrimitive.TooltipTriggerProps & import("react").RefAttributes<HTMLButtonElement>>;
|
|
6
|
+
declare const tooltipContentVariants: (props?: ({
|
|
7
|
+
variant?: "default" | "kbd" | "inverse" | null | undefined;
|
|
8
|
+
multiline?: boolean | null | undefined;
|
|
9
|
+
} & import("class-variance-authority/types").ClassProp) | undefined) => string;
|
|
10
|
+
type TooltipContentProps = React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Content> & VariantProps<typeof tooltipContentVariants> & {
|
|
11
|
+
/** Cap width when `multiline` is true (or just for sizing in general). */
|
|
12
|
+
maxWidth?: number | string;
|
|
13
|
+
/** When set, renders the children as keyboard-shortcut key caps. Wraps each token in a `<kbd>` element with a styled appearance. */
|
|
14
|
+
kbd?: string[];
|
|
15
|
+
/** Default `true`. Set to `false` to hide the arrow. */
|
|
16
|
+
arrow?: boolean;
|
|
17
|
+
};
|
|
18
|
+
declare const TooltipContent: import("react").ForwardRefExoticComponent<Omit<TooltipPrimitive.TooltipContentProps & import("react").RefAttributes<HTMLDivElement>, "ref"> & VariantProps<(props?: ({
|
|
19
|
+
variant?: "default" | "kbd" | "inverse" | null | undefined;
|
|
20
|
+
multiline?: boolean | null | undefined;
|
|
21
|
+
} & import("class-variance-authority/types").ClassProp) | undefined) => string> & {
|
|
22
|
+
/** Cap width when `multiline` is true (or just for sizing in general). */
|
|
23
|
+
maxWidth?: number | string;
|
|
24
|
+
/** When set, renders the children as keyboard-shortcut key caps. Wraps each token in a `<kbd>` element with a styled appearance. */
|
|
25
|
+
kbd?: string[];
|
|
26
|
+
/** Default `true`. Set to `false` to hide the arrow. */
|
|
27
|
+
arrow?: boolean;
|
|
28
|
+
} & import("react").RefAttributes<HTMLDivElement>>;
|
|
29
|
+
export { TooltipProvider, Tooltip, TooltipTrigger, TooltipContent, tooltipContentVariants };
|
|
30
|
+
export type { TooltipContentProps };
|
|
31
|
+
//# sourceMappingURL=tooltip.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tooltip.d.ts","sourceRoot":"","sources":["../../../components/ui/tooltip.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,gBAAgB,MAAM,yBAAyB,CAAC;AAC5D,OAAO,EAAO,KAAK,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAYlE,QAAA,MAAM,eAAe,2DAA4B,CAAC;AAMlD,QAAA,MAAM,OAAO,mDAAwB,CAAC;AACtC,QAAA,MAAM,cAAc,oIAA2B,CAAC;AAMhD,QAAA,MAAM,sBAAsB;;;8EA6B3B,CAAC;AAQF,KAAK,mBAAmB,GAAG,KAAK,CAAC,wBAAwB,CAAC,OAAO,gBAAgB,CAAC,OAAO,CAAC,GACxF,YAAY,CAAC,OAAO,sBAAsB,CAAC,GAAG;IAC5C,0EAA0E;IAC1E,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC3B,oIAAoI;IACpI,GAAG,CAAC,EAAE,MAAM,EAAE,CAAC;IACf,wDAAwD;IACxD,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB,CAAC;AAcJ,QAAA,MAAM,cAAc;;;;IApBhB,0EAA0E;eAC/D,MAAM,GAAG,MAAM;IAC1B,oIAAoI;UAC9H,MAAM,EAAE;IACd,wDAAwD;YAChD,OAAO;kDA8EjB,CAAC;AAGH,OAAO,EAAE,eAAe,EAAE,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,sBAAsB,EAAE,CAAC;AAC5F,YAAY,EAAE,mBAAmB,EAAE,CAAC"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { forwardRef } from "react";
|
|
4
|
+
import * as TooltipPrimitive from "@radix-ui/react-tooltip";
|
|
5
|
+
import { cva } from "class-variance-authority";
|
|
6
|
+
import { cn } from "@/lib/utils";
|
|
7
|
+
// Per docs/emara-ui-phase-3-components.md §4. Brought forward into v0.1 per
|
|
8
|
+
// docs/emara-ui-implementation-plan.md §5.
|
|
9
|
+
// ----------------------------------------------------------------------------
|
|
10
|
+
// TooltipProvider — typically wraps the app once. Re-export so consumers
|
|
11
|
+
// don't have to import from Radix directly.
|
|
12
|
+
// ----------------------------------------------------------------------------
|
|
13
|
+
const TooltipProvider = TooltipPrimitive.Provider;
|
|
14
|
+
// ----------------------------------------------------------------------------
|
|
15
|
+
// Tooltip root — Radix props passthrough.
|
|
16
|
+
// ----------------------------------------------------------------------------
|
|
17
|
+
const Tooltip = TooltipPrimitive.Root;
|
|
18
|
+
const TooltipTrigger = TooltipPrimitive.Trigger;
|
|
19
|
+
// ----------------------------------------------------------------------------
|
|
20
|
+
// TooltipContent
|
|
21
|
+
// ----------------------------------------------------------------------------
|
|
22
|
+
const tooltipContentVariants = cva([
|
|
23
|
+
"z-tooltip select-none px-2 py-1 text-xs leading-snug rounded-md shadow-md",
|
|
24
|
+
// Animations driven by Radix data-state. Side-specific slide-in.
|
|
25
|
+
"data-[state=delayed-open]:animate-[scale-in_var(--duration-fast)_var(--ease-out)]",
|
|
26
|
+
"data-[state=closed]:animate-[scale-out_var(--duration-fast)_var(--ease-in)]",
|
|
27
|
+
"data-[side=top]:data-[state=delayed-open]:animate-[slide-in-from-bottom_var(--duration-fast)_var(--ease-out)]",
|
|
28
|
+
"data-[side=bottom]:data-[state=delayed-open]:animate-[slide-in-from-top_var(--duration-fast)_var(--ease-out)]",
|
|
29
|
+
"data-[side=left]:data-[state=delayed-open]:animate-[slide-in-from-end_var(--duration-fast)_var(--ease-out)]",
|
|
30
|
+
"data-[side=right]:data-[state=delayed-open]:animate-[slide-in-from-start_var(--duration-fast)_var(--ease-out)]",
|
|
31
|
+
].join(" "), {
|
|
32
|
+
variants: {
|
|
33
|
+
variant: {
|
|
34
|
+
// Dark bubble against any surface — classic tooltip.
|
|
35
|
+
default: "bg-foreground text-background",
|
|
36
|
+
// Inverse — light bubble for dark contexts (e.g. dark sidebar).
|
|
37
|
+
inverse: "bg-background text-foreground border border-border",
|
|
38
|
+
// Keyboard-shortcut style — uses kbd key caps inside.
|
|
39
|
+
kbd: "bg-foreground text-background font-mono",
|
|
40
|
+
},
|
|
41
|
+
multiline: {
|
|
42
|
+
// Single-line tooltip truncates; multi-line wraps within maxWidth.
|
|
43
|
+
true: "whitespace-normal",
|
|
44
|
+
false: "whitespace-nowrap",
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
defaultVariants: { variant: "default", multiline: false },
|
|
48
|
+
});
|
|
49
|
+
const arrowFillClass = {
|
|
50
|
+
default: "fill-foreground",
|
|
51
|
+
inverse: "fill-background",
|
|
52
|
+
kbd: "fill-foreground",
|
|
53
|
+
};
|
|
54
|
+
function Kbd({ k }) {
|
|
55
|
+
// `min-w-[1.25em]` is intentionally em-relative (not a Tailwind spacing
|
|
56
|
+
// token): kbd keys scale with the surrounding text size, and the visual
|
|
57
|
+
// contract is "always at least one character wide" — that's an em-bound
|
|
58
|
+
// measurement, not a px one. Per design-tokens §4.2 sub-canonical note.
|
|
59
|
+
return (_jsx("kbd", { className: "border-background/30 bg-background/10 inline-block min-w-[1.25em] rounded border px-1 text-center font-mono text-[10px] leading-tight", children: k }));
|
|
60
|
+
}
|
|
61
|
+
const TooltipContent = forwardRef(function TooltipContent({ className, variant, multiline, maxWidth, kbd, arrow = true, sideOffset = 6, style, children, ...props }, ref) {
|
|
62
|
+
const resolvedVariant = variant ?? (kbd ? "kbd" : "default");
|
|
63
|
+
const widthStyle = maxWidth !== undefined
|
|
64
|
+
? { maxWidth: typeof maxWidth === "number" ? `${maxWidth}px` : maxWidth }
|
|
65
|
+
: undefined;
|
|
66
|
+
const body = kbd ? (_jsxs("span", { className: "inline-flex items-center gap-1", children: [children ? (_jsxs(_Fragment, { children: [_jsx("span", { children: children }), _jsx("span", { className: "opacity-70", children: "\u00B7" })] })) : null, kbd.map((k, i) => (_jsxs("span", { className: "inline-flex items-center gap-0.5", children: [i > 0 ? _jsx("span", { className: "opacity-70", children: "+" }) : null, _jsx(Kbd, { k: k })] }, `${k}-${i}`)))] })) : (children);
|
|
67
|
+
return (_jsx(TooltipPrimitive.Portal, { children: _jsxs(TooltipPrimitive.Content, { ref: ref, sideOffset: sideOffset, style: { ...widthStyle, ...style }, className: cn(tooltipContentVariants({ variant: resolvedVariant, multiline }), className), ...props, children: [body, arrow ? (_jsx(TooltipPrimitive.Arrow, { width: 10, height: 5, className: cn(arrowFillClass[resolvedVariant]) })) : null] }) }));
|
|
68
|
+
});
|
|
69
|
+
TooltipContent.displayName = "TooltipContent";
|
|
70
|
+
export { TooltipProvider, Tooltip, TooltipTrigger, TooltipContent, tooltipContentVariants };
|
|
71
|
+
//# sourceMappingURL=tooltip.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tooltip.js","sourceRoot":"","sources":["../../../components/ui/tooltip.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { type VariantProps } from "class-variance-authority";
|
|
2
|
+
declare const topBarVariants: (props?: ({
|
|
3
|
+
variant?: "default" | "transparent" | "elevated" | null | undefined;
|
|
4
|
+
size?: "sm" | "md" | "lg" | null | undefined;
|
|
5
|
+
sticky?: boolean | null | undefined;
|
|
6
|
+
bordered?: boolean | null | undefined;
|
|
7
|
+
} & import("class-variance-authority/types").ClassProp) | undefined) => string;
|
|
8
|
+
type TopBarVariants = VariantProps<typeof topBarVariants>;
|
|
9
|
+
type TopBarProps = Omit<React.HTMLAttributes<HTMLElement>, "size"> & TopBarVariants & {
|
|
10
|
+
asChild?: boolean;
|
|
11
|
+
/** Override the rendered element. Default `<header>`. */
|
|
12
|
+
as?: "header" | "div";
|
|
13
|
+
};
|
|
14
|
+
declare const TopBar: import("react").ForwardRefExoticComponent<Omit<import("react").HTMLAttributes<HTMLElement>, "size"> & TopBarVariants & {
|
|
15
|
+
asChild?: boolean;
|
|
16
|
+
/** Override the rendered element. Default `<header>`. */
|
|
17
|
+
as?: "header" | "div";
|
|
18
|
+
} & import("react").RefAttributes<HTMLElement>>;
|
|
19
|
+
declare const TopBarStart: import("react").ForwardRefExoticComponent<import("react").HTMLAttributes<HTMLDivElement> & import("react").RefAttributes<HTMLDivElement>>;
|
|
20
|
+
declare const TopBarCenter: import("react").ForwardRefExoticComponent<import("react").HTMLAttributes<HTMLDivElement> & import("react").RefAttributes<HTMLDivElement>>;
|
|
21
|
+
declare const TopBarEnd: import("react").ForwardRefExoticComponent<import("react").HTMLAttributes<HTMLDivElement> & import("react").RefAttributes<HTMLDivElement>>;
|
|
22
|
+
type TopBarBrandProps = React.HTMLAttributes<HTMLDivElement> & {
|
|
23
|
+
asChild?: boolean;
|
|
24
|
+
};
|
|
25
|
+
declare const TopBarBrand: import("react").ForwardRefExoticComponent<import("react").HTMLAttributes<HTMLDivElement> & {
|
|
26
|
+
asChild?: boolean;
|
|
27
|
+
} & import("react").RefAttributes<HTMLDivElement>>;
|
|
28
|
+
export { TopBar, TopBarStart, TopBarCenter, TopBarEnd, TopBarBrand, topBarVariants };
|
|
29
|
+
export type { TopBarProps, TopBarBrandProps };
|
|
30
|
+
//# sourceMappingURL=top-bar.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"top-bar.d.ts","sourceRoot":"","sources":["../../../components/ui/top-bar.tsx"],"names":[],"mappings":"AAIA,OAAO,EAAO,KAAK,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAQlE,QAAA,MAAM,cAAc;;;;;8EA4BlB,CAAC;AAEH,KAAK,cAAc,GAAG,YAAY,CAAC,OAAO,cAAc,CAAC,CAAC;AAE1D,KAAK,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC,GAChE,cAAc,GAAG;IACf,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,yDAAyD;IACzD,EAAE,CAAC,EAAE,QAAQ,GAAG,KAAK,CAAC;CACvB,CAAC;AAEJ,QAAA,MAAM,MAAM;cALE,OAAO;IACjB,yDAAyD;SACpD,QAAQ,GAAG,KAAK;+CA0BvB,CAAC;AAKH,QAAA,MAAM,WAAW,2IAWhB,CAAC;AAGF,QAAA,MAAM,YAAY,2IAiBjB,CAAC;AAGF,QAAA,MAAM,SAAS,2IAWd,CAAC;AAKF,KAAK,gBAAgB,GAAG,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC,GAAG;IAC7D,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB,CAAC;AAEF,QAAA,MAAM,WAAW;cAHL,OAAO;kDAoBjB,CAAC;AAGH,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,YAAY,EAAE,SAAS,EAAE,WAAW,EAAE,cAAc,EAAE,CAAC;AACrF,YAAY,EAAE,WAAW,EAAE,gBAAgB,EAAE,CAAC"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
+
import { forwardRef } from "react";
|
|
4
|
+
import { Slot } from "@radix-ui/react-slot";
|
|
5
|
+
import { cva } from "class-variance-authority";
|
|
6
|
+
import { cn } from "@/lib/utils";
|
|
7
|
+
// Per docs/emara-ui-phase-5-components.md §3.
|
|
8
|
+
// --- Root -------------------------------------------------------------------
|
|
9
|
+
const topBarVariants = cva("flex w-full items-center bg-background text-foreground", {
|
|
10
|
+
variants: {
|
|
11
|
+
variant: {
|
|
12
|
+
default: "border-b border-border",
|
|
13
|
+
elevated: "shadow-sm",
|
|
14
|
+
transparent: "bg-transparent",
|
|
15
|
+
},
|
|
16
|
+
size: {
|
|
17
|
+
// Heights match the AppShell `header-sm|md|lg` tokens.
|
|
18
|
+
sm: "h-12 px-3",
|
|
19
|
+
md: "h-14 px-4",
|
|
20
|
+
lg: "h-16 px-5",
|
|
21
|
+
},
|
|
22
|
+
sticky: {
|
|
23
|
+
true: "sticky top-0 z-sticky",
|
|
24
|
+
false: "",
|
|
25
|
+
},
|
|
26
|
+
bordered: {
|
|
27
|
+
true: "border-b border-border",
|
|
28
|
+
false: "",
|
|
29
|
+
},
|
|
30
|
+
},
|
|
31
|
+
defaultVariants: {
|
|
32
|
+
variant: "default",
|
|
33
|
+
size: "md",
|
|
34
|
+
sticky: false,
|
|
35
|
+
bordered: false,
|
|
36
|
+
},
|
|
37
|
+
});
|
|
38
|
+
const TopBar = forwardRef(function TopBar({ className, variant = "default", size = "md", sticky = false, bordered = false, asChild = false, as = "header", ...props }, ref) {
|
|
39
|
+
const Comp = (asChild ? Slot : as);
|
|
40
|
+
return (_jsx(Comp, { ref: ref, "data-slot": "top-bar", role: as === "header" && !asChild ? "banner" : undefined, className: cn(topBarVariants({ variant, size, sticky, bordered }), className), ...props }));
|
|
41
|
+
});
|
|
42
|
+
TopBar.displayName = "TopBar";
|
|
43
|
+
// --- Slots ------------------------------------------------------------------
|
|
44
|
+
const TopBarStart = forwardRef(function TopBarStart({ className, ...props }, ref) {
|
|
45
|
+
return (_jsx("div", { ref: ref, "data-slot": "top-bar-start", className: cn("me-auto flex min-w-0 items-center gap-2", className), ...props }));
|
|
46
|
+
});
|
|
47
|
+
TopBarStart.displayName = "TopBarStart";
|
|
48
|
+
const TopBarCenter = forwardRef(function TopBarCenter({ className, role, ...props }, ref) {
|
|
49
|
+
return (_jsx("div", { ref: ref, "data-slot": "top-bar-center",
|
|
50
|
+
// Hides on narrow viewports — consumers can override.
|
|
51
|
+
className: cn("hidden min-w-0 flex-1 items-center justify-center gap-2 px-3 md:flex", className), ...(role ? { role } : {}), ...props }));
|
|
52
|
+
});
|
|
53
|
+
TopBarCenter.displayName = "TopBarCenter";
|
|
54
|
+
const TopBarEnd = forwardRef(function TopBarEnd({ className, ...props }, ref) {
|
|
55
|
+
return (_jsx("div", { ref: ref, "data-slot": "top-bar-end", className: cn("ms-auto flex items-center gap-2", className), ...props }));
|
|
56
|
+
});
|
|
57
|
+
TopBarEnd.displayName = "TopBarEnd";
|
|
58
|
+
const TopBarBrand = forwardRef(function TopBarBrand({ className, asChild = false, ...props }, ref) {
|
|
59
|
+
const Comp = asChild ? Slot : "div";
|
|
60
|
+
return (_jsx(Comp, { ref: ref, "data-slot": "top-bar-brand", className: cn("text-foreground inline-flex items-center gap-2 font-semibold", "[&_svg]:size-5 [&_svg]:shrink-0", className), ...props }));
|
|
61
|
+
});
|
|
62
|
+
TopBarBrand.displayName = "TopBarBrand";
|
|
63
|
+
export { TopBar, TopBarStart, TopBarCenter, TopBarEnd, TopBarBrand, topBarVariants };
|
|
64
|
+
//# sourceMappingURL=top-bar.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"top-bar.js","sourceRoot":"","sources":["../../../components/ui/top-bar.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../lib/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAQ,KAAK,UAAU,EAAE,MAAM,MAAM,CAAC;AAG7C,wBAAgB,EAAE,CAAC,GAAG,MAAM,EAAE,UAAU,EAAE,GAAG,MAAM,CAElD"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../lib/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAmB,MAAM,MAAM,CAAC;AAC7C,OAAO,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAEzC,MAAM,UAAU,EAAE,CAAC,GAAG,MAAoB;IACxC,OAAO,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC;AAC/B,CAAC"}
|
package/lib/utils.ts
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@emara/ui",
|
|
3
|
+
"version": "1.1.0",
|
|
4
|
+
"description": "Emara UI — React component library. Canonical install path is `npx @emara/cli add <name>` (shadcn-style copy-paste); direct package install is supported as an alternate path.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"emara",
|
|
7
|
+
"emara-ui",
|
|
8
|
+
"shadcn",
|
|
9
|
+
"react",
|
|
10
|
+
"react-19",
|
|
11
|
+
"tailwind",
|
|
12
|
+
"tailwind-v4",
|
|
13
|
+
"components",
|
|
14
|
+
"rtl",
|
|
15
|
+
"radix",
|
|
16
|
+
"ui"
|
|
17
|
+
],
|
|
18
|
+
"homepage": "https://github.com/abdelkader-zaglou/emara-ui#readme",
|
|
19
|
+
"bugs": {
|
|
20
|
+
"url": "https://github.com/abdelkader-zaglou/emara-ui/issues"
|
|
21
|
+
},
|
|
22
|
+
"repository": {
|
|
23
|
+
"type": "git",
|
|
24
|
+
"url": "git+https://github.com/abdelkader-zaglou/emara-ui.git",
|
|
25
|
+
"directory": "packages/ui"
|
|
26
|
+
},
|
|
27
|
+
"license": "MIT",
|
|
28
|
+
"author": "Abdelkader Zaglou",
|
|
29
|
+
"type": "module",
|
|
30
|
+
"sideEffects": [
|
|
31
|
+
"**/*.css"
|
|
32
|
+
],
|
|
33
|
+
"files": [
|
|
34
|
+
"dist",
|
|
35
|
+
"components",
|
|
36
|
+
"lib",
|
|
37
|
+
"styles",
|
|
38
|
+
"README.md"
|
|
39
|
+
],
|
|
40
|
+
"publishConfig": {
|
|
41
|
+
"access": "public",
|
|
42
|
+
"registry": "https://registry.npmjs.org/"
|
|
43
|
+
},
|
|
44
|
+
"exports": {
|
|
45
|
+
"./styles/globals.css": "./styles/globals.css",
|
|
46
|
+
"./lib/utils": {
|
|
47
|
+
"types": "./lib/utils.ts",
|
|
48
|
+
"import": "./lib/utils.ts"
|
|
49
|
+
}
|
|
50
|
+
},
|
|
51
|
+
"scripts": {
|
|
52
|
+
"build": "tsc -p tsconfig.build.json",
|
|
53
|
+
"typecheck": "tsc --noEmit",
|
|
54
|
+
"lint": "eslint . --max-warnings 0",
|
|
55
|
+
"lint:fix": "eslint . --fix",
|
|
56
|
+
"test": "vitest run",
|
|
57
|
+
"test:watch": "vitest"
|
|
58
|
+
},
|
|
59
|
+
"peerDependencies": {
|
|
60
|
+
"react": ">=19.0.0",
|
|
61
|
+
"react-dom": ">=19.0.0",
|
|
62
|
+
"react-hook-form": ">=7.50.0"
|
|
63
|
+
},
|
|
64
|
+
"peerDependenciesMeta": {
|
|
65
|
+
"react-hook-form": {
|
|
66
|
+
"optional": true
|
|
67
|
+
}
|
|
68
|
+
},
|
|
69
|
+
"dependencies": {
|
|
70
|
+
"@radix-ui/react-avatar": "^1.1.0",
|
|
71
|
+
"@radix-ui/react-checkbox": "^1.1.0",
|
|
72
|
+
"@radix-ui/react-context-menu": "^2.2.0",
|
|
73
|
+
"@radix-ui/react-dialog": "^1.1.0",
|
|
74
|
+
"@radix-ui/react-dropdown-menu": "^2.1.0",
|
|
75
|
+
"@radix-ui/react-label": "^2.1.0",
|
|
76
|
+
"@radix-ui/react-popover": "^1.1.0",
|
|
77
|
+
"@radix-ui/react-radio-group": "^1.2.0",
|
|
78
|
+
"@radix-ui/react-select": "^2.1.0",
|
|
79
|
+
"@radix-ui/react-separator": "^1.1.0",
|
|
80
|
+
"@radix-ui/react-accordion": "^1.2.0",
|
|
81
|
+
"@radix-ui/react-collapsible": "^1.1.0",
|
|
82
|
+
"@radix-ui/react-slot": "^1.2.0",
|
|
83
|
+
"@radix-ui/react-tabs": "^1.1.0",
|
|
84
|
+
"@tanstack/react-table": "^8.20.0",
|
|
85
|
+
"@radix-ui/react-switch": "^1.1.0",
|
|
86
|
+
"@radix-ui/react-tooltip": "^1.2.0",
|
|
87
|
+
"@remixicon/react": "^4.9.0",
|
|
88
|
+
"class-variance-authority": "^0.7.1",
|
|
89
|
+
"clsx": "^2.1.1",
|
|
90
|
+
"cmdk": "^1.1.0",
|
|
91
|
+
"date-fns": "^4.1.0",
|
|
92
|
+
"react-day-picker": "^9.4.0",
|
|
93
|
+
"sonner": "^2.0.0",
|
|
94
|
+
"tailwind-merge": "^3.6.0"
|
|
95
|
+
},
|
|
96
|
+
"devDependencies": {
|
|
97
|
+
"@emara/eslint-plugin": "workspace:*",
|
|
98
|
+
"@storybook/react-vite": "^10.4.0",
|
|
99
|
+
"@testing-library/jest-dom": "^6.9.0",
|
|
100
|
+
"@testing-library/react": "^16.3.0",
|
|
101
|
+
"@testing-library/user-event": "^14.6.0",
|
|
102
|
+
"@types/react": "^19.2.0",
|
|
103
|
+
"@types/react-dom": "^19.2.0",
|
|
104
|
+
"jsdom": "^29.1.0",
|
|
105
|
+
"react": "^19.2.0",
|
|
106
|
+
"react-dom": "^19.2.0",
|
|
107
|
+
"react-hook-form": "^7.55.0",
|
|
108
|
+
"storybook": "^10.4.0",
|
|
109
|
+
"tailwindcss": "^4.3.0",
|
|
110
|
+
"vitest": "^4.1.0"
|
|
111
|
+
}
|
|
112
|
+
}
|