Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 62 additions & 0 deletions packages/js/services/wp/use-display-feedback.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import { useGlobalNotices } from '@wpsocio/ui/wp/global-notices';
import { FORM_ERROR } from '@wpsocio/utilities/constants.js';
import { getErrorStrings } from '@wpsocio/utilities/misc.js';
import type { AnyObject } from '@wpsocio/utilities/types.js';
import { useCallback, useMemo } from 'react';

interface DisplayFeedback {
clearNotices: VoidFunction;
displayValidationErrors: (errors: AnyObject, error?: string) => void;
displaySubmitErrors: (errors: AnyObject, submitError?: string) => void;
}

type DF = DisplayFeedback;

export const useDisplayFeedback = (): DF => {
const { createErrorNotice, removeAllNotices } = useGlobalNotices();

const displayErrors = useCallback(
(errors: AnyObject) => {
const errorStrings = getErrorStrings(errors);
for (const error of errorStrings) {
createErrorNotice(error);
}
},
[createErrorNotice],
);

const clearNotices = useCallback(() => {
removeAllNotices('snackbar');
}, [removeAllNotices]);

const displaySubmitErrors = useCallback<DF['displaySubmitErrors']>(
({ [FORM_ERROR]: formError, ...errors }, submitError) => {
// biome-ignore lint/suspicious/noConsoleLog: <explanation>
console.log({ errors, submitError, formError });
clearNotices();

if (submitError || formError) {
createErrorNotice(submitError || formError);
}
displayErrors(errors);
},
[displayErrors, createErrorNotice, clearNotices],
);

const displayValidationErrors = useCallback<DF['displayValidationErrors']>(
(errors) => {
clearNotices();
displayErrors(errors);
},
[displayErrors, clearNotices],
);

return useMemo(
() => ({
clearNotices,
displaySubmitErrors,
displayValidationErrors,
}),
[clearNotices, displaySubmitErrors, displayValidationErrors],
);
};
17 changes: 17 additions & 0 deletions packages/js/shared-ui/components/wp/admin-container/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { Flex, __experimentalView as View } from '@wordpress/components';
import clsx from 'clsx';
import styles from './styles.module.scss';

export type WpAdminContainerProps = React.ComponentProps<typeof Flex>;

export function WpAdminContainer({
children,
className,
...props
}: WpAdminContainerProps) {
return (
<Flex className={clsx(styles.container, className)} {...props}>
<View className={styles.view}>{children}</View>
</Flex>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
@use '@wpsocio/ui/wp-base-styles.scss' as wp;

:global(#wpcontent) {
padding-inline: 0 !important;
}
:global(#wpwrap) {
background: #fff;
}

.container {
max-width: 64rem;
padding: 0.75rem;

&:global(.components-flex) {
width: auto;
}

@include wp.break-small {
padding: 1.5rem;
}

.view {
width: 100%;
}
}
28 changes: 28 additions & 0 deletions packages/js/shared-ui/components/wp/main-menu/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { MenuGroup, MenuItem } from '@wordpress/components';
import { __ } from '@wpsocio/i18n';
import { chevronRight } from '@wpsocio/ui/icons/wp';
import styles from './styles.module.scss';

export type MenuItemProps = React.ComponentProps<typeof MenuItem>;

export type MainMenuProps = {
items: MenuItemProps[];
};

export function MainMenu({ items }: MainMenuProps) {
return (
<MenuGroup className={styles.container}>
{items.map((item, index) => (
<MenuItem
key={item.id || index}
info={__('Manage your bot tokens.')}
icon={item.icon || chevronRight}
iconPosition="right"
{...item}
>
{item.children || item.label || item.title}
</MenuItem>
))}
</MenuGroup>
);
}
26 changes: 26 additions & 0 deletions packages/js/shared-ui/components/wp/main-menu/styles.module.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
@use '@wpsocio/ui/wp-base-styles.scss' as wp;

.container {
div[role="group"] {
display: flex;
flex-direction: column;
gap: 1rem
}

:global(.components-menu-item__button) {
height: auto;
padding: 0;
}

:global(.components-menu-item__item) {
@include wp.body-x-large();
}

:global(.components-menu-item__info) {
@include wp.body-large();
}

:global(.components-menu-item__info) {
text-align: start;
}
}
50 changes: 50 additions & 0 deletions packages/js/shared-ui/components/wp/plugin-header/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import {
__experimentalDivider as Divider,
Flex,
FlexBlock,
__experimentalView as View,
} from '@wordpress/components';
import { __experimentalHeading as Heading } from '@wordpress/components';
import styles from './styles.module.scss';

export interface PluginHeaderProps {
title: string;
description?: string;
version?: string;
logoUrl?: string;
}

export const PluginHeader: React.FC<PluginHeaderProps> = ({
logoUrl,
title,
version,
description,
}) => {
return (
<Flex className={styles.container} gap={4} direction="column">
<FlexBlock>
<Flex gap={2} justify="start">
{logoUrl && (
<div className={styles.logo}>
<img alt={title} src={logoUrl} />
</div>
)}
<Heading level={1} className={styles.title}>
{title}
{version ? (
<View className={styles.version} as="span">
&nbsp;v{version}
</View>
) : null}
</Heading>
</Flex>
</FlexBlock>
{description ? (
<FlexBlock className={styles.description} as="span">
{description}
</FlexBlock>
) : null}
<Divider />
</Flex>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
@use '@wpsocio/ui/wp-base-styles.scss' as wp;

.container {
.logo {
height: 2rem;
width: 2rem;

img {
height: 100%;
width: 100%;
object-fit: contain;
}
}

.title {
@include wp.heading-x-large();
font-size: 1.5rem;
}

.version {
@include wp.body-medium();
color: wp.$gray-700;
font-style: italic;
}

.description {
@include wp.body-large();
color: wp.$gray-700;
}

hr {
color: wp.$gray-200;
}
}
59 changes: 59 additions & 0 deletions packages/js/shared-ui/components/wp/plugin-sub-page/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import {
Button,
Flex,
FlexBlock,
FlexItem,
__experimentalHeading as Heading,
__experimentalView as View,
} from '@wordpress/components';
import { __, isRTL } from '@wpsocio/i18n';
import { chevronLeft, chevronRight } from '@wpsocio/ui/icons/wp';
import styles from './styles.module.scss';

export interface PluginSubPageProps {
title: string;
description?: string;
children?: React.ReactNode;
onClickBack?: VoidFunction;
backButtonLabel?: string;
headerAction?: React.ReactNode;
}

export const PluginSubPage: React.FC<PluginSubPageProps> = ({
title,
description,
children,
onClickBack,
headerAction,
backButtonLabel,
}) => {
return (
<View className={styles.container}>
<Flex className={styles.header} align="start" gap={4}>
<FlexBlock>
<Flex justify="start" gap={4} wrap>
{onClickBack ? (
<View>
<Button
onClick={onClickBack}
label={__('Go back')}
icon={isRTL() ? chevronRight : chevronLeft}
>
{backButtonLabel}
</Button>
</View>
) : null}
<View>
<Heading level={2} className={styles.title}>
{title}
</Heading>
<View className={styles.description}>{description}</View>
</View>
</Flex>
</FlexBlock>
<FlexItem>{headerAction}</FlexItem>
</Flex>
<View className={styles.content}>{children}</View>
</View>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
@use '@wpsocio/ui/wp-base-styles.scss' as wp;

.container {
padding-block: 1rem;

.header {
// padding to account for back button icon padding
padding-inline-end: 1rem;
width: auto;
}

.title {
@include wp.heading-x-large();
}

.description {
@include wp.body-large();
color: wp.$gray-700;
}

.content {
padding: 2rem 1rem;
}
}
4 changes: 4 additions & 0 deletions packages/js/shared-ui/definitions.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
declare module '*.module.scss' {
const classes: { [key: string]: string };
export default classes;
}
18 changes: 18 additions & 0 deletions packages/js/shared-ui/form/wp/form-field.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { useFormContext } from '@wpsocio/form';
import {
type ControllerProps,
type FieldPath,
type FieldValues,
FormField as FormFieldUI,
} from '@wpsocio/ui/wp/form';

export const FormField = <
TFieldValues extends FieldValues = FieldValues,
TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,
>({
...props
}: ControllerProps<TFieldValues, TName>) => {
const { control } = useFormContext<TFieldValues>();

return <FormFieldUI control={control} {...props} />;
};
25 changes: 25 additions & 0 deletions packages/js/shared-ui/form/wp/form-item/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { FormItem as FormItemUI, FormMessage } from '@wpsocio/ui/wp/form';
import clsx from 'clsx';
import styles from './styles.module.scss';

export interface FormItemProps extends React.HTMLAttributes<HTMLDivElement> {
afterMessage?: React.ReactNode;
control?: React.ReactNode;
}

export function FormItem({
afterMessage,
control,
children,
...props
}: FormItemProps) {
return (
<FormItemUI {...props} className={clsx(styles.container, props.className)}>
<div>{control || children}</div>
<div className={clsx(styles['message-wrapper'])}>
<FormMessage />
</div>
{afterMessage}
</FormItemUI>
);
}
8 changes: 8 additions & 0 deletions packages/js/shared-ui/form/wp/form-item/styles.module.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
@use '@wpsocio/ui/wp-base-styles.scss' as wp;

.container {

.message-wrapper {
margin-top: 0.5rem;
}
}
Loading
Loading