mado-ui 0.3.0 → 0.3.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/css/index.css CHANGED
@@ -451,6 +451,9 @@
451
451
  .min-w-0 {
452
452
  min-width: calc(var(--spacing) * 0);
453
453
  }
454
+ .min-w-64 {
455
+ min-width: calc(var(--spacing) * 64);
456
+ }
454
457
  .min-w-fit {
455
458
  min-width: fit-content;
456
459
  }
@@ -1278,18 +1281,18 @@
1278
1281
  transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));
1279
1282
  transition-duration: var(--tw-duration, var(--default-transition-duration));
1280
1283
  }
1281
- .transition-\[background-size\] {
1282
- transition-property: background-size;
1284
+ .transition-\[background-size\,background-image\,color\] {
1285
+ transition-property: background-size,background-image,color;
1283
1286
  transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));
1284
1287
  transition-duration: var(--tw-duration, var(--default-transition-duration));
1285
1288
  }
1286
- .transition-\[background-size_background-image_color\] {
1287
- transition-property: background-size background-image color;
1289
+ .transition-\[background-size\,color\] {
1290
+ transition-property: background-size,color;
1288
1291
  transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));
1289
1292
  transition-duration: var(--tw-duration, var(--default-transition-duration));
1290
1293
  }
1291
- .transition-\[background-size_color\] {
1292
- transition-property: background-size color;
1294
+ .transition-\[background-size\] {
1295
+ transition-property: background-size;
1293
1296
  transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));
1294
1297
  transition-duration: var(--tw-duration, var(--default-transition-duration));
1295
1298
  }
@@ -1313,8 +1316,8 @@
1313
1316
  transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));
1314
1317
  transition-duration: var(--tw-duration, var(--default-transition-duration));
1315
1318
  }
1316
- .transition-\[transform_color\] {
1317
- transition-property: transform color;
1319
+ .transition-\[transform\,color\] {
1320
+ transition-property: transform,color;
1318
1321
  transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));
1319
1322
  transition-duration: var(--tw-duration, var(--default-transition-duration));
1320
1323
  }
@@ -1376,6 +1379,9 @@
1376
1379
  .\[--theme-color\:var\(--color-cyan-500\)\] {
1377
1380
  --theme-color: var(--color-cyan-500);
1378
1381
  }
1382
+ .\[--theme-color\:var\(--color-primary-500\)\] {
1383
+ --theme-color: var(--color-primary-500);
1384
+ }
1379
1385
  .\[--theme-color\:var\(--color-ui-blue\)\] {
1380
1386
  --theme-color: var(--color-ui-blue);
1381
1387
  }
@@ -1709,6 +1715,14 @@
1709
1715
  color: var(--color-ui-red);
1710
1716
  }
1711
1717
  }
1718
+ .after\:transition-\[transform\,background-color\] {
1719
+ &::after {
1720
+ content: var(--tw-content);
1721
+ transition-property: transform,background-color;
1722
+ transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));
1723
+ transition-duration: var(--tw-duration, var(--default-transition-duration));
1724
+ }
1725
+ }
1712
1726
  .after\:transition-\[transform_background-color\] {
1713
1727
  &::after {
1714
1728
  content: var(--tw-content);
@@ -1752,6 +1766,12 @@
1752
1766
  --theme-color: var(--color-blue-500);
1753
1767
  }
1754
1768
  }
1769
+ .after\:\[--theme-color\:var\(--color-primary-500\)\] {
1770
+ &::after {
1771
+ content: var(--tw-content);
1772
+ --theme-color: var(--color-primary-500);
1773
+ }
1774
+ }
1755
1775
  .after\:\[--theme-color\:var\(--color-ui-blue\)\] {
1756
1776
  &::after {
1757
1777
  content: var(--tw-content);
@@ -1,3 +1,4 @@
1
+ import { Url, UrlObject } from 'node:url';
1
2
  import { ElementType } from 'react';
2
3
  import { AnyElementProps, OneOf } from '../types';
3
4
  type ColorTheme = OneOf<[
@@ -20,24 +21,88 @@ type ColorTheme = OneOf<[
20
21
  ]>;
21
22
  }
22
23
  ]>;
23
- type LinkOrOther<TTag extends ElementType> = (AnyElementProps<TTag> & {
24
- href?: never;
25
- }) | (AnchorProps & {
26
- href: string;
27
- });
28
- export type ButtonProps<TTag extends ElementType> = LinkOrOther<TTag> & ColorTheme & {
24
+ type LinkOrOther<TTag extends ElementType = typeof HeadlessButton> = OneOf<[
25
+ AnyElementProps<TTag> & {
26
+ href?: never;
27
+ },
28
+ AnyElementProps<typeof Anchor> & {
29
+ href?: string | Url | UrlObject;
30
+ }
31
+ ]>;
32
+ export type ButtonPadding = 'none' | 'xs' | 'sm' | 'md' | 'lg' | 'xl';
33
+ export type ButtonBorderRadius = 'none' | 'xs' | 'sm' | 'md' | 'lg' | 'xl' | 'full';
34
+ export type ButtonProps<TTag extends ElementType = typeof HeadlessButton> = LinkOrOther<TTag> & ColorTheme & {
29
35
  /** Customizes the theme color to a sensible gradient. */
30
36
  gradient?: boolean;
31
37
  /** The size of the element based on padding. */
32
- padding?: 'none' | 'xs' | 'sm' | 'md' | 'lg' | 'xl';
33
- /** The size of the border-1 radius. */
34
- rounded?: 'none' | 'xs' | 'sm' | 'md' | 'lg' | 'xl' | 'full';
38
+ padding?: ButtonPadding;
39
+ /** The size of the border radius. */
40
+ rounded?: ButtonBorderRadius;
41
+ };
42
+ export type ExtendedButtonConfig = {
43
+ /** Modifies the default(s) for what element is rendered. The `as` prop on the component still overrides the default(s) set here. */
44
+ as?: ElementType | {
45
+ /** Modifies the base link element when `href` is present. */
46
+ link?: ElementType;
47
+ /** Modifies the base button element. */
48
+ default?: ElementType;
49
+ };
50
+ /** Adds default classes. */
51
+ className?: string;
52
+ defaultTheme?: ColorTheme['theme'] | string;
53
+ /** Sets the default for the `gradient` prop. */
54
+ gradient?: boolean;
55
+ /** Sets the default for the `padding` prop. */
56
+ padding?: ButtonPadding;
57
+ /** Sets the default for the `rounded` prop. */
58
+ rounded?: ButtonBorderRadius;
59
+ /** Add more theme options. */
60
+ theme?: {
61
+ [themeName: string]: {
62
+ /** Custom theme configuration */
63
+ customTheme: NonNullable<ColorTheme['customTheme']>;
64
+ /** Additional CSS classes to apply */
65
+ className?: string;
66
+ };
67
+ };
68
+ };
69
+ export type ExtendedThemeNames<T extends ExtendedButtonConfig> = T['theme'] extends Record<string, unknown> ? keyof T['theme'] : never;
70
+ export type ExtendedButtonProps<TExtendedConfig extends ExtendedButtonConfig, TTag extends ElementType = typeof HeadlessButton> = Omit<ButtonProps<TTag>, 'theme' | 'customTheme'> & {
71
+ theme?: ButtonProps<TTag>['theme'] | ExtendedThemeNames<TExtendedConfig>;
72
+ customTheme?: ButtonProps<TTag>['customTheme'];
35
73
  };
36
- import { AnchorProps } from './link';
74
+ import { Anchor } from './link';
37
75
  import { Button as HeadlessButton } from '@headlessui/react';
38
76
  /**
39
77
  * # Button
40
78
  * - A pre-styled button with utility props for easy customization depending on use case.
41
79
  */
42
80
  export default function Button<TTag extends ElementType = typeof HeadlessButton>({ className, customTheme, gradient, padding, rounded, theme, ...props }: ButtonProps<TTag>): import("react/jsx-runtime").JSX.Element;
81
+ /**
82
+ * # createButton
83
+ * Creates an extended Button component with additional theme options.
84
+ *
85
+ * @param extendedThemes - Configuration object defining new themes
86
+ * @returns A new Button component with extended theme support
87
+ *
88
+ * @example
89
+ * ```tsx
90
+ * const MyButton = createButton({
91
+ * as: {
92
+ * default: 'div',
93
+ * link: NextLink
94
+ * },
95
+ * className: 'min-w-64',
96
+ * padding: 'sm',
97
+ * rounded: 'full',
98
+ * theme: {
99
+ * primary: {
100
+ * customTheme: { themeColor: '[--theme-color:var(--color-primary-500)]' },
101
+ * className: 'text-white'
102
+ * }
103
+ * }
104
+ * })
105
+ * ```
106
+ */
107
+ export declare function createButton<TExtendedConfig extends ExtendedButtonConfig>(config: TExtendedConfig): <TTag extends ElementType = typeof HeadlessButton>({ theme, className, customTheme, gradient, padding, rounded, as, ...props }: ExtendedButtonProps<TExtendedConfig, TTag>) => import("react/jsx-runtime").JSX.Element;
43
108
  export {};
@@ -5,14 +5,12 @@ export type DetailsBodyProps<TTag extends ElementType = 'div'> = Omit<Disclosure
5
5
  export type DetailsProps<TTag extends ElementType = 'div'> = Omit<DisclosureProps<TTag>, 'className' | 'role'> & {
6
6
  className?: string;
7
7
  };
8
- export type DetailsSummaryProps<TTag extends ElementType = typeof Button> = Omit<DisclosureButtonProps<TTag> & {
9
- href?: never;
10
- }, 'className' | 'href' | 'role'> & {
8
+ export type DetailsSummaryProps<TTag extends ElementType = typeof Button<typeof HeadlessButton>> = Omit<DisclosureButtonProps<TTag>, 'as' | 'className' | 'role'> & {
11
9
  arrow?: boolean | ReactNode;
12
10
  className?: string;
13
11
  };
14
- import { DisclosureProps, DisclosureButtonProps, DisclosurePanelProps } from '@headlessui/react';
12
+ import { Button as HeadlessButton, DisclosureProps, DisclosureButtonProps, DisclosurePanelProps } from '@headlessui/react';
15
13
  import Button from './button';
16
- export declare function DetailsSummary<TTag extends ElementType = typeof Button<'button'>>({ arrow, as, children, className, ...props }: DetailsSummaryProps<TTag>): import("react/jsx-runtime").JSX.Element;
14
+ export declare function DetailsSummary<TTag extends ElementType = typeof Button>({ arrow, children, className, ...props }: DetailsSummaryProps<TTag>): import("react/jsx-runtime").JSX.Element;
17
15
  export declare function DetailsBody<TTag extends ElementType = 'div'>({ children, className, ...props }: DetailsBodyProps<TTag>): import("react/jsx-runtime").JSX.Element;
18
16
  export default function Details<TTag extends ElementType = 'div'>({ as, className, ...props }: DetailsProps<TTag>): import("react/jsx-runtime").JSX.Element;
@@ -7,10 +7,11 @@ export type DropDownButtonProps<TTag extends ElementType = 'button'> = Omit<Menu
7
7
  export type DropDownItemProps = MenuItemProps;
8
8
  export type DropDownItemsProps = Omit<MenuItemsProps, 'className' | 'transition'> & {
9
9
  className?: string;
10
+ containerClassName?: string;
10
11
  };
11
12
  export type DropDownProps = MenuProps;
12
13
  export type DropDownSectionProps = MenuSectionProps & {
13
- label: string;
14
+ label?: string;
14
15
  labelProps?: Omit<MenuHeadingProps, 'children'> & {
15
16
  /** @deprecated Use `label` instead. */
16
17
  children?: never;
@@ -22,7 +23,7 @@ export type DropDownSeparatorProps = MenuSeparatorProps;
22
23
  import { MenuButtonProps, MenuHeadingProps, MenuItemProps, MenuItemsProps, MenuProps, MenuSectionProps, MenuSeparatorProps } from '@headlessui/react';
23
24
  export declare function DropDownButton<TTag extends ElementType = 'button'>({ arrow, as, children, className, ...props }: DropDownButtonProps<TTag>): import("react/jsx-runtime").JSX.Element;
24
25
  export declare function DropDownItem({ as, ...props }: DropDownItemProps): import("react/jsx-runtime").JSX.Element;
25
- export declare function DropDownItems({ anchor, children, className, style, ...props }: DropDownItemsProps): import("react/jsx-runtime").JSX.Element;
26
+ export declare function DropDownItems({ anchor, children, className, containerClassName, style, ...props }: DropDownItemsProps): import("react/jsx-runtime").JSX.Element;
26
27
  export declare function DropDownSection({ children, label, labelProps, separatorAbove, separatorBelow, ...props }: DropDownSectionProps): import("react/jsx-runtime").JSX.Element;
27
28
  export declare function DropDownSeparator({ className, ...props }: DropDownSeparatorProps): import("react/jsx-runtime").JSX.Element;
28
29
  export default function DropDown(props: DropDownProps): import("react/jsx-runtime").JSX.Element;
@@ -1,7 +1,6 @@
1
1
  import { ReactNode } from 'react';
2
- export type SubmitButtonProps = Omit<ButtonProps<'button'> & {
3
- href?: never;
4
- }, 'as' | 'customTheme' | 'href' | 'theme'> & {
2
+ export type SubmitButtonProps = Omit<ButtonProps, 'as' | 'customTheme' | 'href' | 'theme'> & {
3
+ /** This doesn't do much by default, because we use built-in colors for different form states. You'll have to modify a good bit to make this do anything. */
5
4
  customTheme?: {
6
5
  /** Example: `'[--theme-color:var(--color-blue-500)]'` */
7
6
  themeColor: string;
@@ -1,11 +1,11 @@
1
- import Button, { ButtonProps } from './button';
1
+ import Button, { ButtonProps, createButton, ExtendedButtonConfig, ExtendedButtonProps } from './button';
2
2
  import Details, { DetailsBody, DetailsBodyProps, DetailsProps, DetailsSummary, DetailsSummaryProps } from './details';
3
3
  import DropDown, { DropDownButton, DropDownButtonProps, DropDownItem, DropDownItemProps, DropDownItems, DropDownItemsProps, DropDownProps, DropDownSection, DropDownSectionProps, DropDownSeparator, DropDownSeparatorProps } from './drop-down';
4
4
  import Form, { Fieldset, FieldsetProps, FormProps, FormSubmitArgs, Input, InputProps, SubmitButton, SubmitButtonProps, Textarea, TextareaProps } from './form';
5
5
  import Ghost from './ghost';
6
6
  import Heading, { HeadingProps } from './heading';
7
- import Link, { Anchor, AnchorProps, LinkProps } from './link';
7
+ import Link, { Anchor, AnchorProps, createLink, ExtendedLinkConfig, ExtendedLinkProps, LinkProps } from './link';
8
8
  import Modal, { ModalDialog, ModalProps, ModalTrigger } from './modal';
9
9
  import Time from './time';
10
10
  import Tooltip, { TooltipPanel, TooltipProps, TooltipTrigger } from './tooltip';
11
- export { Anchor, AnchorProps, Button, ButtonProps, Details, DetailsBody, DetailsBodyProps, DetailsProps, DetailsSummary, DetailsSummaryProps, DropDown, DropDownButton, DropDownButtonProps, DropDownItem, DropDownItemProps, DropDownItems, DropDownItemsProps, DropDownProps, DropDownSection, DropDownSectionProps, DropDownSeparator, DropDownSeparatorProps, Fieldset, FieldsetProps, Form, FormProps, FormSubmitArgs, Ghost, Heading, HeadingProps, Input, InputProps, Link, LinkProps, Modal, ModalDialog, ModalProps, ModalTrigger, SubmitButton, SubmitButtonProps, Textarea, TextareaProps, Time, Tooltip, TooltipPanel, TooltipProps, TooltipTrigger, };
11
+ export { Anchor, AnchorProps, Button, ButtonProps, createButton, createLink, Details, DetailsBody, DetailsBodyProps, DetailsProps, DetailsSummary, DetailsSummaryProps, DropDown, DropDownButton, DropDownButtonProps, DropDownItem, DropDownItemProps, DropDownItems, DropDownItemsProps, DropDownProps, DropDownSection, DropDownSectionProps, DropDownSeparator, DropDownSeparatorProps, ExtendedButtonConfig, ExtendedButtonProps, ExtendedLinkConfig, ExtendedLinkProps, Fieldset, FieldsetProps, Form, FormProps, FormSubmitArgs, Ghost, Heading, HeadingProps, Input, InputProps, Link, LinkProps, Modal, ModalDialog, ModalProps, ModalTrigger, SubmitButton, SubmitButtonProps, Textarea, TextareaProps, Time, Tooltip, TooltipPanel, TooltipProps, TooltipTrigger, };
@@ -1,9 +1,9 @@
1
1
  import { AnyElementProps, OneOf } from '../types';
2
2
  import { ElementType } from 'react';
3
- export type AnchorProps<TTag extends ElementType<any, 'a'> = 'a'> = AnyElementProps<TTag> & {
3
+ export type AnchorProps<TTag extends ElementType = 'a'> = AnyElementProps<TTag> & {
4
4
  disabled?: boolean;
5
5
  };
6
- export declare function Anchor({ as, className, disabled, href, onClick, target, rel, ...props }: AnchorProps): import("react/jsx-runtime").JSX.Element;
6
+ export declare function Anchor<TTag extends ElementType = 'a'>({ as, className, disabled, href, onClick, target, rel, ...props }: AnchorProps<TTag>): import("react/jsx-runtime").JSX.Element;
7
7
  type ThemeColorOrClasses = OneOf<[
8
8
  {
9
9
  /**
@@ -28,7 +28,7 @@ type ColorTheme = OneOf<[
28
28
  customTheme: ThemeColorOrClasses;
29
29
  }
30
30
  ]>;
31
- export type LinkProps<TTag extends ElementType<any, 'a'> = 'a'> = AnyElementProps<TTag, OneOf<[
31
+ export type LinkProps<TTag extends ElementType = typeof Anchor> = AnyElementProps<TTag, OneOf<[
32
32
  {
33
33
  type?: 'center' | 'lift' | 'ltr' | 'multiline' | 'multiline-center' | 'multiline-lift' | 'multiline-ltr' | 'multiline-rtl' | 'multiline-static' | 'normal' | 'rtl' | 'static';
34
34
  },
@@ -65,5 +65,62 @@ export type LinkProps<TTag extends ElementType<any, 'a'> = 'a'> = AnyElementProp
65
65
  * @example
66
66
  * <Link href='/about' type='fill-ltr' theme='red' title='About Us'>Learn more about our company</Link>
67
67
  */
68
- export default function Link({ as, className, customTheme, theme, type, ...props }: LinkProps): import("react/jsx-runtime").JSX.Element;
68
+ export default function Link<TTag extends ElementType = typeof Anchor>({ as, className, customTheme, theme, type, ...props }: LinkProps<TTag>): import("react/jsx-runtime").JSX.Element;
69
+ export type ExtendedLinkConfig = {
70
+ /** Modifies the default element that is rendered. The `as` prop on the component still overrides the default set here. */
71
+ as?: ElementType;
72
+ /** Adds default classes. */
73
+ className?: string;
74
+ /** Sets the default theme. */
75
+ defaultTheme?: ColorTheme['theme'] | string;
76
+ /** Sets the default for the `type` prop. */
77
+ type?: LinkProps['type'];
78
+ /** Add more theme options. */
79
+ theme?: {
80
+ [themeName: string]: {
81
+ /** Custom theme configuration - supports both multiline and regular link theme formats */
82
+ customTheme: Omit<ThemeColorOrClasses, 'themeColor'> & {
83
+ themeColor?: {
84
+ /** Example: `'after:[--theme-color:var(--color-blue-500)]'` */
85
+ fill: string;
86
+ /** Example: `'[--theme-color:var(--color-blue-500)]'` */
87
+ multilineFill: string;
88
+ };
89
+ };
90
+ /** Additional CSS classes to apply */
91
+ className?: string;
92
+ };
93
+ };
94
+ };
95
+ export type ExtendedThemeNames<T extends ExtendedLinkConfig> = T['theme'] extends Record<string, unknown> ? keyof T['theme'] : never;
96
+ export type ExtendedLinkProps<TExtendedConfig extends ExtendedLinkConfig, TTag extends ElementType = typeof Anchor> = Omit<LinkProps<TTag>, 'theme' | 'customTheme'> & {
97
+ theme?: LinkProps<TTag>['theme'] | ExtendedThemeNames<TExtendedConfig>;
98
+ customTheme?: LinkProps<TTag>['customTheme'];
99
+ };
100
+ /**
101
+ * # createLink
102
+ * Creates an extended Link component with additional theme options.
103
+ *
104
+ * @param config - Configuration object defining new themes and defaults
105
+ * @returns A new Link component with extended theme support
106
+ *
107
+ * @example
108
+ * ```tsx
109
+ * const MyLink = createLink({
110
+ * as: NextLink,
111
+ * className: 'font-bold',
112
+ * type: 'fill',
113
+ * theme: {
114
+ * primary: {
115
+ * customTheme: {
116
+ * fill: 'after:[--theme-color:var(--color-primary-500)]',
117
+ * multilineFill: '[--theme-color:var(--color-primary-500)]'
118
+ * },
119
+ * className: 'text-white'
120
+ * }
121
+ * }
122
+ * })
123
+ * ```
124
+ */
125
+ export declare function createLink<TExtendedConfig extends ExtendedLinkConfig>(config: TExtendedConfig): <TTag extends ElementType = typeof Anchor>({ theme, className, customTheme, type, as, ...props }: ExtendedLinkProps<TExtendedConfig, TTag>) => import("react/jsx-runtime").JSX.Element;
69
126
  export {};
@@ -346,7 +346,7 @@ const lineLiftClasses = twJoin([
346
346
  scaleYClasses,
347
347
  'after:origin-bottom after:translate-y-1 after:scale-x-75 active:after:translate-y-0 active:after:scale-x-100 pointer-fine:hover:after:translate-y-0 pointer-fine:hover:after:scale-x-100',
348
348
  ]);
349
- const fillClasses = twJoin(baseClasses, 'whitespace-nowrap transition-[transform_color] after:top-1/2 after:h-[calc(100%+0.05rem)] after:w-[calc(100%+0.25rem)] after:-translate-y-1/2 after:rounded after:ease-exponential active:text-zinc-50 pointer-fine:hover:text-zinc-50');
349
+ const fillClasses = twJoin(baseClasses, 'whitespace-nowrap transition-[transform,color] after:top-1/2 after:h-[calc(100%+0.05rem)] after:w-[calc(100%+0.25rem)] after:-translate-y-1/2 after:rounded after:ease-exponential active:text-zinc-50 pointer-fine:hover:text-zinc-50');
350
350
  // Define theme-specific fill color transition classes
351
351
  const getFillColorTransitionClasses = (theme = 'blue', customTheme) => {
352
352
  let fillColorTransitionClasses = twJoin(fillClasses, 'transition-transform after:bg-(--theme-color)');
@@ -399,7 +399,7 @@ const getFillColorTransitionClasses = (theme = 'blue', customTheme) => {
399
399
  };
400
400
  // Define theme-specific fill center classes
401
401
  const getFillCenterClasses = (theme = 'blue', customTheme) => {
402
- let fillCenterColorClasses = twJoin(fillClasses, 'after:scale-x-50 after:scale-y-[0.25] after:bg-(--theme-color)/0 after:transition-[transform_background-color] active:after:scale-x-100 active:after:scale-y-100 active:after:bg-(--theme-color) pointer-fine:hover:after:scale-x-100 pointer-fine:hover:after:scale-y-100 pointer-fine:hover:after:bg-(--theme-color)');
402
+ let fillCenterColorClasses = twJoin(fillClasses, 'after:scale-x-50 after:scale-y-[0.25] after:bg-(--theme-color)/0 after:transition-[transform,background-color] active:after:scale-x-100 active:after:scale-y-100 active:after:bg-(--theme-color) pointer-fine:hover:after:scale-x-100 pointer-fine:hover:after:scale-y-100 pointer-fine:hover:after:bg-(--theme-color)');
403
403
  switch (theme) {
404
404
  case 'blue':
405
405
  fillCenterColorClasses = twJoin(fillCenterColorClasses, 'after:[--theme-color:var(--color-ui-blue)]');
@@ -458,7 +458,7 @@ const multilineLineCenterClasses = twJoin([multilineXClasses, 'bg-[position:50%_
458
458
  const multilineLineLiftClasses = twJoin(multilineLineClasses, 'bg-[size:auto_0px] focus-visible:bg-[size:auto_2px] active:bg-[size:auto_2px] pointer-fine:hover:bg-[size:auto_2px]');
459
459
  const multilineFillBaseClasses = twJoin(multilineBaseClasses, 'rounded px-0.5 py-0.75 focus-visible:text-zinc-50 active:text-zinc-50 pointer-fine:hover:text-zinc-50');
460
460
  const getMultilineFillColorClasses = (theme = 'blue', customTheme) => {
461
- let multilineFillColorClasses = twJoin(multilineFillBaseClasses, 'from-(--theme-color) to-(--theme-color) transition-[background-size_color]');
461
+ let multilineFillColorClasses = twJoin(multilineFillBaseClasses, 'from-(--theme-color) to-(--theme-color) transition-[background-size,color]');
462
462
  switch (theme) {
463
463
  case 'blue':
464
464
  multilineFillColorClasses = twJoin(multilineFillColorClasses, '[--theme-color:var(--color-ui-blue)]');
@@ -507,7 +507,7 @@ const getMultilineFillColorClasses = (theme = 'blue', customTheme) => {
507
507
  return multilineFillColorClasses;
508
508
  };
509
509
  const getMultilineFillClasses = (theme = 'blue', customTheme) => {
510
- let multilineFillColorClasses = twJoin(multilineFillBaseClasses, 'from-(--theme-color)/0 to-(--theme-color)/0 bg-[size:50%_0px] bg-[position:50%_50%] transition-[background-size_background-image_color] focus-visible:from-(--theme-color) focus-visible:to-(--theme-color) focus-visible:bg-[size:100%_100%] active:from-(--theme-color) active:to-(--theme-color) active:bg-[size:100%_100%] contrast-more:from-(--theme-color)/0 pointer-fine:hover:from-(--theme-color) pointer-fine:hover:to-(--theme-color) pointer-fine:hover:bg-[size:100%_100%]');
510
+ let multilineFillColorClasses = twJoin(multilineFillBaseClasses, 'from-(--theme-color)/0 to-(--theme-color)/0 bg-[size:50%_0px] bg-[position:50%_50%] transition-[background-size,background-image,color] focus-visible:from-(--theme-color) focus-visible:to-(--theme-color) focus-visible:bg-[size:100%_100%] active:from-(--theme-color) active:to-(--theme-color) active:bg-[size:100%_100%] contrast-more:from-(--theme-color)/0 pointer-fine:hover:from-(--theme-color) pointer-fine:hover:to-(--theme-color) pointer-fine:hover:bg-[size:100%_100%]');
511
511
  switch (theme) {
512
512
  case 'blue':
513
513
  multilineFillColorClasses = twJoin(multilineFillColorClasses, '[--theme-color:var(--color-ui-blue)]');
@@ -647,6 +647,71 @@ function Link({ as, className, customTheme, theme = 'blue', type, ...props }) {
647
647
  const LinkElement = as || Anchor;
648
648
  return jsx(LinkElement, { ...props, className: twMerge(linkClasses, className) });
649
649
  }
650
+ /**
651
+ * # createLink
652
+ * Creates an extended Link component with additional theme options.
653
+ *
654
+ * @param config - Configuration object defining new themes and defaults
655
+ * @returns A new Link component with extended theme support
656
+ *
657
+ * @example
658
+ * ```tsx
659
+ * const MyLink = createLink({
660
+ * as: NextLink,
661
+ * className: 'font-bold',
662
+ * type: 'fill',
663
+ * theme: {
664
+ * primary: {
665
+ * customTheme: {
666
+ * fill: 'after:[--theme-color:var(--color-primary-500)]',
667
+ * multilineFill: '[--theme-color:var(--color-primary-500)]'
668
+ * },
669
+ * className: 'text-white'
670
+ * }
671
+ * }
672
+ * })
673
+ * ```
674
+ */
675
+ function createLink(config) {
676
+ return function ExtendedLink({ theme, className, customTheme, type, as, ...props }) {
677
+ const finalType = type !== undefined ? type : config.type, finalTheme = theme !== undefined ? theme : config.defaultTheme;
678
+ const configClassName = config.className;
679
+ const shouldOverrideElement = !Boolean(as) && Boolean(config.as);
680
+ const linkProps = {
681
+ ...props,
682
+ className: undefined,
683
+ customTheme: undefined,
684
+ type: finalType,
685
+ };
686
+ if (shouldOverrideElement) {
687
+ linkProps.as = config.as;
688
+ }
689
+ else if (as) {
690
+ linkProps.as = as;
691
+ }
692
+ if (finalTheme && typeof finalTheme === 'string' && config.theme && finalTheme in config.theme) {
693
+ const extendedTheme = config.theme[finalTheme];
694
+ if (customTheme)
695
+ return (jsx(Link, { ...linkProps, theme: 'custom', customTheme: customTheme, className: twMerge(configClassName, extendedTheme.className, className) }));
696
+ let resolvedCustomTheme;
697
+ if (extendedTheme.customTheme.themeColor) {
698
+ const isMultilineType = finalType ? finalType.includes('multiline') : false;
699
+ resolvedCustomTheme = {
700
+ themeColor: isMultilineType
701
+ ? extendedTheme.customTheme.themeColor.multilineFill
702
+ : extendedTheme.customTheme.themeColor.fill,
703
+ };
704
+ }
705
+ else {
706
+ resolvedCustomTheme = {
707
+ classes: extendedTheme.customTheme.classes,
708
+ };
709
+ }
710
+ return (jsx(Link, { ...linkProps, theme: 'custom', customTheme: resolvedCustomTheme, className: twMerge(configClassName, extendedTheme.className, className) }));
711
+ }
712
+ return (jsx(Link, { ...linkProps, theme: finalTheme, className: twMerge(configClassName, className), customTheme: customTheme }));
713
+ };
714
+ }
650
715
 
651
716
  /**
652
717
  * # Button
@@ -732,9 +797,76 @@ function Button({ className, customTheme, gradient = false, padding = 'md', roun
732
797
  themeClasses,
733
798
  className,
734
799
  ]);
735
- const ButtonElement = 'as' in props ? props.as : props.href ? Anchor : Button$1;
736
- const { as, ...restProps } = 'as' in props ? props : { ...props, as: undefined };
737
- return jsx(ButtonElement, { ...restProps, className: buttonClasses });
800
+ if ('href' in props && !props.as && props.href)
801
+ return jsx(Button$1, { ...props, as: Anchor, className: buttonClasses });
802
+ return jsx(Button$1, { ...props, className: buttonClasses });
803
+ }
804
+ /**
805
+ * # createButton
806
+ * Creates an extended Button component with additional theme options.
807
+ *
808
+ * @param extendedThemes - Configuration object defining new themes
809
+ * @returns A new Button component with extended theme support
810
+ *
811
+ * @example
812
+ * ```tsx
813
+ * const MyButton = createButton({
814
+ * as: {
815
+ * default: 'div',
816
+ * link: NextLink
817
+ * },
818
+ * className: 'min-w-64',
819
+ * padding: 'sm',
820
+ * rounded: 'full',
821
+ * theme: {
822
+ * primary: {
823
+ * customTheme: { themeColor: '[--theme-color:var(--color-primary-500)]' },
824
+ * className: 'text-white'
825
+ * }
826
+ * }
827
+ * })
828
+ * ```
829
+ */
830
+ function createButton(config) {
831
+ return function ExtendedButton({ theme, className, customTheme, gradient, padding, rounded, as, ...props }) {
832
+ const finalGradient = gradient !== undefined ? gradient : config.gradient, finalPadding = padding !== undefined ? padding : config.padding, finalRounded = rounded !== undefined ? rounded : config.rounded, finalTheme = theme !== undefined ? theme : config.defaultTheme;
833
+ const configClassName = config.className;
834
+ const shouldOverrideElement = !Boolean(as) && Boolean(config.as);
835
+ const getOverrideElement = () => {
836
+ if (!config.as)
837
+ return undefined;
838
+ if (typeof config.as === 'function' || typeof config.as === 'string')
839
+ return config.as;
840
+ const hasHref = 'href' in props && props.href;
841
+ if (hasHref && config.as.link) {
842
+ return config.as.link;
843
+ }
844
+ else if (!hasHref && config.as.default) {
845
+ return config.as.default;
846
+ }
847
+ return undefined;
848
+ };
849
+ const buttonProps = {
850
+ ...props,
851
+ className: undefined,
852
+ customTheme: undefined,
853
+ gradient: finalGradient,
854
+ padding: finalPadding,
855
+ rounded: finalRounded,
856
+ };
857
+ if (shouldOverrideElement) {
858
+ const overrideElement = getOverrideElement();
859
+ if (overrideElement)
860
+ buttonProps.as = overrideElement;
861
+ }
862
+ else if (as)
863
+ buttonProps.as = as;
864
+ if (finalTheme && typeof finalTheme === 'string' && config.theme && finalTheme in config.theme) {
865
+ const extendedTheme = config.theme[finalTheme];
866
+ return (jsx(Button, { ...buttonProps, theme: 'custom', customTheme: customTheme || extendedTheme.customTheme, className: twMerge(configClassName, extendedTheme.className, className) }));
867
+ }
868
+ return (jsx(Button, { ...buttonProps, theme: finalTheme, className: twMerge(configClassName, className), customTheme: customTheme }));
869
+ };
738
870
  }
739
871
 
740
872
  function ChevronDown(props) {
@@ -749,10 +881,8 @@ function xmark(props) {
749
881
  return (jsx("svg", { viewBox: '0 0 64 64', ...props, children: jsx("path", { d: 'M1,63c0.7,0.7,1.6,1,2.6,1s1.9-0.3,2.6-1L32,37.1L57.8,63c0.7,0.7,1.5,1,2.5,1c1,0,1.9-0.3,2.6-1c0.7-0.7,1-1.6,1-2.6 c0-1-0.3-1.8-1-2.5L37.1,32L63,6.2c0.7-0.7,1-1.6,1-2.6S63.7,1.7,63,1c-0.7-0.7-1.6-1-2.6-1c-1,0-1.8,0.3-2.5,1L32,26.9L6.2,1 C5.5,0.3,4.6,0,3.6,0C2.6,0,1.7,0.3,1,1C0.3,1.7,0,2.6,0,3.6c0,1,0.3,1.9,1,2.6L26.9,32L1,57.8c-0.7,0.7-1,1.5-1,2.6 C0,61.4,0.3,62.3,1,63z' }) }));
750
882
  }
751
883
 
752
- function DetailsSummary({ arrow = true, as, children, className, ...props }) {
753
- return (
754
- // @ts-expect-error Button has some extra props
755
- jsx(DisclosureButton, { ...props, as: as || (Button), className: twMerge('w-full', className, Boolean(arrow) && 'grid grid-cols-[1fr_1rem] gap-2'), role: 'summary', children: bag => (jsxs(Fragment$1, { children: [typeof children === 'function' ? children(bag) : children, arrow &&
884
+ function DetailsSummary({ arrow = true, children, className, ...props }) {
885
+ return (jsx(DisclosureButton, { ...props, as: (Button), className: twMerge('w-full', className, Boolean(arrow) && 'grid grid-cols-[1fr_1rem] gap-2'), role: 'summary', children: bag => (jsxs(Fragment$1, { children: [typeof children === 'function' ? children(bag) : children, arrow &&
756
886
  (typeof arrow === 'boolean' ? (jsx(ChevronDown, { className: 'absolute top-1/2 right-3 block w-4 -translate-y-1/2' })) : (arrow))] })) }));
757
887
  }
758
888
  function DetailsBody({ children, className, ...props }) {
@@ -769,7 +899,7 @@ function DropDownButton({ arrow = true, as, children, className, ...props }) {
769
899
  function DropDownItem({ as, ...props }) {
770
900
  return jsx(MenuItem, { as: as || 'div', ...props });
771
901
  }
772
- function DropDownItems({ anchor, children, className, style, ...props }) {
902
+ function DropDownItems({ anchor, children, className, containerClassName, style, ...props }) {
773
903
  const getAnchorProps = () => {
774
904
  let initialAnchor = { gap: '1rem', padding: '1rem', to: 'bottom start' };
775
905
  if (anchor) {
@@ -781,11 +911,11 @@ function DropDownItems({ anchor, children, className, style, ...props }) {
781
911
  return initialAnchor;
782
912
  };
783
913
  const anchorProps = getAnchorProps();
784
- return (jsx(MenuItems, { ...props, anchor: anchorProps, className: 'grid grid-rows-1fr rounded-xl shadow-xl transition-rows duration-500 ease-exponential data-closed:grid-rows-0fr', transition: true, style: { ...style, minWidth: 'var(--button-width)' }, children: bag => (jsx("div", { className: 'overflow-y-hidden', children: jsx("div", { className: twMerge('bg-neutral-50/20 px-6 py-5 backdrop-blur-md backdrop-brightness-150', className), children: typeof children === 'function' ? children(bag) : children }) })) }));
914
+ return (jsx(MenuItems, { ...props, anchor: anchorProps, className: twMerge('grid grid-rows-1fr rounded-xl shadow-xl transition-rows duration-500 ease-exponential data-closed:grid-rows-0fr', containerClassName), transition: true, style: { ...style, minWidth: 'var(--button-width)' }, children: bag => (jsx("div", { className: 'overflow-y-scroll', children: jsx("div", { className: twMerge('rounded-xl bg-neutral-50/20 px-6 py-5 backdrop-blur-md backdrop-brightness-150', className), children: typeof children === 'function' ? children(bag) : children }) })) }));
785
915
  }
786
916
  function DropDownSection({ children, label, labelProps, separatorAbove, separatorBelow, ...props }) {
787
917
  const { labelClassName, ...restLabelProps } = { labelClassName: labelProps?.className || '', ...labelProps };
788
- return (jsx(MenuSection, { ...props, children: sectionBag => (jsxs(Fragment$1, { children: [separatorAbove && jsx(DropDownSeparator, {}), jsx(MenuHeading, { ...restLabelProps, className: headingBag => twMerge('text-[size:larger] font-bold', typeof labelClassName === 'function' ? labelClassName(headingBag) : labelClassName), children: label }), typeof children === 'function' ? children(sectionBag) : children, separatorBelow && jsx(DropDownSeparator, {})] })) }));
918
+ return (jsx(MenuSection, { ...props, children: sectionBag => (jsxs(Fragment$1, { children: [separatorAbove && jsx(DropDownSeparator, {}), label && (jsx(MenuHeading, { ...restLabelProps, className: headingBag => twMerge('text-[size:larger] font-bold', typeof labelClassName === 'function' ? labelClassName(headingBag) : labelClassName), children: label })), typeof children === 'function' ? children(sectionBag) : children, separatorBelow && jsx(DropDownSeparator, {})] })) }));
789
919
  }
790
920
  function DropDownSeparator({ className, ...props }) {
791
921
  return (jsx(MenuSeparator, { ...props, className: bag => twMerge('my-4 block h-px rounded-full bg-neutral-950/20', typeof className === 'function' ? className(bag) : className) }));
@@ -3210,7 +3340,7 @@ function Input({ checked, className, defaultValue, description, descriptionProps
3210
3340
  : descriptionProps?.className), children: description }))] }));
3211
3341
  }
3212
3342
 
3213
- function SubmitButton({ children, className, customTheme, error, incomplete, loading, success, type = 'submit', ...props }) {
3343
+ function SubmitButton({ children, className, customTheme, error, incomplete, loading, success, type, ...props }) {
3214
3344
  const [formStatus] = useFormStatus();
3215
3345
  const getFormStatusButtonClasses = () => {
3216
3346
  switch (formStatus) {
@@ -3258,9 +3388,9 @@ function SubmitButton({ children, className, customTheme, error, incomplete, loa
3258
3388
  }
3259
3389
  };
3260
3390
  const dataFormState = getDataFormState();
3261
- return (jsx(Button, { ...props, ...dataFormState, as: 'button', className: twMerge([formStatusButtonClasses, 'w-full text-white data-loading:text-black', className]), customTheme: {
3391
+ return (jsx(Button, { ...props, ...dataFormState, className: twMerge([formStatusButtonClasses, 'w-full text-white data-loading:text-black', className]), customTheme: {
3262
3392
  themeColor: twMerge('data-error:[--theme-color:var(--color-ui-red)] data-incomplete:[--theme-color:var(--color-ui-grey)] data-loading:[--theme-color:var(--color-ui-yellow)] data-readonly:[--theme-color:var(--color-ui-grey)] data-ready:[--theme-color:var(--color-ui-blue)] data-success:[--theme-color:var(--color-ui-green)]', customTheme?.themeColor),
3263
- }, theme: 'custom', type: type, children: buttonText }));
3393
+ }, theme: 'custom', type: type || 'submit', children: buttonText }));
3264
3394
  }
3265
3395
 
3266
3396
  function Textarea({ className, defaultValue, description, descriptionProps, disabled, fieldProps, invalid = true, label, labelProps, name, onBlur, onChange, placeholder, ref, required = true, value, ...props }) {
@@ -3602,5 +3732,5 @@ function Time({ children, dateObject, dateTime, day, hours, milliseconds, minute
3602
3732
  return (jsx("time", { dateTime: dateAndTime, ref: ref, ...props, children: dateDisplay }));
3603
3733
  }
3604
3734
 
3605
- export { Anchor, Button, Details, DetailsBody, DetailsSummary, DropDown, DropDownButton, DropDownItem, DropDownItems, DropDownSection, DropDownSeparator, Fieldset, Form, Ghost, Heading, Input, Link, Modal, ModalDialog, ModalTrigger, SubmitButton, Textarea, Time, Tooltip, TooltipPanel, TooltipTrigger };
3735
+ export { Anchor, Button, Details, DetailsBody, DetailsSummary, DropDown, DropDownButton, DropDownItem, DropDownItems, DropDownSection, DropDownSeparator, Fieldset, Form, Ghost, Heading, Input, Link, Modal, ModalDialog, ModalTrigger, SubmitButton, Textarea, Time, Tooltip, TooltipPanel, TooltipTrigger, createButton, createLink };
3606
3736
  //# sourceMappingURL=components.esm.js.map