diff --git a/package.json b/package.json index c3b0e88..fcd555e 100644 --- a/package.json +++ b/package.json @@ -24,11 +24,15 @@ "-----------------------------------------------------------------------": "" }, "dependencies": { + "@glideapps/glide-data-grid": "5.0.0-beta1", "axios": "0.27.2", "clsx": "1.2.1", + "lodash": "4.17.21", + "marked": "4.0.18", "next": "12.2.2", "react": "18.2.0", - "react-dom": "18.2.0" + "react-dom": "18.2.0", + "react-responsive-carousel": "3.2.23" }, "devDependencies": { "@next/bundle-analyzer": "12.2.2", diff --git a/src/components/pages/index-page/IndexPage.tsx b/src/components/pages/index-page/IndexPage.tsx index 551e923..0bce073 100644 --- a/src/components/pages/index-page/IndexPage.tsx +++ b/src/components/pages/index-page/IndexPage.tsx @@ -1,13 +1,63 @@ import React from 'react'; import Link from 'next/link'; import { Routes } from '../../../constants/Routes'; +import { GridCellKind } from "@glideapps/glide-data-grid"; +import type { GridCell, GridColumn, Item } from "@glideapps/glide-data-grid"; +import { UiTableDynamic } from "../../shared/ui-table/UiTable.dynamic"; interface IProps { testId?: string; } +const data = [ + { + name: 'Hines Fowler', + company: 'BUZZNESS', + email: 'hinesfowler@buzzness.com', + phone: '+1 (869) 405-3127', + }, + { + name: 'Joe Fowler', + company: 'Buz', + email: 'joefowler@buzzness.com', + phone: '+1 (869) 405-3127', + }, +]; + +const columns: GridColumn[] = [ + { + title: 'Name', + id: 'name', + }, + { + title: 'Company', + id: 'company', + }, + { + title: 'Email', + id: 'email', + }, + { + title: 'Phone', + id: 'phone', + }, +]; export const IndexPage: React.FC = (props) => { const { testId = IndexPage.displayName } = props; + const getContent = React.useCallback((cell: Item): GridCell => { + const [col, row] = cell; + const dataRow = data[row]; + // dumb but simple way to do this + const indexes: string[] = ['name', 'company', 'email', 'phone']; + const d = dataRow[indexes[col]]; + + return { + kind: GridCellKind.Text, + allowOverlay: false, + displayData: d, + data: d, + }; + }, []); return (
@@ -25,6 +75,16 @@ export const IndexPage: React.FC = (props) => { About

+ +
+ +
); }; diff --git a/src/components/shared/ui-table/UiTable.constants.ts b/src/components/shared/ui-table/UiTable.constants.ts new file mode 100644 index 0000000..44b666b --- /dev/null +++ b/src/components/shared/ui-table/UiTable.constants.ts @@ -0,0 +1,8 @@ +import { GridSelection } from '@glideapps/glide-data-grid/dist/ts/data-grid/data-grid-types'; +import { CompactSelection } from '@glideapps/glide-data-grid'; + +export const gridSelection: GridSelection = { + current: undefined, + rows: CompactSelection.empty(), + columns: CompactSelection.empty(), +}; diff --git a/src/components/shared/ui-table/UiTable.dynamic.tsx b/src/components/shared/ui-table/UiTable.dynamic.tsx new file mode 100644 index 0000000..292d5ad --- /dev/null +++ b/src/components/shared/ui-table/UiTable.dynamic.tsx @@ -0,0 +1,11 @@ +import React from 'react'; +import dynamic from 'next/dynamic'; +import { UiTable } from './UiTable'; + +export const UiTableDynamic = dynamic( + () => { + return import('./UiTable' /* webpackChunkName: "UiTable" */); + }, + // eslint-disable-next-line react/display-name + { ssr: false } +) as typeof UiTable; diff --git a/src/components/shared/ui-table/UiTable.tsx b/src/components/shared/ui-table/UiTable.tsx new file mode 100644 index 0000000..fe552e5 --- /dev/null +++ b/src/components/shared/ui-table/UiTable.tsx @@ -0,0 +1,41 @@ +import React from 'react'; +import { DataEditor, DataEditorProps, GridMouseEventArgs } from '@glideapps/glide-data-grid'; +import { GetRowThemeCallback } from '@glideapps/glide-data-grid/dist/ts/data-grid/data-grid-render'; +import { gridSelection } from './UiTable.constants'; + +interface IProps extends DataEditorProps {} + +export const UiTable: React.FC = (props) => { + const [hoverRow, setHoverRow] = React.useState(undefined); + const onItemHovered = React.useCallback((args: GridMouseEventArgs) => { + const [, row] = args.location; + + setHoverRow(args.kind !== 'cell' ? undefined : row); + }, []); + const getRowThemeOverride = React.useCallback( + (row) => { + if (row !== hoverRow) { + return undefined; + } + + return { + bgCell: '#f7f7f7', + bgCellMedium: '#f0f0f0', + }; + }, + [hoverRow] + ); + + return ( + + ); +}; + +UiTable.displayName = 'UiTable'; + +export default UiTable; diff --git a/src/pages/_app.tsx b/src/pages/_app.tsx index a810f3c..c604b71 100644 --- a/src/pages/_app.tsx +++ b/src/pages/_app.tsx @@ -1,3 +1,4 @@ +import '@glideapps/glide-data-grid/dist/index.css'; import '../css/main.css'; import React from 'react'; diff --git a/yarn.lock b/yarn.lock index ddde2cd..98f7777 100644 --- a/yarn.lock +++ b/yarn.lock @@ -495,6 +495,14 @@ minimatch "^3.1.2" strip-json-comments "^3.1.1" +"@glideapps/glide-data-grid@5.0.0-beta1": + version "5.0.0-beta1" + resolved "https://registry.yarnpkg.com/@glideapps/glide-data-grid/-/glide-data-grid-5.0.0-beta1.tgz#5cee7a1dcf0cc1e8a924a06ae29ae97c86002d7e" + integrity sha512-3H0GYwCUV/Gxyv/pQylzD2DYbJvGQFINh2ulg3ZUBlPrAIwVV0Ovs/1mT8Wqw7geAtZmQ6TbnTq1FoJPOxinQQ== + dependencies: + canvas-hypertxt "^0.0.3" + react-number-format "^4.4.1" + "@humanwhocodes/config-array@^0.9.2": version "0.9.5" resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.9.5.tgz#2cbaf9a89460da24b5ca6531b8bbfc23e1df50c7" @@ -1517,6 +1525,11 @@ caniuse-lite@^1.0.30001332, caniuse-lite@^1.0.30001366: resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001367.tgz#2b97fe472e8fa29c78c5970615d7cd2ee414108a" integrity sha512-XDgbeOHfifWV3GEES2B8rtsrADx4Jf+juKX2SICJcaUhjYBO3bR96kvEIHa15VU6ohtOhBZuPGGYGbXMRn0NCw== +canvas-hypertxt@^0.0.3: + version "0.0.3" + resolved "https://registry.yarnpkg.com/canvas-hypertxt/-/canvas-hypertxt-0.0.3.tgz#2d09f3f8bae812d2d2aeba77162ac69ff3b8deb8" + integrity sha512-Wmi0bfM+T6BAwFg3wZ1q3vXmltAcO/zPPfHSblJkOeuO9fwhSDMCIbaBLok71PONoOQHYnsk4CQ/GS1Ai7+OnQ== + chalk@^2.0.0, chalk@^2.3.0, chalk@^2.4.1: version "2.4.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" @@ -1557,6 +1570,11 @@ cjs-module-lexer@^1.0.0: resolved "https://registry.yarnpkg.com/cjs-module-lexer/-/cjs-module-lexer-1.2.2.tgz#9f84ba3244a512f3a54e5277e8eef4c489864e40" integrity sha512-cOU9usZw8/dXIXKtwa8pM0OTJQuJkxMN6w30csNRUerHfeQ5R6U3kkU/FtJeIf3M202OHfY2U8ccInBG7/xogA== +classnames@^2.2.5: + version "2.3.1" + resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.3.1.tgz#dfcfa3891e306ec1dad105d0e88f4417b8535e8e" + integrity sha512-OlQdbZ7gLfGarSqxesMesDa5uz7KFbID8Kpq/SxIoNGDqY8lSYs0D+hhtBXhcdB3rcbXArFr7vlHheLk1voeNA== + cliui@^7.0.2: version "7.0.4" resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f" @@ -3363,7 +3381,7 @@ lodash.merge@^4.6.2: resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== -lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.20, lodash@^4.17.4: +lodash@4.17.21, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.20, lodash@^4.17.4: version "4.17.21" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== @@ -3406,6 +3424,11 @@ makeerror@1.0.12: dependencies: tmpl "1.0.5" +marked@4.0.18: + version "4.0.18" + resolved "https://registry.yarnpkg.com/marked/-/marked-4.0.18.tgz#cd0ac54b2e5610cfb90e8fd46ccaa8292c9ed569" + integrity sha512-wbLDJ7Zh0sqA0Vdg6aqlbT+yPxqLblpAZh1mK2+AO2twQkPywvvqQNfEPVwSSRjZ7dZcdeVBIAgiO7MMp3Dszw== + maximatch@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/maximatch/-/maximatch-0.1.0.tgz#86cd8d6b04c9f307c05a6b9419906d0360fb13a2" @@ -3933,7 +3956,7 @@ prompts@^2.0.1: kleur "^3.0.3" sisteransi "^1.0.5" -prop-types@^15.8.1: +prop-types@^15.5.8, prop-types@^15.7.2, prop-types@^15.8.1: version "15.8.1" resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5" integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg== @@ -3980,6 +4003,13 @@ react-dom@18.2.0: loose-envify "^1.1.0" scheduler "^0.23.0" +react-easy-swipe@^0.0.21: + version "0.0.21" + resolved "https://registry.yarnpkg.com/react-easy-swipe/-/react-easy-swipe-0.0.21.tgz#ce9384d576f7a8529dc2ca377c1bf03920bac8eb" + integrity sha512-OeR2jAxdoqUMHIn/nS9fgreI5hSpgGoL5ezdal4+oO7YSSgJR8ga+PkYGJrSrJ9MKlPcQjMQXnketrD7WNmNsg== + dependencies: + prop-types "^15.5.8" + react-is@^16.13.1: version "16.13.1" resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" @@ -3995,6 +4025,22 @@ react-is@^18.0.0: resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.2.0.tgz#199431eeaaa2e09f86427efbb4f1473edb47609b" integrity sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w== +react-number-format@^4.4.1: + version "4.9.3" + resolved "https://registry.yarnpkg.com/react-number-format/-/react-number-format-4.9.3.tgz#338500fe9c61b1ac73c8d6dff4ec97dd13fd2b50" + integrity sha512-am1A1xYAbENuKJ+zpM7V+B1oRTSeOHYltqVKExznIVFweBzhLmOBmyb1DfIKjHo90E0bo1p3nzVJ2NgS5xh+sQ== + dependencies: + prop-types "^15.7.2" + +react-responsive-carousel@3.2.23: + version "3.2.23" + resolved "https://registry.yarnpkg.com/react-responsive-carousel/-/react-responsive-carousel-3.2.23.tgz#4c0016ff54603e604bb5c1f9e7ef2d1eda133f1d" + integrity sha512-pqJLsBaKHWJhw/ItODgbVoziR2z4lpcJg+YwmRlSk4rKH32VE633mAtZZ9kDXjy4wFO+pgUZmDKPsPe1fPmHCg== + dependencies: + classnames "^2.2.5" + prop-types "^15.5.8" + react-easy-swipe "^0.0.21" + react@18.2.0: version "18.2.0" resolved "https://registry.yarnpkg.com/react/-/react-18.2.0.tgz#555bd98592883255fa00de14f1151a917b5d77d5"