diff --git a/public/locales/en/alert-input-modal.json b/public/locales/en/alert-input-modal.json new file mode 100644 index 0000000..ca78413 --- /dev/null +++ b/public/locales/en/alert-input-modal.json @@ -0,0 +1,8 @@ +{ + "title": "Insert Callout", + "type": "Type", + "content": "Content", + "contentPlaceholder": "Enter content", + "cancel": "Cancel", + "confirm": "Confirm" +} diff --git a/public/locales/en/tabs.json b/public/locales/en/tabs.json index adac75c..bca59b2 100644 --- a/public/locales/en/tabs.json +++ b/public/locales/en/tabs.json @@ -19,6 +19,7 @@ "italic": "italic", "numbered_list": "numbered_list", "quote": "quote", + "insert_alert": "insert alert", "table": "table" }, "categorys": { diff --git a/public/locales/zh-TW/alert-input-modal.json b/public/locales/zh-TW/alert-input-modal.json new file mode 100644 index 0000000..4608673 --- /dev/null +++ b/public/locales/zh-TW/alert-input-modal.json @@ -0,0 +1,8 @@ +{ + "title": "插入 Callout", + "type": "類型", + "content": "內容", + "contentPlaceholder": "請填寫內容", + "cancel": "取消", + "confirm": "確認" +} diff --git a/public/locales/zh-TW/tabs.json b/public/locales/zh-TW/tabs.json index 1124002..c0bc2da 100644 --- a/public/locales/zh-TW/tabs.json +++ b/public/locales/zh-TW/tabs.json @@ -18,6 +18,7 @@ "italic": "斜體", "numbered_list": "編號清單", "quote": "引用", + "insert_alert": "插入 Callout", "table": "表格" }, "categorys": { diff --git a/src/components/alert-input-modal.js b/src/components/alert-input-modal.js new file mode 100644 index 0000000..b0df3af --- /dev/null +++ b/src/components/alert-input-modal.js @@ -0,0 +1,93 @@ +import React, { useState } from 'react'; +import PropTypes from 'prop-types'; +import { useTranslation } from '@/lib/i18n'; +import BasicModal from '@/components/core/modal/basic-modal'; + +const ALERT_TYPES = ['Note', 'Tip', 'Important', 'Warning', 'Caution']; + +const AlertInputModal = ({ isOpen, onClose, onConfirm }) => { + const [type, setType] = useState(ALERT_TYPES[0]); + const [content, setContent] = useState(''); + const t = useTranslation('alert-input-modal'); + + const resetForm = () => { + setType(ALERT_TYPES[0]); + setContent(''); + }; + + const handleClose = () => { + resetForm(); + onClose(); + }; + + const handleConfirm = () => { + onConfirm(`\n> [!${type.toUpperCase()}]${content.trim() ? ` ${content.trim()}` : ''}`); + handleClose(); + }; + + return ( + +
+
+ +
+ +
+ + + +
+
+
+
+ + setContent(e.target.value)} + placeholder={t('contentPlaceholder')} + className="w-full border border-border-main rounded-lg px-4 py-3 text-base text-text-primary placeholder:text-text-placeholder focus:outline-none focus:ring-2 focus:ring-primary" + /> +
+
+
+ ); +}; + +AlertInputModal.propTypes = { + isOpen: PropTypes.bool.isRequired, + onClose: PropTypes.func.isRequired, + onConfirm: PropTypes.func.isRequired, +}; + +export default AlertInputModal; diff --git a/src/components/edit-icons-tab.js b/src/components/edit-icons-tab.js index 957049d..6413973 100644 --- a/src/components/edit-icons-tab.js +++ b/src/components/edit-icons-tab.js @@ -10,6 +10,7 @@ import { compare } from '@/lib/data-process'; import mathTabList from '@/lib/tabs/math'; import ImageUploadModal from './image-upload-modal'; import LinkInputModal from './link-input-modal'; +import AlertInputModal from './alert-input-modal'; import Tooltip from './core/tooltip'; const generateUniqueId = (length = 8) => { @@ -24,6 +25,7 @@ const EditIconsTab = ({ insertLatex, addImageToExport }) => { const [selectedMathTabIndex, setSelectedMathTabIndex] = useState(0); const [isImageModalOpen, setIsImageModalOpen] = useState(false); const [isLinkModalOpen, setIsLinkModalOpen] = useState(false); + const [isAlertModalOpen, setIsAlertModalOpen] = useState(false); const t = useTranslation('tabs'); @@ -38,6 +40,17 @@ const EditIconsTab = ({ insertLatex, addImageToExport }) => { [insertLatex] ); + const handleAlertConfirm = useCallback( + (markdown) => { + insertLatex({ + id: 'insert_alert', + latex: markdown, + offset: 0, + }); + }, + [insertLatex] + ); + const handleImageConfirm = useCallback( (file, altText) => { const fileID = generateUniqueId(); @@ -146,6 +159,10 @@ const EditIconsTab = ({ insertLatex, addImageToExport }) => { setIsLinkModalOpen(true); return; } + if (tab.id === 'insert_alert') { + setIsAlertModalOpen(true); + return; + } insertLatex(tab); }} > @@ -166,6 +183,11 @@ const EditIconsTab = ({ insertLatex, addImageToExport }) => { onClose={() => setIsLinkModalOpen(false)} onConfirm={handleLinkConfirm} /> + setIsAlertModalOpen(false)} + onConfirm={handleAlertConfirm} + /> ); }; diff --git a/src/components/svg/markdown/alert.svg b/src/components/svg/markdown/alert.svg new file mode 100644 index 0000000..0097e1f --- /dev/null +++ b/src/components/svg/markdown/alert.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/src/lib/tabs/markdowns.js b/src/lib/tabs/markdowns.js index 7304fec..02cd8ff 100644 --- a/src/lib/tabs/markdowns.js +++ b/src/lib/tabs/markdowns.js @@ -13,6 +13,7 @@ import { ReactComponent as CreateLink } from '@/components/svg/markdown/create_l import { ReactComponent as InsertImage } from '@/components/svg/markdown/insert_image.svg'; import { ReactComponent as Quote } from '@/components/svg/markdown/quote.svg'; import { ReactComponent as Table } from '@/components/svg/markdown/table.svg'; +import { ReactComponent as Alert } from '@/components/svg/markdown/alert.svg'; const markdowns = [ { @@ -127,6 +128,14 @@ const markdowns = [ shortcut: -1, Icon: Quote, }, + { + id: 'insert_alert', + latex: '', + offset: 0, + category: 'markdown', + shortcut: -1, + Icon: Alert, + }, { id: 'table', latex: `\n\nc1|c2|c3