├── .husky ├── .gitignore ├── commit-msg └── pre-commit ├── .prettierignore ├── .env ├── .dockerignore ├── src ├── react-app-env.d.ts ├── setupTests.ts ├── components │ ├── atoms │ │ ├── Tag │ │ │ ├── index.ts │ │ │ ├── Tag.model.ts │ │ │ ├── Tag.styled.ts │ │ │ └── Tag.tsx │ │ ├── List │ │ │ ├── index.ts │ │ │ ├── List.model.ts │ │ │ ├── List.styled.ts │ │ │ ├── List.tsx │ │ │ ├── List.stories.tsx │ │ │ └── List.test.tsx │ │ ├── Logo │ │ │ ├── index.ts │ │ │ ├── Logo.model.ts │ │ │ ├── Logo.test.tsx │ │ │ ├── Logo.styled.ts │ │ │ └── Logo.tsx │ │ ├── Button │ │ │ ├── index.ts │ │ │ ├── Button.model.ts │ │ │ ├── Button.tsx │ │ │ ├── Button.test.tsx │ │ │ ├── Button.styled.ts │ │ │ └── Button.stories.tsx │ │ ├── Header │ │ │ ├── index.ts │ │ │ ├── Header.tsx │ │ │ ├── Header.styled.ts │ │ │ ├── Header.test.tsx │ │ │ └── Header.stories.tsx │ │ ├── Input │ │ │ ├── index.ts │ │ │ ├── Input.model.ts │ │ │ ├── Input.test.tsx │ │ │ ├── Input.styled.ts │ │ │ ├── Input.tsx │ │ │ └── Input.stories.tsx │ │ ├── Toast │ │ │ ├── index.ts │ │ │ ├── Toast.model.ts │ │ │ ├── Toast.styled.ts │ │ │ ├── Toast.stories.tsx │ │ │ ├── Toast.tsx │ │ │ └── Toast.test.tsx │ │ ├── Spinner │ │ │ ├── index.ts │ │ │ ├── Spinner.stories.tsx │ │ │ ├── Spinner.test.tsx │ │ │ ├── Spinner.tsx │ │ │ └── Spinner.styled.ts │ │ ├── ListItem │ │ │ ├── index.ts │ │ │ ├── ListItem.model.ts │ │ │ ├── ListItem.tsx │ │ │ ├── ListItem.styled.ts │ │ │ └── ListItem.stories.tsx │ │ ├── TextArea │ │ │ ├── index.ts │ │ │ ├── TextArea.styled.ts │ │ │ ├── TextArea.stories.tsx │ │ │ ├── TextArea.tsx │ │ │ └── TextArea.test.tsx │ │ ├── Paragraph │ │ │ ├── index.ts │ │ │ ├── Paragraph.test.tsx │ │ │ ├── Paragraph.styled.ts │ │ │ ├── Paragraph.tsx │ │ │ └── Paragraph.stories.tsx │ │ ├── SocialButton │ │ │ ├── index.ts │ │ │ ├── SocialButton.model.ts │ │ │ ├── SocialButton.stories.tsx │ │ │ ├── SocialButton.styled.ts │ │ │ ├── SocialButton.test.tsx │ │ │ └── SocialButton.tsx │ │ ├── GradientBackground │ │ │ ├── index.ts │ │ │ ├── GradientBackground.model.ts │ │ │ ├── GradientBackground.tsx │ │ │ └── GradientBackground.styled.ts │ │ └── Ranges │ │ │ ├── index.ts │ │ │ ├── LevelRange │ │ │ ├── data.ts │ │ │ ├── LevelRange.stories.tsx │ │ │ ├── LevelRange.test.tsx │ │ │ ├── LevelRange.tsx │ │ │ └── LevelRange.styled.ts │ │ │ └── DefaultRange │ │ │ ├── Range.stories.tsx │ │ │ ├── Range.test.tsx │ │ │ ├── Range.tsx │ │ │ └── Range.styled.ts │ ├── molecules │ │ ├── CourseTags │ │ │ ├── index.ts │ │ │ ├── CourseTags.model.ts │ │ │ ├── CourseTags.styled.ts │ │ │ ├── exampleTags.ts │ │ │ └── CourseTags.tsx │ │ ├── SelectInput │ │ │ ├── Option │ │ │ │ ├── index.ts │ │ │ │ ├── Option.model.ts │ │ │ │ ├── Option.styled.ts │ │ │ │ └── Option.tsx │ │ │ ├── Select │ │ │ │ ├── index.ts │ │ │ │ ├── Select.model.ts │ │ │ │ ├── Select.styled.ts │ │ │ │ └── Select.tsx │ │ │ ├── index.ts │ │ │ ├── SelectInput.model.ts │ │ │ ├── SelectInput.tsx │ │ │ ├── SelectInput.test.tsx │ │ │ └── SelectInput.stories.tsx │ │ ├── SkillCard │ │ │ ├── index.ts │ │ │ ├── SkillCard.model.ts │ │ │ ├── SkillCard.test.tsx │ │ │ ├── SkillCard.stories.tsx │ │ │ ├── SkillCard.tsx │ │ │ └── SkillCard.styled.ts │ │ └── MultiStepForm │ │ │ ├── index.ts │ │ │ ├── ProgressBar │ │ │ ├── index.ts │ │ │ ├── ProgressBar.model.ts │ │ │ ├── ProgressBar.tsx │ │ │ └── ProgressBar.styled.ts │ │ │ ├── ActionButtons │ │ │ ├── index.ts │ │ │ ├── ActionButtons.model.ts │ │ │ ├── ActionButton.styled.ts │ │ │ └── ActionButtons.tsx │ │ │ ├── MultiStep.model.ts │ │ │ ├── MultiStepForm.styled.ts │ │ │ ├── MultiStepForm.tsx │ │ │ └── MultiStepFormBody.tsx │ ├── organisms │ │ └── CourseList │ │ │ ├── index.ts │ │ │ ├── CourseElement │ │ │ ├── index.ts │ │ │ ├── CourseElement.model.ts │ │ │ ├── CourseElement.tsx │ │ │ └── CourseElement.styled.ts │ │ │ ├── CourseList.model.ts │ │ │ ├── CourseList.tsx │ │ │ └── CourseList.styled.ts │ └── forms │ │ └── ExampleForm │ │ ├── Step1.tsx │ │ ├── Step3.tsx │ │ ├── Step2.tsx │ │ └── index.tsx ├── hooks │ ├── useCookie │ │ ├── index.ts │ │ ├── useCookie.model.ts │ │ └── useCookie.ts │ ├── useTimeout │ │ ├── index.ts │ │ └── useTimeout.ts │ ├── useDebounce │ │ ├── index.ts │ │ └── useDebounce.ts │ ├── useInterval │ │ ├── index.ts │ │ └── useInterval.ts │ ├── useTextClip │ │ ├── index.ts │ │ └── useTextClip.ts │ ├── useFormProgress │ │ ├── index.ts │ │ └── useFormProgress.ts │ ├── useOutsideClick │ │ ├── index.ts │ │ ├── useOutsideClick.ts │ │ └── useOutsideClick.test.tsx │ ├── useDocumentTitle │ │ ├── index.ts │ │ ├── useDocumentTitle.ts │ │ └── useDocumentTitle.test.tsx │ ├── useEventListener │ │ ├── index.ts │ │ ├── useEventListener.ts │ │ └── useEventListener.test.tsx │ └── index.ts ├── types │ └── interfaces.ts ├── pages │ ├── UnderConstruction │ │ ├── index.tsx │ │ └── UnderConstruction.tsx │ ├── api │ │ └── hello.js │ ├── index.tsx │ ├── _app.tsx │ ├── _error.tsx │ └── _document.tsx ├── assets │ ├── images │ │ ├── index.ts │ │ ├── arrow-icon.svg │ │ └── listItemIcon.svg │ └── svg │ │ ├── multistepform-next.svg │ │ ├── unchecked-option-icon.svg │ │ ├── multistepform-submit.svg │ │ ├── checked-option-icon.svg │ │ ├── listItemIcon.svg │ │ ├── inputIcon.svg │ │ ├── button-icon.svg │ │ ├── spinner-left-bracket.svg │ │ ├── toast-icon-info.svg │ │ ├── spinner-right-bracket.svg │ │ ├── foundation_social-facebook.svg │ │ ├── google-logo.svg │ │ ├── toast-icon-success.svg │ │ ├── foundation_social-linkedin.svg │ │ ├── toast-icon-error.svg │ │ ├── github-logo.svg │ │ ├── index.ts │ │ ├── foundation_social-github.svg │ │ ├── logo-icon.svg │ │ └── logo-text.svg ├── styles │ ├── devices.ts │ ├── GlobalStyles.tsx │ ├── GlobalStyles.test.tsx │ ├── UnderConstruction.styled.ts │ ├── colors.ts │ └── typography.ts └── redux │ ├── store.ts │ ├── reducers │ ├── loader.ts │ └── multiStepExample.ts │ └── ReduxTestComponent │ └── ReduxTestComponent.tsx ├── public └── favicon.ico ├── .prettierrc ├── .storybook ├── preview-head.html ├── manager.js ├── main.js └── preview.js ├── Dockerfile ├── .babelrc ├── .github ├── auto_assign.yml └── workflows │ ├── auto_assign_to_PR.yml │ ├── PRlint.yml │ ├── node_build_and_test.yml │ ├── coverage-report.yml │ ├── publish-storybook.yml │ ├── codeql-analysis.yml │ └── frontend_aws_deploy.yml ├── next-env.d.ts ├── .vscode └── settings.json ├── frontend_task_definition.json ├── README.md ├── .gitignore ├── .stylelintrc.json ├── next.config.js ├── tsconfig.json ├── commitlint.config.js ├── .eslintrc └── package.json /.husky/.gitignore: -------------------------------------------------------------------------------- 1 | _ 2 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | build -------------------------------------------------------------------------------- /.env: -------------------------------------------------------------------------------- 1 | SKIP_PREFLIGHT_CHECK=true 2 | -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | npm-debug.log 3 | Dockerfile 4 | -------------------------------------------------------------------------------- /src/react-app-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /src/setupTests.ts: -------------------------------------------------------------------------------- 1 | import '@testing-library/jest-dom/extend-expect'; 2 | -------------------------------------------------------------------------------- /.husky/commit-msg: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | . "$(dirname "$0")/_/husky.sh" 3 | 4 | npx commitlint -e -------------------------------------------------------------------------------- /.husky/pre-commit: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | . "$(dirname "$0")/_/husky.sh" 3 | 4 | npx lint-staged -------------------------------------------------------------------------------- /src/components/atoms/Tag/index.ts: -------------------------------------------------------------------------------- 1 | import Tag from './Tag'; 2 | 3 | export default Tag; 4 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Geeks-Academy/frontend/HEAD/public/favicon.ico -------------------------------------------------------------------------------- /src/components/atoms/List/index.ts: -------------------------------------------------------------------------------- 1 | import List from './List'; 2 | 3 | export default List; 4 | -------------------------------------------------------------------------------- /src/components/atoms/Logo/index.ts: -------------------------------------------------------------------------------- 1 | import Logo from './Logo'; 2 | 3 | export default Logo; 4 | -------------------------------------------------------------------------------- /src/components/atoms/Button/index.ts: -------------------------------------------------------------------------------- 1 | import Button from './Button'; 2 | 3 | export default Button; 4 | -------------------------------------------------------------------------------- /src/components/atoms/Header/index.ts: -------------------------------------------------------------------------------- 1 | import Header from './Header'; 2 | 3 | export default Header; 4 | -------------------------------------------------------------------------------- /src/components/atoms/Input/index.ts: -------------------------------------------------------------------------------- 1 | import Input from './Input'; 2 | 3 | export default Input; 4 | -------------------------------------------------------------------------------- /src/components/atoms/Toast/index.ts: -------------------------------------------------------------------------------- 1 | import Toast from './Toast'; 2 | 3 | export default Toast; 4 | -------------------------------------------------------------------------------- /src/components/atoms/Spinner/index.ts: -------------------------------------------------------------------------------- 1 | import Spinner from './Spinner'; 2 | 3 | export default Spinner; 4 | -------------------------------------------------------------------------------- /src/hooks/useCookie/index.ts: -------------------------------------------------------------------------------- 1 | import useCookie from './useCookie'; 2 | 3 | export default useCookie; 4 | -------------------------------------------------------------------------------- /src/hooks/useTimeout/index.ts: -------------------------------------------------------------------------------- 1 | import useTimeout from './useTimeout'; 2 | 3 | export default useTimeout; 4 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true, 3 | "printWidth": 100, 4 | "jsxBracketSameLine": false 5 | } -------------------------------------------------------------------------------- /src/components/atoms/ListItem/index.ts: -------------------------------------------------------------------------------- 1 | import ListItem from './ListItem'; 2 | 3 | export default ListItem; 4 | -------------------------------------------------------------------------------- /src/components/atoms/TextArea/index.ts: -------------------------------------------------------------------------------- 1 | import TextArea from './TextArea'; 2 | 3 | export default TextArea; 4 | -------------------------------------------------------------------------------- /src/hooks/useDebounce/index.ts: -------------------------------------------------------------------------------- 1 | import useDebounce from './useDebounce'; 2 | 3 | export default useDebounce; 4 | -------------------------------------------------------------------------------- /src/hooks/useInterval/index.ts: -------------------------------------------------------------------------------- 1 | import useInterval from './useInterval'; 2 | 3 | export default useInterval; 4 | -------------------------------------------------------------------------------- /src/hooks/useTextClip/index.ts: -------------------------------------------------------------------------------- 1 | import useTextClip from './useTextClip'; 2 | 3 | export default useTextClip; 4 | -------------------------------------------------------------------------------- /src/components/atoms/Paragraph/index.ts: -------------------------------------------------------------------------------- 1 | import Paragraph from './Paragraph'; 2 | 3 | export default Paragraph; 4 | -------------------------------------------------------------------------------- /src/types/interfaces.ts: -------------------------------------------------------------------------------- 1 | export interface IAttributes extends React.HTMLAttributes, React.RefAttributes {} 2 | -------------------------------------------------------------------------------- /src/components/molecules/CourseTags/index.ts: -------------------------------------------------------------------------------- 1 | import CourseTags from './CourseTags'; 2 | 3 | export default CourseTags; 4 | -------------------------------------------------------------------------------- /src/components/molecules/SelectInput/Option/index.ts: -------------------------------------------------------------------------------- 1 | import Option from './Option'; 2 | 3 | export default Option; 4 | -------------------------------------------------------------------------------- /src/components/molecules/SelectInput/Select/index.ts: -------------------------------------------------------------------------------- 1 | import Select from './Select'; 2 | 3 | export default Select; 4 | -------------------------------------------------------------------------------- /src/components/molecules/SkillCard/index.ts: -------------------------------------------------------------------------------- 1 | import SkillCard from './SkillCard'; 2 | 3 | export default SkillCard; 4 | -------------------------------------------------------------------------------- /src/components/organisms/CourseList/index.ts: -------------------------------------------------------------------------------- 1 | import CourseList from './CourseList'; 2 | 3 | export default CourseList; 4 | -------------------------------------------------------------------------------- /src/components/atoms/SocialButton/index.ts: -------------------------------------------------------------------------------- 1 | import SocialButton from './SocialButton'; 2 | 3 | export default SocialButton; 4 | -------------------------------------------------------------------------------- /src/components/molecules/SelectInput/index.ts: -------------------------------------------------------------------------------- 1 | import SelectInput from './SelectInput'; 2 | 3 | export default SelectInput; 4 | -------------------------------------------------------------------------------- /src/hooks/useFormProgress/index.ts: -------------------------------------------------------------------------------- 1 | import useFormProgress from './useFormProgress'; 2 | 3 | export default useFormProgress; 4 | -------------------------------------------------------------------------------- /src/hooks/useOutsideClick/index.ts: -------------------------------------------------------------------------------- 1 | import useOutsideClick from './useOutsideClick'; 2 | 3 | export default useOutsideClick; 4 | -------------------------------------------------------------------------------- /src/hooks/useDocumentTitle/index.ts: -------------------------------------------------------------------------------- 1 | import useDocumentTitle from './useDocumentTitle'; 2 | 3 | export default useDocumentTitle; 4 | -------------------------------------------------------------------------------- /src/hooks/useEventListener/index.ts: -------------------------------------------------------------------------------- 1 | import useEventListener from './useEventListener'; 2 | 3 | export default useEventListener; 4 | -------------------------------------------------------------------------------- /src/components/molecules/MultiStepForm/index.ts: -------------------------------------------------------------------------------- 1 | import MultiStepForm from './MultiStepForm'; 2 | 3 | export default MultiStepForm; 4 | -------------------------------------------------------------------------------- /src/pages/UnderConstruction/index.tsx: -------------------------------------------------------------------------------- 1 | import UnderConstruction from './UnderConstruction'; 2 | 3 | export default UnderConstruction; 4 | -------------------------------------------------------------------------------- /src/components/molecules/MultiStepForm/ProgressBar/index.ts: -------------------------------------------------------------------------------- 1 | import ProgressBar from './ProgressBar'; 2 | 3 | export default ProgressBar; 4 | -------------------------------------------------------------------------------- /src/components/organisms/CourseList/CourseElement/index.ts: -------------------------------------------------------------------------------- 1 | import CourseElement from './CourseElement'; 2 | 3 | export default CourseElement; 4 | -------------------------------------------------------------------------------- /src/assets/images/index.ts: -------------------------------------------------------------------------------- 1 | export { default as ListItemIcon } from './listItemIcon.svg'; 2 | export { default as ArrowIcon } from './arrow-icon.svg'; 3 | -------------------------------------------------------------------------------- /src/components/atoms/GradientBackground/index.ts: -------------------------------------------------------------------------------- 1 | import GradientBackground from './GradientBackground'; 2 | 3 | export default GradientBackground; 4 | -------------------------------------------------------------------------------- /src/components/molecules/MultiStepForm/ActionButtons/index.ts: -------------------------------------------------------------------------------- 1 | import ActionButtons from './ActionButtons'; 2 | 3 | export default ActionButtons; 4 | -------------------------------------------------------------------------------- /.storybook/preview-head.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/hooks/useCookie/useCookie.model.ts: -------------------------------------------------------------------------------- 1 | export interface IOptions { 2 | date?: Date; 3 | path?: string; 4 | domain?: string; 5 | secure?: string; 6 | } 7 | -------------------------------------------------------------------------------- /src/components/atoms/Ranges/index.ts: -------------------------------------------------------------------------------- 1 | import Range from './DefaultRange/Range'; 2 | import LevelRange from './LevelRange/LevelRange'; 3 | 4 | export { Range, LevelRange }; 5 | -------------------------------------------------------------------------------- /src/pages/api/hello.js: -------------------------------------------------------------------------------- 1 | // Next.js API route support: https://nextjs.org/docs/api-routes/introduction 2 | 3 | export default (req, res) => { 4 | res.statusCode = 200; 5 | res.json({ name: 'John Doe' }); 6 | }; 7 | -------------------------------------------------------------------------------- /src/components/atoms/List/List.model.ts: -------------------------------------------------------------------------------- 1 | export interface ILink { 2 | url: string; 3 | text: string; 4 | } 5 | export interface IListElement { 6 | id: number; 7 | txt: string; 8 | link?: ILink; 9 | } 10 | -------------------------------------------------------------------------------- /src/pages/index.tsx: -------------------------------------------------------------------------------- 1 | import UnderConstruction from './UnderConstruction'; 2 | 3 | export default function Home() { 4 | return ( 5 |
6 | 7 |
8 | ); 9 | } 10 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:16.0-buster-slim 2 | RUN mkdir -p /usr/src/app 3 | WORKDIR /usr/src/app 4 | COPY package.json /usr/src/app/ 5 | COPY . /usr/src/app/ 6 | RUN npm i 7 | RUN npm run build 8 | ENTRYPOINT ["npm", "start"] 9 | -------------------------------------------------------------------------------- /src/assets/images/arrow-icon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/assets/svg/multistepform-next.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /src/components/atoms/ListItem/ListItem.model.ts: -------------------------------------------------------------------------------- 1 | export interface ILink { 2 | url: string; 3 | text: string; 4 | } 5 | 6 | export interface IListItem { 7 | id: number; 8 | txt: string; 9 | link?: ILink; 10 | } 11 | -------------------------------------------------------------------------------- /src/components/molecules/SkillCard/SkillCard.model.ts: -------------------------------------------------------------------------------- 1 | import { IAttributes } from 'types/interfaces'; 2 | 3 | export interface ISkillCard extends IAttributes { 4 | title: string; 5 | content: string; 6 | } 7 | -------------------------------------------------------------------------------- /src/assets/svg/unchecked-option-icon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/components/atoms/Tag/Tag.model.ts: -------------------------------------------------------------------------------- 1 | import { IAttributes } from 'types/interfaces'; 2 | 3 | export interface IProps extends IAttributes { 4 | bgColor?: string; 5 | fontColor?: string; 6 | getWidth?: any; 7 | } 8 | -------------------------------------------------------------------------------- /src/assets/svg/multistepform-submit.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /src/components/atoms/Logo/Logo.model.ts: -------------------------------------------------------------------------------- 1 | import { IAttributes } from 'types/interfaces'; 2 | 3 | export interface IProps extends IAttributes { 4 | logoOnly?: boolean; 5 | textPlacement?: 'vertical' | 'horizontal'; 6 | } 7 | -------------------------------------------------------------------------------- /src/components/molecules/MultiStepForm/ActionButtons/ActionButtons.model.ts: -------------------------------------------------------------------------------- 1 | export interface IActionButtons { 2 | activeStep: number; 3 | onBack: () => void; 4 | onNext: () => void; 5 | onCancel: () => void; 6 | lastStep: number; 7 | } 8 | -------------------------------------------------------------------------------- /src/components/atoms/Ranges/LevelRange/data.ts: -------------------------------------------------------------------------------- 1 | export const data = [ 2 | { id: 1, label: 'newbie', value: 25 }, 3 | { id: 2, label: 'junior', value: 50 }, 4 | { id: 3, label: 'mid', value: 75 }, 5 | { id: 4, label: 'senior', value: 100 }, 6 | ]; 7 | -------------------------------------------------------------------------------- /src/hooks/useTextClip/useTextClip.ts: -------------------------------------------------------------------------------- 1 | const useTextClip = (text: string, maxChar = 70): string => { 2 | if (text.length > maxChar) { 3 | text = `${text.substring(0, maxChar)}...`; 4 | } 5 | return text; 6 | }; 7 | 8 | export default useTextClip; 9 | -------------------------------------------------------------------------------- /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | "next/babel" 4 | ], 5 | "plugins": [ 6 | [ 7 | "styled-components", 8 | { 9 | "ssr": true, 10 | "displayName": true, 11 | "preprocess": false 12 | } 13 | ] 14 | ] 15 | } -------------------------------------------------------------------------------- /.github/auto_assign.yml: -------------------------------------------------------------------------------- 1 | addReviewers: true 2 | addAssignees: author 3 | numberOfReviewers: 0 4 | reviewers: 5 | - PiotrGrobelak 6 | - hendrysiak 7 | - Krysik 8 | - hayuna 9 | - TomaszKorenberg 10 | - MaciejSpalek 11 | - caren1 12 | - zeglarz 13 | -------------------------------------------------------------------------------- /src/components/atoms/List/List.styled.ts: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | import typography from 'styles/typography'; 4 | 5 | export const StyledList = styled.ul` 6 | margin: 0; 7 | ${typography.body.L}; 8 | list-style: none; 9 | `; 10 | -------------------------------------------------------------------------------- /src/components/molecules/CourseTags/CourseTags.model.ts: -------------------------------------------------------------------------------- 1 | import { IProps as Tag } from 'components/atoms/Tag/Tag.model'; 2 | import { IAttributes } from 'types/interfaces'; 3 | 4 | export interface IProps extends IAttributes { 5 | tags: Tag[]; 6 | } 7 | -------------------------------------------------------------------------------- /src/components/molecules/MultiStepForm/ActionButtons/ActionButton.styled.ts: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | export const StyledButtonWrapper = styled.div` 4 | display: flex; 5 | justify-content: space-between; 6 | grid-gap: 25px; 7 | margin-top: 35px; 8 | `; 9 | -------------------------------------------------------------------------------- /src/components/molecules/MultiStepForm/ProgressBar/ProgressBar.model.ts: -------------------------------------------------------------------------------- 1 | import { IFormData } from '../MultiStep.model'; 2 | 3 | export interface IProgressBar { 4 | steps: number[]; 5 | activeStep: number; 6 | changeStep: (step: number) => void; 7 | formData: IFormData; 8 | } 9 | -------------------------------------------------------------------------------- /src/components/organisms/CourseList/CourseList.model.ts: -------------------------------------------------------------------------------- 1 | import { IAttributes } from 'types/interfaces'; 2 | import { IProps as Course } from './CourseElement/CourseElement.model'; 3 | 4 | export interface IProps extends IAttributes { 5 | courses: Course[]; 6 | } 7 | -------------------------------------------------------------------------------- /next-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | /// 3 | /// 4 | 5 | declare module '*.png'; 6 | declare module '*.jpg'; 7 | declare module '*.jpeg'; 8 | declare module '*.svg'; 9 | declare module '*.gif'; 10 | -------------------------------------------------------------------------------- /src/components/atoms/TextArea/TextArea.styled.ts: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | import colors from 'styles/colors'; 3 | 4 | export const StyledTextArea = styled.textarea` 5 | padding: 5px; 6 | width: 300px; 7 | height: 100px; 8 | border: 1px solid ${colors.background.Neutral80}; 9 | `; 10 | -------------------------------------------------------------------------------- /src/assets/svg/checked-option-icon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/components/atoms/Header/Header.tsx: -------------------------------------------------------------------------------- 1 | import { IAttributes } from 'types/interfaces'; 2 | 3 | import { Title } from './Header.styled'; 4 | 5 | const Header = ({ children, ...props }: IAttributes): JSX.Element => { 6 | return {children}; 7 | }; 8 | 9 | export default Header; 10 | -------------------------------------------------------------------------------- /src/components/atoms/Input/Input.model.ts: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export interface IProps extends React.InputHTMLAttributes { 4 | icon?: string; 5 | fullWidth?: boolean; 6 | label?: string; 7 | error?: string; 8 | onChange?: any; // todo: add property type 9 | debounce?: number; 10 | } 11 | -------------------------------------------------------------------------------- /src/components/atoms/GradientBackground/GradientBackground.model.ts: -------------------------------------------------------------------------------- 1 | import { IAttributes } from 'types/interfaces'; 2 | 3 | export type GradientType = { 4 | angle?: string; 5 | colors: string[]; 6 | }; 7 | 8 | export interface IProps extends IAttributes { 9 | background: string; 10 | gradient?: GradientType; 11 | } 12 | -------------------------------------------------------------------------------- /src/components/molecules/SelectInput/Option/Option.model.ts: -------------------------------------------------------------------------------- 1 | import { ISingleOption } from '../SelectInput.model'; 2 | 3 | export interface IOption { 4 | isMulti: boolean; 5 | option: ISingleOption; 6 | selectedOptions: ISingleOption[]; 7 | currentOptionId: string; 8 | updateSelectedOptions: (option: ISingleOption) => void; 9 | } 10 | -------------------------------------------------------------------------------- /src/styles/devices.ts: -------------------------------------------------------------------------------- 1 | const device = { 2 | mobile: `@media (max-width: 640px)`, 3 | mobileL: `@media (max-width: 767px)`, 4 | tablet: `@media (min-width: 768px)`, 5 | tabletL: `@media (min-width: 1024px)`, 6 | desktop: `@media (min-width: 1366px)`, 7 | desktopFHD: `@media (min-width: 1920px)`, 8 | }; 9 | 10 | export default device; 11 | -------------------------------------------------------------------------------- /src/components/molecules/SelectInput/Select/Select.model.ts: -------------------------------------------------------------------------------- 1 | import { ISingleOption } from '../SelectInput.model'; 2 | 3 | export interface ISelect { 4 | isMulti: boolean; 5 | selectCaption: string; 6 | inputPlaceholder: string; 7 | options: ISingleOption[]; 8 | onChange: (selection: ISingleOption[]) => void; 9 | isOpen?: boolean; 10 | } 11 | -------------------------------------------------------------------------------- /src/hooks/useDocumentTitle/useDocumentTitle.ts: -------------------------------------------------------------------------------- 1 | import { useEffect, useState } from 'react'; 2 | 3 | const useDocumentTitle = (title: string): void => { 4 | const [documentTitle] = useState(title); 5 | 6 | useEffect(() => { 7 | document.title = documentTitle; 8 | }, [documentTitle]); 9 | }; 10 | 11 | export default useDocumentTitle; 12 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "typescript.tsdk": "node_modules/typescript/lib", 3 | "eslint.alwaysShowStatus": true, 4 | "editor.codeActionsOnSave": { 5 | "source.fixAll.eslint": true, 6 | "source.fixAll": true 7 | }, 8 | "editor.formatOnSave": false, 9 | "javascript.preferences.importModuleSpecifier": "non-relative" 10 | } 11 | -------------------------------------------------------------------------------- /.github/workflows/auto_assign_to_PR.yml: -------------------------------------------------------------------------------- 1 | name: Auto Assign 2 | 3 | on: 4 | pull_request: 5 | types: [opened] 6 | 7 | jobs: 8 | add-reviewers: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - name: add reviewers & assign author 12 | uses: kentaro-m/auto-assign-action@v1.1.1 13 | with: 14 | repo-token: ${{ secrets.GITHUB_TOKEN }} -------------------------------------------------------------------------------- /src/components/atoms/SocialButton/SocialButton.model.ts: -------------------------------------------------------------------------------- 1 | export type Logo = 'github' | 'google'; 2 | export type Role = 'developer' | 'non-developer'; 3 | 4 | export enum DefaultLogo { 5 | GOOGLE = 'google', 6 | GITHUB = 'github', 7 | } 8 | 9 | export enum DefaultRole { 10 | DEVELOPER = 'Login as developer', 11 | NONDEVELOPER = 'Login as non developer', 12 | } 13 | -------------------------------------------------------------------------------- /src/components/molecules/SelectInput/SelectInput.model.ts: -------------------------------------------------------------------------------- 1 | export interface ISingleOption { 2 | id: string; 3 | value: string; 4 | } 5 | 6 | export interface ISelectInput { 7 | isMulti?: boolean; 8 | selectCaption: string; 9 | inputPlaceholder: string; 10 | options: ISingleOption[]; 11 | onChange: (selection: ISingleOption[]) => void; 12 | isOpen?: boolean; 13 | } 14 | -------------------------------------------------------------------------------- /src/components/atoms/Button/Button.model.ts: -------------------------------------------------------------------------------- 1 | import { IAttributes } from 'types/interfaces'; 2 | 3 | export type IconPosition = 'left' | 'right' | null; 4 | 5 | export interface IButton extends IAttributes { 6 | icon?: string; 7 | iconPos?: IconPosition; 8 | filled?: boolean; 9 | outline?: boolean; 10 | disabled?: boolean; 11 | transparent?: boolean; 12 | } 13 | -------------------------------------------------------------------------------- /src/components/molecules/MultiStepForm/MultiStep.model.ts: -------------------------------------------------------------------------------- 1 | export interface IFormData { 2 | [key: string]: string | boolean; 3 | } 4 | 5 | export interface IMultiStepForm { 6 | title?: string; 7 | children?: JSX.Element[] | JSX.Element; 8 | onSubmit: (data: IFormData) => void; 9 | onNext: (data: IFormData) => void; 10 | onBack: (data: IFormData) => void; 11 | onCancel: () => void; 12 | } 13 | -------------------------------------------------------------------------------- /.storybook/manager.js: -------------------------------------------------------------------------------- 1 | import { addons } from '@storybook/addons'; 2 | 3 | addons.setConfig({ 4 | isFullscreen: false, 5 | showNav: true, 6 | showPanel: true, 7 | panelPosition: 'bottom', 8 | sidebarAnimations: true, 9 | enableShortcuts: false, 10 | isToolshown: true, 11 | theme: undefined, 12 | selectedPanel: undefined, 13 | initialActive: 'sidebar', 14 | showRoots: true, 15 | }); 16 | -------------------------------------------------------------------------------- /src/components/atoms/Paragraph/Paragraph.test.tsx: -------------------------------------------------------------------------------- 1 | import { render } from '@testing-library/react'; 2 | import Paragraph from './Paragraph'; 3 | 4 | describe('Paragraph', () => { 5 | test('render Paragraph component with text', () => { 6 | const text = 'Test text'; 7 | const { getByText } = render({text}); 8 | expect(getByText(text)).toBeInTheDocument(); 9 | }); 10 | }); 11 | -------------------------------------------------------------------------------- /src/styles/GlobalStyles.tsx: -------------------------------------------------------------------------------- 1 | import { createGlobalStyle } from 'styled-components'; 2 | import typography from './typography'; 3 | 4 | const GlobalStyles = createGlobalStyle` 5 | * { 6 | ${typography.globalStyles}; 7 | } 8 | *, *::before, *::after { 9 | box-sizing: border-box; 10 | } 11 | body{ 12 | margin: 0; 13 | } 14 | `; 15 | 16 | export default GlobalStyles; 17 | -------------------------------------------------------------------------------- /src/components/molecules/MultiStepForm/MultiStepForm.styled.ts: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | export const StyledTitle = styled.h1` 4 | font-weight: bold; 5 | text-align: center; 6 | `; 7 | 8 | export const StyledForm = styled.form` 9 | display: flex; 10 | flex-direction: column; 11 | 12 | div { 13 | display: flex; 14 | flex-direction: column; 15 | row-gap: 24px; 16 | } 17 | `; 18 | -------------------------------------------------------------------------------- /.github/workflows/PRlint.yml: -------------------------------------------------------------------------------- 1 | name: PR lint 2 | 3 | on: 4 | pull_request: 5 | types: ['opened', 'edited', 'reopened', 'synchronize'] 6 | 7 | jobs: 8 | pr-lint: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - uses: seferov/pr-lint-action@master 12 | with: 13 | title-regex: '^\FRDQ-\d+( - )?.*' 14 | title-regex-flags: 'g' # optional 15 | error-message: 'Add Vivify ID to your title' -------------------------------------------------------------------------------- /src/components/atoms/Header/Header.styled.ts: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | import device from 'styles/devices'; 4 | import typography from 'styles/typography'; 5 | import colors from 'styles/colors'; 6 | 7 | export const Title = styled.h1` 8 | color: ${colors.background.NeutralBlack}; 9 | ${typography.header.bold.L} 10 | 11 | ${device.mobile} { 12 | ${typography.header.bold.S} 13 | } 14 | `; 15 | -------------------------------------------------------------------------------- /src/components/atoms/Paragraph/Paragraph.styled.ts: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | import device from 'styles/devices'; 4 | import typography from 'styles/typography'; 5 | import colors from 'styles/colors'; 6 | 7 | export const StyledParagraph = styled.p` 8 | color: ${colors.background.NeutralBlack}; 9 | ${typography.body.M} 10 | 11 | ${device.tablet} { 12 | ${typography.body.L} 13 | } 14 | `; 15 | -------------------------------------------------------------------------------- /src/hooks/useDebounce/useDebounce.ts: -------------------------------------------------------------------------------- 1 | import { useState } from 'react'; 2 | 3 | const useDebounce = () => { 4 | const [typingTimeout, setTypingTimeout] = useState(); 5 | return (action: () => void, waitTime: number) => { 6 | clearTimeout(typingTimeout); 7 | const timeout: any = setTimeout(() => action(), waitTime); 8 | setTypingTimeout(timeout); 9 | }; 10 | }; 11 | 12 | export default useDebounce; 13 | -------------------------------------------------------------------------------- /src/pages/_app.tsx: -------------------------------------------------------------------------------- 1 | import type { AppProps } from 'next/app'; 2 | import GlobalStyles from 'styles/GlobalStyles'; 3 | import { Provider } from 'react-redux'; 4 | import { store } from 'redux/store'; 5 | 6 | export default function MyApp({ Component, pageProps }: AppProps): JSX.Element { 7 | return ( 8 | 9 | 10 | 11 | 12 | ); 13 | } 14 | -------------------------------------------------------------------------------- /src/redux/store.ts: -------------------------------------------------------------------------------- 1 | import { configureStore } from '@reduxjs/toolkit'; 2 | import loader from 'redux/reducers/loader'; 3 | import multiStepExample from 'redux/reducers/multiStepExample'; 4 | 5 | export const store = configureStore({ 6 | reducer: { 7 | loader: loader.reducer, 8 | multiStepExample: multiStepExample.reducer, 9 | }, 10 | }); 11 | 12 | export interface RootState { 13 | [key: string]: Record; 14 | } 15 | -------------------------------------------------------------------------------- /src/assets/svg/listItemIcon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/components/atoms/Header/Header.test.tsx: -------------------------------------------------------------------------------- 1 | import { cleanup, render } from '@testing-library/react'; 2 | import Header from './Header'; 3 | 4 | afterEach(cleanup); 5 | 6 | describe('Header', () => { 7 | test('render Header component with title', () => { 8 | const title = 'Example title'; 9 | const { getByText } = render(
{title}
); 10 | expect(getByText(title)).toHaveTextContent(/Example/i); 11 | }); 12 | }); 13 | -------------------------------------------------------------------------------- /src/assets/images/listItemIcon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/components/atoms/Paragraph/Paragraph.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { StyledParagraph } from './Paragraph.styled'; 3 | 4 | export interface IProps 5 | extends React.HTMLAttributes, 6 | React.RefAttributes {} 7 | 8 | const Paragraph = ({ children, ...props }: IProps): JSX.Element => { 9 | return {children}; 10 | }; 11 | 12 | export default Paragraph; 13 | -------------------------------------------------------------------------------- /src/components/molecules/SkillCard/SkillCard.test.tsx: -------------------------------------------------------------------------------- 1 | import { render } from '@testing-library/react'; 2 | import SkillCard from './SkillCard'; 3 | 4 | describe('SkillCard', () => { 5 | test('render SkillCard component with title', () => { 6 | const title = 'Test text'; 7 | const content = 'Test content'; 8 | const { getByText } = render(); 9 | expect(getByText(title)).toBeInTheDocument(); 10 | }); 11 | }); 12 | -------------------------------------------------------------------------------- /src/hooks/useOutsideClick/useOutsideClick.ts: -------------------------------------------------------------------------------- 1 | import { useEventListener } from 'hooks'; 2 | import { RefObject } from 'react'; 3 | 4 | const useOutsideClick = (ref: RefObject, callback: () => void): void => { 5 | const handleClick = (e: Event) => { 6 | if (ref.current && !ref.current.contains(e.target as HTMLElement)) { 7 | callback(); 8 | } 9 | }; 10 | useEventListener('click', handleClick); 11 | }; 12 | 13 | export default useOutsideClick; 14 | -------------------------------------------------------------------------------- /src/components/atoms/Spinner/Spinner.stories.tsx: -------------------------------------------------------------------------------- 1 | import { IAttributes } from 'types/interfaces'; 2 | import Spinner from './Spinner'; 3 | 4 | export default { 5 | title: 'atoms/Spinner', 6 | component: Spinner, 7 | argTypes: { 8 | className: { 9 | control: { 10 | disable: true, 11 | }, 12 | }, 13 | }, 14 | }; 15 | 16 | export const SpinnerComponent = (props: IAttributes): JSX.Element => ( 17 | 18 | ); 19 | -------------------------------------------------------------------------------- /src/hooks/useDocumentTitle/useDocumentTitle.test.tsx: -------------------------------------------------------------------------------- 1 | import { render } from '@testing-library/react'; 2 | import { useDocumentTitle } from 'hooks'; 3 | 4 | const Component = (): JSX.Element => { 5 | useDocumentTitle('Document Title'); 6 | return
; 7 | }; 8 | 9 | describe('useDocumentTitle hook', () => { 10 | test('should change document title', () => { 11 | render(); 12 | expect(document.title).toEqual('Document Title'); 13 | }); 14 | }); 15 | -------------------------------------------------------------------------------- /src/redux/reducers/loader.ts: -------------------------------------------------------------------------------- 1 | import { createSlice } from '@reduxjs/toolkit'; 2 | 3 | interface InitialLoaderState { 4 | isLoading: boolean; 5 | } 6 | 7 | const initialState: InitialLoaderState = { 8 | isLoading: false, 9 | }; 10 | 11 | const loader = createSlice({ 12 | name: 'loader', 13 | initialState, 14 | reducers: { 15 | toggleLoader: (state): void => { 16 | state.isLoading = !state.isLoading; 17 | }, 18 | }, 19 | }); 20 | 21 | export default loader; 22 | -------------------------------------------------------------------------------- /src/components/organisms/CourseList/CourseElement/CourseElement.model.ts: -------------------------------------------------------------------------------- 1 | import { IProps as Tag } from 'components/atoms/Tag/Tag.model'; 2 | import { IAttributes } from 'types/interfaces'; 3 | 4 | export interface IProps extends IAttributes { 5 | description: string; 6 | image: string; 7 | author: string; 8 | releaseDate: Date; 9 | price: number; 10 | score: number; 11 | level: 'Junior' | 'Mid' | 'Senior'; 12 | tags: Tag[]; 13 | recommendation?: boolean; 14 | } 15 | -------------------------------------------------------------------------------- /src/components/atoms/Tag/Tag.styled.ts: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | import typography from 'styles/typography'; 3 | 4 | export const TagElement = styled.div<{ fontColor?: string; bgColor?: string }>` 5 | display: inline-block; 6 | margin: 0px 3px; 7 | padding: 4px 8px; 8 | border-radius: 4px; 9 | ${typography.body.S}; 10 | background-color: ${(props) => props.bgColor || 'rgba(95, 236, 152, 0.2)'}; 11 | color: ${(props) => props.fontColor || 'rgba(0, 102, 41, 0.7)'}; 12 | `; 13 | -------------------------------------------------------------------------------- /frontend_task_definition.json: -------------------------------------------------------------------------------- 1 | { 2 | "family": "geeks_frontend", 3 | "containerDefinitions": [ 4 | { 5 | "name": "geeks_frontend", 6 | "image": "", 7 | "cpu": 10, 8 | "memoryReservation": 128, 9 | "portMappings": [ 10 | { 11 | "containerPort": 80, 12 | "hostPort": 0, 13 | "protocol": "tcp" 14 | } 15 | ] 16 | } 17 | ] 18 | } 19 | -------------------------------------------------------------------------------- /src/hooks/index.ts: -------------------------------------------------------------------------------- 1 | export { default as useDebounce } from './useDebounce'; 2 | export { default as useOutsideClick } from './useOutsideClick'; 3 | export { default as useDocumentTitle } from './useDocumentTitle'; 4 | export { default as useEventListener } from './useEventListener'; 5 | export { default as useFormProgress } from './useFormProgress'; 6 | export { default as useTextClip } from './useTextClip'; 7 | export { default as useInterval } from './useInterval'; 8 | export { default as useTimeout } from './useTimeout'; 9 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # frontend 2 | Microservice for UI of application 3 | 4 | [![CodeFactor](https://www.codefactor.io/repository/github/geeks-academy/frontend/badge)](https://www.codefactor.io/repository/github/geeks-academy/frontend) 5 | 6 | 7 | ### Commitlint configuration: 8 | 9 | Your commit message should contain PREFIX: FRDQ, ID as a number, and SUBJECT. 10 | Example: ```"FRDQ-21 - Your commit message"``` 11 | 12 | 13 | [Show demo](https://geeks.academy/) 14 | 15 | [Show storybook](https://geeks-academy.github.io/frontend) 16 | -------------------------------------------------------------------------------- /src/components/atoms/Ranges/DefaultRange/Range.stories.tsx: -------------------------------------------------------------------------------- 1 | import { Meta } from '@storybook/react/types-6-0'; 2 | import { IAttributes } from 'types/interfaces'; 3 | import Range from './Range'; 4 | 5 | export default { 6 | title: 'atoms/Ranges/Range', 7 | component: Range, 8 | argTypes: { 9 | className: { 10 | control: { 11 | disable: true, 12 | }, 13 | }, 14 | }, 15 | } as Meta; 16 | 17 | export const DefaultRange = (props: IAttributes): JSX.Element => ( 18 | 19 | ); 20 | -------------------------------------------------------------------------------- /src/components/atoms/GradientBackground/GradientBackground.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { StyledHeader, StyledWrapper } from './GradientBackground.styled'; 3 | import { IProps } from './GradientBackground.model'; 4 | 5 | const GradientBackground = ({ background, gradient, children, ...props }: IProps): JSX.Element => { 6 | return ( 7 | 8 | {children} 9 | 10 | ); 11 | }; 12 | 13 | export default GradientBackground; 14 | -------------------------------------------------------------------------------- /src/components/atoms/SocialButton/SocialButton.stories.tsx: -------------------------------------------------------------------------------- 1 | import SocialButton from './SocialButton'; 2 | 3 | export default { 4 | title: 'atoms/SocialButton', 5 | component: SocialButton, 6 | argTypes: { 7 | className: { 8 | control: { 9 | disable: true, 10 | }, 11 | }, 12 | }, 13 | }; 14 | 15 | export const GoogleButton = (): JSX.Element => ( 16 | 17 | ); 18 | 19 | export const GithubButton = (): JSX.Element => ; 20 | -------------------------------------------------------------------------------- /src/components/organisms/CourseList/CourseList.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { IProps } from './CourseList.model'; 3 | import { Courses } from './CourseList.styled'; 4 | import CourseElement from './CourseElement'; 5 | 6 | const CourseList = ({ courses, ...props }: IProps): JSX.Element => { 7 | return ( 8 |
9 | {courses.map((course) => ( 10 | 11 | 12 | 13 | ))} 14 |
15 | ); 16 | }; 17 | 18 | export default CourseList; 19 | -------------------------------------------------------------------------------- /src/assets/svg/inputIcon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/components/atoms/TextArea/TextArea.stories.tsx: -------------------------------------------------------------------------------- 1 | import { IAttributes } from 'types/interfaces'; 2 | import TextArea from './TextArea'; 3 | 4 | export default { 5 | title: 'atoms/TextArea', 6 | component: TextArea, 7 | argTypes: { 8 | placeholder: { 9 | defaultValue: 'Type something...', 10 | type: 'string', 11 | }, 12 | className: { 13 | control: { 14 | disable: true, 15 | }, 16 | }, 17 | }, 18 | }; 19 | 20 | export const Default = ({ placeholder }: IAttributes): JSX.Element => ( 21 |