diff --git a/apps/web/src/app/app-layout.tsx b/apps/web/src/app/app-layout.tsx index 541f8ce..daf94dc 100644 --- a/apps/web/src/app/app-layout.tsx +++ b/apps/web/src/app/app-layout.tsx @@ -1,12 +1,12 @@ -import { ActionIcon, Anchor, Card, Group, Text } from '@mantine/core' -import { UiContainer, UiTheme, useUiColorScheme } from '@pubkey-ui/core' +import { ActionIcon, Anchor, Box, Card, Group, Text } from '@mantine/core' +import { UiContainer, useUiColorScheme } from '@pubkey-ui/core' import { IconMoon, IconSun } from '@tabler/icons-react' import { ReactNode } from 'react' import { Link } from 'react-router-dom' export function AppLayout({ children }: { children: ReactNode }) { return ( - + @@ -29,7 +29,7 @@ export function AppLayout({ children }: { children: ReactNode }) { {children} - + ) } diff --git a/apps/web/src/app/app.tsx b/apps/web/src/app/app.tsx index f88ff9d..5b8fbd9 100644 --- a/apps/web/src/app/app.tsx +++ b/apps/web/src/app/app.tsx @@ -1,11 +1,15 @@ +import { UiThemeProvider } from '@pubkey-ui/core' +import { Link } from 'react-router-dom' import { AppLayout } from './app-layout' import { AppRoutes } from './app-routes' export function App() { return ( - - - + {children}}> + + + + ) } diff --git a/apps/web/src/app/features/demo/demo-feature-toast.tsx b/apps/web/src/app/features/demo/demo-feature-toast.tsx new file mode 100644 index 0000000..fe86959 --- /dev/null +++ b/apps/web/src/app/features/demo/demo-feature-toast.tsx @@ -0,0 +1,24 @@ +import { Button, SimpleGrid } from '@mantine/core' +import { toastError, toastInfo, toastSuccess, toastWarning } from '@pubkey-ui/core' +import { DemoCard } from './demo-card' + +export function DemoFeatureToast() { + return ( + + + + + + + + + ) +} diff --git a/apps/web/src/app/features/demo/demo-feature.tsx b/apps/web/src/app/features/demo/demo-feature.tsx index a73f115..0c73701 100644 --- a/apps/web/src/app/features/demo/demo-feature.tsx +++ b/apps/web/src/app/features/demo/demo-feature.tsx @@ -7,6 +7,7 @@ import { DemoFeatureGroup } from './demo-feature-group' import { DemoFeatureSearchInput } from './demo-feature-search-input' import { DemoFeatureStack } from './demo-feature-stack' import { DemoFeatureTime } from './demo-feature-time' +import { DemoFeatureToast } from './demo-feature-toast' export function DemoFeature() { return ( @@ -20,6 +21,7 @@ export function DemoFeature() { + ) diff --git a/apps/web/src/app/features/dev/dev-feature-search.tsx b/apps/web/src/app/features/dev/dev-feature-search.tsx index d43eb6a..9ce4dd2 100644 --- a/apps/web/src/app/features/dev/dev-feature-search.tsx +++ b/apps/web/src/app/features/dev/dev-feature-search.tsx @@ -1,5 +1,17 @@ -import { UiContainer } from '@pubkey-ui/core' +import { Anchor, Button } from '@mantine/core' +import { UiCard, UiContainer, useUiTheme } from '@pubkey-ui/core' export function DevFeatureSearch() { - return xx + const { Link } = useUiTheme() + return ( + + TEST + + Go to demo + + + + ) } diff --git a/apps/web/src/app/features/dev/dev-feature.tsx b/apps/web/src/app/features/dev/dev-feature.tsx index e97db64..56a68d5 100644 --- a/apps/web/src/app/features/dev/dev-feature.tsx +++ b/apps/web/src/app/features/dev/dev-feature.tsx @@ -1,12 +1,5 @@ -import { UiContainer, UiStack } from '@pubkey-ui/core' import { DevFeatureSearch } from './dev-feature-search' export function DevFeature() { - return ( - - - - - - ) + return } diff --git a/packages/core/src/lib/index.ts b/packages/core/src/lib/index.ts index cb76b9c..a9fd0be 100644 --- a/packages/core/src/lib/index.ts +++ b/packages/core/src/lib/index.ts @@ -6,5 +6,6 @@ export * from './ui-debug' export * from './ui-group' export * from './ui-search-input' export * from './ui-stack' -export * from './ui-time' export * from './ui-theme' +export * from './ui-time' +export * from './ui-toast' diff --git a/packages/core/src/lib/ui-theme/index.ts b/packages/core/src/lib/ui-theme/index.ts index fd87c6b..8a0742f 100644 --- a/packages/core/src/lib/ui-theme/index.ts +++ b/packages/core/src/lib/ui-theme/index.ts @@ -1,3 +1,3 @@ export * from './ui-color-scheme-provider' -export * from './ui-theme' +export * from './ui-theme-provider' export * from './use-ui-breakpoints' diff --git a/packages/core/src/lib/ui-theme/ui-theme-provider.tsx b/packages/core/src/lib/ui-theme/ui-theme-provider.tsx new file mode 100644 index 0000000..d9bb5f6 --- /dev/null +++ b/packages/core/src/lib/ui-theme/ui-theme-provider.tsx @@ -0,0 +1,58 @@ +import { ColorSchemeScript, createTheme, DEFAULT_THEME, Loader, MantineProvider } from '@mantine/core' +import { ModalsProvider } from '@mantine/modals' +import { Notifications } from '@mantine/notifications' +import { createContext, FunctionComponent, ReactNode, Suspense, useContext } from 'react' +import { UiColorSchemeProvider } from './ui-color-scheme-provider' + +// Import the mantine theme styles +import './ui-theme-styles' + +const theme = createTheme({ + colors: { + brand: DEFAULT_THEME.colors.blue, + }, + primaryColor: 'brand', +}) + +export type UiThemeLink = FunctionComponent<{ + children: ReactNode + to: string + target?: HTMLAnchorElement['target'] + rel?: HTMLAnchorElement['rel'] +}> + +export const defaultUiThemeLink: UiThemeLink = ({ children, ...props }) => ( + + {children} + +) + +export interface UiThemeProviderContext { + Link: UiThemeLink +} + +const Context = createContext({} as UiThemeProviderContext) + +export function UiThemeProvider({ children, link }: { children: ReactNode; link?: UiThemeLink }) { + const value: UiThemeProviderContext = { + Link: link ?? defaultUiThemeLink, + } + + return ( + + + + + + + }>{children} + + + + + ) +} + +export function useUiTheme() { + return useContext(Context) +} diff --git a/packages/core/src/lib/ui-theme/ui-theme.tsx b/packages/core/src/lib/ui-theme/ui-theme.tsx deleted file mode 100644 index fb3b56a..0000000 --- a/packages/core/src/lib/ui-theme/ui-theme.tsx +++ /dev/null @@ -1,31 +0,0 @@ -import { ColorSchemeScript, createTheme, DEFAULT_THEME, Loader, MantineProvider } from '@mantine/core' -import { ModalsProvider } from '@mantine/modals' -import { Notifications } from '@mantine/notifications' -import { ReactNode, Suspense } from 'react' -import { UiColorSchemeProvider } from './ui-color-scheme-provider' - -// Import the mantine theme styles -import './ui-theme-styles' - -const theme = createTheme({ - colors: { - brand: DEFAULT_THEME.colors.blue, - }, - primaryColor: 'brand', -}) - -export function UiTheme({ children }: { children: ReactNode }) { - return ( - <> - - - - - - }>{children} - - - - - ) -} diff --git a/packages/core/src/lib/ui-toast/index.ts b/packages/core/src/lib/ui-toast/index.ts new file mode 100644 index 0000000..569a288 --- /dev/null +++ b/packages/core/src/lib/ui-toast/index.ts @@ -0,0 +1 @@ +export * from './ui-toast' diff --git a/packages/core/src/lib/ui-toast/ui-toast.tsx b/packages/core/src/lib/ui-toast/ui-toast.tsx new file mode 100644 index 0000000..16de603 --- /dev/null +++ b/packages/core/src/lib/ui-toast/ui-toast.tsx @@ -0,0 +1,37 @@ +import { NotificationData, notifications } from '@mantine/notifications' + +export type ToastProps = string | NotificationData + +export function toastSuccess(notification: ToastProps) { + notification = typeof notification === 'string' ? { message: notification } : notification + notifications.show({ + color: notification?.color ?? 'green', + title: notification?.title ?? 'Success', + message: notification?.message, + }) +} + +export function toastError(notification: ToastProps) { + notification = typeof notification === 'string' ? { message: notification } : notification + notifications.show({ + color: notification?.color ?? 'red', + title: notification?.title ?? 'Error', + message: notification?.message, + }) +} +export function toastWarning(notification: ToastProps) { + notification = typeof notification === 'string' ? { message: notification } : notification + notifications.show({ + color: notification?.color ?? 'yellow', + title: notification?.title ?? 'Warning', + message: notification?.message, + }) +} +export function toastInfo(notification: ToastProps) { + notification = typeof notification === 'string' ? { message: notification } : notification + notifications.show({ + color: notification?.color ?? 'cyan', + title: notification?.title ?? 'Info', + message: notification?.message, + }) +} diff --git a/packages/generators/package.json b/packages/generators/package.json index f322905..da09396 100644 --- a/packages/generators/package.json +++ b/packages/generators/package.json @@ -3,7 +3,8 @@ "version": "0.0.1", "dependencies": { "@nx/devkit": "17.1.3", - "tslib": "^2.3.0" + "tslib": "^2.3.0", + "@nx/js": "17.1.3" }, "type": "commonjs", "main": "./src/index.js", 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 8a3dd11..ecfbe9c 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 @@ -105,6 +105,122 @@ exports[`component generator should create files for alert 1`] = ` } `; +exports[`component generator should create files for card 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-card';", + ], + "isBinary": false, + "path": "./test/index.ts", + }, + "ui-card-title.tsx": { + "content": [ + "import { Title, TitleProps } from '@mantine/core';", + "import { ReactNode } from 'react';", + "export function UiCardTitle({", + "children,", + "...props", + "}: TitleProps & {", + "children: ReactNode;", + "}) {", + "return (", + "", + "{children}", + "", + ");", + "}", + ], + "isBinary": false, + "path": "./test/ui-card-title.tsx", + }, + "ui-card.tsx": { + "content": [ + "import { Box, Card, CardProps, Skeleton } from '@mantine/core';", + "import { useUiBreakpoints } from '../ui-theme';", + "import { ReactNode } from 'react';", + "import { UiCardTitle } from './ui-card-title';", + "interface UiCardProps extends CardProps {", + "children: ReactNode;", + "loading?: boolean;", + "title?: ReactNode;", + "}", + "export function UiCard({ loading, title, ...props }: UiCardProps) {", + "const { isSm } = useUiBreakpoints();", + "return (", + "", + "{title ? (", + "", + "{typeof title === 'string' ? (", + "{title}", + ") : (", + "title", + ")}", + "", + ") : null}", + "{loading ? (", + "{props.children}", + ") : (", + "props.children", + ")}", + "", + ");", + "}", + ], + "isBinary": false, + "path": "./test/ui-card.tsx", + }, + }, + "path": "./test", + }, + "tsconfig.base.json": { + "content": [ + "{", + ""compilerOptions": {", + ""paths": {}", + "}", + "}", + ], + "isBinary": false, + "path": "./tsconfig.base.json", + }, +} +`; + exports[`component generator should create files for container 1`] = ` { ".prettierrc": { @@ -152,11 +268,23 @@ exports[`component generator should create files for container 1`] = ` "content": [ "import { Container, ContainerProps } from '@mantine/core';", "import { ReactNode } from 'react';", + "import { useUiBreakpoints } from '../ui-theme';", "export interface UiContainerProps extends ContainerProps {", "children: ReactNode;", "}", "export function UiContainer({ children, ...props }: UiContainerProps) {", - "return {children};", + "const { isSm } = useUiBreakpoints();", + "return (", + "", + "{children}", + "", + ");", "}", ], "isBinary": false, @@ -498,6 +626,115 @@ exports[`component generator should create files for group 1`] = ` } `; +exports[`component generator should create files for search-input 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-search-input';", + ], + "isBinary": false, + "path": "./test/index.ts", + }, + "ui-search-input.tsx": { + "content": [ + "import {", + "ActionIcon,", + "ActionIconProps,", + "rem,", + "TextInput,", + "TextInputProps,", + "useMantineTheme,", + "} from '@mantine/core';", + "import { IconArrowRight, IconSearch } from '@tabler/icons-react';", + "export function UiSearchInput({", + "...props", + "}: {", + "icon?: ActionIconProps;", + "text?: TextInputProps;", + "} = {}) {", + "const theme = useMantineTheme();", + "return (", + "", + "}", + "rightSection={", + "", + "", + "", + "}", + "radius="xl"", + "variant="filled"", + "size="md"", + "placeholder="Search"", + "{...props.text}", + "/>", + ");", + "}", + ], + "isBinary": false, + "path": "./test/ui-search-input.tsx", + }, + }, + "path": "./test", + }, + "tsconfig.base.json": { + "content": [ + "{", + ""compilerOptions": {", + ""paths": {}", + "}", + "}", + ], + "isBinary": false, + "path": "./tsconfig.base.json", + }, +} +`; + exports[`component generator should create files for stack 1`] = ` { ".prettierrc": { @@ -545,11 +782,17 @@ exports[`component generator should create files for stack 1`] = ` "content": [ "import { Stack, StackProps } from '@mantine/core';", "import { ReactNode } from 'react';", + "import { useUiBreakpoints } from '../ui-theme';", "export interface UiStackProps extends StackProps {", "children: ReactNode;", "}", "export function UiStack({ children, ...props }: UiStackProps) {", - "return {children};", + "const { isSm } = useUiBreakpoints();", + "return (", + "", + "{children}", + "", + ");", "}", ], "isBinary": false, @@ -610,49 +853,319 @@ exports[`component generator should create files for theme 1`] = ` "children": { "index.ts": { "content": [ - "export * from './ui-theme';", + "export * from './ui-color-scheme-provider';", + "export * from './ui-theme-provider';", + "export * from './use-ui-breakpoints';", ], "isBinary": false, "path": "./test/index.ts", }, - "ui-theme.tsx": { + "ui-color-scheme-provider.tsx": { + "content": [ + "import {", + "MantineColorScheme,", + "useComputedColorScheme,", + "useMantineColorScheme,", + "} from '@mantine/core';", + "import { useHotkeys } from '@mantine/hooks';", + "import { createContext, ReactNode, useContext } from 'react';", + "export interface UiColorSchemeProviderContext {", + "colorScheme: MantineColorScheme;", + "toggleColorScheme: (colorScheme?: MantineColorScheme) => void;", + "}", + "const Context = createContext(", + "{} as UiColorSchemeProviderContext", + ");", + "export function UiColorSchemeProvider({ children }: { children: ReactNode }) {", + "const { toggleColorScheme } = useMantineColorScheme();", + "const colorScheme = useComputedColorScheme('dark', {", + "getInitialValueInEffect: true,", + "});", + "useHotkeys([['mod+J', () => toggleColorScheme()]]);", + "const value: UiColorSchemeProviderContext = {", + "colorScheme,", + "toggleColorScheme,", + "};", + "return {children};", + "}", + "export function useUiColorScheme() {", + "return useContext(Context);", + "}", + ], + "isBinary": false, + "path": "./test/ui-color-scheme-provider.tsx", + }, + "ui-theme-provider.tsx": { "content": [ "import {", + "ColorSchemeScript,", "createTheme,", "DEFAULT_THEME,", "Loader,", "MantineProvider,", "} from '@mantine/core';", - "import { ReactNode, Suspense } from 'react';", - "import { Notifications } from '@mantine/notifications';", "import { ModalsProvider } from '@mantine/modals';", - "// Core styles", - "import '@mantine/core/styles.css';", - "// Package styles", - "import '@mantine/dates/styles.css';", - "import '@mantine/notifications/styles.css';", - "export interface UiThemeProps {", - "children: ReactNode;", - "}", + "import { Notifications } from '@mantine/notifications';", + "import {", + "createContext,", + "FunctionComponent,", + "ReactNode,", + "Suspense,", + "useContext,", + "} from 'react';", + "import { UiColorSchemeProvider } from './ui-color-scheme-provider';", + "// Import the mantine theme styles", + "import './ui-theme-styles';", "const theme = createTheme({", "colors: {", "brand: DEFAULT_THEME.colors.blue,", "},", "primaryColor: 'brand',", "});", - "export function UiTheme({ children }: UiThemeProps) {", + "export type UiThemeLink = FunctionComponent<{", + "children: ReactNode;", + "to: string;", + "target?: HTMLAnchorElement['target'];", + "rel?: HTMLAnchorElement['rel'];", + "}>;", + "export const defaultUiThemeLink: UiThemeLink = ({ children, ...props }) => (", + "", + "{children}", + "", + ");", + "export interface UiThemeProviderContext {", + "Link: UiThemeLink;", + "}", + "const Context = createContext(", + "{} as UiThemeProviderContext", + ");", + "export function UiThemeProvider({", + "children,", + "link,", + "}: {", + "children: ReactNode;", + "link?: UiThemeLink;", + "}) {", + "const value: UiThemeProviderContext = {", + "Link: link ?? defaultUiThemeLink,", + "};", "return (", - "", + "", + "", + "", + "", "", "", "}>{children}", "", + "", "", + "", ");", "}", + "export function useUiTheme() {", + "return useContext(Context);", + "}", + ], + "isBinary": false, + "path": "./test/ui-theme-provider.tsx", + }, + "ui-theme-styles.ts": { + "content": [ + "// Core styles", + "import '@mantine/core/styles.css';", + "// Package styles", + "import '@mantine/dates/styles.css';", + "import '@mantine/notifications/styles.css';", + ], + "isBinary": false, + "path": "./test/ui-theme-styles.ts", + }, + }, + "path": "./test", + }, + "tsconfig.base.json": { + "content": [ + "{", + ""compilerOptions": {", + ""paths": {}", + "}", + "}", + ], + "isBinary": false, + "path": "./tsconfig.base.json", + }, +} +`; + +exports[`component generator should create files for time 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-time';", + ], + "isBinary": false, + "path": "./test/index.ts", + }, + "ui-time.tsx": { + "content": [ + "import { Text, TextProps } from '@mantine/core';", + "import TimeAgo from 'timeago-react';", + "export interface UiTimeProps extends TextProps {", + "date: Date;", + "prefix?: string;", + "suffix?: string;", + "}", + "export function UiTime({ date, prefix, suffix, ...props }: UiTimeProps) {", + "return (", + "", + "{prefix}", + "", + "{suffix}", + "", + ");", + "}", + ], + "isBinary": false, + "path": "./test/ui-time.tsx", + }, + }, + "path": "./test", + }, + "tsconfig.base.json": { + "content": [ + "{", + ""compilerOptions": {", + ""paths": {}", + "}", + "}", + ], + "isBinary": false, + "path": "./tsconfig.base.json", + }, +} +`; + +exports[`component generator should create files for toast 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-toast';", + ], + "isBinary": false, + "path": "./test/index.ts", + }, + "ui-toast.tsx": { + "content": [ + "import { NotificationData, notifications } from '@mantine/notifications';", + "export type ToastProps = string | NotificationData;", + "export function toastSuccess(notification: ToastProps) {", + "notification =", + "typeof notification === 'string' ? { message: notification } : notification;", + "notifications.show({", + "color: notification?.color ?? 'green',", + "title: notification?.title ?? 'Success',", + "message: notification?.message,", + "});", + "}", + "export function toastError(notification: ToastProps) {", + "notification =", + "typeof notification === 'string' ? { message: notification } : notification;", + "notifications.show({", + "color: notification?.color ?? 'red',", + "title: notification?.title ?? 'Error',", + "message: notification?.message,", + "});", + "}", + "export function toastWarning(notification: ToastProps) {", + "notification =", + "typeof notification === 'string' ? { message: notification } : notification;", + "notifications.show({", + "color: notification?.color ?? 'yellow',", + "title: notification?.title ?? 'Warning',", + "message: notification?.message,", + "});", + "}", + "export function toastInfo(notification: ToastProps) {", + "notification =", + "typeof notification === 'string' ? { message: notification } : notification;", + "notifications.show({", + "color: notification?.color ?? 'cyan',", + "title: notification?.title ?? 'Info',", + "message: notification?.message,", + "});", + "}", ], "isBinary": false, - "path": "./test/ui-theme.tsx", + "path": "./test/ui-toast.tsx", }, }, "path": "./test", 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 47da064..7705fa6 100644 --- a/packages/generators/src/generators/component/component-generator-schema.d.ts +++ b/packages/generators/src/generators/component/component-generator-schema.d.ts @@ -13,7 +13,18 @@ export interface ComponentGeneratorSchema { /** * The type of component to create */ - type: 'alert' | 'card' | 'container' | 'copy' | 'debug' | 'group' | 'search-input' | 'stack' | 'time' | 'theme' + type: + | 'alert' + | 'card' + | 'container' + | 'copy' + | 'debug' + | 'group' + | 'search-input' + | 'stack' + | 'theme' + | 'time' + | 'toast' /** * The prefix to use for the component */ diff --git a/packages/generators/src/generators/component/component-generator-schema.json b/packages/generators/src/generators/component/component-generator-schema.json index 16ea2a5..f01df2a 100644 --- a/packages/generators/src/generators/component/component-generator-schema.json +++ b/packages/generators/src/generators/component/component-generator-schema.json @@ -15,7 +15,19 @@ "type": { "type": "string", "description": "The type of component to create", - "enum": ["alert", "card", "container", "copy", "debug", "group", "search-input", "stack", "time", "theme"], + "enum": [ + "alert", + "card", + "container", + "copy", + "debug", + "group", + "search-input", + "stack", + "theme", + "time", + "toast" + ], "x-prompt": "What type of component do you want to create?" }, "prefix": { diff --git a/packages/generators/src/generators/component/files/search-input/__prefixFileName__-search-input.tsx.template b/packages/generators/src/generators/component/files/search-input/__prefixFileName__-search-input.tsx.template index 2c22170..ad540f3 100644 --- a/packages/generators/src/generators/component/files/search-input/__prefixFileName__-search-input.tsx.template +++ b/packages/generators/src/generators/component/files/search-input/__prefixFileName__-search-input.tsx.template @@ -1,7 +1,7 @@ import { ActionIcon, ActionIconProps, rem, TextInput, TextInputProps, useMantineTheme } from '@mantine/core' import { IconArrowRight, IconSearch } from '@tabler/icons-react' -export function UiSearchInput({ +export function <%= prefix.className %>SearchInput({ ...props }: { icon?: ActionIconProps diff --git a/packages/generators/src/generators/component/files/theme/__prefixFileName__-theme-provider.tsx.template b/packages/generators/src/generators/component/files/theme/__prefixFileName__-theme-provider.tsx.template new file mode 100644 index 0000000..a985b0e --- /dev/null +++ b/packages/generators/src/generators/component/files/theme/__prefixFileName__-theme-provider.tsx.template @@ -0,0 +1,58 @@ +import { ColorSchemeScript, createTheme, DEFAULT_THEME, Loader, MantineProvider } from '@mantine/core' +import { ModalsProvider } from '@mantine/modals' +import { Notifications } from '@mantine/notifications' +import { createContext, FunctionComponent, ReactNode, Suspense, useContext } from 'react' +import { <%= prefix.className %>ColorSchemeProvider } from './<%= prefix.fileName %>-color-scheme-provider' + +// Import the mantine theme styles +import './<%= prefix.fileName %>-theme-styles' + +const theme = createTheme({ + colors: { + brand: DEFAULT_THEME.colors.blue, + }, + primaryColor: 'brand', +}) + +export type <%= prefix.className %>ThemeLink = FunctionComponent<{ + children: ReactNode + to: string + target?: HTMLAnchorElement['target'] + rel?: HTMLAnchorElement['rel'] +}> + +export const default<%= prefix.className %>ThemeLink: <%= prefix.className %>ThemeLink = ({ children, ...props }) => ( + + {children} + +) + +export interface <%= prefix.className %>ThemeProviderContext { + Link: <%= prefix.className %>ThemeLink +} + +const Context = createContext<<%= prefix.className %>ThemeProviderContext>({} as <%= prefix.className %>ThemeProviderContext) + +export function <%= prefix.className %>ThemeProvider({ children, link }: { children: ReactNode; link?: <%= prefix.className %>ThemeLink }) { + const value: <%= prefix.className %>ThemeProviderContext = { + Link: link ?? default<%= prefix.className %>ThemeLink, + } + + return ( + + + + <<%= prefix.className %>ColorSchemeProvider> + + + }>{children} + + ColorSchemeProvider> + + + ) +} + +export function use<%= prefix.className %>Theme() { + return useContext(Context) +} diff --git a/packages/generators/src/generators/component/files/theme/__prefixFileName__-theme.tsx.template b/packages/generators/src/generators/component/files/theme/__prefixFileName__-theme.tsx.template deleted file mode 100644 index f626dd4..0000000 --- a/packages/generators/src/generators/component/files/theme/__prefixFileName__-theme.tsx.template +++ /dev/null @@ -1,31 +0,0 @@ -import { ColorSchemeScript, createTheme, DEFAULT_THEME, Loader, MantineProvider } from '@mantine/core' -import { ModalsProvider } from '@mantine/modals' -import { Notifications } from '@mantine/notifications' -import { ReactNode, Suspense } from 'react' -import { <%= prefix.className %>ColorSchemeProvider } from './<%= prefix.fileName %>-color-scheme-provider' - -// Import the mantine theme styles -import './<%= prefix.fileName %>-theme-styles' - -const theme = createTheme({ - colors: { - brand: DEFAULT_THEME.colors.blue, - }, - primaryColor: 'brand', -}) - -export function <%= prefix.className %>Theme({ children }: { children: ReactNode }) { - return ( - <> - - - <<%= prefix.className %>ColorSchemeProvider> - - - }>{children} - - ColorSchemeProvider> - - - ) -} diff --git a/packages/generators/src/generators/component/files/theme/index.ts.template b/packages/generators/src/generators/component/files/theme/index.ts.template index ab2a403..444f928 100644 --- a/packages/generators/src/generators/component/files/theme/index.ts.template +++ b/packages/generators/src/generators/component/files/theme/index.ts.template @@ -1,3 +1,3 @@ export * from './<%= prefixFileName %>-color-scheme-provider' -export * from './<%= prefixFileName %>-theme' +export * from './<%= prefixFileName %>-theme-provider' export * from './use-<%= prefixFileName %>-breakpoints' diff --git a/packages/generators/src/generators/component/files/toast/__prefixFileName__-toast.tsx.template b/packages/generators/src/generators/component/files/toast/__prefixFileName__-toast.tsx.template new file mode 100644 index 0000000..16de603 --- /dev/null +++ b/packages/generators/src/generators/component/files/toast/__prefixFileName__-toast.tsx.template @@ -0,0 +1,37 @@ +import { NotificationData, notifications } from '@mantine/notifications' + +export type ToastProps = string | NotificationData + +export function toastSuccess(notification: ToastProps) { + notification = typeof notification === 'string' ? { message: notification } : notification + notifications.show({ + color: notification?.color ?? 'green', + title: notification?.title ?? 'Success', + message: notification?.message, + }) +} + +export function toastError(notification: ToastProps) { + notification = typeof notification === 'string' ? { message: notification } : notification + notifications.show({ + color: notification?.color ?? 'red', + title: notification?.title ?? 'Error', + message: notification?.message, + }) +} +export function toastWarning(notification: ToastProps) { + notification = typeof notification === 'string' ? { message: notification } : notification + notifications.show({ + color: notification?.color ?? 'yellow', + title: notification?.title ?? 'Warning', + message: notification?.message, + }) +} +export function toastInfo(notification: ToastProps) { + notification = typeof notification === 'string' ? { message: notification } : notification + notifications.show({ + color: notification?.color ?? 'cyan', + title: notification?.title ?? 'Info', + message: notification?.message, + }) +} diff --git a/packages/generators/src/generators/component/files/toast/index.ts.template b/packages/generators/src/generators/component/files/toast/index.ts.template new file mode 100644 index 0000000..8ba8175 --- /dev/null +++ b/packages/generators/src/generators/component/files/toast/index.ts.template @@ -0,0 +1 @@ +export * from './<%= prefixFileName %>-toast' 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 c488d15..79ece8b 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 @@ -39,12 +39,16 @@ exports[`components generator should run successfully 1`] = ` "index.ts": { "content": [ "export * from './ui-alert';", + "export * from './ui-card';", "export * from './ui-container';", "export * from './ui-copy';", "export * from './ui-debug';", "export * from './ui-group';", + "export * from './ui-search-input';", "export * from './ui-stack';", "export * from './ui-theme';", + "export * from './ui-time';", + "export * from './ui-toast';", ], "isBinary": false, "path": "./test/index.ts", @@ -106,6 +110,74 @@ exports[`components generator should run successfully 1`] = ` }, "path": "./test/ui-alert", }, + "ui-card": { + "children": { + "index.ts": { + "content": [ + "export * from './ui-card';", + ], + "isBinary": false, + "path": "./test/ui-card/index.ts", + }, + "ui-card-title.tsx": { + "content": [ + "import { Title, TitleProps } from '@mantine/core';", + "import { ReactNode } from 'react';", + "export function UiCardTitle({", + "children,", + "...props", + "}: TitleProps & {", + "children: ReactNode;", + "}) {", + "return (", + "", + "{children}", + "", + ");", + "}", + ], + "isBinary": false, + "path": "./test/ui-card/ui-card-title.tsx", + }, + "ui-card.tsx": { + "content": [ + "import { Box, Card, CardProps, Skeleton } from '@mantine/core';", + "import { useUiBreakpoints } from '../ui-theme';", + "import { ReactNode } from 'react';", + "import { UiCardTitle } from './ui-card-title';", + "interface UiCardProps extends CardProps {", + "children: ReactNode;", + "loading?: boolean;", + "title?: ReactNode;", + "}", + "export function UiCard({ loading, title, ...props }: UiCardProps) {", + "const { isSm } = useUiBreakpoints();", + "return (", + "", + "{title ? (", + "", + "{typeof title === 'string' ? (", + "{title}", + ") : (", + "title", + ")}", + "", + ") : null}", + "{loading ? (", + "{props.children}", + ") : (", + "props.children", + ")}", + "", + ");", + "}", + ], + "isBinary": false, + "path": "./test/ui-card/ui-card.tsx", + }, + }, + "path": "./test/ui-card", + }, "ui-container": { "children": { "index.ts": { @@ -119,11 +191,23 @@ exports[`components generator should run successfully 1`] = ` "content": [ "import { Container, ContainerProps } from '@mantine/core';", "import { ReactNode } from 'react';", + "import { useUiBreakpoints } from '../ui-theme';", "export interface UiContainerProps extends ContainerProps {", "children: ReactNode;", "}", "export function UiContainer({ children, ...props }: UiContainerProps) {", - "return {children};", + "const { isSm } = useUiBreakpoints();", + "return (", + "", + "{children}", + "", + ");", "}", ], "isBinary": false, @@ -307,6 +391,67 @@ exports[`components generator should run successfully 1`] = ` }, "path": "./test/ui-group", }, + "ui-search-input": { + "children": { + "index.ts": { + "content": [ + "export * from './ui-search-input';", + ], + "isBinary": false, + "path": "./test/ui-search-input/index.ts", + }, + "ui-search-input.tsx": { + "content": [ + "import {", + "ActionIcon,", + "ActionIconProps,", + "rem,", + "TextInput,", + "TextInputProps,", + "useMantineTheme,", + "} from '@mantine/core';", + "import { IconArrowRight, IconSearch } from '@tabler/icons-react';", + "export function UiSearchInput({", + "...props", + "}: {", + "icon?: ActionIconProps;", + "text?: TextInputProps;", + "} = {}) {", + "const theme = useMantineTheme();", + "return (", + "", + "}", + "rightSection={", + "", + "", + "", + "}", + "radius="xl"", + "variant="filled"", + "size="md"", + "placeholder="Search"", + "{...props.text}", + "/>", + ");", + "}", + ], + "isBinary": false, + "path": "./test/ui-search-input/ui-search-input.tsx", + }, + }, + "path": "./test/ui-search-input", + }, "ui-stack": { "children": { "index.ts": { @@ -320,11 +465,17 @@ exports[`components generator should run successfully 1`] = ` "content": [ "import { Stack, StackProps } from '@mantine/core';", "import { ReactNode } from 'react';", + "import { useUiBreakpoints } from '../ui-theme';", "export interface UiStackProps extends StackProps {", "children: ReactNode;", "}", "export function UiStack({ children, ...props }: UiStackProps) {", - "return {children};", + "const { isSm } = useUiBreakpoints();", + "return (", + "", + "{children}", + "", + ");", "}", ], "isBinary": false, @@ -337,53 +488,227 @@ exports[`components generator should run successfully 1`] = ` "children": { "index.ts": { "content": [ - "export * from './ui-theme';", + "export * from './ui-color-scheme-provider';", + "export * from './ui-theme-provider';", + "export * from './use-ui-breakpoints';", ], "isBinary": false, "path": "./test/ui-theme/index.ts", }, - "ui-theme.tsx": { + "ui-color-scheme-provider.tsx": { + "content": [ + "import {", + "MantineColorScheme,", + "useComputedColorScheme,", + "useMantineColorScheme,", + "} from '@mantine/core';", + "import { useHotkeys } from '@mantine/hooks';", + "import { createContext, ReactNode, useContext } from 'react';", + "export interface UiColorSchemeProviderContext {", + "colorScheme: MantineColorScheme;", + "toggleColorScheme: (colorScheme?: MantineColorScheme) => void;", + "}", + "const Context = createContext(", + "{} as UiColorSchemeProviderContext", + ");", + "export function UiColorSchemeProvider({ children }: { children: ReactNode }) {", + "const { toggleColorScheme } = useMantineColorScheme();", + "const colorScheme = useComputedColorScheme('dark', {", + "getInitialValueInEffect: true,", + "});", + "useHotkeys([['mod+J', () => toggleColorScheme()]]);", + "const value: UiColorSchemeProviderContext = {", + "colorScheme,", + "toggleColorScheme,", + "};", + "return {children};", + "}", + "export function useUiColorScheme() {", + "return useContext(Context);", + "}", + ], + "isBinary": false, + "path": "./test/ui-theme/ui-color-scheme-provider.tsx", + }, + "ui-theme-provider.tsx": { "content": [ "import {", + "ColorSchemeScript,", "createTheme,", "DEFAULT_THEME,", "Loader,", "MantineProvider,", "} from '@mantine/core';", - "import { ReactNode, Suspense } from 'react';", - "import { Notifications } from '@mantine/notifications';", "import { ModalsProvider } from '@mantine/modals';", - "// Core styles", - "import '@mantine/core/styles.css';", - "// Package styles", - "import '@mantine/dates/styles.css';", - "import '@mantine/notifications/styles.css';", - "export interface UiThemeProps {", - "children: ReactNode;", - "}", + "import { Notifications } from '@mantine/notifications';", + "import {", + "createContext,", + "FunctionComponent,", + "ReactNode,", + "Suspense,", + "useContext,", + "} from 'react';", + "import { UiColorSchemeProvider } from './ui-color-scheme-provider';", + "// Import the mantine theme styles", + "import './ui-theme-styles';", "const theme = createTheme({", "colors: {", "brand: DEFAULT_THEME.colors.blue,", "},", "primaryColor: 'brand',", "});", - "export function UiTheme({ children }: UiThemeProps) {", + "export type UiThemeLink = FunctionComponent<{", + "children: ReactNode;", + "to: string;", + "target?: HTMLAnchorElement['target'];", + "rel?: HTMLAnchorElement['rel'];", + "}>;", + "export const defaultUiThemeLink: UiThemeLink = ({ children, ...props }) => (", + "", + "{children}", + "", + ");", + "export interface UiThemeProviderContext {", + "Link: UiThemeLink;", + "}", + "const Context = createContext(", + "{} as UiThemeProviderContext", + ");", + "export function UiThemeProvider({", + "children,", + "link,", + "}: {", + "children: ReactNode;", + "link?: UiThemeLink;", + "}) {", + "const value: UiThemeProviderContext = {", + "Link: link ?? defaultUiThemeLink,", + "};", "return (", - "", + "", + "", + "", + "", "", "", "}>{children}", "", + "", "", + "", ");", "}", + "export function useUiTheme() {", + "return useContext(Context);", + "}", ], "isBinary": false, - "path": "./test/ui-theme/ui-theme.tsx", + "path": "./test/ui-theme/ui-theme-provider.tsx", + }, + "ui-theme-styles.ts": { + "content": [ + "// Core styles", + "import '@mantine/core/styles.css';", + "// Package styles", + "import '@mantine/dates/styles.css';", + "import '@mantine/notifications/styles.css';", + ], + "isBinary": false, + "path": "./test/ui-theme/ui-theme-styles.ts", }, }, "path": "./test/ui-theme", }, + "ui-time": { + "children": { + "index.ts": { + "content": [ + "export * from './ui-time';", + ], + "isBinary": false, + "path": "./test/ui-time/index.ts", + }, + "ui-time.tsx": { + "content": [ + "import { Text, TextProps } from '@mantine/core';", + "import TimeAgo from 'timeago-react';", + "export interface UiTimeProps extends TextProps {", + "date: Date;", + "prefix?: string;", + "suffix?: string;", + "}", + "export function UiTime({ date, prefix, suffix, ...props }: UiTimeProps) {", + "return (", + "", + "{prefix}", + "", + "{suffix}", + "", + ");", + "}", + ], + "isBinary": false, + "path": "./test/ui-time/ui-time.tsx", + }, + }, + "path": "./test/ui-time", + }, + "ui-toast": { + "children": { + "index.ts": { + "content": [ + "export * from './ui-toast';", + ], + "isBinary": false, + "path": "./test/ui-toast/index.ts", + }, + "ui-toast.tsx": { + "content": [ + "import { NotificationData, notifications } from '@mantine/notifications';", + "export type ToastProps = string | NotificationData;", + "export function toastSuccess(notification: ToastProps) {", + "notification =", + "typeof notification === 'string' ? { message: notification } : notification;", + "notifications.show({", + "color: notification?.color ?? 'green',", + "title: notification?.title ?? 'Success',", + "message: notification?.message,", + "});", + "}", + "export function toastError(notification: ToastProps) {", + "notification =", + "typeof notification === 'string' ? { message: notification } : notification;", + "notifications.show({", + "color: notification?.color ?? 'red',", + "title: notification?.title ?? 'Error',", + "message: notification?.message,", + "});", + "}", + "export function toastWarning(notification: ToastProps) {", + "notification =", + "typeof notification === 'string' ? { message: notification } : notification;", + "notifications.show({", + "color: notification?.color ?? 'yellow',", + "title: notification?.title ?? 'Warning',", + "message: notification?.message,", + "});", + "}", + "export function toastInfo(notification: ToastProps) {", + "notification =", + "typeof notification === 'string' ? { message: notification } : notification;", + "notifications.show({", + "color: notification?.color ?? 'cyan',", + "title: notification?.title ?? 'Info',", + "message: notification?.message,", + "});", + "}", + ], + "isBinary": false, + "path": "./test/ui-toast/ui-toast.tsx", + }, + }, + "path": "./test/ui-toast", + }, }, "path": "./test", }, diff --git a/packages/generators/src/generators/components/components.ts b/packages/generators/src/generators/components/components.ts index ab2cc42..fd842c6 100644 --- a/packages/generators/src/generators/components/components.ts +++ b/packages/generators/src/generators/components/components.ts @@ -9,6 +9,7 @@ export const components: ComponentGeneratorSchema['type'][] = [ 'group', 'search-input', 'stack', - 'time', 'theme', + 'time', + 'toast', ] 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 new file mode 100644 index 0000000..7992f25 --- /dev/null +++ b/packages/generators/src/generators/feature/__snapshots__/feature-generator.spec.ts.snap @@ -0,0 +1,361 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`feature generator should create files for demo 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": { + "demo-card.tsx": { + "content": [ + "import { UiCard, UiStack } from '@pubkey-ui/core';", + "export function DemoCard({", + "children,", + "title,", + "}: {", + "children: React.ReactNode;", + "title: string;", + "}) {", + "return (", + "", + "{children}", + "", + ");", + "}", + ], + "isBinary": false, + "path": "./test/demo-card.tsx", + }, + "demo-feature-alerts.tsx": { + "content": [ + "import { SimpleGrid } from '@mantine/core';", + "import {", + "UiAlert,", + "UiError,", + "UiInfo,", + "UiSuccess,", + "UiWarning,", + "} from '@pubkey-ui/core';", + "import { DemoCard } from './demo-card';", + "export function DemoFeatureAlerts() {", + "return (", + "", + "", + "", + "", + "", + "", + "", + "", + "", + ");", + "}", + ], + "isBinary": false, + "path": "./test/demo-feature-alerts.tsx", + }, + "demo-feature-card.tsx": { + "content": [ + "import { UiCard, UiStack } from '@pubkey-ui/core';", + "export function DemoFeatureCard() {", + "return (", + "", + "", + "CARD CONTENT", + "", + "", + ");", + "}", + ], + "isBinary": false, + "path": "./test/demo-feature-card.tsx", + }, + "demo-feature-copy.tsx": { + "content": [ + "import { UiCopy, UiStack } from '@pubkey-ui/core';", + "import { DemoCard } from './demo-card';", + "export function DemoFeatureCopy() {", + "return (", + "", + "", + "", + "", + "", + ");", + "}", + ], + "isBinary": false, + "path": "./test/demo-feature-copy.tsx", + }, + "demo-feature-debug.tsx": { + "content": [ + "import { SimpleGrid } from '@mantine/core';", + "import { UiDebug, UiDebugModal } from '@pubkey-ui/core';", + "import { DemoCard } from './demo-card';", + "export function DemoFeatureDebug() {", + "return (", + "", + "", + "", + "", + "", + "", + "", + "", + ");", + "}", + ], + "isBinary": false, + "path": "./test/demo-feature-debug.tsx", + }, + "demo-feature-group.tsx": { + "content": [ + "import { Button, SimpleGrid } from '@mantine/core';", + "import { UiGroup } from '@pubkey-ui/core';", + "import { DemoCard } from './demo-card';", + "export function DemoFeatureGroup() {", + "return (", + "", + "", + "", + " ", + "", + "", + " ", + "", + "", + " ", + "", + "", + " ", + "", + "", + " ", + "", + "", + " ", + "", + "", + "", + ");", + "}", + ], + "isBinary": false, + "path": "./test/demo-feature-group.tsx", + }, + "demo-feature-search-input.tsx": { + "content": [ + "import { SimpleGrid } from '@mantine/core';", + "import { UiGroup, UiSearchInput } from '@pubkey-ui/core';", + "import { DemoCard } from './demo-card';", + "export function DemoFeatureSearchInput() {", + "return (", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + ");", + "}", + ], + "isBinary": false, + "path": "./test/demo-feature-search-input.tsx", + }, + "demo-feature-stack.tsx": { + "content": [ + "import { Button, SimpleGrid } from '@mantine/core';", + "import { UiStack } from '@pubkey-ui/core';", + "import { DemoCard } from './demo-card';", + "export function DemoFeatureStack() {", + "return (", + "", + "", + "", + " ", + "", + "", + " ", + "", + "", + " ", + "", + "", + " ", + "", + "", + " ", + "", + "", + " ", + "", + "", + "", + ");", + "}", + ], + "isBinary": false, + "path": "./test/demo-feature-stack.tsx", + }, + "demo-feature-time.tsx": { + "content": [ + "import { SimpleGrid } from '@mantine/core';", + "import { UiTime } from '@pubkey-ui/core';", + "import { DemoCard } from './demo-card';", + "export function DemoFeatureTime() {", + "return (", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + ");", + "}", + ], + "isBinary": false, + "path": "./test/demo-feature-time.tsx", + }, + "demo-feature-toast.tsx": { + "content": [ + "import { Button, SimpleGrid } from '@mantine/core';", + "import {", + "toastError,", + "toastInfo,", + "toastSuccess,", + "toastWarning,", + "} from '@pubkey-ui/core';", + "import { DemoCard } from './demo-card';", + "export function DemoFeatureToast() {", + "return (", + "", + "", + " toastSuccess('This is a success toast')}", + ">", + "Toast Success", + "", + " toastError('This is an error toast')}", + ">", + "Toast Error", + "", + " toastWarning('This is a warning toast')}", + ">", + "Toast Warning", + "", + "", + "", + "", + ");", + "}", + ], + "isBinary": false, + "path": "./test/demo-feature-toast.tsx", + }, + "demo-feature.tsx": { + "content": [ + "import { UiContainer, UiStack } from '@pubkey-ui/core';", + "import { DemoFeatureAlerts } from './demo-feature-alerts';", + "import { DemoFeatureCard } from './demo-feature-card';", + "import { DemoFeatureCopy } from './demo-feature-copy';", + "import { DemoFeatureDebug } from './demo-feature-debug';", + "import { DemoFeatureGroup } from './demo-feature-group';", + "import { DemoFeatureSearchInput } from './demo-feature-search-input';", + "import { DemoFeatureStack } from './demo-feature-stack';", + "import { DemoFeatureTime } from './demo-feature-time';", + "import { DemoFeatureToast } from './demo-feature-toast';", + "export function DemoFeature() {", + "return (", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + ");", + "}", + ], + "isBinary": false, + "path": "./test/demo-feature.tsx", + }, + }, + "path": "./test", + }, + "tsconfig.base.json": { + "content": [ + "{", + ""compilerOptions": {", + ""paths": {}", + "}", + "}", + ], + "isBinary": false, + "path": "./tsconfig.base.json", + }, +} +`; diff --git a/packages/generators/src/generators/feature/feature-generator.spec.ts b/packages/generators/src/generators/feature/feature-generator.spec.ts index 8d2e0a1..3ea1b52 100644 --- a/packages/generators/src/generators/feature/feature-generator.spec.ts +++ b/packages/generators/src/generators/feature/feature-generator.spec.ts @@ -1,20 +1,23 @@ +import { Tree } from '@nx/devkit' import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing' -import { Tree, readProjectConfiguration } from '@nx/devkit' +import { getRecursiveFileContents } from '../../' +import { features } from '../features/features' import { featureGenerator } from './feature-generator' import { FeatureGeneratorSchema } from './feature-generator-schema' describe('feature generator', () => { let tree: Tree - const options: FeatureGeneratorSchema = { name: 'test' } + const options: FeatureGeneratorSchema = { directory: 'test', type: 'demo' } beforeEach(() => { tree = createTreeWithEmptyWorkspace() }) - it('should run successfully', async () => { - await featureGenerator(tree, options) - const config = readProjectConfiguration(tree, 'test') - expect(config).toBeDefined() + it.each(features)('should create files for %s', async (type) => { + await featureGenerator(tree, { ...options, type }) + + const contents = getRecursiveFileContents(tree, '.') + expect(contents).toMatchSnapshot() }) }) diff --git a/packages/generators/src/generators/feature/files/demo/demo-feature-toast.tsx.template b/packages/generators/src/generators/feature/files/demo/demo-feature-toast.tsx.template new file mode 100644 index 0000000..fe86959 --- /dev/null +++ b/packages/generators/src/generators/feature/files/demo/demo-feature-toast.tsx.template @@ -0,0 +1,24 @@ +import { Button, SimpleGrid } from '@mantine/core' +import { toastError, toastInfo, toastSuccess, toastWarning } from '@pubkey-ui/core' +import { DemoCard } from './demo-card' + +export function DemoFeatureToast() { + return ( + + + + + + + + + ) +} 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 f5f0e24..d56d93e 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 @@ -7,6 +7,7 @@ import { DemoFeatureGroup } from './demo-feature-group' import { DemoFeatureSearchInput } from './demo-feature-search-input' import { DemoFeatureStack } from './demo-feature-stack' import { DemoFeatureTime } from './demo-feature-time' +import { DemoFeatureToast } from './demo-feature-toast' export function DemoFeature() { return ( @@ -20,6 +21,7 @@ export function DemoFeature() { + Stack> Container> ) 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 new file mode 100644 index 0000000..13839e9 --- /dev/null +++ b/packages/generators/src/generators/features/__snapshots__/features-generator.spec.ts.snap @@ -0,0 +1,373 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`features generator should run successfully 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": { + "demo": { + "children": { + "demo-card.tsx": { + "content": [ + "import { UiCard, UiStack } from '@pubkey-ui/core';", + "export function DemoCard({", + "children,", + "title,", + "}: {", + "children: React.ReactNode;", + "title: string;", + "}) {", + "return (", + "", + "{children}", + "", + ");", + "}", + ], + "isBinary": false, + "path": "./test/demo/demo-card.tsx", + }, + "demo-feature-alerts.tsx": { + "content": [ + "import { SimpleGrid } from '@mantine/core';", + "import {", + "UiAlert,", + "UiError,", + "UiInfo,", + "UiSuccess,", + "UiWarning,", + "} from '@pubkey-ui/core';", + "import { DemoCard } from './demo-card';", + "export function DemoFeatureAlerts() {", + "return (", + "", + "", + "", + "", + "", + "", + "", + "", + "", + ");", + "}", + ], + "isBinary": false, + "path": "./test/demo/demo-feature-alerts.tsx", + }, + "demo-feature-card.tsx": { + "content": [ + "import { UiCard, UiStack } from '@pubkey-ui/core';", + "export function DemoFeatureCard() {", + "return (", + "", + "", + "CARD CONTENT", + "", + "", + ");", + "}", + ], + "isBinary": false, + "path": "./test/demo/demo-feature-card.tsx", + }, + "demo-feature-copy.tsx": { + "content": [ + "import { UiCopy, UiStack } from '@pubkey-ui/core';", + "import { DemoCard } from './demo-card';", + "export function DemoFeatureCopy() {", + "return (", + "", + "", + "", + "", + "", + ");", + "}", + ], + "isBinary": false, + "path": "./test/demo/demo-feature-copy.tsx", + }, + "demo-feature-debug.tsx": { + "content": [ + "import { SimpleGrid } from '@mantine/core';", + "import { UiDebug, UiDebugModal } from '@pubkey-ui/core';", + "import { DemoCard } from './demo-card';", + "export function DemoFeatureDebug() {", + "return (", + "", + "", + "", + "", + "", + "", + "", + "", + ");", + "}", + ], + "isBinary": false, + "path": "./test/demo/demo-feature-debug.tsx", + }, + "demo-feature-group.tsx": { + "content": [ + "import { Button, SimpleGrid } from '@mantine/core';", + "import { UiGroup } from '@pubkey-ui/core';", + "import { DemoCard } from './demo-card';", + "export function DemoFeatureGroup() {", + "return (", + "", + "", + "", + " ", + "", + "", + " ", + "", + "", + " ", + "", + "", + " ", + "", + "", + " ", + "", + "", + " ", + "", + "", + "", + ");", + "}", + ], + "isBinary": false, + "path": "./test/demo/demo-feature-group.tsx", + }, + "demo-feature-search-input.tsx": { + "content": [ + "import { SimpleGrid } from '@mantine/core';", + "import { UiGroup, UiSearchInput } from '@pubkey-ui/core';", + "import { DemoCard } from './demo-card';", + "export function DemoFeatureSearchInput() {", + "return (", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + ");", + "}", + ], + "isBinary": false, + "path": "./test/demo/demo-feature-search-input.tsx", + }, + "demo-feature-stack.tsx": { + "content": [ + "import { Button, SimpleGrid } from '@mantine/core';", + "import { UiStack } from '@pubkey-ui/core';", + "import { DemoCard } from './demo-card';", + "export function DemoFeatureStack() {", + "return (", + "", + "", + "", + " ", + "", + "", + " ", + "", + "", + " ", + "", + "", + " ", + "", + "", + " ", + "", + "", + " ", + "", + "", + "", + ");", + "}", + ], + "isBinary": false, + "path": "./test/demo/demo-feature-stack.tsx", + }, + "demo-feature-time.tsx": { + "content": [ + "import { SimpleGrid } from '@mantine/core';", + "import { UiTime } from '@pubkey-ui/core';", + "import { DemoCard } from './demo-card';", + "export function DemoFeatureTime() {", + "return (", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + ");", + "}", + ], + "isBinary": false, + "path": "./test/demo/demo-feature-time.tsx", + }, + "demo-feature-toast.tsx": { + "content": [ + "import { Button, SimpleGrid } from '@mantine/core';", + "import {", + "toastError,", + "toastInfo,", + "toastSuccess,", + "toastWarning,", + "} from '@pubkey-ui/core';", + "import { DemoCard } from './demo-card';", + "export function DemoFeatureToast() {", + "return (", + "", + "", + " toastSuccess('This is a success toast')}", + ">", + "Toast Success", + "", + " toastError('This is an error toast')}", + ">", + "Toast Error", + "", + " toastWarning('This is a warning toast')}", + ">", + "Toast Warning", + "", + "", + "", + "", + ");", + "}", + ], + "isBinary": false, + "path": "./test/demo/demo-feature-toast.tsx", + }, + "demo-feature.tsx": { + "content": [ + "import { UiContainer, UiStack } from '@pubkey-ui/core';", + "import { DemoFeatureAlerts } from './demo-feature-alerts';", + "import { DemoFeatureCard } from './demo-feature-card';", + "import { DemoFeatureCopy } from './demo-feature-copy';", + "import { DemoFeatureDebug } from './demo-feature-debug';", + "import { DemoFeatureGroup } from './demo-feature-group';", + "import { DemoFeatureSearchInput } from './demo-feature-search-input';", + "import { DemoFeatureStack } from './demo-feature-stack';", + "import { DemoFeatureTime } from './demo-feature-time';", + "import { DemoFeatureToast } from './demo-feature-toast';", + "export function DemoFeature() {", + "return (", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + ");", + "}", + ], + "isBinary": false, + "path": "./test/demo/demo-feature.tsx", + }, + }, + "path": "./test/demo", + }, + "index.ts": { + "content": [ + "export * from './demo/demo-feature';", + ], + "isBinary": false, + "path": "./test/index.ts", + }, + }, + "path": "./test", + }, + "tsconfig.base.json": { + "content": [ + "{", + ""compilerOptions": {", + ""paths": {}", + "}", + "}", + ], + "isBinary": false, + "path": "./tsconfig.base.json", + }, +} +`; diff --git a/packages/generators/src/generators/features/features-generator.ts b/packages/generators/src/generators/features/features-generator.ts index abb7295..12cf4eb 100644 --- a/packages/generators/src/generators/features/features-generator.ts +++ b/packages/generators/src/generators/features/features-generator.ts @@ -2,12 +2,12 @@ import { formatFiles, Tree } from '@nx/devkit' import { join } from 'path' import featureGenerator from '../feature/feature-generator' import { FeaturesGeneratorSchema } from './features-generator-schema' -import { templates } from './templates' +import { features } from './features' export async function featuresGenerator(tree: Tree, options: FeaturesGeneratorSchema) { const prefix = options.prefix ?? 'ui' const exports: string[] = [] - for (const type of templates) { + for (const type of features) { const target = type await featureGenerator(tree, { directory: join(options.directory, target), diff --git a/packages/generators/src/generators/features/templates.ts b/packages/generators/src/generators/features/features.ts similarity index 53% rename from packages/generators/src/generators/features/templates.ts rename to packages/generators/src/generators/features/features.ts index 8cef20e..ca33078 100644 --- a/packages/generators/src/generators/features/templates.ts +++ b/packages/generators/src/generators/features/features.ts @@ -1,3 +1,3 @@ import { FeatureGeneratorSchema } from '../feature/feature-generator-schema' -export const templates: FeatureGeneratorSchema['type'][] = ['demo'] +export const features: FeatureGeneratorSchema['type'][] = ['demo'] diff --git a/packages/generators/src/generators/features/files/src/index.ts.template b/packages/generators/src/generators/features/files/src/index.ts.template deleted file mode 100644 index 877d430..0000000 --- a/packages/generators/src/generators/features/files/src/index.ts.template +++ /dev/null @@ -1 +0,0 @@ -const variable = "<%= name %>"; \ No newline at end of file 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 0764f69..446e39b 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 @@ -35,7 +35,8 @@ exports[`theme generator should run successfully 1`] = ` ""@mantine/modals": "^7.2.2",", ""@mantine/notifications": "^7.2.2",", ""@tabler/icons-react": "^2.42.0",", - ""dayjs": "^1.11.10"", + ""dayjs": "^1.11.10",", + ""timeago-react": "^3.0.6"", "},", ""devDependencies": {", ""postcss": "^8.4.31",", @@ -75,12 +76,12 @@ exports[`theme generator should run successfully 1`] = ` "children": { "app.tsx": { "content": [ - "import { UiTheme } from './ui/ui-theme';", + "import { UiThemeProvider } from './ui/ui-theme';", "export function App() {", "return (", - "", + "", "
Welcome test-target
", - "
", + "", ");", "}", ], @@ -92,12 +93,16 @@ exports[`theme generator should run successfully 1`] = ` "index.ts": { "content": [ "export * from './ui-alert';", + "export * from './ui-card';", "export * from './ui-container';", "export * from './ui-copy';", "export * from './ui-debug';", "export * from './ui-group';", + "export * from './ui-search-input';", "export * from './ui-stack';", "export * from './ui-theme';", + "export * from './ui-time';", + "export * from './ui-toast';", ], "isBinary": false, "path": "./test-target/src/app/ui/index.ts", @@ -159,6 +164,74 @@ exports[`theme generator should run successfully 1`] = ` }, "path": "./test-target/src/app/ui/ui-alert", }, + "ui-card": { + "children": { + "index.ts": { + "content": [ + "export * from './ui-card';", + ], + "isBinary": false, + "path": "./test-target/src/app/ui/ui-card/index.ts", + }, + "ui-card-title.tsx": { + "content": [ + "import { Title, TitleProps } from '@mantine/core';", + "import { ReactNode } from 'react';", + "export function UiCardTitle({", + "children,", + "...props", + "}: TitleProps & {", + "children: ReactNode;", + "}) {", + "return (", + "", + "{children}", + "", + ");", + "}", + ], + "isBinary": false, + "path": "./test-target/src/app/ui/ui-card/ui-card-title.tsx", + }, + "ui-card.tsx": { + "content": [ + "import { Box, Card, CardProps, Skeleton } from '@mantine/core';", + "import { useUiBreakpoints } from '../ui-theme';", + "import { ReactNode } from 'react';", + "import { UiCardTitle } from './ui-card-title';", + "interface UiCardProps extends CardProps {", + "children: ReactNode;", + "loading?: boolean;", + "title?: ReactNode;", + "}", + "export function UiCard({ loading, title, ...props }: UiCardProps) {", + "const { isSm } = useUiBreakpoints();", + "return (", + "", + "{title ? (", + "", + "{typeof title === 'string' ? (", + "{title}", + ") : (", + "title", + ")}", + "", + ") : null}", + "{loading ? (", + "{props.children}", + ") : (", + "props.children", + ")}", + "", + ");", + "}", + ], + "isBinary": false, + "path": "./test-target/src/app/ui/ui-card/ui-card.tsx", + }, + }, + "path": "./test-target/src/app/ui/ui-card", + }, "ui-container": { "children": { "index.ts": { @@ -172,11 +245,23 @@ exports[`theme generator should run successfully 1`] = ` "content": [ "import { Container, ContainerProps } from '@mantine/core';", "import { ReactNode } from 'react';", + "import { useUiBreakpoints } from '../ui-theme';", "export interface UiContainerProps extends ContainerProps {", "children: ReactNode;", "}", "export function UiContainer({ children, ...props }: UiContainerProps) {", - "return {children};", + "const { isSm } = useUiBreakpoints();", + "return (", + "", + "{children}", + "", + ");", "}", ], "isBinary": false, @@ -360,6 +445,67 @@ exports[`theme generator should run successfully 1`] = ` }, "path": "./test-target/src/app/ui/ui-group", }, + "ui-search-input": { + "children": { + "index.ts": { + "content": [ + "export * from './ui-search-input';", + ], + "isBinary": false, + "path": "./test-target/src/app/ui/ui-search-input/index.ts", + }, + "ui-search-input.tsx": { + "content": [ + "import {", + "ActionIcon,", + "ActionIconProps,", + "rem,", + "TextInput,", + "TextInputProps,", + "useMantineTheme,", + "} from '@mantine/core';", + "import { IconArrowRight, IconSearch } from '@tabler/icons-react';", + "export function UiSearchInput({", + "...props", + "}: {", + "icon?: ActionIconProps;", + "text?: TextInputProps;", + "} = {}) {", + "const theme = useMantineTheme();", + "return (", + "", + "}", + "rightSection={", + "", + "", + "", + "}", + "radius="xl"", + "variant="filled"", + "size="md"", + "placeholder="Search"", + "{...props.text}", + "/>", + ");", + "}", + ], + "isBinary": false, + "path": "./test-target/src/app/ui/ui-search-input/ui-search-input.tsx", + }, + }, + "path": "./test-target/src/app/ui/ui-search-input", + }, "ui-stack": { "children": { "index.ts": { @@ -373,11 +519,17 @@ exports[`theme generator should run successfully 1`] = ` "content": [ "import { Stack, StackProps } from '@mantine/core';", "import { ReactNode } from 'react';", + "import { useUiBreakpoints } from '../ui-theme';", "export interface UiStackProps extends StackProps {", "children: ReactNode;", "}", "export function UiStack({ children, ...props }: UiStackProps) {", - "return {children};", + "const { isSm } = useUiBreakpoints();", + "return (", + "", + "{children}", + "", + ");", "}", ], "isBinary": false, @@ -390,53 +542,227 @@ exports[`theme generator should run successfully 1`] = ` "children": { "index.ts": { "content": [ - "export * from './ui-theme';", + "export * from './ui-color-scheme-provider';", + "export * from './ui-theme-provider';", + "export * from './use-ui-breakpoints';", ], "isBinary": false, "path": "./test-target/src/app/ui/ui-theme/index.ts", }, - "ui-theme.tsx": { + "ui-color-scheme-provider.tsx": { + "content": [ + "import {", + "MantineColorScheme,", + "useComputedColorScheme,", + "useMantineColorScheme,", + "} from '@mantine/core';", + "import { useHotkeys } from '@mantine/hooks';", + "import { createContext, ReactNode, useContext } from 'react';", + "export interface UiColorSchemeProviderContext {", + "colorScheme: MantineColorScheme;", + "toggleColorScheme: (colorScheme?: MantineColorScheme) => void;", + "}", + "const Context = createContext(", + "{} as UiColorSchemeProviderContext", + ");", + "export function UiColorSchemeProvider({ children }: { children: ReactNode }) {", + "const { toggleColorScheme } = useMantineColorScheme();", + "const colorScheme = useComputedColorScheme('dark', {", + "getInitialValueInEffect: true,", + "});", + "useHotkeys([['mod+J', () => toggleColorScheme()]]);", + "const value: UiColorSchemeProviderContext = {", + "colorScheme,", + "toggleColorScheme,", + "};", + "return {children};", + "}", + "export function useUiColorScheme() {", + "return useContext(Context);", + "}", + ], + "isBinary": false, + "path": "./test-target/src/app/ui/ui-theme/ui-color-scheme-provider.tsx", + }, + "ui-theme-provider.tsx": { "content": [ "import {", + "ColorSchemeScript,", "createTheme,", "DEFAULT_THEME,", "Loader,", "MantineProvider,", "} from '@mantine/core';", - "import { ReactNode, Suspense } from 'react';", - "import { Notifications } from '@mantine/notifications';", "import { ModalsProvider } from '@mantine/modals';", - "// Core styles", - "import '@mantine/core/styles.css';", - "// Package styles", - "import '@mantine/dates/styles.css';", - "import '@mantine/notifications/styles.css';", - "export interface UiThemeProps {", - "children: ReactNode;", - "}", + "import { Notifications } from '@mantine/notifications';", + "import {", + "createContext,", + "FunctionComponent,", + "ReactNode,", + "Suspense,", + "useContext,", + "} from 'react';", + "import { UiColorSchemeProvider } from './ui-color-scheme-provider';", + "// Import the mantine theme styles", + "import './ui-theme-styles';", "const theme = createTheme({", "colors: {", "brand: DEFAULT_THEME.colors.blue,", "},", "primaryColor: 'brand',", "});", - "export function UiTheme({ children }: UiThemeProps) {", + "export type UiThemeLink = FunctionComponent<{", + "children: ReactNode;", + "to: string;", + "target?: HTMLAnchorElement['target'];", + "rel?: HTMLAnchorElement['rel'];", + "}>;", + "export const defaultUiThemeLink: UiThemeLink = ({ children, ...props }) => (", + "", + "{children}", + "", + ");", + "export interface UiThemeProviderContext {", + "Link: UiThemeLink;", + "}", + "const Context = createContext(", + "{} as UiThemeProviderContext", + ");", + "export function UiThemeProvider({", + "children,", + "link,", + "}: {", + "children: ReactNode;", + "link?: UiThemeLink;", + "}) {", + "const value: UiThemeProviderContext = {", + "Link: link ?? defaultUiThemeLink,", + "};", "return (", - "", + "", + "", + "", + "", "", "", "}>{children}", "", + "", "", + "", ");", "}", + "export function useUiTheme() {", + "return useContext(Context);", + "}", ], "isBinary": false, - "path": "./test-target/src/app/ui/ui-theme/ui-theme.tsx", + "path": "./test-target/src/app/ui/ui-theme/ui-theme-provider.tsx", + }, + "ui-theme-styles.ts": { + "content": [ + "// Core styles", + "import '@mantine/core/styles.css';", + "// Package styles", + "import '@mantine/dates/styles.css';", + "import '@mantine/notifications/styles.css';", + ], + "isBinary": false, + "path": "./test-target/src/app/ui/ui-theme/ui-theme-styles.ts", }, }, "path": "./test-target/src/app/ui/ui-theme", }, + "ui-time": { + "children": { + "index.ts": { + "content": [ + "export * from './ui-time';", + ], + "isBinary": false, + "path": "./test-target/src/app/ui/ui-time/index.ts", + }, + "ui-time.tsx": { + "content": [ + "import { Text, TextProps } from '@mantine/core';", + "import TimeAgo from 'timeago-react';", + "export interface UiTimeProps extends TextProps {", + "date: Date;", + "prefix?: string;", + "suffix?: string;", + "}", + "export function UiTime({ date, prefix, suffix, ...props }: UiTimeProps) {", + "return (", + "", + "{prefix}", + "", + "{suffix}", + "", + ");", + "}", + ], + "isBinary": false, + "path": "./test-target/src/app/ui/ui-time/ui-time.tsx", + }, + }, + "path": "./test-target/src/app/ui/ui-time", + }, + "ui-toast": { + "children": { + "index.ts": { + "content": [ + "export * from './ui-toast';", + ], + "isBinary": false, + "path": "./test-target/src/app/ui/ui-toast/index.ts", + }, + "ui-toast.tsx": { + "content": [ + "import { NotificationData, notifications } from '@mantine/notifications';", + "export type ToastProps = string | NotificationData;", + "export function toastSuccess(notification: ToastProps) {", + "notification =", + "typeof notification === 'string' ? { message: notification } : notification;", + "notifications.show({", + "color: notification?.color ?? 'green',", + "title: notification?.title ?? 'Success',", + "message: notification?.message,", + "});", + "}", + "export function toastError(notification: ToastProps) {", + "notification =", + "typeof notification === 'string' ? { message: notification } : notification;", + "notifications.show({", + "color: notification?.color ?? 'red',", + "title: notification?.title ?? 'Error',", + "message: notification?.message,", + "});", + "}", + "export function toastWarning(notification: ToastProps) {", + "notification =", + "typeof notification === 'string' ? { message: notification } : notification;", + "notifications.show({", + "color: notification?.color ?? 'yellow',", + "title: notification?.title ?? 'Warning',", + "message: notification?.message,", + "});", + "}", + "export function toastInfo(notification: ToastProps) {", + "notification =", + "typeof notification === 'string' ? { message: notification } : notification;", + "notifications.show({", + "color: notification?.color ?? 'cyan',", + "title: notification?.title ?? 'Info',", + "message: notification?.message,", + "});", + "}", + ], + "isBinary": false, + "path": "./test-target/src/app/ui/ui-toast/ui-toast.tsx", + }, + }, + "path": "./test-target/src/app/ui/ui-toast", + }, }, "path": "./test-target/src/app/ui", }, diff --git a/packages/generators/src/generators/theme/files/src/app/app.tsx.template b/packages/generators/src/generators/theme/files/src/app/app.tsx.template index 8f5dcd7..48d95b6 100644 --- a/packages/generators/src/generators/theme/files/src/app/app.tsx.template +++ b/packages/generators/src/generators/theme/files/src/app/app.tsx.template @@ -1,9 +1,9 @@ -import { UiTheme } from './ui/ui-theme' +import { UiThemeProvider } from './ui/ui-theme' export function App() { return ( - +
Welcome <%= directory %>
-
+ ) }