From b27dfe55e2223f2b5ee8e234718efd5c4942b1b8 Mon Sep 17 00:00:00 2001 From: Samet Date: Wed, 15 May 2024 16:09:33 +0300 Subject: [PATCH 1/2] feat(#212): implemented user profile with grid --- app/profile/page.tsx | 77 +++++++++++++++++++++++++++++++++++ app/user/[uid]/page.tsx | 29 +++++++++++++ components/layout/navbar.tsx | 4 ++ components/layout/profile.tsx | 23 +++++++++++ components/ui/image.tsx | 2 + components/widget/builder.tsx | 71 ++++++++++++++++++++++++++++++++ package-lock.json | 57 ++++++++++++++++++++++++++ package.json | 2 + 8 files changed, 265 insertions(+) create mode 100644 app/profile/page.tsx create mode 100644 app/user/[uid]/page.tsx create mode 100644 components/layout/profile.tsx create mode 100644 components/widget/builder.tsx diff --git a/app/profile/page.tsx b/app/profile/page.tsx new file mode 100644 index 0000000..124e7da --- /dev/null +++ b/app/profile/page.tsx @@ -0,0 +1,77 @@ +// "use client"; + +import prisma from "@/services/prisma"; +import { Platform, PlatformCode, PlatformQuery } from "@prisma/client"; +import { templates, samples } from "@/platforms"; +import { RocksGridBuilder } from "@/components/widget/builder"; + +type IPlatformQueries = { + platform: Platform & { queries: Array }; +}; + +const PlatformQueries = async ({ platform }: IPlatformQueries, key: string) => { + const template = templates[platform.code]; + const sample = samples[platform.code]; + + return Promise.all( + platform.queries.map((query) => + PlatformQueryView( + { + query, + template: template as any, + sample: sample as any, + }, + query.id + ) + ) + ); +}; + +type IPlatformQueryView = { + query: PlatformQuery; + template: { + [key in keyof typeof PlatformCode]: ( + ...params: any + ) => Promise; + }; + sample: { [key in keyof typeof PlatformCode]: any }; +}; + +const PlatformQueryView = async ( + { query, template, sample }: IPlatformQueryView, + key: string +) => { + const getView = template[query.name as keyof typeof template]; + const sampleData = sample[query.name as keyof typeof samples]; + if (!sampleData) return <>No data.; + + return getView(sampleData.result, sampleData.config); +}; + +type UserOwnProfileProps = { params: { uid: string } }; +export default async function UserOwnProfile({ params }: UserOwnProfileProps) { + const platforms = await prisma.platform.findMany({ + include: { + queries: { + where: { publicQueryId: { isSet: false } }, + }, + }, + }); + + const rocksWithView = ( + await Promise.all( + platforms.map((platform) => PlatformQueries({ platform }, platform.id)) + ) + ).flatMap((item) => item); + + return ( +
+
+

User profile

+
+
+ +
+
+ ); +} diff --git a/app/user/[uid]/page.tsx b/app/user/[uid]/page.tsx new file mode 100644 index 0000000..3733f52 --- /dev/null +++ b/app/user/[uid]/page.tsx @@ -0,0 +1,29 @@ +import { Profile } from "@/components/layout/profile"; +import { RocksGridBuilder } from "@/components/widget/builder"; +import prisma from "@/services/prisma"; + +type UserProfileProps = { + params: { + uid: string; + }; +}; + +export default async function UserProfile({ params }: UserProfileProps) { + const userId = params.uid; + + const user = await prisma.user.findUnique({ + where: { id: userId }, + }); + if (!user) return

User not found

; + + return ( +
+
+ +
+
+ +
+
+ ); +} diff --git a/components/layout/navbar.tsx b/components/layout/navbar.tsx index 46a8e4c..095ed94 100644 --- a/components/layout/navbar.tsx +++ b/components/layout/navbar.tsx @@ -28,6 +28,7 @@ const links = [ export default function NavbarWithLogin({ session }: INavbarWithLogin) { const segment = useSelectedLayoutSegment(); + return (
@@ -82,6 +83,9 @@ export default function NavbarWithLogin({ session }: INavbarWithLogin) { {link.title} ))} + + Profile + Connects diff --git a/components/layout/profile.tsx b/components/layout/profile.tsx new file mode 100644 index 0000000..14e14b2 --- /dev/null +++ b/components/layout/profile.tsx @@ -0,0 +1,23 @@ +import { User } from "@prisma/client"; +import NextImage from "next/image"; + +type ProfileType = { + user: User; +}; + +export const Profile = ({ user }: ProfileType) => { + return ( +
+ {user.image && ( + + )} +

{user.name}

+
+ ); +}; diff --git a/components/ui/image.tsx b/components/ui/image.tsx index d2e57d5..f6bb16b 100644 --- a/components/ui/image.tsx +++ b/components/ui/image.tsx @@ -1,3 +1,5 @@ +"use client"; + import { useState } from "react"; import NextImage, { ImageProps } from "next/image"; import { cn } from "@/utils"; diff --git a/components/widget/builder.tsx b/components/widget/builder.tsx new file mode 100644 index 0000000..3515207 --- /dev/null +++ b/components/widget/builder.tsx @@ -0,0 +1,71 @@ +"use client"; + +import { Responsive, WidthProvider } from "react-grid-layout"; +import "react-grid-layout/css/styles.css"; +import "react-resizable/css/styles.css"; +import { useMemo } from "react"; +import { FaPlus } from "react-icons/fa"; + +const ResponsiveGridLayout = WidthProvider(Responsive); + +type RocksGridBuilderProps = { + rocks: Array; +}; + +export function RocksGridBuilder({ rocks }: RocksGridBuilderProps) { + // const layout: Array = []; + + function onBreakpointChange(newBreakpoint: string, newCols: number) { + console.log({ newBreakpoint, newCols }); + } + + const addPlaceholder = useMemo( + () => ( +
+
+ +

Add a widget

+
+
+ ), + [] + ); + + return ( + + {addPlaceholder} + {rocks.map((rock, index) => { + return ( +
+ {rock} +
+ ); + })} +
+ ); +} diff --git a/package-lock.json b/package-lock.json index b8b57eb..dbe5091 100644 --- a/package-lock.json +++ b/package-lock.json @@ -33,6 +33,7 @@ "qs": "^6.11.1", "react": "18.2.0", "react-dom": "18.2.0", + "react-grid-layout": "^1.3.4", "react-icons": "^4.8.0", "tailwind-merge": "^1.10.0", "yup": "^1.0.2" @@ -50,6 +51,7 @@ "@types/passport-oauth2-refresh": "^1.1.1", "@types/react": "^18.3.2", "@types/react-dom": "18.0.8", + "@types/react-grid-layout": "^1.3.2", "@types/testing-library__jest-dom": "^5.14.5", "autoprefixer": "^10.4.14", "copy-webpack-plugin": "^11.0.0", @@ -3464,6 +3466,15 @@ "@types/react": "*" } }, + "node_modules/@types/react-grid-layout": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@types/react-grid-layout/-/react-grid-layout-1.3.2.tgz", + "integrity": "sha512-ZzpBEOC1JTQ7MGe1h1cPKSLP4jSWuxc+yvT4TsAlEW9+EFPzAf8nxQfFd7ea9gL17Em7PbwJZAsiwfQQBUklZQ==", + "dev": true, + "dependencies": { + "@types/react": "*" + } + }, "node_modules/@types/serve-static": { "version": "1.15.1", "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.1.tgz", @@ -8846,6 +8857,11 @@ "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==", "dev": true }, + "node_modules/lodash.isequal": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", + "integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==" + }, "node_modules/lodash.isfunction": { "version": "3.0.9", "resolved": "https://registry.npmjs.org/lodash.isfunction/-/lodash.isfunction-3.0.9.tgz", @@ -10595,6 +10611,19 @@ "react": "^18.2.0" } }, + "node_modules/react-draggable": { + "version": "4.4.5", + "resolved": "https://registry.npmjs.org/react-draggable/-/react-draggable-4.4.5.tgz", + "integrity": "sha512-OMHzJdyJbYTZo4uQE393fHcqqPYsEtkjfMgvCHr6rejT+Ezn4OZbNyGH50vv+SunC1RMvwOTSWkEODQLzw1M9g==", + "dependencies": { + "clsx": "^1.1.1", + "prop-types": "^15.8.1" + }, + "peerDependencies": { + "react": ">= 16.3.0", + "react-dom": ">= 16.3.0" + } + }, "node_modules/react-element-to-jsx-string": { "version": "15.0.0", "resolved": "https://registry.npmjs.org/react-element-to-jsx-string/-/react-element-to-jsx-string-15.0.0.tgz", @@ -10614,6 +10643,22 @@ "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.1.0.tgz", "integrity": "sha512-Fl7FuabXsJnV5Q1qIOQwx/sagGF18kogb4gpfcG4gjLBWO0WDiiz1ko/ExayuxE7InyQkBLkxRFG5oxY6Uu3Kg==" }, + "node_modules/react-grid-layout": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/react-grid-layout/-/react-grid-layout-1.3.4.tgz", + "integrity": "sha512-sB3rNhorW77HUdOjB4JkelZTdJGQKuXLl3gNg+BI8gJkTScspL1myfZzW/EM0dLEn+1eH+xW+wNqk0oIM9o7cw==", + "dependencies": { + "clsx": "^1.1.1", + "lodash.isequal": "^4.0.0", + "prop-types": "^15.8.1", + "react-draggable": "^4.0.0", + "react-resizable": "^3.0.4" + }, + "peerDependencies": { + "react": ">= 16.3.0", + "react-dom": ">= 16.3.0" + } + }, "node_modules/react-icons": { "version": "4.8.0", "resolved": "https://registry.npmjs.org/react-icons/-/react-icons-4.8.0.tgz", @@ -10673,6 +10718,18 @@ } } }, + "node_modules/react-resizable": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/react-resizable/-/react-resizable-3.0.5.tgz", + "integrity": "sha512-vKpeHhI5OZvYn82kXOs1bC8aOXktGU5AmKAgaZS4F5JPburCtbmDPqE7Pzp+1kN4+Wb81LlF33VpGwWwtXem+w==", + "dependencies": { + "prop-types": "15.x", + "react-draggable": "^4.0.3" + }, + "peerDependencies": { + "react": ">= 16.3" + } + }, "node_modules/react-style-singleton": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/react-style-singleton/-/react-style-singleton-2.2.1.tgz", diff --git a/package.json b/package.json index 229abb0..8d254a0 100644 --- a/package.json +++ b/package.json @@ -46,6 +46,7 @@ "qs": "^6.11.1", "react": "18.2.0", "react-dom": "18.2.0", + "react-grid-layout": "^1.3.4", "react-icons": "^4.8.0", "tailwind-merge": "^1.10.0", "yup": "^1.0.2" @@ -63,6 +64,7 @@ "@types/passport-oauth2-refresh": "^1.1.1", "@types/react": "^18.3.2", "@types/react-dom": "18.0.8", + "@types/react-grid-layout": "^1.3.2", "@types/testing-library__jest-dom": "^5.14.5", "autoprefixer": "^10.4.14", "copy-webpack-plugin": "^11.0.0", From aa00a7b0309e3c59faaa3fe1870967c8041c82d0 Mon Sep 17 00:00:00 2001 From: Samet Date: Thu, 16 May 2024 00:10:27 +0300 Subject: [PATCH 2/2] feat(#212): exported rock stories properly --- app/profile/page.tsx | 77 ----------- lib/@dsvgui/components/article/export.ts | 5 + .../components/article/index.stories.tsx | 126 +++++++----------- lib/@dsvgui/components/article/index.tsx | 16 ++- lib/@dsvgui/components/barstats/export.ts | 5 + .../components/barstats/index.stories.tsx | 6 +- lib/@dsvgui/components/calendar/export.ts | 5 + .../components/calendar/index.stories.tsx | 6 +- lib/@dsvgui/components/fallback/export.ts | 5 + .../components/fallback/index.stories.tsx | 6 +- lib/@dsvgui/components/flock/export.ts | 5 + .../components/flock/index.stories.tsx | 38 +++--- lib/@dsvgui/components/flock/index.tsx | 5 +- lib/@dsvgui/components/grid/index.stories.tsx | 37 +++++ .../grid.tsx => components/grid/index.tsx} | 28 ++-- lib/@dsvgui/components/line/export.ts | 14 ++ lib/@dsvgui/components/line/index.stories.tsx | 21 ++- lib/@dsvgui/components/metrics/export.ts | 6 + .../components/metrics/index.stories.tsx | 6 +- lib/@dsvgui/components/placeholder/export.ts | 17 +++ .../components/placeholder/index.stories.tsx | 14 +- lib/@dsvgui/components/progress/export.ts | 5 + .../components/progress/index.stories.tsx | 8 +- lib/@dsvgui/document/type.ts | 4 + lib/@dsvgui/utils/encoded.ts | 2 + lib/@dsvgui/utils/index.ts | 45 +++++-- 26 files changed, 276 insertions(+), 236 deletions(-) delete mode 100644 app/profile/page.tsx create mode 100644 lib/@dsvgui/components/article/export.ts create mode 100644 lib/@dsvgui/components/barstats/export.ts create mode 100644 lib/@dsvgui/components/calendar/export.ts create mode 100644 lib/@dsvgui/components/fallback/export.ts create mode 100644 lib/@dsvgui/components/flock/export.ts create mode 100644 lib/@dsvgui/components/grid/index.stories.tsx rename lib/@dsvgui/{utils/grid.tsx => components/grid/index.tsx} (54%) create mode 100644 lib/@dsvgui/components/line/export.ts create mode 100644 lib/@dsvgui/components/metrics/export.ts create mode 100644 lib/@dsvgui/components/placeholder/export.ts create mode 100644 lib/@dsvgui/components/progress/export.ts create mode 100644 lib/@dsvgui/utils/encoded.ts diff --git a/app/profile/page.tsx b/app/profile/page.tsx deleted file mode 100644 index 124e7da..0000000 --- a/app/profile/page.tsx +++ /dev/null @@ -1,77 +0,0 @@ -// "use client"; - -import prisma from "@/services/prisma"; -import { Platform, PlatformCode, PlatformQuery } from "@prisma/client"; -import { templates, samples } from "@/platforms"; -import { RocksGridBuilder } from "@/components/widget/builder"; - -type IPlatformQueries = { - platform: Platform & { queries: Array }; -}; - -const PlatformQueries = async ({ platform }: IPlatformQueries, key: string) => { - const template = templates[platform.code]; - const sample = samples[platform.code]; - - return Promise.all( - platform.queries.map((query) => - PlatformQueryView( - { - query, - template: template as any, - sample: sample as any, - }, - query.id - ) - ) - ); -}; - -type IPlatformQueryView = { - query: PlatformQuery; - template: { - [key in keyof typeof PlatformCode]: ( - ...params: any - ) => Promise; - }; - sample: { [key in keyof typeof PlatformCode]: any }; -}; - -const PlatformQueryView = async ( - { query, template, sample }: IPlatformQueryView, - key: string -) => { - const getView = template[query.name as keyof typeof template]; - const sampleData = sample[query.name as keyof typeof samples]; - if (!sampleData) return <>No data.; - - return getView(sampleData.result, sampleData.config); -}; - -type UserOwnProfileProps = { params: { uid: string } }; -export default async function UserOwnProfile({ params }: UserOwnProfileProps) { - const platforms = await prisma.platform.findMany({ - include: { - queries: { - where: { publicQueryId: { isSet: false } }, - }, - }, - }); - - const rocksWithView = ( - await Promise.all( - platforms.map((platform) => PlatformQueries({ platform }, platform.id)) - ) - ).flatMap((item) => item); - - return ( -
-
-

User profile

-
-
- -
-
- ); -} diff --git a/lib/@dsvgui/components/article/export.ts b/lib/@dsvgui/components/article/export.ts new file mode 100644 index 0000000..cafa4de --- /dev/null +++ b/lib/@dsvgui/components/article/export.ts @@ -0,0 +1,5 @@ +import { getGridComponents } from "../../utils"; +import { Base, Compact, WithoutImage } from "./index.stories"; +import { Article } from "./index"; + +export default getGridComponents([Base, Compact, WithoutImage], Article); diff --git a/lib/@dsvgui/components/article/index.stories.tsx b/lib/@dsvgui/components/article/index.stories.tsx index cf3ba37..3d772af 100644 --- a/lib/@dsvgui/components/article/index.stories.tsx +++ b/lib/@dsvgui/components/article/index.stories.tsx @@ -2,8 +2,9 @@ import React from "react"; import type { Meta, StoryObj } from "@storybook/react"; import { Article, articleDocumentPreferences, IArticle } from "./index"; -import { readImageURL } from "../../utils"; -import { Grid } from "../../utils/grid"; +import { getGridComponents, readImageURL } from "../../utils"; +import { Grid } from "../grid"; +import { encodedPlaceholder } from "../../utils/encoded"; const meta: Meta = { title: "Article", @@ -19,6 +20,13 @@ const meta: Meta = { }; export default meta; +const imageLoader = async ({ args: { articles } }: { args: IArticle }) => { + const thumbnails = await Promise.all( + articles.map((article) => readImageURL(article.thumbnail.value)) + ); + return { thumbnails }; +}; + type Story = StoryObj; export const Base: Story = { @@ -36,10 +44,9 @@ export const Base: Story = { author: "sametcodes", }, thumbnail: { - value: - "https://res.cloudinary.com/practicaldev/image/fetch/s--uJ_UDNhq--/c_imagga_scale,f_auto,fl_progressive,h_420,q_auto,w_1000/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/h2q16fucjwb4cla0ho05.png", - width: 150, - height: 150, + value: encodedPlaceholder, + width: 300, + height: 300, }, publish_date: "20.03.2023", like_count: 3, @@ -52,10 +59,9 @@ export const Base: Story = { author: "eminkokdemir", }, thumbnail: { - value: - "https://res.cloudinary.com/practicaldev/image/fetch/s--r3He9vYK--/c_imagga_scale,f_auto,fl_progressive,h_420,q_auto,w_1000/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fuc2yb3yi1680dgmfj25.png", - width: 150, - height: 150, + value: encodedPlaceholder, + width: 300, + height: 300, }, publish_date: "20.03.2023", like_count: 3, @@ -68,10 +74,9 @@ export const Base: Story = { author: "ekurt", }, thumbnail: { - value: - "https://res.cloudinary.com/practicaldev/image/fetch/s--Wzj_6u7j--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/53d24e36pofszh6shj6t.png", - width: 150, - height: 150, + value: encodedPlaceholder, + width: 300, + height: 300, }, publish_date: "20.03.2023", like_count: 3, @@ -85,10 +90,9 @@ export const Base: Story = { author: "aydinfz", }, thumbnail: { - value: - "https://res.cloudinary.com/practicaldev/image/fetch/s--_hLjVEgA--/c_imagga_scale,f_auto,fl_progressive,h_420,q_auto,w_1000/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ewoetr6z83in1o5iu5uc.png", - width: 150, - height: 150, + value: encodedPlaceholder, + width: 300, + height: 300, }, publish_date: "20.03.2023", like_count: 3, @@ -96,14 +100,7 @@ export const Base: Story = { }, ], }, - loaders: [ - async ({ args: { articles } }) => { - const thumbnails = await Promise.all( - articles.map((article) => readImageURL(article.thumbnail.value)) - ); - return { thumbnails }; - }, - ], + loaders: [imageLoader], }; export const Compact: Story = { @@ -121,10 +118,9 @@ export const Compact: Story = { author: "sametcodes", }, thumbnail: { - value: - "https://res.cloudinary.com/practicaldev/image/fetch/s--uJ_UDNhq--/c_imagga_scale,f_auto,fl_progressive,h_420,q_auto,w_1000/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/h2q16fucjwb4cla0ho05.png", - width: 150, - height: 150, + value: encodedPlaceholder, + width: 400, + height: 400, }, publish_date: "20.03.2023", like_count: 3, @@ -137,10 +133,9 @@ export const Compact: Story = { author: "eminkokdemir", }, thumbnail: { - value: - "https://res.cloudinary.com/practicaldev/image/fetch/s--r3He9vYK--/c_imagga_scale,f_auto,fl_progressive,h_420,q_auto,w_1000/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fuc2yb3yi1680dgmfj25.png", - width: 150, - height: 150, + value: encodedPlaceholder, + width: 400, + height: 400, }, publish_date: "20.03.2023", like_count: 3, @@ -153,10 +148,9 @@ export const Compact: Story = { author: "ekurt", }, thumbnail: { - value: - "https://res.cloudinary.com/practicaldev/image/fetch/s--Wzj_6u7j--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/53d24e36pofszh6shj6t.png", - width: 150, - height: 150, + value: encodedPlaceholder, + width: 400, + height: 400, }, publish_date: "20.03.2023", like_count: 3, @@ -170,10 +164,9 @@ export const Compact: Story = { author: "aydinfz", }, thumbnail: { - value: - "https://res.cloudinary.com/practicaldev/image/fetch/s--_hLjVEgA--/c_imagga_scale,f_auto,fl_progressive,h_420,q_auto,w_1000/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ewoetr6z83in1o5iu5uc.png", - width: 150, - height: 150, + value: encodedPlaceholder, + width: 400, + height: 400, }, publish_date: "20.03.2023", like_count: 3, @@ -181,14 +174,7 @@ export const Compact: Story = { }, ], }, - loaders: [ - async ({ args: { articles } }) => { - const thumbnails = await Promise.all( - articles.map((article) => readImageURL(article.thumbnail.value)) - ); - return { thumbnails }; - }, - ], + loaders: [imageLoader], }; export const WithoutImage: Story = { @@ -206,10 +192,9 @@ export const WithoutImage: Story = { author: "sametcodes", }, thumbnail: { - value: - "https://res.cloudinary.com/practicaldev/image/fetch/s--uJ_UDNhq--/c_imagga_scale,f_auto,fl_progressive,h_420,q_auto,w_1000/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/h2q16fucjwb4cla0ho05.png", - width: 150, - height: 150, + value: encodedPlaceholder, + width: 400, + height: 400, }, publish_date: "20.03.2023", like_count: 3, @@ -222,10 +207,9 @@ export const WithoutImage: Story = { author: "eminkokdemir", }, thumbnail: { - value: - "https://res.cloudinary.com/practicaldev/image/fetch/s--r3He9vYK--/c_imagga_scale,f_auto,fl_progressive,h_420,q_auto,w_1000/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fuc2yb3yi1680dgmfj25.png", - width: 150, - height: 150, + value: encodedPlaceholder, + width: 400, + height: 400, }, publish_date: "20.03.2023", like_count: 3, @@ -238,10 +222,9 @@ export const WithoutImage: Story = { author: "ekurt", }, thumbnail: { - value: - "https://res.cloudinary.com/practicaldev/image/fetch/s--Wzj_6u7j--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/53d24e36pofszh6shj6t.png", - width: 150, - height: 150, + value: encodedPlaceholder, + width: 400, + height: 400, }, publish_date: "20.03.2023", like_count: 3, @@ -255,10 +238,9 @@ export const WithoutImage: Story = { author: "aydinfz", }, thumbnail: { - value: - "https://res.cloudinary.com/practicaldev/image/fetch/s--_hLjVEgA--/c_imagga_scale,f_auto,fl_progressive,h_420,q_auto,w_1000/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ewoetr6z83in1o5iu5uc.png", - width: 150, - height: 150, + value: encodedPlaceholder, + width: 400, + height: 400, }, publish_date: "20.03.2023", like_count: 3, @@ -266,16 +248,10 @@ export const WithoutImage: Story = { }, ], }, - loaders: [ - async ({ args: { articles } }) => { - const thumbnails = await Promise.all( - articles.map((article) => readImageURL(article.thumbnail.value)) - ); - return { thumbnails }; - }, - ], + loaders: [imageLoader], }; +const rocks = getGridComponents([Base, Compact, WithoutImage], Article); export const WithGrid = () => { - return ; + return ; }; diff --git a/lib/@dsvgui/components/article/index.tsx b/lib/@dsvgui/components/article/index.tsx index a6a0abc..a7e4da4 100644 --- a/lib/@dsvgui/components/article/index.tsx +++ b/lib/@dsvgui/components/article/index.tsx @@ -1,6 +1,6 @@ import React from "react"; -import { Document, Text, getDocumentSize } from "../../document"; +import { Document, Text } from "../../document"; import { wrapText, getTextWidth } from "../../utils"; import { AiOutlineCalendar, AiOutlineLike } from "react-icons/ai"; @@ -8,6 +8,7 @@ import { BiTimeFive } from "react-icons/bi"; import { IoPersonCircleOutline } from "react-icons/io5"; import { DocumentMeta } from "../../document/type"; +import { getDocumentSize } from "../../document/document"; export type IArticle = { articles: Array<{ @@ -45,7 +46,7 @@ export const Article: React.FC = ({ articles, document }) => { const withImage = document.w > 4; const documentId = Math.random().toString(36).substr(2, 9); - const rowHeight = height / articles.length; + const rowHeight = height / articles.slice(0, document.h).length; const innerPadding = 30; const thumbnailWidth = withImage ? 100 : 0; const titleWidth = Math.max( @@ -59,7 +60,7 @@ export const Article: React.FC = ({ articles, document }) => { return ( - {articles.map((article, key: number) => { + {articles.slice(0, document.h).map((article, key: number) => { const yOffset = rowHeight * key; const xOffset = thumbnailWidth + 20; @@ -79,9 +80,9 @@ export const Article: React.FC = ({ articles, document }) => { @@ -202,7 +203,10 @@ export const Article: React.FC = ({ articles, document }) => { width={article.thumbnail.width} height={500} xmlnsXlink="http://www.w3.org/1999/xlink" - xlinkHref={`data:image/png;base64,${article.thumbnail.value}`} + xlinkHref={`data:image/png;base64,${article.thumbnail.value.replace( + "data:image/png;base64,", + "" + )}`} /> )} diff --git a/lib/@dsvgui/components/barstats/export.ts b/lib/@dsvgui/components/barstats/export.ts new file mode 100644 index 0000000..8d7cd6c --- /dev/null +++ b/lib/@dsvgui/components/barstats/export.ts @@ -0,0 +1,5 @@ +import { getGridComponents } from "../../utils"; +import { Base, Compact } from "./index.stories"; +import { BarStats } from "./index"; + +export default getGridComponents([Base, Compact], BarStats); diff --git a/lib/@dsvgui/components/barstats/index.stories.tsx b/lib/@dsvgui/components/barstats/index.stories.tsx index 322a8b7..5c79afe 100644 --- a/lib/@dsvgui/components/barstats/index.stories.tsx +++ b/lib/@dsvgui/components/barstats/index.stories.tsx @@ -1,5 +1,6 @@ import type { Meta, StoryObj } from "@storybook/react"; -import { Grid } from "../../utils/grid"; +import { getGridComponents } from "../../utils"; +import { Grid } from "../grid"; import { BarStats, barstatsDocumentPreferences, IBarStats } from "./index"; const meta: Meta = { @@ -112,6 +113,7 @@ export const Compact: Story = { }, }; +const rocks = getGridComponents([Base, Compact], BarStats); export const WithGrid = () => { - return ; + return ; }; diff --git a/lib/@dsvgui/components/calendar/export.ts b/lib/@dsvgui/components/calendar/export.ts new file mode 100644 index 0000000..f8b4d60 --- /dev/null +++ b/lib/@dsvgui/components/calendar/export.ts @@ -0,0 +1,5 @@ +import { Base, Compact, WithStreak } from "./index.stories"; +import { Calendar } from "./index"; +import { getGridComponents } from "../../utils"; + +export default getGridComponents([Base, Compact, WithStreak], Calendar); diff --git a/lib/@dsvgui/components/calendar/index.stories.tsx b/lib/@dsvgui/components/calendar/index.stories.tsx index f142a3c..d142447 100644 --- a/lib/@dsvgui/components/calendar/index.stories.tsx +++ b/lib/@dsvgui/components/calendar/index.stories.tsx @@ -1,5 +1,6 @@ import type { Meta, StoryObj } from "@storybook/react"; -import { Grid } from "../../utils/grid"; +import { getGridComponents } from "../../utils"; +import { Grid } from "../grid"; import { Calendar, calendarDocumentPreferences, ICalendar } from "./index"; const meta: Meta = { @@ -77,6 +78,7 @@ export const WithStreak: Story = { }, }; +const rocks = getGridComponents([Base, Compact, WithStreak], Calendar); export const WithGrid = () => { - return ; + return ; }; diff --git a/lib/@dsvgui/components/fallback/export.ts b/lib/@dsvgui/components/fallback/export.ts new file mode 100644 index 0000000..129f982 --- /dev/null +++ b/lib/@dsvgui/components/fallback/export.ts @@ -0,0 +1,5 @@ +import { getGridComponents } from "../../utils"; +import { Fallback } from "./index"; +import { Base } from "./index.stories"; + +export default getGridComponents([Base], Fallback); diff --git a/lib/@dsvgui/components/fallback/index.stories.tsx b/lib/@dsvgui/components/fallback/index.stories.tsx index 27b305a..e32d702 100644 --- a/lib/@dsvgui/components/fallback/index.stories.tsx +++ b/lib/@dsvgui/components/fallback/index.stories.tsx @@ -1,5 +1,6 @@ import type { Meta, StoryObj } from "@storybook/react"; -import { Grid } from "../../utils/grid"; +import { getGridComponents } from "../../utils"; +import { Grid } from "../grid"; import { Fallback, IFallback, documentPreferences } from "./index"; const meta: Meta = { @@ -22,6 +23,7 @@ export const Base: Story = { }, }; +const rocks = getGridComponents([Base], Fallback); export const WithGrid = () => { - return ; + return ; }; diff --git a/lib/@dsvgui/components/flock/export.ts b/lib/@dsvgui/components/flock/export.ts new file mode 100644 index 0000000..0ef894e --- /dev/null +++ b/lib/@dsvgui/components/flock/export.ts @@ -0,0 +1,5 @@ +import { getGridComponents } from "../../utils"; +import { Base, WithText } from "./index.stories"; +import { Flock } from "./index"; + +export default getGridComponents([Base, WithText], Flock); diff --git a/lib/@dsvgui/components/flock/index.stories.tsx b/lib/@dsvgui/components/flock/index.stories.tsx index dfbeadd..81b1aa5 100644 --- a/lib/@dsvgui/components/flock/index.stories.tsx +++ b/lib/@dsvgui/components/flock/index.stories.tsx @@ -3,7 +3,9 @@ import React from "react"; import type { Meta, StoryObj } from "@storybook/react"; import { Flock, IFlock, flockDocumentPreferences } from "./index"; import { readImageURL } from "../../utils"; -import { Grid } from "../../utils/grid"; +import { Grid } from "../grid"; +import { getGridComponents } from "../../utils/index"; +import { encodedPlaceholder } from "../../utils/encoded"; const meta: Meta = { title: "Flock", @@ -19,12 +21,19 @@ const meta: Meta = { }; export default meta; +const imageLoader = async ({ args }: { args: IFlock }) => { + const images = await Promise.all( + args.members.map((member) => readImageURL(member.image.value)) + ); + return { images }; +}; + type Story = StoryObj; const produceMockImages = (n: number, width: number, height: number) => { return Array.from({ length: n }).map((_, key) => ({ image: { - value: "https://picsum.photos/300/300", + value: encodedPlaceholder, width, height, }, @@ -41,16 +50,9 @@ export const Base: Story = { }, title: "Flock", subtitle: "This is a flock component", - members: produceMockImages(16, 5, 5), + members: produceMockImages(200, 5, 5), }, - loaders: [ - async ({ args }) => { - const images = await Promise.all( - args.members.map((member) => readImageURL(member.image.value)) - ); - return { images }; - }, - ], + loaders: [imageLoader], }; export const WithText: Story = { @@ -62,18 +64,12 @@ export const WithText: Story = { }, title: "Flock", subtitle: "This is a flock component", - members: produceMockImages(16, 5, 5), + members: produceMockImages(200, 5, 5), }, - loaders: [ - async ({ args }) => { - const images = await Promise.all( - args.members.map((member) => readImageURL(member.image.value)) - ); - return { images }; - }, - ], + loaders: [imageLoader], }; +const rocks = getGridComponents([Base, WithText], Flock); export const WithGrid = () => { - return ; + return ; }; diff --git a/lib/@dsvgui/components/flock/index.tsx b/lib/@dsvgui/components/flock/index.tsx index 690f78b..b20d3f4 100644 --- a/lib/@dsvgui/components/flock/index.tsx +++ b/lib/@dsvgui/components/flock/index.tsx @@ -107,7 +107,10 @@ export const Flock: React.FC = ({ width="460" height="460" xmlnsXlink="http://www.w3.org/1999/xlink" - xlinkHref={`data:image/png;base64,${member.image.value}`} + xlinkHref={`data:image/png;base64,${member.image.value.replace( + "data:image/png;base64,", + "" + )}`} /> diff --git a/lib/@dsvgui/components/grid/index.stories.tsx b/lib/@dsvgui/components/grid/index.stories.tsx new file mode 100644 index 0000000..7674a38 --- /dev/null +++ b/lib/@dsvgui/components/grid/index.stories.tsx @@ -0,0 +1,37 @@ +import type { Meta, StoryObj } from "@storybook/react"; +import { Grid } from "./index"; +import { GridItem } from "../../document/type"; + +import articleRocks from "../article/export"; +import barstatsRocks from "../barstats/export"; +import calendarRocks from "../calendar/export"; +import flockRocks from "../flock/export"; +import lineRocks from "../line/export"; +import metricsRocks from "../metrics/export"; +import placeholderRocks from "../placeholder/export"; +import progressRocks from "../progress/export"; + +const meta: Meta = { + title: "Grid", + component: Grid, +}; +export default meta; + +type Story = StoryObj; + +const items: Array> = [ + ...articleRocks, + ...barstatsRocks, + ...calendarRocks, + ...flockRocks, + ...lineRocks, + ...metricsRocks, + ...placeholderRocks, + ...progressRocks, +]; + +export const Base: Story = { + args: { + rocks: items, + }, +}; diff --git a/lib/@dsvgui/utils/grid.tsx b/lib/@dsvgui/components/grid/index.tsx similarity index 54% rename from lib/@dsvgui/utils/grid.tsx rename to lib/@dsvgui/components/grid/index.tsx index 8b9a6fe..f0e410f 100644 --- a/lib/@dsvgui/utils/grid.tsx +++ b/lib/@dsvgui/components/grid/index.tsx @@ -1,30 +1,27 @@ -import { ReactRenderer } from "@storybook/react"; -import { StoryAnnotations } from "@storybook/types"; import { useState } from "react"; import GridLayout from "react-grid-layout"; -import { DocumentMeta } from "../document/type"; +import { GridItem } from "../../document/type"; -export const Grid = ({ - component: Component, - stories, +export const Grid = ({ + rocks, }: { - component: React.FC; - stories: Array>>; + rocks: Array>; }) => { - const componentSizes: Array = stories.map((story, i) => { - const { document } = story.args as T; + const componentSizes: Array = rocks.map((rock, i) => { + const { document } = rock as GridItem; return { - ...(document || { w: 4, h: 2 }), x: 0, - y: stories + y: rocks .slice(0, i) .reduce( (acc, c) => - acc + ((c.args as T).document as { w: number; h: number }).h, + acc + ((c as GridItem).document as { w: number; h: number }).h, 0 ), i: i.toString(), + w: (document as { w: number; h: number }).w, + h: (document as { w: number; h: number }).h, }; }, []); @@ -46,11 +43,12 @@ export const Grid = ({ layout={layout} onLayoutChange={onLayoutChange} > - {stories.map((story, i) => { + {rocks.map((rock: GridItem, i) => { const document = layout[i]; + const { document: _, component: Component, ...rest } = rock; return (
- +
); })} diff --git a/lib/@dsvgui/components/line/export.ts b/lib/@dsvgui/components/line/export.ts new file mode 100644 index 0000000..a02300c --- /dev/null +++ b/lib/@dsvgui/components/line/export.ts @@ -0,0 +1,14 @@ +import { getGridComponents } from "../../utils"; +import { + Compact, + Colored, + WithSecondaryTitle, + WithPeriodLabels, + MultipleLines, +} from "./index.stories"; +import { Line } from "./index"; + +export default getGridComponents( + [Compact, Colored, WithSecondaryTitle, WithPeriodLabels, MultipleLines], + Line +); diff --git a/lib/@dsvgui/components/line/index.stories.tsx b/lib/@dsvgui/components/line/index.stories.tsx index 762e0e1..58896a9 100644 --- a/lib/@dsvgui/components/line/index.stories.tsx +++ b/lib/@dsvgui/components/line/index.stories.tsx @@ -1,6 +1,7 @@ import type { Meta, StoryObj } from "@storybook/react"; -import { Grid } from "../../utils/grid"; +import { Grid } from "../grid"; import { ILine, Line, documentPreferences } from "./index"; +import { getGridComponents } from "../../utils/index"; const meta: Meta = { title: "Line", @@ -138,17 +139,11 @@ export const MultipleLines: Story = { }, }; +const rocks = getGridComponents( + [Compact, Colored, WithSecondaryTitle, WithPeriodLabels, MultipleLines], + Line +); + export const WithGrid = () => { - return ( - - ); + return ; }; diff --git a/lib/@dsvgui/components/metrics/export.ts b/lib/@dsvgui/components/metrics/export.ts new file mode 100644 index 0000000..bb610de --- /dev/null +++ b/lib/@dsvgui/components/metrics/export.ts @@ -0,0 +1,6 @@ +import { getGridComponents } from "../../utils"; +import { Metrics } from "./index"; + +import { Base, Multiple, Long } from "./index.stories"; + +export default getGridComponents([Base, Multiple, Long], Metrics); diff --git a/lib/@dsvgui/components/metrics/index.stories.tsx b/lib/@dsvgui/components/metrics/index.stories.tsx index 0388c0c..0bbcd3e 100644 --- a/lib/@dsvgui/components/metrics/index.stories.tsx +++ b/lib/@dsvgui/components/metrics/index.stories.tsx @@ -2,7 +2,8 @@ import type { Meta, StoryObj } from "@storybook/react"; import { metricsDocumentPreferences, IMetrics, Metrics } from "./index"; import { SiCodewars, SiGithub, SiWakatime } from "react-icons/si"; -import { Grid } from "../../utils/grid"; +import { Grid } from "../grid"; +import { getGridComponents } from "../../utils"; const meta: Meta = { title: "Metrics", @@ -55,6 +56,7 @@ export const Long: Story = { }, }; +const rocks = getGridComponents([Base, Multiple, Long], Metrics); export const WithGrid = () => { - return ; + return ; }; diff --git a/lib/@dsvgui/components/placeholder/export.ts b/lib/@dsvgui/components/placeholder/export.ts new file mode 100644 index 0000000..b32439c --- /dev/null +++ b/lib/@dsvgui/components/placeholder/export.ts @@ -0,0 +1,17 @@ +import { + Size1x1, + Size2x1, + Size1x2, + Size2x2, + Size3x2, + Size2x3, + Size3x3, +} from "./index.stories"; + +import { getGridComponents } from "../../utils"; +import { Placeholder } from "./index"; + +export default getGridComponents( + [Size1x1, Size2x1, Size1x2, Size2x2, Size3x2, Size2x3, Size3x3], + Placeholder +); diff --git a/lib/@dsvgui/components/placeholder/index.stories.tsx b/lib/@dsvgui/components/placeholder/index.stories.tsx index 3ca2aff..40e6c16 100644 --- a/lib/@dsvgui/components/placeholder/index.stories.tsx +++ b/lib/@dsvgui/components/placeholder/index.stories.tsx @@ -1,5 +1,6 @@ import type { Meta, StoryObj } from "@storybook/react"; -import { Grid } from "../../utils/grid"; +import { getGridComponents } from "../../utils"; +import { Grid } from "../grid"; import { documentPreferences, Placeholder } from "./index"; const meta: Meta = { @@ -87,11 +88,10 @@ export const Size3x3: Story = { loaders: [], }; +const rocks = getGridComponents( + [Size1x1, Size2x1, Size1x2, Size2x2, Size3x2, Size2x3, Size3x3], + Placeholder +); export const WithGrid = () => { - return ( - - ); + return ; }; diff --git a/lib/@dsvgui/components/progress/export.ts b/lib/@dsvgui/components/progress/export.ts new file mode 100644 index 0000000..6adfed1 --- /dev/null +++ b/lib/@dsvgui/components/progress/export.ts @@ -0,0 +1,5 @@ +import { Base, OnlyFirstLine, OnlyProgress } from "./index.stories"; +import { Progress } from "./index"; +import { getGridComponents } from "../../utils"; + +export default getGridComponents([Base, OnlyFirstLine, OnlyProgress], Progress); diff --git a/lib/@dsvgui/components/progress/index.stories.tsx b/lib/@dsvgui/components/progress/index.stories.tsx index 4fa0242..a8ac02e 100644 --- a/lib/@dsvgui/components/progress/index.stories.tsx +++ b/lib/@dsvgui/components/progress/index.stories.tsx @@ -4,7 +4,8 @@ import { progressDocumentPreferences, IProgress, Progress } from "./index"; import { AiOutlineCalendar } from "react-icons/ai"; import { HiChartBar } from "react-icons/hi"; import { VscIssues, VscGitPullRequest } from "react-icons/vsc"; -import { Grid } from "../../utils/grid"; +import { Grid } from "../grid"; +import { getGridComponents } from "../../utils"; const meta: Meta = { title: "Progress", @@ -68,8 +69,7 @@ export const OnlyProgress: Story = { }, }; +const rocks = getGridComponents([Base, OnlyFirstLine, OnlyProgress], Progress); export const WithGrid = () => { - return ( - - ); + return ; }; diff --git a/lib/@dsvgui/document/type.ts b/lib/@dsvgui/document/type.ts index 74353a5..c74bb6f 100644 --- a/lib/@dsvgui/document/type.ts +++ b/lib/@dsvgui/document/type.ts @@ -4,3 +4,7 @@ export type DocumentMeta = { h: number; }; }; + +export type GridItem = { + component: React.FC; +} & DocumentMeta; diff --git a/lib/@dsvgui/utils/encoded.ts b/lib/@dsvgui/utils/encoded.ts new file mode 100644 index 0000000..aca31ca --- /dev/null +++ b/lib/@dsvgui/utils/encoded.ts @@ -0,0 +1,2 @@ +export const encodedPlaceholder: string = + "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAZAAAAGQCAYAAACAvzbMAAAUgUlEQVR4nO3da3cT1xUG4CPJtgwxxndDgISspCukq5e0a7X//wfwOaVdhJar7wZ8l2xL/ZCSApHtOdu6jKTn+ZTEo9F2vKX3zMyZM5XHjx+3EwBkqg66AACGkwABIESAABAiQAAIESAAhAgQAEIECAAhAgSAEAECQIgAASBEgAAQIkAACBEgAIQIEABCBAgAIQIEgBABAkCIAAEgRIAAECJAAAgRIACECBAAQgQIACECBIAQAQJAiAABIESAABAiQAAIESAAhAgQAEIECAAhAgSAEAECQIgAASBEgAAQIkAACBEgAIQIEABCBAgAIQIEgBABAkCIAAEgRIAAECJAAAgRIACECBAAQgQIACECBIAQAQJAiAABIESAABAiQAAIESAAhAgQAEIECAAhAgSAEAECQIgAASBEgAAQIkAACBEgAIQIEABCBAgAIQIEgBABAkCIAAEgRIAAECJAAAgRIACECBAAQgQIACECBIAQAQJAiAABIESAABAiQAAIESAAhAgQAEIECAAhAgSAEAECQIgAASBEgAAQIkAACBEgAIQIEABCBAgAIQIEgBABAkCIAAEgRIAAECJAAAgRIACECBAAQgQIACECBIAQAQJAiAABIESAABAiQAAIESAAhAgQAEIECAAhAgSAEAECQIgAASBEgAAQIkAACBEgAIQIEABCBAgAIQIEgBABAkCIAAEgRIAAECJAAAgRIACECBAAQgQIACECBIAQAQJAiAABIESAABAiQAAIESAAhAgQAEIECAAhAgSAEAECQIgAASBEgAAQIkAACBEgAIQIEABCBAgAIQIEgBABAkCIAAEgRIAAECJAAAgRIACECBAAQgQIACECBIAQAQJAiAABIESAABAiQAAIESAAhAgQAEIECAAhAgSAEAECQIgAASBEgAAQIkAACBEgAIQIEABCBAgAIQIEgBABAkCIAAEgRIAAECJAAAgRIACECBAAQgQIACECBIAQAQJAiAABIESAABAiQAAIESAAhAgQAEIECAAhAgSAEAECQIgAASBEgAAQIkAACBEgAIQIEABCBAgAIQIEgJCJQRdQRsfHx2ltbS0dHBykw8PDVKvVUr1eT9PT0+nGjRtpcXExffHFF4MuE65Fn3NdlcePH7cHXURZtFqt9OLF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FSqVSqpUKqlaraaJiYk0NTWVZmZmutYctVot/fDDD+ndu3fp1atXWaPmD6anp9O9e/fS6upq1+87KHt9nTSbzd9Mof0wkq5Wq6larabJyclf17rKCYWVlZX0n//858JA+LhfarVampqaSrdv3y79/SD6vNz1lVXl8ePHvXuMGtmazWba3d1NBwcH6ejoKDUajXR+fp7Oz89TpVJJtVotTU5Opps3b6YvvvgiLSws9OTwe1jrYziUvY/KXl9ZCBAAQsbjOAuArhMgAIQIEABCBAgAIQIEgBABAkCIAAEgRIAAECJAAAgRIACECBAAQgQIACECBIAQAQJAiAABIESAABAiQAAIESAAhAgQAEIECAAhAgSAEAECQIgAASBEgAAQIkAACBEgAIQIEABCBAgAIQIEgBABAkCIAAEgRIAAECJAAAgRIACECBAAQgQIACECBIAQAQJAiAABIESAABAiQAAIESAAhAgQAEIECAAhAgSAEAECQIgAASBEgAAQIkAACBEgAIQIEABCBAgAIQIEgBABAkCIAAEgRIAAECJAAAgRIACECBAAQgQIACECBIAQAQJAiAABIESAABAiQAAIESAAhAgQAEIECAAhAgSAEAECQIgAASBEgAAQIkAACBEgAIQIEABCBAgAIQIEgBABAkCIAAEgRIAAECJAAAgRIACECBAAQgQIACECBIAQAQJAiAABIESAABAiQAAIESAAhAgQAEIECAAhAgSAEAECQIgAASBEgAAQIkAACBEgAIQIEABCBAgAIQIEgBABAkCIAAEgRIAAECJAAAgRIACECBAAQgQIACECBIAQAQJAiAABIESAABAiQAAIESAAhAgQAEIECAAhAgSAEAECQIgAASBEgAAQIkAACBEgAIQIEABCBAgAIQIEgBABAkCIAAEgRIAAECJAAAgRIACECBAAQgQIACECBIAQAQJAiAABIESAABAiQAAIESAAhAgQAEIECAAhAgSAEAECQIgAASBEgAAQIkAACBEgAIQIEABCBAgAIQIEgBABAkCIAAEgRIAAEPJf4W5es+2XGEQAAAAASUVORK5CYII="; diff --git a/lib/@dsvgui/utils/index.ts b/lib/@dsvgui/utils/index.ts index 1c7a03e..8105e7d 100644 --- a/lib/@dsvgui/utils/index.ts +++ b/lib/@dsvgui/utils/index.ts @@ -2,6 +2,9 @@ import getImageSize from "image-size"; import opentype from "opentype.js"; import { loadFontBuffer } from "./fonts"; import { FontFamily, defaultFont } from "../document/fonts"; +import { StoryAnnotations } from "@storybook/types"; +import { ReactRenderer } from "@storybook/react"; +import { GridItem } from "../document/type"; type IGetTextWidth = ( inputText: string | number | null, @@ -124,19 +127,43 @@ export function generateColorVariations(inputColor: string, step: number = 5) { return variations; } +export function readImageBuffer(data: string | ArrayBuffer) { + let buffer: Buffer = Buffer.from(""); + + if (typeof data === "string") { + buffer = Buffer.from(data.split(",")[1], "base64"); + } + if (data instanceof ArrayBuffer) { + buffer = Buffer.from(data); + } + + const imageData = getImageSize(buffer); + return { + value: buffer.toString("base64"), + width: imageData.width || 0, + height: imageData.height || 0, + }; +} + export async function readImageURL(url: string) { + if (url.startsWith("data:image")) { + return readImageBuffer(url); + } + const response = await fetch(url, { referrerPolicy: "no-referrer", redirect: "follow", }); const arrayBuffer = await response.arrayBuffer(); - - const buffer = Buffer.from(arrayBuffer); - const imageData = getImageSize(buffer); - - return { - value: buffer.toString("base64"), - width: imageData.width, - height: imageData.height, - }; + return readImageBuffer(arrayBuffer); } + +export const getGridComponents = ( + item: Array>>, + component: React.FC +) => { + return item.map(({ args }) => ({ + ...args, + component, + })) as Array>; +};