Skip to content

Commit

Permalink
feat: allow icon customization
Browse files Browse the repository at this point in the history
  • Loading branch information
petyosi committed Nov 18, 2023
1 parent 48e65dd commit fc131a2
Show file tree
Hide file tree
Showing 36 changed files with 389 additions and 194 deletions.
78 changes: 59 additions & 19 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,7 @@
"vite": "^4.3.9",
"vite-plugin-dts": "^2.3.0",
"vite-plugin-svgr": "^3.2.0",
"vite-tsconfig-paths": "^4.2.1",
"vitest": "^0.31.1"
},
"publishConfig": {
Expand Down
14 changes: 13 additions & 1 deletion src/MDXEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import LexicalErrorBoundary from '@lexical/react/LexicalErrorBoundary.js'
import classNames from 'classnames'
import { ToMarkdownOptions } from './exportMarkdownFromLexical'
import { noop } from './utils/fp'
import { IconKey } from './plugins/core/Icon'

const LexicalProvider: React.FC<{ children: JSX.Element | string | (JSX.Element | string)[] }> = ({ children }) => {
const [initialRootEditorState, nodes, readOnly] = corePluginHooks.useEmitterValues(
Expand Down Expand Up @@ -118,12 +119,22 @@ export interface MDXEditorProps {
* Note: Don't use this mode to render content for consumption - render the markdown using a library of your choice instead.
*/
readOnly?: boolean
/**
* Use this prop to customize the icons used across the editor. Pass a function that returns an icon (JSX) for a given icon key.
*/
iconComponentFor?: (name: IconKey) => JSX.Element
}

const DEFAULT_MARKDOWN_OPTIONS: ToMarkdownOptions = {
listItemIndent: 'one'
}

const DefaultIcon = React.lazy(() => import('./plugins/core/Icon'))

const defaultIconComponentFor = (name: IconKey) => {
return <DefaultIcon name={name} />
}

/**
* The interface for the {@link MDXEditor} object reference.
*
Expand Down Expand Up @@ -233,7 +244,8 @@ export const MDXEditor = React.forwardRef<MDXEditorMethods, MDXEditorProps>((pro
toMarkdownOptions: props.toMarkdownOptions ?? DEFAULT_MARKDOWN_OPTIONS,
autoFocus: props.autoFocus ?? false,
placeholder: props.placeholder ?? '',
readOnly: Boolean(props.readOnly)
readOnly: Boolean(props.readOnly),
iconComponentFor: props.iconComponentFor ?? defaultIconComponentFor
}),
...(props.plugins || [])
]}
Expand Down
File renamed without changes
14 changes: 7 additions & 7 deletions src/icons/arrow_drop_down.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
8 changes: 0 additions & 8 deletions src/icons/arrow_right.svg

This file was deleted.

File renamed without changes
File renamed without changes
143 changes: 143 additions & 0 deletions src/plugins/core/Icon.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
import React from 'react'

import add_column from '@/icons/add_column.svg'
import add_photo from '@/icons/add_photo.svg'
import add_row from '@/icons/add_row.svg'
import arrow_drop_down from '@/icons/arrow_drop_down.svg'
import check from '@/icons/check.svg'
import check_small from '@/icons/check_small.svg'
import close from '@/icons/close.svg'
import code from '@/icons/code.svg'
import content_copy from '@/icons/content_copy.svg'
import delete_big from '@/icons/delete_big.svg'
import delete_small from '@/icons/delete_small.svg'
import sandpack from '@/icons/sandpack.svg'
import difference from '@/icons/difference.svg'
import edit from '@/icons/edit.svg'
import admonition from '@/icons/admonition.svg'
import extension from '@/icons/extension.svg'
import format_align_center from '@/icons/format_align_center.svg'
import format_align_left from '@/icons/format_align_left.svg'
import format_align_right from '@/icons/format_align_right.svg'
import format_bold from '@/icons/format_bold.svg'
import format_italic from '@/icons/format_italic.svg'
import format_list_bulleted from '@/icons/format_list_bulleted.svg'
import format_list_checked from '@/icons/format_list_checked.svg'
import format_list_numbered from '@/icons/format_list_numbered.svg'
import format_underlined from '@/icons/format_underlined.svg'
import frame_source from '@/icons/frame_source.svg'
import frontmatter from '@/icons/frontmatter.svg'
import horizontal_rule from '@/icons/horizontal_rule.svg'
import insert_col_left from '@/icons/insert_col_left.svg'
import insert_col_right from '@/icons/insert_col_right.svg'
import insert_row_above from '@/icons/insert_row_above.svg'
import insert_row_below from '@/icons/insert_row_below.svg'
import link from '@/icons/link.svg'
import link_off from '@/icons/link_off.svg'
import markdown from '@/icons/markdown.svg'
import more_horiz from '@/icons/more_horiz.svg'
import more_vert from '@/icons/more_vert.svg'
import open_in_new from '@/icons/open_in_new.svg'
import redo from '@/icons/redo.svg'
import rich_text from '@/icons/rich_text.svg'
import settings from '@/icons/settings.svg'
import table from '@/icons/table.svg'
import undo from '@/icons/undo.svg'

export type IconKey =
| 'add_column'
| 'add_photo'
| 'add_row'
| 'arrow_drop_down'
| 'check'
| 'check_small'
| 'close'
| 'code'
| 'content_copy'
| 'delete_big'
| 'delete_small'
| 'sandpack'
| 'difference'
| 'edit'
| 'admonition'
| 'extension'
| 'format_align_center'
| 'format_align_left'
| 'format_align_right'
| 'format_bold'
| 'format_italic'
| 'format_list_bulleted'
| 'format_list_checked'
| 'format_list_numbered'
| 'format_underlined'
| 'frame_source'
| 'frontmatter'
| 'horizontal_rule'
| 'insert_col_left'
| 'insert_col_right'
| 'insert_row_above'
| 'insert_row_below'
| 'link'
| 'link_off'
| 'markdown'
| 'more_horiz'
| 'more_vert'
| 'open_in_new'
| 'redo'
| 'rich_text'
| 'settings'
| 'table'
| 'undo'

const IconMap: Record<IconKey, React.FC> = {
add_column,
add_photo,
add_row,
arrow_drop_down,
check,
check_small,
close,
code,
content_copy,
delete_big,
delete_small,
sandpack,
difference,
edit,
admonition,
extension,
format_align_center,
format_align_left,
format_align_right,
format_bold,
format_italic,
format_list_bulleted,
format_list_checked,
format_list_numbered,
format_underlined,
frame_source,
frontmatter,
horizontal_rule,
insert_col_left,
insert_col_right,
insert_row_above,
insert_row_below,
link,
link_off,
markdown,
more_horiz,
more_vert,
open_in_new,
redo,
rich_text,
settings,
table,
undo
}

const Icon: React.FC<{ name: IconKey }> = ({ name }) => {
const IconComponent = IconMap[name]
return <IconComponent />
}

export default Icon
5 changes: 3 additions & 2 deletions src/plugins/core/PropertyPopover.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@
import * as RadixPopover from '@radix-ui/react-popover'
import React from 'react'
import { useForm } from 'react-hook-form'
import SettingsIcon from '../../icons/settings.svg'
import styles from '../../styles/ui.module.css'

import { PopoverContent, PopoverPortal } from './ui/PopoverUtils'
import { corePluginHooks } from '.'

/**
* The properties of the {@link PropertyPopover} React component.
Expand All @@ -31,13 +31,14 @@ export interface PropertyPopoverProps {
*/
export const PropertyPopover: React.FC<PropertyPopoverProps> = ({ title, properties, onChange }) => {
const [open, setOpen] = React.useState(false)
const [iconComponentFor] = corePluginHooks.useEmitterValues('iconComponentFor')

const { register, handleSubmit, reset } = useForm({ defaultValues: properties })

return (
<RadixPopover.Root open={open} onOpenChange={(v) => setOpen(v)}>
<RadixPopover.Trigger className={styles.iconButton}>
<SettingsIcon style={{ display: 'block' }} />
<div>{iconComponentFor('settings')}</div>
</RadixPopover.Trigger>
<PopoverPortal>
<PopoverContent>
Expand Down
Loading

0 comments on commit fc131a2

Please sign in to comment.