@fanvue/ui 2.1.0 → 2.1.2
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/cjs/components/Autocomplete/Autocomplete.cjs +3 -2
- package/dist/cjs/components/Autocomplete/Autocomplete.cjs.map +1 -1
- package/dist/cjs/components/DropdownMenu/DropdownMenu.cjs +30 -20
- package/dist/cjs/components/DropdownMenu/DropdownMenu.cjs.map +1 -1
- package/dist/cjs/components/InfoBox/InfoBox.cjs +3 -1
- package/dist/cjs/components/InfoBox/InfoBox.cjs.map +1 -1
- package/dist/cjs/components/Select/Select.cjs +31 -20
- package/dist/cjs/components/Select/Select.cjs.map +1 -1
- package/dist/cjs/components/Tooltip/Tooltip.cjs +1 -1
- package/dist/cjs/components/Tooltip/Tooltip.cjs.map +1 -1
- package/dist/cjs/utils/floatingContentCollisionPadding.cjs +6 -0
- package/dist/cjs/utils/floatingContentCollisionPadding.cjs.map +1 -0
- package/dist/components/Autocomplete/Autocomplete.mjs +3 -2
- package/dist/components/Autocomplete/Autocomplete.mjs.map +1 -1
- package/dist/components/DropdownMenu/DropdownMenu.mjs +30 -20
- package/dist/components/DropdownMenu/DropdownMenu.mjs.map +1 -1
- package/dist/components/InfoBox/InfoBox.mjs +3 -1
- package/dist/components/InfoBox/InfoBox.mjs.map +1 -1
- package/dist/components/Select/Select.mjs +31 -20
- package/dist/components/Select/Select.mjs.map +1 -1
- package/dist/components/Tooltip/Tooltip.mjs +1 -1
- package/dist/components/Tooltip/Tooltip.mjs.map +1 -1
- package/dist/utils/floatingContentCollisionPadding.mjs +6 -0
- package/dist/utils/floatingContentCollisionPadding.mjs.map +1 -0
- package/package.json +1 -1
|
@@ -5,6 +5,7 @@ const jsxRuntime = require("react/jsx-runtime");
|
|
|
5
5
|
const PopoverPrimitive = require("@radix-ui/react-popover");
|
|
6
6
|
const React = require("react");
|
|
7
7
|
const cn = require("../../utils/cn.cjs");
|
|
8
|
+
const floatingContentCollisionPadding = require("../../utils/floatingContentCollisionPadding.cjs");
|
|
8
9
|
const ChevronDownIcon = require("../Icons/ChevronDownIcon.cjs");
|
|
9
10
|
const CloseIcon = require("../Icons/CloseIcon.cjs");
|
|
10
11
|
const SpinnerIcon = require("../Icons/SpinnerIcon.cjs");
|
|
@@ -178,12 +179,12 @@ const Autocomplete = React__namespace.forwardRef((props, ref) => {
|
|
|
178
179
|
PopoverPrimitive__namespace.Content,
|
|
179
180
|
{
|
|
180
181
|
sideOffset: 4,
|
|
181
|
-
collisionPadding:
|
|
182
|
+
collisionPadding: floatingContentCollisionPadding.FLOATING_CONTENT_COLLISION_PADDING,
|
|
182
183
|
onOpenAutoFocus: (e) => e.preventDefault(),
|
|
183
184
|
onCloseAutoFocus: (e) => e.preventDefault(),
|
|
184
185
|
style: { zIndex: "var(--fanvue-ui-portal-z-index, 50)" },
|
|
185
186
|
className: cn.cn(
|
|
186
|
-
"w-(--radix-
|
|
187
|
+
"w-max min-w-(--radix-popper-anchor-width) max-w-(--radix-popover-content-available-width) overflow-hidden rounded-sm border border-neutral-alphas-200 bg-bg-primary text-content-primary shadow-[0_4px_16px_rgba(0,0,0,0.10)]",
|
|
187
188
|
"data-[state=closed]:animate-out data-[state=open]:animate-in",
|
|
188
189
|
"data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
|
|
189
190
|
"data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Autocomplete.cjs","sources":["../../../../src/components/Autocomplete/Autocomplete.tsx"],"sourcesContent":["import * as Popover from \"@radix-ui/react-popover\";\nimport * as React from \"react\";\nimport { cn } from \"@/utils/cn\";\nimport { ChevronDownIcon } from \"../Icons/ChevronDownIcon\";\nimport { CloseIcon } from \"../Icons/CloseIcon\";\nimport { SpinnerIcon } from \"../Icons/SpinnerIcon\";\nimport { AutocompleteDropdownContent } from \"./AutocompleteDropdownContent\";\nimport { AutocompleteTag } from \"./AutocompleteTag\";\nimport { useAutocomplete } from \"./useAutocomplete\";\n\nexport type AutocompleteSize = \"48\" | \"40\" | \"32\";\n\nexport interface AutocompleteOption {\n value: string;\n label?: string;\n disabled?: boolean;\n}\n\ninterface AutocompleteBaseProps {\n label?: string;\n \"aria-label\"?: string;\n \"aria-labelledby\"?: string;\n helperText?: string;\n /** @default \"48\" */\n size?: AutocompleteSize;\n /** @default false */\n error?: boolean;\n errorMessage?: string;\n placeholder?: string;\n leftIcon?: React.ReactNode;\n /** @default false */\n fullWidth?: boolean;\n /** @default false */\n disabled?: boolean;\n /** @default false */\n clearable?: boolean;\n clearAriaLabel?: string;\n id?: string;\n className?: string;\n options: AutocompleteOption[];\n inputValue?: string;\n onInputChange?: (value: string) => void;\n filterFn?: (option: AutocompleteOption, query: string) => boolean;\n /** @default false */\n creatable?: boolean;\n creatableLabel?: (inputValue: string) => string;\n onCreate?: (inputValue: string) => void;\n /** @default false */\n loading?: boolean;\n loadingText?: string;\n emptyText?: string;\n renderOption?: (\n option: AutocompleteOption,\n state: { selected: boolean; active: boolean },\n ) => React.ReactNode;\n renderTag?: (option: AutocompleteOption, onRemove: () => void) => React.ReactNode;\n open?: boolean;\n defaultOpen?: boolean;\n onOpenChange?: (open: boolean) => void;\n}\n\ninterface AutocompleteSingleProps extends AutocompleteBaseProps {\n multiple?: false;\n value?: string | null;\n defaultValue?: string | null;\n onChange?: (value: string | null) => void;\n}\n\ninterface AutocompleteMultiProps extends AutocompleteBaseProps {\n multiple: true;\n value?: string[];\n defaultValue?: string[];\n onChange?: (values: string[]) => void;\n}\n\nexport type AutocompleteProps = AutocompleteSingleProps | AutocompleteMultiProps;\n\nconst CONTAINER_HEIGHT: Record<AutocompleteSize, string> = {\n \"48\": \"min-h-12\",\n \"40\": \"min-h-10\",\n \"32\": \"min-h-8\",\n};\n\nconst INPUT_SIZE_CLASSES: Record<AutocompleteSize, string> = {\n \"48\": \"typography-regular-body-lg\",\n \"40\": \"typography-regular-body-lg\",\n \"32\": \"typography-regular-body-md\",\n};\n\nconst PADDING_CLASSES: Record<AutocompleteSize, string> = {\n \"48\": \"px-4 py-1.5 gap-3\",\n \"40\": \"px-4 py-1 gap-3\",\n \"32\": \"px-3 py-1 gap-2\",\n};\n\nfunction warnMissingAccessibleName(label?: string, ariaLabel?: string, ariaLabelledBy?: string) {\n if (process.env.NODE_ENV !== \"production\") {\n if (!label && !ariaLabel && !ariaLabelledBy) {\n console.warn(\n \"Autocomplete: no accessible name provided. Pass a `label`, `aria-label`, or `aria-labelledby` prop.\",\n );\n }\n }\n}\n\n// biome-ignore lint/complexity/noExcessiveCognitiveComplexity: Conditional JSX branches in the render template\nexport const Autocomplete = React.forwardRef<HTMLInputElement, AutocompleteProps>((props, ref) => {\n const {\n label,\n \"aria-label\": ariaLabel,\n \"aria-labelledby\": ariaLabelledby,\n helperText,\n size = \"48\",\n error = false,\n errorMessage,\n placeholder,\n leftIcon,\n fullWidth = false,\n disabled = false,\n clearable = false,\n clearAriaLabel = \"Clear\",\n className,\n loading = false,\n loadingText,\n emptyText = \"No results\",\n renderOption,\n renderTag,\n } = props;\n\n const ac = useAutocomplete(props);\n\n React.useImperativeHandle(ref, () => ac.inputRef.current as HTMLInputElement);\n\n warnMissingAccessibleName(label, ariaLabel, ariaLabelledby);\n\n const bottomText = error && errorMessage ? errorMessage : helperText;\n\n return (\n <Popover.Root open={ac.isOpen && !disabled} onOpenChange={ac.handleOpenChange}>\n <div\n className={cn(\"flex flex-col\", fullWidth && \"w-full\", className)}\n data-autocomplete-root=\"\"\n data-disabled={disabled ? \"\" : undefined}\n data-error={error ? \"\" : undefined}\n >\n {label && (\n <label\n htmlFor={ac.inputId}\n className=\"typography-semibold-body-sm px-1 pt-1 pb-2 text-content-primary\"\n >\n {label}\n </label>\n )}\n\n <Popover.Anchor asChild>\n {/* biome-ignore lint/a11y/noStaticElementInteractions: Container delegates click to the inner input */}\n {/* biome-ignore lint/a11y/useKeyWithClickEvents: Keyboard interaction is handled by the inner combobox input */}\n <div\n className={cn(\n \"flex flex-wrap items-center overflow-hidden rounded-sm border bg-neutral-alphas-100 has-focus-visible:outline-none motion-safe:transition-colors\",\n error ? \"border-error-content\" : \"border-transparent\",\n !disabled && !error && \"hover:border-neutral-alphas-400\",\n ac.isOpen && !error && !disabled && \"border-neutral-alphas-400\",\n CONTAINER_HEIGHT[size],\n PADDING_CLASSES[size],\n disabled && \"opacity-50\",\n )}\n onClick={ac.handleContainerClick}\n >\n {leftIcon && (\n <div className=\"flex size-5 shrink-0 items-center justify-center text-content-secondary\">\n {leftIcon}\n </div>\n )}\n\n <div className=\"flex min-w-0 flex-1 flex-wrap items-center gap-1.5\">\n {ac.isMulti &&\n ac.selectedMultiOptions.map((opt) => (\n <AutocompleteTag\n key={opt.value}\n option={opt}\n disabled={disabled}\n onRemove={() => ac.toggleMulti(opt.value)}\n renderTag={renderTag}\n />\n ))}\n\n <input\n ref={ac.inputRef}\n id={ac.inputId}\n role=\"combobox\"\n type=\"text\"\n disabled={disabled}\n aria-expanded={ac.isOpen}\n aria-controls={ac.isOpen ? ac.listboxId : undefined}\n aria-activedescendant={ac.activeDescendantId}\n aria-autocomplete=\"list\"\n aria-describedby={bottomText ? ac.helperTextId : undefined}\n aria-invalid={error || undefined}\n aria-label={ariaLabel}\n aria-labelledby={ariaLabelledby}\n autoComplete=\"off\"\n placeholder={\n ac.isMulti && ac.selectedMultiValues.length > 0 ? undefined : placeholder\n }\n value={ac.displayInputValue}\n onChange={ac.handleInputChange}\n onKeyDown={ac.handleKeyDown}\n onFocus={ac.handleFocus}\n onBlur={ac.handleBlur}\n className={cn(\n \"min-w-[40px] flex-1 truncate bg-transparent text-content-primary no-underline placeholder:text-content-secondary placeholder:opacity-40 focus:outline-none disabled:cursor-not-allowed\",\n INPUT_SIZE_CLASSES[size],\n )}\n />\n </div>\n\n <div className=\"flex shrink-0 items-center gap-1\">\n {loading && <SpinnerIcon className=\"size-4 animate-spin text-content-secondary\" />}\n {clearable && ac.hasClearableValue && !disabled && (\n <button\n type=\"button\"\n tabIndex={-1}\n aria-label={clearAriaLabel}\n className=\"flex size-5 shrink-0 cursor-pointer items-center justify-center text-content-secondary hover:text-content-primary active:scale-95\"\n onClick={ac.handleClear}\n >\n <CloseIcon className=\"size-4\" />\n </button>\n )}\n <div className=\"flex size-5 shrink-0 items-center justify-center text-content-secondary\">\n <ChevronDownIcon\n className={cn(\"size-5 transition-transform\", ac.isOpen && \"rotate-180\")}\n />\n </div>\n </div>\n </div>\n </Popover.Anchor>\n\n <Popover.Portal>\n <Popover.Content\n sideOffset={4}\n collisionPadding={8}\n onOpenAutoFocus={(e) => e.preventDefault()}\n onCloseAutoFocus={(e) => e.preventDefault()}\n style={{ zIndex: \"var(--fanvue-ui-portal-z-index, 50)\" }}\n className={cn(\n \"w-(--radix-popover-trigger-width) min-w-(--radix-popper-anchor-width) overflow-hidden rounded-sm border border-neutral-alphas-200 bg-bg-primary text-content-primary shadow-[0_4px_16px_rgba(0,0,0,0.10)]\",\n \"data-[state=closed]:animate-out data-[state=open]:animate-in\",\n \"data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0\",\n \"data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95\",\n \"data-[side=bottom]:slide-in-from-top-2 data-[side=top]:slide-in-from-bottom-2\",\n )}\n >\n <div\n ref={ac.listRef}\n id={ac.listboxId}\n role=\"listbox\"\n aria-label={label ?? ariaLabel ?? \"Options\"}\n aria-multiselectable={ac.isMulti || undefined}\n className=\"max-h-60 overflow-y-auto p-1\"\n >\n <AutocompleteDropdownContent\n loading={loading}\n loadingText={loadingText}\n emptyText={emptyText}\n visibleOptions={ac.visibleOptions}\n listboxId={ac.listboxId}\n activeIndex={ac.activeIndex}\n isMulti={ac.isMulti}\n selectedMultiValues={ac.selectedMultiValues}\n selectedValue={ac.selectedValue}\n onSelect={ac.handleSelect}\n onMouseEnter={ac.setActiveIndex}\n renderOption={renderOption}\n />\n </div>\n </Popover.Content>\n </Popover.Portal>\n\n {bottomText && (\n <p\n id={ac.helperTextId}\n className={cn(\n \"typography-regular-body-sm px-2 pt-1 pb-0.5\",\n error ? \"text-error-content\" : \"text-content-secondary\",\n )}\n >\n {bottomText}\n </p>\n )}\n </div>\n </Popover.Root>\n );\n});\n\nAutocomplete.displayName = \"Autocomplete\";\n"],"names":["React","useAutocomplete","jsx","Popover","jsxs","cn","AutocompleteTag","SpinnerIcon","CloseIcon","ChevronDownIcon","AutocompleteDropdownContent"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Autocomplete.cjs","sources":["../../../../src/components/Autocomplete/Autocomplete.tsx"],"sourcesContent":["import * as Popover from \"@radix-ui/react-popover\";\nimport * as React from \"react\";\nimport { cn } from \"@/utils/cn\";\nimport { FLOATING_CONTENT_COLLISION_PADDING } from \"@/utils/floatingContentCollisionPadding\";\nimport { ChevronDownIcon } from \"../Icons/ChevronDownIcon\";\nimport { CloseIcon } from \"../Icons/CloseIcon\";\nimport { SpinnerIcon } from \"../Icons/SpinnerIcon\";\nimport { AutocompleteDropdownContent } from \"./AutocompleteDropdownContent\";\nimport { AutocompleteTag } from \"./AutocompleteTag\";\nimport { useAutocomplete } from \"./useAutocomplete\";\n\nexport type AutocompleteSize = \"48\" | \"40\" | \"32\";\n\nexport interface AutocompleteOption {\n value: string;\n label?: string;\n disabled?: boolean;\n}\n\ninterface AutocompleteBaseProps {\n label?: string;\n \"aria-label\"?: string;\n \"aria-labelledby\"?: string;\n helperText?: string;\n /** @default \"48\" */\n size?: AutocompleteSize;\n /** @default false */\n error?: boolean;\n errorMessage?: string;\n placeholder?: string;\n leftIcon?: React.ReactNode;\n /** @default false */\n fullWidth?: boolean;\n /** @default false */\n disabled?: boolean;\n /** @default false */\n clearable?: boolean;\n clearAriaLabel?: string;\n id?: string;\n className?: string;\n options: AutocompleteOption[];\n inputValue?: string;\n onInputChange?: (value: string) => void;\n filterFn?: (option: AutocompleteOption, query: string) => boolean;\n /** @default false */\n creatable?: boolean;\n creatableLabel?: (inputValue: string) => string;\n onCreate?: (inputValue: string) => void;\n /** @default false */\n loading?: boolean;\n loadingText?: string;\n emptyText?: string;\n renderOption?: (\n option: AutocompleteOption,\n state: { selected: boolean; active: boolean },\n ) => React.ReactNode;\n renderTag?: (option: AutocompleteOption, onRemove: () => void) => React.ReactNode;\n open?: boolean;\n defaultOpen?: boolean;\n onOpenChange?: (open: boolean) => void;\n}\n\ninterface AutocompleteSingleProps extends AutocompleteBaseProps {\n multiple?: false;\n value?: string | null;\n defaultValue?: string | null;\n onChange?: (value: string | null) => void;\n}\n\ninterface AutocompleteMultiProps extends AutocompleteBaseProps {\n multiple: true;\n value?: string[];\n defaultValue?: string[];\n onChange?: (values: string[]) => void;\n}\n\nexport type AutocompleteProps = AutocompleteSingleProps | AutocompleteMultiProps;\n\nconst CONTAINER_HEIGHT: Record<AutocompleteSize, string> = {\n \"48\": \"min-h-12\",\n \"40\": \"min-h-10\",\n \"32\": \"min-h-8\",\n};\n\nconst INPUT_SIZE_CLASSES: Record<AutocompleteSize, string> = {\n \"48\": \"typography-regular-body-lg\",\n \"40\": \"typography-regular-body-lg\",\n \"32\": \"typography-regular-body-md\",\n};\n\nconst PADDING_CLASSES: Record<AutocompleteSize, string> = {\n \"48\": \"px-4 py-1.5 gap-3\",\n \"40\": \"px-4 py-1 gap-3\",\n \"32\": \"px-3 py-1 gap-2\",\n};\n\nfunction warnMissingAccessibleName(label?: string, ariaLabel?: string, ariaLabelledBy?: string) {\n if (process.env.NODE_ENV !== \"production\") {\n if (!label && !ariaLabel && !ariaLabelledBy) {\n console.warn(\n \"Autocomplete: no accessible name provided. Pass a `label`, `aria-label`, or `aria-labelledby` prop.\",\n );\n }\n }\n}\n\n// biome-ignore lint/complexity/noExcessiveCognitiveComplexity: Conditional JSX branches in the render template\nexport const Autocomplete = React.forwardRef<HTMLInputElement, AutocompleteProps>((props, ref) => {\n const {\n label,\n \"aria-label\": ariaLabel,\n \"aria-labelledby\": ariaLabelledby,\n helperText,\n size = \"48\",\n error = false,\n errorMessage,\n placeholder,\n leftIcon,\n fullWidth = false,\n disabled = false,\n clearable = false,\n clearAriaLabel = \"Clear\",\n className,\n loading = false,\n loadingText,\n emptyText = \"No results\",\n renderOption,\n renderTag,\n } = props;\n\n const ac = useAutocomplete(props);\n\n React.useImperativeHandle(ref, () => ac.inputRef.current as HTMLInputElement);\n\n warnMissingAccessibleName(label, ariaLabel, ariaLabelledby);\n\n const bottomText = error && errorMessage ? errorMessage : helperText;\n\n return (\n <Popover.Root open={ac.isOpen && !disabled} onOpenChange={ac.handleOpenChange}>\n <div\n className={cn(\"flex flex-col\", fullWidth && \"w-full\", className)}\n data-autocomplete-root=\"\"\n data-disabled={disabled ? \"\" : undefined}\n data-error={error ? \"\" : undefined}\n >\n {label && (\n <label\n htmlFor={ac.inputId}\n className=\"typography-semibold-body-sm px-1 pt-1 pb-2 text-content-primary\"\n >\n {label}\n </label>\n )}\n\n <Popover.Anchor asChild>\n {/* biome-ignore lint/a11y/noStaticElementInteractions: Container delegates click to the inner input */}\n {/* biome-ignore lint/a11y/useKeyWithClickEvents: Keyboard interaction is handled by the inner combobox input */}\n <div\n className={cn(\n \"flex flex-wrap items-center overflow-hidden rounded-sm border bg-neutral-alphas-100 has-focus-visible:outline-none motion-safe:transition-colors\",\n error ? \"border-error-content\" : \"border-transparent\",\n !disabled && !error && \"hover:border-neutral-alphas-400\",\n ac.isOpen && !error && !disabled && \"border-neutral-alphas-400\",\n CONTAINER_HEIGHT[size],\n PADDING_CLASSES[size],\n disabled && \"opacity-50\",\n )}\n onClick={ac.handleContainerClick}\n >\n {leftIcon && (\n <div className=\"flex size-5 shrink-0 items-center justify-center text-content-secondary\">\n {leftIcon}\n </div>\n )}\n\n <div className=\"flex min-w-0 flex-1 flex-wrap items-center gap-1.5\">\n {ac.isMulti &&\n ac.selectedMultiOptions.map((opt) => (\n <AutocompleteTag\n key={opt.value}\n option={opt}\n disabled={disabled}\n onRemove={() => ac.toggleMulti(opt.value)}\n renderTag={renderTag}\n />\n ))}\n\n <input\n ref={ac.inputRef}\n id={ac.inputId}\n role=\"combobox\"\n type=\"text\"\n disabled={disabled}\n aria-expanded={ac.isOpen}\n aria-controls={ac.isOpen ? ac.listboxId : undefined}\n aria-activedescendant={ac.activeDescendantId}\n aria-autocomplete=\"list\"\n aria-describedby={bottomText ? ac.helperTextId : undefined}\n aria-invalid={error || undefined}\n aria-label={ariaLabel}\n aria-labelledby={ariaLabelledby}\n autoComplete=\"off\"\n placeholder={\n ac.isMulti && ac.selectedMultiValues.length > 0 ? undefined : placeholder\n }\n value={ac.displayInputValue}\n onChange={ac.handleInputChange}\n onKeyDown={ac.handleKeyDown}\n onFocus={ac.handleFocus}\n onBlur={ac.handleBlur}\n className={cn(\n \"min-w-[40px] flex-1 truncate bg-transparent text-content-primary no-underline placeholder:text-content-secondary placeholder:opacity-40 focus:outline-none disabled:cursor-not-allowed\",\n INPUT_SIZE_CLASSES[size],\n )}\n />\n </div>\n\n <div className=\"flex shrink-0 items-center gap-1\">\n {loading && <SpinnerIcon className=\"size-4 animate-spin text-content-secondary\" />}\n {clearable && ac.hasClearableValue && !disabled && (\n <button\n type=\"button\"\n tabIndex={-1}\n aria-label={clearAriaLabel}\n className=\"flex size-5 shrink-0 cursor-pointer items-center justify-center text-content-secondary hover:text-content-primary active:scale-95\"\n onClick={ac.handleClear}\n >\n <CloseIcon className=\"size-4\" />\n </button>\n )}\n <div className=\"flex size-5 shrink-0 items-center justify-center text-content-secondary\">\n <ChevronDownIcon\n className={cn(\"size-5 transition-transform\", ac.isOpen && \"rotate-180\")}\n />\n </div>\n </div>\n </div>\n </Popover.Anchor>\n\n <Popover.Portal>\n <Popover.Content\n sideOffset={4}\n collisionPadding={FLOATING_CONTENT_COLLISION_PADDING}\n onOpenAutoFocus={(e) => e.preventDefault()}\n onCloseAutoFocus={(e) => e.preventDefault()}\n style={{ zIndex: \"var(--fanvue-ui-portal-z-index, 50)\" }}\n className={cn(\n \"w-max min-w-(--radix-popper-anchor-width) max-w-(--radix-popover-content-available-width) overflow-hidden rounded-sm border border-neutral-alphas-200 bg-bg-primary text-content-primary shadow-[0_4px_16px_rgba(0,0,0,0.10)]\",\n \"data-[state=closed]:animate-out data-[state=open]:animate-in\",\n \"data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0\",\n \"data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95\",\n \"data-[side=bottom]:slide-in-from-top-2 data-[side=top]:slide-in-from-bottom-2\",\n )}\n >\n <div\n ref={ac.listRef}\n id={ac.listboxId}\n role=\"listbox\"\n aria-label={label ?? ariaLabel ?? \"Options\"}\n aria-multiselectable={ac.isMulti || undefined}\n className=\"max-h-60 overflow-y-auto p-1\"\n >\n <AutocompleteDropdownContent\n loading={loading}\n loadingText={loadingText}\n emptyText={emptyText}\n visibleOptions={ac.visibleOptions}\n listboxId={ac.listboxId}\n activeIndex={ac.activeIndex}\n isMulti={ac.isMulti}\n selectedMultiValues={ac.selectedMultiValues}\n selectedValue={ac.selectedValue}\n onSelect={ac.handleSelect}\n onMouseEnter={ac.setActiveIndex}\n renderOption={renderOption}\n />\n </div>\n </Popover.Content>\n </Popover.Portal>\n\n {bottomText && (\n <p\n id={ac.helperTextId}\n className={cn(\n \"typography-regular-body-sm px-2 pt-1 pb-0.5\",\n error ? \"text-error-content\" : \"text-content-secondary\",\n )}\n >\n {bottomText}\n </p>\n )}\n </div>\n </Popover.Root>\n );\n});\n\nAutocomplete.displayName = \"Autocomplete\";\n"],"names":["React","useAutocomplete","jsx","Popover","jsxs","cn","AutocompleteTag","SpinnerIcon","CloseIcon","ChevronDownIcon","FLOATING_CONTENT_COLLISION_PADDING","AutocompleteDropdownContent"],"mappings":"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"}
|
|
@@ -5,6 +5,7 @@ const jsxRuntime = require("react/jsx-runtime");
|
|
|
5
5
|
const DropdownMenuPrimitive = require("@radix-ui/react-dropdown-menu");
|
|
6
6
|
const React = require("react");
|
|
7
7
|
const cn = require("../../utils/cn.cjs");
|
|
8
|
+
const floatingContentCollisionPadding = require("../../utils/floatingContentCollisionPadding.cjs");
|
|
8
9
|
function _interopNamespaceDefault(e) {
|
|
9
10
|
const n = Object.create(null, { [Symbol.toStringTag]: { value: "Module" } });
|
|
10
11
|
if (e) {
|
|
@@ -26,27 +27,36 @@ const React__namespace = /* @__PURE__ */ _interopNamespaceDefault(React);
|
|
|
26
27
|
const DropdownMenu = DropdownMenuPrimitive__namespace.Root;
|
|
27
28
|
const DropdownMenuTrigger = DropdownMenuPrimitive__namespace.Trigger;
|
|
28
29
|
DropdownMenuTrigger.displayName = "DropdownMenuTrigger";
|
|
29
|
-
const DropdownMenuContent = React__namespace.forwardRef(
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
sideOffset,
|
|
34
|
-
|
|
35
|
-
"min-w-[180px] overflow-y-auto rounded-lg border border-neutral-alphas-200 bg-bg-primary p-1 shadow-lg",
|
|
36
|
-
"data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95",
|
|
37
|
-
"data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95",
|
|
38
|
-
"data-[side=top]:slide-in-from-bottom-2 data-[side=bottom]:slide-in-from-top-2",
|
|
39
|
-
"data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2",
|
|
40
|
-
className
|
|
41
|
-
),
|
|
42
|
-
style: {
|
|
43
|
-
zIndex: "var(--fanvue-ui-portal-z-index, 50)",
|
|
44
|
-
maxHeight: "var(--radix-dropdown-menu-content-available-height)",
|
|
45
|
-
...style
|
|
46
|
-
},
|
|
30
|
+
const DropdownMenuContent = React__namespace.forwardRef(
|
|
31
|
+
({
|
|
32
|
+
className,
|
|
33
|
+
style,
|
|
34
|
+
sideOffset = 4,
|
|
35
|
+
collisionPadding = floatingContentCollisionPadding.FLOATING_CONTENT_COLLISION_PADDING,
|
|
47
36
|
...props
|
|
48
|
-
}
|
|
49
|
-
|
|
37
|
+
}, ref) => /* @__PURE__ */ jsxRuntime.jsx(DropdownMenuPrimitive__namespace.Portal, { children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
38
|
+
DropdownMenuPrimitive__namespace.Content,
|
|
39
|
+
{
|
|
40
|
+
ref,
|
|
41
|
+
sideOffset,
|
|
42
|
+
collisionPadding,
|
|
43
|
+
className: cn.cn(
|
|
44
|
+
"w-max min-w-(--radix-dropdown-menu-trigger-width) max-w-(--radix-dropdown-menu-content-available-width) overflow-y-auto rounded-sm border border-neutral-alphas-200 bg-bg-primary p-1 shadow-lg",
|
|
45
|
+
"data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95",
|
|
46
|
+
"data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95",
|
|
47
|
+
"data-[side=top]:slide-in-from-bottom-2 data-[side=bottom]:slide-in-from-top-2",
|
|
48
|
+
"data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2",
|
|
49
|
+
className
|
|
50
|
+
),
|
|
51
|
+
style: {
|
|
52
|
+
zIndex: "var(--fanvue-ui-portal-z-index, 50)",
|
|
53
|
+
maxHeight: "var(--radix-dropdown-menu-content-available-height)",
|
|
54
|
+
...style
|
|
55
|
+
},
|
|
56
|
+
...props
|
|
57
|
+
}
|
|
58
|
+
) })
|
|
59
|
+
);
|
|
50
60
|
DropdownMenuContent.displayName = "DropdownMenuContent";
|
|
51
61
|
const DropdownMenuGroup = DropdownMenuPrimitive__namespace.Group;
|
|
52
62
|
DropdownMenuGroup.displayName = "DropdownMenuGroup";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DropdownMenu.cjs","sources":["../../../../src/components/DropdownMenu/DropdownMenu.tsx"],"sourcesContent":["import * as DropdownMenuPrimitive from \"@radix-ui/react-dropdown-menu\";\nimport * as React from \"react\";\nimport { cn } from \"../../utils/cn\";\n\n/** Props for the {@link DropdownMenu} root component. */\nexport interface DropdownMenuProps\n extends React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Root> {}\n\n/** Root component that manages open/close state for a dropdown menu. */\nexport const DropdownMenu = DropdownMenuPrimitive.Root;\n\n/** Props for the {@link DropdownMenuTrigger} component. */\nexport type DropdownMenuTriggerProps = React.ComponentPropsWithoutRef<\n typeof DropdownMenuPrimitive.Trigger\n>;\n\n/** The element that toggles the dropdown menu when clicked. */\nexport const DropdownMenuTrigger = DropdownMenuPrimitive.Trigger;\nDropdownMenuTrigger.displayName = \"DropdownMenuTrigger\";\n\n/** Props for the {@link DropdownMenuContent} component. */\nexport interface DropdownMenuContentProps\n extends React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Content> {}\n\n/**\n * The positioned content panel rendered inside a portal.\n *\n * Override the portal z-index per-instance via `style={{ zIndex: 1500 }}` or\n * globally with the `--fanvue-ui-portal-z-index` CSS custom property.\n *\n * @example\n * ```tsx\n * <DropdownMenu>\n * <DropdownMenuTrigger asChild>\n * <Button>Open</Button>\n * </DropdownMenuTrigger>\n * <DropdownMenuContent>\n * <DropdownMenuItem>Option 1</DropdownMenuItem>\n * <DropdownMenuItem>Option 2</DropdownMenuItem>\n * </DropdownMenuContent>\n * </DropdownMenu>\n * ```\n */\nexport const DropdownMenuContent = React.forwardRef<\n React.ComponentRef<typeof DropdownMenuPrimitive.Content>,\n DropdownMenuContentProps\n>(({
|
|
1
|
+
{"version":3,"file":"DropdownMenu.cjs","sources":["../../../../src/components/DropdownMenu/DropdownMenu.tsx"],"sourcesContent":["import * as DropdownMenuPrimitive from \"@radix-ui/react-dropdown-menu\";\nimport * as React from \"react\";\nimport { cn } from \"../../utils/cn\";\nimport { FLOATING_CONTENT_COLLISION_PADDING } from \"../../utils/floatingContentCollisionPadding\";\n\n/** Props for the {@link DropdownMenu} root component. */\nexport interface DropdownMenuProps\n extends React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Root> {}\n\n/** Root component that manages open/close state for a dropdown menu. */\nexport const DropdownMenu = DropdownMenuPrimitive.Root;\n\n/** Props for the {@link DropdownMenuTrigger} component. */\nexport type DropdownMenuTriggerProps = React.ComponentPropsWithoutRef<\n typeof DropdownMenuPrimitive.Trigger\n>;\n\n/** The element that toggles the dropdown menu when clicked. */\nexport const DropdownMenuTrigger = DropdownMenuPrimitive.Trigger;\nDropdownMenuTrigger.displayName = \"DropdownMenuTrigger\";\n\n/** Props for the {@link DropdownMenuContent} component. */\nexport interface DropdownMenuContentProps\n extends React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Content> {}\n\n/**\n * The positioned content panel rendered inside a portal.\n *\n * Override the portal z-index per-instance via `style={{ zIndex: 1500 }}` or\n * globally with the `--fanvue-ui-portal-z-index` CSS custom property.\n *\n * @example\n * ```tsx\n * <DropdownMenu>\n * <DropdownMenuTrigger asChild>\n * <Button>Open</Button>\n * </DropdownMenuTrigger>\n * <DropdownMenuContent>\n * <DropdownMenuItem>Option 1</DropdownMenuItem>\n * <DropdownMenuItem>Option 2</DropdownMenuItem>\n * </DropdownMenuContent>\n * </DropdownMenu>\n * ```\n */\nexport const DropdownMenuContent = React.forwardRef<\n React.ComponentRef<typeof DropdownMenuPrimitive.Content>,\n DropdownMenuContentProps\n>(\n (\n {\n className,\n style,\n sideOffset = 4,\n collisionPadding = FLOATING_CONTENT_COLLISION_PADDING,\n ...props\n },\n ref,\n ) => (\n <DropdownMenuPrimitive.Portal>\n <DropdownMenuPrimitive.Content\n ref={ref}\n sideOffset={sideOffset}\n collisionPadding={collisionPadding}\n className={cn(\n \"w-max min-w-(--radix-dropdown-menu-trigger-width) max-w-(--radix-dropdown-menu-content-available-width) overflow-y-auto rounded-sm border border-neutral-alphas-200 bg-bg-primary p-1 shadow-lg\",\n \"data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95\",\n \"data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95\",\n \"data-[side=top]:slide-in-from-bottom-2 data-[side=bottom]:slide-in-from-top-2\",\n \"data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2\",\n className,\n )}\n style={{\n zIndex: \"var(--fanvue-ui-portal-z-index, 50)\",\n maxHeight: \"var(--radix-dropdown-menu-content-available-height)\",\n ...style,\n }}\n {...props}\n />\n </DropdownMenuPrimitive.Portal>\n ),\n);\nDropdownMenuContent.displayName = \"DropdownMenuContent\";\n\n/** Props for the {@link DropdownMenuGroup} component. */\nexport type DropdownMenuGroupProps = React.ComponentPropsWithoutRef<\n typeof DropdownMenuPrimitive.Group\n>;\n\n/** Groups related menu items. Accepts an optional `DropdownMenuLabel`. */\nexport const DropdownMenuGroup = DropdownMenuPrimitive.Group;\nDropdownMenuGroup.displayName = \"DropdownMenuGroup\";\n\n/** Props for the {@link DropdownMenuLabel} component. */\nexport interface DropdownMenuLabelProps\n extends React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Label> {}\n\n/** A label for a group of items. Not focusable or selectable. */\nexport const DropdownMenuLabel = React.forwardRef<\n React.ComponentRef<typeof DropdownMenuPrimitive.Label>,\n DropdownMenuLabelProps\n>(({ className, ...props }, ref) => (\n <DropdownMenuPrimitive.Label\n ref={ref}\n className={cn(\"typography-medium-body-xs px-2 py-1.5 text-content-secondary\", className)}\n {...props}\n />\n));\nDropdownMenuLabel.displayName = \"DropdownMenuLabel\";\n\n/** Available sizes for a dropdown menu item. */\nexport type DropdownMenuItemSize = \"sm\" | \"md\";\n\nexport interface DropdownMenuItemProps\n extends React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Item> {\n /** Height of the menu item row. @default \"sm\" */\n size?: DropdownMenuItemSize;\n /** Whether the item uses destructive (error) styling. */\n destructive?: boolean;\n /** Icon rendered before the label. */\n leadingIcon?: React.ReactNode;\n /** Icon rendered after the label. */\n trailingIcon?: React.ReactNode;\n /** Whether the item is in a selected state. */\n selected?: boolean;\n}\n\n/**\n * An individual item within a {@link DropdownMenuContent}.\n *\n * @example\n * ```tsx\n * <DropdownMenuItem>Edit profile</DropdownMenuItem>\n * <DropdownMenuItem destructive>Delete</DropdownMenuItem>\n * <DropdownMenuItem leadingIcon={<EditIcon />}>Edit</DropdownMenuItem>\n *\n * // As a link\n * <DropdownMenuItem asChild>\n * <a href=\"/settings\">Settings</a>\n * </DropdownMenuItem>\n * ```\n */\nexport const DropdownMenuItem = React.forwardRef<\n React.ComponentRef<typeof DropdownMenuPrimitive.Item>,\n DropdownMenuItemProps\n>(\n (\n {\n size = \"sm\",\n destructive,\n leadingIcon,\n trailingIcon,\n selected,\n className,\n children,\n asChild,\n ...props\n },\n ref,\n ) => {\n const itemClassName = cn(\n \"flex w-full cursor-pointer items-center gap-1 rounded px-2 outline-none\",\n \"data-[disabled]:cursor-not-allowed data-[disabled]:opacity-50\",\n \"data-[highlighted]:bg-neutral-alphas-100\",\n size === \"sm\" ? \"min-h-[34px] py-1\" : \"min-h-[40px] py-1.5\",\n size === \"sm\" ? \"typography-medium-body-sm\" : \"typography-medium-body-md\",\n destructive && \"text-error-content\",\n selected && \"bg-success-surface\",\n className,\n );\n\n if (asChild) {\n return (\n <DropdownMenuPrimitive.Item ref={ref} asChild className={itemClassName} {...props}>\n {children}\n </DropdownMenuPrimitive.Item>\n );\n }\n\n return (\n <DropdownMenuPrimitive.Item ref={ref} className={itemClassName} {...props}>\n {leadingIcon}\n <span className=\"flex-1\">{children}</span>\n {trailingIcon}\n </DropdownMenuPrimitive.Item>\n );\n },\n);\nDropdownMenuItem.displayName = \"DropdownMenuItem\";\n\n/** Props for the {@link DropdownMenuSeparator} component. */\nexport interface DropdownMenuSeparatorProps\n extends React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Separator> {}\n\n/** Visual separator between groups of items. */\nexport const DropdownMenuSeparator = React.forwardRef<\n React.ComponentRef<typeof DropdownMenuPrimitive.Separator>,\n DropdownMenuSeparatorProps\n>(({ className, ...props }, ref) => (\n <DropdownMenuPrimitive.Separator\n ref={ref}\n className={cn(\"my-1 h-px bg-neutral-alphas-200\", className)}\n {...props}\n />\n));\nDropdownMenuSeparator.displayName = \"DropdownMenuSeparator\";\n"],"names":["DropdownMenuPrimitive","React","FLOATING_CONTENT_COLLISION_PADDING","jsx","cn","jsxs"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AAUO,MAAM,eAAeA,iCAAsB;AAQ3C,MAAM,sBAAsBA,iCAAsB;AACzD,oBAAoB,cAAc;AAyB3B,MAAM,sBAAsBC,iBAAM;AAAA,EAIvC,CACE;AAAA,IACE;AAAA,IACA;AAAA,IACA,aAAa;AAAA,IACb,mBAAmBC,gCAAAA;AAAAA,IACnB,GAAG;AAAA,EAAA,GAEL,QAEAC,2BAAAA,IAACH,iCAAsB,QAAtB,EACC,UAAAG,2BAAAA;AAAAA,IAACH,iCAAsB;AAAA,IAAtB;AAAA,MACC;AAAA,MACA;AAAA,MACA;AAAA,MACA,WAAWI,GAAAA;AAAAA,QACT;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MAAA;AAAA,MAEF,OAAO;AAAA,QACL,QAAQ;AAAA,QACR,WAAW;AAAA,QACX,GAAG;AAAA,MAAA;AAAA,MAEJ,GAAG;AAAA,IAAA;AAAA,EAAA,EACN,CACF;AAEJ;AACA,oBAAoB,cAAc;AAQ3B,MAAM,oBAAoBJ,iCAAsB;AACvD,kBAAkB,cAAc;AAOzB,MAAM,oBAAoBC,iBAAM,WAGrC,CAAC,EAAE,WAAW,GAAG,MAAA,GAAS,QAC1BE,2BAAAA;AAAAA,EAACH,iCAAsB;AAAA,EAAtB;AAAA,IACC;AAAA,IACA,WAAWI,GAAAA,GAAG,gEAAgE,SAAS;AAAA,IACtF,GAAG;AAAA,EAAA;AACN,CACD;AACD,kBAAkB,cAAc;AAkCzB,MAAM,mBAAmBH,iBAAM;AAAA,EAIpC,CACE;AAAA,IACE,OAAO;AAAA,IACP;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,GAAG;AAAA,EAAA,GAEL,QACG;AACH,UAAM,gBAAgBG,GAAAA;AAAAA,MACpB;AAAA,MACA;AAAA,MACA;AAAA,MACA,SAAS,OAAO,sBAAsB;AAAA,MACtC,SAAS,OAAO,8BAA8B;AAAA,MAC9C,eAAe;AAAA,MACf,YAAY;AAAA,MACZ;AAAA,IAAA;AAGF,QAAI,SAAS;AACX,aACED,+BAACH,iCAAsB,MAAtB,EAA2B,KAAU,SAAO,MAAC,WAAW,eAAgB,GAAG,OACzE,SAAA,CACH;AAAA,IAEJ;AAEA,WACEK,2BAAAA,KAACL,iCAAsB,MAAtB,EAA2B,KAAU,WAAW,eAAgB,GAAG,OACjE,UAAA;AAAA,MAAA;AAAA,MACDG,2BAAAA,IAAC,QAAA,EAAK,WAAU,UAAU,SAAA,CAAS;AAAA,MAClC;AAAA,IAAA,GACH;AAAA,EAEJ;AACF;AACA,iBAAiB,cAAc;AAOxB,MAAM,wBAAwBF,iBAAM,WAGzC,CAAC,EAAE,WAAW,GAAG,MAAA,GAAS,QAC1BE,2BAAAA;AAAAA,EAACH,iCAAsB;AAAA,EAAtB;AAAA,IACC;AAAA,IACA,WAAWI,GAAAA,GAAG,mCAAmC,SAAS;AAAA,IACzD,GAAG;AAAA,EAAA;AACN,CACD;AACD,sBAAsB,cAAc;;;;;;;;"}
|
|
@@ -5,6 +5,7 @@ const jsxRuntime = require("react/jsx-runtime");
|
|
|
5
5
|
const PopoverPrimitive = require("@radix-ui/react-popover");
|
|
6
6
|
const React = require("react");
|
|
7
7
|
const cn = require("../../utils/cn.cjs");
|
|
8
|
+
const floatingContentCollisionPadding = require("../../utils/floatingContentCollisionPadding.cjs");
|
|
8
9
|
const Button = require("../Button/Button.cjs");
|
|
9
10
|
function _interopNamespaceDefault(e) {
|
|
10
11
|
const n = Object.create(null, { [Symbol.toStringTag]: { value: "Module" } });
|
|
@@ -47,6 +48,7 @@ const InfoBoxContent = React__namespace.forwardRef(
|
|
|
47
48
|
children,
|
|
48
49
|
style,
|
|
49
50
|
onOpenAutoFocus,
|
|
51
|
+
collisionPadding = floatingContentCollisionPadding.FLOATING_CONTENT_COLLISION_PADDING,
|
|
50
52
|
...props
|
|
51
53
|
}, ref) => {
|
|
52
54
|
const hasHeader = icon !== void 0 || heading !== void 0 || pill !== void 0;
|
|
@@ -57,7 +59,7 @@ const InfoBoxContent = React__namespace.forwardRef(
|
|
|
57
59
|
{
|
|
58
60
|
ref,
|
|
59
61
|
sideOffset,
|
|
60
|
-
collisionPadding
|
|
62
|
+
collisionPadding,
|
|
61
63
|
style: { zIndex: "var(--fanvue-ui-portal-z-index, 50)", ...style },
|
|
62
64
|
className: cn.cn(
|
|
63
65
|
"typography-regular-body-md max-w-[280px] overflow-hidden rounded-md border border-white/20 bg-surface-primary-inverted p-4 text-content-primary-inverted shadow-[0px_2px_4px_0px_rgba(17,24,39,0.08)]",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"InfoBox.cjs","sources":["../../../../src/components/InfoBox/InfoBox.tsx"],"sourcesContent":["import * as PopoverPrimitive from \"@radix-ui/react-popover\";\nimport * as React from \"react\";\nimport { cn } from \"../../utils/cn\";\nimport { Button } from \"../Button/Button\";\n\n/** Props for the {@link InfoBox} root component. */\nexport interface InfoBoxProps extends React.ComponentPropsWithoutRef<typeof PopoverPrimitive.Root> {\n open?: boolean;\n onOpenChange?: (open: boolean) => void;\n defaultOpen?: boolean;\n}\n\n/** Root component that manages open/close state for an info box. */\nexport const InfoBox = PopoverPrimitive.Root;\n\n/** Props for the {@link InfoBoxTrigger} component. */\nexport type InfoBoxTriggerProps = React.ComponentPropsWithoutRef<typeof PopoverPrimitive.Trigger>;\n\n/** The element that triggers the info box on click. */\nexport const InfoBoxTrigger = PopoverPrimitive.Trigger;\n\n/** Action button with a label and click handler. */\ninterface InfoBoxButtonAction {\n label: string;\n onClick?: () => void;\n}\n\n/** Custom element rendered in place of the default action button. */\ninterface InfoBoxElementAction {\n element: React.ReactNode;\n}\n\n/** Action configuration for {@link InfoBoxContent}. */\nexport type InfoBoxAction = InfoBoxButtonAction | InfoBoxElementAction;\n\nexport interface InfoBoxContentProps\n extends React.ComponentPropsWithoutRef<typeof PopoverPrimitive.Content> {\n /** Whether to show the directional arrow pointer. @default true */\n showArrow?: boolean;\n /** Heading text rendered at the top of the info box. */\n heading?: React.ReactNode;\n /** Icon element displayed to the left of the heading. */\n icon?: React.ReactNode;\n /** Pill or badge element displayed to the right of the heading. */\n pill?: React.ReactNode;\n /** Primary action button (brand green). */\n primaryAction?: InfoBoxAction;\n /** Secondary action button (ghost). */\n secondaryAction?: InfoBoxAction;\n}\n\nconst ACTION_CLASSES: Record<\"brand\" | \"tertiary\", string> = {\n brand: \"hover:bg-brand-primary-default/80 hover:text-content-on-brand\",\n tertiary:\n \"text-content-primary-inverted hover:text-content-primary-inverted hover:bg-content-primary-inverted/10\",\n};\n\nconst ActionButton = ({\n action,\n variant,\n}: {\n action: InfoBoxAction;\n variant: \"brand\" | \"tertiary\";\n}) =>\n \"element\" in action ? (\n action.element\n ) : (\n <Button variant={variant} onClick={action.onClick} className={ACTION_CLASSES[variant]}>\n {action.label}\n </Button>\n );\n\nexport const InfoBoxContent = React.forwardRef<\n React.ComponentRef<typeof PopoverPrimitive.Content>,\n InfoBoxContentProps\n>(\n (\n {\n className,\n showArrow = true,\n sideOffset = 8,\n heading,\n icon,\n pill,\n primaryAction,\n secondaryAction,\n children,\n style,\n onOpenAutoFocus,\n ...props\n },\n ref,\n ) => {\n const hasHeader = icon !== undefined || heading !== undefined || pill !== undefined;\n const hasActions = primaryAction !== undefined || secondaryAction !== undefined;\n const headingId = React.useId();\n\n return (\n <PopoverPrimitive.Portal>\n <PopoverPrimitive.Content\n ref={ref}\n sideOffset={sideOffset}\n collisionPadding={
|
|
1
|
+
{"version":3,"file":"InfoBox.cjs","sources":["../../../../src/components/InfoBox/InfoBox.tsx"],"sourcesContent":["import * as PopoverPrimitive from \"@radix-ui/react-popover\";\nimport * as React from \"react\";\nimport { cn } from \"../../utils/cn\";\nimport { FLOATING_CONTENT_COLLISION_PADDING } from \"../../utils/floatingContentCollisionPadding\";\nimport { Button } from \"../Button/Button\";\n\n/** Props for the {@link InfoBox} root component. */\nexport interface InfoBoxProps extends React.ComponentPropsWithoutRef<typeof PopoverPrimitive.Root> {\n open?: boolean;\n onOpenChange?: (open: boolean) => void;\n defaultOpen?: boolean;\n}\n\n/** Root component that manages open/close state for an info box. */\nexport const InfoBox = PopoverPrimitive.Root;\n\n/** Props for the {@link InfoBoxTrigger} component. */\nexport type InfoBoxTriggerProps = React.ComponentPropsWithoutRef<typeof PopoverPrimitive.Trigger>;\n\n/** The element that triggers the info box on click. */\nexport const InfoBoxTrigger = PopoverPrimitive.Trigger;\n\n/** Action button with a label and click handler. */\ninterface InfoBoxButtonAction {\n label: string;\n onClick?: () => void;\n}\n\n/** Custom element rendered in place of the default action button. */\ninterface InfoBoxElementAction {\n element: React.ReactNode;\n}\n\n/** Action configuration for {@link InfoBoxContent}. */\nexport type InfoBoxAction = InfoBoxButtonAction | InfoBoxElementAction;\n\nexport interface InfoBoxContentProps\n extends React.ComponentPropsWithoutRef<typeof PopoverPrimitive.Content> {\n /** Whether to show the directional arrow pointer. @default true */\n showArrow?: boolean;\n /** Heading text rendered at the top of the info box. */\n heading?: React.ReactNode;\n /** Icon element displayed to the left of the heading. */\n icon?: React.ReactNode;\n /** Pill or badge element displayed to the right of the heading. */\n pill?: React.ReactNode;\n /** Primary action button (brand green). */\n primaryAction?: InfoBoxAction;\n /** Secondary action button (ghost). */\n secondaryAction?: InfoBoxAction;\n}\n\nconst ACTION_CLASSES: Record<\"brand\" | \"tertiary\", string> = {\n brand: \"hover:bg-brand-primary-default/80 hover:text-content-on-brand\",\n tertiary:\n \"text-content-primary-inverted hover:text-content-primary-inverted hover:bg-content-primary-inverted/10\",\n};\n\nconst ActionButton = ({\n action,\n variant,\n}: {\n action: InfoBoxAction;\n variant: \"brand\" | \"tertiary\";\n}) =>\n \"element\" in action ? (\n action.element\n ) : (\n <Button variant={variant} onClick={action.onClick} className={ACTION_CLASSES[variant]}>\n {action.label}\n </Button>\n );\n\nexport const InfoBoxContent = React.forwardRef<\n React.ComponentRef<typeof PopoverPrimitive.Content>,\n InfoBoxContentProps\n>(\n (\n {\n className,\n showArrow = true,\n sideOffset = 8,\n heading,\n icon,\n pill,\n primaryAction,\n secondaryAction,\n children,\n style,\n onOpenAutoFocus,\n collisionPadding = FLOATING_CONTENT_COLLISION_PADDING,\n ...props\n },\n ref,\n ) => {\n const hasHeader = icon !== undefined || heading !== undefined || pill !== undefined;\n const hasActions = primaryAction !== undefined || secondaryAction !== undefined;\n const headingId = React.useId();\n\n return (\n <PopoverPrimitive.Portal>\n <PopoverPrimitive.Content\n ref={ref}\n sideOffset={sideOffset}\n collisionPadding={collisionPadding}\n style={{ zIndex: \"var(--fanvue-ui-portal-z-index, 50)\", ...style }}\n className={cn(\n \"typography-regular-body-md max-w-[280px] overflow-hidden rounded-md border border-white/20 bg-surface-primary-inverted p-4 text-content-primary-inverted shadow-[0px_2px_4px_0px_rgba(17,24,39,0.08)]\",\n className,\n )}\n align=\"center\"\n aria-labelledby={heading ? headingId : undefined}\n arrowPadding={12}\n onOpenAutoFocus={(e) => {\n // Prevent auto-focus stealing when opening — content is supplementary, not a dialog.\n e.preventDefault();\n onOpenAutoFocus?.(e);\n }}\n {...props}\n >\n <div className=\"flex flex-col gap-3\">\n {hasHeader && (\n <div className=\"flex items-center gap-3\">\n {icon && <div className=\"size-5 shrink-0\">{icon}</div>}\n {heading && (\n <p\n id={headingId}\n className=\"typography-semibold-body-lg min-w-0 flex-1 text-content-primary-inverted\"\n >\n {heading}\n </p>\n )}\n {pill && <div className=\"shrink-0\">{pill}</div>}\n </div>\n )}\n {children && (\n <div className=\"typography-regular-body-md text-content-primary-inverted\">\n {children}\n </div>\n )}\n {hasActions && (\n <div className=\"flex items-center gap-1\">\n {primaryAction && <ActionButton action={primaryAction} variant=\"brand\" />}\n {secondaryAction && <ActionButton action={secondaryAction} variant=\"tertiary\" />}\n </div>\n )}\n </div>\n {showArrow && (\n <PopoverPrimitive.Arrow\n className={\n \"-translate-y-px! fill-surface-primary-inverted stroke-2 stroke-surface-primary-inverted\"\n }\n width={12}\n height={6}\n />\n )}\n </PopoverPrimitive.Content>\n </PopoverPrimitive.Portal>\n );\n },\n);\nInfoBoxContent.displayName = \"InfoBoxContent\";\n"],"names":["PopoverPrimitive","Button","React","FLOATING_CONTENT_COLLISION_PADDING","jsx","jsxs","cn"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;AAcO,MAAM,UAAUA,4BAAiB;AAMjC,MAAM,iBAAiBA,4BAAiB;AAgC/C,MAAM,iBAAuD;AAAA,EAC3D,OAAO;AAAA,EACP,UACE;AACJ;AAEA,MAAM,eAAe,CAAC;AAAA,EACpB;AAAA,EACA;AACF,MAIE,aAAa,SACX,OAAO,yCAENC,OAAAA,QAAA,EAAO,SAAkB,SAAS,OAAO,SAAS,WAAW,eAAe,OAAO,GACjF,iBAAO,OACV;AAGG,MAAM,iBAAiBC,iBAAM;AAAA,EAIlC,CACE;AAAA,IACE;AAAA,IACA,YAAY;AAAA,IACZ,aAAa;AAAA,IACb;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,mBAAmBC,gCAAAA;AAAAA,IACnB,GAAG;AAAA,EAAA,GAEL,QACG;AACH,UAAM,YAAY,SAAS,UAAa,YAAY,UAAa,SAAS;AAC1E,UAAM,aAAa,kBAAkB,UAAa,oBAAoB;AACtE,UAAM,YAAYD,iBAAM,MAAA;AAExB,WACEE,2BAAAA,IAACJ,4BAAiB,QAAjB,EACC,UAAAK,2BAAAA;AAAAA,MAACL,4BAAiB;AAAA,MAAjB;AAAA,QACC;AAAA,QACA;AAAA,QACA;AAAA,QACA,OAAO,EAAE,QAAQ,uCAAuC,GAAG,MAAA;AAAA,QAC3D,WAAWM,GAAAA;AAAAA,UACT;AAAA,UACA;AAAA,QAAA;AAAA,QAEF,OAAM;AAAA,QACN,mBAAiB,UAAU,YAAY;AAAA,QACvC,cAAc;AAAA,QACd,iBAAiB,CAAC,MAAM;AAEtB,YAAE,eAAA;AACF,4BAAkB,CAAC;AAAA,QACrB;AAAA,QACC,GAAG;AAAA,QAEJ,UAAA;AAAA,UAAAD,2BAAAA,KAAC,OAAA,EAAI,WAAU,uBACZ,UAAA;AAAA,YAAA,aACCA,2BAAAA,KAAC,OAAA,EAAI,WAAU,2BACZ,UAAA;AAAA,cAAA,QAAQD,2BAAAA,IAAC,OAAA,EAAI,WAAU,mBAAmB,UAAA,MAAK;AAAA,cAC/C,WACCA,2BAAAA;AAAAA,gBAAC;AAAA,gBAAA;AAAA,kBACC,IAAI;AAAA,kBACJ,WAAU;AAAA,kBAET,UAAA;AAAA,gBAAA;AAAA,cAAA;AAAA,cAGJ,QAAQA,2BAAAA,IAAC,OAAA,EAAI,WAAU,YAAY,UAAA,KAAA,CAAK;AAAA,YAAA,GAC3C;AAAA,YAED,YACCA,2BAAAA,IAAC,OAAA,EAAI,WAAU,4DACZ,UACH;AAAA,YAED,cACCC,2BAAAA,KAAC,OAAA,EAAI,WAAU,2BACZ,UAAA;AAAA,cAAA,iBAAiBD,2BAAAA,IAAC,cAAA,EAAa,QAAQ,eAAe,SAAQ,SAAQ;AAAA,cACtE,mBAAmBA,2BAAAA,IAAC,cAAA,EAAa,QAAQ,iBAAiB,SAAQ,WAAA,CAAW;AAAA,YAAA,EAAA,CAChF;AAAA,UAAA,GAEJ;AAAA,UACC,aACCA,2BAAAA;AAAAA,YAACJ,4BAAiB;AAAA,YAAjB;AAAA,cACC,WACE;AAAA,cAEF,OAAO;AAAA,cACP,QAAQ;AAAA,YAAA;AAAA,UAAA;AAAA,QACV;AAAA,MAAA;AAAA,IAAA,GAGN;AAAA,EAEJ;AACF;AACA,eAAe,cAAc;;;;"}
|
|
@@ -5,6 +5,7 @@ const jsxRuntime = require("react/jsx-runtime");
|
|
|
5
5
|
const SelectPrimitive = require("@radix-ui/react-select");
|
|
6
6
|
const React = require("react");
|
|
7
7
|
const cn = require("../../utils/cn.cjs");
|
|
8
|
+
const floatingContentCollisionPadding = require("../../utils/floatingContentCollisionPadding.cjs");
|
|
8
9
|
const CheckIcon = require("../Icons/CheckIcon.cjs");
|
|
9
10
|
const ChevronDownIcon = require("../Icons/ChevronDownIcon.cjs");
|
|
10
11
|
function _interopNamespaceDefault(e) {
|
|
@@ -141,26 +142,36 @@ const Select = React__namespace.forwardRef(
|
|
|
141
142
|
}
|
|
142
143
|
);
|
|
143
144
|
Select.displayName = "Select";
|
|
144
|
-
const SelectContent = React__namespace.forwardRef(
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
position,
|
|
149
|
-
sideOffset,
|
|
150
|
-
collisionPadding
|
|
151
|
-
style
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
145
|
+
const SelectContent = React__namespace.forwardRef(
|
|
146
|
+
({
|
|
147
|
+
className,
|
|
148
|
+
children,
|
|
149
|
+
position = "popper",
|
|
150
|
+
sideOffset = 4,
|
|
151
|
+
collisionPadding = floatingContentCollisionPadding.FLOATING_CONTENT_COLLISION_PADDING,
|
|
152
|
+
style,
|
|
153
|
+
...props
|
|
154
|
+
}, ref) => /* @__PURE__ */ jsxRuntime.jsx(SelectPrimitive__namespace.Portal, { children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
155
|
+
SelectPrimitive__namespace.Content,
|
|
156
|
+
{
|
|
157
|
+
ref,
|
|
158
|
+
position,
|
|
159
|
+
sideOffset,
|
|
160
|
+
collisionPadding,
|
|
161
|
+
style: { zIndex: "var(--fanvue-ui-portal-z-index, 50)", ...style },
|
|
162
|
+
className: cn.cn(
|
|
163
|
+
"relative w-max min-w-(--radix-select-trigger-width) max-w-(--radix-select-content-available-width) overflow-hidden rounded-sm border border-neutral-alphas-200 bg-bg-primary text-content-primary shadow-[0_4px_16px_rgba(0,0,0,0.10)]",
|
|
164
|
+
"data-[state=closed]:animate-out data-[state=open]:animate-in",
|
|
165
|
+
"data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
|
|
166
|
+
"data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95",
|
|
167
|
+
"data-[side=bottom]:slide-in-from-top-2 data-[side=top]:slide-in-from-bottom-2",
|
|
168
|
+
className
|
|
169
|
+
),
|
|
170
|
+
...props,
|
|
171
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(SelectPrimitive__namespace.Viewport, { className: "max-h-[var(--radix-select-content-available-height)] overflow-y-auto p-1", children })
|
|
172
|
+
}
|
|
173
|
+
) })
|
|
174
|
+
);
|
|
164
175
|
SelectContent.displayName = "SelectContent";
|
|
165
176
|
const SelectItem = React__namespace.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
166
177
|
SelectPrimitive__namespace.Item,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Select.cjs","sources":["../../../../src/components/Select/Select.tsx"],"sourcesContent":["import * as SelectPrimitive from \"@radix-ui/react-select\";\nimport * as React from \"react\";\nimport { cn } from \"@/utils/cn\";\nimport { CheckIcon } from \"../Icons/CheckIcon\";\nimport { ChevronDownIcon } from \"../Icons/ChevronDownIcon\";\n\n/** Select field height in pixels. */\nexport type SelectSize = \"48\" | \"40\" | \"32\";\n\ntype SelectContextValue = {\n size: SelectSize;\n error: boolean;\n disabled?: boolean;\n};\n\nconst SelectContext = React.createContext<SelectContextValue>({\n size: \"48\",\n error: false,\n});\n\nconst TRIGGER_HEIGHT: Record<SelectSize, string> = {\n \"48\": \"h-12\",\n \"40\": \"h-10\",\n \"32\": \"h-8\",\n};\n\nconst TRIGGER_PADDING_X: Record<SelectSize, string> = {\n \"48\": \"px-4\",\n \"40\": \"px-4\",\n \"32\": \"px-3\",\n};\n\nconst TRIGGER_GAP: Record<SelectSize, string> = {\n \"48\": \"gap-3\",\n \"40\": \"gap-3\",\n \"32\": \"gap-2\",\n};\n\nconst TRIGGER_TYPOGRAPHY: Record<SelectSize, string> = {\n \"48\": \"typography-regular-body-lg\",\n \"40\": \"typography-regular-body-lg\",\n \"32\": \"typography-regular-body-md\",\n};\n\nexport interface SelectProps extends Omit<SelectPrimitive.SelectProps, \"dir\"> {\n /** Label text displayed above the trigger. Also used as the accessible name. */\n label?: string;\n /** Accessible name applied directly to the trigger button when no visible `label` is provided. */\n \"aria-label\"?: string;\n /** ID of an external element that labels the trigger button. */\n \"aria-labelledby\"?: string;\n /** Helper text displayed below the trigger. Replaced by `errorMessage` when `error` is `true`. */\n helperText?: string;\n /** Height of the select field in pixels. @default \"48\" */\n size?: SelectSize;\n /** Whether the field is in an error state. @default false */\n error?: boolean;\n /** Error message displayed below the trigger. Shown instead of `helperText` when `error` is `true`. */\n errorMessage?: string;\n /** Placeholder shown when no value is selected. */\n placeholder?: string;\n /** Icon element displayed at the left side of the trigger. */\n leftIcon?: React.ReactNode;\n /** Whether the field stretches to fill its container width. @default false */\n fullWidth?: boolean;\n /** Wraps the `className` of the outermost container div. */\n className?: string;\n /** HTML `id` applied to the trigger button. Auto-generated if omitted. */\n id?: string;\n}\n\n/**\n * A select field with optional label, helper/error text, and an icon slot,\n * built on Radix UI Select for full accessibility and keyboard navigation.\n *\n * Pair with {@link SelectContent} and {@link SelectItem} to provide options.\n *\n * @example\n * ```tsx\n * <Select label=\"Country\" placeholder=\"Select a country\">\n * <SelectContent>\n * <SelectItem value=\"us\">United States</SelectItem>\n * <SelectItem value=\"uk\">United Kingdom</SelectItem>\n * </SelectContent>\n * </Select>\n * ```\n */\nexport const Select = React.forwardRef<\n React.ComponentRef<typeof SelectPrimitive.Trigger>,\n SelectProps\n>(\n (\n {\n label,\n helperText,\n size = \"48\",\n error = false,\n errorMessage,\n placeholder,\n leftIcon,\n fullWidth = false,\n className,\n id,\n disabled,\n children,\n \"aria-label\": ariaLabel,\n \"aria-labelledby\": ariaLabelledby,\n ...props\n },\n ref,\n ) => {\n const generatedId = React.useId();\n const triggerId = id ?? generatedId;\n const helperTextId = `${triggerId}-helper`;\n const bottomText = error && errorMessage ? errorMessage : helperText;\n\n return (\n <SelectContext.Provider value={{ size, error, disabled }}>\n <div\n className={cn(\"flex flex-col\", fullWidth && \"w-full\", className)}\n data-disabled={disabled ? \"\" : undefined}\n data-error={error ? \"\" : undefined}\n >\n {label && (\n <label\n htmlFor={triggerId}\n className=\"typography-semibold-body-sm px-1 pt-1 pb-2 text-content-primary\"\n >\n {label}\n </label>\n )}\n\n <SelectPrimitive.Root disabled={disabled} {...props}>\n <SelectPrimitive.Trigger\n ref={ref}\n id={triggerId}\n aria-label={ariaLabel}\n aria-labelledby={ariaLabelledby}\n aria-describedby={bottomText ? helperTextId : undefined}\n aria-invalid={error || undefined}\n className={cn(\n \"flex w-full cursor-pointer items-center justify-between rounded-sm border bg-neutral-alphas-50 outline-none motion-safe:transition-colors\",\n TRIGGER_HEIGHT[size],\n TRIGGER_PADDING_X[size],\n TRIGGER_GAP[size],\n TRIGGER_TYPOGRAPHY[size],\n error ? \"border-error-content\" : \"border-transparent\",\n !disabled &&\n !error &&\n \"hover:border-neutral-alphas-400 data-[state=open]:border-neutral-alphas-400\",\n disabled && \"cursor-not-allowed opacity-50\",\n )}\n >\n <div className=\"flex min-w-0 items-center gap-2\">\n {leftIcon && (\n <span\n className=\"flex size-5 shrink-0 items-center justify-center text-content-secondary\"\n data-testid=\"left-icon\"\n >\n {leftIcon}\n </span>\n )}\n <span className=\"min-w-0 flex-1 truncate text-left text-content-primary [&>[data-placeholder]]:text-content-secondary [&>[data-placeholder]]:opacity-40\">\n <SelectPrimitive.Value placeholder={placeholder} />\n </span>\n </div>\n\n <SelectPrimitive.Icon asChild>\n <ChevronDownIcon />\n </SelectPrimitive.Icon>\n </SelectPrimitive.Trigger>\n\n {children}\n </SelectPrimitive.Root>\n\n {bottomText && (\n <p\n id={helperTextId}\n className={cn(\n \"typography-regular-body-sm px-2 pt-1 pb-0.5\",\n error ? \"text-error-content\" : \"text-content-secondary\",\n )}\n >\n {bottomText}\n </p>\n )}\n </div>\n </SelectContext.Provider>\n );\n },\n);\n\nSelect.displayName = \"Select\";\n\nexport interface SelectContentProps\n extends React.ComponentPropsWithoutRef<typeof SelectPrimitive.Content> {}\n\n/**\n * The dropdown panel rendered inside a portal. Place {@link SelectItem} elements\n * (and optionally {@link SelectGroup} / {@link SelectLabel}) as children.\n */\nexport const SelectContent = React.forwardRef<\n React.ComponentRef<typeof SelectPrimitive.Content>,\n SelectContentProps\n>(({ className, children, position = \"popper\", sideOffset = 4, style, ...props }, ref) => (\n <SelectPrimitive.Portal>\n <SelectPrimitive.Content\n ref={ref}\n position={position}\n sideOffset={sideOffset}\n collisionPadding={8}\n style={{ zIndex: \"var(--fanvue-ui-portal-z-index, 50)\", ...style }}\n className={cn(\n \"relative min-w-(--radix-select-trigger-width) overflow-hidden rounded-sm border border-neutral-alphas-200 bg-bg-primary text-content-primary shadow-[0_4px_16px_rgba(0,0,0,0.10)]\",\n \"data-[state=closed]:animate-out data-[state=open]:animate-in\",\n \"data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0\",\n \"data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95\",\n \"data-[side=bottom]:slide-in-from-top-2 data-[side=top]:slide-in-from-bottom-2\",\n className,\n )}\n {...props}\n >\n <SelectPrimitive.Viewport className=\"max-h-[var(--radix-select-content-available-height)] overflow-y-auto p-1\">\n {children}\n </SelectPrimitive.Viewport>\n </SelectPrimitive.Content>\n </SelectPrimitive.Portal>\n));\n\nSelectContent.displayName = \"SelectContent\";\n\nexport interface SelectItemProps\n extends React.ComponentPropsWithoutRef<typeof SelectPrimitive.Item> {}\n\n/**\n * An individual option inside {@link SelectContent}.\n */\nexport const SelectItem = React.forwardRef<\n React.ComponentRef<typeof SelectPrimitive.Item>,\n SelectItemProps\n>(({ className, children, ...props }, ref) => (\n <SelectPrimitive.Item\n ref={ref}\n className={cn(\n \"typography-regular-body-lg relative flex w-full cursor-pointer select-none items-center gap-2 rounded-xs py-2 pr-2 pl-3 text-content-primary outline-none\",\n \"focus:bg-neutral-alphas-100 data-disabled:pointer-events-none data-disabled:opacity-50\",\n className,\n )}\n {...props}\n >\n <SelectPrimitive.ItemText>{children}</SelectPrimitive.ItemText>\n <SelectPrimitive.ItemIndicator className=\"ml-auto flex size-4 shrink-0 items-center justify-center\">\n <CheckIcon className=\"size-4 text-content-primary\" />\n </SelectPrimitive.ItemIndicator>\n </SelectPrimitive.Item>\n));\n\nSelectItem.displayName = \"SelectItem\";\n\n/** Props for {@link SelectGroup}. */\nexport type SelectGroupProps = React.ComponentPropsWithoutRef<typeof SelectPrimitive.Group>;\n\n/**\n * Groups related {@link SelectItem} elements under a {@link SelectLabel}.\n */\nexport const SelectGroup = SelectPrimitive.Group;\nSelectGroup.displayName = \"SelectGroup\";\n\nexport interface SelectLabelProps\n extends React.ComponentPropsWithoutRef<typeof SelectPrimitive.Label> {}\n\n/**\n * A non-interactive label shown above a {@link SelectGroup}.\n */\nexport const SelectLabel = React.forwardRef<\n React.ComponentRef<typeof SelectPrimitive.Label>,\n SelectLabelProps\n>(({ className, ...props }, ref) => (\n <SelectPrimitive.Label\n ref={ref}\n className={cn(\"typography-semibold-body-sm px-3 py-1.5 text-content-secondary\", className)}\n {...props}\n />\n));\n\nSelectLabel.displayName = \"SelectLabel\";\n\nexport interface SelectSeparatorProps\n extends React.ComponentPropsWithoutRef<typeof SelectPrimitive.Separator> {}\n\n/** A horizontal rule that visually separates groups in {@link SelectContent}. */\nexport const SelectSeparator = React.forwardRef<\n React.ComponentRef<typeof SelectPrimitive.Separator>,\n SelectSeparatorProps\n>(({ className, ...props }, ref) => (\n <SelectPrimitive.Separator\n ref={ref}\n className={cn(\"-mx-1 my-1 h-px bg-neutral-alphas-200\", className)}\n {...props}\n />\n));\n\nSelectSeparator.displayName = \"SelectSeparator\";\n"],"names":["React","jsx","jsxs","cn","SelectPrimitive","ChevronDownIcon","CheckIcon"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Select.cjs","sources":["../../../../src/components/Select/Select.tsx"],"sourcesContent":["import * as SelectPrimitive from \"@radix-ui/react-select\";\nimport * as React from \"react\";\nimport { cn } from \"@/utils/cn\";\nimport { FLOATING_CONTENT_COLLISION_PADDING } from \"@/utils/floatingContentCollisionPadding\";\nimport { CheckIcon } from \"../Icons/CheckIcon\";\nimport { ChevronDownIcon } from \"../Icons/ChevronDownIcon\";\n\n/** Select field height in pixels. */\nexport type SelectSize = \"48\" | \"40\" | \"32\";\n\ntype SelectContextValue = {\n size: SelectSize;\n error: boolean;\n disabled?: boolean;\n};\n\nconst SelectContext = React.createContext<SelectContextValue>({\n size: \"48\",\n error: false,\n});\n\nconst TRIGGER_HEIGHT: Record<SelectSize, string> = {\n \"48\": \"h-12\",\n \"40\": \"h-10\",\n \"32\": \"h-8\",\n};\n\nconst TRIGGER_PADDING_X: Record<SelectSize, string> = {\n \"48\": \"px-4\",\n \"40\": \"px-4\",\n \"32\": \"px-3\",\n};\n\nconst TRIGGER_GAP: Record<SelectSize, string> = {\n \"48\": \"gap-3\",\n \"40\": \"gap-3\",\n \"32\": \"gap-2\",\n};\n\nconst TRIGGER_TYPOGRAPHY: Record<SelectSize, string> = {\n \"48\": \"typography-regular-body-lg\",\n \"40\": \"typography-regular-body-lg\",\n \"32\": \"typography-regular-body-md\",\n};\n\nexport interface SelectProps extends Omit<SelectPrimitive.SelectProps, \"dir\"> {\n /** Label text displayed above the trigger. Also used as the accessible name. */\n label?: string;\n /** Accessible name applied directly to the trigger button when no visible `label` is provided. */\n \"aria-label\"?: string;\n /** ID of an external element that labels the trigger button. */\n \"aria-labelledby\"?: string;\n /** Helper text displayed below the trigger. Replaced by `errorMessage` when `error` is `true`. */\n helperText?: string;\n /** Height of the select field in pixels. @default \"48\" */\n size?: SelectSize;\n /** Whether the field is in an error state. @default false */\n error?: boolean;\n /** Error message displayed below the trigger. Shown instead of `helperText` when `error` is `true`. */\n errorMessage?: string;\n /** Placeholder shown when no value is selected. */\n placeholder?: string;\n /** Icon element displayed at the left side of the trigger. */\n leftIcon?: React.ReactNode;\n /** Whether the field stretches to fill its container width. @default false */\n fullWidth?: boolean;\n /** Wraps the `className` of the outermost container div. */\n className?: string;\n /** HTML `id` applied to the trigger button. Auto-generated if omitted. */\n id?: string;\n}\n\n/**\n * A select field with optional label, helper/error text, and an icon slot,\n * built on Radix UI Select for full accessibility and keyboard navigation.\n *\n * Pair with {@link SelectContent} and {@link SelectItem} to provide options.\n *\n * @example\n * ```tsx\n * <Select label=\"Country\" placeholder=\"Select a country\">\n * <SelectContent>\n * <SelectItem value=\"us\">United States</SelectItem>\n * <SelectItem value=\"uk\">United Kingdom</SelectItem>\n * </SelectContent>\n * </Select>\n * ```\n */\nexport const Select = React.forwardRef<\n React.ComponentRef<typeof SelectPrimitive.Trigger>,\n SelectProps\n>(\n (\n {\n label,\n helperText,\n size = \"48\",\n error = false,\n errorMessage,\n placeholder,\n leftIcon,\n fullWidth = false,\n className,\n id,\n disabled,\n children,\n \"aria-label\": ariaLabel,\n \"aria-labelledby\": ariaLabelledby,\n ...props\n },\n ref,\n ) => {\n const generatedId = React.useId();\n const triggerId = id ?? generatedId;\n const helperTextId = `${triggerId}-helper`;\n const bottomText = error && errorMessage ? errorMessage : helperText;\n\n return (\n <SelectContext.Provider value={{ size, error, disabled }}>\n <div\n className={cn(\"flex flex-col\", fullWidth && \"w-full\", className)}\n data-disabled={disabled ? \"\" : undefined}\n data-error={error ? \"\" : undefined}\n >\n {label && (\n <label\n htmlFor={triggerId}\n className=\"typography-semibold-body-sm px-1 pt-1 pb-2 text-content-primary\"\n >\n {label}\n </label>\n )}\n\n <SelectPrimitive.Root disabled={disabled} {...props}>\n <SelectPrimitive.Trigger\n ref={ref}\n id={triggerId}\n aria-label={ariaLabel}\n aria-labelledby={ariaLabelledby}\n aria-describedby={bottomText ? helperTextId : undefined}\n aria-invalid={error || undefined}\n className={cn(\n \"flex w-full cursor-pointer items-center justify-between rounded-sm border bg-neutral-alphas-50 outline-none motion-safe:transition-colors\",\n TRIGGER_HEIGHT[size],\n TRIGGER_PADDING_X[size],\n TRIGGER_GAP[size],\n TRIGGER_TYPOGRAPHY[size],\n error ? \"border-error-content\" : \"border-transparent\",\n !disabled &&\n !error &&\n \"hover:border-neutral-alphas-400 data-[state=open]:border-neutral-alphas-400\",\n disabled && \"cursor-not-allowed opacity-50\",\n )}\n >\n <div className=\"flex min-w-0 items-center gap-2\">\n {leftIcon && (\n <span\n className=\"flex size-5 shrink-0 items-center justify-center text-content-secondary\"\n data-testid=\"left-icon\"\n >\n {leftIcon}\n </span>\n )}\n <span className=\"min-w-0 flex-1 truncate text-left text-content-primary [&>[data-placeholder]]:text-content-secondary [&>[data-placeholder]]:opacity-40\">\n <SelectPrimitive.Value placeholder={placeholder} />\n </span>\n </div>\n\n <SelectPrimitive.Icon asChild>\n <ChevronDownIcon />\n </SelectPrimitive.Icon>\n </SelectPrimitive.Trigger>\n\n {children}\n </SelectPrimitive.Root>\n\n {bottomText && (\n <p\n id={helperTextId}\n className={cn(\n \"typography-regular-body-sm px-2 pt-1 pb-0.5\",\n error ? \"text-error-content\" : \"text-content-secondary\",\n )}\n >\n {bottomText}\n </p>\n )}\n </div>\n </SelectContext.Provider>\n );\n },\n);\n\nSelect.displayName = \"Select\";\n\nexport interface SelectContentProps\n extends React.ComponentPropsWithoutRef<typeof SelectPrimitive.Content> {}\n\n/**\n * The dropdown panel rendered inside a portal. Place {@link SelectItem} elements\n * (and optionally {@link SelectGroup} / {@link SelectLabel}) as children.\n */\nexport const SelectContent = React.forwardRef<\n React.ComponentRef<typeof SelectPrimitive.Content>,\n SelectContentProps\n>(\n (\n {\n className,\n children,\n position = \"popper\",\n sideOffset = 4,\n collisionPadding = FLOATING_CONTENT_COLLISION_PADDING,\n style,\n ...props\n },\n ref,\n ) => (\n <SelectPrimitive.Portal>\n <SelectPrimitive.Content\n ref={ref}\n position={position}\n sideOffset={sideOffset}\n collisionPadding={collisionPadding}\n style={{ zIndex: \"var(--fanvue-ui-portal-z-index, 50)\", ...style }}\n className={cn(\n \"relative w-max min-w-(--radix-select-trigger-width) max-w-(--radix-select-content-available-width) overflow-hidden rounded-sm border border-neutral-alphas-200 bg-bg-primary text-content-primary shadow-[0_4px_16px_rgba(0,0,0,0.10)]\",\n \"data-[state=closed]:animate-out data-[state=open]:animate-in\",\n \"data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0\",\n \"data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95\",\n \"data-[side=bottom]:slide-in-from-top-2 data-[side=top]:slide-in-from-bottom-2\",\n className,\n )}\n {...props}\n >\n <SelectPrimitive.Viewport className=\"max-h-[var(--radix-select-content-available-height)] overflow-y-auto p-1\">\n {children}\n </SelectPrimitive.Viewport>\n </SelectPrimitive.Content>\n </SelectPrimitive.Portal>\n ),\n);\n\nSelectContent.displayName = \"SelectContent\";\n\nexport interface SelectItemProps\n extends React.ComponentPropsWithoutRef<typeof SelectPrimitive.Item> {}\n\n/**\n * An individual option inside {@link SelectContent}.\n */\nexport const SelectItem = React.forwardRef<\n React.ComponentRef<typeof SelectPrimitive.Item>,\n SelectItemProps\n>(({ className, children, ...props }, ref) => (\n <SelectPrimitive.Item\n ref={ref}\n className={cn(\n \"typography-regular-body-lg relative flex w-full cursor-pointer select-none items-center gap-2 rounded-xs py-2 pr-2 pl-3 text-content-primary outline-none\",\n \"focus:bg-neutral-alphas-100 data-disabled:pointer-events-none data-disabled:opacity-50\",\n className,\n )}\n {...props}\n >\n <SelectPrimitive.ItemText>{children}</SelectPrimitive.ItemText>\n <SelectPrimitive.ItemIndicator className=\"ml-auto flex size-4 shrink-0 items-center justify-center\">\n <CheckIcon className=\"size-4 text-content-primary\" />\n </SelectPrimitive.ItemIndicator>\n </SelectPrimitive.Item>\n));\n\nSelectItem.displayName = \"SelectItem\";\n\n/** Props for {@link SelectGroup}. */\nexport type SelectGroupProps = React.ComponentPropsWithoutRef<typeof SelectPrimitive.Group>;\n\n/**\n * Groups related {@link SelectItem} elements under a {@link SelectLabel}.\n */\nexport const SelectGroup = SelectPrimitive.Group;\nSelectGroup.displayName = \"SelectGroup\";\n\nexport interface SelectLabelProps\n extends React.ComponentPropsWithoutRef<typeof SelectPrimitive.Label> {}\n\n/**\n * A non-interactive label shown above a {@link SelectGroup}.\n */\nexport const SelectLabel = React.forwardRef<\n React.ComponentRef<typeof SelectPrimitive.Label>,\n SelectLabelProps\n>(({ className, ...props }, ref) => (\n <SelectPrimitive.Label\n ref={ref}\n className={cn(\"typography-semibold-body-sm px-3 py-1.5 text-content-secondary\", className)}\n {...props}\n />\n));\n\nSelectLabel.displayName = \"SelectLabel\";\n\nexport interface SelectSeparatorProps\n extends React.ComponentPropsWithoutRef<typeof SelectPrimitive.Separator> {}\n\n/** A horizontal rule that visually separates groups in {@link SelectContent}. */\nexport const SelectSeparator = React.forwardRef<\n React.ComponentRef<typeof SelectPrimitive.Separator>,\n SelectSeparatorProps\n>(({ className, ...props }, ref) => (\n <SelectPrimitive.Separator\n ref={ref}\n className={cn(\"-mx-1 my-1 h-px bg-neutral-alphas-200\", className)}\n {...props}\n />\n));\n\nSelectSeparator.displayName = \"SelectSeparator\";\n"],"names":["React","jsx","jsxs","cn","SelectPrimitive","ChevronDownIcon","FLOATING_CONTENT_COLLISION_PADDING","CheckIcon"],"mappings":"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"}
|
|
@@ -35,7 +35,7 @@ const TooltipContent = React__namespace.forwardRef(({ className, sideOffset = 8,
|
|
|
35
35
|
collisionPadding: 8,
|
|
36
36
|
style: { zIndex: "var(--fanvue-ui-portal-z-index, 50)", ...style },
|
|
37
37
|
className: cn.cn(
|
|
38
|
-
"typography-semibold-body-sm max-w-[320px] rounded-
|
|
38
|
+
"typography-semibold-body-sm max-w-[320px] rounded-sm bg-surface-primary-inverted px-4 py-2 text-content-primary-inverted shadow-[0px_1px_4px_0px_rgba(0,0,0,0.06),0px_1px_3px_0px_rgba(0,0,0,0.05)]",
|
|
39
39
|
className
|
|
40
40
|
),
|
|
41
41
|
align: "center",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Tooltip.cjs","sources":["../../../../src/components/Tooltip/Tooltip.tsx"],"sourcesContent":["import * as TooltipPrimitive from \"@radix-ui/react-tooltip\";\nimport * as React from \"react\";\nimport { cn } from \"../../utils/cn\";\n\n/** Props for the {@link TooltipProvider}. Wraps Radix `Tooltip.Provider`. */\nexport type TooltipProviderProps = React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Provider>;\n\n/** Provides tooltip delay and skip-delay context. Wrap your app or a subtree. */\nexport const TooltipProvider = TooltipPrimitive.Provider;\n\n/** Props for the {@link Tooltip} root component. */\nexport interface TooltipProps extends React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Root> {\n open?: boolean;\n onOpenChange?: (open: boolean) => void;\n defaultOpen?: boolean;\n}\n\n/** Root component that manages open/close state for a single tooltip. */\nexport const Tooltip = TooltipPrimitive.Root;\n\n/** Props for the {@link TooltipTrigger} component. */\nexport type TooltipTriggerProps = React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Trigger>;\n\n/** The element that triggers the tooltip on hover/focus. */\nexport const TooltipTrigger = TooltipPrimitive.Trigger;\n\nexport type TooltipContentProps = React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Content>;\n\nexport const TooltipContent = React.forwardRef<\n React.ComponentRef<typeof TooltipPrimitive.Content>,\n TooltipContentProps\n>(({ className, sideOffset = 8, style, ...props }, ref) => {\n return (\n <TooltipPrimitive.Portal>\n <TooltipPrimitive.Content\n ref={ref}\n sideOffset={sideOffset}\n collisionPadding={8}\n style={{ zIndex: \"var(--fanvue-ui-portal-z-index, 50)\", ...style }}\n className={cn(\n \"typography-semibold-body-sm max-w-[320px] rounded-
|
|
1
|
+
{"version":3,"file":"Tooltip.cjs","sources":["../../../../src/components/Tooltip/Tooltip.tsx"],"sourcesContent":["import * as TooltipPrimitive from \"@radix-ui/react-tooltip\";\nimport * as React from \"react\";\nimport { cn } from \"../../utils/cn\";\n\n/** Props for the {@link TooltipProvider}. Wraps Radix `Tooltip.Provider`. */\nexport type TooltipProviderProps = React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Provider>;\n\n/** Provides tooltip delay and skip-delay context. Wrap your app or a subtree. */\nexport const TooltipProvider = TooltipPrimitive.Provider;\n\n/** Props for the {@link Tooltip} root component. */\nexport interface TooltipProps extends React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Root> {\n open?: boolean;\n onOpenChange?: (open: boolean) => void;\n defaultOpen?: boolean;\n}\n\n/** Root component that manages open/close state for a single tooltip. */\nexport const Tooltip = TooltipPrimitive.Root;\n\n/** Props for the {@link TooltipTrigger} component. */\nexport type TooltipTriggerProps = React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Trigger>;\n\n/** The element that triggers the tooltip on hover/focus. */\nexport const TooltipTrigger = TooltipPrimitive.Trigger;\n\nexport type TooltipContentProps = React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Content>;\n\nexport const TooltipContent = React.forwardRef<\n React.ComponentRef<typeof TooltipPrimitive.Content>,\n TooltipContentProps\n>(({ className, sideOffset = 8, style, ...props }, ref) => {\n return (\n <TooltipPrimitive.Portal>\n <TooltipPrimitive.Content\n ref={ref}\n sideOffset={sideOffset}\n collisionPadding={8}\n style={{ zIndex: \"var(--fanvue-ui-portal-z-index, 50)\", ...style }}\n className={cn(\n \"typography-semibold-body-sm max-w-[320px] rounded-sm bg-surface-primary-inverted px-4 py-2 text-content-primary-inverted shadow-[0px_1px_4px_0px_rgba(0,0,0,0.06),0px_1px_3px_0px_rgba(0,0,0,0.05)]\",\n className,\n )}\n align=\"center\"\n {...props}\n />\n </TooltipPrimitive.Portal>\n );\n});\nTooltipContent.displayName = \"TooltipContent\";\n"],"names":["TooltipPrimitive","React","jsx","cn"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;AAQO,MAAM,kBAAkBA,4BAAiB;AAUzC,MAAM,UAAUA,4BAAiB;AAMjC,MAAM,iBAAiBA,4BAAiB;AAIxC,MAAM,iBAAiBC,iBAAM,WAGlC,CAAC,EAAE,WAAW,aAAa,GAAG,OAAO,GAAG,MAAA,GAAS,QAAQ;AACzD,SACEC,2BAAAA,IAACF,4BAAiB,QAAjB,EACC,UAAAE,2BAAAA;AAAAA,IAACF,4BAAiB;AAAA,IAAjB;AAAA,MACC;AAAA,MACA;AAAA,MACA,kBAAkB;AAAA,MAClB,OAAO,EAAE,QAAQ,uCAAuC,GAAG,MAAA;AAAA,MAC3D,WAAWG,GAAAA;AAAAA,QACT;AAAA,QACA;AAAA,MAAA;AAAA,MAEF,OAAM;AAAA,MACL,GAAG;AAAA,IAAA;AAAA,EAAA,GAER;AAEJ,CAAC;AACD,eAAe,cAAc;;;;;"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
"use strict";
|
|
3
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
4
|
+
const FLOATING_CONTENT_COLLISION_PADDING = 16;
|
|
5
|
+
exports.FLOATING_CONTENT_COLLISION_PADDING = FLOATING_CONTENT_COLLISION_PADDING;
|
|
6
|
+
//# sourceMappingURL=floatingContentCollisionPadding.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"floatingContentCollisionPadding.cjs","sources":["../../../src/utils/floatingContentCollisionPadding.ts"],"sourcesContent":["/**\n * Default viewport inset for Radix-positioned panels (dropdown, select list, autocomplete).\n * Applied via `collisionPadding` so content stays off screen edges on narrow viewports.\n */\nexport const FLOATING_CONTENT_COLLISION_PADDING = 16;\n"],"names":[],"mappings":";;;AAIO,MAAM,qCAAqC;;"}
|
|
@@ -3,6 +3,7 @@ import { jsx, jsxs } from "react/jsx-runtime";
|
|
|
3
3
|
import * as PopoverPrimitive from "@radix-ui/react-popover";
|
|
4
4
|
import * as React from "react";
|
|
5
5
|
import { cn } from "../../utils/cn.mjs";
|
|
6
|
+
import { FLOATING_CONTENT_COLLISION_PADDING } from "../../utils/floatingContentCollisionPadding.mjs";
|
|
6
7
|
import { ChevronDownIcon } from "../Icons/ChevronDownIcon.mjs";
|
|
7
8
|
import { CloseIcon } from "../Icons/CloseIcon.mjs";
|
|
8
9
|
import { SpinnerIcon } from "../Icons/SpinnerIcon.mjs";
|
|
@@ -158,12 +159,12 @@ const Autocomplete = React.forwardRef((props, ref) => {
|
|
|
158
159
|
PopoverPrimitive.Content,
|
|
159
160
|
{
|
|
160
161
|
sideOffset: 4,
|
|
161
|
-
collisionPadding:
|
|
162
|
+
collisionPadding: FLOATING_CONTENT_COLLISION_PADDING,
|
|
162
163
|
onOpenAutoFocus: (e) => e.preventDefault(),
|
|
163
164
|
onCloseAutoFocus: (e) => e.preventDefault(),
|
|
164
165
|
style: { zIndex: "var(--fanvue-ui-portal-z-index, 50)" },
|
|
165
166
|
className: cn(
|
|
166
|
-
"w-(--radix-
|
|
167
|
+
"w-max min-w-(--radix-popper-anchor-width) max-w-(--radix-popover-content-available-width) overflow-hidden rounded-sm border border-neutral-alphas-200 bg-bg-primary text-content-primary shadow-[0_4px_16px_rgba(0,0,0,0.10)]",
|
|
167
168
|
"data-[state=closed]:animate-out data-[state=open]:animate-in",
|
|
168
169
|
"data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
|
|
169
170
|
"data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Autocomplete.mjs","sources":["../../../src/components/Autocomplete/Autocomplete.tsx"],"sourcesContent":["import * as Popover from \"@radix-ui/react-popover\";\nimport * as React from \"react\";\nimport { cn } from \"@/utils/cn\";\nimport { ChevronDownIcon } from \"../Icons/ChevronDownIcon\";\nimport { CloseIcon } from \"../Icons/CloseIcon\";\nimport { SpinnerIcon } from \"../Icons/SpinnerIcon\";\nimport { AutocompleteDropdownContent } from \"./AutocompleteDropdownContent\";\nimport { AutocompleteTag } from \"./AutocompleteTag\";\nimport { useAutocomplete } from \"./useAutocomplete\";\n\nexport type AutocompleteSize = \"48\" | \"40\" | \"32\";\n\nexport interface AutocompleteOption {\n value: string;\n label?: string;\n disabled?: boolean;\n}\n\ninterface AutocompleteBaseProps {\n label?: string;\n \"aria-label\"?: string;\n \"aria-labelledby\"?: string;\n helperText?: string;\n /** @default \"48\" */\n size?: AutocompleteSize;\n /** @default false */\n error?: boolean;\n errorMessage?: string;\n placeholder?: string;\n leftIcon?: React.ReactNode;\n /** @default false */\n fullWidth?: boolean;\n /** @default false */\n disabled?: boolean;\n /** @default false */\n clearable?: boolean;\n clearAriaLabel?: string;\n id?: string;\n className?: string;\n options: AutocompleteOption[];\n inputValue?: string;\n onInputChange?: (value: string) => void;\n filterFn?: (option: AutocompleteOption, query: string) => boolean;\n /** @default false */\n creatable?: boolean;\n creatableLabel?: (inputValue: string) => string;\n onCreate?: (inputValue: string) => void;\n /** @default false */\n loading?: boolean;\n loadingText?: string;\n emptyText?: string;\n renderOption?: (\n option: AutocompleteOption,\n state: { selected: boolean; active: boolean },\n ) => React.ReactNode;\n renderTag?: (option: AutocompleteOption, onRemove: () => void) => React.ReactNode;\n open?: boolean;\n defaultOpen?: boolean;\n onOpenChange?: (open: boolean) => void;\n}\n\ninterface AutocompleteSingleProps extends AutocompleteBaseProps {\n multiple?: false;\n value?: string | null;\n defaultValue?: string | null;\n onChange?: (value: string | null) => void;\n}\n\ninterface AutocompleteMultiProps extends AutocompleteBaseProps {\n multiple: true;\n value?: string[];\n defaultValue?: string[];\n onChange?: (values: string[]) => void;\n}\n\nexport type AutocompleteProps = AutocompleteSingleProps | AutocompleteMultiProps;\n\nconst CONTAINER_HEIGHT: Record<AutocompleteSize, string> = {\n \"48\": \"min-h-12\",\n \"40\": \"min-h-10\",\n \"32\": \"min-h-8\",\n};\n\nconst INPUT_SIZE_CLASSES: Record<AutocompleteSize, string> = {\n \"48\": \"typography-regular-body-lg\",\n \"40\": \"typography-regular-body-lg\",\n \"32\": \"typography-regular-body-md\",\n};\n\nconst PADDING_CLASSES: Record<AutocompleteSize, string> = {\n \"48\": \"px-4 py-1.5 gap-3\",\n \"40\": \"px-4 py-1 gap-3\",\n \"32\": \"px-3 py-1 gap-2\",\n};\n\nfunction warnMissingAccessibleName(label?: string, ariaLabel?: string, ariaLabelledBy?: string) {\n if (process.env.NODE_ENV !== \"production\") {\n if (!label && !ariaLabel && !ariaLabelledBy) {\n console.warn(\n \"Autocomplete: no accessible name provided. Pass a `label`, `aria-label`, or `aria-labelledby` prop.\",\n );\n }\n }\n}\n\n// biome-ignore lint/complexity/noExcessiveCognitiveComplexity: Conditional JSX branches in the render template\nexport const Autocomplete = React.forwardRef<HTMLInputElement, AutocompleteProps>((props, ref) => {\n const {\n label,\n \"aria-label\": ariaLabel,\n \"aria-labelledby\": ariaLabelledby,\n helperText,\n size = \"48\",\n error = false,\n errorMessage,\n placeholder,\n leftIcon,\n fullWidth = false,\n disabled = false,\n clearable = false,\n clearAriaLabel = \"Clear\",\n className,\n loading = false,\n loadingText,\n emptyText = \"No results\",\n renderOption,\n renderTag,\n } = props;\n\n const ac = useAutocomplete(props);\n\n React.useImperativeHandle(ref, () => ac.inputRef.current as HTMLInputElement);\n\n warnMissingAccessibleName(label, ariaLabel, ariaLabelledby);\n\n const bottomText = error && errorMessage ? errorMessage : helperText;\n\n return (\n <Popover.Root open={ac.isOpen && !disabled} onOpenChange={ac.handleOpenChange}>\n <div\n className={cn(\"flex flex-col\", fullWidth && \"w-full\", className)}\n data-autocomplete-root=\"\"\n data-disabled={disabled ? \"\" : undefined}\n data-error={error ? \"\" : undefined}\n >\n {label && (\n <label\n htmlFor={ac.inputId}\n className=\"typography-semibold-body-sm px-1 pt-1 pb-2 text-content-primary\"\n >\n {label}\n </label>\n )}\n\n <Popover.Anchor asChild>\n {/* biome-ignore lint/a11y/noStaticElementInteractions: Container delegates click to the inner input */}\n {/* biome-ignore lint/a11y/useKeyWithClickEvents: Keyboard interaction is handled by the inner combobox input */}\n <div\n className={cn(\n \"flex flex-wrap items-center overflow-hidden rounded-sm border bg-neutral-alphas-100 has-focus-visible:outline-none motion-safe:transition-colors\",\n error ? \"border-error-content\" : \"border-transparent\",\n !disabled && !error && \"hover:border-neutral-alphas-400\",\n ac.isOpen && !error && !disabled && \"border-neutral-alphas-400\",\n CONTAINER_HEIGHT[size],\n PADDING_CLASSES[size],\n disabled && \"opacity-50\",\n )}\n onClick={ac.handleContainerClick}\n >\n {leftIcon && (\n <div className=\"flex size-5 shrink-0 items-center justify-center text-content-secondary\">\n {leftIcon}\n </div>\n )}\n\n <div className=\"flex min-w-0 flex-1 flex-wrap items-center gap-1.5\">\n {ac.isMulti &&\n ac.selectedMultiOptions.map((opt) => (\n <AutocompleteTag\n key={opt.value}\n option={opt}\n disabled={disabled}\n onRemove={() => ac.toggleMulti(opt.value)}\n renderTag={renderTag}\n />\n ))}\n\n <input\n ref={ac.inputRef}\n id={ac.inputId}\n role=\"combobox\"\n type=\"text\"\n disabled={disabled}\n aria-expanded={ac.isOpen}\n aria-controls={ac.isOpen ? ac.listboxId : undefined}\n aria-activedescendant={ac.activeDescendantId}\n aria-autocomplete=\"list\"\n aria-describedby={bottomText ? ac.helperTextId : undefined}\n aria-invalid={error || undefined}\n aria-label={ariaLabel}\n aria-labelledby={ariaLabelledby}\n autoComplete=\"off\"\n placeholder={\n ac.isMulti && ac.selectedMultiValues.length > 0 ? undefined : placeholder\n }\n value={ac.displayInputValue}\n onChange={ac.handleInputChange}\n onKeyDown={ac.handleKeyDown}\n onFocus={ac.handleFocus}\n onBlur={ac.handleBlur}\n className={cn(\n \"min-w-[40px] flex-1 truncate bg-transparent text-content-primary no-underline placeholder:text-content-secondary placeholder:opacity-40 focus:outline-none disabled:cursor-not-allowed\",\n INPUT_SIZE_CLASSES[size],\n )}\n />\n </div>\n\n <div className=\"flex shrink-0 items-center gap-1\">\n {loading && <SpinnerIcon className=\"size-4 animate-spin text-content-secondary\" />}\n {clearable && ac.hasClearableValue && !disabled && (\n <button\n type=\"button\"\n tabIndex={-1}\n aria-label={clearAriaLabel}\n className=\"flex size-5 shrink-0 cursor-pointer items-center justify-center text-content-secondary hover:text-content-primary active:scale-95\"\n onClick={ac.handleClear}\n >\n <CloseIcon className=\"size-4\" />\n </button>\n )}\n <div className=\"flex size-5 shrink-0 items-center justify-center text-content-secondary\">\n <ChevronDownIcon\n className={cn(\"size-5 transition-transform\", ac.isOpen && \"rotate-180\")}\n />\n </div>\n </div>\n </div>\n </Popover.Anchor>\n\n <Popover.Portal>\n <Popover.Content\n sideOffset={4}\n collisionPadding={8}\n onOpenAutoFocus={(e) => e.preventDefault()}\n onCloseAutoFocus={(e) => e.preventDefault()}\n style={{ zIndex: \"var(--fanvue-ui-portal-z-index, 50)\" }}\n className={cn(\n \"w-(--radix-popover-trigger-width) min-w-(--radix-popper-anchor-width) overflow-hidden rounded-sm border border-neutral-alphas-200 bg-bg-primary text-content-primary shadow-[0_4px_16px_rgba(0,0,0,0.10)]\",\n \"data-[state=closed]:animate-out data-[state=open]:animate-in\",\n \"data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0\",\n \"data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95\",\n \"data-[side=bottom]:slide-in-from-top-2 data-[side=top]:slide-in-from-bottom-2\",\n )}\n >\n <div\n ref={ac.listRef}\n id={ac.listboxId}\n role=\"listbox\"\n aria-label={label ?? ariaLabel ?? \"Options\"}\n aria-multiselectable={ac.isMulti || undefined}\n className=\"max-h-60 overflow-y-auto p-1\"\n >\n <AutocompleteDropdownContent\n loading={loading}\n loadingText={loadingText}\n emptyText={emptyText}\n visibleOptions={ac.visibleOptions}\n listboxId={ac.listboxId}\n activeIndex={ac.activeIndex}\n isMulti={ac.isMulti}\n selectedMultiValues={ac.selectedMultiValues}\n selectedValue={ac.selectedValue}\n onSelect={ac.handleSelect}\n onMouseEnter={ac.setActiveIndex}\n renderOption={renderOption}\n />\n </div>\n </Popover.Content>\n </Popover.Portal>\n\n {bottomText && (\n <p\n id={ac.helperTextId}\n className={cn(\n \"typography-regular-body-sm px-2 pt-1 pb-0.5\",\n error ? \"text-error-content\" : \"text-content-secondary\",\n )}\n >\n {bottomText}\n </p>\n )}\n </div>\n </Popover.Root>\n );\n});\n\nAutocomplete.displayName = \"Autocomplete\";\n"],"names":["Popover"],"mappings":";;;;;;;;;;;AA6EA,MAAM,mBAAqD;AAAA,EACzD,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AACR;AAEA,MAAM,qBAAuD;AAAA,EAC3D,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AACR;AAEA,MAAM,kBAAoD;AAAA,EACxD,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AACR;AAEA,SAAS,0BAA0B,OAAgB,WAAoB,gBAAyB;AAC9F,MAAI,QAAQ,IAAI,aAAa,cAAc;AACzC,QAAI,CAAC,SAAS,CAAC,aAAa,CAAC,gBAAgB;AAC3C,cAAQ;AAAA,QACN;AAAA,MAAA;AAAA,IAEJ;AAAA,EACF;AACF;AAGO,MAAM,eAAe,MAAM,WAAgD,CAAC,OAAO,QAAQ;AAChG,QAAM;AAAA,IACJ;AAAA,IACA,cAAc;AAAA,IACd,mBAAmB;AAAA,IACnB;AAAA,IACA,OAAO;AAAA,IACP,QAAQ;AAAA,IACR;AAAA,IACA;AAAA,IACA;AAAA,IACA,YAAY;AAAA,IACZ,WAAW;AAAA,IACX,YAAY;AAAA,IACZ,iBAAiB;AAAA,IACjB;AAAA,IACA,UAAU;AAAA,IACV;AAAA,IACA,YAAY;AAAA,IACZ;AAAA,IACA;AAAA,EAAA,IACE;AAEJ,QAAM,KAAK,gBAAgB,KAAK;AAEhC,QAAM,oBAAoB,KAAK,MAAM,GAAG,SAAS,OAA2B;AAE5E,4BAA0B,OAAO,WAAW,cAAc;AAE1D,QAAM,aAAa,SAAS,eAAe,eAAe;AAE1D,SACE,oBAACA,iBAAQ,MAAR,EAAa,MAAM,GAAG,UAAU,CAAC,UAAU,cAAc,GAAG,kBAC3D,UAAA;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,WAAW,GAAG,iBAAiB,aAAa,UAAU,SAAS;AAAA,MAC/D,0BAAuB;AAAA,MACvB,iBAAe,WAAW,KAAK;AAAA,MAC/B,cAAY,QAAQ,KAAK;AAAA,MAExB,UAAA;AAAA,QAAA,SACC;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,SAAS,GAAG;AAAA,YACZ,WAAU;AAAA,YAET,UAAA;AAAA,UAAA;AAAA,QAAA;AAAA,QAIL,oBAACA,iBAAQ,QAAR,EAAe,SAAO,MAGrB,UAAA;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,WAAW;AAAA,cACT;AAAA,cACA,QAAQ,yBAAyB;AAAA,cACjC,CAAC,YAAY,CAAC,SAAS;AAAA,cACvB,GAAG,UAAU,CAAC,SAAS,CAAC,YAAY;AAAA,cACpC,iBAAiB,IAAI;AAAA,cACrB,gBAAgB,IAAI;AAAA,cACpB,YAAY;AAAA,YAAA;AAAA,YAEd,SAAS,GAAG;AAAA,YAEX,UAAA;AAAA,cAAA,YACC,oBAAC,OAAA,EAAI,WAAU,2EACZ,UAAA,UACH;AAAA,cAGF,qBAAC,OAAA,EAAI,WAAU,sDACZ,UAAA;AAAA,gBAAA,GAAG,WACF,GAAG,qBAAqB,IAAI,CAAC,QAC3B;AAAA,kBAAC;AAAA,kBAAA;AAAA,oBAEC,QAAQ;AAAA,oBACR;AAAA,oBACA,UAAU,MAAM,GAAG,YAAY,IAAI,KAAK;AAAA,oBACxC;AAAA,kBAAA;AAAA,kBAJK,IAAI;AAAA,gBAAA,CAMZ;AAAA,gBAEH;AAAA,kBAAC;AAAA,kBAAA;AAAA,oBACC,KAAK,GAAG;AAAA,oBACR,IAAI,GAAG;AAAA,oBACP,MAAK;AAAA,oBACL,MAAK;AAAA,oBACL;AAAA,oBACA,iBAAe,GAAG;AAAA,oBAClB,iBAAe,GAAG,SAAS,GAAG,YAAY;AAAA,oBAC1C,yBAAuB,GAAG;AAAA,oBAC1B,qBAAkB;AAAA,oBAClB,oBAAkB,aAAa,GAAG,eAAe;AAAA,oBACjD,gBAAc,SAAS;AAAA,oBACvB,cAAY;AAAA,oBACZ,mBAAiB;AAAA,oBACjB,cAAa;AAAA,oBACb,aACE,GAAG,WAAW,GAAG,oBAAoB,SAAS,IAAI,SAAY;AAAA,oBAEhE,OAAO,GAAG;AAAA,oBACV,UAAU,GAAG;AAAA,oBACb,WAAW,GAAG;AAAA,oBACd,SAAS,GAAG;AAAA,oBACZ,QAAQ,GAAG;AAAA,oBACX,WAAW;AAAA,sBACT;AAAA,sBACA,mBAAmB,IAAI;AAAA,oBAAA;AAAA,kBACzB;AAAA,gBAAA;AAAA,cACF,GACF;AAAA,cAEA,qBAAC,OAAA,EAAI,WAAU,oCACZ,UAAA;AAAA,gBAAA,WAAW,oBAAC,aAAA,EAAY,WAAU,6CAAA,CAA6C;AAAA,gBAC/E,aAAa,GAAG,qBAAqB,CAAC,YACrC;AAAA,kBAAC;AAAA,kBAAA;AAAA,oBACC,MAAK;AAAA,oBACL,UAAU;AAAA,oBACV,cAAY;AAAA,oBACZ,WAAU;AAAA,oBACV,SAAS,GAAG;AAAA,oBAEZ,UAAA,oBAAC,WAAA,EAAU,WAAU,SAAA,CAAS;AAAA,kBAAA;AAAA,gBAAA;AAAA,gBAGlC,oBAAC,OAAA,EAAI,WAAU,2EACb,UAAA;AAAA,kBAAC;AAAA,kBAAA;AAAA,oBACC,WAAW,GAAG,+BAA+B,GAAG,UAAU,YAAY;AAAA,kBAAA;AAAA,gBAAA,EACxE,CACF;AAAA,cAAA,EAAA,CACF;AAAA,YAAA;AAAA,UAAA;AAAA,QAAA,GAEJ;AAAA,QAEA,oBAACA,iBAAQ,QAAR,EACC,UAAA;AAAA,UAACA,iBAAQ;AAAA,UAAR;AAAA,YACC,YAAY;AAAA,YACZ,kBAAkB;AAAA,YAClB,iBAAiB,CAAC,MAAM,EAAE,eAAA;AAAA,YAC1B,kBAAkB,CAAC,MAAM,EAAE,eAAA;AAAA,YAC3B,OAAO,EAAE,QAAQ,sCAAA;AAAA,YACjB,WAAW;AAAA,cACT;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,YAAA;AAAA,YAGF,UAAA;AAAA,cAAC;AAAA,cAAA;AAAA,gBACC,KAAK,GAAG;AAAA,gBACR,IAAI,GAAG;AAAA,gBACP,MAAK;AAAA,gBACL,cAAY,SAAS,aAAa;AAAA,gBAClC,wBAAsB,GAAG,WAAW;AAAA,gBACpC,WAAU;AAAA,gBAEV,UAAA;AAAA,kBAAC;AAAA,kBAAA;AAAA,oBACC;AAAA,oBACA;AAAA,oBACA;AAAA,oBACA,gBAAgB,GAAG;AAAA,oBACnB,WAAW,GAAG;AAAA,oBACd,aAAa,GAAG;AAAA,oBAChB,SAAS,GAAG;AAAA,oBACZ,qBAAqB,GAAG;AAAA,oBACxB,eAAe,GAAG;AAAA,oBAClB,UAAU,GAAG;AAAA,oBACb,cAAc,GAAG;AAAA,oBACjB;AAAA,kBAAA;AAAA,gBAAA;AAAA,cACF;AAAA,YAAA;AAAA,UACF;AAAA,QAAA,GAEJ;AAAA,QAEC,cACC;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,IAAI,GAAG;AAAA,YACP,WAAW;AAAA,cACT;AAAA,cACA,QAAQ,uBAAuB;AAAA,YAAA;AAAA,YAGhC,UAAA;AAAA,UAAA;AAAA,QAAA;AAAA,MACH;AAAA,IAAA;AAAA,EAAA,GAGN;AAEJ,CAAC;AAED,aAAa,cAAc;"}
|
|
1
|
+
{"version":3,"file":"Autocomplete.mjs","sources":["../../../src/components/Autocomplete/Autocomplete.tsx"],"sourcesContent":["import * as Popover from \"@radix-ui/react-popover\";\nimport * as React from \"react\";\nimport { cn } from \"@/utils/cn\";\nimport { FLOATING_CONTENT_COLLISION_PADDING } from \"@/utils/floatingContentCollisionPadding\";\nimport { ChevronDownIcon } from \"../Icons/ChevronDownIcon\";\nimport { CloseIcon } from \"../Icons/CloseIcon\";\nimport { SpinnerIcon } from \"../Icons/SpinnerIcon\";\nimport { AutocompleteDropdownContent } from \"./AutocompleteDropdownContent\";\nimport { AutocompleteTag } from \"./AutocompleteTag\";\nimport { useAutocomplete } from \"./useAutocomplete\";\n\nexport type AutocompleteSize = \"48\" | \"40\" | \"32\";\n\nexport interface AutocompleteOption {\n value: string;\n label?: string;\n disabled?: boolean;\n}\n\ninterface AutocompleteBaseProps {\n label?: string;\n \"aria-label\"?: string;\n \"aria-labelledby\"?: string;\n helperText?: string;\n /** @default \"48\" */\n size?: AutocompleteSize;\n /** @default false */\n error?: boolean;\n errorMessage?: string;\n placeholder?: string;\n leftIcon?: React.ReactNode;\n /** @default false */\n fullWidth?: boolean;\n /** @default false */\n disabled?: boolean;\n /** @default false */\n clearable?: boolean;\n clearAriaLabel?: string;\n id?: string;\n className?: string;\n options: AutocompleteOption[];\n inputValue?: string;\n onInputChange?: (value: string) => void;\n filterFn?: (option: AutocompleteOption, query: string) => boolean;\n /** @default false */\n creatable?: boolean;\n creatableLabel?: (inputValue: string) => string;\n onCreate?: (inputValue: string) => void;\n /** @default false */\n loading?: boolean;\n loadingText?: string;\n emptyText?: string;\n renderOption?: (\n option: AutocompleteOption,\n state: { selected: boolean; active: boolean },\n ) => React.ReactNode;\n renderTag?: (option: AutocompleteOption, onRemove: () => void) => React.ReactNode;\n open?: boolean;\n defaultOpen?: boolean;\n onOpenChange?: (open: boolean) => void;\n}\n\ninterface AutocompleteSingleProps extends AutocompleteBaseProps {\n multiple?: false;\n value?: string | null;\n defaultValue?: string | null;\n onChange?: (value: string | null) => void;\n}\n\ninterface AutocompleteMultiProps extends AutocompleteBaseProps {\n multiple: true;\n value?: string[];\n defaultValue?: string[];\n onChange?: (values: string[]) => void;\n}\n\nexport type AutocompleteProps = AutocompleteSingleProps | AutocompleteMultiProps;\n\nconst CONTAINER_HEIGHT: Record<AutocompleteSize, string> = {\n \"48\": \"min-h-12\",\n \"40\": \"min-h-10\",\n \"32\": \"min-h-8\",\n};\n\nconst INPUT_SIZE_CLASSES: Record<AutocompleteSize, string> = {\n \"48\": \"typography-regular-body-lg\",\n \"40\": \"typography-regular-body-lg\",\n \"32\": \"typography-regular-body-md\",\n};\n\nconst PADDING_CLASSES: Record<AutocompleteSize, string> = {\n \"48\": \"px-4 py-1.5 gap-3\",\n \"40\": \"px-4 py-1 gap-3\",\n \"32\": \"px-3 py-1 gap-2\",\n};\n\nfunction warnMissingAccessibleName(label?: string, ariaLabel?: string, ariaLabelledBy?: string) {\n if (process.env.NODE_ENV !== \"production\") {\n if (!label && !ariaLabel && !ariaLabelledBy) {\n console.warn(\n \"Autocomplete: no accessible name provided. Pass a `label`, `aria-label`, or `aria-labelledby` prop.\",\n );\n }\n }\n}\n\n// biome-ignore lint/complexity/noExcessiveCognitiveComplexity: Conditional JSX branches in the render template\nexport const Autocomplete = React.forwardRef<HTMLInputElement, AutocompleteProps>((props, ref) => {\n const {\n label,\n \"aria-label\": ariaLabel,\n \"aria-labelledby\": ariaLabelledby,\n helperText,\n size = \"48\",\n error = false,\n errorMessage,\n placeholder,\n leftIcon,\n fullWidth = false,\n disabled = false,\n clearable = false,\n clearAriaLabel = \"Clear\",\n className,\n loading = false,\n loadingText,\n emptyText = \"No results\",\n renderOption,\n renderTag,\n } = props;\n\n const ac = useAutocomplete(props);\n\n React.useImperativeHandle(ref, () => ac.inputRef.current as HTMLInputElement);\n\n warnMissingAccessibleName(label, ariaLabel, ariaLabelledby);\n\n const bottomText = error && errorMessage ? errorMessage : helperText;\n\n return (\n <Popover.Root open={ac.isOpen && !disabled} onOpenChange={ac.handleOpenChange}>\n <div\n className={cn(\"flex flex-col\", fullWidth && \"w-full\", className)}\n data-autocomplete-root=\"\"\n data-disabled={disabled ? \"\" : undefined}\n data-error={error ? \"\" : undefined}\n >\n {label && (\n <label\n htmlFor={ac.inputId}\n className=\"typography-semibold-body-sm px-1 pt-1 pb-2 text-content-primary\"\n >\n {label}\n </label>\n )}\n\n <Popover.Anchor asChild>\n {/* biome-ignore lint/a11y/noStaticElementInteractions: Container delegates click to the inner input */}\n {/* biome-ignore lint/a11y/useKeyWithClickEvents: Keyboard interaction is handled by the inner combobox input */}\n <div\n className={cn(\n \"flex flex-wrap items-center overflow-hidden rounded-sm border bg-neutral-alphas-100 has-focus-visible:outline-none motion-safe:transition-colors\",\n error ? \"border-error-content\" : \"border-transparent\",\n !disabled && !error && \"hover:border-neutral-alphas-400\",\n ac.isOpen && !error && !disabled && \"border-neutral-alphas-400\",\n CONTAINER_HEIGHT[size],\n PADDING_CLASSES[size],\n disabled && \"opacity-50\",\n )}\n onClick={ac.handleContainerClick}\n >\n {leftIcon && (\n <div className=\"flex size-5 shrink-0 items-center justify-center text-content-secondary\">\n {leftIcon}\n </div>\n )}\n\n <div className=\"flex min-w-0 flex-1 flex-wrap items-center gap-1.5\">\n {ac.isMulti &&\n ac.selectedMultiOptions.map((opt) => (\n <AutocompleteTag\n key={opt.value}\n option={opt}\n disabled={disabled}\n onRemove={() => ac.toggleMulti(opt.value)}\n renderTag={renderTag}\n />\n ))}\n\n <input\n ref={ac.inputRef}\n id={ac.inputId}\n role=\"combobox\"\n type=\"text\"\n disabled={disabled}\n aria-expanded={ac.isOpen}\n aria-controls={ac.isOpen ? ac.listboxId : undefined}\n aria-activedescendant={ac.activeDescendantId}\n aria-autocomplete=\"list\"\n aria-describedby={bottomText ? ac.helperTextId : undefined}\n aria-invalid={error || undefined}\n aria-label={ariaLabel}\n aria-labelledby={ariaLabelledby}\n autoComplete=\"off\"\n placeholder={\n ac.isMulti && ac.selectedMultiValues.length > 0 ? undefined : placeholder\n }\n value={ac.displayInputValue}\n onChange={ac.handleInputChange}\n onKeyDown={ac.handleKeyDown}\n onFocus={ac.handleFocus}\n onBlur={ac.handleBlur}\n className={cn(\n \"min-w-[40px] flex-1 truncate bg-transparent text-content-primary no-underline placeholder:text-content-secondary placeholder:opacity-40 focus:outline-none disabled:cursor-not-allowed\",\n INPUT_SIZE_CLASSES[size],\n )}\n />\n </div>\n\n <div className=\"flex shrink-0 items-center gap-1\">\n {loading && <SpinnerIcon className=\"size-4 animate-spin text-content-secondary\" />}\n {clearable && ac.hasClearableValue && !disabled && (\n <button\n type=\"button\"\n tabIndex={-1}\n aria-label={clearAriaLabel}\n className=\"flex size-5 shrink-0 cursor-pointer items-center justify-center text-content-secondary hover:text-content-primary active:scale-95\"\n onClick={ac.handleClear}\n >\n <CloseIcon className=\"size-4\" />\n </button>\n )}\n <div className=\"flex size-5 shrink-0 items-center justify-center text-content-secondary\">\n <ChevronDownIcon\n className={cn(\"size-5 transition-transform\", ac.isOpen && \"rotate-180\")}\n />\n </div>\n </div>\n </div>\n </Popover.Anchor>\n\n <Popover.Portal>\n <Popover.Content\n sideOffset={4}\n collisionPadding={FLOATING_CONTENT_COLLISION_PADDING}\n onOpenAutoFocus={(e) => e.preventDefault()}\n onCloseAutoFocus={(e) => e.preventDefault()}\n style={{ zIndex: \"var(--fanvue-ui-portal-z-index, 50)\" }}\n className={cn(\n \"w-max min-w-(--radix-popper-anchor-width) max-w-(--radix-popover-content-available-width) overflow-hidden rounded-sm border border-neutral-alphas-200 bg-bg-primary text-content-primary shadow-[0_4px_16px_rgba(0,0,0,0.10)]\",\n \"data-[state=closed]:animate-out data-[state=open]:animate-in\",\n \"data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0\",\n \"data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95\",\n \"data-[side=bottom]:slide-in-from-top-2 data-[side=top]:slide-in-from-bottom-2\",\n )}\n >\n <div\n ref={ac.listRef}\n id={ac.listboxId}\n role=\"listbox\"\n aria-label={label ?? ariaLabel ?? \"Options\"}\n aria-multiselectable={ac.isMulti || undefined}\n className=\"max-h-60 overflow-y-auto p-1\"\n >\n <AutocompleteDropdownContent\n loading={loading}\n loadingText={loadingText}\n emptyText={emptyText}\n visibleOptions={ac.visibleOptions}\n listboxId={ac.listboxId}\n activeIndex={ac.activeIndex}\n isMulti={ac.isMulti}\n selectedMultiValues={ac.selectedMultiValues}\n selectedValue={ac.selectedValue}\n onSelect={ac.handleSelect}\n onMouseEnter={ac.setActiveIndex}\n renderOption={renderOption}\n />\n </div>\n </Popover.Content>\n </Popover.Portal>\n\n {bottomText && (\n <p\n id={ac.helperTextId}\n className={cn(\n \"typography-regular-body-sm px-2 pt-1 pb-0.5\",\n error ? \"text-error-content\" : \"text-content-secondary\",\n )}\n >\n {bottomText}\n </p>\n )}\n </div>\n </Popover.Root>\n );\n});\n\nAutocomplete.displayName = \"Autocomplete\";\n"],"names":["Popover"],"mappings":"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"}
|
|
@@ -3,30 +3,40 @@ import { jsx, jsxs } from "react/jsx-runtime";
|
|
|
3
3
|
import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu";
|
|
4
4
|
import * as React from "react";
|
|
5
5
|
import { cn } from "../../utils/cn.mjs";
|
|
6
|
+
import { FLOATING_CONTENT_COLLISION_PADDING } from "../../utils/floatingContentCollisionPadding.mjs";
|
|
6
7
|
const DropdownMenu = DropdownMenuPrimitive.Root;
|
|
7
8
|
const DropdownMenuTrigger = DropdownMenuPrimitive.Trigger;
|
|
8
9
|
DropdownMenuTrigger.displayName = "DropdownMenuTrigger";
|
|
9
|
-
const DropdownMenuContent = React.forwardRef(
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
sideOffset,
|
|
14
|
-
|
|
15
|
-
"min-w-[180px] overflow-y-auto rounded-lg border border-neutral-alphas-200 bg-bg-primary p-1 shadow-lg",
|
|
16
|
-
"data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95",
|
|
17
|
-
"data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95",
|
|
18
|
-
"data-[side=top]:slide-in-from-bottom-2 data-[side=bottom]:slide-in-from-top-2",
|
|
19
|
-
"data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2",
|
|
20
|
-
className
|
|
21
|
-
),
|
|
22
|
-
style: {
|
|
23
|
-
zIndex: "var(--fanvue-ui-portal-z-index, 50)",
|
|
24
|
-
maxHeight: "var(--radix-dropdown-menu-content-available-height)",
|
|
25
|
-
...style
|
|
26
|
-
},
|
|
10
|
+
const DropdownMenuContent = React.forwardRef(
|
|
11
|
+
({
|
|
12
|
+
className,
|
|
13
|
+
style,
|
|
14
|
+
sideOffset = 4,
|
|
15
|
+
collisionPadding = FLOATING_CONTENT_COLLISION_PADDING,
|
|
27
16
|
...props
|
|
28
|
-
}
|
|
29
|
-
|
|
17
|
+
}, ref) => /* @__PURE__ */ jsx(DropdownMenuPrimitive.Portal, { children: /* @__PURE__ */ jsx(
|
|
18
|
+
DropdownMenuPrimitive.Content,
|
|
19
|
+
{
|
|
20
|
+
ref,
|
|
21
|
+
sideOffset,
|
|
22
|
+
collisionPadding,
|
|
23
|
+
className: cn(
|
|
24
|
+
"w-max min-w-(--radix-dropdown-menu-trigger-width) max-w-(--radix-dropdown-menu-content-available-width) overflow-y-auto rounded-sm border border-neutral-alphas-200 bg-bg-primary p-1 shadow-lg",
|
|
25
|
+
"data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95",
|
|
26
|
+
"data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95",
|
|
27
|
+
"data-[side=top]:slide-in-from-bottom-2 data-[side=bottom]:slide-in-from-top-2",
|
|
28
|
+
"data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2",
|
|
29
|
+
className
|
|
30
|
+
),
|
|
31
|
+
style: {
|
|
32
|
+
zIndex: "var(--fanvue-ui-portal-z-index, 50)",
|
|
33
|
+
maxHeight: "var(--radix-dropdown-menu-content-available-height)",
|
|
34
|
+
...style
|
|
35
|
+
},
|
|
36
|
+
...props
|
|
37
|
+
}
|
|
38
|
+
) })
|
|
39
|
+
);
|
|
30
40
|
DropdownMenuContent.displayName = "DropdownMenuContent";
|
|
31
41
|
const DropdownMenuGroup = DropdownMenuPrimitive.Group;
|
|
32
42
|
DropdownMenuGroup.displayName = "DropdownMenuGroup";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DropdownMenu.mjs","sources":["../../../src/components/DropdownMenu/DropdownMenu.tsx"],"sourcesContent":["import * as DropdownMenuPrimitive from \"@radix-ui/react-dropdown-menu\";\nimport * as React from \"react\";\nimport { cn } from \"../../utils/cn\";\n\n/** Props for the {@link DropdownMenu} root component. */\nexport interface DropdownMenuProps\n extends React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Root> {}\n\n/** Root component that manages open/close state for a dropdown menu. */\nexport const DropdownMenu = DropdownMenuPrimitive.Root;\n\n/** Props for the {@link DropdownMenuTrigger} component. */\nexport type DropdownMenuTriggerProps = React.ComponentPropsWithoutRef<\n typeof DropdownMenuPrimitive.Trigger\n>;\n\n/** The element that toggles the dropdown menu when clicked. */\nexport const DropdownMenuTrigger = DropdownMenuPrimitive.Trigger;\nDropdownMenuTrigger.displayName = \"DropdownMenuTrigger\";\n\n/** Props for the {@link DropdownMenuContent} component. */\nexport interface DropdownMenuContentProps\n extends React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Content> {}\n\n/**\n * The positioned content panel rendered inside a portal.\n *\n * Override the portal z-index per-instance via `style={{ zIndex: 1500 }}` or\n * globally with the `--fanvue-ui-portal-z-index` CSS custom property.\n *\n * @example\n * ```tsx\n * <DropdownMenu>\n * <DropdownMenuTrigger asChild>\n * <Button>Open</Button>\n * </DropdownMenuTrigger>\n * <DropdownMenuContent>\n * <DropdownMenuItem>Option 1</DropdownMenuItem>\n * <DropdownMenuItem>Option 2</DropdownMenuItem>\n * </DropdownMenuContent>\n * </DropdownMenu>\n * ```\n */\nexport const DropdownMenuContent = React.forwardRef<\n React.ComponentRef<typeof DropdownMenuPrimitive.Content>,\n DropdownMenuContentProps\n>(({
|
|
1
|
+
{"version":3,"file":"DropdownMenu.mjs","sources":["../../../src/components/DropdownMenu/DropdownMenu.tsx"],"sourcesContent":["import * as DropdownMenuPrimitive from \"@radix-ui/react-dropdown-menu\";\nimport * as React from \"react\";\nimport { cn } from \"../../utils/cn\";\nimport { FLOATING_CONTENT_COLLISION_PADDING } from \"../../utils/floatingContentCollisionPadding\";\n\n/** Props for the {@link DropdownMenu} root component. */\nexport interface DropdownMenuProps\n extends React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Root> {}\n\n/** Root component that manages open/close state for a dropdown menu. */\nexport const DropdownMenu = DropdownMenuPrimitive.Root;\n\n/** Props for the {@link DropdownMenuTrigger} component. */\nexport type DropdownMenuTriggerProps = React.ComponentPropsWithoutRef<\n typeof DropdownMenuPrimitive.Trigger\n>;\n\n/** The element that toggles the dropdown menu when clicked. */\nexport const DropdownMenuTrigger = DropdownMenuPrimitive.Trigger;\nDropdownMenuTrigger.displayName = \"DropdownMenuTrigger\";\n\n/** Props for the {@link DropdownMenuContent} component. */\nexport interface DropdownMenuContentProps\n extends React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Content> {}\n\n/**\n * The positioned content panel rendered inside a portal.\n *\n * Override the portal z-index per-instance via `style={{ zIndex: 1500 }}` or\n * globally with the `--fanvue-ui-portal-z-index` CSS custom property.\n *\n * @example\n * ```tsx\n * <DropdownMenu>\n * <DropdownMenuTrigger asChild>\n * <Button>Open</Button>\n * </DropdownMenuTrigger>\n * <DropdownMenuContent>\n * <DropdownMenuItem>Option 1</DropdownMenuItem>\n * <DropdownMenuItem>Option 2</DropdownMenuItem>\n * </DropdownMenuContent>\n * </DropdownMenu>\n * ```\n */\nexport const DropdownMenuContent = React.forwardRef<\n React.ComponentRef<typeof DropdownMenuPrimitive.Content>,\n DropdownMenuContentProps\n>(\n (\n {\n className,\n style,\n sideOffset = 4,\n collisionPadding = FLOATING_CONTENT_COLLISION_PADDING,\n ...props\n },\n ref,\n ) => (\n <DropdownMenuPrimitive.Portal>\n <DropdownMenuPrimitive.Content\n ref={ref}\n sideOffset={sideOffset}\n collisionPadding={collisionPadding}\n className={cn(\n \"w-max min-w-(--radix-dropdown-menu-trigger-width) max-w-(--radix-dropdown-menu-content-available-width) overflow-y-auto rounded-sm border border-neutral-alphas-200 bg-bg-primary p-1 shadow-lg\",\n \"data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95\",\n \"data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95\",\n \"data-[side=top]:slide-in-from-bottom-2 data-[side=bottom]:slide-in-from-top-2\",\n \"data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2\",\n className,\n )}\n style={{\n zIndex: \"var(--fanvue-ui-portal-z-index, 50)\",\n maxHeight: \"var(--radix-dropdown-menu-content-available-height)\",\n ...style,\n }}\n {...props}\n />\n </DropdownMenuPrimitive.Portal>\n ),\n);\nDropdownMenuContent.displayName = \"DropdownMenuContent\";\n\n/** Props for the {@link DropdownMenuGroup} component. */\nexport type DropdownMenuGroupProps = React.ComponentPropsWithoutRef<\n typeof DropdownMenuPrimitive.Group\n>;\n\n/** Groups related menu items. Accepts an optional `DropdownMenuLabel`. */\nexport const DropdownMenuGroup = DropdownMenuPrimitive.Group;\nDropdownMenuGroup.displayName = \"DropdownMenuGroup\";\n\n/** Props for the {@link DropdownMenuLabel} component. */\nexport interface DropdownMenuLabelProps\n extends React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Label> {}\n\n/** A label for a group of items. Not focusable or selectable. */\nexport const DropdownMenuLabel = React.forwardRef<\n React.ComponentRef<typeof DropdownMenuPrimitive.Label>,\n DropdownMenuLabelProps\n>(({ className, ...props }, ref) => (\n <DropdownMenuPrimitive.Label\n ref={ref}\n className={cn(\"typography-medium-body-xs px-2 py-1.5 text-content-secondary\", className)}\n {...props}\n />\n));\nDropdownMenuLabel.displayName = \"DropdownMenuLabel\";\n\n/** Available sizes for a dropdown menu item. */\nexport type DropdownMenuItemSize = \"sm\" | \"md\";\n\nexport interface DropdownMenuItemProps\n extends React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Item> {\n /** Height of the menu item row. @default \"sm\" */\n size?: DropdownMenuItemSize;\n /** Whether the item uses destructive (error) styling. */\n destructive?: boolean;\n /** Icon rendered before the label. */\n leadingIcon?: React.ReactNode;\n /** Icon rendered after the label. */\n trailingIcon?: React.ReactNode;\n /** Whether the item is in a selected state. */\n selected?: boolean;\n}\n\n/**\n * An individual item within a {@link DropdownMenuContent}.\n *\n * @example\n * ```tsx\n * <DropdownMenuItem>Edit profile</DropdownMenuItem>\n * <DropdownMenuItem destructive>Delete</DropdownMenuItem>\n * <DropdownMenuItem leadingIcon={<EditIcon />}>Edit</DropdownMenuItem>\n *\n * // As a link\n * <DropdownMenuItem asChild>\n * <a href=\"/settings\">Settings</a>\n * </DropdownMenuItem>\n * ```\n */\nexport const DropdownMenuItem = React.forwardRef<\n React.ComponentRef<typeof DropdownMenuPrimitive.Item>,\n DropdownMenuItemProps\n>(\n (\n {\n size = \"sm\",\n destructive,\n leadingIcon,\n trailingIcon,\n selected,\n className,\n children,\n asChild,\n ...props\n },\n ref,\n ) => {\n const itemClassName = cn(\n \"flex w-full cursor-pointer items-center gap-1 rounded px-2 outline-none\",\n \"data-[disabled]:cursor-not-allowed data-[disabled]:opacity-50\",\n \"data-[highlighted]:bg-neutral-alphas-100\",\n size === \"sm\" ? \"min-h-[34px] py-1\" : \"min-h-[40px] py-1.5\",\n size === \"sm\" ? \"typography-medium-body-sm\" : \"typography-medium-body-md\",\n destructive && \"text-error-content\",\n selected && \"bg-success-surface\",\n className,\n );\n\n if (asChild) {\n return (\n <DropdownMenuPrimitive.Item ref={ref} asChild className={itemClassName} {...props}>\n {children}\n </DropdownMenuPrimitive.Item>\n );\n }\n\n return (\n <DropdownMenuPrimitive.Item ref={ref} className={itemClassName} {...props}>\n {leadingIcon}\n <span className=\"flex-1\">{children}</span>\n {trailingIcon}\n </DropdownMenuPrimitive.Item>\n );\n },\n);\nDropdownMenuItem.displayName = \"DropdownMenuItem\";\n\n/** Props for the {@link DropdownMenuSeparator} component. */\nexport interface DropdownMenuSeparatorProps\n extends React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Separator> {}\n\n/** Visual separator between groups of items. */\nexport const DropdownMenuSeparator = React.forwardRef<\n React.ComponentRef<typeof DropdownMenuPrimitive.Separator>,\n DropdownMenuSeparatorProps\n>(({ className, ...props }, ref) => (\n <DropdownMenuPrimitive.Separator\n ref={ref}\n className={cn(\"my-1 h-px bg-neutral-alphas-200\", className)}\n {...props}\n />\n));\nDropdownMenuSeparator.displayName = \"DropdownMenuSeparator\";\n"],"names":[],"mappings":";;;;;;AAUO,MAAM,eAAe,sBAAsB;AAQ3C,MAAM,sBAAsB,sBAAsB;AACzD,oBAAoB,cAAc;AAyB3B,MAAM,sBAAsB,MAAM;AAAA,EAIvC,CACE;AAAA,IACE;AAAA,IACA;AAAA,IACA,aAAa;AAAA,IACb,mBAAmB;AAAA,IACnB,GAAG;AAAA,EAAA,GAEL,QAEA,oBAAC,sBAAsB,QAAtB,EACC,UAAA;AAAA,IAAC,sBAAsB;AAAA,IAAtB;AAAA,MACC;AAAA,MACA;AAAA,MACA;AAAA,MACA,WAAW;AAAA,QACT;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MAAA;AAAA,MAEF,OAAO;AAAA,QACL,QAAQ;AAAA,QACR,WAAW;AAAA,QACX,GAAG;AAAA,MAAA;AAAA,MAEJ,GAAG;AAAA,IAAA;AAAA,EAAA,EACN,CACF;AAEJ;AACA,oBAAoB,cAAc;AAQ3B,MAAM,oBAAoB,sBAAsB;AACvD,kBAAkB,cAAc;AAOzB,MAAM,oBAAoB,MAAM,WAGrC,CAAC,EAAE,WAAW,GAAG,MAAA,GAAS,QAC1B;AAAA,EAAC,sBAAsB;AAAA,EAAtB;AAAA,IACC;AAAA,IACA,WAAW,GAAG,gEAAgE,SAAS;AAAA,IACtF,GAAG;AAAA,EAAA;AACN,CACD;AACD,kBAAkB,cAAc;AAkCzB,MAAM,mBAAmB,MAAM;AAAA,EAIpC,CACE;AAAA,IACE,OAAO;AAAA,IACP;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,GAAG;AAAA,EAAA,GAEL,QACG;AACH,UAAM,gBAAgB;AAAA,MACpB;AAAA,MACA;AAAA,MACA;AAAA,MACA,SAAS,OAAO,sBAAsB;AAAA,MACtC,SAAS,OAAO,8BAA8B;AAAA,MAC9C,eAAe;AAAA,MACf,YAAY;AAAA,MACZ;AAAA,IAAA;AAGF,QAAI,SAAS;AACX,aACE,oBAAC,sBAAsB,MAAtB,EAA2B,KAAU,SAAO,MAAC,WAAW,eAAgB,GAAG,OACzE,SAAA,CACH;AAAA,IAEJ;AAEA,WACE,qBAAC,sBAAsB,MAAtB,EAA2B,KAAU,WAAW,eAAgB,GAAG,OACjE,UAAA;AAAA,MAAA;AAAA,MACD,oBAAC,QAAA,EAAK,WAAU,UAAU,SAAA,CAAS;AAAA,MAClC;AAAA,IAAA,GACH;AAAA,EAEJ;AACF;AACA,iBAAiB,cAAc;AAOxB,MAAM,wBAAwB,MAAM,WAGzC,CAAC,EAAE,WAAW,GAAG,MAAA,GAAS,QAC1B;AAAA,EAAC,sBAAsB;AAAA,EAAtB;AAAA,IACC;AAAA,IACA,WAAW,GAAG,mCAAmC,SAAS;AAAA,IACzD,GAAG;AAAA,EAAA;AACN,CACD;AACD,sBAAsB,cAAc;"}
|
|
@@ -3,6 +3,7 @@ import { jsx, jsxs } from "react/jsx-runtime";
|
|
|
3
3
|
import * as PopoverPrimitive from "@radix-ui/react-popover";
|
|
4
4
|
import * as React from "react";
|
|
5
5
|
import { cn } from "../../utils/cn.mjs";
|
|
6
|
+
import { FLOATING_CONTENT_COLLISION_PADDING } from "../../utils/floatingContentCollisionPadding.mjs";
|
|
6
7
|
import { Button } from "../Button/Button.mjs";
|
|
7
8
|
const InfoBox = PopoverPrimitive.Root;
|
|
8
9
|
const InfoBoxTrigger = PopoverPrimitive.Trigger;
|
|
@@ -27,6 +28,7 @@ const InfoBoxContent = React.forwardRef(
|
|
|
27
28
|
children,
|
|
28
29
|
style,
|
|
29
30
|
onOpenAutoFocus,
|
|
31
|
+
collisionPadding = FLOATING_CONTENT_COLLISION_PADDING,
|
|
30
32
|
...props
|
|
31
33
|
}, ref) => {
|
|
32
34
|
const hasHeader = icon !== void 0 || heading !== void 0 || pill !== void 0;
|
|
@@ -37,7 +39,7 @@ const InfoBoxContent = React.forwardRef(
|
|
|
37
39
|
{
|
|
38
40
|
ref,
|
|
39
41
|
sideOffset,
|
|
40
|
-
collisionPadding
|
|
42
|
+
collisionPadding,
|
|
41
43
|
style: { zIndex: "var(--fanvue-ui-portal-z-index, 50)", ...style },
|
|
42
44
|
className: cn(
|
|
43
45
|
"typography-regular-body-md max-w-[280px] overflow-hidden rounded-md border border-white/20 bg-surface-primary-inverted p-4 text-content-primary-inverted shadow-[0px_2px_4px_0px_rgba(17,24,39,0.08)]",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"InfoBox.mjs","sources":["../../../src/components/InfoBox/InfoBox.tsx"],"sourcesContent":["import * as PopoverPrimitive from \"@radix-ui/react-popover\";\nimport * as React from \"react\";\nimport { cn } from \"../../utils/cn\";\nimport { Button } from \"../Button/Button\";\n\n/** Props for the {@link InfoBox} root component. */\nexport interface InfoBoxProps extends React.ComponentPropsWithoutRef<typeof PopoverPrimitive.Root> {\n open?: boolean;\n onOpenChange?: (open: boolean) => void;\n defaultOpen?: boolean;\n}\n\n/** Root component that manages open/close state for an info box. */\nexport const InfoBox = PopoverPrimitive.Root;\n\n/** Props for the {@link InfoBoxTrigger} component. */\nexport type InfoBoxTriggerProps = React.ComponentPropsWithoutRef<typeof PopoverPrimitive.Trigger>;\n\n/** The element that triggers the info box on click. */\nexport const InfoBoxTrigger = PopoverPrimitive.Trigger;\n\n/** Action button with a label and click handler. */\ninterface InfoBoxButtonAction {\n label: string;\n onClick?: () => void;\n}\n\n/** Custom element rendered in place of the default action button. */\ninterface InfoBoxElementAction {\n element: React.ReactNode;\n}\n\n/** Action configuration for {@link InfoBoxContent}. */\nexport type InfoBoxAction = InfoBoxButtonAction | InfoBoxElementAction;\n\nexport interface InfoBoxContentProps\n extends React.ComponentPropsWithoutRef<typeof PopoverPrimitive.Content> {\n /** Whether to show the directional arrow pointer. @default true */\n showArrow?: boolean;\n /** Heading text rendered at the top of the info box. */\n heading?: React.ReactNode;\n /** Icon element displayed to the left of the heading. */\n icon?: React.ReactNode;\n /** Pill or badge element displayed to the right of the heading. */\n pill?: React.ReactNode;\n /** Primary action button (brand green). */\n primaryAction?: InfoBoxAction;\n /** Secondary action button (ghost). */\n secondaryAction?: InfoBoxAction;\n}\n\nconst ACTION_CLASSES: Record<\"brand\" | \"tertiary\", string> = {\n brand: \"hover:bg-brand-primary-default/80 hover:text-content-on-brand\",\n tertiary:\n \"text-content-primary-inverted hover:text-content-primary-inverted hover:bg-content-primary-inverted/10\",\n};\n\nconst ActionButton = ({\n action,\n variant,\n}: {\n action: InfoBoxAction;\n variant: \"brand\" | \"tertiary\";\n}) =>\n \"element\" in action ? (\n action.element\n ) : (\n <Button variant={variant} onClick={action.onClick} className={ACTION_CLASSES[variant]}>\n {action.label}\n </Button>\n );\n\nexport const InfoBoxContent = React.forwardRef<\n React.ComponentRef<typeof PopoverPrimitive.Content>,\n InfoBoxContentProps\n>(\n (\n {\n className,\n showArrow = true,\n sideOffset = 8,\n heading,\n icon,\n pill,\n primaryAction,\n secondaryAction,\n children,\n style,\n onOpenAutoFocus,\n ...props\n },\n ref,\n ) => {\n const hasHeader = icon !== undefined || heading !== undefined || pill !== undefined;\n const hasActions = primaryAction !== undefined || secondaryAction !== undefined;\n const headingId = React.useId();\n\n return (\n <PopoverPrimitive.Portal>\n <PopoverPrimitive.Content\n ref={ref}\n sideOffset={sideOffset}\n collisionPadding={
|
|
1
|
+
{"version":3,"file":"InfoBox.mjs","sources":["../../../src/components/InfoBox/InfoBox.tsx"],"sourcesContent":["import * as PopoverPrimitive from \"@radix-ui/react-popover\";\nimport * as React from \"react\";\nimport { cn } from \"../../utils/cn\";\nimport { FLOATING_CONTENT_COLLISION_PADDING } from \"../../utils/floatingContentCollisionPadding\";\nimport { Button } from \"../Button/Button\";\n\n/** Props for the {@link InfoBox} root component. */\nexport interface InfoBoxProps extends React.ComponentPropsWithoutRef<typeof PopoverPrimitive.Root> {\n open?: boolean;\n onOpenChange?: (open: boolean) => void;\n defaultOpen?: boolean;\n}\n\n/** Root component that manages open/close state for an info box. */\nexport const InfoBox = PopoverPrimitive.Root;\n\n/** Props for the {@link InfoBoxTrigger} component. */\nexport type InfoBoxTriggerProps = React.ComponentPropsWithoutRef<typeof PopoverPrimitive.Trigger>;\n\n/** The element that triggers the info box on click. */\nexport const InfoBoxTrigger = PopoverPrimitive.Trigger;\n\n/** Action button with a label and click handler. */\ninterface InfoBoxButtonAction {\n label: string;\n onClick?: () => void;\n}\n\n/** Custom element rendered in place of the default action button. */\ninterface InfoBoxElementAction {\n element: React.ReactNode;\n}\n\n/** Action configuration for {@link InfoBoxContent}. */\nexport type InfoBoxAction = InfoBoxButtonAction | InfoBoxElementAction;\n\nexport interface InfoBoxContentProps\n extends React.ComponentPropsWithoutRef<typeof PopoverPrimitive.Content> {\n /** Whether to show the directional arrow pointer. @default true */\n showArrow?: boolean;\n /** Heading text rendered at the top of the info box. */\n heading?: React.ReactNode;\n /** Icon element displayed to the left of the heading. */\n icon?: React.ReactNode;\n /** Pill or badge element displayed to the right of the heading. */\n pill?: React.ReactNode;\n /** Primary action button (brand green). */\n primaryAction?: InfoBoxAction;\n /** Secondary action button (ghost). */\n secondaryAction?: InfoBoxAction;\n}\n\nconst ACTION_CLASSES: Record<\"brand\" | \"tertiary\", string> = {\n brand: \"hover:bg-brand-primary-default/80 hover:text-content-on-brand\",\n tertiary:\n \"text-content-primary-inverted hover:text-content-primary-inverted hover:bg-content-primary-inverted/10\",\n};\n\nconst ActionButton = ({\n action,\n variant,\n}: {\n action: InfoBoxAction;\n variant: \"brand\" | \"tertiary\";\n}) =>\n \"element\" in action ? (\n action.element\n ) : (\n <Button variant={variant} onClick={action.onClick} className={ACTION_CLASSES[variant]}>\n {action.label}\n </Button>\n );\n\nexport const InfoBoxContent = React.forwardRef<\n React.ComponentRef<typeof PopoverPrimitive.Content>,\n InfoBoxContentProps\n>(\n (\n {\n className,\n showArrow = true,\n sideOffset = 8,\n heading,\n icon,\n pill,\n primaryAction,\n secondaryAction,\n children,\n style,\n onOpenAutoFocus,\n collisionPadding = FLOATING_CONTENT_COLLISION_PADDING,\n ...props\n },\n ref,\n ) => {\n const hasHeader = icon !== undefined || heading !== undefined || pill !== undefined;\n const hasActions = primaryAction !== undefined || secondaryAction !== undefined;\n const headingId = React.useId();\n\n return (\n <PopoverPrimitive.Portal>\n <PopoverPrimitive.Content\n ref={ref}\n sideOffset={sideOffset}\n collisionPadding={collisionPadding}\n style={{ zIndex: \"var(--fanvue-ui-portal-z-index, 50)\", ...style }}\n className={cn(\n \"typography-regular-body-md max-w-[280px] overflow-hidden rounded-md border border-white/20 bg-surface-primary-inverted p-4 text-content-primary-inverted shadow-[0px_2px_4px_0px_rgba(17,24,39,0.08)]\",\n className,\n )}\n align=\"center\"\n aria-labelledby={heading ? headingId : undefined}\n arrowPadding={12}\n onOpenAutoFocus={(e) => {\n // Prevent auto-focus stealing when opening — content is supplementary, not a dialog.\n e.preventDefault();\n onOpenAutoFocus?.(e);\n }}\n {...props}\n >\n <div className=\"flex flex-col gap-3\">\n {hasHeader && (\n <div className=\"flex items-center gap-3\">\n {icon && <div className=\"size-5 shrink-0\">{icon}</div>}\n {heading && (\n <p\n id={headingId}\n className=\"typography-semibold-body-lg min-w-0 flex-1 text-content-primary-inverted\"\n >\n {heading}\n </p>\n )}\n {pill && <div className=\"shrink-0\">{pill}</div>}\n </div>\n )}\n {children && (\n <div className=\"typography-regular-body-md text-content-primary-inverted\">\n {children}\n </div>\n )}\n {hasActions && (\n <div className=\"flex items-center gap-1\">\n {primaryAction && <ActionButton action={primaryAction} variant=\"brand\" />}\n {secondaryAction && <ActionButton action={secondaryAction} variant=\"tertiary\" />}\n </div>\n )}\n </div>\n {showArrow && (\n <PopoverPrimitive.Arrow\n className={\n \"-translate-y-px! fill-surface-primary-inverted stroke-2 stroke-surface-primary-inverted\"\n }\n width={12}\n height={6}\n />\n )}\n </PopoverPrimitive.Content>\n </PopoverPrimitive.Portal>\n );\n },\n);\nInfoBoxContent.displayName = \"InfoBoxContent\";\n"],"names":[],"mappings":";;;;;;;AAcO,MAAM,UAAU,iBAAiB;AAMjC,MAAM,iBAAiB,iBAAiB;AAgC/C,MAAM,iBAAuD;AAAA,EAC3D,OAAO;AAAA,EACP,UACE;AACJ;AAEA,MAAM,eAAe,CAAC;AAAA,EACpB;AAAA,EACA;AACF,MAIE,aAAa,SACX,OAAO,8BAEN,QAAA,EAAO,SAAkB,SAAS,OAAO,SAAS,WAAW,eAAe,OAAO,GACjF,iBAAO,OACV;AAGG,MAAM,iBAAiB,MAAM;AAAA,EAIlC,CACE;AAAA,IACE;AAAA,IACA,YAAY;AAAA,IACZ,aAAa;AAAA,IACb;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,mBAAmB;AAAA,IACnB,GAAG;AAAA,EAAA,GAEL,QACG;AACH,UAAM,YAAY,SAAS,UAAa,YAAY,UAAa,SAAS;AAC1E,UAAM,aAAa,kBAAkB,UAAa,oBAAoB;AACtE,UAAM,YAAY,MAAM,MAAA;AAExB,WACE,oBAAC,iBAAiB,QAAjB,EACC,UAAA;AAAA,MAAC,iBAAiB;AAAA,MAAjB;AAAA,QACC;AAAA,QACA;AAAA,QACA;AAAA,QACA,OAAO,EAAE,QAAQ,uCAAuC,GAAG,MAAA;AAAA,QAC3D,WAAW;AAAA,UACT;AAAA,UACA;AAAA,QAAA;AAAA,QAEF,OAAM;AAAA,QACN,mBAAiB,UAAU,YAAY;AAAA,QACvC,cAAc;AAAA,QACd,iBAAiB,CAAC,MAAM;AAEtB,YAAE,eAAA;AACF,4BAAkB,CAAC;AAAA,QACrB;AAAA,QACC,GAAG;AAAA,QAEJ,UAAA;AAAA,UAAA,qBAAC,OAAA,EAAI,WAAU,uBACZ,UAAA;AAAA,YAAA,aACC,qBAAC,OAAA,EAAI,WAAU,2BACZ,UAAA;AAAA,cAAA,QAAQ,oBAAC,OAAA,EAAI,WAAU,mBAAmB,UAAA,MAAK;AAAA,cAC/C,WACC;AAAA,gBAAC;AAAA,gBAAA;AAAA,kBACC,IAAI;AAAA,kBACJ,WAAU;AAAA,kBAET,UAAA;AAAA,gBAAA;AAAA,cAAA;AAAA,cAGJ,QAAQ,oBAAC,OAAA,EAAI,WAAU,YAAY,UAAA,KAAA,CAAK;AAAA,YAAA,GAC3C;AAAA,YAED,YACC,oBAAC,OAAA,EAAI,WAAU,4DACZ,UACH;AAAA,YAED,cACC,qBAAC,OAAA,EAAI,WAAU,2BACZ,UAAA;AAAA,cAAA,iBAAiB,oBAAC,cAAA,EAAa,QAAQ,eAAe,SAAQ,SAAQ;AAAA,cACtE,mBAAmB,oBAAC,cAAA,EAAa,QAAQ,iBAAiB,SAAQ,WAAA,CAAW;AAAA,YAAA,EAAA,CAChF;AAAA,UAAA,GAEJ;AAAA,UACC,aACC;AAAA,YAAC,iBAAiB;AAAA,YAAjB;AAAA,cACC,WACE;AAAA,cAEF,OAAO;AAAA,cACP,QAAQ;AAAA,YAAA;AAAA,UAAA;AAAA,QACV;AAAA,MAAA;AAAA,IAAA,GAGN;AAAA,EAEJ;AACF;AACA,eAAe,cAAc;"}
|
|
@@ -3,6 +3,7 @@ import { jsx, jsxs } from "react/jsx-runtime";
|
|
|
3
3
|
import * as SelectPrimitive from "@radix-ui/react-select";
|
|
4
4
|
import * as React from "react";
|
|
5
5
|
import { cn } from "../../utils/cn.mjs";
|
|
6
|
+
import { FLOATING_CONTENT_COLLISION_PADDING } from "../../utils/floatingContentCollisionPadding.mjs";
|
|
6
7
|
import { CheckIcon } from "../Icons/CheckIcon.mjs";
|
|
7
8
|
import { ChevronDownIcon } from "../Icons/ChevronDownIcon.mjs";
|
|
8
9
|
const SelectContext = React.createContext({
|
|
@@ -121,26 +122,36 @@ const Select = React.forwardRef(
|
|
|
121
122
|
}
|
|
122
123
|
);
|
|
123
124
|
Select.displayName = "Select";
|
|
124
|
-
const SelectContent = React.forwardRef(
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
position,
|
|
129
|
-
sideOffset,
|
|
130
|
-
collisionPadding
|
|
131
|
-
style
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
125
|
+
const SelectContent = React.forwardRef(
|
|
126
|
+
({
|
|
127
|
+
className,
|
|
128
|
+
children,
|
|
129
|
+
position = "popper",
|
|
130
|
+
sideOffset = 4,
|
|
131
|
+
collisionPadding = FLOATING_CONTENT_COLLISION_PADDING,
|
|
132
|
+
style,
|
|
133
|
+
...props
|
|
134
|
+
}, ref) => /* @__PURE__ */ jsx(SelectPrimitive.Portal, { children: /* @__PURE__ */ jsx(
|
|
135
|
+
SelectPrimitive.Content,
|
|
136
|
+
{
|
|
137
|
+
ref,
|
|
138
|
+
position,
|
|
139
|
+
sideOffset,
|
|
140
|
+
collisionPadding,
|
|
141
|
+
style: { zIndex: "var(--fanvue-ui-portal-z-index, 50)", ...style },
|
|
142
|
+
className: cn(
|
|
143
|
+
"relative w-max min-w-(--radix-select-trigger-width) max-w-(--radix-select-content-available-width) overflow-hidden rounded-sm border border-neutral-alphas-200 bg-bg-primary text-content-primary shadow-[0_4px_16px_rgba(0,0,0,0.10)]",
|
|
144
|
+
"data-[state=closed]:animate-out data-[state=open]:animate-in",
|
|
145
|
+
"data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
|
|
146
|
+
"data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95",
|
|
147
|
+
"data-[side=bottom]:slide-in-from-top-2 data-[side=top]:slide-in-from-bottom-2",
|
|
148
|
+
className
|
|
149
|
+
),
|
|
150
|
+
...props,
|
|
151
|
+
children: /* @__PURE__ */ jsx(SelectPrimitive.Viewport, { className: "max-h-[var(--radix-select-content-available-height)] overflow-y-auto p-1", children })
|
|
152
|
+
}
|
|
153
|
+
) })
|
|
154
|
+
);
|
|
144
155
|
SelectContent.displayName = "SelectContent";
|
|
145
156
|
const SelectItem = React.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs(
|
|
146
157
|
SelectPrimitive.Item,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Select.mjs","sources":["../../../src/components/Select/Select.tsx"],"sourcesContent":["import * as SelectPrimitive from \"@radix-ui/react-select\";\nimport * as React from \"react\";\nimport { cn } from \"@/utils/cn\";\nimport { CheckIcon } from \"../Icons/CheckIcon\";\nimport { ChevronDownIcon } from \"../Icons/ChevronDownIcon\";\n\n/** Select field height in pixels. */\nexport type SelectSize = \"48\" | \"40\" | \"32\";\n\ntype SelectContextValue = {\n size: SelectSize;\n error: boolean;\n disabled?: boolean;\n};\n\nconst SelectContext = React.createContext<SelectContextValue>({\n size: \"48\",\n error: false,\n});\n\nconst TRIGGER_HEIGHT: Record<SelectSize, string> = {\n \"48\": \"h-12\",\n \"40\": \"h-10\",\n \"32\": \"h-8\",\n};\n\nconst TRIGGER_PADDING_X: Record<SelectSize, string> = {\n \"48\": \"px-4\",\n \"40\": \"px-4\",\n \"32\": \"px-3\",\n};\n\nconst TRIGGER_GAP: Record<SelectSize, string> = {\n \"48\": \"gap-3\",\n \"40\": \"gap-3\",\n \"32\": \"gap-2\",\n};\n\nconst TRIGGER_TYPOGRAPHY: Record<SelectSize, string> = {\n \"48\": \"typography-regular-body-lg\",\n \"40\": \"typography-regular-body-lg\",\n \"32\": \"typography-regular-body-md\",\n};\n\nexport interface SelectProps extends Omit<SelectPrimitive.SelectProps, \"dir\"> {\n /** Label text displayed above the trigger. Also used as the accessible name. */\n label?: string;\n /** Accessible name applied directly to the trigger button when no visible `label` is provided. */\n \"aria-label\"?: string;\n /** ID of an external element that labels the trigger button. */\n \"aria-labelledby\"?: string;\n /** Helper text displayed below the trigger. Replaced by `errorMessage` when `error` is `true`. */\n helperText?: string;\n /** Height of the select field in pixels. @default \"48\" */\n size?: SelectSize;\n /** Whether the field is in an error state. @default false */\n error?: boolean;\n /** Error message displayed below the trigger. Shown instead of `helperText` when `error` is `true`. */\n errorMessage?: string;\n /** Placeholder shown when no value is selected. */\n placeholder?: string;\n /** Icon element displayed at the left side of the trigger. */\n leftIcon?: React.ReactNode;\n /** Whether the field stretches to fill its container width. @default false */\n fullWidth?: boolean;\n /** Wraps the `className` of the outermost container div. */\n className?: string;\n /** HTML `id` applied to the trigger button. Auto-generated if omitted. */\n id?: string;\n}\n\n/**\n * A select field with optional label, helper/error text, and an icon slot,\n * built on Radix UI Select for full accessibility and keyboard navigation.\n *\n * Pair with {@link SelectContent} and {@link SelectItem} to provide options.\n *\n * @example\n * ```tsx\n * <Select label=\"Country\" placeholder=\"Select a country\">\n * <SelectContent>\n * <SelectItem value=\"us\">United States</SelectItem>\n * <SelectItem value=\"uk\">United Kingdom</SelectItem>\n * </SelectContent>\n * </Select>\n * ```\n */\nexport const Select = React.forwardRef<\n React.ComponentRef<typeof SelectPrimitive.Trigger>,\n SelectProps\n>(\n (\n {\n label,\n helperText,\n size = \"48\",\n error = false,\n errorMessage,\n placeholder,\n leftIcon,\n fullWidth = false,\n className,\n id,\n disabled,\n children,\n \"aria-label\": ariaLabel,\n \"aria-labelledby\": ariaLabelledby,\n ...props\n },\n ref,\n ) => {\n const generatedId = React.useId();\n const triggerId = id ?? generatedId;\n const helperTextId = `${triggerId}-helper`;\n const bottomText = error && errorMessage ? errorMessage : helperText;\n\n return (\n <SelectContext.Provider value={{ size, error, disabled }}>\n <div\n className={cn(\"flex flex-col\", fullWidth && \"w-full\", className)}\n data-disabled={disabled ? \"\" : undefined}\n data-error={error ? \"\" : undefined}\n >\n {label && (\n <label\n htmlFor={triggerId}\n className=\"typography-semibold-body-sm px-1 pt-1 pb-2 text-content-primary\"\n >\n {label}\n </label>\n )}\n\n <SelectPrimitive.Root disabled={disabled} {...props}>\n <SelectPrimitive.Trigger\n ref={ref}\n id={triggerId}\n aria-label={ariaLabel}\n aria-labelledby={ariaLabelledby}\n aria-describedby={bottomText ? helperTextId : undefined}\n aria-invalid={error || undefined}\n className={cn(\n \"flex w-full cursor-pointer items-center justify-between rounded-sm border bg-neutral-alphas-50 outline-none motion-safe:transition-colors\",\n TRIGGER_HEIGHT[size],\n TRIGGER_PADDING_X[size],\n TRIGGER_GAP[size],\n TRIGGER_TYPOGRAPHY[size],\n error ? \"border-error-content\" : \"border-transparent\",\n !disabled &&\n !error &&\n \"hover:border-neutral-alphas-400 data-[state=open]:border-neutral-alphas-400\",\n disabled && \"cursor-not-allowed opacity-50\",\n )}\n >\n <div className=\"flex min-w-0 items-center gap-2\">\n {leftIcon && (\n <span\n className=\"flex size-5 shrink-0 items-center justify-center text-content-secondary\"\n data-testid=\"left-icon\"\n >\n {leftIcon}\n </span>\n )}\n <span className=\"min-w-0 flex-1 truncate text-left text-content-primary [&>[data-placeholder]]:text-content-secondary [&>[data-placeholder]]:opacity-40\">\n <SelectPrimitive.Value placeholder={placeholder} />\n </span>\n </div>\n\n <SelectPrimitive.Icon asChild>\n <ChevronDownIcon />\n </SelectPrimitive.Icon>\n </SelectPrimitive.Trigger>\n\n {children}\n </SelectPrimitive.Root>\n\n {bottomText && (\n <p\n id={helperTextId}\n className={cn(\n \"typography-regular-body-sm px-2 pt-1 pb-0.5\",\n error ? \"text-error-content\" : \"text-content-secondary\",\n )}\n >\n {bottomText}\n </p>\n )}\n </div>\n </SelectContext.Provider>\n );\n },\n);\n\nSelect.displayName = \"Select\";\n\nexport interface SelectContentProps\n extends React.ComponentPropsWithoutRef<typeof SelectPrimitive.Content> {}\n\n/**\n * The dropdown panel rendered inside a portal. Place {@link SelectItem} elements\n * (and optionally {@link SelectGroup} / {@link SelectLabel}) as children.\n */\nexport const SelectContent = React.forwardRef<\n React.ComponentRef<typeof SelectPrimitive.Content>,\n SelectContentProps\n>(({ className, children, position = \"popper\", sideOffset = 4, style, ...props }, ref) => (\n <SelectPrimitive.Portal>\n <SelectPrimitive.Content\n ref={ref}\n position={position}\n sideOffset={sideOffset}\n collisionPadding={8}\n style={{ zIndex: \"var(--fanvue-ui-portal-z-index, 50)\", ...style }}\n className={cn(\n \"relative min-w-(--radix-select-trigger-width) overflow-hidden rounded-sm border border-neutral-alphas-200 bg-bg-primary text-content-primary shadow-[0_4px_16px_rgba(0,0,0,0.10)]\",\n \"data-[state=closed]:animate-out data-[state=open]:animate-in\",\n \"data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0\",\n \"data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95\",\n \"data-[side=bottom]:slide-in-from-top-2 data-[side=top]:slide-in-from-bottom-2\",\n className,\n )}\n {...props}\n >\n <SelectPrimitive.Viewport className=\"max-h-[var(--radix-select-content-available-height)] overflow-y-auto p-1\">\n {children}\n </SelectPrimitive.Viewport>\n </SelectPrimitive.Content>\n </SelectPrimitive.Portal>\n));\n\nSelectContent.displayName = \"SelectContent\";\n\nexport interface SelectItemProps\n extends React.ComponentPropsWithoutRef<typeof SelectPrimitive.Item> {}\n\n/**\n * An individual option inside {@link SelectContent}.\n */\nexport const SelectItem = React.forwardRef<\n React.ComponentRef<typeof SelectPrimitive.Item>,\n SelectItemProps\n>(({ className, children, ...props }, ref) => (\n <SelectPrimitive.Item\n ref={ref}\n className={cn(\n \"typography-regular-body-lg relative flex w-full cursor-pointer select-none items-center gap-2 rounded-xs py-2 pr-2 pl-3 text-content-primary outline-none\",\n \"focus:bg-neutral-alphas-100 data-disabled:pointer-events-none data-disabled:opacity-50\",\n className,\n )}\n {...props}\n >\n <SelectPrimitive.ItemText>{children}</SelectPrimitive.ItemText>\n <SelectPrimitive.ItemIndicator className=\"ml-auto flex size-4 shrink-0 items-center justify-center\">\n <CheckIcon className=\"size-4 text-content-primary\" />\n </SelectPrimitive.ItemIndicator>\n </SelectPrimitive.Item>\n));\n\nSelectItem.displayName = \"SelectItem\";\n\n/** Props for {@link SelectGroup}. */\nexport type SelectGroupProps = React.ComponentPropsWithoutRef<typeof SelectPrimitive.Group>;\n\n/**\n * Groups related {@link SelectItem} elements under a {@link SelectLabel}.\n */\nexport const SelectGroup = SelectPrimitive.Group;\nSelectGroup.displayName = \"SelectGroup\";\n\nexport interface SelectLabelProps\n extends React.ComponentPropsWithoutRef<typeof SelectPrimitive.Label> {}\n\n/**\n * A non-interactive label shown above a {@link SelectGroup}.\n */\nexport const SelectLabel = React.forwardRef<\n React.ComponentRef<typeof SelectPrimitive.Label>,\n SelectLabelProps\n>(({ className, ...props }, ref) => (\n <SelectPrimitive.Label\n ref={ref}\n className={cn(\"typography-semibold-body-sm px-3 py-1.5 text-content-secondary\", className)}\n {...props}\n />\n));\n\nSelectLabel.displayName = \"SelectLabel\";\n\nexport interface SelectSeparatorProps\n extends React.ComponentPropsWithoutRef<typeof SelectPrimitive.Separator> {}\n\n/** A horizontal rule that visually separates groups in {@link SelectContent}. */\nexport const SelectSeparator = React.forwardRef<\n React.ComponentRef<typeof SelectPrimitive.Separator>,\n SelectSeparatorProps\n>(({ className, ...props }, ref) => (\n <SelectPrimitive.Separator\n ref={ref}\n className={cn(\"-mx-1 my-1 h-px bg-neutral-alphas-200\", className)}\n {...props}\n />\n));\n\nSelectSeparator.displayName = \"SelectSeparator\";\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Select.mjs","sources":["../../../src/components/Select/Select.tsx"],"sourcesContent":["import * as SelectPrimitive from \"@radix-ui/react-select\";\nimport * as React from \"react\";\nimport { cn } from \"@/utils/cn\";\nimport { FLOATING_CONTENT_COLLISION_PADDING } from \"@/utils/floatingContentCollisionPadding\";\nimport { CheckIcon } from \"../Icons/CheckIcon\";\nimport { ChevronDownIcon } from \"../Icons/ChevronDownIcon\";\n\n/** Select field height in pixels. */\nexport type SelectSize = \"48\" | \"40\" | \"32\";\n\ntype SelectContextValue = {\n size: SelectSize;\n error: boolean;\n disabled?: boolean;\n};\n\nconst SelectContext = React.createContext<SelectContextValue>({\n size: \"48\",\n error: false,\n});\n\nconst TRIGGER_HEIGHT: Record<SelectSize, string> = {\n \"48\": \"h-12\",\n \"40\": \"h-10\",\n \"32\": \"h-8\",\n};\n\nconst TRIGGER_PADDING_X: Record<SelectSize, string> = {\n \"48\": \"px-4\",\n \"40\": \"px-4\",\n \"32\": \"px-3\",\n};\n\nconst TRIGGER_GAP: Record<SelectSize, string> = {\n \"48\": \"gap-3\",\n \"40\": \"gap-3\",\n \"32\": \"gap-2\",\n};\n\nconst TRIGGER_TYPOGRAPHY: Record<SelectSize, string> = {\n \"48\": \"typography-regular-body-lg\",\n \"40\": \"typography-regular-body-lg\",\n \"32\": \"typography-regular-body-md\",\n};\n\nexport interface SelectProps extends Omit<SelectPrimitive.SelectProps, \"dir\"> {\n /** Label text displayed above the trigger. Also used as the accessible name. */\n label?: string;\n /** Accessible name applied directly to the trigger button when no visible `label` is provided. */\n \"aria-label\"?: string;\n /** ID of an external element that labels the trigger button. */\n \"aria-labelledby\"?: string;\n /** Helper text displayed below the trigger. Replaced by `errorMessage` when `error` is `true`. */\n helperText?: string;\n /** Height of the select field in pixels. @default \"48\" */\n size?: SelectSize;\n /** Whether the field is in an error state. @default false */\n error?: boolean;\n /** Error message displayed below the trigger. Shown instead of `helperText` when `error` is `true`. */\n errorMessage?: string;\n /** Placeholder shown when no value is selected. */\n placeholder?: string;\n /** Icon element displayed at the left side of the trigger. */\n leftIcon?: React.ReactNode;\n /** Whether the field stretches to fill its container width. @default false */\n fullWidth?: boolean;\n /** Wraps the `className` of the outermost container div. */\n className?: string;\n /** HTML `id` applied to the trigger button. Auto-generated if omitted. */\n id?: string;\n}\n\n/**\n * A select field with optional label, helper/error text, and an icon slot,\n * built on Radix UI Select for full accessibility and keyboard navigation.\n *\n * Pair with {@link SelectContent} and {@link SelectItem} to provide options.\n *\n * @example\n * ```tsx\n * <Select label=\"Country\" placeholder=\"Select a country\">\n * <SelectContent>\n * <SelectItem value=\"us\">United States</SelectItem>\n * <SelectItem value=\"uk\">United Kingdom</SelectItem>\n * </SelectContent>\n * </Select>\n * ```\n */\nexport const Select = React.forwardRef<\n React.ComponentRef<typeof SelectPrimitive.Trigger>,\n SelectProps\n>(\n (\n {\n label,\n helperText,\n size = \"48\",\n error = false,\n errorMessage,\n placeholder,\n leftIcon,\n fullWidth = false,\n className,\n id,\n disabled,\n children,\n \"aria-label\": ariaLabel,\n \"aria-labelledby\": ariaLabelledby,\n ...props\n },\n ref,\n ) => {\n const generatedId = React.useId();\n const triggerId = id ?? generatedId;\n const helperTextId = `${triggerId}-helper`;\n const bottomText = error && errorMessage ? errorMessage : helperText;\n\n return (\n <SelectContext.Provider value={{ size, error, disabled }}>\n <div\n className={cn(\"flex flex-col\", fullWidth && \"w-full\", className)}\n data-disabled={disabled ? \"\" : undefined}\n data-error={error ? \"\" : undefined}\n >\n {label && (\n <label\n htmlFor={triggerId}\n className=\"typography-semibold-body-sm px-1 pt-1 pb-2 text-content-primary\"\n >\n {label}\n </label>\n )}\n\n <SelectPrimitive.Root disabled={disabled} {...props}>\n <SelectPrimitive.Trigger\n ref={ref}\n id={triggerId}\n aria-label={ariaLabel}\n aria-labelledby={ariaLabelledby}\n aria-describedby={bottomText ? helperTextId : undefined}\n aria-invalid={error || undefined}\n className={cn(\n \"flex w-full cursor-pointer items-center justify-between rounded-sm border bg-neutral-alphas-50 outline-none motion-safe:transition-colors\",\n TRIGGER_HEIGHT[size],\n TRIGGER_PADDING_X[size],\n TRIGGER_GAP[size],\n TRIGGER_TYPOGRAPHY[size],\n error ? \"border-error-content\" : \"border-transparent\",\n !disabled &&\n !error &&\n \"hover:border-neutral-alphas-400 data-[state=open]:border-neutral-alphas-400\",\n disabled && \"cursor-not-allowed opacity-50\",\n )}\n >\n <div className=\"flex min-w-0 items-center gap-2\">\n {leftIcon && (\n <span\n className=\"flex size-5 shrink-0 items-center justify-center text-content-secondary\"\n data-testid=\"left-icon\"\n >\n {leftIcon}\n </span>\n )}\n <span className=\"min-w-0 flex-1 truncate text-left text-content-primary [&>[data-placeholder]]:text-content-secondary [&>[data-placeholder]]:opacity-40\">\n <SelectPrimitive.Value placeholder={placeholder} />\n </span>\n </div>\n\n <SelectPrimitive.Icon asChild>\n <ChevronDownIcon />\n </SelectPrimitive.Icon>\n </SelectPrimitive.Trigger>\n\n {children}\n </SelectPrimitive.Root>\n\n {bottomText && (\n <p\n id={helperTextId}\n className={cn(\n \"typography-regular-body-sm px-2 pt-1 pb-0.5\",\n error ? \"text-error-content\" : \"text-content-secondary\",\n )}\n >\n {bottomText}\n </p>\n )}\n </div>\n </SelectContext.Provider>\n );\n },\n);\n\nSelect.displayName = \"Select\";\n\nexport interface SelectContentProps\n extends React.ComponentPropsWithoutRef<typeof SelectPrimitive.Content> {}\n\n/**\n * The dropdown panel rendered inside a portal. Place {@link SelectItem} elements\n * (and optionally {@link SelectGroup} / {@link SelectLabel}) as children.\n */\nexport const SelectContent = React.forwardRef<\n React.ComponentRef<typeof SelectPrimitive.Content>,\n SelectContentProps\n>(\n (\n {\n className,\n children,\n position = \"popper\",\n sideOffset = 4,\n collisionPadding = FLOATING_CONTENT_COLLISION_PADDING,\n style,\n ...props\n },\n ref,\n ) => (\n <SelectPrimitive.Portal>\n <SelectPrimitive.Content\n ref={ref}\n position={position}\n sideOffset={sideOffset}\n collisionPadding={collisionPadding}\n style={{ zIndex: \"var(--fanvue-ui-portal-z-index, 50)\", ...style }}\n className={cn(\n \"relative w-max min-w-(--radix-select-trigger-width) max-w-(--radix-select-content-available-width) overflow-hidden rounded-sm border border-neutral-alphas-200 bg-bg-primary text-content-primary shadow-[0_4px_16px_rgba(0,0,0,0.10)]\",\n \"data-[state=closed]:animate-out data-[state=open]:animate-in\",\n \"data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0\",\n \"data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95\",\n \"data-[side=bottom]:slide-in-from-top-2 data-[side=top]:slide-in-from-bottom-2\",\n className,\n )}\n {...props}\n >\n <SelectPrimitive.Viewport className=\"max-h-[var(--radix-select-content-available-height)] overflow-y-auto p-1\">\n {children}\n </SelectPrimitive.Viewport>\n </SelectPrimitive.Content>\n </SelectPrimitive.Portal>\n ),\n);\n\nSelectContent.displayName = \"SelectContent\";\n\nexport interface SelectItemProps\n extends React.ComponentPropsWithoutRef<typeof SelectPrimitive.Item> {}\n\n/**\n * An individual option inside {@link SelectContent}.\n */\nexport const SelectItem = React.forwardRef<\n React.ComponentRef<typeof SelectPrimitive.Item>,\n SelectItemProps\n>(({ className, children, ...props }, ref) => (\n <SelectPrimitive.Item\n ref={ref}\n className={cn(\n \"typography-regular-body-lg relative flex w-full cursor-pointer select-none items-center gap-2 rounded-xs py-2 pr-2 pl-3 text-content-primary outline-none\",\n \"focus:bg-neutral-alphas-100 data-disabled:pointer-events-none data-disabled:opacity-50\",\n className,\n )}\n {...props}\n >\n <SelectPrimitive.ItemText>{children}</SelectPrimitive.ItemText>\n <SelectPrimitive.ItemIndicator className=\"ml-auto flex size-4 shrink-0 items-center justify-center\">\n <CheckIcon className=\"size-4 text-content-primary\" />\n </SelectPrimitive.ItemIndicator>\n </SelectPrimitive.Item>\n));\n\nSelectItem.displayName = \"SelectItem\";\n\n/** Props for {@link SelectGroup}. */\nexport type SelectGroupProps = React.ComponentPropsWithoutRef<typeof SelectPrimitive.Group>;\n\n/**\n * Groups related {@link SelectItem} elements under a {@link SelectLabel}.\n */\nexport const SelectGroup = SelectPrimitive.Group;\nSelectGroup.displayName = \"SelectGroup\";\n\nexport interface SelectLabelProps\n extends React.ComponentPropsWithoutRef<typeof SelectPrimitive.Label> {}\n\n/**\n * A non-interactive label shown above a {@link SelectGroup}.\n */\nexport const SelectLabel = React.forwardRef<\n React.ComponentRef<typeof SelectPrimitive.Label>,\n SelectLabelProps\n>(({ className, ...props }, ref) => (\n <SelectPrimitive.Label\n ref={ref}\n className={cn(\"typography-semibold-body-sm px-3 py-1.5 text-content-secondary\", className)}\n {...props}\n />\n));\n\nSelectLabel.displayName = \"SelectLabel\";\n\nexport interface SelectSeparatorProps\n extends React.ComponentPropsWithoutRef<typeof SelectPrimitive.Separator> {}\n\n/** A horizontal rule that visually separates groups in {@link SelectContent}. */\nexport const SelectSeparator = React.forwardRef<\n React.ComponentRef<typeof SelectPrimitive.Separator>,\n SelectSeparatorProps\n>(({ className, ...props }, ref) => (\n <SelectPrimitive.Separator\n ref={ref}\n className={cn(\"-mx-1 my-1 h-px bg-neutral-alphas-200\", className)}\n {...props}\n />\n));\n\nSelectSeparator.displayName = \"SelectSeparator\";\n"],"names":[],"mappings":";;;;;;;;AAgBA,MAAM,gBAAgB,MAAM,cAAkC;AAAA,EAC5D,MAAM;AAAA,EACN,OAAO;AACT,CAAC;AAED,MAAM,iBAA6C;AAAA,EACjD,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AACR;AAEA,MAAM,oBAAgD;AAAA,EACpD,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AACR;AAEA,MAAM,cAA0C;AAAA,EAC9C,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AACR;AAEA,MAAM,qBAAiD;AAAA,EACrD,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AACR;AA6CO,MAAM,SAAS,MAAM;AAAA,EAI1B,CACE;AAAA,IACE;AAAA,IACA;AAAA,IACA,OAAO;AAAA,IACP,QAAQ;AAAA,IACR;AAAA,IACA;AAAA,IACA;AAAA,IACA,YAAY;AAAA,IACZ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,cAAc;AAAA,IACd,mBAAmB;AAAA,IACnB,GAAG;AAAA,EAAA,GAEL,QACG;AACH,UAAM,cAAc,MAAM,MAAA;AAC1B,UAAM,YAAY,MAAM;AACxB,UAAM,eAAe,GAAG,SAAS;AACjC,UAAM,aAAa,SAAS,eAAe,eAAe;AAE1D,WACE,oBAAC,cAAc,UAAd,EAAuB,OAAO,EAAE,MAAM,OAAO,YAC5C,UAAA;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,WAAW,GAAG,iBAAiB,aAAa,UAAU,SAAS;AAAA,QAC/D,iBAAe,WAAW,KAAK;AAAA,QAC/B,cAAY,QAAQ,KAAK;AAAA,QAExB,UAAA;AAAA,UAAA,SACC;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,SAAS;AAAA,cACT,WAAU;AAAA,cAET,UAAA;AAAA,YAAA;AAAA,UAAA;AAAA,+BAIJ,gBAAgB,MAAhB,EAAqB,UAAqB,GAAG,OAC5C,UAAA;AAAA,YAAA;AAAA,cAAC,gBAAgB;AAAA,cAAhB;AAAA,gBACC;AAAA,gBACA,IAAI;AAAA,gBACJ,cAAY;AAAA,gBACZ,mBAAiB;AAAA,gBACjB,oBAAkB,aAAa,eAAe;AAAA,gBAC9C,gBAAc,SAAS;AAAA,gBACvB,WAAW;AAAA,kBACT;AAAA,kBACA,eAAe,IAAI;AAAA,kBACnB,kBAAkB,IAAI;AAAA,kBACtB,YAAY,IAAI;AAAA,kBAChB,mBAAmB,IAAI;AAAA,kBACvB,QAAQ,yBAAyB;AAAA,kBACjC,CAAC,YACC,CAAC,SACD;AAAA,kBACF,YAAY;AAAA,gBAAA;AAAA,gBAGd,UAAA;AAAA,kBAAA,qBAAC,OAAA,EAAI,WAAU,mCACZ,UAAA;AAAA,oBAAA,YACC;AAAA,sBAAC;AAAA,sBAAA;AAAA,wBACC,WAAU;AAAA,wBACV,eAAY;AAAA,wBAEX,UAAA;AAAA,sBAAA;AAAA,oBAAA;AAAA,oBAGL,oBAAC,UAAK,WAAU,0IACd,8BAAC,gBAAgB,OAAhB,EAAsB,YAAA,CAA0B,EAAA,CACnD;AAAA,kBAAA,GACF;AAAA,kBAEA,oBAAC,gBAAgB,MAAhB,EAAqB,SAAO,MAC3B,UAAA,oBAAC,mBAAgB,EAAA,CACnB;AAAA,gBAAA;AAAA,cAAA;AAAA,YAAA;AAAA,YAGD;AAAA,UAAA,GACH;AAAA,UAEC,cACC;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,IAAI;AAAA,cACJ,WAAW;AAAA,gBACT;AAAA,gBACA,QAAQ,uBAAuB;AAAA,cAAA;AAAA,cAGhC,UAAA;AAAA,YAAA;AAAA,UAAA;AAAA,QACH;AAAA,MAAA;AAAA,IAAA,GAGN;AAAA,EAEJ;AACF;AAEA,OAAO,cAAc;AASd,MAAM,gBAAgB,MAAM;AAAA,EAIjC,CACE;AAAA,IACE;AAAA,IACA;AAAA,IACA,WAAW;AAAA,IACX,aAAa;AAAA,IACb,mBAAmB;AAAA,IACnB;AAAA,IACA,GAAG;AAAA,EAAA,GAEL,QAEA,oBAAC,gBAAgB,QAAhB,EACC,UAAA;AAAA,IAAC,gBAAgB;AAAA,IAAhB;AAAA,MACC;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,OAAO,EAAE,QAAQ,uCAAuC,GAAG,MAAA;AAAA,MAC3D,WAAW;AAAA,QACT;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MAAA;AAAA,MAED,GAAG;AAAA,MAEJ,8BAAC,gBAAgB,UAAhB,EAAyB,WAAU,4EACjC,SAAA,CACH;AAAA,IAAA;AAAA,EAAA,EACF,CACF;AAEJ;AAEA,cAAc,cAAc;AAQrB,MAAM,aAAa,MAAM,WAG9B,CAAC,EAAE,WAAW,UAAU,GAAG,SAAS,QACpC;AAAA,EAAC,gBAAgB;AAAA,EAAhB;AAAA,IACC;AAAA,IACA,WAAW;AAAA,MACT;AAAA,MACA;AAAA,MACA;AAAA,IAAA;AAAA,IAED,GAAG;AAAA,IAEJ,UAAA;AAAA,MAAA,oBAAC,gBAAgB,UAAhB,EAA0B,SAAA,CAAS;AAAA,MACpC,oBAAC,gBAAgB,eAAhB,EAA8B,WAAU,4DACvC,UAAA,oBAAC,WAAA,EAAU,WAAU,8BAAA,CAA8B,EAAA,CACrD;AAAA,IAAA;AAAA,EAAA;AACF,CACD;AAED,WAAW,cAAc;AAQlB,MAAM,cAAc,gBAAgB;AAC3C,YAAY,cAAc;AAQnB,MAAM,cAAc,MAAM,WAG/B,CAAC,EAAE,WAAW,GAAG,MAAA,GAAS,QAC1B;AAAA,EAAC,gBAAgB;AAAA,EAAhB;AAAA,IACC;AAAA,IACA,WAAW,GAAG,kEAAkE,SAAS;AAAA,IACxF,GAAG;AAAA,EAAA;AACN,CACD;AAED,YAAY,cAAc;AAMnB,MAAM,kBAAkB,MAAM,WAGnC,CAAC,EAAE,WAAW,GAAG,MAAA,GAAS,QAC1B;AAAA,EAAC,gBAAgB;AAAA,EAAhB;AAAA,IACC;AAAA,IACA,WAAW,GAAG,yCAAyC,SAAS;AAAA,IAC/D,GAAG;AAAA,EAAA;AACN,CACD;AAED,gBAAgB,cAAc;"}
|
|
@@ -15,7 +15,7 @@ const TooltipContent = React.forwardRef(({ className, sideOffset = 8, style, ...
|
|
|
15
15
|
collisionPadding: 8,
|
|
16
16
|
style: { zIndex: "var(--fanvue-ui-portal-z-index, 50)", ...style },
|
|
17
17
|
className: cn(
|
|
18
|
-
"typography-semibold-body-sm max-w-[320px] rounded-
|
|
18
|
+
"typography-semibold-body-sm max-w-[320px] rounded-sm bg-surface-primary-inverted px-4 py-2 text-content-primary-inverted shadow-[0px_1px_4px_0px_rgba(0,0,0,0.06),0px_1px_3px_0px_rgba(0,0,0,0.05)]",
|
|
19
19
|
className
|
|
20
20
|
),
|
|
21
21
|
align: "center",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Tooltip.mjs","sources":["../../../src/components/Tooltip/Tooltip.tsx"],"sourcesContent":["import * as TooltipPrimitive from \"@radix-ui/react-tooltip\";\nimport * as React from \"react\";\nimport { cn } from \"../../utils/cn\";\n\n/** Props for the {@link TooltipProvider}. Wraps Radix `Tooltip.Provider`. */\nexport type TooltipProviderProps = React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Provider>;\n\n/** Provides tooltip delay and skip-delay context. Wrap your app or a subtree. */\nexport const TooltipProvider = TooltipPrimitive.Provider;\n\n/** Props for the {@link Tooltip} root component. */\nexport interface TooltipProps extends React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Root> {\n open?: boolean;\n onOpenChange?: (open: boolean) => void;\n defaultOpen?: boolean;\n}\n\n/** Root component that manages open/close state for a single tooltip. */\nexport const Tooltip = TooltipPrimitive.Root;\n\n/** Props for the {@link TooltipTrigger} component. */\nexport type TooltipTriggerProps = React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Trigger>;\n\n/** The element that triggers the tooltip on hover/focus. */\nexport const TooltipTrigger = TooltipPrimitive.Trigger;\n\nexport type TooltipContentProps = React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Content>;\n\nexport const TooltipContent = React.forwardRef<\n React.ComponentRef<typeof TooltipPrimitive.Content>,\n TooltipContentProps\n>(({ className, sideOffset = 8, style, ...props }, ref) => {\n return (\n <TooltipPrimitive.Portal>\n <TooltipPrimitive.Content\n ref={ref}\n sideOffset={sideOffset}\n collisionPadding={8}\n style={{ zIndex: \"var(--fanvue-ui-portal-z-index, 50)\", ...style }}\n className={cn(\n \"typography-semibold-body-sm max-w-[320px] rounded-
|
|
1
|
+
{"version":3,"file":"Tooltip.mjs","sources":["../../../src/components/Tooltip/Tooltip.tsx"],"sourcesContent":["import * as TooltipPrimitive from \"@radix-ui/react-tooltip\";\nimport * as React from \"react\";\nimport { cn } from \"../../utils/cn\";\n\n/** Props for the {@link TooltipProvider}. Wraps Radix `Tooltip.Provider`. */\nexport type TooltipProviderProps = React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Provider>;\n\n/** Provides tooltip delay and skip-delay context. Wrap your app or a subtree. */\nexport const TooltipProvider = TooltipPrimitive.Provider;\n\n/** Props for the {@link Tooltip} root component. */\nexport interface TooltipProps extends React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Root> {\n open?: boolean;\n onOpenChange?: (open: boolean) => void;\n defaultOpen?: boolean;\n}\n\n/** Root component that manages open/close state for a single tooltip. */\nexport const Tooltip = TooltipPrimitive.Root;\n\n/** Props for the {@link TooltipTrigger} component. */\nexport type TooltipTriggerProps = React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Trigger>;\n\n/** The element that triggers the tooltip on hover/focus. */\nexport const TooltipTrigger = TooltipPrimitive.Trigger;\n\nexport type TooltipContentProps = React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Content>;\n\nexport const TooltipContent = React.forwardRef<\n React.ComponentRef<typeof TooltipPrimitive.Content>,\n TooltipContentProps\n>(({ className, sideOffset = 8, style, ...props }, ref) => {\n return (\n <TooltipPrimitive.Portal>\n <TooltipPrimitive.Content\n ref={ref}\n sideOffset={sideOffset}\n collisionPadding={8}\n style={{ zIndex: \"var(--fanvue-ui-portal-z-index, 50)\", ...style }}\n className={cn(\n \"typography-semibold-body-sm max-w-[320px] rounded-sm bg-surface-primary-inverted px-4 py-2 text-content-primary-inverted shadow-[0px_1px_4px_0px_rgba(0,0,0,0.06),0px_1px_3px_0px_rgba(0,0,0,0.05)]\",\n className,\n )}\n align=\"center\"\n {...props}\n />\n </TooltipPrimitive.Portal>\n );\n});\nTooltipContent.displayName = \"TooltipContent\";\n"],"names":[],"mappings":";;;;;AAQO,MAAM,kBAAkB,iBAAiB;AAUzC,MAAM,UAAU,iBAAiB;AAMjC,MAAM,iBAAiB,iBAAiB;AAIxC,MAAM,iBAAiB,MAAM,WAGlC,CAAC,EAAE,WAAW,aAAa,GAAG,OAAO,GAAG,MAAA,GAAS,QAAQ;AACzD,SACE,oBAAC,iBAAiB,QAAjB,EACC,UAAA;AAAA,IAAC,iBAAiB;AAAA,IAAjB;AAAA,MACC;AAAA,MACA;AAAA,MACA,kBAAkB;AAAA,MAClB,OAAO,EAAE,QAAQ,uCAAuC,GAAG,MAAA;AAAA,MAC3D,WAAW;AAAA,QACT;AAAA,QACA;AAAA,MAAA;AAAA,MAEF,OAAM;AAAA,MACL,GAAG;AAAA,IAAA;AAAA,EAAA,GAER;AAEJ,CAAC;AACD,eAAe,cAAc;"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"floatingContentCollisionPadding.mjs","sources":["../../src/utils/floatingContentCollisionPadding.ts"],"sourcesContent":["/**\n * Default viewport inset for Radix-positioned panels (dropdown, select list, autocomplete).\n * Applied via `collisionPadding` so content stays off screen edges on narrow viewports.\n */\nexport const FLOATING_CONTENT_COLLISION_PADDING = 16;\n"],"names":[],"mappings":";AAIO,MAAM,qCAAqC;"}
|