diff --git a/ui/package.json b/ui/package.json index a91756e9..1cbd8ff3 100644 --- a/ui/package.json +++ b/ui/package.json @@ -5,6 +5,7 @@ "packageManager": "yarn@3.6.1", "dependencies": { "@emotion/react": "^11.11.0", + "@excalidraw/excalidraw": "^0.16.0", "@faker-js/faker": "^7.6.0", "@mantine/core": "^6.0.10", "@mantine/ds": "^6.0.10", @@ -28,7 +29,7 @@ "jspdf": "^2.5.1", "jszip": "^3.10.1", "jszip-utils": "^0.1.0", - "lucide-react": "^0.260.0", + "lucide-react": "^0.262.0", "marked": "^7.0.1", "react": "^18.2.0", "react-dom": "^18.2.0", diff --git a/ui/src/assets/home/avatar.gif b/ui/src/assets/home/avatar.gif new file mode 100644 index 00000000..284c6c50 Binary files /dev/null and b/ui/src/assets/home/avatar.gif differ diff --git a/ui/src/assets/home/detection.svg b/ui/src/assets/home/detection.svg new file mode 100644 index 00000000..9b3176dc --- /dev/null +++ b/ui/src/assets/home/detection.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/ui/src/assets/home/header.svg b/ui/src/assets/home/header.svg new file mode 100644 index 00000000..5813d2d8 --- /dev/null +++ b/ui/src/assets/home/header.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/ui/src/assets/home/hero.jpg b/ui/src/assets/home/hero.jpg new file mode 100644 index 00000000..242f5c21 Binary files /dev/null and b/ui/src/assets/home/hero.jpg differ diff --git a/ui/src/assets/home/share.svg b/ui/src/assets/home/share.svg new file mode 100644 index 00000000..aabf4d3e --- /dev/null +++ b/ui/src/assets/home/share.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/ui/src/assets/home/verification.svg b/ui/src/assets/home/verification.svg new file mode 100644 index 00000000..c29cf5ab --- /dev/null +++ b/ui/src/assets/home/verification.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/ui/src/components/Hoc/withPageTitle.tsx b/ui/src/components/Hoc/withPageTitle.tsx index 10cc0d23..abdb968f 100644 --- a/ui/src/components/Hoc/withPageTitle.tsx +++ b/ui/src/components/Hoc/withPageTitle.tsx @@ -1,5 +1,6 @@ import Text from "components/General/Text/Text"; import usePageTitle from "components/Hoc/utils/hooks/usePageTitle"; +import style from "./withpagetitle.module.scss"; const withPageTitle = ( WrappedComponent: React.ComponentType @@ -8,12 +9,17 @@ const withPageTitle = ( const [title, description] = usePageTitle(); return ( - <> - - -
+
+ {title !== "Home" && ( + <> + + +
+ + )} + - +
); }; diff --git a/ui/src/components/Hoc/withpagetitle.module.scss b/ui/src/components/Hoc/withpagetitle.module.scss new file mode 100644 index 00000000..bcd745ff --- /dev/null +++ b/ui/src/components/Hoc/withpagetitle.module.scss @@ -0,0 +1,3 @@ +.withpagetitle { + padding: var(--bt-size-10) var(--bt-size-10) 0 var(--bt-size-10); +} diff --git a/ui/src/components/Layouts/Footer/Footer.module.scss b/ui/src/components/Layouts/Footer/Footer.module.scss index ae7d252f..26b29285 100644 --- a/ui/src/components/Layouts/Footer/Footer.module.scss +++ b/ui/src/components/Layouts/Footer/Footer.module.scss @@ -1,37 +1,36 @@ .footer { + margin-top: var(--bt-size-20); + margin-left: calc(var(--bt-size-10) * -1); + margin-right: calc(var(--bt-size-10) * -1); + padding: var(--bt-size-10); display: flex; - flex-direction: column; + justify-content: space-between; + align-items: center; - &__monogram { - display: block; - max-width: var(--bt-size-135); - max-height: var(--bt-size-55); - width: auto; - height: auto; - padding-top: var(--bt-size-10); - padding-bottom: var(--bt-size-10); - margin-bottom: var(--bt-size-10); - - &_dark { - border-bottom: var(--bt-border-solid-light); - } - - &_light { - border-bottom: var(--bt-border-solid-dark); - } - } - - &__menuCollapse { - @media (max-width: 768px) { - display: none; + &__left { + display: flex; + align-items: center; + gap: var(--bt-size-20); + &_list { + list-style-type: none; + display: flex; + gap: var(--bt-size-10); + padding: 0px; } } - &__moon { - margin-top: var(--bt-size-3); - } + @media (max-width: 767px) { + gap: var(--bt-size-10); + flex-direction: column; + align-items: center; + justify-items: center; - &__sun { - margin-top: var(--bt-size-minus-1); + &__left { + display: flex; + flex-direction: column; + justify-items: center; + align-items: center; + gap: var(--bt-size-10); + } } } diff --git a/ui/src/components/Layouts/Footer/index.tsx b/ui/src/components/Layouts/Footer/index.tsx index 6d393573..93b48931 100644 --- a/ui/src/components/Layouts/Footer/index.tsx +++ b/ui/src/components/Layouts/Footer/index.tsx @@ -1,69 +1,63 @@ -import { theme, Switch, Space, Button } from "antd"; +import React from "react"; import style from "./Footer.module.scss"; -import MonogramDark from "assets/netlify-monogram-dark.svg"; -import MonogramLight from "assets/netlify-monogram-light.svg"; -import Logo from "assets/netlify-dark.svg"; -import { FooterProps } from "./utils/types"; -import { classNames } from "lib/utils/helper"; import Icon from "components/General/Icon"; +import { Typography, theme } from "antd"; +import { ResponsiveButton } from "components/General/FormComponents"; -const Footer: React.FC = ({ - handleThemeChange, - isDarkMode, - collapsed, - handleMenuCollapse, -}) => { +const Footer: React.FC = () => { const { - token: { colorBgContainer, colorText }, + token: { colorBgContainer }, } = theme.useToken(); - const monogram = isDarkMode ? MonogramDark : MonogramLight; return ( - - - Deploys by Netlify - +
+
+ + © {new Date().getFullYear()} Binarytree + +
+
- } - unCheckedChildren={ -
- -
+
  • + Privacy +
  • +
  • + Terms +
  • +
  • + + Status + +
  • + + + + } + onClick={() => + window.open( + "https://github.com/lifeparticle/binarytree", + "_blank", + "noopener" + ) } - onChange={handleThemeChange} - style={{ backgroundColor: colorText }} - checked={isDarkMode} /> - - -
    + ); }; diff --git a/ui/src/components/Layouts/Menu/utils/constants.ts b/ui/src/components/Layouts/Menu/utils/constants.ts index b1d230c8..3504d34e 100644 --- a/ui/src/components/Layouts/Menu/utils/constants.ts +++ b/ui/src/components/Layouts/Menu/utils/constants.ts @@ -1,16 +1,10 @@ import { MenuProps } from "antd"; import { IconName } from "components/General/Icon/utils/types"; import { getItem } from "components/Layouts/Menu/utils/helper"; -import { routes } from "pages/Routes/utils/constant"; -import { Route, RouteId } from "pages/Routes/utils/types"; +import { routesById } from "pages/Routes/utils/constant"; const IN_DEVELOPMENT = import.meta.env.DEV; -const routesById = routes.reduce((acc, route) => { - acc[route.id] = route; - return acc; -}, {} as Record); - export const MENU_ITEMS = [ { name: "Newsfeed", @@ -162,6 +156,12 @@ export const MENU_ITEMS = [ icon: "Wrench", show: true, children: [ + { + name: routesById.diagramming.title, + url: routesById.diagramming.path, + icon: "PencilRuler", + show: true, + }, { name: routesById.svgformatter.title, url: routesById.svgformatter.path, diff --git a/ui/src/components/Layouts/Sidebar/Footer/Footer.module.scss b/ui/src/components/Layouts/Sidebar/Footer/Footer.module.scss new file mode 100644 index 00000000..ae7d252f --- /dev/null +++ b/ui/src/components/Layouts/Sidebar/Footer/Footer.module.scss @@ -0,0 +1,37 @@ +.footer { + display: flex; + flex-direction: column; + + &__monogram { + display: block; + max-width: var(--bt-size-135); + max-height: var(--bt-size-55); + width: auto; + height: auto; + padding-top: var(--bt-size-10); + padding-bottom: var(--bt-size-10); + margin-bottom: var(--bt-size-10); + + &_dark { + border-bottom: var(--bt-border-solid-light); + } + + &_light { + border-bottom: var(--bt-border-solid-dark); + } + } + + &__menuCollapse { + @media (max-width: 768px) { + display: none; + } + } + + &__moon { + margin-top: var(--bt-size-3); + } + + &__sun { + margin-top: var(--bt-size-minus-1); + } +} diff --git a/ui/src/components/Layouts/Sidebar/Footer/index.tsx b/ui/src/components/Layouts/Sidebar/Footer/index.tsx new file mode 100644 index 00000000..6d393573 --- /dev/null +++ b/ui/src/components/Layouts/Sidebar/Footer/index.tsx @@ -0,0 +1,70 @@ +import { theme, Switch, Space, Button } from "antd"; +import style from "./Footer.module.scss"; +import MonogramDark from "assets/netlify-monogram-dark.svg"; +import MonogramLight from "assets/netlify-monogram-light.svg"; +import Logo from "assets/netlify-dark.svg"; +import { FooterProps } from "./utils/types"; +import { classNames } from "lib/utils/helper"; +import Icon from "components/General/Icon"; + +const Footer: React.FC = ({ + handleThemeChange, + isDarkMode, + collapsed, + handleMenuCollapse, +}) => { + const { + token: { colorBgContainer, colorText }, + } = theme.useToken(); + + const monogram = isDarkMode ? MonogramDark : MonogramLight; + return ( + + + Deploys by Netlify + + + + + + } + unCheckedChildren={ +
    + +
    + } + onChange={handleThemeChange} + style={{ backgroundColor: colorText }} + checked={isDarkMode} + /> + + +
    + ); +}; + +export default Footer; diff --git a/ui/src/components/Layouts/Footer/tests/Footer.test.tsx b/ui/src/components/Layouts/Sidebar/Footer/tests/Footer.test.tsx similarity index 94% rename from ui/src/components/Layouts/Footer/tests/Footer.test.tsx rename to ui/src/components/Layouts/Sidebar/Footer/tests/Footer.test.tsx index c338c7bd..4838c753 100644 --- a/ui/src/components/Layouts/Footer/tests/Footer.test.tsx +++ b/ui/src/components/Layouts/Sidebar/Footer/tests/Footer.test.tsx @@ -1,6 +1,6 @@ import { render, screen } from "@testing-library/react"; import { afterAll, describe, vi } from "vitest"; -import Footer from "components/Layouts/Footer"; +import Footer from "components/Layouts/Sidebar/Footer"; // Mock the window.innerWidth to simulate different screen sizes const originalInnerWidth = window.innerWidth; diff --git a/ui/src/components/Layouts/Footer/utils/types.ts b/ui/src/components/Layouts/Sidebar/Footer/utils/types.ts similarity index 100% rename from ui/src/components/Layouts/Footer/utils/types.ts rename to ui/src/components/Layouts/Sidebar/Footer/utils/types.ts diff --git a/ui/src/components/Layouts/Sidebar/index.tsx b/ui/src/components/Layouts/Sidebar/index.tsx index ddab461a..719090ce 100644 --- a/ui/src/components/Layouts/Sidebar/index.tsx +++ b/ui/src/components/Layouts/Sidebar/index.tsx @@ -5,7 +5,7 @@ import { MENU_COLLAPSED_STORAGE_KEY } from "./utils/constants"; import useMenuCollapsed from "lib/utils/hooks/useMenuCollapsed"; import { useContext } from "react"; import { DarkModeContext } from "lib/utils/context/DarkModeProvider"; -import Footer from "components/Layouts/Footer"; +import Footer from "components/Layouts/Sidebar/Footer"; import style from "./Sidebar.module.scss"; const { Sider } = Layout; diff --git a/ui/src/index.css b/ui/src/index.css index 667c960b..a6f52157 100644 --- a/ui/src/index.css +++ b/ui/src/index.css @@ -78,7 +78,7 @@ h5 { overflow-x: auto; overflow-y: auto; max-height: 100dvh; - padding: var(--bt-size-10) var(--bt-size-10) 0 var(--bt-size-10); + /* padding: var(--bt-size-10) var(--bt-size-10) 0 var(--bt-size-10); */ scroll-behavior: smooth; } diff --git a/ui/src/pages/About/components/Footer/Footer.module.scss b/ui/src/pages/About/components/Footer/Footer.module.scss deleted file mode 100644 index 26b29285..00000000 --- a/ui/src/pages/About/components/Footer/Footer.module.scss +++ /dev/null @@ -1,36 +0,0 @@ -.footer { - margin-top: var(--bt-size-20); - margin-left: calc(var(--bt-size-10) * -1); - margin-right: calc(var(--bt-size-10) * -1); - padding: var(--bt-size-10); - display: flex; - justify-content: space-between; - align-items: center; - - &__left { - display: flex; - align-items: center; - gap: var(--bt-size-20); - &_list { - list-style-type: none; - display: flex; - gap: var(--bt-size-10); - padding: 0px; - } - } - - @media (max-width: 767px) { - gap: var(--bt-size-10); - flex-direction: column; - align-items: center; - justify-items: center; - - &__left { - display: flex; - flex-direction: column; - justify-items: center; - align-items: center; - gap: var(--bt-size-10); - } - } -} diff --git a/ui/src/pages/About/components/Footer/index.tsx b/ui/src/pages/About/components/Footer/index.tsx deleted file mode 100644 index 93b48931..00000000 --- a/ui/src/pages/About/components/Footer/index.tsx +++ /dev/null @@ -1,64 +0,0 @@ -import React from "react"; -import style from "./Footer.module.scss"; -import Icon from "components/General/Icon"; -import { Typography, theme } from "antd"; -import { ResponsiveButton } from "components/General/FormComponents"; - -const Footer: React.FC = () => { - const { - token: { colorBgContainer }, - } = theme.useToken(); - - return ( -
    -
    -
    - - © {new Date().getFullYear()} Binarytree - -
    - -
    - - } - onClick={() => - window.open( - "https://github.com/lifeparticle/binarytree", - "_blank", - "noopener" - ) - } - /> -
    - ); -}; - -export default Footer; diff --git a/ui/src/pages/About/index.tsx b/ui/src/pages/About/index.tsx index 3953d0e6..245aad62 100644 --- a/ui/src/pages/About/index.tsx +++ b/ui/src/pages/About/index.tsx @@ -1,6 +1,4 @@ import { - API_COLUMNS, - API_DATA, FEATURE_COLUMNS, FEATURE_DATA, APP_VALUES, @@ -11,7 +9,7 @@ import { import { Card, List, Table, Typography } from "antd"; import style from "./About.module.scss"; import about from "assets/about.jpg"; -import Footer from "./components/Footer"; +import Footer from "../../components/Layouts/Footer"; const About = () => { return ( @@ -76,15 +74,6 @@ const About = () => { scroll={{ x: "calc(50%)" }} /> - "API's"} - scroll={{ x: "calc(50%)" }} - bordered - /> -
    @@ -93,23 +93,15 @@ const API_COLUMNS: ColumnsType = [ }, ]; -const API_DATA: Api[] = [ - { - name: "News", - api: "https://newsapi.org", - key: "news", - }, -]; - const OTHER_COLUMNS: ColumnsType = [ { title: "Name", dataIndex: "name", key: "name", render: (text, record) => ( - + {text} - + ), align: "center", }, @@ -126,6 +118,16 @@ const OTHER_DATA: Other[] = [ name: "Open Props", url: "https://github.com/argyleink/open-props", }, + { + key: "3", + name: "News API", + url: "https://newsapi.org", + }, + { + key: "4", + name: "unDraw", + url: "https://undraw.co/", + }, ]; const FEATURE_COLUMNS: ColumnsType = [ @@ -186,29 +188,29 @@ const FEATURE_COLUMNS: ColumnsType = [ const FEATURE_DATA: Feature[] = [ { - key: "1", - name: "Newsfeed", + key: routesById.newsfeed.id, + name: routesById.newsfeed.title, description: "Tech news", link: "/newsfeed", library: [{ name: "Vanilla JS", url: "" }], }, { - key: "2", - name: "Color Picker", + key: routesById.colorpicker.id, + name: routesById.colorpicker.title, description: "Choose your desired color", link: "/colors/cp", library: [{ name: "tiny-color-2", url: LIBRARY_URLS["tiny-color-2"] }], }, { - key: "3", - name: "Shades & Tints", + key: routesById.shadesandtints.id, + name: routesById.shadesandtints.title, description: "Choose your desired Shades and Tints", link: "/colors/shades", library: [{ name: "values.js", url: LIBRARY_URLS["values.js"] }], }, { - key: "4", - name: "Border Radius", + key: routesById.borderradius.id, + name: routesById.borderradius.title, description: "Choose your desired border radius", link: "/css/br", library: [{ name: "faker.js", url: LIBRARY_URLS["faker-js"] }], @@ -221,29 +223,29 @@ const FEATURE_DATA: Feature[] = [ // library: [{ name: "faker.js", url: LIBRARY_URLS["faker-js"] }], // }, { - key: "6", - name: "SVG Formatter", + key: routesById.svgformatter.id, + name: routesById.svgformatter.title, description: "Merge svg path", link: "/css/svg-formatter", library: [{ name: "Vanilla JS", url: "" }], }, { - key: "7", - name: "Base64", + key: routesById.base64.id, + name: routesById.base64.title, description: "Convert text to base64", link: "/converter/base-64", library: [{ name: "Vanilla JS", url: "" }], }, { - key: "8", - name: "Pixel", + key: routesById.pixelconverter.id, + name: routesById.pixelconverter.title, description: "Convert pixel to rem", link: "/converter/pixel", library: [{ name: "Vanilla JS", url: "" }], }, { - key: "9", - name: "Json To Typescript", + key: routesById.jsontotypescript.id, + name: routesById.jsontotypescript.title, description: "Convert Json to typescript", link: "/converter/jtt", library: [ @@ -254,8 +256,8 @@ const FEATURE_DATA: Feature[] = [ ], }, { - key: "10", - name: "Data", + key: routesById.data.id, + name: routesById.data.title, description: "Generate any type of data", link: "/generator/data", library: [ @@ -270,8 +272,8 @@ const FEATURE_DATA: Feature[] = [ ], }, { - key: "11", - name: "Image", + key: routesById.image.id, + name: routesById.image.title, description: "Generate image from color code", link: "/generator/igfc", library: [ @@ -290,8 +292,8 @@ const FEATURE_DATA: Feature[] = [ ], }, { - key: "12", - name: "Avatar", + key: routesById.avatar.id, + name: routesById.avatar.title, description: "Generate avatar from text", link: "/generator/avatar", library: [ @@ -310,15 +312,15 @@ const FEATURE_DATA: Feature[] = [ ], }, { - key: "13", - name: "QR Code", + key: routesById.qrcode.id, + name: routesById.qrcode.title, description: "Generate QR code from text", link: "/generator/qrcode", library: [], }, { - key: "14", - name: "Sorting", + key: routesById.sorting.id, + name: routesById.sorting.title, description: "Sort numbers or strings", link: "/generator/sorting", library: [{ name: "Vanilla JS", url: "" }], @@ -331,8 +333,8 @@ const FEATURE_DATA: Feature[] = [ library: [{ name: "Vanilla JS", url: "" }], }, { - key: "16", - name: "Editor", + key: routesById.editor.id, + name: routesById.editor.title, description: "Write markdown and download", link: "/markdown/me", library: [ @@ -343,8 +345,8 @@ const FEATURE_DATA: Feature[] = [ ], }, { - key: "17", - name: "Table", + key: routesById.table.id, + name: routesById.table.title, description: "Generate a table from the markdown", link: "/markdown/md-table-generator", library: [ @@ -355,8 +357,8 @@ const FEATURE_DATA: Feature[] = [ ], }, { - key: "18", - name: "Table of content", + key: routesById.tableofcontent.id, + name: routesById.tableofcontent.title, description: "Generate table from markdown", link: "/markdown/toc", library: [ @@ -367,8 +369,8 @@ const FEATURE_DATA: Feature[] = [ ], }, { - key: "19", - name: "Text Editor", + key: routesById.texteditor.id, + name: routesById.texteditor.title, description: "Generate rich text", link: "/text/te", library: [ @@ -379,8 +381,8 @@ const FEATURE_DATA: Feature[] = [ ], }, { - key: "20", - name: "Mimetype", + key: routesById.mimetype.id, + name: routesById.mimetype.title, description: "Search mimetype", link: "/info/mimetype", library: [{ name: "Vanilla JS", url: "" }], @@ -391,7 +393,6 @@ export { LIBRARY_URLS, FEATURE_COLUMNS, FEATURE_DATA, - API_DATA, API_COLUMNS, APP_VALUES, APP_SUPPORT, diff --git a/ui/src/pages/Colors/ColorPicker/ColorPicker.module.scss b/ui/src/pages/Colors/ColorPicker/ColorPicker.module.scss index 010b9c23..2a19ce91 100644 --- a/ui/src/pages/Colors/ColorPicker/ColorPicker.module.scss +++ b/ui/src/pages/Colors/ColorPicker/ColorPicker.module.scss @@ -1,6 +1,6 @@ .cp { display: grid; - grid-template-columns: 380px 360px 425px 425px; + grid-template-columns: 380px 360px 435px 435px; gap: var(--bt-size-16); justify-content: center; @@ -24,14 +24,14 @@ } @media (max-width: 1900px) { - grid-template-columns: 380px 360px 400px; + grid-template-columns: 435px 360px 435px; } @media (max-width: 1500px) { - grid-template-columns: 400px 400px; + grid-template-columns: 435px 435px; } @media (max-width: 1100px) { - grid-template-columns: 400px; + grid-template-columns: 435px; } } diff --git a/ui/src/pages/Colors/ColorPicker/index.tsx b/ui/src/pages/Colors/ColorPicker/index.tsx index 1f949568..946872f7 100644 --- a/ui/src/pages/Colors/ColorPicker/index.tsx +++ b/ui/src/pages/Colors/ColorPicker/index.tsx @@ -1,4 +1,4 @@ -import React, { useState, useMemo, ChangeEvent, useEffect } from "react"; +import React, { useMemo, ChangeEvent } from "react"; import style from "./ColorPicker.module.scss"; import { Card, Form, Space } from "antd"; import { ColorPicker as CP } from "@mantine/core"; @@ -14,34 +14,35 @@ import { ResponsiveInputWithLabel } from "components/General/FormComponents"; import { useSearchParams } from "react-router-dom"; const ColorPicker: React.FC = () => { - const [searchParams, setSearchParams] = useSearchParams(); - const color = String(searchParams.get("color") || INITIAL_COLOR); + const [searchParams, setSearchParams] = useSearchParams({ + color: INITIAL_COLOR, + format: INITIAL_FORMAT, + }); - const [format, setFormat] = useState( - determineFormat(color) || INITIAL_FORMAT - ); + const color = String(searchParams.get("color")); + const format = String(searchParams.get("format")) as FormatType; + + console.log(color, format); const colors = useMemo(() => calculateColors(color), [color]); + console.log(colors); const setColor = (color: string) => { - searchParams.set("color", color); - setSearchParams(searchParams); + setSearchParams( + (prev) => { + prev.set("color", color); + prev.set("format", determineFormat(color)); + return prev; + }, + { replace: true } + ); }; const onInputChange = (e: ChangeEvent) => { const input = e.target.value.trim(); - searchParams.set("color", input); - setSearchParams(searchParams); - setFormat(determineFormat(input)); + setColor(input); }; - useEffect(() => { - if (!searchParams.get("color")) { - searchParams.set("color", INITIAL_COLOR); - setSearchParams(searchParams); - } - }, []); - return (
    @@ -62,7 +63,15 @@ const ColorPicker: React.FC = () => { + setSearchParams( + (prev) => { + prev.set("format", format); + return prev; + }, + { replace: true } + ) + } /> diff --git a/ui/src/pages/Colors/ShadesAndTints/utils/helper.ts b/ui/src/pages/Colors/ShadesAndTints/utils/helper.ts index 3b6925aa..7bc899e5 100644 --- a/ui/src/pages/Colors/ShadesAndTints/utils/helper.ts +++ b/ui/src/pages/Colors/ShadesAndTints/utils/helper.ts @@ -13,17 +13,21 @@ const generateShadesForColor = ( selectedColor: string, count: number ): { shades: string[]; tints: string[] } => { - if (!selectedColor || !count || count <= 0) - return { shades: [], tints: [] }; + try { + if (!selectedColor || !count || count <= 0) + return { shades: [], tints: [] }; - const values = new Values(selectedColor); - const shadesArray = values.shades(count); - const tintsArray = values.tints(count); + const values = new Values(selectedColor); + const shadesArray = values.shades(count); + const tintsArray = values.tints(count); - const shades = shadesArray.map((shade) => "#" + shade.hex); - const tints = tintsArray.map((tint) => "#" + tint.hex); + const shades = shadesArray.map((shade) => "#" + shade.hex); + const tints = tintsArray.map((tint) => "#" + tint.hex); - return { shades, tints }; + return { shades, tints }; + } catch (err) { + return { shades: [], tints: [] }; + } }; const generateRandomColor = () => { diff --git a/ui/src/pages/Home/Home.module.scss b/ui/src/pages/Home/Home.module.scss index 2e9b5f21..2f8cc324 100644 --- a/ui/src/pages/Home/Home.module.scss +++ b/ui/src/pages/Home/Home.module.scss @@ -1,6 +1,64 @@ .home { - display: flex; - align-items: center; - justify-content: center; - height: var(--bt-full-page-height); + background-color: #e6e6ff; + padding-left: 10px; + padding-right: 10px; + &__content { + padding-top: 80px; + padding-left: 200px; + padding-right: 200px; + display: flex; + flex-direction: column; + + gap: 50px; + + &_header { + display: flex; + flex-direction: row; + + &_text { + display: flex; + flex-direction: column; + gap: 30px; + } + } + + &_values, + &_features { + align-items: center; + display: flex; + flex-direction: column; + gap: 20px; + } + + &_values { + &_value { + display: grid; + gap: 20px; + grid-template-columns: 1fr 1fr 1fr; + } + } + + &_features { + &_select { + display: flex; + flex-direction: column; + gap: 20px; + } + } + + &_footer { + display: flex; + justify-content: center; + align-items: center; + &_content { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + gap: 10px; + padding-left: 100px; + padding-right: 100px; + } + } + } } diff --git a/ui/src/pages/Home/index.tsx b/ui/src/pages/Home/index.tsx index 1c699871..ab0ee6e7 100644 --- a/ui/src/pages/Home/index.tsx +++ b/ui/src/pages/Home/index.tsx @@ -1,10 +1,155 @@ import Text from "components/General/Text/Text"; import style from "./Home.module.scss"; +import { Card, Typography, Image, Space } from "antd"; +import header from "assets/home/header.svg"; +import share from "assets/home/share.svg"; +import verification from "assets/home/verification.svg"; +import detection from "assets/home/detection.svg"; +import { APP_VALUES, FEATURE_DATA } from "pages/About/utils/constants"; +import { + ResponsiveButton, + ResponsiveSegementWithLabel, +} from "components/General/FormComponents"; +import Footer from "components/Layouts/Footer"; +import PageGrid from "components/Layouts/PageGrid"; +import { SEGMENTED_OPTIONS, DESCRIPTIONS } from "./utils/constants"; +import { useState } from "react"; + +const onClick = (url: string) => { + window.open(url, "_blank", "noopener"); +}; const Home = () => { + const [feature, setFeature] = useState(SEGMENTED_OPTIONS[0].value); + return (
    - +
    +
    +
    + + + At binarytree.dev, we provide an array of developer + productivity tools designed to help you save time. + With an{" "} + + ever-growing number of features + {" "} + (currently {FEATURE_DATA.length}), our + platform is constantly evolving to meet the needs of + developers like you. + +
    + + +
    +
    + + + +
    + { + setFeature(value as string); + }} + /> + {DESCRIPTIONS[feature].description} + More +
    + +
    +
    +
    +
    + +
    + } + > + {APP_VALUES[0]} + + + } + > + {APP_VALUES[1]} + + + } + > + {APP_VALUES[2]} + +
    +
    +
    + + } + > + + + Embrace the efficiency that binarytree.dev + brings to your development process. Our tools + are designed to eliminate unnecessary + complexities, allowing you to streamline your + work and direct your focus towards the core of + your projects. With binarytree.dev, you're not + just coding faster - you're crafting with + precision and focusing on what truly matters. + Discover a smoother, smarter way to develop + today. + + + onClick("converter/base-64")} + > + Base64 converter + + + onClick( + "https://github.com/lifeparticle/binarytree/issues" + ) + } + > + Request Features + + + + +
    +
    +
    ); }; diff --git a/ui/src/pages/Home/utils/constants.ts b/ui/src/pages/Home/utils/constants.ts new file mode 100644 index 00000000..5d0d62bd --- /dev/null +++ b/ui/src/pages/Home/utils/constants.ts @@ -0,0 +1,37 @@ +import { FEATURE_DATA } from "pages/About/utils/constants"; +import base64 from "assets/home/avatar.gif"; + +interface DescriptionType { + description: string; + image: string; +} + +const VALUES = ["avatar", "shadesandtints", "toc"]; + +const LABELS: Record = { + avatar: "Base64", + shadesandtints: "Shades & Tints", + toc: "Table of Content", +}; + +const IMAGES: Record = { + base64, + shadesandtints: base64, + toc: base64, +}; + +const DESCRIPTIONS: Record = { + avatar: { description: FEATURE_DATA[10].description, image: IMAGES.base64 }, + shadesandtints: { + description: FEATURE_DATA[2].description, + image: IMAGES.shadesandtints, + }, + toc: { description: FEATURE_DATA[16].description, image: IMAGES.toc }, +}; + +const SEGMENTED_OPTIONS = VALUES.map((value) => ({ + label: LABELS[value], + value, +})); + +export { SEGMENTED_OPTIONS, DESCRIPTIONS }; diff --git a/ui/src/pages/Routes/utils/constant.tsx b/ui/src/pages/Routes/utils/constant.tsx index a7131559..f5d289b5 100644 --- a/ui/src/pages/Routes/utils/constant.tsx +++ b/ui/src/pages/Routes/utils/constant.tsx @@ -1,4 +1,5 @@ -import { Route } from "./types"; +import Diagramming from "pages/Tools/Diagramming"; +import { Route, RouteId } from "./types"; import { About, Avatar, @@ -265,17 +266,26 @@ export const routes: Route[] = [ description: "Find out what type your file fancies itself as.", component: Mimetype, }, + { + id: "diagramming", + path: "/tools/diagramming", + title: "Diagramming", + description: + "Channel your inner Da Vinci of diagrams. Who said flowcharts can't be art?", + component: Diagramming, + }, { id: "diffchecker", path: "/tools/textdiff", title: "Diffchecker", - description: "Find out the difference between text", + description: + "Ever wondered what’s different? We did too! Play spot the difference with text.", component: Diffchecker, }, { id: "/", path: "/", - title: "", + title: "Home", description: "", component: Home, }, @@ -301,3 +311,8 @@ export const routes: Route[] = [ component: PageNotFound, }, ]; + +export const routesById = routes.reduce((acc, route) => { + acc[route.id] = route; + return acc; +}, {} as Record); diff --git a/ui/src/pages/Routes/utils/types.ts b/ui/src/pages/Routes/utils/types.ts index 13598c2f..aa9227c2 100644 --- a/ui/src/pages/Routes/utils/types.ts +++ b/ui/src/pages/Routes/utils/types.ts @@ -32,6 +32,7 @@ type RouteId = | "texteditor" | "mimetype" | "diffchecker" + | "diagramming" | "/" | "about" | "feedback" diff --git a/ui/src/pages/Tools/Diagramming/diagramming.module.scss b/ui/src/pages/Tools/Diagramming/diagramming.module.scss new file mode 100644 index 00000000..f92eed7a --- /dev/null +++ b/ui/src/pages/Tools/Diagramming/diagramming.module.scss @@ -0,0 +1,3 @@ +.diagramming { + height: calc(100dvh - 110px); +} diff --git a/ui/src/pages/Tools/Diagramming/index.tsx b/ui/src/pages/Tools/Diagramming/index.tsx new file mode 100644 index 00000000..bbc504e3 --- /dev/null +++ b/ui/src/pages/Tools/Diagramming/index.tsx @@ -0,0 +1,12 @@ +import { Excalidraw } from "@excalidraw/excalidraw"; +import style from "./diagramming.module.scss"; + +const Diagramming = () => { + return ( +
    + +
    + ); +}; + +export default Diagramming; diff --git a/ui/src/pages/Tools/Diffchecker/index.tsx b/ui/src/pages/Tools/Diffchecker/index.tsx index 4983287e..4157b36a 100644 --- a/ui/src/pages/Tools/Diffchecker/index.tsx +++ b/ui/src/pages/Tools/Diffchecker/index.tsx @@ -1,7 +1,6 @@ import { Card, Form, Input } from "antd"; import PageGrid from "components/Layouts/PageGrid"; import React, { useState } from "react"; - import { diffChars, Change } from "diff"; import { ResponsiveButton } from "components/General/FormComponents"; import style from "./Diffchecker.module.scss"; diff --git a/ui/src/pages/Data/Sorting/Sorting.module.scss b/ui/src/pages/Tools/Sorting/Sorting.module.scss similarity index 100% rename from ui/src/pages/Data/Sorting/Sorting.module.scss rename to ui/src/pages/Tools/Sorting/Sorting.module.scss diff --git a/ui/src/pages/Data/Sorting/index.tsx b/ui/src/pages/Tools/Sorting/index.tsx similarity index 100% rename from ui/src/pages/Data/Sorting/index.tsx rename to ui/src/pages/Tools/Sorting/index.tsx diff --git a/ui/src/pages/Data/Sorting/tests/sorting.test.tsx b/ui/src/pages/Tools/Sorting/tests/sorting.test.tsx similarity index 92% rename from ui/src/pages/Data/Sorting/tests/sorting.test.tsx rename to ui/src/pages/Tools/Sorting/tests/sorting.test.tsx index 055f759e..98660fe2 100644 --- a/ui/src/pages/Data/Sorting/tests/sorting.test.tsx +++ b/ui/src/pages/Tools/Sorting/tests/sorting.test.tsx @@ -1,6 +1,6 @@ import { render, screen } from "@testing-library/react"; import { describe, expect } from "vitest"; -import Sorting from "pages/Data/Sorting"; +import Sorting from "pages/Tools/Sorting"; describe("Sorting", () => { test("render sorting component without crash", () => { diff --git a/ui/src/pages/Data/Sorting/utils/constants.ts b/ui/src/pages/Tools/Sorting/utils/constants.ts similarity index 100% rename from ui/src/pages/Data/Sorting/utils/constants.ts rename to ui/src/pages/Tools/Sorting/utils/constants.ts diff --git a/ui/src/pages/Data/Sorting/utils/helper.ts b/ui/src/pages/Tools/Sorting/utils/helper.ts similarity index 100% rename from ui/src/pages/Data/Sorting/utils/helper.ts rename to ui/src/pages/Tools/Sorting/utils/helper.ts diff --git a/ui/src/pages/CSS/SvgFormatter/SvgFormatter.module.scss b/ui/src/pages/Tools/SvgFormatter/SvgFormatter.module.scss similarity index 100% rename from ui/src/pages/CSS/SvgFormatter/SvgFormatter.module.scss rename to ui/src/pages/Tools/SvgFormatter/SvgFormatter.module.scss diff --git a/ui/src/pages/CSS/SvgFormatter/index.tsx b/ui/src/pages/Tools/SvgFormatter/index.tsx similarity index 100% rename from ui/src/pages/CSS/SvgFormatter/index.tsx rename to ui/src/pages/Tools/SvgFormatter/index.tsx diff --git a/ui/src/pages/CSS/SvgFormatter/utils/helper.ts b/ui/src/pages/Tools/SvgFormatter/utils/helper.ts similarity index 100% rename from ui/src/pages/CSS/SvgFormatter/utils/helper.ts rename to ui/src/pages/Tools/SvgFormatter/utils/helper.ts diff --git a/ui/src/pages/pages.ts b/ui/src/pages/pages.ts index 56dfc1cb..29fc60ab 100644 --- a/ui/src/pages/pages.ts +++ b/ui/src/pages/pages.ts @@ -11,7 +11,6 @@ const ShadesAndTints = lazy(() => import("pages/Colors/ShadesAndTints")); const BorderRadius = lazy(() => import("pages/CSS/BorderRadius")); const BoxShadow = lazy(() => import("pages/CSS/BoxShadow")); -const SvgFormatter = lazy(() => import("pages/CSS/SvgFormatter")); const Base64 = lazy(() => import("pages/Converter/Base64")); const Pixel = lazy(() => import("pages/Converter/Pixel")); @@ -23,7 +22,6 @@ const ImageGeneratorFromColors = lazy( ); const Avatar = lazy(() => import("pages/Data/Avatar")); const QRcode = lazy(() => import("pages/Data/QRcode")); -const Sorting = lazy(() => import("pages/Data/Sorting")); const Blog = lazy(() => import("pages/Resource/Blog")); const Book = lazy(() => import("pages/Resource/Book")); @@ -43,10 +41,14 @@ const MarkdownEditor = lazy(() => import("pages/Markdown/MarkdownEditor")); const TableGenerator = lazy(() => import("pages/Markdown/MdTableGenerator")); const TableOfContent = lazy(() => import("pages/Markdown/TableOfContent")); +const Diagramming = lazy(() => import("pages/Tools/Diagramming")); +const Diffchecker = lazy(() => import("pages/Tools/Diffchecker")); +const Sorting = lazy(() => import("pages/Tools/Sorting")); +const SvgFormatter = lazy(() => import("pages/Tools/SvgFormatter")); + const TextEditor = lazy(() => import("pages/Text/TextEditor")); const Mimetype = lazy(() => import("pages/Information/Mimetype")); -const Diffchecker = lazy(() => import("pages/Tools/Diffchecker")); export { About, @@ -60,6 +62,8 @@ export { Course, DataGenerator, DesignSystem, + Diagramming, + Diffchecker, Feedback, Github, Home, @@ -85,5 +89,4 @@ export { TvSeries, UiUx, YouTube, - Diffchecker, }; diff --git a/ui/yarn.lock b/ui/yarn.lock index 59f898e6..958a90d6 100644 --- a/ui/yarn.lock +++ b/ui/yarn.lock @@ -708,6 +708,16 @@ __metadata: languageName: node linkType: hard +"@excalidraw/excalidraw@npm:^0.16.0": + version: 0.16.0 + resolution: "@excalidraw/excalidraw@npm:0.16.0" + peerDependencies: + react: ^17.0.2 || ^18.2.0 + react-dom: ^17.0.2 || ^18.2.0 + checksum: b3d321a802b7b5b86f65f2036cab59759904589cab131e6c2cf547d138f28b821d1aada3e4ec7c3d37bb37de45250231cd367b29f053f2ede1b6379d562368a5 + languageName: node + linkType: hard + "@faker-js/faker@npm:^7.6.0": version: 7.6.0 resolution: "@faker-js/faker@npm:7.6.0" @@ -3071,6 +3081,7 @@ __metadata: resolution: "code@workspace:." dependencies: "@emotion/react": ^11.11.0 + "@excalidraw/excalidraw": ^0.16.0 "@faker-js/faker": ^7.6.0 "@mantine/core": ^6.0.10 "@mantine/ds": ^6.0.10 @@ -3114,7 +3125,7 @@ __metadata: jspdf: ^2.5.1 jszip: ^3.10.1 jszip-utils: ^0.1.0 - lucide-react: ^0.260.0 + lucide-react: ^0.262.0 marked: ^7.0.1 react: ^18.2.0 react-dom: ^18.2.0 @@ -6038,12 +6049,12 @@ __metadata: languageName: node linkType: hard -"lucide-react@npm:^0.260.0": - version: 0.260.0 - resolution: "lucide-react@npm:0.260.0" +"lucide-react@npm:^0.262.0": + version: 0.262.0 + resolution: "lucide-react@npm:0.262.0" peerDependencies: react: ^16.5.1 || ^17.0.0 || ^18.0.0 - checksum: 27e1b44ed859988a939e750ddaf0d6f1a652b87cd104314c62ec7ee26b92cfc037b9d402ce8468a7c8b3883e174a85dedb18be39ec7cddd9d215b58512ff2dc7 + checksum: ff64ced6f67de2674b41d775f7fd216d2bcf952a9c133a32e8838a349f2726deeb52885f6ecb221e12884ad12565b0516c2557712bf8800c88eb2f7e12182c4b languageName: node linkType: hard