@sunggang/ui-lib 0.0.5 → 0.0.7
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/index.esm.css +1082 -0
- package/index.esm.d.ts +1 -0
- package/index.esm.js +5870 -0
- package/package.json +5 -2
- package/src/components/ui/switch.d.ts +4 -0
- package/src/{index.ts → index.d.ts} +1 -2
- package/src/lib/DropImage/index.d.ts +14 -0
- package/src/lib/Modal/ErrorContent.d.ts +7 -0
- package/src/lib/Modal/Modal.d.ts +7 -0
- package/src/lib/Modal/ModalContent.d.ts +10 -0
- package/src/lib/Spin/index.d.ts +5 -0
- package/src/lib/UploadImage/BaseTemplate.d.ts +7 -0
- package/src/lib/UploadImage/CustomUpload.d.ts +10 -0
- package/src/lib/hello-server.d.ts +1 -0
- package/src/lib/uiLibrary.d.ts +4 -0
- package/src/lib/utils.d.ts +2 -0
- package/src/server.d.ts +1 -0
- package/.eslintrc.json +0 -18
- package/.storybook/main.js +0 -14
- package/.storybook/preview.js +0 -1
- package/.storybook/tailwind-imports.css +0 -81
- package/components.json +0 -15
- package/postcss.config.js +0 -10
- package/project.json +0 -31
- package/src/components/ui/switch.tsx +0 -27
- package/src/lib/DropImage/index.stories.tsx +0 -42
- package/src/lib/DropImage/index.tsx +0 -110
- package/src/lib/Modal/BaseModal.jsx +0 -52
- package/src/lib/Modal/ErrorContent.tsx +0 -21
- package/src/lib/Modal/FullScreenModal.jsx +0 -39
- package/src/lib/Modal/Modal.tsx +0 -36
- package/src/lib/Modal/ModalContent.tsx +0 -60
- package/src/lib/Modal/NoticeModal.jsx +0 -91
- package/src/lib/Modal/index.jsx +0 -1
- package/src/lib/Spin/index.tsx +0 -20
- package/src/lib/Switch/index.stories.tsx +0 -24
- package/src/lib/UploadImage/BaseTemplate.tsx +0 -73
- package/src/lib/UploadImage/CustomUpload.stories.tsx +0 -52
- package/src/lib/UploadImage/CustomUpload.tsx +0 -95
- package/src/lib/hello-server.tsx +0 -4
- package/src/lib/uiLibrary.module.css +0 -7
- package/src/lib/uiLibrary.spec.tsx +0 -10
- package/src/lib/uiLibrary.tsx +0 -14
- package/src/lib/utils.ts +0 -6
- package/src/server.ts +0 -2
- package/storybook-static/249.d700bcb8.iframe.bundle.js +0 -95
- package/storybook-static/249.d700bcb8.iframe.bundle.js.LICENSE.txt +0 -25
- package/storybook-static/249.d700bcb8.iframe.bundle.js.map +0 -1
- package/storybook-static/272.859c45b5.iframe.bundle.js +0 -1
- package/storybook-static/297.86b29044.iframe.bundle.js +0 -1
- package/storybook-static/301.7b83a51f.iframe.bundle.js +0 -1
- package/storybook-static/311.5beb2d3d.iframe.bundle.js +0 -1
- package/storybook-static/312.aa18d841.iframe.bundle.js +0 -1
- package/storybook-static/501.1fba3663.iframe.bundle.js +0 -1
- package/storybook-static/754.9ec23ac4.iframe.bundle.js +0 -1
- package/storybook-static/777.4b1d90f9.iframe.bundle.js +0 -1
- package/storybook-static/794.2230a3f3.iframe.bundle.js +0 -1
- package/storybook-static/852.18487f4c.iframe.bundle.js +0 -402
- package/storybook-static/852.18487f4c.iframe.bundle.js.LICENSE.txt +0 -23
- package/storybook-static/852.18487f4c.iframe.bundle.js.map +0 -1
- package/storybook-static/DropImage-index-stories.befa1b35.iframe.bundle.js +0 -1
- package/storybook-static/Switch-index-stories.9cfb2ba1.iframe.bundle.js +0 -1
- package/storybook-static/UploadImage-CustomUpload-stories.521444aa.iframe.bundle.js +0 -1
- package/storybook-static/favicon.svg +0 -7
- package/storybook-static/iframe.html +0 -370
- package/storybook-static/index.html +0 -151
- package/storybook-static/index.json +0 -1
- package/storybook-static/main.6f3c811b.iframe.bundle.js +0 -1
- package/storybook-static/project.json +0 -1
- package/storybook-static/runtime~main.28408b82.iframe.bundle.js +0 -1
- package/storybook-static/sb-addons/essentials-actions-2/manager-bundle.js +0 -3
- package/storybook-static/sb-addons/essentials-actions-2/manager-bundle.js.LEGAL.txt +0 -0
- package/storybook-static/sb-addons/essentials-backgrounds-3/manager-bundle.js +0 -12
- package/storybook-static/sb-addons/essentials-backgrounds-3/manager-bundle.js.LEGAL.txt +0 -0
- package/storybook-static/sb-addons/essentials-controls-1/manager-bundle.js +0 -79
- package/storybook-static/sb-addons/essentials-controls-1/manager-bundle.js.LEGAL.txt +0 -28
- package/storybook-static/sb-addons/essentials-measure-6/manager-bundle.js +0 -3
- package/storybook-static/sb-addons/essentials-measure-6/manager-bundle.js.LEGAL.txt +0 -0
- package/storybook-static/sb-addons/essentials-outline-7/manager-bundle.js +0 -3
- package/storybook-static/sb-addons/essentials-outline-7/manager-bundle.js.LEGAL.txt +0 -0
- package/storybook-static/sb-addons/essentials-toolbars-5/manager-bundle.js +0 -3
- package/storybook-static/sb-addons/essentials-toolbars-5/manager-bundle.js.LEGAL.txt +0 -0
- package/storybook-static/sb-addons/essentials-viewport-4/manager-bundle.js +0 -3
- package/storybook-static/sb-addons/essentials-viewport-4/manager-bundle.js.LEGAL.txt +0 -0
- package/storybook-static/sb-addons/storybook-core-server-presets-0/common-manager-bundle.js +0 -3
- package/storybook-static/sb-addons/storybook-core-server-presets-0/common-manager-bundle.js.LEGAL.txt +0 -0
- package/storybook-static/sb-common-assets/fonts.css +0 -31
- package/storybook-static/sb-common-assets/nunito-sans-bold-italic.woff2 +0 -0
- package/storybook-static/sb-common-assets/nunito-sans-bold.woff2 +0 -0
- package/storybook-static/sb-common-assets/nunito-sans-italic.woff2 +0 -0
- package/storybook-static/sb-common-assets/nunito-sans-regular.woff2 +0 -0
- package/storybook-static/sb-manager/WithTooltip-Y7J54OF7-KHQOWZXS.js +0 -1
- package/storybook-static/sb-manager/chunk-3F3RRPB3.js +0 -347
- package/storybook-static/sb-manager/chunk-62YMTM65.js +0 -6
- package/storybook-static/sb-manager/chunk-AQBE2B7B.js +0 -183
- package/storybook-static/sb-manager/chunk-Q3RBXCN3.js +0 -231
- package/storybook-static/sb-manager/chunk-XP3HGWTR.js +0 -1
- package/storybook-static/sb-manager/chunk-YME6VNXZ.js +0 -9
- package/storybook-static/sb-manager/formatter-B5HCVTEV-7DCBOGO6.js +0 -58
- package/storybook-static/sb-manager/globals-module-info.js +0 -1
- package/storybook-static/sb-manager/globals-runtime.js +0 -1
- package/storybook-static/sb-manager/globals.js +0 -1
- package/storybook-static/sb-manager/index.js +0 -1
- package/storybook-static/sb-manager/runtime.js +0 -1
- package/storybook-static/sb-manager/syntaxhighlighter-JOJW2KGS-WAFIMSO6.js +0 -1
- package/storybook-static/sb-preview/globals.js +0 -1
- package/storybook-static/sb-preview/runtime.js +0 -128
- package/tailwind.config.js +0 -76
- package/tsconfig.json +0 -25
- package/tsconfig.lib.json +0 -29
- package/tsconfig.storybook.json +0 -31
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
|
|
3
|
-
interface ModalContentProps {
|
|
4
|
-
title?: string;
|
|
5
|
-
setModal?: any;
|
|
6
|
-
children: React.ReactNode;
|
|
7
|
-
onClick?: any;
|
|
8
|
-
notice?: boolean;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
const ModalContent: React.FC<ModalContentProps> = ({
|
|
12
|
-
title,
|
|
13
|
-
setModal,
|
|
14
|
-
children,
|
|
15
|
-
onClick,
|
|
16
|
-
notice = false,
|
|
17
|
-
}) => (
|
|
18
|
-
<form>
|
|
19
|
-
{title && (
|
|
20
|
-
<div className="text-2xl text-gray-700 font-medium border-solid border-b border-gray-300 mb-4 p-4">
|
|
21
|
-
{title}
|
|
22
|
-
</div>
|
|
23
|
-
)}
|
|
24
|
-
|
|
25
|
-
{children && <div className="py-4 px-8">{children}</div>}
|
|
26
|
-
|
|
27
|
-
<div className="flex items-center text-base p-4 px-8 justify-around">
|
|
28
|
-
{notice ? (
|
|
29
|
-
<button
|
|
30
|
-
type="button"
|
|
31
|
-
className="w-24 h-10 px-2 text-white bg-gray-600 rounded"
|
|
32
|
-
onClick={setModal}
|
|
33
|
-
>
|
|
34
|
-
確定
|
|
35
|
-
</button>
|
|
36
|
-
) : (
|
|
37
|
-
<>
|
|
38
|
-
<button
|
|
39
|
-
type="button"
|
|
40
|
-
className="w-24 h-10 px-2 text-white bg-gray-600 rounded"
|
|
41
|
-
onClick={setModal}
|
|
42
|
-
>
|
|
43
|
-
取消
|
|
44
|
-
</button>
|
|
45
|
-
{onClick && (
|
|
46
|
-
<button
|
|
47
|
-
type="button"
|
|
48
|
-
className="w-24 h-10 mx-3 text-white bg-gray-500 rounded"
|
|
49
|
-
onClick={onClick}
|
|
50
|
-
>
|
|
51
|
-
送出
|
|
52
|
-
</button>
|
|
53
|
-
)}
|
|
54
|
-
</>
|
|
55
|
-
)}
|
|
56
|
-
</div>
|
|
57
|
-
</form>
|
|
58
|
-
);
|
|
59
|
-
|
|
60
|
-
export default ModalContent;
|
|
@@ -1,91 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import PropTypes from 'prop-types';
|
|
3
|
-
import { Icon } from '@iconify/react';
|
|
4
|
-
|
|
5
|
-
const NoticeModal = ({
|
|
6
|
-
title,
|
|
7
|
-
buttonName,
|
|
8
|
-
content,
|
|
9
|
-
setModal,
|
|
10
|
-
onClick,
|
|
11
|
-
onlyCheck,
|
|
12
|
-
action,
|
|
13
|
-
cancelButtonName = '取消',
|
|
14
|
-
cancelFunc,
|
|
15
|
-
}) => {
|
|
16
|
-
const statusCode = action?.statusCode;
|
|
17
|
-
|
|
18
|
-
const actionFunc = () => {
|
|
19
|
-
if (statusCode === 'book_dates') return action?.resetCalendar();
|
|
20
|
-
if (statusCode === 'book_expired') return action?.redirectBook();
|
|
21
|
-
if (statusCode === 'not_registered_2times') return action?.redirectToPay();
|
|
22
|
-
return null;
|
|
23
|
-
};
|
|
24
|
-
|
|
25
|
-
const actionName =
|
|
26
|
-
statusCode === 'book_dates' ? action?.resetCalendarName : action?.redirectCalendarName;
|
|
27
|
-
|
|
28
|
-
const onlyCheckList = ['points', 'tickets', 'promo_tickets', 'member_group'];
|
|
29
|
-
|
|
30
|
-
const onlyCheckAction = onlyCheck || onlyCheckList.includes(statusCode);
|
|
31
|
-
|
|
32
|
-
return (
|
|
33
|
-
<div className="px-8 py-9">
|
|
34
|
-
<button className="w-full flex justify-end" type="button" onClick={() => setModal()}>
|
|
35
|
-
<Icon className="text-[#000000]" icon="ic:baseline-close" width="24" height="24" />
|
|
36
|
-
</button>
|
|
37
|
-
<div className="text-[28px] text-gray-700 font-medium min-w-[16rem] pb-2">{title}</div>
|
|
38
|
-
|
|
39
|
-
<div className="text-[20px] text-[#5A5A5A] pb-8">
|
|
40
|
-
<div>{content}</div>
|
|
41
|
-
</div>
|
|
42
|
-
<div className="flex items-center text-lg text-base justify-center gap-8">
|
|
43
|
-
{onlyCheckAction ? (
|
|
44
|
-
<button
|
|
45
|
-
type="button"
|
|
46
|
-
className={['px-8 py-3 px-2 text-white bg-[#0C7489] rounded-[10px]'].join(' ')}
|
|
47
|
-
onClick={() => {
|
|
48
|
-
setModal();
|
|
49
|
-
}}
|
|
50
|
-
>
|
|
51
|
-
確認
|
|
52
|
-
</button>
|
|
53
|
-
) : (
|
|
54
|
-
<>
|
|
55
|
-
<button
|
|
56
|
-
type="button"
|
|
57
|
-
className={[
|
|
58
|
-
'px-6 lg:px-8 py-3 rounded-[10px]',
|
|
59
|
-
'border border-solid border-[#656565] text-[#5A5A5A] bg-[#F5F5F5]',
|
|
60
|
-
].join(' ')}
|
|
61
|
-
onClick={() => (cancelFunc ? cancelFunc() : setModal())}
|
|
62
|
-
>
|
|
63
|
-
{cancelButtonName}
|
|
64
|
-
</button>
|
|
65
|
-
<button
|
|
66
|
-
type="button"
|
|
67
|
-
className="px-6 lg:px-8 py-3 text-white bg-[#0C7489] rounded-[10px]"
|
|
68
|
-
onClick={statusCode ? actionFunc : onClick}
|
|
69
|
-
>
|
|
70
|
-
{actionName || buttonName}
|
|
71
|
-
</button>
|
|
72
|
-
</>
|
|
73
|
-
)}
|
|
74
|
-
</div>
|
|
75
|
-
</div>
|
|
76
|
-
);
|
|
77
|
-
};
|
|
78
|
-
|
|
79
|
-
NoticeModal.propTypes = {
|
|
80
|
-
setModal: PropTypes.func,
|
|
81
|
-
title: PropTypes.string,
|
|
82
|
-
buttonName: PropTypes.string,
|
|
83
|
-
content: PropTypes.node,
|
|
84
|
-
onClick: PropTypes.func,
|
|
85
|
-
onlyCheck: PropTypes.bool,
|
|
86
|
-
action: PropTypes.shape(),
|
|
87
|
-
cancelButtonName: PropTypes.string,
|
|
88
|
-
cancelFunc: PropTypes.func,
|
|
89
|
-
};
|
|
90
|
-
|
|
91
|
-
export default NoticeModal;
|
package/src/lib/Modal/index.jsx
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { default } from './Modal';
|
package/src/lib/Spin/index.tsx
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
export function Spin(props: {
|
|
2
|
-
show: boolean;
|
|
3
|
-
overlayBackground?: 'bg-[#00000055]' | undefined;
|
|
4
|
-
}) {
|
|
5
|
-
const { show, overlayBackground = 'bg-[#00000055]' } = props;
|
|
6
|
-
return show ? (
|
|
7
|
-
<div
|
|
8
|
-
className={[
|
|
9
|
-
'fixed flex justify-center items-center w-full h-full left-0 top-0 z-[9999] overflow-hidden',
|
|
10
|
-
overlayBackground,
|
|
11
|
-
].join(' ')}
|
|
12
|
-
>
|
|
13
|
-
<div className="top-2/4 left-2/4">
|
|
14
|
-
<div className="w-10 h-10 rounded-full border-4 border-solid border-[#ffffff33] border-t-[#dbdbdb] animate-spin" />
|
|
15
|
-
</div>
|
|
16
|
-
</div>
|
|
17
|
-
) : null;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
export default Spin;
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import type { Meta, StoryFn } from '@storybook/react';
|
|
2
|
-
import { Switch } from '../../components/ui/switch';
|
|
3
|
-
|
|
4
|
-
interface SwitchProps {
|
|
5
|
-
id?: string;
|
|
6
|
-
onCheckedChange?: () => void;
|
|
7
|
-
disabled: boolean;
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
export default {
|
|
11
|
-
component: Switch,
|
|
12
|
-
title: 'Switch',
|
|
13
|
-
} as Meta;
|
|
14
|
-
|
|
15
|
-
const Template: StoryFn<SwitchProps> = (args) => {
|
|
16
|
-
return <Switch {...args} />;
|
|
17
|
-
};
|
|
18
|
-
|
|
19
|
-
export const Base = Template.bind({});
|
|
20
|
-
Base.args = {
|
|
21
|
-
id: 'ad-123',
|
|
22
|
-
onCheckedChange: () => ({}),
|
|
23
|
-
disabled: false,
|
|
24
|
-
};
|
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
import { useState, useEffect, FC } from 'react';
|
|
2
|
-
import { Icon } from '@iconify/react';
|
|
3
|
-
|
|
4
|
-
interface BaseTemplateProps {
|
|
5
|
-
file?: File | null;
|
|
6
|
-
imageUrl?: string;
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
const BaseTemplate: FC<BaseTemplateProps> = ({ file, imageUrl }) => {
|
|
10
|
-
const [tempImage, setTempImage] = useState<string | null>(null);
|
|
11
|
-
|
|
12
|
-
useEffect(() => {
|
|
13
|
-
let fileReader: FileReader | null;
|
|
14
|
-
let isCancel = false;
|
|
15
|
-
|
|
16
|
-
if (file) {
|
|
17
|
-
fileReader = new FileReader();
|
|
18
|
-
fileReader.onload = (e) => {
|
|
19
|
-
const { result } = e.target as FileReader;
|
|
20
|
-
if (result && !isCancel) {
|
|
21
|
-
setTempImage(result.toString());
|
|
22
|
-
}
|
|
23
|
-
};
|
|
24
|
-
fileReader.readAsDataURL(file);
|
|
25
|
-
}
|
|
26
|
-
return () => {
|
|
27
|
-
setTempImage(null);
|
|
28
|
-
isCancel = true;
|
|
29
|
-
if (fileReader && fileReader.readyState === 1) {
|
|
30
|
-
fileReader.abort();
|
|
31
|
-
}
|
|
32
|
-
};
|
|
33
|
-
}, [file]);
|
|
34
|
-
|
|
35
|
-
return (
|
|
36
|
-
<div className="max-w-sm mx-auto bg-white rounded-lg shadow-md overflow-hidden items-center">
|
|
37
|
-
<div className="px-4 py-6 w-72 h-56">
|
|
38
|
-
{tempImage || imageUrl ? (
|
|
39
|
-
<img
|
|
40
|
-
className="w-full h-full object-contain border-dashed border-2 border-gray-400 p-6 rounded-lg"
|
|
41
|
-
src={tempImage || imageUrl}
|
|
42
|
-
alt=""
|
|
43
|
-
/>
|
|
44
|
-
) : (
|
|
45
|
-
<div
|
|
46
|
-
id="image-preview"
|
|
47
|
-
className="max-w-sm p-6 bg-gray-100 border-dashed border-2 border-gray-400 rounded-lg items-center mx-auto text-center cursor-pointer"
|
|
48
|
-
>
|
|
49
|
-
<div className="cursor-pointer">
|
|
50
|
-
<div className="flex justify-center">
|
|
51
|
-
<Icon
|
|
52
|
-
icon="material-symbols:upload"
|
|
53
|
-
width="2.5rem"
|
|
54
|
-
height="2.5rem"
|
|
55
|
-
/>
|
|
56
|
-
</div>
|
|
57
|
-
|
|
58
|
-
<p className="font-normal text-sm text-gray-400 py-4">
|
|
59
|
-
圖片僅支援 png、jpg、jpeg
|
|
60
|
-
</p>
|
|
61
|
-
|
|
62
|
-
<h5 className="mb-2 text-xl font-bold tracking-tight text-gray-700">
|
|
63
|
-
上傳圖片
|
|
64
|
-
</h5>
|
|
65
|
-
</div>
|
|
66
|
-
</div>
|
|
67
|
-
)}
|
|
68
|
-
</div>
|
|
69
|
-
</div>
|
|
70
|
-
);
|
|
71
|
-
};
|
|
72
|
-
|
|
73
|
-
export default BaseTemplate;
|
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
import React, { useState } from 'react';
|
|
2
|
-
import type { Meta, StoryFn } from '@storybook/react';
|
|
3
|
-
import { CustomUpload } from './CustomUpload';
|
|
4
|
-
|
|
5
|
-
interface CustomUploadProps {
|
|
6
|
-
file?: File | null;
|
|
7
|
-
setFile?: any;
|
|
8
|
-
imageUrl?: string;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
export default {
|
|
12
|
-
component: CustomUpload,
|
|
13
|
-
title: 'CustomUpload',
|
|
14
|
-
} as Meta;
|
|
15
|
-
|
|
16
|
-
const demoIcon =
|
|
17
|
-
'https://gobobook.s3.ap-northeast-1.amazonaws.com/regions/DEV/vaadin_golf.svg';
|
|
18
|
-
|
|
19
|
-
const Template: StoryFn<CustomUploadProps> = (args) => {
|
|
20
|
-
const [file, setFile] = useState(null);
|
|
21
|
-
return <CustomUpload {...args} file={file} setFile={setFile} />;
|
|
22
|
-
};
|
|
23
|
-
|
|
24
|
-
const CustomerTemplate: StoryFn<CustomUploadProps> = (args) => {
|
|
25
|
-
const [file, setFile] = useState(null);
|
|
26
|
-
return (
|
|
27
|
-
<CustomUpload {...args} file={file} setFile={setFile}>
|
|
28
|
-
<div className="border border-solid border-gray-400 p-4">
|
|
29
|
-
<div>圖片僅支援 png、jpg、jpeg</div>
|
|
30
|
-
<div>點擊上傳</div>
|
|
31
|
-
</div>
|
|
32
|
-
</CustomUpload>
|
|
33
|
-
);
|
|
34
|
-
};
|
|
35
|
-
|
|
36
|
-
export const Base = Template.bind({});
|
|
37
|
-
Base.args = {
|
|
38
|
-
file: null,
|
|
39
|
-
setFile: () => {
|
|
40
|
-
return;
|
|
41
|
-
},
|
|
42
|
-
imageUrl: demoIcon,
|
|
43
|
-
};
|
|
44
|
-
|
|
45
|
-
export const Customer = CustomerTemplate.bind({});
|
|
46
|
-
Customer.args = {
|
|
47
|
-
file: null,
|
|
48
|
-
setFile: () => {
|
|
49
|
-
return;
|
|
50
|
-
},
|
|
51
|
-
imageUrl: '',
|
|
52
|
-
};
|
|
@@ -1,95 +0,0 @@
|
|
|
1
|
-
import React, { useState, useRef, ChangeEvent } from 'react';
|
|
2
|
-
import ErrorContent from '../Modal/ErrorContent';
|
|
3
|
-
import Modal from '../Modal';
|
|
4
|
-
import BaseTemplate from './BaseTemplate';
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
interface CustomUploadProps {
|
|
8
|
-
className?: string;
|
|
9
|
-
children?: React.ReactNode;
|
|
10
|
-
file?: File | null;
|
|
11
|
-
setFile?: any;
|
|
12
|
-
imageUrl?: string;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
export const CustomUpload: React.FC<CustomUploadProps> = ({
|
|
16
|
-
className,
|
|
17
|
-
children,
|
|
18
|
-
file,
|
|
19
|
-
setFile,
|
|
20
|
-
imageUrl,
|
|
21
|
-
}) => {
|
|
22
|
-
const imageMimeType = /image\/(png|jpg|jpeg)/i;
|
|
23
|
-
const DEFAULT_IMAGE_SIZE_LIMIT_IN_BYTES = 5120000; // 5000 KB
|
|
24
|
-
|
|
25
|
-
const [modal, setModal] = useState<React.ReactNode | null>(null);
|
|
26
|
-
|
|
27
|
-
const hiddenFileInput = useRef<HTMLInputElement | null>(null);
|
|
28
|
-
|
|
29
|
-
const handleImageClick = () => {
|
|
30
|
-
hiddenFileInput.current?.click();
|
|
31
|
-
};
|
|
32
|
-
|
|
33
|
-
const handleImageChange = (event: ChangeEvent<HTMLInputElement>) => {
|
|
34
|
-
const currentFile = event.target.files?.[0];
|
|
35
|
-
|
|
36
|
-
if (!currentFile) {
|
|
37
|
-
setFile(null);
|
|
38
|
-
return;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
if (currentFile && !currentFile.type?.match(imageMimeType)) {
|
|
42
|
-
setModal(
|
|
43
|
-
<ErrorContent setModal={setModal} errmsg="圖片僅支援 png、jpg、jpeg!" />
|
|
44
|
-
);
|
|
45
|
-
return;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
if (currentFile && currentFile.size > DEFAULT_IMAGE_SIZE_LIMIT_IN_BYTES) {
|
|
49
|
-
setModal(
|
|
50
|
-
<ErrorContent
|
|
51
|
-
setModal={setModal}
|
|
52
|
-
errmsg={
|
|
53
|
-
<span>
|
|
54
|
-
選擇的檔案大小:
|
|
55
|
-
{String((currentFile.size / 1024 / 1024).toFixed(3))}
|
|
56
|
-
{' MB'}
|
|
57
|
-
<br />
|
|
58
|
-
<hr />
|
|
59
|
-
上限:
|
|
60
|
-
{String(
|
|
61
|
-
(DEFAULT_IMAGE_SIZE_LIMIT_IN_BYTES / 1024 / 1024).toFixed(3)
|
|
62
|
-
)}
|
|
63
|
-
{' MB'}
|
|
64
|
-
</span>
|
|
65
|
-
}
|
|
66
|
-
/>
|
|
67
|
-
);
|
|
68
|
-
return;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
setFile(currentFile);
|
|
72
|
-
};
|
|
73
|
-
|
|
74
|
-
return (
|
|
75
|
-
<>
|
|
76
|
-
<button
|
|
77
|
-
className={className ? [className].join(' ') : ''}
|
|
78
|
-
type="button"
|
|
79
|
-
onClick={handleImageClick}
|
|
80
|
-
>
|
|
81
|
-
{children || <BaseTemplate file={file} imageUrl={imageUrl} />}
|
|
82
|
-
<input
|
|
83
|
-
type="file"
|
|
84
|
-
ref={hiddenFileInput}
|
|
85
|
-
accept=".png, .jpg, .jpeg"
|
|
86
|
-
onChange={handleImageChange}
|
|
87
|
-
className="hidden"
|
|
88
|
-
/>
|
|
89
|
-
</button>
|
|
90
|
-
{modal && <Modal modal={modal} unsetModal={setModal} />}
|
|
91
|
-
</>
|
|
92
|
-
);
|
|
93
|
-
};
|
|
94
|
-
|
|
95
|
-
export default CustomUpload;
|
package/src/lib/hello-server.tsx
DELETED
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import { render } from '@testing-library/react';
|
|
2
|
-
|
|
3
|
-
import UiLibrary from './uiLibrary';
|
|
4
|
-
|
|
5
|
-
describe('UiLibrary', () => {
|
|
6
|
-
it('should render successfully', () => {
|
|
7
|
-
const { baseElement } = render(<UiLibrary />);
|
|
8
|
-
expect(baseElement).toBeTruthy();
|
|
9
|
-
});
|
|
10
|
-
});
|
package/src/lib/uiLibrary.tsx
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import styles from './uiLibrary.module.css';
|
|
2
|
-
|
|
3
|
-
/* eslint-disable-next-line */
|
|
4
|
-
export interface UiLibraryProps {}
|
|
5
|
-
|
|
6
|
-
export function UiLibrary(props: UiLibraryProps) {
|
|
7
|
-
return (
|
|
8
|
-
<div className={styles['container']}>
|
|
9
|
-
<h1>Welcome to UiLibrary!</h1>
|
|
10
|
-
</div>
|
|
11
|
-
);
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
export default UiLibrary;
|
package/src/lib/utils.ts
DELETED
package/src/server.ts
DELETED