Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature: Locale Provider #434

Merged
merged 23 commits into from
Sep 1, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -508,7 +508,7 @@ const undisplayedSections: UndisplayedSection[] = [
},
{
title: "Utils",
components: [{ title: "Portal" }],
components: [{ title: "Portal" }, { title: "LocaleProvider" }],
},
];

Expand Down
42 changes: 23 additions & 19 deletions src/components/ConfirmModal/ConfirmModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { IconName } from "../Icon/Icon";
import Modal, { ModalCloseReason, ModalProps } from "../Modal";
import Fade from "../Fade";
import { CSSTransitionProps } from "../../utils/reactTransitionGroup";
import { useLocaleProps } from "../../hooks/useLocaleProps";

export type ConfirmModalCloseReason = "clickCloseIcon" | "clickCancelButton";

Expand Down Expand Up @@ -73,25 +74,28 @@ export type ConfirmModalProps = {
children?: React.ReactNode;
};

const ConfirmModal: React.FunctionComponent<ConfirmModalProps> = ({
title,
confirmText = "Confirm",
cancelText = "Cancel",
children,
onClose,
onSubmit,
buttonColor = "primary",
isOpen = true,
disabled,
loading,
fullSize = false,
overflowYScroll = true,
disableHorizontalPadding = false,
subActions = [],
tipElement,
modalProps,
fadeProps,
}) => {
const ConfirmModal: React.FunctionComponent<ConfirmModalProps> = (inProps) => {
const props = useLocaleProps({ props: inProps, name: "ConfirmModal" });
const {
title,
confirmText = "Confirm",
cancelText = "Cancel",
children,
onClose,
onSubmit,
buttonColor = "primary",
isOpen = true,
disabled,
loading,
fullSize = false,
overflowYScroll = true,
disableHorizontalPadding = false,
subActions = [],
tipElement,
modalProps,
fadeProps,
} = props;

const theme = useTheme();
const showFooter = !!onSubmit;
const [iconWrapperElement, setIconWrapperElement] =
Expand Down
17 changes: 10 additions & 7 deletions src/components/FileUploader/FileUploader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import Typography from "../Typography";
import Flex from "../Flex";
import Icon from "../Icon";
import Spacer from "../Spacer";
import { useLocaleProps } from "../../hooks/useLocaleProps";

export type FileUploaderProps = {
description?: string;
Expand All @@ -20,13 +21,15 @@ export type FileUploaderProps = {
) => void;
};

const FileUploader: React.FunctionComponent<FileUploaderProps> = ({
accept,
title = "Click or Drag & Drop file.",
width,
description,
onSelectFiles,
}) => {
const FileUploader: React.FunctionComponent<FileUploaderProps> = (inProps) => {
const props = useLocaleProps({ props: inProps, name: "FileUploader" });
const {
accept,
title = "Click or Drag & Drop file.",
width,
description,
onSelectFiles,
} = props;
const fileRef = React.useRef<HTMLInputElement>(null);
const [filesDraggedOver, setFilesDraggedOver] = React.useState(false);

Expand Down
39 changes: 20 additions & 19 deletions src/components/ItemEmpty/ItemEmpty.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import * as Styled from "./styled";
import Spacer from "../Spacer";
import Typography from "../Typography";
import defaultEmptyImage from "../../../assets/emptyImage.png";
import { useLocaleProps } from "../../hooks/useLocaleProps";

export type ItemEmptyProps = {
title?: string;
Expand All @@ -11,24 +12,24 @@ export type ItemEmptyProps = {
imageWidth?: number;
};

const ItemEmpty: React.FunctionComponent<ItemEmptyProps> = ({
title = "Not found.",
subtitle,
emptyImage,
imageWidth = 80,
}) => (
<Styled.EmptyContainer>
<Styled.EmptyImage
src={emptyImage ? emptyImage : defaultEmptyImage}
width={imageWidth}
/>
<Spacer pt={2} pb={1}>
<Typography weight="bold" size="md" align="center">
{title}
</Typography>
</Spacer>
{subtitle && <Typography size="sm">{subtitle}</Typography>}
</Styled.EmptyContainer>
);
const ItemEmpty: React.FunctionComponent<ItemEmptyProps> = (inProps) => {
const props = useLocaleProps({ props: inProps, name: "ItemEmpty" });
const { title = "Not found.", subtitle, emptyImage, imageWidth = 80 } = props;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ItemEmpty の NotFound も useLocaleProps の対象にしました。


return (
<Styled.EmptyContainer>
<Styled.EmptyImage
src={emptyImage ? emptyImage : defaultEmptyImage}
width={imageWidth}
/>
<Spacer pt={2} pb={1}>
<Typography weight="bold" size="md" align="center">
{title}
</Typography>
</Spacer>
{subtitle && <Typography size="sm">{subtitle}</Typography>}
</Styled.EmptyContainer>
);
};

export default ItemEmpty;
198 changes: 198 additions & 0 deletions src/components/LocaleProvider/LocaleProvider.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,198 @@
import * as React from "react";
import { Story } from "@storybook/react/types-6-0";
import LocaleProvider, { LocaleProviderProps } from ".";
import {
Button,
Card,
ConfirmModal,
MultipleFilter,
Select,
Spacer,
ToggleButton,
} from "..";

import * as locales from "../../constants/locale";
import FileUploader from "../FileUploader";
import ItemEmpty from "../ItemEmpty";
import { FilterPackType, ReferedFilterType } from "../MultipleFilter/types";

export default {
title: "Components/Utils/LocaleProvider",
component: LocaleProvider,
};

const filterPacksExample: FilterPackType[] = [
{
categoryName: "Row name",
filters: [
{
filterName: "Demand",
control: {
type: "text",
},
},
{
filterName: "Channel",
control: {
type: "text",
},
},
{
filterName: "Attribute",
control: {
type: "text",
},
},
{
filterName: "Type",
control: {
type: "text",
},
},
],
},
{
categoryName: "Linking",
filters: [
{
filterName: "Device",
control: {
type: "select",
options: ["Not selected", "Not Linking", "Linking"],
},
},
{
filterName: "Site",
control: {
type: "select",
options: ["Not selected", "Not Linking", "Linking"],
},
},
],
},
{
categoryName: "Condition",
filters: [
{
filterName: "Public",
control: {
type: "boolean",
},
},
{
filterName: "Active",
control: {
type: "boolean",
},
},
],
},
];

export const Example: Story<LocaleProviderProps> = (args) => {
const localeOptions = Object.keys(locales).map((_) => ({
label: _,
value: _,
}));
localeOptions.unshift({ label: "Unspecified(default behavior)", value: "" });
const [active, setActive] = React.useState<boolean>(false);
const [isOpen, setIsOpen] = React.useState(false);
const [selectedLocale, setSelectedLocale] = React.useState(localeOptions[1]);
const handleToggleButton = () => {
setIsOpen(!isOpen);
};

const handleLocationChange = (v: { label: string; value: string }) => {
setSelectedLocale(v);
};

const [filters, setFilters] = React.useState<ReferedFilterType[]>([]);
const handleChange = (referedFilters: ReferedFilterType[]) => {
setFilters(referedFilters);
};

return (
<LocaleProvider locale={locales[selectedLocale.value]}>
<Spacer pl={2} pt={2} pb={4}>
<div> Select a locale! </div>
<Select
options={localeOptions}
defaultValue={selectedLocale}
onChange={handleLocationChange}
/>
<div>Selected locale: {selectedLocale.value} </div>
</Spacer>

<h2>ToggleButton</h2>
<Spacer pl={2} pt={2} pb={4}>
<ToggleButton active={active} onChange={() => setActive(!active)} />
</Spacer>

<h2>ConfirmModal</h2>
<Spacer pl={2} pt={2} pb={4}>
<Button onClick={handleToggleButton}>Open Modal</Button>
<ConfirmModal
title="ConfirmModal Test"
onClose={handleToggleButton}
onSubmit={() => {
/** void. Code to show the footer */
}}
{...args}
isOpen={isOpen}
>
Content
</ConfirmModal>
</Spacer>

<h2>FileUploader</h2>
<Spacer pl={2} pt={2} pb={4}>
<FileUploader onSelectFiles={() => {}} />
</Spacer>

<h2>ItemEmpty</h2>
<Spacer pl={2} pt={2} pb={4}>
<ItemEmpty />
</Spacer>

<h2>MultipleFilter</h2>
<Spacer pl={2} pt={2} pb={40}>
<MultipleFilter
filterPacks={filterPacksExample}
onChange={handleChange}
/>
</Spacer>
</LocaleProvider>
);
};

export const CustomLocale: Story<LocaleProviderProps> = () => {
const koKR: locales.Localization = {
components: {
ToggleButton: {
defaultProps: { activeText: "온", inActiveText: "오프" },
},
},
};
const [active, setActive] = React.useState<boolean>(false);
return (
<LocaleProvider locale={koKR}>
<h2>Define Custom Locale</h2>
<Spacer pl={2} pt={2} pb={4}>
<ToggleButton active={active} onChange={() => setActive(!active)} />
</Spacer>

<div>You can define a custom locale definition as follows.</div>
<br />
<Card>
<pre>
&#047;&#047; Custom Locale <br />
const koKR: locales.Localization = {JSON.stringify(koKR, null, 4)}
<br />
<br />
&#047;&#047; Apply to LocaleProvider <br />
{"<LocaleProvider locale={koKR}>"}
</pre>
</Card>
</LocaleProvider>
);
};
21 changes: 21 additions & 0 deletions src/components/LocaleProvider/LocaleProvider.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import * as React from "react";
import { enUS, Localization } from "../../constants/locale";

export type LocaleProviderProps = {
locale?: Localization;
};

export const LocaleContext = React.createContext<LocaleProviderProps>({
// Default locale
locale: enUS,
});
const LocaleProvider: React.FunctionComponent<LocaleProviderProps> = ({
locale,
children,
}) => (
<LocaleContext.Provider value={{ locale: locale }}>
{children}
</LocaleContext.Provider>
);

export default LocaleProvider;
14 changes: 14 additions & 0 deletions src/components/LocaleProvider/__tests__/LocaleProvider.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import * as React from "react";
import "@testing-library/jest-dom/extend-expect";
import { cleanup } from "@testing-library/react";
import { renderWithThemeProvider } from "../../../utils/renderWithThemeProvider";
import LocaleProvider from "../";

describe("LocaleProvider component testing", () => {
afterEach(cleanup);

test("LocaleProvider", () => {
const { asFragment } = renderWithThemeProvider(<LocaleProvider />);
expect(asFragment()).toBeTruthy();
});
});
2 changes: 2 additions & 0 deletions src/components/LocaleProvider/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export { default } from "./LocaleProvider";
export type { LocaleProviderProps } from "./LocaleProvider";
Loading