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
+ ) => (
-
+
{title}
)
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