|
|
|
|
@ -3,7 +3,6 @@ import { Input } from '@/components/ui/input'
@@ -3,7 +3,6 @@ import { Input } from '@/components/ui/input'
|
|
|
|
|
import { |
|
|
|
|
Dialog, |
|
|
|
|
DialogContent, |
|
|
|
|
DialogFooter, |
|
|
|
|
DialogHeader, |
|
|
|
|
DialogTitle |
|
|
|
|
} from '@/components/ui/dialog' |
|
|
|
|
@ -644,7 +643,7 @@ export default function AdvancedEventLabDialog({
@@ -644,7 +643,7 @@ export default function AdvancedEventLabDialog({
|
|
|
|
|
'.cm-scroller': { overflow: 'auto', minHeight: 0 }, |
|
|
|
|
// Large dvh mins fight stacked flex/grid rows and overflow onto the preview; host + row cap height instead.
|
|
|
|
|
'.cm-content': { |
|
|
|
|
minHeight: '11rem', |
|
|
|
|
minHeight: '12rem', |
|
|
|
|
fontFamily: 'var(--font-mono, ui-monospace, monospace)' |
|
|
|
|
}, |
|
|
|
|
// LanguageTool hits: drop default thin SVG underline, use thick wavy line (see `LT_GRAMMAR_MARK_CLASS`).
|
|
|
|
|
@ -878,10 +877,91 @@ export default function AdvancedEventLabDialog({
@@ -878,10 +877,91 @@ export default function AdvancedEventLabDialog({
|
|
|
|
|
<DialogTitle>{t('Advanced event lab')}</DialogTitle> |
|
|
|
|
</DialogHeader> |
|
|
|
|
|
|
|
|
|
<div className="flex flex-col gap-2 px-4 py-2 border-b shrink-0 flex-wrap"> |
|
|
|
|
<div className="min-h-0 max-h-[calc(90dvh-3.25rem)] overflow-y-auto overscroll-y-contain"> |
|
|
|
|
<div className="flex shrink-0 flex-col px-4 py-2 pb-4"> |
|
|
|
|
<div className="mb-2 flex flex-wrap gap-2"> |
|
|
|
|
<Button |
|
|
|
|
type="button" |
|
|
|
|
variant="outline" |
|
|
|
|
size="sm" |
|
|
|
|
disabled={!canUndoCheckpoint} |
|
|
|
|
title={t('Advanced lab undo checkpoint hint')} |
|
|
|
|
onClick={handleUndoCheckpoint} |
|
|
|
|
> |
|
|
|
|
<Undo2 className="mr-1 inline h-4 w-4" /> |
|
|
|
|
{t('Advanced lab undo checkpoint')} |
|
|
|
|
</Button> |
|
|
|
|
</div> |
|
|
|
|
|
|
|
|
|
<Tabs |
|
|
|
|
value={labBodyTab} |
|
|
|
|
onValueChange={(v) => { |
|
|
|
|
const next = v as 'edit' | 'preview' |
|
|
|
|
if (next === 'preview') flushPreviewDocNow() |
|
|
|
|
setLabBodyTab(next) |
|
|
|
|
}} |
|
|
|
|
className="flex flex-col gap-2" |
|
|
|
|
> |
|
|
|
|
<TabsList className="h-auto w-auto shrink-0 flex-wrap justify-start gap-1 p-1"> |
|
|
|
|
<TabsTrigger value="edit" className="shrink-0"> |
|
|
|
|
{t( |
|
|
|
|
markupMode === 'asciidoc' |
|
|
|
|
? 'Advanced lab markup label asciidoc' |
|
|
|
|
: 'Advanced lab markup label markdown' |
|
|
|
|
)} |
|
|
|
|
</TabsTrigger> |
|
|
|
|
<TabsTrigger value="preview" className="shrink-0"> |
|
|
|
|
{t('Advanced lab preview')} |
|
|
|
|
</TabsTrigger> |
|
|
|
|
</TabsList> |
|
|
|
|
|
|
|
|
|
<TabsContent |
|
|
|
|
value="edit" |
|
|
|
|
forceMount |
|
|
|
|
className="mt-0 flex flex-col gap-2 data-[state=inactive]:hidden focus-visible:ring-0 focus-visible:ring-offset-0" |
|
|
|
|
> |
|
|
|
|
<AdvancedEventLabMarkupToolbar markupMode={markupMode} viewRef={markupView} sliceRef={sliceRef} /> |
|
|
|
|
<div |
|
|
|
|
ref={markupHost} |
|
|
|
|
className="min-h-[24rem] h-[min(84vh,56rem)] overflow-hidden rounded-md border bg-muted/20" |
|
|
|
|
/> |
|
|
|
|
</TabsContent> |
|
|
|
|
|
|
|
|
|
<TabsContent |
|
|
|
|
value="preview" |
|
|
|
|
className="mt-0 data-[state=inactive]:hidden focus-visible:ring-0 focus-visible:ring-offset-0" |
|
|
|
|
> |
|
|
|
|
<div className="min-h-[24rem] h-[min(84vh,56rem)] overflow-y-auto rounded-md border border-border bg-background py-2 text-left"> |
|
|
|
|
<AdvancedEventLabPreviewPane |
|
|
|
|
markupMode={markupMode} |
|
|
|
|
source={previewDoc} |
|
|
|
|
previewAuthorPubkey={previewAuthorPubkey} |
|
|
|
|
previewEmojiTags={mergedLabPreviewEmojiTags} |
|
|
|
|
/> |
|
|
|
|
</div> |
|
|
|
|
</TabsContent> |
|
|
|
|
</Tabs> |
|
|
|
|
</div> |
|
|
|
|
|
|
|
|
|
{formatToolbar ? ( |
|
|
|
|
<div className="mt-2 border-t bg-muted/20 px-2 py-2">{formatToolbar}</div> |
|
|
|
|
) : null} |
|
|
|
|
|
|
|
|
|
<div className="mt-2 border-t bg-background px-4 py-3"> |
|
|
|
|
<div className="flex flex-col-reverse gap-2 sm:flex-row sm:justify-end"> |
|
|
|
|
<Button type="button" variant="outline" onClick={() => handleDialogOpenChange(false)}> |
|
|
|
|
{t('Advanced lab cancel undo')} |
|
|
|
|
</Button> |
|
|
|
|
<Button type="button" onClick={handleApply}> |
|
|
|
|
{t('Apply')} |
|
|
|
|
</Button> |
|
|
|
|
</div> |
|
|
|
|
</div> |
|
|
|
|
|
|
|
|
|
<div className="border-t bg-background px-4 pb-4 pt-3"> |
|
|
|
|
<div className="flex flex-wrap items-end gap-3"> |
|
|
|
|
{isLanguageToolConfigured() ? ( |
|
|
|
|
<div className="space-y-1 min-w-[10rem]"> |
|
|
|
|
<div className="min-w-[10rem] space-y-1"> |
|
|
|
|
<Label htmlFor="lt-lang">{t('Advanced lab grammar language')}</Label> |
|
|
|
|
<Select |
|
|
|
|
value={ltLang} |
|
|
|
|
@ -1052,83 +1132,9 @@ export default function AdvancedEventLabDialog({
@@ -1052,83 +1132,9 @@ export default function AdvancedEventLabDialog({
|
|
|
|
|
{t('Advanced lab use translation read aloud')} |
|
|
|
|
</Button> |
|
|
|
|
) : null} |
|
|
|
|
<Button |
|
|
|
|
type="button" |
|
|
|
|
variant="outline" |
|
|
|
|
size="sm" |
|
|
|
|
disabled={!canUndoCheckpoint} |
|
|
|
|
title={t('Advanced lab undo checkpoint hint')} |
|
|
|
|
onClick={handleUndoCheckpoint} |
|
|
|
|
> |
|
|
|
|
<Undo2 className="h-4 w-4 mr-1 inline" /> |
|
|
|
|
{t('Advanced lab undo checkpoint')} |
|
|
|
|
</Button> |
|
|
|
|
</div> |
|
|
|
|
</div> |
|
|
|
|
|
|
|
|
|
<div className="flex min-h-0 flex-1 flex-col overflow-hidden overscroll-y-contain px-4 py-2"> |
|
|
|
|
<Tabs |
|
|
|
|
value={labBodyTab} |
|
|
|
|
onValueChange={(v) => { |
|
|
|
|
const next = v as 'edit' | 'preview' |
|
|
|
|
if (next === 'preview') flushPreviewDocNow() |
|
|
|
|
setLabBodyTab(next) |
|
|
|
|
}} |
|
|
|
|
className="flex min-h-0 flex-1 flex-col gap-2" |
|
|
|
|
> |
|
|
|
|
<TabsList className="h-auto w-auto shrink-0 flex-wrap justify-start gap-1 p-1"> |
|
|
|
|
<TabsTrigger value="edit" className="shrink-0"> |
|
|
|
|
{t( |
|
|
|
|
markupMode === 'asciidoc' |
|
|
|
|
? 'Advanced lab markup label asciidoc' |
|
|
|
|
: 'Advanced lab markup label markdown' |
|
|
|
|
)} |
|
|
|
|
</TabsTrigger> |
|
|
|
|
<TabsTrigger value="preview" className="shrink-0"> |
|
|
|
|
{t('Advanced lab preview')} |
|
|
|
|
</TabsTrigger> |
|
|
|
|
</TabsList> |
|
|
|
|
|
|
|
|
|
<TabsContent |
|
|
|
|
value="edit" |
|
|
|
|
forceMount |
|
|
|
|
className="mt-0 flex min-h-0 flex-1 flex-col gap-2 overflow-hidden data-[state=inactive]:hidden focus-visible:ring-0 focus-visible:ring-offset-0" |
|
|
|
|
> |
|
|
|
|
<AdvancedEventLabMarkupToolbar markupMode={markupMode} viewRef={markupView} sliceRef={sliceRef} /> |
|
|
|
|
<div |
|
|
|
|
ref={markupHost} |
|
|
|
|
className="flex min-h-0 flex-1 flex-col overflow-hidden rounded-md border bg-muted/20 min-h-[min(58dvh,32rem)]" |
|
|
|
|
/> |
|
|
|
|
</TabsContent> |
|
|
|
|
|
|
|
|
|
<TabsContent |
|
|
|
|
value="preview" |
|
|
|
|
className="mt-0 flex min-h-0 flex-1 flex-col overflow-hidden data-[state=inactive]:hidden focus-visible:ring-0 focus-visible:ring-offset-0" |
|
|
|
|
> |
|
|
|
|
<div className="flex min-h-0 flex-1 overflow-y-auto rounded-md border border-border bg-background py-2 text-left"> |
|
|
|
|
<AdvancedEventLabPreviewPane |
|
|
|
|
markupMode={markupMode} |
|
|
|
|
source={previewDoc} |
|
|
|
|
previewAuthorPubkey={previewAuthorPubkey} |
|
|
|
|
previewEmojiTags={mergedLabPreviewEmojiTags} |
|
|
|
|
/> |
|
|
|
|
</div> |
|
|
|
|
</TabsContent> |
|
|
|
|
</Tabs> |
|
|
|
|
</div> |
|
|
|
|
|
|
|
|
|
{formatToolbar ? ( |
|
|
|
|
<div className="shrink-0 border-t bg-muted/20 px-2 py-2">{formatToolbar}</div> |
|
|
|
|
) : null} |
|
|
|
|
|
|
|
|
|
<DialogFooter className="shrink-0 px-4 py-3 border-t gap-2"> |
|
|
|
|
<Button type="button" variant="outline" onClick={() => handleDialogOpenChange(false)}> |
|
|
|
|
{t('Advanced lab cancel undo')} |
|
|
|
|
</Button> |
|
|
|
|
<Button type="button" onClick={handleApply}> |
|
|
|
|
{t('Apply')} |
|
|
|
|
</Button> |
|
|
|
|
</DialogFooter> |
|
|
|
|
</DialogContent> |
|
|
|
|
</Dialog> |
|
|
|
|
) |
|
|
|
|
@ -1137,9 +1143,10 @@ export default function AdvancedEventLabDialog({
@@ -1137,9 +1143,10 @@ export default function AdvancedEventLabDialog({
|
|
|
|
|
/** Responsive shell: ~5× prior max width cap and ~3× vertical use of viewport (still clamped). */ |
|
|
|
|
function cnDialogShell(): string { |
|
|
|
|
return [ |
|
|
|
|
'z-[250] max-w-none flex min-h-0 flex-col gap-0 overflow-hidden p-0', |
|
|
|
|
'z-[250] !flex max-w-none flex-col gap-0 overflow-hidden p-0', |
|
|
|
|
'w-[min(98vw,calc(72rem*5))]', |
|
|
|
|
'h-[min(94vh,calc(28rem*3))]', |
|
|
|
|
'max-h-[min(96vh,90dvh)]' |
|
|
|
|
'max-h-[min(96vh,90dvh)]', |
|
|
|
|
'top-[max(0.5rem,env(safe-area-inset-top,0px))] !translate-y-0', |
|
|
|
|
'sm:top-[50%] sm:!translate-y-[-50%]' |
|
|
|
|
].join(' ') |
|
|
|
|
} |
|
|
|
|
|