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

Ability to customize table-background-color #4047

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
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
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ export const TableCellElement = withRef<
style={
{
'--cellBackground': element.background,
backgroundColor: element.backgroundColor,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use above line instead

maxWidth: width || 240,
minWidth: width || 120,
...style,
Expand Down
78 changes: 76 additions & 2 deletions apps/www/src/registry/default/plate-ui/table-element.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
'use client';

import React from 'react';
import React, { useCallback } from 'react';

import type * as DropdownMenuPrimitive from '@radix-ui/react-dropdown-menu';
import type { TTableElement } from '@udecode/plate-table';

import { PopoverAnchor } from '@radix-ui/react-popover';
import { cn, withRef } from '@udecode/cn';
Expand All @@ -18,30 +17,42 @@ import {
withHOC,
} from '@udecode/plate/react';
import { BlockSelectionPlugin } from '@udecode/plate-selection/react';
import {
type TTableElement,
setCellBackgroundColor,
} from '@udecode/plate-table';
import {
TablePlugin,
TableProvider,
useColorDropdownMenu,
useColorDropdownMenuState,
useTableBordersDropdownMenuContentState,
useTableElement,
useTableMergeState,
useTableStore,
} from '@udecode/plate-table/react';
import {
ArrowDown,
ArrowLeft,
ArrowRight,
ArrowUp,
CombineIcon,
EraserIcon,
Grid2X2Icon,
PaintBucketIcon,
SquareSplitHorizontalIcon,
Trash2Icon,
XIcon,
} from 'lucide-react';

import { DEFAULT_COLORS, DEFAULT_CUSTOM_COLORS } from './color-constants';
import { ColorPicker } from './color-picker';
import {
DropdownMenu,
DropdownMenuCheckboxItem,
DropdownMenuContent,
DropdownMenuGroup,
DropdownMenuItem,
DropdownMenuPortal,
DropdownMenuTrigger,
} from './dropdown-menu';
Expand All @@ -56,6 +67,7 @@ import {
BorderTop,
} from './table-icons';
import { Toolbar, ToolbarButton, ToolbarGroup } from './toolbar';
import { ColorDropdownMenuItems } from './color-dropdown-menu-items';

export const TableElement = withHOC(
TableProvider,
Expand Down Expand Up @@ -134,6 +146,9 @@ export const TableFloatingToolbar = withRef<typeof PopoverContent>(
contentEditable={false}
>
<ToolbarGroup>
<ColorDropdownMenu tooltip="Background color">
<PaintBucketIcon />
</ColorDropdownMenu>
{canMerge && (
<ToolbarButton
onClick={() => tf.table.merge()}
Expand Down Expand Up @@ -321,3 +336,62 @@ export const TableBordersDropdownMenuContent = withRef<
</DropdownMenuContent>
);
});

type ColorDropdownMenuProps = {
children: React.ReactNode;
tooltip: string;
};

export function ColorDropdownMenu({
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
export function ColorDropdownMenu({
function ColorDropdownMenu({

children,
tooltip,
}: ColorDropdownMenuProps) {
const state = useColorDropdownMenuState({
colors: DEFAULT_COLORS,
customColors: DEFAULT_CUSTOM_COLORS,
});

const { buttonProps, menuProps } = useColorDropdownMenu(state);

const editor = useEditorRef();
const selectedCells = useTableStore().get.selectedCells();

const onUpdateColor = useCallback(
(color: string) => {
state.onToggle();
setCellBackgroundColor(editor, { color, selectedCells });
},
[state, selectedCells, editor]
);

const onClearColor = useCallback(() => {
state.onToggle();
setCellBackgroundColor(editor, { color: 'transparent', selectedCells });
}, [state, selectedCells, editor]);

return (
<DropdownMenu modal={false} {...menuProps}>
<DropdownMenuTrigger asChild>
<ToolbarButton tooltip={tooltip} {...buttonProps}>
{children}
</ToolbarButton>
</DropdownMenuTrigger>

<DropdownMenuContent align="start">
<DropdownMenuGroup label="Colors">
<ColorDropdownMenuItems
className="px-2"
colors={state.colors}
updateColor={onUpdateColor}
/>
</DropdownMenuGroup>
<DropdownMenuGroup>
<DropdownMenuItem className="p-2" onClick={onClearColor}>
<EraserIcon />
<span>Clear</span>
</DropdownMenuItem>
</DropdownMenuGroup>
</DropdownMenuContent>
</DropdownMenu>
);
}
1 change: 1 addition & 0 deletions packages/table/src/lib/background-color/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './setCellBackgroundColor';
55 changes: 55 additions & 0 deletions packages/table/src/lib/background-color/setCellBackgroundColor.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import type { SlateEditor, TElement } from '@udecode/plate';

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

import { getCellTypes } from '../utils/index';

export const setCellBackgroundColor = (
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To move to transforms folder

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
export const setCellBackgroundColor = (
export const setCellBackground = (

editor: SlateEditor,
options: {
color: string;
selectedCells: TElement[] | null;
}
) => {
const { color, selectedCells } = options;

const hasSelectedCells = selectedCells && selectedCells.length > 0;

if (hasSelectedCells) {
selectedCells.forEach((cell) =>
setSingleCellBackgroundColor(editor, cell, color)
);

return;
}

const cellPath = editor.api.node<TTableCellElement>({
match: { type: getCellTypes(editor) },
})?.[1];

if (cellPath) {
editor.tf.setNodes<TTableCellElement>(
{ backgroundColor: color },
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
{ backgroundColor: color },
{ background: color },

{
at: cellPath,
}
);
}
};

const setSingleCellBackgroundColor = (
editor: SlateEditor,
cell: TTableCellElement,
color: string
) => {
const cellPath = editor.api.findPath(cell);

if (cellPath) {
editor.tf.setNodes<TTableCellElement>(
{ backgroundColor: color },
{
at: cellPath,
}
);
}
};
5 changes: 2 additions & 3 deletions packages/table/src/lib/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
/**
* @file Automatically generated by barrelsby.
*/
/** @file Automatically generated by barrelsby. */

export * from './BaseTablePlugin';
export * from './constants';
Expand All @@ -20,3 +18,4 @@ export * from './merge/index';
export * from './queries/index';
export * from './transforms/index';
export * from './utils/index';
export * from './background-color/index';
10 changes: 10 additions & 0 deletions packages/table/src/lib/queries/getCellBackgroundColor.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import type { TTableCellElement } from '../types';

/**
* Returns the backgroundColor attribute of the table cell element.
*
* @default '' if undefined
*/
export const getCellBackgroundColor = (cellElem: TTableCellElement) => {
return cellElem.backgroundColor || '';
};
Comment on lines +8 to +10
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Redundant, let's remove it

1 change: 1 addition & 0 deletions packages/table/src/lib/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ export interface TTableCellElement extends TElement {
top?: BorderStyle;
};
background?: string;
backgroundColor?: string;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use background instead

colSpan?: number;
rowSpan?: number;
size?: number;
Expand Down
5 changes: 2 additions & 3 deletions packages/table/src/react/hooks/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
/**
* @file Automatically generated by barrelsby.
*/
/** @file Automatically generated by barrelsby. */

export * from './useCellIndices';
export * from './useTableMergeState';
export * from './useColorDropdownMenu';
40 changes: 40 additions & 0 deletions packages/table/src/react/hooks/useColorDropdownMenu.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import React from 'react';

export const useColorDropdownMenuState = ({
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We stop packaging such hooks going forward, this can be moved into the component

colors,
customColors,
}: {
colors: { isBrightColor: boolean; name: string; value: string }[];
customColors: { isBrightColor: boolean; name: string; value: string }[];
closeOnSelect?: boolean;
}) => {
const [open, setOpen] = React.useState(false);
const onToggle = React.useCallback(
(value = !open) => {
setOpen(value);
},
[open, setOpen]
);

return {
colors,
customColors,
open,
onToggle,
};
};

export const useColorDropdownMenu = ({
open,
onToggle,
}: ReturnType<typeof useColorDropdownMenuState>) => {
return {
buttonProps: {
pressed: open,
},
menuProps: {
open,
onOpenChange: onToggle,
},
};
};