@atom-learning/components 9.0.0-beta.2 → 9.0.0-beta.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/badge/Badge.d.ts +6 -1
- package/dist/components/badge/BadgeText.d.ts +5 -0
- package/dist/components/data-table/DataTable.d.ts +6 -1
- package/dist/components/data-table/DataTable.types.d.ts +2 -2
- package/dist/components/data-table/DataTable.types.js.map +1 -1
- package/dist/components/data-table/usePagination.d.ts +1 -1
- package/dist/components/data-table/usePagination.js.map +1 -1
- package/dist/components/dropdown-menu/DropdownMenu.d.ts +1 -1
- package/dist/components/dropdown-menu/DropdownMenuLinkItem.d.ts +1 -1
- package/dist/components/dropdown-menu/DropdownMenuLinkItem.js +4 -1
- package/dist/components/dropdown-menu/DropdownMenuLinkItem.js.map +1 -1
- package/dist/components/empty-state/EmptyState.d.ts +6 -1
- package/dist/components/empty-state/EmptyStateBody.d.ts +5 -0
- package/dist/components/empty-state/EmptyStateImage.d.ts +1 -1
- package/dist/components/file-input/FileInput.d.ts +3 -2
- package/dist/components/file-input/FileInput.js +5 -1
- package/dist/components/file-input/FileInput.js.map +1 -1
- package/dist/components/index.d.ts +3 -0
- package/dist/components/index.js.map +1 -1
- package/dist/components/input/Input.d.ts +6 -1
- package/dist/components/keyboard-shortcut/KeyboardShortcut.d.ts +6 -1
- package/dist/components/keyboard-shortcut/index.d.ts +6 -1
- package/dist/components/navigation/NavigationMenu.d.ts +6 -1
- package/dist/components/navigation/NavigationMenuDropdownItem.d.ts +6 -1
- package/dist/components/navigation-menu-vertical/NavigationMenuVertical.d.ts +6 -1
- package/dist/components/navigation-menu-vertical/NavigationMenuVerticalText.d.ts +5 -0
- package/dist/components/segmented-control/SegmentedControl.d.ts +10 -0
- package/dist/components/segmented-control/SegmentedControlDescription.d.ts +5 -0
- package/dist/components/segmented-control/SegmentedControlHeading.d.ts +5 -0
- package/dist/components/side-bar/SideBar.d.ts +7 -2
- package/dist/components/side-bar/SideBarComponents.d.ts +7 -2
- package/dist/components/stepper/StepperStepLabel.d.ts +5 -0
- package/dist/components/top-bar/TopBar.d.ts +6 -1
- package/dist/components/top-bar/TopBarBrand.d.ts +6 -1
- package/dist/docgen.json +1 -1
- package/dist/index.cjs.js +8 -2
- package/dist/index.cjs.js.map +1 -1
- package/dist/styled.d.ts +12 -2
- package/dist/styled.js.map +1 -1
- package/package.json +1 -1
package/dist/styled.d.ts
CHANGED
|
@@ -44,6 +44,13 @@ export interface PolymorphicComponent<TDefaultElement extends ElementType, OwnPr
|
|
|
44
44
|
(props: DefaultElementProps<TDefaultElement, OwnProps>): React.ReactElement | null;
|
|
45
45
|
displayName?: string;
|
|
46
46
|
__isStyledComponent?: boolean;
|
|
47
|
+
/**
|
|
48
|
+
* Phantom brand (never present at runtime) that carries this component's own
|
|
49
|
+
* props so a wrapping styled() can recover them via {@link BaseOwnProps}.
|
|
50
|
+
* Optional so plain function casts to this interface stay assignable; nominal
|
|
51
|
+
* enough that foreign polymorphic components (Reach, Radix) don't match it.
|
|
52
|
+
*/
|
|
53
|
+
readonly __ownProps?: OwnProps;
|
|
47
54
|
}
|
|
48
55
|
export interface StyledComponent<TDefaultElement extends ElementType, OwnProps> {
|
|
49
56
|
(props: OwnProps & Omit<React.ComponentPropsWithRef<TDefaultElement>, keyof OwnProps | 'as'>): React.ReactElement | null;
|
|
@@ -53,6 +60,9 @@ export interface StyledComponent<TDefaultElement extends ElementType, OwnProps>
|
|
|
53
60
|
type PolymorphicElementProps<E extends ElementType, OwnProps> = OwnProps & {
|
|
54
61
|
as?: E;
|
|
55
62
|
} & Omit<React.ComponentPropsWithRef<E>, keyof OwnProps | 'as'>;
|
|
63
|
+
type BaseOwnProps<T> = T extends {
|
|
64
|
+
readonly __ownProps?: infer OwnProps;
|
|
65
|
+
} ? unknown extends OwnProps ? unknown : OwnProps : unknown;
|
|
56
66
|
/**
|
|
57
67
|
* Extract the props a styled component accepts, optionally for a specific
|
|
58
68
|
* `as` element. `React.ComponentProps<typeof Box>` only describes the default
|
|
@@ -73,6 +83,6 @@ export declare function styled<TElement extends ElementType, V extends VariantCo
|
|
|
73
83
|
}): StyledComponent<TElement, VariantProps<V, false>>;
|
|
74
84
|
export declare function styled<TElement extends ElementType, V extends VariantConfig | undefined = undefined>(el: TElement, styles: StyledConfig<V>, options: {
|
|
75
85
|
enableResponsiveVariants: true;
|
|
76
|
-
}): PolymorphicComponent<TElement, VariantProps<V, true>>;
|
|
77
|
-
export declare function styled<TElement extends ElementType, V extends VariantConfig | undefined = undefined>(el: TElement, styles: StyledConfig<V>): PolymorphicComponent<TElement, VariantProps<V, false>>;
|
|
86
|
+
}): PolymorphicComponent<TElement, VariantProps<V, true> & BaseOwnProps<TElement>>;
|
|
87
|
+
export declare function styled<TElement extends ElementType, V extends VariantConfig | undefined = undefined>(el: TElement, styles: StyledConfig<V>): PolymorphicComponent<TElement, VariantProps<V, false> & BaseOwnProps<TElement>>;
|
|
78
88
|
export {};
|
package/dist/styled.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"styled.js","names":[],"sources":["../src/styled.tsx"],"sourcesContent":["import clsx, { type ClassValue } from 'clsx'\nimport React, { type ElementType, type ReactElement } from 'react'\nimport { extendTailwindMerge } from 'tailwind-merge'\nimport { defaultConfig, tv } from 'tailwind-variants'\n\ndefaultConfig.twMerge = false\n\nconst isArbitraryNumber = (value: string) =>\n /^\\[[\\d.]+\\]$/.test(value) || !Number.isNaN(Number(value))\n\nconst twMerge = extendTailwindMerge<\n 'capsize' | 'capsize-before' | 'capsize-after'\n>({\n extend: {\n classGroups: {\n capsize: [{ capsize: ['none', isArbitraryNumber] }],\n 'capsize-before': [{ 'capsize-before': [isArbitraryNumber] }],\n 'capsize-after': [{ 'capsize-after': [isArbitraryNumber] }]\n },\n conflictingClassGroups: {\n capsize: ['capsize-before', 'capsize-after'],\n 'capsize-before': ['capsize'],\n 'capsize-after': ['capsize']\n }\n }\n})\n\nexport const cn = (...inputs: ClassValue[]) => twMerge(clsx(inputs))\n\ntype Breakpoint = '@initial' | '@sm' | '@md' | '@lg' | '@xl'\n\nexport const Theme = ({\n children,\n theme\n}: React.PropsWithChildren<{ theme?: Record<string, string> }>) => (\n <div className=\"contents\" style={theme}>\n {children}\n </div>\n)\n\nexport const createTheme = (config: Record<string, Record<string, string>>) =>\n Object.fromEntries(\n Object.values(config).flatMap((tokens) =>\n Object.entries(tokens).map(([token, value]) => [`--${token}`, value])\n )\n )\n\n// ---------------------------------------------------------------------------\n// Local typing for styled()\n// ---------------------------------------------------------------------------\n\n// Responsive variant prop: either a single value or a per-breakpoint map\n// Each breakpoint can have a different value from the union type V\ntype ResponsiveVariant<V extends string | number | boolean> =\n | V\n | Partial<Record<Breakpoint, V>>\n\n// Helpers to derive value type from variant config keys\ntype Keys<V> = keyof V\ntype StringKeys<V> = Extract<Keys<V>, string>\ntype NumberKeys<V> = Extract<Keys<V>, number>\n// Booleans are represented as string keys \"true\"/\"false\" in our VariantConfig,\n// so we only need to detect those in StringKeys.\ntype BooleanKeys<V> = Extract<StringKeys<V>, 'true' | 'false'>\n\ntype HasBoolLikeKeys<V> =\n BooleanKeys<V> extends never\n ? Extract<StringKeys<V>, 'true' | 'false'> extends never\n ? false\n : true\n : true\n\n// If a variant's keys are boolean-like, expose the prop as boolean.\n// If it has numeric keys, allow those numbers and their string forms.\n// Otherwise use a string union of the keys.\ntype VariantValueType<V> =\n HasBoolLikeKeys<V> extends true\n ? boolean\n : [NumberKeys<V>] extends [never]\n ? StringKeys<V>\n : NumberKeys<V> | `${NumberKeys<V>}`\n\n// Shape of the `variants` section passed to styled()\ntype VariantConfig = Record<string, Record<string | number, string | string[]>>\n\n// Options for styled() function\ntype StyledOptions = {\n enableResponsiveVariants?: boolean\n enablePolymorphism?: boolean\n}\n\n// Helper to check if responsive variants are enabled\ntype AreResponsiveVariantsEnabled<O> = O extends {\n enableResponsiveVariants: true\n}\n ? true\n : false\n\n// Props derived from a `variants` config\n// If enableResponsiveVariants is true, all variants support responsive values\n// If enableResponsiveVariants is not provided or false, variants do not support responsive values\ntype VariantProps<\n V extends VariantConfig | undefined,\n R extends boolean = false\n> = V extends VariantConfig\n ? R extends true\n ? {\n [K in keyof V]?: ResponsiveVariant<VariantValueType<V[K]>>\n }\n : {\n [K in keyof V]?: VariantValueType<V[K]>\n }\n : unknown\n\n// Typed config for our styled helper.\n// We intentionally *don't* rely on tailwind-variants' TS types here;\n// we only care about enough structure to derive props.\ntype StyledConfig<V extends VariantConfig | undefined = undefined> = {\n base?: string | string[]\n variants?: V\n compoundVariants?: Array<\n {\n class?: string | string[]\n } & (V extends VariantConfig\n ? {\n [K in keyof V]?: VariantValueType<V[K]> | VariantValueType<V[K]>[]\n }\n : Record<string, never>)\n >\n defaultVariants?: V extends VariantConfig\n ? { [K in keyof V]?: VariantValueType<V[K]> }\n : Record<string, never>\n}\n\n// Props of the default element. `as` is typed `never` so JSX usage with `as`\n// can only resolve through the generic polymorphic signature — signatures\n// built from this can never accept calls the generic one would reject.\ntype DefaultElementProps<\n TDefaultElement extends ElementType,\n OwnProps\n> = OwnProps & { as?: never } & Omit<\n React.ComponentPropsWithRef<TDefaultElement>,\n keyof OwnProps | 'as'\n >\n\n// Polymorphic component type: `as` prop narrows accepted props and ref type.\n//\n// The non-generic default-element signature appears twice on purpose. Tooling\n// that inspects call signatures disagrees on which one to read: props-table\n// generation (react-docgen-typescript) reads the FIRST, while type-level\n// inference (React.ComponentProps and friends) reads the LAST. If either\n// tool lands on the generic signature instead, TAs erases to its ElementType\n// constraint and the props collapse to `any` (docgen then also loses every\n// element-specific prop, e.g. Radix's asChild).\nexport interface PolymorphicComponent<\n TDefaultElement extends ElementType,\n OwnProps\n> {\n (\n props: DefaultElementProps<TDefaultElement, OwnProps>\n ): React.ReactElement | null\n <TAs extends ElementType = TDefaultElement>(\n props: OwnProps & { as?: TAs } & Omit<\n React.ComponentPropsWithRef<TAs>,\n keyof OwnProps | 'as'\n >\n ): React.ReactElement | null\n (\n props: DefaultElementProps<TDefaultElement, OwnProps>\n ): React.ReactElement | null\n displayName?: string\n __isStyledComponent?: boolean\n}\n\n// Non-polymorphic component type: no `as` prop. Single concrete call\n// signature, so React.ComponentProps and react-docgen-typescript both read\n// it directly — no sandwich needed.\nexport interface StyledComponent<\n TDefaultElement extends ElementType,\n OwnProps\n> {\n (\n props: OwnProps &\n Omit<React.ComponentPropsWithRef<TDefaultElement>, keyof OwnProps | 'as'>\n ): React.ReactElement | null\n displayName?: string\n __isStyledComponent?: boolean\n}\n\ntype PolymorphicElementProps<E extends ElementType, OwnProps> = OwnProps & {\n as?: E\n} & Omit<React.ComponentPropsWithRef<E>, keyof OwnProps | 'as'>\n\n/**\n * Extract the props a styled component accepts, optionally for a specific\n * `as` element. `React.ComponentProps<typeof Box>` only describes the default\n * element (with `as` unusable); use this to retarget or to build wrappers\n * that re-expose polymorphism:\n *\n * ```tsx\n * type AnchorBoxProps = StyledComponentProps<typeof Box, 'a'> // href, anchor ref…\n * ```\n */\nexport type StyledComponentProps<C, TAs extends ElementType = never> =\n C extends PolymorphicComponent<\n infer TDefault extends ElementType,\n infer OwnProps\n >\n ? PolymorphicElementProps<[TAs] extends [never] ? TDefault : TAs, OwnProps>\n : C extends ElementType\n ? React.ComponentPropsWithRef<[TAs] extends [never] ? C : TAs>\n : never\n\n// Function overloads for better type inference\n\n// enablePolymorphism: false — no `as` prop\nexport function styled<\n TElement extends ElementType,\n V extends VariantConfig | undefined = undefined\n>(\n el: TElement,\n styles: StyledConfig<V>,\n options: { enablePolymorphism: false; enableResponsiveVariants: true }\n): StyledComponent<TElement, VariantProps<V, true>>\n\nexport function styled<\n TElement extends ElementType,\n V extends VariantConfig | undefined = undefined\n>(\n el: TElement,\n styles: StyledConfig<V>,\n options: { enablePolymorphism: false }\n): StyledComponent<TElement, VariantProps<V, false>>\n\n// enablePolymorphism: true (default) — `as` prop available\nexport function styled<\n TElement extends ElementType,\n V extends VariantConfig | undefined = undefined\n>(\n el: TElement,\n styles: StyledConfig<V>,\n options: { enableResponsiveVariants: true }\n): PolymorphicComponent<TElement, VariantProps<V, true>>\n\nexport function styled<\n TElement extends ElementType,\n V extends VariantConfig | undefined = undefined\n>(\n el: TElement,\n styles: StyledConfig<V>\n): PolymorphicComponent<TElement, VariantProps<V, false>>\n\n// Implementation\nexport function styled<\n TElement extends ElementType,\n V extends VariantConfig | undefined = undefined,\n O extends StyledOptions | undefined = undefined\n>(el: TElement, styles: StyledConfig<V>, options?: O) {\n const variantKeys = Object.keys(styles.variants || {})\n const enableResponsiveVariants = options?.enableResponsiveVariants === true\n const tvFn = tv(styles as any)\n\n type ResponsiveVariantsEnabled = AreResponsiveVariantsEnabled<O>\n type VariantPropsType = VariantProps<V, ResponsiveVariantsEnabled>\n type BaseProps = React.ComponentPropsWithRef<TElement>\n // Extract variant keys to omit from BaseProps so variant props override native HTML attributes\n type VariantKeys = V extends VariantConfig ? keyof V : never\n type StyledProps = Omit<BaseProps, VariantKeys> &\n VariantPropsType & {\n as?: ElementType\n ref?: React.Ref<React.ComponentRef<TElement>>\n className?: string\n /** @internal wrapper classes passed between nested styled components */\n __wrapperClasses?: string\n }\n\n const Comp = (props: StyledProps) => {\n const { ref, ...propsWithoutRef } = props\n const additionalStyles = enableResponsiveVariants\n ? variantKeys\n .map((variantKey) => {\n const responsiveVariantConfig:\n | Record<Breakpoint, string | number>\n | undefined = props[variantKey]\n const variantStyles: Record<string, string | string[]> =\n styles.variants![variantKey]\n\n if (\n typeof responsiveVariantConfig === 'object' &&\n responsiveVariantConfig &&\n !Array.isArray(responsiveVariantConfig)\n ) {\n return Object.entries(responsiveVariantConfig).flatMap(\n ([key, val]) => {\n const valStr = String(val)\n const styleArr: string | string[] =\n variantStyles && variantStyles[valStr]\n\n if (styleArr && Array.isArray(styleArr)) {\n return styleArr.flatMap((cls: string) => {\n if (key === '@initial') return cls\n return `${key.replace('@', '')}:${cls}`\n })\n }\n return []\n }\n )\n }\n\n return []\n })\n .flat()\n : []\n\n // Filter out variant props that don't belong to this component before calling tvFn\n // This prevents tailwind-variants from processing props meant for wrapped components\n // Only pass props that are in this component's variant keys\n // For boolean variants, only include them if the value is explicitly true or false (not null/undefined)\n // Note: tailwind-variants treats null as \"no variant\" but undefined/missing as \"apply false variant\"\n // So we need to convert undefined to null for boolean variants to prevent default behavior\n const propsForTv =\n variantKeys.length > 0\n ? Object.fromEntries(\n Object.entries(props as Record<string, unknown>)\n .filter(([key]) => variantKeys.includes(key))\n .map(([key, value]) => {\n // Check if this is a boolean variant (has both 'true' and 'false' keys)\n const variantConfig = styles.variants?.[key]\n if (\n variantConfig &&\n 'true' in variantConfig &&\n 'false' in variantConfig\n ) {\n // For boolean variants, only include if value is explicitly true or false\n // Convert undefined to null to prevent tailwind-variants from applying false variant\n if (value === true || value === false) {\n return [key, value]\n }\n // For null/undefined, pass null to prevent tailwind-variants from applying defaults\n // This ensures that when a boolean prop is explicitly null/undefined, no variant is applied\n return [key, null]\n }\n // For non-boolean variants, pass value as-is (including null/undefined)\n return [key, value]\n })\n )\n : {}\n\n const cls = tvFn(propsForTv)\n\n const filteredProps = Object.fromEntries(\n Object.entries(props).filter(\n ([key]) =>\n !variantKeys.includes(key) &&\n key !== 'as' &&\n key !== '__wrapperClasses'\n )\n )\n\n const mergedClassName = clsx(cls, additionalStyles).trim()\n const propsClassName = props.className\n // Check for wrapper classes passed from a parent styled component\n const wrapperClasses = props.__wrapperClasses\n\n if (\n typeof el === 'string' ||\n typeof el === 'function' ||\n (el && typeof el === 'object')\n ) {\n const elementType = el as ElementType\n\n // If el is a host string ('div', 'span', etc.) we must not pass variant props to the DOM.\n if (typeof el === 'string') {\n const { className: _, ...restFilteredProps } = filteredProps as any\n // Merge order: wrapper classes (lowest priority) < component classes < user's className (highest priority)\n // This ensures variant classes from this component override base classes from wrapper\n // IMPORTANT: When propsClassName exists (could be from asChild), we need to ensure child's classes win\n // over parent classes, but user's className should still have highest priority.\n // Strategy: Only apply special merge when wrapperClasses exist (nested styled component scenario).\n // For regular cases (no wrapperClasses), use standard merge order so user's className has highest priority.\n const finalClassName =\n wrapperClasses && propsClassName\n ? twMerge(mergedClassName, wrapperClasses, propsClassName) // wrapper overrides base, user className wins\n : wrapperClasses\n ? twMerge(mergedClassName, wrapperClasses) // wrapper overrides base\n : propsClassName\n ? (() => {\n // When propsClassName comes from asChild (Radix), we want this component's classes to win\n // When propsClassName is a regular className prop, the user's className should win (highest priority)\n // We can detect asChild scenario by checking if propsClassName contains classes that look like they came from a parent component\n // (e.g., data attribute variants like data-[state=closed]:rounded-sm)\n // If it does, treat it as asChild and let component classes win. Otherwise, let user's className win.\n const hasDataAttributeVariants = propsClassName\n .split(' ')\n .some((cls) => /^data-\\[state=[^\\]]+\\]:/.test(cls))\n\n if (hasDataAttributeVariants) {\n // This is likely from asChild - component's classes should win\n return twMerge(propsClassName, mergedClassName)\n } else {\n // Regular className prop - user's className should win (highest priority)\n return twMerge(mergedClassName, propsClassName)\n }\n })()\n : twMerge(mergedClassName) // Always merge mergedClassName to resolve conflicts within it (e.g., bg-[unset] vs bg-(--base))\n\n return React.createElement(props.as || elementType, {\n ...restFilteredProps,\n ref,\n className: finalClassName\n })\n }\n\n // If el is a function component (including forwardRef), pass ALL props through\n // (the wrapped component may expect variant props), but ensure className and ref are forwarded.\n // We need to pass all props (not filteredProps) because the underlying component may have its own variants\n //\n // For className merging with wrapped styled components:\n // Solution: Pass wrapper's classes via __wrapperClasses prop for styled components to merge correctly.\n // For regular function components, merge wrapper classes with our classes and pass as className.\n // This ensures:\n // - Styled components can merge: wrapper classes < wrapped component classes < user's className\n // - Regular components get merged classes directly and don't receive __wrapperClasses\n // Filter out variant props and __wrapperClasses from props passed to function components\n // This prevents them from ending up in the DOM.\n // Note: We filter out variant props that belong to THIS component. Variant props that belong to\n // the wrapped component will be passed through (they're not in variantKeys), and the wrapped\n // component will filter them if it's a styled component.\n // Note: 'as' prop is filtered from filteredProps to prevent it from going to DOM for string elements,\n // but we add it back for function components since they need it for polymorphism.\n const { className: _, ...restFilteredProps } = filteredProps as any\n const asProp = props.as // Extract 'as' prop separately\n // Note: __wrapperClasses is already filtered out in filteredProps, so restFilteredProps doesn't include it\n\n // For styled components: Pass wrapper classes via __wrapperClasses so they can merge correctly.\n // Styled components extract __wrapperClasses from props (before filteredProps) and filter it in filteredProps.\n // For regular function components: We merge wrapper classes into className, but also pass __wrapperClasses\n // which they may spread. To prevent it in DOM, we need to ensure it's filtered, but we can't control that.\n // However, styled components that wrap regular components will filter __wrapperClasses in their filteredProps.\n if (wrapperClasses) {\n // We have wrapper classes from parent - this is a nested styled component scenario\n // Merge order: wrapper classes (base) < this component's classes (variants) < user's className\n // This ensures variant classes override base classes via twMerge\n // IMPORTANT: When propsClassName exists (could be from asChild), we need to ensure this component's classes win.\n // Strategy: Merge wrapperClasses with propsClassName first, then merge with mergedClassName last.\n // This ensures: wrapperClasses < propsClassName < mergedClassName (this component's classes win)\n // This is critical when propsClassName contains parent classes from asChild merge.\n const finalClassName = propsClassName\n ? twMerge(wrapperClasses, propsClassName, mergedClassName) // This component's classes win by being merged last\n : twMerge(wrapperClasses, mergedClassName)\n\n // Check if the wrapped component is a styled component\n // React.forwardRef components are objects, not functions\n const isStyledComponent =\n (typeof elementType === 'function' ||\n typeof elementType === 'object') &&\n elementType !== null &&\n (elementType as any).__isStyledComponent === true\n\n const propsForComponent: any = {\n ...restFilteredProps, // Base props (filters THIS component's variant props, __wrapperClasses, 'as')\n ...(asProp ? { as: asProp } : {}), // Add 'as' prop back for function components (polymorphic support)\n // Note: We don't add variant props back - they're already filtered by filteredProps.\n ref\n }\n\n if (isStyledComponent) {\n // Wrapped component is a styled component - pass __wrapperClasses so variant classes win\n // IMPORTANT: When propsClassName exists (could be from asChild), it may contain both parent and child classes.\n // We should NOT merge propsClassName with mergedClassName here, because that would remove child classes.\n // Instead, pass propsClassName as-is (or merge only wrapperClasses with mergedClassName) so the child\n // can merge its own classes last. The child will merge: twMerge(__wrapperClasses, propsClassName, child's mergedClassName).\n // This ensures child's classes win by being merged last.\n // Merge wrapperClasses with mergedClassName to create the wrapper classes for the child\n const combinedWrapperClasses = twMerge(\n wrapperClasses,\n mergedClassName\n )\n propsForComponent.__wrapperClasses = combinedWrapperClasses\n propsForComponent.className = propsClassName || undefined\n } else {\n // Wrapped component is not a styled component - merge wrapper classes into className\n // and don't pass __wrapperClasses (it would end up in DOM)\n propsForComponent.className = finalClassName\n }\n return React.createElement(elementType, propsForComponent)\n } else {\n // No wrapper classes from parent - we're top-level\n // For function components: Pass __wrapperClasses so styled components can merge correctly.\n // Styled components extract __wrapperClasses from their props (before filteredProps) and filter it in filteredProps.\n // Regular function components will receive __wrapperClasses but should filter it out themselves.\n // We also merge wrapper classes into className for regular function components.\n // Note: We pass __wrapperClasses in props (not filteredProps) so styled components can access it,\n // but styled components filter it in their filteredProps so it won't go to DOM.\n // Regular function components that spread all props will pass __wrapperClasses to DOM, which is a problem.\n // But we can't distinguish them, so we rely on styled components filtering it.\n // Check if the wrapped component is a styled component\n // elementType is the component itself (e.g., Inner when Outer extends Inner)\n // React.forwardRef components are objects, not functions, but we can still check the flag\n const isStyledComponent =\n (typeof elementType === 'function' ||\n typeof elementType === 'object') &&\n elementType !== null &&\n (elementType as any).__isStyledComponent === true\n\n const propsForComponent: any = {\n ...restFilteredProps, // Filters out __wrapperClasses, variant props, 'as'\n ...(asProp ? { as: asProp } : {}),\n ref\n }\n\n if (isStyledComponent) {\n // Styled component - pass wrapper classes via __wrapperClasses so variant classes can take precedence\n // IMPORTANT: When propsClassName exists, we need to distinguish between:\n // 1. User's className (should win - highest priority)\n // 2. className from asChild/parent component (component's classes should win)\n // We detect asChild by checking for data attribute variants (e.g., data-[state=closed]:rounded-sm)\n const hasDataAttributeVariants = propsClassName\n ? propsClassName\n .split(' ')\n .some((cls) => /^data-\\[state=[^\\]]+\\]:/.test(cls))\n : false\n\n const mergedPropsAndComponent = propsClassName\n ? hasDataAttributeVariants\n ? // This is likely from asChild - component's classes should win\n twMerge(propsClassName, mergedClassName)\n : // Regular user className - user's className should win (highest priority)\n twMerge(mergedClassName, propsClassName)\n : mergedClassName\n propsForComponent.__wrapperClasses = mergedClassName\n propsForComponent.className = mergedPropsAndComponent || undefined\n } else {\n // Regular function component - merge wrapper classes into className\n // Standard merge order: component classes < user's className (highest priority)\n propsForComponent.className = twMerge(mergedClassName, propsClassName)\n }\n return React.createElement(elementType, propsForComponent)\n }\n }\n\n if (React.isValidElement(el)) {\n const element = el as ReactElement<unknown>\n // Merge existing element className, incoming filteredProps.className and our computed class\n const existingClass = (element.props as any).className\n const incomingClass = (filteredProps as any).className\n const finalClassName = cn(\n existingClass,\n incomingClass,\n mergedClassName\n ).trim()\n\n const cloneProps: any = {\n // ...element.props,\n ...filteredProps,\n as: props.as || (element.props as { as?: ElementType }).as,\n className: finalClassName\n }\n\n // Forward the ref if provided\n if (ref) {\n cloneProps.ref = ref\n }\n\n return React.cloneElement(element, cloneProps)\n }\n\n throw Error('Something is wrong')\n }\n\n // Mark the component as a styled component so we can detect it later\n ;(Comp as any).__isStyledComponent = true\n\n // Name the component for DevTools and error component stacks — without\n // this every styled component reads as the inner function name, \"Comp\"\n const baseName =\n typeof el === 'string'\n ? el\n : (el as any).displayName || (el as any).name || 'Component'\n Comp.displayName = baseName.startsWith('styled.')\n ? baseName\n : `styled.${baseName}`\n\n return Comp\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"styled.js","names":[],"sources":["../src/styled.tsx"],"sourcesContent":["import clsx, { type ClassValue } from 'clsx'\nimport React, { type ElementType, type ReactElement } from 'react'\nimport { extendTailwindMerge } from 'tailwind-merge'\nimport { defaultConfig, tv } from 'tailwind-variants'\n\ndefaultConfig.twMerge = false\n\nconst isArbitraryNumber = (value: string) =>\n /^\\[[\\d.]+\\]$/.test(value) || !Number.isNaN(Number(value))\n\nconst twMerge = extendTailwindMerge<\n 'capsize' | 'capsize-before' | 'capsize-after'\n>({\n extend: {\n classGroups: {\n capsize: [{ capsize: ['none', isArbitraryNumber] }],\n 'capsize-before': [{ 'capsize-before': [isArbitraryNumber] }],\n 'capsize-after': [{ 'capsize-after': [isArbitraryNumber] }]\n },\n conflictingClassGroups: {\n capsize: ['capsize-before', 'capsize-after'],\n 'capsize-before': ['capsize'],\n 'capsize-after': ['capsize']\n }\n }\n})\n\nexport const cn = (...inputs: ClassValue[]) => twMerge(clsx(inputs))\n\ntype Breakpoint = '@initial' | '@sm' | '@md' | '@lg' | '@xl'\n\nexport const Theme = ({\n children,\n theme\n}: React.PropsWithChildren<{ theme?: Record<string, string> }>) => (\n <div className=\"contents\" style={theme}>\n {children}\n </div>\n)\n\nexport const createTheme = (config: Record<string, Record<string, string>>) =>\n Object.fromEntries(\n Object.values(config).flatMap((tokens) =>\n Object.entries(tokens).map(([token, value]) => [`--${token}`, value])\n )\n )\n\n// ---------------------------------------------------------------------------\n// Local typing for styled()\n// ---------------------------------------------------------------------------\n\n// Responsive variant prop: either a single value or a per-breakpoint map\n// Each breakpoint can have a different value from the union type V\ntype ResponsiveVariant<V extends string | number | boolean> =\n | V\n | Partial<Record<Breakpoint, V>>\n\n// Helpers to derive value type from variant config keys\ntype Keys<V> = keyof V\ntype StringKeys<V> = Extract<Keys<V>, string>\ntype NumberKeys<V> = Extract<Keys<V>, number>\n// Booleans are represented as string keys \"true\"/\"false\" in our VariantConfig,\n// so we only need to detect those in StringKeys.\ntype BooleanKeys<V> = Extract<StringKeys<V>, 'true' | 'false'>\n\ntype HasBoolLikeKeys<V> =\n BooleanKeys<V> extends never\n ? Extract<StringKeys<V>, 'true' | 'false'> extends never\n ? false\n : true\n : true\n\n// If a variant's keys are boolean-like, expose the prop as boolean.\n// If it has numeric keys, allow those numbers and their string forms.\n// Otherwise use a string union of the keys.\ntype VariantValueType<V> =\n HasBoolLikeKeys<V> extends true\n ? boolean\n : [NumberKeys<V>] extends [never]\n ? StringKeys<V>\n : NumberKeys<V> | `${NumberKeys<V>}`\n\n// Shape of the `variants` section passed to styled()\ntype VariantConfig = Record<string, Record<string | number, string | string[]>>\n\n// Options for styled() function\ntype StyledOptions = {\n enableResponsiveVariants?: boolean\n enablePolymorphism?: boolean\n}\n\n// Helper to check if responsive variants are enabled\ntype AreResponsiveVariantsEnabled<O> = O extends {\n enableResponsiveVariants: true\n}\n ? true\n : false\n\n// Props derived from a `variants` config\n// If enableResponsiveVariants is true, all variants support responsive values\n// If enableResponsiveVariants is not provided or false, variants do not support responsive values\ntype VariantProps<\n V extends VariantConfig | undefined,\n R extends boolean = false\n> = V extends VariantConfig\n ? R extends true\n ? {\n [K in keyof V]?: ResponsiveVariant<VariantValueType<V[K]>>\n }\n : {\n [K in keyof V]?: VariantValueType<V[K]>\n }\n : unknown\n\n// Typed config for our styled helper.\n// We intentionally *don't* rely on tailwind-variants' TS types here;\n// we only care about enough structure to derive props.\ntype StyledConfig<V extends VariantConfig | undefined = undefined> = {\n base?: string | string[]\n variants?: V\n compoundVariants?: Array<\n {\n class?: string | string[]\n } & (V extends VariantConfig\n ? {\n [K in keyof V]?: VariantValueType<V[K]> | VariantValueType<V[K]>[]\n }\n : Record<string, never>)\n >\n defaultVariants?: V extends VariantConfig\n ? { [K in keyof V]?: VariantValueType<V[K]> }\n : Record<string, never>\n}\n\n// Props of the default element. `as` is typed `never` so JSX usage with `as`\n// can only resolve through the generic polymorphic signature — signatures\n// built from this can never accept calls the generic one would reject.\ntype DefaultElementProps<\n TDefaultElement extends ElementType,\n OwnProps\n> = OwnProps & { as?: never } & Omit<\n React.ComponentPropsWithRef<TDefaultElement>,\n keyof OwnProps | 'as'\n >\n\n// Polymorphic component type: `as` prop narrows accepted props and ref type.\n//\n// The non-generic default-element signature appears twice on purpose. Tooling\n// that inspects call signatures disagrees on which one to read: props-table\n// generation (react-docgen-typescript) reads the FIRST, while type-level\n// inference (React.ComponentProps and friends) reads the LAST. If either\n// tool lands on the generic signature instead, TAs erases to its ElementType\n// constraint and the props collapse to `any` (docgen then also loses every\n// element-specific prop, e.g. Radix's asChild).\nexport interface PolymorphicComponent<\n TDefaultElement extends ElementType,\n OwnProps\n> {\n (\n props: DefaultElementProps<TDefaultElement, OwnProps>\n ): React.ReactElement | null\n <TAs extends ElementType = TDefaultElement>(\n props: OwnProps & { as?: TAs } & Omit<\n React.ComponentPropsWithRef<TAs>,\n keyof OwnProps | 'as'\n >\n ): React.ReactElement | null\n (\n props: DefaultElementProps<TDefaultElement, OwnProps>\n ): React.ReactElement | null\n displayName?: string\n __isStyledComponent?: boolean\n /**\n * Phantom brand (never present at runtime) that carries this component's own\n * props so a wrapping styled() can recover them via {@link BaseOwnProps}.\n * Optional so plain function casts to this interface stay assignable; nominal\n * enough that foreign polymorphic components (Reach, Radix) don't match it.\n */\n readonly __ownProps?: OwnProps\n}\n\n// Non-polymorphic component type: no `as` prop. Single concrete call\n// signature, so React.ComponentProps and react-docgen-typescript both read\n// it directly — no sandwich needed.\nexport interface StyledComponent<\n TDefaultElement extends ElementType,\n OwnProps\n> {\n (\n props: OwnProps &\n Omit<React.ComponentPropsWithRef<TDefaultElement>, keyof OwnProps | 'as'>\n ): React.ReactElement | null\n displayName?: string\n __isStyledComponent?: boolean\n}\n\ntype PolymorphicElementProps<E extends ElementType, OwnProps> = OwnProps & {\n as?: E\n} & Omit<React.ComponentPropsWithRef<E>, keyof OwnProps | 'as'>\n\n// When styled() wraps one of our own polymorphic components (rather than a host\n// string), that component's own props (variants + custom props) are part of the\n// styled component's identity and must persist regardless of `as`. Without this\n// they live only in the default element's `ComponentPropsWithRef` and get\n// dropped by the generic `as` signature, which keys element props off the `as`\n// target. Recover them via the `__ownProps` phantom brand — matching on that\n// field (rather than the call signatures) means foreign polymorphic components\n// (Reach, Radix) and host strings don't match and instead contribute `unknown`,\n// the intersection identity, so their attributes still swap with `as`.\ntype BaseOwnProps<T> = T extends { readonly __ownProps?: infer OwnProps }\n ? unknown extends OwnProps\n ? unknown\n : OwnProps\n : unknown\n\n/**\n * Extract the props a styled component accepts, optionally for a specific\n * `as` element. `React.ComponentProps<typeof Box>` only describes the default\n * element (with `as` unusable); use this to retarget or to build wrappers\n * that re-expose polymorphism:\n *\n * ```tsx\n * type AnchorBoxProps = StyledComponentProps<typeof Box, 'a'> // href, anchor ref…\n * ```\n */\nexport type StyledComponentProps<C, TAs extends ElementType = never> =\n C extends PolymorphicComponent<\n infer TDefault extends ElementType,\n infer OwnProps\n >\n ? PolymorphicElementProps<[TAs] extends [never] ? TDefault : TAs, OwnProps>\n : C extends ElementType\n ? React.ComponentPropsWithRef<[TAs] extends [never] ? C : TAs>\n : never\n\n// Function overloads for better type inference\n\n// enablePolymorphism: false — no `as` prop\nexport function styled<\n TElement extends ElementType,\n V extends VariantConfig | undefined = undefined\n>(\n el: TElement,\n styles: StyledConfig<V>,\n options: { enablePolymorphism: false; enableResponsiveVariants: true }\n): StyledComponent<TElement, VariantProps<V, true>>\n\nexport function styled<\n TElement extends ElementType,\n V extends VariantConfig | undefined = undefined\n>(\n el: TElement,\n styles: StyledConfig<V>,\n options: { enablePolymorphism: false }\n): StyledComponent<TElement, VariantProps<V, false>>\n\n// enablePolymorphism: true (default) — `as` prop available\nexport function styled<\n TElement extends ElementType,\n V extends VariantConfig | undefined = undefined\n>(\n el: TElement,\n styles: StyledConfig<V>,\n options: { enableResponsiveVariants: true }\n): PolymorphicComponent<\n TElement,\n VariantProps<V, true> & BaseOwnProps<TElement>\n>\n\nexport function styled<\n TElement extends ElementType,\n V extends VariantConfig | undefined = undefined\n>(\n el: TElement,\n styles: StyledConfig<V>\n): PolymorphicComponent<\n TElement,\n VariantProps<V, false> & BaseOwnProps<TElement>\n>\n\n// Implementation\nexport function styled<\n TElement extends ElementType,\n V extends VariantConfig | undefined = undefined,\n O extends StyledOptions | undefined = undefined\n>(el: TElement, styles: StyledConfig<V>, options?: O) {\n const variantKeys = Object.keys(styles.variants || {})\n const enableResponsiveVariants = options?.enableResponsiveVariants === true\n const tvFn = tv(styles as any)\n\n type ResponsiveVariantsEnabled = AreResponsiveVariantsEnabled<O>\n type VariantPropsType = VariantProps<V, ResponsiveVariantsEnabled>\n type BaseProps = React.ComponentPropsWithRef<TElement>\n // Extract variant keys to omit from BaseProps so variant props override native HTML attributes\n type VariantKeys = V extends VariantConfig ? keyof V : never\n type StyledProps = Omit<BaseProps, VariantKeys> &\n VariantPropsType & {\n as?: ElementType\n ref?: React.Ref<React.ComponentRef<TElement>>\n className?: string\n /** @internal wrapper classes passed between nested styled components */\n __wrapperClasses?: string\n }\n\n const Comp = (props: StyledProps) => {\n const { ref, ...propsWithoutRef } = props\n const additionalStyles = enableResponsiveVariants\n ? variantKeys\n .map((variantKey) => {\n const responsiveVariantConfig:\n | Record<Breakpoint, string | number>\n | undefined = props[variantKey]\n const variantStyles: Record<string, string | string[]> =\n styles.variants![variantKey]\n\n if (\n typeof responsiveVariantConfig === 'object' &&\n responsiveVariantConfig &&\n !Array.isArray(responsiveVariantConfig)\n ) {\n return Object.entries(responsiveVariantConfig).flatMap(\n ([key, val]) => {\n const valStr = String(val)\n const styleArr: string | string[] =\n variantStyles && variantStyles[valStr]\n\n if (styleArr && Array.isArray(styleArr)) {\n return styleArr.flatMap((cls: string) => {\n if (key === '@initial') return cls\n return `${key.replace('@', '')}:${cls}`\n })\n }\n return []\n }\n )\n }\n\n return []\n })\n .flat()\n : []\n\n // Filter out variant props that don't belong to this component before calling tvFn\n // This prevents tailwind-variants from processing props meant for wrapped components\n // Only pass props that are in this component's variant keys\n // For boolean variants, only include them if the value is explicitly true or false (not null/undefined)\n // Note: tailwind-variants treats null as \"no variant\" but undefined/missing as \"apply false variant\"\n // So we need to convert undefined to null for boolean variants to prevent default behavior\n const propsForTv =\n variantKeys.length > 0\n ? Object.fromEntries(\n Object.entries(props as Record<string, unknown>)\n .filter(([key]) => variantKeys.includes(key))\n .map(([key, value]) => {\n // Check if this is a boolean variant (has both 'true' and 'false' keys)\n const variantConfig = styles.variants?.[key]\n if (\n variantConfig &&\n 'true' in variantConfig &&\n 'false' in variantConfig\n ) {\n // For boolean variants, only include if value is explicitly true or false\n // Convert undefined to null to prevent tailwind-variants from applying false variant\n if (value === true || value === false) {\n return [key, value]\n }\n // For null/undefined, pass null to prevent tailwind-variants from applying defaults\n // This ensures that when a boolean prop is explicitly null/undefined, no variant is applied\n return [key, null]\n }\n // For non-boolean variants, pass value as-is (including null/undefined)\n return [key, value]\n })\n )\n : {}\n\n const cls = tvFn(propsForTv)\n\n const filteredProps = Object.fromEntries(\n Object.entries(props).filter(\n ([key]) =>\n !variantKeys.includes(key) &&\n key !== 'as' &&\n key !== '__wrapperClasses'\n )\n )\n\n const mergedClassName = clsx(cls, additionalStyles).trim()\n const propsClassName = props.className\n // Check for wrapper classes passed from a parent styled component\n const wrapperClasses = props.__wrapperClasses\n\n if (\n typeof el === 'string' ||\n typeof el === 'function' ||\n (el && typeof el === 'object')\n ) {\n const elementType = el as ElementType\n\n // If el is a host string ('div', 'span', etc.) we must not pass variant props to the DOM.\n if (typeof el === 'string') {\n const { className: _, ...restFilteredProps } = filteredProps as any\n // Merge order: wrapper classes (lowest priority) < component classes < user's className (highest priority)\n // This ensures variant classes from this component override base classes from wrapper\n // IMPORTANT: When propsClassName exists (could be from asChild), we need to ensure child's classes win\n // over parent classes, but user's className should still have highest priority.\n // Strategy: Only apply special merge when wrapperClasses exist (nested styled component scenario).\n // For regular cases (no wrapperClasses), use standard merge order so user's className has highest priority.\n const finalClassName =\n wrapperClasses && propsClassName\n ? twMerge(mergedClassName, wrapperClasses, propsClassName) // wrapper overrides base, user className wins\n : wrapperClasses\n ? twMerge(mergedClassName, wrapperClasses) // wrapper overrides base\n : propsClassName\n ? (() => {\n // When propsClassName comes from asChild (Radix), we want this component's classes to win\n // When propsClassName is a regular className prop, the user's className should win (highest priority)\n // We can detect asChild scenario by checking if propsClassName contains classes that look like they came from a parent component\n // (e.g., data attribute variants like data-[state=closed]:rounded-sm)\n // If it does, treat it as asChild and let component classes win. Otherwise, let user's className win.\n const hasDataAttributeVariants = propsClassName\n .split(' ')\n .some((cls) => /^data-\\[state=[^\\]]+\\]:/.test(cls))\n\n if (hasDataAttributeVariants) {\n // This is likely from asChild - component's classes should win\n return twMerge(propsClassName, mergedClassName)\n } else {\n // Regular className prop - user's className should win (highest priority)\n return twMerge(mergedClassName, propsClassName)\n }\n })()\n : twMerge(mergedClassName) // Always merge mergedClassName to resolve conflicts within it (e.g., bg-[unset] vs bg-(--base))\n\n return React.createElement(props.as || elementType, {\n ...restFilteredProps,\n ref,\n className: finalClassName\n })\n }\n\n // If el is a function component (including forwardRef), pass ALL props through\n // (the wrapped component may expect variant props), but ensure className and ref are forwarded.\n // We need to pass all props (not filteredProps) because the underlying component may have its own variants\n //\n // For className merging with wrapped styled components:\n // Solution: Pass wrapper's classes via __wrapperClasses prop for styled components to merge correctly.\n // For regular function components, merge wrapper classes with our classes and pass as className.\n // This ensures:\n // - Styled components can merge: wrapper classes < wrapped component classes < user's className\n // - Regular components get merged classes directly and don't receive __wrapperClasses\n // Filter out variant props and __wrapperClasses from props passed to function components\n // This prevents them from ending up in the DOM.\n // Note: We filter out variant props that belong to THIS component. Variant props that belong to\n // the wrapped component will be passed through (they're not in variantKeys), and the wrapped\n // component will filter them if it's a styled component.\n // Note: 'as' prop is filtered from filteredProps to prevent it from going to DOM for string elements,\n // but we add it back for function components since they need it for polymorphism.\n const { className: _, ...restFilteredProps } = filteredProps as any\n const asProp = props.as // Extract 'as' prop separately\n // Note: __wrapperClasses is already filtered out in filteredProps, so restFilteredProps doesn't include it\n\n // For styled components: Pass wrapper classes via __wrapperClasses so they can merge correctly.\n // Styled components extract __wrapperClasses from props (before filteredProps) and filter it in filteredProps.\n // For regular function components: We merge wrapper classes into className, but also pass __wrapperClasses\n // which they may spread. To prevent it in DOM, we need to ensure it's filtered, but we can't control that.\n // However, styled components that wrap regular components will filter __wrapperClasses in their filteredProps.\n if (wrapperClasses) {\n // We have wrapper classes from parent - this is a nested styled component scenario\n // Merge order: wrapper classes (base) < this component's classes (variants) < user's className\n // This ensures variant classes override base classes via twMerge\n // IMPORTANT: When propsClassName exists (could be from asChild), we need to ensure this component's classes win.\n // Strategy: Merge wrapperClasses with propsClassName first, then merge with mergedClassName last.\n // This ensures: wrapperClasses < propsClassName < mergedClassName (this component's classes win)\n // This is critical when propsClassName contains parent classes from asChild merge.\n const finalClassName = propsClassName\n ? twMerge(wrapperClasses, propsClassName, mergedClassName) // This component's classes win by being merged last\n : twMerge(wrapperClasses, mergedClassName)\n\n // Check if the wrapped component is a styled component\n // React.forwardRef components are objects, not functions\n const isStyledComponent =\n (typeof elementType === 'function' ||\n typeof elementType === 'object') &&\n elementType !== null &&\n (elementType as any).__isStyledComponent === true\n\n const propsForComponent: any = {\n ...restFilteredProps, // Base props (filters THIS component's variant props, __wrapperClasses, 'as')\n ...(asProp ? { as: asProp } : {}), // Add 'as' prop back for function components (polymorphic support)\n // Note: We don't add variant props back - they're already filtered by filteredProps.\n ref\n }\n\n if (isStyledComponent) {\n // Wrapped component is a styled component - pass __wrapperClasses so variant classes win\n // IMPORTANT: When propsClassName exists (could be from asChild), it may contain both parent and child classes.\n // We should NOT merge propsClassName with mergedClassName here, because that would remove child classes.\n // Instead, pass propsClassName as-is (or merge only wrapperClasses with mergedClassName) so the child\n // can merge its own classes last. The child will merge: twMerge(__wrapperClasses, propsClassName, child's mergedClassName).\n // This ensures child's classes win by being merged last.\n // Merge wrapperClasses with mergedClassName to create the wrapper classes for the child\n const combinedWrapperClasses = twMerge(\n wrapperClasses,\n mergedClassName\n )\n propsForComponent.__wrapperClasses = combinedWrapperClasses\n propsForComponent.className = propsClassName || undefined\n } else {\n // Wrapped component is not a styled component - merge wrapper classes into className\n // and don't pass __wrapperClasses (it would end up in DOM)\n propsForComponent.className = finalClassName\n }\n return React.createElement(elementType, propsForComponent)\n } else {\n // No wrapper classes from parent - we're top-level\n // For function components: Pass __wrapperClasses so styled components can merge correctly.\n // Styled components extract __wrapperClasses from their props (before filteredProps) and filter it in filteredProps.\n // Regular function components will receive __wrapperClasses but should filter it out themselves.\n // We also merge wrapper classes into className for regular function components.\n // Note: We pass __wrapperClasses in props (not filteredProps) so styled components can access it,\n // but styled components filter it in their filteredProps so it won't go to DOM.\n // Regular function components that spread all props will pass __wrapperClasses to DOM, which is a problem.\n // But we can't distinguish them, so we rely on styled components filtering it.\n // Check if the wrapped component is a styled component\n // elementType is the component itself (e.g., Inner when Outer extends Inner)\n // React.forwardRef components are objects, not functions, but we can still check the flag\n const isStyledComponent =\n (typeof elementType === 'function' ||\n typeof elementType === 'object') &&\n elementType !== null &&\n (elementType as any).__isStyledComponent === true\n\n const propsForComponent: any = {\n ...restFilteredProps, // Filters out __wrapperClasses, variant props, 'as'\n ...(asProp ? { as: asProp } : {}),\n ref\n }\n\n if (isStyledComponent) {\n // Styled component - pass wrapper classes via __wrapperClasses so variant classes can take precedence\n // IMPORTANT: When propsClassName exists, we need to distinguish between:\n // 1. User's className (should win - highest priority)\n // 2. className from asChild/parent component (component's classes should win)\n // We detect asChild by checking for data attribute variants (e.g., data-[state=closed]:rounded-sm)\n const hasDataAttributeVariants = propsClassName\n ? propsClassName\n .split(' ')\n .some((cls) => /^data-\\[state=[^\\]]+\\]:/.test(cls))\n : false\n\n const mergedPropsAndComponent = propsClassName\n ? hasDataAttributeVariants\n ? // This is likely from asChild - component's classes should win\n twMerge(propsClassName, mergedClassName)\n : // Regular user className - user's className should win (highest priority)\n twMerge(mergedClassName, propsClassName)\n : mergedClassName\n propsForComponent.__wrapperClasses = mergedClassName\n propsForComponent.className = mergedPropsAndComponent || undefined\n } else {\n // Regular function component - merge wrapper classes into className\n // Standard merge order: component classes < user's className (highest priority)\n propsForComponent.className = twMerge(mergedClassName, propsClassName)\n }\n return React.createElement(elementType, propsForComponent)\n }\n }\n\n if (React.isValidElement(el)) {\n const element = el as ReactElement<unknown>\n // Merge existing element className, incoming filteredProps.className and our computed class\n const existingClass = (element.props as any).className\n const incomingClass = (filteredProps as any).className\n const finalClassName = cn(\n existingClass,\n incomingClass,\n mergedClassName\n ).trim()\n\n const cloneProps: any = {\n // ...element.props,\n ...filteredProps,\n as: props.as || (element.props as { as?: ElementType }).as,\n className: finalClassName\n }\n\n // Forward the ref if provided\n if (ref) {\n cloneProps.ref = ref\n }\n\n return React.cloneElement(element, cloneProps)\n }\n\n throw Error('Something is wrong')\n }\n\n // Mark the component as a styled component so we can detect it later\n ;(Comp as any).__isStyledComponent = true\n\n // Name the component for DevTools and error component stacks — without\n // this every styled component reads as the inner function name, \"Comp\"\n const baseName =\n typeof el === 'string'\n ? el\n : (el as any).displayName || (el as any).name || 'Component'\n Comp.displayName = baseName.startsWith('styled.')\n ? baseName\n : `styled.${baseName}`\n\n return Comp\n}\n"],"mappings":";;;;;;AAKA,cAAc,UAAU;AAExB,IAAM,qBAAqB,UACzB,eAAe,KAAK,KAAK,KAAK,CAAC,OAAO,MAAM,OAAO,KAAK,CAAC;AAE3D,IAAM,UAAU,oBAEd,EACA,QAAQ;CACN,aAAa;EACX,SAAS,CAAC,EAAE,SAAS,CAAC,QAAQ,iBAAiB,EAAE,CAAC;EAClD,kBAAkB,CAAC,EAAE,kBAAkB,CAAC,iBAAiB,EAAE,CAAC;EAC5D,iBAAiB,CAAC,EAAE,iBAAiB,CAAC,iBAAiB,EAAE,CAAC;CAC5D;CACA,wBAAwB;EACtB,SAAS,CAAC,kBAAkB,eAAe;EAC3C,kBAAkB,CAAC,SAAS;EAC5B,iBAAiB,CAAC,SAAS;CAC7B;AACF,EACF,CAAC;AAED,IAAa,MAAM,GAAG,WAAyB,QAAQ,KAAK,MAAM,CAAC;AAInE,IAAa,SAAS,EACpB,UACA,YAEA,oBAAC,OAAD;CAAK,WAAU;CAAW,OAAO;CAC9B;AACE,CAAA;AAGP,IAAa,eAAe,WAC1B,OAAO,YACL,OAAO,OAAO,MAAM,CAAC,CAAC,SAAS,WAC7B,OAAO,QAAQ,MAAM,CAAC,CAAC,KAAK,CAAC,OAAO,WAAW,CAAC,KAAK,SAAS,KAAK,CAAC,CACtE,CACF;AA4OF,SAAgB,OAId,IAAc,QAAyB,SAAa;CACpD,MAAM,cAAc,OAAO,KAAK,OAAO,YAAY,CAAC,CAAC;CACrD,MAAM,2BAA2B,SAAS,6BAA6B;CACvE,MAAM,OAAO,GAAG,MAAa;CAgB7B,MAAM,QAAQ,UAAuB;EACnC,MAAM,EAAE,KAAK,GAAG,oBAAoB;EACpC,MAAM,mBAAmB,2BACrB,YACG,KAAK,eAAe;GACnB,MAAM,0BAEU,MAAM;GACtB,MAAM,gBACJ,OAAO,SAAU;GAEnB,IACE,OAAO,4BAA4B,YACnC,2BACA,CAAC,MAAM,QAAQ,uBAAuB,GAEtC,OAAO,OAAO,QAAQ,uBAAuB,CAAC,CAAC,SAC5C,CAAC,KAAK,SAAS;IAEd,MAAM,WACJ,iBAAiB,cAFJ,OAAO,GAEW;IAEjC,IAAI,YAAY,MAAM,QAAQ,QAAQ,GACpC,OAAO,SAAS,SAAS,QAAgB;KACvC,IAAI,QAAQ,YAAY,OAAO;KAC/B,OAAO,GAAG,IAAI,QAAQ,KAAK,EAAE,EAAE,GAAG;IACpC,CAAC;IAEH,OAAO,CAAC;GACV,CACF;GAGF,OAAO,CAAC;EACV,CAAC,CAAC,CACD,KAAK,IACR,CAAC;EAoCL,MAAM,MAAM,KA3BV,YAAY,SAAS,IACjB,OAAO,YACL,OAAO,QAAQ,KAAgC,CAAC,CAC7C,QAAQ,CAAC,SAAS,YAAY,SAAS,GAAG,CAAC,CAAC,CAC5C,KAAK,CAAC,KAAK,WAAW;GAErB,MAAM,gBAAgB,OAAO,WAAW;GACxC,IACE,iBACA,UAAU,iBACV,WAAW,eACX;IAGA,IAAI,UAAU,QAAQ,UAAU,OAC9B,OAAO,CAAC,KAAK,KAAK;IAIpB,OAAO,CAAC,KAAK,IAAI;GACnB;GAEA,OAAO,CAAC,KAAK,KAAK;EACpB,CAAC,CACL,IACA,CAAC,CAEoB;EAE3B,MAAM,gBAAgB,OAAO,YAC3B,OAAO,QAAQ,KAAK,CAAC,CAAC,QACnB,CAAC,SACA,CAAC,YAAY,SAAS,GAAG,KACzB,QAAQ,QACR,QAAQ,kBACZ,CACF;EAEA,MAAM,kBAAkB,KAAK,KAAK,gBAAgB,CAAC,CAAC,KAAK;EACzD,MAAM,iBAAiB,MAAM;EAE7B,MAAM,iBAAiB,MAAM;EAE7B,IACE,OAAO,OAAO,YACd,OAAO,OAAO,cACb,MAAM,OAAO,OAAO,UACrB;GACA,MAAM,cAAc;GAGpB,IAAI,OAAO,OAAO,UAAU;IAC1B,MAAM,EAAE,WAAW,GAAG,GAAG,sBAAsB;IAO/C,MAAM,iBACJ,kBAAkB,iBACd,QAAQ,iBAAiB,gBAAgB,cAAc,IACvD,iBACE,QAAQ,iBAAiB,cAAc,IACvC,wBACS;KAUL,IAJiC,eAC9B,MAAM,GAAG,CAAC,CACV,MAAM,QAAQ,0BAA0B,KAAK,GAAG,CAE/C,GAEF,OAAO,QAAQ,gBAAgB,eAAe;UAG9C,OAAO,QAAQ,iBAAiB,cAAc;IAElD,EAAA,CAAG,IACH,QAAQ,eAAe;IAEjC,OAAO,MAAM,cAAc,MAAM,MAAM,aAAa;KAClD,GAAG;KACH;KACA,WAAW;IACb,CAAC;GACH;GAmBA,MAAM,EAAE,WAAW,GAAG,GAAG,sBAAsB;GAC/C,MAAM,SAAS,MAAM;GAQrB,IAAI,gBAAgB;IAQlB,MAAM,iBAAiB,iBACnB,QAAQ,gBAAgB,gBAAgB,eAAe,IACvD,QAAQ,gBAAgB,eAAe;IAI3C,MAAM,qBACH,OAAO,gBAAgB,cACtB,OAAO,gBAAgB,aACzB,gBAAgB,QACf,YAAoB,wBAAwB;IAE/C,MAAM,oBAAyB;KAC7B,GAAG;KACH,GAAI,SAAS,EAAE,IAAI,OAAO,IAAI,CAAC;KAE/B;IACF;IAEA,IAAI,mBAAmB;KAYrB,kBAAkB,mBAJa,QAC7B,gBACA,eAEmC;KACrC,kBAAkB,YAAY,kBAAkB,KAAA;IAClD,OAGE,kBAAkB,YAAY;IAEhC,OAAO,MAAM,cAAc,aAAa,iBAAiB;GAC3D,OAAO;IAaL,MAAM,qBACH,OAAO,gBAAgB,cACtB,OAAO,gBAAgB,aACzB,gBAAgB,QACf,YAAoB,wBAAwB;IAE/C,MAAM,oBAAyB;KAC7B,GAAG;KACH,GAAI,SAAS,EAAE,IAAI,OAAO,IAAI,CAAC;KAC/B;IACF;IAEA,IAAI,mBAAmB;KAMrB,MAAM,2BAA2B,iBAC7B,eACG,MAAM,GAAG,CAAC,CACV,MAAM,QAAQ,0BAA0B,KAAK,GAAG,CAAC,IACpD;KAEJ,MAAM,0BAA0B,iBAC5B,2BAEE,QAAQ,gBAAgB,eAAe,IAEvC,QAAQ,iBAAiB,cAAc,IACzC;KACJ,kBAAkB,mBAAmB;KACrC,kBAAkB,YAAY,2BAA2B,KAAA;IAC3D,OAGE,kBAAkB,YAAY,QAAQ,iBAAiB,cAAc;IAEvE,OAAO,MAAM,cAAc,aAAa,iBAAiB;GAC3D;EACF;EAEA,IAAI,MAAM,eAAe,EAAE,GAAG;GAC5B,MAAM,UAAU;GAEhB,MAAM,gBAAiB,QAAQ,MAAc;GAC7C,MAAM,gBAAiB,cAAsB;GAC7C,MAAM,iBAAiB,GACrB,eACA,eACA,eACF,CAAC,CAAC,KAAK;GAEP,MAAM,aAAkB;IAEtB,GAAG;IACH,IAAI,MAAM,MAAO,QAAQ,MAA+B;IACxD,WAAW;GACb;GAGA,IAAI,KACF,WAAW,MAAM;GAGnB,OAAO,MAAM,aAAa,SAAS,UAAU;EAC/C;EAEA,MAAM,MAAM,oBAAoB;CAClC;CAGC,KAAc,sBAAsB;CAIrC,MAAM,WACJ,OAAO,OAAO,WACV,KACC,GAAW,eAAgB,GAAW,QAAQ;CACrD,KAAK,cAAc,SAAS,WAAW,SAAS,IAC5C,WACA,UAAU;CAEd,OAAO;AACT"}
|