@music-vine/cadence 2.6.2 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -44
- package/dist/components/accordion.d.ts +71 -0
- package/dist/components/accordion.d.ts.map +1 -0
- package/dist/components/accordion.js +2 -2
- package/dist/components/accordion.js.map +1 -1
- package/dist/components/badge.d.ts +62 -0
- package/dist/components/badge.d.ts.map +1 -0
- package/dist/components/badge.js +1 -1
- package/dist/components/badge.js.map +1 -1
- package/dist/components/breadcrumb.d.ts +42 -0
- package/dist/components/breadcrumb.d.ts.map +1 -0
- package/dist/components/button.d.ts +117 -0
- package/dist/components/button.d.ts.map +1 -0
- package/dist/components/button.js +3 -3
- package/dist/components/button.js.map +1 -1
- package/dist/components/card.d.ts +56 -0
- package/dist/components/card.d.ts.map +1 -0
- package/dist/components/card.js.map +1 -1
- package/dist/components/carousel-dots.d.ts +17 -0
- package/dist/components/carousel-dots.d.ts.map +1 -0
- package/dist/components/carousel-dots.js +1 -1
- package/dist/components/carousel-dots.js.map +1 -1
- package/dist/components/carousel.d.ts +99 -0
- package/dist/components/carousel.d.ts.map +1 -0
- package/dist/components/carousel.js +2 -2
- package/dist/components/carousel.js.map +1 -1
- package/dist/components/checkbox.d.ts +34 -0
- package/dist/components/checkbox.d.ts.map +1 -0
- package/dist/components/checkbox.js +1 -1
- package/dist/components/checkbox.js.map +1 -1
- package/dist/components/context-menu.d.ts +126 -0
- package/dist/components/context-menu.d.ts.map +1 -0
- package/dist/components/context-menu.js +6 -6
- package/dist/components/context-menu.js.map +1 -1
- package/dist/components/dialog.d.ts +85 -0
- package/dist/components/dialog.d.ts.map +1 -0
- package/dist/components/dialog.js +1 -1
- package/dist/components/dialog.js.map +1 -1
- package/dist/components/drawer.d.ts +90 -0
- package/dist/components/drawer.d.ts.map +1 -0
- package/dist/components/drawer.js.map +1 -1
- package/dist/components/index.d.ts +36 -0
- package/dist/components/index.d.ts.map +1 -0
- package/dist/components/input.d.ts +69 -0
- package/dist/components/input.d.ts.map +1 -0
- package/dist/components/input.js +61 -57
- package/dist/components/input.js.map +2 -2
- package/dist/components/label.d.ts +36 -0
- package/dist/components/label.d.ts.map +1 -0
- package/dist/components/popover.d.ts +61 -0
- package/dist/components/popover.d.ts.map +1 -0
- package/dist/components/popover.js +1 -1
- package/dist/components/popover.js.map +1 -1
- package/dist/components/price-tag.d.ts +31 -0
- package/dist/components/price-tag.d.ts.map +1 -0
- package/dist/components/price-tag.js.map +1 -1
- package/dist/components/radio-group.d.ts +15 -0
- package/dist/components/radio-group.d.ts.map +1 -0
- package/dist/components/radio-group.js +1 -1
- package/dist/components/radio-group.js.map +1 -1
- package/dist/components/scroll-area.d.ts +33 -0
- package/dist/components/scroll-area.d.ts.map +1 -0
- package/dist/components/scroll-area.js.map +1 -1
- package/dist/components/scroll-drum.d.ts +96 -0
- package/dist/components/scroll-drum.d.ts.map +1 -0
- package/dist/components/scroll-drum.js +63 -34
- package/dist/components/scroll-drum.js.map +2 -2
- package/dist/components/select.d.ts +49 -0
- package/dist/components/select.d.ts.map +1 -0
- package/dist/components/select.js +1 -1
- package/dist/components/select.js.map +1 -1
- package/dist/components/separator.d.ts +35 -0
- package/dist/components/separator.d.ts.map +1 -0
- package/dist/components/skeleton.d.ts +44 -0
- package/dist/components/skeleton.d.ts.map +1 -0
- package/dist/components/slider.d.ts +21 -0
- package/dist/components/slider.d.ts.map +1 -0
- package/dist/components/slider.js +1 -1
- package/dist/components/slider.js.map +1 -1
- package/dist/components/stacking-card.d.ts +89 -0
- package/dist/components/stacking-card.d.ts.map +1 -0
- package/dist/components/stacking-card.js +3 -3
- package/dist/components/stacking-card.js.map +2 -2
- package/dist/components/tabs.d.ts +46 -0
- package/dist/components/tabs.d.ts.map +1 -0
- package/dist/components/tabs.js +2 -2
- package/dist/components/tabs.js.map +1 -1
- package/dist/components/textarea.d.ts +34 -0
- package/dist/components/textarea.d.ts.map +1 -0
- package/dist/components/toast.d.ts +67 -0
- package/dist/components/toast.d.ts.map +1 -0
- package/dist/components/toast.js +2 -2
- package/dist/components/toast.js.map +2 -2
- package/dist/components/toggle-button.d.ts +54 -0
- package/dist/components/toggle-button.d.ts.map +1 -0
- package/dist/components/toggle-button.js.map +1 -1
- package/dist/components/typography/heading.d.ts +20 -0
- package/dist/components/typography/heading.d.ts.map +1 -0
- package/dist/components/typography/heading.js.map +1 -1
- package/dist/components/typography/index.d.ts +5 -0
- package/dist/components/typography/index.d.ts.map +1 -0
- package/dist/components/typography/list.d.ts +23 -0
- package/dist/components/typography/list.d.ts.map +1 -0
- package/dist/components/typography/list.js +1 -1
- package/dist/components/typography/list.js.map +2 -2
- package/dist/components/typography/prose.d.ts +8 -0
- package/dist/components/typography/prose.d.ts.map +1 -0
- package/dist/components/typography/text.d.ts +13 -0
- package/dist/components/typography/text.d.ts.map +1 -0
- package/dist/icons/custom/boards-indicator.d.ts +6 -0
- package/dist/icons/custom/boards-indicator.d.ts.map +1 -0
- package/dist/icons/custom/boards-indicator.js +7 -2
- package/dist/icons/custom/boards-indicator.js.map +2 -2
- package/dist/icons/custom/download-history.d.ts +5 -0
- package/dist/icons/custom/download-history.d.ts.map +1 -0
- package/dist/icons/custom/download-history.js +3 -4
- package/dist/icons/custom/download-history.js.map +2 -2
- package/dist/icons/custom/exclamation-mark-in-octagon.d.ts +5 -0
- package/dist/icons/custom/exclamation-mark-in-octagon.d.ts.map +1 -0
- package/dist/icons/custom/exclamation-mark-in-octagon.js +6 -3
- package/dist/icons/custom/exclamation-mark-in-octagon.js.map +2 -2
- package/dist/icons/custom/horizontal-orientation.d.ts +5 -0
- package/dist/icons/custom/horizontal-orientation.d.ts.map +1 -0
- package/dist/icons/custom/horizontal-orientation.js +4 -3
- package/dist/icons/custom/horizontal-orientation.js.map +2 -2
- package/dist/icons/custom/lightning-bolt.d.ts +5 -0
- package/dist/icons/custom/lightning-bolt.d.ts.map +1 -0
- package/dist/icons/custom/lightning-bolt.js +24 -27
- package/dist/icons/custom/lightning-bolt.js.map +2 -2
- package/dist/icons/custom/music-file.d.ts +5 -0
- package/dist/icons/custom/music-file.d.ts.map +1 -0
- package/dist/icons/custom/music-file.js +17 -0
- package/dist/icons/custom/music-file.js.map +7 -0
- package/dist/icons/custom/pin.d.ts +5 -0
- package/dist/icons/custom/pin.d.ts.map +1 -0
- package/dist/icons/custom/pin.js +4 -1
- package/dist/icons/custom/pin.js.map +2 -2
- package/dist/icons/custom/premium-star.d.ts +11 -0
- package/dist/icons/custom/premium-star.d.ts.map +1 -0
- package/dist/icons/custom/premium-star.js +3 -1
- package/dist/icons/custom/premium-star.js.map +2 -2
- package/dist/icons/custom/social/discord.d.ts +5 -0
- package/dist/icons/custom/social/discord.d.ts.map +1 -0
- package/dist/icons/custom/social/discord.js +3 -4
- package/dist/icons/custom/social/discord.js.map +2 -2
- package/dist/icons/custom/social/index.d.ts +4 -0
- package/dist/icons/custom/social/index.d.ts.map +1 -0
- package/dist/icons/custom/social/tiktok.d.ts +5 -0
- package/dist/icons/custom/social/tiktok.d.ts.map +1 -0
- package/dist/icons/custom/social/tiktok.js +3 -4
- package/dist/icons/custom/social/tiktok.js.map +2 -2
- package/dist/icons/custom/social/twitter-x.d.ts +5 -0
- package/dist/icons/custom/social/twitter-x.d.ts.map +1 -0
- package/dist/icons/custom/social/twitter-x.js +19 -22
- package/dist/icons/custom/social/twitter-x.js.map +2 -2
- package/dist/icons/custom/square-aspect-ratio.d.ts +5 -0
- package/dist/icons/custom/square-aspect-ratio.d.ts.map +1 -0
- package/dist/icons/custom/square-aspect-ratio.js +4 -1
- package/dist/icons/custom/square-aspect-ratio.js.map +2 -2
- package/dist/icons/custom/tick-in-circle.d.ts +8 -0
- package/dist/icons/custom/tick-in-circle.d.ts.map +1 -0
- package/dist/icons/custom/tick-in-circle.js +25 -25
- package/dist/icons/custom/tick-in-circle.js.map +2 -2
- package/dist/icons/custom/tick-small.d.ts +5 -0
- package/dist/icons/custom/tick-small.d.ts.map +1 -0
- package/dist/icons/custom/tick-small.js +8 -10
- package/dist/icons/custom/tick-small.js.map +2 -2
- package/dist/icons/custom/tick.d.ts +5 -0
- package/dist/icons/custom/tick.d.ts.map +1 -0
- package/dist/icons/custom/tick.js +2 -2
- package/dist/icons/custom/tick.js.map +2 -2
- package/dist/icons/custom/types.d.ts +3 -0
- package/dist/icons/custom/types.d.ts.map +1 -0
- package/dist/icons/custom/types.js +1 -0
- package/dist/icons/custom/types.js.map +7 -0
- package/dist/icons/custom/ultra-wide-aspect-ratio.d.ts +5 -0
- package/dist/icons/custom/ultra-wide-aspect-ratio.d.ts.map +1 -0
- package/dist/icons/custom/ultra-wide-aspect-ratio.js +4 -1
- package/dist/icons/custom/ultra-wide-aspect-ratio.js.map +2 -2
- package/dist/icons/custom/uppbeat-credit.d.ts +5 -0
- package/dist/icons/custom/uppbeat-credit.d.ts.map +1 -0
- package/dist/icons/custom/uppbeat-credit.js +2 -4
- package/dist/icons/custom/uppbeat-credit.js.map +2 -2
- package/dist/icons/custom/vertical-orientation.d.ts +5 -0
- package/dist/icons/custom/vertical-orientation.d.ts.map +1 -0
- package/dist/icons/custom/vertical-orientation.js +4 -1
- package/dist/icons/custom/vertical-orientation.js.map +2 -2
- package/dist/icons/custom/view-credit-note.d.ts +5 -0
- package/dist/icons/custom/view-credit-note.d.ts.map +1 -0
- package/dist/icons/custom/view-credit-note.js +4 -1
- package/dist/icons/custom/view-credit-note.js.map +2 -2
- package/dist/icons/index.d.ts +28 -0
- package/dist/icons/index.d.ts.map +1 -0
- package/dist/icons/index.js +4 -5
- package/dist/icons/index.js.map +2 -2
- package/dist/index.d.ts +19 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/lib/utils.d.ts +12 -0
- package/dist/lib/utils.d.ts.map +1 -0
- package/dist/lib/utils.js +7 -17
- package/dist/lib/utils.js.map +2 -2
- package/dist/styles/index.css +16 -3
- package/dist/styles/storybook.css +2 -2
- package/dist/test/setup.d.ts +2 -0
- package/dist/test/setup.d.ts.map +1 -0
- package/dist/theme/index.d.ts +142 -0
- package/dist/theme/index.d.ts.map +1 -0
- package/dist/theme/index.js +1 -1
- package/dist/theme/index.js.map +2 -2
- package/package.json +4 -9
- package/{tailwind.config.v4.css → tailwind.config.css} +35 -14
- package/dist/styles/index.v4.css +0 -49
- package/tailwind.config.ts +0 -313
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/components/button.tsx"],
|
|
4
|
-
"sourcesContent": ["/**\n * @module Button\n *\n * Versatile button component with multiple variants, sizes, and responsive options.\n * Supports all standard button interactions plus loading states and icon-only modes.\n *\n * @see {@link https://ui.shadcn.com/docs/components/button Shadcn Button}\n *\n * @example\n * // Basic buttons\n * <Button>Default</Button>\n * <Button variant=\"brand\">Primary Action</Button>\n * <Button variant=\"subtle\">Secondary</Button>\n *\n * @example\n * // Sizes\n * <Button size=\"xs\">Extra Small</Button>\n * <Button size=\"sm\">Small</Button>\n * <Button size=\"lg\">Large</Button>\n * <Button size=\"xl\">Extra Large</Button>\n *\n * @example\n * // Responsive size (changes at breakpoints)\n * <Button size={{ default: \"sm\", md: \"default\", lg: \"lg\" }}>\n * Responsive Button\n * </Button>\n *\n * @example\n * // Icon button\n * <Button icon size=\"default\"><PlayIcon /></Button>\n *\n * @example\n * // As link (using asChild)\n * <Button asChild variant=\"brand\">\n * <a href=\"/signup\">Sign Up</a>\n * </Button>\n *\n * @example\n * // With loading state\n * <Button disabled>\n * <Loading visible={isLoading} />\n * {isLoading ? \"Loading...\" : \"Submit\"}\n * </Button>\n */\nimport { cva, type VariantProps } from \"class-variance-authority\";\nimport { LoaderCircle } from \"lucide-react\";\nimport { Slot as SlotPrimitive } from \"radix-ui\";\nimport type { ButtonHTMLAttributes, Ref } from \"react\";\n\nimport { cn } from \"../lib/utils\";\n\n/** Size classes for consistent button dimensions */\n// Define size classes once as a single source of truth (including leading but not font sizes)\nconst sizeClasses = {\n default: \"h-8 px-4 py-2 leading-8\",\n xs: \"h-5 gap-1.5 px-2 leading-5\",\n sm: \"h-7 px-3 py-2 leading-6\",\n lg: \"h-10 px-4 py-2 leading-8\",\n xl: \"h-12 px-8 py-3 leading-10\",\n icon: \"h-8 w-8 leading-8\",\n} as const;\n\nconst fontSizeClasses = {\n xxs: \"text-xxs\",\n xs: \"text-xs\",\n sm: \"text-sm\",\n base: \"text-base\",\n lg: \"text-lg\",\n xl: \"text-xl\",\n} as const;\n\n// Type definitions for responsive sizes\ntype ButtonSize = \"default\" | \"xs\" | \"sm\" | \"lg\" | \"icon\" | \"xl\";\n\ntype ButtonFontSize = \"xxs\" | \"xs\" | \"sm\" | \"base\" | \"lg\" | \"xl\" | null;\n\n// Default font size mapping based on button size (excludes null)\nconst defaultFontSizeForSize: Record<\n ButtonSize,\n Exclude<ButtonFontSize, null>\n> = {\n xs: \"xs\",\n sm: \"xs\",\n default: \"base\",\n lg: \"base\",\n icon: \"base\",\n xl: \"lg\",\n};\n\nconst buttonVariants = cva(\n \"inline-flex items-center justify-center gap-2 whitespace-nowrap font-normal font-sans text-base transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--focus-ring)] focus-visible:ring-offset-2 focus-visible:ring-offset-[var(--focus-ring-offset)] enabled:cursor-pointer disabled:cursor-not-allowed disabled:opacity-50\",\n {\n variants: {\n variant: {\n // BRANDING VARIANTS (use CSS variables for themeability)\n subtle:\n \"border-1 border-gray-150 border-solid bg-white text-gray-950 hover:bg-gray-50 active:border-brand-primary-hover active:bg-brand-secondary active:text-brand-primary-hover disabled:bg-gray-50 active:disabled:border-gray-150 active:disabled:bg-gray-50 active:disabled:text-gray-950 dark:border-gray-800 dark:bg-gray-950 dark:text-white dark:disabled:border-gray-900 dark:disabled:bg-gray-950 dark:disabled:text-white dark:active:border-white dark:active:text-white dark:disabled:active:border-gray-900 dark:disabled:active:bg-gray-950 dark:disabled:active:text-white dark:hover:bg-gray-900\",\n brand:\n \"border-1 border-brand-primary border-solid bg-brand-primary font-semibold text-white hover:border-brand-primary-hover hover:bg-brand-primary-hover disabled:hover:bg-brand-primary-hover\",\n brandSecondary:\n \"border-1 border-brand-secondary border-solid bg-brand-secondary font-semibold text-brand-primary-hover hover:border-brand-secondary-hover hover:bg-brand-secondary-hover disabled:hover:bg-brand-secondary-hover dark:border-gray-900 dark:bg-gray-900 hover:dark:border-gray-800 hover:dark:bg-gray-800 dark:text-white dark:disabled:hover:border-gray-900 dark:disabled:hover:bg-gray-900\",\n bold: \"border-gray-950 bg-gray-950 font-semibold text-white dark:border-white dark:bg-white dark:text-gray-950\",\n light:\n \"border-gray-150 bg-gray-100 font-semibold text-gray-950 hover:border-gray-200 hover:bg-gray-200 disabled:hover:border-gray-150 disabled:hover:bg-gray-100 dark:border-gray-800 dark:bg-gray-800 dark:text-white dark:hover:bg-gray-700 dark:disabled:hover:bg-gray-800\",\n transparent:\n \"!border-transparent bg-transparent font-semibold text-gray-950 hover:border-gray-50 hover:bg-gray-50 disabled:hover:border-transparent disabled:hover:bg-transparent dark:text-white dark:hover:border-gray-900 dark:hover:bg-gray-900\",\n contrast:\n \"border-white bg-white font-semibold text-gray-950 hover:bg-gray-50 hover:disabled:border-white hover:disabled:bg-white\",\n success:\n \"border-green-600 bg-green-600 font-semibold text-white hover:border-green-700 hover:bg-green-700 disabled:hover:border-green-600 disabled:hover:bg-green-600 dark:border-green-500 dark:bg-green-500 dark:hover:border-green-650 dark:hover:bg-green-650 dark:disabled:hover:border-green-500 dark:disabled:hover:bg-green-500\",\n error:\n \"border-red-600 bg-red-600 font-semibold text-white hover:bg-red-700 disabled:hover:border-red-700 disabled:hover:bg-red-700 dark:border-red-500 dark:bg-red-500 dark:hover:border-red-600 dark:hover:bg-red-600 dark:disabled:hover:border-red-600 dark:disabled:hover:bg-red-600\",\n },\n\n size: sizeClasses,\n fontSize: {\n ...fontSizeClasses,\n null: \"\", // No font size class, relies on compound variants\n },\n borderRadius: {\n default: \"rounded-lg\",\n sm: \"rounded\",\n full: \"rounded-full\",\n rounded: \"rounded-[100px]\",\n },\n border: {\n true: \"border border-solid\",\n false: \"border-none\",\n },\n noFeedback: {\n true: \"\",\n false: \"transition-scale active:scale-[0.97] disabled:scale-100\",\n },\n },\n compoundVariants: [\n // Size + BorderRadius compounds\n {\n size: \"sm\",\n borderRadius: \"default\",\n className: \"rounded-lg\",\n },\n {\n size: \"xs\",\n borderRadius: \"default\",\n className: \"rounded-md\",\n },\n\n // Variant + Border compounds\n {\n variant: \"transparent\",\n border: true,\n className: \"border-gray-200 dark:border-gray-800\",\n },\n {\n variant: \"success\",\n border: true,\n className: \"border-green-dark\",\n },\n {\n variant: \"contrast\",\n border: true,\n className: \"border-white\",\n },\n // Size + fontSize compounds (default font size for each size when no explicit fontSize)\n { size: \"xs\", fontSize: null, className: \"text-xs\" },\n { size: \"sm\", fontSize: null, className: \"text-xs\" },\n { size: \"default\", fontSize: null, className: \"text-base\" },\n { size: \"lg\", fontSize: null, className: \"text-base\" },\n { size: \"icon\", fontSize: null, className: \"text-base\" },\n { size: \"xl\", fontSize: null, className: \"text-lg\" },\n ],\n defaultVariants: {\n variant: \"bold\",\n size: \"default\",\n fontSize: null,\n borderRadius: \"default\",\n border: false,\n noFeedback: false,\n },\n }\n);\n\ntype ResponsiveButtonSize =\n | ButtonSize\n | {\n default: ButtonSize;\n xxs?: ButtonSize;\n xs?: ButtonSize;\n sm?: ButtonSize;\n md?: ButtonSize;\n lg?: ButtonSize;\n xl?: ButtonSize;\n \"2xl\"?: ButtonSize;\n };\n\ntype ResponsiveButtonFontSize =\n | Exclude<ButtonFontSize, null>\n | {\n default?: Exclude<ButtonFontSize, null>;\n xxs?: Exclude<ButtonFontSize, null>;\n xs?: Exclude<ButtonFontSize, null>;\n sm?: Exclude<ButtonFontSize, null>;\n md?: Exclude<ButtonFontSize, null>;\n lg?: Exclude<ButtonFontSize, null>;\n xl?: Exclude<ButtonFontSize, null>;\n \"2xl\"?: Exclude<ButtonFontSize, null>;\n };\n\nconst getSizeClasses = (sizeKey: ButtonSize): string =>\n sizeClasses[sizeKey] || \"\";\n\nconst getFontSizeClasses = (\n fontSizeKey: Exclude<ButtonFontSize, null>\n): string => fontSizeClasses[fontSizeKey] || \"\";\n\n// Function to generate responsive Tailwind classes\nfunction generateResponsiveSizeClasses(size?: ResponsiveButtonSize): string {\n if (!size || typeof size === \"string\") {\n return \"\";\n }\n\n const classes: string[] = [];\n\n // Add responsive classes for each breakpoint\n const breakpoints = [\n { prefix: \"xxs\", value: size.xxs },\n { prefix: \"xs\", value: size.xs },\n { prefix: \"sm\", value: size.sm },\n { prefix: \"md\", value: size.md },\n { prefix: \"lg\", value: size.lg },\n { prefix: \"xl\", value: size.xl },\n { prefix: \"2xl\", value: size[\"2xl\"] },\n ];\n\n for (const breakpoint of breakpoints) {\n if (breakpoint.value) {\n const breakpointSizeClasses = getSizeClasses(breakpoint.value);\n const responsiveClasses = breakpointSizeClasses\n .split(\" \")\n .filter((cls) => cls.trim() !== \"\")\n .map((cls) => `${breakpoint.prefix}:${cls}`)\n .join(\" \");\n if (responsiveClasses) {\n classes.push(responsiveClasses);\n }\n }\n }\n\n return classes.join(\" \");\n}\n\nfunction generateResponsiveFontSizeClasses(\n fontSize?: ResponsiveButtonFontSize\n): string {\n if (!fontSize || typeof fontSize === \"string\") {\n return \"\";\n }\n\n const classes: string[] = [];\n\n // Add responsive classes for each breakpoint\n const breakpoints = [\n { prefix: \"xxs\", value: fontSize.xxs },\n { prefix: \"xs\", value: fontSize.xs },\n { prefix: \"sm\", value: fontSize.sm },\n { prefix: \"md\", value: fontSize.md },\n { prefix: \"lg\", value: fontSize.lg },\n { prefix: \"xl\", value: fontSize.xl },\n { prefix: \"2xl\", value: fontSize[\"2xl\"] },\n ];\n\n for (const breakpoint of breakpoints) {\n if (breakpoint.value) {\n const breakpointFontSizeClasses = getFontSizeClasses(breakpoint.value);\n const responsiveClasses = breakpointFontSizeClasses\n .split(\" \")\n .filter((cls) => cls.trim() !== \"\")\n .map((cls) => `${breakpoint.prefix}:${cls}`)\n .join(\" \");\n if (responsiveClasses) {\n classes.push(responsiveClasses);\n }\n }\n }\n\n return classes.join(\" \");\n}\n\n/**\n * Props for the Button component.\n *\n * @property variant - Color/style: `brand`, `brandSecondary`, `subtle`, `bold`, `light`, `transparent`, `contrast`, `success`, `error`\n * @property size - Size or responsive size object: `xs`, `sm`, `default`, `lg`, `xl`, `icon`\n * @property fontSize - Override font size or responsive font size object\n * @property borderRadius - Corner style: `default`, `sm`, `full`, `rounded`\n * @property border - Show border when true\n * @property noFeedback - Disable scale animation on click\n * @property asChild - Render as child element (e.g., for links)\n * @property icon - Square aspect ratio with no padding (for icon-only buttons)\n */\nexport interface ButtonProps\n extends ButtonHTMLAttributes<HTMLButtonElement>,\n Omit<VariantProps<typeof buttonVariants>, \"size\" | \"fontSize\"> {\n asChild?: boolean;\n size?: ResponsiveButtonSize;\n fontSize?: ResponsiveButtonFontSize;\n icon?: boolean;\n ref?: Ref<HTMLButtonElement>;\n}\n\nconst Button = ({\n className,\n variant,\n size,\n borderRadius,\n border,\n noFeedback,\n asChild = false,\n type,\n children,\n fontSize,\n icon = false,\n ref,\n ...props\n}: ButtonProps) => {\n const Comp = asChild ? SlotPrimitive.Slot : \"button\";\n const buttonType = asChild ? undefined : (type ?? \"button\");\n\n // Generate responsive classes or use the cva size variant\n const responsiveClasses =\n typeof size === \"object\" ? generateResponsiveSizeClasses(size) : undefined;\n\n // Generate responsive font size classes\n let responsiveFontSizeClasses: string | undefined;\n if (typeof fontSize === \"object\") {\n // User provided explicit responsive font sizes\n responsiveFontSizeClasses = generateResponsiveFontSizeClasses(fontSize);\n } else if (typeof size === \"object\" && fontSize === undefined) {\n // Auto-generate responsive font sizes based on responsive sizes\n const autoFontSize: ResponsiveButtonFontSize = {\n default: defaultFontSizeForSize[size.default] || \"base\",\n };\n\n // Map over the size object to create the auto font size object\n const breakpointMappings = [\n { sizeKey: \"xxs\" as const, fontKey: \"xxs\" as const },\n { sizeKey: \"xs\" as const, fontKey: \"xs\" as const },\n { sizeKey: \"sm\" as const, fontKey: \"sm\" as const },\n { sizeKey: \"md\" as const, fontKey: \"md\" as const },\n { sizeKey: \"lg\" as const, fontKey: \"lg\" as const },\n { sizeKey: \"xl\" as const, fontKey: \"xl\" as const },\n { sizeKey: \"2xl\" as const, fontKey: \"2xl\" as const },\n ];\n\n for (const { sizeKey, fontKey } of breakpointMappings) {\n const sizeValue = (size as Record<string, ButtonSize>)[sizeKey];\n if (sizeValue && sizeValue in defaultFontSizeForSize) {\n (autoFontSize as Record<string, Exclude<ButtonFontSize, null>>)[\n fontKey\n ] = defaultFontSizeForSize[sizeValue as ButtonSize];\n }\n }\n\n responsiveFontSizeClasses = generateResponsiveFontSizeClasses(autoFontSize);\n }\n\n // For object sizes, use the default size in the cva\n const cvaSize = typeof size === \"object\" ? size.default : size;\n\n // Determine font size for cva\n let cvaFontSize: ButtonFontSize = null;\n if (fontSize) {\n if (typeof fontSize === \"object\") {\n // If fontSize object has no default, let compound variants handle it (null)\n cvaFontSize = fontSize.default || null;\n } else {\n cvaFontSize = fontSize;\n }\n } // null triggers compound variants for default font sizes\n\n // Generate icon classes if icon prop is true\n let iconClasses = \"\";\n if (icon) {\n iconClasses = \"aspect-square p-0\";\n\n // If using responsive sizes, we need to override padding at each breakpoint\n if (typeof size === \"object\") {\n const iconResponsiveClasses: string[] = [];\n\n const breakpointMappings = [\n { sizeKey: \"xxs\" as const, prefix: \"xxs\" },\n { sizeKey: \"xs\" as const, prefix: \"xs\" },\n { sizeKey: \"sm\" as const, prefix: \"sm\" },\n { sizeKey: \"md\" as const, prefix: \"md\" },\n { sizeKey: \"lg\" as const, prefix: \"lg\" },\n { sizeKey: \"xl\" as const, prefix: \"xl\" },\n { sizeKey: \"2xl\" as const, prefix: \"2xl\" },\n ];\n\n for (const { sizeKey, prefix } of breakpointMappings) {\n const sizeValue = (size as Record<string, ButtonSize>)[sizeKey];\n if (sizeValue) {\n iconResponsiveClasses.push(`${prefix}:p-0`);\n }\n }\n\n if (iconResponsiveClasses.length > 0) {\n iconClasses += ` ${iconResponsiveClasses.join(\" \")}`;\n }\n }\n }\n\n return (\n <Comp\n className={cn(\n buttonVariants({\n variant,\n size: cvaSize,\n fontSize: cvaFontSize,\n borderRadius,\n border,\n noFeedback,\n }),\n responsiveClasses,\n responsiveFontSizeClasses,\n iconClasses,\n className\n )}\n ref={ref}\n type={buttonType}\n {...props}\n >\n {children}\n </Comp>\n );\n};\n\n/** CVA variants for Loading spinner sizing */\nconst loadingVariants = cva(\n \"hidden w-4 animate-[spin_0.75s_linear_infinite] text-inherit\",\n {\n variants: {\n size: {\n default: \"w-4\",\n lg: \"w-5\",\n sm: \"w-3\",\n xs: \"w-3\",\n icon: \"w-4\",\n xl: \"w-5\",\n },\n visible: {\n true: \"block\",\n false: \"hidden\",\n },\n },\n defaultVariants: {\n size: \"default\",\n visible: false,\n },\n }\n);\n\n/**\n * Animated loading spinner for use inside buttons.\n *\n * @param size - Match parent button size for proper scaling\n * @param visible - Show/hide the spinner\n *\n * @example\n * <Button disabled={isLoading}>\n * <Loading visible={isLoading} size=\"default\" />\n * Submit\n * </Button>\n */\nconst Loading = ({ size, visible }: VariantProps<typeof loadingVariants>) => (\n <LoaderCircle className={cn(loadingVariants({ size, visible }))} />\n);\n\nexport { Button, buttonVariants, Loading, loadingVariants };\nexport type {\n ResponsiveButtonSize,\n ButtonSize,\n ResponsiveButtonFontSize,\n ButtonFontSize,\n};\n"],
|
|
4
|
+
"sourcesContent": ["/**\n * @module Button\n *\n * Versatile button component with multiple variants, sizes, and responsive options.\n * Supports all standard button interactions plus loading states and icon-only modes.\n *\n * @see {@link https://ui.shadcn.com/docs/components/button Shadcn Button}\n *\n * @example\n * // Basic buttons\n * <Button>Default</Button>\n * <Button variant=\"brand\">Primary Action</Button>\n * <Button variant=\"subtle\">Secondary</Button>\n *\n * @example\n * // Sizes\n * <Button size=\"xs\">Extra Small</Button>\n * <Button size=\"sm\">Small</Button>\n * <Button size=\"lg\">Large</Button>\n * <Button size=\"xl\">Extra Large</Button>\n *\n * @example\n * // Responsive size (changes at breakpoints)\n * <Button size={{ default: \"sm\", md: \"default\", lg: \"lg\" }}>\n * Responsive Button\n * </Button>\n *\n * @example\n * // Icon button\n * <Button icon size=\"default\"><PlayIcon /></Button>\n *\n * @example\n * // As link (using asChild)\n * <Button asChild variant=\"brand\">\n * <a href=\"/signup\">Sign Up</a>\n * </Button>\n *\n * @example\n * // With loading state\n * <Button disabled>\n * <Loading visible={isLoading} />\n * {isLoading ? \"Loading...\" : \"Submit\"}\n * </Button>\n */\nimport { cva, type VariantProps } from \"class-variance-authority\";\nimport { LoaderCircle } from \"lucide-react\";\nimport { Slot as SlotPrimitive } from \"radix-ui\";\nimport type { ButtonHTMLAttributes, Ref } from \"react\";\n\nimport { cn } from \"../lib/utils\";\n\n/** Size classes for consistent button dimensions */\n// Define size classes once as a single source of truth (including leading but not font sizes)\nconst sizeClasses = {\n default: \"h-8 px-4 py-2 leading-8\",\n xs: \"h-5 gap-1.5 px-2 leading-5\",\n sm: \"h-7 px-3 py-2 leading-6\",\n lg: \"h-10 px-4 py-2 leading-8\",\n xl: \"h-12 px-8 py-3 leading-10\",\n icon: \"h-8 w-8 leading-8\",\n} as const;\n\nconst fontSizeClasses = {\n xxs: \"text-xxs\",\n xs: \"text-xs\",\n sm: \"text-sm\",\n base: \"text-base\",\n lg: \"text-lg\",\n xl: \"text-xl\",\n} as const;\n\n// Type definitions for responsive sizes\ntype ButtonSize = \"default\" | \"xs\" | \"sm\" | \"lg\" | \"icon\" | \"xl\";\n\ntype ButtonFontSize = \"xxs\" | \"xs\" | \"sm\" | \"base\" | \"lg\" | \"xl\" | null;\n\n// Default font size mapping based on button size (excludes null)\nconst defaultFontSizeForSize: Record<\n ButtonSize,\n Exclude<ButtonFontSize, null>\n> = {\n xs: \"xs\",\n sm: \"xs\",\n default: \"base\",\n lg: \"base\",\n icon: \"base\",\n xl: \"lg\",\n};\n\nconst buttonVariants = cva(\n \"inline-flex items-center justify-center gap-2 whitespace-nowrap font-normal font-sans text-base transition-colors focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-[var(--focus-ring)] focus-visible:ring-offset-2 focus-visible:ring-offset-[var(--focus-ring-offset)] enabled:cursor-pointer disabled:cursor-not-allowed disabled:opacity-50\",\n {\n variants: {\n variant: {\n // BRANDING VARIANTS (use CSS variables for themeability)\n subtle:\n \"border-1 border-gray-150 border-solid bg-white text-gray-950 hover:bg-gray-50 active:border-brand-primary-hover active:bg-brand-secondary active:text-brand-primary-hover disabled:bg-gray-50 active:disabled:border-gray-150 active:disabled:bg-gray-50 active:disabled:text-gray-950 dark:border-gray-800 dark:bg-gray-950 dark:text-white dark:disabled:border-gray-900 dark:disabled:bg-gray-950 dark:disabled:text-white dark:active:border-white dark:active:text-white dark:disabled:active:border-gray-900 dark:disabled:active:bg-gray-950 dark:disabled:active:text-white dark:hover:bg-gray-900\",\n brand:\n \"border-1 border-brand-primary border-solid bg-brand-primary font-semibold text-white hover:border-brand-primary-hover hover:bg-brand-primary-hover disabled:hover:bg-brand-primary-hover\",\n brandSecondary:\n \"border-1 border-brand-secondary border-solid bg-brand-secondary font-semibold text-brand-primary-hover hover:border-brand-secondary-hover hover:bg-brand-secondary-hover disabled:hover:bg-brand-secondary-hover dark:border-gray-900 dark:bg-gray-900 hover:dark:border-gray-800 hover:dark:bg-gray-800 dark:text-white dark:disabled:hover:border-gray-900 dark:disabled:hover:bg-gray-900\",\n bold: \"border-gray-950 bg-gray-950 font-semibold text-white dark:border-white dark:bg-white dark:text-gray-950\",\n light:\n \"border-gray-150 bg-gray-100 font-semibold text-gray-950 hover:border-gray-200 hover:bg-gray-200 disabled:hover:border-gray-150 disabled:hover:bg-gray-100 dark:border-gray-800 dark:bg-gray-800 dark:text-white dark:hover:bg-gray-700 dark:disabled:hover:bg-gray-800\",\n transparent:\n \"border-transparent! bg-transparent font-semibold text-gray-950 hover:border-gray-50 hover:bg-gray-50 disabled:hover:border-transparent disabled:hover:bg-transparent dark:text-white dark:hover:border-gray-900 dark:hover:bg-gray-900\",\n contrast:\n \"border-white bg-white font-semibold text-gray-950 hover:bg-gray-50 hover:disabled:border-white hover:disabled:bg-white\",\n success:\n \"border-green-600 bg-green-600 font-semibold text-white hover:border-green-700 hover:bg-green-700 disabled:hover:border-green-600 disabled:hover:bg-green-600 dark:border-green-500 dark:bg-green-500 dark:hover:border-green-650 dark:hover:bg-green-650 dark:disabled:hover:border-green-500 dark:disabled:hover:bg-green-500\",\n error:\n \"border-red-600 bg-red-600 font-semibold text-white hover:bg-red-700 disabled:hover:border-red-700 disabled:hover:bg-red-700 dark:border-red-500 dark:bg-red-500 dark:hover:border-red-600 dark:hover:bg-red-600 dark:disabled:hover:border-red-600 dark:disabled:hover:bg-red-600\",\n },\n\n size: sizeClasses,\n fontSize: {\n ...fontSizeClasses,\n null: \"\", // No font size class, relies on compound variants\n },\n borderRadius: {\n default: \"rounded-lg\",\n sm: \"rounded\",\n full: \"rounded-full\",\n rounded: \"rounded-[100px]\",\n },\n border: {\n true: \"border border-solid\",\n false: \"border-none\",\n },\n noFeedback: {\n true: \"\",\n false: \"transition-transform active:scale-[0.97] disabled:scale-100\",\n },\n },\n compoundVariants: [\n // Size + BorderRadius compounds\n {\n size: \"sm\",\n borderRadius: \"default\",\n className: \"rounded-lg\",\n },\n {\n size: \"xs\",\n borderRadius: \"default\",\n className: \"rounded-md\",\n },\n\n // Variant + Border compounds\n {\n variant: \"transparent\",\n border: true,\n className: \"border-gray-200 dark:border-gray-800\",\n },\n {\n variant: \"success\",\n border: true,\n className: \"border-green-dark\",\n },\n {\n variant: \"contrast\",\n border: true,\n className: \"border-white\",\n },\n // Size + fontSize compounds (default font size for each size when no explicit fontSize)\n { size: \"xs\", fontSize: null, className: \"text-xs\" },\n { size: \"sm\", fontSize: null, className: \"text-xs\" },\n { size: \"default\", fontSize: null, className: \"text-base\" },\n { size: \"lg\", fontSize: null, className: \"text-base\" },\n { size: \"icon\", fontSize: null, className: \"text-base\" },\n { size: \"xl\", fontSize: null, className: \"text-lg\" },\n ],\n defaultVariants: {\n variant: \"bold\",\n size: \"default\",\n fontSize: null,\n borderRadius: \"default\",\n border: false,\n noFeedback: false,\n },\n }\n);\n\ntype ResponsiveButtonSize =\n | ButtonSize\n | {\n default: ButtonSize;\n xxs?: ButtonSize;\n xs?: ButtonSize;\n sm?: ButtonSize;\n md?: ButtonSize;\n lg?: ButtonSize;\n xl?: ButtonSize;\n \"2xl\"?: ButtonSize;\n };\n\ntype ResponsiveButtonFontSize =\n | Exclude<ButtonFontSize, null>\n | {\n default?: Exclude<ButtonFontSize, null>;\n xxs?: Exclude<ButtonFontSize, null>;\n xs?: Exclude<ButtonFontSize, null>;\n sm?: Exclude<ButtonFontSize, null>;\n md?: Exclude<ButtonFontSize, null>;\n lg?: Exclude<ButtonFontSize, null>;\n xl?: Exclude<ButtonFontSize, null>;\n \"2xl\"?: Exclude<ButtonFontSize, null>;\n };\n\nconst getSizeClasses = (sizeKey: ButtonSize): string =>\n sizeClasses[sizeKey] || \"\";\n\nconst getFontSizeClasses = (\n fontSizeKey: Exclude<ButtonFontSize, null>\n): string => fontSizeClasses[fontSizeKey] || \"\";\n\n// Function to generate responsive Tailwind classes\nfunction generateResponsiveSizeClasses(size?: ResponsiveButtonSize): string {\n if (!size || typeof size === \"string\") {\n return \"\";\n }\n\n const classes: string[] = [];\n\n // Add responsive classes for each breakpoint\n const breakpoints = [\n { prefix: \"xxs\", value: size.xxs },\n { prefix: \"xs\", value: size.xs },\n { prefix: \"sm\", value: size.sm },\n { prefix: \"md\", value: size.md },\n { prefix: \"lg\", value: size.lg },\n { prefix: \"xl\", value: size.xl },\n { prefix: \"2xl\", value: size[\"2xl\"] },\n ];\n\n for (const breakpoint of breakpoints) {\n if (breakpoint.value) {\n const breakpointSizeClasses = getSizeClasses(breakpoint.value);\n const responsiveClasses = breakpointSizeClasses\n .split(\" \")\n .filter((cls) => cls.trim() !== \"\")\n .map((cls) => `${breakpoint.prefix}:${cls}`)\n .join(\" \");\n if (responsiveClasses) {\n classes.push(responsiveClasses);\n }\n }\n }\n\n return classes.join(\" \");\n}\n\nfunction generateResponsiveFontSizeClasses(\n fontSize?: ResponsiveButtonFontSize\n): string {\n if (!fontSize || typeof fontSize === \"string\") {\n return \"\";\n }\n\n const classes: string[] = [];\n\n // Add responsive classes for each breakpoint\n const breakpoints = [\n { prefix: \"xxs\", value: fontSize.xxs },\n { prefix: \"xs\", value: fontSize.xs },\n { prefix: \"sm\", value: fontSize.sm },\n { prefix: \"md\", value: fontSize.md },\n { prefix: \"lg\", value: fontSize.lg },\n { prefix: \"xl\", value: fontSize.xl },\n { prefix: \"2xl\", value: fontSize[\"2xl\"] },\n ];\n\n for (const breakpoint of breakpoints) {\n if (breakpoint.value) {\n const breakpointFontSizeClasses = getFontSizeClasses(breakpoint.value);\n const responsiveClasses = breakpointFontSizeClasses\n .split(\" \")\n .filter((cls) => cls.trim() !== \"\")\n .map((cls) => `${breakpoint.prefix}:${cls}`)\n .join(\" \");\n if (responsiveClasses) {\n classes.push(responsiveClasses);\n }\n }\n }\n\n return classes.join(\" \");\n}\n\n/**\n * Props for the Button component.\n *\n * @property variant - Color/style: `brand`, `brandSecondary`, `subtle`, `bold`, `light`, `transparent`, `contrast`, `success`, `error`\n * @property size - Size or responsive size object: `xs`, `sm`, `default`, `lg`, `xl`, `icon`\n * @property fontSize - Override font size or responsive font size object\n * @property borderRadius - Corner style: `default`, `sm`, `full`, `rounded`\n * @property border - Show border when true\n * @property noFeedback - Disable scale animation on click\n * @property asChild - Render as child element (e.g., for links)\n * @property icon - Square aspect ratio with no padding (for icon-only buttons)\n */\nexport interface ButtonProps\n extends ButtonHTMLAttributes<HTMLButtonElement>,\n Omit<VariantProps<typeof buttonVariants>, \"size\" | \"fontSize\"> {\n asChild?: boolean;\n fontSize?: ResponsiveButtonFontSize;\n icon?: boolean;\n ref?: Ref<HTMLButtonElement>;\n size?: ResponsiveButtonSize;\n}\n\nconst Button = ({\n className,\n variant,\n size,\n borderRadius,\n border,\n noFeedback,\n asChild = false,\n type,\n children,\n fontSize,\n icon = false,\n ref,\n ...props\n}: ButtonProps) => {\n const Comp = asChild ? SlotPrimitive.Slot : \"button\";\n const buttonType = asChild ? undefined : (type ?? \"button\");\n\n // Generate responsive classes or use the cva size variant\n const responsiveClasses =\n typeof size === \"object\" ? generateResponsiveSizeClasses(size) : undefined;\n\n // Generate responsive font size classes\n let responsiveFontSizeClasses: string | undefined;\n if (typeof fontSize === \"object\") {\n // User provided explicit responsive font sizes\n responsiveFontSizeClasses = generateResponsiveFontSizeClasses(fontSize);\n } else if (typeof size === \"object\" && fontSize === undefined) {\n // Auto-generate responsive font sizes based on responsive sizes\n const autoFontSize: ResponsiveButtonFontSize = {\n default: defaultFontSizeForSize[size.default] || \"base\",\n };\n\n // Map over the size object to create the auto font size object\n const breakpointMappings = [\n { sizeKey: \"xxs\" as const, fontKey: \"xxs\" as const },\n { sizeKey: \"xs\" as const, fontKey: \"xs\" as const },\n { sizeKey: \"sm\" as const, fontKey: \"sm\" as const },\n { sizeKey: \"md\" as const, fontKey: \"md\" as const },\n { sizeKey: \"lg\" as const, fontKey: \"lg\" as const },\n { sizeKey: \"xl\" as const, fontKey: \"xl\" as const },\n { sizeKey: \"2xl\" as const, fontKey: \"2xl\" as const },\n ];\n\n for (const { sizeKey, fontKey } of breakpointMappings) {\n const sizeValue = (size as Record<string, ButtonSize>)[sizeKey];\n if (sizeValue && sizeValue in defaultFontSizeForSize) {\n (autoFontSize as Record<string, Exclude<ButtonFontSize, null>>)[\n fontKey\n ] = defaultFontSizeForSize[sizeValue as ButtonSize];\n }\n }\n\n responsiveFontSizeClasses = generateResponsiveFontSizeClasses(autoFontSize);\n }\n\n // For object sizes, use the default size in the cva\n const cvaSize = typeof size === \"object\" ? size.default : size;\n\n // Determine font size for cva\n let cvaFontSize: ButtonFontSize = null;\n if (fontSize) {\n if (typeof fontSize === \"object\") {\n // If fontSize object has no default, let compound variants handle it (null)\n cvaFontSize = fontSize.default || null;\n } else {\n cvaFontSize = fontSize;\n }\n } // null triggers compound variants for default font sizes\n\n // Generate icon classes if icon prop is true\n let iconClasses = \"\";\n if (icon) {\n iconClasses = \"aspect-square p-0\";\n\n // If using responsive sizes, we need to override padding at each breakpoint\n if (typeof size === \"object\") {\n const iconResponsiveClasses: string[] = [];\n\n const breakpointMappings = [\n { sizeKey: \"xxs\" as const, prefix: \"xxs\" },\n { sizeKey: \"xs\" as const, prefix: \"xs\" },\n { sizeKey: \"sm\" as const, prefix: \"sm\" },\n { sizeKey: \"md\" as const, prefix: \"md\" },\n { sizeKey: \"lg\" as const, prefix: \"lg\" },\n { sizeKey: \"xl\" as const, prefix: \"xl\" },\n { sizeKey: \"2xl\" as const, prefix: \"2xl\" },\n ];\n\n for (const { sizeKey, prefix } of breakpointMappings) {\n const sizeValue = (size as Record<string, ButtonSize>)[sizeKey];\n if (sizeValue) {\n iconResponsiveClasses.push(`${prefix}:p-0`);\n }\n }\n\n if (iconResponsiveClasses.length > 0) {\n iconClasses += ` ${iconResponsiveClasses.join(\" \")}`;\n }\n }\n }\n\n return (\n <Comp\n className={cn(\n buttonVariants({\n variant,\n size: cvaSize,\n fontSize: cvaFontSize,\n borderRadius,\n border,\n noFeedback,\n }),\n responsiveClasses,\n responsiveFontSizeClasses,\n iconClasses,\n className\n )}\n ref={ref}\n type={buttonType}\n {...props}\n >\n {children}\n </Comp>\n );\n};\n\n/** CVA variants for Loading spinner sizing */\nconst loadingVariants = cva(\n \"hidden w-4 animate-[spin_0.75s_linear_infinite] text-inherit\",\n {\n variants: {\n size: {\n default: \"w-4\",\n lg: \"w-5\",\n sm: \"w-3\",\n xs: \"w-3\",\n icon: \"w-4\",\n xl: \"w-5\",\n },\n visible: {\n true: \"block\",\n false: \"hidden\",\n },\n },\n defaultVariants: {\n size: \"default\",\n visible: false,\n },\n }\n);\n\n/**\n * Animated loading spinner for use inside buttons.\n *\n * @param size - Match parent button size for proper scaling\n * @param visible - Show/hide the spinner\n *\n * @example\n * <Button disabled={isLoading}>\n * <Loading visible={isLoading} size=\"default\" />\n * Submit\n * </Button>\n */\nconst Loading = ({ size, visible }: VariantProps<typeof loadingVariants>) => (\n <LoaderCircle className={cn(loadingVariants({ size, visible }))} />\n);\n\nexport type {\n ButtonFontSize,\n ButtonSize,\n ResponsiveButtonFontSize,\n ResponsiveButtonSize,\n};\nexport { Button, buttonVariants, Loading, loadingVariants };\n"],
|
|
5
5
|
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module Card
|
|
3
|
+
*
|
|
4
|
+
* Container component for grouping related content with consistent styling.
|
|
5
|
+
* Provides structured sections for headers, content, and footers.
|
|
6
|
+
*
|
|
7
|
+
* @see {@link https://ui.shadcn.com/docs/components/card Shadcn Card}
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* // Basic card
|
|
11
|
+
* <Card>
|
|
12
|
+
* <CardHeader>
|
|
13
|
+
* <CardTitle>Subscription</CardTitle>
|
|
14
|
+
* <CardDescription>Your current plan details</CardDescription>
|
|
15
|
+
* </CardHeader>
|
|
16
|
+
* <CardContent>
|
|
17
|
+
* <p>Premium Plan - $9.99/month</p>
|
|
18
|
+
* </CardContent>
|
|
19
|
+
* <CardFooter>
|
|
20
|
+
* <Button>Manage</Button>
|
|
21
|
+
* </CardFooter>
|
|
22
|
+
* </Card>
|
|
23
|
+
*/
|
|
24
|
+
import type { Ref } from "react";
|
|
25
|
+
/** Main card container with border, shadow, and rounded corners. */
|
|
26
|
+
interface CardProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
27
|
+
ref?: Ref<HTMLDivElement>;
|
|
28
|
+
}
|
|
29
|
+
declare const Card: ({ className, ref, ...props }: CardProps) => import("react/jsx-runtime").JSX.Element;
|
|
30
|
+
/** Card header section with vertical spacing for title and description. */
|
|
31
|
+
interface CardHeaderProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
32
|
+
ref?: Ref<HTMLDivElement>;
|
|
33
|
+
}
|
|
34
|
+
declare const CardHeader: ({ className, ref, ...props }: CardHeaderProps) => import("react/jsx-runtime").JSX.Element;
|
|
35
|
+
/** Card title with semibold weight and larger text. */
|
|
36
|
+
interface CardTitleProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
37
|
+
ref?: Ref<HTMLDivElement>;
|
|
38
|
+
}
|
|
39
|
+
declare const CardTitle: ({ className, ref, ...props }: CardTitleProps) => import("react/jsx-runtime").JSX.Element;
|
|
40
|
+
/** Muted description text below the card title. */
|
|
41
|
+
interface CardDescriptionProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
42
|
+
ref?: Ref<HTMLDivElement>;
|
|
43
|
+
}
|
|
44
|
+
declare const CardDescription: ({ className, ref, ...props }: CardDescriptionProps) => import("react/jsx-runtime").JSX.Element;
|
|
45
|
+
/** Main content area of the card. */
|
|
46
|
+
interface CardContentProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
47
|
+
ref?: Ref<HTMLDivElement>;
|
|
48
|
+
}
|
|
49
|
+
declare const CardContent: ({ className, ref, ...props }: CardContentProps) => import("react/jsx-runtime").JSX.Element;
|
|
50
|
+
/** Card footer section, typically for actions/buttons. */
|
|
51
|
+
interface CardFooterProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
52
|
+
ref?: Ref<HTMLDivElement>;
|
|
53
|
+
}
|
|
54
|
+
declare const CardFooter: ({ className, ref, ...props }: CardFooterProps) => import("react/jsx-runtime").JSX.Element;
|
|
55
|
+
export { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, };
|
|
56
|
+
//# sourceMappingURL=card.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"card.d.ts","sourceRoot":"","sources":["../../src/components/card.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,OAAO,CAAC;AAIjC,oEAAoE;AACpE,UAAU,SAAU,SAAQ,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC;IAC9D,GAAG,CAAC,EAAE,GAAG,CAAC,cAAc,CAAC,CAAC;CAC3B;AAED,QAAA,MAAM,IAAI,GAAI,8BAA8B,SAAS,4CASpD,CAAC;AAEF,2EAA2E;AAC3E,UAAU,eAAgB,SAAQ,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC;IACpE,GAAG,CAAC,EAAE,GAAG,CAAC,cAAc,CAAC,CAAC;CAC3B;AAED,QAAA,MAAM,UAAU,GAAI,8BAA8B,eAAe,4CAMhE,CAAC;AAEF,uDAAuD;AACvD,UAAU,cAAe,SAAQ,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC;IACnE,GAAG,CAAC,EAAE,GAAG,CAAC,cAAc,CAAC,CAAC;CAC3B;AAED,QAAA,MAAM,SAAS,GAAI,8BAA8B,cAAc,4CAS9D,CAAC;AAEF,mDAAmD;AACnD,UAAU,oBAAqB,SAAQ,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC;IACzE,GAAG,CAAC,EAAE,GAAG,CAAC,cAAc,CAAC,CAAC;CAC3B;AAED,QAAA,MAAM,eAAe,GAAI,8BAItB,oBAAoB,4CAMtB,CAAC;AAEF,qCAAqC;AACrC,UAAU,gBAAiB,SAAQ,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC;IACrE,GAAG,CAAC,EAAE,GAAG,CAAC,cAAc,CAAC,CAAC;CAC3B;AAED,QAAA,MAAM,WAAW,GAAI,8BAA8B,gBAAgB,4CAElE,CAAC;AAEF,0DAA0D;AAC1D,UAAU,eAAgB,SAAQ,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC;IACpE,GAAG,CAAC,EAAE,GAAG,CAAC,cAAc,CAAC,CAAC;CAC3B;AAED,QAAA,MAAM,UAAU,GAAI,8BAA8B,eAAe,4CAMhE,CAAC;AAEF,OAAO,EACL,IAAI,EACJ,WAAW,EACX,eAAe,EACf,UAAU,EACV,UAAU,EACV,SAAS,GACV,CAAC"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/components/card.tsx"],
|
|
4
|
-
"sourcesContent": ["/**\n * @module Card\n *\n * Container component for grouping related content with consistent styling.\n * Provides structured sections for headers, content, and footers.\n *\n * @see {@link https://ui.shadcn.com/docs/components/card Shadcn Card}\n *\n * @example\n * // Basic card\n * <Card>\n * <CardHeader>\n * <CardTitle>Subscription</CardTitle>\n * <CardDescription>Your current plan details</CardDescription>\n * </CardHeader>\n * <CardContent>\n * <p>Premium Plan - $9.99/month</p>\n * </CardContent>\n * <CardFooter>\n * <Button>Manage</Button>\n * </CardFooter>\n * </Card>\n */\nimport type { Ref } from \"react\";\n\nimport { cn } from \"../lib/utils\";\n\n/** Main card container with border, shadow, and rounded corners. */\ninterface CardProps extends React.HTMLAttributes<HTMLDivElement> {\n ref?: Ref<HTMLDivElement>;\n}\n\nconst Card = ({ className, ref, ...props }: CardProps) => (\n <div\n className={cn(\n \"rounded-lg border border-gray-150 border-solid bg-white text-gray-950 shadow-card dark:border-gray-800 dark:bg-gray-950 dark:text-gray-50\",\n className\n )}\n ref={ref}\n {...props}\n />\n);\n\n/** Card header section with vertical spacing for title and description. */\ninterface CardHeaderProps extends React.HTMLAttributes<HTMLDivElement> {\n ref?: Ref<HTMLDivElement>;\n}\n\nconst CardHeader = ({ className, ref, ...props }: CardHeaderProps) => (\n <div\n className={cn(\"flex flex-col space-y-1.5 p-6\", className)}\n ref={ref}\n {...props}\n />\n);\n\n/** Card title with semibold weight and larger text. */\ninterface CardTitleProps extends React.HTMLAttributes<HTMLDivElement> {\n ref?: Ref<HTMLDivElement>;\n}\n\nconst CardTitle = ({ className, ref, ...props }: CardTitleProps) => (\n <div\n className={cn(\n \"font-semibold text-2xl leading-none tracking-tight\",\n className\n )}\n ref={ref}\n {...props}\n />\n);\n\n/** Muted description text below the card title. */\ninterface CardDescriptionProps extends React.HTMLAttributes<HTMLDivElement> {\n ref?: Ref<HTMLDivElement>;\n}\n\nconst CardDescription = ({\n className,\n ref,\n ...props\n}: CardDescriptionProps) => (\n <div\n className={cn(\"text-gray-600 text-sm dark:text-gray-400\", className)}\n ref={ref}\n {...props}\n />\n);\n\n/** Main content area of the card. */\ninterface CardContentProps extends React.HTMLAttributes<HTMLDivElement> {\n ref?: Ref<HTMLDivElement>;\n}\n\nconst CardContent = ({ className, ref, ...props }: CardContentProps) => (\n <div className={cn(\"p-6 pt-0\", className)} ref={ref} {...props} />\n);\n\n/** Card footer section, typically for actions/buttons. */\ninterface CardFooterProps extends React.HTMLAttributes<HTMLDivElement> {\n ref?: Ref<HTMLDivElement>;\n}\n\nconst CardFooter = ({ className, ref, ...props }: CardFooterProps) => (\n <div\n className={cn(\"flex items-center p-6 pt-0\", className)}\n ref={ref}\n {...props}\n />\n);\n\nexport {\n Card,\n
|
|
4
|
+
"sourcesContent": ["/**\n * @module Card\n *\n * Container component for grouping related content with consistent styling.\n * Provides structured sections for headers, content, and footers.\n *\n * @see {@link https://ui.shadcn.com/docs/components/card Shadcn Card}\n *\n * @example\n * // Basic card\n * <Card>\n * <CardHeader>\n * <CardTitle>Subscription</CardTitle>\n * <CardDescription>Your current plan details</CardDescription>\n * </CardHeader>\n * <CardContent>\n * <p>Premium Plan - $9.99/month</p>\n * </CardContent>\n * <CardFooter>\n * <Button>Manage</Button>\n * </CardFooter>\n * </Card>\n */\nimport type { Ref } from \"react\";\n\nimport { cn } from \"../lib/utils\";\n\n/** Main card container with border, shadow, and rounded corners. */\ninterface CardProps extends React.HTMLAttributes<HTMLDivElement> {\n ref?: Ref<HTMLDivElement>;\n}\n\nconst Card = ({ className, ref, ...props }: CardProps) => (\n <div\n className={cn(\n \"rounded-lg border border-gray-150 border-solid bg-white text-gray-950 shadow-card dark:border-gray-800 dark:bg-gray-950 dark:text-gray-50\",\n className\n )}\n ref={ref}\n {...props}\n />\n);\n\n/** Card header section with vertical spacing for title and description. */\ninterface CardHeaderProps extends React.HTMLAttributes<HTMLDivElement> {\n ref?: Ref<HTMLDivElement>;\n}\n\nconst CardHeader = ({ className, ref, ...props }: CardHeaderProps) => (\n <div\n className={cn(\"flex flex-col space-y-1.5 p-6\", className)}\n ref={ref}\n {...props}\n />\n);\n\n/** Card title with semibold weight and larger text. */\ninterface CardTitleProps extends React.HTMLAttributes<HTMLDivElement> {\n ref?: Ref<HTMLDivElement>;\n}\n\nconst CardTitle = ({ className, ref, ...props }: CardTitleProps) => (\n <div\n className={cn(\n \"font-semibold text-2xl leading-none tracking-tight\",\n className\n )}\n ref={ref}\n {...props}\n />\n);\n\n/** Muted description text below the card title. */\ninterface CardDescriptionProps extends React.HTMLAttributes<HTMLDivElement> {\n ref?: Ref<HTMLDivElement>;\n}\n\nconst CardDescription = ({\n className,\n ref,\n ...props\n}: CardDescriptionProps) => (\n <div\n className={cn(\"text-gray-600 text-sm dark:text-gray-400\", className)}\n ref={ref}\n {...props}\n />\n);\n\n/** Main content area of the card. */\ninterface CardContentProps extends React.HTMLAttributes<HTMLDivElement> {\n ref?: Ref<HTMLDivElement>;\n}\n\nconst CardContent = ({ className, ref, ...props }: CardContentProps) => (\n <div className={cn(\"p-6 pt-0\", className)} ref={ref} {...props} />\n);\n\n/** Card footer section, typically for actions/buttons. */\ninterface CardFooterProps extends React.HTMLAttributes<HTMLDivElement> {\n ref?: Ref<HTMLDivElement>;\n}\n\nconst CardFooter = ({ className, ref, ...props }: CardFooterProps) => (\n <div\n className={cn(\"flex items-center p-6 pt-0\", className)}\n ref={ref}\n {...props}\n />\n);\n\nexport {\n Card,\n CardContent,\n CardDescription,\n CardFooter,\n CardHeader,\n CardTitle,\n};\n"],
|
|
5
5
|
"mappings": "AAiCE;AARF,SAAS,UAAU;AAOnB,MAAM,OAAO,CAAC,EAAE,WAAW,KAAK,GAAG,MAAM,MACvC;AAAA,EAAC;AAAA;AAAA,IACC,WAAW;AAAA,MACT;AAAA,MACA;AAAA,IACF;AAAA,IACA;AAAA,IACC,GAAG;AAAA;AACN;AAQF,MAAM,aAAa,CAAC,EAAE,WAAW,KAAK,GAAG,MAAM,MAC7C;AAAA,EAAC;AAAA;AAAA,IACC,WAAW,GAAG,iCAAiC,SAAS;AAAA,IACxD;AAAA,IACC,GAAG;AAAA;AACN;AAQF,MAAM,YAAY,CAAC,EAAE,WAAW,KAAK,GAAG,MAAM,MAC5C;AAAA,EAAC;AAAA;AAAA,IACC,WAAW;AAAA,MACT;AAAA,MACA;AAAA,IACF;AAAA,IACA;AAAA,IACC,GAAG;AAAA;AACN;AAQF,MAAM,kBAAkB,CAAC;AAAA,EACvB;AAAA,EACA;AAAA,EACA,GAAG;AACL,MACE;AAAA,EAAC;AAAA;AAAA,IACC,WAAW,GAAG,4CAA4C,SAAS;AAAA,IACnE;AAAA,IACC,GAAG;AAAA;AACN;AAQF,MAAM,cAAc,CAAC,EAAE,WAAW,KAAK,GAAG,MAAM,MAC9C,oBAAC,SAAI,WAAW,GAAG,YAAY,SAAS,GAAG,KAAW,GAAG,OAAO;AAQlE,MAAM,aAAa,CAAC,EAAE,WAAW,KAAK,GAAG,MAAM,MAC7C;AAAA,EAAC;AAAA;AAAA,IACC,WAAW,GAAG,8BAA8B,SAAS;AAAA,IACrD;AAAA,IACC,GAAG;AAAA;AACN;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { CarouselApi } from "./carousel";
|
|
2
|
+
/**
|
|
3
|
+
* Props for CarouselDots component.
|
|
4
|
+
* @property api - Embla Carousel API instance from useCarousel or setApi
|
|
5
|
+
* @property count - Total number of slides
|
|
6
|
+
*/
|
|
7
|
+
interface CarouselDotsProps {
|
|
8
|
+
api: CarouselApi | null;
|
|
9
|
+
className?: string;
|
|
10
|
+
count: number;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Dot indicators for carousel navigation. Highlights current slide and allows direct jump.
|
|
14
|
+
*/
|
|
15
|
+
export declare const CarouselDots: ({ api, count, className }: CarouselDotsProps) => import("react/jsx-runtime").JSX.Element;
|
|
16
|
+
export {};
|
|
17
|
+
//# sourceMappingURL=carousel-dots.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"carousel-dots.d.ts","sourceRoot":"","sources":["../../src/components/carousel-dots.tsx"],"names":[],"mappings":"AAsBA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE9C;;;;GAIG;AACH,UAAU,iBAAiB;IACzB,GAAG,EAAE,WAAW,GAAG,IAAI,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;CACf;AAED;;GAEG;AACH,eAAO,MAAM,YAAY,GAAI,2BAA2B,iBAAiB,4CA8DxE,CAAC"}
|
|
@@ -39,7 +39,7 @@ const CarouselDots = ({ api, count, className }) => {
|
|
|
39
39
|
borderRadius: "full",
|
|
40
40
|
className: cn(
|
|
41
41
|
"size-2 transition-all duration-300 2xl:size-3",
|
|
42
|
-
selectedIndex === index ? "hover
|
|
42
|
+
selectedIndex === index ? "hover:bg-brand-primary! border-brand-primary bg-brand-primary hover:border-brand-primary" : "hover:bg-gray-300! dark:hover:bg-gray-600! border-gray-300 bg-gray-300 dark:border-gray-600 dark:bg-gray-600 dark:hover:border-gray-600"
|
|
43
43
|
),
|
|
44
44
|
icon: true,
|
|
45
45
|
onClick: () => onClick(index),
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/components/carousel-dots.tsx"],
|
|
4
|
-
"sourcesContent": ["/**\n * @module CarouselDots\n *\n * Navigation dots for Carousel component. Shows current slide position and allows direct navigation.\n *\n * @example\n * // With Carousel\n * const [api, setApi] = useState<CarouselApi>();\n *\n * <Carousel setApi={setApi}>\n * <CarouselContent>\n * <CarouselItem>Slide 1</CarouselItem>\n * <CarouselItem>Slide 2</CarouselItem>\n * </CarouselContent>\n * </Carousel>\n * <CarouselDots api={api} count={2} />\n */\nimport * as React from \"react\";\n\nimport { cn } from \"../lib/utils\";\nimport { Button } from \"./button\";\n\nimport type { CarouselApi } from \"./carousel\";\n\n/**\n * Props for CarouselDots component.\n * @property api - Embla Carousel API instance from useCarousel or setApi\n * @property count - Total number of slides\n */\ninterface CarouselDotsProps {\n api: CarouselApi | null;\n
|
|
4
|
+
"sourcesContent": ["/**\n * @module CarouselDots\n *\n * Navigation dots for Carousel component. Shows current slide position and allows direct navigation.\n *\n * @example\n * // With Carousel\n * const [api, setApi] = useState<CarouselApi>();\n *\n * <Carousel setApi={setApi}>\n * <CarouselContent>\n * <CarouselItem>Slide 1</CarouselItem>\n * <CarouselItem>Slide 2</CarouselItem>\n * </CarouselContent>\n * </Carousel>\n * <CarouselDots api={api} count={2} />\n */\nimport * as React from \"react\";\n\nimport { cn } from \"../lib/utils\";\nimport { Button } from \"./button\";\n\nimport type { CarouselApi } from \"./carousel\";\n\n/**\n * Props for CarouselDots component.\n * @property api - Embla Carousel API instance from useCarousel or setApi\n * @property count - Total number of slides\n */\ninterface CarouselDotsProps {\n api: CarouselApi | null;\n className?: string;\n count: number;\n}\n\n/**\n * Dot indicators for carousel navigation. Highlights current slide and allows direct jump.\n */\nexport const CarouselDots = ({ api, count, className }: CarouselDotsProps) => {\n const [selectedIndex, setSelectedIndex] = React.useState(0);\n const currentIndexRef = React.useRef(selectedIndex);\n\n React.useEffect(() => {\n if (!api) {\n return;\n }\n\n const updateIndex = () => {\n const newIndex = api.selectedScrollSnap();\n\n if (currentIndexRef.current !== newIndex) {\n currentIndexRef.current = newIndex;\n // Schedule state update outside of useEffect\n queueMicrotask(() => {\n setSelectedIndex(newIndex);\n });\n }\n };\n\n // Subscribe to select events\n api.on(\"select\", updateIndex);\n // Initial update\n updateIndex();\n\n // Cleanup\n return () => {\n api.off(\"select\", updateIndex);\n };\n }, [api]);\n\n const onClick = React.useCallback(\n (index: number) => {\n api?.scrollTo(index);\n },\n [api]\n );\n\n return (\n <div className={cn(\"flex items-center justify-center gap-2\", className)}>\n {Array.from({ length: count }).map((_, index) => (\n <Button\n aria-current={selectedIndex === index ? \"true\" : undefined}\n aria-label={`Go to slide ${index + 1}`}\n border\n borderRadius=\"full\"\n className={cn(\n \"size-2 transition-all duration-300 2xl:size-3\",\n selectedIndex === index\n ? \"hover:bg-brand-primary! border-brand-primary bg-brand-primary hover:border-brand-primary\"\n : \"hover:bg-gray-300! dark:hover:bg-gray-600! border-gray-300 bg-gray-300 dark:border-gray-600 dark:bg-gray-600 dark:hover:border-gray-600\"\n )}\n icon\n key={index}\n onClick={() => onClick(index)}\n size=\"sm\"\n variant=\"bold\"\n />\n ))}\n </div>\n );\n};\n"],
|
|
5
5
|
"mappings": "AAgFQ;AA/DR,YAAY,WAAW;AAEvB,SAAS,UAAU;AACnB,SAAS,cAAc;AAkBhB,MAAM,eAAe,CAAC,EAAE,KAAK,OAAO,UAAU,MAAyB;AAC5E,QAAM,CAAC,eAAe,gBAAgB,IAAI,MAAM,SAAS,CAAC;AAC1D,QAAM,kBAAkB,MAAM,OAAO,aAAa;AAElD,QAAM,UAAU,MAAM;AACpB,QAAI,CAAC,KAAK;AACR;AAAA,IACF;AAEA,UAAM,cAAc,MAAM;AACxB,YAAM,WAAW,IAAI,mBAAmB;AAExC,UAAI,gBAAgB,YAAY,UAAU;AACxC,wBAAgB,UAAU;AAE1B,uBAAe,MAAM;AACnB,2BAAiB,QAAQ;AAAA,QAC3B,CAAC;AAAA,MACH;AAAA,IACF;AAGA,QAAI,GAAG,UAAU,WAAW;AAE5B,gBAAY;AAGZ,WAAO,MAAM;AACX,UAAI,IAAI,UAAU,WAAW;AAAA,IAC/B;AAAA,EACF,GAAG,CAAC,GAAG,CAAC;AAER,QAAM,UAAU,MAAM;AAAA,IACpB,CAAC,UAAkB;AACjB,WAAK,SAAS,KAAK;AAAA,IACrB;AAAA,IACA,CAAC,GAAG;AAAA,EACN;AAEA,SACE,oBAAC,SAAI,WAAW,GAAG,0CAA0C,SAAS,GACnE,gBAAM,KAAK,EAAE,QAAQ,MAAM,CAAC,EAAE,IAAI,CAAC,GAAG,UACrC;AAAA,IAAC;AAAA;AAAA,MACC,gBAAc,kBAAkB,QAAQ,SAAS;AAAA,MACjD,cAAY,eAAe,QAAQ,CAAC;AAAA,MACpC,QAAM;AAAA,MACN,cAAa;AAAA,MACb,WAAW;AAAA,QACT;AAAA,QACA,kBAAkB,QACd,6FACA;AAAA,MACN;AAAA,MACA,MAAI;AAAA,MAEJ,SAAS,MAAM,QAAQ,KAAK;AAAA,MAC5B,MAAK;AAAA,MACL,SAAQ;AAAA;AAAA,IAHH;AAAA,EAIP,CACD,GACH;AAEJ;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module Carousel
|
|
3
|
+
*
|
|
4
|
+
* Touch-enabled carousel/slider built on Embla Carousel.
|
|
5
|
+
* Supports horizontal/vertical orientation, keyboard navigation, and custom plugins.
|
|
6
|
+
*
|
|
7
|
+
* @see {@link https://ui.shadcn.com/docs/components/carousel Shadcn Carousel}
|
|
8
|
+
* @see {@link https://www.embla-carousel.com/ Embla Carousel}
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* // Basic carousel
|
|
12
|
+
* <Carousel>
|
|
13
|
+
* <CarouselContent>
|
|
14
|
+
* <CarouselItem>Slide 1</CarouselItem>
|
|
15
|
+
* <CarouselItem>Slide 2</CarouselItem>
|
|
16
|
+
* <CarouselItem>Slide 3</CarouselItem>
|
|
17
|
+
* </CarouselContent>
|
|
18
|
+
* <CarouselPrevious />
|
|
19
|
+
* <CarouselNext />
|
|
20
|
+
* </Carousel>
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* // With API access and autoplay
|
|
24
|
+
* const [api, setApi] = useState<CarouselApi>();
|
|
25
|
+
*
|
|
26
|
+
* <Carousel setApi={setApi} opts={{ loop: true }}>
|
|
27
|
+
* <CarouselContent>...</CarouselContent>
|
|
28
|
+
* </Carousel>
|
|
29
|
+
*/
|
|
30
|
+
import useEmblaCarousel, { type UseEmblaCarouselType } from "embla-carousel-react";
|
|
31
|
+
import type * as React from "react";
|
|
32
|
+
import type { Ref } from "react";
|
|
33
|
+
import { Button } from "./button";
|
|
34
|
+
/** Embla Carousel API type for external control */
|
|
35
|
+
type CarouselApi = UseEmblaCarouselType[1];
|
|
36
|
+
type UseCarouselParameters = Parameters<typeof useEmblaCarousel>;
|
|
37
|
+
type CarouselOptions = UseCarouselParameters[0];
|
|
38
|
+
type CarouselPlugin = UseCarouselParameters[1];
|
|
39
|
+
interface CarouselProps {
|
|
40
|
+
opts?: CarouselOptions;
|
|
41
|
+
orientation?: "horizontal" | "vertical";
|
|
42
|
+
plugins?: CarouselPlugin;
|
|
43
|
+
setApi?: (api: CarouselApi) => void;
|
|
44
|
+
}
|
|
45
|
+
type CarouselContextProps = {
|
|
46
|
+
carouselRef: ReturnType<typeof useEmblaCarousel>[0];
|
|
47
|
+
api: ReturnType<typeof useEmblaCarousel>[1];
|
|
48
|
+
scrollPrev: () => void;
|
|
49
|
+
scrollNext: () => void;
|
|
50
|
+
canScrollPrev: boolean;
|
|
51
|
+
canScrollNext: boolean;
|
|
52
|
+
} & CarouselProps;
|
|
53
|
+
/**
|
|
54
|
+
* Hook to access carousel state and controls from child components.
|
|
55
|
+
* Must be used within a Carousel component.
|
|
56
|
+
*
|
|
57
|
+
* @returns Carousel API, scroll functions, and navigation state
|
|
58
|
+
* @throws Error if used outside of Carousel
|
|
59
|
+
*/
|
|
60
|
+
export declare function useCarousel(): CarouselContextProps;
|
|
61
|
+
/**
|
|
62
|
+
* Root carousel container. Provides context for child components.
|
|
63
|
+
*
|
|
64
|
+
* @param opts - Embla Carousel options (loop, align, dragFree, etc.)
|
|
65
|
+
* @param plugins - Embla plugins (autoplay, etc.)
|
|
66
|
+
* @param orientation - `"horizontal"` (default) or `"vertical"`
|
|
67
|
+
* @param setApi - Callback to receive the carousel API
|
|
68
|
+
*/
|
|
69
|
+
declare const Carousel: ({ orientation, opts, setApi, plugins, className, children, ref, ...props }: React.HTMLAttributes<HTMLDivElement> & CarouselProps & {
|
|
70
|
+
ref?: Ref<HTMLDivElement>;
|
|
71
|
+
}) => import("react/jsx-runtime").JSX.Element;
|
|
72
|
+
/**
|
|
73
|
+
* Container for carousel slides. Handles overflow and flex layout.
|
|
74
|
+
* @param containerClassName - Classes for the outer overflow container
|
|
75
|
+
*/
|
|
76
|
+
declare const CarouselContent: ({ className, containerClassName, ref, ...props }: React.HTMLAttributes<HTMLDivElement> & {
|
|
77
|
+
containerClassName?: string;
|
|
78
|
+
ref?: Ref<HTMLDivElement>;
|
|
79
|
+
}) => import("react/jsx-runtime").JSX.Element;
|
|
80
|
+
/** Props for CarouselItem component */
|
|
81
|
+
interface CarouselItemProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
82
|
+
ref?: Ref<HTMLDivElement>;
|
|
83
|
+
useCustomStyles?: boolean;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Individual slide within the carousel.
|
|
87
|
+
* @param useCustomStyles - Use responsive grid-based sizing instead of full-width
|
|
88
|
+
*/
|
|
89
|
+
declare const CarouselItem: ({ className, useCustomStyles, ref, ...props }: CarouselItemProps) => import("react/jsx-runtime").JSX.Element;
|
|
90
|
+
/** Previous slide button. Auto-disabled when at the start. */
|
|
91
|
+
declare const CarouselPrevious: ({ className, variant, size, ref, ...props }: React.ComponentProps<typeof Button> & {
|
|
92
|
+
ref?: Ref<HTMLButtonElement>;
|
|
93
|
+
}) => import("react/jsx-runtime").JSX.Element;
|
|
94
|
+
/** Next slide button. Auto-disabled when at the end. */
|
|
95
|
+
declare const CarouselNext: ({ className, variant, size, ref, ...props }: React.ComponentProps<typeof Button> & {
|
|
96
|
+
ref?: Ref<HTMLButtonElement>;
|
|
97
|
+
}) => import("react/jsx-runtime").JSX.Element;
|
|
98
|
+
export { Carousel, type CarouselApi, CarouselContent, CarouselItem, CarouselNext, CarouselPrevious, type CarouselProps, };
|
|
99
|
+
//# sourceMappingURL=carousel.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"carousel.d.ts","sourceRoot":"","sources":["../../src/components/carousel.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,OAAO,gBAAgB,EAAE,EACvB,KAAK,oBAAoB,EAC1B,MAAM,sBAAsB,CAAC;AAE9B,OAAO,KAAK,KAAK,KAAK,MAAM,OAAO,CAAC;AACpC,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,OAAO,CAAC;AAWjC,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAElC,mDAAmD;AACnD,KAAK,WAAW,GAAG,oBAAoB,CAAC,CAAC,CAAC,CAAC;AAC3C,KAAK,qBAAqB,GAAG,UAAU,CAAC,OAAO,gBAAgB,CAAC,CAAC;AACjE,KAAK,eAAe,GAAG,qBAAqB,CAAC,CAAC,CAAC,CAAC;AAChD,KAAK,cAAc,GAAG,qBAAqB,CAAC,CAAC,CAAC,CAAC;AAE/C,UAAU,aAAa;IACrB,IAAI,CAAC,EAAE,eAAe,CAAC;IACvB,WAAW,CAAC,EAAE,YAAY,GAAG,UAAU,CAAC;IACxC,OAAO,CAAC,EAAE,cAAc,CAAC;IACzB,MAAM,CAAC,EAAE,CAAC,GAAG,EAAE,WAAW,KAAK,IAAI,CAAC;CACrC;AAED,KAAK,oBAAoB,GAAG;IAC1B,WAAW,EAAE,UAAU,CAAC,OAAO,gBAAgB,CAAC,CAAC,CAAC,CAAC,CAAC;IACpD,GAAG,EAAE,UAAU,CAAC,OAAO,gBAAgB,CAAC,CAAC,CAAC,CAAC,CAAC;IAC5C,UAAU,EAAE,MAAM,IAAI,CAAC;IACvB,UAAU,EAAE,MAAM,IAAI,CAAC;IACvB,aAAa,EAAE,OAAO,CAAC;IACvB,aAAa,EAAE,OAAO,CAAC;CACxB,GAAG,aAAa,CAAC;AAIlB;;;;;;GAMG;AACH,wBAAgB,WAAW,yBAQ1B;AAED;;;;;;;GAOG;AACH,QAAA,MAAM,QAAQ,GAAI,4EASf,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC,GACrC,aAAa,GAAG;IACd,GAAG,CAAC,EAAE,GAAG,CAAC,cAAc,CAAC,CAAC;CAC3B,4CAsGF,CAAC;AAEF;;;GAGG;AACH,QAAA,MAAM,eAAe,GAAI,kDAKtB,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC,GAAG;IACxC,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,GAAG,CAAC,EAAE,GAAG,CAAC,cAAc,CAAC,CAAC;CAC3B,4CAmBA,CAAC;AAEF,uCAAuC;AACvC,UAAU,iBAAkB,SAAQ,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC;IACtE,GAAG,CAAC,EAAE,GAAG,CAAC,cAAc,CAAC,CAAC;IAC1B,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B;AAED;;;GAGG;AACH,QAAA,MAAM,YAAY,GAAI,+CAKnB,iBAAiB,4CAoBnB,CAAC;AAEF,8DAA8D;AAC9D,QAAA,MAAM,gBAAgB,GAAI,6CAMvB,KAAK,CAAC,cAAc,CAAC,OAAO,MAAM,CAAC,GAAG;IACvC,GAAG,CAAC,EAAE,GAAG,CAAC,iBAAiB,CAAC,CAAC;CAC9B,4CAwBA,CAAC;AAEF,wDAAwD;AACxD,QAAA,MAAM,YAAY,GAAI,6CAMnB,KAAK,CAAC,cAAc,CAAC,OAAO,MAAM,CAAC,GAAG;IACvC,GAAG,CAAC,EAAE,GAAG,CAAC,iBAAiB,CAAC,CAAC;CAC9B,4CAwBA,CAAC;AAEF,OAAO,EACL,QAAQ,EACR,KAAK,WAAW,EAChB,eAAe,EACf,YAAY,EACZ,YAAY,EACZ,gBAAgB,EAChB,KAAK,aAAa,GACnB,CAAC"}
|
|
@@ -180,7 +180,7 @@ const CarouselPrevious = ({
|
|
|
180
180
|
className: cn(
|
|
181
181
|
"absolute h-8 w-8 rounded-full",
|
|
182
182
|
orientation === "horizontal" ? "top-1/2 -left-12 -translate-y-1/2" : "-top-12 left-1/2 -translate-x-1/2 rotate-90",
|
|
183
|
-
!canScrollPrev && "
|
|
183
|
+
!canScrollPrev && "cursor-default!",
|
|
184
184
|
className
|
|
185
185
|
),
|
|
186
186
|
disabled: !canScrollPrev,
|
|
@@ -210,7 +210,7 @@ const CarouselNext = ({
|
|
|
210
210
|
className: cn(
|
|
211
211
|
"absolute h-8 w-8 rounded-full",
|
|
212
212
|
orientation === "horizontal" ? "top-1/2 -right-12 -translate-y-1/2" : "-bottom-12 left-1/2 -translate-x-1/2 rotate-90",
|
|
213
|
-
!canScrollNext && "
|
|
213
|
+
!canScrollNext && "cursor-default!",
|
|
214
214
|
className
|
|
215
215
|
),
|
|
216
216
|
disabled: !canScrollNext,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/components/carousel.tsx"],
|
|
4
|
-
"sourcesContent": ["/**\n * @module Carousel\n *\n * Touch-enabled carousel/slider built on Embla Carousel.\n * Supports horizontal/vertical orientation, keyboard navigation, and custom plugins.\n *\n * @see {@link https://ui.shadcn.com/docs/components/carousel Shadcn Carousel}\n * @see {@link https://www.embla-carousel.com/ Embla Carousel}\n *\n * @example\n * // Basic carousel\n * <Carousel>\n * <CarouselContent>\n * <CarouselItem>Slide 1</CarouselItem>\n * <CarouselItem>Slide 2</CarouselItem>\n * <CarouselItem>Slide 3</CarouselItem>\n * </CarouselContent>\n * <CarouselPrevious />\n * <CarouselNext />\n * </Carousel>\n *\n * @example\n * // With API access and autoplay\n * const [api, setApi] = useState<CarouselApi>();\n *\n * <Carousel setApi={setApi} opts={{ loop: true }}>\n * <CarouselContent>...</CarouselContent>\n * </Carousel>\n */\nimport useEmblaCarousel, {\n type UseEmblaCarouselType,\n} from \"embla-carousel-react\";\nimport { ArrowLeft, ArrowRight } from \"lucide-react\";\nimport type * as React from \"react\";\nimport type { Ref } from \"react\";\nimport {\n createContext,\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useState,\n} from \"react\";\n\nimport { cn } from \"../lib/utils\";\nimport { Button } from \"./button\";\n\n/** Embla Carousel API type for external control */\ntype CarouselApi = UseEmblaCarouselType[1];\ntype UseCarouselParameters = Parameters<typeof useEmblaCarousel>;\ntype CarouselOptions = UseCarouselParameters[0];\ntype CarouselPlugin = UseCarouselParameters[1];\n\ninterface CarouselProps {\n opts?: CarouselOptions;\n
|
|
4
|
+
"sourcesContent": ["/**\n * @module Carousel\n *\n * Touch-enabled carousel/slider built on Embla Carousel.\n * Supports horizontal/vertical orientation, keyboard navigation, and custom plugins.\n *\n * @see {@link https://ui.shadcn.com/docs/components/carousel Shadcn Carousel}\n * @see {@link https://www.embla-carousel.com/ Embla Carousel}\n *\n * @example\n * // Basic carousel\n * <Carousel>\n * <CarouselContent>\n * <CarouselItem>Slide 1</CarouselItem>\n * <CarouselItem>Slide 2</CarouselItem>\n * <CarouselItem>Slide 3</CarouselItem>\n * </CarouselContent>\n * <CarouselPrevious />\n * <CarouselNext />\n * </Carousel>\n *\n * @example\n * // With API access and autoplay\n * const [api, setApi] = useState<CarouselApi>();\n *\n * <Carousel setApi={setApi} opts={{ loop: true }}>\n * <CarouselContent>...</CarouselContent>\n * </Carousel>\n */\nimport useEmblaCarousel, {\n type UseEmblaCarouselType,\n} from \"embla-carousel-react\";\nimport { ArrowLeft, ArrowRight } from \"lucide-react\";\nimport type * as React from \"react\";\nimport type { Ref } from \"react\";\nimport {\n createContext,\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useState,\n} from \"react\";\n\nimport { cn } from \"../lib/utils\";\nimport { Button } from \"./button\";\n\n/** Embla Carousel API type for external control */\ntype CarouselApi = UseEmblaCarouselType[1];\ntype UseCarouselParameters = Parameters<typeof useEmblaCarousel>;\ntype CarouselOptions = UseCarouselParameters[0];\ntype CarouselPlugin = UseCarouselParameters[1];\n\ninterface CarouselProps {\n opts?: CarouselOptions;\n orientation?: \"horizontal\" | \"vertical\";\n plugins?: CarouselPlugin;\n setApi?: (api: CarouselApi) => void;\n}\n\ntype CarouselContextProps = {\n carouselRef: ReturnType<typeof useEmblaCarousel>[0];\n api: ReturnType<typeof useEmblaCarousel>[1];\n scrollPrev: () => void;\n scrollNext: () => void;\n canScrollPrev: boolean;\n canScrollNext: boolean;\n} & CarouselProps;\n\nconst CarouselContext = createContext<CarouselContextProps | null>(null);\n\n/**\n * Hook to access carousel state and controls from child components.\n * Must be used within a Carousel component.\n *\n * @returns Carousel API, scroll functions, and navigation state\n * @throws Error if used outside of Carousel\n */\nexport function useCarousel() {\n const context = useContext(CarouselContext);\n\n if (!context) {\n throw new Error(\"useCarousel must be used within a <Carousel />\");\n }\n\n return context;\n}\n\n/**\n * Root carousel container. Provides context for child components.\n *\n * @param opts - Embla Carousel options (loop, align, dragFree, etc.)\n * @param plugins - Embla plugins (autoplay, etc.)\n * @param orientation - `\"horizontal\"` (default) or `\"vertical\"`\n * @param setApi - Callback to receive the carousel API\n */\nconst Carousel = ({\n orientation = \"horizontal\",\n opts,\n setApi,\n plugins,\n className,\n children,\n ref,\n ...props\n}: React.HTMLAttributes<HTMLDivElement> &\n CarouselProps & {\n ref?: Ref<HTMLDivElement>;\n }) => {\n const [carouselRef, api] = useEmblaCarousel(\n {\n ...opts,\n axis: orientation === \"horizontal\" ? \"x\" : \"y\",\n },\n plugins\n );\n\n const [canScrollPrev, setCanScrollPrev] = useState(false);\n const [canScrollNext, setCanScrollNext] = useState(false);\n\n const onSelect = useCallback((carouselApi: CarouselApi) => {\n if (!carouselApi) {\n return;\n }\n\n setCanScrollPrev(carouselApi.canScrollPrev());\n setCanScrollNext(carouselApi.canScrollNext());\n }, []);\n\n const scrollPrev = useCallback(() => {\n api?.scrollPrev();\n }, [api]);\n\n const scrollNext = useCallback(() => {\n api?.scrollNext();\n }, [api]);\n\n const handleKeyDown = useCallback(\n (event: React.KeyboardEvent<HTMLDivElement>) => {\n if (event.key === \"ArrowLeft\") {\n event.preventDefault();\n scrollPrev();\n } else if (event.key === \"ArrowRight\") {\n event.preventDefault();\n scrollNext();\n }\n },\n [scrollPrev, scrollNext]\n );\n\n const carouselContextValue = useMemo(\n () => ({\n carouselRef,\n api,\n opts,\n orientation:\n orientation || (opts?.axis === \"y\" ? \"vertical\" : \"horizontal\"),\n scrollPrev,\n scrollNext,\n canScrollPrev,\n canScrollNext,\n }),\n [\n api,\n canScrollNext,\n canScrollPrev,\n carouselRef,\n opts,\n orientation,\n scrollNext,\n scrollPrev,\n ]\n );\n\n useEffect(() => {\n if (!(api && setApi)) {\n return;\n }\n\n setApi(api);\n }, [api, setApi]);\n\n useEffect(() => {\n if (!api) {\n return;\n }\n\n onSelect(api);\n api.on(\"reInit\", onSelect);\n api.on(\"select\", onSelect);\n\n return () => {\n api?.off(\"select\", onSelect);\n };\n }, [api, onSelect]);\n\n return (\n <CarouselContext.Provider value={carouselContextValue}>\n <div\n aria-roledescription=\"carousel\"\n className={cn(\"relative\", className)}\n onKeyDownCapture={handleKeyDown}\n ref={ref}\n role=\"region\"\n {...props}\n >\n {children}\n </div>\n </CarouselContext.Provider>\n );\n};\n\n/**\n * Container for carousel slides. Handles overflow and flex layout.\n * @param containerClassName - Classes for the outer overflow container\n */\nconst CarouselContent = ({\n className,\n containerClassName,\n ref,\n ...props\n}: React.HTMLAttributes<HTMLDivElement> & {\n containerClassName?: string;\n ref?: Ref<HTMLDivElement>;\n}) => {\n const { carouselRef, orientation } = useCarousel();\n\n return (\n <div\n className={cn(\"overflow-hidden\", containerClassName)}\n ref={carouselRef}\n >\n <div\n className={cn(\n \"flex\",\n orientation === \"horizontal\" ? \"-ml-4\" : \"-mt-4 flex-col\",\n className\n )}\n ref={ref}\n {...props}\n />\n </div>\n );\n};\n\n/** Props for CarouselItem component */\ninterface CarouselItemProps extends React.HTMLAttributes<HTMLDivElement> {\n ref?: Ref<HTMLDivElement>;\n useCustomStyles?: boolean;\n}\n\n/**\n * Individual slide within the carousel.\n * @param useCustomStyles - Use responsive grid-based sizing instead of full-width\n */\nconst CarouselItem = ({\n className,\n useCustomStyles,\n ref,\n ...props\n}: CarouselItemProps) => {\n const { orientation } = useCarousel();\n\n return (\n <div\n aria-roledescription=\"slide\"\n className={cn(\n useCustomStyles\n ? \"min-w-0 shrink-0 grow-0 @[1150px]:basis-1/6 @[1400px]:basis-[14.28%] @[1580px]:basis-[12.5%] @[540px]:basis-1/4 @[900px]:basis-1/5 basis-1/3 overflow-hidden px-0 pr-2\"\n : cn(\n \"min-w-0 shrink-0 grow-0 basis-full\",\n orientation === \"horizontal\" ? \"pl-4\" : \"pt-4\"\n ),\n className\n )}\n ref={ref}\n role=\"group\"\n {...props}\n />\n );\n};\n\n/** Previous slide button. Auto-disabled when at the start. */\nconst CarouselPrevious = ({\n className,\n variant = \"subtle\",\n size = \"icon\",\n ref,\n ...props\n}: React.ComponentProps<typeof Button> & {\n ref?: Ref<HTMLButtonElement>;\n}) => {\n const { orientation, scrollPrev, canScrollPrev } = useCarousel();\n\n return (\n <Button\n className={cn(\n \"absolute h-8 w-8 rounded-full\",\n orientation === \"horizontal\"\n ? \"top-1/2 -left-12 -translate-y-1/2\"\n : \"-top-12 left-1/2 -translate-x-1/2 rotate-90\",\n !canScrollPrev && \"cursor-default!\",\n className\n )}\n disabled={!canScrollPrev}\n onClick={scrollPrev}\n ref={ref}\n size={size}\n variant={variant}\n {...props}\n >\n <ArrowLeft className=\"h-4 w-4\" />\n <span className=\"sr-only\">Previous slide</span>\n </Button>\n );\n};\n\n/** Next slide button. Auto-disabled when at the end. */\nconst CarouselNext = ({\n className,\n variant = \"subtle\",\n size = \"icon\",\n ref,\n ...props\n}: React.ComponentProps<typeof Button> & {\n ref?: Ref<HTMLButtonElement>;\n}) => {\n const { orientation, scrollNext, canScrollNext } = useCarousel();\n\n return (\n <Button\n className={cn(\n \"absolute h-8 w-8 rounded-full\",\n orientation === \"horizontal\"\n ? \"top-1/2 -right-12 -translate-y-1/2\"\n : \"-bottom-12 left-1/2 -translate-x-1/2 rotate-90\",\n !canScrollNext && \"cursor-default!\",\n className\n )}\n disabled={!canScrollNext}\n onClick={scrollNext}\n ref={ref}\n size={size}\n variant={variant}\n {...props}\n >\n <ArrowRight className=\"h-4 w-4\" />\n <span className=\"sr-only\">Next slide</span>\n </Button>\n );\n};\n\nexport {\n Carousel,\n type CarouselApi,\n CarouselContent,\n CarouselItem,\n CarouselNext,\n CarouselPrevious,\n type CarouselProps,\n};\n"],
|
|
5
5
|
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { Checkbox as CheckboxPrimitive } from "radix-ui";
|
|
2
|
+
import type * as React from "react";
|
|
3
|
+
import type { Ref } from "react";
|
|
4
|
+
/**
|
|
5
|
+
* Props for the Checkbox component.
|
|
6
|
+
* @property variant - Visual style: `"default"` (square) or `"rounded"` (circular)
|
|
7
|
+
*/
|
|
8
|
+
interface CheckboxProps extends React.ComponentPropsWithoutRef<typeof CheckboxPrimitive.Root> {
|
|
9
|
+
ref?: Ref<React.ElementRef<typeof CheckboxPrimitive.Root>>;
|
|
10
|
+
variant?: "default" | "rounded";
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Interactive checkbox with check indicator.
|
|
14
|
+
* Supports checked, unchecked, and indeterminate states.
|
|
15
|
+
*/
|
|
16
|
+
declare const Checkbox: ({ className, variant, ref, ...props }: CheckboxProps) => import("react/jsx-runtime").JSX.Element;
|
|
17
|
+
/**
|
|
18
|
+
* Props for the DummyCheckbox component.
|
|
19
|
+
* @property variant - Visual style: `"default"` or `"rounded"`
|
|
20
|
+
* @property checked - Whether to show the check indicator
|
|
21
|
+
*/
|
|
22
|
+
interface DummyCheckboxProps extends React.ComponentPropsWithoutRef<"div"> {
|
|
23
|
+
checked?: boolean;
|
|
24
|
+
ref?: Ref<HTMLDivElement>;
|
|
25
|
+
variant?: "default" | "rounded";
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Non-interactive checkbox for display purposes only.
|
|
29
|
+
* Visually identical to Checkbox but without click/keyboard handling.
|
|
30
|
+
* Useful for list items where the parent handles selection.
|
|
31
|
+
*/
|
|
32
|
+
declare const DummyCheckbox: ({ className, variant, checked, ref, ...props }: DummyCheckboxProps) => import("react/jsx-runtime").JSX.Element;
|
|
33
|
+
export { Checkbox, type CheckboxProps, DummyCheckbox };
|
|
34
|
+
//# sourceMappingURL=checkbox.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"checkbox.d.ts","sourceRoot":"","sources":["../../src/components/checkbox.tsx"],"names":[],"mappings":"AAwBA,OAAO,EAAE,QAAQ,IAAI,iBAAiB,EAAE,MAAM,UAAU,CAAC;AACzD,OAAO,KAAK,KAAK,KAAK,MAAM,OAAO,CAAC;AACpC,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,OAAO,CAAC;AAkBjC;;;GAGG;AACH,UAAU,aACR,SAAQ,KAAK,CAAC,wBAAwB,CAAC,OAAO,iBAAiB,CAAC,IAAI,CAAC;IACrE,GAAG,CAAC,EAAE,GAAG,CAAC,KAAK,CAAC,UAAU,CAAC,OAAO,iBAAiB,CAAC,IAAI,CAAC,CAAC,CAAC;IAC3D,OAAO,CAAC,EAAE,SAAS,GAAG,SAAS,CAAC;CACjC;AAED;;;GAGG;AACH,QAAA,MAAM,QAAQ,GAAI,uCAKf,aAAa,4CAYf,CAAC;AAEF;;;;GAIG;AACH,UAAU,kBAAmB,SAAQ,KAAK,CAAC,wBAAwB,CAAC,KAAK,CAAC;IACxE,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,GAAG,CAAC,EAAE,GAAG,CAAC,cAAc,CAAC,CAAC;IAC1B,OAAO,CAAC,EAAE,SAAS,GAAG,SAAS,CAAC;CACjC;AAED;;;;GAIG;AACH,QAAA,MAAM,aAAa,GAAI,gDAMpB,kBAAkB,4CAepB,CAAC;AAEF,OAAO,EAAE,QAAQ,EAAE,KAAK,aAAa,EAAE,aAAa,EAAE,CAAC"}
|
|
@@ -4,7 +4,7 @@ import { Check } from "lucide-react";
|
|
|
4
4
|
import { Checkbox as CheckboxPrimitive } from "radix-ui";
|
|
5
5
|
import { cn } from "../lib/utils";
|
|
6
6
|
const checkboxVariants = cva(
|
|
7
|
-
"peer h-4 w-4 shrink-0 rounded border border-gray-200 border-solid ring-offset-white hover:bg-gray-50 focus-visible:outline-
|
|
7
|
+
"peer h-4 w-4 shrink-0 rounded border border-gray-200 border-solid ring-offset-white hover:bg-gray-50 focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-[var(--focus-ring)] focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-brand-primary data-[state=checked]:text-white data-[state=checked]:hover:bg-brand-primary-hover dark:border-gray-800 dark:ring-offset-gray-950 dark:data-[state=checked]:bg-brand-primary dark:data-[state=checked]:text-white dark:focus-visible:ring-[var(--focus-ring)] dark:hover:bg-gray-900 dark:data-[state=checked]:hover:bg-brand-primary-hover",
|
|
8
8
|
{
|
|
9
9
|
variants: {
|
|
10
10
|
variant: {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/components/checkbox.tsx"],
|
|
4
|
-
"sourcesContent": ["/**\n * @module Checkbox\n *\n * Toggle control for binary choices. Built on Radix UI Checkbox primitive.\n *\n * @see {@link https://ui.shadcn.com/docs/components/checkbox Shadcn Checkbox}\n * @see {@link https://www.radix-ui.com/primitives/docs/components/checkbox Radix Checkbox}\n *\n * @example\n * // Basic checkbox\n * <Checkbox id=\"terms\" />\n * <label htmlFor=\"terms\">Accept terms</label>\n *\n * @example\n * // Controlled checkbox\n * const [checked, setChecked] = useState(false);\n * <Checkbox checked={checked} onCheckedChange={setChecked} />\n *\n * @example\n * // Rounded variant\n * <Checkbox variant=\"rounded\" />\n */\nimport { cva } from \"class-variance-authority\";\nimport { Check } from \"lucide-react\";\nimport { Checkbox as CheckboxPrimitive } from \"radix-ui\";\nimport type * as React from \"react\";\nimport type { Ref } from \"react\";\n\nimport { cn } from \"../lib/utils\";\n\n/** CVA variants for checkbox styling */\nconst checkboxVariants = cva(\n \"peer h-4 w-4 shrink-0 rounded border border-gray-200 border-solid ring-offset-white hover:bg-gray-50 focus-visible:outline-
|
|
4
|
+
"sourcesContent": ["/**\n * @module Checkbox\n *\n * Toggle control for binary choices. Built on Radix UI Checkbox primitive.\n *\n * @see {@link https://ui.shadcn.com/docs/components/checkbox Shadcn Checkbox}\n * @see {@link https://www.radix-ui.com/primitives/docs/components/checkbox Radix Checkbox}\n *\n * @example\n * // Basic checkbox\n * <Checkbox id=\"terms\" />\n * <label htmlFor=\"terms\">Accept terms</label>\n *\n * @example\n * // Controlled checkbox\n * const [checked, setChecked] = useState(false);\n * <Checkbox checked={checked} onCheckedChange={setChecked} />\n *\n * @example\n * // Rounded variant\n * <Checkbox variant=\"rounded\" />\n */\nimport { cva } from \"class-variance-authority\";\nimport { Check } from \"lucide-react\";\nimport { Checkbox as CheckboxPrimitive } from \"radix-ui\";\nimport type * as React from \"react\";\nimport type { Ref } from \"react\";\n\nimport { cn } from \"../lib/utils\";\n\n/** CVA variants for checkbox styling */\nconst checkboxVariants = cva(\n \"peer h-4 w-4 shrink-0 rounded border border-gray-200 border-solid ring-offset-white hover:bg-gray-50 focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-[var(--focus-ring)] focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-brand-primary data-[state=checked]:text-white data-[state=checked]:hover:bg-brand-primary-hover dark:border-gray-800 dark:ring-offset-gray-950 dark:data-[state=checked]:bg-brand-primary dark:data-[state=checked]:text-white dark:focus-visible:ring-[var(--focus-ring)] dark:hover:bg-gray-900 dark:data-[state=checked]:hover:bg-brand-primary-hover\",\n {\n variants: {\n variant: {\n default: \"\",\n rounded:\n \"rounded-full dark:border-gray-500 [&[data-state='checked']]:border-brand-primary [&[data-state='checked']]:bg-brand-primary\",\n },\n },\n }\n);\n\n/**\n * Props for the Checkbox component.\n * @property variant - Visual style: `\"default\"` (square) or `\"rounded\"` (circular)\n */\ninterface CheckboxProps\n extends React.ComponentPropsWithoutRef<typeof CheckboxPrimitive.Root> {\n ref?: Ref<React.ElementRef<typeof CheckboxPrimitive.Root>>;\n variant?: \"default\" | \"rounded\";\n}\n\n/**\n * Interactive checkbox with check indicator.\n * Supports checked, unchecked, and indeterminate states.\n */\nconst Checkbox = ({\n className,\n variant = \"default\",\n ref,\n ...props\n}: CheckboxProps) => (\n <CheckboxPrimitive.Root\n className={cn(checkboxVariants({ variant }), className)}\n ref={ref}\n {...props}\n >\n <CheckboxPrimitive.Indicator\n className={cn(\"flex items-center justify-center text-current\")}\n >\n <Check className=\"h-4 w-4\" />\n </CheckboxPrimitive.Indicator>\n </CheckboxPrimitive.Root>\n);\n\n/**\n * Props for the DummyCheckbox component.\n * @property variant - Visual style: `\"default\"` or `\"rounded\"`\n * @property checked - Whether to show the check indicator\n */\ninterface DummyCheckboxProps extends React.ComponentPropsWithoutRef<\"div\"> {\n checked?: boolean;\n ref?: Ref<HTMLDivElement>;\n variant?: \"default\" | \"rounded\";\n}\n\n/**\n * Non-interactive checkbox for display purposes only.\n * Visually identical to Checkbox but without click/keyboard handling.\n * Useful for list items where the parent handles selection.\n */\nconst DummyCheckbox = ({\n className,\n variant = \"default\",\n checked,\n ref,\n ...props\n}: DummyCheckboxProps) => (\n <div\n className={cn(checkboxVariants({ variant }), className)}\n data-state={checked ? \"checked\" : \"unchecked\"}\n ref={ref}\n {...props}\n >\n <div\n className={cn(\n checked ? \"flex items-center justify-center text-current\" : \"hidden\"\n )}\n >\n <Check className=\"h-4 w-4\" />\n </div>\n </div>\n);\n\nexport { Checkbox, type CheckboxProps, DummyCheckbox };\n"],
|
|
5
5
|
"mappings": "AAwEM;AAlDN,SAAS,WAAW;AACpB,SAAS,aAAa;AACtB,SAAS,YAAY,yBAAyB;AAI9C,SAAS,UAAU;AAGnB,MAAM,mBAAmB;AAAA,EACvB;AAAA,EACA;AAAA,IACE,UAAU;AAAA,MACR,SAAS;AAAA,QACP,SAAS;AAAA,QACT,SACE;AAAA,MACJ;AAAA,IACF;AAAA,EACF;AACF;AAgBA,MAAM,WAAW,CAAC;AAAA,EAChB;AAAA,EACA,UAAU;AAAA,EACV;AAAA,EACA,GAAG;AACL,MACE;AAAA,EAAC,kBAAkB;AAAA,EAAlB;AAAA,IACC,WAAW,GAAG,iBAAiB,EAAE,QAAQ,CAAC,GAAG,SAAS;AAAA,IACtD;AAAA,IACC,GAAG;AAAA,IAEJ;AAAA,MAAC,kBAAkB;AAAA,MAAlB;AAAA,QACC,WAAW,GAAG,+CAA+C;AAAA,QAE7D,8BAAC,SAAM,WAAU,WAAU;AAAA;AAAA,IAC7B;AAAA;AACF;AAmBF,MAAM,gBAAgB,CAAC;AAAA,EACrB;AAAA,EACA,UAAU;AAAA,EACV;AAAA,EACA;AAAA,EACA,GAAG;AACL,MACE;AAAA,EAAC;AAAA;AAAA,IACC,WAAW,GAAG,iBAAiB,EAAE,QAAQ,CAAC,GAAG,SAAS;AAAA,IACtD,cAAY,UAAU,YAAY;AAAA,IAClC;AAAA,IACC,GAAG;AAAA,IAEJ;AAAA,MAAC;AAAA;AAAA,QACC,WAAW;AAAA,UACT,UAAU,kDAAkD;AAAA,QAC9D;AAAA,QAEA,8BAAC,SAAM,WAAU,WAAU;AAAA;AAAA,IAC7B;AAAA;AACF;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|