diff --git a/apps/web/src/app/features/demo/demo-feature-dashboard-grid.tsx b/apps/web/src/app/features/demo/demo-feature-dashboard-grid.tsx new file mode 100644 index 0000000..a86458c --- /dev/null +++ b/apps/web/src/app/features/demo/demo-feature-dashboard-grid.tsx @@ -0,0 +1,57 @@ +import { UiCard, UiDashboardGrid, UiDashboardItem, UiStack } from '@pubkey-ui/core' +import { + IconBuildingBank, + IconCashBanknote, + IconCoin, + IconCreditCard, + IconReceipt, + IconReceiptRefund, + IconReceiptTax, + IconRepeat, + IconReport, +} from '@tabler/icons-react' +import { ReactNode } from 'react' +import { useRoutes } from 'react-router-dom' + +export function useDashboardItems(): { + links: UiDashboardItem[] + routes: ReactNode +} { + const links: UiDashboardItem[] = [ + { to: 'credit-cards', label: 'Credit cards', icon: IconCreditCard }, + { to: 'banks-nearby', label: 'Banks nearby', icon: IconBuildingBank }, + { to: 'transfers', label: 'Transfers', icon: IconRepeat }, + { to: 'refunds', label: 'Refunds', icon: IconReceiptRefund }, + { to: 'receipts', label: 'Receipts', icon: IconReceipt }, + { to: 'taxes', label: 'Taxes', icon: IconReceiptTax }, + { to: 'reports', label: 'Reports', icon: IconReport }, + { to: 'payments', label: 'Payments', icon: IconCoin }, + { to: 'cashback', label: 'Cashback', icon: IconCashBanknote }, + ] + const routes = useRoutes([ + { index: true, element:
Dashboard Grid
}, + ...links.map((link) => ({ path: link.to, element:
{link.label}
})), + ]) + + return { + links, + routes, + } +} + +export function DemoFeatureDashboardGrid() { + const base = '/demo/dashboard-grid' + const { links, routes } = useDashboardItems() + return ( + + ({ + to: `${base}/${to}`, + label, + icon, + }))} + /> + {routes} + + ) +} diff --git a/apps/web/src/app/features/demo/demo-feature.tsx b/apps/web/src/app/features/demo/demo-feature.tsx index 399388c..31e15fe 100644 --- a/apps/web/src/app/features/demo/demo-feature.tsx +++ b/apps/web/src/app/features/demo/demo-feature.tsx @@ -5,6 +5,7 @@ import { Link, Navigate, useLocation, useRoutes } from 'react-router-dom' import { DemoFeatureAlerts } from './demo-feature-alerts' import { DemoFeatureCard } from './demo-feature-card' import { DemoFeatureCopy } from './demo-feature-copy' +import { DemoFeatureDashboardGrid } from './demo-feature-dashboard-grid' import { DemoFeatureDebug } from './demo-feature-debug' import { DemoFeatureGroup } from './demo-feature-group' import { DemoFeatureHeader } from './demo-feature-header' @@ -26,6 +27,7 @@ export function DemoFeature() { { path: 'alerts', label: 'Alerts', element: }, { path: 'card', label: 'Card', element: }, { path: 'copy', label: 'Copy', element: }, + { path: 'dashboard-grid', label: 'Dashboard Grid', element: }, { path: 'debug', label: 'Debug', element: }, { path: 'group', label: 'Group', element: }, { path: 'header', label: 'Header', element: }, diff --git a/apps/web/src/app/features/dev/dev-feature-action-grid.tsx b/apps/web/src/app/features/dev/dev-feature-action-grid.tsx new file mode 100644 index 0000000..a230fb7 --- /dev/null +++ b/apps/web/src/app/features/dev/dev-feature-action-grid.tsx @@ -0,0 +1,34 @@ +import { UiCard, UiContainer, UiDashboardGrid } from '@pubkey-ui/core' +import { + IconBuildingBank, + IconCashBanknote, + IconCoin, + IconCreditCard, + IconReceipt, + IconReceiptRefund, + IconReceiptTax, + IconRepeat, + IconReport, +} from '@tabler/icons-react' + +export function DevFeatureActionGrid() { + return ( + + + + + + ) +} diff --git a/apps/web/src/app/features/dev/dev-feature-logo.tsx b/apps/web/src/app/features/dev/dev-feature-logo.tsx deleted file mode 100644 index 30548e7..0000000 --- a/apps/web/src/app/features/dev/dev-feature-logo.tsx +++ /dev/null @@ -1,30 +0,0 @@ -import { - UiCard, - UiContainer, - UiGroup, - UiLogo, - UiLogoType, - UiLogoTypeBlack, - UiLogoTypeWhite, - UiStack, -} from '@pubkey-ui/core' - -export function DevFeatureLogo() { - return ( - - - - - - - - - - - - - - - - ) -} diff --git a/apps/web/src/app/features/dev/dev-feature.tsx b/apps/web/src/app/features/dev/dev-feature.tsx index 666f05c..f34e2e9 100644 --- a/apps/web/src/app/features/dev/dev-feature.tsx +++ b/apps/web/src/app/features/dev/dev-feature.tsx @@ -1,11 +1,11 @@ import { UiContainer } from '@pubkey-ui/core' import { DevFeatureLink } from './dev-feature-link' -import { DevFeatureLogo } from './dev-feature-logo' +import { DevFeatureActionGrid } from './dev-feature-action-grid' export function DevFeature() { return ( - + ) diff --git a/packages/core/src/lib/index.ts b/packages/core/src/lib/index.ts index 650b073..be93fe0 100644 --- a/packages/core/src/lib/index.ts +++ b/packages/core/src/lib/index.ts @@ -2,6 +2,7 @@ export * from './ui-alert' export * from './ui-card' export * from './ui-container' export * from './ui-copy' +export * from './ui-dashboard-grid' export * from './ui-debug' export * from './ui-group' export * from './ui-header' diff --git a/packages/core/src/lib/ui-dashboard-grid/index.ts b/packages/core/src/lib/ui-dashboard-grid/index.ts new file mode 100644 index 0000000..f98e359 --- /dev/null +++ b/packages/core/src/lib/ui-dashboard-grid/index.ts @@ -0,0 +1 @@ +export * from './ui-dashboard-grid' diff --git a/packages/core/src/lib/ui-dashboard-grid/ui-dashboard-grid.module.css b/packages/core/src/lib/ui-dashboard-grid/ui-dashboard-grid.module.css new file mode 100644 index 0000000..e727aa1 --- /dev/null +++ b/packages/core/src/lib/ui-dashboard-grid/ui-dashboard-grid.module.css @@ -0,0 +1,16 @@ +.item { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + text-align: center; + border-radius: var(--mantine-radius-md); + height: rem(180px); + background-color: light-dark(var(--mantine-color-gray-0), var(--mantine-color-dark-7)); + transition: box-shadow 150ms ease, transform 100ms ease; + + @mixin hover { + box-shadow: var(--mantine-shadow-md); + transform: scale(1.05); + } +} diff --git a/packages/core/src/lib/ui-dashboard-grid/ui-dashboard-grid.tsx b/packages/core/src/lib/ui-dashboard-grid/ui-dashboard-grid.tsx new file mode 100644 index 0000000..40a999f --- /dev/null +++ b/packages/core/src/lib/ui-dashboard-grid/ui-dashboard-grid.tsx @@ -0,0 +1,42 @@ +import { SimpleGrid, Text, UnstyledButton, useMantineTheme } from '@mantine/core' +import { useUiTheme } from '../ui-theme' +import { ComponentType } from 'react' + +import classes from './ui-dashboard-grid.module.css' + +const linkColors = ['violet', 'indigo', 'blue', 'green', 'teal', 'cyan', 'pink', 'red', 'orange'] + +export function getColorByIndex(index: number) { + return linkColors[index % linkColors.length] +} + +export interface UiDashboardItem { + icon: ComponentType<{ color?: string; size: number | string }> + label: string + to: string + color?: string +} + +export interface UiDashboardGridProps { + links: UiDashboardItem[] +} + +export function UiDashboardGrid({ links }: UiDashboardGridProps) { + const { Link } = useUiTheme() + const theme = useMantineTheme() + + const items = links.map((item, index) => ( + + + + {item.label} + + + )) + + return ( + + {items} + + ) +} diff --git a/packages/generators/src/generators/component/__snapshots__/component-generator.spec.ts.snap b/packages/generators/src/generators/component/__snapshots__/component-generator.spec.ts.snap index 23533e1..43cf4f0 100644 --- a/packages/generators/src/generators/component/__snapshots__/component-generator.spec.ts.snap +++ b/packages/generators/src/generators/component/__snapshots__/component-generator.spec.ts.snap @@ -397,6 +397,156 @@ exports[`component generator should create files for copy 1`] = ` } `; +exports[`component generator should create files for dashboard-grid 1`] = ` +{ + ".prettierrc": { + "content": [ + "{ "singleQuote": true }", + ], + "isBinary": false, + "path": "./.prettierrc", + }, + "nx.json": { + "content": [ + "{", + ""affected": { "defaultBase": "main" },", + ""targetDefaults": {", + ""build": { "cache": true },", + ""lint": { "cache": true },", + ""e2e": { "cache": true }", + "}", + "}", + ], + "isBinary": false, + "path": "./nx.json", + }, + "package.json": { + "content": [ + "{", + ""name": "@proj/source",", + ""dependencies": {},", + ""devDependencies": {}", + "}", + ], + "isBinary": false, + "path": "./package.json", + }, + "test": { + "children": { + "index.ts": { + "content": [ + "export * from './ui-dashboard-grid';", + ], + "isBinary": false, + "path": "./test/index.ts", + }, + "ui-dashboard-grid.module.css": { + "content": [ + ".item {", + "display: flex;", + "flex-direction: column;", + "align-items: center;", + "justify-content: center;", + "text-align: center;", + "border-radius: var(--mantine-radius-md);", + "height: rem(180px);", + "background-color: light-dark(", + "var(--mantine-color-white),", + "var(--mantine-color-dark-7)", + ");", + "transition: box-shadow 150ms ease, transform 100ms ease;", + "@mixin hover {", + "box-shadow: var(--mantine-shadow-md) !important;", + "transform: scale(1.05);", + "}", + "}", + ], + "isBinary": false, + "path": "./test/ui-dashboard-grid.module.css", + }, + "ui-dashboard-grid.tsx": { + "content": [ + "import {", + "SimpleGrid,", + "Text,", + "UnstyledButton,", + "useMantineTheme,", + "} from '@mantine/core';", + "import { useUiTheme } from '../ui-theme';", + "import { ComponentType } from 'react';", + "import classes from './ui-dashboard-grid.module.css';", + "const linkColors = [", + "'violet',", + "'indigo',", + "'blue',", + "'green',", + "'teal',", + "'cyan',", + "'pink',", + "'red',", + "'orange',", + "];", + "export function getColorByIndex(index: number) {", + "return linkColors[index % linkColors.length];", + "}", + "export interface UiDashboardItem {", + "icon: ComponentType<{ color?: string; size: number | string }>;", + "label: string;", + "to: string;", + "color?: string;", + "}", + "export interface UiDashboardGridProps {", + "links: UiDashboardItem[];", + "}", + "export function UiDashboardGrid({ links }: UiDashboardGridProps) {", + "const { Link } = useUiTheme();", + "const theme = useMantineTheme();", + "const items = links.map((item, index) => (", + "", + "", + "", + "{item.label}", + "", + "", + "));", + "return (", + "", + "{items}", + "", + ");", + "}", + ], + "isBinary": false, + "path": "./test/ui-dashboard-grid.tsx", + }, + }, + "path": "./test", + }, + "tsconfig.base.json": { + "content": [ + "{", + ""compilerOptions": {", + ""paths": {}", + "}", + "}", + ], + "isBinary": false, + "path": "./tsconfig.base.json", + }, +} +`; + exports[`component generator should create files for debug 1`] = ` { ".prettierrc": { @@ -673,7 +823,10 @@ exports[`component generator should create files for header 1`] = ` "content": [ ".header {", "height: rem(56px);", - "background-color: var(--mantine-color-body);", + "background-color: light-dark(", + "var(--mantine-color-white),", + "var(--mantine-color-dark-9)", + ");", "padding-left: var(--mantine-spacing-md);", "padding-right: var(--mantine-spacing-md);", "}", @@ -699,6 +852,13 @@ exports[`component generator should create files for header 1`] = ` ");", "}", "}", + ".linkActive {", + "background-color: light-dark(", + "var(--mantine-color-gray-0),", + "var(--mantine-color-dark-6)", + ");", + "color: light-dark(var(--mantine-color-brand-6), var(--mantine-color-brand-4));", + "}", ], "isBinary": false, "path": "./test/ui-header.module.css", @@ -707,7 +867,8 @@ exports[`component generator should create files for header 1`] = ` "content": [ "import { Anchor, Burger, Group } from '@mantine/core';", "import { ReactNode } from 'react';", - "import { Link } from 'react-router-dom';", + "import cx from 'clsx';", + "import { Link, useLocation } from 'react-router-dom';", "import { UiLogo, UiLogoType } from '../ui-logo';", "import classes from './ui-header.module.css';", "export interface UiHeaderProps {", @@ -732,12 +893,15 @@ exports[`component generator should create files for header 1`] = ` "profile,", "toggle,", "}: UiHeaderProps) {", + "const { pathname } = useLocation();", "const items = links.map((link) => (", "", "{link.label}", "", diff --git a/packages/generators/src/generators/component/component-generator-schema.d.ts b/packages/generators/src/generators/component/component-generator-schema.d.ts index 424ff14..939530a 100644 --- a/packages/generators/src/generators/component/component-generator-schema.d.ts +++ b/packages/generators/src/generators/component/component-generator-schema.d.ts @@ -19,6 +19,7 @@ export interface ComponentGeneratorSchema { | 'container' | 'copy' | 'debug' + | 'dashboard-grid' | 'group' | 'header' | 'layout' diff --git a/packages/generators/src/generators/component/component-generator-schema.json b/packages/generators/src/generators/component/component-generator-schema.json index 072b6b1..ae8ac70 100644 --- a/packages/generators/src/generators/component/component-generator-schema.json +++ b/packages/generators/src/generators/component/component-generator-schema.json @@ -21,6 +21,7 @@ "container", "copy", "debug", + "dashboard-grid", "group", "header", "layout", diff --git a/packages/generators/src/generators/component/files/dashboard-grid/__prefixFileName__-dashboard-grid.module.css.template b/packages/generators/src/generators/component/files/dashboard-grid/__prefixFileName__-dashboard-grid.module.css.template new file mode 100644 index 0000000..e727aa1 --- /dev/null +++ b/packages/generators/src/generators/component/files/dashboard-grid/__prefixFileName__-dashboard-grid.module.css.template @@ -0,0 +1,16 @@ +.item { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + text-align: center; + border-radius: var(--mantine-radius-md); + height: rem(180px); + background-color: light-dark(var(--mantine-color-gray-0), var(--mantine-color-dark-7)); + transition: box-shadow 150ms ease, transform 100ms ease; + + @mixin hover { + box-shadow: var(--mantine-shadow-md); + transform: scale(1.05); + } +} diff --git a/packages/generators/src/generators/component/files/dashboard-grid/__prefixFileName__-dashboard-grid.tsx.template b/packages/generators/src/generators/component/files/dashboard-grid/__prefixFileName__-dashboard-grid.tsx.template new file mode 100644 index 0000000..9b4e9cb --- /dev/null +++ b/packages/generators/src/generators/component/files/dashboard-grid/__prefixFileName__-dashboard-grid.tsx.template @@ -0,0 +1,42 @@ +import { SimpleGrid, Text, UnstyledButton, useMantineTheme } from '@mantine/core' +import { use<%= prefix.className %>Theme } from '../<%= prefix.fileName %>-theme' +import { ComponentType } from 'react' + +import classes from './<%= prefix.fileName %>-dashboard-grid.module.css' + +const linkColors = ['violet', 'indigo', 'blue', 'green', 'teal', 'cyan', 'pink', 'red', 'orange'] + +export function getColorByIndex(index: number) { + return linkColors[index % linkColors.length] +} + +export interface <%= prefix.className %>DashboardItem { + icon: ComponentType<{ color?: string; size: number | string }> + label: string + to: string + color?: string +} + +export interface <%= prefix.className %>DashboardGridProps { + links: <%= prefix.className %>DashboardItem[] +} + +export function <%= prefix.className %>DashboardGrid({ links }: <%= prefix.className %>DashboardGridProps) { + const { Link } = use<%= prefix.className %>Theme() + const theme = useMantineTheme() + + const items = links.map((item, index) => ( + + + + {item.label} + + + )) + + return ( + + {items} + + ) +} diff --git a/packages/generators/src/generators/component/files/dashboard-grid/index.ts.template b/packages/generators/src/generators/component/files/dashboard-grid/index.ts.template new file mode 100644 index 0000000..f8cd7b0 --- /dev/null +++ b/packages/generators/src/generators/component/files/dashboard-grid/index.ts.template @@ -0,0 +1 @@ +export * from './<%= prefixFileName %>-dashboard-grid' diff --git a/packages/generators/src/generators/components/__snapshots__/components-generator.spec.ts.snap b/packages/generators/src/generators/components/__snapshots__/components-generator.spec.ts.snap index 649739c..5740bf9 100644 --- a/packages/generators/src/generators/components/__snapshots__/components-generator.spec.ts.snap +++ b/packages/generators/src/generators/components/__snapshots__/components-generator.spec.ts.snap @@ -42,6 +42,7 @@ exports[`components generator should run successfully 1`] = ` "export * from './ui-card';", "export * from './ui-container';", "export * from './ui-copy';", + "export * from './ui-dashboard-grid';", "export * from './ui-debug';", "export * from './ui-group';", "export * from './ui-header';", @@ -264,6 +265,108 @@ exports[`components generator should run successfully 1`] = ` }, "path": "./test/ui-copy", }, + "ui-dashboard-grid": { + "children": { + "index.ts": { + "content": [ + "export * from './ui-dashboard-grid';", + ], + "isBinary": false, + "path": "./test/ui-dashboard-grid/index.ts", + }, + "ui-dashboard-grid.module.css": { + "content": [ + ".item {", + "display: flex;", + "flex-direction: column;", + "align-items: center;", + "justify-content: center;", + "text-align: center;", + "border-radius: var(--mantine-radius-md);", + "height: rem(180px);", + "background-color: light-dark(", + "var(--mantine-color-white),", + "var(--mantine-color-dark-7)", + ");", + "transition: box-shadow 150ms ease, transform 100ms ease;", + "@mixin hover {", + "box-shadow: var(--mantine-shadow-md) !important;", + "transform: scale(1.05);", + "}", + "}", + ], + "isBinary": false, + "path": "./test/ui-dashboard-grid/ui-dashboard-grid.module.css", + }, + "ui-dashboard-grid.tsx": { + "content": [ + "import {", + "SimpleGrid,", + "Text,", + "UnstyledButton,", + "useMantineTheme,", + "} from '@mantine/core';", + "import { useUiTheme } from '../ui-theme';", + "import { ComponentType } from 'react';", + "import classes from './ui-dashboard-grid.module.css';", + "const linkColors = [", + "'violet',", + "'indigo',", + "'blue',", + "'green',", + "'teal',", + "'cyan',", + "'pink',", + "'red',", + "'orange',", + "];", + "export function getColorByIndex(index: number) {", + "return linkColors[index % linkColors.length];", + "}", + "export interface UiDashboardItem {", + "icon: ComponentType<{ color?: string; size: number | string }>;", + "label: string;", + "to: string;", + "color?: string;", + "}", + "export interface UiDashboardGridProps {", + "links: UiDashboardItem[];", + "}", + "export function UiDashboardGrid({ links }: UiDashboardGridProps) {", + "const { Link } = useUiTheme();", + "const theme = useMantineTheme();", + "const items = links.map((item, index) => (", + "", + "", + "", + "{item.label}", + "", + "", + "));", + "return (", + "", + "{items}", + "", + ");", + "}", + ], + "isBinary": false, + "path": "./test/ui-dashboard-grid/ui-dashboard-grid.tsx", + }, + }, + "path": "./test/ui-dashboard-grid", + }, "ui-debug": { "children": { "index.ts": { @@ -410,7 +513,10 @@ exports[`components generator should run successfully 1`] = ` "content": [ ".header {", "height: rem(56px);", - "background-color: var(--mantine-color-body);", + "background-color: light-dark(", + "var(--mantine-color-white),", + "var(--mantine-color-dark-9)", + ");", "padding-left: var(--mantine-spacing-md);", "padding-right: var(--mantine-spacing-md);", "}", @@ -436,6 +542,13 @@ exports[`components generator should run successfully 1`] = ` ");", "}", "}", + ".linkActive {", + "background-color: light-dark(", + "var(--mantine-color-gray-0),", + "var(--mantine-color-dark-6)", + ");", + "color: light-dark(var(--mantine-color-brand-6), var(--mantine-color-brand-4));", + "}", ], "isBinary": false, "path": "./test/ui-header/ui-header.module.css", @@ -444,7 +557,8 @@ exports[`components generator should run successfully 1`] = ` "content": [ "import { Anchor, Burger, Group } from '@mantine/core';", "import { ReactNode } from 'react';", - "import { Link } from 'react-router-dom';", + "import cx from 'clsx';", + "import { Link, useLocation } from 'react-router-dom';", "import { UiLogo, UiLogoType } from '../ui-logo';", "import classes from './ui-header.module.css';", "export interface UiHeaderProps {", @@ -469,12 +583,15 @@ exports[`components generator should run successfully 1`] = ` "profile,", "toggle,", "}: UiHeaderProps) {", + "const { pathname } = useLocation();", "const items = links.map((link) => (", "", "{link.label}", "", diff --git a/packages/generators/src/generators/components/components.ts b/packages/generators/src/generators/components/components.ts index 5fd1021..49abb0c 100644 --- a/packages/generators/src/generators/components/components.ts +++ b/packages/generators/src/generators/components/components.ts @@ -5,6 +5,7 @@ export const components: ComponentGeneratorSchema['type'][] = [ 'card', 'container', 'copy', + 'dashboard-grid', 'debug', 'group', 'header', diff --git a/packages/generators/src/generators/feature/__snapshots__/feature-generator.spec.ts.snap b/packages/generators/src/generators/feature/__snapshots__/feature-generator.spec.ts.snap index e2f5910..990058b 100644 --- a/packages/generators/src/generators/feature/__snapshots__/feature-generator.spec.ts.snap +++ b/packages/generators/src/generators/feature/__snapshots__/feature-generator.spec.ts.snap @@ -97,6 +97,74 @@ exports[`feature generator should create files for demo 1`] = ` "isBinary": false, "path": "./test/demo-feature-copy.tsx", }, + "demo-feature-dashboard-grid.tsx": { + "content": [ + "import {", + "UiCard,", + "UiDashboardGrid,", + "UiDashboardItem,", + "UiStack,", + "} from '@pubkey-ui/core';", + "import {", + "IconBuildingBank,", + "IconCashBanknote,", + "IconCoin,", + "IconCreditCard,", + "IconReceipt,", + "IconReceiptRefund,", + "IconReceiptTax,", + "IconRepeat,", + "IconReport,", + "} from '@tabler/icons-react';", + "import { ReactNode } from 'react';", + "import { useRoutes } from 'react-router-dom';", + "export function useDashboardItems(): {", + "links: UiDashboardItem[];", + "routes: ReactNode;", + "} {", + "const links: UiDashboardItem[] = [", + "{ to: 'credit-cards', label: 'Credit cards', icon: IconCreditCard },", + "{ to: 'banks-nearby', label: 'Banks nearby', icon: IconBuildingBank },", + "{ to: 'transfers', label: 'Transfers', icon: IconRepeat },", + "{ to: 'refunds', label: 'Refunds', icon: IconReceiptRefund },", + "{ to: 'receipts', label: 'Receipts', icon: IconReceipt },", + "{ to: 'taxes', label: 'Taxes', icon: IconReceiptTax },", + "{ to: 'reports', label: 'Reports', icon: IconReport },", + "{ to: 'payments', label: 'Payments', icon: IconCoin },", + "{ to: 'cashback', label: 'Cashback', icon: IconCashBanknote },", + "];", + "const routes = useRoutes([", + "{ index: true, element:
Dashboard Grid
},", + "...links.map((link) => ({", + "path: link.to,", + "element:
{link.label}
,", + "})),", + "]);", + "return {", + "links,", + "routes,", + "};", + "}", + "export function DemoFeatureDashboardGrid() {", + "const base = '/demo/dashboard-grid';", + "const { links, routes } = useDashboardItems();", + "return (", + "", + " ({", + "to: \`\${base}/\${to}\`,", + "label,", + "icon,", + "}))}", + "/>", + "{routes}", + "", + ");", + "}", + ], + "isBinary": false, + "path": "./test/demo-feature-dashboard-grid.tsx", + }, "demo-feature-debug.tsx": { "content": [ "import { SimpleGrid } from '@mantine/core';", @@ -665,6 +733,7 @@ exports[`feature generator should create files for demo 1`] = ` "import { DemoFeatureAlerts } from './demo-feature-alerts';", "import { DemoFeatureCard } from './demo-feature-card';", "import { DemoFeatureCopy } from './demo-feature-copy';", + "import { DemoFeatureDashboardGrid } from './demo-feature-dashboard-grid';", "import { DemoFeatureDebug } from './demo-feature-debug';", "import { DemoFeatureGroup } from './demo-feature-group';", "import { DemoFeatureHeader } from './demo-feature-header';", @@ -685,6 +754,11 @@ exports[`feature generator should create files for demo 1`] = ` "{ path: 'alerts', label: 'Alerts', element: },", "{ path: 'card', label: 'Card', element: },", "{ path: 'copy', label: 'Copy', element: },", + "{", + "path: 'dashboard-grid',", + "label: 'Dashboard Grid',", + "element: ,", + "},", "{ path: 'debug', label: 'Debug', element: },", "{ path: 'group', label: 'Group', element: },", "{ path: 'header', label: 'Header', element: },", diff --git a/packages/generators/src/generators/feature/files/demo/demo-feature-dashboard-grid.tsx.template b/packages/generators/src/generators/feature/files/demo/demo-feature-dashboard-grid.tsx.template new file mode 100644 index 0000000..8a909a8 --- /dev/null +++ b/packages/generators/src/generators/feature/files/demo/demo-feature-dashboard-grid.tsx.template @@ -0,0 +1,57 @@ +import { <%= prefix.className %>Card, <%= prefix.className %>DashboardGrid, <%= prefix.className %>DashboardItem, <%= prefix.className %>Stack } from '<%= uiImport %>' +import { + IconBuildingBank, + IconCashBanknote, + IconCoin, + IconCreditCard, + IconReceipt, + IconReceiptRefund, + IconReceiptTax, + IconRepeat, + IconReport, +} from '@tabler/icons-react' +import { ReactNode } from 'react' +import { useRoutes } from 'react-router-dom' + +export function useDashboardItems(): { + links: <%= prefix.className %>DashboardItem[] + routes: ReactNode +} { + const links: <%= prefix.className %>DashboardItem[] = [ + { to: 'credit-cards', label: 'Credit cards', icon: IconCreditCard }, + { to: 'banks-nearby', label: 'Banks nearby', icon: IconBuildingBank }, + { to: 'transfers', label: 'Transfers', icon: IconRepeat }, + { to: 'refunds', label: 'Refunds', icon: IconReceiptRefund }, + { to: 'receipts', label: 'Receipts', icon: IconReceipt }, + { to: 'taxes', label: 'Taxes', icon: IconReceiptTax }, + { to: 'reports', label: 'Reports', icon: IconReport }, + { to: 'payments', label: 'Payments', icon: IconCoin }, + { to: 'cashback', label: 'Cashback', icon: IconCashBanknote }, + ] + const routes = useRoutes([ + { index: true, element:
Dashboard Grid
}, + ...links.map((link) => ({ path: link.to, element:
{link.label}
})), + ]) + + return { + links, + routes, + } +} + +export function DemoFeatureDashboardGrid() { + const base = '/demo/dashboard-grid' + const { links, routes } = useDashboardItems() + return ( + <<%= prefix.className %>Stack> + <<%= prefix.className %>DashboardGrid + links={links.map(({ to, label, icon }) => ({ + to: `${base}/${to}`, + label, + icon, + }))} + /> + <<%= prefix.className %>Card>{routes}Card> + Stack> + ) +} diff --git a/packages/generators/src/generators/feature/files/demo/demo-feature.tsx.template b/packages/generators/src/generators/feature/files/demo/demo-feature.tsx.template index fda97c6..018c5c6 100644 --- a/packages/generators/src/generators/feature/files/demo/demo-feature.tsx.template +++ b/packages/generators/src/generators/feature/files/demo/demo-feature.tsx.template @@ -5,6 +5,7 @@ import { Link, Navigate, useLocation, useRoutes } from 'react-router-dom' import { DemoFeatureAlerts } from './demo-feature-alerts' import { DemoFeatureCard } from './demo-feature-card' import { DemoFeatureCopy } from './demo-feature-copy' +import { DemoFeatureDashboardGrid } from './demo-feature-dashboard-grid' import { DemoFeatureDebug } from './demo-feature-debug' import { DemoFeatureGroup } from './demo-feature-group' import { DemoFeatureHeader } from './demo-feature-header' @@ -26,6 +27,7 @@ element: ReactNode { path: 'alerts', label: 'Alerts', element: }, { path: 'card', label: 'Card', element: }, { path: 'copy', label: 'Copy', element: }, +{ path: 'dashboard-grid', label: 'Dashboard Grid', element: }, { path: 'debug', label: 'Debug', element: }, { path: 'group', label: 'Group', element: }, { path: 'header', label: 'Header', element: }, diff --git a/packages/generators/src/generators/features/__snapshots__/features-generator.spec.ts.snap b/packages/generators/src/generators/features/__snapshots__/features-generator.spec.ts.snap index b65bf8d..6964d15 100644 --- a/packages/generators/src/generators/features/__snapshots__/features-generator.spec.ts.snap +++ b/packages/generators/src/generators/features/__snapshots__/features-generator.spec.ts.snap @@ -99,6 +99,74 @@ exports[`features generator should run successfully 1`] = ` "isBinary": false, "path": "./test/demo/demo-feature-copy.tsx", }, + "demo-feature-dashboard-grid.tsx": { + "content": [ + "import {", + "UiCard,", + "UiDashboardGrid,", + "UiDashboardItem,", + "UiStack,", + "} from '@pubkey-ui/core';", + "import {", + "IconBuildingBank,", + "IconCashBanknote,", + "IconCoin,", + "IconCreditCard,", + "IconReceipt,", + "IconReceiptRefund,", + "IconReceiptTax,", + "IconRepeat,", + "IconReport,", + "} from '@tabler/icons-react';", + "import { ReactNode } from 'react';", + "import { useRoutes } from 'react-router-dom';", + "export function useDashboardItems(): {", + "links: UiDashboardItem[];", + "routes: ReactNode;", + "} {", + "const links: UiDashboardItem[] = [", + "{ to: 'credit-cards', label: 'Credit cards', icon: IconCreditCard },", + "{ to: 'banks-nearby', label: 'Banks nearby', icon: IconBuildingBank },", + "{ to: 'transfers', label: 'Transfers', icon: IconRepeat },", + "{ to: 'refunds', label: 'Refunds', icon: IconReceiptRefund },", + "{ to: 'receipts', label: 'Receipts', icon: IconReceipt },", + "{ to: 'taxes', label: 'Taxes', icon: IconReceiptTax },", + "{ to: 'reports', label: 'Reports', icon: IconReport },", + "{ to: 'payments', label: 'Payments', icon: IconCoin },", + "{ to: 'cashback', label: 'Cashback', icon: IconCashBanknote },", + "];", + "const routes = useRoutes([", + "{ index: true, element:
Dashboard Grid
},", + "...links.map((link) => ({", + "path: link.to,", + "element:
{link.label}
,", + "})),", + "]);", + "return {", + "links,", + "routes,", + "};", + "}", + "export function DemoFeatureDashboardGrid() {", + "const base = '/demo/dashboard-grid';", + "const { links, routes } = useDashboardItems();", + "return (", + "", + " ({", + "to: \`\${base}/\${to}\`,", + "label,", + "icon,", + "}))}", + "/>", + "{routes}", + "", + ");", + "}", + ], + "isBinary": false, + "path": "./test/demo/demo-feature-dashboard-grid.tsx", + }, "demo-feature-debug.tsx": { "content": [ "import { SimpleGrid } from '@mantine/core';", @@ -667,6 +735,7 @@ exports[`features generator should run successfully 1`] = ` "import { DemoFeatureAlerts } from './demo-feature-alerts';", "import { DemoFeatureCard } from './demo-feature-card';", "import { DemoFeatureCopy } from './demo-feature-copy';", + "import { DemoFeatureDashboardGrid } from './demo-feature-dashboard-grid';", "import { DemoFeatureDebug } from './demo-feature-debug';", "import { DemoFeatureGroup } from './demo-feature-group';", "import { DemoFeatureHeader } from './demo-feature-header';", @@ -687,6 +756,11 @@ exports[`features generator should run successfully 1`] = ` "{ path: 'alerts', label: 'Alerts', element: },", "{ path: 'card', label: 'Card', element: },", "{ path: 'copy', label: 'Copy', element: },", + "{", + "path: 'dashboard-grid',", + "label: 'Dashboard Grid',", + "element: ,", + "},", "{ path: 'debug', label: 'Debug', element: },", "{ path: 'group', label: 'Group', element: },", "{ path: 'header', label: 'Header', element: },", diff --git a/packages/generators/src/generators/theme/__snapshots__/theme-generator.spec.ts.snap b/packages/generators/src/generators/theme/__snapshots__/theme-generator.spec.ts.snap index cf52784..e0591b8 100644 --- a/packages/generators/src/generators/theme/__snapshots__/theme-generator.spec.ts.snap +++ b/packages/generators/src/generators/theme/__snapshots__/theme-generator.spec.ts.snap @@ -244,6 +244,7 @@ exports[`theme generator should run successfully 1`] = ` "export * from './ui-card';", "export * from './ui-container';", "export * from './ui-copy';", + "export * from './ui-dashboard-grid';", "export * from './ui-debug';", "export * from './ui-group';", "export * from './ui-header';", @@ -466,6 +467,108 @@ exports[`theme generator should run successfully 1`] = ` }, "path": "./test-target/src/app/ui/ui-copy", }, + "ui-dashboard-grid": { + "children": { + "index.ts": { + "content": [ + "export * from './ui-dashboard-grid';", + ], + "isBinary": false, + "path": "./test-target/src/app/ui/ui-dashboard-grid/index.ts", + }, + "ui-dashboard-grid.module.css": { + "content": [ + ".item {", + "display: flex;", + "flex-direction: column;", + "align-items: center;", + "justify-content: center;", + "text-align: center;", + "border-radius: var(--mantine-radius-md);", + "height: rem(180px);", + "background-color: light-dark(", + "var(--mantine-color-white),", + "var(--mantine-color-dark-7)", + ");", + "transition: box-shadow 150ms ease, transform 100ms ease;", + "@mixin hover {", + "box-shadow: var(--mantine-shadow-md) !important;", + "transform: scale(1.05);", + "}", + "}", + ], + "isBinary": false, + "path": "./test-target/src/app/ui/ui-dashboard-grid/ui-dashboard-grid.module.css", + }, + "ui-dashboard-grid.tsx": { + "content": [ + "import {", + "SimpleGrid,", + "Text,", + "UnstyledButton,", + "useMantineTheme,", + "} from '@mantine/core';", + "import { useUiTheme } from '../ui-theme';", + "import { ComponentType } from 'react';", + "import classes from './ui-dashboard-grid.module.css';", + "const linkColors = [", + "'violet',", + "'indigo',", + "'blue',", + "'green',", + "'teal',", + "'cyan',", + "'pink',", + "'red',", + "'orange',", + "];", + "export function getColorByIndex(index: number) {", + "return linkColors[index % linkColors.length];", + "}", + "export interface UiDashboardItem {", + "icon: ComponentType<{ color?: string; size: number | string }>;", + "label: string;", + "to: string;", + "color?: string;", + "}", + "export interface UiDashboardGridProps {", + "links: UiDashboardItem[];", + "}", + "export function UiDashboardGrid({ links }: UiDashboardGridProps) {", + "const { Link } = useUiTheme();", + "const theme = useMantineTheme();", + "const items = links.map((item, index) => (", + "", + "", + "", + "{item.label}", + "", + "", + "));", + "return (", + "", + "{items}", + "", + ");", + "}", + ], + "isBinary": false, + "path": "./test-target/src/app/ui/ui-dashboard-grid/ui-dashboard-grid.tsx", + }, + }, + "path": "./test-target/src/app/ui/ui-dashboard-grid", + }, "ui-debug": { "children": { "index.ts": { @@ -612,7 +715,10 @@ exports[`theme generator should run successfully 1`] = ` "content": [ ".header {", "height: rem(56px);", - "background-color: var(--mantine-color-body);", + "background-color: light-dark(", + "var(--mantine-color-white),", + "var(--mantine-color-dark-9)", + ");", "padding-left: var(--mantine-spacing-md);", "padding-right: var(--mantine-spacing-md);", "}",