Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add WP Telegram Comments plugin #4

Merged
merged 6 commits into from
Dec 15, 2023
Merged
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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ vendor/
/plugins/*/
# Except for the ones in this repo
!/plugins/wp-test-plugin/
!/plugins/wptelegram-comments/

# Build tools/IDEs
.rollup.cache/
Expand Down
2 changes: 1 addition & 1 deletion .vscode/extensions.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@
"bmewburn.vscode-intelephense-client",
"biomejs.biome"
]
}
}
2 changes: 1 addition & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,4 @@
"quickfix.biome": "explicit",
"source.organizeImports.biome": "explicit"
}
}
}
81 changes: 81 additions & 0 deletions packages/js/adapters/ColorPicker/ColorInputPicker.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import {
Button,
ButtonProps,
InputAddonProps,
InputProps,
Popover,
PopoverBody,
PopoverContent,
PopoverTrigger,
} from '@chakra-ui/react';
import { useCallback, useMemo, useState } from 'react';
import { TextInput } from '../Input';
import { useDebouncedCallback } from '../hooks';
import { ColorPicker, ColorPickerProps } from './ColorPicker';

const addonBeforeProps: InputAddonProps = { px: '0px', py: '0px' };

export const ColorInputPicker: React.FC<ColorPickerProps> = ({
value,
onChange,
...props
}) => {
const [currentColor, setCurrentColor] = useState(value || '');

const buttonProps = useMemo<ButtonProps>(
() => ({ backgroundColor: currentColor }),
[currentColor],
);

const onChangeInput = useCallback<NonNullable<InputProps['onChange']>>(
(event) => {
const newColor = event.target.value;

onChange?.(newColor);
setCurrentColor(newColor);
},
[onChange],
);

const onChangeColor = useCallback(
(newColor: string) => {
onChange?.(newColor);
setCurrentColor(newColor);
},
[onChange],
);

const debouncedOnChangeColor = useDebouncedCallback(onChangeColor, 200);

return (
<Popover placement="bottom">
<TextInput
addonBeforeProps={addonBeforeProps}
addonBefore={
<PopoverTrigger>
<Button
variant="ghost"
borderEndRadius="0px"
height="100%"
{...buttonProps}
_hover={buttonProps}
_active={buttonProps}
/>
</PopoverTrigger>
}
value={currentColor}
maxWidth="100px"
onChange={onChangeInput}
/>
<PopoverContent maxW="max-content">
<PopoverBody padding="0px">
<ColorPicker
value={currentColor}
onChange={debouncedOnChangeColor}
{...props}
/>
</PopoverBody>
</PopoverContent>
</Popover>
);
};
16 changes: 16 additions & 0 deletions packages/js/adapters/ColorPicker/ColorPicker.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { HexColorPicker } from 'react-colorful';

type HexColorPickerProps = React.ComponentProps<typeof HexColorPicker>;

export interface ColorPickerProps
extends Partial<Omit<HexColorPickerProps, 'color'>> {
value?: string;
ref?: unknown;
}

export const ColorPicker: React.FC<ColorPickerProps> = ({
value,
...props
}) => {
return <HexColorPicker color={value} {...props} />;
};
4 changes: 4 additions & 0 deletions packages/js/adapters/ColorPicker/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export * from './ColorPicker';
export * from './ColorInputPicker';

export { HexColorInput as ColorInput } from 'react-colorful';
30 changes: 30 additions & 0 deletions packages/js/adapters/Input/NumberInput.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { forwardRef } from 'react';
import {
NumberDecrementStepper,
NumberIncrementStepper,
NumberInput as ChakraNumberInput,
NumberInputProps as ChakraNumberInputProps,
NumberInputField,
NumberInputStepper,
} from '@chakra-ui/react';

export interface NumberInputProps
extends Omit<ChakraNumberInputProps, 'onChange'> {
// fix the mess created by react-hook-form and chakra
onChange?: React.ChangeEventHandler<HTMLInputElement>;
onChangeValue?: (valueAsString: string, valueAsNumber: number) => void;
}

export const NumberInput = forwardRef<HTMLInputElement, NumberInputProps>(
({ onChange, onChangeValue, ...props }, ref) => {
return (
<ChakraNumberInput {...props} onChange={onChangeValue}>
<NumberInputField onChange={onChange} ref={ref} />
<NumberInputStepper>
<NumberIncrementStepper />
<NumberDecrementStepper />
</NumberInputStepper>
</ChakraNumberInput>
);
},
);
44 changes: 44 additions & 0 deletions packages/js/adapters/Input/TextInput.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import {
Input,
InputAddonProps,
InputGroup,
InputGroupProps,
InputLeftAddon,
InputProps,
InputRightAddon,
} from '@chakra-ui/react';
import { forwardRef } from 'react';

export interface TextInputProps extends InputProps {
addonBefore?: React.ReactNode;
addonAfter?: React.ReactNode;
addonBeforeProps?: InputAddonProps;
addonAfterProps?: InputAddonProps;
wrapperProps?: InputGroupProps;
}

export const TextInput = forwardRef<HTMLInputElement, TextInputProps>(
(
{
addonBefore,
addonAfter,
addonBeforeProps,
addonAfterProps,
wrapperProps,
...rest
},
ref,
) => {
return (
<InputGroup {...wrapperProps}>
{addonBefore && (
<InputLeftAddon {...addonBeforeProps}>{addonBefore}</InputLeftAddon>
)}
<Input {...rest} ref={ref} />
{addonAfter && (
<InputRightAddon {...addonAfterProps}>{addonAfter}</InputRightAddon>
)}
</InputGroup>
);
},
);
2 changes: 2 additions & 0 deletions packages/js/adapters/Input/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from './TextInput';
export * from './NumberInput';
11 changes: 11 additions & 0 deletions packages/js/adapters/Link/Link.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { forwardRef } from 'react';
import {
Link as ChakraLink,
LinkProps as ChakraLinkProps,
} from '@chakra-ui/react';

export const Link = forwardRef<HTMLAnchorElement, ChakraLinkProps>(
(props, ref) => {
return <ChakraLink ref={ref} color="#0073aa" isExternal {...props} />;
},
);
1 change: 1 addition & 0 deletions packages/js/adapters/Link/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './Link';
92 changes: 92 additions & 0 deletions packages/js/adapters/Modal/Modal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
import {
Modal as ChakraModal,
ModalBody,
ModalCloseButton,
ModalContent,
ModalFooter,
ModalHeader,
ModalOverlay,
Button,
ButtonProps,
} from '@chakra-ui/react';

export interface ModalProps extends React.ComponentProps<typeof ChakraModal> {
bodyClassName?: string;
cancelButtonProps?: ButtonProps;
className?: string;
closeButton?: React.ReactNode;
content?: React.ReactNode;
destroyOnClose?: boolean;
footerContent?: React.ReactNode;
isClosable?: boolean;
submitButtonProps?: ButtonProps;
title?: React.ReactNode;
withBorder?: boolean;
}

export const Modal: React.FC<ModalProps> = ({
bodyClassName,
cancelButtonProps,
children,
className,
closeButton,
content,
destroyOnClose = true,
footerContent,
isClosable = true,
isOpen,
submitButtonProps,
title,
...props
}) => {
if (destroyOnClose && !isOpen) {
return null;
}

const cancelButton = cancelButtonProps && (
<Button mr={3} {...cancelButtonProps} />
);
const submitButton = submitButtonProps && (
<Button variantColor="blue" {...submitButtonProps} />
);
const defaultFooterNode = (cancelButton || submitButton) && (
<>
{cancelButton}
{submitButton}
</>
);

const footerNode = footerContent ? (
<>
{cancelButton && cancelButton}
{footerContent}
</>
) : (
defaultFooterNode
);

return (
<ChakraModal
closeOnOverlayClick={isClosable}
isCentered
isOpen={isOpen}
{...props}
>
<ModalOverlay>
<ModalContent role="alertdialog" className={className}>
<ModalHeader>{title}</ModalHeader>

{closeButton ? (
closeButton
) : (
<ModalCloseButton isDisabled={!isClosable} />
)}

<ModalBody className={bodyClassName}>{children || content}</ModalBody>

{footerNode && <ModalFooter>{footerNode}</ModalFooter>}
</ModalContent>
</ModalOverlay>
</ChakraModal>
);
};
1 change: 1 addition & 0 deletions packages/js/adapters/Modal/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './Modal';
53 changes: 53 additions & 0 deletions packages/js/adapters/Multicheck/MultiCheck.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import {
Checkbox,
CheckboxGroup,
CheckboxGroupProps,
Stack,
StackProps,
} from '@chakra-ui/react';
import { useMemo } from 'react';

import type { OptionsType } from '../types';

export interface MultiCheckProps extends CheckboxGroupProps {
name?: string;
options?: OptionsType;
isInline?: boolean;
ref?: unknown;
}

const dir: StackProps['direction'] = ['column', 'row'];

export const MultiCheck: React.FC<MultiCheckProps> = ({
children,
options,
isInline,
...restProps
}) => {
const childNodes = useMemo(() => {
return options?.map(({ label, value, ...rest }, index) => {
return (
<Checkbox value={value} {...rest} key={`${value}${index}`}>
{label}
</Checkbox>
);
});
}, [options]);

// make sure the value is array
const value = useMemo(
() =>
restProps.value === undefined ? restProps.value : restProps.value || [],
[restProps.value],
);

const direction = isInline ? dir : 'column';

return (
<CheckboxGroup {...restProps} value={value}>
<Stack direction={direction} spacing="0.5em">
{childNodes || children}
</Stack>
</CheckboxGroup>
);
};
1 change: 1 addition & 0 deletions packages/js/adapters/Multicheck/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './MultiCheck';
Loading