@sutrata/editor 0.3.0 → 0.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/ai/VoiceConfirmDialog.js +3 -1
- package/dist/ai/VoiceToolbar.js +8 -8
- package/dist/context/DocumentContext.js +30 -24
- package/dist/editor/SelectionMenu.js +3 -1
- package/dist/file/builtin-exporters.js +20 -24
- package/dist/findreplace/FindReplace.js +31 -22
- package/dist/findreplace/scroll-to-match.d.ts +1 -1
- package/dist/findreplace/scroll-to-match.js +12 -2
- package/dist/i18n/useTranslation.js +1 -1
- package/dist/import/AIImportDialog.js +20 -18
- package/dist/locales/bn.json +195 -13
- package/dist/locales/en.json +194 -12
- package/dist/locales/gu.json +195 -13
- package/dist/locales/hi.json +195 -13
- package/dist/locales/kn.json +195 -13
- package/dist/locales/ml.json +195 -13
- package/dist/locales/mr.json +195 -13
- package/dist/locales/or.json +195 -13
- package/dist/locales/pa.json +194 -12
- package/dist/locales/si.json +195 -13
- package/dist/locales/ta.json +195 -13
- package/dist/locales/te.json +195 -13
- package/dist/navigator/SceneNavigator.js +118 -62
- package/dist/navigator/StatisticsDialog.js +4 -2
- package/dist/navigator/scene-list.d.ts +7 -0
- package/dist/navigator/scene-list.js +14 -0
- package/dist/shell/AppBar.js +2 -2
- package/dist/shell/AppShell.js +1 -1
- package/dist/shell/ConfirmDialog.js +4 -2
- package/dist/shell/ElementToolbar.js +4 -2
- package/dist/shell/LanguageStatus.js +3 -1
- package/dist/shell/StatusBar.js +1 -1
- package/dist/shell/VersionHistory.js +4 -2
- package/dist/source/find-highlight-source.d.ts +1 -1
- package/dist/source/find-highlight-source.js +3 -2
- package/dist/styles/screenplay.css +12 -0
- package/dist/titlepage/ExportDialog.js +6 -6
- package/dist/titlepage/TitlePageDialog.js +2 -2
- package/package.json +1 -1
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { useLayoutEffect, useMemo, useRef, useState } from 'react';
|
|
3
3
|
import { diffWordsWithSpace } from 'diff';
|
|
4
|
+
import { useTranslation } from '../i18n/useTranslation';
|
|
4
5
|
// Word-level diff over the full text (not line-bucketed): if only one word in
|
|
5
6
|
// a sentence changed, only that word is marked added/removed — the rest of
|
|
6
7
|
// the sentence comes back as an unchanged, unstyled Change chunk. Whitespace
|
|
@@ -17,6 +18,7 @@ function formatTimestamp(ts) {
|
|
|
17
18
|
});
|
|
18
19
|
}
|
|
19
20
|
export function VersionHistory({ versions, filePath, onRestore, onClearAll, visible, onClose }) {
|
|
21
|
+
const { t } = useTranslation();
|
|
20
22
|
const [selectedId, setSelectedId] = useState(null);
|
|
21
23
|
const diffScrollRef = useRef(null);
|
|
22
24
|
// Maps a diff-part index (only added/removed parts) to its rendered <span>,
|
|
@@ -75,7 +77,7 @@ export function VersionHistory({ versions, filePath, onRestore, onClearAll, visi
|
|
|
75
77
|
if (!visible || !filePath)
|
|
76
78
|
return null;
|
|
77
79
|
return (_jsx("div", { className: "cs-dialog-overlay", role: "presentation", onClick: e => { if (e.target === e.currentTarget)
|
|
78
|
-
onClose(); }, children: _jsxs("div", { className: "cs-dialog", role: "dialog", "aria-modal": "true", "aria-labelledby": "cs-version-dialog-title", style: { maxWidth: '620px', width: '92%', maxHeight: '80vh', display: 'flex', flexDirection: 'column' }, children: [_jsxs("div", { className: "cs-panel-header", children: [_jsx("span", { id: "cs-version-dialog-title", className: "cs-panel-title", children:
|
|
80
|
+
onClose(); }, children: _jsxs("div", { className: "cs-dialog", role: "dialog", "aria-modal": "true", "aria-labelledby": "cs-version-dialog-title", style: { maxWidth: '620px', width: '92%', maxHeight: '80vh', display: 'flex', flexDirection: 'column' }, children: [_jsxs("div", { className: "cs-panel-header", children: [_jsx("span", { id: "cs-version-dialog-title", className: "cs-panel-title", children: t('version.title') }), _jsx("button", { className: "cs-panel-close", onClick: onClose, "aria-label": t('common.close'), children: "\u00D7" })] }), _jsxs("div", { className: "cs-version-body", children: [_jsx("div", { className: "cs-version-list", children: versions.length === 0 ? (_jsx("div", { className: "cs-version-empty", children: t('version.empty') })) : (versions.map((v, idx) => (_jsxs("button", { type: "button", className: `cs-version-list-item${selectedId === v.id ? ' cs-version-list-item-active' : ''}`, onClick: () => setSelectedId(v.id), children: [_jsx("div", { className: "cs-version-list-item-label", children: idx === 0 ? t('version.current') : formatTimestamp(v.timestamp) }), idx !== 0 && _jsx("div", { className: "cs-version-list-item-date", children: formatTimestamp(v.timestamp) })] }, v.id)))) }), _jsxs("div", { className: "cs-version-diff-wrap", children: [_jsx("div", { className: "cs-version-diff", ref: diffScrollRef, children: !selectedVersion ? (_jsx("div", { className: "cs-version-empty", children: t('version.select') })) : selectedVersion.id === currentVersion?.id ? (_jsx("div", { className: "cs-version-empty", children: t('version.isCurrent') })) : diff ? (diff.every(part => !part.added && !part.removed) ? (_jsx("div", { className: "cs-version-empty", children: t('version.noDiff') })) : (_jsx("div", { className: "cs-version-diff-content", children: diff.map((part, i) => {
|
|
79
81
|
const isChange = part.added || part.removed;
|
|
80
82
|
return (_jsx("span", { ref: isChange ? (el) => {
|
|
81
83
|
if (el)
|
|
@@ -85,5 +87,5 @@ export function VersionHistory({ versions, filePath, onRestore, onClearAll, visi
|
|
|
85
87
|
} : undefined, className: part.added ? 'cs-version-diff-added'
|
|
86
88
|
: part.removed ? 'cs-version-diff-removed'
|
|
87
89
|
: undefined, children: part.value }, i));
|
|
88
|
-
}) }))) : null }), _jsx("div", { className: "cs-version-diff-minimap", "aria-hidden": "true", children: markers.map((m, i) => (_jsx("button", { type: "button", className: `cs-version-diff-marker cs-version-diff-marker-${m.type}`, style: { top: `${m.position * 100}%` }, title: m.type === 'added' ? '
|
|
90
|
+
}) }))) : null }), _jsx("div", { className: "cs-version-diff-minimap", "aria-hidden": "true", children: markers.map((m, i) => (_jsx("button", { type: "button", className: `cs-version-diff-marker cs-version-diff-marker-${m.type}`, style: { top: `${m.position * 100}%` }, title: m.type === 'added' ? t('version.jumpAdded') : t('version.jumpRemoved'), onClick: () => scrollToMarker(m.position) }, i))) })] })] }), _jsxs("div", { className: "cs-version-footer", children: [_jsx("button", { type: "button", className: "cs-confirm-btn-cancel cs-version-clear-btn", onClick: () => void onClearAll(), disabled: versions.length === 0, children: t('version.delete') }), _jsxs("div", { style: { display: 'flex', gap: '10px' }, children: [_jsx("button", { type: "button", className: "cs-confirm-btn-cancel", onClick: onClose, children: t('common.close') }), selectedVersion && selectedVersion.id !== currentVersion?.id && (_jsx("button", { type: "button", className: "cs-confirm-btn-primary", onClick: () => onRestore(selectedVersion), children: t('version.restore') }))] })] })] }) }));
|
|
89
91
|
}
|
|
@@ -11,4 +11,4 @@ export declare function setSourceFindHighlights(matches: SourceMatch[], activeIn
|
|
|
11
11
|
/** Called by FindReplace when the panel closes — clears all source-view highlights. */
|
|
12
12
|
export declare function clearSourceFindHighlights(): void;
|
|
13
13
|
/** Scroll the source view so the given match is visible. */
|
|
14
|
-
export declare function scrollToSourceMatch(match: SourceMatch): void;
|
|
14
|
+
export declare function scrollToSourceMatch(match: SourceMatch, center?: boolean): void;
|
|
@@ -39,9 +39,10 @@ export function clearSourceFindHighlights() {
|
|
|
39
39
|
setSourceFindHighlights([], 0);
|
|
40
40
|
}
|
|
41
41
|
/** Scroll the source view so the given match is visible. */
|
|
42
|
-
export function scrollToSourceMatch(match) {
|
|
42
|
+
export function scrollToSourceMatch(match, center = true) {
|
|
43
43
|
const view = getSourceView();
|
|
44
44
|
if (!view)
|
|
45
45
|
return;
|
|
46
|
-
|
|
46
|
+
// 'nearest' only scrolls when the match is off-screen (used while typing).
|
|
47
|
+
view.dispatch({ effects: EditorView.scrollIntoView(match.start, { y: center ? 'center' : 'nearest' }) });
|
|
47
48
|
}
|
|
@@ -3117,3 +3117,15 @@ html, body, #root { height: 100%; margin: 0; padding: 0; overflow: hidden; }
|
|
|
3117
3117
|
color: var(--cs-ui-warning, #c2410c); background: var(--cs-ui-warning-subtle, #fff7ed);
|
|
3118
3118
|
user-select: none; vertical-align: middle;
|
|
3119
3119
|
}
|
|
3120
|
+
|
|
3121
|
+
/* Section headings (acts, sequences) shown as anchors in the navigator. */
|
|
3122
|
+
.cs-nav-section-anchor {
|
|
3123
|
+
background: var(--cs-ui-bg-panel-subtle, #f4f2ea);
|
|
3124
|
+
border-bottom: 1px solid var(--cs-ui-border-light, #e2e0d6);
|
|
3125
|
+
}
|
|
3126
|
+
.cs-nav-section-anchor .cs-nav-heading {
|
|
3127
|
+
font-weight: 700;
|
|
3128
|
+
text-transform: uppercase;
|
|
3129
|
+
font-size: 11px;
|
|
3130
|
+
letter-spacing: 0.04em;
|
|
3131
|
+
}
|
|
@@ -80,12 +80,12 @@ export function ExportDialog() {
|
|
|
80
80
|
setWarnings(output && !(output instanceof Blob) ? output.warnings ?? [] : []);
|
|
81
81
|
if (blob)
|
|
82
82
|
downloadBlob(selected.fileName(ctx), blob);
|
|
83
|
-
showToast(selected.successMessage ??
|
|
83
|
+
showToast(selected.successMessage ?? t('export.exported').replace('{label}', selected.label), blob ? 'success' : 'info');
|
|
84
84
|
}
|
|
85
85
|
catch (err) {
|
|
86
86
|
console.error('Export failed', err);
|
|
87
87
|
setWarnings(['An error occurred during export. Please check the console.']);
|
|
88
|
-
showToast('
|
|
88
|
+
showToast(t('export.failed'), 'error');
|
|
89
89
|
}
|
|
90
90
|
finally {
|
|
91
91
|
setIsExporting(false);
|
|
@@ -102,14 +102,14 @@ export function ExportDialog() {
|
|
|
102
102
|
return (_jsx("div", { className: "cs-export-overlay", role: "presentation", onClick: e => {
|
|
103
103
|
if (e.target === e.currentTarget)
|
|
104
104
|
setExportVisible(false);
|
|
105
|
-
}, children: _jsxs("div", { className: "cs-export-dialog", role: "dialog", "aria-modal": "true", "aria-labelledby": "cs-export-title", style: { maxHeight: '90vh', maxWidth: '540px', width: '92%', display: 'flex', flexDirection: 'column' }, children: [_jsxs("div", { className: "cs-panel-header", children: [_jsx("span", { id: "cs-export-title", className: "cs-panel-title", children: t('export.title') }), _jsx("button", { className: "cs-panel-close", onClick: () => setExportVisible(false), "aria-label":
|
|
105
|
+
}, children: _jsxs("div", { className: "cs-export-dialog", role: "dialog", "aria-modal": "true", "aria-labelledby": "cs-export-title", style: { maxHeight: '90vh', maxWidth: '540px', width: '92%', display: 'flex', flexDirection: 'column' }, children: [_jsxs("div", { className: "cs-panel-header", children: [_jsx("span", { id: "cs-export-title", className: "cs-panel-title", children: t('export.title') }), _jsx("button", { className: "cs-panel-close", onClick: () => setExportVisible(false), "aria-label": t('common.close'), children: "\u00D7" })] }), _jsxs("div", { className: "cs-panel-body", style: { overflowY: 'auto', flex: 1, padding: '16px' }, children: [_jsxs("div", { className: "cs-export-segmented", role: "tablist", "aria-label": t('export.category'), children: [_jsx("button", { type: "button", role: "tab", "aria-selected": tab === 'screenplay', className: `cs-export-seg-btn${tab === 'screenplay' ? ' cs-export-seg-btn-active' : ''}`, onClick: () => {
|
|
106
106
|
setTab('screenplay');
|
|
107
107
|
if (selected?.group !== 'screenplay')
|
|
108
108
|
setFormatId(screenplayFormats[0]?.id ?? '');
|
|
109
|
-
}, children:
|
|
109
|
+
}, children: t('export.tab.screenplay') }), reportFormats.length > 0 && _jsx("button", { type: "button", role: "tab", "aria-selected": tab === 'reports', className: `cs-export-seg-btn${tab === 'reports' ? ' cs-export-seg-btn-active' : ''}`, onClick: () => {
|
|
110
110
|
setTab('reports');
|
|
111
111
|
if (selected?.group !== 'report')
|
|
112
112
|
setFormatId(reportFormats[0]?.id ?? '');
|
|
113
|
-
}, children:
|
|
114
|
-
setFormatId(f.id); }, children: [_jsx("input", { type: "radio", name: "format", value: f.id, checked: selected?.id === f.id, onChange: () => setFormatId(f.id), style: { marginTop: '2px' } }), _jsxs("div", { children: [_jsx("strong", { style: { fontSize: '13px', display: 'block', color: 'var(--cs-ui-text-light-primary, #1c1b18)' }, children: f.label }), f.description && (_jsx("span", { style: { fontSize: '11px', color: 'var(--cs-ui-text-light-secondary, #59574f)' }, children: f.description }))] })] }, f.id))) }), showStylePicker && (_jsxs("div", { className: "cs-settings-row", style: { marginTop: '14px', padding: '10px', background: 'var(--cs-ui-bg-panel-subtle, #f4f2ea)', borderRadius: '6px' }, children: [_jsx("label", { className: "cs-settings-label", htmlFor: "cs-export-style-select", style: { fontSize: '12px' }, children: t('export.style') }), _jsxs("select", { id: "cs-export-style-select", className: "cs-settings-select", value: styleOverride, onChange: e => setStyleOverride(e.target.value), children: [_jsxs("option", { value: "", children: [t('export.styleDefault'), " (", resolvedStyle.name, ")"] }), styleChoices.map(s => (_jsx("option", { value: s.id, children: s.name }, s.id)))] })] })), showSkipNotes && (_jsxs("div", { className: "cs-settings-row", style: { marginTop: '8px', padding: '10px', background: 'var(--cs-ui-bg-panel-subtle, #f4f2ea)', borderRadius: '6px', display: 'flex', alignItems: 'center', gap: '8px' }, children: [_jsx("input", { id: "cs-export-skip-notes", type: "checkbox", checked: skipNotes, onChange: e => setSkipNotes(e.target.checked) }), _jsx("label", { htmlFor: "cs-export-skip-notes", className: "cs-settings-label", style: { fontSize: '12px', margin: 0 }, children:
|
|
113
|
+
}, children: t('export.tab.reports') })] }), tab === 'screenplay' ? (_jsxs("div", { children: [_jsx("div", { className: "cs-export-card-grid", children: screenplayFormats.map(f => (_jsxs("div", { className: `cs-export-format-card${selected?.id === f.id ? ' cs-export-format-card-selected' : ''}`, onClick: () => setFormatId(f.id), role: "radio", "aria-checked": selected?.id === f.id, tabIndex: 0, onKeyDown: e => { if (e.key === 'Enter' || e.key === ' ')
|
|
114
|
+
setFormatId(f.id); }, children: [_jsx("input", { type: "radio", name: "format", value: f.id, checked: selected?.id === f.id, onChange: () => setFormatId(f.id), style: { marginTop: '2px' } }), _jsxs("div", { children: [_jsx("strong", { style: { fontSize: '13px', display: 'block', color: 'var(--cs-ui-text-light-primary, #1c1b18)' }, children: f.label }), f.description && (_jsx("span", { style: { fontSize: '11px', color: 'var(--cs-ui-text-light-secondary, #59574f)' }, children: f.description }))] })] }, f.id))) }), showStylePicker && (_jsxs("div", { className: "cs-settings-row", style: { marginTop: '14px', padding: '10px', background: 'var(--cs-ui-bg-panel-subtle, #f4f2ea)', borderRadius: '6px' }, children: [_jsx("label", { className: "cs-settings-label", htmlFor: "cs-export-style-select", style: { fontSize: '12px' }, children: t('export.style') }), _jsxs("select", { id: "cs-export-style-select", className: "cs-settings-select", value: styleOverride, onChange: e => setStyleOverride(e.target.value), children: [_jsxs("option", { value: "", children: [t('export.styleDefault'), " (", resolvedStyle.name, ")"] }), styleChoices.map(s => (_jsx("option", { value: s.id, children: s.name }, s.id)))] })] })), showSkipNotes && (_jsxs("div", { className: "cs-settings-row", style: { marginTop: '8px', padding: '10px', background: 'var(--cs-ui-bg-panel-subtle, #f4f2ea)', borderRadius: '6px', display: 'flex', alignItems: 'center', gap: '8px' }, children: [_jsx("input", { id: "cs-export-skip-notes", type: "checkbox", checked: skipNotes, onChange: e => setSkipNotes(e.target.checked) }), _jsx("label", { htmlFor: "cs-export-skip-notes", className: "cs-settings-label", style: { fontSize: '12px', margin: 0 }, children: t('export.skipNotes') })] })), showRomanize && (_jsxs("div", { className: "cs-settings-row", style: { marginTop: '8px', padding: '10px', background: 'var(--cs-ui-bg-panel-subtle, #f4f2ea)', borderRadius: '6px', flexWrap: 'wrap', gap: '8px' }, children: [_jsx("label", { className: "cs-settings-label", htmlFor: "cs-export-romanize-select", style: { fontSize: '12px' }, children: t('export.romanized') }), _jsxs("select", { id: "cs-export-romanize-select", className: "cs-settings-select", value: romanizeScope, onChange: e => setRomanizeScope(e.target.value), children: [_jsx("option", { value: "off", children: t('export.roman.off') }), _jsx("option", { value: "all", children: t('export.roman.all') }), _jsx("option", { value: "dialogue", children: t('export.roman.dialogue') })] }), romanizeScope !== 'off' && (_jsxs("select", { "aria-label": t('export.roman.variant'), className: "cs-settings-select", value: romanizeVariant, onChange: e => setRomanizeVariant(e.target.value), children: [_jsx("option", { value: "strict", children: t('export.roman.strict') }), _jsx("option", { value: "colloquial", children: t('export.roman.colloquial') })] })), romanizeScope !== 'off' && (_jsx("span", { style: { fontSize: '11px', color: 'var(--cs-ui-text-light-secondary, #59574f)', flexBasis: '100%' }, children: t('export.roman.note') }))] }))] })) : (_jsxs("div", { children: [reportFamilies.map(([family, formats]) => (_jsxs("div", { className: "cs-export-report-box", children: [_jsxs("div", { className: "cs-export-report-header", children: [_jsx("span", { className: "cs-export-report-title", children: family }), _jsx("div", { className: "cs-export-chips", children: formats.map(f => (_jsx("button", { type: "button", className: `cs-export-chip${selected?.id === f.id ? ' cs-export-chip-active' : ''}`, onClick: () => setFormatId(f.id), children: f.formatLabel ?? f.label }, f.id))) })] }), formats[0].description && (_jsx("div", { style: { fontSize: '11px', color: 'var(--cs-ui-text-light-secondary, #59574f)' }, children: formats[0].description }))] }, family))), showReportRomanize && (_jsxs("div", { className: "cs-settings-row", style: { marginTop: '8px', padding: '10px', background: 'var(--cs-ui-bg-panel-subtle, #f4f2ea)', borderRadius: '6px', flexWrap: 'wrap', gap: '8px' }, children: [_jsx("label", { className: "cs-settings-label", htmlFor: "cs-export-romanize-reports", style: { fontSize: '12px' }, children: t('export.romanized') }), _jsxs("select", { id: "cs-export-romanize-reports", className: "cs-settings-select", value: romanizeReports ? 'on' : 'off', onChange: e => setRomanizeReports(e.target.value === 'on'), children: [_jsx("option", { value: "off", children: t('export.roman.off') }), _jsx("option", { value: "on", children: t('export.roman.allReports') })] }), romanizeReports && (_jsxs("select", { "aria-label": t('export.roman.variant'), className: "cs-settings-select", value: romanizeVariant, onChange: e => setRomanizeVariant(e.target.value), children: [_jsx("option", { value: "strict", children: t('export.roman.strict') }), _jsx("option", { value: "colloquial", children: t('export.roman.colloquial') })] }))] }))] })), warnings.length > 0 && (_jsxs("div", { className: "cs-export-warnings", style: { background: '#fffbeb', border: '1px solid #fcd34d', padding: '10px', borderRadius: '4px', marginTop: '14px' }, children: [_jsx("div", { className: "cs-export-warn-title", style: { fontWeight: 600, color: '#b45309', fontSize: '12px', marginBottom: '4px' }, children: t('export.warnings') }), warnings.map((w, i) => (_jsxs("div", { className: "cs-export-warn-item", style: { fontSize: '11px', color: '#59574f' }, children: ["\u2022 ", w] }, i)))] }))] }), _jsxs("div", { className: "cs-export-actions", style: { borderTop: '1px solid var(--cs-ui-border-light-subtle, #eeece4)', padding: '12px 16px', display: 'flex', justifyContent: 'flex-end', gap: '8px', background: 'var(--cs-ui-bg-panel-subtle, #f4f2ea)' }, children: [_jsx("button", { type: "button", className: "cs-confirm-btn-cancel", onClick: () => setExportVisible(false), children: t('export.cancel') }), _jsx("button", { type: "button", className: "cs-confirm-btn-primary", onClick: doExport, disabled: isExporting || !selected, children: isExporting ? t('export.exporting') : t('export.download') })] })] }) }));
|
|
115
115
|
}
|
|
@@ -70,12 +70,12 @@ export function TitlePageDialog({ onClose }) {
|
|
|
70
70
|
onClose();
|
|
71
71
|
}
|
|
72
72
|
return (_jsx("div", { className: "cs-export-overlay", role: "presentation", onClick: e => { if (e.target === e.currentTarget)
|
|
73
|
-
onClose(); }, children: _jsxs("div", { className: "cs-export-dialog cs-tp-dialog", role: "dialog", "aria-modal": "true", "aria-labelledby": "cs-tp-title", children: [_jsxs("div", { className: "cs-panel-header", children: [_jsx("span", { id: "cs-tp-title", className: "cs-panel-title", children: t('titlePage.title') }), _jsx("button", { className: "cs-panel-close", onClick: onClose, "aria-label": t('titlePage.cancel'), children: "\u00D7" })] }), _jsxs("div", { className: "cs-tp-body", children: [_jsx("div", { className: "cs-tp-tabs", role: "tablist", "aria-orientation": "vertical", "aria-label": t('titlePage.title'), children: TABS.map(id => (_jsx("button", { ref: el => { tabRefs.current[id] = el; }, type: "button", role: "tab", id: `cs-tp-tab-${id}`, "aria-selected": tab === id, "aria-controls": `cs-tp-panel-${id}`, tabIndex: tab === id ? 0 : -1, className: `cs-tp-tab${tab === id ? ' cs-tp-tab-active' : ''}`, onClick: () => setTab(id), onKeyDown: e => onTabKey(e, id), children: t(`titlePage.section.${id}`) }, id))) }), _jsxs("form", { className: "cs-tp-form", onSubmit: e => { e.preventDefault(); save(); }, children: [_jsxs(Panel, { id: "story", active: tab, children: [_jsx(Field, { label: t('titlePage.field.title'), htmlFor: "cs-tp-f-title", children: _jsx("input", { id: "cs-tp-f-title", ref: firstFieldRef, className: "cs-tp-input", value: form.title, onChange: e => set('title', e.target.value) }) }), form.altTitles.map((alt, i) => (_jsxs("div", { className: "cs-tp-row", children: [_jsxs("select", { "aria-label": t('titlePage.field.titleLanguage'), className: "cs-settings-select cs-tp-lang-select", value: alt.lang, onChange: e => set('altTitles', form.altTitles.map((a, j) => j === i ? { ...a, lang: e.target.value } : a)), children: [_jsx("option", { value: "", children: t('titlePage.chooseLanguage') }), langs.map(l => _jsx("option", { value: l.code, children: l.label }, l.code))] }), _jsx("input", { "aria-label": t('titlePage.field.titleIn'), className: "cs-tp-input", value: alt.text, onChange: e => set('altTitles', form.altTitles.map((a, j) => j === i ? { ...a, text: e.target.value } : a)) }), _jsx("button", { type: "button", className: "cs-tp-remove", "aria-label": t('titlePage.remove'), onClick: () => set('altTitles', form.altTitles.filter((_, j) => j !== i)), children: "\u00D7" })] }, i))), _jsxs("button", { type: "button", className: "cs-tp-add", onClick: () => set('altTitles', [...form.altTitles, { lang: '', text: '' }]), children: ["+ ", t('titlePage.addTitle')] }), _jsx(Field, { label: t('titlePage.field.logline'), htmlFor: "cs-tp-f-logline", hint: _jsx("span", { className: logWords > 50 ? 'cs-tp-count-bad' : logWords > 30 ? 'cs-tp-count-warn' : 'cs-tp-count', children: t('titlePage.words').replace('{n}', String(logWords)) }), children: _jsx("textarea", { id: "cs-tp-f-logline", className: "cs-tp-input", rows: 2, value: form.logline, onChange: e => set('logline', e.target.value) }) })] }), _jsxs(Panel, { id: "credits", active: tab, children: [_jsx(TextField, { id: "author", label: t('titlePage.field.author'), value: form.author, onChange: v => set('author', v) }), _jsx(TextField, { id: "credit", label: t('titlePage.field.credit'), placeholder:
|
|
73
|
+
onClose(); }, children: _jsxs("div", { className: "cs-export-dialog cs-tp-dialog", role: "dialog", "aria-modal": "true", "aria-labelledby": "cs-tp-title", children: [_jsxs("div", { className: "cs-panel-header", children: [_jsx("span", { id: "cs-tp-title", className: "cs-panel-title", children: t('titlePage.title') }), _jsx("button", { className: "cs-panel-close", onClick: onClose, "aria-label": t('titlePage.cancel'), children: "\u00D7" })] }), _jsxs("div", { className: "cs-tp-body", children: [_jsx("div", { className: "cs-tp-tabs", role: "tablist", "aria-orientation": "vertical", "aria-label": t('titlePage.title'), children: TABS.map(id => (_jsx("button", { ref: el => { tabRefs.current[id] = el; }, type: "button", role: "tab", id: `cs-tp-tab-${id}`, "aria-selected": tab === id, "aria-controls": `cs-tp-panel-${id}`, tabIndex: tab === id ? 0 : -1, className: `cs-tp-tab${tab === id ? ' cs-tp-tab-active' : ''}`, onClick: () => setTab(id), onKeyDown: e => onTabKey(e, id), children: t(`titlePage.section.${id}`) }, id))) }), _jsxs("form", { className: "cs-tp-form", onSubmit: e => { e.preventDefault(); save(); }, children: [_jsxs(Panel, { id: "story", active: tab, children: [_jsx(Field, { label: t('titlePage.field.title'), htmlFor: "cs-tp-f-title", children: _jsx("input", { id: "cs-tp-f-title", ref: firstFieldRef, className: "cs-tp-input", value: form.title, onChange: e => set('title', e.target.value) }) }), form.altTitles.map((alt, i) => (_jsxs("div", { className: "cs-tp-row", children: [_jsxs("select", { "aria-label": t('titlePage.field.titleLanguage'), className: "cs-settings-select cs-tp-lang-select", value: alt.lang, onChange: e => set('altTitles', form.altTitles.map((a, j) => j === i ? { ...a, lang: e.target.value } : a)), children: [_jsx("option", { value: "", children: t('titlePage.chooseLanguage') }), langs.map(l => _jsx("option", { value: l.code, children: l.label }, l.code))] }), _jsx("input", { "aria-label": t('titlePage.field.titleIn'), className: "cs-tp-input", value: alt.text, onChange: e => set('altTitles', form.altTitles.map((a, j) => j === i ? { ...a, text: e.target.value } : a)) }), _jsx("button", { type: "button", className: "cs-tp-remove", "aria-label": t('titlePage.remove'), onClick: () => set('altTitles', form.altTitles.filter((_, j) => j !== i)), children: "\u00D7" })] }, i))), _jsxs("button", { type: "button", className: "cs-tp-add", onClick: () => set('altTitles', [...form.altTitles, { lang: '', text: '' }]), children: ["+ ", t('titlePage.addTitle')] }), _jsx(Field, { label: t('titlePage.field.logline'), htmlFor: "cs-tp-f-logline", hint: _jsx("span", { className: logWords > 50 ? 'cs-tp-count-bad' : logWords > 30 ? 'cs-tp-count-warn' : 'cs-tp-count', children: t('titlePage.words').replace('{n}', String(logWords)) }), children: _jsx("textarea", { id: "cs-tp-f-logline", className: "cs-tp-input", rows: 2, value: form.logline, onChange: e => set('logline', e.target.value) }) })] }), _jsxs(Panel, { id: "credits", active: tab, children: [_jsx(TextField, { id: "author", label: t('titlePage.field.author'), value: form.author, onChange: v => set('author', v) }), _jsx(TextField, { id: "credit", label: t('titlePage.field.credit'), placeholder: t('titlePage.placeholder.credit'), value: form.credit, onChange: v => set('credit', v) }), _jsx(TextField, { id: "source", label: t('titlePage.field.source'), value: form.source, onChange: v => set('source', v) }), _jsx(TextField, { id: "story", label: t('titlePage.field.story'), value: form.story, onChange: v => set('story', v) }), _jsx(TextField, { id: "screenplay", label: t('titlePage.field.screenplay'), value: form.screenplay, onChange: v => set('screenplay', v) }), _jsx(TextField, { id: "dialogue", label: t('titlePage.field.dialogue'), value: form.dialogue, onChange: v => set('dialogue', v) })] }), _jsxs(Panel, { id: "draft", active: tab, children: [_jsx(TextField, { id: "draft", label: t('titlePage.field.draft'), placeholder: t('titlePage.placeholder.draft'), value: form.draft, onChange: v => set('draft', v) }), _jsx(TextField, { id: "revision", label: t('titlePage.field.revision'), value: form.revision, onChange: v => set('revision', v) }), _jsx(Field, { label: t('titlePage.field.date'), htmlFor: "cs-tp-f-date", children: _jsx(DateInput, { id: "cs-tp-f-date", value: form.date, onChange: v => set('date', v), usePickerLabel: t('titlePage.usePicker'), useTextLabel: t('titlePage.useText') }) })] }), _jsxs(Panel, { id: "contact", active: tab, children: [_jsx(Field, { label: t('titlePage.field.contact'), htmlFor: "cs-tp-f-contact", children: _jsx("textarea", { id: "cs-tp-f-contact", className: "cs-tp-input", rows: 3, value: form.contact, onChange: e => set('contact', e.target.value) }) }), _jsx(TextField, { id: "copyright", label: t('titlePage.field.copyright'), placeholder: "\u00A9 2026 \u2026", value: form.copyright, onChange: v => set('copyright', v) })] }), _jsxs(Panel, { id: "document", active: tab, children: [_jsx(Field, { label: t('titlePage.field.lang'), htmlFor: "cs-tp-f-lang", children: _jsxs("select", { id: "cs-tp-f-lang", className: "cs-settings-select", value: form.lang, onChange: e => set('lang', e.target.value), children: [_jsx("option", { value: "", children: t('titlePage.notSet') }), langs.map(l => _jsx("option", { value: l.code, children: l.label }, l.code))] }) }), _jsx(Field, { label: t('titlePage.field.langSecondary'), htmlFor: "cs-tp-f-lang2", children: _jsxs("div", { className: "cs-tp-chips", children: [form.langSecondary.map(code => (_jsxs("span", { className: "cs-tp-chip", children: [langLabel(code), _jsx("button", { type: "button", "aria-label": `${t('titlePage.remove')} ${langLabel(code)}`, onClick: () => set('langSecondary', form.langSecondary.filter(c => c !== code)), children: "\u00D7" })] }, code))), _jsxs("select", { id: "cs-tp-f-lang2", className: "cs-settings-select", value: "", onChange: e => {
|
|
74
74
|
const code = e.target.value;
|
|
75
75
|
if (code && !form.langSecondary.includes(code))
|
|
76
76
|
set('langSecondary', [...form.langSecondary, code]);
|
|
77
77
|
}, children: [_jsx("option", { value: "", children: t('titlePage.addLanguage') }), langs.filter(l => l.code !== form.lang && !form.langSecondary.includes(l.code))
|
|
78
|
-
.map(l => _jsx("option", { value: l.code, children: l.label }, l.code))] })] }) }), _jsx(Field, { label: t('titlePage.field.page'), htmlFor: "cs-tp-f-page", children: _jsxs("select", { id: "cs-tp-f-page", className: "cs-settings-select", value: form.page, onChange: e => set('page', e.target.value), children: [_jsx("option", { value: "", children: t('titlePage.pageDefault') }), _jsx("option", { value: "A4", children: "A4" }), _jsx("option", { value: "Letter", children:
|
|
78
|
+
.map(l => _jsx("option", { value: l.code, children: l.label }, l.code))] })] }) }), _jsx(Field, { label: t('titlePage.field.page'), htmlFor: "cs-tp-f-page", children: _jsxs("select", { id: "cs-tp-f-page", className: "cs-settings-select", value: form.page, onChange: e => set('page', e.target.value), children: [_jsx("option", { value: "", children: t('titlePage.pageDefault') }), _jsx("option", { value: "A4", children: "A4" }), _jsx("option", { value: "Letter", children: t('titlePage.pageLetter') })] }) }), _jsx(Field, { label: t('titlePage.field.style'), htmlFor: "cs-tp-f-style", children: _jsxs("select", { id: "cs-tp-f-style", className: "cs-settings-select", value: form.style, onChange: e => set('style', e.target.value), children: [_jsx("option", { value: "", children: t('titlePage.styleDefault').replace('{name}', defaultStyleName) }), styles.map(s => _jsx("option", { value: s.id, children: s.name }, s.id)), form.style && !styles.some(s => s.id === form.style) && (_jsx("option", { value: form.style, children: form.style }))] }) }), _jsx(TextField, { id: "watermark", label: t('titlePage.field.watermark'), placeholder: t('titlePage.placeholder.watermark'), value: form.watermark, onChange: v => set('watermark', v) })] }), _jsxs(Panel, { id: "other", active: tab, children: [form.custom.map((c, i) => (_jsxs("div", { className: "cs-tp-row", children: [_jsx("input", { "aria-label": t('titlePage.field.key'), className: "cs-tp-input cs-tp-key", value: c.key, placeholder: t('titlePage.placeholder.key'), onChange: e => set('custom', form.custom.map((x, j) => j === i ? { ...x, key: e.target.value } : x)) }), _jsx("input", { "aria-label": t('titlePage.field.value'), className: "cs-tp-input", value: c.value, onChange: e => set('custom', form.custom.map((x, j) => j === i ? { ...x, value: e.target.value } : x)) }), _jsx("button", { type: "button", className: "cs-tp-remove", "aria-label": t('titlePage.remove'), onClick: () => set('custom', form.custom.filter((_, j) => j !== i)), children: "\u00D7" })] }, i))), _jsxs("button", { type: "button", className: "cs-tp-add", onClick: () => set('custom', [...form.custom, { key: '', value: '' }]), children: ["+ ", t('titlePage.addField')] }), preservedCount > 0 && (_jsx("p", { className: "cs-tp-note", children: t('titlePage.preserved').replace('{n}', String(preservedCount)) }))] })] })] }), _jsxs("div", { className: "cs-export-actions cs-tp-actions", children: [_jsx("button", { type: "button", className: "cs-confirm-btn-cancel", onClick: onClose, children: t('titlePage.cancel') }), _jsx("button", { type: "button", className: "cs-confirm-btn-primary", onClick: save, children: t('titlePage.save') })] })] }) }));
|
|
79
79
|
}
|
|
80
80
|
function Panel({ id, active, children }) {
|
|
81
81
|
return (_jsx("div", { role: "tabpanel", id: `cs-tp-panel-${id}`, "aria-labelledby": `cs-tp-tab-${id}`, className: "cs-tp-panel", hidden: active !== id, children: children }));
|
package/package.json
CHANGED