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}
+
+ <%= prefix.className %>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}
-
- <%= prefix.className %>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 (",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ ");",
+ "}",
+ ],
+ "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() {
+
<%= prefix.className %>Stack>
<%= prefix.className %>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 (",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ ");",
+ "}",
+ ],
+ "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 %>
-
+
)
}