diff --git a/app/src/admin/api/system.ts b/app/src/admin/api/system.ts index 8aa0bd3..0087e39 100644 --- a/app/src/admin/api/system.ts +++ b/app/src/admin/api/system.ts @@ -14,6 +14,7 @@ export type GeneralState = { backend: string; docs: string; file: string; + pwa_manifest: string; }; export type MailState = { @@ -117,6 +118,7 @@ export const initialSystemState: SystemProps = { backend: "", docs: "", file: "", + pwa_manifest: "", }, site: { relay_plan: false, diff --git a/app/src/assets/globals.less b/app/src/assets/globals.less index e001f1b..648204d 100644 --- a/app/src/assets/globals.less +++ b/app/src/assets/globals.less @@ -118,6 +118,10 @@ --assistant-border-hover: hsla(218, 100%, 64%, .25); --assistant-shadow: hsla(218, 100%, 64%, .05); } + + [type='text']:focus, input:where(:not([type])):focus, [type='email']:focus, [type='url']:focus, [type='password']:focus, [type='number']:focus, [type='date']:focus, [type='datetime-local']:focus, [type='month']:focus, [type='search']:focus, [type='tel']:focus, [type='time']:focus, [type='week']:focus, [multiple]:focus, textarea:focus, select:focus { + @apply border-border; + } } * { diff --git a/app/src/assets/ui.less b/app/src/assets/ui.less index 4e909ed..186bc91 100644 --- a/app/src/assets/ui.less +++ b/app/src/assets/ui.less @@ -371,3 +371,7 @@ input[type="number"] { .text-common { color: hsl(var(--text)) !important; } + +.error-border { + border-color: hsl(var(--destructive)) !important; +} diff --git a/app/src/components/EditorProvider.tsx b/app/src/components/EditorProvider.tsx index 1da8c8c..50f329c 100644 --- a/app/src/components/EditorProvider.tsx +++ b/app/src/components/EditorProvider.tsx @@ -11,7 +11,7 @@ import { useTranslation } from "react-i18next"; import "@/assets/common/editor.less"; import { Textarea } from "./ui/textarea.tsx"; import Markdown from "./Markdown.tsx"; -import React, { useEffect, useRef, useState } from "react"; +import React, { useEffect, useMemo, useRef, useState } from "react"; import { Toggle } from "./ui/toggle.tsx"; import { mobile } from "@/utils/device.ts"; import { Button } from "./ui/button.tsx"; @@ -23,6 +23,8 @@ type RichEditorProps = { onChange: (value: string) => void; maxLength?: number; + formatter?: (value: string) => string; + isInvalid?: (value: string) => boolean; title?: string; open?: boolean; @@ -38,7 +40,9 @@ function RichEditor({ value, onChange, maxLength, + formatter, submittable, + isInvalid, onSubmit, setOpen, closeOnSubmit, @@ -48,6 +52,13 @@ function RichEditor({ const [openPreview, setOpenPreview] = useState(!mobile); const [openInput, setOpenInput] = useState(true); + const formattedValue = useMemo(() => { + return formatter ? formatter(value) : value; + }, [value, formatter]); + const invalid = useMemo(() => { + return isInvalid ? isInvalid(value) : false; + }, [value, isInvalid]); + const handler = () => { if (!input.current) return; const target = input.current as HTMLElement; @@ -133,7 +144,10 @@ function RichEditor({