@comitor/ui 0.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/LICENSE +21 -0
- package/README.md +458 -0
- package/dist/chart/chart.d.ts +88 -0
- package/dist/chart/chart.js +199 -0
- package/dist/chart/chart.js.map +1 -0
- package/dist/chart/comitor-chart.d.ts +109 -0
- package/dist/chart/comitor-chart.js +189 -0
- package/dist/chart/comitor-chart.js.map +1 -0
- package/dist/chart/index.d.ts +4 -0
- package/dist/chart/index.js +3 -0
- package/dist/chart/index.js.map +1 -0
- package/dist/components/composite/avatar-group.d.ts +33 -0
- package/dist/components/composite/avatar-group.js +86 -0
- package/dist/components/composite/avatar-group.js.map +1 -0
- package/dist/components/composite/combobox.d.ts +70 -0
- package/dist/components/composite/combobox.js +291 -0
- package/dist/components/composite/combobox.js.map +1 -0
- package/dist/components/composite/command-palette.d.ts +56 -0
- package/dist/components/composite/command-palette.js +131 -0
- package/dist/components/composite/command-palette.js.map +1 -0
- package/dist/components/composite/confirm-dialog.d.ts +40 -0
- package/dist/components/composite/confirm-dialog.js +96 -0
- package/dist/components/composite/confirm-dialog.js.map +1 -0
- package/dist/components/composite/copy-button.d.ts +27 -0
- package/dist/components/composite/copy-button.js +80 -0
- package/dist/components/composite/copy-button.js.map +1 -0
- package/dist/components/composite/data-table.d.ts +136 -0
- package/dist/components/composite/data-table.js +300 -0
- package/dist/components/composite/data-table.js.map +1 -0
- package/dist/components/composite/date-picker.d.ts +77 -0
- package/dist/components/composite/date-picker.js +268 -0
- package/dist/components/composite/date-picker.js.map +1 -0
- package/dist/components/composite/empty-state.d.ts +38 -0
- package/dist/components/composite/empty-state.js +35 -0
- package/dist/components/composite/empty-state.js.map +1 -0
- package/dist/components/composite/filter-chips.d.ts +39 -0
- package/dist/components/composite/filter-chips.js +79 -0
- package/dist/components/composite/filter-chips.js.map +1 -0
- package/dist/components/composite/form-field.d.ts +58 -0
- package/dist/components/composite/form-field.js +81 -0
- package/dist/components/composite/form-field.js.map +1 -0
- package/dist/components/composite/form-section.d.ts +33 -0
- package/dist/components/composite/form-section.js +85 -0
- package/dist/components/composite/form-section.js.map +1 -0
- package/dist/components/composite/inline-edit.d.ts +38 -0
- package/dist/components/composite/inline-edit.js +165 -0
- package/dist/components/composite/inline-edit.js.map +1 -0
- package/dist/components/composite/keyboard-hint.d.ts +31 -0
- package/dist/components/composite/keyboard-hint.js +72 -0
- package/dist/components/composite/keyboard-hint.js.map +1 -0
- package/dist/components/composite/letter-avatar.d.ts +47 -0
- package/dist/components/composite/letter-avatar.js +66 -0
- package/dist/components/composite/letter-avatar.js.map +1 -0
- package/dist/components/composite/page-container.d.ts +25 -0
- package/dist/components/composite/page-container.js +23 -0
- package/dist/components/composite/page-container.js.map +1 -0
- package/dist/components/composite/page-header.d.ts +49 -0
- package/dist/components/composite/page-header.js +75 -0
- package/dist/components/composite/page-header.js.map +1 -0
- package/dist/components/composite/relative-time.d.ts +28 -0
- package/dist/components/composite/relative-time.js +44 -0
- package/dist/components/composite/relative-time.js.map +1 -0
- package/dist/components/composite/search-filter-bar.d.ts +38 -0
- package/dist/components/composite/search-filter-bar.js +135 -0
- package/dist/components/composite/search-filter-bar.js.map +1 -0
- package/dist/components/composite/stat-card.d.ts +48 -0
- package/dist/components/composite/stat-card.js +76 -0
- package/dist/components/composite/stat-card.js.map +1 -0
- package/dist/components/composite/status-config.d.ts +85 -0
- package/dist/components/composite/status-config.js +41 -0
- package/dist/components/composite/status-config.js.map +1 -0
- package/dist/components/composite/status-pill.d.ts +26 -0
- package/dist/components/composite/status-pill.js +59 -0
- package/dist/components/composite/status-pill.js.map +1 -0
- package/dist/components/composite/table-pagination.d.ts +31 -0
- package/dist/components/composite/table-pagination.js +103 -0
- package/dist/components/composite/table-pagination.js.map +1 -0
- package/dist/components/composite/text-utils.d.ts +38 -0
- package/dist/components/composite/text-utils.js +40 -0
- package/dist/components/composite/text-utils.js.map +1 -0
- package/dist/components/composite/toast.d.ts +56 -0
- package/dist/components/composite/toast.js +63 -0
- package/dist/components/composite/toast.js.map +1 -0
- package/dist/components/ui/accordion.d.ts +17 -0
- package/dist/components/ui/accordion.js +53 -0
- package/dist/components/ui/accordion.js.map +1 -0
- package/dist/components/ui/alert-dialog.d.ts +34 -0
- package/dist/components/ui/alert-dialog.js +103 -0
- package/dist/components/ui/alert-dialog.js.map +1 -0
- package/dist/components/ui/alert.d.ts +16 -0
- package/dist/components/ui/alert.js +50 -0
- package/dist/components/ui/alert.js.map +1 -0
- package/dist/components/ui/aspect-ratio.d.ts +7 -0
- package/dist/components/ui/aspect-ratio.js +10 -0
- package/dist/components/ui/aspect-ratio.js.map +1 -0
- package/dist/components/ui/avatar.d.ts +11 -0
- package/dist/components/ui/avatar.js +33 -0
- package/dist/components/ui/avatar.js.map +1 -0
- package/dist/components/ui/badge.d.ts +15 -0
- package/dist/components/ui/badge.js +37 -0
- package/dist/components/ui/badge.js.map +1 -0
- package/dist/components/ui/breadcrumb.d.ts +30 -0
- package/dist/components/ui/breadcrumb.js +89 -0
- package/dist/components/ui/breadcrumb.js.map +1 -0
- package/dist/components/ui/button-group.d.ts +21 -0
- package/dist/components/ui/button-group.js +62 -0
- package/dist/components/ui/button-group.js.map +1 -0
- package/dist/components/ui/button.d.ts +21 -0
- package/dist/components/ui/button.js +70 -0
- package/dist/components/ui/button.js.map +1 -0
- package/dist/components/ui/calendar.d.ts +26 -0
- package/dist/components/ui/calendar.js +148 -0
- package/dist/components/ui/calendar.js.map +1 -0
- package/dist/components/ui/card.d.ts +33 -0
- package/dist/components/ui/card.js +70 -0
- package/dist/components/ui/card.js.map +1 -0
- package/dist/components/ui/carousel.d.ts +46 -0
- package/dist/components/ui/carousel.js +173 -0
- package/dist/components/ui/carousel.js.map +1 -0
- package/dist/components/ui/checkbox.d.ts +17 -0
- package/dist/components/ui/checkbox.js +67 -0
- package/dist/components/ui/checkbox.js.map +1 -0
- package/dist/components/ui/collapsible.d.ts +17 -0
- package/dist/components/ui/collapsible.js +18 -0
- package/dist/components/ui/collapsible.js.map +1 -0
- package/dist/components/ui/command.d.ts +41 -0
- package/dist/components/ui/command.js +122 -0
- package/dist/components/ui/command.js.map +1 -0
- package/dist/components/ui/context-menu.d.ts +51 -0
- package/dist/components/ui/context-menu.js +166 -0
- package/dist/components/ui/context-menu.js.map +1 -0
- package/dist/components/ui/dialog.d.ts +48 -0
- package/dist/components/ui/dialog.js +131 -0
- package/dist/components/ui/dialog.js.map +1 -0
- package/dist/components/ui/drawer.d.ts +32 -0
- package/dist/components/ui/drawer.js +102 -0
- package/dist/components/ui/drawer.js.map +1 -0
- package/dist/components/ui/dropdown-menu.d.ts +52 -0
- package/dist/components/ui/dropdown-menu.js +167 -0
- package/dist/components/ui/dropdown-menu.js.map +1 -0
- package/dist/components/ui/empty.d.ts +22 -0
- package/dist/components/ui/empty.js +87 -0
- package/dist/components/ui/empty.js.map +1 -0
- package/dist/components/ui/field.d.ts +46 -0
- package/dist/components/ui/field.js +197 -0
- package/dist/components/ui/field.js.map +1 -0
- package/dist/components/ui/form.d.ts +50 -0
- package/dist/components/ui/form.js +100 -0
- package/dist/components/ui/form.js.map +1 -0
- package/dist/components/ui/hover-card.d.ts +17 -0
- package/dist/components/ui/hover-card.js +31 -0
- package/dist/components/ui/hover-card.js.map +1 -0
- package/dist/components/ui/input-group.d.ts +26 -0
- package/dist/components/ui/input-group.js +148 -0
- package/dist/components/ui/input-group.js.map +1 -0
- package/dist/components/ui/input-otp.d.ts +23 -0
- package/dist/components/ui/input-otp.js +54 -0
- package/dist/components/ui/input-otp.js.map +1 -0
- package/dist/components/ui/input.d.ts +21 -0
- package/dist/components/ui/input.js +62 -0
- package/dist/components/ui/input.js.map +1 -0
- package/dist/components/ui/item.d.ts +39 -0
- package/dist/components/ui/item.js +142 -0
- package/dist/components/ui/item.js.map +1 -0
- package/dist/components/ui/kbd.d.ts +8 -0
- package/dist/components/ui/kbd.js +25 -0
- package/dist/components/ui/kbd.js.map +1 -0
- package/dist/components/ui/label.d.ts +7 -0
- package/dist/components/ui/label.js +21 -0
- package/dist/components/ui/label.js.map +1 -0
- package/dist/components/ui/menubar.d.ts +51 -0
- package/dist/components/ui/menubar.js +196 -0
- package/dist/components/ui/menubar.js.map +1 -0
- package/dist/components/ui/navigation-menu.d.ts +39 -0
- package/dist/components/ui/navigation-menu.js +123 -0
- package/dist/components/ui/navigation-menu.js.map +1 -0
- package/dist/components/ui/pagination.d.ts +40 -0
- package/dist/components/ui/pagination.js +95 -0
- package/dist/components/ui/pagination.js.map +1 -0
- package/dist/components/ui/popover.d.ts +19 -0
- package/dist/components/ui/popover.js +35 -0
- package/dist/components/ui/popover.js.map +1 -0
- package/dist/components/ui/progress.d.ts +12 -0
- package/dist/components/ui/progress.js +27 -0
- package/dist/components/ui/progress.js.map +1 -0
- package/dist/components/ui/radio-group.d.ts +9 -0
- package/dist/components/ui/radio-group.js +34 -0
- package/dist/components/ui/radio-group.js.map +1 -0
- package/dist/components/ui/resizable.d.ts +19 -0
- package/dist/components/ui/resizable.js +38 -0
- package/dist/components/ui/resizable.js.map +1 -0
- package/dist/components/ui/scroll-area.d.ts +13 -0
- package/dist/components/ui/scroll-area.js +46 -0
- package/dist/components/ui/scroll-area.js.map +1 -0
- package/dist/components/ui/select.d.ts +33 -0
- package/dist/components/ui/select.js +133 -0
- package/dist/components/ui/select.js.map +1 -0
- package/dist/components/ui/separator.d.ts +7 -0
- package/dist/components/ui/separator.js +23 -0
- package/dist/components/ui/separator.js.map +1 -0
- package/dist/components/ui/sheet.d.ts +38 -0
- package/dist/components/ui/sheet.js +96 -0
- package/dist/components/ui/sheet.js.map +1 -0
- package/dist/components/ui/skeleton.d.ts +6 -0
- package/dist/components/ui/skeleton.js +9 -0
- package/dist/components/ui/skeleton.js.map +1 -0
- package/dist/components/ui/slider.d.ts +12 -0
- package/dist/components/ui/slider.js +54 -0
- package/dist/components/ui/slider.js.map +1 -0
- package/dist/components/ui/sonner.d.ts +9 -0
- package/dist/components/ui/sonner.js +25 -0
- package/dist/components/ui/sonner.js.map +1 -0
- package/dist/components/ui/spinner.d.ts +6 -0
- package/dist/components/ui/spinner.js +10 -0
- package/dist/components/ui/spinner.js.map +1 -0
- package/dist/components/ui/switch.d.ts +14 -0
- package/dist/components/ui/switch.js +65 -0
- package/dist/components/ui/switch.js.map +1 -0
- package/dist/components/ui/table.d.ts +30 -0
- package/dist/components/ui/table.js +87 -0
- package/dist/components/ui/table.js.map +1 -0
- package/dist/components/ui/tabs.d.ts +35 -0
- package/dist/components/ui/tabs.js +54 -0
- package/dist/components/ui/tabs.js.map +1 -0
- package/dist/components/ui/textarea.d.ts +6 -0
- package/dist/components/ui/textarea.js +19 -0
- package/dist/components/ui/textarea.js.map +1 -0
- package/dist/components/ui/toggle-group.d.ts +18 -0
- package/dist/components/ui/toggle-group.js +52 -0
- package/dist/components/ui/toggle-group.js.map +1 -0
- package/dist/components/ui/toggle.d.ts +15 -0
- package/dist/components/ui/toggle.js +33 -0
- package/dist/components/ui/toggle.js.map +1 -0
- package/dist/components/ui/tooltip.d.ts +21 -0
- package/dist/components/ui/tooltip.js +38 -0
- package/dist/components/ui/tooltip.js.map +1 -0
- package/dist/form.d.ts +5 -0
- package/dist/form.js +2 -0
- package/dist/form.js.map +1 -0
- package/dist/index.d.ts +111 -0
- package/dist/index.js +76 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/cn.d.ts +16 -0
- package/dist/lib/cn.js +9 -0
- package/dist/lib/cn.js.map +1 -0
- package/dist/shell/app-header.d.ts +41 -0
- package/dist/shell/app-header.js +136 -0
- package/dist/shell/app-header.js.map +1 -0
- package/dist/shell/app-launcher.d.ts +33 -0
- package/dist/shell/app-launcher.js +189 -0
- package/dist/shell/app-launcher.js.map +1 -0
- package/dist/shell/app-shell.d.ts +44 -0
- package/dist/shell/app-shell.js +99 -0
- package/dist/shell/app-shell.js.map +1 -0
- package/dist/shell/comitor-lockup.d.ts +33 -0
- package/dist/shell/comitor-lockup.js +112 -0
- package/dist/shell/comitor-lockup.js.map +1 -0
- package/dist/shell/comitor-logo.d.ts +28 -0
- package/dist/shell/comitor-logo.js +92 -0
- package/dist/shell/comitor-logo.js.map +1 -0
- package/dist/shell/index.d.ts +24 -0
- package/dist/shell/index.js +23 -0
- package/dist/shell/index.js.map +1 -0
- package/dist/shell/mobile-menu.d.ts +26 -0
- package/dist/shell/mobile-menu.js +56 -0
- package/dist/shell/mobile-menu.js.map +1 -0
- package/dist/shell/notifications-button.d.ts +22 -0
- package/dist/shell/notifications-button.js +39 -0
- package/dist/shell/notifications-button.js.map +1 -0
- package/dist/shell/shell-context.d.ts +91 -0
- package/dist/shell/shell-context.js +233 -0
- package/dist/shell/shell-context.js.map +1 -0
- package/dist/shell/shell-link.d.ts +19 -0
- package/dist/shell/shell-link.js +18 -0
- package/dist/shell/shell-link.js.map +1 -0
- package/dist/shell/sidebar-group.d.ts +21 -0
- package/dist/shell/sidebar-group.js +43 -0
- package/dist/shell/sidebar-group.js.map +1 -0
- package/dist/shell/sidebar-menu-item.d.ts +27 -0
- package/dist/shell/sidebar-menu-item.js +152 -0
- package/dist/shell/sidebar-menu-item.js.map +1 -0
- package/dist/shell/sidebar.d.ts +26 -0
- package/dist/shell/sidebar.js +92 -0
- package/dist/shell/sidebar.js.map +1 -0
- package/dist/shell/theme-provider.d.ts +18 -0
- package/dist/shell/theme-provider.js +29 -0
- package/dist/shell/theme-provider.js.map +1 -0
- package/dist/shell/theme-toggle.d.ts +28 -0
- package/dist/shell/theme-toggle.js +67 -0
- package/dist/shell/theme-toggle.js.map +1 -0
- package/dist/shell/types.d.ts +168 -0
- package/dist/shell/types.js +38 -0
- package/dist/shell/types.js.map +1 -0
- package/dist/shell/user-menu.d.ts +42 -0
- package/dist/shell/user-menu.js +132 -0
- package/dist/shell/user-menu.js.map +1 -0
- package/dist/shell/utils.d.ts +62 -0
- package/dist/shell/utils.js +73 -0
- package/dist/shell/utils.js.map +1 -0
- package/dist/shell/workspace-switcher.d.ts +24 -0
- package/dist/shell/workspace-switcher.js +219 -0
- package/dist/shell/workspace-switcher.js.map +1 -0
- package/dist/tokens.d.ts +173 -0
- package/dist/tokens.js +161 -0
- package/dist/tokens.js.map +1 -0
- package/package.json +151 -0
- package/styles.css +357 -0
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import useEmblaCarousel, { UseEmblaCarouselType } from 'embla-carousel-react';
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
import { ButtonProps } from './button.js';
|
|
4
|
+
import 'class-variance-authority/types';
|
|
5
|
+
import 'class-variance-authority';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Carousel (embla) — băng chuyền ngang/dọc, điều hướng được bằng phím ←/→.
|
|
9
|
+
* `useCarousel()` được export để app tự dựng chấm chỉ báo hoặc nút điều khiển riêng.
|
|
10
|
+
* Chuỗi cho trình đọc màn hình mặc định tiếng Việt, override qua prop `srLabel`.
|
|
11
|
+
*/
|
|
12
|
+
type CarouselApi = UseEmblaCarouselType[1];
|
|
13
|
+
type UseCarouselParameters = Parameters<typeof useEmblaCarousel>;
|
|
14
|
+
type CarouselOptions = UseCarouselParameters[0];
|
|
15
|
+
type CarouselPlugin = UseCarouselParameters[1];
|
|
16
|
+
type CarouselOwnProps = {
|
|
17
|
+
opts?: CarouselOptions;
|
|
18
|
+
plugins?: CarouselPlugin;
|
|
19
|
+
orientation?: "horizontal" | "vertical";
|
|
20
|
+
setApi?: (api: CarouselApi) => void;
|
|
21
|
+
};
|
|
22
|
+
type CarouselProps = React.ComponentProps<"div"> & CarouselOwnProps;
|
|
23
|
+
type CarouselContentProps = React.ComponentProps<"div">;
|
|
24
|
+
type CarouselItemProps = React.ComponentProps<"div">;
|
|
25
|
+
type CarouselPreviousProps = ButtonProps & {
|
|
26
|
+
srLabel?: string;
|
|
27
|
+
};
|
|
28
|
+
type CarouselNextProps = ButtonProps & {
|
|
29
|
+
srLabel?: string;
|
|
30
|
+
};
|
|
31
|
+
type CarouselContextProps = {
|
|
32
|
+
carouselRef: ReturnType<typeof useEmblaCarousel>[0];
|
|
33
|
+
api: ReturnType<typeof useEmblaCarousel>[1];
|
|
34
|
+
scrollPrev: () => void;
|
|
35
|
+
scrollNext: () => void;
|
|
36
|
+
canScrollPrev: boolean;
|
|
37
|
+
canScrollNext: boolean;
|
|
38
|
+
} & CarouselOwnProps;
|
|
39
|
+
declare function useCarousel(): CarouselContextProps;
|
|
40
|
+
declare function Carousel({ orientation, opts, setApi, plugins, className, children, ...props }: CarouselProps): React.JSX.Element;
|
|
41
|
+
declare function CarouselContent({ className, ...props }: CarouselContentProps): React.JSX.Element;
|
|
42
|
+
declare function CarouselItem({ className, ...props }: CarouselItemProps): React.JSX.Element;
|
|
43
|
+
declare function CarouselPrevious({ className, variant, size, srLabel, ...props }: CarouselPreviousProps): React.JSX.Element;
|
|
44
|
+
declare function CarouselNext({ className, variant, size, srLabel, ...props }: CarouselNextProps): React.JSX.Element;
|
|
45
|
+
|
|
46
|
+
export { Carousel, type CarouselApi, CarouselContent, type CarouselContentProps, type CarouselContextProps, CarouselItem, type CarouselItemProps, CarouselNext, type CarouselNextProps, type CarouselOptions, type CarouselOwnProps, type CarouselPlugin, CarouselPrevious, type CarouselPreviousProps, type CarouselProps, useCarousel };
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
import useEmblaCarousel from "embla-carousel-react";
|
|
4
|
+
import { ArrowLeft, ArrowRight } from "lucide-react";
|
|
5
|
+
import * as React from "react";
|
|
6
|
+
import { cn } from "../../lib/cn.js";
|
|
7
|
+
import { Button } from "./button.js";
|
|
8
|
+
const CarouselContext = React.createContext(null);
|
|
9
|
+
function useCarousel() {
|
|
10
|
+
const context = React.useContext(CarouselContext);
|
|
11
|
+
if (!context) {
|
|
12
|
+
throw new Error("useCarousel ph\u1EA3i \u0111\u01B0\u1EE3c d\xF9ng b\xEAn trong <Carousel />");
|
|
13
|
+
}
|
|
14
|
+
return context;
|
|
15
|
+
}
|
|
16
|
+
function Carousel({ orientation = "horizontal", opts, setApi, plugins, className, children, ...props }) {
|
|
17
|
+
const [carouselRef, api] = useEmblaCarousel(
|
|
18
|
+
{
|
|
19
|
+
...opts,
|
|
20
|
+
axis: orientation === "horizontal" ? "x" : "y"
|
|
21
|
+
},
|
|
22
|
+
plugins
|
|
23
|
+
);
|
|
24
|
+
const [canScrollPrev, setCanScrollPrev] = React.useState(false);
|
|
25
|
+
const [canScrollNext, setCanScrollNext] = React.useState(false);
|
|
26
|
+
const onSelect = React.useCallback((emblaApi) => {
|
|
27
|
+
if (!emblaApi) return;
|
|
28
|
+
setCanScrollPrev(emblaApi.canScrollPrev());
|
|
29
|
+
setCanScrollNext(emblaApi.canScrollNext());
|
|
30
|
+
}, []);
|
|
31
|
+
const scrollPrev = React.useCallback(() => {
|
|
32
|
+
api?.scrollPrev();
|
|
33
|
+
}, [api]);
|
|
34
|
+
const scrollNext = React.useCallback(() => {
|
|
35
|
+
api?.scrollNext();
|
|
36
|
+
}, [api]);
|
|
37
|
+
const handleKeyDown = React.useCallback(
|
|
38
|
+
(event) => {
|
|
39
|
+
if (event.key === "ArrowLeft") {
|
|
40
|
+
event.preventDefault();
|
|
41
|
+
scrollPrev();
|
|
42
|
+
} else if (event.key === "ArrowRight") {
|
|
43
|
+
event.preventDefault();
|
|
44
|
+
scrollNext();
|
|
45
|
+
}
|
|
46
|
+
},
|
|
47
|
+
[scrollPrev, scrollNext]
|
|
48
|
+
);
|
|
49
|
+
React.useEffect(() => {
|
|
50
|
+
if (!api || !setApi) return;
|
|
51
|
+
setApi(api);
|
|
52
|
+
}, [api, setApi]);
|
|
53
|
+
React.useEffect(() => {
|
|
54
|
+
if (!api) return;
|
|
55
|
+
onSelect(api);
|
|
56
|
+
api.on("reInit", onSelect);
|
|
57
|
+
api.on("select", onSelect);
|
|
58
|
+
return () => {
|
|
59
|
+
api?.off("select", onSelect);
|
|
60
|
+
};
|
|
61
|
+
}, [api, onSelect]);
|
|
62
|
+
return /* @__PURE__ */ jsx(
|
|
63
|
+
CarouselContext.Provider,
|
|
64
|
+
{
|
|
65
|
+
value: {
|
|
66
|
+
carouselRef,
|
|
67
|
+
api,
|
|
68
|
+
opts,
|
|
69
|
+
orientation: orientation || (opts?.axis === "y" ? "vertical" : "horizontal"),
|
|
70
|
+
scrollPrev,
|
|
71
|
+
scrollNext,
|
|
72
|
+
canScrollPrev,
|
|
73
|
+
canScrollNext
|
|
74
|
+
},
|
|
75
|
+
children: /* @__PURE__ */ jsx(
|
|
76
|
+
"div",
|
|
77
|
+
{
|
|
78
|
+
onKeyDownCapture: handleKeyDown,
|
|
79
|
+
className: cn("relative", className),
|
|
80
|
+
role: "region",
|
|
81
|
+
"aria-roledescription": "b\u0103ng chuy\u1EC1n",
|
|
82
|
+
"data-slot": "carousel",
|
|
83
|
+
...props,
|
|
84
|
+
children
|
|
85
|
+
}
|
|
86
|
+
)
|
|
87
|
+
}
|
|
88
|
+
);
|
|
89
|
+
}
|
|
90
|
+
function CarouselContent({ className, ...props }) {
|
|
91
|
+
const { carouselRef, orientation } = useCarousel();
|
|
92
|
+
return /* @__PURE__ */ jsx("div", { ref: carouselRef, className: "overflow-hidden", "data-slot": "carousel-content", children: /* @__PURE__ */ jsx("div", { className: cn("flex", orientation === "horizontal" ? "-ml-4" : "-mt-4 flex-col", className), ...props }) });
|
|
93
|
+
}
|
|
94
|
+
function CarouselItem({ className, ...props }) {
|
|
95
|
+
const { orientation } = useCarousel();
|
|
96
|
+
return /* @__PURE__ */ jsx(
|
|
97
|
+
"div",
|
|
98
|
+
{
|
|
99
|
+
role: "group",
|
|
100
|
+
"aria-roledescription": "trang chi\u1EBFu",
|
|
101
|
+
"data-slot": "carousel-item",
|
|
102
|
+
className: cn("min-w-0 shrink-0 grow-0 basis-full", orientation === "horizontal" ? "pl-4" : "pt-4", className),
|
|
103
|
+
...props
|
|
104
|
+
}
|
|
105
|
+
);
|
|
106
|
+
}
|
|
107
|
+
function CarouselPrevious({
|
|
108
|
+
className,
|
|
109
|
+
variant = "outline",
|
|
110
|
+
size = "icon",
|
|
111
|
+
srLabel = "Trang chi\u1EBFu tr\u01B0\u1EDBc",
|
|
112
|
+
...props
|
|
113
|
+
}) {
|
|
114
|
+
const { orientation, scrollPrev, canScrollPrev } = useCarousel();
|
|
115
|
+
return /* @__PURE__ */ jsxs(
|
|
116
|
+
Button,
|
|
117
|
+
{
|
|
118
|
+
"data-slot": "carousel-previous",
|
|
119
|
+
variant,
|
|
120
|
+
size,
|
|
121
|
+
className: cn(
|
|
122
|
+
"absolute size-8 rounded-full",
|
|
123
|
+
orientation === "horizontal" ? "top-1/2 -left-12 -translate-y-1/2" : "-top-12 left-1/2 -translate-x-1/2 rotate-90",
|
|
124
|
+
className
|
|
125
|
+
),
|
|
126
|
+
disabled: !canScrollPrev,
|
|
127
|
+
onClick: scrollPrev,
|
|
128
|
+
...props,
|
|
129
|
+
children: [
|
|
130
|
+
/* @__PURE__ */ jsx(ArrowLeft, {}),
|
|
131
|
+
/* @__PURE__ */ jsx("span", { className: "sr-only", children: srLabel })
|
|
132
|
+
]
|
|
133
|
+
}
|
|
134
|
+
);
|
|
135
|
+
}
|
|
136
|
+
function CarouselNext({
|
|
137
|
+
className,
|
|
138
|
+
variant = "outline",
|
|
139
|
+
size = "icon",
|
|
140
|
+
srLabel = "Trang chi\u1EBFu sau",
|
|
141
|
+
...props
|
|
142
|
+
}) {
|
|
143
|
+
const { orientation, scrollNext, canScrollNext } = useCarousel();
|
|
144
|
+
return /* @__PURE__ */ jsxs(
|
|
145
|
+
Button,
|
|
146
|
+
{
|
|
147
|
+
"data-slot": "carousel-next",
|
|
148
|
+
variant,
|
|
149
|
+
size,
|
|
150
|
+
className: cn(
|
|
151
|
+
"absolute size-8 rounded-full",
|
|
152
|
+
orientation === "horizontal" ? "top-1/2 -right-12 -translate-y-1/2" : "-bottom-12 left-1/2 -translate-x-1/2 rotate-90",
|
|
153
|
+
className
|
|
154
|
+
),
|
|
155
|
+
disabled: !canScrollNext,
|
|
156
|
+
onClick: scrollNext,
|
|
157
|
+
...props,
|
|
158
|
+
children: [
|
|
159
|
+
/* @__PURE__ */ jsx(ArrowRight, {}),
|
|
160
|
+
/* @__PURE__ */ jsx("span", { className: "sr-only", children: srLabel })
|
|
161
|
+
]
|
|
162
|
+
}
|
|
163
|
+
);
|
|
164
|
+
}
|
|
165
|
+
export {
|
|
166
|
+
Carousel,
|
|
167
|
+
CarouselContent,
|
|
168
|
+
CarouselItem,
|
|
169
|
+
CarouselNext,
|
|
170
|
+
CarouselPrevious,
|
|
171
|
+
useCarousel
|
|
172
|
+
};
|
|
173
|
+
//# sourceMappingURL=carousel.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/components/ui/carousel.tsx"],"sourcesContent":["\"use client\";\n\nimport useEmblaCarousel, { type UseEmblaCarouselType } from \"embla-carousel-react\";\nimport { ArrowLeft, ArrowRight } from \"lucide-react\";\nimport * as React from \"react\";\nimport { cn } from \"../../lib/cn.js\";\nimport { Button, type ButtonProps } from \"./button.js\";\n\n/**\n * Carousel (embla) — băng chuyền ngang/dọc, điều hướng được bằng phím ←/→.\n * `useCarousel()` được export để app tự dựng chấm chỉ báo hoặc nút điều khiển riêng.\n * Chuỗi cho trình đọc màn hình mặc định tiếng Việt, override qua prop `srLabel`.\n */\n\nexport type CarouselApi = UseEmblaCarouselType[1];\ntype UseCarouselParameters = Parameters<typeof useEmblaCarousel>;\nexport type CarouselOptions = UseCarouselParameters[0];\nexport type CarouselPlugin = UseCarouselParameters[1];\n\nexport type CarouselOwnProps = {\n opts?: CarouselOptions;\n plugins?: CarouselPlugin;\n orientation?: \"horizontal\" | \"vertical\";\n setApi?: (api: CarouselApi) => void;\n};\n\nexport type CarouselProps = React.ComponentProps<\"div\"> & CarouselOwnProps;\nexport type CarouselContentProps = React.ComponentProps<\"div\">;\nexport type CarouselItemProps = React.ComponentProps<\"div\">;\nexport type CarouselPreviousProps = ButtonProps & { srLabel?: string };\nexport type CarouselNextProps = ButtonProps & { srLabel?: string };\n\nexport type CarouselContextProps = {\n carouselRef: ReturnType<typeof useEmblaCarousel>[0];\n api: ReturnType<typeof useEmblaCarousel>[1];\n scrollPrev: () => void;\n scrollNext: () => void;\n canScrollPrev: boolean;\n canScrollNext: boolean;\n} & CarouselOwnProps;\n\nconst CarouselContext = React.createContext<CarouselContextProps | null>(null);\n\nfunction useCarousel(): CarouselContextProps {\n const context = React.useContext(CarouselContext);\n\n if (!context) {\n throw new Error(\"useCarousel phải được dùng bên trong <Carousel />\");\n }\n\n return context;\n}\n\nfunction Carousel({ orientation = \"horizontal\", opts, setApi, plugins, className, children, ...props }: CarouselProps) {\n const [carouselRef, api] = useEmblaCarousel(\n {\n ...opts,\n axis: orientation === \"horizontal\" ? \"x\" : \"y\"\n },\n plugins\n );\n const [canScrollPrev, setCanScrollPrev] = React.useState(false);\n const [canScrollNext, setCanScrollNext] = React.useState(false);\n\n const onSelect = React.useCallback((emblaApi: CarouselApi) => {\n if (!emblaApi) return;\n setCanScrollPrev(emblaApi.canScrollPrev());\n setCanScrollNext(emblaApi.canScrollNext());\n }, []);\n\n const scrollPrev = React.useCallback(() => {\n api?.scrollPrev();\n }, [api]);\n\n const scrollNext = React.useCallback(() => {\n api?.scrollNext();\n }, [api]);\n\n const handleKeyDown = React.useCallback(\n (event: React.KeyboardEvent<HTMLDivElement>) => {\n if (event.key === \"ArrowLeft\") {\n event.preventDefault();\n scrollPrev();\n } else if (event.key === \"ArrowRight\") {\n event.preventDefault();\n scrollNext();\n }\n },\n [scrollPrev, scrollNext]\n );\n\n React.useEffect(() => {\n if (!api || !setApi) return;\n setApi(api);\n }, [api, setApi]);\n\n React.useEffect(() => {\n if (!api) return;\n onSelect(api);\n api.on(\"reInit\", onSelect);\n api.on(\"select\", onSelect);\n\n return () => {\n api?.off(\"select\", onSelect);\n };\n }, [api, onSelect]);\n\n return (\n <CarouselContext.Provider\n value={{\n carouselRef,\n api: api,\n opts,\n orientation: orientation || (opts?.axis === \"y\" ? \"vertical\" : \"horizontal\"),\n scrollPrev,\n scrollNext,\n canScrollPrev,\n canScrollNext\n }}\n >\n <div\n onKeyDownCapture={handleKeyDown}\n className={cn(\"relative\", className)}\n role=\"region\"\n aria-roledescription=\"băng chuyền\"\n data-slot=\"carousel\"\n {...props}\n >\n {children}\n </div>\n </CarouselContext.Provider>\n );\n}\n\nfunction CarouselContent({ className, ...props }: CarouselContentProps) {\n const { carouselRef, orientation } = useCarousel();\n\n return (\n <div ref={carouselRef} className=\"overflow-hidden\" data-slot=\"carousel-content\">\n <div className={cn(\"flex\", orientation === \"horizontal\" ? \"-ml-4\" : \"-mt-4 flex-col\", className)} {...props} />\n </div>\n );\n}\n\nfunction CarouselItem({ className, ...props }: CarouselItemProps) {\n const { orientation } = useCarousel();\n\n return (\n <div\n role=\"group\"\n aria-roledescription=\"trang chiếu\"\n data-slot=\"carousel-item\"\n className={cn(\"min-w-0 shrink-0 grow-0 basis-full\", orientation === \"horizontal\" ? \"pl-4\" : \"pt-4\", className)}\n {...props}\n />\n );\n}\n\nfunction CarouselPrevious({\n className,\n variant = \"outline\",\n size = \"icon\",\n srLabel = \"Trang chiếu trước\",\n ...props\n}: CarouselPreviousProps) {\n const { orientation, scrollPrev, canScrollPrev } = useCarousel();\n\n return (\n <Button\n data-slot=\"carousel-previous\"\n variant={variant}\n size={size}\n className={cn(\n \"absolute size-8 rounded-full\",\n orientation === \"horizontal\"\n ? \"top-1/2 -left-12 -translate-y-1/2\"\n : \"-top-12 left-1/2 -translate-x-1/2 rotate-90\",\n className\n )}\n disabled={!canScrollPrev}\n onClick={scrollPrev}\n {...props}\n >\n <ArrowLeft />\n <span className=\"sr-only\">{srLabel}</span>\n </Button>\n );\n}\n\nfunction CarouselNext({\n className,\n variant = \"outline\",\n size = \"icon\",\n srLabel = \"Trang chiếu sau\",\n ...props\n}: CarouselNextProps) {\n const { orientation, scrollNext, canScrollNext } = useCarousel();\n\n return (\n <Button\n data-slot=\"carousel-next\"\n variant={variant}\n size={size}\n className={cn(\n \"absolute size-8 rounded-full\",\n orientation === \"horizontal\"\n ? \"top-1/2 -right-12 -translate-y-1/2\"\n : \"-bottom-12 left-1/2 -translate-x-1/2 rotate-90\",\n className\n )}\n disabled={!canScrollNext}\n onClick={scrollNext}\n {...props}\n >\n <ArrowRight />\n <span className=\"sr-only\">{srLabel}</span>\n </Button>\n );\n}\n\nexport { Carousel, CarouselContent, CarouselItem, CarouselNext, CarouselPrevious, useCarousel };\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import * as CheckboxPrimitive from '@radix-ui/react-checkbox';
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
|
|
4
|
+
interface CheckboxProps extends React.ComponentProps<typeof CheckboxPrimitive.Root> {
|
|
5
|
+
/** Nhãn đặt cạnh ô đánh dấu; có nhãn thì component tự bọc thêm lớp bố cục. */
|
|
6
|
+
label?: string;
|
|
7
|
+
/** Mô tả phụ dưới nhãn. */
|
|
8
|
+
description?: string;
|
|
9
|
+
/**
|
|
10
|
+
* Đường tắt cho trạng thái "chọn một phần" — đè lên `checked`.
|
|
11
|
+
* Tương đương `checked="indeterminate"`; giữ lại cho tương thích ngược.
|
|
12
|
+
*/
|
|
13
|
+
indeterminate?: boolean;
|
|
14
|
+
}
|
|
15
|
+
declare function Checkbox({ className, label, description, indeterminate, checked, id, ...props }: CheckboxProps): React.JSX.Element;
|
|
16
|
+
|
|
17
|
+
export { Checkbox, type CheckboxProps };
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
import * as CheckboxPrimitive from "@radix-ui/react-checkbox";
|
|
4
|
+
import { CheckIcon, MinusIcon } from "lucide-react";
|
|
5
|
+
import * as React from "react";
|
|
6
|
+
import { cn } from "../../lib/cn.js";
|
|
7
|
+
function Checkbox({ className, label, description, indeterminate, checked, id, ...props }) {
|
|
8
|
+
const generatedId = React.useId();
|
|
9
|
+
const checkboxId = id ?? generatedId;
|
|
10
|
+
const control = /* @__PURE__ */ jsx(
|
|
11
|
+
CheckboxPrimitive.Root,
|
|
12
|
+
{
|
|
13
|
+
id: checkboxId,
|
|
14
|
+
"data-slot": "checkbox",
|
|
15
|
+
checked: indeterminate ? "indeterminate" : checked,
|
|
16
|
+
className: cn(
|
|
17
|
+
"peer size-4 shrink-0 rounded border border-input bg-background",
|
|
18
|
+
"transition-colors duration-150 ease-out",
|
|
19
|
+
"data-[state=checked]:bg-primary data-[state=checked]:border-primary data-[state=checked]:text-primary-foreground",
|
|
20
|
+
"data-[state=indeterminate]:bg-primary data-[state=indeterminate]:border-primary data-[state=indeterminate]:text-primary-foreground",
|
|
21
|
+
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring/50 focus-visible:ring-offset-2 focus-visible:ring-offset-background",
|
|
22
|
+
"hover:border-ash-300 dark:hover:border-ash-500",
|
|
23
|
+
"disabled:cursor-not-allowed disabled:opacity-50",
|
|
24
|
+
className
|
|
25
|
+
),
|
|
26
|
+
...props,
|
|
27
|
+
children: /* @__PURE__ */ jsxs(
|
|
28
|
+
CheckboxPrimitive.Indicator,
|
|
29
|
+
{
|
|
30
|
+
"data-slot": "checkbox-indicator",
|
|
31
|
+
className: "group/checkbox-indicator flex items-center justify-center text-current transition-none",
|
|
32
|
+
children: [
|
|
33
|
+
/* @__PURE__ */ jsx(
|
|
34
|
+
MinusIcon,
|
|
35
|
+
{
|
|
36
|
+
className: "hidden size-2.5 group-data-[state=indeterminate]/checkbox-indicator:block",
|
|
37
|
+
strokeWidth: 3
|
|
38
|
+
}
|
|
39
|
+
),
|
|
40
|
+
/* @__PURE__ */ jsx(CheckIcon, { className: "hidden size-2.5 group-data-[state=checked]/checkbox-indicator:block", strokeWidth: 3 })
|
|
41
|
+
]
|
|
42
|
+
}
|
|
43
|
+
)
|
|
44
|
+
}
|
|
45
|
+
);
|
|
46
|
+
if (!label && !description) {
|
|
47
|
+
return control;
|
|
48
|
+
}
|
|
49
|
+
return /* @__PURE__ */ jsxs("div", { className: "flex items-start gap-2.5", children: [
|
|
50
|
+
control,
|
|
51
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-0.5", children: [
|
|
52
|
+
label && /* @__PURE__ */ jsx(
|
|
53
|
+
"label",
|
|
54
|
+
{
|
|
55
|
+
htmlFor: checkboxId,
|
|
56
|
+
className: "text-sm font-medium text-foreground cursor-pointer select-none leading-none",
|
|
57
|
+
children: label
|
|
58
|
+
}
|
|
59
|
+
),
|
|
60
|
+
description && /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground leading-relaxed", children: description })
|
|
61
|
+
] })
|
|
62
|
+
] });
|
|
63
|
+
}
|
|
64
|
+
export {
|
|
65
|
+
Checkbox
|
|
66
|
+
};
|
|
67
|
+
//# sourceMappingURL=checkbox.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/components/ui/checkbox.tsx"],"sourcesContent":["\"use client\";\n\nimport * as CheckboxPrimitive from \"@radix-ui/react-checkbox\";\nimport { CheckIcon, MinusIcon } from \"lucide-react\";\nimport * as React from \"react\";\nimport { cn } from \"../../lib/cn.js\";\n\nexport interface CheckboxProps extends React.ComponentProps<typeof CheckboxPrimitive.Root> {\n /** Nhãn đặt cạnh ô đánh dấu; có nhãn thì component tự bọc thêm lớp bố cục. */\n label?: string;\n /** Mô tả phụ dưới nhãn. */\n description?: string;\n /**\n * Đường tắt cho trạng thái \"chọn một phần\" — đè lên `checked`.\n * Tương đương `checked=\"indeterminate\"`; giữ lại cho tương thích ngược.\n */\n indeterminate?: boolean;\n}\n\n/*\n * Style port từ comitor-ds (đổi gray-* → ash-* theo namespace của package).\n *\n * ─ ICON BÁM THEO STATE THẬT, KHÔNG THEO PROP ─\n * Bản cũ chọn icon bằng `indeterminate ? <Minus/> : <Check/>`, tức chỉ nhìn PROP. Ai truyền\n * `checked=\"indeterminate\"` thẳng (Radix cho phép, và `composite/data-table.tsx` đang làm đúng\n * như vậy cho ô \"chọn tất cả\") thì nền chuyển sang trạng thái một phần nhưng icon vẫn là dấu\n * tick → mới chọn vài dòng mà đầu bảng trông y hệt đã chọn hết. Trường hợp không kiểm soát\n * (`defaultChecked=\"indeterminate\"`) còn sai cả sau khi người dùng bấm.\n * Nay cả hai icon cùng được render và bật/tắt bằng `data-state` của chính Radix Indicator\n * (Radix phát `data-state=\"checked\" | \"indeterminate\"` trên Indicator) → luôn khớp state thật,\n * kể cả ở nhánh không kiểm soát.\n *\n * ─ MÀU ─ `bg-primary` + `text-primary-foreground` thay cho `bg-gold-300 text-ink`: bậc gold thô\n * giống nhau ở cả hai theme nên bảng màu dark của package (`--primary: #F5D060`) không được áp\n * dụng và app đổi `--primary` cũng không đổi được ô đánh dấu. Tương phản dấu tick trên nền ô:\n * light 10,19:1 (không đổi) · dark 12,67:1 (trước 10,19:1) — vượt xa mức 3:1 cho phần tử phi văn bản.\n */\nfunction Checkbox({ className, label, description, indeterminate, checked, id, ...props }: CheckboxProps) {\n const generatedId = React.useId();\n const checkboxId = id ?? generatedId;\n\n const control = (\n <CheckboxPrimitive.Root\n id={checkboxId}\n data-slot=\"checkbox\"\n checked={indeterminate ? \"indeterminate\" : checked}\n className={cn(\n \"peer size-4 shrink-0 rounded border border-input bg-background\",\n \"transition-colors duration-150 ease-out\",\n \"data-[state=checked]:bg-primary data-[state=checked]:border-primary data-[state=checked]:text-primary-foreground\",\n \"data-[state=indeterminate]:bg-primary data-[state=indeterminate]:border-primary data-[state=indeterminate]:text-primary-foreground\",\n \"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring/50 focus-visible:ring-offset-2 focus-visible:ring-offset-background\",\n \"hover:border-ash-300 dark:hover:border-ash-500\",\n \"disabled:cursor-not-allowed disabled:opacity-50\",\n className\n )}\n {...props}\n >\n <CheckboxPrimitive.Indicator\n data-slot=\"checkbox-indicator\"\n className=\"group/checkbox-indicator flex items-center justify-center text-current transition-none\"\n >\n <MinusIcon\n className=\"hidden size-2.5 group-data-[state=indeterminate]/checkbox-indicator:block\"\n strokeWidth={3}\n />\n <CheckIcon className=\"hidden size-2.5 group-data-[state=checked]/checkbox-indicator:block\" strokeWidth={3} />\n </CheckboxPrimitive.Indicator>\n </CheckboxPrimitive.Root>\n );\n\n if (!label && !description) {\n return control;\n }\n\n return (\n <div className=\"flex items-start gap-2.5\">\n {control}\n <div className=\"flex flex-col gap-0.5\">\n {label && (\n <label\n htmlFor={checkboxId}\n className=\"text-sm font-medium text-foreground cursor-pointer select-none leading-none\"\n >\n {label}\n </label>\n )}\n {description && <p className=\"text-xs text-muted-foreground leading-relaxed\">{description}</p>}\n </div>\n </div>\n );\n}\n\nexport { Checkbox };\n"],"mappings":";AA0DM,SAIE,KAJF;AAxDN,YAAY,uBAAuB;AACnC,SAAS,WAAW,iBAAiB;AACrC,YAAY,WAAW;AACvB,SAAS,UAAU;AAgCnB,SAAS,SAAS,EAAE,WAAW,OAAO,aAAa,eAAe,SAAS,IAAI,GAAG,MAAM,GAAkB;AACxG,QAAM,cAAc,MAAM,MAAM;AAChC,QAAM,aAAa,MAAM;AAEzB,QAAM,UACJ;AAAA,IAAC,kBAAkB;AAAA,IAAlB;AAAA,MACC,IAAI;AAAA,MACJ,aAAU;AAAA,MACV,SAAS,gBAAgB,kBAAkB;AAAA,MAC3C,WAAW;AAAA,QACT;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,MACC,GAAG;AAAA,MAEJ;AAAA,QAAC,kBAAkB;AAAA,QAAlB;AAAA,UACC,aAAU;AAAA,UACV,WAAU;AAAA,UAEV;AAAA;AAAA,cAAC;AAAA;AAAA,gBACC,WAAU;AAAA,gBACV,aAAa;AAAA;AAAA,YACf;AAAA,YACA,oBAAC,aAAU,WAAU,uEAAsE,aAAa,GAAG;AAAA;AAAA;AAAA,MAC7G;AAAA;AAAA,EACF;AAGF,MAAI,CAAC,SAAS,CAAC,aAAa;AAC1B,WAAO;AAAA,EACT;AAEA,SACE,qBAAC,SAAI,WAAU,4BACZ;AAAA;AAAA,IACD,qBAAC,SAAI,WAAU,yBACZ;AAAA,eACC;AAAA,QAAC;AAAA;AAAA,UACC,SAAS;AAAA,UACT,WAAU;AAAA,UAET;AAAA;AAAA,MACH;AAAA,MAED,eAAe,oBAAC,OAAE,WAAU,iDAAiD,uBAAY;AAAA,OAC5F;AAAA,KACF;AAEJ;","names":[]}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import * as CollapsiblePrimitive from '@radix-ui/react-collapsible';
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Collapsible (Radix) — không style sẵn, chỉ gắn `data-slot`.
|
|
6
|
+
* Muốn có animation trượt: thêm class `data-[state=open]:animate-collapsible-down
|
|
7
|
+
* data-[state=closed]:animate-collapsible-up overflow-hidden` cho `CollapsibleContent`
|
|
8
|
+
* (keyframes do `tw-animate-css` cấp).
|
|
9
|
+
*/
|
|
10
|
+
type CollapsibleProps = React.ComponentProps<typeof CollapsiblePrimitive.Root>;
|
|
11
|
+
type CollapsibleTriggerProps = React.ComponentProps<typeof CollapsiblePrimitive.CollapsibleTrigger>;
|
|
12
|
+
type CollapsibleContentProps = React.ComponentProps<typeof CollapsiblePrimitive.CollapsibleContent>;
|
|
13
|
+
declare function Collapsible({ ...props }: CollapsibleProps): React.JSX.Element;
|
|
14
|
+
declare function CollapsibleTrigger({ ...props }: CollapsibleTriggerProps): React.JSX.Element;
|
|
15
|
+
declare function CollapsibleContent({ ...props }: CollapsibleContentProps): React.JSX.Element;
|
|
16
|
+
|
|
17
|
+
export { Collapsible, CollapsibleContent, type CollapsibleContentProps, type CollapsibleProps, CollapsibleTrigger, type CollapsibleTriggerProps };
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx } from "react/jsx-runtime";
|
|
3
|
+
import * as CollapsiblePrimitive from "@radix-ui/react-collapsible";
|
|
4
|
+
function Collapsible({ ...props }) {
|
|
5
|
+
return /* @__PURE__ */ jsx(CollapsiblePrimitive.Root, { "data-slot": "collapsible", ...props });
|
|
6
|
+
}
|
|
7
|
+
function CollapsibleTrigger({ ...props }) {
|
|
8
|
+
return /* @__PURE__ */ jsx(CollapsiblePrimitive.CollapsibleTrigger, { "data-slot": "collapsible-trigger", ...props });
|
|
9
|
+
}
|
|
10
|
+
function CollapsibleContent({ ...props }) {
|
|
11
|
+
return /* @__PURE__ */ jsx(CollapsiblePrimitive.CollapsibleContent, { "data-slot": "collapsible-content", ...props });
|
|
12
|
+
}
|
|
13
|
+
export {
|
|
14
|
+
Collapsible,
|
|
15
|
+
CollapsibleContent,
|
|
16
|
+
CollapsibleTrigger
|
|
17
|
+
};
|
|
18
|
+
//# sourceMappingURL=collapsible.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/components/ui/collapsible.tsx"],"sourcesContent":["\"use client\";\n\nimport * as CollapsiblePrimitive from \"@radix-ui/react-collapsible\";\nimport type * as React from \"react\";\n\n/**\n * Collapsible (Radix) — không style sẵn, chỉ gắn `data-slot`.\n * Muốn có animation trượt: thêm class `data-[state=open]:animate-collapsible-down\n * data-[state=closed]:animate-collapsible-up overflow-hidden` cho `CollapsibleContent`\n * (keyframes do `tw-animate-css` cấp).\n */\n\nexport type CollapsibleProps = React.ComponentProps<typeof CollapsiblePrimitive.Root>;\nexport type CollapsibleTriggerProps = React.ComponentProps<typeof CollapsiblePrimitive.CollapsibleTrigger>;\nexport type CollapsibleContentProps = React.ComponentProps<typeof CollapsiblePrimitive.CollapsibleContent>;\n\nfunction Collapsible({ ...props }: CollapsibleProps) {\n return <CollapsiblePrimitive.Root data-slot=\"collapsible\" {...props} />;\n}\n\nfunction CollapsibleTrigger({ ...props }: CollapsibleTriggerProps) {\n return <CollapsiblePrimitive.CollapsibleTrigger data-slot=\"collapsible-trigger\" {...props} />;\n}\n\nfunction CollapsibleContent({ ...props }: CollapsibleContentProps) {\n return <CollapsiblePrimitive.CollapsibleContent data-slot=\"collapsible-content\" {...props} />;\n}\n\nexport { Collapsible, CollapsibleContent, CollapsibleTrigger };\n"],"mappings":";AAiBS;AAfT,YAAY,0BAA0B;AActC,SAAS,YAAY,EAAE,GAAG,MAAM,GAAqB;AACnD,SAAO,oBAAC,qBAAqB,MAArB,EAA0B,aAAU,eAAe,GAAG,OAAO;AACvE;AAEA,SAAS,mBAAmB,EAAE,GAAG,MAAM,GAA4B;AACjE,SAAO,oBAAC,qBAAqB,oBAArB,EAAwC,aAAU,uBAAuB,GAAG,OAAO;AAC7F;AAEA,SAAS,mBAAmB,EAAE,GAAG,MAAM,GAA4B;AACjE,SAAO,oBAAC,qBAAqB,oBAArB,EAAwC,aAAU,uBAAuB,GAAG,OAAO;AAC7F;","names":[]}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { Command as Command$1 } from 'cmdk';
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
import { Dialog } from './dialog.js';
|
|
4
|
+
import '@radix-ui/react-dialog';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Command — danh sách lệnh có lọc theo phím gõ (cmdk).
|
|
8
|
+
*
|
|
9
|
+
* Đây là primitive trần: composite `CommandPalette` và `Combobox` (Tier 2) dựng lên
|
|
10
|
+
* từ đây. `CommandDialog` bọc sẵn trong `Dialog` cho bảng lệnh Cmd/Ctrl+K.
|
|
11
|
+
*
|
|
12
|
+
* Lưu ý a11y: `CommandDialog` bắt buộc có tiêu đề + mô tả cho trình đọc màn hình
|
|
13
|
+
* (đặt trong `DialogHeader` ẩn `sr-only`) — đổi bằng prop `title`/`description`.
|
|
14
|
+
*/
|
|
15
|
+
type CommandProps = React.ComponentProps<typeof Command$1>;
|
|
16
|
+
declare function Command({ className, ...props }: CommandProps): React.JSX.Element;
|
|
17
|
+
type CommandDialogProps = React.ComponentProps<typeof Dialog> & {
|
|
18
|
+
/** Tiêu đề cho trình đọc màn hình. Mặc định "Bảng lệnh". */
|
|
19
|
+
title?: string;
|
|
20
|
+
/** Mô tả cho trình đọc màn hình. Mặc định "Tìm và chạy một lệnh…". */
|
|
21
|
+
description?: string;
|
|
22
|
+
className?: string;
|
|
23
|
+
showCloseButton?: boolean;
|
|
24
|
+
};
|
|
25
|
+
declare function CommandDialog({ title, description, children, className, showCloseButton, ...props }: CommandDialogProps): React.JSX.Element;
|
|
26
|
+
type CommandInputProps = React.ComponentProps<typeof Command$1.Input>;
|
|
27
|
+
declare function CommandInput({ className, ...props }: CommandInputProps): React.JSX.Element;
|
|
28
|
+
type CommandListProps = React.ComponentProps<typeof Command$1.List>;
|
|
29
|
+
declare function CommandList({ className, ...props }: CommandListProps): React.JSX.Element;
|
|
30
|
+
type CommandEmptyProps = React.ComponentProps<typeof Command$1.Empty>;
|
|
31
|
+
declare function CommandEmpty({ ...props }: CommandEmptyProps): React.JSX.Element;
|
|
32
|
+
type CommandGroupProps = React.ComponentProps<typeof Command$1.Group>;
|
|
33
|
+
declare function CommandGroup({ className, ...props }: CommandGroupProps): React.JSX.Element;
|
|
34
|
+
type CommandSeparatorProps = React.ComponentProps<typeof Command$1.Separator>;
|
|
35
|
+
declare function CommandSeparator({ className, ...props }: CommandSeparatorProps): React.JSX.Element;
|
|
36
|
+
type CommandItemProps = React.ComponentProps<typeof Command$1.Item>;
|
|
37
|
+
declare function CommandItem({ className, ...props }: CommandItemProps): React.JSX.Element;
|
|
38
|
+
type CommandShortcutProps = React.ComponentProps<"span">;
|
|
39
|
+
declare function CommandShortcut({ className, ...props }: CommandShortcutProps): React.JSX.Element;
|
|
40
|
+
|
|
41
|
+
export { Command, CommandDialog, type CommandDialogProps, CommandEmpty, type CommandEmptyProps, CommandGroup, type CommandGroupProps, CommandInput, type CommandInputProps, CommandItem, type CommandItemProps, CommandList, type CommandListProps, type CommandProps, CommandSeparator, type CommandSeparatorProps, CommandShortcut, type CommandShortcutProps };
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { Command as CommandPrimitive } from "cmdk";
|
|
4
|
+
import { SearchIcon } from "lucide-react";
|
|
5
|
+
import { cn } from "../../lib/cn.js";
|
|
6
|
+
import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle } from "./dialog.js";
|
|
7
|
+
function Command({ className, ...props }) {
|
|
8
|
+
return /* @__PURE__ */ jsx(
|
|
9
|
+
CommandPrimitive,
|
|
10
|
+
{
|
|
11
|
+
"data-slot": "command",
|
|
12
|
+
className: cn(
|
|
13
|
+
"bg-popover text-popover-foreground flex h-full w-full flex-col overflow-hidden rounded-md",
|
|
14
|
+
className
|
|
15
|
+
),
|
|
16
|
+
...props
|
|
17
|
+
}
|
|
18
|
+
);
|
|
19
|
+
}
|
|
20
|
+
function CommandDialog({
|
|
21
|
+
title = "B\u1EA3ng l\u1EC7nh",
|
|
22
|
+
description = "T\xECm v\xE0 ch\u1EA1y m\u1ED9t l\u1EC7nh\u2026",
|
|
23
|
+
children,
|
|
24
|
+
className,
|
|
25
|
+
showCloseButton = true,
|
|
26
|
+
...props
|
|
27
|
+
}) {
|
|
28
|
+
return /* @__PURE__ */ jsxs(Dialog, { ...props, children: [
|
|
29
|
+
/* @__PURE__ */ jsxs(DialogHeader, { className: "sr-only", children: [
|
|
30
|
+
/* @__PURE__ */ jsx(DialogTitle, { children: title }),
|
|
31
|
+
/* @__PURE__ */ jsx(DialogDescription, { children: description })
|
|
32
|
+
] }),
|
|
33
|
+
/* @__PURE__ */ jsx(DialogContent, { className: cn("overflow-hidden p-0", className), showCloseButton, children: /* @__PURE__ */ jsx(Command, { className: "[&_[cmdk-group-heading]]:text-muted-foreground **:data-[slot=command-input-wrapper]:h-12 [&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group]]:px-2 [&_[cmdk-group]:not([hidden])_~[cmdk-group]]:pt-0 [&_[cmdk-input-wrapper]_svg]:h-5 [&_[cmdk-input-wrapper]_svg]:w-5 [&_[cmdk-input]]:h-12 [&_[cmdk-item]]:px-2 [&_[cmdk-item]]:py-3 [&_[cmdk-item]_svg]:h-5 [&_[cmdk-item]_svg]:w-5", children }) })
|
|
34
|
+
] });
|
|
35
|
+
}
|
|
36
|
+
function CommandInput({ className, ...props }) {
|
|
37
|
+
return /* @__PURE__ */ jsxs("div", { "data-slot": "command-input-wrapper", className: "flex h-9 items-center gap-2 border-b px-3", children: [
|
|
38
|
+
/* @__PURE__ */ jsx(SearchIcon, { className: "size-4 shrink-0 opacity-50" }),
|
|
39
|
+
/* @__PURE__ */ jsx(
|
|
40
|
+
CommandPrimitive.Input,
|
|
41
|
+
{
|
|
42
|
+
"data-slot": "command-input",
|
|
43
|
+
className: cn(
|
|
44
|
+
"placeholder:text-muted-foreground flex h-10 w-full rounded-md bg-transparent py-3 text-sm outline-hidden disabled:cursor-not-allowed disabled:opacity-50",
|
|
45
|
+
className
|
|
46
|
+
),
|
|
47
|
+
...props
|
|
48
|
+
}
|
|
49
|
+
)
|
|
50
|
+
] });
|
|
51
|
+
}
|
|
52
|
+
function CommandList({ className, ...props }) {
|
|
53
|
+
return /* @__PURE__ */ jsx(
|
|
54
|
+
CommandPrimitive.List,
|
|
55
|
+
{
|
|
56
|
+
"data-slot": "command-list",
|
|
57
|
+
className: cn("max-h-[300px] scroll-py-1 overflow-x-hidden overflow-y-auto", className),
|
|
58
|
+
...props
|
|
59
|
+
}
|
|
60
|
+
);
|
|
61
|
+
}
|
|
62
|
+
function CommandEmpty({ ...props }) {
|
|
63
|
+
return /* @__PURE__ */ jsx(CommandPrimitive.Empty, { "data-slot": "command-empty", className: "py-6 text-center text-sm", ...props });
|
|
64
|
+
}
|
|
65
|
+
function CommandGroup({ className, ...props }) {
|
|
66
|
+
return /* @__PURE__ */ jsx(
|
|
67
|
+
CommandPrimitive.Group,
|
|
68
|
+
{
|
|
69
|
+
"data-slot": "command-group",
|
|
70
|
+
className: cn(
|
|
71
|
+
"text-foreground [&_[cmdk-group-heading]]:text-muted-foreground overflow-hidden p-1 [&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:py-1.5 [&_[cmdk-group-heading]]:text-xs [&_[cmdk-group-heading]]:font-medium",
|
|
72
|
+
className
|
|
73
|
+
),
|
|
74
|
+
...props
|
|
75
|
+
}
|
|
76
|
+
);
|
|
77
|
+
}
|
|
78
|
+
function CommandSeparator({ className, ...props }) {
|
|
79
|
+
return /* @__PURE__ */ jsx(
|
|
80
|
+
CommandPrimitive.Separator,
|
|
81
|
+
{
|
|
82
|
+
"data-slot": "command-separator",
|
|
83
|
+
className: cn("bg-border -mx-1 h-px", className),
|
|
84
|
+
...props
|
|
85
|
+
}
|
|
86
|
+
);
|
|
87
|
+
}
|
|
88
|
+
function CommandItem({ className, ...props }) {
|
|
89
|
+
return /* @__PURE__ */ jsx(
|
|
90
|
+
CommandPrimitive.Item,
|
|
91
|
+
{
|
|
92
|
+
"data-slot": "command-item",
|
|
93
|
+
className: cn(
|
|
94
|
+
"data-[selected=true]:bg-accent data-[selected=true]:text-accent-foreground [&_svg:not([class*='text-'])]:text-muted-foreground relative flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden select-none data-[disabled=true]:pointer-events-none data-[disabled=true]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
|
|
95
|
+
className
|
|
96
|
+
),
|
|
97
|
+
...props
|
|
98
|
+
}
|
|
99
|
+
);
|
|
100
|
+
}
|
|
101
|
+
function CommandShortcut({ className, ...props }) {
|
|
102
|
+
return /* @__PURE__ */ jsx(
|
|
103
|
+
"span",
|
|
104
|
+
{
|
|
105
|
+
"data-slot": "command-shortcut",
|
|
106
|
+
className: cn("text-muted-foreground ml-auto text-xs tracking-widest", className),
|
|
107
|
+
...props
|
|
108
|
+
}
|
|
109
|
+
);
|
|
110
|
+
}
|
|
111
|
+
export {
|
|
112
|
+
Command,
|
|
113
|
+
CommandDialog,
|
|
114
|
+
CommandEmpty,
|
|
115
|
+
CommandGroup,
|
|
116
|
+
CommandInput,
|
|
117
|
+
CommandItem,
|
|
118
|
+
CommandList,
|
|
119
|
+
CommandSeparator,
|
|
120
|
+
CommandShortcut
|
|
121
|
+
};
|
|
122
|
+
//# sourceMappingURL=command.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/components/ui/command.tsx"],"sourcesContent":["\"use client\";\n\nimport { Command as CommandPrimitive } from \"cmdk\";\nimport { SearchIcon } from \"lucide-react\";\nimport type * as React from \"react\";\nimport { cn } from \"../../lib/cn.js\";\nimport { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle } from \"./dialog.js\";\n\n/**\n * Command — danh sách lệnh có lọc theo phím gõ (cmdk).\n *\n * Đây là primitive trần: composite `CommandPalette` và `Combobox` (Tier 2) dựng lên\n * từ đây. `CommandDialog` bọc sẵn trong `Dialog` cho bảng lệnh Cmd/Ctrl+K.\n *\n * Lưu ý a11y: `CommandDialog` bắt buộc có tiêu đề + mô tả cho trình đọc màn hình\n * (đặt trong `DialogHeader` ẩn `sr-only`) — đổi bằng prop `title`/`description`.\n */\n\nexport type CommandProps = React.ComponentProps<typeof CommandPrimitive>;\n\nfunction Command({ className, ...props }: CommandProps) {\n return (\n <CommandPrimitive\n data-slot=\"command\"\n className={cn(\n \"bg-popover text-popover-foreground flex h-full w-full flex-col overflow-hidden rounded-md\",\n className\n )}\n {...props}\n />\n );\n}\n\nexport type CommandDialogProps = React.ComponentProps<typeof Dialog> & {\n /** Tiêu đề cho trình đọc màn hình. Mặc định \"Bảng lệnh\". */\n title?: string;\n /** Mô tả cho trình đọc màn hình. Mặc định \"Tìm và chạy một lệnh…\". */\n description?: string;\n className?: string;\n showCloseButton?: boolean;\n};\n\nfunction CommandDialog({\n title = \"Bảng lệnh\",\n description = \"Tìm và chạy một lệnh…\",\n children,\n className,\n showCloseButton = true,\n ...props\n}: CommandDialogProps) {\n return (\n <Dialog {...props}>\n <DialogHeader className=\"sr-only\">\n <DialogTitle>{title}</DialogTitle>\n <DialogDescription>{description}</DialogDescription>\n </DialogHeader>\n <DialogContent className={cn(\"overflow-hidden p-0\", className)} showCloseButton={showCloseButton}>\n <Command className=\"[&_[cmdk-group-heading]]:text-muted-foreground **:data-[slot=command-input-wrapper]:h-12 [&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group]]:px-2 [&_[cmdk-group]:not([hidden])_~[cmdk-group]]:pt-0 [&_[cmdk-input-wrapper]_svg]:h-5 [&_[cmdk-input-wrapper]_svg]:w-5 [&_[cmdk-input]]:h-12 [&_[cmdk-item]]:px-2 [&_[cmdk-item]]:py-3 [&_[cmdk-item]_svg]:h-5 [&_[cmdk-item]_svg]:w-5\">\n {children}\n </Command>\n </DialogContent>\n </Dialog>\n );\n}\n\nexport type CommandInputProps = React.ComponentProps<typeof CommandPrimitive.Input>;\n\nfunction CommandInput({ className, ...props }: CommandInputProps) {\n return (\n <div data-slot=\"command-input-wrapper\" className=\"flex h-9 items-center gap-2 border-b px-3\">\n <SearchIcon className=\"size-4 shrink-0 opacity-50\" />\n <CommandPrimitive.Input\n data-slot=\"command-input\"\n className={cn(\n \"placeholder:text-muted-foreground flex h-10 w-full rounded-md bg-transparent py-3 text-sm outline-hidden disabled:cursor-not-allowed disabled:opacity-50\",\n className\n )}\n {...props}\n />\n </div>\n );\n}\n\nexport type CommandListProps = React.ComponentProps<typeof CommandPrimitive.List>;\n\nfunction CommandList({ className, ...props }: CommandListProps) {\n return (\n <CommandPrimitive.List\n data-slot=\"command-list\"\n className={cn(\"max-h-[300px] scroll-py-1 overflow-x-hidden overflow-y-auto\", className)}\n {...props}\n />\n );\n}\n\nexport type CommandEmptyProps = React.ComponentProps<typeof CommandPrimitive.Empty>;\n\nfunction CommandEmpty({ ...props }: CommandEmptyProps) {\n return <CommandPrimitive.Empty data-slot=\"command-empty\" className=\"py-6 text-center text-sm\" {...props} />;\n}\n\nexport type CommandGroupProps = React.ComponentProps<typeof CommandPrimitive.Group>;\n\nfunction CommandGroup({ className, ...props }: CommandGroupProps) {\n return (\n <CommandPrimitive.Group\n data-slot=\"command-group\"\n className={cn(\n \"text-foreground [&_[cmdk-group-heading]]:text-muted-foreground overflow-hidden p-1 [&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:py-1.5 [&_[cmdk-group-heading]]:text-xs [&_[cmdk-group-heading]]:font-medium\",\n className\n )}\n {...props}\n />\n );\n}\n\nexport type CommandSeparatorProps = React.ComponentProps<typeof CommandPrimitive.Separator>;\n\nfunction CommandSeparator({ className, ...props }: CommandSeparatorProps) {\n return (\n <CommandPrimitive.Separator\n data-slot=\"command-separator\"\n className={cn(\"bg-border -mx-1 h-px\", className)}\n {...props}\n />\n );\n}\n\nexport type CommandItemProps = React.ComponentProps<typeof CommandPrimitive.Item>;\n\nfunction CommandItem({ className, ...props }: CommandItemProps) {\n return (\n <CommandPrimitive.Item\n data-slot=\"command-item\"\n className={cn(\n \"data-[selected=true]:bg-accent data-[selected=true]:text-accent-foreground [&_svg:not([class*='text-'])]:text-muted-foreground relative flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden select-none data-[disabled=true]:pointer-events-none data-[disabled=true]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\n className\n )}\n {...props}\n />\n );\n}\n\nexport type CommandShortcutProps = React.ComponentProps<\"span\">;\n\nfunction CommandShortcut({ className, ...props }: CommandShortcutProps) {\n return (\n <span\n data-slot=\"command-shortcut\"\n className={cn(\"text-muted-foreground ml-auto text-xs tracking-widest\", className)}\n {...props}\n />\n );\n}\n\nexport {\n Command,\n CommandDialog,\n CommandEmpty,\n CommandGroup,\n CommandInput,\n CommandItem,\n CommandList,\n CommandSeparator,\n CommandShortcut\n};\n"],"mappings":";AAsBI,cA8BE,YA9BF;AApBJ,SAAS,WAAW,wBAAwB;AAC5C,SAAS,kBAAkB;AAE3B,SAAS,UAAU;AACnB,SAAS,QAAQ,eAAe,mBAAmB,cAAc,mBAAmB;AAcpF,SAAS,QAAQ,EAAE,WAAW,GAAG,MAAM,GAAiB;AACtD,SACE;AAAA,IAAC;AAAA;AAAA,MACC,aAAU;AAAA,MACV,WAAW;AAAA,QACT;AAAA,QACA;AAAA,MACF;AAAA,MACC,GAAG;AAAA;AAAA,EACN;AAEJ;AAWA,SAAS,cAAc;AAAA,EACrB,QAAQ;AAAA,EACR,cAAc;AAAA,EACd;AAAA,EACA;AAAA,EACA,kBAAkB;AAAA,EAClB,GAAG;AACL,GAAuB;AACrB,SACE,qBAAC,UAAQ,GAAG,OACV;AAAA,yBAAC,gBAAa,WAAU,WACtB;AAAA,0BAAC,eAAa,iBAAM;AAAA,MACpB,oBAAC,qBAAmB,uBAAY;AAAA,OAClC;AAAA,IACA,oBAAC,iBAAc,WAAW,GAAG,uBAAuB,SAAS,GAAG,iBAC9D,8BAAC,WAAQ,WAAU,yZAChB,UACH,GACF;AAAA,KACF;AAEJ;AAIA,SAAS,aAAa,EAAE,WAAW,GAAG,MAAM,GAAsB;AAChE,SACE,qBAAC,SAAI,aAAU,yBAAwB,WAAU,6CAC/C;AAAA,wBAAC,cAAW,WAAU,8BAA6B;AAAA,IACnD;AAAA,MAAC,iBAAiB;AAAA,MAAjB;AAAA,QACC,aAAU;AAAA,QACV,WAAW;AAAA,UACT;AAAA,UACA;AAAA,QACF;AAAA,QACC,GAAG;AAAA;AAAA,IACN;AAAA,KACF;AAEJ;AAIA,SAAS,YAAY,EAAE,WAAW,GAAG,MAAM,GAAqB;AAC9D,SACE;AAAA,IAAC,iBAAiB;AAAA,IAAjB;AAAA,MACC,aAAU;AAAA,MACV,WAAW,GAAG,+DAA+D,SAAS;AAAA,MACrF,GAAG;AAAA;AAAA,EACN;AAEJ;AAIA,SAAS,aAAa,EAAE,GAAG,MAAM,GAAsB;AACrD,SAAO,oBAAC,iBAAiB,OAAjB,EAAuB,aAAU,iBAAgB,WAAU,4BAA4B,GAAG,OAAO;AAC3G;AAIA,SAAS,aAAa,EAAE,WAAW,GAAG,MAAM,GAAsB;AAChE,SACE;AAAA,IAAC,iBAAiB;AAAA,IAAjB;AAAA,MACC,aAAU;AAAA,MACV,WAAW;AAAA,QACT;AAAA,QACA;AAAA,MACF;AAAA,MACC,GAAG;AAAA;AAAA,EACN;AAEJ;AAIA,SAAS,iBAAiB,EAAE,WAAW,GAAG,MAAM,GAA0B;AACxE,SACE;AAAA,IAAC,iBAAiB;AAAA,IAAjB;AAAA,MACC,aAAU;AAAA,MACV,WAAW,GAAG,wBAAwB,SAAS;AAAA,MAC9C,GAAG;AAAA;AAAA,EACN;AAEJ;AAIA,SAAS,YAAY,EAAE,WAAW,GAAG,MAAM,GAAqB;AAC9D,SACE;AAAA,IAAC,iBAAiB;AAAA,IAAjB;AAAA,MACC,aAAU;AAAA,MACV,WAAW;AAAA,QACT;AAAA,QACA;AAAA,MACF;AAAA,MACC,GAAG;AAAA;AAAA,EACN;AAEJ;AAIA,SAAS,gBAAgB,EAAE,WAAW,GAAG,MAAM,GAAyB;AACtE,SACE;AAAA,IAAC;AAAA;AAAA,MACC,aAAU;AAAA,MACV,WAAW,GAAG,yDAAyD,SAAS;AAAA,MAC/E,GAAG;AAAA;AAAA,EACN;AAEJ;","names":[]}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import * as ContextMenuPrimitive from '@radix-ui/react-context-menu';
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* ContextMenu — menu chuột phải (Radix ContextMenu).
|
|
6
|
+
*
|
|
7
|
+
* Dùng cho thao tác nhanh trên thẻ task, dòng bảng, mục sidebar. Cấu trúc mục
|
|
8
|
+
* giống `DropdownMenu` (cùng biến thể `destructive`, `inset`) để hai menu nhìn như một.
|
|
9
|
+
* Vì chuột phải không có trên thiết bị cảm ứng, mọi thao tác ở đây phải có đường
|
|
10
|
+
* thay thế (nút "…" mở DropdownMenu).
|
|
11
|
+
*/
|
|
12
|
+
type ContextMenuProps = React.ComponentProps<typeof ContextMenuPrimitive.Root>;
|
|
13
|
+
declare function ContextMenu({ ...props }: ContextMenuProps): React.JSX.Element;
|
|
14
|
+
type ContextMenuTriggerProps = React.ComponentProps<typeof ContextMenuPrimitive.Trigger>;
|
|
15
|
+
declare function ContextMenuTrigger({ ...props }: ContextMenuTriggerProps): React.JSX.Element;
|
|
16
|
+
type ContextMenuGroupProps = React.ComponentProps<typeof ContextMenuPrimitive.Group>;
|
|
17
|
+
declare function ContextMenuGroup({ ...props }: ContextMenuGroupProps): React.JSX.Element;
|
|
18
|
+
type ContextMenuPortalProps = React.ComponentProps<typeof ContextMenuPrimitive.Portal>;
|
|
19
|
+
declare function ContextMenuPortal({ ...props }: ContextMenuPortalProps): React.JSX.Element;
|
|
20
|
+
type ContextMenuSubProps = React.ComponentProps<typeof ContextMenuPrimitive.Sub>;
|
|
21
|
+
declare function ContextMenuSub({ ...props }: ContextMenuSubProps): React.JSX.Element;
|
|
22
|
+
type ContextMenuRadioGroupProps = React.ComponentProps<typeof ContextMenuPrimitive.RadioGroup>;
|
|
23
|
+
declare function ContextMenuRadioGroup({ ...props }: ContextMenuRadioGroupProps): React.JSX.Element;
|
|
24
|
+
type ContextMenuSubTriggerProps = React.ComponentProps<typeof ContextMenuPrimitive.SubTrigger> & {
|
|
25
|
+
inset?: boolean;
|
|
26
|
+
};
|
|
27
|
+
declare function ContextMenuSubTrigger({ className, inset, children, ...props }: ContextMenuSubTriggerProps): React.JSX.Element;
|
|
28
|
+
type ContextMenuSubContentProps = React.ComponentProps<typeof ContextMenuPrimitive.SubContent>;
|
|
29
|
+
declare function ContextMenuSubContent({ className, ...props }: ContextMenuSubContentProps): React.JSX.Element;
|
|
30
|
+
type ContextMenuContentProps = React.ComponentProps<typeof ContextMenuPrimitive.Content>;
|
|
31
|
+
declare function ContextMenuContent({ className, ...props }: ContextMenuContentProps): React.JSX.Element;
|
|
32
|
+
type ContextMenuItemVariant = "default" | "destructive";
|
|
33
|
+
type ContextMenuItemProps = React.ComponentProps<typeof ContextMenuPrimitive.Item> & {
|
|
34
|
+
inset?: boolean;
|
|
35
|
+
variant?: ContextMenuItemVariant;
|
|
36
|
+
};
|
|
37
|
+
declare function ContextMenuItem({ className, inset, variant, ...props }: ContextMenuItemProps): React.JSX.Element;
|
|
38
|
+
type ContextMenuCheckboxItemProps = React.ComponentProps<typeof ContextMenuPrimitive.CheckboxItem>;
|
|
39
|
+
declare function ContextMenuCheckboxItem({ className, children, checked, ...props }: ContextMenuCheckboxItemProps): React.JSX.Element;
|
|
40
|
+
type ContextMenuRadioItemProps = React.ComponentProps<typeof ContextMenuPrimitive.RadioItem>;
|
|
41
|
+
declare function ContextMenuRadioItem({ className, children, ...props }: ContextMenuRadioItemProps): React.JSX.Element;
|
|
42
|
+
type ContextMenuLabelProps = React.ComponentProps<typeof ContextMenuPrimitive.Label> & {
|
|
43
|
+
inset?: boolean;
|
|
44
|
+
};
|
|
45
|
+
declare function ContextMenuLabel({ className, inset, ...props }: ContextMenuLabelProps): React.JSX.Element;
|
|
46
|
+
type ContextMenuSeparatorProps = React.ComponentProps<typeof ContextMenuPrimitive.Separator>;
|
|
47
|
+
declare function ContextMenuSeparator({ className, ...props }: ContextMenuSeparatorProps): React.JSX.Element;
|
|
48
|
+
type ContextMenuShortcutProps = React.ComponentProps<"span">;
|
|
49
|
+
declare function ContextMenuShortcut({ className, ...props }: ContextMenuShortcutProps): React.JSX.Element;
|
|
50
|
+
|
|
51
|
+
export { ContextMenu, ContextMenuCheckboxItem, type ContextMenuCheckboxItemProps, ContextMenuContent, type ContextMenuContentProps, ContextMenuGroup, type ContextMenuGroupProps, ContextMenuItem, type ContextMenuItemProps, type ContextMenuItemVariant, ContextMenuLabel, type ContextMenuLabelProps, ContextMenuPortal, type ContextMenuPortalProps, type ContextMenuProps, ContextMenuRadioGroup, type ContextMenuRadioGroupProps, ContextMenuRadioItem, type ContextMenuRadioItemProps, ContextMenuSeparator, type ContextMenuSeparatorProps, ContextMenuShortcut, type ContextMenuShortcutProps, ContextMenuSub, ContextMenuSubContent, type ContextMenuSubContentProps, type ContextMenuSubProps, ContextMenuSubTrigger, type ContextMenuSubTriggerProps, ContextMenuTrigger, type ContextMenuTriggerProps };
|