@comitor/ui 0.1.0 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +303 -43
- package/dist/chart/chart.d.ts +35 -3
- package/dist/chart/chart.js.map +1 -1
- package/dist/chart/comitor-chart.d.ts +16 -3
- package/dist/chart/comitor-chart.js.map +1 -1
- package/dist/chart/index.d.ts +2 -2
- package/dist/components/composite/avatar-group.js +1 -1
- package/dist/components/composite/avatar-group.js.map +1 -1
- package/dist/components/composite/combobox.d.ts +9 -2
- package/dist/components/composite/combobox.js +9 -2
- package/dist/components/composite/combobox.js.map +1 -1
- package/dist/components/composite/confirm-dialog.js +1 -1
- package/dist/components/composite/confirm-dialog.js.map +1 -1
- package/dist/components/composite/copy-button.js +1 -1
- package/dist/components/composite/copy-button.js.map +1 -1
- package/dist/components/composite/data-table.d.ts +17 -8
- package/dist/components/composite/data-table.js +8 -8
- package/dist/components/composite/data-table.js.map +1 -1
- package/dist/components/composite/filter-chips.js +6 -5
- package/dist/components/composite/filter-chips.js.map +1 -1
- package/dist/components/composite/form-field.js +3 -1
- package/dist/components/composite/form-field.js.map +1 -1
- package/dist/components/composite/form-section.js +5 -5
- package/dist/components/composite/form-section.js.map +1 -1
- package/dist/components/composite/inline-edit.js +1 -1
- package/dist/components/composite/inline-edit.js.map +1 -1
- package/dist/components/composite/keyboard-hint.d.ts +16 -0
- package/dist/components/composite/keyboard-hint.js +8 -6
- package/dist/components/composite/keyboard-hint.js.map +1 -1
- package/dist/components/composite/letter-avatar.d.ts +10 -18
- package/dist/components/composite/letter-avatar.js +6 -17
- package/dist/components/composite/letter-avatar.js.map +1 -1
- package/dist/components/composite/search-filter-bar.d.ts +41 -3
- package/dist/components/composite/search-filter-bar.js +27 -15
- package/dist/components/composite/search-filter-bar.js.map +1 -1
- package/dist/components/composite/stat-card.d.ts +16 -1
- package/dist/components/composite/stat-card.js +16 -9
- package/dist/components/composite/stat-card.js.map +1 -1
- package/dist/components/composite/status-config.d.ts +69 -16
- package/dist/components/composite/status-config.js +10 -10
- package/dist/components/composite/status-config.js.map +1 -1
- package/dist/components/composite/status-pill.js +5 -1
- package/dist/components/composite/status-pill.js.map +1 -1
- package/dist/components/composite/table-pagination.d.ts +46 -4
- package/dist/components/composite/table-pagination.js +27 -24
- package/dist/components/composite/table-pagination.js.map +1 -1
- package/dist/components/composite/text-utils.d.ts +12 -11
- package/dist/components/composite/text-utils.js +7 -16
- package/dist/components/composite/text-utils.js.map +1 -1
- package/dist/components/composite/toast.js +16 -6
- package/dist/components/composite/toast.js.map +1 -1
- package/dist/components/ui/alert.js +1 -1
- package/dist/components/ui/alert.js.map +1 -1
- package/dist/components/ui/badge.js +4 -4
- package/dist/components/ui/badge.js.map +1 -1
- package/dist/components/ui/button.js +3 -3
- package/dist/components/ui/button.js.map +1 -1
- package/dist/components/ui/calendar.d.ts +41 -0
- package/dist/components/ui/calendar.js +1 -1
- package/dist/components/ui/calendar.js.map +1 -1
- package/dist/components/ui/card.d.ts +35 -2
- package/dist/components/ui/card.js +17 -3
- package/dist/components/ui/card.js.map +1 -1
- package/dist/components/ui/checkbox.js +3 -3
- package/dist/components/ui/checkbox.js.map +1 -1
- package/dist/components/ui/command.js +1 -1
- package/dist/components/ui/command.js.map +1 -1
- package/dist/components/ui/context-menu.js +1 -1
- package/dist/components/ui/context-menu.js.map +1 -1
- package/dist/components/ui/drawer.js +1 -1
- package/dist/components/ui/drawer.js.map +1 -1
- package/dist/components/ui/dropdown-menu.js +1 -1
- package/dist/components/ui/dropdown-menu.js.map +1 -1
- package/dist/components/ui/empty.js +1 -1
- package/dist/components/ui/empty.js.map +1 -1
- package/dist/components/ui/field.js +4 -4
- package/dist/components/ui/field.js.map +1 -1
- package/dist/components/ui/form.js +8 -2
- package/dist/components/ui/form.js.map +1 -1
- package/dist/components/ui/input-group.js +3 -3
- package/dist/components/ui/input-group.js.map +1 -1
- package/dist/components/ui/input-otp.js +1 -1
- package/dist/components/ui/input-otp.js.map +1 -1
- package/dist/components/ui/input.js +3 -3
- package/dist/components/ui/input.js.map +1 -1
- package/dist/components/ui/item.js +1 -1
- package/dist/components/ui/item.js.map +1 -1
- package/dist/components/ui/menubar.js +1 -1
- package/dist/components/ui/menubar.js.map +1 -1
- package/dist/components/ui/navigation-menu.js +1 -1
- package/dist/components/ui/navigation-menu.js.map +1 -1
- package/dist/components/ui/pagination.js +1 -1
- package/dist/components/ui/pagination.js.map +1 -1
- package/dist/components/ui/progress.d.ts +26 -0
- package/dist/components/ui/progress.js +5 -2
- package/dist/components/ui/progress.js.map +1 -1
- package/dist/components/ui/radio-group.js +2 -2
- package/dist/components/ui/radio-group.js.map +1 -1
- package/dist/components/ui/resizable.d.ts +14 -0
- package/dist/components/ui/resizable.js +2 -2
- package/dist/components/ui/resizable.js.map +1 -1
- package/dist/components/ui/scroll-area.js +1 -1
- package/dist/components/ui/scroll-area.js.map +1 -1
- package/dist/components/ui/select.d.ts +33 -0
- package/dist/components/ui/select.js +3 -3
- package/dist/components/ui/select.js.map +1 -1
- package/dist/components/ui/slider.d.ts +19 -0
- package/dist/components/ui/slider.js +3 -3
- package/dist/components/ui/slider.js.map +1 -1
- package/dist/components/ui/sonner.d.ts +21 -3
- package/dist/components/ui/sonner.js +1 -2
- package/dist/components/ui/sonner.js.map +1 -1
- package/dist/components/ui/switch.js +2 -2
- package/dist/components/ui/switch.js.map +1 -1
- package/dist/components/ui/table.d.ts +16 -0
- package/dist/components/ui/table.js +1 -1
- package/dist/components/ui/table.js.map +1 -1
- package/dist/components/ui/tabs.js +1 -1
- package/dist/components/ui/tabs.js.map +1 -1
- package/dist/components/ui/textarea.js +1 -1
- package/dist/components/ui/textarea.js.map +1 -1
- package/dist/components/ui/toggle.js +1 -1
- package/dist/components/ui/toggle.js.map +1 -1
- package/dist/index.d.ts +6 -5
- package/dist/index.js +17 -2
- package/dist/index.js.map +1 -1
- package/dist/lib/avatar-tone.d.ts +126 -0
- package/dist/lib/avatar-tone.js +68 -0
- package/dist/lib/avatar-tone.js.map +1 -0
- package/dist/shell/app-header.js +12 -2
- package/dist/shell/app-header.js.map +1 -1
- package/dist/shell/app-launcher.js +2 -2
- package/dist/shell/app-launcher.js.map +1 -1
- package/dist/shell/app-shell.d.ts +2 -0
- package/dist/shell/index.d.ts +3 -3
- package/dist/shell/shell-context.d.ts +29 -8
- package/dist/shell/shell-context.js +6 -20
- package/dist/shell/shell-context.js.map +1 -1
- package/dist/shell/sidebar-group.js +5 -3
- package/dist/shell/sidebar-group.js.map +1 -1
- package/dist/shell/sidebar-menu-item.js +15 -7
- package/dist/shell/sidebar-menu-item.js.map +1 -1
- package/dist/shell/types.d.ts +17 -1
- package/dist/shell/types.js.map +1 -1
- package/dist/shell/user-menu.js +3 -2
- package/dist/shell/user-menu.js.map +1 -1
- package/dist/shell/utils.d.ts +36 -24
- package/dist/shell/utils.js +55 -20
- package/dist/shell/utils.js.map +1 -1
- package/dist/shell/workspace-switcher.js +23 -8
- package/dist/shell/workspace-switcher.js.map +1 -1
- package/dist/tokens.d.ts +165 -17
- package/dist/tokens.js +122 -25
- package/dist/tokens.js.map +1 -1
- package/package.json +8 -5
- package/styles.css +312 -22
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/components/ui/dropdown-menu.tsx"],"sourcesContent":["\"use client\";\n\nimport * as DropdownMenuPrimitive from \"@radix-ui/react-dropdown-menu\";\nimport { CheckIcon, ChevronRightIcon, CircleIcon } from \"lucide-react\";\nimport type * as React from \"react\";\nimport { cn } from \"../../lib/cn.js\";\n\n/**\n * DropdownMenu — menu bung ra từ một nút (Radix DropdownMenu).\n *\n * Xương sống của UserMenu, menu thao tác trên dòng bảng, WorkspaceSwitcher.\n * `DropdownMenuItem` có `variant=\"destructive\"` cho mục nguy hiểm (Xóa, Đăng xuất)\n * và `inset` để thụt lề cho ngang hàng với mục có icon chọn.\n */\n\nexport type DropdownMenuProps = React.ComponentProps<typeof DropdownMenuPrimitive.Root>;\n\nfunction DropdownMenu({ ...props }: DropdownMenuProps) {\n return <DropdownMenuPrimitive.Root data-slot=\"dropdown-menu\" {...props} />;\n}\n\nexport type DropdownMenuPortalProps = React.ComponentProps<typeof DropdownMenuPrimitive.Portal>;\n\nfunction DropdownMenuPortal({ ...props }: DropdownMenuPortalProps) {\n return <DropdownMenuPrimitive.Portal data-slot=\"dropdown-menu-portal\" {...props} />;\n}\n\nexport type DropdownMenuTriggerProps = React.ComponentProps<typeof DropdownMenuPrimitive.Trigger>;\n\nfunction DropdownMenuTrigger({ ...props }: DropdownMenuTriggerProps) {\n return <DropdownMenuPrimitive.Trigger data-slot=\"dropdown-menu-trigger\" {...props} />;\n}\n\nexport type DropdownMenuContentProps = React.ComponentProps<typeof DropdownMenuPrimitive.Content>;\n\nfunction DropdownMenuContent({ className, sideOffset = 4, ...props }: DropdownMenuContentProps) {\n return (\n <DropdownMenuPrimitive.Portal>\n <DropdownMenuPrimitive.Content\n data-slot=\"dropdown-menu-content\"\n sideOffset={sideOffset}\n className={cn(\n \"bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 max-h-(--radix-dropdown-menu-content-available-height) min-w-[8rem] origin-(--radix-dropdown-menu-content-transform-origin) overflow-x-hidden overflow-y-auto rounded-md border p-1 shadow-overlay\",\n className\n )}\n {...props}\n />\n </DropdownMenuPrimitive.Portal>\n );\n}\n\nexport type DropdownMenuGroupProps = React.ComponentProps<typeof DropdownMenuPrimitive.Group>;\n\nfunction DropdownMenuGroup({ ...props }: DropdownMenuGroupProps) {\n return <DropdownMenuPrimitive.Group data-slot=\"dropdown-menu-group\" {...props} />;\n}\n\nexport type DropdownMenuItemVariant = \"default\" | \"destructive\";\n\nexport type DropdownMenuItemProps = React.ComponentProps<typeof DropdownMenuPrimitive.Item> & {\n /** Thụt lề trái để thẳng hàng với mục có ô đánh dấu. */\n inset?: boolean;\n /** \"destructive\" tô đỏ cho thao tác nguy hiểm. Mặc định \"default\". */\n variant?: DropdownMenuItemVariant;\n};\n\nfunction DropdownMenuItem({ className, inset, variant = \"default\", ...props }: DropdownMenuItemProps) {\n return (\n <DropdownMenuPrimitive.Item\n data-slot=\"dropdown-menu-item\"\n data-inset={inset}\n data-variant={variant}\n className={cn(\n \"focus:bg-accent focus:text-accent-foreground data-[variant=destructive]:text-destructive data-[variant=destructive]:focus:bg-destructive/10 dark:data-[variant=destructive]:focus:bg-destructive/20 data-[variant=destructive]:focus:text-destructive data-[variant=destructive]:*:[svg]:!text-destructive [&_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]:pointer-events-none data-[disabled]:opacity-50 data-[inset]:pl-8 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\n className\n )}\n {...props}\n />\n );\n}\n\nexport type DropdownMenuCheckboxItemProps = React.ComponentProps<typeof DropdownMenuPrimitive.CheckboxItem>;\n\nfunction DropdownMenuCheckboxItem({ className, children, checked, ...props }: DropdownMenuCheckboxItemProps) {\n return (\n <DropdownMenuPrimitive.CheckboxItem\n data-slot=\"dropdown-menu-checkbox-item\"\n className={cn(\n \"focus:bg-accent focus:text-accent-foreground relative flex cursor-default items-center gap-2 rounded-sm py-1.5 pr-2 pl-8 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\n className\n )}\n checked={checked}\n {...props}\n >\n <span className=\"pointer-events-none absolute left-2 flex size-3.5 items-center justify-center\">\n <DropdownMenuPrimitive.ItemIndicator>\n <CheckIcon className=\"size-4\" />\n </DropdownMenuPrimitive.ItemIndicator>\n </span>\n {children}\n </DropdownMenuPrimitive.CheckboxItem>\n );\n}\n\nexport type DropdownMenuRadioGroupProps = React.ComponentProps<typeof DropdownMenuPrimitive.RadioGroup>;\n\nfunction DropdownMenuRadioGroup({ ...props }: DropdownMenuRadioGroupProps) {\n return <DropdownMenuPrimitive.RadioGroup data-slot=\"dropdown-menu-radio-group\" {...props} />;\n}\n\nexport type DropdownMenuRadioItemProps = React.ComponentProps<typeof DropdownMenuPrimitive.RadioItem>;\n\nfunction DropdownMenuRadioItem({ className, children, ...props }: DropdownMenuRadioItemProps) {\n return (\n <DropdownMenuPrimitive.RadioItem\n data-slot=\"dropdown-menu-radio-item\"\n className={cn(\n \"focus:bg-accent focus:text-accent-foreground relative flex cursor-default items-center gap-2 rounded-sm py-1.5 pr-2 pl-8 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\n className\n )}\n {...props}\n >\n <span className=\"pointer-events-none absolute left-2 flex size-3.5 items-center justify-center\">\n <DropdownMenuPrimitive.ItemIndicator>\n <CircleIcon className=\"size-2 fill-current\" />\n </DropdownMenuPrimitive.ItemIndicator>\n </span>\n {children}\n </DropdownMenuPrimitive.RadioItem>\n );\n}\n\nexport type DropdownMenuLabelProps = React.ComponentProps<typeof DropdownMenuPrimitive.Label> & {\n inset?: boolean;\n};\n\nfunction DropdownMenuLabel({ className, inset, ...props }: DropdownMenuLabelProps) {\n return (\n <DropdownMenuPrimitive.Label\n data-slot=\"dropdown-menu-label\"\n data-inset={inset}\n className={cn(\"px-2 py-1.5 text-sm font-medium data-[inset]:pl-8\", className)}\n {...props}\n />\n );\n}\n\nexport type DropdownMenuSeparatorProps = React.ComponentProps<typeof DropdownMenuPrimitive.Separator>;\n\nfunction DropdownMenuSeparator({ className, ...props }: DropdownMenuSeparatorProps) {\n return (\n <DropdownMenuPrimitive.Separator\n data-slot=\"dropdown-menu-separator\"\n className={cn(\"bg-border -mx-1 my-1 h-px\", className)}\n {...props}\n />\n );\n}\n\nexport type DropdownMenuShortcutProps = React.ComponentProps<\"span\">;\n\nfunction DropdownMenuShortcut({ className, ...props }: DropdownMenuShortcutProps) {\n return (\n <span\n data-slot=\"dropdown-menu-shortcut\"\n className={cn(\"text-muted-foreground ml-auto text-xs tracking-widest\", className)}\n {...props}\n />\n );\n}\n\nexport type DropdownMenuSubProps = React.ComponentProps<typeof DropdownMenuPrimitive.Sub>;\n\nfunction DropdownMenuSub({ ...props }: DropdownMenuSubProps) {\n return <DropdownMenuPrimitive.Sub data-slot=\"dropdown-menu-sub\" {...props} />;\n}\n\nexport type DropdownMenuSubTriggerProps = React.ComponentProps<typeof DropdownMenuPrimitive.SubTrigger> & {\n inset?: boolean;\n};\n\nfunction DropdownMenuSubTrigger({ className, inset, children, ...props }: DropdownMenuSubTriggerProps) {\n return (\n <DropdownMenuPrimitive.SubTrigger\n data-slot=\"dropdown-menu-sub-trigger\"\n data-inset={inset}\n className={cn(\n \"focus:bg-accent focus:text-accent-foreground data-[state=open]:bg-accent data-[state=open]:text-accent-foreground [&_svg:not([class*='text-'])]:text-muted-foreground flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden select-none data-[inset]:pl-8 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\n className\n )}\n {...props}\n >\n {children}\n <ChevronRightIcon className=\"ml-auto size-4\" />\n </DropdownMenuPrimitive.SubTrigger>\n );\n}\n\nexport type DropdownMenuSubContentProps = React.ComponentProps<typeof DropdownMenuPrimitive.SubContent>;\n\nfunction DropdownMenuSubContent({ className, ...props }: DropdownMenuSubContentProps) {\n return (\n <DropdownMenuPrimitive.SubContent\n data-slot=\"dropdown-menu-sub-content\"\n className={cn(\n \"bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 min-w-[8rem] origin-(--radix-dropdown-menu-content-transform-origin) overflow-hidden rounded-md border p-1 shadow-overlay\",\n className\n )}\n {...props}\n />\n );\n}\n\nexport {\n DropdownMenu,\n DropdownMenuCheckboxItem,\n DropdownMenuContent,\n DropdownMenuGroup,\n DropdownMenuItem,\n DropdownMenuLabel,\n DropdownMenuPortal,\n DropdownMenuRadioGroup,\n DropdownMenuRadioItem,\n DropdownMenuSeparator,\n DropdownMenuShortcut,\n DropdownMenuSub,\n DropdownMenuSubContent,\n DropdownMenuSubTrigger,\n DropdownMenuTrigger\n};\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../src/components/ui/dropdown-menu.tsx"],"sourcesContent":["\"use client\";\n\nimport * as DropdownMenuPrimitive from \"@radix-ui/react-dropdown-menu\";\nimport { CheckIcon, ChevronRightIcon, CircleIcon } from \"lucide-react\";\nimport type * as React from \"react\";\nimport { cn } from \"../../lib/cn.js\";\n\n/**\n * DropdownMenu — menu bung ra từ một nút (Radix DropdownMenu).\n *\n * Xương sống của UserMenu, menu thao tác trên dòng bảng, WorkspaceSwitcher.\n * `DropdownMenuItem` có `variant=\"destructive\"` cho mục nguy hiểm (Xóa, Đăng xuất)\n * và `inset` để thụt lề cho ngang hàng với mục có icon chọn.\n */\n\nexport type DropdownMenuProps = React.ComponentProps<typeof DropdownMenuPrimitive.Root>;\n\nfunction DropdownMenu({ ...props }: DropdownMenuProps) {\n return <DropdownMenuPrimitive.Root data-slot=\"dropdown-menu\" {...props} />;\n}\n\nexport type DropdownMenuPortalProps = React.ComponentProps<typeof DropdownMenuPrimitive.Portal>;\n\nfunction DropdownMenuPortal({ ...props }: DropdownMenuPortalProps) {\n return <DropdownMenuPrimitive.Portal data-slot=\"dropdown-menu-portal\" {...props} />;\n}\n\nexport type DropdownMenuTriggerProps = React.ComponentProps<typeof DropdownMenuPrimitive.Trigger>;\n\nfunction DropdownMenuTrigger({ ...props }: DropdownMenuTriggerProps) {\n return <DropdownMenuPrimitive.Trigger data-slot=\"dropdown-menu-trigger\" {...props} />;\n}\n\nexport type DropdownMenuContentProps = React.ComponentProps<typeof DropdownMenuPrimitive.Content>;\n\nfunction DropdownMenuContent({ className, sideOffset = 4, ...props }: DropdownMenuContentProps) {\n return (\n <DropdownMenuPrimitive.Portal>\n <DropdownMenuPrimitive.Content\n data-slot=\"dropdown-menu-content\"\n sideOffset={sideOffset}\n className={cn(\n \"bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 max-h-(--radix-dropdown-menu-content-available-height) min-w-[8rem] origin-(--radix-dropdown-menu-content-transform-origin) overflow-x-hidden overflow-y-auto rounded-md border p-1 shadow-overlay\",\n className\n )}\n {...props}\n />\n </DropdownMenuPrimitive.Portal>\n );\n}\n\nexport type DropdownMenuGroupProps = React.ComponentProps<typeof DropdownMenuPrimitive.Group>;\n\nfunction DropdownMenuGroup({ ...props }: DropdownMenuGroupProps) {\n return <DropdownMenuPrimitive.Group data-slot=\"dropdown-menu-group\" {...props} />;\n}\n\nexport type DropdownMenuItemVariant = \"default\" | \"destructive\";\n\nexport type DropdownMenuItemProps = React.ComponentProps<typeof DropdownMenuPrimitive.Item> & {\n /** Thụt lề trái để thẳng hàng với mục có ô đánh dấu. */\n inset?: boolean;\n /** \"destructive\" tô đỏ cho thao tác nguy hiểm. Mặc định \"default\". */\n variant?: DropdownMenuItemVariant;\n};\n\nfunction DropdownMenuItem({ className, inset, variant = \"default\", ...props }: DropdownMenuItemProps) {\n return (\n <DropdownMenuPrimitive.Item\n data-slot=\"dropdown-menu-item\"\n data-inset={inset}\n data-variant={variant}\n // `text-destructive-ink` chứ KHÔNG `text-destructive`: `--destructive` là màu NỀN (nút xoá),\n // ghim một giá trị cho cả hai theme nên làm CHỮ trên nền popover tối chỉ được 3,53:1 ✗ —\n // và tệ thêm khi focus vì nền chuyển sang `bg-destructive/20` (2,98:1 ✗). Bậc ink đạt cả\n // hai theme, cả hai nền: 7,15:1 / 6,18:1 (light, nghỉ / focus) · 6,42:1 / 5,42:1 (dark).\n className={cn(\n \"focus:bg-accent focus:text-accent-foreground data-[variant=destructive]:text-destructive-ink data-[variant=destructive]:focus:bg-destructive/10 dark:data-[variant=destructive]:focus:bg-destructive/20 data-[variant=destructive]:focus:text-destructive-ink data-[variant=destructive]:*:[svg]:!text-destructive-ink [&_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]:pointer-events-none data-[disabled]:opacity-50 data-[inset]:pl-8 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\n className\n )}\n {...props}\n />\n );\n}\n\nexport type DropdownMenuCheckboxItemProps = React.ComponentProps<typeof DropdownMenuPrimitive.CheckboxItem>;\n\nfunction DropdownMenuCheckboxItem({ className, children, checked, ...props }: DropdownMenuCheckboxItemProps) {\n return (\n <DropdownMenuPrimitive.CheckboxItem\n data-slot=\"dropdown-menu-checkbox-item\"\n className={cn(\n \"focus:bg-accent focus:text-accent-foreground relative flex cursor-default items-center gap-2 rounded-sm py-1.5 pr-2 pl-8 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\n className\n )}\n checked={checked}\n {...props}\n >\n <span className=\"pointer-events-none absolute left-2 flex size-3.5 items-center justify-center\">\n <DropdownMenuPrimitive.ItemIndicator>\n <CheckIcon className=\"size-4\" />\n </DropdownMenuPrimitive.ItemIndicator>\n </span>\n {children}\n </DropdownMenuPrimitive.CheckboxItem>\n );\n}\n\nexport type DropdownMenuRadioGroupProps = React.ComponentProps<typeof DropdownMenuPrimitive.RadioGroup>;\n\nfunction DropdownMenuRadioGroup({ ...props }: DropdownMenuRadioGroupProps) {\n return <DropdownMenuPrimitive.RadioGroup data-slot=\"dropdown-menu-radio-group\" {...props} />;\n}\n\nexport type DropdownMenuRadioItemProps = React.ComponentProps<typeof DropdownMenuPrimitive.RadioItem>;\n\nfunction DropdownMenuRadioItem({ className, children, ...props }: DropdownMenuRadioItemProps) {\n return (\n <DropdownMenuPrimitive.RadioItem\n data-slot=\"dropdown-menu-radio-item\"\n className={cn(\n \"focus:bg-accent focus:text-accent-foreground relative flex cursor-default items-center gap-2 rounded-sm py-1.5 pr-2 pl-8 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\n className\n )}\n {...props}\n >\n <span className=\"pointer-events-none absolute left-2 flex size-3.5 items-center justify-center\">\n <DropdownMenuPrimitive.ItemIndicator>\n <CircleIcon className=\"size-2 fill-current\" />\n </DropdownMenuPrimitive.ItemIndicator>\n </span>\n {children}\n </DropdownMenuPrimitive.RadioItem>\n );\n}\n\nexport type DropdownMenuLabelProps = React.ComponentProps<typeof DropdownMenuPrimitive.Label> & {\n inset?: boolean;\n};\n\nfunction DropdownMenuLabel({ className, inset, ...props }: DropdownMenuLabelProps) {\n return (\n <DropdownMenuPrimitive.Label\n data-slot=\"dropdown-menu-label\"\n data-inset={inset}\n className={cn(\"px-2 py-1.5 text-sm font-medium data-[inset]:pl-8\", className)}\n {...props}\n />\n );\n}\n\nexport type DropdownMenuSeparatorProps = React.ComponentProps<typeof DropdownMenuPrimitive.Separator>;\n\nfunction DropdownMenuSeparator({ className, ...props }: DropdownMenuSeparatorProps) {\n return (\n <DropdownMenuPrimitive.Separator\n data-slot=\"dropdown-menu-separator\"\n className={cn(\"bg-border -mx-1 my-1 h-px\", className)}\n {...props}\n />\n );\n}\n\nexport type DropdownMenuShortcutProps = React.ComponentProps<\"span\">;\n\nfunction DropdownMenuShortcut({ className, ...props }: DropdownMenuShortcutProps) {\n return (\n <span\n data-slot=\"dropdown-menu-shortcut\"\n className={cn(\"text-muted-foreground ml-auto text-xs tracking-widest\", className)}\n {...props}\n />\n );\n}\n\nexport type DropdownMenuSubProps = React.ComponentProps<typeof DropdownMenuPrimitive.Sub>;\n\nfunction DropdownMenuSub({ ...props }: DropdownMenuSubProps) {\n return <DropdownMenuPrimitive.Sub data-slot=\"dropdown-menu-sub\" {...props} />;\n}\n\nexport type DropdownMenuSubTriggerProps = React.ComponentProps<typeof DropdownMenuPrimitive.SubTrigger> & {\n inset?: boolean;\n};\n\nfunction DropdownMenuSubTrigger({ className, inset, children, ...props }: DropdownMenuSubTriggerProps) {\n return (\n <DropdownMenuPrimitive.SubTrigger\n data-slot=\"dropdown-menu-sub-trigger\"\n data-inset={inset}\n className={cn(\n \"focus:bg-accent focus:text-accent-foreground data-[state=open]:bg-accent data-[state=open]:text-accent-foreground [&_svg:not([class*='text-'])]:text-muted-foreground flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden select-none data-[inset]:pl-8 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\n className\n )}\n {...props}\n >\n {children}\n <ChevronRightIcon className=\"ml-auto size-4\" />\n </DropdownMenuPrimitive.SubTrigger>\n );\n}\n\nexport type DropdownMenuSubContentProps = React.ComponentProps<typeof DropdownMenuPrimitive.SubContent>;\n\nfunction DropdownMenuSubContent({ className, ...props }: DropdownMenuSubContentProps) {\n return (\n <DropdownMenuPrimitive.SubContent\n data-slot=\"dropdown-menu-sub-content\"\n className={cn(\n \"bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 min-w-[8rem] origin-(--radix-dropdown-menu-content-transform-origin) overflow-hidden rounded-md border p-1 shadow-overlay\",\n className\n )}\n {...props}\n />\n );\n}\n\nexport {\n DropdownMenu,\n DropdownMenuCheckboxItem,\n DropdownMenuContent,\n DropdownMenuGroup,\n DropdownMenuItem,\n DropdownMenuLabel,\n DropdownMenuPortal,\n DropdownMenuRadioGroup,\n DropdownMenuRadioItem,\n DropdownMenuSeparator,\n DropdownMenuShortcut,\n DropdownMenuSub,\n DropdownMenuSubContent,\n DropdownMenuSubTrigger,\n DropdownMenuTrigger\n};\n"],"mappings":"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","names":[]}
|
|
@@ -58,7 +58,7 @@ function EmptyDescription({ className, ...props }) {
|
|
|
58
58
|
{
|
|
59
59
|
"data-slot": "empty-description",
|
|
60
60
|
className: cn(
|
|
61
|
-
"text-muted-foreground [&>a:hover]:text-primary text-sm/relaxed [&>a]:underline [&>a]:underline-offset-4",
|
|
61
|
+
"text-muted-foreground [&>a:hover]:text-primary-ink text-sm/relaxed [&>a]:underline [&>a]:underline-offset-4",
|
|
62
62
|
className
|
|
63
63
|
),
|
|
64
64
|
...props
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/components/ui/empty.tsx"],"sourcesContent":["import { cva, type VariantProps } from \"class-variance-authority\";\nimport type * as React from \"react\";\nimport { cn } from \"../../lib/cn.js\";\n\nexport type EmptyProps = React.ComponentProps<\"div\">;\nexport type EmptyHeaderProps = React.ComponentProps<\"div\">;\nexport type EmptyTitleProps = React.ComponentProps<\"div\">;\nexport type EmptyDescriptionProps = React.ComponentProps<\"div\">;\nexport type EmptyContentProps = React.ComponentProps<\"div\">;\n\nfunction Empty({ className, ...props }: EmptyProps) {\n return (\n <div\n data-slot=\"empty\"\n className={cn(\n \"flex min-w-0 flex-1 flex-col items-center justify-center gap-6 rounded-lg border-dashed p-6 text-center text-balance md:p-12\",\n className\n )}\n {...props}\n />\n );\n}\n\nfunction EmptyHeader({ className, ...props }: EmptyHeaderProps) {\n return (\n <div\n data-slot=\"empty-header\"\n className={cn(\"flex max-w-sm flex-col items-center gap-2 text-center\", className)}\n {...props}\n />\n );\n}\n\nconst emptyMediaVariants = cva(\n \"flex shrink-0 items-center justify-center mb-2 [&_svg]:pointer-events-none [&_svg]:shrink-0\",\n {\n variants: {\n variant: {\n default: \"bg-transparent\",\n icon: \"bg-muted text-foreground flex size-10 shrink-0 items-center justify-center rounded-lg [&_svg:not([class*='size-'])]:size-6\"\n }\n },\n defaultVariants: {\n variant: \"default\"\n }\n }\n);\n\nexport interface EmptyMediaProps extends React.ComponentProps<\"div\">, VariantProps<typeof emptyMediaVariants> {}\n\nfunction EmptyMedia({ className, variant = \"default\", ...props }: EmptyMediaProps) {\n return (\n <div\n data-slot=\"empty-icon\"\n data-variant={variant}\n className={cn(emptyMediaVariants({ variant, className }))}\n {...props}\n />\n );\n}\n\nfunction EmptyTitle({ className, ...props }: EmptyTitleProps) {\n return <div data-slot=\"empty-title\" className={cn(\"text-lg font-medium tracking-tight\", className)} {...props} />;\n}\n\nfunction EmptyDescription({ className, ...props }: EmptyDescriptionProps) {\n return (\n <div\n data-slot=\"empty-description\"\n className={cn(\n \"text-muted-foreground [&>a:hover]:text-primary text-sm/relaxed [&>a]:underline [&>a]:underline-offset-4\",\n className\n )}\n {...props}\n />\n );\n}\n\nfunction EmptyContent({ className, ...props }: EmptyContentProps) {\n return (\n <div\n data-slot=\"empty-content\"\n className={cn(\"flex w-full max-w-sm min-w-0 flex-col items-center gap-4 text-sm text-balance\", className)}\n {...props}\n />\n );\n}\n\nexport { Empty, EmptyContent, EmptyDescription, EmptyHeader, EmptyMedia, EmptyTitle, emptyMediaVariants };\n"],"mappings":"AAYI;AAZJ,SAAS,WAA8B;AAEvC,SAAS,UAAU;AAQnB,SAAS,MAAM,EAAE,WAAW,GAAG,MAAM,GAAe;AAClD,SACE;AAAA,IAAC;AAAA;AAAA,MACC,aAAU;AAAA,MACV,WAAW;AAAA,QACT;AAAA,QACA;AAAA,MACF;AAAA,MACC,GAAG;AAAA;AAAA,EACN;AAEJ;AAEA,SAAS,YAAY,EAAE,WAAW,GAAG,MAAM,GAAqB;AAC9D,SACE;AAAA,IAAC;AAAA;AAAA,MACC,aAAU;AAAA,MACV,WAAW,GAAG,yDAAyD,SAAS;AAAA,MAC/E,GAAG;AAAA;AAAA,EACN;AAEJ;AAEA,MAAM,qBAAqB;AAAA,EACzB;AAAA,EACA;AAAA,IACE,UAAU;AAAA,MACR,SAAS;AAAA,QACP,SAAS;AAAA,QACT,MAAM;AAAA,MACR;AAAA,IACF;AAAA,IACA,iBAAiB;AAAA,MACf,SAAS;AAAA,IACX;AAAA,EACF;AACF;AAIA,SAAS,WAAW,EAAE,WAAW,UAAU,WAAW,GAAG,MAAM,GAAoB;AACjF,SACE;AAAA,IAAC;AAAA;AAAA,MACC,aAAU;AAAA,MACV,gBAAc;AAAA,MACd,WAAW,GAAG,mBAAmB,EAAE,SAAS,UAAU,CAAC,CAAC;AAAA,MACvD,GAAG;AAAA;AAAA,EACN;AAEJ;AAEA,SAAS,WAAW,EAAE,WAAW,GAAG,MAAM,GAAoB;AAC5D,SAAO,oBAAC,SAAI,aAAU,eAAc,WAAW,GAAG,sCAAsC,SAAS,GAAI,GAAG,OAAO;AACjH;AAEA,SAAS,iBAAiB,EAAE,WAAW,GAAG,MAAM,GAA0B;AACxE,SACE;AAAA,IAAC;AAAA;AAAA,MACC,aAAU;AAAA,MACV,WAAW;AAAA,QACT;AAAA,QACA;AAAA,MACF;AAAA,MACC,GAAG;AAAA;AAAA,EACN;AAEJ;AAEA,SAAS,aAAa,EAAE,WAAW,GAAG,MAAM,GAAsB;AAChE,SACE;AAAA,IAAC;AAAA;AAAA,MACC,aAAU;AAAA,MACV,WAAW,GAAG,iFAAiF,SAAS;AAAA,MACvG,GAAG;AAAA;AAAA,EACN;AAEJ;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../src/components/ui/empty.tsx"],"sourcesContent":["import { cva, type VariantProps } from \"class-variance-authority\";\nimport type * as React from \"react\";\nimport { cn } from \"../../lib/cn.js\";\n\nexport type EmptyProps = React.ComponentProps<\"div\">;\nexport type EmptyHeaderProps = React.ComponentProps<\"div\">;\nexport type EmptyTitleProps = React.ComponentProps<\"div\">;\nexport type EmptyDescriptionProps = React.ComponentProps<\"div\">;\nexport type EmptyContentProps = React.ComponentProps<\"div\">;\n\nfunction Empty({ className, ...props }: EmptyProps) {\n return (\n <div\n data-slot=\"empty\"\n className={cn(\n \"flex min-w-0 flex-1 flex-col items-center justify-center gap-6 rounded-lg border-dashed p-6 text-center text-balance md:p-12\",\n className\n )}\n {...props}\n />\n );\n}\n\nfunction EmptyHeader({ className, ...props }: EmptyHeaderProps) {\n return (\n <div\n data-slot=\"empty-header\"\n className={cn(\"flex max-w-sm flex-col items-center gap-2 text-center\", className)}\n {...props}\n />\n );\n}\n\nconst emptyMediaVariants = cva(\n \"flex shrink-0 items-center justify-center mb-2 [&_svg]:pointer-events-none [&_svg]:shrink-0\",\n {\n variants: {\n variant: {\n default: \"bg-transparent\",\n icon: \"bg-muted text-foreground flex size-10 shrink-0 items-center justify-center rounded-lg [&_svg:not([class*='size-'])]:size-6\"\n }\n },\n defaultVariants: {\n variant: \"default\"\n }\n }\n);\n\nexport interface EmptyMediaProps extends React.ComponentProps<\"div\">, VariantProps<typeof emptyMediaVariants> {}\n\nfunction EmptyMedia({ className, variant = \"default\", ...props }: EmptyMediaProps) {\n return (\n <div\n data-slot=\"empty-icon\"\n data-variant={variant}\n className={cn(emptyMediaVariants({ variant, className }))}\n {...props}\n />\n );\n}\n\nfunction EmptyTitle({ className, ...props }: EmptyTitleProps) {\n return <div data-slot=\"empty-title\" className={cn(\"text-lg font-medium tracking-tight\", className)} {...props} />;\n}\n\nfunction EmptyDescription({ className, ...props }: EmptyDescriptionProps) {\n return (\n <div\n data-slot=\"empty-description\"\n className={cn(\n \"text-muted-foreground [&>a:hover]:text-primary-ink text-sm/relaxed [&>a]:underline [&>a]:underline-offset-4\",\n className\n )}\n {...props}\n />\n );\n}\n\nfunction EmptyContent({ className, ...props }: EmptyContentProps) {\n return (\n <div\n data-slot=\"empty-content\"\n className={cn(\"flex w-full max-w-sm min-w-0 flex-col items-center gap-4 text-sm text-balance\", className)}\n {...props}\n />\n );\n}\n\nexport { Empty, EmptyContent, EmptyDescription, EmptyHeader, EmptyMedia, EmptyTitle, emptyMediaVariants };\n"],"mappings":"AAYI;AAZJ,SAAS,WAA8B;AAEvC,SAAS,UAAU;AAQnB,SAAS,MAAM,EAAE,WAAW,GAAG,MAAM,GAAe;AAClD,SACE;AAAA,IAAC;AAAA;AAAA,MACC,aAAU;AAAA,MACV,WAAW;AAAA,QACT;AAAA,QACA;AAAA,MACF;AAAA,MACC,GAAG;AAAA;AAAA,EACN;AAEJ;AAEA,SAAS,YAAY,EAAE,WAAW,GAAG,MAAM,GAAqB;AAC9D,SACE;AAAA,IAAC;AAAA;AAAA,MACC,aAAU;AAAA,MACV,WAAW,GAAG,yDAAyD,SAAS;AAAA,MAC/E,GAAG;AAAA;AAAA,EACN;AAEJ;AAEA,MAAM,qBAAqB;AAAA,EACzB;AAAA,EACA;AAAA,IACE,UAAU;AAAA,MACR,SAAS;AAAA,QACP,SAAS;AAAA,QACT,MAAM;AAAA,MACR;AAAA,IACF;AAAA,IACA,iBAAiB;AAAA,MACf,SAAS;AAAA,IACX;AAAA,EACF;AACF;AAIA,SAAS,WAAW,EAAE,WAAW,UAAU,WAAW,GAAG,MAAM,GAAoB;AACjF,SACE;AAAA,IAAC;AAAA;AAAA,MACC,aAAU;AAAA,MACV,gBAAc;AAAA,MACd,WAAW,GAAG,mBAAmB,EAAE,SAAS,UAAU,CAAC,CAAC;AAAA,MACvD,GAAG;AAAA;AAAA,EACN;AAEJ;AAEA,SAAS,WAAW,EAAE,WAAW,GAAG,MAAM,GAAoB;AAC5D,SAAO,oBAAC,SAAI,aAAU,eAAc,WAAW,GAAG,sCAAsC,SAAS,GAAI,GAAG,OAAO;AACjH;AAEA,SAAS,iBAAiB,EAAE,WAAW,GAAG,MAAM,GAA0B;AACxE,SACE;AAAA,IAAC;AAAA;AAAA,MACC,aAAU;AAAA,MACV,WAAW;AAAA,QACT;AAAA,QACA;AAAA,MACF;AAAA,MACC,GAAG;AAAA;AAAA,EACN;AAEJ;AAEA,SAAS,aAAa,EAAE,WAAW,GAAG,MAAM,GAAsB;AAChE,SACE;AAAA,IAAC;AAAA;AAAA,MACC,aAAU;AAAA,MACV,WAAW,GAAG,iFAAiF,SAAS;AAAA,MACvG,GAAG;AAAA;AAAA,EACN;AAEJ;","names":[]}
|
|
@@ -43,7 +43,7 @@ function FieldGroup({ className, ...props }) {
|
|
|
43
43
|
}
|
|
44
44
|
);
|
|
45
45
|
}
|
|
46
|
-
const fieldVariants = cva("group/field flex w-full data-[invalid=true]:text-destructive", {
|
|
46
|
+
const fieldVariants = cva("group/field flex w-full data-[invalid=true]:text-destructive-ink", {
|
|
47
47
|
variants: {
|
|
48
48
|
orientation: {
|
|
49
49
|
vertical: ["flex-col gap-2 [&>*]:w-full [&>.sr-only]:w-auto"],
|
|
@@ -93,7 +93,7 @@ function FieldLabel({ className, ...props }) {
|
|
|
93
93
|
className: cn(
|
|
94
94
|
"group/field-label peer/field-label flex w-fit gap-2 leading-snug group-data-[disabled=true]/field:opacity-50",
|
|
95
95
|
"has-[>[data-slot=field]]:w-full has-[>[data-slot=field]]:flex-col has-[>[data-slot=field]]:rounded-md has-[>[data-slot=field]]:border [&>*]:data-[slot=field]:p-4",
|
|
96
|
-
"has-data-[state=checked]:bg-primary/5 has-data-[state=checked]:border-primary dark:has-data-[state=checked]:bg-primary/10",
|
|
96
|
+
"has-data-[state=checked]:bg-primary/5 has-data-[state=checked]:border-primary-ink dark:has-data-[state=checked]:bg-primary/10",
|
|
97
97
|
className
|
|
98
98
|
),
|
|
99
99
|
...props
|
|
@@ -121,7 +121,7 @@ function FieldDescription({ className, ...props }) {
|
|
|
121
121
|
className: cn(
|
|
122
122
|
"text-muted-foreground text-sm leading-normal font-normal group-has-[[data-orientation=horizontal]]/field:text-balance",
|
|
123
123
|
"last:mt-0 nth-last-2:-mt-1 [[data-variant=legend]+&]:-mt-1.5",
|
|
124
|
-
"[&>a:hover]:text-primary [&>a]:underline [&>a]:underline-offset-4",
|
|
124
|
+
"[&>a:hover]:text-primary-ink [&>a]:underline [&>a]:underline-offset-4",
|
|
125
125
|
className
|
|
126
126
|
),
|
|
127
127
|
...props
|
|
@@ -175,7 +175,7 @@ function FieldError({ className, children, errors, ...props }) {
|
|
|
175
175
|
{
|
|
176
176
|
role: "alert",
|
|
177
177
|
"data-slot": "field-error",
|
|
178
|
-
className: cn("text-destructive text-sm font-normal", className),
|
|
178
|
+
className: cn("text-destructive-ink text-sm font-normal", className),
|
|
179
179
|
...props,
|
|
180
180
|
children: content
|
|
181
181
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/components/ui/field.tsx"],"sourcesContent":["\"use client\";\n\nimport { cva, type VariantProps } from \"class-variance-authority\";\nimport type * as React from \"react\";\nimport { useMemo } from \"react\";\nimport { cn } from \"../../lib/cn.js\";\nimport { Label, type LabelProps } from \"./label.js\";\nimport { Separator } from \"./separator.js\";\n\nexport type FieldSetProps = React.ComponentProps<\"fieldset\">;\n\nfunction FieldSet({ className, ...props }: FieldSetProps) {\n return (\n <fieldset\n data-slot=\"field-set\"\n className={cn(\n \"flex flex-col gap-6\",\n \"has-[>[data-slot=checkbox-group]]:gap-3 has-[>[data-slot=radio-group]]:gap-3\",\n className\n )}\n {...props}\n />\n );\n}\n\nexport interface FieldLegendProps extends React.ComponentProps<\"legend\"> {\n /** `legend` = tiêu đề nhóm cỡ base; `label` = cỡ sm như một nhãn thường. */\n variant?: \"legend\" | \"label\";\n}\n\nfunction FieldLegend({ className, variant = \"legend\", ...props }: FieldLegendProps) {\n return (\n <legend\n data-slot=\"field-legend\"\n data-variant={variant}\n className={cn(\"mb-3 font-medium\", \"data-[variant=legend]:text-base\", \"data-[variant=label]:text-sm\", className)}\n {...props}\n />\n );\n}\n\nexport type FieldGroupProps = React.ComponentProps<\"div\">;\n\nfunction FieldGroup({ className, ...props }: FieldGroupProps) {\n return (\n <div\n data-slot=\"field-group\"\n className={cn(\n \"group/field-group @container/field-group flex w-full flex-col gap-7 data-[slot=checkbox-group]:gap-3 [&>[data-slot=field-group]]:gap-4\",\n className\n )}\n {...props}\n />\n );\n}\n\nconst fieldVariants = cva(\"group/field flex w-full data-[invalid=true]:text-destructive\", {\n variants: {\n orientation: {\n vertical: [\"flex-col gap-2 [&>*]:w-full [&>.sr-only]:w-auto\"],\n horizontal: [\n \"flex-row items-center gap-3\",\n \"[&>[data-slot=field-label]]:flex-auto\",\n \"has-[>[data-slot=field-content]]:items-start has-[>[data-slot=field-content]]:[&>[role=checkbox],[role=radio]]:mt-px\"\n ],\n responsive: [\n \"flex-col gap-2 [&>*]:w-full [&>.sr-only]:w-auto @md/field-group:flex-row @md/field-group:items-center @md/field-group:gap-3 @md/field-group:[&>*]:w-auto\",\n \"@md/field-group:[&>[data-slot=field-label]]:flex-auto\",\n \"@md/field-group:has-[>[data-slot=field-content]]:items-start @md/field-group:has-[>[data-slot=field-content]]:[&>[role=checkbox],[role=radio]]:mt-px\"\n ]\n }\n },\n defaultVariants: {\n orientation: \"vertical\"\n }\n});\n\nexport interface FieldProps extends React.ComponentProps<\"div\">, VariantProps<typeof fieldVariants> {}\n\nfunction Field({ className, orientation = \"vertical\", ...props }: FieldProps) {\n return (\n <div\n role=\"group\"\n data-slot=\"field\"\n data-orientation={orientation}\n className={cn(fieldVariants({ orientation }), className)}\n {...props}\n />\n );\n}\n\nexport type FieldContentProps = React.ComponentProps<\"div\">;\n\nfunction FieldContent({ className, ...props }: FieldContentProps) {\n return (\n <div\n data-slot=\"field-content\"\n className={cn(\"group/field-content flex flex-1 flex-col gap-1.5 leading-snug\", className)}\n {...props}\n />\n );\n}\n\nexport type FieldLabelProps = LabelProps;\n\nfunction FieldLabel({ className, ...props }: FieldLabelProps) {\n return (\n <Label\n data-slot=\"field-label\"\n className={cn(\n \"group/field-label peer/field-label flex w-fit gap-2 leading-snug group-data-[disabled=true]/field:opacity-50\",\n \"has-[>[data-slot=field]]:w-full has-[>[data-slot=field]]:flex-col has-[>[data-slot=field]]:rounded-md has-[>[data-slot=field]]:border [&>*]:data-[slot=field]:p-4\",\n \"has-data-[state=checked]:bg-primary/5 has-data-[state=checked]:border-primary dark:has-data-[state=checked]:bg-primary/10\",\n className\n )}\n {...props}\n />\n );\n}\n\nexport type FieldTitleProps = React.ComponentProps<\"div\">;\n\nfunction FieldTitle({ className, ...props }: FieldTitleProps) {\n return (\n <div\n data-slot=\"field-label\"\n className={cn(\n \"flex w-fit items-center gap-2 text-sm leading-snug font-medium group-data-[disabled=true]/field:opacity-50\",\n className\n )}\n {...props}\n />\n );\n}\n\nexport type FieldDescriptionProps = React.ComponentProps<\"p\">;\n\nfunction FieldDescription({ className, ...props }: FieldDescriptionProps) {\n return (\n <p\n data-slot=\"field-description\"\n className={cn(\n \"text-muted-foreground text-sm leading-normal font-normal group-has-[[data-orientation=horizontal]]/field:text-balance\",\n \"last:mt-0 nth-last-2:-mt-1 [[data-variant=legend]+&]:-mt-1.5\",\n \"[&>a:hover]:text-primary [&>a]:underline [&>a]:underline-offset-4\",\n className\n )}\n {...props}\n />\n );\n}\n\nexport interface FieldSeparatorProps extends React.ComponentProps<\"div\"> {\n /** Có nội dung thì chữ nằm giữa đường kẻ (kiểu \"hoặc\"). */\n children?: React.ReactNode;\n}\n\nfunction FieldSeparator({ children, className, ...props }: FieldSeparatorProps) {\n return (\n <div\n data-slot=\"field-separator\"\n data-content={!!children}\n className={cn(\"relative -my-2 h-5 text-sm group-data-[variant=outline]/field-group:-mb-2\", className)}\n {...props}\n >\n <Separator className=\"absolute inset-0 top-1/2\" />\n {children && (\n <span\n className=\"bg-background text-muted-foreground relative mx-auto block w-fit px-2\"\n data-slot=\"field-separator-content\"\n >\n {children}\n </span>\n )}\n </div>\n );\n}\n\nexport interface FieldErrorProps extends React.ComponentProps<\"div\"> {\n /**\n * Danh sách lỗi (khớp shape của react-hook-form). Bỏ qua khi đã truyền `children`.\n * Một lỗi → in thẳng; nhiều lỗi → danh sách gạch đầu dòng.\n */\n errors?: Array<{ message?: string } | undefined>;\n}\n\nfunction FieldError({ className, children, errors, ...props }: FieldErrorProps) {\n const content = useMemo(() => {\n if (children) {\n return children;\n }\n\n if (!errors) {\n return null;\n }\n\n // Lọc sạch phần tử rỗng trước để dùng chính message làm key (tránh key theo index).\n const messages = errors.flatMap((error) => (error?.message ? [error.message] : []));\n\n if (messages.length === 0) {\n return null;\n }\n\n if (messages.length === 1) {\n return messages[0];\n }\n\n return (\n <ul className=\"ml-4 flex list-disc flex-col gap-1\">\n {messages.map((message) => (\n <li key={message}>{message}</li>\n ))}\n </ul>\n );\n }, [children, errors]);\n\n if (!content) {\n return null;\n }\n\n return (\n <div\n role=\"alert\"\n data-slot=\"field-error\"\n className={cn(\"text-destructive text-sm font-normal\", className)}\n {...props}\n >\n {content}\n </div>\n );\n}\n\nexport {\n Field,\n FieldContent,\n FieldDescription,\n FieldError,\n FieldGroup,\n FieldLabel,\n FieldLegend,\n FieldSeparator,\n FieldSet,\n FieldTitle,\n fieldVariants\n};\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../src/components/ui/field.tsx"],"sourcesContent":["\"use client\";\n\nimport { cva, type VariantProps } from \"class-variance-authority\";\nimport type * as React from \"react\";\nimport { useMemo } from \"react\";\nimport { cn } from \"../../lib/cn.js\";\nimport { Label, type LabelProps } from \"./label.js\";\nimport { Separator } from \"./separator.js\";\n\nexport type FieldSetProps = React.ComponentProps<\"fieldset\">;\n\nfunction FieldSet({ className, ...props }: FieldSetProps) {\n return (\n <fieldset\n data-slot=\"field-set\"\n className={cn(\n \"flex flex-col gap-6\",\n \"has-[>[data-slot=checkbox-group]]:gap-3 has-[>[data-slot=radio-group]]:gap-3\",\n className\n )}\n {...props}\n />\n );\n}\n\nexport interface FieldLegendProps extends React.ComponentProps<\"legend\"> {\n /** `legend` = tiêu đề nhóm cỡ base; `label` = cỡ sm như một nhãn thường. */\n variant?: \"legend\" | \"label\";\n}\n\nfunction FieldLegend({ className, variant = \"legend\", ...props }: FieldLegendProps) {\n return (\n <legend\n data-slot=\"field-legend\"\n data-variant={variant}\n className={cn(\"mb-3 font-medium\", \"data-[variant=legend]:text-base\", \"data-[variant=label]:text-sm\", className)}\n {...props}\n />\n );\n}\n\nexport type FieldGroupProps = React.ComponentProps<\"div\">;\n\nfunction FieldGroup({ className, ...props }: FieldGroupProps) {\n return (\n <div\n data-slot=\"field-group\"\n className={cn(\n \"group/field-group @container/field-group flex w-full flex-col gap-7 data-[slot=checkbox-group]:gap-3 [&>[data-slot=field-group]]:gap-4\",\n className\n )}\n {...props}\n />\n );\n}\n\n// `text-destructive-ink` (bậc CHỮ đỏ) chứ không `text-destructive` (bậc NỀN đỏ của nút xoá):\n// bậc nền chỉ 3,76:1 trên `--background` và 3,53:1 trên `--card` ở dark ✗. Ink: 7,15:1 (light) ·\n// 6,84:1 / 6,42:1 (dark) ✓. Cùng một lối với `form.tsx` và `composite/form-field.tsx`.\nconst fieldVariants = cva(\"group/field flex w-full data-[invalid=true]:text-destructive-ink\", {\n variants: {\n orientation: {\n vertical: [\"flex-col gap-2 [&>*]:w-full [&>.sr-only]:w-auto\"],\n horizontal: [\n \"flex-row items-center gap-3\",\n \"[&>[data-slot=field-label]]:flex-auto\",\n \"has-[>[data-slot=field-content]]:items-start has-[>[data-slot=field-content]]:[&>[role=checkbox],[role=radio]]:mt-px\"\n ],\n responsive: [\n \"flex-col gap-2 [&>*]:w-full [&>.sr-only]:w-auto @md/field-group:flex-row @md/field-group:items-center @md/field-group:gap-3 @md/field-group:[&>*]:w-auto\",\n \"@md/field-group:[&>[data-slot=field-label]]:flex-auto\",\n \"@md/field-group:has-[>[data-slot=field-content]]:items-start @md/field-group:has-[>[data-slot=field-content]]:[&>[role=checkbox],[role=radio]]:mt-px\"\n ]\n }\n },\n defaultVariants: {\n orientation: \"vertical\"\n }\n});\n\nexport interface FieldProps extends React.ComponentProps<\"div\">, VariantProps<typeof fieldVariants> {}\n\nfunction Field({ className, orientation = \"vertical\", ...props }: FieldProps) {\n return (\n <div\n role=\"group\"\n data-slot=\"field\"\n data-orientation={orientation}\n className={cn(fieldVariants({ orientation }), className)}\n {...props}\n />\n );\n}\n\nexport type FieldContentProps = React.ComponentProps<\"div\">;\n\nfunction FieldContent({ className, ...props }: FieldContentProps) {\n return (\n <div\n data-slot=\"field-content\"\n className={cn(\"group/field-content flex flex-1 flex-col gap-1.5 leading-snug\", className)}\n {...props}\n />\n );\n}\n\nexport type FieldLabelProps = LabelProps;\n\n/*\n * Thẻ chọn (label bọc cả một Field, kiểu radio-card): trạng thái ĐÃ CHỌN được kể bằng nền tint\n * `bg-primary/5` — chỉ khác nền trang cỡ 1,03:1 — nên VIỀN mới là tín hiệu thật, và nó chịu\n * ngưỡng 3:1 của WCAG 1.4.11. `border-primary` gold #E8B824 chỉ **1,86:1** với nền trang và\n * **1,80:1** với chính cái tint (light) ✗. `--primary-ink`: 6,51:1 với nền trang · 6,30:1 với\n * tint (light); 12,67:1 · 10,43:1 (dark) ✓. Tint giữ nguyên `--primary` vì đó là vai trò TÔ NỀN.\n */\nfunction FieldLabel({ className, ...props }: FieldLabelProps) {\n return (\n <Label\n data-slot=\"field-label\"\n className={cn(\n \"group/field-label peer/field-label flex w-fit gap-2 leading-snug group-data-[disabled=true]/field:opacity-50\",\n \"has-[>[data-slot=field]]:w-full has-[>[data-slot=field]]:flex-col has-[>[data-slot=field]]:rounded-md has-[>[data-slot=field]]:border [&>*]:data-[slot=field]:p-4\",\n \"has-data-[state=checked]:bg-primary/5 has-data-[state=checked]:border-primary-ink dark:has-data-[state=checked]:bg-primary/10\",\n className\n )}\n {...props}\n />\n );\n}\n\nexport type FieldTitleProps = React.ComponentProps<\"div\">;\n\nfunction FieldTitle({ className, ...props }: FieldTitleProps) {\n return (\n <div\n data-slot=\"field-label\"\n className={cn(\n \"flex w-fit items-center gap-2 text-sm leading-snug font-medium group-data-[disabled=true]/field:opacity-50\",\n className\n )}\n {...props}\n />\n );\n}\n\nexport type FieldDescriptionProps = React.ComponentProps<\"p\">;\n\nfunction FieldDescription({ className, ...props }: FieldDescriptionProps) {\n return (\n <p\n data-slot=\"field-description\"\n className={cn(\n \"text-muted-foreground text-sm leading-normal font-normal group-has-[[data-orientation=horizontal]]/field:text-balance\",\n \"last:mt-0 nth-last-2:-mt-1 [[data-variant=legend]+&]:-mt-1.5\",\n \"[&>a:hover]:text-primary-ink [&>a]:underline [&>a]:underline-offset-4\",\n className\n )}\n {...props}\n />\n );\n}\n\nexport interface FieldSeparatorProps extends React.ComponentProps<\"div\"> {\n /** Có nội dung thì chữ nằm giữa đường kẻ (kiểu \"hoặc\"). */\n children?: React.ReactNode;\n}\n\nfunction FieldSeparator({ children, className, ...props }: FieldSeparatorProps) {\n return (\n <div\n data-slot=\"field-separator\"\n data-content={!!children}\n className={cn(\"relative -my-2 h-5 text-sm group-data-[variant=outline]/field-group:-mb-2\", className)}\n {...props}\n >\n <Separator className=\"absolute inset-0 top-1/2\" />\n {children && (\n <span\n className=\"bg-background text-muted-foreground relative mx-auto block w-fit px-2\"\n data-slot=\"field-separator-content\"\n >\n {children}\n </span>\n )}\n </div>\n );\n}\n\nexport interface FieldErrorProps extends React.ComponentProps<\"div\"> {\n /**\n * Danh sách lỗi (khớp shape của react-hook-form). Bỏ qua khi đã truyền `children`.\n * Một lỗi → in thẳng; nhiều lỗi → danh sách gạch đầu dòng.\n */\n errors?: Array<{ message?: string } | undefined>;\n}\n\nfunction FieldError({ className, children, errors, ...props }: FieldErrorProps) {\n const content = useMemo(() => {\n if (children) {\n return children;\n }\n\n if (!errors) {\n return null;\n }\n\n // Lọc sạch phần tử rỗng trước để dùng chính message làm key (tránh key theo index).\n const messages = errors.flatMap((error) => (error?.message ? [error.message] : []));\n\n if (messages.length === 0) {\n return null;\n }\n\n if (messages.length === 1) {\n return messages[0];\n }\n\n return (\n <ul className=\"ml-4 flex list-disc flex-col gap-1\">\n {messages.map((message) => (\n <li key={message}>{message}</li>\n ))}\n </ul>\n );\n }, [children, errors]);\n\n if (!content) {\n return null;\n }\n\n return (\n <div\n role=\"alert\"\n data-slot=\"field-error\"\n className={cn(\"text-destructive-ink text-sm font-normal\", className)}\n {...props}\n >\n {content}\n </div>\n );\n}\n\nexport {\n Field,\n FieldContent,\n FieldDescription,\n FieldError,\n FieldGroup,\n FieldLabel,\n FieldLegend,\n FieldSeparator,\n FieldSet,\n FieldTitle,\n fieldVariants\n};\n"],"mappings":"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","names":[]}
|
|
@@ -48,7 +48,7 @@ function FormLabel({ className, ...props }) {
|
|
|
48
48
|
{
|
|
49
49
|
"data-slot": "form-label",
|
|
50
50
|
"data-error": !!error,
|
|
51
|
-
className: cn("data-[error=true]:text-destructive", className),
|
|
51
|
+
className: cn("data-[error=true]:text-destructive-ink", className),
|
|
52
52
|
htmlFor: formItemId,
|
|
53
53
|
...props
|
|
54
54
|
}
|
|
@@ -85,7 +85,13 @@ function FormMessage({ className, ...props }) {
|
|
|
85
85
|
if (!body) {
|
|
86
86
|
return null;
|
|
87
87
|
}
|
|
88
|
-
return
|
|
88
|
+
return (
|
|
89
|
+
// `text-destructive-ink`, không phải `text-destructive`: `--destructive` là token NỀN (nút
|
|
90
|
+
// xoá) và ghim một giá trị cho cả hai theme, nên làm CHỮ thì chỉ 3,76:1 trên `--background`
|
|
91
|
+
// và 3,53:1 trên `--card` ở dark ✗ (light thì vừa đủ 5,03:1 — mỗi theme hỏng một nửa).
|
|
92
|
+
// Bậc ink: 7,15:1 (light) · 6,84:1 / 6,42:1 (dark, trên `--background` / `--card`) ✓.
|
|
93
|
+
/* @__PURE__ */ jsx("p", { "data-slot": "form-message", id: formMessageId, className: cn("text-destructive-ink text-sm", className), ...props, children: body })
|
|
94
|
+
);
|
|
89
95
|
}
|
|
90
96
|
export {
|
|
91
97
|
Form,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/components/ui/form.tsx"],"sourcesContent":["\"use client\";\n\nimport type * as LabelPrimitive from \"@radix-ui/react-label\";\nimport { Slot } from \"@radix-ui/react-slot\";\nimport * as React from \"react\";\nimport {\n Controller,\n type ControllerProps,\n type FieldPath,\n type FieldValues,\n FormProvider,\n useFormContext,\n useFormState\n} from \"react-hook-form\";\nimport { cn } from \"../../lib/cn.js\";\nimport { Label } from \"./label.js\";\n\n/**\n * Binding shadcn ⇄ react-hook-form.\n *\n * ⚠ `react-hook-form` là peer OPTIONAL và có React context singleton: app và\n * package BẮT BUỘC dùng chung một bản, nếu không `useFormContext()` sẽ đọc nhầm\n * provider. Vì vậy file này phải nằm ở entry riêng `./form`, KHÔNG gom vào barrel `.`\n * (xem §3.2 + §8.2 của docs/spec-package.md).\n *\n * Lưu ý tên: `FormField` ở đây là wrapper của `Controller` (API shadcn), khác với\n * composite `FormField` (grid + label + error) ở Tier 2.\n */\n\nconst Form = FormProvider;\n\ntype FormFieldContextValue<\n TFieldValues extends FieldValues = FieldValues,\n TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>\n> = {\n name: TName;\n};\n\nconst FormFieldContext = React.createContext<FormFieldContextValue>({} as FormFieldContextValue);\n\nexport type FormProps = React.ComponentProps<typeof FormProvider>;\nexport type FormFieldProps<\n TFieldValues extends FieldValues = FieldValues,\n TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>\n> = ControllerProps<TFieldValues, TName>;\nexport type FormItemProps = React.ComponentProps<\"div\">;\nexport type FormLabelProps = React.ComponentProps<typeof LabelPrimitive.Root>;\nexport type FormControlProps = React.ComponentProps<typeof Slot>;\nexport type FormDescriptionProps = React.ComponentProps<\"p\">;\nexport type FormMessageProps = React.ComponentProps<\"p\">;\n\nconst FormField = <\n TFieldValues extends FieldValues = FieldValues,\n TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>\n>({\n ...props\n}: FormFieldProps<TFieldValues, TName>) => {\n return (\n <FormFieldContext.Provider value={{ name: props.name }}>\n <Controller {...props} />\n </FormFieldContext.Provider>\n );\n};\n\ntype FormItemContextValue = {\n id: string;\n};\n\nconst FormItemContext = React.createContext<FormItemContextValue>({} as FormItemContextValue);\n\n/**\n * Gom id (a11y) + trạng thái lỗi của field đang bao quanh.\n * Khác bản comitor-ds: kiểm tra context TRƯỚC khi dùng (bản gốc throw sau khi đã\n * đọc `fieldContext.name`, nên lỗi thật bị che bởi crash khác).\n */\nconst useFormField = () => {\n const fieldContext = React.useContext(FormFieldContext);\n const itemContext = React.useContext(FormItemContext);\n\n if (!fieldContext?.name) {\n throw new Error(\"useFormField phải được dùng bên trong <FormField>\");\n }\n\n const { getFieldState } = useFormContext();\n const formState = useFormState({ name: fieldContext.name });\n const fieldState = getFieldState(fieldContext.name, formState);\n\n const { id } = itemContext;\n\n return {\n id,\n name: fieldContext.name,\n formItemId: `${id}-form-item`,\n formDescriptionId: `${id}-form-item-description`,\n formMessageId: `${id}-form-item-message`,\n ...fieldState\n };\n};\n\nfunction FormItem({ className, ...props }: FormItemProps) {\n const id = React.useId();\n\n return (\n <FormItemContext.Provider value={{ id }}>\n <div data-slot=\"form-item\" className={cn(\"grid gap-2\", className)} {...props} />\n </FormItemContext.Provider>\n );\n}\n\nfunction FormLabel({ className, ...props }: FormLabelProps) {\n const { error, formItemId } = useFormField();\n\n return (\n <Label\n data-slot=\"form-label\"\n data-error={!!error}\n className={cn(\"data-[error=true]:text-destructive\", className)}\n htmlFor={formItemId}\n {...props}\n />\n );\n}\n\nfunction FormControl({ ...props }: FormControlProps) {\n const { error, formItemId, formDescriptionId, formMessageId } = useFormField();\n\n return (\n <Slot\n data-slot=\"form-control\"\n id={formItemId}\n aria-describedby={!error ? `${formDescriptionId}` : `${formDescriptionId} ${formMessageId}`}\n aria-invalid={!!error}\n {...props}\n />\n );\n}\n\nfunction FormDescription({ className, ...props }: FormDescriptionProps) {\n const { formDescriptionId } = useFormField();\n\n return (\n <p\n data-slot=\"form-description\"\n id={formDescriptionId}\n className={cn(\"text-muted-foreground text-sm\", className)}\n {...props}\n />\n );\n}\n\nfunction FormMessage({ className, ...props }: FormMessageProps) {\n const { error, formMessageId } = useFormField();\n const body = error ? String(error?.message ?? \"\") : props.children;\n\n if (!body) {\n return null;\n }\n\n return (\n <p data-slot=\"form-message\" id={formMessageId} className={cn(\"text-destructive text-sm\", className)} {...props}>\n {body}\n </p>\n );\n}\n\nexport { Form, FormControl, FormDescription, FormField, FormItem, FormLabel, FormMessage, useFormField };\n"],"mappings":";AA2DM;AAxDN,SAAS,YAAY;AACrB,YAAY,WAAW;AACvB;AAAA,EACE;AAAA,EAIA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,UAAU;AACnB,SAAS,aAAa;AActB,MAAM,OAAO;AASb,MAAM,mBAAmB,MAAM,cAAqC,CAAC,CAA0B;AAa/F,MAAM,YAAY,CAGhB;AAAA,EACA,GAAG;AACL,MAA2C;AACzC,SACE,oBAAC,iBAAiB,UAAjB,EAA0B,OAAO,EAAE,MAAM,MAAM,KAAK,GACnD,8BAAC,cAAY,GAAG,OAAO,GACzB;AAEJ;AAMA,MAAM,kBAAkB,MAAM,cAAoC,CAAC,CAAyB;AAO5F,MAAM,eAAe,MAAM;AACzB,QAAM,eAAe,MAAM,WAAW,gBAAgB;AACtD,QAAM,cAAc,MAAM,WAAW,eAAe;AAEpD,MAAI,CAAC,cAAc,MAAM;AACvB,UAAM,IAAI,MAAM,6EAAmD;AAAA,EACrE;AAEA,QAAM,EAAE,cAAc,IAAI,eAAe;AACzC,QAAM,YAAY,aAAa,EAAE,MAAM,aAAa,KAAK,CAAC;AAC1D,QAAM,aAAa,cAAc,aAAa,MAAM,SAAS;AAE7D,QAAM,EAAE,GAAG,IAAI;AAEf,SAAO;AAAA,IACL;AAAA,IACA,MAAM,aAAa;AAAA,IACnB,YAAY,GAAG,EAAE;AAAA,IACjB,mBAAmB,GAAG,EAAE;AAAA,IACxB,eAAe,GAAG,EAAE;AAAA,IACpB,GAAG;AAAA,EACL;AACF;AAEA,SAAS,SAAS,EAAE,WAAW,GAAG,MAAM,GAAkB;AACxD,QAAM,KAAK,MAAM,MAAM;AAEvB,SACE,oBAAC,gBAAgB,UAAhB,EAAyB,OAAO,EAAE,GAAG,GACpC,8BAAC,SAAI,aAAU,aAAY,WAAW,GAAG,cAAc,SAAS,GAAI,GAAG,OAAO,GAChF;AAEJ;AAEA,SAAS,UAAU,EAAE,WAAW,GAAG,MAAM,GAAmB;AAC1D,QAAM,EAAE,OAAO,WAAW,IAAI,aAAa;AAE3C,SACE;AAAA,IAAC;AAAA;AAAA,MACC,aAAU;AAAA,MACV,cAAY,CAAC,CAAC;AAAA,MACd,WAAW,GAAG,
|
|
1
|
+
{"version":3,"sources":["../../../src/components/ui/form.tsx"],"sourcesContent":["\"use client\";\n\nimport type * as LabelPrimitive from \"@radix-ui/react-label\";\nimport { Slot } from \"@radix-ui/react-slot\";\nimport * as React from \"react\";\nimport {\n Controller,\n type ControllerProps,\n type FieldPath,\n type FieldValues,\n FormProvider,\n useFormContext,\n useFormState\n} from \"react-hook-form\";\nimport { cn } from \"../../lib/cn.js\";\nimport { Label } from \"./label.js\";\n\n/**\n * Binding shadcn ⇄ react-hook-form.\n *\n * ⚠ `react-hook-form` là peer OPTIONAL và có React context singleton: app và\n * package BẮT BUỘC dùng chung một bản, nếu không `useFormContext()` sẽ đọc nhầm\n * provider. Vì vậy file này phải nằm ở entry riêng `./form`, KHÔNG gom vào barrel `.`\n * (xem §3.2 + §8.2 của docs/spec-package.md).\n *\n * Lưu ý tên: `FormField` ở đây là wrapper của `Controller` (API shadcn), khác với\n * composite `FormField` (grid + label + error) ở Tier 2.\n */\n\nconst Form = FormProvider;\n\ntype FormFieldContextValue<\n TFieldValues extends FieldValues = FieldValues,\n TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>\n> = {\n name: TName;\n};\n\nconst FormFieldContext = React.createContext<FormFieldContextValue>({} as FormFieldContextValue);\n\nexport type FormProps = React.ComponentProps<typeof FormProvider>;\nexport type FormFieldProps<\n TFieldValues extends FieldValues = FieldValues,\n TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>\n> = ControllerProps<TFieldValues, TName>;\nexport type FormItemProps = React.ComponentProps<\"div\">;\nexport type FormLabelProps = React.ComponentProps<typeof LabelPrimitive.Root>;\nexport type FormControlProps = React.ComponentProps<typeof Slot>;\nexport type FormDescriptionProps = React.ComponentProps<\"p\">;\nexport type FormMessageProps = React.ComponentProps<\"p\">;\n\nconst FormField = <\n TFieldValues extends FieldValues = FieldValues,\n TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>\n>({\n ...props\n}: FormFieldProps<TFieldValues, TName>) => {\n return (\n <FormFieldContext.Provider value={{ name: props.name }}>\n <Controller {...props} />\n </FormFieldContext.Provider>\n );\n};\n\ntype FormItemContextValue = {\n id: string;\n};\n\nconst FormItemContext = React.createContext<FormItemContextValue>({} as FormItemContextValue);\n\n/**\n * Gom id (a11y) + trạng thái lỗi của field đang bao quanh.\n * Khác bản comitor-ds: kiểm tra context TRƯỚC khi dùng (bản gốc throw sau khi đã\n * đọc `fieldContext.name`, nên lỗi thật bị che bởi crash khác).\n */\nconst useFormField = () => {\n const fieldContext = React.useContext(FormFieldContext);\n const itemContext = React.useContext(FormItemContext);\n\n if (!fieldContext?.name) {\n throw new Error(\"useFormField phải được dùng bên trong <FormField>\");\n }\n\n const { getFieldState } = useFormContext();\n const formState = useFormState({ name: fieldContext.name });\n const fieldState = getFieldState(fieldContext.name, formState);\n\n const { id } = itemContext;\n\n return {\n id,\n name: fieldContext.name,\n formItemId: `${id}-form-item`,\n formDescriptionId: `${id}-form-item-description`,\n formMessageId: `${id}-form-item-message`,\n ...fieldState\n };\n};\n\nfunction FormItem({ className, ...props }: FormItemProps) {\n const id = React.useId();\n\n return (\n <FormItemContext.Provider value={{ id }}>\n <div data-slot=\"form-item\" className={cn(\"grid gap-2\", className)} {...props} />\n </FormItemContext.Provider>\n );\n}\n\nfunction FormLabel({ className, ...props }: FormLabelProps) {\n const { error, formItemId } = useFormField();\n\n return (\n <Label\n data-slot=\"form-label\"\n data-error={!!error}\n className={cn(\"data-[error=true]:text-destructive-ink\", className)}\n htmlFor={formItemId}\n {...props}\n />\n );\n}\n\nfunction FormControl({ ...props }: FormControlProps) {\n const { error, formItemId, formDescriptionId, formMessageId } = useFormField();\n\n return (\n <Slot\n data-slot=\"form-control\"\n id={formItemId}\n aria-describedby={!error ? `${formDescriptionId}` : `${formDescriptionId} ${formMessageId}`}\n aria-invalid={!!error}\n {...props}\n />\n );\n}\n\nfunction FormDescription({ className, ...props }: FormDescriptionProps) {\n const { formDescriptionId } = useFormField();\n\n return (\n <p\n data-slot=\"form-description\"\n id={formDescriptionId}\n className={cn(\"text-muted-foreground text-sm\", className)}\n {...props}\n />\n );\n}\n\nfunction FormMessage({ className, ...props }: FormMessageProps) {\n const { error, formMessageId } = useFormField();\n const body = error ? String(error?.message ?? \"\") : props.children;\n\n if (!body) {\n return null;\n }\n\n return (\n // `text-destructive-ink`, không phải `text-destructive`: `--destructive` là token NỀN (nút\n // xoá) và ghim một giá trị cho cả hai theme, nên làm CHỮ thì chỉ 3,76:1 trên `--background`\n // và 3,53:1 trên `--card` ở dark ✗ (light thì vừa đủ 5,03:1 — mỗi theme hỏng một nửa).\n // Bậc ink: 7,15:1 (light) · 6,84:1 / 6,42:1 (dark, trên `--background` / `--card`) ✓.\n <p data-slot=\"form-message\" id={formMessageId} className={cn(\"text-destructive-ink text-sm\", className)} {...props}>\n {body}\n </p>\n );\n}\n\nexport { Form, FormControl, FormDescription, FormField, FormItem, FormLabel, FormMessage, useFormField };\n"],"mappings":";AA2DM;AAxDN,SAAS,YAAY;AACrB,YAAY,WAAW;AACvB;AAAA,EACE;AAAA,EAIA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,UAAU;AACnB,SAAS,aAAa;AActB,MAAM,OAAO;AASb,MAAM,mBAAmB,MAAM,cAAqC,CAAC,CAA0B;AAa/F,MAAM,YAAY,CAGhB;AAAA,EACA,GAAG;AACL,MAA2C;AACzC,SACE,oBAAC,iBAAiB,UAAjB,EAA0B,OAAO,EAAE,MAAM,MAAM,KAAK,GACnD,8BAAC,cAAY,GAAG,OAAO,GACzB;AAEJ;AAMA,MAAM,kBAAkB,MAAM,cAAoC,CAAC,CAAyB;AAO5F,MAAM,eAAe,MAAM;AACzB,QAAM,eAAe,MAAM,WAAW,gBAAgB;AACtD,QAAM,cAAc,MAAM,WAAW,eAAe;AAEpD,MAAI,CAAC,cAAc,MAAM;AACvB,UAAM,IAAI,MAAM,6EAAmD;AAAA,EACrE;AAEA,QAAM,EAAE,cAAc,IAAI,eAAe;AACzC,QAAM,YAAY,aAAa,EAAE,MAAM,aAAa,KAAK,CAAC;AAC1D,QAAM,aAAa,cAAc,aAAa,MAAM,SAAS;AAE7D,QAAM,EAAE,GAAG,IAAI;AAEf,SAAO;AAAA,IACL;AAAA,IACA,MAAM,aAAa;AAAA,IACnB,YAAY,GAAG,EAAE;AAAA,IACjB,mBAAmB,GAAG,EAAE;AAAA,IACxB,eAAe,GAAG,EAAE;AAAA,IACpB,GAAG;AAAA,EACL;AACF;AAEA,SAAS,SAAS,EAAE,WAAW,GAAG,MAAM,GAAkB;AACxD,QAAM,KAAK,MAAM,MAAM;AAEvB,SACE,oBAAC,gBAAgB,UAAhB,EAAyB,OAAO,EAAE,GAAG,GACpC,8BAAC,SAAI,aAAU,aAAY,WAAW,GAAG,cAAc,SAAS,GAAI,GAAG,OAAO,GAChF;AAEJ;AAEA,SAAS,UAAU,EAAE,WAAW,GAAG,MAAM,GAAmB;AAC1D,QAAM,EAAE,OAAO,WAAW,IAAI,aAAa;AAE3C,SACE;AAAA,IAAC;AAAA;AAAA,MACC,aAAU;AAAA,MACV,cAAY,CAAC,CAAC;AAAA,MACd,WAAW,GAAG,0CAA0C,SAAS;AAAA,MACjE,SAAS;AAAA,MACR,GAAG;AAAA;AAAA,EACN;AAEJ;AAEA,SAAS,YAAY,EAAE,GAAG,MAAM,GAAqB;AACnD,QAAM,EAAE,OAAO,YAAY,mBAAmB,cAAc,IAAI,aAAa;AAE7E,SACE;AAAA,IAAC;AAAA;AAAA,MACC,aAAU;AAAA,MACV,IAAI;AAAA,MACJ,oBAAkB,CAAC,QAAQ,GAAG,iBAAiB,KAAK,GAAG,iBAAiB,IAAI,aAAa;AAAA,MACzF,gBAAc,CAAC,CAAC;AAAA,MACf,GAAG;AAAA;AAAA,EACN;AAEJ;AAEA,SAAS,gBAAgB,EAAE,WAAW,GAAG,MAAM,GAAyB;AACtE,QAAM,EAAE,kBAAkB,IAAI,aAAa;AAE3C,SACE;AAAA,IAAC;AAAA;AAAA,MACC,aAAU;AAAA,MACV,IAAI;AAAA,MACJ,WAAW,GAAG,iCAAiC,SAAS;AAAA,MACvD,GAAG;AAAA;AAAA,EACN;AAEJ;AAEA,SAAS,YAAY,EAAE,WAAW,GAAG,MAAM,GAAqB;AAC9D,QAAM,EAAE,OAAO,cAAc,IAAI,aAAa;AAC9C,QAAM,OAAO,QAAQ,OAAO,OAAO,WAAW,EAAE,IAAI,MAAM;AAE1D,MAAI,CAAC,MAAM;AACT,WAAO;AAAA,EACT;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA,IAKE,oBAAC,OAAE,aAAU,gBAAe,IAAI,eAAe,WAAW,GAAG,gCAAgC,SAAS,GAAI,GAAG,OAC1G,gBACH;AAAA;AAEJ;","names":[]}
|
|
@@ -12,7 +12,7 @@ function InputGroup({ className, ...props }) {
|
|
|
12
12
|
"data-slot": "input-group",
|
|
13
13
|
role: "group",
|
|
14
14
|
className: cn(
|
|
15
|
-
"group/input-group border-input
|
|
15
|
+
"group/input-group border-input relative flex w-full items-center rounded-md border shadow-xs transition-colors duration-150 ease-out outline-none",
|
|
16
16
|
"h-9 has-[>textarea]:h-auto",
|
|
17
17
|
// Biến thể theo vị trí addon.
|
|
18
18
|
"has-[>[data-align=inline-start]]:[&>input]:pl-2",
|
|
@@ -20,9 +20,9 @@ function InputGroup({ className, ...props }) {
|
|
|
20
20
|
"has-[>[data-align=block-start]]:h-auto has-[>[data-align=block-start]]:flex-col has-[>[data-align=block-start]]:[&>input]:pb-3",
|
|
21
21
|
"has-[>[data-align=block-end]]:h-auto has-[>[data-align=block-end]]:flex-col has-[>[data-align=block-end]]:[&>input]:pt-3",
|
|
22
22
|
// Trạng thái focus.
|
|
23
|
-
"has-[[data-slot=input-group-control]:focus-visible]:border-
|
|
23
|
+
"has-[[data-slot=input-group-control]:focus-visible]:border-primary-ink has-[[data-slot=input-group-control]:focus-visible]:ring-ring/50 has-[[data-slot=input-group-control]:focus-visible]:ring-2 has-[[data-slot=input-group-control]:focus-visible]:ring-offset-2 has-[[data-slot=input-group-control]:focus-visible]:ring-offset-background",
|
|
24
24
|
// Trạng thái lỗi.
|
|
25
|
-
"has-[[data-slot][aria-invalid=true]]:ring-destructive/20 has-[[data-slot][aria-invalid=true]]:border-destructive dark:has-[[data-slot][aria-invalid=true]]:ring-destructive/40",
|
|
25
|
+
"has-[[data-slot][aria-invalid=true]]:ring-destructive/20 has-[[data-slot][aria-invalid=true]]:border-destructive-ink dark:has-[[data-slot][aria-invalid=true]]:ring-destructive/40",
|
|
26
26
|
className
|
|
27
27
|
),
|
|
28
28
|
...props
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/components/ui/input-group.tsx"],"sourcesContent":["\"use client\";\n\nimport { cva, type VariantProps } from \"class-variance-authority\";\nimport type * as React from \"react\";\nimport { cn } from \"../../lib/cn.js\";\nimport { Button, type ButtonProps } from \"./button.js\";\nimport { Input } from \"./input.js\";\nimport { Textarea } from \"./textarea.js\";\n\nexport type InputGroupProps = React.ComponentProps<\"div\">;\n\nfunction InputGroup({ className, ...props }: InputGroupProps) {\n return (\n <div\n data-slot=\"input-group\"\n role=\"group\"\n className={cn(\n \"group/input-group border-input
|
|
1
|
+
{"version":3,"sources":["../../../src/components/ui/input-group.tsx"],"sourcesContent":["\"use client\";\n\nimport { cva, type VariantProps } from \"class-variance-authority\";\nimport type * as React from \"react\";\nimport { cn } from \"../../lib/cn.js\";\nimport { Button, type ButtonProps } from \"./button.js\";\nimport { Input } from \"./input.js\";\nimport { Textarea } from \"./textarea.js\";\n\n/*\n * ─ KHÔNG CÓ `dark:bg-input/30` (cùng lý do với Textarea) ─\n * `--input` = `--control-edge` là token VIỀN control (hợp đồng màu §3), không phải bậc tô nền.\n * Riêng ở đây cái sai còn kín hơn: lớp tô nằm trên thẻ CHA, còn chữ `--muted-foreground` nằm ở\n * `InputGroupAddon` và ở placeholder của `Input`/`Textarea` con — tức KHÁC chuỗi lớp, nên\n * `scripts/check-contrast.mjs` không thấy được cặp này (giới hạn §8.1). Số vẫn hỏng y hệt\n * Textarea: 3,81 · 3,54 · 3,22:1 ✗ ở dark. Bỏ lớp tô → addon và placeholder về đo với nền TRANG,\n * 5,70 · 5,35 · 4,86:1 ✓; khung nhóm vẫn do `border-input` khoanh (4,21–4,94:1 ở dark).\n */\nexport type InputGroupProps = React.ComponentProps<\"div\">;\n\nfunction InputGroup({ className, ...props }: InputGroupProps) {\n return (\n <div\n data-slot=\"input-group\"\n role=\"group\"\n className={cn(\n \"group/input-group border-input relative flex w-full items-center rounded-md border shadow-xs transition-colors duration-150 ease-out outline-none\",\n \"h-9 has-[>textarea]:h-auto\",\n\n // Biến thể theo vị trí addon.\n \"has-[>[data-align=inline-start]]:[&>input]:pl-2\",\n \"has-[>[data-align=inline-end]]:[&>input]:pr-2\",\n \"has-[>[data-align=block-start]]:h-auto has-[>[data-align=block-start]]:flex-col has-[>[data-align=block-start]]:[&>input]:pb-3\",\n \"has-[>[data-align=block-end]]:h-auto has-[>[data-align=block-end]]:flex-col has-[>[data-align=block-end]]:[&>input]:pt-3\",\n\n // Trạng thái focus.\n \"has-[[data-slot=input-group-control]:focus-visible]:border-primary-ink has-[[data-slot=input-group-control]:focus-visible]:ring-ring/50 has-[[data-slot=input-group-control]:focus-visible]:ring-2 has-[[data-slot=input-group-control]:focus-visible]:ring-offset-2 has-[[data-slot=input-group-control]:focus-visible]:ring-offset-background\",\n\n // Trạng thái lỗi.\n \"has-[[data-slot][aria-invalid=true]]:ring-destructive/20 has-[[data-slot][aria-invalid=true]]:border-destructive-ink dark:has-[[data-slot][aria-invalid=true]]:ring-destructive/40\",\n\n className\n )}\n {...props}\n />\n );\n}\n\nconst inputGroupAddonVariants = cva(\n \"text-muted-foreground flex h-auto cursor-text items-center justify-center gap-2 py-1.5 text-sm font-medium select-none [&>svg:not([class*='size-'])]:size-4 [&>kbd]:rounded-[calc(var(--radius)-5px)] group-data-[disabled=true]/input-group:opacity-50\",\n {\n variants: {\n align: {\n \"inline-start\": \"order-first pl-3 has-[>button]:ml-[-0.45rem] has-[>kbd]:ml-[-0.35rem]\",\n \"inline-end\": \"order-last pr-3 has-[>button]:mr-[-0.4rem] has-[>kbd]:mr-[-0.35rem]\",\n \"block-start\":\n \"order-first w-full justify-start px-3 pt-3 [.border-b]:pb-3 group-has-[>input]/input-group:pt-2.5\",\n \"block-end\": \"order-last w-full justify-start px-3 pb-3 [.border-t]:pt-3 group-has-[>input]/input-group:pb-2.5\"\n }\n },\n defaultVariants: {\n align: \"inline-start\"\n }\n }\n);\n\nexport interface InputGroupAddonProps\n extends React.ComponentProps<\"div\">,\n VariantProps<typeof inputGroupAddonVariants> {}\n\n/*\n * Bấm vào vùng addon thì dồn focus sang ô nhập bên trong (trừ khi bấm trúng một nút).\n * Đây là tiện ích chuột thuần tuý — bàn phím vẫn Tab thẳng vào input/button nên không\n * cần onKeyDown; addon không phải phần tử tương tác.\n */\nfunction InputGroupAddon({ className, align = \"inline-start\", ...props }: InputGroupAddonProps) {\n return (\n // biome-ignore lint/a11y/useKeyWithClickEvents: chỉ là lối tắt bằng chuột, bàn phím đã Tab thẳng tới control\n <div\n role=\"group\"\n data-slot=\"input-group-addon\"\n data-align={align}\n className={cn(inputGroupAddonVariants({ align }), className)}\n onClick={(event) => {\n if ((event.target as HTMLElement).closest(\"button\")) {\n return;\n }\n event.currentTarget.parentElement?.querySelector(\"input\")?.focus();\n }}\n {...props}\n />\n );\n}\n\nconst inputGroupButtonVariants = cva(\"text-sm shadow-none flex gap-2 items-center\", {\n variants: {\n size: {\n xs: \"h-6 gap-1 px-2 rounded-[calc(var(--radius)-5px)] [&>svg:not([class*='size-'])]:size-3.5 has-[>svg]:px-2\",\n sm: \"h-8 px-2.5 gap-1.5 rounded-md has-[>svg]:px-2.5\",\n \"icon-xs\": \"size-6 rounded-[calc(var(--radius)-5px)] p-0 has-[>svg]:p-0\",\n \"icon-sm\": \"size-8 p-0 has-[>svg]:p-0\"\n }\n },\n defaultVariants: {\n size: \"xs\"\n }\n});\n\nexport type InputGroupButtonProps = Omit<ButtonProps, \"size\"> & VariantProps<typeof inputGroupButtonVariants>;\n\nfunction InputGroupButton({\n className,\n type = \"button\",\n variant = \"ghost\",\n size = \"xs\",\n ...props\n}: InputGroupButtonProps) {\n return (\n <Button\n type={type}\n data-size={size}\n variant={variant}\n className={cn(inputGroupButtonVariants({ size }), className)}\n {...props}\n />\n );\n}\n\nexport type InputGroupTextProps = React.ComponentProps<\"span\">;\n\nfunction InputGroupText({ className, ...props }: InputGroupTextProps) {\n return (\n <span\n className={cn(\n \"text-muted-foreground flex items-center gap-2 text-sm [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4\",\n className\n )}\n {...props}\n />\n );\n}\n\nexport type InputGroupInputProps = React.ComponentProps<\"input\">;\n\nfunction InputGroupInput({ className, ...props }: InputGroupInputProps) {\n return (\n <Input\n data-slot=\"input-group-control\"\n className={cn(\n \"flex-1 rounded-none border-0 bg-transparent shadow-none focus-visible:ring-0 dark:bg-transparent\",\n className\n )}\n {...props}\n />\n );\n}\n\nexport type InputGroupTextareaProps = React.ComponentProps<\"textarea\">;\n\nfunction InputGroupTextarea({ className, ...props }: InputGroupTextareaProps) {\n return (\n <Textarea\n data-slot=\"input-group-control\"\n className={cn(\n \"flex-1 resize-none rounded-none border-0 bg-transparent py-3 shadow-none focus-visible:ring-0 dark:bg-transparent\",\n className\n )}\n {...props}\n />\n );\n}\n\nexport {\n InputGroup,\n InputGroupAddon,\n InputGroupButton,\n InputGroupInput,\n InputGroupText,\n InputGroupTextarea,\n inputGroupAddonVariants,\n inputGroupButtonVariants\n};\n"],"mappings":";AAsBI;AApBJ,SAAS,WAA8B;AAEvC,SAAS,UAAU;AACnB,SAAS,cAAgC;AACzC,SAAS,aAAa;AACtB,SAAS,gBAAgB;AAazB,SAAS,WAAW,EAAE,WAAW,GAAG,MAAM,GAAoB;AAC5D,SACE;AAAA,IAAC;AAAA;AAAA,MACC,aAAU;AAAA,MACV,MAAK;AAAA,MACL,WAAW;AAAA,QACT;AAAA,QACA;AAAA;AAAA,QAGA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA;AAAA,QAGA;AAAA;AAAA,QAGA;AAAA,QAEA;AAAA,MACF;AAAA,MACC,GAAG;AAAA;AAAA,EACN;AAEJ;AAEA,MAAM,0BAA0B;AAAA,EAC9B;AAAA,EACA;AAAA,IACE,UAAU;AAAA,MACR,OAAO;AAAA,QACL,gBAAgB;AAAA,QAChB,cAAc;AAAA,QACd,eACE;AAAA,QACF,aAAa;AAAA,MACf;AAAA,IACF;AAAA,IACA,iBAAiB;AAAA,MACf,OAAO;AAAA,IACT;AAAA,EACF;AACF;AAWA,SAAS,gBAAgB,EAAE,WAAW,QAAQ,gBAAgB,GAAG,MAAM,GAAyB;AAC9F;AAAA;AAAA,IAEE;AAAA,MAAC;AAAA;AAAA,QACC,MAAK;AAAA,QACL,aAAU;AAAA,QACV,cAAY;AAAA,QACZ,WAAW,GAAG,wBAAwB,EAAE,MAAM,CAAC,GAAG,SAAS;AAAA,QAC3D,SAAS,CAAC,UAAU;AAClB,cAAK,MAAM,OAAuB,QAAQ,QAAQ,GAAG;AACnD;AAAA,UACF;AACA,gBAAM,cAAc,eAAe,cAAc,OAAO,GAAG,MAAM;AAAA,QACnE;AAAA,QACC,GAAG;AAAA;AAAA,IACN;AAAA;AAEJ;AAEA,MAAM,2BAA2B,IAAI,+CAA+C;AAAA,EAClF,UAAU;AAAA,IACR,MAAM;AAAA,MACJ,IAAI;AAAA,MACJ,IAAI;AAAA,MACJ,WAAW;AAAA,MACX,WAAW;AAAA,IACb;AAAA,EACF;AAAA,EACA,iBAAiB;AAAA,IACf,MAAM;AAAA,EACR;AACF,CAAC;AAID,SAAS,iBAAiB;AAAA,EACxB;AAAA,EACA,OAAO;AAAA,EACP,UAAU;AAAA,EACV,OAAO;AAAA,EACP,GAAG;AACL,GAA0B;AACxB,SACE;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA,aAAW;AAAA,MACX;AAAA,MACA,WAAW,GAAG,yBAAyB,EAAE,KAAK,CAAC,GAAG,SAAS;AAAA,MAC1D,GAAG;AAAA;AAAA,EACN;AAEJ;AAIA,SAAS,eAAe,EAAE,WAAW,GAAG,MAAM,GAAwB;AACpE,SACE;AAAA,IAAC;AAAA;AAAA,MACC,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;AAAA,QACT;AAAA,QACA;AAAA,MACF;AAAA,MACC,GAAG;AAAA;AAAA,EACN;AAEJ;AAIA,SAAS,mBAAmB,EAAE,WAAW,GAAG,MAAM,GAA4B;AAC5E,SACE;AAAA,IAAC;AAAA;AAAA,MACC,aAAU;AAAA,MACV,WAAW;AAAA,QACT;AAAA,QACA;AAAA,MACF;AAAA,MACC,GAAG;AAAA;AAAA,EACN;AAEJ;","names":[]}
|
|
@@ -27,7 +27,7 @@ function InputOTPSlot({ index, className, ...props }) {
|
|
|
27
27
|
"data-slot": "input-otp-slot",
|
|
28
28
|
"data-active": slot?.isActive,
|
|
29
29
|
className: cn(
|
|
30
|
-
"data-[active=true]:border-
|
|
30
|
+
"data-[active=true]:border-primary-ink data-[active=true]:ring-ring/50 data-[active=true]:aria-invalid:ring-destructive/20 dark:data-[active=true]:aria-invalid:ring-destructive/40 aria-invalid:border-destructive-ink data-[active=true]:aria-invalid:border-destructive-ink border-input relative flex h-9 w-9 items-center justify-center border-y border-r text-sm shadow-xs transition-colors duration-150 ease-out outline-none first:rounded-l-md first:border-l last:rounded-r-md data-[active=true]:z-10 data-[active=true]:ring-[3px]",
|
|
31
31
|
className
|
|
32
32
|
),
|
|
33
33
|
...props,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/components/ui/input-otp.tsx"],"sourcesContent":["\"use client\";\n\nimport { OTPInput, OTPInputContext } from \"input-otp\";\nimport { MinusIcon } from \"lucide-react\";\nimport * as React from \"react\";\nimport { cn } from \"../../lib/cn.js\";\n\n/**\n * InputOTP — ô nhập mã OTP (input-otp). Dùng cho luồng 2FA / xác thực email.\n *\n * Khác bản comitor-ds: đọc slot bằng optional chaining thay vì `?? {}` — tsconfig\n * bật `noUncheckedIndexedAccess` nên `slots[index]` là `Slot | undefined`.\n */\n\nexport type InputOTPProps = React.ComponentProps<typeof OTPInput> & {\n containerClassName?: string;\n};\nexport type InputOTPGroupProps = React.ComponentProps<\"div\">;\nexport type InputOTPSlotProps = React.ComponentProps<\"div\"> & { index: number };\nexport type InputOTPSeparatorProps = React.ComponentProps<\"div\">;\n\nfunction InputOTP({ className, containerClassName, ...props }: InputOTPProps) {\n return (\n <OTPInput\n data-slot=\"input-otp\"\n containerClassName={cn(\"flex items-center gap-2 has-disabled:opacity-50\", containerClassName)}\n className={cn(\"disabled:cursor-not-allowed\", className)}\n {...props}\n />\n );\n}\n\nfunction InputOTPGroup({ className, ...props }: InputOTPGroupProps) {\n return <div data-slot=\"input-otp-group\" className={cn(\"flex items-center\", className)} {...props} />;\n}\n\nfunction InputOTPSlot({ index, className, ...props }: InputOTPSlotProps) {\n const inputOTPContext = React.useContext(OTPInputContext);\n const slot = inputOTPContext?.slots[index];\n\n return (\n <div\n data-slot=\"input-otp-slot\"\n data-active={slot?.isActive}\n className={cn(\n \"data-[active=true]:border-
|
|
1
|
+
{"version":3,"sources":["../../../src/components/ui/input-otp.tsx"],"sourcesContent":["\"use client\";\n\nimport { OTPInput, OTPInputContext } from \"input-otp\";\nimport { MinusIcon } from \"lucide-react\";\nimport * as React from \"react\";\nimport { cn } from \"../../lib/cn.js\";\n\n/**\n * InputOTP — ô nhập mã OTP (input-otp). Dùng cho luồng 2FA / xác thực email.\n *\n * Khác bản comitor-ds: đọc slot bằng optional chaining thay vì `?? {}` — tsconfig\n * bật `noUncheckedIndexedAccess` nên `slots[index]` là `Slot | undefined`.\n */\n\nexport type InputOTPProps = React.ComponentProps<typeof OTPInput> & {\n containerClassName?: string;\n};\nexport type InputOTPGroupProps = React.ComponentProps<\"div\">;\nexport type InputOTPSlotProps = React.ComponentProps<\"div\"> & { index: number };\nexport type InputOTPSeparatorProps = React.ComponentProps<\"div\">;\n\nfunction InputOTP({ className, containerClassName, ...props }: InputOTPProps) {\n return (\n <OTPInput\n data-slot=\"input-otp\"\n containerClassName={cn(\"flex items-center gap-2 has-disabled:opacity-50\", containerClassName)}\n className={cn(\"disabled:cursor-not-allowed\", className)}\n {...props}\n />\n );\n}\n\nfunction InputOTPGroup({ className, ...props }: InputOTPGroupProps) {\n return <div data-slot=\"input-otp-group\" className={cn(\"flex items-center\", className)} {...props} />;\n}\n\nfunction InputOTPSlot({ index, className, ...props }: InputOTPSlotProps) {\n const inputOTPContext = React.useContext(OTPInputContext);\n const slot = inputOTPContext?.slots[index];\n\n return (\n <div\n data-slot=\"input-otp-slot\"\n data-active={slot?.isActive}\n className={cn(\n \"data-[active=true]:border-primary-ink data-[active=true]:ring-ring/50 data-[active=true]:aria-invalid:ring-destructive/20 dark:data-[active=true]:aria-invalid:ring-destructive/40 aria-invalid:border-destructive-ink data-[active=true]:aria-invalid:border-destructive-ink border-input relative flex h-9 w-9 items-center justify-center border-y border-r text-sm shadow-xs transition-colors duration-150 ease-out outline-none first:rounded-l-md first:border-l last:rounded-r-md data-[active=true]:z-10 data-[active=true]:ring-[3px]\",\n className\n )}\n {...props}\n >\n {slot?.char}\n {slot?.hasFakeCaret && (\n <div className=\"pointer-events-none absolute inset-0 flex items-center justify-center\">\n <div className=\"animate-caret-blink bg-foreground h-4 w-px duration-1000\" />\n </div>\n )}\n </div>\n );\n}\n\nfunction InputOTPSeparator({ ...props }: InputOTPSeparatorProps) {\n return (\n // biome-ignore lint/a11y/useFocusableInteractive: dấu phân cách tĩnh giữa các nhóm ô, không phải splitter kéo được nên không cần focus\n // biome-ignore lint/a11y/useAriaPropsForRole: separator tĩnh không có giá trị → không cần aria-valuenow\n <div data-slot=\"input-otp-separator\" role=\"separator\" {...props}>\n <MinusIcon />\n </div>\n );\n}\n\nexport { InputOTP, InputOTPGroup, InputOTPSeparator, InputOTPSlot };\n"],"mappings":";AAuBI,cAkBA,YAlBA;AArBJ,SAAS,UAAU,uBAAuB;AAC1C,SAAS,iBAAiB;AAC1B,YAAY,WAAW;AACvB,SAAS,UAAU;AAgBnB,SAAS,SAAS,EAAE,WAAW,oBAAoB,GAAG,MAAM,GAAkB;AAC5E,SACE;AAAA,IAAC;AAAA;AAAA,MACC,aAAU;AAAA,MACV,oBAAoB,GAAG,mDAAmD,kBAAkB;AAAA,MAC5F,WAAW,GAAG,+BAA+B,SAAS;AAAA,MACrD,GAAG;AAAA;AAAA,EACN;AAEJ;AAEA,SAAS,cAAc,EAAE,WAAW,GAAG,MAAM,GAAuB;AAClE,SAAO,oBAAC,SAAI,aAAU,mBAAkB,WAAW,GAAG,qBAAqB,SAAS,GAAI,GAAG,OAAO;AACpG;AAEA,SAAS,aAAa,EAAE,OAAO,WAAW,GAAG,MAAM,GAAsB;AACvE,QAAM,kBAAkB,MAAM,WAAW,eAAe;AACxD,QAAM,OAAO,iBAAiB,MAAM,KAAK;AAEzC,SACE;AAAA,IAAC;AAAA;AAAA,MACC,aAAU;AAAA,MACV,eAAa,MAAM;AAAA,MACnB,WAAW;AAAA,QACT;AAAA,QACA;AAAA,MACF;AAAA,MACC,GAAG;AAAA,MAEH;AAAA,cAAM;AAAA,QACN,MAAM,gBACL,oBAAC,SAAI,WAAU,yEACb,8BAAC,SAAI,WAAU,4DAA2D,GAC5E;AAAA;AAAA;AAAA,EAEJ;AAEJ;AAEA,SAAS,kBAAkB,EAAE,GAAG,MAAM,GAA2B;AAC/D;AAAA;AAAA;AAAA,IAGE,oBAAC,SAAI,aAAU,uBAAsB,MAAK,aAAa,GAAG,OACxD,8BAAC,aAAU,GACb;AAAA;AAEJ;","names":[]}
|
|
@@ -32,9 +32,9 @@ function Input({
|
|
|
32
32
|
className: cn(
|
|
33
33
|
"w-full h-9 px-3 rounded-md border bg-background text-sm text-foreground placeholder:text-muted-foreground",
|
|
34
34
|
"transition-colors duration-150 ease-out",
|
|
35
|
-
"focus:outline-none focus:ring-2 focus:ring-ring/50 focus:border-
|
|
35
|
+
"focus:outline-none focus:ring-2 focus:ring-ring/50 focus:border-primary-ink",
|
|
36
36
|
"disabled:opacity-50 disabled:cursor-not-allowed disabled:bg-muted",
|
|
37
|
-
hasError ? "border-
|
|
37
|
+
hasError ? "border-destructive-ink focus:ring-destructive/30 focus:border-destructive-ink" : "border-input hover:border-control-edge-strong",
|
|
38
38
|
left && "pl-9",
|
|
39
39
|
right && "pr-9",
|
|
40
40
|
className
|
|
@@ -52,7 +52,7 @@ function Input({
|
|
|
52
52
|
inputEl,
|
|
53
53
|
right && /* @__PURE__ */ jsx("div", { className: "pointer-events-none absolute right-3 flex items-center text-muted-foreground", children: right })
|
|
54
54
|
] }),
|
|
55
|
-
error && /* @__PURE__ */ jsx("p", { id: `${inputId}-error`, className: "mt-1.5 text-xs text-
|
|
55
|
+
error && /* @__PURE__ */ jsx("p", { id: `${inputId}-error`, className: "mt-1.5 text-xs text-destructive-ink", children: error }),
|
|
56
56
|
hint && !error && /* @__PURE__ */ jsx("p", { id: `${inputId}-hint`, className: "mt-1.5 text-xs text-muted-foreground", children: hint })
|
|
57
57
|
] });
|
|
58
58
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/components/ui/input.tsx"],"sourcesContent":["\"use client\";\n\nimport * as React from \"react\";\nimport { cn } from \"../../lib/cn.js\";\n\nexport interface InputProps extends React.ComponentProps<\"input\"> {\n /** Nhãn hiển thị phía trên ô nhập. */\n label?: string;\n /** Thông báo lỗi — có giá trị là ô nhập chuyển sang trạng thái lỗi. */\n error?: string;\n /** Gợi ý phụ dưới ô nhập; bị `error` che khi có lỗi. */\n hint?: string;\n /** Nội dung chèn bên trái trong lòng ô nhập (icon, đơn vị…). */\n leftAddon?: React.ReactNode;\n /** Nội dung chèn bên phải trong lòng ô nhập. */\n rightAddon?: React.ReactNode;\n /** Alias của `leftAddon`. */\n leftIcon?: React.ReactNode;\n /** Alias của `rightAddon`. */\n rightIcon?: React.ReactNode;\n}\n\n/*\n * Style port nguyên trạng từ comitor-ds. Các prop label / error / hint / addon là phần\n * BỔ SUNG: không truyền cái nào thì component render đúng một thẻ <input> trần đã style.\n * (Đổi gray-* → ash-* theo namespace thang xám của package — xem styles.css.)\n */\nfunction Input({\n className,\n type,\n label,\n error,\n hint,\n leftAddon,\n rightAddon,\n leftIcon,\n rightIcon,\n id,\n \"aria-invalid\": ariaInvalid,\n ...props\n}: InputProps) {\n const reactId = React.useId();\n const inputId = id ?? reactId;\n const hasError = Boolean(error) || ariaInvalid === true || ariaInvalid === \"true\";\n const left = leftAddon ?? leftIcon;\n const right = rightAddon ?? rightIcon;\n\n const inputEl = (\n <input\n id={inputId}\n type={type}\n data-slot=\"input\"\n aria-invalid={hasError || undefined}\n aria-describedby={error ? `${inputId}-error` : hint ? `${inputId}-hint` : undefined}\n className={cn(\n \"w-full h-9 px-3 rounded-md border bg-background text-sm text-foreground placeholder:text-muted-foreground\",\n \"transition-colors duration-150 ease-out\",\n \"focus:outline-none focus:ring-2 focus:ring-ring/50 focus:border-
|
|
1
|
+
{"version":3,"sources":["../../../src/components/ui/input.tsx"],"sourcesContent":["\"use client\";\n\nimport * as React from \"react\";\nimport { cn } from \"../../lib/cn.js\";\n\nexport interface InputProps extends React.ComponentProps<\"input\"> {\n /** Nhãn hiển thị phía trên ô nhập. */\n label?: string;\n /** Thông báo lỗi — có giá trị là ô nhập chuyển sang trạng thái lỗi. */\n error?: string;\n /** Gợi ý phụ dưới ô nhập; bị `error` che khi có lỗi. */\n hint?: string;\n /** Nội dung chèn bên trái trong lòng ô nhập (icon, đơn vị…). */\n leftAddon?: React.ReactNode;\n /** Nội dung chèn bên phải trong lòng ô nhập. */\n rightAddon?: React.ReactNode;\n /** Alias của `leftAddon`. */\n leftIcon?: React.ReactNode;\n /** Alias của `rightAddon`. */\n rightIcon?: React.ReactNode;\n}\n\n/*\n * Style port nguyên trạng từ comitor-ds. Các prop label / error / hint / addon là phần\n * BỔ SUNG: không truyền cái nào thì component render đúng một thẻ <input> trần đã style.\n * (Đổi gray-* → ash-* theo namespace thang xám của package — xem styles.css.)\n *\n * ─ TRẠNG THÁI LỖI: BẬC `-ink`, KHÔNG PHẢI `--red` CŨNG KHÔNG PHẢI `--destructive` ─\n *\n * `--red` là thang màu phụ THÔ, vai trò TÔ NỀN: light #D64545 (chữ 12px trên nền trắng chỉ\n * 4,38:1 ✗), dark #F87171. `--destructive` là màu NỀN của nút xoá, ghim một giá trị cho cả hai\n * theme. Cả hai đều không phải bậc dành cho chữ/viền đứng trên nền TRANG — bậc đó là\n * `--destructive-ink` (= `--red-ink`), và nó gánh cả chữ lẫn viền:\n *\n * chữ lỗi `--destructive-ink` #9A3537 trên nền trắng = 7,15:1 ✓ · #F87171 trên #0E1116 = 6,84:1 ✓\n * viền lỗi cùng token : 7,15:1 (light) / 6,84:1 (dark) ✓ (ngưỡng viền control 3:1)\n *\n * Bản trước dùng `border-destructive` cho viền (5,03:1 light nhưng chỉ **3,76:1** ở dark — sát\n * ngưỡng) và một chuỗi `color-mix(--destructive, --ink 30%)` + `dark:text-red` cho chữ. Số thì\n * đạt, nhưng nhánh `dark:text-red` là token NỀN đem làm màu CHỮ — đúng cái lỗi mà hợp đồng màu\n * cấm; và chuỗi color-mix chép tay ở đây dễ lệch % so với `Badge`. Nay cả hai đi qua một token.\n *\n * ─ VIỀN LÚC NGHỈ / HOVER / FOCUS ─\n * `border-input` (= `--control-edge`) 3,83:1 (light) · 4,94:1 (dark) ✓. Hover phải ĐẬM HƠN lúc\n * nghỉ: `hover:border-ash-300 dark:hover:border-ash-500` cũ ở light chỉ **1,62:1** — rê chuột\n * vào là ô nhập gần như biến mất. Nay `--control-edge-strong`: 10,55:1 (light) · 11,65:1 (dark).\n * Focus cũng vậy — `focus:border-gold-300` (#E8B824) chỉ **1,86:1** trên nền trắng, tức lúc focus\n * ô nhập MẤT ranh giới; `--primary-ink` giữ đúng sắc gold mà đạt 6,51:1 (light) · 12,67:1 (dark).\n */\nfunction Input({\n className,\n type,\n label,\n error,\n hint,\n leftAddon,\n rightAddon,\n leftIcon,\n rightIcon,\n id,\n \"aria-invalid\": ariaInvalid,\n ...props\n}: InputProps) {\n const reactId = React.useId();\n const inputId = id ?? reactId;\n const hasError = Boolean(error) || ariaInvalid === true || ariaInvalid === \"true\";\n const left = leftAddon ?? leftIcon;\n const right = rightAddon ?? rightIcon;\n\n const inputEl = (\n <input\n id={inputId}\n type={type}\n data-slot=\"input\"\n aria-invalid={hasError || undefined}\n aria-describedby={error ? `${inputId}-error` : hint ? `${inputId}-hint` : undefined}\n className={cn(\n \"w-full h-9 px-3 rounded-md border bg-background text-sm text-foreground placeholder:text-muted-foreground\",\n \"transition-colors duration-150 ease-out\",\n \"focus:outline-none focus:ring-2 focus:ring-ring/50 focus:border-primary-ink\",\n \"disabled:opacity-50 disabled:cursor-not-allowed disabled:bg-muted\",\n hasError\n ? \"border-destructive-ink focus:ring-destructive/30 focus:border-destructive-ink\"\n : \"border-input hover:border-control-edge-strong\",\n left && \"pl-9\",\n right && \"pr-9\",\n className\n )}\n {...props}\n />\n );\n\n if (!label && !error && !hint && !left && !right) {\n return inputEl;\n }\n\n return (\n <div className=\"w-full\">\n {label && (\n <label htmlFor={inputId} className=\"mb-1.5 block text-sm font-medium text-foreground\">\n {label}\n </label>\n )}\n <div className=\"relative flex items-center\">\n {left && (\n <div className=\"pointer-events-none absolute left-3 flex items-center text-muted-foreground\">{left}</div>\n )}\n {inputEl}\n {right && (\n <div className=\"pointer-events-none absolute right-3 flex items-center text-muted-foreground\">{right}</div>\n )}\n </div>\n {error && (\n <p id={`${inputId}-error`} className=\"mt-1.5 text-xs text-destructive-ink\">\n {error}\n </p>\n )}\n {hint && !error && (\n <p id={`${inputId}-hint`} className=\"mt-1.5 text-xs text-muted-foreground\">\n {hint}\n </p>\n )}\n </div>\n );\n}\n\nexport { Input };\n"],"mappings":";AAsEI,cAiCE,YAjCF;AApEJ,YAAY,WAAW;AACvB,SAAS,UAAU;AA8CnB,SAAS,MAAM;AAAA,EACb;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,gBAAgB;AAAA,EAChB,GAAG;AACL,GAAe;AACb,QAAM,UAAU,MAAM,MAAM;AAC5B,QAAM,UAAU,MAAM;AACtB,QAAM,WAAW,QAAQ,KAAK,KAAK,gBAAgB,QAAQ,gBAAgB;AAC3E,QAAM,OAAO,aAAa;AAC1B,QAAM,QAAQ,cAAc;AAE5B,QAAM,UACJ;AAAA,IAAC;AAAA;AAAA,MACC,IAAI;AAAA,MACJ;AAAA,MACA,aAAU;AAAA,MACV,gBAAc,YAAY;AAAA,MAC1B,oBAAkB,QAAQ,GAAG,OAAO,WAAW,OAAO,GAAG,OAAO,UAAU;AAAA,MAC1E,WAAW;AAAA,QACT;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA,WACI,kFACA;AAAA,QACJ,QAAQ;AAAA,QACR,SAAS;AAAA,QACT;AAAA,MACF;AAAA,MACC,GAAG;AAAA;AAAA,EACN;AAGF,MAAI,CAAC,SAAS,CAAC,SAAS,CAAC,QAAQ,CAAC,QAAQ,CAAC,OAAO;AAChD,WAAO;AAAA,EACT;AAEA,SACE,qBAAC,SAAI,WAAU,UACZ;AAAA,aACC,oBAAC,WAAM,SAAS,SAAS,WAAU,oDAChC,iBACH;AAAA,IAEF,qBAAC,SAAI,WAAU,8BACZ;AAAA,cACC,oBAAC,SAAI,WAAU,+EAA+E,gBAAK;AAAA,MAEpG;AAAA,MACA,SACC,oBAAC,SAAI,WAAU,gFAAgF,iBAAM;AAAA,OAEzG;AAAA,IACC,SACC,oBAAC,OAAE,IAAI,GAAG,OAAO,UAAU,WAAU,uCAClC,iBACH;AAAA,IAED,QAAQ,CAAC,SACR,oBAAC,OAAE,IAAI,GAAG,OAAO,SAAS,WAAU,wCACjC,gBACH;AAAA,KAEJ;AAEJ;","names":[]}
|
|
@@ -95,7 +95,7 @@ function ItemDescription({ className, ...props }) {
|
|
|
95
95
|
"data-slot": "item-description",
|
|
96
96
|
className: cn(
|
|
97
97
|
"text-muted-foreground line-clamp-2 text-sm leading-normal font-normal text-balance",
|
|
98
|
-
"[&>a:hover]:text-primary [&>a]:underline [&>a]:underline-offset-4",
|
|
98
|
+
"[&>a:hover]:text-primary-ink [&>a]:underline [&>a]:underline-offset-4",
|
|
99
99
|
className
|
|
100
100
|
),
|
|
101
101
|
...props
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/components/ui/item.tsx"],"sourcesContent":["import { Slot } from \"@radix-ui/react-slot\";\nimport { cva, type VariantProps } from \"class-variance-authority\";\nimport type * as React from \"react\";\nimport { cn } from \"../../lib/cn.js\";\nimport { Separator, type SeparatorProps } from \"./separator.js\";\n\nexport type ItemGroupProps = React.ComponentProps<\"div\">;\nexport type ItemSeparatorProps = SeparatorProps;\n\nfunction ItemGroup({ className, ...props }: ItemGroupProps) {\n return (\n <div role=\"list\" data-slot=\"item-group\" className={cn(\"group/item-group flex flex-col\", className)} {...props} />\n );\n}\n\nfunction ItemSeparator({ className, ...props }: ItemSeparatorProps) {\n return <Separator data-slot=\"item-separator\" orientation=\"horizontal\" className={cn(\"my-0\", className)} {...props} />;\n}\n\nconst itemVariants = cva(\n \"group/item flex items-center border border-transparent text-sm rounded-md transition-colors duration-150 ease-out [a&]:hover:bg-accent/50 [a&]:transition-colors flex-wrap outline-none focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring/50 focus-visible:ring-offset-2 focus-visible:ring-offset-background\",\n {\n variants: {\n variant: {\n default: \"bg-transparent\",\n outline: \"border-border\",\n muted: \"bg-muted/50\"\n },\n size: {\n default: \"p-4 gap-4\",\n sm: \"py-3 px-4 gap-2.5\"\n }\n },\n defaultVariants: {\n variant: \"default\",\n size: \"default\"\n }\n }\n);\n\nexport interface ItemProps extends React.ComponentProps<\"div\">, VariantProps<typeof itemVariants> {\n /** Render ra chính phần tử con (Radix Slot) — dùng khi cần <a> hoặc <button>. */\n asChild?: boolean;\n}\n\nfunction Item({ className, variant = \"default\", size = \"default\", asChild = false, ...props }: ItemProps) {\n const Comp = asChild ? Slot : \"div\";\n return (\n <Comp\n data-slot=\"item\"\n data-variant={variant}\n data-size={size}\n className={cn(itemVariants({ variant, size, className }))}\n {...props}\n />\n );\n}\n\nconst itemMediaVariants = cva(\n \"flex shrink-0 items-center justify-center gap-2 group-has-[[data-slot=item-description]]/item:self-start [&_svg]:pointer-events-none group-has-[[data-slot=item-description]]/item:translate-y-0.5\",\n {\n variants: {\n variant: {\n default: \"bg-transparent\",\n icon: \"size-8 border rounded-sm bg-muted [&_svg:not([class*='size-'])]:size-4\",\n image: \"size-10 rounded-sm overflow-hidden [&_img]:size-full [&_img]:object-cover\"\n }\n },\n defaultVariants: {\n variant: \"default\"\n }\n }\n);\n\nexport interface ItemMediaProps extends React.ComponentProps<\"div\">, VariantProps<typeof itemMediaVariants> {}\nexport type ItemContentProps = React.ComponentProps<\"div\">;\nexport type ItemTitleProps = React.ComponentProps<\"div\">;\nexport type ItemDescriptionProps = React.ComponentProps<\"p\">;\nexport type ItemActionsProps = React.ComponentProps<\"div\">;\nexport type ItemHeaderProps = React.ComponentProps<\"div\">;\nexport type ItemFooterProps = React.ComponentProps<\"div\">;\n\nfunction ItemMedia({ className, variant = \"default\", ...props }: ItemMediaProps) {\n return (\n <div\n data-slot=\"item-media\"\n data-variant={variant}\n className={cn(itemMediaVariants({ variant, className }))}\n {...props}\n />\n );\n}\n\nfunction ItemContent({ className, ...props }: ItemContentProps) {\n return (\n <div\n data-slot=\"item-content\"\n className={cn(\"flex flex-1 flex-col gap-1 [&+[data-slot=item-content]]:flex-none\", className)}\n {...props}\n />\n );\n}\n\nfunction ItemTitle({ className, ...props }: ItemTitleProps) {\n return (\n <div\n data-slot=\"item-title\"\n className={cn(\"flex w-fit items-center gap-2 text-sm leading-snug font-medium\", className)}\n {...props}\n />\n );\n}\n\nfunction ItemDescription({ className, ...props }: ItemDescriptionProps) {\n return (\n <p\n data-slot=\"item-description\"\n className={cn(\n \"text-muted-foreground line-clamp-2 text-sm leading-normal font-normal text-balance\",\n \"[&>a:hover]:text-primary [&>a]:underline [&>a]:underline-offset-4\",\n className\n )}\n {...props}\n />\n );\n}\n\nfunction ItemActions({ className, ...props }: ItemActionsProps) {\n return <div data-slot=\"item-actions\" className={cn(\"flex items-center gap-2\", className)} {...props} />;\n}\n\nfunction ItemHeader({ className, ...props }: ItemHeaderProps) {\n return (\n <div\n data-slot=\"item-header\"\n className={cn(\"flex basis-full items-center justify-between gap-2\", className)}\n {...props}\n />\n );\n}\n\nfunction ItemFooter({ className, ...props }: ItemFooterProps) {\n return (\n <div\n data-slot=\"item-footer\"\n className={cn(\"flex basis-full items-center justify-between gap-2\", className)}\n {...props}\n />\n );\n}\n\nexport {\n Item,\n ItemActions,\n ItemContent,\n ItemDescription,\n ItemFooter,\n ItemGroup,\n ItemHeader,\n ItemMedia,\n ItemSeparator,\n ItemTitle,\n itemMediaVariants,\n itemVariants\n};\n"],"mappings":"AAWI;AAXJ,SAAS,YAAY;AACrB,SAAS,WAA8B;AAEvC,SAAS,UAAU;AACnB,SAAS,iBAAsC;AAK/C,SAAS,UAAU,EAAE,WAAW,GAAG,MAAM,GAAmB;AAC1D,SACE,oBAAC,SAAI,MAAK,QAAO,aAAU,cAAa,WAAW,GAAG,kCAAkC,SAAS,GAAI,GAAG,OAAO;AAEnH;AAEA,SAAS,cAAc,EAAE,WAAW,GAAG,MAAM,GAAuB;AAClE,SAAO,oBAAC,aAAU,aAAU,kBAAiB,aAAY,cAAa,WAAW,GAAG,QAAQ,SAAS,GAAI,GAAG,OAAO;AACrH;AAEA,MAAM,eAAe;AAAA,EACnB;AAAA,EACA;AAAA,IACE,UAAU;AAAA,MACR,SAAS;AAAA,QACP,SAAS;AAAA,QACT,SAAS;AAAA,QACT,OAAO;AAAA,MACT;AAAA,MACA,MAAM;AAAA,QACJ,SAAS;AAAA,QACT,IAAI;AAAA,MACN;AAAA,IACF;AAAA,IACA,iBAAiB;AAAA,MACf,SAAS;AAAA,MACT,MAAM;AAAA,IACR;AAAA,EACF;AACF;AAOA,SAAS,KAAK,EAAE,WAAW,UAAU,WAAW,OAAO,WAAW,UAAU,OAAO,GAAG,MAAM,GAAc;AACxG,QAAM,OAAO,UAAU,OAAO;AAC9B,SACE;AAAA,IAAC;AAAA;AAAA,MACC,aAAU;AAAA,MACV,gBAAc;AAAA,MACd,aAAW;AAAA,MACX,WAAW,GAAG,aAAa,EAAE,SAAS,MAAM,UAAU,CAAC,CAAC;AAAA,MACvD,GAAG;AAAA;AAAA,EACN;AAEJ;AAEA,MAAM,oBAAoB;AAAA,EACxB;AAAA,EACA;AAAA,IACE,UAAU;AAAA,MACR,SAAS;AAAA,QACP,SAAS;AAAA,QACT,MAAM;AAAA,QACN,OAAO;AAAA,MACT;AAAA,IACF;AAAA,IACA,iBAAiB;AAAA,MACf,SAAS;AAAA,IACX;AAAA,EACF;AACF;AAUA,SAAS,UAAU,EAAE,WAAW,UAAU,WAAW,GAAG,MAAM,GAAmB;AAC/E,SACE;AAAA,IAAC;AAAA;AAAA,MACC,aAAU;AAAA,MACV,gBAAc;AAAA,MACd,WAAW,GAAG,kBAAkB,EAAE,SAAS,UAAU,CAAC,CAAC;AAAA,MACtD,GAAG;AAAA;AAAA,EACN;AAEJ;AAEA,SAAS,YAAY,EAAE,WAAW,GAAG,MAAM,GAAqB;AAC9D,SACE;AAAA,IAAC;AAAA;AAAA,MACC,aAAU;AAAA,MACV,WAAW,GAAG,qEAAqE,SAAS;AAAA,MAC3F,GAAG;AAAA;AAAA,EACN;AAEJ;AAEA,SAAS,UAAU,EAAE,WAAW,GAAG,MAAM,GAAmB;AAC1D,SACE;AAAA,IAAC;AAAA;AAAA,MACC,aAAU;AAAA,MACV,WAAW,GAAG,kEAAkE,SAAS;AAAA,MACxF,GAAG;AAAA;AAAA,EACN;AAEJ;AAEA,SAAS,gBAAgB,EAAE,WAAW,GAAG,MAAM,GAAyB;AACtE,SACE;AAAA,IAAC;AAAA;AAAA,MACC,aAAU;AAAA,MACV,WAAW;AAAA,QACT;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,MACC,GAAG;AAAA;AAAA,EACN;AAEJ;AAEA,SAAS,YAAY,EAAE,WAAW,GAAG,MAAM,GAAqB;AAC9D,SAAO,oBAAC,SAAI,aAAU,gBAAe,WAAW,GAAG,2BAA2B,SAAS,GAAI,GAAG,OAAO;AACvG;AAEA,SAAS,WAAW,EAAE,WAAW,GAAG,MAAM,GAAoB;AAC5D,SACE;AAAA,IAAC;AAAA;AAAA,MACC,aAAU;AAAA,MACV,WAAW,GAAG,sDAAsD,SAAS;AAAA,MAC5E,GAAG;AAAA;AAAA,EACN;AAEJ;AAEA,SAAS,WAAW,EAAE,WAAW,GAAG,MAAM,GAAoB;AAC5D,SACE;AAAA,IAAC;AAAA;AAAA,MACC,aAAU;AAAA,MACV,WAAW,GAAG,sDAAsD,SAAS;AAAA,MAC5E,GAAG;AAAA;AAAA,EACN;AAEJ;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../src/components/ui/item.tsx"],"sourcesContent":["import { Slot } from \"@radix-ui/react-slot\";\nimport { cva, type VariantProps } from \"class-variance-authority\";\nimport type * as React from \"react\";\nimport { cn } from \"../../lib/cn.js\";\nimport { Separator, type SeparatorProps } from \"./separator.js\";\n\nexport type ItemGroupProps = React.ComponentProps<\"div\">;\nexport type ItemSeparatorProps = SeparatorProps;\n\nfunction ItemGroup({ className, ...props }: ItemGroupProps) {\n return (\n <div role=\"list\" data-slot=\"item-group\" className={cn(\"group/item-group flex flex-col\", className)} {...props} />\n );\n}\n\nfunction ItemSeparator({ className, ...props }: ItemSeparatorProps) {\n return <Separator data-slot=\"item-separator\" orientation=\"horizontal\" className={cn(\"my-0\", className)} {...props} />;\n}\n\nconst itemVariants = cva(\n \"group/item flex items-center border border-transparent text-sm rounded-md transition-colors duration-150 ease-out [a&]:hover:bg-accent/50 [a&]:transition-colors flex-wrap outline-none focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring/50 focus-visible:ring-offset-2 focus-visible:ring-offset-background\",\n {\n variants: {\n variant: {\n default: \"bg-transparent\",\n outline: \"border-border\",\n muted: \"bg-muted/50\"\n },\n size: {\n default: \"p-4 gap-4\",\n sm: \"py-3 px-4 gap-2.5\"\n }\n },\n defaultVariants: {\n variant: \"default\",\n size: \"default\"\n }\n }\n);\n\nexport interface ItemProps extends React.ComponentProps<\"div\">, VariantProps<typeof itemVariants> {\n /** Render ra chính phần tử con (Radix Slot) — dùng khi cần <a> hoặc <button>. */\n asChild?: boolean;\n}\n\nfunction Item({ className, variant = \"default\", size = \"default\", asChild = false, ...props }: ItemProps) {\n const Comp = asChild ? Slot : \"div\";\n return (\n <Comp\n data-slot=\"item\"\n data-variant={variant}\n data-size={size}\n className={cn(itemVariants({ variant, size, className }))}\n {...props}\n />\n );\n}\n\nconst itemMediaVariants = cva(\n \"flex shrink-0 items-center justify-center gap-2 group-has-[[data-slot=item-description]]/item:self-start [&_svg]:pointer-events-none group-has-[[data-slot=item-description]]/item:translate-y-0.5\",\n {\n variants: {\n variant: {\n default: \"bg-transparent\",\n icon: \"size-8 border rounded-sm bg-muted [&_svg:not([class*='size-'])]:size-4\",\n image: \"size-10 rounded-sm overflow-hidden [&_img]:size-full [&_img]:object-cover\"\n }\n },\n defaultVariants: {\n variant: \"default\"\n }\n }\n);\n\nexport interface ItemMediaProps extends React.ComponentProps<\"div\">, VariantProps<typeof itemMediaVariants> {}\nexport type ItemContentProps = React.ComponentProps<\"div\">;\nexport type ItemTitleProps = React.ComponentProps<\"div\">;\nexport type ItemDescriptionProps = React.ComponentProps<\"p\">;\nexport type ItemActionsProps = React.ComponentProps<\"div\">;\nexport type ItemHeaderProps = React.ComponentProps<\"div\">;\nexport type ItemFooterProps = React.ComponentProps<\"div\">;\n\nfunction ItemMedia({ className, variant = \"default\", ...props }: ItemMediaProps) {\n return (\n <div\n data-slot=\"item-media\"\n data-variant={variant}\n className={cn(itemMediaVariants({ variant, className }))}\n {...props}\n />\n );\n}\n\nfunction ItemContent({ className, ...props }: ItemContentProps) {\n return (\n <div\n data-slot=\"item-content\"\n className={cn(\"flex flex-1 flex-col gap-1 [&+[data-slot=item-content]]:flex-none\", className)}\n {...props}\n />\n );\n}\n\nfunction ItemTitle({ className, ...props }: ItemTitleProps) {\n return (\n <div\n data-slot=\"item-title\"\n className={cn(\"flex w-fit items-center gap-2 text-sm leading-snug font-medium\", className)}\n {...props}\n />\n );\n}\n\nfunction ItemDescription({ className, ...props }: ItemDescriptionProps) {\n return (\n <p\n data-slot=\"item-description\"\n className={cn(\n \"text-muted-foreground line-clamp-2 text-sm leading-normal font-normal text-balance\",\n \"[&>a:hover]:text-primary-ink [&>a]:underline [&>a]:underline-offset-4\",\n className\n )}\n {...props}\n />\n );\n}\n\nfunction ItemActions({ className, ...props }: ItemActionsProps) {\n return <div data-slot=\"item-actions\" className={cn(\"flex items-center gap-2\", className)} {...props} />;\n}\n\nfunction ItemHeader({ className, ...props }: ItemHeaderProps) {\n return (\n <div\n data-slot=\"item-header\"\n className={cn(\"flex basis-full items-center justify-between gap-2\", className)}\n {...props}\n />\n );\n}\n\nfunction ItemFooter({ className, ...props }: ItemFooterProps) {\n return (\n <div\n data-slot=\"item-footer\"\n className={cn(\"flex basis-full items-center justify-between gap-2\", className)}\n {...props}\n />\n );\n}\n\nexport {\n Item,\n ItemActions,\n ItemContent,\n ItemDescription,\n ItemFooter,\n ItemGroup,\n ItemHeader,\n ItemMedia,\n ItemSeparator,\n ItemTitle,\n itemMediaVariants,\n itemVariants\n};\n"],"mappings":"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","names":[]}
|
|
@@ -68,7 +68,7 @@ function MenubarItem({ className, inset, variant = "default", ...props }) {
|
|
|
68
68
|
"data-inset": inset,
|
|
69
69
|
"data-variant": variant,
|
|
70
70
|
className: cn(
|
|
71
|
-
"focus:bg-accent focus:text-accent-foreground data-[variant=destructive]:text-destructive data-[variant=destructive]:focus:bg-destructive/10 dark:data-[variant=destructive]:focus:bg-destructive/20 data-[variant=destructive]:focus:text-destructive data-[variant=destructive]:*:[svg]:!text-destructive [&_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]:pointer-events-none data-[disabled]:opacity-50 data-[inset]:pl-8 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
|
|
71
|
+
"focus:bg-accent focus:text-accent-foreground data-[variant=destructive]:text-destructive-ink data-[variant=destructive]:focus:bg-destructive/10 dark:data-[variant=destructive]:focus:bg-destructive/20 data-[variant=destructive]:focus:text-destructive-ink data-[variant=destructive]:*:[svg]:!text-destructive-ink [&_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]:pointer-events-none data-[disabled]:opacity-50 data-[inset]:pl-8 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
|
|
72
72
|
className
|
|
73
73
|
),
|
|
74
74
|
...props
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/components/ui/menubar.tsx"],"sourcesContent":["\"use client\";\n\nimport * as MenubarPrimitive from \"@radix-ui/react-menubar\";\nimport { CheckIcon, ChevronRightIcon, CircleIcon } from \"lucide-react\";\nimport type * as React from \"react\";\nimport { cn } from \"../../lib/cn.js\";\n\n/**\n * Menubar — thanh menu ngang kiểu ứng dụng desktop (Radix Menubar).\n *\n * Dùng cho màn hình soạn thảo/bảng tính (Docs, Sheets nội bộ) — nơi cần nhóm lệnh\n * cố định. KHÔNG dùng làm điều hướng chính của app: điều hướng nằm ở Sidebar/AppHeader.\n */\n\nexport type MenubarProps = React.ComponentProps<typeof MenubarPrimitive.Root>;\n\nfunction Menubar({ className, ...props }: MenubarProps) {\n return (\n <MenubarPrimitive.Root\n data-slot=\"menubar\"\n className={cn(\"bg-background flex h-9 items-center gap-1 rounded-md border p-1 shadow-xs\", className)}\n {...props}\n />\n );\n}\n\nexport type MenubarMenuProps = React.ComponentProps<typeof MenubarPrimitive.Menu>;\n\nfunction MenubarMenu({ ...props }: MenubarMenuProps) {\n return <MenubarPrimitive.Menu data-slot=\"menubar-menu\" {...props} />;\n}\n\nexport type MenubarGroupProps = React.ComponentProps<typeof MenubarPrimitive.Group>;\n\nfunction MenubarGroup({ ...props }: MenubarGroupProps) {\n return <MenubarPrimitive.Group data-slot=\"menubar-group\" {...props} />;\n}\n\nexport type MenubarPortalProps = React.ComponentProps<typeof MenubarPrimitive.Portal>;\n\nfunction MenubarPortal({ ...props }: MenubarPortalProps) {\n return <MenubarPrimitive.Portal data-slot=\"menubar-portal\" {...props} />;\n}\n\nexport type MenubarRadioGroupProps = React.ComponentProps<typeof MenubarPrimitive.RadioGroup>;\n\nfunction MenubarRadioGroup({ ...props }: MenubarRadioGroupProps) {\n return <MenubarPrimitive.RadioGroup data-slot=\"menubar-radio-group\" {...props} />;\n}\n\nexport type MenubarTriggerProps = React.ComponentProps<typeof MenubarPrimitive.Trigger>;\n\nfunction MenubarTrigger({ className, ...props }: MenubarTriggerProps) {\n return (\n <MenubarPrimitive.Trigger\n data-slot=\"menubar-trigger\"\n className={cn(\n \"focus:bg-accent focus:text-accent-foreground data-[state=open]:bg-accent data-[state=open]:text-accent-foreground flex items-center rounded-sm px-2 py-1 text-sm font-medium outline-hidden select-none\",\n className\n )}\n {...props}\n />\n );\n}\n\nexport type MenubarContentProps = React.ComponentProps<typeof MenubarPrimitive.Content>;\n\nfunction MenubarContent({\n className,\n align = \"start\",\n alignOffset = -4,\n sideOffset = 8,\n ...props\n}: MenubarContentProps) {\n return (\n <MenubarPortal>\n <MenubarPrimitive.Content\n data-slot=\"menubar-content\"\n align={align}\n alignOffset={alignOffset}\n sideOffset={sideOffset}\n className={cn(\n \"bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 min-w-[12rem] origin-(--radix-menubar-content-transform-origin) overflow-hidden rounded-md border p-1 shadow-overlay\",\n className\n )}\n {...props}\n />\n </MenubarPortal>\n );\n}\n\nexport type MenubarItemVariant = \"default\" | \"destructive\";\n\nexport type MenubarItemProps = React.ComponentProps<typeof MenubarPrimitive.Item> & {\n inset?: boolean;\n variant?: MenubarItemVariant;\n};\n\nfunction MenubarItem({ className, inset, variant = \"default\", ...props }: MenubarItemProps) {\n return (\n <MenubarPrimitive.Item\n data-slot=\"menubar-item\"\n data-inset={inset}\n data-variant={variant}\n className={cn(\n \"focus:bg-accent focus:text-accent-foreground data-[variant=destructive]:text-destructive data-[variant=destructive]:focus:bg-destructive/10 dark:data-[variant=destructive]:focus:bg-destructive/20 data-[variant=destructive]:focus:text-destructive data-[variant=destructive]:*:[svg]:!text-destructive [&_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]:pointer-events-none data-[disabled]:opacity-50 data-[inset]:pl-8 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\n className\n )}\n {...props}\n />\n );\n}\n\nexport type MenubarCheckboxItemProps = React.ComponentProps<typeof MenubarPrimitive.CheckboxItem>;\n\nfunction MenubarCheckboxItem({ className, children, checked, ...props }: MenubarCheckboxItemProps) {\n return (\n <MenubarPrimitive.CheckboxItem\n data-slot=\"menubar-checkbox-item\"\n className={cn(\n \"focus:bg-accent focus:text-accent-foreground relative flex cursor-default items-center gap-2 rounded-xs py-1.5 pr-2 pl-8 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\n className\n )}\n checked={checked}\n {...props}\n >\n <span className=\"pointer-events-none absolute left-2 flex size-3.5 items-center justify-center\">\n <MenubarPrimitive.ItemIndicator>\n <CheckIcon className=\"size-4\" />\n </MenubarPrimitive.ItemIndicator>\n </span>\n {children}\n </MenubarPrimitive.CheckboxItem>\n );\n}\n\nexport type MenubarRadioItemProps = React.ComponentProps<typeof MenubarPrimitive.RadioItem>;\n\nfunction MenubarRadioItem({ className, children, ...props }: MenubarRadioItemProps) {\n return (\n <MenubarPrimitive.RadioItem\n data-slot=\"menubar-radio-item\"\n className={cn(\n \"focus:bg-accent focus:text-accent-foreground relative flex cursor-default items-center gap-2 rounded-xs py-1.5 pr-2 pl-8 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\n className\n )}\n {...props}\n >\n <span className=\"pointer-events-none absolute left-2 flex size-3.5 items-center justify-center\">\n <MenubarPrimitive.ItemIndicator>\n <CircleIcon className=\"size-2 fill-current\" />\n </MenubarPrimitive.ItemIndicator>\n </span>\n {children}\n </MenubarPrimitive.RadioItem>\n );\n}\n\nexport type MenubarLabelProps = React.ComponentProps<typeof MenubarPrimitive.Label> & {\n inset?: boolean;\n};\n\nfunction MenubarLabel({ className, inset, ...props }: MenubarLabelProps) {\n return (\n <MenubarPrimitive.Label\n data-slot=\"menubar-label\"\n data-inset={inset}\n className={cn(\"px-2 py-1.5 text-sm font-medium data-[inset]:pl-8\", className)}\n {...props}\n />\n );\n}\n\nexport type MenubarSeparatorProps = React.ComponentProps<typeof MenubarPrimitive.Separator>;\n\nfunction MenubarSeparator({ className, ...props }: MenubarSeparatorProps) {\n return (\n <MenubarPrimitive.Separator\n data-slot=\"menubar-separator\"\n className={cn(\"bg-border -mx-1 my-1 h-px\", className)}\n {...props}\n />\n );\n}\n\nexport type MenubarShortcutProps = React.ComponentProps<\"span\">;\n\nfunction MenubarShortcut({ className, ...props }: MenubarShortcutProps) {\n return (\n <span\n data-slot=\"menubar-shortcut\"\n className={cn(\"text-muted-foreground ml-auto text-xs tracking-widest\", className)}\n {...props}\n />\n );\n}\n\nexport type MenubarSubProps = React.ComponentProps<typeof MenubarPrimitive.Sub>;\n\nfunction MenubarSub({ ...props }: MenubarSubProps) {\n return <MenubarPrimitive.Sub data-slot=\"menubar-sub\" {...props} />;\n}\n\nexport type MenubarSubTriggerProps = React.ComponentProps<typeof MenubarPrimitive.SubTrigger> & {\n inset?: boolean;\n};\n\nfunction MenubarSubTrigger({ className, inset, children, ...props }: MenubarSubTriggerProps) {\n return (\n <MenubarPrimitive.SubTrigger\n data-slot=\"menubar-sub-trigger\"\n data-inset={inset}\n className={cn(\n \"focus:bg-accent focus:text-accent-foreground data-[state=open]:bg-accent data-[state=open]:text-accent-foreground flex cursor-default items-center rounded-sm px-2 py-1.5 text-sm outline-none select-none data-[inset]:pl-8\",\n className\n )}\n {...props}\n >\n {children}\n <ChevronRightIcon className=\"ml-auto h-4 w-4\" />\n </MenubarPrimitive.SubTrigger>\n );\n}\n\nexport type MenubarSubContentProps = React.ComponentProps<typeof MenubarPrimitive.SubContent>;\n\nfunction MenubarSubContent({ className, ...props }: MenubarSubContentProps) {\n return (\n <MenubarPrimitive.SubContent\n data-slot=\"menubar-sub-content\"\n className={cn(\n \"bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 min-w-[8rem] origin-(--radix-menubar-content-transform-origin) overflow-hidden rounded-md border p-1 shadow-overlay\",\n className\n )}\n {...props}\n />\n );\n}\n\nexport {\n Menubar,\n MenubarCheckboxItem,\n MenubarContent,\n MenubarGroup,\n MenubarItem,\n MenubarLabel,\n MenubarMenu,\n MenubarPortal,\n MenubarRadioGroup,\n MenubarRadioItem,\n MenubarSeparator,\n MenubarShortcut,\n MenubarSub,\n MenubarSubContent,\n MenubarSubTrigger,\n MenubarTrigger\n};\n"],"mappings":";AAkBI,cAmGA,YAnGA;AAhBJ,YAAY,sBAAsB;AAClC,SAAS,WAAW,kBAAkB,kBAAkB;AAExD,SAAS,UAAU;AAWnB,SAAS,QAAQ,EAAE,WAAW,GAAG,MAAM,GAAiB;AACtD,SACE;AAAA,IAAC,iBAAiB;AAAA,IAAjB;AAAA,MACC,aAAU;AAAA,MACV,WAAW,GAAG,6EAA6E,SAAS;AAAA,MACnG,GAAG;AAAA;AAAA,EACN;AAEJ;AAIA,SAAS,YAAY,EAAE,GAAG,MAAM,GAAqB;AACnD,SAAO,oBAAC,iBAAiB,MAAjB,EAAsB,aAAU,gBAAgB,GAAG,OAAO;AACpE;AAIA,SAAS,aAAa,EAAE,GAAG,MAAM,GAAsB;AACrD,SAAO,oBAAC,iBAAiB,OAAjB,EAAuB,aAAU,iBAAiB,GAAG,OAAO;AACtE;AAIA,SAAS,cAAc,EAAE,GAAG,MAAM,GAAuB;AACvD,SAAO,oBAAC,iBAAiB,QAAjB,EAAwB,aAAU,kBAAkB,GAAG,OAAO;AACxE;AAIA,SAAS,kBAAkB,EAAE,GAAG,MAAM,GAA2B;AAC/D,SAAO,oBAAC,iBAAiB,YAAjB,EAA4B,aAAU,uBAAuB,GAAG,OAAO;AACjF;AAIA,SAAS,eAAe,EAAE,WAAW,GAAG,MAAM,GAAwB;AACpE,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,eAAe;AAAA,EACtB;AAAA,EACA,QAAQ;AAAA,EACR,cAAc;AAAA,EACd,aAAa;AAAA,EACb,GAAG;AACL,GAAwB;AACtB,SACE,oBAAC,iBACC;AAAA,IAAC,iBAAiB;AAAA,IAAjB;AAAA,MACC,aAAU;AAAA,MACV;AAAA,MACA;AAAA,MACA;AAAA,MACA,WAAW;AAAA,QACT;AAAA,QACA;AAAA,MACF;AAAA,MACC,GAAG;AAAA;AAAA,EACN,GACF;AAEJ;AASA,SAAS,YAAY,EAAE,WAAW,OAAO,UAAU,WAAW,GAAG,MAAM,GAAqB;AAC1F,SACE;AAAA,IAAC,iBAAiB;AAAA,IAAjB;AAAA,MACC,aAAU;AAAA,MACV,cAAY;AAAA,MACZ,gBAAc;AAAA,MACd,WAAW;AAAA,QACT;AAAA,QACA;AAAA,MACF;AAAA,MACC,GAAG;AAAA;AAAA,EACN;AAEJ;AAIA,SAAS,oBAAoB,EAAE,WAAW,UAAU,SAAS,GAAG,MAAM,GAA6B;AACjG,SACE;AAAA,IAAC,iBAAiB;AAAA,IAAjB;AAAA,MACC,aAAU;AAAA,MACV,WAAW;AAAA,QACT;AAAA,QACA;AAAA,MACF;AAAA,MACA;AAAA,MACC,GAAG;AAAA,MAEJ;AAAA,4BAAC,UAAK,WAAU,iFACd,8BAAC,iBAAiB,eAAjB,EACC,8BAAC,aAAU,WAAU,UAAS,GAChC,GACF;AAAA,QACC;AAAA;AAAA;AAAA,EACH;AAEJ;AAIA,SAAS,iBAAiB,EAAE,WAAW,UAAU,GAAG,MAAM,GAA0B;AAClF,SACE;AAAA,IAAC,iBAAiB;AAAA,IAAjB;AAAA,MACC,aAAU;AAAA,MACV,WAAW;AAAA,QACT;AAAA,QACA;AAAA,MACF;AAAA,MACC,GAAG;AAAA,MAEJ;AAAA,4BAAC,UAAK,WAAU,iFACd,8BAAC,iBAAiB,eAAjB,EACC,8BAAC,cAAW,WAAU,uBAAsB,GAC9C,GACF;AAAA,QACC;AAAA;AAAA;AAAA,EACH;AAEJ;AAMA,SAAS,aAAa,EAAE,WAAW,OAAO,GAAG,MAAM,GAAsB;AACvE,SACE;AAAA,IAAC,iBAAiB;AAAA,IAAjB;AAAA,MACC,aAAU;AAAA,MACV,cAAY;AAAA,MACZ,WAAW,GAAG,qDAAqD,SAAS;AAAA,MAC3E,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,6BAA6B,SAAS;AAAA,MACnD,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;AAIA,SAAS,WAAW,EAAE,GAAG,MAAM,GAAoB;AACjD,SAAO,oBAAC,iBAAiB,KAAjB,EAAqB,aAAU,eAAe,GAAG,OAAO;AAClE;AAMA,SAAS,kBAAkB,EAAE,WAAW,OAAO,UAAU,GAAG,MAAM,GAA2B;AAC3F,SACE;AAAA,IAAC,iBAAiB;AAAA,IAAjB;AAAA,MACC,aAAU;AAAA,MACV,cAAY;AAAA,MACZ,WAAW;AAAA,QACT;AAAA,QACA;AAAA,MACF;AAAA,MACC,GAAG;AAAA,MAEH;AAAA;AAAA,QACD,oBAAC,oBAAiB,WAAU,mBAAkB;AAAA;AAAA;AAAA,EAChD;AAEJ;AAIA,SAAS,kBAAkB,EAAE,WAAW,GAAG,MAAM,GAA2B;AAC1E,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;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../src/components/ui/menubar.tsx"],"sourcesContent":["\"use client\";\n\nimport * as MenubarPrimitive from \"@radix-ui/react-menubar\";\nimport { CheckIcon, ChevronRightIcon, CircleIcon } from \"lucide-react\";\nimport type * as React from \"react\";\nimport { cn } from \"../../lib/cn.js\";\n\n/**\n * Menubar — thanh menu ngang kiểu ứng dụng desktop (Radix Menubar).\n *\n * Dùng cho màn hình soạn thảo/bảng tính (Docs, Sheets nội bộ) — nơi cần nhóm lệnh\n * cố định. KHÔNG dùng làm điều hướng chính của app: điều hướng nằm ở Sidebar/AppHeader.\n */\n\nexport type MenubarProps = React.ComponentProps<typeof MenubarPrimitive.Root>;\n\nfunction Menubar({ className, ...props }: MenubarProps) {\n return (\n <MenubarPrimitive.Root\n data-slot=\"menubar\"\n className={cn(\"bg-background flex h-9 items-center gap-1 rounded-md border p-1 shadow-xs\", className)}\n {...props}\n />\n );\n}\n\nexport type MenubarMenuProps = React.ComponentProps<typeof MenubarPrimitive.Menu>;\n\nfunction MenubarMenu({ ...props }: MenubarMenuProps) {\n return <MenubarPrimitive.Menu data-slot=\"menubar-menu\" {...props} />;\n}\n\nexport type MenubarGroupProps = React.ComponentProps<typeof MenubarPrimitive.Group>;\n\nfunction MenubarGroup({ ...props }: MenubarGroupProps) {\n return <MenubarPrimitive.Group data-slot=\"menubar-group\" {...props} />;\n}\n\nexport type MenubarPortalProps = React.ComponentProps<typeof MenubarPrimitive.Portal>;\n\nfunction MenubarPortal({ ...props }: MenubarPortalProps) {\n return <MenubarPrimitive.Portal data-slot=\"menubar-portal\" {...props} />;\n}\n\nexport type MenubarRadioGroupProps = React.ComponentProps<typeof MenubarPrimitive.RadioGroup>;\n\nfunction MenubarRadioGroup({ ...props }: MenubarRadioGroupProps) {\n return <MenubarPrimitive.RadioGroup data-slot=\"menubar-radio-group\" {...props} />;\n}\n\nexport type MenubarTriggerProps = React.ComponentProps<typeof MenubarPrimitive.Trigger>;\n\nfunction MenubarTrigger({ className, ...props }: MenubarTriggerProps) {\n return (\n <MenubarPrimitive.Trigger\n data-slot=\"menubar-trigger\"\n className={cn(\n \"focus:bg-accent focus:text-accent-foreground data-[state=open]:bg-accent data-[state=open]:text-accent-foreground flex items-center rounded-sm px-2 py-1 text-sm font-medium outline-hidden select-none\",\n className\n )}\n {...props}\n />\n );\n}\n\nexport type MenubarContentProps = React.ComponentProps<typeof MenubarPrimitive.Content>;\n\nfunction MenubarContent({\n className,\n align = \"start\",\n alignOffset = -4,\n sideOffset = 8,\n ...props\n}: MenubarContentProps) {\n return (\n <MenubarPortal>\n <MenubarPrimitive.Content\n data-slot=\"menubar-content\"\n align={align}\n alignOffset={alignOffset}\n sideOffset={sideOffset}\n className={cn(\n \"bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 min-w-[12rem] origin-(--radix-menubar-content-transform-origin) overflow-hidden rounded-md border p-1 shadow-overlay\",\n className\n )}\n {...props}\n />\n </MenubarPortal>\n );\n}\n\nexport type MenubarItemVariant = \"default\" | \"destructive\";\n\nexport type MenubarItemProps = React.ComponentProps<typeof MenubarPrimitive.Item> & {\n inset?: boolean;\n variant?: MenubarItemVariant;\n};\n\nfunction MenubarItem({ className, inset, variant = \"default\", ...props }: MenubarItemProps) {\n return (\n <MenubarPrimitive.Item\n data-slot=\"menubar-item\"\n data-inset={inset}\n data-variant={variant}\n // `text-destructive-ink` chứ KHÔNG `text-destructive`: `--destructive` là màu NỀN (nút xoá),\n // ghim một giá trị cho cả hai theme nên làm CHỮ trên nền popover tối chỉ được 3,53:1 ✗ —\n // và tệ thêm khi focus vì nền chuyển sang `bg-destructive/20` (2,98:1 ✗). Bậc ink đạt cả\n // hai theme, cả hai nền: 7,15:1 / 6,18:1 (light, nghỉ / focus) · 6,42:1 / 5,42:1 (dark).\n className={cn(\n \"focus:bg-accent focus:text-accent-foreground data-[variant=destructive]:text-destructive-ink data-[variant=destructive]:focus:bg-destructive/10 dark:data-[variant=destructive]:focus:bg-destructive/20 data-[variant=destructive]:focus:text-destructive-ink data-[variant=destructive]:*:[svg]:!text-destructive-ink [&_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]:pointer-events-none data-[disabled]:opacity-50 data-[inset]:pl-8 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\n className\n )}\n {...props}\n />\n );\n}\n\nexport type MenubarCheckboxItemProps = React.ComponentProps<typeof MenubarPrimitive.CheckboxItem>;\n\nfunction MenubarCheckboxItem({ className, children, checked, ...props }: MenubarCheckboxItemProps) {\n return (\n <MenubarPrimitive.CheckboxItem\n data-slot=\"menubar-checkbox-item\"\n className={cn(\n \"focus:bg-accent focus:text-accent-foreground relative flex cursor-default items-center gap-2 rounded-xs py-1.5 pr-2 pl-8 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\n className\n )}\n checked={checked}\n {...props}\n >\n <span className=\"pointer-events-none absolute left-2 flex size-3.5 items-center justify-center\">\n <MenubarPrimitive.ItemIndicator>\n <CheckIcon className=\"size-4\" />\n </MenubarPrimitive.ItemIndicator>\n </span>\n {children}\n </MenubarPrimitive.CheckboxItem>\n );\n}\n\nexport type MenubarRadioItemProps = React.ComponentProps<typeof MenubarPrimitive.RadioItem>;\n\nfunction MenubarRadioItem({ className, children, ...props }: MenubarRadioItemProps) {\n return (\n <MenubarPrimitive.RadioItem\n data-slot=\"menubar-radio-item\"\n className={cn(\n \"focus:bg-accent focus:text-accent-foreground relative flex cursor-default items-center gap-2 rounded-xs py-1.5 pr-2 pl-8 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\n className\n )}\n {...props}\n >\n <span className=\"pointer-events-none absolute left-2 flex size-3.5 items-center justify-center\">\n <MenubarPrimitive.ItemIndicator>\n <CircleIcon className=\"size-2 fill-current\" />\n </MenubarPrimitive.ItemIndicator>\n </span>\n {children}\n </MenubarPrimitive.RadioItem>\n );\n}\n\nexport type MenubarLabelProps = React.ComponentProps<typeof MenubarPrimitive.Label> & {\n inset?: boolean;\n};\n\nfunction MenubarLabel({ className, inset, ...props }: MenubarLabelProps) {\n return (\n <MenubarPrimitive.Label\n data-slot=\"menubar-label\"\n data-inset={inset}\n className={cn(\"px-2 py-1.5 text-sm font-medium data-[inset]:pl-8\", className)}\n {...props}\n />\n );\n}\n\nexport type MenubarSeparatorProps = React.ComponentProps<typeof MenubarPrimitive.Separator>;\n\nfunction MenubarSeparator({ className, ...props }: MenubarSeparatorProps) {\n return (\n <MenubarPrimitive.Separator\n data-slot=\"menubar-separator\"\n className={cn(\"bg-border -mx-1 my-1 h-px\", className)}\n {...props}\n />\n );\n}\n\nexport type MenubarShortcutProps = React.ComponentProps<\"span\">;\n\nfunction MenubarShortcut({ className, ...props }: MenubarShortcutProps) {\n return (\n <span\n data-slot=\"menubar-shortcut\"\n className={cn(\"text-muted-foreground ml-auto text-xs tracking-widest\", className)}\n {...props}\n />\n );\n}\n\nexport type MenubarSubProps = React.ComponentProps<typeof MenubarPrimitive.Sub>;\n\nfunction MenubarSub({ ...props }: MenubarSubProps) {\n return <MenubarPrimitive.Sub data-slot=\"menubar-sub\" {...props} />;\n}\n\nexport type MenubarSubTriggerProps = React.ComponentProps<typeof MenubarPrimitive.SubTrigger> & {\n inset?: boolean;\n};\n\nfunction MenubarSubTrigger({ className, inset, children, ...props }: MenubarSubTriggerProps) {\n return (\n <MenubarPrimitive.SubTrigger\n data-slot=\"menubar-sub-trigger\"\n data-inset={inset}\n className={cn(\n \"focus:bg-accent focus:text-accent-foreground data-[state=open]:bg-accent data-[state=open]:text-accent-foreground flex cursor-default items-center rounded-sm px-2 py-1.5 text-sm outline-none select-none data-[inset]:pl-8\",\n className\n )}\n {...props}\n >\n {children}\n <ChevronRightIcon className=\"ml-auto h-4 w-4\" />\n </MenubarPrimitive.SubTrigger>\n );\n}\n\nexport type MenubarSubContentProps = React.ComponentProps<typeof MenubarPrimitive.SubContent>;\n\nfunction MenubarSubContent({ className, ...props }: MenubarSubContentProps) {\n return (\n <MenubarPrimitive.SubContent\n data-slot=\"menubar-sub-content\"\n className={cn(\n \"bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 min-w-[8rem] origin-(--radix-menubar-content-transform-origin) overflow-hidden rounded-md border p-1 shadow-overlay\",\n className\n )}\n {...props}\n />\n );\n}\n\nexport {\n Menubar,\n MenubarCheckboxItem,\n MenubarContent,\n MenubarGroup,\n MenubarItem,\n MenubarLabel,\n MenubarMenu,\n MenubarPortal,\n MenubarRadioGroup,\n MenubarRadioItem,\n MenubarSeparator,\n MenubarShortcut,\n MenubarSub,\n MenubarSubContent,\n MenubarSubTrigger,\n MenubarTrigger\n};\n"],"mappings":"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","names":[]}
|
|
@@ -105,7 +105,7 @@ function NavigationMenuIndicator({ className, ...props }) {
|
|
|
105
105
|
className
|
|
106
106
|
),
|
|
107
107
|
...props,
|
|
108
|
-
children: /* @__PURE__ */ jsx("div", { className: "bg-
|
|
108
|
+
children: /* @__PURE__ */ jsx("div", { className: "bg-primary-ink relative top-[60%] h-2 w-2 rotate-45 rounded-tl-sm shadow-md" })
|
|
109
109
|
}
|
|
110
110
|
);
|
|
111
111
|
}
|