@uxf/ui 1.0.0-beta.16 → 1.0.0-beta.18
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 +1 -1
- package/button/button.css +0 -75
- package/button/button.stories.tsx +0 -98
- package/button/button.tsx +0 -36
- package/button/index.ts +0 -2
- package/button/theme.ts +0 -20
- package/image-gallery/components/close-button.tsx +0 -19
- package/image-gallery/components/dot.tsx +0 -17
- package/image-gallery/components/gallery.tsx +0 -67
- package/image-gallery/components/icon-chevron-left.tsx +0 -18
- package/image-gallery/components/icon-chevron-right.tsx +0 -18
- package/image-gallery/components/icon-close.tsx +0 -22
- package/image-gallery/components/next-button.tsx +0 -19
- package/image-gallery/components/previous-button.tsx +0 -19
- package/image-gallery/context.tsx +0 -17
- package/image-gallery/image-gallery.stories.tsx +0 -33
- package/image-gallery/image-gallery.tsx +0 -59
- package/image-gallery/image.tsx +0 -19
- package/image-gallery/index.ts +0 -3
- package/image-gallery/types.ts +0 -6
- package/image-gallery/use-image.ts +0 -17
- package/input/index.ts +0 -14
- package/input/input-basic.css +0 -18
- package/input/input-element.tsx +0 -30
- package/input/input-left-addon.tsx +0 -12
- package/input/input-left-element.tsx +0 -11
- package/input/input-right-addon.tsx +0 -11
- package/input/input-right-element.tsx +0 -11
- package/input/input.css +0 -75
- package/input/input.stories.tsx +0 -79
- package/input/input.tsx +0 -70
- package/input/theme.ts +0 -7
- package/text-input/index.ts +0 -1
- package/text-input/text-input.css +0 -29
- package/text-input/text-input.stories.tsx +0 -72
- package/text-input/text-input.tsx +0 -99
- package/tsconfig.json +0 -7
- package/tsconfig.tsbuildinfo +0 -1
- package/types/form-control-props.ts +0 -35
- package/types/index.ts +0 -1
- package/utils/action.ts +0 -14
- package/utils/component-structure-analyzer.css +0 -28
- package/utils/component-structure-analyzer.tsx +0 -12
- package/utils/cx.ts +0 -56
- package/utils/forwardRef.ts +0 -30
- package/utils/storybook-config.tsx +0 -42
package/package.json
CHANGED
package/button/button.css
DELETED
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
.button {
|
|
2
|
-
@apply inline-flex items-center rounded font-medium shadow-md shadow-sm focus:outline-none focus:ring-2 focus:ring-offset-2;
|
|
3
|
-
|
|
4
|
-
&--disabled {
|
|
5
|
-
@apply pointer-events-none opacity-40;
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
&--size-xs {
|
|
9
|
-
@apply px-2.5 py-1.5 text-xs;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
&--size-sm {
|
|
13
|
-
@apply px-3 py-2 text-sm leading-4;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
&--size-default {
|
|
17
|
-
@apply px-4 py-2 text-sm;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
&--size-lg {
|
|
21
|
-
@apply px-4 py-2 text-base;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
&--size-xl {
|
|
25
|
-
@apply border px-6 py-3 text-base;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
&--variant-outlined {
|
|
29
|
-
@apply border bg-white;
|
|
30
|
-
|
|
31
|
-
&.button--color-default {
|
|
32
|
-
@apply border-primary-500 text-primary-700 hover:bg-primary-50 focus:ring-primary-500;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
&.button--color-white {
|
|
36
|
-
@apply border-gray-300 text-gray-700 hover:bg-gray-50 focus:ring-gray-500;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
&.button--color-success {
|
|
40
|
-
@apply border-success-500 text-success-700 hover:bg-success-50 focus:ring-success-500;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
&.button--color-warning {
|
|
44
|
-
@apply border-warning-500 text-warning-700 hover:bg-warning-50 focus:ring-warning-500;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
&.button--color-error {
|
|
48
|
-
@apply border-error-500 text-error-700 hover:bg-error-50 focus:ring-error-500;
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
&--variant-default {
|
|
53
|
-
@apply border-transparent text-white;
|
|
54
|
-
|
|
55
|
-
&.button--color-default {
|
|
56
|
-
@apply bg-primary-500 hover:bg-primary-600 focus:ring-primary-400;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
&.button--color-white {
|
|
60
|
-
@apply bg-gray-50 text-gray-700 shadow-none hover:bg-gray-100 focus:ring-gray-500;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
&.button--color-success {
|
|
64
|
-
@apply bg-success-500 hover:bg-success-600 focus:ring-success-400;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
&.button--color-warning {
|
|
68
|
-
@apply bg-warning-500 hover:bg-warning-600 focus:ring-warning-400;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
&.button--color-error {
|
|
72
|
-
@apply bg-error-500 hover:bg-error-600 focus:ring-error-400;
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
}
|
|
@@ -1,98 +0,0 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
import { Button } from "@uxf/ui/button";
|
|
3
|
-
import { useStorybookConfig } from "@uxf/ui/utils/storybook-config";
|
|
4
|
-
import { Fragment } from "react";
|
|
5
|
-
|
|
6
|
-
export default {
|
|
7
|
-
title: "UI/Button",
|
|
8
|
-
component: Button,
|
|
9
|
-
};
|
|
10
|
-
|
|
11
|
-
export function Default() {
|
|
12
|
-
const config = useStorybookConfig("Button");
|
|
13
|
-
|
|
14
|
-
return (
|
|
15
|
-
<div className="space-y-2">
|
|
16
|
-
{config.variants.map((variant) => (
|
|
17
|
-
<Fragment key={variant}>
|
|
18
|
-
{config.colors.map((color) => (
|
|
19
|
-
<Fragment key={color}>
|
|
20
|
-
{config.sizes.map((size) => (
|
|
21
|
-
<div>
|
|
22
|
-
<Button
|
|
23
|
-
key={size}
|
|
24
|
-
variant={variant}
|
|
25
|
-
color={color}
|
|
26
|
-
size={size}
|
|
27
|
-
>
|
|
28
|
-
Button
|
|
29
|
-
</Button>
|
|
30
|
-
</div>
|
|
31
|
-
))}
|
|
32
|
-
</Fragment>
|
|
33
|
-
))}
|
|
34
|
-
</Fragment>
|
|
35
|
-
))}
|
|
36
|
-
</div>
|
|
37
|
-
);
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
export function Disabled() {
|
|
41
|
-
const config = useStorybookConfig("Button");
|
|
42
|
-
|
|
43
|
-
return (
|
|
44
|
-
<div className="space-y-2">
|
|
45
|
-
{config.variants.map((variant) => (
|
|
46
|
-
<Fragment key={variant}>
|
|
47
|
-
{config.colors.map((color) => (
|
|
48
|
-
<Fragment key={color}>
|
|
49
|
-
{config.sizes.map((size) => (
|
|
50
|
-
<div>
|
|
51
|
-
<Button
|
|
52
|
-
key={size}
|
|
53
|
-
variant={variant}
|
|
54
|
-
color={color}
|
|
55
|
-
size={size}
|
|
56
|
-
disabled
|
|
57
|
-
>
|
|
58
|
-
Button
|
|
59
|
-
</Button>
|
|
60
|
-
</div>
|
|
61
|
-
))}
|
|
62
|
-
</Fragment>
|
|
63
|
-
))}
|
|
64
|
-
</Fragment>
|
|
65
|
-
))}
|
|
66
|
-
</div>
|
|
67
|
-
);
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
export function Loading() {
|
|
71
|
-
const config = useStorybookConfig("Button");
|
|
72
|
-
|
|
73
|
-
return (
|
|
74
|
-
<div className="space-y-2">
|
|
75
|
-
{config.variants.map((variant) => (
|
|
76
|
-
<Fragment key={variant}>
|
|
77
|
-
{config.colors.map((color) => (
|
|
78
|
-
<Fragment key={color}>
|
|
79
|
-
{config.sizes.map((size) => (
|
|
80
|
-
<div>
|
|
81
|
-
<Button
|
|
82
|
-
key={size}
|
|
83
|
-
variant={variant}
|
|
84
|
-
color={color}
|
|
85
|
-
size={size}
|
|
86
|
-
loading
|
|
87
|
-
>
|
|
88
|
-
Button
|
|
89
|
-
</Button>
|
|
90
|
-
</div>
|
|
91
|
-
))}
|
|
92
|
-
</Fragment>
|
|
93
|
-
))}
|
|
94
|
-
</Fragment>
|
|
95
|
-
))}
|
|
96
|
-
</div>
|
|
97
|
-
);
|
|
98
|
-
}
|
package/button/button.tsx
DELETED
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
import React, { ReactNode } from "react";
|
|
2
|
-
import { ButtonColors, ButtonSizes, ButtonVariants } from "@uxf/ui/button";
|
|
3
|
-
import { cx } from "@uxf/core/utils/cx";
|
|
4
|
-
|
|
5
|
-
interface ButtonProps {
|
|
6
|
-
variant?: keyof ButtonVariants;
|
|
7
|
-
color?: keyof ButtonColors;
|
|
8
|
-
size?: keyof ButtonSizes;
|
|
9
|
-
disabled?: boolean;
|
|
10
|
-
loading?: boolean;
|
|
11
|
-
startAdornment?: ReactNode;
|
|
12
|
-
endAdornment?: ReactNode;
|
|
13
|
-
type?: "button" | "submit" | "reset";
|
|
14
|
-
children: ReactNode;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
function Button(props: ButtonProps) {
|
|
18
|
-
const className = cx(
|
|
19
|
-
"button",
|
|
20
|
-
`button--color-${props.color ?? "default"}`,
|
|
21
|
-
`button--size-${props.size ?? "default"}`,
|
|
22
|
-
`button--variant-${props.variant ?? "default"}`,
|
|
23
|
-
props.disabled && `button--disabled`,
|
|
24
|
-
props.loading && `button--loading`
|
|
25
|
-
);
|
|
26
|
-
|
|
27
|
-
return (
|
|
28
|
-
<button type={props.type} className={className}>
|
|
29
|
-
{props.startAdornment}
|
|
30
|
-
{props.children}
|
|
31
|
-
{props.endAdornment}
|
|
32
|
-
</button>
|
|
33
|
-
);
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
export default Button;
|
package/button/index.ts
DELETED
package/button/theme.ts
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
export interface ButtonVariants {
|
|
2
|
-
outlined: true;
|
|
3
|
-
default: true;
|
|
4
|
-
}
|
|
5
|
-
|
|
6
|
-
export interface ButtonSizes {
|
|
7
|
-
xs: true;
|
|
8
|
-
sm: true;
|
|
9
|
-
default: true;
|
|
10
|
-
lg: true;
|
|
11
|
-
xl: true;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
export interface ButtonColors {
|
|
15
|
-
default: true;
|
|
16
|
-
white: true;
|
|
17
|
-
success: true;
|
|
18
|
-
warning: true;
|
|
19
|
-
error: true;
|
|
20
|
-
}
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
import IconClose from "./icon-close";
|
|
3
|
-
|
|
4
|
-
interface CloseButtonProps {
|
|
5
|
-
onClick: () => void;
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
function CloseButton(props: CloseButtonProps) {
|
|
9
|
-
return (
|
|
10
|
-
<button
|
|
11
|
-
className="bg-black bg-opacity-50 p-3"
|
|
12
|
-
onClick={() => props.onClick()}
|
|
13
|
-
>
|
|
14
|
-
<IconClose />
|
|
15
|
-
</button>
|
|
16
|
-
);
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
export default CloseButton;
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import { cx } from "@uxf/core/utils/cx";
|
|
2
|
-
import React from "react";
|
|
3
|
-
|
|
4
|
-
interface DotProps {
|
|
5
|
-
active?: boolean;
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
function Dot(props: DotProps) {
|
|
9
|
-
const className = cx(
|
|
10
|
-
"h-2 w-2 rounded-full",
|
|
11
|
-
props.active ? "bg-gray-500" : "bg-white"
|
|
12
|
-
);
|
|
13
|
-
|
|
14
|
-
return <div className={className} />;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
export default Dot;
|
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
import CloseButton from "./close-button";
|
|
2
|
-
import PreviousButton from "./previous-button";
|
|
3
|
-
import NextButton from "./next-button";
|
|
4
|
-
import Dot from "./dot";
|
|
5
|
-
import React, { useEffect } from "react";
|
|
6
|
-
import { ImageGalleryImageProps } from "../types";
|
|
7
|
-
|
|
8
|
-
interface GalleryProps {
|
|
9
|
-
onClose: () => void;
|
|
10
|
-
onNext: () => void;
|
|
11
|
-
onPrevious: () => void;
|
|
12
|
-
imageIndex: number;
|
|
13
|
-
images: ImageGalleryImageProps[];
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
function Gallery(props: GalleryProps) {
|
|
17
|
-
useEffect(() => {
|
|
18
|
-
const onKeyDown = (event: KeyboardEvent) => {
|
|
19
|
-
switch (event.key) {
|
|
20
|
-
case "ArrowRight":
|
|
21
|
-
props.onNext();
|
|
22
|
-
break;
|
|
23
|
-
case "ArrowLeft":
|
|
24
|
-
props.onPrevious();
|
|
25
|
-
break;
|
|
26
|
-
case "Escape":
|
|
27
|
-
props.onClose();
|
|
28
|
-
break;
|
|
29
|
-
}
|
|
30
|
-
};
|
|
31
|
-
|
|
32
|
-
document.body.style.overflow = "hidden";
|
|
33
|
-
window.addEventListener("keydown", onKeyDown);
|
|
34
|
-
|
|
35
|
-
return () => {
|
|
36
|
-
document.body.style.overflow = "auto";
|
|
37
|
-
window.removeEventListener("keydown", onKeyDown);
|
|
38
|
-
};
|
|
39
|
-
}, []);
|
|
40
|
-
|
|
41
|
-
return (
|
|
42
|
-
<div className="fixed inset-0 top-0 bottom-0 z-50 flex flex-col bg-black bg-opacity-75 transition-opacity">
|
|
43
|
-
<div className="flex justify-end">
|
|
44
|
-
<CloseButton onClick={props.onClose} />
|
|
45
|
-
</div>
|
|
46
|
-
<div className="container mx-auto flex h-full flex-1 flex-col">
|
|
47
|
-
<div className="relative flex flex-1 items-center justify-center">
|
|
48
|
-
<img
|
|
49
|
-
className="absolute left-0 right-0 top-0 h-full w-full object-contain"
|
|
50
|
-
src={props.images[props.imageIndex].src}
|
|
51
|
-
/>
|
|
52
|
-
<div className="pointer-events-none absolute inset-0 flex items-center justify-between p-2">
|
|
53
|
-
<PreviousButton onClick={props.onPrevious} />
|
|
54
|
-
<NextButton onClick={props.onNext} />
|
|
55
|
-
</div>
|
|
56
|
-
</div>
|
|
57
|
-
</div>
|
|
58
|
-
<div className="row mx-auto flex space-x-2 p-4">
|
|
59
|
-
{props.images.map((url, index) => (
|
|
60
|
-
<Dot key={url.src} active={index === props.imageIndex} />
|
|
61
|
-
))}
|
|
62
|
-
</div>
|
|
63
|
-
</div>
|
|
64
|
-
);
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
export default Gallery;
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
|
|
3
|
-
function IconChevronLeft() {
|
|
4
|
-
return (
|
|
5
|
-
<svg
|
|
6
|
-
xmlns="http://www.w3.org/2000/svg"
|
|
7
|
-
className="h-10 w-10 text-white"
|
|
8
|
-
fill="none"
|
|
9
|
-
viewBox="0 0 24 24"
|
|
10
|
-
stroke="currentColor"
|
|
11
|
-
strokeWidth={2}
|
|
12
|
-
>
|
|
13
|
-
<path strokeLinecap="round" strokeLinejoin="round" d="M15 19l-7-7 7-7" />
|
|
14
|
-
</svg>
|
|
15
|
-
);
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export default IconChevronLeft;
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
|
|
3
|
-
function IconChevronRight() {
|
|
4
|
-
return (
|
|
5
|
-
<svg
|
|
6
|
-
xmlns="http://www.w3.org/2000/svg"
|
|
7
|
-
className="h-10 w-10 text-white"
|
|
8
|
-
fill="none"
|
|
9
|
-
viewBox="0 0 24 24"
|
|
10
|
-
stroke="currentColor"
|
|
11
|
-
strokeWidth={2}
|
|
12
|
-
>
|
|
13
|
-
<path strokeLinecap="round" strokeLinejoin="round" d="M9 5l7 7-7 7" />
|
|
14
|
-
</svg>
|
|
15
|
-
);
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export default IconChevronRight;
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
|
|
3
|
-
function IconClose() {
|
|
4
|
-
return (
|
|
5
|
-
<svg
|
|
6
|
-
xmlns="http://www.w3.org/2000/svg"
|
|
7
|
-
fill="none"
|
|
8
|
-
viewBox="0 0 24 24"
|
|
9
|
-
stroke="currentColor"
|
|
10
|
-
strokeWidth={2}
|
|
11
|
-
className="h-10 w-10 text-white"
|
|
12
|
-
>
|
|
13
|
-
<path
|
|
14
|
-
strokeLinecap="round"
|
|
15
|
-
strokeLinejoin="round"
|
|
16
|
-
d="M6 18L18 6M6 6l12 12"
|
|
17
|
-
/>
|
|
18
|
-
</svg>
|
|
19
|
-
);
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
export default IconClose;
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
import IconChevronRight from "./icon-chevron-right";
|
|
3
|
-
|
|
4
|
-
interface NextButtonProps {
|
|
5
|
-
onClick: () => void;
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
function NextButton(props: NextButtonProps) {
|
|
9
|
-
return (
|
|
10
|
-
<button
|
|
11
|
-
className="pointer-events-auto rounded-full bg-black bg-opacity-50 p-2"
|
|
12
|
-
onClick={props.onClick}
|
|
13
|
-
>
|
|
14
|
-
<IconChevronRight />
|
|
15
|
-
</button>
|
|
16
|
-
);
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
export default NextButton;
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
import IconChevronLeft from "./icon-chevron-left";
|
|
3
|
-
|
|
4
|
-
interface PreviousButtonProps {
|
|
5
|
-
onClick: () => void;
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
function PreviousButton(props: PreviousButtonProps) {
|
|
9
|
-
return (
|
|
10
|
-
<button
|
|
11
|
-
className="pointer-events-auto rounded-full bg-black bg-opacity-50 p-2"
|
|
12
|
-
onClick={props.onClick}
|
|
13
|
-
>
|
|
14
|
-
<IconChevronLeft />
|
|
15
|
-
</button>
|
|
16
|
-
);
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
export default PreviousButton;
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import { createContext, useContext } from "react";
|
|
2
|
-
import { ImageGalleryImageProps } from "./types";
|
|
3
|
-
|
|
4
|
-
type ContextType = {
|
|
5
|
-
registerImage: (props: ImageGalleryImageProps) => void;
|
|
6
|
-
unregisterImage: (props: ImageGalleryImageProps) => void;
|
|
7
|
-
openGallery: (props: ImageGalleryImageProps) => void;
|
|
8
|
-
};
|
|
9
|
-
|
|
10
|
-
const ImageGalleryContext = createContext<ContextType>({
|
|
11
|
-
registerImage: () => null,
|
|
12
|
-
unregisterImage: () => null,
|
|
13
|
-
openGallery: () => null,
|
|
14
|
-
});
|
|
15
|
-
|
|
16
|
-
export const ImageGalleryProvider = ImageGalleryContext.Provider;
|
|
17
|
-
export const useImageGalleryContext = () => useContext(ImageGalleryContext);
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
import ImageGallery from "./image-gallery";
|
|
3
|
-
import Image from "./image";
|
|
4
|
-
|
|
5
|
-
export default {
|
|
6
|
-
title: "Lab/ImageGallery",
|
|
7
|
-
component: ImageGallery,
|
|
8
|
-
parameters: { actions: { argTypesRegex: "^on.*" } },
|
|
9
|
-
};
|
|
10
|
-
|
|
11
|
-
const images = [
|
|
12
|
-
"https://opentopo.app/hero_image.jpeg",
|
|
13
|
-
"https://opentopo.app/generated/area-18/d/9/d9033d93-ea48-4f66-b0c1-6045c091b326_1024_1024_c.jpg",
|
|
14
|
-
"https://opentopo.app/generated/area-16/f/4/f4a4ca79-ea9e-44d1-a4ec-3c8ccfbcc218_1024_1024_c.jpg",
|
|
15
|
-
"https://opentopo.app/generated/area-1/8/b/8b84e378-1f55-4ce7-b750-b504091cb833_1024_1024_c.jpg",
|
|
16
|
-
"https://opentopo.app/generated/area-2/e/7/e7ec532b-20c2-407e-9305-fa7cfb71f01f_1024_1024_c.jpg",
|
|
17
|
-
];
|
|
18
|
-
|
|
19
|
-
export function Default() {
|
|
20
|
-
return (
|
|
21
|
-
<ImageGallery>
|
|
22
|
-
<div className="flex-direction flex gap-2">
|
|
23
|
-
{images.map((src) => (
|
|
24
|
-
<Image
|
|
25
|
-
key={src}
|
|
26
|
-
src={src}
|
|
27
|
-
className="h-56 w-56 cursor-pointer object-cover transition-transform hover:scale-105"
|
|
28
|
-
/>
|
|
29
|
-
))}
|
|
30
|
-
</div>
|
|
31
|
-
</ImageGallery>
|
|
32
|
-
);
|
|
33
|
-
}
|
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
import React, { ReactNode, useCallback, useState } from "react";
|
|
2
|
-
import { ImageGalleryProvider } from "./context";
|
|
3
|
-
import { ImageGalleryImageProps } from "./types";
|
|
4
|
-
import Gallery from "./components/gallery";
|
|
5
|
-
|
|
6
|
-
interface ImageGalleryProviderProps {
|
|
7
|
-
children: ReactNode;
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
function ImageGallery(props: ImageGalleryProviderProps) {
|
|
11
|
-
const [images, setImages] = useState<ImageGalleryImageProps[]>([]);
|
|
12
|
-
const [imageIndex, setImageIndex] = useState<null | number>(null);
|
|
13
|
-
|
|
14
|
-
const registerImage = (image: ImageGalleryImageProps) =>
|
|
15
|
-
setImages((v) => [...v, image]);
|
|
16
|
-
|
|
17
|
-
const unregisterImage = (image: ImageGalleryImageProps) =>
|
|
18
|
-
setImages((v) => v.filter((u) => u.src !== image.src));
|
|
19
|
-
|
|
20
|
-
const openGallery = (image: ImageGalleryImageProps) =>
|
|
21
|
-
setImageIndex(images.findIndex((i) => i.src === image.src));
|
|
22
|
-
|
|
23
|
-
const onPrevious = useCallback(() => {
|
|
24
|
-
setImageIndex((v) => (v === null ? null : v - 1));
|
|
25
|
-
}, []);
|
|
26
|
-
|
|
27
|
-
const onNext = useCallback(() => {
|
|
28
|
-
setImageIndex((v) => (v === null ? null : v + 1));
|
|
29
|
-
}, []);
|
|
30
|
-
|
|
31
|
-
// modulo bug https://stackoverflow.com/a/4467559
|
|
32
|
-
const moduloImageIndex =
|
|
33
|
-
imageIndex === null
|
|
34
|
-
? null
|
|
35
|
-
: imageIndex < 0
|
|
36
|
-
? ((imageIndex % images.length) + images.length) % images.length
|
|
37
|
-
: imageIndex % images.length;
|
|
38
|
-
|
|
39
|
-
const contextValue = { registerImage, unregisterImage, openGallery };
|
|
40
|
-
|
|
41
|
-
return (
|
|
42
|
-
<>
|
|
43
|
-
<ImageGalleryProvider value={contextValue}>
|
|
44
|
-
{props.children}
|
|
45
|
-
</ImageGalleryProvider>
|
|
46
|
-
{typeof moduloImageIndex === "number" && (
|
|
47
|
-
<Gallery
|
|
48
|
-
onClose={() => setImageIndex(null)}
|
|
49
|
-
onNext={onNext}
|
|
50
|
-
onPrevious={onPrevious}
|
|
51
|
-
imageIndex={moduloImageIndex}
|
|
52
|
-
images={images}
|
|
53
|
-
/>
|
|
54
|
-
)}
|
|
55
|
-
</>
|
|
56
|
-
);
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
export default ImageGallery;
|
package/image-gallery/image.tsx
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
import { useImage } from "./use-image";
|
|
3
|
-
import { ImageGalleryImageProps } from "@uxf/ui/image-gallery/types";
|
|
4
|
-
|
|
5
|
-
function Image(props: ImageGalleryImageProps) {
|
|
6
|
-
const openGallery = useImage(props);
|
|
7
|
-
|
|
8
|
-
return (
|
|
9
|
-
<img
|
|
10
|
-
src={props.src}
|
|
11
|
-
alt={props.alt}
|
|
12
|
-
title={props.title}
|
|
13
|
-
className={props.className}
|
|
14
|
-
onClick={() => openGallery(props)}
|
|
15
|
-
/>
|
|
16
|
-
);
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
export default Image;
|
package/image-gallery/index.ts
DELETED
package/image-gallery/types.ts
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import { useEffect } from "react";
|
|
2
|
-
import { useImageGalleryContext } from "./context";
|
|
3
|
-
import { ImageGalleryImageProps } from "./types";
|
|
4
|
-
|
|
5
|
-
export function useImage(props: ImageGalleryImageProps) {
|
|
6
|
-
const { registerImage, unregisterImage, openGallery } =
|
|
7
|
-
useImageGalleryContext();
|
|
8
|
-
|
|
9
|
-
useEffect(() => {
|
|
10
|
-
registerImage(props);
|
|
11
|
-
return () => {
|
|
12
|
-
unregisterImage(props);
|
|
13
|
-
};
|
|
14
|
-
}, [props]);
|
|
15
|
-
|
|
16
|
-
return openGallery;
|
|
17
|
-
}
|
package/input/index.ts
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import RootInput from "./input";
|
|
2
|
-
import Element from "./input-element";
|
|
3
|
-
import LeftElement from "./input-left-element";
|
|
4
|
-
import RightElement from "./input-right-element";
|
|
5
|
-
import LeftAddon from "./input-left-addon";
|
|
6
|
-
import RightAddon from "./input-right-addon";
|
|
7
|
-
|
|
8
|
-
export const Input = Object.assign(RootInput, {
|
|
9
|
-
Element,
|
|
10
|
-
LeftElement,
|
|
11
|
-
RightElement,
|
|
12
|
-
LeftAddon,
|
|
13
|
-
RightAddon,
|
|
14
|
-
});
|
package/input/input-basic.css
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
.uxf-input {
|
|
2
|
-
@apply flex flex-row;
|
|
3
|
-
}
|
|
4
|
-
|
|
5
|
-
.uxf-input__wrapper {
|
|
6
|
-
@apply flex w-full flex-row;
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
.uxf-input__element {
|
|
10
|
-
@apply w-full px-2;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
.uxf-input__left-element,
|
|
14
|
-
.uxf-input__right-element,
|
|
15
|
-
.uxf-input__left-addon,
|
|
16
|
-
.uxf-input__right-addon {
|
|
17
|
-
@apply flex flex-row items-center whitespace-nowrap;
|
|
18
|
-
}
|
package/input/input-element.tsx
DELETED
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
import { forwardRef } from "@uxf/ui/utils/forwardRef";
|
|
3
|
-
import { FormControlProps } from "@uxf/ui/types/form-control-props";
|
|
4
|
-
|
|
5
|
-
export interface InputElementProps extends FormControlProps<string> {
|
|
6
|
-
id?: string;
|
|
7
|
-
placeholder?: string;
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
type InputTypeRef = HTMLInputElement;
|
|
11
|
-
|
|
12
|
-
function InputElement(
|
|
13
|
-
props: InputElementProps,
|
|
14
|
-
ref: React.ForwardedRef<InputTypeRef>
|
|
15
|
-
) {
|
|
16
|
-
return (
|
|
17
|
-
<input
|
|
18
|
-
id={props.id}
|
|
19
|
-
ref={ref}
|
|
20
|
-
className="uxf-input__element"
|
|
21
|
-
value={props.value}
|
|
22
|
-
onFocus={props.onFocus}
|
|
23
|
-
onBlur={props.onBlur}
|
|
24
|
-
onChange={(event) => props.onChange?.(event.target.value, event)}
|
|
25
|
-
placeholder={props.placeholder}
|
|
26
|
-
/>
|
|
27
|
-
);
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
export default forwardRef("InputElement", InputElement);
|