@brainfish-ai/components 0.35.19 → 0.35.20
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/esm/chunks/{ChatSearch.DD63KIj6.js → ChatSearch.Crh0QjPs.js} +2 -2
- package/dist/esm/chunks/{ChatSearch.DD63KIj6.js.map → ChatSearch.Crh0QjPs.js.map} +1 -1
- package/dist/esm/chunks/{Conversation.CfhUJm_Q.js → Conversation.CWR55agZ.js} +2 -2
- package/dist/esm/chunks/{Conversation.CfhUJm_Q.js.map → Conversation.CWR55agZ.js.map} +1 -1
- package/dist/esm/chunks/{FormattedMessage.CEEjawib.js → FormattedMessage.DXVhkV-z.js} +14 -14
- package/dist/esm/chunks/{FormattedMessage.CEEjawib.js.map → FormattedMessage.DXVhkV-z.js.map} +1 -1
- package/dist/esm/chunks/{button.C7qRaFMP.js → button.DXe2tRBO.js} +3 -3
- package/dist/esm/chunks/{button.C7qRaFMP.js.map → button.DXe2tRBO.js.map} +1 -1
- package/dist/esm/chunks/{combobox.DKotd4uC.js → combobox.Ccfe3IGO.js} +4 -4
- package/dist/esm/chunks/{combobox.DKotd4uC.js.map → combobox.Ccfe3IGO.js.map} +1 -1
- package/dist/esm/chunks/{data-table.1ptJ47z8.js → data-table.Dn7VQJFo.js} +2 -2
- package/dist/esm/chunks/{data-table.1ptJ47z8.js.map → data-table.Dn7VQJFo.js.map} +1 -1
- package/dist/esm/chunks/{date-picker.Bto-A8WE.js → date-picker.GRONonNX.js} +2 -2
- package/dist/esm/chunks/{date-picker.Bto-A8WE.js.map → date-picker.GRONonNX.js.map} +1 -1
- package/dist/esm/chunks/{feedback.aGVWiKHH.js → feedback.nVBNjdPh.js} +2 -2
- package/dist/esm/chunks/{feedback.aGVWiKHH.js.map → feedback.nVBNjdPh.js.map} +1 -1
- package/dist/esm/chunks/{file-upload-status.sUoGRgbH.js → file-upload-status.znDE1kUC.js} +2 -2
- package/dist/esm/chunks/{file-upload-status.sUoGRgbH.js.map → file-upload-status.znDE1kUC.js.map} +1 -1
- package/dist/esm/chunks/{filters.Bxyw3eHZ.js → filters.CZJ31Eqj.js} +4 -4
- package/dist/esm/chunks/{filters.Bxyw3eHZ.js.map → filters.CZJ31Eqj.js.map} +1 -1
- package/dist/esm/chunks/{font-picker.CVZovtmt.js → font-picker.DrA0q0TI.js} +2 -2
- package/dist/esm/chunks/{font-picker.CVZovtmt.js.map → font-picker.DrA0q0TI.js.map} +1 -1
- package/dist/esm/chunks/{header-nav.BY2ppP8j.js → header-nav.BQXr30-S.js} +2 -2
- package/dist/esm/chunks/{header-nav.BY2ppP8j.js.map → header-nav.BQXr30-S.js.map} +1 -1
- package/dist/esm/chunks/{header-pane.DCGet3RZ.js → header-pane.D40kbO-a.js} +2 -2
- package/dist/esm/chunks/{header-pane.DCGet3RZ.js.map → header-pane.D40kbO-a.js.map} +1 -1
- package/dist/esm/chunks/index.C9B3bui8.js +2 -0
- package/dist/esm/chunks/index.C9B3bui8.js.map +1 -0
- package/dist/esm/chunks/{input-with-tags.aktIpAck.js → input-with-tags.4LvQIIuq.js} +3 -3
- package/dist/esm/chunks/{input-with-tags.aktIpAck.js.map → input-with-tags.4LvQIIuq.js.map} +1 -1
- package/dist/esm/chunks/{sidebar.tGcs3r4O.js → sidebar.CM8HDZg0.js} +16 -16
- package/dist/esm/chunks/{sidebar.tGcs3r4O.js.map → sidebar.CM8HDZg0.js.map} +1 -1
- package/dist/esm/chunks/{simpleSelect.BiNOqq3j.js → simpleSelect.C1KHuEVe.js} +3 -3
- package/dist/esm/chunks/{simpleSelect.BiNOqq3j.js.map → simpleSelect.C1KHuEVe.js.map} +1 -1
- package/dist/esm/chunks/{suggestion-card.DKQAazak.js → suggestion-card.PPUwB3ML.js} +2 -2
- package/dist/esm/chunks/{suggestion-card.DKQAazak.js.map → suggestion-card.PPUwB3ML.js.map} +1 -1
- package/dist/esm/chunks/{two-level-combobox.CWKR1tXX.js → two-level-combobox.CQUmvlq6.js} +3 -3
- package/dist/esm/chunks/{two-level-combobox.CWKR1tXX.js.map → two-level-combobox.CQUmvlq6.js.map} +1 -1
- package/dist/esm/components/article-suggestions-banner.js +1 -1
- package/dist/esm/components/articles-coverage.js +4 -4
- package/dist/esm/components/articles-updated.js +2 -2
- package/dist/esm/components/chart-area-linear.js +4 -4
- package/dist/esm/components/chart-area-linear.js.map +1 -1
- package/dist/esm/components/chart-radial-stacked.js +2 -2
- package/dist/esm/components/chart-radial-stacked.js.map +1 -1
- package/dist/esm/components/chat-search.js +1 -1
- package/dist/esm/components/combobox.js +1 -1
- package/dist/esm/components/conversation.js +1 -1
- package/dist/esm/components/convos.js +12 -12
- package/dist/esm/components/data-table.js +1 -1
- package/dist/esm/components/date-picker.js +1 -1
- package/dist/esm/components/feedback.js +1 -1
- package/dist/esm/components/file-upload.js +1 -1
- package/dist/esm/components/filter.js +1 -1
- package/dist/esm/components/font-picker.js +1 -1
- package/dist/esm/components/input-with-tags.js +1 -1
- package/dist/esm/components/markdown.js +1 -1
- package/dist/esm/components/metric-card.js +2 -2
- package/dist/esm/components/metric-card.js.map +1 -1
- package/dist/esm/components/select.js +1 -1
- package/dist/esm/components/two-level-combobox.js +1 -1
- package/dist/esm/components/ui/alert-dialog.js +1 -1
- package/dist/esm/components/ui/breadcrumb.js +1 -1
- package/dist/esm/components/ui/button-group.js +1 -1
- package/dist/esm/components/ui/button.js +1 -1
- package/dist/esm/components/ui/combobox.js +1 -1
- package/dist/esm/components/ui/div-button.js +1 -1
- package/dist/esm/components/ui/item.js +5 -5
- package/dist/esm/components/ui/label.js +1 -1
- package/dist/esm/components/ui/popover.js +1 -1
- package/dist/esm/components/ui/radio-group.js +2 -2
- package/dist/esm/components/ui/separator.js +1 -1
- package/dist/esm/components/ui/sheet.js +1 -1
- package/dist/esm/components/ui/spinner.js +2 -2
- package/dist/esm/components/ui/switch.js +2 -2
- package/dist/esm/global.css +1 -1
- package/dist/esm/index.js +1 -1
- package/dist/esm/layouts/full-layout.js +1 -1
- package/dist/esm/layouts/header-nav.js +1 -1
- package/dist/esm/layouts/sidebar.js +1 -1
- package/dist/esm/logos/microsoft-logo.js +2 -2
- package/dist/esm/scenes/knowledge-review.js +6 -6
- package/dist/esm/tailwind.preset.js +1 -1
- package/dist/esm/tailwind.preset.js.map +1 -1
- package/dist/stats.html +1 -1
- package/package.json +7 -7
- package/tailwind.preset.ts +2 -1
- package/dist/esm/chunks/index.Ca2JkOFO.js +0 -2
- package/dist/esm/chunks/index.Ca2JkOFO.js.map +0 -1
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import*as e from"react";import{S as r}from"./index.
|
|
2
|
-
return e.createElement(l,{className:t(d({variant:s,size:o,elevation:i,disabled:n,className:a})),ref:u
|
|
3
|
-
//# sourceMappingURL=button.
|
|
1
|
+
import*as e from"react";import{S as r}from"./index.C9B3bui8.js";import{cva as a}from"class-variance-authority";import{c as t}from"./utils.DtKoarLP.js";const s="shadow-brand hover:shadow-none !transition-shadow duration-300 ease-in-out active:shadow-brand-active dark:shadow-brand-dark dark:hover:shadow-none dark:active:shadow-brand-dark-active",d=a("inline-flex items-center text-dark-900 justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-5 [&_svg]:shrink-0",{variants:{variant:{default:"bg-primary text-primary border border-primary shadow hover:bg-primary/90",destructive:"bg-destructive text-destructive border border-destructive hover:bg-destructive/90",success:"bg-success text-success border border-success hover:bg-success/90",outline:"border border-input border-border hover:bg-dark-200 active:bg-dark-400 disabled:text-subtlest",surface:"bg-surface text-dark-900 rounded border border-border hover:bg-dark-200 active:bg-dark-400",secondary:"bg-secondary text-secondary-foreground hover:bg-secondary/80",suggestion:"bg-blue-600 text-white rounded-full",ghost:"hover:bg-dark-200 active:bg-dark-400",link:"text-foreground underline-offset-4 hover:underline",dark:"bg-dark-700 text-white dark:text-primary shadow hover:bg-dark-800 dark:bg-primary dark:hover:bg-primary/80 focus-visible:bg-dark-800 dark:focus-visible:bg-primary/80"},size:{default:"h-9 p-2",xs:"h-8 rounded-md px-2 text-sm gap-1.5",sm:"h-8 rounded-md px-3 text-sm",lg:"h-10 rounded-md px-8",icon:"h-9 w-9 [&_svg]:size-5"},elevation:{flat:"",shadow:`${s}`},disabled:{true:"text-subtlest pointer-events-none bg-dark-400 border-dark-600 opacity-90",false:""}},defaultVariants:{variant:"default",size:"default",elevation:"flat",disabled:!1}}),o=e.forwardRef(({className:a,variant:s,size:o,elevation:i,disabled:n,asChild:b=!1,...u},c)=>{const l=b?r:"button";/* @__PURE__ */
|
|
2
|
+
return e.createElement(l,{className:t(d({variant:s,size:o,elevation:i,disabled:n,className:a})),ref:c,...u,disabled:n??void 0})});o.displayName="Button";export{o as B,s as a,d as b};
|
|
3
|
+
//# sourceMappingURL=button.DXe2tRBO.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"button.
|
|
1
|
+
{"version":3,"file":"button.DXe2tRBO.js","sources":["../../../src/lib/styles.ts","../../../src/components/ui/button.tsx"],"sourcesContent":["export const brandShadowEffect =\n 'shadow-brand hover:shadow-none !transition-shadow duration-300 ease-in-out active:shadow-brand-active dark:shadow-brand-dark dark:hover:shadow-none dark:active:shadow-brand-dark-active';\n","import * as React from 'react';\nimport { Slot } from '@radix-ui/react-slot';\nimport { cva, type VariantProps } from 'class-variance-authority';\n\nimport { cn } from '@/lib/utils';\nimport { brandShadowEffect } from '@/lib/styles';\n\nconst buttonVariants = cva(\n 'inline-flex items-center text-dark-900 justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-5 [&_svg]:shrink-0',\n {\n variants: {\n variant: {\n default: 'bg-primary text-primary border border-primary shadow hover:bg-primary/90',\n destructive: 'bg-destructive text-destructive border border-destructive hover:bg-destructive/90',\n success: 'bg-success text-success border border-success hover:bg-success/90',\n outline: 'border border-input border-border hover:bg-dark-200 active:bg-dark-400 disabled:text-subtlest',\n surface: 'bg-surface text-dark-900 rounded border border-border hover:bg-dark-200 active:bg-dark-400',\n secondary: 'bg-secondary text-secondary-foreground hover:bg-secondary/80',\n suggestion: 'bg-blue-600 text-white rounded-full',\n ghost: 'hover:bg-dark-200 active:bg-dark-400',\n link: 'text-foreground underline-offset-4 hover:underline',\n dark: 'bg-dark-700 text-white dark:text-primary shadow hover:bg-dark-800 dark:bg-primary dark:hover:bg-primary/80 focus-visible:bg-dark-800 dark:focus-visible:bg-primary/80',\n },\n size: {\n default: 'h-9 p-2',\n xs: 'h-8 rounded-md px-2 text-sm gap-1.5',\n sm: 'h-8 rounded-md px-3 text-sm',\n lg: 'h-10 rounded-md px-8',\n icon: 'h-9 w-9 [&_svg]:size-5',\n },\n elevation: {\n flat: '',\n shadow: `${brandShadowEffect}`,\n },\n disabled: {\n true: 'text-subtlest pointer-events-none bg-dark-400 border-dark-600 opacity-90',\n false: '',\n },\n },\n defaultVariants: {\n variant: 'default',\n size: 'default',\n elevation: 'flat',\n disabled: false as boolean | null | undefined,\n },\n },\n);\n\nexport interface ButtonProps\n extends Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, 'disabled'>, VariantProps<typeof buttonVariants> {\n asChild?: boolean;\n}\n\nconst Button = React.forwardRef<HTMLButtonElement, ButtonProps>(\n ({ className, variant, size, elevation, disabled, asChild = false, ...props }, ref) => {\n const Comp = asChild ? Slot : 'button';\n\n return (\n <Comp\n className={cn(buttonVariants({ variant, size, elevation, disabled, className }))}\n ref={ref}\n {...props}\n disabled={disabled ?? undefined}\n />\n );\n },\n);\nButton.displayName = 'Button';\n\nexport { Button, buttonVariants };\n"],"names":["brandShadowEffect","buttonVariants","cva","variants","variant","default","destructive","success","outline","surface","secondary","suggestion","ghost","link","dark","size","xs","sm","lg","icon","elevation","flat","shadow","disabled","true","false","defaultVariants","Button","React","forwardRef","className","asChild","props","ref","Comp","Slot","createElement","cn","displayName"],"mappings":"uJAAO,MAAMA,EACX,2LCMIC,EAAiBC,EACrB,sTACA,CACEC,SAAU,CACRC,QAAS,CACPC,QAAS,2EACTC,YAAa,oFACbC,QAAS,oEACTC,QAAS,gGACTC,QAAS,6FACTC,UAAW,+DACXC,WAAY,sCACZC,MAAO,uCACPC,KAAM,qDACNC,KAAM,yKAERC,KAAM,CACJV,QAAS,UACTW,GAAI,sCACJC,GAAI,8BACJC,GAAI,uBACJC,KAAM,0BAERC,UAAW,CACTC,KAAM,GACNC,OAAQ,GAAGtB,KAEbuB,SAAU,CACRC,KAAM,2EACNC,MAAO,KAGXC,gBAAiB,CACftB,QAAS,UACTW,KAAM,UACNK,UAAW,OACXG,UAAU,KAUVI,EAASC,EAAMC,WACnB,EAAGC,YAAW1B,UAASW,OAAMK,YAAWG,WAAUQ,WAAU,KAAUC,GAASC,KAC7E,MAAMC,EAAOH,EAAUI,EAAO;AAE9B,OACEP,EAAAQ,cAACF,EAAA,CACCJ,UAAWO,EAAGpC,EAAe,CAAEG,UAASW,OAAMK,YAAWG,WAAUO,eACnEG,SACID,EACJT,SAAUA,QAAY,MAK9BI,EAAOW,YAAc"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import*as e from"react";import{CaretUpDown as t,Check as a}from"@phosphor-icons/react";import{c as l}from"./utils.DtKoarLP.js";import{B as n}from"./button.
|
|
2
|
-
return e.createElement(i,{open:O,onOpenChange:e=>{e&&R.current&&W(S||R.current.offsetWidth),T(e),y?.(e)}},/* @__PURE__ */e.createElement(p,{asChild:!0},/* @__PURE__ */e.createElement(n,{ref:R,variant:"outline",role:"combobox","aria-expanded":O,disabled:
|
|
1
|
+
import*as e from"react";import{CaretUpDown as t,Check as a}from"@phosphor-icons/react";import{c as l}from"./utils.DtKoarLP.js";import{B as n}from"./button.DXe2tRBO.js";import{Command as o,CommandInput as r,CommandList as s,CommandEmpty as c,CommandGroup as m,CommandItem as u}from"../components/ui/command.js";import{Popover as i,PopoverTrigger as p,PopoverContent as d}from"../components/ui/popover.js";function f({options:f,defaultValueLabel:E,placeholder:b,noResultsLabel:v,className:h,onOpenChange:y,onChange:g,dropdownWidth:S,value:j,disabled:w=!1,renderItem:C,renderValue:N,renderTrigger:x,appendToBody:B=!0}){const[O,T]=e.useState(!1),[k,I]=e.useState(""),L=void 0!==j?j:k,R=e.useRef(null),[V,W]=e.useState(null),q=f.find(e=>e.value===L),F=e=>{const t=e===L?"":e;void 0===j&&I(t),T(!1),g?.(t)},$=q?N?N(q):q.label:E;/* @__PURE__ */
|
|
2
|
+
return e.createElement(i,{open:O,onOpenChange:e=>{e&&R.current&&W(S||R.current.offsetWidth),T(e),y?.(e)}},/* @__PURE__ */e.createElement(p,{asChild:!0},/* @__PURE__ */e.createElement(n,{ref:R,variant:"outline",role:"combobox","aria-expanded":O,disabled:w,className:l("w-full justify-between",h)},x?x({selectedItem:q,isOpen:O}):$,
|
|
3
3
|
/* @__PURE__ */e.createElement(t,{className:"opacity-50"}))),/* @__PURE__ */e.createElement(d,{appendToBody:B,className:"p-0",style:{width:V?`${V}px`:"auto"},align:"start"},
|
|
4
|
-
/* @__PURE__ */e.createElement(o,null,/* @__PURE__ */e.createElement(r,{placeholder:b}),/* @__PURE__ */e.createElement(s,null,/* @__PURE__ */e.createElement(c,null,v),/* @__PURE__ */e.createElement(m,null,f.map(t=>{const n=L===t.value;return
|
|
4
|
+
/* @__PURE__ */e.createElement(o,null,/* @__PURE__ */e.createElement(r,{placeholder:b}),/* @__PURE__ */e.createElement(s,null,/* @__PURE__ */e.createElement(c,null,v),/* @__PURE__ */e.createElement(m,null,f.map(t=>{const n=L===t.value;return C?/* @__PURE__ */e.createElement(e.Fragment,{key:t.value},C({item:t,isSelected:n,onSelect:()=>F(t.value)})):/* @__PURE__ */e.createElement(u,{key:t.value,value:t.label,onSelect:e=>{const t=f.find(t=>t.label===e);F(t?.value||"")}},t.label,
|
|
5
5
|
/* @__PURE__ */e.createElement(a,{className:l("ml-auto",n?"opacity-100":"opacity-0")}))}))))))}export{f as C};
|
|
6
|
-
//# sourceMappingURL=combobox.
|
|
6
|
+
//# sourceMappingURL=combobox.Ccfe3IGO.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"combobox.
|
|
1
|
+
{"version":3,"file":"combobox.Ccfe3IGO.js","sources":["../../../src/components/combobox/combobox.tsx"],"sourcesContent":["import * as React from 'react';\nimport { Check, CaretUpDown } from '@phosphor-icons/react';\n\nimport { cn } from '@/lib/utils';\nimport { Button } from '@/components/ui/button';\nimport { Command, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList } from '@/components/ui/command';\nimport { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover';\n\nexport interface ComboboxItem {\n value: string;\n label: string;\n icon?: React.ReactNode;\n /** Additional data that can be passed to custom renderers */\n\n data?: any;\n}\n\nexport interface ComboboxRenderItemProps<T extends ComboboxItem = ComboboxItem> {\n item: T;\n isSelected: boolean;\n onSelect: () => void;\n}\n\nexport interface ComboboxProps<T extends ComboboxItem = ComboboxItem> {\n options: T[];\n defaultValueLabel: string;\n placeholder: string;\n noResultsLabel: string;\n className?: string;\n dropdownWidth?: number;\n value?: string;\n /** Whether the combobox is disabled */\n disabled?: boolean;\n /** Callback on open state change */\n onOpenChange?: (open: boolean) => void;\n /** Callback on value change */\n onChange?: (value: string) => void;\n /** Custom render function for each item in the dropdown */\n renderItem?: (props: ComboboxRenderItemProps<T>) => React.ReactNode;\n /** Custom render function for the selected value in the trigger button */\n renderValue?: (item: T) => React.ReactNode;\n /** Custom render function for the entire trigger button content */\n renderTrigger?: (props: { selectedItem: T | undefined; isOpen: boolean }) => React.ReactNode;\n /**\n * When false, the dropdown stays in the React tree instead of portaling to body.\n * Use inside modals/dialogs so the list is not detached from the dialog layer.\n */\n appendToBody?: boolean;\n}\n\nexport function Combobox<T extends ComboboxItem = ComboboxItem>({\n options,\n defaultValueLabel,\n placeholder,\n noResultsLabel,\n className,\n onOpenChange,\n onChange,\n dropdownWidth,\n value: controlledValue,\n disabled = false,\n renderItem,\n renderValue,\n renderTrigger,\n appendToBody = true,\n}: ComboboxProps<T>) {\n const [open, setOpen] = React.useState(false);\n const [internalValue, setInternalValue] = React.useState('');\n\n // Use controlled value if provided, otherwise use internal state\n const value = controlledValue !== undefined ? controlledValue : internalValue;\n const triggerRef = React.useRef<HTMLButtonElement>(null);\n const [triggerWidth, setTriggerWidth] = React.useState<number | null>(null);\n\n const selectedItem = options.find((option) => option.value === value);\n\n // Update width when popover opens\n const handleOpenChange = (isOpen: boolean) => {\n if (isOpen && triggerRef.current) {\n setTriggerWidth(dropdownWidth ? dropdownWidth : triggerRef.current.offsetWidth);\n }\n setOpen(isOpen);\n onOpenChange?.(isOpen);\n };\n\n const handleSelect = (selectedValue: string) => {\n const newValue = selectedValue === value ? '' : selectedValue;\n\n // Update internal state only if not controlled\n if (controlledValue === undefined) {\n setInternalValue(newValue);\n }\n\n setOpen(false);\n onChange?.(newValue);\n };\n\n // Default trigger content\n const defaultTriggerContent = selectedItem\n ? renderValue\n ? renderValue(selectedItem)\n : selectedItem.label\n : defaultValueLabel;\n\n return (\n <Popover open={open} onOpenChange={handleOpenChange}>\n <PopoverTrigger asChild>\n <Button\n ref={triggerRef}\n variant=\"outline\"\n role=\"combobox\"\n aria-expanded={open}\n disabled={disabled}\n className={cn('w-full justify-between', className)}\n >\n {renderTrigger ? renderTrigger({ selectedItem, isOpen: open }) : defaultTriggerContent}\n <CaretUpDown className=\"opacity-50\" />\n </Button>\n </PopoverTrigger>\n <PopoverContent\n appendToBody={appendToBody}\n className=\"p-0\"\n style={{\n width: triggerWidth ? `${triggerWidth}px` : 'auto',\n }}\n align=\"start\"\n >\n <Command>\n <CommandInput placeholder={placeholder} />\n <CommandList>\n <CommandEmpty>{noResultsLabel}</CommandEmpty>\n <CommandGroup>\n {options.map((option) => {\n const isSelected = value === option.value;\n\n if (renderItem) {\n return (\n <React.Fragment key={option.value}>\n {renderItem({\n item: option,\n isSelected,\n onSelect: () => handleSelect(option.value),\n })}\n </React.Fragment>\n );\n }\n\n return (\n <CommandItem\n key={option.value}\n value={option.label}\n onSelect={(currentLabel) => {\n const selectedOption = options.find((opt) => opt.label === currentLabel);\n\n handleSelect(selectedOption?.value || '');\n }}\n >\n {option.label}\n <Check className={cn('ml-auto', isSelected ? 'opacity-100' : 'opacity-0')} />\n </CommandItem>\n );\n })}\n </CommandGroup>\n </CommandList>\n </Command>\n </PopoverContent>\n </Popover>\n );\n}\n"],"names":["Combobox","options","defaultValueLabel","placeholder","noResultsLabel","className","onOpenChange","onChange","dropdownWidth","value","controlledValue","disabled","renderItem","renderValue","renderTrigger","appendToBody","open","setOpen","React","useState","internalValue","setInternalValue","triggerRef","useRef","triggerWidth","setTriggerWidth","selectedItem","find","option","handleSelect","selectedValue","newValue","defaultTriggerContent","label","createElement","Popover","isOpen","current","offsetWidth","PopoverTrigger","asChild","Button","ref","variant","role","cn","CaretUpDown","PopoverContent","style","width","align","Command","CommandInput","CommandList","CommandEmpty","CommandGroup","map","isSelected","Fragment","key","item","onSelect","CommandItem","currentLabel","selectedOption","opt","Check"],"mappings":"oZAkDO,SAASA,GAAgDC,QAC9DA,EAAAC,kBACAA,EAAAC,YACAA,EAAAC,eACAA,EAAAC,UACAA,EAAAC,aACAA,EAAAC,SACAA,EAAAC,cACAA,EACAC,MAAOC,EAAAC,SACPA,GAAW,EAAAC,WACXA,EAAAC,YACAA,EAAAC,cACAA,EAAAC,aACAA,GAAe,IAEf,MAAOC,EAAMC,GAAWC,EAAMC,UAAS,IAChCC,EAAeC,GAAoBH,EAAMC,SAAS,IAGnDV,OAA4B,IAApBC,EAAgCA,EAAkBU,EAC1DE,EAAaJ,EAAMK,OAA0B,OAC5CC,EAAcC,GAAmBP,EAAMC,SAAwB,MAEhEO,EAAezB,EAAQ0B,KAAMC,GAAWA,EAAOnB,QAAUA,GAWzDoB,EAAgBC,IACpB,MAAMC,EAAWD,IAAkBrB,EAAQ,GAAKqB,OAGxB,IAApBpB,GACFW,EAAiBU,GAGnBd,GAAQ,GACRV,IAAWwB,IAIPC,EAAwBN,EAC1Bb,EACEA,EAAYa,GACZA,EAAaO,MACf/B;AAEJ,OACEgB,EAAAgB,cAACC,GAAQnB,OAAYV,aA5BG8B,IACpBA,GAAUd,EAAWe,SACvBZ,EAAgBjB,GAAgCc,EAAWe,QAAQC,aAErErB,EAAQmB,GACR9B,IAAe8B,oBAwBblB,EAAAgB,cAACK,EAAA,CAAeC,SAAO,kBACrBtB,EAAAgB,cAACO,EAAA,CACCC,IAAKpB,EACLqB,QAAQ,UACRC,KAAK,WACL,gBAAe5B,EACfL,WACAN,UAAWwC,EAAG,yBAA0BxC,IAEvCS,EAAgBA,EAAc,CAAEY,eAAcU,OAAQpB,IAAUgB;eACjEd,EAAAgB,cAACY,EAAA,CAAYzC,UAAU,gCAG3Ba,EAAAgB,cAACa,EAAA,CACChC,eACAV,UAAU,MACV2C,MAAO,CACLC,MAAOzB,EAAe,GAAGA,MAAmB,QAE9C0B,MAAM;+BAELC,EAAA,oBACCjC,EAAAgB,cAACkB,EAAA,CAAajD,+BACde,EAAAgB,cAACmB,EAAA,oBACCnC,EAAAgB,cAACoB,EAAA,KAAclD,kBACfc,EAAAgB,cAACqB,OACEtD,EAAQuD,IAAK5B,IACZ,MAAM6B,EAAahD,IAAUmB,EAAOnB,MAEpC,OAAIG,iCAECM,EAAMwC,SAAN,CAAeC,IAAK/B,EAAOnB,OACzBG,EAAW,CACVgD,KAAMhC,EACN6B,aACAI,SAAU,IAAMhC,EAAaD,EAAOnB,yBAO1CS,EAAAgB,cAAC4B,EAAA,CACCH,IAAK/B,EAAOnB,MACZA,MAAOmB,EAAOK,MACd4B,SAAWE,IACT,MAAMC,EAAiB/D,EAAQ0B,KAAMsC,GAAQA,EAAIhC,QAAU8B,GAE3DlC,EAAamC,GAAgBvD,OAAS,MAGvCmB,EAAOK;eACRf,EAAAgB,cAACgC,GAAM7D,UAAWwC,EAAG,UAAWY,EAAa,cAAgB,sBAUjF"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import e,{useCallback as t}from"react";import{useReactTable as a,getSortedRowModel as n,getExpandedRowModel as l,getFilteredRowModel as
|
|
1
|
+
import e,{useCallback as t}from"react";import{useReactTable as a,getSortedRowModel as n,getExpandedRowModel as l,getFilteredRowModel as s,getPaginationRowModel as r,getCoreRowModel as o,flexRender as i}from"@tanstack/react-table";import{AnimatePresence as d,motion as m}from"framer-motion";import{TableRow as c,TableCell as p,Table as g,TableHeader as u,TableHead as h,TableBody as E}from"../components/ui/table.js";import{c as f}from"./utils.DtKoarLP.js";const x=({className:t,...a})=>/* @__PURE__ */e.createElement("div",{className:f("animate-original-pulse rounded-md bg-muted",t),...a}),w={initial:{height:0},animate:{height:"auto",transition:{height:{type:"spring",stiffness:450,damping:20}}},exit:{height:0,transition:{height:{duration:.1,ease:"linear"}}}};function N({columns:N,data:b,getRowCanExpand:y=()=>!0,className:C,expandeRowClassName:k,isLoading:R=!1,skeletonRowCount:S=10,...v}){const[M,$]=e.useState({}),[z,D]=e.useState([]);e.useEffect(()=>{$({})},[b]);const F=a({data:b,columns:N,getCoreRowModel:o(),state:{expanded:M,sorting:z},onExpandedChange:$,onSortingChange:D,getRowCanExpand:N.some(e=>e.expandedContent)?y:void 0,getPaginationRowModel:r(),getFilteredRowModel:s(),getExpandedRowModel:l(),getSortedRowModel:n()}),I=t(()=>Array.from({length:S}).map((t,a)=>/* @__PURE__ */e.createElement(c,{key:`skeleton-${a}`},N.map((t,n)=>/* @__PURE__ */e.createElement(p,{key:`skeleton-cell-${a}-${n}`,className:"first:pl-4 last:pr-4 py-4",style:{width:t.size}},
|
|
2
2
|
/* @__PURE__ */e.createElement(x,{className:"h-4 w-full"}))))),[S,N]),V=t(()=>F.getRowModel().rows.map(t=>/* @__PURE__ */e.createElement(e.Fragment,{key:t.original.id||t.id},/* @__PURE__ */e.createElement(c,{"data-state":t.getIsSelected()&&"selected",className:f(t.getIsExpanded()&&"border-b-0")},t.getVisibleCells().map(t=>/* @__PURE__ */e.createElement(p,{key:t.id,className:"first:pl-4 last:pr-4 py-4",style:{width:t.column.getSize()}},i(t.column.columnDef.cell,t.getContext())))),/* @__PURE__ */e.createElement(d,{initial:!1},t.getIsExpanded()&&(()=>{const a=N.find(e=>e.expandedContent);return a?.expandedContent?/* @__PURE__ */e.createElement(e.Fragment,null,/* @__PURE__ */e.createElement(c,{"aria-hidden":!0,role:"presentation",className:"border-none"},/* @__PURE__ */e.createElement(p,{colSpan:t.getVisibleCells().length,className:"p-0 inset-0 h-[1px] w-full"},/* @__PURE__ */e.createElement("div",{className:"custom-dashed-border-b absolute inset-0 h-[1px]"}))),/* @__PURE__ */e.createElement(c,{key:`${t.id}-expanded`},/* @__PURE__ */e.createElement(p,{colSpan:t.getVisibleCells().length,className:f("first:pl-4 last:pr-4 py-4 overflow-hidden",k)},
|
|
3
3
|
/* @__PURE__ */e.createElement(m.div,{variants:w,initial:"initial",animate:"animate",exit:"exit"},a.expandedContent(t))))):null})()))),[F,N,k]),j=F.getRowModel().rows?.length;/* @__PURE__ */
|
|
4
4
|
return e.createElement("div",{className:f("overflow-hidden rounded-md border border-border bg-card",C),...v},/* @__PURE__ */e.createElement(g,{className:"overflow-hidden"},/* @__PURE__ */e.createElement(u,null,F.getHeaderGroups().map(t=>/* @__PURE__ */e.createElement(c,{key:t.id},t.headers.map(t=>/* @__PURE__ */e.createElement(h,{key:t.id,className:"space-x-4 first:pl-4 last:pr-4 py-4 text-current",style:{width:t.getSize()}},t.isPlaceholder?null:i(t.column.columnDef.header,t.getContext())))))),/* @__PURE__ */e.createElement(E,null,R?I():j?V():/* @__PURE__ */e.createElement(c,null,/* @__PURE__ */e.createElement(p,{colSpan:N.length,className:"h-24 text-center"},"No results.")))))}export{N as D};
|
|
5
|
-
//# sourceMappingURL=data-table.
|
|
5
|
+
//# sourceMappingURL=data-table.Dn7VQJFo.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"data-table.1ptJ47z8.js","sources":["../../../src/components/data-table/data-table.tsx"],"sourcesContent":["import React, { useCallback } from 'react';\nimport {\n ColumnDef,\n flexRender,\n getCoreRowModel,\n useReactTable,\n ExpandedState,\n SortingState,\n getPaginationRowModel,\n getFilteredRowModel,\n getExpandedRowModel,\n getSortedRowModel,\n Row,\n} from '@tanstack/react-table';\nimport { motion, AnimatePresence } from 'framer-motion';\n\nimport { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '../ui/table';\n\nimport { cn } from '@/lib/utils';\n\n// Skeleton component for loading state\nconst Skeleton = ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) => (\n <div className={cn('animate-original-pulse rounded-md bg-muted', className)} {...props} />\n);\n\n// Framer Motion Accordion Variants for bouncy accordion effect\nconst accordionVariants = {\n initial: {\n height: 0,\n },\n animate: {\n height: 'auto',\n transition: {\n height: {\n type: 'spring',\n stiffness: 450, // increase to make it more stiff (less bouncy), therefore increasing the speed of the animation\n damping: 20, // increase to make it more dampened and slow\n },\n },\n },\n exit: {\n height: 0,\n transition: {\n height: {\n duration: 0.1,\n ease: 'linear',\n },\n },\n },\n};\n\nexport type ExtendedColumnDef<TData, TValue = unknown> = ColumnDef<TData, TValue> & {\n expandedContent?: (row: Row<TData>) => React.ReactNode;\n};\n\nexport interface DataTableProps<TData, TValue> extends React.HTMLAttributes<HTMLDivElement> {\n columns: ExtendedColumnDef<TData, TValue>[];\n data: TData[];\n getRowCanExpand?: (row: Row<TData>) => boolean;\n className?: string;\n expandeRowClassName?: string;\n isLoading?: boolean;\n skeletonRowCount?: number;\n}\n\nexport function DataTable<TData extends Record<string, any> & { id?: string | number }, TValue>({\n columns,\n data,\n getRowCanExpand = () => true,\n className,\n expandeRowClassName,\n isLoading = false,\n skeletonRowCount = 10,\n ...props\n}: DataTableProps<TData, TValue>) {\n const [expanded, setExpanded] = React.useState<ExpandedState>({});\n const [sorting, setSorting] = React.useState<SortingState>([]);\n\n // Reset expanded state when data changes. Collapse all rows when data changes.\n React.useEffect(() => {\n setExpanded({});\n }, [data]);\n\n const table = useReactTable({\n data,\n columns,\n getCoreRowModel: getCoreRowModel(),\n state: {\n expanded,\n sorting,\n },\n onExpandedChange: setExpanded,\n onSortingChange: setSorting,\n getRowCanExpand: columns.some((col) => col.expandedContent) ? getRowCanExpand : undefined,\n getPaginationRowModel: getPaginationRowModel(),\n getFilteredRowModel: getFilteredRowModel(),\n getExpandedRowModel: getExpandedRowModel(),\n getSortedRowModel: getSortedRowModel(),\n });\n\n // Render the skeleton rows for loading state\n const renderSkeletonRows = useCallback(() => {\n return Array.from({ length: skeletonRowCount }).map((_, index) => (\n <TableRow key={`skeleton-${index}`}>\n {columns.map((column, colIndex) => (\n <TableCell\n key={`skeleton-cell-${index}-${colIndex}`}\n className=\"first:pl-4 last:pr-4 py-4\"\n style={{ width: column.size }}\n >\n <Skeleton className=\"h-4 w-full\" />\n </TableCell>\n ))}\n </TableRow>\n ));\n }, [skeletonRowCount, columns]);\n\n // Render the table rows\n const renderTableRows = useCallback(() => {\n return table.getRowModel().rows.map((row) => (\n <React.Fragment key={row.original.id || row.id}>\n <TableRow data-state={row.getIsSelected() && 'selected'} className={cn(row.getIsExpanded() && 'border-b-0')}>\n {row.getVisibleCells().map((cell) => (\n <TableCell key={cell.id} className=\"first:pl-4 last:pr-4 py-4\" style={{ width: cell.column.getSize() }}>\n {flexRender(cell.column.columnDef.cell, cell.getContext())}\n </TableCell>\n ))}\n </TableRow>\n <AnimatePresence initial={false}>\n {row.getIsExpanded() &&\n (() => {\n // Find the first column with expandedContent\n const expandedColumn = columns.find((col) => col.expandedContent);\n\n return expandedColumn?.expandedContent ? (\n <>\n <TableRow aria-hidden role=\"presentation\" className=\"border-none\">\n <TableCell colSpan={row.getVisibleCells().length} className=\"p-0 inset-0 h-[1px] w-full\">\n <div className=\"custom-dashed-border-b absolute inset-0 h-[1px]\" />\n </TableCell>\n </TableRow>\n <TableRow key={`${row.id}-expanded`}>\n <TableCell\n colSpan={row.getVisibleCells().length}\n className={cn('first:pl-4 last:pr-4 py-4 overflow-hidden', expandeRowClassName)}\n >\n <motion.div variants={accordionVariants} initial=\"initial\" animate=\"animate\" exit=\"exit\">\n {expandedColumn.expandedContent(row)}\n </motion.div>\n </TableCell>\n </TableRow>\n </>\n ) : null;\n })()}\n </AnimatePresence>\n </React.Fragment>\n ));\n }, [table, columns, expandeRowClassName]);\n\n const hasResults = table.getRowModel().rows?.length;\n\n return (\n <div className={cn('overflow-hidden rounded-md border border-border bg-card', className)} {...props}>\n <Table className=\"overflow-hidden\">\n <TableHeader>\n {table.getHeaderGroups().map((headerGroup) => (\n <TableRow key={headerGroup.id}>\n {headerGroup.headers.map((header) => (\n <TableHead\n key={header.id}\n className=\"space-x-4 first:pl-4 last:pr-4 py-4 text-current\"\n style={{ width: header.getSize() }}\n >\n {header.isPlaceholder ? null : flexRender(header.column.columnDef.header, header.getContext())}\n </TableHead>\n ))}\n </TableRow>\n ))}\n </TableHeader>\n <TableBody>\n {isLoading ? (\n renderSkeletonRows()\n ) : hasResults ? (\n renderTableRows()\n ) : (\n <TableRow>\n <TableCell colSpan={columns.length} className=\"h-24 text-center\">\n No results.\n </TableCell>\n </TableRow>\n )}\n </TableBody>\n </Table>\n </div>\n );\n}\n"],"names":["Skeleton","className","props","React","createElement","cn","accordionVariants","initial","height","animate","transition","type","stiffness","damping","exit","duration","ease","DataTable","columns","data","getRowCanExpand","expandeRowClassName","isLoading","skeletonRowCount","expanded","setExpanded","useState","sorting","setSorting","useEffect","table","useReactTable","getCoreRowModel","state","onExpandedChange","onSortingChange","some","col","expandedContent","getPaginationRowModel","getFilteredRowModel","getExpandedRowModel","getSortedRowModel","renderSkeletonRows","useCallback","Array","from","length","map","_","index","TableRow","key","column","colIndex","TableCell","style","width","size","renderTableRows","getRowModel","rows","row","Fragment","original","id","getIsSelected","getIsExpanded","getVisibleCells","cell","getSize","flexRender","columnDef","getContext","AnimatePresence","expandedColumn","find","role","colSpan","motion","div","variants","hasResults","Table","TableHeader","getHeaderGroups","headerGroup","headers","header","TableHead","isPlaceholder","TableBody"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"data-table.Dn7VQJFo.js","sources":["../../../src/components/data-table/data-table.tsx"],"sourcesContent":["import React, { useCallback } from 'react';\nimport {\n ColumnDef,\n flexRender,\n getCoreRowModel,\n useReactTable,\n ExpandedState,\n SortingState,\n getPaginationRowModel,\n getFilteredRowModel,\n getExpandedRowModel,\n getSortedRowModel,\n Row,\n} from '@tanstack/react-table';\nimport { motion, AnimatePresence } from 'framer-motion';\n\nimport { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '../ui/table';\n\nimport { cn } from '@/lib/utils';\n\n// Skeleton component for loading state\nconst Skeleton = ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) => (\n <div className={cn('animate-original-pulse rounded-md bg-muted', className)} {...props} />\n);\n\n// Framer Motion Accordion Variants for bouncy accordion effect\nconst accordionVariants = {\n initial: {\n height: 0,\n },\n animate: {\n height: 'auto',\n transition: {\n height: {\n type: 'spring',\n stiffness: 450, // increase to make it more stiff (less bouncy), therefore increasing the speed of the animation\n damping: 20, // increase to make it more dampened and slow\n },\n },\n },\n exit: {\n height: 0,\n transition: {\n height: {\n duration: 0.1,\n ease: 'linear',\n },\n },\n },\n};\n\nexport type ExtendedColumnDef<TData, TValue = unknown> = ColumnDef<TData, TValue> & {\n expandedContent?: (row: Row<TData>) => React.ReactNode;\n};\n\nexport interface DataTableProps<TData, TValue> extends React.HTMLAttributes<HTMLDivElement> {\n columns: ExtendedColumnDef<TData, TValue>[];\n data: TData[];\n getRowCanExpand?: (row: Row<TData>) => boolean;\n className?: string;\n expandeRowClassName?: string;\n isLoading?: boolean;\n skeletonRowCount?: number;\n}\n\nexport function DataTable<TData extends Record<string, any> & { id?: string | number }, TValue>({\n columns,\n data,\n getRowCanExpand = () => true,\n className,\n expandeRowClassName,\n isLoading = false,\n skeletonRowCount = 10,\n ...props\n}: DataTableProps<TData, TValue>) {\n const [expanded, setExpanded] = React.useState<ExpandedState>({});\n const [sorting, setSorting] = React.useState<SortingState>([]);\n\n // Reset expanded state when data changes. Collapse all rows when data changes.\n React.useEffect(() => {\n setExpanded({});\n }, [data]);\n\n const table = useReactTable({\n data,\n columns,\n getCoreRowModel: getCoreRowModel(),\n state: {\n expanded,\n sorting,\n },\n onExpandedChange: setExpanded,\n onSortingChange: setSorting,\n getRowCanExpand: columns.some((col) => col.expandedContent) ? getRowCanExpand : undefined,\n getPaginationRowModel: getPaginationRowModel(),\n getFilteredRowModel: getFilteredRowModel(),\n getExpandedRowModel: getExpandedRowModel(),\n getSortedRowModel: getSortedRowModel(),\n });\n\n // Render the skeleton rows for loading state\n const renderSkeletonRows = useCallback(() => {\n return Array.from({ length: skeletonRowCount }).map((_, index) => (\n <TableRow key={`skeleton-${index}`}>\n {columns.map((column, colIndex) => (\n <TableCell\n key={`skeleton-cell-${index}-${colIndex}`}\n className=\"first:pl-4 last:pr-4 py-4\"\n style={{ width: column.size }}\n >\n <Skeleton className=\"h-4 w-full\" />\n </TableCell>\n ))}\n </TableRow>\n ));\n }, [skeletonRowCount, columns]);\n\n // Render the table rows\n const renderTableRows = useCallback(() => {\n return table.getRowModel().rows.map((row) => (\n <React.Fragment key={row.original.id || row.id}>\n <TableRow data-state={row.getIsSelected() && 'selected'} className={cn(row.getIsExpanded() && 'border-b-0')}>\n {row.getVisibleCells().map((cell) => (\n <TableCell key={cell.id} className=\"first:pl-4 last:pr-4 py-4\" style={{ width: cell.column.getSize() }}>\n {flexRender(cell.column.columnDef.cell, cell.getContext())}\n </TableCell>\n ))}\n </TableRow>\n <AnimatePresence initial={false}>\n {row.getIsExpanded() &&\n (() => {\n // Find the first column with expandedContent\n const expandedColumn = columns.find((col) => col.expandedContent);\n\n return expandedColumn?.expandedContent ? (\n <>\n <TableRow aria-hidden role=\"presentation\" className=\"border-none\">\n <TableCell colSpan={row.getVisibleCells().length} className=\"p-0 inset-0 h-[1px] w-full\">\n <div className=\"custom-dashed-border-b absolute inset-0 h-[1px]\" />\n </TableCell>\n </TableRow>\n <TableRow key={`${row.id}-expanded`}>\n <TableCell\n colSpan={row.getVisibleCells().length}\n className={cn('first:pl-4 last:pr-4 py-4 overflow-hidden', expandeRowClassName)}\n >\n <motion.div variants={accordionVariants} initial=\"initial\" animate=\"animate\" exit=\"exit\">\n {expandedColumn.expandedContent(row)}\n </motion.div>\n </TableCell>\n </TableRow>\n </>\n ) : null;\n })()}\n </AnimatePresence>\n </React.Fragment>\n ));\n }, [table, columns, expandeRowClassName]);\n\n const hasResults = table.getRowModel().rows?.length;\n\n return (\n <div className={cn('overflow-hidden rounded-md border border-border bg-card', className)} {...props}>\n <Table className=\"overflow-hidden\">\n <TableHeader>\n {table.getHeaderGroups().map((headerGroup) => (\n <TableRow key={headerGroup.id}>\n {headerGroup.headers.map((header) => (\n <TableHead\n key={header.id}\n className=\"space-x-4 first:pl-4 last:pr-4 py-4 text-current\"\n style={{ width: header.getSize() }}\n >\n {header.isPlaceholder ? null : flexRender(header.column.columnDef.header, header.getContext())}\n </TableHead>\n ))}\n </TableRow>\n ))}\n </TableHeader>\n <TableBody>\n {isLoading ? (\n renderSkeletonRows()\n ) : hasResults ? (\n renderTableRows()\n ) : (\n <TableRow>\n <TableCell colSpan={columns.length} className=\"h-24 text-center\">\n No results.\n </TableCell>\n </TableRow>\n )}\n </TableBody>\n </Table>\n </div>\n );\n}\n"],"names":["Skeleton","className","props","React","createElement","cn","accordionVariants","initial","height","animate","transition","type","stiffness","damping","exit","duration","ease","DataTable","columns","data","getRowCanExpand","expandeRowClassName","isLoading","skeletonRowCount","expanded","setExpanded","useState","sorting","setSorting","useEffect","table","useReactTable","getCoreRowModel","state","onExpandedChange","onSortingChange","some","col","expandedContent","getPaginationRowModel","getFilteredRowModel","getExpandedRowModel","getSortedRowModel","renderSkeletonRows","useCallback","Array","from","length","map","_","index","TableRow","key","column","colIndex","TableCell","style","width","size","renderTableRows","getRowModel","rows","row","Fragment","original","id","getIsSelected","getIsExpanded","getVisibleCells","cell","getSize","flexRender","columnDef","getContext","AnimatePresence","expandedColumn","find","role","colSpan","motion","div","variants","hasResults","Table","TableHeader","getHeaderGroups","headerGroup","headers","header","TableHead","isPlaceholder","TableBody"],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import*as e from"react";import{format as t}from"date-fns";import{CalendarBlank as a}from"@phosphor-icons/react";import{c as r}from"./utils.DtKoarLP.js";import{B as o}from"./button.
|
|
1
|
+
import*as e from"react";import{format as t}from"date-fns";import{CalendarBlank as a}from"@phosphor-icons/react";import{c as r}from"./utils.DtKoarLP.js";import{B as o}from"./button.DXe2tRBO.js";import{Calendar as s}from"../components/ui/calendar.js";import{Popover as m,PopoverTrigger as l,PopoverContent as n}from"../components/ui/popover.js";import '../date-picker.css';function c({date:c,setDate:i,className:p,placeholder:f="Select date"}){/* @__PURE__ */
|
|
2
2
|
return e.createElement(m,null,/* @__PURE__ */e.createElement(l,{asChild:!0},/* @__PURE__ */e.createElement(o,{variant:"outline",className:r("w-full justify-start text-left font-normal text-base",!c&&"text-muted-foreground",p)},
|
|
3
3
|
/* @__PURE__ */e.createElement(a,{className:"mr-2 !w-5 !h-5"}),c?t(c,"PPP"):f)),/* @__PURE__ */e.createElement(n,{className:"w-auto p-0 z-[9999]"},/* @__PURE__ */e.createElement(s,{mode:"single",selected:c,onSelect:i,className:"single-date-picker-calendar"})))}export{c as D};
|
|
4
|
-
//# sourceMappingURL=date-picker.
|
|
4
|
+
//# sourceMappingURL=date-picker.GRONonNX.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"date-picker.
|
|
1
|
+
{"version":3,"file":"date-picker.GRONonNX.js","sources":["../../../src/components/date-picker/date-picker.tsx"],"sourcesContent":["import * as React from 'react';\nimport { format } from 'date-fns';\nimport { CalendarBlank as CalendarIcon } from '@phosphor-icons/react';\n\nimport { cn } from '@/lib/utils';\nimport { Button } from '@/components/ui/button';\nimport { Calendar } from '@/components/ui/calendar';\nimport { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover';\nimport '../ui/calendar.css';\n\ninterface DatePickerProps {\n date: Date | undefined;\n setDate: (date: Date | undefined) => void;\n className?: string;\n placeholder?: string;\n}\n\nexport function DatePicker({ date, setDate, className, placeholder = 'Select date' }: DatePickerProps) {\n return (\n <Popover>\n <PopoverTrigger asChild>\n <Button\n variant=\"outline\"\n className={cn(\n 'w-full justify-start text-left font-normal text-base',\n !date && 'text-muted-foreground',\n className,\n )}\n >\n <CalendarIcon className=\"mr-2 !w-5 !h-5\" />\n {date ? format(date, 'PPP') : placeholder}\n </Button>\n </PopoverTrigger>\n <PopoverContent className=\"w-auto p-0 z-[9999]\">\n <Calendar mode=\"single\" selected={date} onSelect={setDate} className=\"single-date-picker-calendar\" />\n </PopoverContent>\n </Popover>\n );\n}\n"],"names":["DatePicker","date","setDate","className","placeholder","React","createElement","Popover","PopoverTrigger","asChild","Button","variant","cn","CalendarIcon","format","PopoverContent","Calendar","mode","selected","onSelect"],"mappings":"uVAiBO,SAASA,GAAWC,KAAEA,EAAAC,QAAMA,YAASC,EAAAC,YAAWA,EAAc;AACnE,OACEC,EAAAC,cAACC,EAAA,oBACCF,EAAAC,cAACE,EAAA,CAAeC,SAAO,kBACrBJ,EAAAC,cAACI,EAAA,CACCC,QAAQ,UACRR,UAAWS,EACT,wDACCX,GAAQ,wBACTE;eAGFE,EAAAC,cAACO,EAAA,CAAaV,UAAU,mBACvBF,EAAOa,EAAOb,EAAM,OAASG,mBAGlCC,EAAAC,cAACS,EAAA,CAAeZ,UAAU,sCACxBE,EAAAC,cAACU,EAAA,CAASC,KAAK,SAASC,SAAUjB,EAAMkB,SAAUjB,EAASC,UAAU,iCAI7E"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import e,{useState as t,useRef as a,useEffect as n}from"react";import{PaperPlaneRight as r,X as l,Heart as i,ThumbsUp as o,ThumbsDown as c}from"@phosphor-icons/react";import{AnimatePresence as s,motion as m}from"framer-motion";import{Card as d,CardContent as u,CardFooter as p}from"../components/ui/card.js";import{Textarea as f}from"../components/ui/textarea.js";import{B as h}from"./button.
|
|
1
|
+
import e,{useState as t,useRef as a,useEffect as n}from"react";import{PaperPlaneRight as r,X as l,Heart as i,ThumbsUp as o,ThumbsDown as c}from"@phosphor-icons/react";import{AnimatePresence as s,motion as m}from"framer-motion";import{Card as d,CardContent as u,CardFooter as p}from"../components/ui/card.js";import{Textarea as f}from"../components/ui/textarea.js";import{B as h}from"./button.DXe2tRBO.js";import{TooltipProvider as E,Tooltip as b,TooltipTrigger as g,TooltipContent as y}from"../components/ui/tooltip.js";import{c as v}from"./utils.DtKoarLP.js";function x({open:i,onSubmit:o,thankYouText:c="Thank you for your feedback!",placeholder:E="What could we have done better? Your feedback is valuable to us...",maxLength:b=500}){const[g,y]=t(""),[v,x]=t(!1),k=a(null);n(()=>{i&&(y(""),x(!1),setTimeout(()=>k.current?.focus(),0))},[i]);const N=()=>{g.trim()&&(o?.(g),x(!0))};/* @__PURE__ */
|
|
2
2
|
return e.createElement(s,null,i&&!v&&/* @__PURE__ */e.createElement(m.div,{initial:{opacity:0,y:12},animate:{opacity:1,y:0},exit:{opacity:0,y:12},transition:{duration:.25,ease:[.4,0,.2,1]}},
|
|
3
3
|
/* @__PURE__ */e.createElement(d,{className:"gap-2 p-3"},/* @__PURE__ */e.createElement(u,{className:"px-0"},/* @__PURE__ */e.createElement(f,{ref:k,placeholder:E,className:"w-full border-none shadow-none focus-visible:ring-0 p-0",maxLength:b,value:g,rows:4,onChange:e=>y(e.target.value),onKeyDown:e=>{"Enter"!==e.key||e.shiftKey||(e.preventDefault(),N())}}),/* @__PURE__ */e.createElement("div",{className:"flex justify-end mt-1"},/* @__PURE__ */e.createElement("span",{className:"text-xs text-muted-foreground select-none"},b-g.length," characters remaining"))),/* @__PURE__ */e.createElement(p,{className:"p-0 gap-2 flex-row-reverse"},/* @__PURE__ */e.createElement(h,{size:"icon",onClick:N,disabled:!g.length,"aria-label":"Submit feedback"},/* @__PURE__ */e.createElement(r,{"aria-hidden":"true",weight:"bold"})),/* @__PURE__ */e.createElement(h,{size:"icon",variant:"ghost",onClick:()=>{y(""),k.current?.focus()},"aria-label":"Cancel feedback"},
|
|
4
4
|
/* @__PURE__ */e.createElement(l,{"aria-hidden":"true",weight:"bold"}))))),i&&v&&/* @__PURE__ */e.createElement(m.div,{initial:{opacity:0,y:12},animate:{opacity:1,y:0},exit:{opacity:0,y:12},transition:{duration:.25,ease:[.4,0,.2,1]}},
|
|
@@ -10,4 +10,4 @@ return e.createElement("div",{className:"flex flex-col gap-2"},/* @__PURE__ */e.
|
|
|
10
10
|
/* @__PURE__ */e.createElement(o,{weight:"bold"})))),/* @__PURE__ */e.createElement(y,null,/* @__PURE__ */e.createElement("p",null,i.positiveAnswerText||"Helpful"))))),/* @__PURE__ */e.createElement(E,null,/* @__PURE__ */e.createElement(b,null,/* @__PURE__ */e.createElement(g,{asChild:!0},/* @__PURE__ */e.createElement(h,{variant:"ghost",size:"sm",className:"rounded-md size-9 flex items-center justify-center transition-all duration-200 transform hover:scale-105 active:scale-95 "+("reject"===r?"bg-red-100 text-red-600 hover:bg-red-200":"text-dark-500"),onClick:()=>z("reject"),disabled:d},
|
|
11
11
|
/* @__PURE__ */e.createElement(m.div,{initial:{scale:1},animate:{scale:"reject"===r?[1,1.2,1]:1},transition:{duration:.3}},
|
|
12
12
|
/* @__PURE__ */e.createElement(c,{weight:"bold"})))),/* @__PURE__ */e.createElement(y,null,/* @__PURE__ */e.createElement("p",null,i.negativeAnswerText||"Not helpful"))))),/* @__PURE__ */e.createElement(s,null,j&&/* @__PURE__ */e.createElement(x,{open:j,onSubmit:f,thankYouText:v,placeholder:p,maxLength:u})))}export{N as F};
|
|
13
|
-
//# sourceMappingURL=feedback.
|
|
13
|
+
//# sourceMappingURL=feedback.nVBNjdPh.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"feedback.aGVWiKHH.js","sources":["../../../src/components/feedback/feedback-reason.tsx","../../../src/components/love/love.tsx","../../../src/components/feedback/feedback.tsx"],"sourcesContent":["import React, { useRef, useEffect, useState } from 'react';\nimport { motion, AnimatePresence } from 'framer-motion';\nimport { PaperPlaneRight, X } from '@phosphor-icons/react';\n\nimport { Card, CardContent, CardFooter } from '@/components/ui/card';\nimport { Textarea } from '@/components/ui/textarea';\nimport { Button } from '@/components/ui/button';\n\ninterface FeedbackReasonProps {\n open: boolean;\n onSubmit?: (reason: string) => void;\n thankYouText?: string;\n placeholder?: string;\n maxLength?: number;\n}\n\nexport function FeedbackReason({\n open,\n onSubmit,\n thankYouText = 'Thank you for your feedback!',\n placeholder = 'What could we have done better? Your feedback is valuable to us...',\n maxLength = 500,\n}: FeedbackReasonProps) {\n const [reason, setReason] = useState('');\n const [submitted, setSubmitted] = useState(false);\n const textareaRef = useRef<HTMLTextAreaElement>(null);\n\n useEffect(() => {\n if (open) {\n setReason('');\n setSubmitted(false);\n setTimeout(() => textareaRef.current?.focus(), 0);\n }\n }, [open]);\n\n const handleSubmit = () => {\n if (reason.trim()) {\n onSubmit?.(reason);\n setSubmitted(true);\n }\n };\n\n return (\n <AnimatePresence>\n {open && !submitted && (\n <motion.div\n initial={{ opacity: 0, y: 12 }}\n animate={{ opacity: 1, y: 0 }}\n exit={{ opacity: 0, y: 12 }}\n transition={{ duration: 0.25, ease: [0.4, 0, 0.2, 1] }}\n >\n <Card className=\"gap-2 p-3\">\n <CardContent className=\"px-0\">\n <Textarea\n ref={textareaRef}\n placeholder={placeholder}\n className=\"w-full border-none shadow-none focus-visible:ring-0 p-0\"\n maxLength={maxLength}\n value={reason}\n rows={4}\n onChange={(e) => setReason(e.target.value)}\n onKeyDown={(e) => {\n if (e.key === 'Enter' && !e.shiftKey) {\n e.preventDefault();\n handleSubmit();\n }\n }}\n />\n <div className=\"flex justify-end mt-1\">\n <span className=\"text-xs text-muted-foreground select-none\">\n {maxLength - reason.length} characters remaining\n </span>\n </div>\n </CardContent>\n <CardFooter className=\"p-0 gap-2 flex-row-reverse\">\n <Button size=\"icon\" onClick={handleSubmit} disabled={!reason.length} aria-label=\"Submit feedback\">\n <PaperPlaneRight aria-hidden=\"true\" weight=\"bold\" />\n </Button>\n <Button\n size=\"icon\"\n variant=\"ghost\"\n onClick={() => {\n setReason('');\n textareaRef.current?.focus();\n }}\n aria-label=\"Cancel feedback\"\n >\n <X aria-hidden=\"true\" weight=\"bold\" />\n </Button>\n </CardFooter>\n </Card>\n </motion.div>\n )}\n {open && submitted && (\n <motion.div\n initial={{ opacity: 0, y: 12 }}\n animate={{ opacity: 1, y: 0 }}\n exit={{ opacity: 0, y: 12 }}\n transition={{ duration: 0.25, ease: [0.4, 0, 0.2, 1] }}\n >\n <Card className=\"gap-2 p-3\">\n <CardContent className=\"px-0\">\n <p>{thankYouText}</p>\n </CardContent>\n </Card>\n </motion.div>\n )}\n </AnimatePresence>\n );\n}\n","import { Heart } from '@phosphor-icons/react';\nimport { AnimatePresence, motion } from 'framer-motion';\nimport React from 'react';\n\nimport { cn } from '@/lib/utils';\n\ninterface LoveProps extends React.HTMLAttributes<HTMLDivElement> {\n className?: string;\n doAnimation?: boolean;\n}\n\nexport function Love({ className, children, doAnimation = false, ...props }: LoveProps) {\n return (\n <div className={cn('relative', className)} {...props}>\n <AnimatePresence>\n {doAnimation && (\n <>\n {Array.from({ length: 8 }).map((_, i) => (\n <motion.div\n key={i}\n className=\"absolute top-1/2 left-1/2 origin-center pointer-events-none\"\n initial={{ opacity: 0, scale: 0.3, x: 0, y: 0 }}\n animate={{\n opacity: [0, 1, 1, 0],\n scale: [0.3, 1, 1, 0],\n x: [0, Math.cos(i * (Math.PI / 4)) * 30],\n y: [0, Math.sin(i * (Math.PI / 4)) * 30],\n rotate: [0, i % 2 ? 45 : -45],\n }}\n transition={{\n duration: 1.2,\n ease: [0.4, 0, 0.2, 1],\n times: [0, 0.3, 0.7, 1],\n delay: i * 0.1,\n }}\n >\n <Heart\n className=\"size-4 text-rose-500\"\n style={{\n filter: 'drop-shadow(0 0 3px rgba(255, 75, 110, 0.8))',\n strokeWidth: 2.5,\n }}\n />\n </motion.div>\n ))}\n <motion.div\n className=\"absolute inset-0 rounded-full bg-primary pointer-events-none\"\n initial={{ opacity: 0, scale: 0.8 }}\n animate={{\n opacity: [0, 0.15, 0.15, 0],\n scale: [0.8, 1.8, 1.8, 2],\n }}\n transition={{\n duration: 1.2,\n ease: 'easeOut',\n times: [0, 0.3, 0.7, 1],\n }}\n />\n </>\n )}\n </AnimatePresence>\n {children}\n </div>\n );\n}\n","import React, { useState, useRef, useEffect } from 'react';\nimport { ThumbsUp, ThumbsDown } from '@phosphor-icons/react';\nimport { motion, AnimatePresence } from 'framer-motion';\n\nimport { FeedbackReason } from './feedback-reason';\nimport { Love } from '../love';\n\nimport { Button } from '@/components/ui/button';\nimport { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/components/ui/tooltip';\n\nexport type FeedbackResponse = 'accept' | 'reject';\n\ninterface FeedbackProps {\n feedback?: FeedbackResponse;\n onFeedback?: (response: FeedbackResponse) => void;\n textConfig?: {\n positiveAnswerText?: string;\n negativeAnswerText?: string;\n };\n disabled?: boolean;\n feedbackReasonLength?: number;\n feedbackReasonPlaceholder?: string;\n onFeedbackReasonSubmit?: (reason: string) => void;\n feedbackReasonThankYouText?: string;\n}\n\nexport function Feedback({\n feedback,\n onFeedback,\n textConfig = {},\n disabled = false,\n feedbackReasonLength = 500,\n feedbackReasonPlaceholder = 'What could we have done better? Your feedback is valuable to us...',\n onFeedbackReasonSubmit,\n feedbackReasonThankYouText = 'Thank you for your feedback!',\n}: FeedbackProps) {\n const [showHearts, setShowHearts] = useState(false);\n const [showFeedbackReason, setShowFeedbackReason] = useState(false);\n const textareaRef = useRef<HTMLTextAreaElement>(null);\n\n useEffect(() => {\n if (showFeedbackReason && textareaRef.current) {\n textareaRef.current.focus();\n }\n }, [showFeedbackReason]);\n\n const handleFeedback = (response: FeedbackResponse) => {\n if (onFeedback) {\n if (response === 'accept') {\n setShowHearts(true);\n setTimeout(() => setShowHearts(false), 2000);\n }\n onFeedback(response);\n if (response === 'reject') {\n setShowFeedbackReason(true);\n }\n }\n };\n\n return (\n <div className=\"flex flex-col gap-2\">\n <div className=\"flex justify-end gap-2\" data-name=\"Feedback\">\n <TooltipProvider>\n <Love doAnimation={showHearts}>\n <Tooltip>\n <TooltipTrigger asChild>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n className={`rounded-md size-9 flex items-center justify-center transition-all duration-200 transform hover:scale-105 active:scale-95 ${\n feedback === 'accept' ? 'bg-green-100 text-green-600 hover:bg-green-200' : 'text-dark-500'\n }`}\n onClick={() => {\n handleFeedback('accept');\n setShowFeedbackReason(false);\n }}\n disabled={disabled}\n >\n <motion.div\n initial={{ scale: 1 }}\n animate={{ scale: feedback === 'accept' ? [1, 1.2, 1] : 1 }}\n transition={{ duration: 0.3 }}\n >\n <ThumbsUp weight=\"bold\" />\n </motion.div>\n </Button>\n </TooltipTrigger>\n <TooltipContent>\n <p>{textConfig.positiveAnswerText || 'Helpful'}</p>\n </TooltipContent>\n </Tooltip>\n </Love>\n </TooltipProvider>\n <TooltipProvider>\n <Tooltip>\n <TooltipTrigger asChild>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n className={`rounded-md size-9 flex items-center justify-center transition-all duration-200 transform hover:scale-105 active:scale-95 ${\n feedback === 'reject' ? 'bg-red-100 text-red-600 hover:bg-red-200' : 'text-dark-500'\n }`}\n onClick={() => handleFeedback('reject')}\n disabled={disabled}\n >\n <motion.div\n initial={{ scale: 1 }}\n animate={{ scale: feedback === 'reject' ? [1, 1.2, 1] : 1 }}\n transition={{ duration: 0.3 }}\n >\n <ThumbsDown weight=\"bold\" />\n </motion.div>\n </Button>\n </TooltipTrigger>\n <TooltipContent>\n <p>{textConfig.negativeAnswerText || 'Not helpful'}</p>\n </TooltipContent>\n </Tooltip>\n </TooltipProvider>\n </div>\n <AnimatePresence>\n {showFeedbackReason && (\n <FeedbackReason\n open={showFeedbackReason}\n onSubmit={onFeedbackReasonSubmit}\n thankYouText={feedbackReasonThankYouText}\n placeholder={feedbackReasonPlaceholder}\n maxLength={feedbackReasonLength}\n />\n )}\n </AnimatePresence>\n </div>\n );\n}\n"],"names":["FeedbackReason","open","onSubmit","thankYouText","placeholder","maxLength","reason","setReason","useState","submitted","setSubmitted","textareaRef","useRef","useEffect","setTimeout","current","focus","handleSubmit","trim","React","createElement","AnimatePresence","motion","div","initial","opacity","y","animate","exit","transition","duration","ease","Card","className","CardContent","Textarea","ref","value","rows","onChange","e","target","onKeyDown","key","shiftKey","preventDefault","length","CardFooter","Button","size","onClick","disabled","PaperPlaneRight","weight","variant","X","Love","children","doAnimation","props","cn","Fragment","Array","from","map","_","i","scale","x","Math","cos","PI","sin","rotate","times","delay","Heart","style","filter","strokeWidth","Feedback","feedback","onFeedback","textConfig","feedbackReasonLength","feedbackReasonPlaceholder","onFeedbackReasonSubmit","feedbackReasonThankYouText","showHearts","setShowHearts","showFeedbackReason","setShowFeedbackReason","handleFeedback","response","TooltipProvider","Tooltip","TooltipTrigger","asChild","ThumbsUp","TooltipContent","positiveAnswerText","ThumbsDown","negativeAnswerText"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"feedback.nVBNjdPh.js","sources":["../../../src/components/feedback/feedback-reason.tsx","../../../src/components/love/love.tsx","../../../src/components/feedback/feedback.tsx"],"sourcesContent":["import React, { useRef, useEffect, useState } from 'react';\nimport { motion, AnimatePresence } from 'framer-motion';\nimport { PaperPlaneRight, X } from '@phosphor-icons/react';\n\nimport { Card, CardContent, CardFooter } from '@/components/ui/card';\nimport { Textarea } from '@/components/ui/textarea';\nimport { Button } from '@/components/ui/button';\n\ninterface FeedbackReasonProps {\n open: boolean;\n onSubmit?: (reason: string) => void;\n thankYouText?: string;\n placeholder?: string;\n maxLength?: number;\n}\n\nexport function FeedbackReason({\n open,\n onSubmit,\n thankYouText = 'Thank you for your feedback!',\n placeholder = 'What could we have done better? Your feedback is valuable to us...',\n maxLength = 500,\n}: FeedbackReasonProps) {\n const [reason, setReason] = useState('');\n const [submitted, setSubmitted] = useState(false);\n const textareaRef = useRef<HTMLTextAreaElement>(null);\n\n useEffect(() => {\n if (open) {\n setReason('');\n setSubmitted(false);\n setTimeout(() => textareaRef.current?.focus(), 0);\n }\n }, [open]);\n\n const handleSubmit = () => {\n if (reason.trim()) {\n onSubmit?.(reason);\n setSubmitted(true);\n }\n };\n\n return (\n <AnimatePresence>\n {open && !submitted && (\n <motion.div\n initial={{ opacity: 0, y: 12 }}\n animate={{ opacity: 1, y: 0 }}\n exit={{ opacity: 0, y: 12 }}\n transition={{ duration: 0.25, ease: [0.4, 0, 0.2, 1] }}\n >\n <Card className=\"gap-2 p-3\">\n <CardContent className=\"px-0\">\n <Textarea\n ref={textareaRef}\n placeholder={placeholder}\n className=\"w-full border-none shadow-none focus-visible:ring-0 p-0\"\n maxLength={maxLength}\n value={reason}\n rows={4}\n onChange={(e) => setReason(e.target.value)}\n onKeyDown={(e) => {\n if (e.key === 'Enter' && !e.shiftKey) {\n e.preventDefault();\n handleSubmit();\n }\n }}\n />\n <div className=\"flex justify-end mt-1\">\n <span className=\"text-xs text-muted-foreground select-none\">\n {maxLength - reason.length} characters remaining\n </span>\n </div>\n </CardContent>\n <CardFooter className=\"p-0 gap-2 flex-row-reverse\">\n <Button size=\"icon\" onClick={handleSubmit} disabled={!reason.length} aria-label=\"Submit feedback\">\n <PaperPlaneRight aria-hidden=\"true\" weight=\"bold\" />\n </Button>\n <Button\n size=\"icon\"\n variant=\"ghost\"\n onClick={() => {\n setReason('');\n textareaRef.current?.focus();\n }}\n aria-label=\"Cancel feedback\"\n >\n <X aria-hidden=\"true\" weight=\"bold\" />\n </Button>\n </CardFooter>\n </Card>\n </motion.div>\n )}\n {open && submitted && (\n <motion.div\n initial={{ opacity: 0, y: 12 }}\n animate={{ opacity: 1, y: 0 }}\n exit={{ opacity: 0, y: 12 }}\n transition={{ duration: 0.25, ease: [0.4, 0, 0.2, 1] }}\n >\n <Card className=\"gap-2 p-3\">\n <CardContent className=\"px-0\">\n <p>{thankYouText}</p>\n </CardContent>\n </Card>\n </motion.div>\n )}\n </AnimatePresence>\n );\n}\n","import { Heart } from '@phosphor-icons/react';\nimport { AnimatePresence, motion } from 'framer-motion';\nimport React from 'react';\n\nimport { cn } from '@/lib/utils';\n\ninterface LoveProps extends React.HTMLAttributes<HTMLDivElement> {\n className?: string;\n doAnimation?: boolean;\n}\n\nexport function Love({ className, children, doAnimation = false, ...props }: LoveProps) {\n return (\n <div className={cn('relative', className)} {...props}>\n <AnimatePresence>\n {doAnimation && (\n <>\n {Array.from({ length: 8 }).map((_, i) => (\n <motion.div\n key={i}\n className=\"absolute top-1/2 left-1/2 origin-center pointer-events-none\"\n initial={{ opacity: 0, scale: 0.3, x: 0, y: 0 }}\n animate={{\n opacity: [0, 1, 1, 0],\n scale: [0.3, 1, 1, 0],\n x: [0, Math.cos(i * (Math.PI / 4)) * 30],\n y: [0, Math.sin(i * (Math.PI / 4)) * 30],\n rotate: [0, i % 2 ? 45 : -45],\n }}\n transition={{\n duration: 1.2,\n ease: [0.4, 0, 0.2, 1],\n times: [0, 0.3, 0.7, 1],\n delay: i * 0.1,\n }}\n >\n <Heart\n className=\"size-4 text-rose-500\"\n style={{\n filter: 'drop-shadow(0 0 3px rgba(255, 75, 110, 0.8))',\n strokeWidth: 2.5,\n }}\n />\n </motion.div>\n ))}\n <motion.div\n className=\"absolute inset-0 rounded-full bg-primary pointer-events-none\"\n initial={{ opacity: 0, scale: 0.8 }}\n animate={{\n opacity: [0, 0.15, 0.15, 0],\n scale: [0.8, 1.8, 1.8, 2],\n }}\n transition={{\n duration: 1.2,\n ease: 'easeOut',\n times: [0, 0.3, 0.7, 1],\n }}\n />\n </>\n )}\n </AnimatePresence>\n {children}\n </div>\n );\n}\n","import React, { useState, useRef, useEffect } from 'react';\nimport { ThumbsUp, ThumbsDown } from '@phosphor-icons/react';\nimport { motion, AnimatePresence } from 'framer-motion';\n\nimport { FeedbackReason } from './feedback-reason';\nimport { Love } from '../love';\n\nimport { Button } from '@/components/ui/button';\nimport { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/components/ui/tooltip';\n\nexport type FeedbackResponse = 'accept' | 'reject';\n\ninterface FeedbackProps {\n feedback?: FeedbackResponse;\n onFeedback?: (response: FeedbackResponse) => void;\n textConfig?: {\n positiveAnswerText?: string;\n negativeAnswerText?: string;\n };\n disabled?: boolean;\n feedbackReasonLength?: number;\n feedbackReasonPlaceholder?: string;\n onFeedbackReasonSubmit?: (reason: string) => void;\n feedbackReasonThankYouText?: string;\n}\n\nexport function Feedback({\n feedback,\n onFeedback,\n textConfig = {},\n disabled = false,\n feedbackReasonLength = 500,\n feedbackReasonPlaceholder = 'What could we have done better? Your feedback is valuable to us...',\n onFeedbackReasonSubmit,\n feedbackReasonThankYouText = 'Thank you for your feedback!',\n}: FeedbackProps) {\n const [showHearts, setShowHearts] = useState(false);\n const [showFeedbackReason, setShowFeedbackReason] = useState(false);\n const textareaRef = useRef<HTMLTextAreaElement>(null);\n\n useEffect(() => {\n if (showFeedbackReason && textareaRef.current) {\n textareaRef.current.focus();\n }\n }, [showFeedbackReason]);\n\n const handleFeedback = (response: FeedbackResponse) => {\n if (onFeedback) {\n if (response === 'accept') {\n setShowHearts(true);\n setTimeout(() => setShowHearts(false), 2000);\n }\n onFeedback(response);\n if (response === 'reject') {\n setShowFeedbackReason(true);\n }\n }\n };\n\n return (\n <div className=\"flex flex-col gap-2\">\n <div className=\"flex justify-end gap-2\" data-name=\"Feedback\">\n <TooltipProvider>\n <Love doAnimation={showHearts}>\n <Tooltip>\n <TooltipTrigger asChild>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n className={`rounded-md size-9 flex items-center justify-center transition-all duration-200 transform hover:scale-105 active:scale-95 ${\n feedback === 'accept' ? 'bg-green-100 text-green-600 hover:bg-green-200' : 'text-dark-500'\n }`}\n onClick={() => {\n handleFeedback('accept');\n setShowFeedbackReason(false);\n }}\n disabled={disabled}\n >\n <motion.div\n initial={{ scale: 1 }}\n animate={{ scale: feedback === 'accept' ? [1, 1.2, 1] : 1 }}\n transition={{ duration: 0.3 }}\n >\n <ThumbsUp weight=\"bold\" />\n </motion.div>\n </Button>\n </TooltipTrigger>\n <TooltipContent>\n <p>{textConfig.positiveAnswerText || 'Helpful'}</p>\n </TooltipContent>\n </Tooltip>\n </Love>\n </TooltipProvider>\n <TooltipProvider>\n <Tooltip>\n <TooltipTrigger asChild>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n className={`rounded-md size-9 flex items-center justify-center transition-all duration-200 transform hover:scale-105 active:scale-95 ${\n feedback === 'reject' ? 'bg-red-100 text-red-600 hover:bg-red-200' : 'text-dark-500'\n }`}\n onClick={() => handleFeedback('reject')}\n disabled={disabled}\n >\n <motion.div\n initial={{ scale: 1 }}\n animate={{ scale: feedback === 'reject' ? [1, 1.2, 1] : 1 }}\n transition={{ duration: 0.3 }}\n >\n <ThumbsDown weight=\"bold\" />\n </motion.div>\n </Button>\n </TooltipTrigger>\n <TooltipContent>\n <p>{textConfig.negativeAnswerText || 'Not helpful'}</p>\n </TooltipContent>\n </Tooltip>\n </TooltipProvider>\n </div>\n <AnimatePresence>\n {showFeedbackReason && (\n <FeedbackReason\n open={showFeedbackReason}\n onSubmit={onFeedbackReasonSubmit}\n thankYouText={feedbackReasonThankYouText}\n placeholder={feedbackReasonPlaceholder}\n maxLength={feedbackReasonLength}\n />\n )}\n </AnimatePresence>\n </div>\n );\n}\n"],"names":["FeedbackReason","open","onSubmit","thankYouText","placeholder","maxLength","reason","setReason","useState","submitted","setSubmitted","textareaRef","useRef","useEffect","setTimeout","current","focus","handleSubmit","trim","React","createElement","AnimatePresence","motion","div","initial","opacity","y","animate","exit","transition","duration","ease","Card","className","CardContent","Textarea","ref","value","rows","onChange","e","target","onKeyDown","key","shiftKey","preventDefault","length","CardFooter","Button","size","onClick","disabled","PaperPlaneRight","weight","variant","X","Love","children","doAnimation","props","cn","Fragment","Array","from","map","_","i","scale","x","Math","cos","PI","sin","rotate","times","delay","Heart","style","filter","strokeWidth","Feedback","feedback","onFeedback","textConfig","feedbackReasonLength","feedbackReasonPlaceholder","onFeedbackReasonSubmit","feedbackReasonThankYouText","showHearts","setShowHearts","showFeedbackReason","setShowFeedbackReason","handleFeedback","response","TooltipProvider","Tooltip","TooltipTrigger","asChild","ThumbsUp","TooltipContent","positiveAnswerText","ThumbsDown","negativeAnswerText"],"mappings":"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"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import e,{useState as t,useEffect as a,useCallback as s}from"react";import{useDropzone as r}from"react-dropzone";import{CloudArrowUp as l,CaretDown as c,CaretUp as o,FileVideo as n,Circle as m,CheckCircle as i}from"@phosphor-icons/react";import{Card as p,CardContent as d}from"../components/ui/card.js";import{c as u}from"./utils.DtKoarLP.js";import{createPortal as f}from"react-dom";import{B as g}from"./button.
|
|
1
|
+
import e,{useState as t,useEffect as a,useCallback as s}from"react";import{useDropzone as r}from"react-dropzone";import{CloudArrowUp as l,CaretDown as c,CaretUp as o,FileVideo as n,Circle as m,CheckCircle as i}from"@phosphor-icons/react";import{Card as p,CardContent as d}from"../components/ui/card.js";import{c as u}from"./utils.DtKoarLP.js";import{createPortal as f}from"react-dom";import{B as g}from"./button.DXe2tRBO.js";import{Collapsible as x,CollapsibleTrigger as b,CollapsibleContent as N}from"../components/ui/collapsible.js";const E=e=>{if(0===e)return"0 Bytes";const t=Math.floor(Math.log(e)/Math.log(1024));return Number.parseFloat((e/Math.pow(1024,t)).toFixed(2))+" "+["Bytes","KB","MB","GB"][t]};function h({onDropAccepted:t,onDropRejected:a,accept:s={"image/*":[".png",".jpg",".jpeg",".gif",".mp4"],"application/pdf":[".pdf"],"text/*":[".txt",".csv"]},maxSize:c=5242880,maxFiles:o=5,multiple:n=!0,className:m,disabled:i=!1,title:d="Drag & drop files here, or click to select",description:f="",supportsMessage:g="",children:x}){const{getRootProps:b,getInputProps:N,isDragActive:h,isDragReject:v}=r({onDropAccepted:t,onDropRejected:a,accept:s,maxSize:c,multiple:n,disabled:i,maxFiles:o});/* @__PURE__ */
|
|
2
2
|
return e.createElement("div",{"data-testid":"file-upload",className:"w-full space-y-4"},/* @__PURE__ */e.createElement("div",{className:u("group",m,"focus-visible:outline-none"),...b()},/* @__PURE__ */e.createElement(p,{className:u("custom-dashed-border shadow-none p-8 text-center cursor-pointer","group-focus:custom-dashed-border-hover","group-hover:custom-dashed-border-hover",h&&!v&&"border-primary bg-primary/5",v&&"border-destructive bg-destructive/5",i&&"cursor-not-allowed opacity-50")},
|
|
3
3
|
/* @__PURE__ */e.createElement("input",{...N()}),
|
|
4
4
|
/* @__PURE__ */e.createElement("div",{className:"flex flex-col items-center gap-4"},/* @__PURE__ */e.createElement(l,{className:u("size-12",h&&!v&&"text-primary",v&&"text-destructive")}),/* @__PURE__ */e.createElement("div",{className:"space-y-2"},/* @__PURE__ */e.createElement("p",{className:"text-lg font-medium"},h?v?"Some files will be rejected":"Drop files here":d),f&&/* @__PURE__ */e.createElement("p",{className:"text-sm"},f),g?/* @__PURE__ */e.createElement("p",{className:"text-sm"},g):/* @__PURE__ */e.createElement("p",{className:"text-sm"},`Supports: ${Object.values(s).flat().join(", ")} • Max size: ${E(c)}${o>1?` • Max files: ${o}`:""}`))))),x)}const v=e.memo(({className:t})=>/* @__PURE__ */e.createElement("div",{className:u("relative",t)},/* @__PURE__ */e.createElement(i,{className:"absolute size-6 text-green-400",weight:"fill"}),/* @__PURE__ */e.createElement(i,{className:"absolute size-6 text-black",weight:"regular"})));v.displayName="CheckCircleIcon";const y=({uploads:r,className:l,onCancelUpload:i,steps:h=[{id:"upload",label:"Uploading video",status:"current"},{id:"analyze",label:"Analyzing content",status:"pending"},{id:"create",label:"Creating help articles",status:"pending"}],timeRemaining:y,title:z="Video Processing"})=>{const[w,j]=t(!1),[k,M]=t(!0);a(()=>{j(!0)},[]);const C=s(e=>"success"===e.status?"Uploaded":"error"===e.status?"Retry upload":"Cancel upload",[]);if(!w||0===r.length)return null;if("undefined"==typeof document)return null;const D=/* @__PURE__ */e.createElement(x,{open:k,onOpenChange:M,className:u("fixed bottom-3 right-3 w-96 shadow-lg border z-50 transition-all duration-200 h-auto p-0 gap-4 bg-dark-100 rounded-lg overflow-hidden",l)},
|
|
5
5
|
/* @__PURE__ */e.createElement(b,{asChild:!0},/* @__PURE__ */e.createElement("div",{className:"flex items-center justify-between py-4 px-6 bg-foreground text-background cursor-pointer"},/* @__PURE__ */e.createElement("div",{className:"flex flex-col gap-0"},/* @__PURE__ */e.createElement("span",{className:"font-semibold"},z),y&&/* @__PURE__ */e.createElement("span",{className:"text-sm text-muted-foreground"},y)),/* @__PURE__ */e.createElement(g,{variant:"ghost",size:"sm",className:"size-6 p-0"},k?/* @__PURE__ */e.createElement(c,{className:"size-4"}):/* @__PURE__ */e.createElement(o,{className:"size-4"})))),
|
|
6
6
|
/* @__PURE__ */e.createElement(N,null,r.map(t=>/* @__PURE__ */e.createElement(p,{key:t.id,className:u("rounded-none p-0")},/* @__PURE__ */e.createElement(d,{className:"p-0"},/* @__PURE__ */e.createElement("div",{className:"px-6 py-4 border-b"},/* @__PURE__ */e.createElement("div",{className:"flex items-center gap-4"},/* @__PURE__ */e.createElement("div",{className:"size-12 bg-yellow-400 border border-dark rounded-lg flex items-center justify-center text-dark shrink-0"},/* @__PURE__ */e.createElement(n,{className:"size-6"})),/* @__PURE__ */e.createElement("div",{className:"flex-1 flex flex-col gap-0"},/* @__PURE__ */e.createElement("h3",{className:"text-base font-medium flex items-center gap-1 whitespace-nowrap"},/* @__PURE__ */e.createElement("span",{className:"truncate max-w-56"},t.file.name),/* @__PURE__ */e.createElement("span",{className:"shrink-0"}," • ",E(t.file.size))),/* @__PURE__ */e.createElement(g,{variant:"dark",size:"sm",className:"self-start h-6 text-xs bg-foreground text-background",onClick:i,"data-id":t.id,disabled:"success"===t.status||100===t.progress,"data-status":t.status},C(t))))),/* @__PURE__ */e.createElement("ol",{className:"py-2"},h.map(a=>/* @__PURE__ */e.createElement("li",{key:a.id,className:u("flex items-center gap-4 px-6 py-3 relative","after:absolute after:w-[1px] after:bg-foreground after:top-[38px] after:-bottom-[10px] after:left-[35px]","last-of-type:after:hidden")},"completed"===a.status?/* @__PURE__ */e.createElement(v,{className:"size-6"}):/* @__PURE__ */e.createElement(m,{className:"size-6"}),
|
|
7
7
|
/* @__PURE__ */e.createElement("span",{className:"flex items-center gap-1"},`${a.label} ${"upload"===a.id?`— ${Math.round(t.progress)}%`:""}`)))))))));return f(D,document.body)};export{h as F,y as a,E as f};
|
|
8
|
-
//# sourceMappingURL=file-upload-status.
|
|
8
|
+
//# sourceMappingURL=file-upload-status.znDE1kUC.js.map
|
package/dist/esm/chunks/{file-upload-status.sUoGRgbH.js.map → file-upload-status.znDE1kUC.js.map}
RENAMED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"file-upload-status.sUoGRgbH.js","sources":["../../../src/components/file-upload/utils.tsx","../../../src/components/file-upload/file-upload.tsx","../../../src/components/file-upload/file-upload-status.tsx"],"sourcesContent":["export const formatFileSize = (bytes: number) => {\n if (bytes === 0) return '0 Bytes';\n const k = 1024;\n const sizes = ['Bytes', 'KB', 'MB', 'GB'];\n const i = Math.floor(Math.log(bytes) / Math.log(k));\n\n return Number.parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];\n};\n","import React from 'react';\nimport { useDropzone } from 'react-dropzone';\nimport { CloudArrowUp } from '@phosphor-icons/react';\n\nimport type { FileUploadProps } from './types';\nimport { formatFileSize } from './utils';\n\nimport { Card } from '@/components/ui/card';\nimport { cn } from '@/lib/utils';\n\nexport function FileUpload({\n onDropAccepted,\n onDropRejected,\n accept = {\n 'image/*': ['.png', '.jpg', '.jpeg', '.gif', '.mp4'],\n 'application/pdf': ['.pdf'],\n 'text/*': ['.txt', '.csv'],\n },\n maxSize = 5 * 1024 * 1024, // 5MB\n maxFiles = 5,\n multiple = true,\n className,\n disabled = false,\n title = 'Drag & drop files here, or click to select',\n description = '',\n supportsMessage = '',\n children,\n}: FileUploadProps) {\n const { getRootProps, getInputProps, isDragActive, isDragReject } = useDropzone({\n onDropAccepted,\n onDropRejected,\n accept,\n maxSize,\n multiple,\n disabled,\n maxFiles,\n });\n\n return (\n <div data-testid=\"file-upload\" className=\"w-full space-y-4\">\n <div className={cn('group', className, 'focus-visible:outline-none')} {...getRootProps()}>\n <Card\n className={cn(\n 'custom-dashed-border shadow-none p-8 text-center cursor-pointer',\n 'group-focus:custom-dashed-border-hover',\n 'group-hover:custom-dashed-border-hover',\n isDragActive && !isDragReject && 'border-primary bg-primary/5',\n isDragReject && 'border-destructive bg-destructive/5',\n disabled && 'cursor-not-allowed opacity-50',\n )}\n >\n <input {...getInputProps()} />\n <div className=\"flex flex-col items-center gap-4\">\n <CloudArrowUp\n className={cn(\n 'size-12',\n isDragActive && !isDragReject && 'text-primary',\n isDragReject && 'text-destructive',\n )}\n />\n <div className=\"space-y-2\">\n <p className=\"text-lg font-medium\">\n {isDragActive ? (isDragReject ? 'Some files will be rejected' : 'Drop files here') : title}\n </p>\n {description && <p className=\"text-sm\">{description}</p>}\n {supportsMessage ? (\n <p className=\"text-sm\">{supportsMessage}</p>\n ) : (\n <p className=\"text-sm\">\n {`Supports: ${Object.values(accept).flat().join(', ')} • Max size: ${formatFileSize(maxSize)}${\n maxFiles > 1 ? ` • Max files: ${maxFiles}` : ''\n }`}\n </p>\n )}\n </div>\n </div>\n </Card>\n </div>\n {children}\n </div>\n );\n}\n","import React, { useState, useEffect, useCallback } from 'react';\nimport { createPortal } from 'react-dom';\nimport { CaretUp, CaretDown, FileVideo, CheckCircle, Circle } from '@phosphor-icons/react';\n\nimport type { UploadState } from './types';\nimport { formatFileSize } from './utils';\n\nimport { Card, CardContent } from '@/components/ui/card';\nimport { Button } from '@/components/ui/button';\nimport { Collapsible, CollapsibleContent, CollapsibleTrigger } from '@/components/ui/collapsible';\nimport { cn } from '@/lib/utils';\n\nexport interface ProcessingStep {\n id: string;\n label: string;\n status: 'completed' | 'current' | 'pending' | 'error';\n}\n\ninterface FileUploadStatusProps {\n uploads: UploadState[];\n className?: string;\n timeRemaining?: string;\n onCancelUpload?: (e: React.MouseEvent<HTMLButtonElement>) => void;\n steps?: ProcessingStep[];\n title?: string;\n}\n\nconst CheckCircleIcon = React.memo<{ className?: string }>(({ className }) => {\n return (\n <div className={cn('relative', className)}>\n <CheckCircle className=\"absolute size-6 text-green-400\" weight=\"fill\" />\n <CheckCircle className=\"absolute size-6 text-black\" weight=\"regular\" />\n </div>\n );\n});\n\nCheckCircleIcon.displayName = 'CheckCircleIcon';\n\nexport const FileUploadStatus: React.FC<FileUploadStatusProps> = ({\n uploads,\n className,\n onCancelUpload,\n steps = [\n { id: 'upload', label: 'Uploading video', status: 'current' },\n { id: 'analyze', label: 'Analyzing content', status: 'pending' },\n { id: 'create', label: 'Creating help articles', status: 'pending' },\n ],\n timeRemaining,\n title = 'Video Processing',\n}) => {\n const [mounted, setMounted] = useState(false);\n const [isOpen, setIsOpen] = useState(true);\n\n useEffect(() => {\n setMounted(true);\n }, []);\n\n const cancelButtonLabel = useCallback((uploadState: UploadState) => {\n if (uploadState.status === 'success') return 'Uploaded';\n if (uploadState.status === 'error') return 'Retry upload';\n\n return 'Cancel upload';\n }, []);\n\n if (!mounted || uploads.length === 0) return null;\n\n // Ensure we're in a browser environment\n if (typeof document === 'undefined') return null;\n\n const statusCard = (\n <Collapsible\n open={isOpen}\n onOpenChange={setIsOpen}\n className={cn(\n 'fixed bottom-3 right-3 w-96 shadow-lg border z-50 transition-all duration-200 h-auto p-0 gap-4 bg-dark-100 rounded-lg overflow-hidden',\n className,\n )}\n >\n <CollapsibleTrigger asChild>\n <div className=\"flex items-center justify-between py-4 px-6 bg-foreground text-background cursor-pointer\">\n <div className=\"flex flex-col gap-0\">\n <span className=\"font-semibold\">{title}</span>\n {timeRemaining && <span className=\"text-sm text-muted-foreground\">{timeRemaining}</span>}\n </div>\n <Button variant=\"ghost\" size=\"sm\" className=\"size-6 p-0\">\n {isOpen ? <CaretDown className=\"size-4\" /> : <CaretUp className=\"size-4\" />}\n </Button>\n </div>\n </CollapsibleTrigger>\n <CollapsibleContent>\n {uploads.map((upload) => (\n <Card key={upload.id} className={cn('rounded-none p-0')}>\n <CardContent className=\"p-0\">\n {/* File Info */}\n <div className=\"px-6 py-4 border-b\">\n <div className=\"flex items-center gap-4\">\n <div className=\"size-12 bg-yellow-400 border border-dark rounded-lg flex items-center justify-center text-dark shrink-0\">\n <FileVideo className=\"size-6\" />\n </div>\n <div className=\"flex-1 flex flex-col gap-0\">\n <h3 className=\"text-base font-medium flex items-center gap-1 whitespace-nowrap\">\n <span className=\"truncate max-w-56\">{upload.file.name}</span>\n <span className=\"shrink-0\"> • {formatFileSize(upload.file.size)}</span>\n </h3>\n <Button\n variant=\"dark\"\n size=\"sm\"\n className=\"self-start h-6 text-xs bg-foreground text-background\"\n onClick={onCancelUpload}\n data-id={upload.id}\n disabled={upload.status === 'success' || upload.progress === 100}\n data-status={upload.status}\n >\n {cancelButtonLabel(upload)}\n </Button>\n </div>\n </div>\n </div>\n\n {/* Steps */}\n <ol className=\"py-2\">\n {steps.map((step) => (\n <li\n key={step.id}\n className={cn(\n 'flex items-center gap-4 px-6 py-3 relative',\n 'after:absolute after:w-[1px] after:bg-foreground after:top-[38px] after:-bottom-[10px] after:left-[35px]',\n 'last-of-type:after:hidden',\n )}\n >\n {step.status === 'completed' ? (\n <CheckCircleIcon className=\"size-6\" />\n ) : (\n <Circle className=\"size-6\" />\n )}\n <span className=\"flex items-center gap-1\">\n {`${step.label} ${step.id === 'upload' ? `— ${Math.round(upload.progress)}%` : ''}`}\n </span>\n </li>\n ))}\n </ol>\n </CardContent>\n </Card>\n ))}\n </CollapsibleContent>\n </Collapsible>\n );\n\n return createPortal(statusCard, document.body);\n};\n"],"names":["formatFileSize","bytes","i","Math","floor","log","Number","parseFloat","pow","toFixed","FileUpload","onDropAccepted","onDropRejected","accept","maxSize","maxFiles","multiple","className","disabled","title","description","supportsMessage","children","getRootProps","getInputProps","isDragActive","isDragReject","useDropzone","React","createElement","cn","Card","CloudArrowUp","Object","values","flat","join","CheckCircleIcon","memo","CheckCircle","weight","displayName","FileUploadStatus","uploads","onCancelUpload","steps","id","label","status","timeRemaining","mounted","setMounted","useState","isOpen","setIsOpen","useEffect","cancelButtonLabel","useCallback","uploadState","length","document","statusCard","Collapsible","open","onOpenChange","CollapsibleTrigger","asChild","Button","variant","size","CaretDown","CaretUp","CollapsibleContent","map","upload","key","CardContent","FileVideo","file","name","onClick","progress","step","Circle","round","createPortal","body"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"file-upload-status.znDE1kUC.js","sources":["../../../src/components/file-upload/utils.tsx","../../../src/components/file-upload/file-upload.tsx","../../../src/components/file-upload/file-upload-status.tsx"],"sourcesContent":["export const formatFileSize = (bytes: number) => {\n if (bytes === 0) return '0 Bytes';\n const k = 1024;\n const sizes = ['Bytes', 'KB', 'MB', 'GB'];\n const i = Math.floor(Math.log(bytes) / Math.log(k));\n\n return Number.parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];\n};\n","import React from 'react';\nimport { useDropzone } from 'react-dropzone';\nimport { CloudArrowUp } from '@phosphor-icons/react';\n\nimport type { FileUploadProps } from './types';\nimport { formatFileSize } from './utils';\n\nimport { Card } from '@/components/ui/card';\nimport { cn } from '@/lib/utils';\n\nexport function FileUpload({\n onDropAccepted,\n onDropRejected,\n accept = {\n 'image/*': ['.png', '.jpg', '.jpeg', '.gif', '.mp4'],\n 'application/pdf': ['.pdf'],\n 'text/*': ['.txt', '.csv'],\n },\n maxSize = 5 * 1024 * 1024, // 5MB\n maxFiles = 5,\n multiple = true,\n className,\n disabled = false,\n title = 'Drag & drop files here, or click to select',\n description = '',\n supportsMessage = '',\n children,\n}: FileUploadProps) {\n const { getRootProps, getInputProps, isDragActive, isDragReject } = useDropzone({\n onDropAccepted,\n onDropRejected,\n accept,\n maxSize,\n multiple,\n disabled,\n maxFiles,\n });\n\n return (\n <div data-testid=\"file-upload\" className=\"w-full space-y-4\">\n <div className={cn('group', className, 'focus-visible:outline-none')} {...getRootProps()}>\n <Card\n className={cn(\n 'custom-dashed-border shadow-none p-8 text-center cursor-pointer',\n 'group-focus:custom-dashed-border-hover',\n 'group-hover:custom-dashed-border-hover',\n isDragActive && !isDragReject && 'border-primary bg-primary/5',\n isDragReject && 'border-destructive bg-destructive/5',\n disabled && 'cursor-not-allowed opacity-50',\n )}\n >\n <input {...getInputProps()} />\n <div className=\"flex flex-col items-center gap-4\">\n <CloudArrowUp\n className={cn(\n 'size-12',\n isDragActive && !isDragReject && 'text-primary',\n isDragReject && 'text-destructive',\n )}\n />\n <div className=\"space-y-2\">\n <p className=\"text-lg font-medium\">\n {isDragActive ? (isDragReject ? 'Some files will be rejected' : 'Drop files here') : title}\n </p>\n {description && <p className=\"text-sm\">{description}</p>}\n {supportsMessage ? (\n <p className=\"text-sm\">{supportsMessage}</p>\n ) : (\n <p className=\"text-sm\">\n {`Supports: ${Object.values(accept).flat().join(', ')} • Max size: ${formatFileSize(maxSize)}${\n maxFiles > 1 ? ` • Max files: ${maxFiles}` : ''\n }`}\n </p>\n )}\n </div>\n </div>\n </Card>\n </div>\n {children}\n </div>\n );\n}\n","import React, { useState, useEffect, useCallback } from 'react';\nimport { createPortal } from 'react-dom';\nimport { CaretUp, CaretDown, FileVideo, CheckCircle, Circle } from '@phosphor-icons/react';\n\nimport type { UploadState } from './types';\nimport { formatFileSize } from './utils';\n\nimport { Card, CardContent } from '@/components/ui/card';\nimport { Button } from '@/components/ui/button';\nimport { Collapsible, CollapsibleContent, CollapsibleTrigger } from '@/components/ui/collapsible';\nimport { cn } from '@/lib/utils';\n\nexport interface ProcessingStep {\n id: string;\n label: string;\n status: 'completed' | 'current' | 'pending' | 'error';\n}\n\ninterface FileUploadStatusProps {\n uploads: UploadState[];\n className?: string;\n timeRemaining?: string;\n onCancelUpload?: (e: React.MouseEvent<HTMLButtonElement>) => void;\n steps?: ProcessingStep[];\n title?: string;\n}\n\nconst CheckCircleIcon = React.memo<{ className?: string }>(({ className }) => {\n return (\n <div className={cn('relative', className)}>\n <CheckCircle className=\"absolute size-6 text-green-400\" weight=\"fill\" />\n <CheckCircle className=\"absolute size-6 text-black\" weight=\"regular\" />\n </div>\n );\n});\n\nCheckCircleIcon.displayName = 'CheckCircleIcon';\n\nexport const FileUploadStatus: React.FC<FileUploadStatusProps> = ({\n uploads,\n className,\n onCancelUpload,\n steps = [\n { id: 'upload', label: 'Uploading video', status: 'current' },\n { id: 'analyze', label: 'Analyzing content', status: 'pending' },\n { id: 'create', label: 'Creating help articles', status: 'pending' },\n ],\n timeRemaining,\n title = 'Video Processing',\n}) => {\n const [mounted, setMounted] = useState(false);\n const [isOpen, setIsOpen] = useState(true);\n\n useEffect(() => {\n setMounted(true);\n }, []);\n\n const cancelButtonLabel = useCallback((uploadState: UploadState) => {\n if (uploadState.status === 'success') return 'Uploaded';\n if (uploadState.status === 'error') return 'Retry upload';\n\n return 'Cancel upload';\n }, []);\n\n if (!mounted || uploads.length === 0) return null;\n\n // Ensure we're in a browser environment\n if (typeof document === 'undefined') return null;\n\n const statusCard = (\n <Collapsible\n open={isOpen}\n onOpenChange={setIsOpen}\n className={cn(\n 'fixed bottom-3 right-3 w-96 shadow-lg border z-50 transition-all duration-200 h-auto p-0 gap-4 bg-dark-100 rounded-lg overflow-hidden',\n className,\n )}\n >\n <CollapsibleTrigger asChild>\n <div className=\"flex items-center justify-between py-4 px-6 bg-foreground text-background cursor-pointer\">\n <div className=\"flex flex-col gap-0\">\n <span className=\"font-semibold\">{title}</span>\n {timeRemaining && <span className=\"text-sm text-muted-foreground\">{timeRemaining}</span>}\n </div>\n <Button variant=\"ghost\" size=\"sm\" className=\"size-6 p-0\">\n {isOpen ? <CaretDown className=\"size-4\" /> : <CaretUp className=\"size-4\" />}\n </Button>\n </div>\n </CollapsibleTrigger>\n <CollapsibleContent>\n {uploads.map((upload) => (\n <Card key={upload.id} className={cn('rounded-none p-0')}>\n <CardContent className=\"p-0\">\n {/* File Info */}\n <div className=\"px-6 py-4 border-b\">\n <div className=\"flex items-center gap-4\">\n <div className=\"size-12 bg-yellow-400 border border-dark rounded-lg flex items-center justify-center text-dark shrink-0\">\n <FileVideo className=\"size-6\" />\n </div>\n <div className=\"flex-1 flex flex-col gap-0\">\n <h3 className=\"text-base font-medium flex items-center gap-1 whitespace-nowrap\">\n <span className=\"truncate max-w-56\">{upload.file.name}</span>\n <span className=\"shrink-0\"> • {formatFileSize(upload.file.size)}</span>\n </h3>\n <Button\n variant=\"dark\"\n size=\"sm\"\n className=\"self-start h-6 text-xs bg-foreground text-background\"\n onClick={onCancelUpload}\n data-id={upload.id}\n disabled={upload.status === 'success' || upload.progress === 100}\n data-status={upload.status}\n >\n {cancelButtonLabel(upload)}\n </Button>\n </div>\n </div>\n </div>\n\n {/* Steps */}\n <ol className=\"py-2\">\n {steps.map((step) => (\n <li\n key={step.id}\n className={cn(\n 'flex items-center gap-4 px-6 py-3 relative',\n 'after:absolute after:w-[1px] after:bg-foreground after:top-[38px] after:-bottom-[10px] after:left-[35px]',\n 'last-of-type:after:hidden',\n )}\n >\n {step.status === 'completed' ? (\n <CheckCircleIcon className=\"size-6\" />\n ) : (\n <Circle className=\"size-6\" />\n )}\n <span className=\"flex items-center gap-1\">\n {`${step.label} ${step.id === 'upload' ? `— ${Math.round(upload.progress)}%` : ''}`}\n </span>\n </li>\n ))}\n </ol>\n </CardContent>\n </Card>\n ))}\n </CollapsibleContent>\n </Collapsible>\n );\n\n return createPortal(statusCard, document.body);\n};\n"],"names":["formatFileSize","bytes","i","Math","floor","log","Number","parseFloat","pow","toFixed","FileUpload","onDropAccepted","onDropRejected","accept","maxSize","maxFiles","multiple","className","disabled","title","description","supportsMessage","children","getRootProps","getInputProps","isDragActive","isDragReject","useDropzone","React","createElement","cn","Card","CloudArrowUp","Object","values","flat","join","CheckCircleIcon","memo","CheckCircle","weight","displayName","FileUploadStatus","uploads","onCancelUpload","steps","id","label","status","timeRemaining","mounted","setMounted","useState","isOpen","setIsOpen","useEffect","cancelButtonLabel","useCallback","uploadState","length","document","statusCard","Collapsible","open","onOpenChange","CollapsibleTrigger","asChild","Button","variant","size","CaretDown","CaretUp","CollapsibleContent","map","upload","key","CardContent","FileVideo","file","name","onClick","progress","step","Circle","round","createPortal","body"],"mappings":"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"}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import e,{useRef as t,useState as l,forwardRef as r,useImperativeHandle as a,useEffect as n}from"react";import{Check as o,XCircle as s,Plus as c}from"@phosphor-icons/react";import{createId as u}from"@paralleldrive/cuid2";import{B as i}from"./button.
|
|
1
|
+
import e,{useRef as t,useState as l,forwardRef as r,useImperativeHandle as a,useEffect as n}from"react";import{Check as o,XCircle as s,Plus as c}from"@phosphor-icons/react";import{createId as u}from"@paralleldrive/cuid2";import{B as i}from"./button.DXe2tRBO.js";import{Input as m}from"../components/ui/input.js";import{ButtonGroup as d}from"../components/ui/button-group.js";import{DropdownMenu as p,DropdownMenuTrigger as f,DropdownMenuContent as v,DropdownMenuItem as b}from"../components/ui/dropdown-menu.js";import{Popover as g,PopoverTrigger as h,PopoverContent as E}from"../components/ui/popover.js";import{c as y}from"./utils.DtKoarLP.js";var N=/* @__PURE__ */(e=>(e.IS="is",e.IS_NOT="is not",e.CONTAINS="contains",e.DOES_NOT_CONTAIN="does not contain",e.STARTS_WITH="starts with",e))(N||{});const S=({inputValue:l,setInputValue:r,customValuePlaceholder:a,customValueButtonLabel:n,onSubmit:o,handleKeyDown:s})=>{const c=t(null);/* @__PURE__ */
|
|
2
2
|
return e.createElement("form",{className:"p-3",onSubmit:e=>{e.preventDefault(),o()}},
|
|
3
3
|
/* @__PURE__ */e.createElement(m,{ref:c,type:"text",value:l,onChange:e=>r(e.target.value),placeholder:a,className:"mb-2",onKeyDown:e=>s(e,!0)}),
|
|
4
4
|
/* @__PURE__ */e.createElement(i,{type:"submit",variant:"dark",className:"w-full",onKeyDown:e=>s(e,!1),"data-custom-submit-button":!0},n))},w=({internalFilter:r,valueOptions:a,onConfirm:n,onClose:s})=>{const[c,u]=l(()=>{return e=r.value,Array.isArray(e)?e:e?[e]:[];var e}),[m,d]=l(""),p=t([]),f=t(null),v=e=>{const t=a.find(t=>t.id===e),l=c.includes(e);u(r=>{const a=r.includes(e)?r.filter(t=>t!==e):[...r,e];if(t){const e=l?"deselected":"selected";d(`${t.label} ${e}.`)}return a})},b=()=>{n(c),s()},g=e=>c.includes(e),h=e=>{e<a.length?p.current[e]?.focus():f.current?.focus()},E=(e,t)=>{switch(e.key){case"ArrowDown":{e.preventDefault();const l=Math.min(t+1,a.length);h(l);break}case"ArrowUp":{e.preventDefault();const l=Math.max(t-1,0);h(l);break}case"Enter":case"Spacebar":e.preventDefault(),t<a.length?v(a[t].id):b();break;case"Escape":e.preventDefault(),s()}};/* @__PURE__ */
|
|
5
5
|
return e.createElement("div",{className:"py-1",role:"listbox","aria-multiselectable":"true"},/* @__PURE__ */e.createElement("div",{"aria-live":"polite","aria-atomic":"true",className:"sr-only"},m),a.map((t,l)=>/* @__PURE__ */e.createElement("button",{key:t.id,ref:e=>p.current[l]=e,type:"button",className:"relative flex w-full text-left cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none transition-colors hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground",onClick:()=>v(t.id),onKeyDown:e=>E(e,l),role:"option","aria-selected":g(t.id)},g(t.id)&&/* @__PURE__ */e.createElement(o,{size:14,className:"mr-2"}),!g(t.id)&&/* @__PURE__ */e.createElement("span",{className:"mr-2 w-3.5"}),t.label)),/* @__PURE__ */e.createElement("div",{className:"border-t border-border mt-1 pt-2 px-2 pb-2"},/* @__PURE__ */e.createElement(i,{ref:f,onClick:b,size:"sm",className:"w-full",disabled:0===c.length,onKeyDown:e=>E(e,a.length)},"Apply (",c.length," selected)")))},x=({valueOptions:l,isValueSelected:r,onValueSelect:a})=>{const n=t([]),s=e=>{n.current[e]?.focus()};/* @__PURE__ */
|
|
6
|
-
return e.createElement("div",{className:"py-1",role:"listbox"},l.map((t,c)=>/* @__PURE__ */e.createElement("button",{key:t.id,ref:e=>n.current[c]=e,type:"button",className:"relative flex w-full text-left cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none transition-colors hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground",onClick:()=>a(t.id),onKeyDown:e=>((e,t)=>{switch(e.key){case"ArrowDown":{e.preventDefault();const r=Math.min(t+1,l.length-1);s(r);break}case"ArrowUp":{e.preventDefault();const l=Math.max(t-1,0);s(l);break}case"Enter":case"Spacebar":e.preventDefault(),a(l[t].id)}})(e,c)},r(t.id)&&/* @__PURE__ */e.createElement(o,{size:14,className:"mr-2"}),!r(t.id)&&/* @__PURE__ */e.createElement("span",{className:"mr-2 w-3.5"}),t.label)))},C=r(({filter:r,sourceOptions:c,rules:u,onSourceChange:m,onRemoveFilter:y,onFilterChange:C,selectPlaceholder:D="Select a value",customValuePlaceholder:k="Enter custom value",customValueButtonLabel:O="Done",sourceFirstMessage:V="Please select a source first"},A)=>{const[F,T]=l({id:r.id,source:r.source,operator:r.operator||N.IS,value:r.value}),[z,I]=l(""),[K,j]=l(null),_=t(null),B=t(null),M=t(null);a(A,()=>({focus:()=>{B.current?.focus()}}));const P=F.source?u[F.source]:void 0,R=P?.operators||[],
|
|
6
|
+
return e.createElement("div",{className:"py-1",role:"listbox"},l.map((t,c)=>/* @__PURE__ */e.createElement("button",{key:t.id,ref:e=>n.current[c]=e,type:"button",className:"relative flex w-full text-left cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none transition-colors hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground",onClick:()=>a(t.id),onKeyDown:e=>((e,t)=>{switch(e.key){case"ArrowDown":{e.preventDefault();const r=Math.min(t+1,l.length-1);s(r);break}case"ArrowUp":{e.preventDefault();const l=Math.max(t-1,0);s(l);break}case"Enter":case"Spacebar":e.preventDefault(),a(l[t].id)}})(e,c)},r(t.id)&&/* @__PURE__ */e.createElement(o,{size:14,className:"mr-2"}),!r(t.id)&&/* @__PURE__ */e.createElement("span",{className:"mr-2 w-3.5"}),t.label)))},C=r(({filter:r,sourceOptions:c,rules:u,onSourceChange:m,onRemoveFilter:y,onFilterChange:C,selectPlaceholder:D="Select a value",customValuePlaceholder:k="Enter custom value",customValueButtonLabel:O="Done",sourceFirstMessage:V="Please select a source first"},A)=>{const[F,T]=l({id:r.id,source:r.source,operator:r.operator||N.IS,value:r.value}),[z,I]=l(""),[K,j]=l(null),_=t(null),B=t(null),M=t(null);a(A,()=>({focus:()=>{B.current?.focus()}}));const P=F.source?u[F.source]:void 0,R=P?.operators||[],q=P?.multiSelect||!1;let L=P?.inputType||"dropdown";F.operator!==N.CONTAINS&&F.operator!==N.DOES_NOT_CONTAIN||(L="custom");const $=P?.getValueOptions?P.getValueOptions():[],{getSelectedValues:U,isValueSelected:H,getDisplayValue:W}=((e,t,l)=>{const r=()=>Array.isArray(e.value)?e.value:e.value?[e.value]:[];return{getSelectedValues:r,isValueSelected:e=>r().includes(e),getDisplayValue:()=>{const e=r();if(0===e.length)return l;if(1===e.length){const l=t.find(t=>t.id===e[0]);return l?.label||e[0]}return`${e.length} selected`}}})(F,$,D);n(()=>{if("value"===K&&"custom"===L){const e=setTimeout(()=>_.current?.focus(),50);return()=>clearTimeout(e)}},[K,L]),n(()=>{T({id:r.id,source:r.source,operator:r.operator||N.IS,value:r.value})},[r]);const G=e=>{const t=Array.isArray(e.value)?e.value.length>0:!!e.value?.trim();e.source&&e.operator&&t&&C(e)},J=(e,t)=>{const l={...F,[e]:t};if("source"===e){const e=u[t];l.operator=e?.operators[0]?.id,l.value=e?.multiSelect?[]:""}if("operator"===e&&F.source){const e=u[F.source];"dropdown"===e?.inputType&&(l.value=e?.multiSelect?[]:"")}T(l),G(l),q&&"value"===e||j(null)};/* @__PURE__ */
|
|
7
7
|
return e.createElement(d,{ref:M,orientation:"horizontal",className:"rounded-full border border-border divide-x-2 divide-dark-500"},
|
|
8
8
|
/* @__PURE__ */e.createElement(p,{open:"source"===K,onOpenChange:e=>j(e?"source":null),modal:!1},
|
|
9
9
|
/* @__PURE__ */e.createElement(f,{asChild:!0},/* @__PURE__ */e.createElement(i,{ref:B,variant:"ghost",size:"xs",className:"rounded-l-full font-bold"},c.find(e=>e.id===F.source)?.label||c[0]?.label||D)),
|
|
@@ -13,10 +13,10 @@ return e.createElement(d,{ref:M,orientation:"horizontal",className:"rounded-full
|
|
|
13
13
|
/* @__PURE__ */e.createElement(v,{align:"start",className:"w-48"},R.map(t=>/* @__PURE__ */e.createElement(b,{key:t.id,className:"flex items-center",onSelect:()=>J("operator",t.id)},t.id===F.operator&&/* @__PURE__ */e.createElement(o,{size:14,className:"mr-2"}),t.label)))),
|
|
14
14
|
/* @__PURE__ */e.createElement(g,{open:"value"===K,onOpenChange:e=>j(e?"value":null)},
|
|
15
15
|
/* @__PURE__ */e.createElement(h,{asChild:!0},/* @__PURE__ */e.createElement(i,{variant:"ghost",size:"xs",className:"font-bold"},W())),
|
|
16
|
-
/* @__PURE__ */e.createElement(E,{align:"start",className:"w-64 max-h-[min(320px,50vh)] overflow-y-auto p-0"},"custom"
|
|
16
|
+
/* @__PURE__ */e.createElement(E,{align:"start",className:"w-64 max-h-[min(320px,50vh)] overflow-y-auto p-0"},"custom"===L&&/* @__PURE__ */e.createElement("div",{className:"p-3"},/* @__PURE__ */e.createElement(S,{inputValue:z,setInputValue:I,customValuePlaceholder:k,customValueButtonLabel:O,onSubmit:()=>{if(z.trim()){const e={...F,value:z.trim()};T(e),I(""),j(null),e.source&&e.operator&&e.value&&C(e)}},handleKeyDown:(e,t)=>{if("Escape"!==e.key){if("Tab"===e.key)if(t&&!e.shiftKey){e.preventDefault();const t=document.querySelector("[data-custom-submit-button]");t?.focus()}else t||(e.preventDefault(),_.current?.focus())}else j(null)}})),"dropdown"===L&&/* @__PURE__ */e.createElement(e.Fragment,null,F.source?/* @__PURE__ */e.createElement(e.Fragment,null,q?/* @__PURE__ */e.createElement(w,{internalFilter:F,valueOptions:$,onConfirm:e=>{const t={...F,value:e};T(t);t.source&&t.operator&&e.length>0&&C(t),j(null)},onClose:()=>j(null)}):/* @__PURE__ */e.createElement(x,{valueOptions:$,isValueSelected:H,onValueSelect:e=>{const t=U();let l;l=q?t.includes(e)?t.filter(t=>t!==e):[...t,e]:[e];const r={...F,value:q?l:l[0]||""};T(r),G(r),q||j(null)}})):/* @__PURE__ */e.createElement("div",{className:"p-3 text-sm text-gray-500"},V)))),
|
|
17
17
|
/* @__PURE__ */e.createElement(i,{type:"button",variant:"ghost",size:"xs",onClick:()=>{T({id:r.id}),j(null),y(r.id)},className:"p-2 hover:bg-black/10 rounded-none rounded-r-full","aria-label":"Remove filter"},
|
|
18
18
|
/* @__PURE__ */e.createElement(s,{size:16,weight:"fill"})))});C.displayName="Filter";const D=({filters:r,onFilterChange:a,onFilterRemove:o,onFilterAdd:s,sourceOptions:m,rules:d,className:p})=>{const[f,v]=l(r||[]),b=t({});n(()=>{v(r||[])},[r]);const g=f.map(e=>e.source).filter(Boolean),h=m.filter(e=>d[e.id]?.multiSelect?!g.includes(e.id):m),E=h.length>0;/* @__PURE__ */
|
|
19
19
|
return e.createElement("fieldset",{className:y("flex flex-wrap gap-2",p)},/* @__PURE__ */e.createElement("legend",{className:"sr-only"},"Filters"),f?.map(t=>{const l=m.filter(e=>!g.includes(e.id)||e.id===t.source);/* @__PURE__ */
|
|
20
20
|
return e.createElement(C,{key:t.id,ref:e=>{b.current[t.id]=e},filter:t,sourceOptions:l,rules:d,onRemoveFilter:()=>(e=>{const t=f.filter(t=>t.id!==e.id);v(t),o(e.id)})(t),onFilterChange:a})}),E&&/* @__PURE__ */e.createElement(i,{onClick:()=>{if(!E)return;const e={id:u(),source:h[0].id,operator:N.IS,value:d[h[0].id]?.multiSelect?[]:""},t=[...f,e];v(t),requestAnimationFrame(()=>{b.current[e.id]?.focus()}),s?.(e)},variant:"ghost",className:"border border-foreground rounded-full gap-1",size:"sm",title:"Add filter"},
|
|
21
21
|
/* @__PURE__ */e.createElement(c,{size:16}),"Add filter"))};export{C as F,N as O,D as a};
|
|
22
|
-
//# sourceMappingURL=filters.
|
|
22
|
+
//# sourceMappingURL=filters.CZJ31Eqj.js.map
|