takeat-design-system-ui-kit 0.0.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/.storybook/main.ts +17 -0
- package/.storybook/preview.tsx +41 -0
- package/README.md +50 -0
- package/cli/create-story.js +65 -0
- package/eslint.config.js +26 -0
- package/index.html +13 -0
- package/package.json +66 -0
- package/public/vite.svg +1 -0
- package/src/App.css +42 -0
- package/src/App.tsx +7 -0
- package/src/LibraryProvider.tsx +17 -0
- package/src/assets/Spinner.svg +3 -0
- package/src/assets/icons/addCircleFilled.svg +8 -0
- package/src/assets/icons/arrowDown.svg +8 -0
- package/src/assets/icons/arrowDropDown.svg +8 -0
- package/src/assets/icons/arrowDropUp.svg +8 -0
- package/src/assets/icons/arrowUp.svg +8 -0
- package/src/assets/icons/barGraph.svg +8 -0
- package/src/assets/icons/bell.svg +8 -0
- package/src/assets/icons/bellFilled.svg +8 -0
- package/src/assets/icons/bellNotification.svg +8 -0
- package/src/assets/icons/bellNotificationFilled.svg +8 -0
- package/src/assets/icons/bill.svg +8 -0
- package/src/assets/icons/billFilled.svg +8 -0
- package/src/assets/icons/bookOpen.svg +8 -0
- package/src/assets/icons/bookOpenFilled.svg +8 -0
- package/src/assets/icons/bullhorn.svg +3 -0
- package/src/assets/icons/cached.svg +8 -0
- package/src/assets/icons/calendar.svg +8 -0
- package/src/assets/icons/calendarCheck.svg +8 -0
- package/src/assets/icons/calendarCheckFilled.svg +8 -0
- package/src/assets/icons/calendarFilled.svg +8 -0
- package/src/assets/icons/cashier.svg +35 -0
- package/src/assets/icons/cashierFilled.svg +6 -0
- package/src/assets/icons/chat.svg +8 -0
- package/src/assets/icons/chatFilled.svg +8 -0
- package/src/assets/icons/check.svg +8 -0
- package/src/assets/icons/checkbox.svg +8 -0
- package/src/assets/icons/checkboxChecked.svg +8 -0
- package/src/assets/icons/checkboxCheckedFilled.svg +11 -0
- package/src/assets/icons/chevronDown.svg +3 -0
- package/src/assets/icons/chevronLeft.svg +3 -0
- package/src/assets/icons/chevronRight.svg +3 -0
- package/src/assets/icons/chevronUp.svg +3 -0
- package/src/assets/icons/clipboardCheck.svg +8 -0
- package/src/assets/icons/clipboardCheckFilled.svg +8 -0
- package/src/assets/icons/clock.svg +8 -0
- package/src/assets/icons/close.svg +8 -0
- package/src/assets/icons/closeCircle.svg +8 -0
- package/src/assets/icons/closeCircleFilled.svg +8 -0
- package/src/assets/icons/cloud.svg +8 -0
- package/src/assets/icons/cloudFilled.svg +8 -0
- package/src/assets/icons/copy.svg +4 -0
- package/src/assets/icons/copyFilled.svg +4 -0
- package/src/assets/icons/deleteFilled.svg +8 -0
- package/src/assets/icons/dollarSign.svg +8 -0
- package/src/assets/icons/download.svg +8 -0
- package/src/assets/icons/exchange.svg +8 -0
- package/src/assets/icons/exclamation.svg +8 -0
- package/src/assets/icons/externalLink.svg +4 -0
- package/src/assets/icons/eye.svg +3 -0
- package/src/assets/icons/eyeFilled.svg +3 -0
- package/src/assets/icons/eyeSlash.svg +8 -0
- package/src/assets/icons/eyeSlashFilled.svg +8 -0
- package/src/assets/icons/filterList.svg +10 -0
- package/src/assets/icons/folderOpen.svg +8 -0
- package/src/assets/icons/folderOpenFilled.svg +8 -0
- package/src/assets/icons/hand.svg +8 -0
- package/src/assets/icons/handFilled.svg +8 -0
- package/src/assets/icons/helpFilled.svg +8 -0
- package/src/assets/icons/home.svg +8 -0
- package/src/assets/icons/homeFilled.svg +9 -0
- package/src/assets/icons/idCard.svg +8 -0
- package/src/assets/icons/idCardFilled.svg +8 -0
- package/src/assets/icons/info.svg +8 -0
- package/src/assets/icons/infoFilled.svg +8 -0
- package/src/assets/icons/instagram.svg +5 -0
- package/src/assets/icons/like.svg +3 -0
- package/src/assets/icons/likeFilled.svg +4 -0
- package/src/assets/icons/loading.svg +17 -0
- package/src/assets/icons/logout.svg +4 -0
- package/src/assets/icons/mail.svg +8 -0
- package/src/assets/icons/mailFilled.svg +8 -0
- package/src/assets/icons/manager.svg +4 -0
- package/src/assets/icons/menu.svg +8 -0
- package/src/assets/icons/menuCircles.svg +8 -0
- package/src/assets/icons/minus.svg +8 -0
- package/src/assets/icons/minusCircle.svg +8 -0
- package/src/assets/icons/minusCircleFilled.svg +8 -0
- package/src/assets/icons/money.svg +8 -0
- package/src/assets/icons/moneyCircle.svg +8 -0
- package/src/assets/icons/moneyFilled.svg +8 -0
- package/src/assets/icons/motorcycle.svg +3 -0
- package/src/assets/icons/pencil.svg +3 -0
- package/src/assets/icons/pencilFilled.svg +4 -0
- package/src/assets/icons/percent.svg +8 -0
- package/src/assets/icons/phone.svg +8 -0
- package/src/assets/icons/phoneFilled.svg +8 -0
- package/src/assets/icons/piggyBank.svg +8 -0
- package/src/assets/icons/piggyBankFilled.svg +8 -0
- package/src/assets/icons/playCircle.svg +8 -0
- package/src/assets/icons/playCircleFilled.svg +8 -0
- package/src/assets/icons/playSquare.svg +8 -0
- package/src/assets/icons/playSquareFilled.svg +8 -0
- package/src/assets/icons/plus.svg +8 -0
- package/src/assets/icons/plusCircle.svg +8 -0
- package/src/assets/icons/power.svg +8 -0
- package/src/assets/icons/printer.svg +8 -0
- package/src/assets/icons/printerFilled.svg +8 -0
- package/src/assets/icons/qrCode.svg +8 -0
- package/src/assets/icons/question.svg +8 -0
- package/src/assets/icons/radioButton.svg +8 -0
- package/src/assets/icons/radioButtonChecked.svg +8 -0
- package/src/assets/icons/refresh.svg +8 -0
- package/src/assets/icons/scheduleFilled.svg +8 -0
- package/src/assets/icons/search.svg +8 -0
- package/src/assets/icons/settings.svg +4 -0
- package/src/assets/icons/settingsFilled.svg +3 -0
- package/src/assets/icons/star.svg +8 -0
- package/src/assets/icons/starFilled.svg +8 -0
- package/src/assets/icons/store.svg +8 -0
- package/src/assets/icons/storeFilled.svg +8 -0
- package/src/assets/icons/takeatIcon.svg +6 -0
- package/src/assets/icons/takeatIconFilled.svg +6 -0
- package/src/assets/icons/ticket.svg +8 -0
- package/src/assets/icons/ticketFilled.svg +8 -0
- package/src/assets/icons/trash.svg +8 -0
- package/src/assets/icons/trendingDown.svg +8 -0
- package/src/assets/icons/trendingUp.svg +8 -0
- package/src/assets/icons/user.svg +8 -0
- package/src/assets/icons/userAdd.svg +8 -0
- package/src/assets/icons/userAddFilled.svg +8 -0
- package/src/assets/icons/userCircle.svg +8 -0
- package/src/assets/icons/userCircleFilled.svg +8 -0
- package/src/assets/icons/userFilled.svg +8 -0
- package/src/assets/icons/utensils.svg +8 -0
- package/src/assets/icons/waiter.svg +3 -0
- package/src/assets/icons/warning.svg +8 -0
- package/src/assets/icons/warningFilled.svg +8 -0
- package/src/assets/icons/whatsapp.svg +10 -0
- package/src/assets/icons/whatsappFilled.svg +10 -0
- package/src/components/Accordion/Accordion.stories.tsx +19 -0
- package/src/components/Accordion/index.tsx +8 -0
- package/src/components/Accordion/styles.ts +1 -0
- package/src/components/Badge/Badge.stories.tsx +21 -0
- package/src/components/Badge/index.tsx +8 -0
- package/src/components/Badge/styles.ts +1 -0
- package/src/components/Button/Button.stories.tsx +186 -0
- package/src/components/Button/index.tsx +71 -0
- package/src/components/Button/styles.ts +216 -0
- package/src/components/Calendar/Calendar.stories.tsx +69 -0
- package/src/components/Calendar/CalendarComponents/index.tsx +214 -0
- package/src/components/Calendar/CalendarComponents/styles.ts +46 -0
- package/src/components/Calendar/index.tsx +290 -0
- package/src/components/Calendar/styles.ts +203 -0
- package/src/components/Divider/Divider.stories.tsx +57 -0
- package/src/components/Divider/index.tsx +22 -0
- package/src/components/Divider/styles.ts +25 -0
- package/src/components/FormItens/Checkbox/Checkbox.stories.tsx +50 -0
- package/src/components/FormItens/Checkbox/index.tsx +34 -0
- package/src/components/FormItens/Checkbox/styles.ts +96 -0
- package/src/components/FormItens/Input/Input.stories.tsx +138 -0
- package/src/components/FormItens/Input/index.tsx +72 -0
- package/src/components/FormItens/Input/styles.ts +136 -0
- package/src/components/FormItens/Radio/Radio.stories.tsx +76 -0
- package/src/components/FormItens/Radio/index.tsx +35 -0
- package/src/components/FormItens/Radio/styles.ts +112 -0
- package/src/components/FormItens/Select/Select.stories.tsx +83 -0
- package/src/components/FormItens/Select/index.tsx +117 -0
- package/src/components/FormItens/Select/styles.ts +149 -0
- package/src/components/FormItens/Switch/Switch.stories.tsx +127 -0
- package/src/components/FormItens/Switch/index.tsx +59 -0
- package/src/components/FormItens/Switch/styles.ts +123 -0
- package/src/components/Icon/Icon.stories.tsx +87 -0
- package/src/components/Icon/index.tsx +24 -0
- package/src/components/Icon/styles.ts +36 -0
- package/src/components/Layouts/ColumnsGrid/ColumnsGrid.stories.tsx +66 -0
- package/src/components/Layouts/ColumnsGrid/index.tsx +35 -0
- package/src/components/Layouts/ColumnsGrid/styles.ts +21 -0
- package/src/components/Layouts/Grid/Grid.stories.tsx +61 -0
- package/src/components/Layouts/Grid/index.tsx +42 -0
- package/src/components/Layouts/Grid/styles.ts +16 -0
- package/src/components/Layouts/GridArea/GridArea.stories.tsx +64 -0
- package/src/components/Layouts/GridArea/index.tsx +51 -0
- package/src/components/Layouts/GridArea/styles.ts +12 -0
- package/src/components/Layouts/ResponsiveGrid/ResponsiveGrid.stories.tsx +71 -0
- package/src/components/Layouts/ResponsiveGrid/index.tsx +34 -0
- package/src/components/Layouts/ResponsiveGrid/styles.ts +19 -0
- package/src/components/MockComponent/index.tsx +9 -0
- package/src/components/MockComponent/styles.ts +14 -0
- package/src/components/Modal/Modal.stories.tsx +75 -0
- package/src/components/Modal/index.tsx +81 -0
- package/src/components/Modal/styles.ts +75 -0
- package/src/components/NotificationBanner/NotificationBanner.stories.tsx +49 -0
- package/src/components/NotificationBanner/index.tsx +54 -0
- package/src/components/NotificationBanner/styles.ts +48 -0
- package/src/components/SingleTab/SingleTab.stories.tsx +50 -0
- package/src/components/SingleTab/index.tsx +36 -0
- package/src/components/SingleTab/styles.ts +110 -0
- package/src/components/Spinner/Spinner.stories.tsx +20 -0
- package/src/components/Spinner/index.tsx +14 -0
- package/src/components/Spinner/styles.ts +31 -0
- package/src/components/StoriesComponents/index.tsx +0 -0
- package/src/components/StoriesComponents/styles.ts +17 -0
- package/src/components/TabGroup/TabGroup.stories.tsx +64 -0
- package/src/components/TabGroup/index.tsx +75 -0
- package/src/components/TabGroup/styles.ts +7 -0
- package/src/components/Tooltip/Tooltip.stories.tsx +78 -0
- package/src/components/Tooltip/index.tsx +38 -0
- package/src/index.css +68 -0
- package/src/index.ts +19 -0
- package/src/main.tsx +10 -0
- package/src/styled.d.ts +6 -0
- package/src/svg.d.ts +9 -0
- package/src/utils/GlobalStyle.ts +47 -0
- package/src/utils/consts.ts +241 -0
- package/src/utils/functions.ts +327 -0
- package/src/utils/globalTypes.ts +8 -0
- package/src/utils/icons.tsx +15 -0
- package/src/vite-env.d.ts +1 -0
- package/tsconfig.app.json +24 -0
- package/tsconfig.json +7 -0
- package/tsconfig.node.json +22 -0
- package/vite.config.ts +8 -0
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { useState } from "react";
|
|
2
|
+
import { Icon } from ".";
|
|
3
|
+
import { icons } from "../../utils/icons";
|
|
4
|
+
import { IconList, Item, SearchInput } from "./styles";
|
|
5
|
+
import { defaultTheme, ICON_NAMES } from "../../utils/consts";
|
|
6
|
+
import { Meta, StoryObj } from "@storybook/react";
|
|
7
|
+
import { Subtitle } from "../StoriesComponents/styles";
|
|
8
|
+
|
|
9
|
+
const meta: Meta<typeof Icon> = {
|
|
10
|
+
title: "Design System/Icon",
|
|
11
|
+
component: Icon,
|
|
12
|
+
parameters: {
|
|
13
|
+
componentSubtitle: (
|
|
14
|
+
<Subtitle>
|
|
15
|
+
Componente para renderizar os ícones do sistema.
|
|
16
|
+
<br /> Na lista abaixo você pode pesquisar os ícones disponíveis e
|
|
17
|
+
copiar o código para usar no seu projeto. Exemplo: Ao clicar no icone
|
|
18
|
+
"takeatIconFilled" o código{" "}
|
|
19
|
+
{`
|
|
20
|
+
<Icon icon="takeatIconFilled" />`}{" "}
|
|
21
|
+
será copiado para a área de transferência.
|
|
22
|
+
</Subtitle>
|
|
23
|
+
),
|
|
24
|
+
},
|
|
25
|
+
argTypes: {
|
|
26
|
+
icon: {
|
|
27
|
+
control: {
|
|
28
|
+
type: "text",
|
|
29
|
+
},
|
|
30
|
+
},
|
|
31
|
+
color: {
|
|
32
|
+
description: "Cor customizada do ícone (hexadecimal). Exemplo: `#ff0000`",
|
|
33
|
+
control: {
|
|
34
|
+
type: "color",
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
},
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
export default meta;
|
|
41
|
+
|
|
42
|
+
type Story = StoryObj<typeof Icon>;
|
|
43
|
+
|
|
44
|
+
export const Example: Story = {
|
|
45
|
+
name: "Exemplo",
|
|
46
|
+
args: {
|
|
47
|
+
icon: "takeatIconFilled",
|
|
48
|
+
},
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
export const List: Story = {
|
|
52
|
+
name: "Lista de icones",
|
|
53
|
+
render: () => {
|
|
54
|
+
const [search, setSearch] = useState("");
|
|
55
|
+
|
|
56
|
+
return (
|
|
57
|
+
<div>
|
|
58
|
+
<SearchInput
|
|
59
|
+
placeholder="Buscar"
|
|
60
|
+
value={search}
|
|
61
|
+
onChange={(e) => setSearch(e.target.value)}
|
|
62
|
+
/>
|
|
63
|
+
|
|
64
|
+
<IconList>
|
|
65
|
+
{Object.keys(icons)
|
|
66
|
+
.filter((icon) => icon.includes(search))
|
|
67
|
+
.map((icon) => (
|
|
68
|
+
<Item
|
|
69
|
+
key={icon}
|
|
70
|
+
onClick={() =>
|
|
71
|
+
navigator.clipboard.writeText('<Icon icon="' + icon + '" />')
|
|
72
|
+
}
|
|
73
|
+
>
|
|
74
|
+
<Icon
|
|
75
|
+
icon={icon as (typeof ICON_NAMES)[number]}
|
|
76
|
+
color={defaultTheme.colors.primary.default}
|
|
77
|
+
/>
|
|
78
|
+
<span style={{ color: defaultTheme.colors.neutral.darker }}>
|
|
79
|
+
{icon}
|
|
80
|
+
</span>
|
|
81
|
+
</Item>
|
|
82
|
+
))}
|
|
83
|
+
</IconList>
|
|
84
|
+
</div>
|
|
85
|
+
);
|
|
86
|
+
},
|
|
87
|
+
};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import React, { forwardRef } from "react";
|
|
2
|
+
import { icons } from "../../utils/icons";
|
|
3
|
+
import { ICON_NAMES, defaultTheme } from "../../utils/consts";
|
|
4
|
+
|
|
5
|
+
interface IconProps extends React.HTMLAttributes<SVGElement> {
|
|
6
|
+
icon: (typeof ICON_NAMES)[number];
|
|
7
|
+
color?: string;
|
|
8
|
+
size?: number;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export const Icon = forwardRef(function Icon({
|
|
12
|
+
icon,
|
|
13
|
+
color = defaultTheme.colors.neutral.darker,
|
|
14
|
+
size = 26,
|
|
15
|
+
...rest
|
|
16
|
+
}: IconProps) {
|
|
17
|
+
const IconComponent = icons[icon];
|
|
18
|
+
|
|
19
|
+
if (!IconComponent) {
|
|
20
|
+
return null;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
return <IconComponent fill={color} {...rest} height={size} width={size} />;
|
|
24
|
+
});
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import styled from "styled-components";
|
|
2
|
+
import { spacing } from "../../utils/consts";
|
|
3
|
+
|
|
4
|
+
// Componente
|
|
5
|
+
|
|
6
|
+
// Stories
|
|
7
|
+
|
|
8
|
+
export const IconList = styled.div`
|
|
9
|
+
display: flex;
|
|
10
|
+
flex-wrap: wrap;
|
|
11
|
+
gap: ${spacing.xs};
|
|
12
|
+
`;
|
|
13
|
+
|
|
14
|
+
export const Item = styled.div`
|
|
15
|
+
flex-basis: 245px;
|
|
16
|
+
display: flex;
|
|
17
|
+
gap: ${spacing.xs};
|
|
18
|
+
align-items: center;
|
|
19
|
+
padding: ${spacing.xs};
|
|
20
|
+
border: 1px solid ${({ theme }) => theme.colors.neutral.light};
|
|
21
|
+
border-radius: ${spacing.xs};
|
|
22
|
+
cursor: pointer;
|
|
23
|
+
transition: border-color 0.3s;
|
|
24
|
+
|
|
25
|
+
&:hover {
|
|
26
|
+
border-color: ${({ theme }) => theme.colors.neutral.default};
|
|
27
|
+
}
|
|
28
|
+
`;
|
|
29
|
+
|
|
30
|
+
export const SearchInput = styled.input`
|
|
31
|
+
padding: 8px 16px;
|
|
32
|
+
font-size: 16px;
|
|
33
|
+
border-radius: 8px;
|
|
34
|
+
border: 1px solid grey;
|
|
35
|
+
margin-bottom: 16px;
|
|
36
|
+
`;
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { Meta, StoryObj } from "@storybook/react";
|
|
2
|
+
import { MockComponent } from "../../MockComponent";
|
|
3
|
+
import { ColumnsGrid } from "./index";
|
|
4
|
+
import { Subtitle } from "../../StoriesComponents/styles";
|
|
5
|
+
|
|
6
|
+
const meta: Meta<typeof ColumnsGrid> = {
|
|
7
|
+
title: "Layout/Columns Grid",
|
|
8
|
+
component: ColumnsGrid,
|
|
9
|
+
parameters: {
|
|
10
|
+
componentSubtitle: (
|
|
11
|
+
<Subtitle>
|
|
12
|
+
Componente para separar os elementos em colunas, mantendo a altura de
|
|
13
|
+
cada componente, criando o efeito que temos no cardápio do Totem. É uma
|
|
14
|
+
div e aceita todas as props que um div pode receber. Pode ser utilizada
|
|
15
|
+
com o styled components da seguinte forma:
|
|
16
|
+
<br /> const StyledColumnsGrid = styled(ColumnsGrid)``
|
|
17
|
+
</Subtitle>
|
|
18
|
+
),
|
|
19
|
+
},
|
|
20
|
+
argTypes: {
|
|
21
|
+
columnCount: {
|
|
22
|
+
description: "Quantidade de colunas a serem exibidas",
|
|
23
|
+
control: {
|
|
24
|
+
type: "number",
|
|
25
|
+
},
|
|
26
|
+
},
|
|
27
|
+
gap: {
|
|
28
|
+
description:
|
|
29
|
+
"Espaçamento entre os componentes. Caso seja passado apenas um valor, será aplicado o mesmo espaçamento na horizontal e vertical. Caso sejam passados dois valores, o primeiro será o espaçamento vertical e o segundo o horizontal. Formato: `10px` ou `10px 20px`",
|
|
30
|
+
control: {
|
|
31
|
+
type: "text",
|
|
32
|
+
},
|
|
33
|
+
},
|
|
34
|
+
children: {
|
|
35
|
+
description: "Componentes a serem exibidos dentro do grid",
|
|
36
|
+
control: {
|
|
37
|
+
disable: true,
|
|
38
|
+
},
|
|
39
|
+
},
|
|
40
|
+
},
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
const exampleArray = Array.from({ length: 10 }, (_, i) => i + 1);
|
|
44
|
+
|
|
45
|
+
export default meta;
|
|
46
|
+
|
|
47
|
+
type Story = StoryObj<typeof ColumnsGrid>;
|
|
48
|
+
|
|
49
|
+
export const Example: Story = {
|
|
50
|
+
args: {
|
|
51
|
+
columnCount: 3,
|
|
52
|
+
gap: "10px",
|
|
53
|
+
},
|
|
54
|
+
render: (args) => (
|
|
55
|
+
<ColumnsGrid {...args}>
|
|
56
|
+
{exampleArray.map((item) => {
|
|
57
|
+
const randomHeight = Math.floor(Math.random() * 100);
|
|
58
|
+
return (
|
|
59
|
+
<MockComponent style={{ height: randomHeight }} key={item}>
|
|
60
|
+
{item}
|
|
61
|
+
</MockComponent>
|
|
62
|
+
);
|
|
63
|
+
})}
|
|
64
|
+
</ColumnsGrid>
|
|
65
|
+
),
|
|
66
|
+
};
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { Children, forwardRef, ReactNode } from "react";
|
|
2
|
+
import { Column, ColumnsGridContainer } from "./styles";
|
|
3
|
+
|
|
4
|
+
interface ColumnsGridProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
5
|
+
columnCount: number;
|
|
6
|
+
gap?: string;
|
|
7
|
+
children: Iterable<ReactNode>;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export const ColumnsGrid = forwardRef(
|
|
11
|
+
(
|
|
12
|
+
{ columnCount, gap = "10px", children, ...props }: ColumnsGridProps,
|
|
13
|
+
ref: React.Ref<HTMLDivElement>
|
|
14
|
+
) => {
|
|
15
|
+
const array: Array<ReactNode> = Array.from(
|
|
16
|
+
{ length: columnCount },
|
|
17
|
+
(_) => []
|
|
18
|
+
);
|
|
19
|
+
|
|
20
|
+
Children.forEach(children, (child, index) => {
|
|
21
|
+
const column = array[index % columnCount];
|
|
22
|
+
if (Array.isArray(column)) {
|
|
23
|
+
column.push(child);
|
|
24
|
+
}
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
return (
|
|
28
|
+
<ColumnsGridContainer ref={ref} gap={gap} {...props}>
|
|
29
|
+
{array.map((column) => {
|
|
30
|
+
return <Column gap={gap}>{column}</Column>;
|
|
31
|
+
})}
|
|
32
|
+
</ColumnsGridContainer>
|
|
33
|
+
);
|
|
34
|
+
}
|
|
35
|
+
);
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import styled from "styled-components";
|
|
2
|
+
|
|
3
|
+
interface ColumnsGridContainerProps {
|
|
4
|
+
gap: string;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export const ColumnsGridContainer = styled.div<ColumnsGridContainerProps>`
|
|
8
|
+
display: flex;
|
|
9
|
+
gap: ${({ gap }) => gap};
|
|
10
|
+
width: 100%;
|
|
11
|
+
`;
|
|
12
|
+
|
|
13
|
+
interface ColumnProps {
|
|
14
|
+
gap: string;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export const Column = styled.div<ColumnProps>`
|
|
18
|
+
display: flex;
|
|
19
|
+
flex-direction: column;
|
|
20
|
+
gap: ${({ gap }) => gap};
|
|
21
|
+
`;
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { Meta, StoryObj } from "@storybook/react";
|
|
2
|
+
import { MockComponent } from "../../MockComponent";
|
|
3
|
+
import { Grid } from "./index";
|
|
4
|
+
import { Subtitle } from "../../StoriesComponents/styles";
|
|
5
|
+
|
|
6
|
+
const meta: Meta<typeof Grid> = {
|
|
7
|
+
title: "Layout/Grid",
|
|
8
|
+
component: Grid,
|
|
9
|
+
parameters: {
|
|
10
|
+
componentSubtitle: (
|
|
11
|
+
<Subtitle>
|
|
12
|
+
Componente para facilitar a criação de um grid com elementos de
|
|
13
|
+
diferentes larguras. É uma div e aceita todas as props que um div pode
|
|
14
|
+
receber. Pode ser utilizada com o styled components da seguinte forma:
|
|
15
|
+
<br /> const StyledGrid = styled(Grid)``
|
|
16
|
+
</Subtitle>
|
|
17
|
+
),
|
|
18
|
+
},
|
|
19
|
+
argTypes: {
|
|
20
|
+
elementsPerRow: {
|
|
21
|
+
description:
|
|
22
|
+
"Array com a quantidade de elementos por linha. Exemplo: `[1, 4, 2, 3]`",
|
|
23
|
+
control: {
|
|
24
|
+
type: "object",
|
|
25
|
+
},
|
|
26
|
+
},
|
|
27
|
+
gap: {
|
|
28
|
+
description:
|
|
29
|
+
"Espaçamento entre os componentes. Caso seja passado apenas um valor, será aplicado o mesmo espaçamento na horizontal e vertical. Caso sejam passados dois valores, o primeiro será o espaçamento vertical e o segundo o horizontal. Formato: `10px` ou `10px 20px`",
|
|
30
|
+
control: {
|
|
31
|
+
type: "text",
|
|
32
|
+
},
|
|
33
|
+
},
|
|
34
|
+
children: {
|
|
35
|
+
description: "Componentes a serem exibidos dentro do grid",
|
|
36
|
+
control: {
|
|
37
|
+
disable: true,
|
|
38
|
+
},
|
|
39
|
+
},
|
|
40
|
+
},
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
export default meta;
|
|
44
|
+
|
|
45
|
+
type Story = StoryObj<typeof Grid>;
|
|
46
|
+
|
|
47
|
+
const exmapleArray = Array.from({ length: 10 }, (_, i) => i + 1);
|
|
48
|
+
|
|
49
|
+
export const Example: Story = {
|
|
50
|
+
args: {
|
|
51
|
+
elementsPerRow: [1, 4, 2, 3],
|
|
52
|
+
gap: "8px",
|
|
53
|
+
},
|
|
54
|
+
render: (args) => (
|
|
55
|
+
<Grid {...args}>
|
|
56
|
+
{exmapleArray.map((item) => (
|
|
57
|
+
<MockComponent key={item}>{item}</MockComponent>
|
|
58
|
+
))}
|
|
59
|
+
</Grid>
|
|
60
|
+
),
|
|
61
|
+
};
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { cloneElement, forwardRef, ReactElement } from "react";
|
|
2
|
+
import { mmcArray } from "../../../utils/functions";
|
|
3
|
+
import { GridContainer } from "./styles";
|
|
4
|
+
|
|
5
|
+
interface GridProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
6
|
+
elementsPerRow?: number[];
|
|
7
|
+
children: ReactElement[];
|
|
8
|
+
gap?: string;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export const Grid = forwardRef(
|
|
12
|
+
(
|
|
13
|
+
{ elementsPerRow, gap = "8px", children, ...props }: GridProps,
|
|
14
|
+
ref: React.Ref<HTMLDivElement>
|
|
15
|
+
) => {
|
|
16
|
+
const colCount = mmcArray(elementsPerRow || [1]);
|
|
17
|
+
let start = 0;
|
|
18
|
+
|
|
19
|
+
return (
|
|
20
|
+
<GridContainer ref={ref} gap={gap} colCount={colCount} {...props}>
|
|
21
|
+
{elementsPerRow?.map((rowCount) => {
|
|
22
|
+
const elementsToReturn = children
|
|
23
|
+
.slice(start, start + rowCount)
|
|
24
|
+
.map((child) => {
|
|
25
|
+
console.log("child: ", child.props);
|
|
26
|
+
return cloneElement(child, {
|
|
27
|
+
style: {
|
|
28
|
+
...child.props.style,
|
|
29
|
+
gridColumn: `span ${colCount / rowCount}`,
|
|
30
|
+
},
|
|
31
|
+
});
|
|
32
|
+
});
|
|
33
|
+
start += rowCount;
|
|
34
|
+
return elementsToReturn;
|
|
35
|
+
})}
|
|
36
|
+
{children.slice(start).map((child) => {
|
|
37
|
+
return child;
|
|
38
|
+
})}
|
|
39
|
+
</GridContainer>
|
|
40
|
+
);
|
|
41
|
+
}
|
|
42
|
+
);
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import styled from "styled-components";
|
|
2
|
+
|
|
3
|
+
interface GridContainerProps {
|
|
4
|
+
colCount: number;
|
|
5
|
+
gap: string;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export const GridContainer = styled.div<GridContainerProps>`
|
|
9
|
+
display: grid;
|
|
10
|
+
grid-template-columns: repeat(${({ colCount }) => colCount}, 1fr);
|
|
11
|
+
gap: ${({ gap }) => gap};
|
|
12
|
+
|
|
13
|
+
.red {
|
|
14
|
+
background-color: red;
|
|
15
|
+
}
|
|
16
|
+
`;
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { Meta, StoryObj } from "@storybook/react";
|
|
2
|
+
import { MockComponent } from "../../MockComponent";
|
|
3
|
+
import { GridArea } from "./index";
|
|
4
|
+
import { Subtitle } from "../../StoriesComponents/styles";
|
|
5
|
+
|
|
6
|
+
const meta: Meta<typeof GridArea> = {
|
|
7
|
+
title: "Layout/Grid Area",
|
|
8
|
+
component: GridArea,
|
|
9
|
+
parameters: {
|
|
10
|
+
componentSubtitle: (
|
|
11
|
+
<Subtitle>
|
|
12
|
+
Componente para facilitar a criação de um grid com elementos de
|
|
13
|
+
diferentes larguras. É uma div e aceita todas as props que um div pode
|
|
14
|
+
receber. Pode ser utilizada com o styled components da seguinte forma:
|
|
15
|
+
<br /> const StyledGridArea = styled(GridArea)``
|
|
16
|
+
</Subtitle>
|
|
17
|
+
),
|
|
18
|
+
},
|
|
19
|
+
argTypes: {
|
|
20
|
+
areaTemplate: {
|
|
21
|
+
description:
|
|
22
|
+
"Array bidimensional com a quantidade de colunas que cada componente deve ocupar. Os valores positivos representam a quantidade de colunas que o componente deve ocupar, enquanto valores negativos 'renderizam' um espaço em branco. A quantidade de colunas do grid é determinada pela soma de colunas do primeiro array. Exemplo: `[[1, 2, 3, 4, 1], [5, -2, 1]]`",
|
|
23
|
+
control: {
|
|
24
|
+
type: "object",
|
|
25
|
+
},
|
|
26
|
+
},
|
|
27
|
+
gap: {
|
|
28
|
+
description:
|
|
29
|
+
"Espaçamento entre os componentes. Caso seja passado apenas um valor, será aplicado o mesmo espaçamento na horizontal e vertical. Caso sejam passados dois valores, o primeiro será o espaçamento vertical e o segundo o horizontal. Formato: `10px` ou `10px 20px`",
|
|
30
|
+
control: {
|
|
31
|
+
type: "text",
|
|
32
|
+
},
|
|
33
|
+
},
|
|
34
|
+
children: {
|
|
35
|
+
description: "Componentes a serem exibidos dentro do grid",
|
|
36
|
+
control: {
|
|
37
|
+
disable: true,
|
|
38
|
+
},
|
|
39
|
+
},
|
|
40
|
+
},
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
export default meta;
|
|
44
|
+
|
|
45
|
+
type Story = StoryObj<typeof GridArea>;
|
|
46
|
+
|
|
47
|
+
const exmapleArray = Array.from({ length: 10 }, (_, i) => i + 1);
|
|
48
|
+
|
|
49
|
+
export const Example: Story = {
|
|
50
|
+
args: {
|
|
51
|
+
areaTemplate: [
|
|
52
|
+
[1, 2, 3, 4, 1],
|
|
53
|
+
[5, -2, 1],
|
|
54
|
+
],
|
|
55
|
+
gap: "8px",
|
|
56
|
+
},
|
|
57
|
+
render: (args) => (
|
|
58
|
+
<GridArea {...args}>
|
|
59
|
+
{exmapleArray.map((item) => (
|
|
60
|
+
<MockComponent key={item}>{item}</MockComponent>
|
|
61
|
+
))}
|
|
62
|
+
</GridArea>
|
|
63
|
+
),
|
|
64
|
+
};
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import React, { forwardRef } from "react";
|
|
2
|
+
import { GridAreaContainer } from "./styles";
|
|
3
|
+
|
|
4
|
+
interface GridAreaProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
5
|
+
areaTemplate: number[][];
|
|
6
|
+
gap: string;
|
|
7
|
+
children: React.ReactElement[];
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export const GridArea = forwardRef(
|
|
11
|
+
(
|
|
12
|
+
{ areaTemplate, gap = "8px", children, ...props }: GridAreaProps,
|
|
13
|
+
ref: React.Ref<HTMLDivElement>
|
|
14
|
+
) => {
|
|
15
|
+
const colCount = areaTemplate[0].reduce((acc, cur) => {
|
|
16
|
+
return acc + Math.abs(cur);
|
|
17
|
+
}, 0);
|
|
18
|
+
let start = 0;
|
|
19
|
+
|
|
20
|
+
return (
|
|
21
|
+
<GridAreaContainer ref={ref} colCount={colCount} gap={gap} {...props}>
|
|
22
|
+
{areaTemplate.map((row) => {
|
|
23
|
+
const elementsCount = row.length;
|
|
24
|
+
const positiveCount = row.filter((el) => el > 0).length;
|
|
25
|
+
|
|
26
|
+
const elementsToReturn = children
|
|
27
|
+
.slice(start, start + elementsCount)
|
|
28
|
+
.map((child, idx) => {
|
|
29
|
+
if (row[idx] < 0) {
|
|
30
|
+
return (
|
|
31
|
+
<div style={{ gridColumn: `span ${Math.abs(row[idx])}` }} />
|
|
32
|
+
);
|
|
33
|
+
}
|
|
34
|
+
return React.cloneElement(child, {
|
|
35
|
+
style: {
|
|
36
|
+
...child.props.style,
|
|
37
|
+
gridColumn: `span ${row[idx]}`,
|
|
38
|
+
},
|
|
39
|
+
});
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
start += positiveCount;
|
|
43
|
+
return elementsToReturn;
|
|
44
|
+
})}
|
|
45
|
+
{children.slice(start + 1).map((child) => {
|
|
46
|
+
return child;
|
|
47
|
+
})}
|
|
48
|
+
</GridAreaContainer>
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
);
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { styled } from "styled-components";
|
|
2
|
+
|
|
3
|
+
interface GridAreaContainerProps {
|
|
4
|
+
colCount: number;
|
|
5
|
+
gap: string;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export const GridAreaContainer = styled.div<GridAreaContainerProps>`
|
|
9
|
+
display: grid;
|
|
10
|
+
grid-template-columns: repeat(${({ colCount }) => colCount}, 1fr);
|
|
11
|
+
gap: ${({ gap }) => gap};
|
|
12
|
+
`;
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { Meta, StoryObj } from "@storybook/react";
|
|
2
|
+
import { MockComponent } from "../../MockComponent";
|
|
3
|
+
import { ResponsiveGrid } from "./index";
|
|
4
|
+
import { ResizeableContainer, Subtitle } from "../../StoriesComponents/styles";
|
|
5
|
+
|
|
6
|
+
const meta: Meta = {
|
|
7
|
+
title: "Layout/Responsive Grid",
|
|
8
|
+
component: ResponsiveGrid,
|
|
9
|
+
parameters: {
|
|
10
|
+
componentSubtitle: (
|
|
11
|
+
<Subtitle>
|
|
12
|
+
Componente para facilitar a criação de um grid responsivo. É uma div e
|
|
13
|
+
aceita todas as props que um div pode receber. Pode ser utilizada com o
|
|
14
|
+
styled components da seguinte forma:
|
|
15
|
+
<br /> const StyledGridArea = styled(GridArea)``
|
|
16
|
+
</Subtitle>
|
|
17
|
+
),
|
|
18
|
+
},
|
|
19
|
+
argTypes: {
|
|
20
|
+
minWidth: {
|
|
21
|
+
description: "Largura mínima que cada componente pode ter",
|
|
22
|
+
control: {
|
|
23
|
+
type: "text",
|
|
24
|
+
},
|
|
25
|
+
},
|
|
26
|
+
fixedWidth: {
|
|
27
|
+
description:
|
|
28
|
+
"Largura fixa que cada componente deve ter. Caso seja passado, o minWidth será ignorado",
|
|
29
|
+
control: {
|
|
30
|
+
type: "text",
|
|
31
|
+
},
|
|
32
|
+
},
|
|
33
|
+
gap: {
|
|
34
|
+
description:
|
|
35
|
+
"Espaçamento entre os componentes. Caso seja passado apenas um valor, será aplicado o mesmo espaçamento na horizontal e vertical. Caso sejam passados dois valores, o primeiro será o espaçamento vertical e o segundo o horizontal. Formato: `10px` ou `10px 20px`",
|
|
36
|
+
control: {
|
|
37
|
+
type: "text",
|
|
38
|
+
},
|
|
39
|
+
},
|
|
40
|
+
children: {
|
|
41
|
+
description: "Componentes a serem exibidos dentro do grid",
|
|
42
|
+
control: {
|
|
43
|
+
disable: true,
|
|
44
|
+
},
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
export default meta;
|
|
50
|
+
|
|
51
|
+
type Story = StoryObj<typeof ResponsiveGrid>;
|
|
52
|
+
|
|
53
|
+
const exmapleArray = Array.from({ length: 10 }, (_, i) => i + 1);
|
|
54
|
+
|
|
55
|
+
export const Example: Story = {
|
|
56
|
+
args: {
|
|
57
|
+
minWidth: "100px",
|
|
58
|
+
gap: "8px",
|
|
59
|
+
fixedWidth: "",
|
|
60
|
+
},
|
|
61
|
+
render: (args) => (
|
|
62
|
+
<ResizeableContainer>
|
|
63
|
+
<ResponsiveGrid {...args}>
|
|
64
|
+
{exmapleArray.map((item) => (
|
|
65
|
+
<MockComponent key={item}>{item}</MockComponent>
|
|
66
|
+
))}
|
|
67
|
+
</ResponsiveGrid>
|
|
68
|
+
Ajuste o tamanho do container para ver o comportamento do grid {"->"}
|
|
69
|
+
</ResizeableContainer>
|
|
70
|
+
),
|
|
71
|
+
};
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { forwardRef } from "react";
|
|
2
|
+
import { ResponsiveGridContainer } from "./styles";
|
|
3
|
+
|
|
4
|
+
interface ResponsiveGridProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
5
|
+
children: React.ReactElement[];
|
|
6
|
+
gap?: string;
|
|
7
|
+
minWidth?: string;
|
|
8
|
+
fixedWidth?: string;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export const ResponsiveGrid = forwardRef(
|
|
12
|
+
(
|
|
13
|
+
{
|
|
14
|
+
gap = "8px",
|
|
15
|
+
minWidth = "auto",
|
|
16
|
+
fixedWidth,
|
|
17
|
+
children,
|
|
18
|
+
...props
|
|
19
|
+
}: ResponsiveGridProps,
|
|
20
|
+
ref: React.Ref<HTMLDivElement>
|
|
21
|
+
) => {
|
|
22
|
+
return (
|
|
23
|
+
<ResponsiveGridContainer
|
|
24
|
+
ref={ref}
|
|
25
|
+
fixedWidth={fixedWidth}
|
|
26
|
+
minWidth={minWidth}
|
|
27
|
+
gap={gap}
|
|
28
|
+
{...props}
|
|
29
|
+
>
|
|
30
|
+
{children}
|
|
31
|
+
</ResponsiveGridContainer>
|
|
32
|
+
);
|
|
33
|
+
}
|
|
34
|
+
);
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import styled from "styled-components";
|
|
2
|
+
|
|
3
|
+
interface ResponsiveGridContainerProps {
|
|
4
|
+
gap: string;
|
|
5
|
+
minWidth: string;
|
|
6
|
+
fixedWidth?: string;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export const ResponsiveGridContainer = styled.div<ResponsiveGridContainerProps>`
|
|
10
|
+
width: 100%;
|
|
11
|
+
display: grid;
|
|
12
|
+
grid-template-columns: repeat(
|
|
13
|
+
auto-fill,
|
|
14
|
+
${({ minWidth, fixedWidth }) =>
|
|
15
|
+
fixedWidth ? fixedWidth : `minmax(${minWidth}, 1fr)`}
|
|
16
|
+
);
|
|
17
|
+
justify-content: space-between;
|
|
18
|
+
gap: ${({ gap }) => gap};
|
|
19
|
+
`;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { StyledDiv } from "./styles";
|
|
2
|
+
|
|
3
|
+
interface MockComponentProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
4
|
+
children?: React.ReactNode;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export const MockComponent = ({ children, ...rest }: MockComponentProps) => {
|
|
8
|
+
return <StyledDiv {...rest}>{children}</StyledDiv>;
|
|
9
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import styled from "styled-components";
|
|
2
|
+
|
|
3
|
+
export const StyledDiv = styled.div`
|
|
4
|
+
display: flex;
|
|
5
|
+
justify-content: center;
|
|
6
|
+
align-items: center;
|
|
7
|
+
padding: 16px;
|
|
8
|
+
background-color: lightblue;
|
|
9
|
+
border-radius: 8px;
|
|
10
|
+
border: 1px solid blue;
|
|
11
|
+
font-size: 20px;
|
|
12
|
+
font-family: Poppins, sans-serif;
|
|
13
|
+
font-weight: 700;
|
|
14
|
+
`;
|