@lobehub/ui
Version:
Lobe UI is an open-source UI component library for building AIGC web apps
1 lines • 6.14 kB
Source Map (JSON)
{"version":3,"file":"useNativeButton.mjs","names":["NATIVE_BUTTON_MAP: Record<string, boolean>"],"sources":["../../src/hooks/useNativeButton.ts"],"sourcesContent":["import { type ReactElement, type ReactNode, isValidElement, useMemo } from 'react';\n\nexport interface UseNativeButtonOptions {\n /**\n * The children element that will be used as the trigger\n */\n children: ReactNode;\n /**\n * User-provided nativeButton prop\n */\n nativeButton?: boolean;\n /**\n * Additional nativeButton from trigger props (for DropdownMenu)\n */\n triggerNativeButton?: boolean;\n}\n\nexport interface UseNativeButtonResult {\n /**\n * Whether the trigger element is a native button\n */\n isNativeButtonTriggerElement: boolean;\n /**\n * The resolved nativeButton value to pass to Base UI components\n */\n resolvedNativeButton: boolean | undefined;\n}\n\n/**\n * Map of component displayNames to their nativeButton values.\n * Components that render native <button> elements should be true,\n * components that render non-button elements should be false.\n */\nconst NATIVE_BUTTON_MAP: Record<string, boolean> = {\n A: false,\n ActionIcon: false,\n ActionIconGroup: false,\n Alert: false,\n Avatar: false,\n AvatarGroup: false,\n Block: false,\n BottomGradientButton: true,\n Burger: false,\n Button: true,\n Center: false,\n Checkbox: false,\n CheckboxGroup: false,\n Collapse: false,\n ColorSwatches: false,\n CopyButton: false,\n DownloadButton: false,\n EditableText: false,\n Empty: false,\n FileTypeIcon: false,\n Flexbox: false,\n FluentEmoji: false,\n GradientButton: true,\n Highlighter: false,\n Hotkey: false,\n Icon: false,\n Image: false,\n Img: false,\n Input: false,\n InputNumber: false,\n InputPassword: false,\n List: false,\n ListItem: false,\n LobeSelect: false,\n LobeSwitch: false,\n Markdown: false,\n MaterialFileTypeIcon: false,\n Segmented: false,\n Skeleton: false,\n SkeletonAvatar: false,\n SkeletonBlock: false,\n SkeletonButton: false,\n SkeletonParagraph: false,\n SkeletonTags: false,\n SkeletonTitle: false,\n Snippet: false,\n Tag: false,\n Text: false,\n TextArea: false,\n ThemeSwitch: false,\n Video: false,\n};\n\n/**\n * Get the displayName of a React component from an element.\n * Handles function components, forwardRef, memo, etc.\n */\nfunction getComponentDisplayName(element: ReactElement): string | undefined {\n const type = element.type;\n\n if (typeof type === 'string') return undefined;\n\n if (typeof type === 'function') {\n return (type as any).displayName || type.name;\n }\n\n if (typeof type === 'object' && type !== null) {\n // Handle forwardRef, memo, etc.\n const displayName =\n (type as any).displayName ||\n (type as any).render?.displayName ||\n (type as any).render?.name ||\n (type as any).type?.displayName ||\n (type as any).type?.name;\n return displayName;\n }\n\n return undefined;\n}\n\n/**\n * Hook to resolve nativeButton prop for Base UI trigger components.\n *\n * When using `render`, Base UI expects the rendered element to be a native <button> by default.\n * If we can infer it's not, we opt out to avoid warnings (users can still override via `nativeButton`).\n */\nexport function useNativeButton({\n children,\n nativeButton,\n triggerNativeButton,\n}: UseNativeButtonOptions): UseNativeButtonResult {\n const isNativeButtonTriggerElement = useMemo(() => {\n if (!isValidElement(children)) return false;\n return typeof children.type === 'string' && children.type === 'button';\n }, [children]);\n\n const resolvedNativeButton = useMemo(() => {\n // User-provided nativeButton takes highest priority\n if (nativeButton !== undefined) return nativeButton;\n // Trigger props nativeButton (for DropdownMenu) takes second priority\n if (triggerNativeButton !== undefined) return triggerNativeButton;\n // If it's a native button element, return true\n if (isNativeButtonTriggerElement) return true;\n // If children is not a valid element, let Base UI decide\n if (!isValidElement(children)) return undefined;\n // If it's a string type but not a button (e.g., 'div'), return false\n if (typeof children.type === 'string') return false;\n\n // Check if it's a known component from the library\n const displayName = getComponentDisplayName(children);\n if (displayName && displayName in NATIVE_BUTTON_MAP) {\n return NATIVE_BUTTON_MAP[displayName];\n }\n\n // For unknown React components, default to false to avoid warnings\n // since most custom components don't render native buttons\n return false;\n }, [children, isNativeButtonTriggerElement, nativeButton, triggerNativeButton]);\n\n return {\n isNativeButtonTriggerElement,\n resolvedNativeButton,\n };\n}\n"],"mappings":";;;;;;;;AAiCA,MAAMA,oBAA6C;CACjD,GAAG;CACH,YAAY;CACZ,iBAAiB;CACjB,OAAO;CACP,QAAQ;CACR,aAAa;CACb,OAAO;CACP,sBAAsB;CACtB,QAAQ;CACR,QAAQ;CACR,QAAQ;CACR,UAAU;CACV,eAAe;CACf,UAAU;CACV,eAAe;CACf,YAAY;CACZ,gBAAgB;CAChB,cAAc;CACd,OAAO;CACP,cAAc;CACd,SAAS;CACT,aAAa;CACb,gBAAgB;CAChB,aAAa;CACb,QAAQ;CACR,MAAM;CACN,OAAO;CACP,KAAK;CACL,OAAO;CACP,aAAa;CACb,eAAe;CACf,MAAM;CACN,UAAU;CACV,YAAY;CACZ,YAAY;CACZ,UAAU;CACV,sBAAsB;CACtB,WAAW;CACX,UAAU;CACV,gBAAgB;CAChB,eAAe;CACf,gBAAgB;CAChB,mBAAmB;CACnB,cAAc;CACd,eAAe;CACf,SAAS;CACT,KAAK;CACL,MAAM;CACN,UAAU;CACV,aAAa;CACb,OAAO;CACR;;;;;AAMD,SAAS,wBAAwB,SAA2C;CAC1E,MAAM,OAAO,QAAQ;AAErB,KAAI,OAAO,SAAS,SAAU,QAAO;AAErC,KAAI,OAAO,SAAS,WAClB,QAAQ,KAAa,eAAe,KAAK;AAG3C,KAAI,OAAO,SAAS,YAAY,SAAS,KAQvC,QALG,KAAa,eACb,KAAa,QAAQ,eACrB,KAAa,QAAQ,QACrB,KAAa,MAAM,eACnB,KAAa,MAAM;;;;;;;;AAa1B,SAAgB,gBAAgB,EAC9B,UACA,cACA,uBACgD;CAChD,MAAM,+BAA+B,cAAc;AACjD,MAAI,CAAC,eAAe,SAAS,CAAE,QAAO;AACtC,SAAO,OAAO,SAAS,SAAS,YAAY,SAAS,SAAS;IAC7D,CAAC,SAAS,CAAC;AAyBd,QAAO;EACL;EACA,sBAzB2B,cAAc;AAEzC,OAAI,iBAAiB,OAAW,QAAO;AAEvC,OAAI,wBAAwB,OAAW,QAAO;AAE9C,OAAI,6BAA8B,QAAO;AAEzC,OAAI,CAAC,eAAe,SAAS,CAAE,QAAO;AAEtC,OAAI,OAAO,SAAS,SAAS,SAAU,QAAO;GAG9C,MAAM,cAAc,wBAAwB,SAAS;AACrD,OAAI,eAAe,eAAe,kBAChC,QAAO,kBAAkB;AAK3B,UAAO;KACN;GAAC;GAAU;GAA8B;GAAc;GAAoB,CAAC;EAK9E"}