margo-ui 5.2.0 → 6.1.0
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/package.json +2 -2
- package/src/components/blockquote/style.ts +1 -1
- package/src/components/button/button.tsx +13 -16
- package/src/components/button/style.ts +1 -1
- package/src/components/button/type.ts +4 -5
- package/src/components/button_micro/button_micro.tsx +12 -26
- package/src/components/button_micro/type.ts +1 -3
- package/src/components/callout/callout.tsx +15 -0
- package/src/components/callout/style.ts +3 -0
- package/src/components/callout/type.ts +9 -0
- package/src/components/card/style.ts +1 -1
- package/src/components/chip/chip.tsx +1 -1
- package/src/components/code/code.tsx +7 -5
- package/src/components/header/header.tsx +3 -8
- package/src/components/header/type.ts +1 -1
- package/src/components/input/input.tsx +2 -2
- package/src/components/input/type.ts +1 -1
- package/src/components/item/item.tsx +10 -13
- package/src/components/item/style.ts +1 -1
- package/src/components/item/type.ts +2 -3
- package/src/components/label/label.tsx +8 -3
- package/src/components/label/style.ts +3 -1
- package/src/components/label/type.ts +1 -0
- package/src/components/layer/layer.tsx +15 -1
- package/src/components/popover/popover.tsx +4 -4
- package/src/components/popover/style.ts +7 -7
- package/src/components/popover/type.ts +2 -2
- package/src/components/progress_bar/style.ts +2 -1
- package/src/components/sheet/sheet.css +8 -8
- package/src/components/sheet/sheet.tsx +9 -4
- package/src/components/sheet/style.ts +4 -4
- package/src/components/sheet/type.ts +2 -2
- package/src/components/slider/slider.css +73 -0
- package/src/components/slider/slider.tsx +44 -0
- package/src/components/slider/style.ts +2 -0
- package/src/components/slider/type.ts +3 -0
- package/src/components/table/style.ts +2 -1
- package/src/components/text_area/style.ts +10 -0
- package/src/components/text_area/text_area.tsx +25 -0
- package/src/components/text_area/type.ts +11 -0
- package/src/components/tooltip/style.ts +6 -6
- package/src/components/tooltip/tooltip.tsx +3 -3
- package/src/components/tooltip/type.ts +2 -2
- package/src/css/base.css +0 -14
- package/src/css/theme.css +1 -2
- package/src/hoc/background_glow/background_glow.css +3 -5
- package/src/hoc/border_glow/border_glow.tsx +8 -5
- package/src/hoc/border_glow/style.ts +4 -4
- package/src/hoc/border_glow/type.ts +2 -2
- package/src/hoc/pointer_holder/pointer_holder.tsx +5 -1
- package/src/hoc/pointer_holder/type.ts +1 -3
- package/src/index.ts +17 -5
- package/src/utils/cn/cn.ts +10 -0
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "margo-ui",
|
|
3
|
-
"version": "
|
|
4
|
-
"description": "React
|
|
3
|
+
"version": "6.1.0",
|
|
4
|
+
"description": "margo-ui is a React component kit built on Tailwind CSS v4, with compound components and overridable CSS tokens.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"react",
|
|
7
7
|
"ui",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export const blockquoteBaseClassName = "border-l-margo border-primary-darken py-0.5 pl-4 flex
|
|
1
|
+
export const blockquoteBaseClassName = "border-l-margo border-primary-darken py-0.5 pl-4 flex flex-col justify-center";
|
|
@@ -23,19 +23,15 @@ export const Button = <T extends ElementType = "button">({
|
|
|
23
23
|
disabled = false,
|
|
24
24
|
active = false,
|
|
25
25
|
open = false,
|
|
26
|
-
onClickBlur,
|
|
27
26
|
className,
|
|
28
27
|
onClick,
|
|
29
28
|
...rest
|
|
30
29
|
}: ButtonProps<T>) => {
|
|
30
|
+
const isNativeButton = (rest.as ?? "button") === "button";
|
|
31
|
+
|
|
31
32
|
const handleClick = (event: MouseEvent<HTMLElement>) => {
|
|
32
|
-
if (disabled) return;
|
|
33
|
+
if (disabled) return event.preventDefault();
|
|
33
34
|
onClick?.(event);
|
|
34
|
-
if (typeof onClickBlur === "function") {
|
|
35
|
-
const target = event.currentTarget;
|
|
36
|
-
onClickBlur(event);
|
|
37
|
-
setTimeout(() => target.blur(), 150);
|
|
38
|
-
}
|
|
39
35
|
};
|
|
40
36
|
|
|
41
37
|
return (
|
|
@@ -44,9 +40,10 @@ export const Button = <T extends ElementType = "button">({
|
|
|
44
40
|
{...Tag.forward<T>(rest, "button")}
|
|
45
41
|
data-margo-open={open}
|
|
46
42
|
data-margo-disabled={disabled}
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
43
|
+
data-margo-active={active}
|
|
44
|
+
disabled={(isNativeButton && disabled) || undefined}
|
|
45
|
+
aria-disabled={(!isNativeButton && disabled) || undefined}
|
|
46
|
+
inert={!clickable || undefined}
|
|
50
47
|
onClick={handleClick}
|
|
51
48
|
className={cn(
|
|
52
49
|
buttonBaseClassName,
|
|
@@ -59,12 +56,12 @@ export const Button = <T extends ElementType = "button">({
|
|
|
59
56
|
);
|
|
60
57
|
};
|
|
61
58
|
|
|
62
|
-
Button.Icon = ({
|
|
63
|
-
<span className={cn(buttonIconClassName, className)}>{
|
|
59
|
+
Button.Icon = ({ children, className }: ButtonIconProps) => (
|
|
60
|
+
<span className={cn(buttonIconClassName, className)}>{children}</span>
|
|
64
61
|
);
|
|
65
62
|
|
|
66
|
-
Button.Label = ({
|
|
67
|
-
<span className={cn(buttonLabelClassName, className)}>{
|
|
63
|
+
Button.Label = ({ children, className }: ButtonLabelProps) => (
|
|
64
|
+
<span className={cn(buttonLabelClassName, className)}>{children}</span>
|
|
68
65
|
);
|
|
69
66
|
|
|
70
67
|
Button.IconLabel = ({
|
|
@@ -72,14 +69,14 @@ Button.IconLabel = ({
|
|
|
72
69
|
label,
|
|
73
70
|
gap = "0.5rem",
|
|
74
71
|
reverse = false,
|
|
75
|
-
|
|
72
|
+
direction = "right",
|
|
76
73
|
className,
|
|
77
74
|
}: ButtonIconLabelProps) => (
|
|
78
75
|
<span
|
|
79
76
|
style={{ "--margo-button-gap": gap } as CSSProperties}
|
|
80
77
|
className={cn(
|
|
81
78
|
buttonGridClassName,
|
|
82
|
-
|
|
79
|
+
direction === "left" && "[direction:rtl]",
|
|
83
80
|
reverse ? buttonGridReverseClassName : buttonGridForwardClassName,
|
|
84
81
|
className,
|
|
85
82
|
)}
|
|
@@ -7,7 +7,7 @@ export const buttonSurfaceClassName = "border-border";
|
|
|
7
7
|
|
|
8
8
|
export const buttonActiveClassName = "border-primary shadow-button";
|
|
9
9
|
|
|
10
|
-
export const buttonDisabledClassName = "opacity-40";
|
|
10
|
+
export const buttonDisabledClassName = "pointer-events-none opacity-40";
|
|
11
11
|
|
|
12
12
|
export const buttonIconClassName =
|
|
13
13
|
"relative z-10 flex size-4 min-w-0 shrink-0 items-center justify-center [direction:ltr]";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { TagProps } from "react-renderable";
|
|
2
2
|
import type { ElementType, MouseEventHandler, ReactNode } from "react";
|
|
3
3
|
|
|
4
|
-
export type
|
|
4
|
+
export type ButtonIconLabelDirection = "left" | "right";
|
|
5
5
|
|
|
6
6
|
export type ButtonOwnProps = {
|
|
7
7
|
clickable?: boolean;
|
|
@@ -9,18 +9,17 @@ export type ButtonOwnProps = {
|
|
|
9
9
|
active?: boolean;
|
|
10
10
|
open?: boolean;
|
|
11
11
|
onClick?: MouseEventHandler<HTMLElement>;
|
|
12
|
-
onClickBlur?: MouseEventHandler<HTMLElement>;
|
|
13
12
|
};
|
|
14
13
|
|
|
15
14
|
export type ButtonProps<T extends ElementType = "button"> = TagProps<T, ButtonOwnProps>;
|
|
16
15
|
|
|
17
16
|
export type ButtonIconProps = {
|
|
18
|
-
|
|
17
|
+
children: ReactNode;
|
|
19
18
|
className?: string;
|
|
20
19
|
};
|
|
21
20
|
|
|
22
21
|
export type ButtonLabelProps = {
|
|
23
|
-
|
|
22
|
+
children: ReactNode;
|
|
24
23
|
className?: string;
|
|
25
24
|
};
|
|
26
25
|
|
|
@@ -29,6 +28,6 @@ export type ButtonIconLabelProps = {
|
|
|
29
28
|
label: ReactNode;
|
|
30
29
|
gap?: string;
|
|
31
30
|
reverse?: boolean;
|
|
32
|
-
|
|
31
|
+
direction?: ButtonIconLabelDirection;
|
|
33
32
|
className?: string;
|
|
34
33
|
};
|
|
@@ -3,35 +3,21 @@ import { Tag } from "react-renderable";
|
|
|
3
3
|
import { cn } from "../../utils/cn/cn.js";
|
|
4
4
|
import { buttonMicroActiveClassName, buttonMicroBaseClassName, buttonMicroSurfaceClassName } from "./style.js";
|
|
5
5
|
|
|
6
|
-
import type { ElementType
|
|
6
|
+
import type { ElementType } from "react";
|
|
7
7
|
import type { ButtonMicroProps } from "./type.js";
|
|
8
8
|
|
|
9
9
|
export const ButtonMicro = <T extends ElementType = "button">({
|
|
10
10
|
active = false,
|
|
11
|
-
onClickBlur,
|
|
12
|
-
onClick,
|
|
13
11
|
className,
|
|
14
12
|
...rest
|
|
15
|
-
}: ButtonMicroProps<T>) =>
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
<Tag
|
|
27
|
-
{...Tag.forward<T>(rest, "button")}
|
|
28
|
-
data-margo-active={active}
|
|
29
|
-
onClick={handleClick}
|
|
30
|
-
className={cn(
|
|
31
|
-
buttonMicroBaseClassName,
|
|
32
|
-
active ? buttonMicroActiveClassName : buttonMicroSurfaceClassName,
|
|
33
|
-
className,
|
|
34
|
-
)}
|
|
35
|
-
/>
|
|
36
|
-
);
|
|
37
|
-
};
|
|
13
|
+
}: ButtonMicroProps<T>) => (
|
|
14
|
+
<Tag
|
|
15
|
+
{...Tag.forward<T>(rest, "button")}
|
|
16
|
+
data-margo-active={active}
|
|
17
|
+
className={cn(
|
|
18
|
+
buttonMicroBaseClassName,
|
|
19
|
+
active ? buttonMicroActiveClassName : buttonMicroSurfaceClassName,
|
|
20
|
+
className,
|
|
21
|
+
)}
|
|
22
|
+
/>
|
|
23
|
+
);
|
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
import type { TagProps } from "react-renderable";
|
|
2
|
-
import type { ElementType
|
|
2
|
+
import type { ElementType } from "react";
|
|
3
3
|
|
|
4
4
|
export type ButtonMicroOwnProps = {
|
|
5
5
|
active?: boolean;
|
|
6
|
-
onClick?: MouseEventHandler<HTMLElement>;
|
|
7
|
-
onClickBlur?: MouseEventHandler<HTMLElement>;
|
|
8
6
|
};
|
|
9
7
|
|
|
10
8
|
export type ButtonMicroProps<T extends ElementType = "button"> = TagProps<T, ButtonMicroOwnProps>;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { Tag } from "react-renderable";
|
|
2
|
+
|
|
3
|
+
import { cn } from "../../utils/cn/cn.js";
|
|
4
|
+
import { calloutBaseClassName, calloutTitleClassName } from "./style.js";
|
|
5
|
+
|
|
6
|
+
import type { ElementType } from "react";
|
|
7
|
+
import type { CalloutProps, CalloutTitleProps } from "./type.js";
|
|
8
|
+
|
|
9
|
+
export const Callout = <T extends ElementType = "aside">({ className, ...rest }: CalloutProps<T>) => (
|
|
10
|
+
<Tag {...Tag.forward<T>(rest, "aside")} className={cn(calloutBaseClassName, className)} />
|
|
11
|
+
);
|
|
12
|
+
|
|
13
|
+
Callout.Title = ({ children, className }: CalloutTitleProps) => (
|
|
14
|
+
<span className={cn(calloutTitleClassName, className)}>{children}</span>
|
|
15
|
+
);
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { TagProps } from "react-renderable";
|
|
2
|
+
import type { ElementType, ReactNode } from "react";
|
|
3
|
+
|
|
4
|
+
export type CalloutProps<T extends ElementType = "aside"> = TagProps<T>;
|
|
5
|
+
|
|
6
|
+
export type CalloutTitleProps = {
|
|
7
|
+
children: ReactNode;
|
|
8
|
+
className?: string;
|
|
9
|
+
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
export const cardBaseClassName = "rounded-margo-base border-margo border-border bg-main p-5 text-on-main shadow-card";
|
|
2
2
|
|
|
3
|
-
export const cardFocusClassName = `focus:border-primary focus-visible:outline focus-visible:outline-offset-1
|
|
3
|
+
export const cardFocusClassName = `focus-visible:border-primary focus-visible:outline focus-visible:outline-offset-1
|
|
4
4
|
focus-visible:outline-on-main`;
|
|
@@ -7,7 +7,7 @@ import type { ElementType } from "react";
|
|
|
7
7
|
import type { ChipProps } from "./type.js";
|
|
8
8
|
|
|
9
9
|
export const Chip = <T extends ElementType = "div">({ active = false, className, children, ...rest }: ChipProps<T>) => (
|
|
10
|
-
<Tag {...Tag.forward<T>(rest)} className={cn(chipBaseClassName,
|
|
10
|
+
<Tag {...Tag.forward<T>(rest)} className={cn(chipBaseClassName, active && chipActiveClassName, className)}>
|
|
11
11
|
{children}
|
|
12
12
|
</Tag>
|
|
13
13
|
);
|
|
@@ -6,11 +6,13 @@ import { codeBaseClassName, codeFilledClassName } from "./style.js";
|
|
|
6
6
|
import type { ElementType } from "react";
|
|
7
7
|
import type { CodeProps } from "./type.js";
|
|
8
8
|
|
|
9
|
-
export const Code = <T extends ElementType = "code">({
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
9
|
+
export const Code = <T extends ElementType = "code">({
|
|
10
|
+
filled = false,
|
|
11
|
+
className,
|
|
12
|
+
children,
|
|
13
|
+
...rest
|
|
14
|
+
}: CodeProps<T>) => (
|
|
15
|
+
<Tag {...Tag.forward<T>(rest, "code")} className={cn(codeBaseClassName, filled && codeFilledClassName, className)}>
|
|
14
16
|
{children}
|
|
15
17
|
</Tag>
|
|
16
18
|
);
|
|
@@ -1,12 +1,7 @@
|
|
|
1
1
|
import { Tag } from "react-renderable";
|
|
2
2
|
|
|
3
3
|
import { cn } from "../../utils/cn/cn.js";
|
|
4
|
-
import {
|
|
5
|
-
headerBaseClassName,
|
|
6
|
-
headerLeadingClassName,
|
|
7
|
-
headerTitleClassName,
|
|
8
|
-
headerTrailingClassName,
|
|
9
|
-
} from "./style.js";
|
|
4
|
+
import { headerBaseClassName, headerLeadingClassName, headerTitleClassName, headerTrailingClassName } from "./style.js";
|
|
10
5
|
|
|
11
6
|
import type { ElementType } from "react";
|
|
12
7
|
import type { HeaderLeadingProps, HeaderProps, HeaderTitleProps, HeaderTrailingProps } from "./type.js";
|
|
@@ -23,9 +18,9 @@ Header.Leading = ({ children, className }: HeaderLeadingProps) => (
|
|
|
23
18
|
</span>
|
|
24
19
|
);
|
|
25
20
|
|
|
26
|
-
Header.Title = ({
|
|
21
|
+
Header.Title = ({ children, id, className }: HeaderTitleProps) => (
|
|
27
22
|
<span data-margo-header-slot={true} id={id} className={cn(headerTitleClassName, className)}>
|
|
28
|
-
{
|
|
23
|
+
{children}
|
|
29
24
|
</span>
|
|
30
25
|
);
|
|
31
26
|
|
|
@@ -22,9 +22,9 @@ export const Input = <T extends ElementType = "div">({
|
|
|
22
22
|
/>
|
|
23
23
|
);
|
|
24
24
|
|
|
25
|
-
Input.Icon = ({
|
|
25
|
+
Input.Icon = ({ children = <MdSearch className="text-md" />, className }: InputIconProps) => (
|
|
26
26
|
<span data-margo-input-slot={true} className={cn(inputIconClassName, className)}>
|
|
27
|
-
{
|
|
27
|
+
{children}
|
|
28
28
|
</span>
|
|
29
29
|
);
|
|
30
30
|
|
|
@@ -20,20 +20,16 @@ export const Item = <T extends ElementType = "button">({
|
|
|
20
20
|
clickable = true,
|
|
21
21
|
disabled = false,
|
|
22
22
|
active = false,
|
|
23
|
-
onClickBlur,
|
|
24
23
|
onClick,
|
|
25
24
|
className,
|
|
26
25
|
children,
|
|
27
26
|
...rest
|
|
28
27
|
}: ItemProps<T>) => {
|
|
28
|
+
const isNativeButton = (rest.as ?? "button") === "button";
|
|
29
|
+
|
|
29
30
|
const handleClick = (event: MouseEvent<HTMLElement>) => {
|
|
30
|
-
if (disabled) return;
|
|
31
|
+
if (disabled) return event.preventDefault();
|
|
31
32
|
onClick?.(event);
|
|
32
|
-
if (typeof onClickBlur === "function") {
|
|
33
|
-
const target = event.currentTarget;
|
|
34
|
-
onClickBlur(event);
|
|
35
|
-
setTimeout(() => target.blur(), 150);
|
|
36
|
-
}
|
|
37
33
|
};
|
|
38
34
|
|
|
39
35
|
return (
|
|
@@ -42,8 +38,9 @@ export const Item = <T extends ElementType = "button">({
|
|
|
42
38
|
{...Tag.forward<T>(rest, "button")}
|
|
43
39
|
data-margo-active={active}
|
|
44
40
|
data-margo-disabled={disabled}
|
|
45
|
-
|
|
46
|
-
|
|
41
|
+
disabled={(isNativeButton && disabled) || undefined}
|
|
42
|
+
aria-disabled={(!isNativeButton && disabled) || undefined}
|
|
43
|
+
inert={!clickable || undefined}
|
|
47
44
|
onClick={handleClick}
|
|
48
45
|
className={cn(
|
|
49
46
|
itemBaseClassName,
|
|
@@ -58,12 +55,12 @@ export const Item = <T extends ElementType = "button">({
|
|
|
58
55
|
);
|
|
59
56
|
};
|
|
60
57
|
|
|
61
|
-
Item.Icon = ({
|
|
58
|
+
Item.Icon = ({ children = <MdChevronRight className="text-md translate-x-1" />, className }: ItemIconProps) => (
|
|
62
59
|
<span data-margo-item-slot={true} className={cn(itemIconClassName, className)}>
|
|
63
|
-
{
|
|
60
|
+
{children}
|
|
64
61
|
</span>
|
|
65
62
|
);
|
|
66
63
|
|
|
67
|
-
Item.Label = ({
|
|
68
|
-
<span className={cn(itemLabelClassName, className)}>{
|
|
64
|
+
Item.Label = ({ children, className }: ItemLabelProps) => (
|
|
65
|
+
<span className={cn(itemLabelClassName, className)}>{children}</span>
|
|
69
66
|
);
|
|
@@ -8,7 +8,7 @@ hover:shadow-item focus-visible:shadow-item`;
|
|
|
8
8
|
|
|
9
9
|
export const itemActiveClassName = "border-primary";
|
|
10
10
|
|
|
11
|
-
export const itemDisabledClassName = "opacity-40";
|
|
11
|
+
export const itemDisabledClassName = "pointer-events-none opacity-40";
|
|
12
12
|
|
|
13
13
|
export const itemIconClassName = `ml-auto flex size-4 shrink-0 items-center justify-center first:ml-0
|
|
14
14
|
[[data-margo-item-slot]+&]:ml-0`;
|
|
@@ -6,17 +6,16 @@ export type ItemOwnProps = {
|
|
|
6
6
|
disabled?: boolean;
|
|
7
7
|
active?: boolean;
|
|
8
8
|
onClick?: MouseEventHandler<HTMLElement>;
|
|
9
|
-
onClickBlur?: MouseEventHandler<HTMLElement>;
|
|
10
9
|
};
|
|
11
10
|
|
|
12
11
|
export type ItemProps<T extends ElementType = "button"> = TagProps<T, ItemOwnProps>;
|
|
13
12
|
|
|
14
13
|
export type ItemIconProps = {
|
|
15
|
-
|
|
14
|
+
children?: ReactNode;
|
|
16
15
|
className?: string;
|
|
17
16
|
};
|
|
18
17
|
|
|
19
18
|
export type ItemLabelProps = {
|
|
20
|
-
|
|
19
|
+
children: ReactNode;
|
|
21
20
|
className?: string;
|
|
22
21
|
};
|
|
@@ -1,15 +1,20 @@
|
|
|
1
1
|
import { Tag } from "react-renderable";
|
|
2
2
|
|
|
3
3
|
import { cn } from "../../utils/cn/cn.js";
|
|
4
|
-
import { labelBaseClassName, labelDisabledClassName } from "./style.js";
|
|
4
|
+
import { labelBaseClassName, labelDisabledClassName, labelSpacedClassName } from "./style.js";
|
|
5
5
|
|
|
6
6
|
import type { ElementType } from "react";
|
|
7
7
|
import type { LabelProps } from "./type.js";
|
|
8
8
|
|
|
9
|
-
export const Label = <T extends ElementType = "label">({
|
|
9
|
+
export const Label = <T extends ElementType = "label">({
|
|
10
|
+
disabled = false,
|
|
11
|
+
spaced = false,
|
|
12
|
+
className,
|
|
13
|
+
...rest
|
|
14
|
+
}: LabelProps<T>) => (
|
|
10
15
|
<Tag
|
|
11
16
|
{...Tag.forward<T>(rest, "label")}
|
|
12
17
|
data-margo-disabled={disabled}
|
|
13
|
-
className={cn(labelBaseClassName, disabled && labelDisabledClassName, className)}
|
|
18
|
+
className={cn(labelBaseClassName, spaced && labelSpacedClassName, disabled && labelDisabledClassName, className)}
|
|
14
19
|
/>
|
|
15
20
|
);
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
-
export const labelBaseClassName = "block text-mc uppercase tracking-widest text-medium truncate
|
|
1
|
+
export const labelBaseClassName = "block text-mc uppercase tracking-widest text-medium truncate";
|
|
2
|
+
|
|
3
|
+
export const labelSpacedClassName = "pl-3.5 mb-1";
|
|
2
4
|
|
|
3
5
|
export const labelDisabledClassName = "opacity-40";
|
|
@@ -52,6 +52,20 @@ export const Layer = ({ open = false, onClose, dismissible = true, className, ch
|
|
|
52
52
|
};
|
|
53
53
|
}, [open]);
|
|
54
54
|
|
|
55
|
+
useEffect(() => {
|
|
56
|
+
if (!open || dismissible) return;
|
|
57
|
+
|
|
58
|
+
const controller = new AbortController();
|
|
59
|
+
|
|
60
|
+
const handleKeyDown = (event: KeyboardEvent) => {
|
|
61
|
+
if (event.key === "Escape") event.preventDefault();
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
document.addEventListener("keydown", handleKeyDown, { capture: true, signal: controller.signal });
|
|
65
|
+
|
|
66
|
+
return () => controller.abort();
|
|
67
|
+
}, [dismissible, open]);
|
|
68
|
+
|
|
55
69
|
const handleClick = (event: MouseEvent<HTMLDialogElement>) => {
|
|
56
70
|
if (!dismissible || event.target !== event.currentTarget) return;
|
|
57
71
|
|
|
@@ -60,7 +74,7 @@ export const Layer = ({ open = false, onClose, dismissible = true, className, ch
|
|
|
60
74
|
|
|
61
75
|
const handleCancel = (event: SyntheticEvent<HTMLDialogElement>) => {
|
|
62
76
|
event.preventDefault();
|
|
63
|
-
onClose?.();
|
|
77
|
+
if (dismissible) onClose?.();
|
|
64
78
|
};
|
|
65
79
|
|
|
66
80
|
return (
|
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
popoverBaseClassName,
|
|
9
9
|
popoverBodyClassName,
|
|
10
10
|
popoverOriginClassName,
|
|
11
|
-
|
|
11
|
+
popoverPlacementClassName,
|
|
12
12
|
} from "./style.js";
|
|
13
13
|
|
|
14
14
|
import type { ElementType } from "react";
|
|
@@ -20,7 +20,7 @@ export const Popover = ({
|
|
|
20
20
|
open = false,
|
|
21
21
|
onClose,
|
|
22
22
|
dismissible = true,
|
|
23
|
-
|
|
23
|
+
placement = "bottom",
|
|
24
24
|
align = "center",
|
|
25
25
|
className,
|
|
26
26
|
children,
|
|
@@ -90,8 +90,8 @@ export const Popover = ({
|
|
|
90
90
|
data-margo-open={open}
|
|
91
91
|
className={cn(
|
|
92
92
|
popoverBaseClassName,
|
|
93
|
-
|
|
94
|
-
popoverOriginClassName[
|
|
93
|
+
popoverPlacementClassName[placement][align],
|
|
94
|
+
popoverOriginClassName[placement],
|
|
95
95
|
className,
|
|
96
96
|
)}
|
|
97
97
|
>
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { PopoverAlign,
|
|
1
|
+
import type { PopoverAlign, PopoverPlacement } from "./type.js";
|
|
2
2
|
|
|
3
3
|
export const popoverAnchorClassName = "relative inline-block size-fit";
|
|
4
4
|
|
|
@@ -8,13 +8,13 @@ overflow-clip rounded-margo-base border-margo border-border bg-main text-on-main
|
|
|
8
8
|
export const popoverBodyClassName = `flex min-h-0 max-h-56 flex-col gap-1
|
|
9
9
|
overflow-y-auto overscroll-contain w-64 p-2 text-sm`;
|
|
10
10
|
|
|
11
|
-
export const
|
|
12
|
-
|
|
11
|
+
export const popoverPlacementClassName: Record<PopoverPlacement, Record<PopoverAlign, string>> = {
|
|
12
|
+
top: {
|
|
13
13
|
start: "bottom-full left-0 my-1",
|
|
14
14
|
center: "bottom-full left-1/2 my-1 -translate-x-1/2",
|
|
15
15
|
end: "right-0 bottom-full my-1",
|
|
16
16
|
},
|
|
17
|
-
|
|
17
|
+
bottom: {
|
|
18
18
|
start: "top-full left-0 my-1",
|
|
19
19
|
center: "top-full left-1/2 my-1 -translate-x-1/2",
|
|
20
20
|
end: "top-full right-0 my-1",
|
|
@@ -31,9 +31,9 @@ export const popoverPositionClassName: Record<PopoverPosition, Record<PopoverAli
|
|
|
31
31
|
},
|
|
32
32
|
};
|
|
33
33
|
|
|
34
|
-
export const popoverOriginClassName: Record<
|
|
35
|
-
|
|
36
|
-
|
|
34
|
+
export const popoverOriginClassName: Record<PopoverPlacement, string> = {
|
|
35
|
+
top: "origin-bottom",
|
|
36
|
+
bottom: "origin-top",
|
|
37
37
|
left: "origin-right",
|
|
38
38
|
right: "origin-left",
|
|
39
39
|
};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { TagProps } from "react-renderable";
|
|
2
2
|
import type { ComponentPropsWithoutRef, ElementType, ReactNode } from "react";
|
|
3
3
|
|
|
4
|
-
export type
|
|
4
|
+
export type PopoverPlacement = "top" | "right" | "bottom" | "left";
|
|
5
5
|
|
|
6
6
|
export type PopoverAlign = "start" | "center" | "end";
|
|
7
7
|
|
|
@@ -9,7 +9,7 @@ export type PopoverProps = ComponentPropsWithoutRef<"div"> & {
|
|
|
9
9
|
open?: boolean;
|
|
10
10
|
onClose?: () => void;
|
|
11
11
|
dismissible?: boolean;
|
|
12
|
-
|
|
12
|
+
placement?: PopoverPlacement;
|
|
13
13
|
align?: PopoverAlign;
|
|
14
14
|
children?: ReactNode;
|
|
15
15
|
};
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
-
export const progressBarDefaultFill =
|
|
1
|
+
export const progressBarDefaultFill =
|
|
2
|
+
"linear-gradient(to right, var(--margo-color-primary-darken), var(--margo-color-primary))";
|
|
2
3
|
|
|
3
4
|
export const progressBarBaseClassName = "margo-progress-bar relative h-0.5 overflow-hidden";
|
|
@@ -2,19 +2,19 @@
|
|
|
2
2
|
transition: translate var(--margo-layer-duration) var(--margo-layer-easing);
|
|
3
3
|
}
|
|
4
4
|
|
|
5
|
-
.margo-sheet[data-margo-
|
|
5
|
+
.margo-sheet[data-margo-placement="left"] {
|
|
6
6
|
translate: -100% 0;
|
|
7
7
|
}
|
|
8
8
|
|
|
9
|
-
.margo-sheet[data-margo-
|
|
9
|
+
.margo-sheet[data-margo-placement="right"] {
|
|
10
10
|
translate: 100% 0;
|
|
11
11
|
}
|
|
12
12
|
|
|
13
|
-
.margo-sheet[data-margo-
|
|
13
|
+
.margo-sheet[data-margo-placement="top"] {
|
|
14
14
|
translate: 0 -100%;
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
-
.margo-sheet[data-margo-
|
|
17
|
+
.margo-sheet[data-margo-placement="bottom"] {
|
|
18
18
|
translate: 0 100%;
|
|
19
19
|
}
|
|
20
20
|
|
|
@@ -23,19 +23,19 @@ dialog[open] .margo-sheet {
|
|
|
23
23
|
}
|
|
24
24
|
|
|
25
25
|
@starting-style {
|
|
26
|
-
dialog[open] .margo-sheet[data-margo-
|
|
26
|
+
dialog[open] .margo-sheet[data-margo-placement="left"] {
|
|
27
27
|
translate: -100% 0;
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
-
dialog[open] .margo-sheet[data-margo-
|
|
30
|
+
dialog[open] .margo-sheet[data-margo-placement="right"] {
|
|
31
31
|
translate: 100% 0;
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
-
dialog[open] .margo-sheet[data-margo-
|
|
34
|
+
dialog[open] .margo-sheet[data-margo-placement="top"] {
|
|
35
35
|
translate: 0 -100%;
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
-
dialog[open] .margo-sheet[data-margo-
|
|
38
|
+
dialog[open] .margo-sheet[data-margo-placement="bottom"] {
|
|
39
39
|
translate: 0 100%;
|
|
40
40
|
}
|
|
41
41
|
}
|
|
@@ -1,19 +1,24 @@
|
|
|
1
1
|
import { Tag } from "react-renderable";
|
|
2
2
|
|
|
3
3
|
import { cn } from "../../utils/cn/cn.js";
|
|
4
|
-
import { sheetBaseClassName, sheetBodyClassName, sheetFooterClassName,
|
|
4
|
+
import { sheetBaseClassName, sheetBodyClassName, sheetFooterClassName, sheetPlacementClassName } from "./style.js";
|
|
5
5
|
|
|
6
6
|
import type { ElementType } from "react";
|
|
7
7
|
import type { SheetBodyProps, SheetFooterProps, SheetProps } from "./type.js";
|
|
8
8
|
|
|
9
9
|
import "./sheet.css";
|
|
10
10
|
|
|
11
|
-
export const Sheet = <T extends ElementType = "div">({
|
|
11
|
+
export const Sheet = <T extends ElementType = "div">({
|
|
12
|
+
placement = "right",
|
|
13
|
+
className,
|
|
14
|
+
children,
|
|
15
|
+
...rest
|
|
16
|
+
}: SheetProps<T>) => (
|
|
12
17
|
<Tag
|
|
13
18
|
{...Tag.forward<T>(rest)}
|
|
14
|
-
data-margo-
|
|
19
|
+
data-margo-placement={placement}
|
|
15
20
|
data-margo-travel={true}
|
|
16
|
-
className={cn(sheetBaseClassName,
|
|
21
|
+
className={cn(sheetBaseClassName, sheetPlacementClassName[placement], className)}
|
|
17
22
|
>
|
|
18
23
|
{children}
|
|
19
24
|
</Tag>
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { SheetPlacement } from "./type.js";
|
|
2
2
|
|
|
3
3
|
export const sheetBaseClassName = "margo-sheet flex flex-col overflow-hidden border-border bg-main text-on-main";
|
|
4
4
|
|
|
5
|
-
export const
|
|
6
|
-
|
|
7
|
-
|
|
5
|
+
export const sheetPlacementClassName: Record<SheetPlacement, string> = {
|
|
6
|
+
left: "h-full w-[85%] max-w-[26rem] justify-self-start self-stretch border-r-margo",
|
|
7
|
+
right: "h-full w-[85%] max-w-[26rem] justify-self-end self-stretch border-l-margo",
|
|
8
8
|
top: "h-auto max-h-[40%] w-full self-start justify-self-stretch border-b-margo",
|
|
9
9
|
bottom: "h-auto max-h-[40%] w-full self-end justify-self-stretch border-t-margo",
|
|
10
10
|
};
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import type { TagProps } from "react-renderable";
|
|
2
2
|
import type { ElementType } from "react";
|
|
3
3
|
|
|
4
|
-
export type
|
|
4
|
+
export type SheetPlacement = "top" | "right" | "bottom" | "left";
|
|
5
5
|
|
|
6
6
|
export type SheetOwnProps = {
|
|
7
|
-
|
|
7
|
+
placement?: SheetPlacement;
|
|
8
8
|
};
|
|
9
9
|
|
|
10
10
|
export type SheetProps<T extends ElementType = "div"> = TagProps<T, SheetOwnProps>;
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
.margo-slider {
|
|
2
|
+
appearance: none;
|
|
3
|
+
|
|
4
|
+
--margo-slider-track: var(--margo-color-border);
|
|
5
|
+
--margo-slider-fill: var(--margo-color-primary);
|
|
6
|
+
--margo-slider-thumb: var(--margo-color-primary);
|
|
7
|
+
--margo-slider-thumb-border: var(--margo-color-primary-darken);
|
|
8
|
+
--margo-slider-thumb-size: 1rem;
|
|
9
|
+
--margo-slider-track-size: 0.375rem;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
.margo-slider::-webkit-slider-runnable-track {
|
|
13
|
+
block-size: var(--margo-slider-track-size);
|
|
14
|
+
border-radius: 9999px;
|
|
15
|
+
background: linear-gradient(
|
|
16
|
+
to right,
|
|
17
|
+
var(--margo-slider-fill) var(--margo-slider-value, 0%),
|
|
18
|
+
var(--margo-slider-track) var(--margo-slider-value, 0%)
|
|
19
|
+
);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
.margo-slider::-moz-range-track {
|
|
23
|
+
block-size: var(--margo-slider-track-size);
|
|
24
|
+
border-radius: 9999px;
|
|
25
|
+
background: var(--margo-slider-track);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
.margo-slider::-moz-range-progress {
|
|
29
|
+
block-size: var(--margo-slider-track-size);
|
|
30
|
+
border-radius: 9999px;
|
|
31
|
+
background: var(--margo-slider-fill);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
.margo-slider::-webkit-slider-thumb {
|
|
35
|
+
appearance: none;
|
|
36
|
+
inline-size: var(--margo-slider-thumb-size);
|
|
37
|
+
block-size: var(--margo-slider-thumb-size);
|
|
38
|
+
margin-block-start: calc((var(--margo-slider-track-size) - var(--margo-slider-thumb-size)) / 2);
|
|
39
|
+
border: var(--margo-border) solid var(--margo-slider-thumb-border);
|
|
40
|
+
border-radius: 9999px;
|
|
41
|
+
background-color: var(--margo-slider-thumb);
|
|
42
|
+
box-shadow: var(--margo-shadow-button);
|
|
43
|
+
transition: scale 120ms ease-out;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
.margo-slider::-moz-range-thumb {
|
|
47
|
+
inline-size: var(--margo-slider-thumb-size);
|
|
48
|
+
block-size: var(--margo-slider-thumb-size);
|
|
49
|
+
box-sizing: border-box;
|
|
50
|
+
border: var(--margo-border) solid var(--margo-slider-thumb-border);
|
|
51
|
+
border-radius: 9999px;
|
|
52
|
+
background-color: var(--margo-slider-thumb);
|
|
53
|
+
box-shadow: var(--margo-shadow-button);
|
|
54
|
+
transition: scale 120ms ease-out;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
.margo-slider:enabled:active::-webkit-slider-thumb {
|
|
58
|
+
scale: 0.92;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
.margo-slider:enabled:active::-moz-range-thumb {
|
|
62
|
+
scale: 0.92;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
.margo-slider:focus-visible::-webkit-slider-thumb {
|
|
66
|
+
outline: var(--margo-border) solid var(--margo-color-on-main);
|
|
67
|
+
outline-offset: 1px;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
.margo-slider:focus-visible::-moz-range-thumb {
|
|
71
|
+
outline: var(--margo-border) solid var(--margo-color-on-main);
|
|
72
|
+
outline-offset: 1px;
|
|
73
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { cn } from "../../utils/cn/cn.js";
|
|
2
|
+
import { sliderBaseClassName } from "./style.js";
|
|
3
|
+
|
|
4
|
+
import type { ChangeEvent, CSSProperties } from "react";
|
|
5
|
+
import type { SliderProps } from "./type.js";
|
|
6
|
+
|
|
7
|
+
import "./slider.css";
|
|
8
|
+
|
|
9
|
+
const sliderPercent = (value: number, min: number, max: number) =>
|
|
10
|
+
max > min ? `${((Math.min(max, Math.max(min, value)) - min) / (max - min)) * 100}%` : "0%";
|
|
11
|
+
|
|
12
|
+
export const Slider = ({
|
|
13
|
+
min = 0,
|
|
14
|
+
max = 100,
|
|
15
|
+
value,
|
|
16
|
+
defaultValue,
|
|
17
|
+
style,
|
|
18
|
+
className,
|
|
19
|
+
onChange,
|
|
20
|
+
...rest
|
|
21
|
+
}: SliderProps) => {
|
|
22
|
+
const current = Number(value ?? defaultValue ?? (Number(min) + Number(max)) / 2);
|
|
23
|
+
|
|
24
|
+
const handleChange = (event: ChangeEvent<HTMLInputElement>) => {
|
|
25
|
+
const input = event.currentTarget;
|
|
26
|
+
|
|
27
|
+
input.style.setProperty("--margo-slider-value", sliderPercent(input.valueAsNumber, Number(min), Number(max)));
|
|
28
|
+
onChange?.(event);
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
return (
|
|
32
|
+
<input
|
|
33
|
+
{...rest}
|
|
34
|
+
type="range"
|
|
35
|
+
min={min}
|
|
36
|
+
max={max}
|
|
37
|
+
value={value}
|
|
38
|
+
defaultValue={defaultValue}
|
|
39
|
+
onChange={handleChange}
|
|
40
|
+
style={{ ...style, "--margo-slider-value": sliderPercent(current, Number(min), Number(max)) } as CSSProperties}
|
|
41
|
+
className={cn(sliderBaseClassName, className)}
|
|
42
|
+
/>
|
|
43
|
+
);
|
|
44
|
+
};
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
export const tableWrapperClassName =
|
|
1
|
+
export const tableWrapperClassName =
|
|
2
|
+
"w-full overflow-x-auto overscroll-x-none rounded-margo-base border-margo border-border";
|
|
2
3
|
|
|
3
4
|
export const tableBaseClassName = "w-full border-collapse text-xs text-on-main";
|
|
4
5
|
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export const textAreaBaseClassName = `group/text-area flex w-full cursor-text items-stretch rounded-margo-base
|
|
2
|
+
border-margo border-transparent bg-low text-sm text-medium
|
|
3
|
+
hover:border-on-main hover:text-on-main hover:shadow-item
|
|
4
|
+
focus-within:border-primary focus-within:text-on-main
|
|
5
|
+
has-[textarea:disabled]:pointer-events-none has-[textarea:disabled]:cursor-auto has-[textarea:disabled]:opacity-40`;
|
|
6
|
+
|
|
7
|
+
export const textAreaActiveClassName = "border-primary";
|
|
8
|
+
|
|
9
|
+
export const textAreaTextClassName = `min-w-0 flex-1 resize-none border-none bg-transparent px-3 py-2 text-left
|
|
10
|
+
text-on-main outline-none placeholder:text-medium disabled:cursor-auto`;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { Tag } from "react-renderable";
|
|
2
|
+
|
|
3
|
+
import { cn } from "../../utils/cn/cn.js";
|
|
4
|
+
import { textAreaActiveClassName, textAreaBaseClassName, textAreaTextClassName } from "./style.js";
|
|
5
|
+
|
|
6
|
+
import type { ElementType } from "react";
|
|
7
|
+
import type { TextAreaProps, TextAreaTextProps } from "./type.js";
|
|
8
|
+
|
|
9
|
+
export const TextArea = <T extends ElementType = "div">({
|
|
10
|
+
active = false,
|
|
11
|
+
clickable = true,
|
|
12
|
+
className,
|
|
13
|
+
...rest
|
|
14
|
+
}: TextAreaProps<T>) => (
|
|
15
|
+
<Tag
|
|
16
|
+
{...Tag.forward<T>(rest, "div")}
|
|
17
|
+
data-margo-active={active}
|
|
18
|
+
inert={!clickable || undefined}
|
|
19
|
+
className={cn(textAreaBaseClassName, active && textAreaActiveClassName, className)}
|
|
20
|
+
/>
|
|
21
|
+
);
|
|
22
|
+
|
|
23
|
+
TextArea.Text = ({ rows = 4, className, ...rest }: TextAreaTextProps) => (
|
|
24
|
+
<textarea {...rest} rows={rows} className={cn(textAreaTextClassName, className)} />
|
|
25
|
+
);
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { TagProps } from "react-renderable";
|
|
2
|
+
import type { ComponentPropsWithoutRef, ElementType } from "react";
|
|
3
|
+
|
|
4
|
+
export type TextAreaOwnProps = {
|
|
5
|
+
active?: boolean;
|
|
6
|
+
clickable?: boolean;
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
export type TextAreaProps<T extends ElementType = "div"> = TagProps<T, TextAreaOwnProps>;
|
|
10
|
+
|
|
11
|
+
export type TextAreaTextProps = ComponentPropsWithoutRef<"textarea">;
|
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { TooltipPlacement } from "./type.js";
|
|
2
2
|
|
|
3
|
-
export const tooltipAnchorClassName = "group relative inline-block size-fit";
|
|
3
|
+
export const tooltipAnchorClassName = "group/tooltip relative inline-block size-fit";
|
|
4
4
|
|
|
5
5
|
export const tooltipBubbleClassName = `pointer-events-none absolute z-10 rounded-margo-xs bg-on-main px-2 py-0.5 text-xs text-main lowercase
|
|
6
6
|
whitespace-nowrap opacity-0`;
|
|
7
7
|
|
|
8
8
|
export const tooltipTransitionClassName = "transition-opacity duration-[250ms] ease-in-out";
|
|
9
9
|
|
|
10
|
-
export const tooltipVisibleClassName = "group-hover:opacity-100 group-focus-within:opacity-100";
|
|
10
|
+
export const tooltipVisibleClassName = "group-hover/tooltip:opacity-100 group-focus-within/tooltip:opacity-100";
|
|
11
11
|
|
|
12
|
-
export const
|
|
13
|
-
|
|
14
|
-
|
|
12
|
+
export const tooltipPlacementClassName: Record<TooltipPlacement, string> = {
|
|
13
|
+
top: "bottom-[120%] left-1/2 -translate-x-1/2",
|
|
14
|
+
bottom: "top-[120%] left-1/2 -translate-x-1/2",
|
|
15
15
|
left: "top-1/2 right-[calc(100%+0.5rem)] -translate-y-1/2",
|
|
16
16
|
right: "top-1/2 left-[calc(100%+0.5rem)] -translate-y-1/2",
|
|
17
17
|
};
|
|
@@ -6,7 +6,7 @@ import { cn } from "../../utils/cn/cn.js";
|
|
|
6
6
|
import {
|
|
7
7
|
tooltipAnchorClassName,
|
|
8
8
|
tooltipBubbleClassName,
|
|
9
|
-
|
|
9
|
+
tooltipPlacementClassName,
|
|
10
10
|
tooltipTransitionClassName,
|
|
11
11
|
tooltipVisibleClassName,
|
|
12
12
|
} from "./style.js";
|
|
@@ -20,7 +20,7 @@ export const Tooltip = <T extends ElementType = "div">({
|
|
|
20
20
|
className,
|
|
21
21
|
id,
|
|
22
22
|
content,
|
|
23
|
-
|
|
23
|
+
placement = "bottom",
|
|
24
24
|
...rest
|
|
25
25
|
}: TooltipProps<T>) => {
|
|
26
26
|
const contentRef = useRef<ReactNode>(null);
|
|
@@ -40,7 +40,7 @@ export const Tooltip = <T extends ElementType = "div">({
|
|
|
40
40
|
tooltipBubbleClassName,
|
|
41
41
|
tooltipTransitionClassName,
|
|
42
42
|
isFilled && tooltipVisibleClassName,
|
|
43
|
-
|
|
43
|
+
tooltipPlacementClassName[placement],
|
|
44
44
|
)}
|
|
45
45
|
>
|
|
46
46
|
{contentRef.current}
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import type { TagProps } from "react-renderable";
|
|
2
2
|
import type { ElementType, ReactNode } from "react";
|
|
3
3
|
|
|
4
|
-
export type
|
|
4
|
+
export type TooltipPlacement = "top" | "right" | "bottom" | "left";
|
|
5
5
|
|
|
6
6
|
export type TooltipOwnProps = {
|
|
7
7
|
label?: string;
|
|
8
8
|
id?: string;
|
|
9
9
|
content?: ReactNode;
|
|
10
|
-
|
|
10
|
+
placement?: TooltipPlacement;
|
|
11
11
|
children?: ReactNode;
|
|
12
12
|
};
|
|
13
13
|
|
package/src/css/base.css
CHANGED
|
@@ -5,10 +5,6 @@
|
|
|
5
5
|
box-sizing: border-box;
|
|
6
6
|
}
|
|
7
7
|
|
|
8
|
-
canvas {
|
|
9
|
-
width: 100% !important;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
8
|
li {
|
|
13
9
|
list-style: none;
|
|
14
10
|
}
|
|
@@ -22,16 +18,6 @@
|
|
|
22
18
|
text-align: left;
|
|
23
19
|
}
|
|
24
20
|
|
|
25
|
-
::-webkit-scrollbar {
|
|
26
|
-
display: none;
|
|
27
|
-
-webkit-appearance: none;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
::-webkit-scrollbar-button {
|
|
31
|
-
display: none;
|
|
32
|
-
-webkit-appearance: none;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
21
|
input::-webkit-outer-spin-button,
|
|
36
22
|
input::-webkit-inner-spin-button {
|
|
37
23
|
-webkit-appearance: none;
|
package/src/css/theme.css
CHANGED
|
@@ -7,7 +7,8 @@
|
|
|
7
7
|
opacity: 0;
|
|
8
8
|
border-radius: inherit;
|
|
9
9
|
background: radial-gradient(
|
|
10
|
-
var(--margo-background-glow-size, 480px) circle at var(--margo-background-glow-x, 50%)
|
|
10
|
+
var(--margo-background-glow-size, 480px) circle at var(--margo-background-glow-x, 50%)
|
|
11
|
+
var(--margo-background-glow-y, 50%),
|
|
11
12
|
var(--color-primary),
|
|
12
13
|
transparent 70%
|
|
13
14
|
);
|
|
@@ -30,13 +31,10 @@
|
|
|
30
31
|
|
|
31
32
|
@media (hover: hover) and (pointer: fine) {
|
|
32
33
|
.margo-background-glow:hover::before {
|
|
33
|
-
opacity: var(--margo-background-glow-opacity, 0.
|
|
34
|
+
opacity: var(--margo-background-glow-opacity, 0.2);
|
|
34
35
|
}
|
|
35
36
|
|
|
36
37
|
.margo-background-glow:hover::after {
|
|
37
38
|
opacity: var(--margo-background-glow-noise-opacity, 0.04);
|
|
38
39
|
}
|
|
39
40
|
}
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import { cloneElement } from "react";
|
|
2
2
|
|
|
3
3
|
import { cn } from "../../utils/cn/cn.js";
|
|
4
|
-
import { borderGlowBaseClassName,
|
|
4
|
+
import { borderGlowBaseClassName, borderGlowPlacementClassName } from "./style.js";
|
|
5
5
|
|
|
6
6
|
import type { PointerEvent } from "react";
|
|
7
7
|
import type { BorderGlowProps } from "./type.js";
|
|
8
8
|
|
|
9
9
|
import "./border_glow.css";
|
|
10
10
|
|
|
11
|
-
export const BorderGlow = ({ children,
|
|
11
|
+
export const BorderGlow = ({ children, placement = "all", tolerance = 1 }: BorderGlowProps) => {
|
|
12
12
|
const handlePointerMove = (event: PointerEvent<HTMLElement>) => {
|
|
13
13
|
if (event.pointerType !== "mouse") return children.props.onPointerMove?.(event);
|
|
14
14
|
|
|
@@ -18,14 +18,17 @@ export const BorderGlow = ({ children, position = "all", tolerance = 1 }: Border
|
|
|
18
18
|
const size = Math.max(bounds.width, bounds.height) * Math.min(Math.max(tolerance, 0), 1);
|
|
19
19
|
|
|
20
20
|
event.currentTarget.style.setProperty("--margo-border-glow-size", `${size}px`);
|
|
21
|
-
event.currentTarget.style.setProperty("--margo-border-glow-x", `${
|
|
22
|
-
event.currentTarget.style.setProperty(
|
|
21
|
+
event.currentTarget.style.setProperty("--margo-border-glow-x", `${placement === "right" ? bounds.width - x : x}px`);
|
|
22
|
+
event.currentTarget.style.setProperty(
|
|
23
|
+
"--margo-border-glow-y",
|
|
24
|
+
`${placement === "bottom" ? bounds.height - y : y}px`,
|
|
25
|
+
);
|
|
23
26
|
|
|
24
27
|
children.props.onPointerMove?.(event);
|
|
25
28
|
};
|
|
26
29
|
|
|
27
30
|
return cloneElement(children, {
|
|
28
|
-
className: cn(borderGlowBaseClassName,
|
|
31
|
+
className: cn(borderGlowBaseClassName, borderGlowPlacementClassName[placement], children.props.className),
|
|
29
32
|
onPointerMove: handlePointerMove,
|
|
30
33
|
});
|
|
31
34
|
};
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { BorderGlowPlacement } from "./type.js";
|
|
2
2
|
|
|
3
3
|
export const borderGlowBaseClassName = "relative isolate margo-border-glow";
|
|
4
4
|
|
|
5
|
-
export const
|
|
6
|
-
|
|
7
|
-
|
|
5
|
+
export const borderGlowPlacementClassName: Record<BorderGlowPlacement, string> = {
|
|
6
|
+
top: "margo-border-glow--edge-top",
|
|
7
|
+
bottom: "margo-border-glow--edge-bottom",
|
|
8
8
|
left: "margo-border-glow--edge-left",
|
|
9
9
|
right: "margo-border-glow--edge-right",
|
|
10
10
|
all: "margo-border-glow--ring",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { PointerEventHandler, ReactElement } from "react";
|
|
2
2
|
|
|
3
|
-
export type
|
|
3
|
+
export type BorderGlowPlacement = "top" | "right" | "bottom" | "left" | "all";
|
|
4
4
|
|
|
5
5
|
export type BorderGlowChildProps = {
|
|
6
6
|
className?: string;
|
|
@@ -9,6 +9,6 @@ export type BorderGlowChildProps = {
|
|
|
9
9
|
|
|
10
10
|
export type BorderGlowProps = {
|
|
11
11
|
children: ReactElement<BorderGlowChildProps>;
|
|
12
|
-
|
|
12
|
+
placement?: BorderGlowPlacement;
|
|
13
13
|
tolerance?: number;
|
|
14
14
|
};
|
|
@@ -9,7 +9,11 @@ const readKey = (target: EventTarget | null, attribute: string) => {
|
|
|
9
9
|
return holder?.getAttribute(attribute) ?? null;
|
|
10
10
|
};
|
|
11
11
|
|
|
12
|
-
export const PointerHolder = ({
|
|
12
|
+
export const PointerHolder = ({
|
|
13
|
+
children,
|
|
14
|
+
attribute = "data-margo-pointer-holder",
|
|
15
|
+
disabled = false,
|
|
16
|
+
}: PointerHolderProps) => {
|
|
13
17
|
const [keys, setKeys] = useState<string[]>([]);
|
|
14
18
|
|
|
15
19
|
const hold = (target: EventTarget | null) => {
|
|
@@ -1,12 +1,10 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { PointerEventHandler, ReactElement } from "react";
|
|
2
2
|
|
|
3
3
|
export type PointerHolderApi = {
|
|
4
4
|
keys: string[];
|
|
5
5
|
};
|
|
6
6
|
|
|
7
7
|
export type PointerHolderChildProps = {
|
|
8
|
-
onBlur?: FocusEventHandler<HTMLElement>;
|
|
9
|
-
onFocus?: FocusEventHandler<HTMLElement>;
|
|
10
8
|
onPointerLeave?: PointerEventHandler<HTMLElement>;
|
|
11
9
|
onPointerOver?: PointerEventHandler<HTMLElement>;
|
|
12
10
|
};
|
package/src/index.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export { Blockquote } from "./components/blockquote/blockquote.js";
|
|
2
2
|
export { Button } from "./components/button/button.js";
|
|
3
3
|
export { ButtonMicro } from "./components/button_micro/button_micro.js";
|
|
4
|
+
export { Callout } from "./components/callout/callout.js";
|
|
4
5
|
export { Card } from "./components/card/card.js";
|
|
5
6
|
export { Checkbox } from "./components/checkbox/checkbox.js";
|
|
6
7
|
export { Chip } from "./components/chip/chip.js";
|
|
@@ -17,6 +18,8 @@ export { Table } from "./components/table/table.js";
|
|
|
17
18
|
export { Toggle } from "./components/toggle/toggle.js";
|
|
18
19
|
export { Select } from "./components/select/select.js";
|
|
19
20
|
export { Sheet } from "./components/sheet/sheet.js";
|
|
21
|
+
export { Slider } from "./components/slider/slider.js";
|
|
22
|
+
export { TextArea } from "./components/text_area/text_area.js";
|
|
20
23
|
export { Spinner } from "./components/spinner/spinner.js";
|
|
21
24
|
export { Tooltip } from "./components/tooltip/tooltip.js";
|
|
22
25
|
|
|
@@ -39,12 +42,13 @@ export type { BlockquoteProps } from "./components/blockquote/type.js";
|
|
|
39
42
|
|
|
40
43
|
export type {
|
|
41
44
|
ButtonIconLabelProps,
|
|
42
|
-
|
|
45
|
+
ButtonIconLabelDirection,
|
|
43
46
|
ButtonIconProps,
|
|
44
47
|
ButtonLabelProps,
|
|
45
48
|
ButtonProps,
|
|
46
49
|
} from "./components/button/type.js";
|
|
47
50
|
export type { ButtonMicroProps } from "./components/button_micro/type.js";
|
|
51
|
+
export type { CalloutProps, CalloutTitleProps } from "./components/callout/type.js";
|
|
48
52
|
export type { CardProps } from "./components/card/type.js";
|
|
49
53
|
export type { CheckboxProps } from "./components/checkbox/type.js";
|
|
50
54
|
export type { ChipProps } from "./components/chip/type.js";
|
|
@@ -60,7 +64,13 @@ export type { LabelOwnProps, LabelProps } from "./components/label/type.js";
|
|
|
60
64
|
export type { LayerProps } from "./components/layer/type.js";
|
|
61
65
|
export type { InputIconProps, InputProps, InputTextProps } from "./components/input/type.js";
|
|
62
66
|
export type { ItemIconProps, ItemLabelProps, ItemProps } from "./components/item/type.js";
|
|
63
|
-
export type {
|
|
67
|
+
export type {
|
|
68
|
+
PopoverAlign,
|
|
69
|
+
PopoverAnchorProps,
|
|
70
|
+
PopoverBodyProps,
|
|
71
|
+
PopoverPlacement,
|
|
72
|
+
PopoverProps,
|
|
73
|
+
} from "./components/popover/type.js";
|
|
64
74
|
export type { ProgressBarMode, ProgressBarProps } from "./components/progress_bar/type.js";
|
|
65
75
|
export type {
|
|
66
76
|
TableBodyProps,
|
|
@@ -71,13 +81,15 @@ export type {
|
|
|
71
81
|
TableRowProps,
|
|
72
82
|
} from "./components/table/type.js";
|
|
73
83
|
export type { SelectOwnProps, SelectProps } from "./components/select/type.js";
|
|
74
|
-
export type { SheetBodyProps, SheetFooterProps,
|
|
84
|
+
export type { SheetBodyProps, SheetFooterProps, SheetPlacement, SheetProps } from "./components/sheet/type.js";
|
|
85
|
+
export type { SliderProps } from "./components/slider/type.js";
|
|
75
86
|
export type { SpinnerProps } from "./components/spinner/type.js";
|
|
87
|
+
export type { TextAreaOwnProps, TextAreaProps, TextAreaTextProps } from "./components/text_area/type.js";
|
|
76
88
|
export type { ToggleProps } from "./components/toggle/type.js";
|
|
77
|
-
export type {
|
|
89
|
+
export type { TooltipPlacement, TooltipProps } from "./components/tooltip/type.js";
|
|
78
90
|
|
|
79
91
|
export type { BackgroundGlowProps } from "./hoc/background_glow/type.js";
|
|
80
|
-
export type {
|
|
92
|
+
export type { BorderGlowPlacement, BorderGlowProps } from "./hoc/border_glow/type.js";
|
|
81
93
|
export type { PointerHolderProps } from "./hoc/pointer_holder/type.js";
|
|
82
94
|
export type { MaskGradientXProps } from "./hoc/mask_gradient_x/type.js";
|
|
83
95
|
export type { MaskGradientYProps } from "./hoc/mask_gradient_y/type.js";
|
package/src/utils/cn/cn.ts
CHANGED
|
@@ -9,6 +9,9 @@ const isColumnLine = (value: string) => value === "full" || value === "content"
|
|
|
9
9
|
|
|
10
10
|
const isMargoRadiusStep = (value: string) => /^margo-(mc|xs|sm|base)$/.test(value);
|
|
11
11
|
|
|
12
|
+
const MARGO_LEADING_STEPS = ["mc", "xs", "sm", "md", "lg", "base", "xl", "2xl"];
|
|
13
|
+
const MARGO_SHADOWS = ["card", "button", "item", "chip"];
|
|
14
|
+
|
|
12
15
|
const BORDER_SIDES = ["", "x", "y", "s", "e", "t", "r", "b", "l"] as const;
|
|
13
16
|
const RADIUS_CORNERS = ["", "s", "e", "t", "r", "b", "l", "ss", "se", "ee", "es", "tl", "tr", "br", "bl"] as const;
|
|
14
17
|
|
|
@@ -40,9 +43,16 @@ type MargoClassGroupIds =
|
|
|
40
43
|
| "margo-padding";
|
|
41
44
|
|
|
42
45
|
const twMerge = extendTailwindMerge<MargoClassGroupIds>({
|
|
46
|
+
override: {
|
|
47
|
+
conflictingClassGroups: {
|
|
48
|
+
"font-size": [],
|
|
49
|
+
},
|
|
50
|
+
},
|
|
43
51
|
extend: {
|
|
44
52
|
classGroups: {
|
|
45
53
|
"font-size": ["text-mc"],
|
|
54
|
+
leading: [{ leading: MARGO_LEADING_STEPS }],
|
|
55
|
+
shadow: [{ shadow: MARGO_SHADOWS }],
|
|
46
56
|
...borderWidthGroups,
|
|
47
57
|
...radiusGroups,
|
|
48
58
|
"margo-col": [{ "margo-col": [isColumnLine] }],
|