periplo-ui 3.48.0 → 3.48.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/dist/components/Accordion/Accordion.js +1 -1
- package/dist/components/Accordion/Accordion.js.map +1 -1
- package/dist/components/Breadcrumb/Breadcrumb.js +2 -1
- package/dist/components/Breadcrumb/Breadcrumb.js.map +1 -1
- package/dist/components/Button/Button.js +1 -1
- package/dist/components/Button/Button.js.map +1 -1
- package/dist/components/Calendar/Calendar.js +2 -1
- package/dist/components/Calendar/Calendar.js.map +1 -1
- package/dist/components/Carousel/Carousel.js +2 -1
- package/dist/components/Carousel/Carousel.js.map +1 -1
- package/dist/components/Checkbox/Checkbox.js +1 -1
- package/dist/components/Checkbox/Checkbox.js.map +1 -1
- package/dist/components/Chip/Chip.js +1 -1
- package/dist/components/Chip/Chip.js.map +1 -1
- package/dist/components/Combobox/Combobox.js +2 -1
- package/dist/components/Combobox/Combobox.js.map +1 -1
- package/dist/components/Combobox/StaticComboboxList.js +2 -1
- package/dist/components/Combobox/StaticComboboxList.js.map +1 -1
- package/dist/components/Combobox/VirtualizedComboboxList.js +1 -1
- package/dist/components/Combobox/VirtualizedComboboxList.js.map +1 -1
- package/dist/components/Command/Command.js +1 -1
- package/dist/components/Command/Command.js.map +1 -1
- package/dist/components/DataTable/components/DataTableToolbar.js +4 -1
- package/dist/components/DataTable/components/DataTableToolbar.js.map +1 -1
- package/dist/components/DatePicker/DatePicker.js +2 -1
- package/dist/components/DatePicker/DatePicker.js.map +1 -1
- package/dist/components/Dialog/Dialog.js +1 -1
- package/dist/components/Dialog/Dialog.js.map +1 -1
- package/dist/components/InlineMultiSelect/InlineMultiSelect.js +3 -1
- package/dist/components/InlineMultiSelect/InlineMultiSelect.js.map +1 -1
- package/dist/components/Input/Input.js +6 -2
- package/dist/components/Input/Input.js.map +1 -1
- package/dist/components/LazyDatePicker/LazyDatePicker.js +1 -1
- package/dist/components/LazyDatePicker/LazyDatePicker.js.map +1 -1
- package/dist/components/MultiSelect/MultiSelect.js +2 -1
- package/dist/components/MultiSelect/MultiSelect.js.map +1 -1
- package/dist/components/RadioGroup/RadioGroup.js +1 -1
- package/dist/components/RadioGroup/RadioGroup.js.map +1 -1
- package/dist/components/Sidebar/Sidebar.js +2 -2
- package/dist/components/Sidebar/Sidebar.js.map +1 -1
- package/dist/components/Tabs/Tabs.js +2 -2
- package/dist/components/Tabs/Tabs.js.map +1 -1
- package/dist/components/Toaster/Toaster.js +5 -1
- package/dist/components/Toaster/Toaster.js.map +1 -1
- package/package.json +1 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
2
|
-
import { CaretDown } from '@phosphor-icons/react';
|
|
2
|
+
import { CaretDown } from '@phosphor-icons/react/dist/ssr/CaretDown';
|
|
3
3
|
import * as AccordionPrimitive from '@radix-ui/react-accordion';
|
|
4
4
|
import * as React from 'react';
|
|
5
5
|
import { cn } from '../../lib/utils.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Accordion.js","sources":["../../../src/components/Accordion/Accordion.tsx"],"sourcesContent":["import { CaretDown } from '@phosphor-icons/react'\nimport * as AccordionPrimitive from '@radix-ui/react-accordion'\nimport * as React from 'react'\n\nimport { cn } from '@/lib/utils'\n\nconst Accordion = AccordionPrimitive.Root\n\nconst AccordionItem = React.forwardRef<\n React.ComponentRef<typeof AccordionPrimitive.Item>,\n React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Item>\n>(({ className, ...props }, ref) => (\n <AccordionPrimitive.Item ref={ref} className={cn('border-b', className)} {...props} />\n))\nAccordionItem.displayName = 'AccordionItem'\n\nconst AccordionTrigger = React.forwardRef<\n React.ComponentRef<typeof AccordionPrimitive.Trigger>,\n React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Trigger>\n>(({ className, children, ...props }, ref) => (\n <AccordionPrimitive.Header className=\"flex\">\n <AccordionPrimitive.Trigger\n ref={ref}\n className={cn(\n 'flex flex-1 items-center justify-between py-4 font-medium transition-all hover:underline md:py-6 [&[data-state=open]>svg]:rotate-180',\n className,\n )}\n {...props}\n >\n {children}\n <CaretDown className=\"text-foreground h-6 w-6 shrink-0 transition-transform duration-200\" />\n </AccordionPrimitive.Trigger>\n </AccordionPrimitive.Header>\n))\nAccordionTrigger.displayName = AccordionPrimitive.Trigger.displayName\n\nconst AccordionContent = React.forwardRef<\n React.ComponentRef<typeof AccordionPrimitive.Content>,\n React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Content>\n>(({ className, children, ...props }, ref) => (\n <AccordionPrimitive.Content\n ref={ref}\n className=\"data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down overflow-hidden text-sm transition-all\"\n {...props}\n >\n <div className={cn('pt-0 pb-6', className)}>{children}</div>\n </AccordionPrimitive.Content>\n))\n\nAccordionContent.displayName = AccordionPrimitive.Content.displayName\n\nexport { Accordion, AccordionItem, AccordionTrigger, AccordionContent }\n"],"names":[],"mappings":";;;;;;AAMA,MAAM,YAAY,kBAAA,CAAmB;AAErC,MAAM,aAAA,GAAgB,MAAM,UAAA,CAG1B,CAAC,EAAE,SAAA,EAAW,GAAG,KAAA,EAAM,EAAG,GAAA,qBAC1B,GAAA,CAAC,mBAAmB,IAAA,EAAnB,EAAwB,KAAU,SAAA,EAAW,EAAA,CAAG,YAAY,SAAS,CAAA,EAAI,GAAG,KAAA,EAAO,CACrF;AACD,aAAA,CAAc,WAAA,GAAc,eAAA;AAE5B,MAAM,mBAAmB,KAAA,CAAM,UAAA,CAG7B,CAAC,EAAE,WAAW,QAAA,EAAU,GAAG,KAAA,EAAM,EAAG,wBACpC,GAAA,CAAC,kBAAA,CAAmB,MAAA,EAAnB,EAA0B,WAAU,MAAA,EACnC,QAAA,kBAAA,IAAA;AAAA,EAAC,kBAAA,CAAmB,OAAA;AAAA,EAAnB;AAAA,IACC,GAAA;AAAA,IACA,SAAA,EAAW,EAAA;AAAA,MACT,sIAAA;AAAA,MACA;AAAA,KACF;AAAA,IACC,GAAG,KAAA;AAAA,IAEH,QAAA,EAAA;AAAA,MAAA,QAAA;AAAA,sBACD,GAAA,CAAC,SAAA,EAAA,EAAU,SAAA,EAAU,oEAAA,EAAqE;AAAA;AAAA;AAC5F,CAAA,EACF,CACD;AACD,gBAAA,CAAiB,WAAA,GAAc,mBAAmB,OAAA,CAAQ,WAAA;AAE1D,MAAM,gBAAA,GAAmB,KAAA,CAAM,UAAA,CAG7B,CAAC,EAAE,WAAW,QAAA,EAAU,GAAG,KAAA,EAAM,EAAG,GAAA,qBACpC,GAAA;AAAA,EAAC,kBAAA,CAAmB,OAAA;AAAA,EAAnB;AAAA,IACC,GAAA;AAAA,IACA,SAAA,EAAU,0HAAA;AAAA,IACT,GAAG,KAAA;AAAA,IAEJ,8BAAC,KAAA,EAAA,EAAI,SAAA,EAAW,GAAG,WAAA,EAAa,SAAS,GAAI,QAAA,EAAS;AAAA;AACxD,CACD;AAED,gBAAA,CAAiB,WAAA,GAAc,mBAAmB,OAAA,CAAQ,WAAA;;;;"}
|
|
1
|
+
{"version":3,"file":"Accordion.js","sources":["../../../src/components/Accordion/Accordion.tsx"],"sourcesContent":["import { CaretDown } from '@phosphor-icons/react/dist/ssr/CaretDown'\nimport * as AccordionPrimitive from '@radix-ui/react-accordion'\nimport * as React from 'react'\n\nimport { cn } from '@/lib/utils'\n\nconst Accordion = AccordionPrimitive.Root\n\nconst AccordionItem = React.forwardRef<\n React.ComponentRef<typeof AccordionPrimitive.Item>,\n React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Item>\n>(({ className, ...props }, ref) => (\n <AccordionPrimitive.Item ref={ref} className={cn('border-b', className)} {...props} />\n))\nAccordionItem.displayName = 'AccordionItem'\n\nconst AccordionTrigger = React.forwardRef<\n React.ComponentRef<typeof AccordionPrimitive.Trigger>,\n React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Trigger>\n>(({ className, children, ...props }, ref) => (\n <AccordionPrimitive.Header className=\"flex\">\n <AccordionPrimitive.Trigger\n ref={ref}\n className={cn(\n 'flex flex-1 items-center justify-between py-4 font-medium transition-all hover:underline md:py-6 [&[data-state=open]>svg]:rotate-180',\n className,\n )}\n {...props}\n >\n {children}\n <CaretDown className=\"text-foreground h-6 w-6 shrink-0 transition-transform duration-200\" />\n </AccordionPrimitive.Trigger>\n </AccordionPrimitive.Header>\n))\nAccordionTrigger.displayName = AccordionPrimitive.Trigger.displayName\n\nconst AccordionContent = React.forwardRef<\n React.ComponentRef<typeof AccordionPrimitive.Content>,\n React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Content>\n>(({ className, children, ...props }, ref) => (\n <AccordionPrimitive.Content\n ref={ref}\n className=\"data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down overflow-hidden text-sm transition-all\"\n {...props}\n >\n <div className={cn('pt-0 pb-6', className)}>{children}</div>\n </AccordionPrimitive.Content>\n))\n\nAccordionContent.displayName = AccordionPrimitive.Content.displayName\n\nexport { Accordion, AccordionItem, AccordionTrigger, AccordionContent }\n"],"names":[],"mappings":";;;;;;AAMA,MAAM,YAAY,kBAAA,CAAmB;AAErC,MAAM,aAAA,GAAgB,MAAM,UAAA,CAG1B,CAAC,EAAE,SAAA,EAAW,GAAG,KAAA,EAAM,EAAG,GAAA,qBAC1B,GAAA,CAAC,mBAAmB,IAAA,EAAnB,EAAwB,KAAU,SAAA,EAAW,EAAA,CAAG,YAAY,SAAS,CAAA,EAAI,GAAG,KAAA,EAAO,CACrF;AACD,aAAA,CAAc,WAAA,GAAc,eAAA;AAE5B,MAAM,mBAAmB,KAAA,CAAM,UAAA,CAG7B,CAAC,EAAE,WAAW,QAAA,EAAU,GAAG,KAAA,EAAM,EAAG,wBACpC,GAAA,CAAC,kBAAA,CAAmB,MAAA,EAAnB,EAA0B,WAAU,MAAA,EACnC,QAAA,kBAAA,IAAA;AAAA,EAAC,kBAAA,CAAmB,OAAA;AAAA,EAAnB;AAAA,IACC,GAAA;AAAA,IACA,SAAA,EAAW,EAAA;AAAA,MACT,sIAAA;AAAA,MACA;AAAA,KACF;AAAA,IACC,GAAG,KAAA;AAAA,IAEH,QAAA,EAAA;AAAA,MAAA,QAAA;AAAA,sBACD,GAAA,CAAC,SAAA,EAAA,EAAU,SAAA,EAAU,oEAAA,EAAqE;AAAA;AAAA;AAC5F,CAAA,EACF,CACD;AACD,gBAAA,CAAiB,WAAA,GAAc,mBAAmB,OAAA,CAAQ,WAAA;AAE1D,MAAM,gBAAA,GAAmB,KAAA,CAAM,UAAA,CAG7B,CAAC,EAAE,WAAW,QAAA,EAAU,GAAG,KAAA,EAAM,EAAG,GAAA,qBACpC,GAAA;AAAA,EAAC,kBAAA,CAAmB,OAAA;AAAA,EAAnB;AAAA,IACC,GAAA;AAAA,IACA,SAAA,EAAU,0HAAA;AAAA,IACT,GAAG,KAAA;AAAA,IAEJ,8BAAC,KAAA,EAAA,EAAI,SAAA,EAAW,GAAG,WAAA,EAAa,SAAS,GAAI,QAAA,EAAS;AAAA;AACxD,CACD;AAED,gBAAA,CAAiB,WAAA,GAAc,mBAAmB,OAAA,CAAQ,WAAA;;;;"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
2
|
-
import { CaretRight
|
|
2
|
+
import { CaretRight } from '@phosphor-icons/react/dist/ssr/CaretRight';
|
|
3
|
+
import { DotsThree } from '@phosphor-icons/react/dist/ssr/DotsThree';
|
|
3
4
|
import { Slot } from '@radix-ui/react-slot';
|
|
4
5
|
import * as React from 'react';
|
|
5
6
|
import { Typography } from '../Typography/Typography.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Breadcrumb.js","sources":["../../../src/components/Breadcrumb/Breadcrumb.tsx"],"sourcesContent":["import { CaretRight, DotsThree } from '@phosphor-icons/react'\nimport { Slot } from '@radix-ui/react-slot'\nimport * as React from 'react'\n\nimport { Typography } from '../Typography'\n\nimport { cn } from '@/lib/utils'\n\n/**\n * Root container for the breadcrumb navigation.\n * Provides the overall context and ARIA labeling.\n */\nconst BreadcrumbRoot = React.forwardRef<\n HTMLElement,\n React.ComponentPropsWithoutRef<'nav'> & {\n /** Custom separator element to use between breadcrumb items */\n separator?: React.ReactNode\n }\n>(({ ...props }, ref) => <nav ref={ref} aria-label=\"breadcrumb\" {...props} />)\nBreadcrumbRoot.displayName = 'BreadcrumbRoot'\n\n/**\n * Container for breadcrumb items.\n * Handles layout and spacing of the breadcrumb navigation.\n */\nconst BreadcrumbList = React.forwardRef<HTMLOListElement, React.ComponentPropsWithoutRef<'ol'>>(\n ({ className, ...props }, ref) => (\n <ol\n ref={ref}\n className={cn(\n 'text-muted-foreground flex flex-wrap items-center gap-1.5 text-sm break-words sm:gap-2.5',\n className,\n )}\n {...props}\n />\n ),\n)\nBreadcrumbList.displayName = 'BreadcrumbList'\n\n/**\n * Individual breadcrumb item container.\n * Wraps a link or the current page indicator.\n */\nconst BreadcrumbItem = React.forwardRef<HTMLLIElement, React.ComponentPropsWithoutRef<'li'>>(\n ({ className, ...props }, ref) => (\n <li ref={ref} className={cn('inline-flex items-center gap-1.5', className)} {...props} />\n ),\n)\nBreadcrumbItem.displayName = 'BreadcrumbItem'\n\n/** Text transform options for breadcrumb links */\ntype TextTransformOption = 'capitalize' | 'capitalize-first' | 'uppercase' | 'none'\n\n/** Get class names for text transform styling */\nconst getTextTransformClass = (transform: TextTransformOption): string => {\n switch (transform) {\n case 'capitalize-first':\n return '[&]:has-[::first-letter]:uppercase'\n case 'capitalize':\n return 'capitalize'\n case 'uppercase':\n return 'uppercase'\n default:\n return ''\n }\n}\n\n/**\n * Interactive link element for breadcrumb navigation.\n * Can be rendered as a custom element using asChild.\n */\nconst BreadcrumbLink = React.forwardRef<\n HTMLAnchorElement,\n React.ComponentPropsWithoutRef<'a'> & {\n /** When true, the component will render its children directly instead of wrapping them in an anchor tag */\n asChild?: boolean\n /** The text transformation to apply to the link text */\n textTransform?: TextTransformOption\n }\n>(({ asChild, className, textTransform = 'capitalize-first', children, ...props }, ref) => {\n const Comp = asChild ? Slot : 'a'\n\n // Simplify the capitalization logic using a direct string transformation\n const content =\n textTransform === 'capitalize-first' && typeof children === 'string'\n ? children.charAt(0).toUpperCase() + children.slice(1)\n : children\n\n return (\n <Typography variant=\"title-sm\" weight={'medium'}>\n <Comp\n ref={ref}\n className={cn(\n 'text-neutral-500 transition-colors hover:text-neutral-950',\n textTransform !== 'capitalize-first' && getTextTransformClass(textTransform),\n className,\n )}\n {...props}\n >\n {content}\n </Comp>\n </Typography>\n )\n})\nBreadcrumbLink.displayName = 'BreadcrumbLink'\n\n/**\n * Current page indicator in the breadcrumb.\n * Non-interactive element showing the current location.\n */\nconst BreadcrumbPage = React.forwardRef<\n HTMLSpanElement,\n React.ComponentPropsWithoutRef<'span'> & {\n textTransform?: TextTransformOption\n }\n>(({ className, textTransform = 'capitalize-first', children, ...props }, ref) => {\n const content =\n textTransform === 'capitalize-first' && typeof children === 'string'\n ? children.charAt(0).toUpperCase() + children.slice(1)\n : children\n\n return (\n <Typography variant=\"title-sm\">\n <span\n ref={ref}\n aria-disabled=\"true\"\n aria-current=\"page\"\n className={cn(\n 'font-medium text-neutral-950',\n textTransform !== 'capitalize-first' && getTextTransformClass(textTransform),\n className,\n )}\n {...props}\n >\n {content}\n </span>\n </Typography>\n )\n})\nBreadcrumbPage.displayName = 'BreadcrumbPage'\n\n/**\n * Separator element between breadcrumb items.\n * Can be customized with different icons or characters.\n */\nconst BreadcrumbSeparator = ({ children, className, ...props }: React.ComponentProps<'span'>) => (\n <span aria-hidden=\"true\" className={cn('text-neutral-500 [&>svg]:size-3.5', className)} {...props}>\n {children ?? <CaretRight />}\n </span>\n)\nBreadcrumbSeparator.displayName = 'BreadcrumbSeparator'\n\n/**\n * Ellipsis indicator for truncated breadcrumb paths.\n * Used to show that there are hidden items in the path.\n */\nconst BreadcrumbEllipsis = ({ className, ...props }: React.ComponentProps<'span'>) => (\n <span aria-hidden=\"true\" className={cn('flex h-9 w-9 items-center justify-center', className)} {...props}>\n <DotsThree className=\"h-4 w-4\" />\n <span className=\"sr-only\">More</span>\n </span>\n)\nBreadcrumbEllipsis.displayName = 'BreadcrumbEllipsis'\n\n/**\n * Sanitizes a route string by replacing hyphens with spaces.\n * @param route - The route string to sanitize.\n * @returns The sanitized route string.\n */\nconst sanitizeRoute = (route: string) => {\n return route.replace(/-/g, ' ')\n}\n\n/**\n * Transforms a kebab-case route to a camelCase translation key\n * @param route - The route segment in kebab-case\n * @returns The translation key in camelCase\n */\nconst routeToTranslationKey = (route: string): string => {\n return route\n .split('-')\n .map((word, index) => (index === 0 ? word : word.charAt(0).toUpperCase() + word.slice(1)))\n .join('')\n}\n\n/**\n * Gets the routes for the breadcrumb navigation.\n * @param pathname - The current pathname.\n * @param pathMappings - Optional object containing custom path mappings.\n * @param translation - Optional translation function.\n * @param basePath - Optional base path to strip from pathname and use as home route.\n * @returns The routes for the breadcrumb navigation.\n */\nconst getRoutes = (\n pathname: string,\n pathMappings?: Record<string, string | null>,\n translation?: (key: string) => string,\n basePath?: string,\n) => {\n // Strip the base path from pathname if it exists\n let processedPathname = pathname\n if (basePath && pathname.startsWith(basePath)) {\n processedPathname = pathname.slice(basePath.length)\n // Ensure we don't start with a slash after stripping\n if (processedPathname.startsWith('/')) {\n processedPathname = processedPathname.slice(1)\n }\n }\n\n const baseRoutes = processedPathname.split('/').filter(Boolean)\n\n const routes = baseRoutes.map((route, index) => {\n if (pathMappings && route in pathMappings && pathMappings[route] === null) {\n return null\n }\n\n let displayName = route\n\n // Check if there's a custom mapping for this route\n if (pathMappings && pathMappings[route] != null) {\n displayName = pathMappings[route]\n }\n // If there's a translation function, convert route to translation key\n else if (translation) {\n const translationKey = routeToTranslationKey(route)\n displayName = translation(translationKey)\n }\n // If no mapping or translation function, sanitize the route\n else {\n displayName = sanitizeRoute(route)\n }\n\n const routeSegments = baseRoutes.slice(0, index + 1)\n const routePath = routeSegments.join('/')\n const fullHref = basePath ? `${basePath}/${routePath}` : `/${routePath}`\n\n return {\n name: displayName,\n href: fullHref,\n }\n })\n\n // Handle home translation — hide if mapped to null\n const homeKey = 'home'\n if (!(pathMappings && homeKey in pathMappings && pathMappings[homeKey] === null)) {\n const homeHref = basePath ?? '/'\n routes.unshift({\n name: pathMappings?.[homeKey] ?? translation?.(homeKey) ?? 'Home',\n href: homeHref,\n })\n }\n\n return routes.filter(Boolean) as Array<{ name: string; href: string }>\n}\n\n/**\n * Navigation breadcrumb component.\n * Displays a breadcrumb navigation for the current path.\n * @param pathname - The current pathname\n * @param pathMappings - Optional object containing custom path mappings\n * @param translation - Optional translation function\n * @param basePath - Optional base path to strip from pathname and use as home route\n * @param textTransform - Optional text transformation to apply to breadcrumb text\n */\nconst NavigationBreadcrumb = ({\n pathname,\n pathMappings,\n translation,\n basePath,\n textTransform,\n endSlash = true,\n}: {\n pathname: string\n pathMappings?: Record<string, string | null>\n translation?: (key: string) => string\n basePath?: string\n textTransform?: TextTransformOption\n endSlash?: boolean\n}) => {\n return (\n <BreadcrumbRoot>\n <BreadcrumbList>\n {getRoutes(pathname, pathMappings, translation, basePath).map((route, index, array) => (\n <React.Fragment key={index}>\n <BreadcrumbItem>\n {index === array.length - 1 ? (\n <BreadcrumbPage textTransform={textTransform}>{route.name}</BreadcrumbPage>\n ) : (\n <BreadcrumbLink href={route.href + (endSlash ? '/' : '')} textTransform={textTransform}>\n {route.name}\n </BreadcrumbLink>\n )}\n </BreadcrumbItem>\n {index < array.length - 1 && <BreadcrumbSeparator />}\n </React.Fragment>\n ))}\n </BreadcrumbList>\n </BreadcrumbRoot>\n )\n}\n\nconst PagesBreadcrumb = ({\n pages,\n currentPage,\n}: {\n pages: Array<{ link: string; text: string }>\n currentPage: string\n}) => {\n return (\n <BreadcrumbRoot>\n <BreadcrumbList>\n {pages.map((page) => (\n <BreadcrumbItem key={pages.indexOf(page)}>\n <BreadcrumbLink href={page.link}>{page.text}</BreadcrumbLink>\n <BreadcrumbSeparator />\n </BreadcrumbItem>\n ))}\n <BreadcrumbItem>\n <BreadcrumbPage>{currentPage}</BreadcrumbPage>\n </BreadcrumbItem>\n </BreadcrumbList>\n </BreadcrumbRoot>\n )\n}\n\nexport {\n BreadcrumbRoot,\n BreadcrumbList,\n BreadcrumbItem,\n BreadcrumbLink,\n BreadcrumbPage,\n BreadcrumbSeparator,\n BreadcrumbEllipsis,\n NavigationBreadcrumb,\n PagesBreadcrumb,\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Breadcrumb.js","sources":["../../../src/components/Breadcrumb/Breadcrumb.tsx"],"sourcesContent":["import { CaretRight } from '@phosphor-icons/react/dist/ssr/CaretRight'\nimport { DotsThree } from '@phosphor-icons/react/dist/ssr/DotsThree'\nimport { Slot } from '@radix-ui/react-slot'\nimport * as React from 'react'\n\nimport { Typography } from '../Typography'\n\nimport { cn } from '@/lib/utils'\n\n/**\n * Root container for the breadcrumb navigation.\n * Provides the overall context and ARIA labeling.\n */\nconst BreadcrumbRoot = React.forwardRef<\n HTMLElement,\n React.ComponentPropsWithoutRef<'nav'> & {\n /** Custom separator element to use between breadcrumb items */\n separator?: React.ReactNode\n }\n>(({ ...props }, ref) => <nav ref={ref} aria-label=\"breadcrumb\" {...props} />)\nBreadcrumbRoot.displayName = 'BreadcrumbRoot'\n\n/**\n * Container for breadcrumb items.\n * Handles layout and spacing of the breadcrumb navigation.\n */\nconst BreadcrumbList = React.forwardRef<HTMLOListElement, React.ComponentPropsWithoutRef<'ol'>>(\n ({ className, ...props }, ref) => (\n <ol\n ref={ref}\n className={cn(\n 'text-muted-foreground flex flex-wrap items-center gap-1.5 text-sm break-words sm:gap-2.5',\n className,\n )}\n {...props}\n />\n ),\n)\nBreadcrumbList.displayName = 'BreadcrumbList'\n\n/**\n * Individual breadcrumb item container.\n * Wraps a link or the current page indicator.\n */\nconst BreadcrumbItem = React.forwardRef<HTMLLIElement, React.ComponentPropsWithoutRef<'li'>>(\n ({ className, ...props }, ref) => (\n <li ref={ref} className={cn('inline-flex items-center gap-1.5', className)} {...props} />\n ),\n)\nBreadcrumbItem.displayName = 'BreadcrumbItem'\n\n/** Text transform options for breadcrumb links */\ntype TextTransformOption = 'capitalize' | 'capitalize-first' | 'uppercase' | 'none'\n\n/** Get class names for text transform styling */\nconst getTextTransformClass = (transform: TextTransformOption): string => {\n switch (transform) {\n case 'capitalize-first':\n return '[&]:has-[::first-letter]:uppercase'\n case 'capitalize':\n return 'capitalize'\n case 'uppercase':\n return 'uppercase'\n default:\n return ''\n }\n}\n\n/**\n * Interactive link element for breadcrumb navigation.\n * Can be rendered as a custom element using asChild.\n */\nconst BreadcrumbLink = React.forwardRef<\n HTMLAnchorElement,\n React.ComponentPropsWithoutRef<'a'> & {\n /** When true, the component will render its children directly instead of wrapping them in an anchor tag */\n asChild?: boolean\n /** The text transformation to apply to the link text */\n textTransform?: TextTransformOption\n }\n>(({ asChild, className, textTransform = 'capitalize-first', children, ...props }, ref) => {\n const Comp = asChild ? Slot : 'a'\n\n // Simplify the capitalization logic using a direct string transformation\n const content =\n textTransform === 'capitalize-first' && typeof children === 'string'\n ? children.charAt(0).toUpperCase() + children.slice(1)\n : children\n\n return (\n <Typography variant=\"title-sm\" weight={'medium'}>\n <Comp\n ref={ref}\n className={cn(\n 'text-neutral-500 transition-colors hover:text-neutral-950',\n textTransform !== 'capitalize-first' && getTextTransformClass(textTransform),\n className,\n )}\n {...props}\n >\n {content}\n </Comp>\n </Typography>\n )\n})\nBreadcrumbLink.displayName = 'BreadcrumbLink'\n\n/**\n * Current page indicator in the breadcrumb.\n * Non-interactive element showing the current location.\n */\nconst BreadcrumbPage = React.forwardRef<\n HTMLSpanElement,\n React.ComponentPropsWithoutRef<'span'> & {\n textTransform?: TextTransformOption\n }\n>(({ className, textTransform = 'capitalize-first', children, ...props }, ref) => {\n const content =\n textTransform === 'capitalize-first' && typeof children === 'string'\n ? children.charAt(0).toUpperCase() + children.slice(1)\n : children\n\n return (\n <Typography variant=\"title-sm\">\n <span\n ref={ref}\n aria-disabled=\"true\"\n aria-current=\"page\"\n className={cn(\n 'font-medium text-neutral-950',\n textTransform !== 'capitalize-first' && getTextTransformClass(textTransform),\n className,\n )}\n {...props}\n >\n {content}\n </span>\n </Typography>\n )\n})\nBreadcrumbPage.displayName = 'BreadcrumbPage'\n\n/**\n * Separator element between breadcrumb items.\n * Can be customized with different icons or characters.\n */\nconst BreadcrumbSeparator = ({ children, className, ...props }: React.ComponentProps<'span'>) => (\n <span aria-hidden=\"true\" className={cn('text-neutral-500 [&>svg]:size-3.5', className)} {...props}>\n {children ?? <CaretRight />}\n </span>\n)\nBreadcrumbSeparator.displayName = 'BreadcrumbSeparator'\n\n/**\n * Ellipsis indicator for truncated breadcrumb paths.\n * Used to show that there are hidden items in the path.\n */\nconst BreadcrumbEllipsis = ({ className, ...props }: React.ComponentProps<'span'>) => (\n <span aria-hidden=\"true\" className={cn('flex h-9 w-9 items-center justify-center', className)} {...props}>\n <DotsThree className=\"h-4 w-4\" />\n <span className=\"sr-only\">More</span>\n </span>\n)\nBreadcrumbEllipsis.displayName = 'BreadcrumbEllipsis'\n\n/**\n * Sanitizes a route string by replacing hyphens with spaces.\n * @param route - The route string to sanitize.\n * @returns The sanitized route string.\n */\nconst sanitizeRoute = (route: string) => {\n return route.replace(/-/g, ' ')\n}\n\n/**\n * Transforms a kebab-case route to a camelCase translation key\n * @param route - The route segment in kebab-case\n * @returns The translation key in camelCase\n */\nconst routeToTranslationKey = (route: string): string => {\n return route\n .split('-')\n .map((word, index) => (index === 0 ? word : word.charAt(0).toUpperCase() + word.slice(1)))\n .join('')\n}\n\n/**\n * Gets the routes for the breadcrumb navigation.\n * @param pathname - The current pathname.\n * @param pathMappings - Optional object containing custom path mappings.\n * @param translation - Optional translation function.\n * @param basePath - Optional base path to strip from pathname and use as home route.\n * @returns The routes for the breadcrumb navigation.\n */\nconst getRoutes = (\n pathname: string,\n pathMappings?: Record<string, string | null>,\n translation?: (key: string) => string,\n basePath?: string,\n) => {\n // Strip the base path from pathname if it exists\n let processedPathname = pathname\n if (basePath && pathname.startsWith(basePath)) {\n processedPathname = pathname.slice(basePath.length)\n // Ensure we don't start with a slash after stripping\n if (processedPathname.startsWith('/')) {\n processedPathname = processedPathname.slice(1)\n }\n }\n\n const baseRoutes = processedPathname.split('/').filter(Boolean)\n\n const routes = baseRoutes.map((route, index) => {\n if (pathMappings && route in pathMappings && pathMappings[route] === null) {\n return null\n }\n\n let displayName = route\n\n // Check if there's a custom mapping for this route\n if (pathMappings && pathMappings[route] != null) {\n displayName = pathMappings[route]\n }\n // If there's a translation function, convert route to translation key\n else if (translation) {\n const translationKey = routeToTranslationKey(route)\n displayName = translation(translationKey)\n }\n // If no mapping or translation function, sanitize the route\n else {\n displayName = sanitizeRoute(route)\n }\n\n const routeSegments = baseRoutes.slice(0, index + 1)\n const routePath = routeSegments.join('/')\n const fullHref = basePath ? `${basePath}/${routePath}` : `/${routePath}`\n\n return {\n name: displayName,\n href: fullHref,\n }\n })\n\n // Handle home translation — hide if mapped to null\n const homeKey = 'home'\n if (!(pathMappings && homeKey in pathMappings && pathMappings[homeKey] === null)) {\n const homeHref = basePath ?? '/'\n routes.unshift({\n name: pathMappings?.[homeKey] ?? translation?.(homeKey) ?? 'Home',\n href: homeHref,\n })\n }\n\n return routes.filter(Boolean) as Array<{ name: string; href: string }>\n}\n\n/**\n * Navigation breadcrumb component.\n * Displays a breadcrumb navigation for the current path.\n * @param pathname - The current pathname\n * @param pathMappings - Optional object containing custom path mappings\n * @param translation - Optional translation function\n * @param basePath - Optional base path to strip from pathname and use as home route\n * @param textTransform - Optional text transformation to apply to breadcrumb text\n */\nconst NavigationBreadcrumb = ({\n pathname,\n pathMappings,\n translation,\n basePath,\n textTransform,\n endSlash = true,\n}: {\n pathname: string\n pathMappings?: Record<string, string | null>\n translation?: (key: string) => string\n basePath?: string\n textTransform?: TextTransformOption\n endSlash?: boolean\n}) => {\n return (\n <BreadcrumbRoot>\n <BreadcrumbList>\n {getRoutes(pathname, pathMappings, translation, basePath).map((route, index, array) => (\n <React.Fragment key={index}>\n <BreadcrumbItem>\n {index === array.length - 1 ? (\n <BreadcrumbPage textTransform={textTransform}>{route.name}</BreadcrumbPage>\n ) : (\n <BreadcrumbLink href={route.href + (endSlash ? '/' : '')} textTransform={textTransform}>\n {route.name}\n </BreadcrumbLink>\n )}\n </BreadcrumbItem>\n {index < array.length - 1 && <BreadcrumbSeparator />}\n </React.Fragment>\n ))}\n </BreadcrumbList>\n </BreadcrumbRoot>\n )\n}\n\nconst PagesBreadcrumb = ({\n pages,\n currentPage,\n}: {\n pages: Array<{ link: string; text: string }>\n currentPage: string\n}) => {\n return (\n <BreadcrumbRoot>\n <BreadcrumbList>\n {pages.map((page) => (\n <BreadcrumbItem key={pages.indexOf(page)}>\n <BreadcrumbLink href={page.link}>{page.text}</BreadcrumbLink>\n <BreadcrumbSeparator />\n </BreadcrumbItem>\n ))}\n <BreadcrumbItem>\n <BreadcrumbPage>{currentPage}</BreadcrumbPage>\n </BreadcrumbItem>\n </BreadcrumbList>\n </BreadcrumbRoot>\n )\n}\n\nexport {\n BreadcrumbRoot,\n BreadcrumbList,\n BreadcrumbItem,\n BreadcrumbLink,\n BreadcrumbPage,\n BreadcrumbSeparator,\n BreadcrumbEllipsis,\n NavigationBreadcrumb,\n PagesBreadcrumb,\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
2
|
-
import { SpinnerGap } from '@phosphor-icons/react/dist/ssr';
|
|
2
|
+
import { SpinnerGap } from '@phosphor-icons/react/dist/ssr/SpinnerGap';
|
|
3
3
|
import { cva } from 'class-variance-authority';
|
|
4
4
|
import * as React from 'react';
|
|
5
5
|
import { cn } from '../../lib/utils.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Button.js","sources":["../../../src/components/Button/Button.tsx"],"sourcesContent":["import { Icon, IconWeight, IconProps as PhosphorIconProps } from '@phosphor-icons/react'\nimport { SpinnerGap } from '@phosphor-icons/react/dist/ssr'\nimport { cva, type VariantProps } from 'class-variance-authority'\nimport * as React from 'react'\n\nimport { cn } from '../../lib/utils'\nimport { typographyVariants } from '../Typography'\n\nconst buttonVariants = cva(\n 'inline-flex items-center justify-center gap-2 rounded-md font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50',\n {\n variants: {\n /**\n * Defines the visual style of the button\n */\n variant: {\n primary:\n 'bg-primary-500 text-primary-foreground hover:bg-primary-700 active:bg-primary-900 disabled:bg-background-200',\n secondary:\n 'bg-neutral-950 text-neutral-foreground hover:bg-neutral-800 active:bg-neutral-700 disabled:bg-neutral-200 disabled:text-neutral-600',\n ghost:\n 'border border-neutral-500 text-primary-foreground hover:bg-neutral-100/50 active:bg-neutral-200/50 disabled:border-neutral-500 disabled:text-neutral-500',\n 'inverse-ghost':\n 'border border-neutral-50 text-neutral-50 hover:bg-neutral/50 hover:border-neutral-50 active:bg-neutral-600/50 disabled:border-neutral-300 disabled:text-neutral-300',\n text: 'hover:bg-neutral-50 active:bg-neutral-100 text-primary-foreground disabled:text-neutral-500',\n error:\n 'bg-error text-white hover:bg-error-800 active:bg-error-900 disabled:bg-error-200 disabled:text-neutral-600',\n success:\n 'bg-success text-white hover:bg-success-800 active:bg-success-900 disabled:bg-success-200 disabled:text-neutral-600',\n input:\n 'border border-neutral-200 bg-white text-neutral-950 hover:bg-neutral-50 active:bg-neutral-100 focus-visible:border-neutral-950 disabled:bg-neutral-50 focus-visible:ring-0',\n },\n /**\n * Controls the size and padding of the button\n */\n size: {\n sm: 'h-8 px-3 text-sm',\n md: 'h-10 px-4 text-sm',\n lg: 'h-12 px-6 text-base',\n },\n },\n compoundVariants: [\n {\n variant: 'input',\n size: ['sm', 'md', 'lg'],\n className: typographyVariants({ variant: 'body-lg' }),\n },\n ],\n defaultVariants: {\n variant: 'primary',\n size: 'md',\n },\n },\n)\n\nexport type ButtonProps = {\n /**\n * The visual style of the button.\n * @default primary\n */\n variant?: 'primary' | 'secondary' | 'ghost' | 'inverse-ghost' | 'text' | 'error' | 'success'\n\n /**\n * The size of the button, affecting height, padding, and font size.\n * @default md\n */\n size?: 'sm' | 'md' | 'lg'\n\n /**\n * Icon component to display at the start of the button content.\n * Use Phosphor icons for consistent styling.\n * @example <Button StartIcon={House}>Home</Button>\n */\n StartIcon?: Icon\n\n /**\n * Icon component to display at the end of the button content.\n * Use Phosphor icons for consistent styling.\n * @example <Button EndIcon={ArrowRight}>Next</Button>\n */\n EndIcon?: Icon\n\n /**\n * When true, displays a loading spinner and disables the button.\n * The spinner replaces the StartIcon if present.\n * @default false\n */\n loading?: boolean\n\n /**\n * When true, creates a circular button with only the StartIcon visible.\n * @default false\n */\n iconOnly?: boolean\n\n /**\n * The content to display inside the button.\n * Not displayed when iconOnly is true.\n */\n children?: React.ReactNode\n\n /**\n * Custom props to pass to the icons (StartIcon, EndIcon, SpinnerGap).\n * Allows overriding size, weight, color, etc.\n */\n iconProps?: Partial<PhosphorIconProps>\n} & React.ButtonHTMLAttributes<HTMLButtonElement> &\n VariantProps<typeof buttonVariants>\n\n/**\n * A versatile button component that supports multiple variants, sizes, and icon placements.\n *\n * @example\n * // Basic usage\n * <Button>Click me</Button>\n *\n * // With icon\n * <Button StartIcon={House}>Home</Button>\n *\n * // Icon only button\n * <Button StartIcon={Plus} iconOnly aria-label=\"Add item\" />\n *\n * // Loading state\n * <Button loading>Processing...</Button>\n */\nconst Button = React.forwardRef<HTMLButtonElement, ButtonProps>(\n (\n { className, variant = 'primary', size = 'md', StartIcon, EndIcon, loading, iconOnly, iconProps = {}, ...props },\n ref,\n ) => {\n const defaultIconProps = (): { size: number; weight: IconWeight } => {\n switch (size) {\n case 'sm':\n return { size: 16, weight: 'regular' }\n case 'lg':\n return { size: 20, weight: 'regular' }\n default:\n return { size: 18, weight: 'regular' }\n }\n }\n const mergedIconProps = { ...defaultIconProps(), ...iconProps }\n const getIconOnlyClasses = () => {\n switch (size) {\n case 'sm':\n return 'h-8 w-8'\n case 'lg':\n return 'h-12 w-12'\n default:\n return 'h-10 w-10'\n }\n }\n\n return (\n <button\n className={cn(\n buttonVariants({ variant, size, className }),\n iconOnly && 'rounded-full p-0',\n iconOnly && getIconOnlyClasses(),\n className,\n )}\n ref={ref}\n disabled={loading}\n {...props}\n >\n {loading && <SpinnerGap {...defaultIconProps()} className=\"animate-spin\" aria-label=\"Loading\" />}\n {StartIcon && !loading && <StartIcon {...mergedIconProps} className=\"shrink-0\" />}\n {iconOnly ? <span className=\"sr-only\">{props.children}</span> : props.children}\n {EndIcon && !iconOnly && <EndIcon {...mergedIconProps} className=\"shrink-0\" />}\n </button>\n )\n },\n)\nButton.displayName = 'Button'\n\nexport { Button, buttonVariants }\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Button.js","sources":["../../../src/components/Button/Button.tsx"],"sourcesContent":["import { Icon, IconWeight, IconProps as PhosphorIconProps } from '@phosphor-icons/react'\nimport { SpinnerGap } from '@phosphor-icons/react/dist/ssr/SpinnerGap'\nimport { cva, type VariantProps } from 'class-variance-authority'\nimport * as React from 'react'\n\nimport { cn } from '../../lib/utils'\nimport { typographyVariants } from '../Typography'\n\nconst buttonVariants = cva(\n 'inline-flex items-center justify-center gap-2 rounded-md font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50',\n {\n variants: {\n /**\n * Defines the visual style of the button\n */\n variant: {\n primary:\n 'bg-primary-500 text-primary-foreground hover:bg-primary-700 active:bg-primary-900 disabled:bg-background-200',\n secondary:\n 'bg-neutral-950 text-neutral-foreground hover:bg-neutral-800 active:bg-neutral-700 disabled:bg-neutral-200 disabled:text-neutral-600',\n ghost:\n 'border border-neutral-500 text-primary-foreground hover:bg-neutral-100/50 active:bg-neutral-200/50 disabled:border-neutral-500 disabled:text-neutral-500',\n 'inverse-ghost':\n 'border border-neutral-50 text-neutral-50 hover:bg-neutral/50 hover:border-neutral-50 active:bg-neutral-600/50 disabled:border-neutral-300 disabled:text-neutral-300',\n text: 'hover:bg-neutral-50 active:bg-neutral-100 text-primary-foreground disabled:text-neutral-500',\n error:\n 'bg-error text-white hover:bg-error-800 active:bg-error-900 disabled:bg-error-200 disabled:text-neutral-600',\n success:\n 'bg-success text-white hover:bg-success-800 active:bg-success-900 disabled:bg-success-200 disabled:text-neutral-600',\n input:\n 'border border-neutral-200 bg-white text-neutral-950 hover:bg-neutral-50 active:bg-neutral-100 focus-visible:border-neutral-950 disabled:bg-neutral-50 focus-visible:ring-0',\n },\n /**\n * Controls the size and padding of the button\n */\n size: {\n sm: 'h-8 px-3 text-sm',\n md: 'h-10 px-4 text-sm',\n lg: 'h-12 px-6 text-base',\n },\n },\n compoundVariants: [\n {\n variant: 'input',\n size: ['sm', 'md', 'lg'],\n className: typographyVariants({ variant: 'body-lg' }),\n },\n ],\n defaultVariants: {\n variant: 'primary',\n size: 'md',\n },\n },\n)\n\nexport type ButtonProps = {\n /**\n * The visual style of the button.\n * @default primary\n */\n variant?: 'primary' | 'secondary' | 'ghost' | 'inverse-ghost' | 'text' | 'error' | 'success'\n\n /**\n * The size of the button, affecting height, padding, and font size.\n * @default md\n */\n size?: 'sm' | 'md' | 'lg'\n\n /**\n * Icon component to display at the start of the button content.\n * Use Phosphor icons for consistent styling.\n * @example <Button StartIcon={House}>Home</Button>\n */\n StartIcon?: Icon\n\n /**\n * Icon component to display at the end of the button content.\n * Use Phosphor icons for consistent styling.\n * @example <Button EndIcon={ArrowRight}>Next</Button>\n */\n EndIcon?: Icon\n\n /**\n * When true, displays a loading spinner and disables the button.\n * The spinner replaces the StartIcon if present.\n * @default false\n */\n loading?: boolean\n\n /**\n * When true, creates a circular button with only the StartIcon visible.\n * @default false\n */\n iconOnly?: boolean\n\n /**\n * The content to display inside the button.\n * Not displayed when iconOnly is true.\n */\n children?: React.ReactNode\n\n /**\n * Custom props to pass to the icons (StartIcon, EndIcon, SpinnerGap).\n * Allows overriding size, weight, color, etc.\n */\n iconProps?: Partial<PhosphorIconProps>\n} & React.ButtonHTMLAttributes<HTMLButtonElement> &\n VariantProps<typeof buttonVariants>\n\n/**\n * A versatile button component that supports multiple variants, sizes, and icon placements.\n *\n * @example\n * // Basic usage\n * <Button>Click me</Button>\n *\n * // With icon\n * <Button StartIcon={House}>Home</Button>\n *\n * // Icon only button\n * <Button StartIcon={Plus} iconOnly aria-label=\"Add item\" />\n *\n * // Loading state\n * <Button loading>Processing...</Button>\n */\nconst Button = React.forwardRef<HTMLButtonElement, ButtonProps>(\n (\n { className, variant = 'primary', size = 'md', StartIcon, EndIcon, loading, iconOnly, iconProps = {}, ...props },\n ref,\n ) => {\n const defaultIconProps = (): { size: number; weight: IconWeight } => {\n switch (size) {\n case 'sm':\n return { size: 16, weight: 'regular' }\n case 'lg':\n return { size: 20, weight: 'regular' }\n default:\n return { size: 18, weight: 'regular' }\n }\n }\n const mergedIconProps = { ...defaultIconProps(), ...iconProps }\n const getIconOnlyClasses = () => {\n switch (size) {\n case 'sm':\n return 'h-8 w-8'\n case 'lg':\n return 'h-12 w-12'\n default:\n return 'h-10 w-10'\n }\n }\n\n return (\n <button\n className={cn(\n buttonVariants({ variant, size, className }),\n iconOnly && 'rounded-full p-0',\n iconOnly && getIconOnlyClasses(),\n className,\n )}\n ref={ref}\n disabled={loading}\n {...props}\n >\n {loading && <SpinnerGap {...defaultIconProps()} className=\"animate-spin\" aria-label=\"Loading\" />}\n {StartIcon && !loading && <StartIcon {...mergedIconProps} className=\"shrink-0\" />}\n {iconOnly ? <span className=\"sr-only\">{props.children}</span> : props.children}\n {EndIcon && !iconOnly && <EndIcon {...mergedIconProps} className=\"shrink-0\" />}\n </button>\n )\n },\n)\nButton.displayName = 'Button'\n\nexport { Button, buttonVariants }\n"],"names":[],"mappings":"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"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
3
|
-
import { CaretLeft
|
|
3
|
+
import { CaretLeft } from '@phosphor-icons/react/dist/ssr/CaretLeft';
|
|
4
|
+
import { CaretRight } from '@phosphor-icons/react/dist/ssr/CaretRight';
|
|
4
5
|
import { differenceInCalendarDays } from 'date-fns';
|
|
5
6
|
import * as React from 'react';
|
|
6
7
|
import { DayPicker, useDayPicker, labelPrevious, labelNext } from 'react-day-picker';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Calendar.js","sources":["../../../src/components/Calendar/Calendar.tsx"],"sourcesContent":["'use client'\n\nimport { CaretLeft, CaretRight } from '@phosphor-icons/react'\nimport { differenceInCalendarDays } from 'date-fns'\nimport * as React from 'react'\nimport { DayPicker, labelNext, labelPrevious, useDayPicker, type DayPickerProps } from 'react-day-picker'\n\nimport { Button, buttonVariants } from '../Button'\n\nimport { cn } from '@/lib/utils'\n\nexport type CalendarProps = DayPickerProps & {\n /**\n * In the year view, the number of years to display at once.\n * @default 12\n */\n yearRange?: number\n\n /**\n * Wether to show the year switcher in the caption.\n * @default true\n */\n showYearSwitcher?: boolean\n\n monthsClassName?: string\n monthCaptionClassName?: string\n weekdaysClassName?: string\n weekdayClassName?: string\n monthClassName?: string\n captionClassName?: string\n captionLabelClassName?: string\n buttonNextClassName?: string\n buttonPreviousClassName?: string\n navClassName?: string\n monthGridClassName?: string\n weekClassName?: string\n dayClassName?: string\n dayButtonClassName?: string\n rangeStartClassName?: string\n rangeEndClassName?: string\n selectedClassName?: string\n todayClassName?: string\n outsideClassName?: string\n disabledClassName?: string\n rangeMiddleClassName?: string\n hiddenClassName?: string\n}\n\n/**\n * A custom calendar component built on top of react-day-picker.\n * @param props The props for the calendar.\n * @default yearRange 12\n * @returns\n */\nfunction Calendar({\n className,\n showOutsideDays = true,\n showYearSwitcher = true,\n yearRange = 12,\n numberOfMonths,\n ...props\n}: CalendarProps) {\n const [navView, setNavView] = React.useState<'days' | 'years'>('days')\n const [displayYears, setDisplayYears] = React.useState<{\n from: number\n to: number\n }>(\n React.useMemo(() => {\n const currentYear = new Date().getFullYear()\n return {\n from: currentYear - Math.floor(yearRange / 2 - 1),\n to: currentYear + Math.ceil(yearRange / 2),\n }\n }, [yearRange]),\n )\n\n const { onNextClick, onPrevClick, startMonth, endMonth } = props\n\n const columnsDisplayed = navView === 'years' ? 1 : numberOfMonths\n\n const _monthsClassName = cn('relative flex', props.monthsClassName)\n const _monthCaptionClassName = cn('relative mx-10 flex h-7 items-center justify-center', props.monthCaptionClassName)\n const _weekdaysClassName = cn('flex flex-row', props.weekdaysClassName)\n const _weekdayClassName = cn('w-8 text-sm font-normal text-muted-foreground', props.weekdayClassName)\n const _monthClassName = cn('w-full', props.monthClassName)\n const _captionClassName = cn('relative flex items-center justify-center pt-1', props.captionClassName)\n const _captionLabelClassName = cn('truncate text-sm font-medium', props.captionLabelClassName)\n const buttonNavClassName = buttonVariants({\n variant: 'text',\n className: 'absolute h-7 w-7 bg-transparent p-0 opacity-50 hover:opacity-100',\n })\n const _buttonNextClassName = cn(buttonNavClassName, 'right-0', props.buttonNextClassName)\n const _buttonPreviousClassName = cn(buttonNavClassName, 'left-0', props.buttonPreviousClassName)\n const _navClassName = cn('flex items-start', props.navClassName)\n const _monthGridClassName = cn('mx-auto mt-4', props.monthGridClassName)\n const _weekClassName = cn('mt-2 flex w-max items-start', props.weekClassName)\n const _dayClassName = cn('flex size-8 flex-1 items-center justify-center p-0 text-sm', props.dayClassName)\n const _dayButtonClassName = cn(\n buttonVariants({ variant: 'text' }),\n 'size-8 rounded-md p-0 font-normal transition-none aria-selected:opacity-100',\n props.dayButtonClassName,\n )\n const buttonRangeClassName =\n 'bg-primary [&>button]:bg-primary [&>button]:text-primary-foreground [&>button]:hover:bg-primary [&>button]:hover:text-primary-foreground'\n const _rangeStartClassName = cn(buttonRangeClassName, 'day-range-start rounded-s-md', props.rangeStartClassName)\n const _rangeEndClassName = cn(buttonRangeClassName, 'day-range-end rounded-e-md', props.rangeEndClassName)\n const _rangeMiddleClassName = cn(\n 'bg-background-300 !text-foreground [&>button]:bg-transparent [&>button]:!text-foreground [&>button]:hover:bg-transparent [&>button]:hover:!text-foreground',\n props.rangeMiddleClassName,\n )\n const _selectedClassName = cn(\n '[&>button]:bg-primary [&>button]:text-primary-foreground [&>button]:hover:bg-primary [&>button]:hover:text-primary-foreground',\n props.selectedClassName,\n )\n const _todayClassName = cn(\n '[&>button]:bg-background-200 [&>button]:hover:bg-background-200 [&>button]:text-primary-foreground',\n props.todayClassName,\n )\n const _outsideClassName = cn(\n 'day-outside text-muted-foreground opacity-50 aria-selected:text-muted-foreground',\n props.outsideClassName,\n )\n const _disabledClassName = cn('text-muted-foreground opacity-50', props.disabledClassName)\n const _hiddenClassName = cn('invisible flex-1', props.hiddenClassName)\n\n return (\n <DayPicker\n showOutsideDays={showOutsideDays}\n className={cn('rounded-md border p-3 transition-colors', className)}\n id=\"calendar\"\n style={{\n width: `${248.8 * (columnsDisplayed ?? 1)}px`,\n }}\n classNames={{\n months: _monthsClassName,\n month_caption: _monthCaptionClassName,\n weekdays: _weekdaysClassName,\n weekday: _weekdayClassName,\n month: _monthClassName,\n caption: _captionClassName,\n caption_label: _captionLabelClassName,\n button_next: _buttonNextClassName,\n button_previous: _buttonPreviousClassName,\n nav: _navClassName,\n month_grid: _monthGridClassName,\n week: _weekClassName,\n day: _dayClassName,\n day_button: _dayButtonClassName,\n range_start: _rangeStartClassName,\n range_middle: _rangeMiddleClassName,\n range_end: _rangeEndClassName,\n selected: _selectedClassName,\n today: _todayClassName,\n outside: _outsideClassName,\n disabled: _disabledClassName,\n hidden: _hiddenClassName,\n }}\n components={{\n Chevron: ({ orientation }) => {\n const Icon = orientation === 'left' ? CaretLeft : CaretRight\n return <Icon className=\"h-4 w-4\" />\n },\n Nav: ({ className }) => {\n const { nextMonth, previousMonth, goToMonth } = useDayPicker()\n\n const isPreviousDisabled = (() => {\n if (navView === 'years') {\n return (\n (startMonth && differenceInCalendarDays(new Date(displayYears.from - 1, 0, 1), startMonth) < 0) ??\n (endMonth && differenceInCalendarDays(new Date(displayYears.from - 1, 0, 1), endMonth) > 0)\n )\n }\n return !previousMonth\n })()\n\n const isNextDisabled = (() => {\n if (navView === 'years') {\n return (\n (startMonth && differenceInCalendarDays(new Date(displayYears.to + 1, 0, 1), startMonth) < 0) ??\n (endMonth && differenceInCalendarDays(new Date(displayYears.to + 1, 0, 1), endMonth) > 0)\n )\n }\n return !nextMonth\n })()\n\n const handlePreviousClick = React.useCallback(() => {\n if (!previousMonth) return\n if (navView === 'years') {\n setDisplayYears((prev) => ({\n from: prev.from - (prev.to - prev.from + 1),\n to: prev.to - (prev.to - prev.from + 1),\n }))\n onPrevClick?.(new Date(displayYears.from - (displayYears.to - displayYears.from), 0, 1))\n return\n }\n goToMonth(previousMonth)\n onPrevClick?.(previousMonth)\n }, [previousMonth, goToMonth])\n\n const handleNextClick = React.useCallback(() => {\n if (!nextMonth) return\n if (navView === 'years') {\n setDisplayYears((prev) => ({\n from: prev.from + (prev.to - prev.from + 1),\n to: prev.to + (prev.to - prev.from + 1),\n }))\n onNextClick?.(new Date(displayYears.from + (displayYears.to - displayYears.from), 0, 1))\n return\n }\n goToMonth(nextMonth)\n onNextClick?.(nextMonth)\n }, [goToMonth, nextMonth])\n return (\n <nav className={cn('flex items-center', className)}>\n <Button\n variant=\"text\"\n className=\"absolute left-0 h-7 w-7 bg-transparent p-0 opacity-80 hover:opacity-100\"\n type=\"button\"\n tabIndex={isPreviousDisabled ? undefined : -1}\n disabled={isPreviousDisabled}\n aria-label={\n navView === 'years'\n ? `Go to the previous ${displayYears.to - displayYears.from + 1} years`\n : labelPrevious(previousMonth)\n }\n onClick={handlePreviousClick}\n >\n <CaretLeft className=\"h-4 w-4\" />\n </Button>\n\n <Button\n variant=\"text\"\n className=\"absolute right-0 h-7 w-7 bg-transparent p-0 opacity-80 hover:opacity-100\"\n type=\"button\"\n tabIndex={isNextDisabled ? undefined : -1}\n disabled={isNextDisabled}\n aria-label={\n navView === 'years'\n ? `Go to the next ${displayYears.to - displayYears.from + 1} years`\n : labelNext(nextMonth)\n }\n onClick={handleNextClick}\n >\n <CaretRight className=\"h-4 w-4\" />\n </Button>\n </nav>\n )\n },\n CaptionLabel: ({ children, ...props }) => {\n if (!showYearSwitcher) return <span {...props}>{children}</span>\n return (\n <Button\n className=\"h-7 w-full truncate text-sm font-medium\"\n variant=\"text\"\n size=\"sm\"\n onClick={() => setNavView((prev) => (prev === 'days' ? 'years' : 'days'))}\n >\n {navView === 'days' ? children : `${displayYears.from} - ${displayYears.to}`}\n </Button>\n )\n },\n MonthGrid: ({ className, children, ...props }) => {\n const { goToMonth, selected } = useDayPicker()\n if (navView === 'years') {\n return (\n <div className={cn('grid grid-cols-4 gap-y-2', className)} {...props}>\n {Array.from({ length: displayYears.to - displayYears.from + 1 }, (_noUsed, index) => {\n const isBefore =\n differenceInCalendarDays(new Date(displayYears.from + index, 11, 31), startMonth!) < 0\n\n const isAfter = differenceInCalendarDays(new Date(displayYears.from + index, 0, 0), endMonth!) > 0\n\n const isDisabled = isBefore || isAfter\n return (\n <Button\n key={index}\n className={cn(\n 'text-foreground h-7 w-full text-sm font-normal',\n displayYears.from + index === new Date().getFullYear() &&\n 'bg-primary text-primary-foreground font-medium',\n )}\n variant=\"text\"\n onClick={() => {\n setNavView('days')\n goToMonth(new Date(displayYears.from + index, (selected as Date | undefined)?.getMonth() ?? 0))\n }}\n disabled={isDisabled}\n >\n {displayYears.from + index}\n </Button>\n )\n })}\n </div>\n )\n }\n return (\n <table className={className} {...props}>\n {children}\n </table>\n )\n },\n }}\n numberOfMonths={columnsDisplayed}\n {...props}\n />\n )\n}\nCalendar.displayName = 'Calendar'\n\nexport { Calendar }\n"],"names":[],"mappings":";;;;;;;;;AAsDA;AAAkB;AAChB;AACkB;AACC;AACP;AACZ;AAEF;AACE;AACA;AAA8C;AAK1C;AACA;AAAO;AAC2C;AACP;AAC3C;AACY;AAGhB;AAEA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAA0C;AAC/B;AACE;AAEb;AACA;AACA;AACA;AACA;AACA;AACA;AAA4B;AACQ;AAClC;AACM;AAER;AAEA;AACA;AACA;AAA8B;AAC5B;AACM;AAER;AAA2B;AACzB;AACM;AAER;AAAwB;AACtB;AACM;AAER;AAA0B;AACxB;AACM;AAER;AACA;AAEA;AACE;AAAC;AAAA;AACC;AACkE;AAC/D;AACI;AACoC;AAC3C;AACY;AACF;AACO;AACL;AACD;AACF;AACE;AACM;AACF;AACI;AACZ;AACO;AACN;AACD;AACO;AACC;AACC;AACH;AACD;AACH;AACE;AACC;AACF;AACV;AACY;AAER;AACA;AAAiC;AACnC;AAEE;AAEA;AACE;AACE;AAE2F;AAG7F;AAAQ;AAGV;AACE;AACE;AAEyF;AAG3F;AAAQ;AAGV;AACE;AACA;AACE;AAA2B;AACgB;AACJ;AAEvC;AACA;AAAA;AAEF;AACA;AAA2B;AAG7B;AACE;AACA;AACE;AAA2B;AACgB;AACJ;AAEvC;AACA;AAAA;AAEF;AACA;AAAuB;AAEzB;AAEI;AAAA;AAAC;AAAA;AACS;AACE;AACL;AACsC;AACjC;AAIuB;AAExB;AAEsB;AAAA;AACjC;AAEA;AAAC;AAAA;AACS;AACE;AACL;AACkC;AAC7B;AAIe;AAEhB;AAEuB;AAAA;AAClC;AACF;AAEJ;AAEE;AACA;AACE;AAAC;AAAA;AACW;AACF;AACH;AACmE;AAEE;AAAA;AAC5E;AAEJ;AAEE;AACA;AACE;AAGM;AAGA;AAEA;AACA;AACE;AAAC;AAAA;AAEY;AACT;AAEE;AACJ;AACQ;AAEN;AACA;AAA8F;AAChG;AACU;AAEW;AAAA;AAbhB;AAcP;AAGN;AAGJ;AAGE;AAEJ;AACF;AACgB;AACZ;AAAA;AAGV;AACA;;"}
|
|
1
|
+
{"version":3,"file":"Calendar.js","sources":["../../../src/components/Calendar/Calendar.tsx"],"sourcesContent":["'use client'\n\nimport { CaretLeft } from '@phosphor-icons/react/dist/ssr/CaretLeft'\nimport { CaretRight } from '@phosphor-icons/react/dist/ssr/CaretRight'\nimport { differenceInCalendarDays } from 'date-fns'\nimport * as React from 'react'\nimport { DayPicker, labelNext, labelPrevious, useDayPicker, type DayPickerProps } from 'react-day-picker'\n\nimport { Button, buttonVariants } from '../Button'\n\nimport { cn } from '@/lib/utils'\n\nexport type CalendarProps = DayPickerProps & {\n /**\n * In the year view, the number of years to display at once.\n * @default 12\n */\n yearRange?: number\n\n /**\n * Wether to show the year switcher in the caption.\n * @default true\n */\n showYearSwitcher?: boolean\n\n monthsClassName?: string\n monthCaptionClassName?: string\n weekdaysClassName?: string\n weekdayClassName?: string\n monthClassName?: string\n captionClassName?: string\n captionLabelClassName?: string\n buttonNextClassName?: string\n buttonPreviousClassName?: string\n navClassName?: string\n monthGridClassName?: string\n weekClassName?: string\n dayClassName?: string\n dayButtonClassName?: string\n rangeStartClassName?: string\n rangeEndClassName?: string\n selectedClassName?: string\n todayClassName?: string\n outsideClassName?: string\n disabledClassName?: string\n rangeMiddleClassName?: string\n hiddenClassName?: string\n}\n\n/**\n * A custom calendar component built on top of react-day-picker.\n * @param props The props for the calendar.\n * @default yearRange 12\n * @returns\n */\nfunction Calendar({\n className,\n showOutsideDays = true,\n showYearSwitcher = true,\n yearRange = 12,\n numberOfMonths,\n ...props\n}: CalendarProps) {\n const [navView, setNavView] = React.useState<'days' | 'years'>('days')\n const [displayYears, setDisplayYears] = React.useState<{\n from: number\n to: number\n }>(\n React.useMemo(() => {\n const currentYear = new Date().getFullYear()\n return {\n from: currentYear - Math.floor(yearRange / 2 - 1),\n to: currentYear + Math.ceil(yearRange / 2),\n }\n }, [yearRange]),\n )\n\n const { onNextClick, onPrevClick, startMonth, endMonth } = props\n\n const columnsDisplayed = navView === 'years' ? 1 : numberOfMonths\n\n const _monthsClassName = cn('relative flex', props.monthsClassName)\n const _monthCaptionClassName = cn('relative mx-10 flex h-7 items-center justify-center', props.monthCaptionClassName)\n const _weekdaysClassName = cn('flex flex-row', props.weekdaysClassName)\n const _weekdayClassName = cn('w-8 text-sm font-normal text-muted-foreground', props.weekdayClassName)\n const _monthClassName = cn('w-full', props.monthClassName)\n const _captionClassName = cn('relative flex items-center justify-center pt-1', props.captionClassName)\n const _captionLabelClassName = cn('truncate text-sm font-medium', props.captionLabelClassName)\n const buttonNavClassName = buttonVariants({\n variant: 'text',\n className: 'absolute h-7 w-7 bg-transparent p-0 opacity-50 hover:opacity-100',\n })\n const _buttonNextClassName = cn(buttonNavClassName, 'right-0', props.buttonNextClassName)\n const _buttonPreviousClassName = cn(buttonNavClassName, 'left-0', props.buttonPreviousClassName)\n const _navClassName = cn('flex items-start', props.navClassName)\n const _monthGridClassName = cn('mx-auto mt-4', props.monthGridClassName)\n const _weekClassName = cn('mt-2 flex w-max items-start', props.weekClassName)\n const _dayClassName = cn('flex size-8 flex-1 items-center justify-center p-0 text-sm', props.dayClassName)\n const _dayButtonClassName = cn(\n buttonVariants({ variant: 'text' }),\n 'size-8 rounded-md p-0 font-normal transition-none aria-selected:opacity-100',\n props.dayButtonClassName,\n )\n const buttonRangeClassName =\n 'bg-primary [&>button]:bg-primary [&>button]:text-primary-foreground [&>button]:hover:bg-primary [&>button]:hover:text-primary-foreground'\n const _rangeStartClassName = cn(buttonRangeClassName, 'day-range-start rounded-s-md', props.rangeStartClassName)\n const _rangeEndClassName = cn(buttonRangeClassName, 'day-range-end rounded-e-md', props.rangeEndClassName)\n const _rangeMiddleClassName = cn(\n 'bg-background-300 !text-foreground [&>button]:bg-transparent [&>button]:!text-foreground [&>button]:hover:bg-transparent [&>button]:hover:!text-foreground',\n props.rangeMiddleClassName,\n )\n const _selectedClassName = cn(\n '[&>button]:bg-primary [&>button]:text-primary-foreground [&>button]:hover:bg-primary [&>button]:hover:text-primary-foreground',\n props.selectedClassName,\n )\n const _todayClassName = cn(\n '[&>button]:bg-background-200 [&>button]:hover:bg-background-200 [&>button]:text-primary-foreground',\n props.todayClassName,\n )\n const _outsideClassName = cn(\n 'day-outside text-muted-foreground opacity-50 aria-selected:text-muted-foreground',\n props.outsideClassName,\n )\n const _disabledClassName = cn('text-muted-foreground opacity-50', props.disabledClassName)\n const _hiddenClassName = cn('invisible flex-1', props.hiddenClassName)\n\n return (\n <DayPicker\n showOutsideDays={showOutsideDays}\n className={cn('rounded-md border p-3 transition-colors', className)}\n id=\"calendar\"\n style={{\n width: `${248.8 * (columnsDisplayed ?? 1)}px`,\n }}\n classNames={{\n months: _monthsClassName,\n month_caption: _monthCaptionClassName,\n weekdays: _weekdaysClassName,\n weekday: _weekdayClassName,\n month: _monthClassName,\n caption: _captionClassName,\n caption_label: _captionLabelClassName,\n button_next: _buttonNextClassName,\n button_previous: _buttonPreviousClassName,\n nav: _navClassName,\n month_grid: _monthGridClassName,\n week: _weekClassName,\n day: _dayClassName,\n day_button: _dayButtonClassName,\n range_start: _rangeStartClassName,\n range_middle: _rangeMiddleClassName,\n range_end: _rangeEndClassName,\n selected: _selectedClassName,\n today: _todayClassName,\n outside: _outsideClassName,\n disabled: _disabledClassName,\n hidden: _hiddenClassName,\n }}\n components={{\n Chevron: ({ orientation }) => {\n const Icon = orientation === 'left' ? CaretLeft : CaretRight\n return <Icon className=\"h-4 w-4\" />\n },\n Nav: ({ className }) => {\n const { nextMonth, previousMonth, goToMonth } = useDayPicker()\n\n const isPreviousDisabled = (() => {\n if (navView === 'years') {\n return (\n (startMonth && differenceInCalendarDays(new Date(displayYears.from - 1, 0, 1), startMonth) < 0) ??\n (endMonth && differenceInCalendarDays(new Date(displayYears.from - 1, 0, 1), endMonth) > 0)\n )\n }\n return !previousMonth\n })()\n\n const isNextDisabled = (() => {\n if (navView === 'years') {\n return (\n (startMonth && differenceInCalendarDays(new Date(displayYears.to + 1, 0, 1), startMonth) < 0) ??\n (endMonth && differenceInCalendarDays(new Date(displayYears.to + 1, 0, 1), endMonth) > 0)\n )\n }\n return !nextMonth\n })()\n\n const handlePreviousClick = React.useCallback(() => {\n if (!previousMonth) return\n if (navView === 'years') {\n setDisplayYears((prev) => ({\n from: prev.from - (prev.to - prev.from + 1),\n to: prev.to - (prev.to - prev.from + 1),\n }))\n onPrevClick?.(new Date(displayYears.from - (displayYears.to - displayYears.from), 0, 1))\n return\n }\n goToMonth(previousMonth)\n onPrevClick?.(previousMonth)\n }, [previousMonth, goToMonth])\n\n const handleNextClick = React.useCallback(() => {\n if (!nextMonth) return\n if (navView === 'years') {\n setDisplayYears((prev) => ({\n from: prev.from + (prev.to - prev.from + 1),\n to: prev.to + (prev.to - prev.from + 1),\n }))\n onNextClick?.(new Date(displayYears.from + (displayYears.to - displayYears.from), 0, 1))\n return\n }\n goToMonth(nextMonth)\n onNextClick?.(nextMonth)\n }, [goToMonth, nextMonth])\n return (\n <nav className={cn('flex items-center', className)}>\n <Button\n variant=\"text\"\n className=\"absolute left-0 h-7 w-7 bg-transparent p-0 opacity-80 hover:opacity-100\"\n type=\"button\"\n tabIndex={isPreviousDisabled ? undefined : -1}\n disabled={isPreviousDisabled}\n aria-label={\n navView === 'years'\n ? `Go to the previous ${displayYears.to - displayYears.from + 1} years`\n : labelPrevious(previousMonth)\n }\n onClick={handlePreviousClick}\n >\n <CaretLeft className=\"h-4 w-4\" />\n </Button>\n\n <Button\n variant=\"text\"\n className=\"absolute right-0 h-7 w-7 bg-transparent p-0 opacity-80 hover:opacity-100\"\n type=\"button\"\n tabIndex={isNextDisabled ? undefined : -1}\n disabled={isNextDisabled}\n aria-label={\n navView === 'years'\n ? `Go to the next ${displayYears.to - displayYears.from + 1} years`\n : labelNext(nextMonth)\n }\n onClick={handleNextClick}\n >\n <CaretRight className=\"h-4 w-4\" />\n </Button>\n </nav>\n )\n },\n CaptionLabel: ({ children, ...props }) => {\n if (!showYearSwitcher) return <span {...props}>{children}</span>\n return (\n <Button\n className=\"h-7 w-full truncate text-sm font-medium\"\n variant=\"text\"\n size=\"sm\"\n onClick={() => setNavView((prev) => (prev === 'days' ? 'years' : 'days'))}\n >\n {navView === 'days' ? children : `${displayYears.from} - ${displayYears.to}`}\n </Button>\n )\n },\n MonthGrid: ({ className, children, ...props }) => {\n const { goToMonth, selected } = useDayPicker()\n if (navView === 'years') {\n return (\n <div className={cn('grid grid-cols-4 gap-y-2', className)} {...props}>\n {Array.from({ length: displayYears.to - displayYears.from + 1 }, (_noUsed, index) => {\n const isBefore =\n differenceInCalendarDays(new Date(displayYears.from + index, 11, 31), startMonth!) < 0\n\n const isAfter = differenceInCalendarDays(new Date(displayYears.from + index, 0, 0), endMonth!) > 0\n\n const isDisabled = isBefore || isAfter\n return (\n <Button\n key={index}\n className={cn(\n 'text-foreground h-7 w-full text-sm font-normal',\n displayYears.from + index === new Date().getFullYear() &&\n 'bg-primary text-primary-foreground font-medium',\n )}\n variant=\"text\"\n onClick={() => {\n setNavView('days')\n goToMonth(new Date(displayYears.from + index, (selected as Date | undefined)?.getMonth() ?? 0))\n }}\n disabled={isDisabled}\n >\n {displayYears.from + index}\n </Button>\n )\n })}\n </div>\n )\n }\n return (\n <table className={className} {...props}>\n {children}\n </table>\n )\n },\n }}\n numberOfMonths={columnsDisplayed}\n {...props}\n />\n )\n}\nCalendar.displayName = 'Calendar'\n\nexport { Calendar }\n"],"names":[],"mappings":";;;;;;;;;;AAuDA;AAAkB;AAChB;AACkB;AACC;AACP;AACZ;AAEF;AACE;AACA;AAA8C;AAK1C;AACA;AAAO;AAC2C;AACP;AAC3C;AACY;AAGhB;AAEA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAA0C;AAC/B;AACE;AAEb;AACA;AACA;AACA;AACA;AACA;AACA;AAA4B;AACQ;AAClC;AACM;AAER;AAEA;AACA;AACA;AAA8B;AAC5B;AACM;AAER;AAA2B;AACzB;AACM;AAER;AAAwB;AACtB;AACM;AAER;AAA0B;AACxB;AACM;AAER;AACA;AAEA;AACE;AAAC;AAAA;AACC;AACkE;AAC/D;AACI;AACoC;AAC3C;AACY;AACF;AACO;AACL;AACD;AACF;AACE;AACM;AACF;AACI;AACZ;AACO;AACN;AACD;AACO;AACC;AACC;AACH;AACD;AACH;AACE;AACC;AACF;AACV;AACY;AAER;AACA;AAAiC;AACnC;AAEE;AAEA;AACE;AACE;AAE2F;AAG7F;AAAQ;AAGV;AACE;AACE;AAEyF;AAG3F;AAAQ;AAGV;AACE;AACA;AACE;AAA2B;AACgB;AACJ;AAEvC;AACA;AAAA;AAEF;AACA;AAA2B;AAG7B;AACE;AACA;AACE;AAA2B;AACgB;AACJ;AAEvC;AACA;AAAA;AAEF;AACA;AAAuB;AAEzB;AAEI;AAAA;AAAC;AAAA;AACS;AACE;AACL;AACsC;AACjC;AAIuB;AAExB;AAEsB;AAAA;AACjC;AAEA;AAAC;AAAA;AACS;AACE;AACL;AACkC;AAC7B;AAIe;AAEhB;AAEuB;AAAA;AAClC;AACF;AAEJ;AAEE;AACA;AACE;AAAC;AAAA;AACW;AACF;AACH;AACmE;AAEE;AAAA;AAC5E;AAEJ;AAEE;AACA;AACE;AAGM;AAGA;AAEA;AACA;AACE;AAAC;AAAA;AAEY;AACT;AAEE;AACJ;AACQ;AAEN;AACA;AAA8F;AAChG;AACU;AAEW;AAAA;AAbhB;AAcP;AAGN;AAGJ;AAGE;AAEJ;AACF;AACgB;AACZ;AAAA;AAGV;AACA;;"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx } from 'react/jsx-runtime';
|
|
3
|
-
import { ArrowLeft
|
|
3
|
+
import { ArrowLeft } from '@phosphor-icons/react/dist/ssr/ArrowLeft';
|
|
4
|
+
import { ArrowRight } from '@phosphor-icons/react/dist/ssr/ArrowRight';
|
|
4
5
|
import useEmblaCarousel from 'embla-carousel-react';
|
|
5
6
|
import * as React from 'react';
|
|
6
7
|
import { cn } from '../../lib/utils.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Carousel.js","sources":["../../../src/components/Carousel/Carousel.tsx"],"sourcesContent":["'use client'\nimport { ArrowLeft
|
|
1
|
+
{"version":3,"file":"Carousel.js","sources":["../../../src/components/Carousel/Carousel.tsx"],"sourcesContent":["'use client'\nimport { ArrowLeft } from '@phosphor-icons/react/dist/ssr/ArrowLeft'\nimport { ArrowRight } from '@phosphor-icons/react/dist/ssr/ArrowRight'\nimport useEmblaCarousel, { type UseEmblaCarouselType } from 'embla-carousel-react'\nimport * as React from 'react'\n\nimport { cn } from '../../lib/utils'\nimport { Button } from '../Button'\n\ntype CarouselApi = UseEmblaCarouselType[1]\ntype UseCarouselParameters = Parameters<typeof useEmblaCarousel>\ntype CarouselOptions = UseCarouselParameters[0]\ntype CarouselPlugin = UseCarouselParameters[1]\n\nexport type CarouselProps = {\n opts?: CarouselOptions\n plugins?: CarouselPlugin\n orientation?: 'horizontal' | 'vertical'\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 = React.createContext<CarouselContextProps | null>(null)\n\nfunction useCarousel() {\n const context = React.useContext(CarouselContext)\n\n if (!context) {\n throw new Error('useCarousel must be used within a <Carousel />')\n }\n\n return context\n}\n\nconst Carousel = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement> & CarouselProps>(\n ({ orientation = 'horizontal', opts, setApi, plugins, className, children, ...props }, ref) => {\n const [carouselRef, api] = useEmblaCarousel(\n {\n ...opts,\n axis: orientation === 'horizontal' ? 'x' : 'y',\n },\n plugins,\n )\n const [canScrollPrev, setCanScrollPrev] = React.useState(false)\n const [canScrollNext, setCanScrollNext] = React.useState(false)\n\n const onSelect = React.useCallback((api: CarouselApi) => {\n /* istanbul ignore next -- @preserve */\n if (!api) {\n /* istanbul ignore next -- @preserve */\n return\n }\n\n setCanScrollPrev(api.canScrollPrev())\n setCanScrollNext(api.canScrollNext())\n }, [])\n\n const scrollPrev = React.useCallback(() => {\n /* istanbul ignore next -- @preserve */\n api?.scrollPrev()\n }, [api])\n\n const scrollNext = React.useCallback(() => {\n /* istanbul ignore next -- @preserve */\n api?.scrollNext()\n }, [api])\n\n React.useEffect(() => {\n /* istanbul ignore next -- @preserve */\n if (!api || !setApi) {\n return\n }\n /* istanbul ignore next -- @preserve */\n setApi(api)\n }, [api, setApi])\n\n React.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 const obj = React.useMemo(\n () => ({\n carouselRef,\n api: api,\n opts,\n orientation: orientation,\n scrollPrev,\n scrollNext,\n canScrollPrev,\n canScrollNext,\n }),\n [api, canScrollNext, canScrollPrev, carouselRef, opts, orientation, scrollNext, scrollPrev],\n )\n return (\n <CarouselContext.Provider value={obj}>\n <div ref={ref} className={cn('relative', className)} aria-roledescription=\"carousel\" {...props}>\n {children}\n </div>\n </CarouselContext.Provider>\n )\n },\n)\nCarousel.displayName = 'Carousel'\n\nconst CarouselContent = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(\n ({ className, ...props }, ref) => {\n const { carouselRef, orientation } = useCarousel()\n\n return (\n <div ref={carouselRef} className={cn('overflow-hidden', className)}>\n <div ref={ref} className={cn('flex', orientation === 'horizontal' ? '-ml-4' : '-mt-4 flex-col')} {...props} />\n </div>\n )\n },\n)\nCarouselContent.displayName = 'CarouselContent'\n\nconst CarouselItem = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(\n ({ className, ...props }, ref) => {\n const { orientation } = useCarousel()\n\n return (\n <div\n ref={ref}\n aria-roledescription=\"slide\"\n className={cn('min-w-0 shrink-0 grow-0 basis-full', orientation === 'horizontal' ? 'pl-4' : 'pt-4', className)}\n {...props}\n />\n )\n },\n)\nCarouselItem.displayName = 'CarouselItem'\n\nconst CarouselPrevious = React.forwardRef<HTMLButtonElement, React.ComponentProps<typeof Button>>(\n ({ className, ...props }, ref) => {\n const { orientation, scrollPrev, canScrollPrev } = useCarousel()\n\n return (\n <Button\n ref={ref}\n variant={'ghost'}\n iconOnly\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 className,\n )}\n disabled={!canScrollPrev}\n onClick={scrollPrev}\n StartIcon={ArrowLeft}\n {...props}\n >\n <span className=\"sr-only\">Previous slide</span>\n </Button>\n )\n },\n)\nCarouselPrevious.displayName = 'CarouselPrevious'\n\nconst CarouselNext = React.forwardRef<HTMLButtonElement, React.ComponentProps<typeof Button>>(\n ({ className, size = 'icon', ...props }, ref) => {\n const { orientation, scrollNext, canScrollNext } = useCarousel()\n\n return (\n <Button\n ref={ref}\n variant={'ghost'}\n iconOnly\n className={cn(\n 'absolute h-8 w-8 rounded-full',\n /* istanbul ignore next -- @preserve */\n orientation === 'horizontal'\n ? 'top-1/2 -right-12 -translate-y-1/2'\n : '-bottom-12 left-1/2 -translate-x-1/2 rotate-90',\n className,\n )}\n disabled={!canScrollNext}\n onClick={scrollNext}\n StartIcon={ArrowRight}\n {...props}\n >\n <span className=\"sr-only\">Next slide</span>\n </Button>\n )\n },\n)\nCarouselNext.displayName = 'CarouselNext'\n\nexport { type CarouselApi, Carousel, CarouselContent, CarouselItem, CarouselPrevious, CarouselNext, CarouselContext }\n"],"names":[],"mappings":";;;;;;;;;AA8BA;AAEA;AACE;AAEA;AACE;AAAgE;AAGlE;AACF;AAEA;AAAuB;AAEnB;AAA2B;AACzB;AACK;AACwC;AAC7C;AACA;AAEF;AACA;AAEA;AAAyD;AAEvD;AAAU;AAER;AAAA;AAGF;AACA;AAAoC;AAGtC;AAA2C;AAEzC;AAAgB;AAGlB;AAA2C;AAEzC;AAAgB;AAGlB;AAAsB;AAEpB;AACE;AAAA;AACF;AAEA;AAAU;AAGZ;AACE;AACE;AAAA;AAGF;AACA;AACA;AAEA;AACE;AAA0B;AAC5B;AAEF;AAAkB;AACT;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACF;AAC0F;AAE5F;AAKE;AAGN;AACA;AAEA;AAA8B;AAE1B;AAEA;AAGE;AAGN;AACA;AAEA;AAA2B;AAEvB;AAEA;AACE;AAAC;AAAA;AACC;AACqB;AACwF;AACzG;AAAA;AACN;AAGN;AACA;AAEA;AAA+B;AAE3B;AAEA;AACE;AAAC;AAAA;AACC;AACS;AACD;AACG;AACT;AAGI;AACJ;AACF;AACW;AACF;AACE;AACP;AAEoC;AAAA;AAC1C;AAGN;AACA;AAEA;AAA2B;AAEvB;AAEA;AACE;AAAC;AAAA;AACC;AACS;AACD;AACG;AACT;AAAA;AAII;AACJ;AACF;AACW;AACF;AACE;AACP;AAEgC;AAAA;AACtC;AAGN;AACA;;"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { jsx } from 'react/jsx-runtime';
|
|
2
|
-
import { Check } from '@phosphor-icons/react';
|
|
2
|
+
import { Check } from '@phosphor-icons/react/dist/ssr/Check';
|
|
3
3
|
import * as CheckboxPrimitive from '@radix-ui/react-checkbox';
|
|
4
4
|
import * as React from 'react';
|
|
5
5
|
import { cn } from '../../lib/utils.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Checkbox.js","sources":["../../../src/components/Checkbox/Checkbox.tsx"],"sourcesContent":["import { Check } from '@phosphor-icons/react'\nimport * as CheckboxPrimitive from '@radix-ui/react-checkbox'\nimport * as React from 'react'\n\nimport { cn } from '@/lib/utils'\n\ntype CheckboxProps = {\n /** Additional CSS classes to be applied to the checkbox */\n className?: string\n /** The controlled checked state of the checkbox */\n checked?: boolean\n /** The default checked state when initially rendered */\n defaultChecked?: boolean\n /** Whether the checkbox is disabled */\n disabled?: boolean\n /** Whether the checkbox is required in a form */\n required?: boolean\n /** The name of the checkbox when used in a form */\n name?: string\n /** The value of the checkbox when used in a form */\n value?: string\n /** Handler called when the checked state changes */\n onCheckedChange?: (checked: boolean) => void\n} & React.ComponentPropsWithoutRef<typeof CheckboxPrimitive.Root>\n\n/**\n * A controlled checkbox component built on top of Radix UI Checkbox.\n *\n * @example\n * ```tsx\n * // Basic usage\n * <Checkbox />\n *\n * // With controlled state\n * <Checkbox checked={checked} onCheckedChange={setChecked} />\n *\n * // With form integration\n * <Checkbox name=\"terms\" required />\n *\n * // With label\n * <div className=\"flex items-center gap-2\">\n * <Checkbox id=\"terms\" />\n * <label htmlFor=\"terms\">Accept terms</label>\n * </div>\n * ```\n */\nconst Checkbox = React.forwardRef<React.ComponentRef<typeof CheckboxPrimitive.Root>, CheckboxProps>(\n ({ className, ...props }, ref) => (\n <CheckboxPrimitive.Root\n ref={ref}\n className={cn(\n 'peer relative h-5 w-5 shrink-0 rounded-[5px] border border-neutral-300 transition-colors',\n 'focus-visible:ring-2 focus-visible:ring-neutral-500 focus-visible:ring-offset-2 focus-visible:outline-none',\n 'disabled:cursor-not-allowed disabled:bg-neutral-100 disabled:opacity-50',\n 'data-[state=checked]:border-neutral-500 data-[state=checked]:bg-neutral-500',\n 'hover:border-neutral-500 disabled:hover:border-neutral-300 data-[state=checked]:hover:border-neutral-500',\n className,\n )}\n {...props}\n >\n <CheckboxPrimitive.Indicator className={cn('absolute inset-0 flex items-center justify-center')}>\n <Check className=\"h-3.5 w-3.5 text-white\" />\n </CheckboxPrimitive.Indicator>\n </CheckboxPrimitive.Root>\n ),\n)\n\nCheckbox.displayName = 'Checkbox'\n\nexport type { CheckboxProps }\nexport { Checkbox }\n"],"names":[],"mappings":";;;;;;AA8CA,MAAM,WAAW,KAAA,CAAM,UAAA;AAAA,EACrB,CAAC,EAAE,SAAA,EAAW,GAAG,KAAA,IAAS,GAAA,qBACxB,GAAA;AAAA,IAAC,iBAAA,CAAkB,IAAA;AAAA,IAAlB;AAAA,MACC,GAAA;AAAA,MACA,SAAA,EAAW,EAAA;AAAA,QACT,0FAAA;AAAA,QACA,4GAAA;AAAA,QACA,yEAAA;AAAA,QACA,6EAAA;AAAA,QACA,0GAAA;AAAA,QACA;AAAA,OACF;AAAA,MACC,GAAG,KAAA;AAAA,MAEJ,QAAA,kBAAA,GAAA,CAAC,iBAAA,CAAkB,SAAA,EAAlB,EAA4B,SAAA,EAAW,EAAA,CAAG,mDAAmD,CAAA,EAC5F,QAAA,kBAAA,GAAA,CAAC,KAAA,EAAA,EAAM,SAAA,EAAU,wBAAA,EAAyB,CAAA,EAC5C;AAAA;AAAA;AAGN;AAEA,QAAA,CAAS,WAAA,GAAc,UAAA;;;;"}
|
|
1
|
+
{"version":3,"file":"Checkbox.js","sources":["../../../src/components/Checkbox/Checkbox.tsx"],"sourcesContent":["import { Check } from '@phosphor-icons/react/dist/ssr/Check'\nimport * as CheckboxPrimitive from '@radix-ui/react-checkbox'\nimport * as React from 'react'\n\nimport { cn } from '@/lib/utils'\n\ntype CheckboxProps = {\n /** Additional CSS classes to be applied to the checkbox */\n className?: string\n /** The controlled checked state of the checkbox */\n checked?: boolean\n /** The default checked state when initially rendered */\n defaultChecked?: boolean\n /** Whether the checkbox is disabled */\n disabled?: boolean\n /** Whether the checkbox is required in a form */\n required?: boolean\n /** The name of the checkbox when used in a form */\n name?: string\n /** The value of the checkbox when used in a form */\n value?: string\n /** Handler called when the checked state changes */\n onCheckedChange?: (checked: boolean) => void\n} & React.ComponentPropsWithoutRef<typeof CheckboxPrimitive.Root>\n\n/**\n * A controlled checkbox component built on top of Radix UI Checkbox.\n *\n * @example\n * ```tsx\n * // Basic usage\n * <Checkbox />\n *\n * // With controlled state\n * <Checkbox checked={checked} onCheckedChange={setChecked} />\n *\n * // With form integration\n * <Checkbox name=\"terms\" required />\n *\n * // With label\n * <div className=\"flex items-center gap-2\">\n * <Checkbox id=\"terms\" />\n * <label htmlFor=\"terms\">Accept terms</label>\n * </div>\n * ```\n */\nconst Checkbox = React.forwardRef<React.ComponentRef<typeof CheckboxPrimitive.Root>, CheckboxProps>(\n ({ className, ...props }, ref) => (\n <CheckboxPrimitive.Root\n ref={ref}\n className={cn(\n 'peer relative h-5 w-5 shrink-0 rounded-[5px] border border-neutral-300 transition-colors',\n 'focus-visible:ring-2 focus-visible:ring-neutral-500 focus-visible:ring-offset-2 focus-visible:outline-none',\n 'disabled:cursor-not-allowed disabled:bg-neutral-100 disabled:opacity-50',\n 'data-[state=checked]:border-neutral-500 data-[state=checked]:bg-neutral-500',\n 'hover:border-neutral-500 disabled:hover:border-neutral-300 data-[state=checked]:hover:border-neutral-500',\n className,\n )}\n {...props}\n >\n <CheckboxPrimitive.Indicator className={cn('absolute inset-0 flex items-center justify-center')}>\n <Check className=\"h-3.5 w-3.5 text-white\" />\n </CheckboxPrimitive.Indicator>\n </CheckboxPrimitive.Root>\n ),\n)\n\nCheckbox.displayName = 'Checkbox'\n\nexport type { CheckboxProps }\nexport { Checkbox }\n"],"names":[],"mappings":";;;;;;AA8CA,MAAM,WAAW,KAAA,CAAM,UAAA;AAAA,EACrB,CAAC,EAAE,SAAA,EAAW,GAAG,KAAA,IAAS,GAAA,qBACxB,GAAA;AAAA,IAAC,iBAAA,CAAkB,IAAA;AAAA,IAAlB;AAAA,MACC,GAAA;AAAA,MACA,SAAA,EAAW,EAAA;AAAA,QACT,0FAAA;AAAA,QACA,4GAAA;AAAA,QACA,yEAAA;AAAA,QACA,6EAAA;AAAA,QACA,0GAAA;AAAA,QACA;AAAA,OACF;AAAA,MACC,GAAG,KAAA;AAAA,MAEJ,QAAA,kBAAA,GAAA,CAAC,iBAAA,CAAkB,SAAA,EAAlB,EAA4B,SAAA,EAAW,EAAA,CAAG,mDAAmD,CAAA,EAC5F,QAAA,kBAAA,GAAA,CAAC,KAAA,EAAA,EAAM,SAAA,EAAU,wBAAA,EAAyB,CAAA,EAC5C;AAAA;AAAA;AAGN;AAEA,QAAA,CAAS,WAAA,GAAc,UAAA;;;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Chip.js","sources":["../../../src/components/Chip/Chip.tsx"],"sourcesContent":["import { X } from '@phosphor-icons/react'\nimport { cva, type VariantProps } from 'class-variance-authority'\nimport * as React from 'react'\n\nimport { cn } from '@/lib/utils'\n\nconst chipVariants = cva(\n 'inline-flex items-center border font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2',\n {\n variants: {\n /**\n * Defines the visual style of the chip\n */\n variant: {\n default: 'border-transparent bg-neutral-100 text-default-foreground',\n ghost: ' bg-transparent border border-neutral-500 text-primary-foreground',\n primary: 'border-transparent bg-primary text-primary-foreground',\n secondary: 'border-transparent bg-neutral-950 text-neutral-foreground',\n error: 'border-transparent bg-error-600 text-white',\n success: 'border-transparent bg-success-600 text-white',\n },\n /**\n * Controls the size and padding of the chip\n */\n size: {\n sm: 'px-2.5 py-0.5 text-sm',\n md: 'px-2.5 py-1 text-sm',\n lg: 'px-3 py-1 text-md',\n },\n rounded: {\n full: 'rounded-full',\n square: 'rounded-sm',\n },\n },\n defaultVariants: {\n variant: 'default',\n size: 'md',\n rounded: 'full',\n },\n },\n)\n\nexport type ChipProps = {\n /**\n * The visual style of the chip.\n * @default default\n */\n variant?: 'default' | 'ghost' | 'primary' | 'secondary' | 'error' | 'success'\n\n /**\n * The size of the chip, affecting padding and font size.\n * @default md\n */\n size?: 'sm' | 'md' | 'lg'\n\n /**\n * The roundedness of the chip, affecting the border radius.\n * @default full\n */\n rounded?: 'full' | 'square'\n\n /**\n * Optional callback for when the remove button is clicked.\n * When provided, displays a remove button on the chip.\n */\n onRemove?: (\n event:\n | React.KeyboardEvent<HTMLButtonElement | HTMLSpanElement>\n | React.MouseEvent<HTMLButtonElement | HTMLSpanElement, MouseEvent>,\n ) => void\n\n /**\n * The HTML element to use for the remove trigger.\n * Use 'span' when the chip is inside a button context to avoid nested buttons.\n * @default 'button'\n */\n triggerElement?: 'button' | 'span'\n\n /**\n * The content to display inside the chip.\n */\n children?: React.ReactNode\n\n /**\n * Additional CSS classes to apply to the chip.\n */\n className?: string\n} & React.HTMLAttributes<HTMLDivElement> &\n VariantProps<typeof chipVariants>\n\n/**\n * A chip component for displaying compact information with optional remove functionality.\n *\n * @example\n * // Basic usage\n * <Chip>Label</Chip>\n *\n * // With remove button\n * <Chip onRemove={() => console.log('removed')}>Removable</Chip>\n *\n * // Different variants\n * <Chip variant=\"primary\">Primary</Chip>\n * <Chip variant=\"error\">Error</Chip>\n *\n * // Inside button context (e.g., Combobox)\n * <Chip onRemove={() => console.log('removed')} triggerElement=\"span\">\n * Inside Button\n * </Chip>\n */\nfunction Chip({\n className,\n variant = 'default',\n size = 'md',\n rounded = 'full',\n onRemove,\n triggerElement = 'button',\n children,\n ...props\n}: ChipProps) {\n const removeIconClasses =\n 'focus-visible:ring-ring inline-flex h-6 w-6 items-center justify-center rounded-full transition-colors hover:bg-black/10 focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-none'\n\n const RemoveElement = triggerElement\n\n return (\n <div className={cn(chipVariants({ variant, size, rounded }), onRemove && 'gap-1.5 pr-1', className)} {...props}>\n {children}\n {onRemove ? (\n <RemoveElement\n {...(triggerElement === 'button' ? { type: 'button' as const } : {})}\n role={triggerElement === 'span' ? 'button' : undefined}\n tabIndex={triggerElement === 'span' ? 0 : undefined}\n onKeyDown={(event) => {\n if (event.key === 'Enter' || event.key === ' ') {\n event.preventDefault()\n onRemove(event)\n }\n }}\n onMouseDown={(event) => {\n event.preventDefault()\n event.stopPropagation()\n }}\n onClick={onRemove}\n className={removeIconClasses}\n aria-label=\"Remove\"\n >\n <X size={16} weight=\"regular\" className=\"shrink-0\" />\n </RemoveElement>\n ) : null}\n </div>\n )\n}\nChip.displayName = 'Chip'\n\nexport { Chip, chipVariants }\n"],"names":[],"mappings":";;;;;AAMA,MAAM,YAAA,GAAe,GAAA;AAAA,EACnB,mIAAA;AAAA,EACA;AAAA,IACE,QAAA,EAAU;AAAA;AAAA;AAAA;AAAA,MAIR,OAAA,EAAS;AAAA,QACP,OAAA,EAAS,2DAAA;AAAA,QACT,KAAA,EAAO,mEAAA;AAAA,QACP,OAAA,EAAS,uDAAA;AAAA,QACT,SAAA,EAAW,2DAAA;AAAA,QACX,KAAA,EAAO,4CAAA;AAAA,QACP,OAAA,EAAS;AAAA,OACX;AAAA;AAAA;AAAA;AAAA,MAIA,IAAA,EAAM;AAAA,QACJ,EAAA,EAAI,uBAAA;AAAA,QACJ,EAAA,EAAI,qBAAA;AAAA,QACJ,EAAA,EAAI;AAAA,OACN;AAAA,MACA,OAAA,EAAS;AAAA,QACP,IAAA,EAAM,cAAA;AAAA,QACN,MAAA,EAAQ;AAAA;AACV,KACF;AAAA,IACA,eAAA,EAAiB;AAAA,MACf,OAAA,EAAS,SAAA;AAAA,MACT,IAAA,EAAM,IAAA;AAAA,MACN,OAAA,EAAS;AAAA;AACX;AAEJ;AAqEA,SAAS,IAAA,CAAK;AAAA,EACZ,SAAA;AAAA,EACA,OAAA,GAAU,SAAA;AAAA,EACV,IAAA,GAAO,IAAA;AAAA,EACP,OAAA,GAAU,MAAA;AAAA,EACV,QAAA;AAAA,EACA,cAAA,GAAiB,QAAA;AAAA,EACjB,QAAA;AAAA,EACA,GAAG;AACL,CAAA,EAAc;AACZ,EAAA,MAAM,iBAAA,GACJ,sMAAA;AAEF,EAAA,MAAM,aAAA,GAAgB,cAAA;AAEtB,EAAA,4BACG,KAAA,EAAA,EAAI,SAAA,EAAW,EAAA,CAAG,YAAA,CAAa,EAAE,OAAA,EAAS,IAAA,EAAM,OAAA,EAAS,GAAG,QAAA,IAAY,cAAA,EAAgB,SAAS,CAAA,EAAI,GAAG,KAAA,EACtG,QAAA,EAAA;AAAA,IAAA,QAAA;AAAA,IACA,QAAA,mBACC,GAAA;AAAA,MAAC,aAAA;AAAA,MAAA;AAAA,QACE,GAAI,cAAA,KAAmB,QAAA,GAAW,EAAE,IAAA,EAAM,QAAA,KAAsB,EAAC;AAAA,QAClE,IAAA,EAAM,cAAA,KAAmB,MAAA,GAAS,QAAA,GAAW,MAAA;AAAA,QAC7C,QAAA,EAAU,cAAA,KAAmB,MAAA,GAAS,CAAA,GAAI,MAAA;AAAA,QAC1C,SAAA,EAAW,CAAC,KAAA,KAAU;AACpB,UAAA,IAAI,KAAA,CAAM,GAAA,KAAQ,OAAA,IAAW,KAAA,CAAM,QAAQ,GAAA,EAAK;AAC9C,YAAA,KAAA,CAAM,cAAA,EAAe;AACrB,YAAA,QAAA,CAAS,KAAK,CAAA;AAAA;AAChB,SACF;AAAA,QACA,WAAA,EAAa,CAAC,KAAA,KAAU;AACtB,UAAA,KAAA,CAAM,cAAA,EAAe;AACrB,UAAA,KAAA,CAAM,eAAA,EAAgB;AAAA,SACxB;AAAA,QACA,OAAA,EAAS,QAAA;AAAA,QACT,SAAA,EAAW,iBAAA;AAAA,QACX,YAAA,EAAW,QAAA;AAAA,QAEX,8BAAC,CAAA,EAAA,EAAE,IAAA,EAAM,IAAI,MAAA,EAAO,SAAA,EAAU,WAAU,UAAA,EAAW;AAAA;AAAA,KACrD,GACE;AAAA,GAAA,EACN,CAAA;AAEJ;AACA,IAAA,CAAK,WAAA,GAAc,MAAA;;;;"}
|
|
1
|
+
{"version":3,"file":"Chip.js","sources":["../../../src/components/Chip/Chip.tsx"],"sourcesContent":["import { X } from '@phosphor-icons/react/dist/ssr/X'\nimport { cva, type VariantProps } from 'class-variance-authority'\nimport * as React from 'react'\n\nimport { cn } from '@/lib/utils'\n\nconst chipVariants = cva(\n 'inline-flex items-center border font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2',\n {\n variants: {\n /**\n * Defines the visual style of the chip\n */\n variant: {\n default: 'border-transparent bg-neutral-100 text-default-foreground',\n ghost: ' bg-transparent border border-neutral-500 text-primary-foreground',\n primary: 'border-transparent bg-primary text-primary-foreground',\n secondary: 'border-transparent bg-neutral-950 text-neutral-foreground',\n error: 'border-transparent bg-error-600 text-white',\n success: 'border-transparent bg-success-600 text-white',\n },\n /**\n * Controls the size and padding of the chip\n */\n size: {\n sm: 'px-2.5 py-0.5 text-sm',\n md: 'px-2.5 py-1 text-sm',\n lg: 'px-3 py-1 text-md',\n },\n rounded: {\n full: 'rounded-full',\n square: 'rounded-sm',\n },\n },\n defaultVariants: {\n variant: 'default',\n size: 'md',\n rounded: 'full',\n },\n },\n)\n\nexport type ChipProps = {\n /**\n * The visual style of the chip.\n * @default default\n */\n variant?: 'default' | 'ghost' | 'primary' | 'secondary' | 'error' | 'success'\n\n /**\n * The size of the chip, affecting padding and font size.\n * @default md\n */\n size?: 'sm' | 'md' | 'lg'\n\n /**\n * The roundedness of the chip, affecting the border radius.\n * @default full\n */\n rounded?: 'full' | 'square'\n\n /**\n * Optional callback for when the remove button is clicked.\n * When provided, displays a remove button on the chip.\n */\n onRemove?: (\n event:\n | React.KeyboardEvent<HTMLButtonElement | HTMLSpanElement>\n | React.MouseEvent<HTMLButtonElement | HTMLSpanElement, MouseEvent>,\n ) => void\n\n /**\n * The HTML element to use for the remove trigger.\n * Use 'span' when the chip is inside a button context to avoid nested buttons.\n * @default 'button'\n */\n triggerElement?: 'button' | 'span'\n\n /**\n * The content to display inside the chip.\n */\n children?: React.ReactNode\n\n /**\n * Additional CSS classes to apply to the chip.\n */\n className?: string\n} & React.HTMLAttributes<HTMLDivElement> &\n VariantProps<typeof chipVariants>\n\n/**\n * A chip component for displaying compact information with optional remove functionality.\n *\n * @example\n * // Basic usage\n * <Chip>Label</Chip>\n *\n * // With remove button\n * <Chip onRemove={() => console.log('removed')}>Removable</Chip>\n *\n * // Different variants\n * <Chip variant=\"primary\">Primary</Chip>\n * <Chip variant=\"error\">Error</Chip>\n *\n * // Inside button context (e.g., Combobox)\n * <Chip onRemove={() => console.log('removed')} triggerElement=\"span\">\n * Inside Button\n * </Chip>\n */\nfunction Chip({\n className,\n variant = 'default',\n size = 'md',\n rounded = 'full',\n onRemove,\n triggerElement = 'button',\n children,\n ...props\n}: ChipProps) {\n const removeIconClasses =\n 'focus-visible:ring-ring inline-flex h-6 w-6 items-center justify-center rounded-full transition-colors hover:bg-black/10 focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-none'\n\n const RemoveElement = triggerElement\n\n return (\n <div className={cn(chipVariants({ variant, size, rounded }), onRemove && 'gap-1.5 pr-1', className)} {...props}>\n {children}\n {onRemove ? (\n <RemoveElement\n {...(triggerElement === 'button' ? { type: 'button' as const } : {})}\n role={triggerElement === 'span' ? 'button' : undefined}\n tabIndex={triggerElement === 'span' ? 0 : undefined}\n onKeyDown={(event) => {\n if (event.key === 'Enter' || event.key === ' ') {\n event.preventDefault()\n onRemove(event)\n }\n }}\n onMouseDown={(event) => {\n event.preventDefault()\n event.stopPropagation()\n }}\n onClick={onRemove}\n className={removeIconClasses}\n aria-label=\"Remove\"\n >\n <X size={16} weight=\"regular\" className=\"shrink-0\" />\n </RemoveElement>\n ) : null}\n </div>\n )\n}\nChip.displayName = 'Chip'\n\nexport { Chip, chipVariants }\n"],"names":[],"mappings":";;;;;AAMA,MAAM,YAAA,GAAe,GAAA;AAAA,EACnB,mIAAA;AAAA,EACA;AAAA,IACE,QAAA,EAAU;AAAA;AAAA;AAAA;AAAA,MAIR,OAAA,EAAS;AAAA,QACP,OAAA,EAAS,2DAAA;AAAA,QACT,KAAA,EAAO,mEAAA;AAAA,QACP,OAAA,EAAS,uDAAA;AAAA,QACT,SAAA,EAAW,2DAAA;AAAA,QACX,KAAA,EAAO,4CAAA;AAAA,QACP,OAAA,EAAS;AAAA,OACX;AAAA;AAAA;AAAA;AAAA,MAIA,IAAA,EAAM;AAAA,QACJ,EAAA,EAAI,uBAAA;AAAA,QACJ,EAAA,EAAI,qBAAA;AAAA,QACJ,EAAA,EAAI;AAAA,OACN;AAAA,MACA,OAAA,EAAS;AAAA,QACP,IAAA,EAAM,cAAA;AAAA,QACN,MAAA,EAAQ;AAAA;AACV,KACF;AAAA,IACA,eAAA,EAAiB;AAAA,MACf,OAAA,EAAS,SAAA;AAAA,MACT,IAAA,EAAM,IAAA;AAAA,MACN,OAAA,EAAS;AAAA;AACX;AAEJ;AAqEA,SAAS,IAAA,CAAK;AAAA,EACZ,SAAA;AAAA,EACA,OAAA,GAAU,SAAA;AAAA,EACV,IAAA,GAAO,IAAA;AAAA,EACP,OAAA,GAAU,MAAA;AAAA,EACV,QAAA;AAAA,EACA,cAAA,GAAiB,QAAA;AAAA,EACjB,QAAA;AAAA,EACA,GAAG;AACL,CAAA,EAAc;AACZ,EAAA,MAAM,iBAAA,GACJ,sMAAA;AAEF,EAAA,MAAM,aAAA,GAAgB,cAAA;AAEtB,EAAA,4BACG,KAAA,EAAA,EAAI,SAAA,EAAW,EAAA,CAAG,YAAA,CAAa,EAAE,OAAA,EAAS,IAAA,EAAM,OAAA,EAAS,GAAG,QAAA,IAAY,cAAA,EAAgB,SAAS,CAAA,EAAI,GAAG,KAAA,EACtG,QAAA,EAAA;AAAA,IAAA,QAAA;AAAA,IACA,QAAA,mBACC,GAAA;AAAA,MAAC,aAAA;AAAA,MAAA;AAAA,QACE,GAAI,cAAA,KAAmB,QAAA,GAAW,EAAE,IAAA,EAAM,QAAA,KAAsB,EAAC;AAAA,QAClE,IAAA,EAAM,cAAA,KAAmB,MAAA,GAAS,QAAA,GAAW,MAAA;AAAA,QAC7C,QAAA,EAAU,cAAA,KAAmB,MAAA,GAAS,CAAA,GAAI,MAAA;AAAA,QAC1C,SAAA,EAAW,CAAC,KAAA,KAAU;AACpB,UAAA,IAAI,KAAA,CAAM,GAAA,KAAQ,OAAA,IAAW,KAAA,CAAM,QAAQ,GAAA,EAAK;AAC9C,YAAA,KAAA,CAAM,cAAA,EAAe;AACrB,YAAA,QAAA,CAAS,KAAK,CAAA;AAAA;AAChB,SACF;AAAA,QACA,WAAA,EAAa,CAAC,KAAA,KAAU;AACtB,UAAA,KAAA,CAAM,cAAA,EAAe;AACrB,UAAA,KAAA,CAAM,eAAA,EAAgB;AAAA,SACxB;AAAA,QACA,OAAA,EAAS,QAAA;AAAA,QACT,SAAA,EAAW,iBAAA;AAAA,QACX,YAAA,EAAW,QAAA;AAAA,QAEX,8BAAC,CAAA,EAAA,EAAE,IAAA,EAAM,IAAI,MAAA,EAAO,SAAA,EAAU,WAAU,UAAA,EAAW;AAAA;AAAA,KACrD,GACE;AAAA,GAAA,EACN,CAAA;AAEJ;AACA,IAAA,CAAK,WAAA,GAAc,MAAA;;;;"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
2
|
-
import { CaretDown
|
|
2
|
+
import { CaretDown } from '@phosphor-icons/react/dist/ssr/CaretDown';
|
|
3
|
+
import { X } from '@phosphor-icons/react/dist/ssr/X';
|
|
3
4
|
import { cn } from '../../lib/utils.js';
|
|
4
5
|
import { Button, buttonVariants } from '../Button/Button.js';
|
|
5
6
|
import { Command, CommandInput } from '../Command/Command.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Combobox.js","sources":["../../../src/components/Combobox/Combobox.tsx"],"sourcesContent":["import { CaretDown, X } from '@phosphor-icons/react'\n\nimport { cn } from '../../lib/utils'\nimport { Button, buttonVariants } from '../Button'\nimport { Command, CommandInput } from '../Command'\nimport { PopoverContent, PopoverRoot, PopoverTrigger } from '../Popover'\n\nimport { StaticComboboxList } from './StaticComboboxList'\nimport { useCombobox } from './useCombobox'\nimport { VirtualizedComboboxList } from './VirtualizedComboboxList'\n\ntype ComboboxBaseProps<T> = {\n /** Unique identifier for the combobox */\n id?: string\n /** Array of options to display in the combobox */\n options: Array<T>\n /** Function to get the unique identifier from an option. */\n getOptionValue: (option: T) => string\n /** Function to get the display text from an option. */\n getOptionLabel: (option: T) => string\n /** Custom render function for options. If not provided, defaults to showing a checkmark and label */\n renderOption?: (option: T, isSelected: boolean) => React.ReactNode\n /** Placeholder text shown when no option is selected */\n placeholder?: string\n /** Placeholder text for the search input field */\n searchPlaceholder?: string\n /** Message shown when no options match the search query */\n emptyMessage?: string\n /** Additional CSS classes to apply to the combobox trigger */\n className?: string\n /** Whether the combobox is disabled */\n disabled?: boolean\n /** Maximum height of the options list. Can be any valid CSS height value */\n maxHeight?: string | number\n /** Whether to close the dropdown when an option is selected. Defaults to `true` for single select and `false` for multi-select. */\n closeOnSelect?: boolean\n /** Whether the combobox is in a loading state */\n loading?: boolean\n /** Message to show when in loading state */\n loadingPlaceholder?: string\n /** Whether the combobox has an error */\n error?: boolean | string\n /** Custom function to filter options based on search term */\n filterOptions?: (options: Array<T>, searchTerm: string) => Array<T>\n /** Callback function executed when the clear button is clicked. When provided, an X button will appear on hover to clear the selection. */\n onClear?: boolean | (() => void)\n /** Whether the selection can be cleared */\n clearable?: boolean\n /** Whether the combobox is inside a modal */\n modal?: boolean\n /** Placeholder text for the selected multiple options */\n selectedMultiplePlaceholder?: string\n /** Placeholder text for the multiple options */\n multipleOptionsPlaceholder?: string\n /** Special options that appear at the top with their own title. When selected, the combobox switches to single-select mode. */\n specialOptions?: Array<T>\n /** Title for the special options group */\n specialOptionsTitle?: string\n /** Container element to position the combobox relative to. */\n container?: HTMLElement\n}\n\nexport type ComboboxSingleProps<T> = ComboboxBaseProps<T> & {\n multiple?: false\n value?: string\n onChange: (value: string) => void\n /** Custom render function for the selected value display. */\n renderLabel?: (selectedOption: T) => React.ReactNode\n /**\n * Async pagination function.\n * Note: Multiple selection is not supported with virtualization.\n */\n fetchPage?: (params: {\n page: number\n search?: string\n }) => Promise<{ items: Array<T>; hasNextPage: boolean; nextPage: number }>\n}\n\nexport type ComboboxMultipleProps<T> = ComboboxBaseProps<T> & {\n multiple: true\n value?: Array<string>\n onChange: (value: Array<string>) => void\n /** Custom render function for the selected value(s) display. */\n renderLabel?: (selectedOptions: Array<T>, onRemove: (value: string) => void) => React.ReactNode\n /** fetchPage is not allowed with multiple selection */\n fetchPage?: never\n}\n\nexport type ComboboxProps<T> = ComboboxSingleProps<T> | ComboboxMultipleProps<T>\n\n/**\n * A searchable combobox component with support for custom rendering, keyboard navigation, and search filtering.\n *\n * @example Basic usage\n * ```tsx\n * interface User {\n * id: string\n * name: string\n * email: string\n * }\n *\n * <Combobox<User>\n * options={users}\n * value={selectedUserId}\n * onChange={setSelectedUserId}\n * getOptionValue={(user) => user.id}\n * getOptionLabel={(user) => user.name}\n * />\n * ```\n *\n * @example Custom filtering\n * ```tsx\n * <Combobox<User>\n * options={users}\n * value={selectedUserId}\n * onChange={setSelectedUserId}\n * getOptionValue={(user) => user.id}\n * getOptionLabel={(user) => user.name}\n * filterOptions={(options, searchTerm) =>\n * options.filter(user =>\n * user.name.toLowerCase().includes(searchTerm.toLowerCase()) ||\n * user.email.toLowerCase().includes(searchTerm.toLowerCase())\n * )\n * }\n * />\n * ```\n *\n * @example Virtualized infinite scrolling with pagination\n * ```tsx\n * <Combobox<User>\n * options={[]} // Initial options can be empty\n * value={selectedUserId}\n * onChange={setSelectedUserId}\n * getOptionValue={(user) => user.id}\n * getOptionLabel={(user) => user.name}\n * fetchPage={async ({ page, search }) => {\n * const response = await api.getUsers({ page, search })\n * return {\n * items: response.users,\n * hasNextPage: response.page < response.totalPages,\n * nextPage: page + 1\n * }\n * }}\n * />\n * ```\n */\nexport const Combobox = <T extends object>(props: ComboboxProps<T>) => {\n const {\n id,\n options,\n getOptionValue,\n getOptionLabel,\n searchPlaceholder = 'Search...',\n emptyMessage = 'No results found.',\n className = 'w-60',\n disabled = false,\n maxHeight = '300px',\n renderOption,\n loading = false,\n loadingPlaceholder = 'Cargando...',\n error = false,\n multiple,\n onClear,\n modal = false,\n selectedMultiplePlaceholder = 'Selected',\n multipleOptionsPlaceholder = 'Options',\n specialOptions,\n specialOptionsTitle,\n container,\n } = props\n\n const {\n open,\n setOpen,\n searchTerm,\n setSearchTerm,\n setIsHovered,\n hasNextPage,\n loadingMore,\n isVirtualized,\n filteredOptions,\n displayValue,\n hasValue,\n showClearButton,\n handleSelect,\n handleClear,\n loadNextPage,\n } = useCombobox(props)\n\n return (\n <div className=\"flex w-full flex-col gap-1\">\n <PopoverRoot open={open} onOpenChange={setOpen} modal={modal}>\n <PopoverTrigger asChild>\n <Button\n id={id}\n type=\"button\"\n disabled={disabled}\n variant=\"text\"\n className={cn(\n buttonVariants({ variant: 'input', size: 'lg' }),\n 'relative flex justify-between rounded-lg',\n multiple && 'renderLabel' in props && props.renderLabel ? 'h-auto min-h-12' : 'h-12',\n open && 'border-neutral-950',\n disabled && 'cursor-not-allowed',\n error && 'border-error-400 focus-visible:border-error-700',\n className,\n )}\n aria-expanded={open}\n aria-haspopup=\"listbox\"\n onMouseEnter={() => setIsHovered(true)}\n onMouseLeave={() => setIsHovered(false)}\n >\n <span\n className={cn(\n 'block',\n !hasValue && 'text-neutral-300',\n !(multiple && 'renderLabel' in props && props.renderLabel) && 'truncate',\n )}\n >\n {displayValue}\n </span>\n <CaretDown\n className={cn(\n 'h-4 w-4 shrink-0 opacity-50 transition-opacity duration-150',\n showClearButton ? 'opacity-0' : 'opacity-50',\n )}\n />\n {onClear && hasValue && (\n <X\n data-testid=\"clear-button\"\n className={cn(\n 'absolute right-4 z-10 h-4 w-4 shrink-0 cursor-pointer transition-opacity duration-150',\n showClearButton ? 'opacity-100 hover:opacity-70' : 'opacity-0',\n )}\n onClick={handleClear}\n />\n )}\n </Button>\n </PopoverTrigger>\n <PopoverContent className=\"p-0\" container={container}>\n <Command shouldFilter={false}>\n <CommandInput\n placeholder={searchPlaceholder}\n disabled={loading}\n value={searchTerm}\n onValueChange={setSearchTerm}\n />\n {isVirtualized ? (\n <VirtualizedComboboxList\n localOptions={filteredOptions}\n loading={loading}\n loadingPlaceholder={loadingPlaceholder}\n emptyMessage={emptyMessage}\n value={props.value as string}\n getOptionValue={getOptionValue}\n getOptionLabel={getOptionLabel}\n handleSelect={handleSelect}\n renderOption={renderOption}\n maxHeight={maxHeight}\n hasNextPage={hasNextPage}\n loadingMore={loadingMore}\n onLoadMore={loadNextPage}\n />\n ) : (\n <StaticComboboxList\n filteredOptions={filteredOptions}\n loading={loading}\n loadingPlaceholder={loadingPlaceholder}\n emptyMessage={emptyMessage}\n multiple={!!multiple}\n value={props.value}\n getOptionValue={getOptionValue}\n getOptionLabel={getOptionLabel}\n handleSelect={handleSelect}\n renderOption={renderOption}\n maxHeight={maxHeight}\n selectedMultiplePlaceholder={selectedMultiplePlaceholder}\n multipleOptionsPlaceholder={multipleOptionsPlaceholder}\n options={options}\n specialOptions={specialOptions}\n specialOptionsTitle={specialOptionsTitle}\n />\n )}\n </Command>\n </PopoverContent>\n </PopoverRoot>\n {typeof error === 'string' && <span className=\"text-error-500 text-sm\">{error}</span>}\n </div>\n )\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Combobox.js","sources":["../../../src/components/Combobox/Combobox.tsx"],"sourcesContent":["import { CaretDown } from '@phosphor-icons/react/dist/ssr/CaretDown'\nimport { X } from '@phosphor-icons/react/dist/ssr/X'\n\nimport { cn } from '../../lib/utils'\nimport { Button, buttonVariants } from '../Button'\nimport { Command, CommandInput } from '../Command'\nimport { PopoverContent, PopoverRoot, PopoverTrigger } from '../Popover'\n\nimport { StaticComboboxList } from './StaticComboboxList'\nimport { useCombobox } from './useCombobox'\nimport { VirtualizedComboboxList } from './VirtualizedComboboxList'\n\ntype ComboboxBaseProps<T> = {\n /** Unique identifier for the combobox */\n id?: string\n /** Array of options to display in the combobox */\n options: Array<T>\n /** Function to get the unique identifier from an option. */\n getOptionValue: (option: T) => string\n /** Function to get the display text from an option. */\n getOptionLabel: (option: T) => string\n /** Custom render function for options. If not provided, defaults to showing a checkmark and label */\n renderOption?: (option: T, isSelected: boolean) => React.ReactNode\n /** Placeholder text shown when no option is selected */\n placeholder?: string\n /** Placeholder text for the search input field */\n searchPlaceholder?: string\n /** Message shown when no options match the search query */\n emptyMessage?: string\n /** Additional CSS classes to apply to the combobox trigger */\n className?: string\n /** Whether the combobox is disabled */\n disabled?: boolean\n /** Maximum height of the options list. Can be any valid CSS height value */\n maxHeight?: string | number\n /** Whether to close the dropdown when an option is selected. Defaults to `true` for single select and `false` for multi-select. */\n closeOnSelect?: boolean\n /** Whether the combobox is in a loading state */\n loading?: boolean\n /** Message to show when in loading state */\n loadingPlaceholder?: string\n /** Whether the combobox has an error */\n error?: boolean | string\n /** Custom function to filter options based on search term */\n filterOptions?: (options: Array<T>, searchTerm: string) => Array<T>\n /** Callback function executed when the clear button is clicked. When provided, an X button will appear on hover to clear the selection. */\n onClear?: boolean | (() => void)\n /** Whether the selection can be cleared */\n clearable?: boolean\n /** Whether the combobox is inside a modal */\n modal?: boolean\n /** Placeholder text for the selected multiple options */\n selectedMultiplePlaceholder?: string\n /** Placeholder text for the multiple options */\n multipleOptionsPlaceholder?: string\n /** Special options that appear at the top with their own title. When selected, the combobox switches to single-select mode. */\n specialOptions?: Array<T>\n /** Title for the special options group */\n specialOptionsTitle?: string\n /** Container element to position the combobox relative to. */\n container?: HTMLElement\n}\n\nexport type ComboboxSingleProps<T> = ComboboxBaseProps<T> & {\n multiple?: false\n value?: string\n onChange: (value: string) => void\n /** Custom render function for the selected value display. */\n renderLabel?: (selectedOption: T) => React.ReactNode\n /**\n * Async pagination function.\n * Note: Multiple selection is not supported with virtualization.\n */\n fetchPage?: (params: {\n page: number\n search?: string\n }) => Promise<{ items: Array<T>; hasNextPage: boolean; nextPage: number }>\n}\n\nexport type ComboboxMultipleProps<T> = ComboboxBaseProps<T> & {\n multiple: true\n value?: Array<string>\n onChange: (value: Array<string>) => void\n /** Custom render function for the selected value(s) display. */\n renderLabel?: (selectedOptions: Array<T>, onRemove: (value: string) => void) => React.ReactNode\n /** fetchPage is not allowed with multiple selection */\n fetchPage?: never\n}\n\nexport type ComboboxProps<T> = ComboboxSingleProps<T> | ComboboxMultipleProps<T>\n\n/**\n * A searchable combobox component with support for custom rendering, keyboard navigation, and search filtering.\n *\n * @example Basic usage\n * ```tsx\n * interface User {\n * id: string\n * name: string\n * email: string\n * }\n *\n * <Combobox<User>\n * options={users}\n * value={selectedUserId}\n * onChange={setSelectedUserId}\n * getOptionValue={(user) => user.id}\n * getOptionLabel={(user) => user.name}\n * />\n * ```\n *\n * @example Custom filtering\n * ```tsx\n * <Combobox<User>\n * options={users}\n * value={selectedUserId}\n * onChange={setSelectedUserId}\n * getOptionValue={(user) => user.id}\n * getOptionLabel={(user) => user.name}\n * filterOptions={(options, searchTerm) =>\n * options.filter(user =>\n * user.name.toLowerCase().includes(searchTerm.toLowerCase()) ||\n * user.email.toLowerCase().includes(searchTerm.toLowerCase())\n * )\n * }\n * />\n * ```\n *\n * @example Virtualized infinite scrolling with pagination\n * ```tsx\n * <Combobox<User>\n * options={[]} // Initial options can be empty\n * value={selectedUserId}\n * onChange={setSelectedUserId}\n * getOptionValue={(user) => user.id}\n * getOptionLabel={(user) => user.name}\n * fetchPage={async ({ page, search }) => {\n * const response = await api.getUsers({ page, search })\n * return {\n * items: response.users,\n * hasNextPage: response.page < response.totalPages,\n * nextPage: page + 1\n * }\n * }}\n * />\n * ```\n */\nexport const Combobox = <T extends object>(props: ComboboxProps<T>) => {\n const {\n id,\n options,\n getOptionValue,\n getOptionLabel,\n searchPlaceholder = 'Search...',\n emptyMessage = 'No results found.',\n className = 'w-60',\n disabled = false,\n maxHeight = '300px',\n renderOption,\n loading = false,\n loadingPlaceholder = 'Cargando...',\n error = false,\n multiple,\n onClear,\n modal = false,\n selectedMultiplePlaceholder = 'Selected',\n multipleOptionsPlaceholder = 'Options',\n specialOptions,\n specialOptionsTitle,\n container,\n } = props\n\n const {\n open,\n setOpen,\n searchTerm,\n setSearchTerm,\n setIsHovered,\n hasNextPage,\n loadingMore,\n isVirtualized,\n filteredOptions,\n displayValue,\n hasValue,\n showClearButton,\n handleSelect,\n handleClear,\n loadNextPage,\n } = useCombobox(props)\n\n return (\n <div className=\"flex w-full flex-col gap-1\">\n <PopoverRoot open={open} onOpenChange={setOpen} modal={modal}>\n <PopoverTrigger asChild>\n <Button\n id={id}\n type=\"button\"\n disabled={disabled}\n variant=\"text\"\n className={cn(\n buttonVariants({ variant: 'input', size: 'lg' }),\n 'relative flex justify-between rounded-lg',\n multiple && 'renderLabel' in props && props.renderLabel ? 'h-auto min-h-12' : 'h-12',\n open && 'border-neutral-950',\n disabled && 'cursor-not-allowed',\n error && 'border-error-400 focus-visible:border-error-700',\n className,\n )}\n aria-expanded={open}\n aria-haspopup=\"listbox\"\n onMouseEnter={() => setIsHovered(true)}\n onMouseLeave={() => setIsHovered(false)}\n >\n <span\n className={cn(\n 'block',\n !hasValue && 'text-neutral-300',\n !(multiple && 'renderLabel' in props && props.renderLabel) && 'truncate',\n )}\n >\n {displayValue}\n </span>\n <CaretDown\n className={cn(\n 'h-4 w-4 shrink-0 opacity-50 transition-opacity duration-150',\n showClearButton ? 'opacity-0' : 'opacity-50',\n )}\n />\n {onClear && hasValue && (\n <X\n data-testid=\"clear-button\"\n className={cn(\n 'absolute right-4 z-10 h-4 w-4 shrink-0 cursor-pointer transition-opacity duration-150',\n showClearButton ? 'opacity-100 hover:opacity-70' : 'opacity-0',\n )}\n onClick={handleClear}\n />\n )}\n </Button>\n </PopoverTrigger>\n <PopoverContent className=\"p-0\" container={container}>\n <Command shouldFilter={false}>\n <CommandInput\n placeholder={searchPlaceholder}\n disabled={loading}\n value={searchTerm}\n onValueChange={setSearchTerm}\n />\n {isVirtualized ? (\n <VirtualizedComboboxList\n localOptions={filteredOptions}\n loading={loading}\n loadingPlaceholder={loadingPlaceholder}\n emptyMessage={emptyMessage}\n value={props.value as string}\n getOptionValue={getOptionValue}\n getOptionLabel={getOptionLabel}\n handleSelect={handleSelect}\n renderOption={renderOption}\n maxHeight={maxHeight}\n hasNextPage={hasNextPage}\n loadingMore={loadingMore}\n onLoadMore={loadNextPage}\n />\n ) : (\n <StaticComboboxList\n filteredOptions={filteredOptions}\n loading={loading}\n loadingPlaceholder={loadingPlaceholder}\n emptyMessage={emptyMessage}\n multiple={!!multiple}\n value={props.value}\n getOptionValue={getOptionValue}\n getOptionLabel={getOptionLabel}\n handleSelect={handleSelect}\n renderOption={renderOption}\n maxHeight={maxHeight}\n selectedMultiplePlaceholder={selectedMultiplePlaceholder}\n multipleOptionsPlaceholder={multipleOptionsPlaceholder}\n options={options}\n specialOptions={specialOptions}\n specialOptionsTitle={specialOptionsTitle}\n />\n )}\n </Command>\n </PopoverContent>\n </PopoverRoot>\n {typeof error === 'string' && <span className=\"text-error-500 text-sm\">{error}</span>}\n </div>\n )\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
2
|
-
import { CheckSquare
|
|
2
|
+
import { CheckSquare } from '@phosphor-icons/react/dist/ssr/CheckSquare';
|
|
3
|
+
import { Square } from '@phosphor-icons/react/dist/ssr/Square';
|
|
3
4
|
import { useMemo } from 'react';
|
|
4
5
|
import { CommandList, CommandEmpty, CommandGroup, CommandSeparator, CommandItem } from '../Command/Command.js';
|
|
5
6
|
import { ComboboxOptionWithTooltip } from './ComboboxOptionWithTooltip.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"StaticComboboxList.js","sources":["../../../src/components/Combobox/StaticComboboxList.tsx"],"sourcesContent":["import {
|
|
1
|
+
{"version":3,"file":"StaticComboboxList.js","sources":["../../../src/components/Combobox/StaticComboboxList.tsx"],"sourcesContent":["import { CheckSquare } from '@phosphor-icons/react/dist/ssr/CheckSquare'\nimport { Square } from '@phosphor-icons/react/dist/ssr/Square'\nimport { useMemo } from 'react'\n\nimport { CommandEmpty, CommandGroup, CommandItem, CommandList, CommandSeparator } from '../Command'\n\nimport { ComboboxOptionWithTooltip } from './ComboboxOptionWithTooltip'\nimport type { StaticComboboxListProps } from './types'\n\nexport const StaticComboboxList = <T extends object>({\n filteredOptions,\n loading,\n loadingPlaceholder,\n emptyMessage,\n multiple,\n value,\n getOptionValue,\n getOptionLabel,\n handleSelect,\n renderOption,\n maxHeight,\n selectedMultiplePlaceholder,\n multipleOptionsPlaceholder,\n options,\n specialOptions,\n specialOptionsTitle,\n}: StaticComboboxListProps<T>) => {\n const isArrayValue = Array.isArray(value)\n const selectedValues = useMemo(() => (multiple && isArrayValue ? value : []), [multiple, isArrayValue, value])\n\n const isOptionSelected = (optionValue: string) =>\n multiple ? selectedValues.includes(optionValue) : value === optionValue\n\n const regularOptions = useMemo(() => {\n return filteredOptions.filter(\n (option) => !specialOptions?.some((special) => getOptionValue(special) === getOptionValue(option)),\n )\n }, [filteredOptions, specialOptions, getOptionValue])\n\n const regularSelectedOptions = useMemo(() => {\n if (!multiple || !isArrayValue) return []\n\n return options.filter(\n (option) =>\n selectedValues.includes(getOptionValue(option)) &&\n !specialOptions?.some((special) => getOptionValue(special) === getOptionValue(option)),\n )\n }, [options, selectedValues, specialOptions, getOptionValue, multiple, isArrayValue])\n\n const optionsToShow = useMemo(() => {\n if (specialOptions) return regularOptions\n\n if (!multiple || !isArrayValue) return regularOptions\n\n return regularOptions.filter((option) => !selectedValues.includes(getOptionValue(option)))\n }, [regularOptions, specialOptions, selectedValues, getOptionValue, multiple, isArrayValue])\n\n const groupHeading = !specialOptions && multiple ? multipleOptionsPlaceholder : undefined\n\n const OptionItem = ({ option }: { option: T }) => {\n const optionValue = getOptionValue(option)\n const selected = isOptionSelected(optionValue)\n\n return (\n <CommandItem value={optionValue} onSelect={handleSelect}>\n {renderOption ? (\n renderOption(option, selected)\n ) : (\n <>\n {selected ? <CheckSquare className=\"mr-2 !h-6 !w-6\" /> : <Square className=\"mr-2 !h-6 !w-6\" />}\n <ComboboxOptionWithTooltip label={getOptionLabel(option)} />\n </>\n )}\n </CommandItem>\n )\n }\n\n return (\n <CommandList style={{ maxHeight }} className=\"overflow-auto\" onWheel={(event) => event.stopPropagation()}>\n {loading ? (\n <div className=\"text-muted-foreground flex items-center justify-center py-6 text-sm\">{loadingPlaceholder}</div>\n ) : (\n <>\n {filteredOptions.length === 0 &&\n regularOptions.length === 0 &&\n (!specialOptions || specialOptions.length === 0) && <CommandEmpty>{emptyMessage}</CommandEmpty>}\n\n {specialOptions?.length && specialOptionsTitle ? (\n <>\n <CommandGroup heading={specialOptionsTitle}>\n {specialOptions.map((option) => (\n <OptionItem key={getOptionValue(option)} option={option} />\n ))}\n </CommandGroup>\n\n <CommandSeparator className=\"!mx-[10px]\" />\n </>\n ) : null}\n\n {!specialOptions && multiple && isArrayValue && regularSelectedOptions.length > 0 && (\n <CommandGroup heading={selectedMultiplePlaceholder}>\n {regularSelectedOptions.map((option) => (\n <OptionItem key={getOptionValue(option)} option={option} />\n ))}\n </CommandGroup>\n )}\n\n <CommandGroup heading={groupHeading}>\n {optionsToShow.map((option) => (\n <OptionItem key={getOptionValue(option)} option={option} />\n ))}\n </CommandGroup>\n </>\n )}\n </CommandList>\n )\n}\n"],"names":[],"mappings":";;;;;;;AASO,MAAM,qBAAqB,CAAmB;AAAA,EACnD,eAAA;AAAA,EACA,OAAA;AAAA,EACA,kBAAA;AAAA,EACA,YAAA;AAAA,EACA,QAAA;AAAA,EACA,KAAA;AAAA,EACA,cAAA;AAAA,EACA,cAAA;AAAA,EACA,YAAA;AAAA,EACA,YAAA;AAAA,EACA,SAAA;AAAA,EACA,2BAAA;AAAA,EACA,0BAAA;AAAA,EACA,OAAA;AAAA,EACA,cAAA;AAAA,EACA;AACF,CAAA,KAAkC;AAChC,EAAA,MAAM,YAAA,GAAe,KAAA,CAAM,OAAA,CAAQ,KAAK,CAAA;AACxC,EAAA,MAAM,cAAA,GAAiB,OAAA,CAAQ,MAAO,QAAA,IAAY,YAAA,GAAe,KAAA,GAAQ,EAAC,EAAI,CAAC,QAAA,EAAU,YAAA,EAAc,KAAK,CAAC,CAAA;AAE7G,EAAA,MAAM,gBAAA,GAAmB,CAAC,WAAA,KACxB,QAAA,GAAW,eAAe,QAAA,CAAS,WAAW,IAAI,KAAA,KAAU,WAAA;AAE9D,EAAA,MAAM,cAAA,GAAiB,QAAQ,MAAM;AACnC,IAAA,OAAO,eAAA,CAAgB,MAAA;AAAA,MACrB,CAAC,MAAA,KAAW,CAAC,cAAA,EAAgB,IAAA,CAAK,CAAC,OAAA,KAAY,cAAA,CAAe,OAAO,CAAA,KAAM,cAAA,CAAe,MAAM,CAAC;AAAA,KACnG;AAAA,GACF,EAAG,CAAC,eAAA,EAAiB,cAAA,EAAgB,cAAc,CAAC,CAAA;AAEpD,EAAA,MAAM,sBAAA,GAAyB,QAAQ,MAAM;AAC3C,IAAA,IAAI,CAAC,QAAA,IAAY,CAAC,YAAA,SAAqB,EAAC;AAExC,IAAA,OAAO,OAAA,CAAQ,MAAA;AAAA,MACb,CAAC,MAAA,KACC,cAAA,CAAe,SAAS,cAAA,CAAe,MAAM,CAAC,CAAA,IAC9C,CAAC,cAAA,EAAgB,IAAA,CAAK,CAAC,OAAA,KAAY,cAAA,CAAe,OAAO,CAAA,KAAM,cAAA,CAAe,MAAM,CAAC;AAAA,KACzF;AAAA,GACF,EAAG,CAAC,OAAA,EAAS,cAAA,EAAgB,gBAAgB,cAAA,EAAgB,QAAA,EAAU,YAAY,CAAC,CAAA;AAEpF,EAAA,MAAM,aAAA,GAAgB,QAAQ,MAAM;AAClC,IAAA,IAAI,gBAAgB,OAAO,cAAA;AAE3B,IAAA,IAAI,CAAC,QAAA,IAAY,CAAC,YAAA,EAAc,OAAO,cAAA;AAEvC,IAAA,OAAO,cAAA,CAAe,MAAA,CAAO,CAAC,MAAA,KAAW,CAAC,eAAe,QAAA,CAAS,cAAA,CAAe,MAAM,CAAC,CAAC,CAAA;AAAA,GAC3F,EAAG,CAAC,cAAA,EAAgB,cAAA,EAAgB,gBAAgB,cAAA,EAAgB,QAAA,EAAU,YAAY,CAAC,CAAA;AAE3F,EAAA,MAAM,YAAA,GAAe,CAAC,cAAA,IAAkB,QAAA,GAAW,0BAAA,GAA6B,MAAA;AAEhF,EAAA,MAAM,UAAA,GAAa,CAAC,EAAE,MAAA,EAAO,KAAqB;AAChD,IAAA,MAAM,WAAA,GAAc,eAAe,MAAM,CAAA;AACzC,IAAA,MAAM,QAAA,GAAW,iBAAiB,WAAW,CAAA;AAE7C,IAAA,uBACE,GAAA,CAAC,WAAA,EAAA,EAAY,KAAA,EAAO,WAAA,EAAa,QAAA,EAAU,YAAA,EACxC,QAAA,EAAA,YAAA,GACC,YAAA,CAAa,MAAA,EAAQ,QAAQ,CAAA,mBAE7B,IAAA,CAAA,QAAA,EAAA,EACG,QAAA,EAAA;AAAA,MAAA,QAAA,mBAAW,GAAA,CAAC,eAAY,SAAA,EAAU,gBAAA,EAAiB,oBAAK,GAAA,CAAC,MAAA,EAAA,EAAO,WAAU,gBAAA,EAAiB,CAAA;AAAA,sBAC5F,GAAA,CAAC,yBAAA,EAAA,EAA0B,KAAA,EAAO,cAAA,CAAe,MAAM,CAAA,EAAG;AAAA,KAAA,EAC5D,CAAA,EAEJ,CAAA;AAAA,GAEJ;AAEA,EAAA,uBACE,GAAA,CAAC,eAAY,KAAA,EAAO,EAAE,WAAU,EAAG,SAAA,EAAU,iBAAgB,OAAA,EAAS,CAAC,UAAU,KAAA,CAAM,eAAA,IACpF,QAAA,EAAA,OAAA,mBACC,GAAA,CAAC,SAAI,SAAA,EAAU,qEAAA,EAAuE,QAAA,EAAA,kBAAA,EAAmB,CAAA,mBAEzG,IAAA,CAAA,QAAA,EAAA,EACG,QAAA,EAAA;AAAA,IAAA,eAAA,CAAgB,MAAA,KAAW,CAAA,IAC1B,cAAA,CAAe,MAAA,KAAW,CAAA,KACzB,CAAC,cAAA,IAAkB,cAAA,CAAe,MAAA,KAAW,CAAA,CAAA,oBAAM,GAAA,CAAC,YAAA,EAAA,EAAc,QAAA,EAAA,YAAA,EAAa,CAAA;AAAA,IAEjF,cAAA,EAAgB,MAAA,IAAU,mBAAA,mBACzB,IAAA,CAAA,QAAA,EAAA,EACE,QAAA,EAAA;AAAA,sBAAA,GAAA,CAAC,YAAA,EAAA,EAAa,OAAA,EAAS,mBAAA,EACpB,QAAA,EAAA,cAAA,CAAe,IAAI,CAAC,MAAA,qBACnB,GAAA,CAAC,UAAA,EAAA,EAAwC,MAAA,EAAA,EAAxB,cAAA,CAAe,MAAM,CAAmB,CAC1D,CAAA,EACH,CAAA;AAAA,sBAEA,GAAA,CAAC,gBAAA,EAAA,EAAiB,SAAA,EAAU,YAAA,EAAa;AAAA,KAAA,EAC3C,CAAA,GACE,IAAA;AAAA,IAEH,CAAC,kBAAkB,QAAA,IAAY,YAAA,IAAgB,uBAAuB,MAAA,GAAS,CAAA,oBAC9E,GAAA,CAAC,YAAA,EAAA,EAAa,OAAA,EAAS,2BAAA,EACpB,iCAAuB,GAAA,CAAI,CAAC,2BAC3B,GAAA,CAAC,UAAA,EAAA,EAAwC,UAAxB,cAAA,CAAe,MAAM,CAAmB,CAC1D,CAAA,EACH,CAAA;AAAA,oBAGF,GAAA,CAAC,YAAA,EAAA,EAAa,OAAA,EAAS,YAAA,EACpB,wBAAc,GAAA,CAAI,CAAC,MAAA,qBAClB,GAAA,CAAC,cAAwC,MAAA,EAAA,EAAxB,cAAA,CAAe,MAAM,CAAmB,CAC1D,CAAA,EACH;AAAA,GAAA,EACF,CAAA,EAEJ,CAAA;AAEJ;;;;"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
2
|
-
import { Check } from '@phosphor-icons/react';
|
|
2
|
+
import { Check } from '@phosphor-icons/react/dist/ssr/Check';
|
|
3
3
|
import { useVirtualizer } from '@tanstack/react-virtual';
|
|
4
4
|
import { useRef, useEffect } from 'react';
|
|
5
5
|
import { CommandEmpty, CommandItem } from '../Command/Command.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"VirtualizedComboboxList.js","sources":["../../../src/components/Combobox/VirtualizedComboboxList.tsx"],"sourcesContent":["import { Check } from '@phosphor-icons/react'\nimport { useVirtualizer } from '@tanstack/react-virtual'\nimport { useRef, useEffect } from 'react'\n\nimport { CommandEmpty, CommandItem } from '../Command'\n\nimport { ComboboxOptionWithTooltip } from './ComboboxOptionWithTooltip'\nimport type { VirtualizedComboboxListProps } from './types'\n\nexport const VirtualizedComboboxList = <T extends object>({\n localOptions,\n loading,\n loadingPlaceholder,\n emptyMessage,\n value,\n getOptionValue,\n getOptionLabel,\n handleSelect,\n renderOption,\n maxHeight,\n hasNextPage,\n loadingMore,\n onLoadMore,\n}: VirtualizedComboboxListProps<T>) => {\n const parentRef = useRef<HTMLDivElement>(null)\n const hasTriggeredRef = useRef(false)\n\n const totalCount = localOptions.length\n const PREFETCH_THRESHOLD = 25\n\n const rowVirtualizer = useVirtualizer({\n count: totalCount,\n getScrollElement: () => parentRef.current,\n estimateSize: () => 40,\n overscan: 10,\n })\n\n useEffect(() => {\n hasTriggeredRef.current = false\n }, [totalCount])\n\n const virtualItems = rowVirtualizer.getVirtualItems()\n\n useEffect(() => {\n if (virtualItems.length === 0 || !hasNextPage || loadingMore || loading || hasTriggeredRef.current) {\n return\n }\n\n const lastVisibleItem = virtualItems.at(-1)\n const itemsFromEnd = totalCount - (lastVisibleItem?.index ?? 0)\n\n if (itemsFromEnd <= PREFETCH_THRESHOLD) {\n hasTriggeredRef.current = true\n onLoadMore()\n }\n }, [virtualItems, totalCount, hasNextPage, loadingMore, loading, onLoadMore])\n\n if (loading && localOptions.length === 0) {\n return (\n <div className=\"text-muted-foreground flex items-center justify-center py-6 text-sm\">{loadingPlaceholder}</div>\n )\n }\n\n if (localOptions.length === 0 && !loading && !loadingMore) {\n return <CommandEmpty>{emptyMessage}</CommandEmpty>\n }\n\n const getItemAtIndex = (index: number) => {\n const option = localOptions[index]\n const isSelected = value === getOptionValue(option)\n return { option, isSelected }\n }\n\n return (\n <div ref={parentRef} className=\"overflow-auto\" style={{ maxHeight }} onWheel={(event) => event.stopPropagation()}>\n <div style={{ height: `${rowVirtualizer.getTotalSize()}px`, position: 'relative' }}>\n {rowVirtualizer.getVirtualItems().map((virtualRow) => {\n const { option, isSelected } = getItemAtIndex(virtualRow.index)\n const optionValue = getOptionValue(option)\n\n return (\n <div\n key={optionValue}\n data-index={virtualRow.index}\n ref={(el) => {\n if (el) rowVirtualizer.measureElement(el)\n }}\n style={{\n position: 'absolute',\n top: 0,\n left: 0,\n width: '100%',\n transform: `translateY(${virtualRow.start}px)`,\n }}\n >\n <CommandItem value={optionValue} onSelect={handleSelect}>\n {renderOption ? (\n renderOption(option, isSelected)\n ) : (\n <>\n <Check className={`mr-2 h-4 w-4 ${isSelected ? 'opacity-100' : 'opacity-0'}`} />\n <ComboboxOptionWithTooltip label={getOptionLabel(option)} />\n </>\n )}\n </CommandItem>\n </div>\n )\n })}\n </div>\n {loadingMore && (\n <div className=\"flex items-center justify-center py-2 text-sm text-neutral-500\">{loadingPlaceholder}</div>\n )}\n </div>\n )\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"VirtualizedComboboxList.js","sources":["../../../src/components/Combobox/VirtualizedComboboxList.tsx"],"sourcesContent":["import { Check } from '@phosphor-icons/react/dist/ssr/Check'\nimport { useVirtualizer } from '@tanstack/react-virtual'\nimport { useRef, useEffect } from 'react'\n\nimport { CommandEmpty, CommandItem } from '../Command'\n\nimport { ComboboxOptionWithTooltip } from './ComboboxOptionWithTooltip'\nimport type { VirtualizedComboboxListProps } from './types'\n\nexport const VirtualizedComboboxList = <T extends object>({\n localOptions,\n loading,\n loadingPlaceholder,\n emptyMessage,\n value,\n getOptionValue,\n getOptionLabel,\n handleSelect,\n renderOption,\n maxHeight,\n hasNextPage,\n loadingMore,\n onLoadMore,\n}: VirtualizedComboboxListProps<T>) => {\n const parentRef = useRef<HTMLDivElement>(null)\n const hasTriggeredRef = useRef(false)\n\n const totalCount = localOptions.length\n const PREFETCH_THRESHOLD = 25\n\n const rowVirtualizer = useVirtualizer({\n count: totalCount,\n getScrollElement: () => parentRef.current,\n estimateSize: () => 40,\n overscan: 10,\n })\n\n useEffect(() => {\n hasTriggeredRef.current = false\n }, [totalCount])\n\n const virtualItems = rowVirtualizer.getVirtualItems()\n\n useEffect(() => {\n if (virtualItems.length === 0 || !hasNextPage || loadingMore || loading || hasTriggeredRef.current) {\n return\n }\n\n const lastVisibleItem = virtualItems.at(-1)\n const itemsFromEnd = totalCount - (lastVisibleItem?.index ?? 0)\n\n if (itemsFromEnd <= PREFETCH_THRESHOLD) {\n hasTriggeredRef.current = true\n onLoadMore()\n }\n }, [virtualItems, totalCount, hasNextPage, loadingMore, loading, onLoadMore])\n\n if (loading && localOptions.length === 0) {\n return (\n <div className=\"text-muted-foreground flex items-center justify-center py-6 text-sm\">{loadingPlaceholder}</div>\n )\n }\n\n if (localOptions.length === 0 && !loading && !loadingMore) {\n return <CommandEmpty>{emptyMessage}</CommandEmpty>\n }\n\n const getItemAtIndex = (index: number) => {\n const option = localOptions[index]\n const isSelected = value === getOptionValue(option)\n return { option, isSelected }\n }\n\n return (\n <div ref={parentRef} className=\"overflow-auto\" style={{ maxHeight }} onWheel={(event) => event.stopPropagation()}>\n <div style={{ height: `${rowVirtualizer.getTotalSize()}px`, position: 'relative' }}>\n {rowVirtualizer.getVirtualItems().map((virtualRow) => {\n const { option, isSelected } = getItemAtIndex(virtualRow.index)\n const optionValue = getOptionValue(option)\n\n return (\n <div\n key={optionValue}\n data-index={virtualRow.index}\n ref={(el) => {\n if (el) rowVirtualizer.measureElement(el)\n }}\n style={{\n position: 'absolute',\n top: 0,\n left: 0,\n width: '100%',\n transform: `translateY(${virtualRow.start}px)`,\n }}\n >\n <CommandItem value={optionValue} onSelect={handleSelect}>\n {renderOption ? (\n renderOption(option, isSelected)\n ) : (\n <>\n <Check className={`mr-2 h-4 w-4 ${isSelected ? 'opacity-100' : 'opacity-0'}`} />\n <ComboboxOptionWithTooltip label={getOptionLabel(option)} />\n </>\n )}\n </CommandItem>\n </div>\n )\n })}\n </div>\n {loadingMore && (\n <div className=\"flex items-center justify-center py-2 text-sm text-neutral-500\">{loadingPlaceholder}</div>\n )}\n </div>\n )\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
3
|
-
import { MagnifyingGlass } from '@phosphor-icons/react';
|
|
3
|
+
import { MagnifyingGlass } from '@phosphor-icons/react/dist/ssr/MagnifyingGlass';
|
|
4
4
|
import { Command as Command$1 } from 'cmdk';
|
|
5
5
|
import * as React from 'react';
|
|
6
6
|
import { Dialog, DialogContent } from '../Dialog/Dialog.js';
|