diff --git a/packages/editor/src/editor-ui/assets/plugin-icons/icon-audio.tsx b/packages/editor/src/editor-ui/assets/plugin-icons/icon-audio.tsx new file mode 100644 index 0000000000..493709f67f --- /dev/null +++ b/packages/editor/src/editor-ui/assets/plugin-icons/icon-audio.tsx @@ -0,0 +1,52 @@ +export function AudioIcon() { + return ( + + + + + + + + + + + + + ) +} diff --git a/packages/editor/src/editor-ui/assets/plugin-icons/icon-blanks-dnd.tsx b/packages/editor/src/editor-ui/assets/plugin-icons/icon-blanks-dnd.tsx new file mode 100644 index 0000000000..f5aa6e804a --- /dev/null +++ b/packages/editor/src/editor-ui/assets/plugin-icons/icon-blanks-dnd.tsx @@ -0,0 +1,58 @@ +export function BlanksDndIcon() { + return ( + + + + + + + + + + + + + + + + ) +} diff --git a/packages/editor/src/editor-ui/assets/plugin-icons/icon-blanks-typing.tsx b/packages/editor/src/editor-ui/assets/plugin-icons/icon-blanks-typing.tsx new file mode 100644 index 0000000000..4f42cf75fb --- /dev/null +++ b/packages/editor/src/editor-ui/assets/plugin-icons/icon-blanks-typing.tsx @@ -0,0 +1,27 @@ +export function BlanksTypingIcon() { + return ( + + + + + + + + + + + + + + + + + + ) +} diff --git a/packages/editor/src/editor-ui/assets/plugin-icons/icon-box.tsx b/packages/editor/src/editor-ui/assets/plugin-icons/icon-box.tsx new file mode 100644 index 0000000000..e35afca64b --- /dev/null +++ b/packages/editor/src/editor-ui/assets/plugin-icons/icon-box.tsx @@ -0,0 +1,34 @@ +export function BoxIcon() { + return ( + + + + + + + + + ) +} diff --git a/packages/editor/src/editor-ui/assets/plugin-icons/icon-dropzones.tsx b/packages/editor/src/editor-ui/assets/plugin-icons/icon-dropzones.tsx new file mode 100644 index 0000000000..bf28da85fe --- /dev/null +++ b/packages/editor/src/editor-ui/assets/plugin-icons/icon-dropzones.tsx @@ -0,0 +1,60 @@ +export function DropzonesIcon() { + return ( + + + + + + + + + + + + + + + + + + ) +} diff --git a/packages/editor/src/editor-ui/assets/plugin-icons/icon-equations.tsx b/packages/editor/src/editor-ui/assets/plugin-icons/icon-equations.tsx new file mode 100644 index 0000000000..b8160f5576 --- /dev/null +++ b/packages/editor/src/editor-ui/assets/plugin-icons/icon-equations.tsx @@ -0,0 +1,26 @@ +export function EquationsIcon() { + return ( + + + + + + + + + + + + ) +} diff --git a/packages/editor/src/editor-ui/assets/plugin-icons/icon-fallback.tsx b/packages/editor/src/editor-ui/assets/plugin-icons/icon-fallback.tsx new file mode 100644 index 0000000000..58d84a7bef --- /dev/null +++ b/packages/editor/src/editor-ui/assets/plugin-icons/icon-fallback.tsx @@ -0,0 +1,20 @@ +export function FallbackIcon() { + return ( + + + + + + + + ) +} diff --git a/packages/editor/src/editor-ui/assets/plugin-icons/icon-geogebra.tsx b/packages/editor/src/editor-ui/assets/plugin-icons/icon-geogebra.tsx new file mode 100644 index 0000000000..c87db8875b --- /dev/null +++ b/packages/editor/src/editor-ui/assets/plugin-icons/icon-geogebra.tsx @@ -0,0 +1,58 @@ +export function GeogebraIcon() { + return ( + + + + + + + + + + + + + ) +} diff --git a/packages/editor/src/editor-ui/assets/plugin-icons/icon-h5p.tsx b/packages/editor/src/editor-ui/assets/plugin-icons/icon-h5p.tsx new file mode 100644 index 0000000000..3b7b6010d7 --- /dev/null +++ b/packages/editor/src/editor-ui/assets/plugin-icons/icon-h5p.tsx @@ -0,0 +1,31 @@ +export function H5PIcon() { + return ( + + + + + + + + + + + + + ) +} diff --git a/packages/editor/src/editor-ui/assets/plugin-icons/icon-highlight.tsx b/packages/editor/src/editor-ui/assets/plugin-icons/icon-highlight.tsx new file mode 100644 index 0000000000..80be533006 --- /dev/null +++ b/packages/editor/src/editor-ui/assets/plugin-icons/icon-highlight.tsx @@ -0,0 +1,18 @@ +export function HighlightIcon() { + return ( + + + + + + + + + ) +} diff --git a/packages/editor/src/editor-ui/assets/plugin-icons/icon-image.tsx b/packages/editor/src/editor-ui/assets/plugin-icons/icon-image.tsx new file mode 100644 index 0000000000..0d3d186ce6 --- /dev/null +++ b/packages/editor/src/editor-ui/assets/plugin-icons/icon-image.tsx @@ -0,0 +1,22 @@ +export function ImageIcon() { + return ( + + + + + + + + ) +} diff --git a/packages/editor/src/editor-ui/assets/plugin-icons/icon-injection.tsx b/packages/editor/src/editor-ui/assets/plugin-icons/icon-injection.tsx new file mode 100644 index 0000000000..d1fe2d323f --- /dev/null +++ b/packages/editor/src/editor-ui/assets/plugin-icons/icon-injection.tsx @@ -0,0 +1,22 @@ +export function InjectionIcon() { + return ( + + + + + + + + ) +} diff --git a/packages/editor/src/editor-ui/assets/plugin-icons/icon-input-exercise.tsx b/packages/editor/src/editor-ui/assets/plugin-icons/icon-input-exercise.tsx new file mode 100644 index 0000000000..76ab60e0a0 --- /dev/null +++ b/packages/editor/src/editor-ui/assets/plugin-icons/icon-input-exercise.tsx @@ -0,0 +1,24 @@ +export function InputExerciseIcon() { + return ( + + + + + + + + + + + + + + + + ) +} diff --git a/packages/editor/src/editor-ui/assets/plugin-icons/icon-interactive-video.tsx b/packages/editor/src/editor-ui/assets/plugin-icons/icon-interactive-video.tsx new file mode 100644 index 0000000000..205119cf7f --- /dev/null +++ b/packages/editor/src/editor-ui/assets/plugin-icons/icon-interactive-video.tsx @@ -0,0 +1,69 @@ +export function InteractiveVideoIcon() { + return ( + + + + + + + + + + + + + + + + + + + ) +} diff --git a/packages/editor/src/editor-ui/assets/plugin-icons/icon-mc-exercise.tsx b/packages/editor/src/editor-ui/assets/plugin-icons/icon-mc-exercise.tsx new file mode 100644 index 0000000000..633b3b0a92 --- /dev/null +++ b/packages/editor/src/editor-ui/assets/plugin-icons/icon-mc-exercise.tsx @@ -0,0 +1,37 @@ +export function MCExerciseIcon() { + return ( + + + + + + + + + + + + + + + + + + + + + ) +} diff --git a/packages/editor/src/editor-ui/assets/plugin-icons/icon-multimedia.tsx b/packages/editor/src/editor-ui/assets/plugin-icons/icon-multimedia.tsx new file mode 100644 index 0000000000..d1dc8a2247 --- /dev/null +++ b/packages/editor/src/editor-ui/assets/plugin-icons/icon-multimedia.tsx @@ -0,0 +1,26 @@ +export function MultimediaIcon() { + return ( + + + + + + + + + ) +} diff --git a/packages/editor/src/editor-ui/assets/plugin-icons/icon-sc-exercise.tsx b/packages/editor/src/editor-ui/assets/plugin-icons/icon-sc-exercise.tsx new file mode 100644 index 0000000000..7c351ce412 --- /dev/null +++ b/packages/editor/src/editor-ui/assets/plugin-icons/icon-sc-exercise.tsx @@ -0,0 +1,32 @@ +export function SCExerciseIcon() { + return ( + + + + + + + + + + + + + + + + + + + + + ) +} diff --git a/packages/editor/src/editor-ui/assets/plugin-icons/icon-spoiler.tsx b/packages/editor/src/editor-ui/assets/plugin-icons/icon-spoiler.tsx new file mode 100644 index 0000000000..2522d5c3b3 --- /dev/null +++ b/packages/editor/src/editor-ui/assets/plugin-icons/icon-spoiler.tsx @@ -0,0 +1,37 @@ +export function SpoilerIcon() { + return ( + + + + + + + + + + + + + + ) +} diff --git a/packages/editor/src/editor-ui/assets/plugin-icons/icon-table.tsx b/packages/editor/src/editor-ui/assets/plugin-icons/icon-table.tsx new file mode 100644 index 0000000000..26a6c2ccd3 --- /dev/null +++ b/packages/editor/src/editor-ui/assets/plugin-icons/icon-table.tsx @@ -0,0 +1,28 @@ +export function TableIcon() { + return ( + + + + + + + + + + ) +} diff --git a/packages/editor/src/editor-ui/assets/plugin-icons/icon-text-area.tsx b/packages/editor/src/editor-ui/assets/plugin-icons/icon-text-area.tsx new file mode 100644 index 0000000000..0b3b1c93e3 --- /dev/null +++ b/packages/editor/src/editor-ui/assets/plugin-icons/icon-text-area.tsx @@ -0,0 +1,11 @@ +export function TextAreaIcon() { + return ( + + + + + + + + ) +} diff --git a/packages/editor/src/editor-ui/assets/plugin-icons/icon-text.tsx b/packages/editor/src/editor-ui/assets/plugin-icons/icon-text.tsx new file mode 100644 index 0000000000..1f19dab63c --- /dev/null +++ b/packages/editor/src/editor-ui/assets/plugin-icons/icon-text.tsx @@ -0,0 +1,12 @@ +export function TextIcon() { + return ( + + + + + + ) +} diff --git a/packages/editor/src/editor-ui/assets/plugin-icons/icon-video.tsx b/packages/editor/src/editor-ui/assets/plugin-icons/icon-video.tsx new file mode 100644 index 0000000000..4d9cbd6a0f --- /dev/null +++ b/packages/editor/src/editor-ui/assets/plugin-icons/icon-video.tsx @@ -0,0 +1,13 @@ +export function VideoIcon() { + return ( + + + + + + + + + + ) +} diff --git a/packages/editor/src/editor-ui/assets/plugin-icons/image-gallery/icon-image-gallery.tsx b/packages/editor/src/editor-ui/assets/plugin-icons/image-gallery/icon-image-gallery.tsx new file mode 100644 index 0000000000..9817c40c61 --- /dev/null +++ b/packages/editor/src/editor-ui/assets/plugin-icons/image-gallery/icon-image-gallery.tsx @@ -0,0 +1,124 @@ +export function ImageGalleryIcon() { + return ( + + + + + + + + + + + + + + + + + + + + ) +} diff --git a/packages/editor/src/plugins/exercise/components/interactive-exercises-selection.tsx b/packages/editor/src/plugins/exercise/components/interactive-exercises-selection.tsx index 609f556c99..752c6bcad2 100644 --- a/packages/editor/src/plugins/exercise/components/interactive-exercises-selection.tsx +++ b/packages/editor/src/plugins/exercise/components/interactive-exercises-selection.tsx @@ -1,7 +1,6 @@ import { EditorTooltip } from '@editor/editor-ui/editor-tooltip' import { useEditStrings } from '@editor/i18n/edit-strings-provider' import { editorPlugins } from '@editor/plugin/helpers/editor-plugins' -import { PluginMenuIcon } from '@editor/plugins/rows/components/plugin-menu-icon' import { getPluginMenuItems, type PluginMenuItem, @@ -56,7 +55,10 @@ export function InteractiveExercisesSelection({

{exStrings.addOptionalInteractiveEx}

{unwrappedMenuItems.map( - ({ type, title, icon, description, initialState }, index) => ( + ( + { type, title, IconComponent, description, initialState }, + index + ) => ( ) diff --git a/packages/editor/src/plugins/rows/components/plugin-menu-icon.tsx b/packages/editor/src/plugins/rows/components/plugin-menu-icon.tsx deleted file mode 100644 index 50ecb93e02..0000000000 --- a/packages/editor/src/plugins/rows/components/plugin-menu-icon.tsx +++ /dev/null @@ -1,22 +0,0 @@ -import IconFallback from '@editor/editor-ui/assets/plugin-icons/icon-fallback.svg' - -// The icon in next.js gets correctly turned into a component, in vite, we -// want to expose the raw svg string to the packages. As this is also used -// by the web-component, we can't expose a React component. Therefore, we -// have to turn the string here into an svg element using -// dangerouslySetInnerHTML. There should not be any XSS risk with this, as we -// are loading the svgs ourselves from the assets and they can never come -// from a user. -export function PluginMenuIcon({ - icon, -}: { - icon: string | (() => JSX.Element) -}) { - return typeof icon === 'string' ? ( -
- ) : typeof icon !== 'string' ? ( - icon() - ) : ( - - ) -} diff --git a/packages/editor/src/plugins/rows/components/plugin-menu-items.tsx b/packages/editor/src/plugins/rows/components/plugin-menu-items.tsx index 8e4fdda66a..586a9b6e9f 100644 --- a/packages/editor/src/plugins/rows/components/plugin-menu-items.tsx +++ b/packages/editor/src/plugins/rows/components/plugin-menu-items.tsx @@ -3,8 +3,6 @@ import { useEditStrings } from '@editor/i18n/edit-strings-provider' import type { PluginMenuItem } from '@editor/plugins/rows/utils/plugin-menu' import { cn } from '@editor/utils/cn' -import { PluginMenuIcon } from './plugin-menu-icon' - function getTooltipPosition(index: number) { return index % 5 === 0 ? 'right' : index % 5 === 4 ? 'left' : undefined } @@ -54,7 +52,8 @@ export function PluginMenuItems({ function renderListItems(options: PluginMenuItem[], offset: number) { return options.map((pluginMenuItem, index) => { - const { type, initialState, title, icon, description } = pluginMenuItem + const { type, initialState, title, IconComponent, description } = + pluginMenuItem const currentIndex = index + offset const selected = currentIndex === focusedItemIndex const tooltipPosition = getTooltipPosition(index) @@ -78,7 +77,7 @@ export function PluginMenuItems({ )} > - + {title} diff --git a/packages/editor/src/plugins/rows/utils/plugin-menu.ts b/packages/editor/src/plugins/rows/utils/plugin-menu.ts index dd83c36832..f03a4552d9 100644 --- a/packages/editor/src/plugins/rows/utils/plugin-menu.ts +++ b/packages/editor/src/plugins/rows/utils/plugin-menu.ts @@ -1,26 +1,49 @@ import type { EditorProps } from '@editor/core' +import { AudioIcon } from '@editor/editor-ui/assets/plugin-icons/icon-audio' import IconAudio from '@editor/editor-ui/assets/plugin-icons/icon-audio.svg?raw' +import { BlanksDndIcon } from '@editor/editor-ui/assets/plugin-icons/icon-blanks-dnd' import IconBlanksDragAndDrop from '@editor/editor-ui/assets/plugin-icons/icon-blanks-dnd.svg?raw' +import { BlanksTypingIcon } from '@editor/editor-ui/assets/plugin-icons/icon-blanks-typing' import IconBlanksTyping from '@editor/editor-ui/assets/plugin-icons/icon-blanks-typing.svg?raw' +import { BoxIcon } from '@editor/editor-ui/assets/plugin-icons/icon-box' import IconBox from '@editor/editor-ui/assets/plugin-icons/icon-box.svg?raw' +import { DropzonesIcon } from '@editor/editor-ui/assets/plugin-icons/icon-dropzones' import IconDropzones from '@editor/editor-ui/assets/plugin-icons/icon-dropzones.svg?raw' import IconEquation from '@editor/editor-ui/assets/plugin-icons/icon-equation.svg?raw' +import { EquationsIcon } from '@editor/editor-ui/assets/plugin-icons/icon-equations' +import { FallbackIcon } from '@editor/editor-ui/assets/plugin-icons/icon-fallback' import IconFallback from '@editor/editor-ui/assets/plugin-icons/icon-fallback.svg?raw' +import { GeogebraIcon } from '@editor/editor-ui/assets/plugin-icons/icon-geogebra' import IconGeogebra from '@editor/editor-ui/assets/plugin-icons/icon-geogebra.svg?raw' +import { H5PIcon } from '@editor/editor-ui/assets/plugin-icons/icon-h5p' import IconH5p from '@editor/editor-ui/assets/plugin-icons/icon-h5p.svg?raw' +import { HighlightIcon } from '@editor/editor-ui/assets/plugin-icons/icon-highlight' import IconHighlight from '@editor/editor-ui/assets/plugin-icons/icon-highlight.svg?raw' +import { ImageIcon } from '@editor/editor-ui/assets/plugin-icons/icon-image' import IconImage from '@editor/editor-ui/assets/plugin-icons/icon-image.svg?raw' +import { InjectionIcon } from '@editor/editor-ui/assets/plugin-icons/icon-injection' import IconInjection from '@editor/editor-ui/assets/plugin-icons/icon-injection.svg?raw' +import { InputExerciseIcon } from '@editor/editor-ui/assets/plugin-icons/icon-input-exercise' import IconInputExercise from '@editor/editor-ui/assets/plugin-icons/icon-input-exercise.svg?raw' +import { InteractiveVideoIcon } from '@editor/editor-ui/assets/plugin-icons/icon-interactive-video' import IconInteractiveVideo from '@editor/editor-ui/assets/plugin-icons/icon-interactive-video.svg?raw' +import { MCExerciseIcon } from '@editor/editor-ui/assets/plugin-icons/icon-mc-exercise' import IconMcExercise from '@editor/editor-ui/assets/plugin-icons/icon-mc-exercise.svg?raw' +import { MultimediaIcon } from '@editor/editor-ui/assets/plugin-icons/icon-multimedia' import IconMultimedia from '@editor/editor-ui/assets/plugin-icons/icon-multimedia.svg?raw' +import { SCExerciseIcon } from '@editor/editor-ui/assets/plugin-icons/icon-sc-exercise' import IconScExercise from '@editor/editor-ui/assets/plugin-icons/icon-sc-exercise.svg?raw' +import { SpoilerIcon } from '@editor/editor-ui/assets/plugin-icons/icon-spoiler' import IconSpoiler from '@editor/editor-ui/assets/plugin-icons/icon-spoiler.svg?raw' +import { TableIcon } from '@editor/editor-ui/assets/plugin-icons/icon-table' import IconTable from '@editor/editor-ui/assets/plugin-icons/icon-table.svg?raw' +import { TextIcon } from '@editor/editor-ui/assets/plugin-icons/icon-text' +import { TextAreaIcon } from '@editor/editor-ui/assets/plugin-icons/icon-text-area' import IconTextArea from '@editor/editor-ui/assets/plugin-icons/icon-text-area.svg?raw' import IconText from '@editor/editor-ui/assets/plugin-icons/icon-text.svg?raw' +import { VideoIcon } from '@editor/editor-ui/assets/plugin-icons/icon-video' import IconVideo from '@editor/editor-ui/assets/plugin-icons/icon-video.svg?raw' +import { ImageGalleryIcon } from '@editor/editor-ui/assets/plugin-icons/image-gallery/icon-image-gallery' import IconImageGallery from '@editor/editor-ui/assets/plugin-icons/image-gallery/icon-image-gallery.svg?raw' import { EditorPluginType } from '@editor/types/editor-plugin-type' import { AnyEditorDocument } from '@editor/types/editor-plugins' @@ -90,8 +113,9 @@ function getPluginMenuItem(editStrings: EditStrings, type: PluginMenuType) { const [initialState, unwrappedPlugin] = getInitialState(type) const strings = getTitleAndDescription(type, unwrappedPlugin, editStrings) const icon = getIconString(type) + const IconComponent = getIconComponent(type) - return { type, icon, initialState, ...strings } + return { type, icon, IconComponent, initialState, ...strings } } export interface PluginMenuItem { @@ -99,6 +123,7 @@ export interface PluginMenuItem { title: string description: string initialState: EditorProps['initialState'] + IconComponent: React.ComponentType // until we use the editor package in the frontend (only having vite for building) // icons should be strings but are loaded as () => JSX.Element in the frontend (webpack) icon: string | (() => JSX.Element) @@ -240,6 +265,39 @@ function getIconString(type: PluginMenuType) { return iconLookup[type] } +const iconComponentLookup: Record = { + [pluginMenuType.Text]: TextIcon, + [pluginMenuType.Multimedia]: MultimediaIcon, + [pluginMenuType.Video]: VideoIcon, + [pluginMenuType.Box]: BoxIcon, + [pluginMenuType.Equations]: EquationsIcon, + [pluginMenuType.Geogebra]: GeogebraIcon, + [pluginMenuType.Highlight]: HighlightIcon, + [pluginMenuType.Image]: ImageIcon, + [pluginMenuType.ImageGallery]: ImageGalleryIcon, + [pluginMenuType.Injection]: InjectionIcon, + [pluginMenuType.SerloTable]: TableIcon, + [pluginMenuType.Spoiler]: SpoilerIcon, + [pluginMenuType.DropzoneImage]: DropzonesIcon, + [pluginMenuType.SingleChoiceExercise]: SCExerciseIcon, + [pluginMenuType.MultipleChoiceExercise]: MCExerciseIcon, + [pluginMenuType.InputExercise]: InputExerciseIcon, + [pluginMenuType.TextAreaExercise]: TextAreaIcon, + [pluginMenuType.BlanksExercise]: BlanksTypingIcon, + [pluginMenuType.BlanksExerciseDragAndDrop]: BlanksDndIcon, + [pluginMenuType.H5p]: H5PIcon, + [pluginMenuType.ExerciseGroup]: FallbackIcon, + [pluginMenuType.InteractiveVideo]: InteractiveVideoIcon, + [pluginMenuType.Audio]: AudioIcon, + [pluginMenuType.PageLayout]: FallbackIcon, + [pluginMenuType.PagePartners]: FallbackIcon, + [pluginMenuType.EdusharingAsset]: ImageIcon, +} + +function getIconComponent(type: PluginMenuType) { + return iconComponentLookup[type] +} + export function filterPluginMenuItemsBySearchString( option: PluginMenuItem[], searchString: string