@inshapardaz/likhari-react 0.1.7-dev.88 → 0.1.8

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.
@@ -3,10 +3,7 @@ import type { SerializedEditorState } from 'lexical';
3
3
  import { type FormatId } from '@inshapardaz/likhari-converters';
4
4
  import { type EditorFeatureConfig, type FeatureConfigPresetName } from '@inshapardaz/likhari-core';
5
5
  import { type FontOption } from './fonts/index.js';
6
- import { type DraftRestoreMode } from './components/DraftRestore.js';
7
6
  import { type Locale } from './i18n/index.js';
8
- /** What happens when the user is about to leave with unsaved changes. */
9
- export type NavigationGuardMode = 'confirm' | 'save-draft' | 'off';
10
7
  export interface EditorInitialContent {
11
8
  format: Extract<FormatId, 'lexical-json' | 'plain-text'>;
12
9
  value: string;
@@ -73,63 +70,6 @@ export interface EditorRootProps {
73
70
  * `[...DEFAULT_FONT_OPTIONS, { name: 'Mine', family: '"Mine", serif' }]`.
74
71
  */
75
72
  fontOptions?: FontOption[];
76
- /**
77
- * Saves drafts: a debounced autosave of the current content to
78
- * `localStorage` (lexical-editor-spec.md §6.2), a resilience net against an
79
- * accidental tab close that is independent of `onSave`/the Save button. The
80
- * draft is stored under `documentId` when you give one (§6.1); without one, a
81
- * unique id is generated for this editor, so editors never overwrite each
82
- * other's drafts. The toolbar's Drafts button lists every draft in the browser
83
- * to restore or delete. A draft is cleared on a successful explicit save.
84
- * Defaults to `true`.
85
- */
86
- autosave?: boolean;
87
- /**
88
- * What to do on mount when a draft of this `documentId` newer than the initial
89
- * content exists (needs `documentId`):
90
- * - `'prompt'` (default): a banner with Restore / Ignore / Remove draft;
91
- * - `'auto'`: load the draft straight away, no questions (see `onDraftRestored`);
92
- * - `'off'`: keep the initial content; the draft is moved aside into the drafts
93
- * list so new edits don't overwrite it unseen.
94
- */
95
- restoreDraft?: DraftRestoreMode;
96
- /**
97
- * What happens when the user is about to leave with unsaved changes, for both
98
- * `EditorRef.confirmDiscard()` (in-app navigation, which your router guard
99
- * calls) and for closing or refreshing the tab:
100
- * - `'confirm'` (default): `confirmDiscard()` opens an in-editor popup (Save /
101
- * Save draft / Discard changes / Stay). On closing or refreshing the tab no
102
- * popup is possible, and a draft is saved instead when `autosave` is on, so the
103
- * browser's own "leave this page?" prompt is skipped; it only appears as a last
104
- * resort, when no draft could be stored (autosave off, document over
105
- * `autosaveMaxBytes`, storage unavailable);
106
- * - `'save-draft'`: silently saves a draft and lets the user go — no popup, no
107
- * browser prompt. Works even with `autosave={false}`. If the draft can't be
108
- * stored (e.g. the document is over `autosaveMaxBytes`) `confirmDiscard()` falls
109
- * back to the popup, so work is never lost silently;
110
- * - `'off'`: no guard; the user is never asked.
111
- */
112
- navigationGuard?: NavigationGuardMode;
113
- /** Called when a saved draft was loaded into the editor (banner Restore, or `restoreDraft="auto"`). */
114
- onDraftRestored?: (draft: {
115
- documentId: string;
116
- savedAt: number;
117
- }) => void;
118
- /** Debounce delay before writing an autosave draft, in ms. Default `750`. */
119
- autosaveDelayMs?: number;
120
- /**
121
- * Skips (rather than throwing) an autosave write whose JSON would exceed
122
- * this size — `localStorage` has a shared ~5-10MB per-origin ceiling, so a
123
- * single document with embedded base64 images must not be allowed to
124
- * autosave past a sane limit. Default `2_000_000` (~2MB).
125
- */
126
- autosaveMaxBytes?: number;
127
- /**
128
- * How many drafts to keep in the browser, across all documents; the oldest
129
- * beyond this are deleted as new ones are written (this editor's own draft
130
- * is never pruned). Default `20`.
131
- */
132
- autosaveMaxDrafts?: number;
133
73
  }
134
74
  export interface EditorRef {
135
75
  getContent(format: FormatId): string;
@@ -1 +1 @@
1
- {"version":3,"file":"EditorRoot.d.ts","sourceRoot":"","sources":["../src/EditorRoot.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"EditorRoot.d.ts","sourceRoot":"","sources":["../src/EditorRoot.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;AAU1D,OAAO,KAAK,EAAe,qBAAqB,EAAE,MAAM,SAAS,CAAC;AAClE,OAAO,EAAyB,KAAK,QAAQ,EAAE,MAAM,iCAAiC,CAAC;AACvF,OAAO,EAAwB,KAAK,mBAAmB,EAAE,KAAK,uBAAuB,EAAE,MAAM,2BAA2B,CAAC;AAKzH,OAAO,EAAyB,KAAK,UAAU,EAAE,MAAM,SAAS,CAAC;AAIjE,OAAO,EAAgC,KAAK,MAAM,EAAE,MAAM,QAAQ,CAAC;AAEnE,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,OAAO,CAAC,QAAQ,EAAE,cAAc,GAAG,YAAY,CAAC,CAAC;IACzD,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,eAAe;IAC9B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,cAAc,CAAC,EAAE,oBAAoB,CAAC;IACtC,aAAa,CAAC,EAAE,mBAAmB,CAAC;IACpC,aAAa,CAAC,EAAE,uBAAuB,CAAC;IACxC,KAAK,CAAC,EAAE,oBAAoB,CAAC;IAC7B,WAAW,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;IAC/B;;;;;;OAMG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;;;;OAOG;IACH,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACzB,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,qBAAqB,KAAK,IAAI,CAAC;IAClD;;;OAGG;IACH,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,KAAK,IAAI,CAAC;IACrD;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;;;OAIG;IACH,aAAa,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IAChD;;;;;;;OAOG;IACH,UAAU,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5C;;;;;;OAMG;IACH,WAAW,CAAC,EAAE,UAAU,EAAE,CAAC;CAC5B;AAED,MAAM,WAAW,SAAS;IACxB,UAAU,CAAC,MAAM,EAAE,QAAQ,GAAG,MAAM,CAAC;IACrC,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,GAAG,IAAI,CAAC;IAClD,iBAAiB,IAAI,OAAO,CAAC;IAC7B,cAAc,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;IACnC,KAAK,IAAI,IAAI,CAAC;CACf;AAQD,eAAO,MAAM,UAAU,uGAkKrB,CAAC"}
@@ -17,31 +17,19 @@ import { EditorThemeProvider } from './theme/EditorThemeProvider.js';
17
17
  import { Toolbar } from './components/Toolbar.js';
18
18
  import { injectUrduWebFontsCss } from './fonts/index.js';
19
19
  import { LinkPastePlugin } from './plugins/LinkPastePlugin.js';
20
- import { DraftRestore } from './components/DraftRestore.js';
21
- import { LeaveDialog } from './components/LeaveDialog.js';
22
- import { clearDraft, createDraftId, hasDraftContent, pruneDrafts, writeDraft, } from './persistence/draftStorage.js';
23
20
  import { ImageOptionsContext } from './image/ImageOptionsContext.js';
24
21
  import { PortalTargetContext } from './PortalTargetContext.js';
25
22
  import { UiStringsContext, getStrings } from './i18n/index.js';
26
- const DEFAULT_AUTOSAVE_DELAY_MS = 750;
27
- const DEFAULT_AUTOSAVE_MAX_BYTES = 2000000;
28
- const DEFAULT_AUTOSAVE_MAX_DRAFTS = 20;
29
23
  function initialEditorStateJson(initialContent) {
30
24
  if (!initialContent)
31
25
  return undefined;
32
26
  const state = defaultFormatRegistry.parse(initialContent.format, initialContent.value);
33
27
  return JSON.stringify(state);
34
28
  }
35
- export const EditorRoot = forwardRef(function EditorRoot({ documentId, initialContent, featureConfig, featurePreset, theme, colorScheme, accentColor, locale = 'en', placeholder, height = '480px', onChange, onSave, showSave = Boolean(onSave), onImageUpload, fetchImage, fontOptions, autosave = true, restoreDraft = 'prompt', navigationGuard = 'confirm', onDraftRestored, autosaveDelayMs = DEFAULT_AUTOSAVE_DELAY_MS, autosaveMaxBytes = DEFAULT_AUTOSAVE_MAX_BYTES, autosaveMaxDrafts = DEFAULT_AUTOSAVE_MAX_DRAFTS, }, ref) {
29
+ export const EditorRoot = forwardRef(function EditorRoot({ documentId, initialContent, featureConfig, featurePreset, theme, colorScheme, accentColor, locale = 'en', placeholder, height = '480px', onChange, onSave, showSave = Boolean(onSave), onImageUpload, fetchImage, fontOptions, }, ref) {
36
30
  const config = useMemo(() => resolveFeatureConfig(featureConfig, featurePreset), [featureConfig, featurePreset]);
37
31
  const strings = useMemo(() => getStrings(locale), [locale]);
38
32
  const resolvedPlaceholder = placeholder ?? strings.editor.placeholder;
39
- // The draft's storage key: the host's documentId, else — so editors without
40
- // one never overwrite each other — a unique id generated for this editor (or
41
- // the id of an anonymous draft the user restored into it).
42
- const [generatedDraftId] = useState(createDraftId);
43
- const [adoptedDraftId, setAdoptedDraftId] = useState(null);
44
- const draftId = documentId ?? adoptedDraftId ?? generatedDraftId;
45
33
  // The urdu-web-fonts stylesheets are needed for the font dropdown and for
46
34
  // RTL content, whose canvas font (editor.css) is one of those families.
47
35
  useEffect(() => {
@@ -59,136 +47,17 @@ export const EditorRoot = forwardRef(function EditorRoot({ documentId, initialCo
59
47
  const editorStateRef = useRef(null);
60
48
  const lastSavedJsonRef = useRef(null);
61
49
  const [isDirty, setIsDirty] = useState(false);
62
- const isDirtyRef = useRef(isDirty);
63
- isDirtyRef.current = isDirty;
64
- const autosaveTimerRef = useRef(null);
65
- // The latest change not yet written, so unload / unmount can flush it.
66
- const pendingDraftRef = useRef(null);
67
- const flushDraft = () => {
68
- if (autosaveTimerRef.current) {
69
- clearTimeout(autosaveTimerRef.current);
70
- autosaveTimerRef.current = null;
71
- }
72
- const pending = pendingDraftRef.current;
73
- pendingDraftRef.current = null;
74
- if (!pending)
75
- return;
76
- // A document that is blank again isn't worth a draft.
77
- if (hasDraftContent(pending.json)) {
78
- writeDraft(pending.id, pending.json, autosaveMaxBytes);
79
- pruneDrafts(autosaveMaxDrafts, [pending.id]);
80
- }
81
- else {
82
- clearDraft(pending.id);
83
- }
84
- };
85
- const flushDraftRef = useRef(flushDraft);
86
- flushDraftRef.current = flushDraft;
87
- /** Writes the latest content as a draft now, without waiting out the debounce.
88
- * Returns whether it is safely stored (or there was nothing worth storing). */
89
- const saveDraftNow = () => {
90
- if (autosaveTimerRef.current) {
91
- clearTimeout(autosaveTimerRef.current);
92
- autosaveTimerRef.current = null;
93
- }
94
- const latest = editorStateRef.current ? JSON.stringify(editorStateRef.current.toJSON()) : pendingDraftRef.current?.json;
95
- pendingDraftRef.current = null;
96
- if (!latest)
97
- return true;
98
- // A blank document isn't worth a draft.
99
- if (!hasDraftContent(latest)) {
100
- clearDraft(draftId);
101
- return true;
102
- }
103
- const stored = writeDraft(draftId, latest, autosaveMaxBytes);
104
- if (stored)
105
- pruneDrafts(autosaveMaxDrafts, [draftId]);
106
- return stored;
107
- };
108
- const saveDraftNowRef = useRef(saveDraftNow);
109
- saveDraftNowRef.current = saveDraftNow;
110
- const navigationGuardRef = useRef(navigationGuard);
111
- navigationGuardRef.current = navigationGuard;
112
- const autosaveRef = useRef(autosave);
113
- autosaveRef.current = autosave;
114
- // The in-editor "leave?" popup behind confirmDiscard().
115
- const [leavePrompt, setLeavePrompt] = useState(null);
116
- const leaveResolveRef = useRef(null);
117
- const settleLeave = (canLeave) => {
118
- const resolve = leaveResolveRef.current;
119
- leaveResolveRef.current = null;
120
- setLeavePrompt(null);
121
- resolve?.(canLeave);
122
- };
123
- const askToLeave = (draftFailed = false) => new Promise((resolve) => {
124
- leaveResolveRef.current?.(false); // a second call supersedes an unanswered one
125
- leaveResolveRef.current = resolve;
126
- setLeavePrompt({ draftFailed });
127
- });
128
- const confirmDiscardImpl = async () => {
129
- if (!isDirtyRef.current || navigationGuard === 'off')
130
- return true;
131
- if (navigationGuard === 'save-draft') {
132
- if (saveDraftNow())
133
- return true;
134
- return askToLeave(true);
135
- }
136
- return askToLeave();
137
- };
138
- const confirmDiscardRef = useRef(confirmDiscardImpl);
139
- confirmDiscardRef.current = confirmDiscardImpl;
140
- // An unanswered popup must not leave a caller's promise hanging if the editor goes away.
141
- useEffect(() => () => leaveResolveRef.current?.(false), []);
142
- // Computed once, before the first autosave write could possibly run, so
143
- // the restore-prompt plugin below can tell a stored draft that's merely
144
- // identical to the initial content apart (no prompt needed) from one that
145
- // actually represents newer, unsaved work.
146
- const initialContentJsonRef = useRef(undefined);
147
- if (initialContentJsonRef.current === undefined) {
148
- initialContentJsonRef.current = initialEditorStateJson(initialContent);
149
- }
150
50
  const initialConfig = useMemo(() => ({
151
51
  namespace: `likhari-editor-${documentId ?? 'anonymous'}`,
152
52
  nodes: EDITOR_NODES,
153
53
  theme: editorTheme,
154
- editorState: initialContentJsonRef.current,
54
+ editorState: initialEditorStateJson(initialContent),
155
55
  onError(error) {
156
56
  throw error;
157
57
  },
158
58
  }),
159
59
  // eslint-disable-next-line react-hooks/exhaustive-deps
160
60
  []);
161
- // beforeunload (lexical-editor-spec.md §6.4): the automatic half of the
162
- // navigation guard — hasUnsavedChanges()/confirmDiscard() below are the
163
- // imperative half a host's own router guard calls for in-app navigation,
164
- // which the editor can't intercept on its own.
165
- useEffect(() => {
166
- if (typeof window === 'undefined')
167
- return;
168
- const handleBeforeUnload = (event) => {
169
- // Write any edit still waiting out the debounce before the page goes.
170
- flushDraftRef.current();
171
- if (!isDirtyRef.current)
172
- return;
173
- const guard = navigationGuardRef.current;
174
- if (guard === 'off')
175
- return;
176
- // The work is saved as a draft (restorable from the banner / drafts list
177
- // when the page is opened again), so there is nothing to warn about and
178
- // the browser's prompt is skipped. It only appears as a last resort, when
179
- // no draft could be stored (autosave off, document too large, storage
180
- // unavailable) — a page can't customise or replace it, and it is the only
181
- // thing between the user and silently losing their work.
182
- if ((guard === 'save-draft' || autosaveRef.current) && saveDraftNowRef.current())
183
- return;
184
- event.preventDefault();
185
- event.returnValue = '';
186
- };
187
- window.addEventListener('beforeunload', handleBeforeUnload);
188
- return () => window.removeEventListener('beforeunload', handleBeforeUnload);
189
- }, []);
190
- // Unmounting (e.g. in-app navigation) also writes what is still pending.
191
- useEffect(() => () => flushDraftRef.current(), []);
192
61
  useImperativeHandle(ref, () => ({
193
62
  getContent(format) {
194
63
  if (!editorStateRef.current)
@@ -208,35 +77,23 @@ export const EditorRoot = forwardRef(function EditorRoot({ documentId, initialCo
208
77
  hasUnsavedChanges() {
209
78
  return isDirty;
210
79
  },
211
- confirmDiscard() {
212
- return confirmDiscardRef.current();
80
+ async confirmDiscard() {
81
+ if (!isDirty)
82
+ return true;
83
+ if (typeof window === 'undefined')
84
+ return true;
85
+ return window.confirm(strings.editor.confirmDiscard);
213
86
  },
214
87
  focus() {
215
88
  rootElementRef.current?.focus();
216
89
  },
217
- }), [isDirty]);
90
+ }), [isDirty, strings]);
218
91
  const rootElementRef = useRef(null);
219
92
  const handleChange = (state) => {
220
93
  editorStateRef.current = state;
221
94
  const json = JSON.stringify(state.toJSON());
222
95
  setIsDirty(json !== lastSavedJsonRef.current);
223
96
  onChange?.(state.toJSON());
224
- if (autosave) {
225
- pendingDraftRef.current = { id: draftId, json };
226
- if (autosaveTimerRef.current)
227
- clearTimeout(autosaveTimerRef.current);
228
- autosaveTimerRef.current = setTimeout(flushDraft, autosaveDelayMs);
229
- }
230
- };
231
- /** A draft was restored into the editor: that content is unsaved work. */
232
- const handleDraftRestored = (entry) => {
233
- setIsDirty(true);
234
- if (documentId && entry.id === documentId)
235
- onDraftRestored?.({ documentId, savedAt: entry.draft.savedAt });
236
- // Without a documentId the restored draft becomes this editor's own, so
237
- // later edits update it instead of piling up copies.
238
- if (!documentId)
239
- setAdoptedDraftId(entry.id);
240
97
  };
241
98
  const handleSave = () => {
242
99
  if (!editorStateRef.current)
@@ -246,15 +103,6 @@ export const EditorRoot = forwardRef(function EditorRoot({ documentId, initialCo
246
103
  const content = defaultFormatRegistry.serialize(format, json);
247
104
  lastSavedJsonRef.current = JSON.stringify(json);
248
105
  setIsDirty(false);
249
- // A successful explicit save supersedes any in-progress/queued autosave
250
- // draft — don't let a stale one linger and falsely prompt to "restore"
251
- // older content next time this document is opened (§6.2).
252
- if (autosaveTimerRef.current) {
253
- clearTimeout(autosaveTimerRef.current);
254
- autosaveTimerRef.current = null;
255
- }
256
- pendingDraftRef.current = null;
257
- clearDraft(draftId);
258
106
  onSave?.(content, format);
259
107
  };
260
108
  const dir = locale === 'en' ? 'ltr' : 'rtl';
@@ -263,24 +111,5 @@ export const EditorRoot = forwardRef(function EditorRoot({ documentId, initialCo
263
111
  // rather than colliding on a shared one.
264
112
  const portalTargetId = useId();
265
113
  const portalTargetSelector = `#${CSS.escape(portalTargetId)}`;
266
- return (_jsx(EditorThemeProvider, { theme: theme, colorScheme: colorScheme, accentColor: accentColor, scopeElementId: portalTargetId, children: _jsxs("div", { className: "likhari-root", dir: dir, ref: rootElementRef, "data-document-id": documentId, style: { height: typeof height === 'number' ? `${height}px` : height }, children: [_jsx("div", { id: portalTargetId, className: "likhari-portal-target" }), _jsx(PortalTargetContext.Provider, { value: portalTargetSelector, children: _jsxs(UiStringsContext.Provider, { value: strings, children: [_jsx(ImageOptionsContext.Provider, { value: imageOptions, children: _jsxs(LexicalComposer, { initialConfig: initialConfig, children: [_jsx(Toolbar, { config: config, onSave: handleSave, isDirty: isDirty, showSave: showSave, fontOptions: fontOptions, direction: dir, locale: locale, drafts: autosave
267
- ? { currentId: draftId, maxBytes: autosaveMaxBytes, adoptOnRestore: !documentId, onRestored: handleDraftRestored }
268
- : undefined }), documentId && (_jsx(DraftRestore, { draftId: documentId, mode: restoreDraft, initialJson: initialContentJsonRef.current, locale: locale, onRestored: handleDraftRestored })), _jsx("div", { className: "likhari-canvas", children: _jsx(RichTextPlugin, { contentEditable: _jsx(ContentEditable, { className: "likhari-content-editable", dir: dir, "aria-label": strings.editor.contentLabel }), placeholder: _jsx("div", { className: "likhari-placeholder", children: resolvedPlaceholder }), ErrorBoundary: LexicalErrorBoundary }) }), config.history && _jsx(HistoryPlugin, {}), (config.lists.bullet || config.lists.numbered || config.lists.check) && _jsx(ListPlugin, {}), config.lists.check && _jsx(CheckListPlugin, {}), config.links && _jsx(LinkPlugin, {}), config.links && _jsx(LinkPastePlugin, {}), _jsx(OnChangePlugin, { onChange: handleChange })] }) }), _jsx(LeaveDialog, { opened: leavePrompt !== null, canSave: Boolean(onSave), canSaveDraft: autosave || navigationGuard === 'save-draft', draftFailed: leavePrompt?.draftFailed ?? false, onSave: () => {
269
- handleSave();
270
- settleLeave(true);
271
- }, onSaveDraft: () => {
272
- if (saveDraftNow())
273
- settleLeave(true);
274
- else
275
- setLeavePrompt({ draftFailed: true });
276
- }, onDiscard: () => {
277
- // The user chose to drop this work, so no draft of it should linger either.
278
- if (autosaveTimerRef.current) {
279
- clearTimeout(autosaveTimerRef.current);
280
- autosaveTimerRef.current = null;
281
- }
282
- pendingDraftRef.current = null;
283
- clearDraft(draftId);
284
- settleLeave(true);
285
- }, onStay: () => settleLeave(false) })] }) })] }) }));
114
+ return (_jsx(EditorThemeProvider, { theme: theme, colorScheme: colorScheme, accentColor: accentColor, scopeElementId: portalTargetId, children: _jsxs("div", { className: "likhari-root", dir: dir, ref: rootElementRef, "data-document-id": documentId, style: { height: typeof height === 'number' ? `${height}px` : height }, children: [_jsx("div", { id: portalTargetId, className: "likhari-portal-target" }), _jsx(PortalTargetContext.Provider, { value: portalTargetSelector, children: _jsx(UiStringsContext.Provider, { value: strings, children: _jsx(ImageOptionsContext.Provider, { value: imageOptions, children: _jsxs(LexicalComposer, { initialConfig: initialConfig, children: [_jsx(Toolbar, { config: config, onSave: handleSave, isDirty: isDirty, showSave: showSave, fontOptions: fontOptions, direction: dir, locale: locale }), _jsx("div", { className: "likhari-canvas", children: _jsx(RichTextPlugin, { contentEditable: _jsx(ContentEditable, { className: "likhari-content-editable", dir: dir, "aria-label": strings.editor.contentLabel }), placeholder: _jsx("div", { className: "likhari-placeholder", children: resolvedPlaceholder }), ErrorBoundary: LexicalErrorBoundary }) }), config.history && _jsx(HistoryPlugin, {}), (config.lists.bullet || config.lists.numbered || config.lists.check) && _jsx(ListPlugin, {}), config.lists.check && _jsx(CheckListPlugin, {}), config.links && _jsx(LinkPlugin, {}), config.links && _jsx(LinkPastePlugin, {}), _jsx(OnChangePlugin, { onChange: handleChange })] }) }) }) })] }) }));
286
115
  });
@@ -1,4 +1,3 @@
1
- import { type DraftsToolbarOptions } from './DraftsDialog.js';
2
1
  import type { ResolvedEditorFeatureConfig } from '@inshapardaz/likhari-core';
3
2
  import { type FontOption } from '../fonts/index.js';
4
3
  import type { Locale } from '../i18n/strings.js';
@@ -13,8 +12,6 @@ export interface ToolbarProps {
13
12
  direction?: 'ltr' | 'rtl';
14
13
  /** UI locale — picks the translated strings for labels, tooltips and menu items. */
15
14
  locale?: Locale;
16
- /** Autosave drafts: when set, the toolbar offers a Drafts button that lists and restores them. */
17
- drafts?: DraftsToolbarOptions;
18
15
  }
19
- export declare function Toolbar({ config, onSave, isDirty, showSave, fontOptions, direction, locale, drafts }: ToolbarProps): import("react").JSX.Element;
16
+ export declare function Toolbar({ config, onSave, isDirty, showSave, fontOptions, direction, locale }: ToolbarProps): import("react").JSX.Element;
20
17
  //# sourceMappingURL=Toolbar.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"Toolbar.d.ts","sourceRoot":"","sources":["../../src/components/Toolbar.tsx"],"names":[],"mappings":"AA2CA,OAAO,EAAgB,KAAK,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAEzE,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,2BAA2B,CAAC;AAC7E,OAAO,EAA6D,KAAK,UAAU,EAAE,MAAM,UAAU,CAAC;AAItG,OAAO,KAAK,EAAE,MAAM,EAAW,MAAM,iBAAiB,CAAC;AAsUvD,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,2BAA2B,CAAC;IACpC,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IACpB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,sEAAsE;IACtE,WAAW,CAAC,EAAE,UAAU,EAAE,CAAC;IAC3B,wFAAwF;IACxF,SAAS,CAAC,EAAE,KAAK,GAAG,KAAK,CAAC;IAC1B,oFAAoF;IACpF,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,kGAAkG;IAClG,MAAM,CAAC,EAAE,oBAAoB,CAAC;CAC/B;AAED,wBAAgB,OAAO,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,WAAkC,EAAE,SAAiB,EAAE,MAAa,EAAE,MAAM,EAAE,EAAE,YAAY,+BAqxBxJ"}
1
+ {"version":3,"file":"Toolbar.d.ts","sourceRoot":"","sources":["../../src/components/Toolbar.tsx"],"names":[],"mappings":"AA4CA,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,2BAA2B,CAAC;AAC7E,OAAO,EAA6D,KAAK,UAAU,EAAE,MAAM,UAAU,CAAC;AAItG,OAAO,KAAK,EAAE,MAAM,EAAW,MAAM,iBAAiB,CAAC;AAqUvD,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,2BAA2B,CAAC;IACpC,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IACpB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,sEAAsE;IACtE,WAAW,CAAC,EAAE,UAAU,EAAE,CAAC;IAC3B,wFAAwF;IACxF,SAAS,CAAC,EAAE,KAAK,GAAG,KAAK,CAAC;IAC1B,oFAAoF;IACpF,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,wBAAgB,OAAO,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,WAAkC,EAAE,SAAiB,EAAE,MAAa,EAAE,EAAE,YAAY,+BA8wBhJ"}
@@ -12,13 +12,12 @@ import { ImageDialog } from '../image/ImageDialog.js';
12
12
  import { $createImageNode } from '../image/ImageNode.js';
13
13
  import { $createLinkNode, $isLinkNode, TOGGLE_LINK_COMMAND } from '@lexical/link';
14
14
  import { LinkDialog } from './LinkDialog.js';
15
- import { DraftsDialog } from './DraftsDialog.js';
16
15
  import { normalizeLinkUrl } from '../utils/linkUrl.js';
17
16
  import { CANVAS_FONT_DEFAULTS, DEFAULT_FONT_OPTIONS, FONT_SIZES_PX } from '../fonts/index.js';
18
17
  import { setStyleProperty } from '../utils/style.js';
19
18
  import { useStrings } from '../i18n/useStrings.js';
20
19
  import { usePortalTarget } from '../PortalTargetContext.js';
21
- import { IconAbc, IconAlignCenter, IconAlignJustified, IconAlignLeft, IconAlignRight, IconArrowBackUp, IconArrowForwardUp, IconBold, IconClearFormatting, IconDeviceFloppy, IconDots, IconHistory, IconExternalLink, IconFeather, IconH1, IconH2, IconH3, IconH4, IconH5, IconH6, IconIndentDecrease, IconIndentIncrease, IconItalic, IconLetterCase, IconLetterCaseLower, IconLetterCaseUpper, IconLink, IconLinkOff, IconList, IconListCheck, IconListNumbers, IconPencil, IconPhoto, IconPilcrow, IconQuote, IconSparkles, IconStrikethrough, IconSubscript, IconSuperscript, IconTextSize, IconTypography, IconUnderline, IconWand, } from '@tabler/icons-react';
20
+ import { IconAbc, IconAlignCenter, IconAlignJustified, IconAlignLeft, IconAlignRight, IconArrowBackUp, IconArrowForwardUp, IconBold, IconClearFormatting, IconDeviceFloppy, IconDots, IconExternalLink, IconFeather, IconH1, IconH2, IconH3, IconH4, IconH5, IconH6, IconIndentDecrease, IconIndentIncrease, IconItalic, IconLetterCase, IconLetterCaseLower, IconLetterCaseUpper, IconLink, IconLinkOff, IconList, IconListCheck, IconListNumbers, IconPencil, IconPhoto, IconPilcrow, IconQuote, IconSparkles, IconStrikethrough, IconSubscript, IconSuperscript, IconTextSize, IconTypography, IconUnderline, IconWand, } from '@tabler/icons-react';
22
21
  /** Sentinel for "no inline style": Lexical returns the default it is given when
23
22
  * the selection has none, so this tells "unstyled" (show the canvas default)
24
23
  * apart from "styled with a value the dropdown doesn't list" (show nothing). */
@@ -120,12 +119,11 @@ function LinkMenuItems({ url, onEdit, onRemove, strings }) {
120
119
  // Not a URL the editor would accept (e.g. loaded from a document): show it, don't make it clickable.
121
120
  _jsx(Menu.Item, { disabled: true, title: url, className: "likhari-link-menu-url", children: url || strings.link.noUrl })), _jsx(Menu.Item, { leftSection: _jsx(IconPencil, { size: ICON_SIZE, stroke: ICON_STROKE }), onMouseDown: (e) => e.preventDefault(), onClick: onEdit, children: strings.link.editLink }), _jsx(Menu.Item, { color: "red", leftSection: _jsx(IconLinkOff, { size: ICON_SIZE, stroke: ICON_STROKE }), onMouseDown: (e) => e.preventDefault(), onClick: onRemove, children: strings.link.removeLink })] }));
122
121
  }
123
- export function Toolbar({ config, onSave, isDirty, showSave, fontOptions = DEFAULT_FONT_OPTIONS, direction = 'ltr', locale = 'en', drafts }) {
122
+ export function Toolbar({ config, onSave, isDirty, showSave, fontOptions = DEFAULT_FONT_OPTIONS, direction = 'ltr', locale = 'en' }) {
124
123
  const [editor] = useLexicalComposerContext();
125
124
  const [state, setState] = useState(INITIAL_STATE);
126
125
  const strings = useStrings(locale);
127
126
  const portalTarget = usePortalTarget();
128
- const [draftsOpen, setDraftsOpen] = useState(false);
129
127
  // Responsive "priority+" overflow: the toolbar's outer container and a
130
128
  // hidden nowrap clone (rendered with every movable group forced inline)
131
129
  // are both measured; whenever the clone's natural width exceeds the
@@ -586,7 +584,6 @@ export function Toolbar({ config, onSave, isDirty, showSave, fontOptions = DEFAU
586
584
  // the toolbar's own layout width.
587
585
  const fixedGroups = [
588
586
  showSave && (_jsx("div", { className: "likhari-toolbar-group", children: _jsx(ToolbarButton, { icon: IconDeviceFloppy, title: strings.toolbar.save, dirty: Boolean(isDirty), onClick: onSave }) }, "save")),
589
- drafts && (_jsx("div", { className: "likhari-toolbar-group", children: _jsx(ToolbarButton, { icon: IconHistory, title: strings.toolbar.drafts, onClick: () => setDraftsOpen(true) }) }, "drafts")),
590
587
  config.history && (_jsxs("div", { className: "likhari-toolbar-group", children: [_jsx(ToolbarButton, { icon: IconArrowBackUp, title: strings.toolbar.undo, disabled: !state.canUndo, onClick: () => editor.dispatchCommand(UNDO_COMMAND, undefined) }), _jsx(ToolbarButton, { icon: IconArrowForwardUp, title: strings.toolbar.redo, disabled: !state.canRedo, onClick: () => editor.dispatchCommand(REDO_COMMAND, undefined) })] }, "history")),
591
588
  showFormattingGroup && (_jsx("div", { className: "likhari-toolbar-group", children: _jsx(ToolbarSelect, { icon: IconPilcrow, label: strings.toolbar.formattingLabel, width: 148, value: formattingValue, data: formattingOptions, comingSoon: strings.toolbar.comingSoon, renderOption: iconOptionRenderer(FORMATTING_ICONS, IconPilcrow), onChange: withRefocus((v) => applyFormatting(v)) }) }, "formatting")),
592
589
  showInlineGroup && (_jsxs("div", { className: "likhari-toolbar-group", children: [fmt.bold && (_jsx(ToolbarButton, { icon: IconBold, title: strings.toolbar.bold, active: state.activeFormats.has('bold'), onClick: () => formatText('bold') })), fmt.italic && (_jsx(ToolbarButton, { icon: IconItalic, title: strings.toolbar.italic, active: state.activeFormats.has('italic'), onClick: () => formatText('italic') })), fmt.underline && (_jsx(ToolbarButton, { icon: IconUnderline, title: strings.toolbar.underline, active: state.activeFormats.has('underline'), onClick: () => formatText('underline') }))] }, "inline")),
@@ -620,5 +617,5 @@ export function Toolbar({ config, onSave, isDirty, showSave, fontOptions = DEFAU
620
617
  display: 'flex',
621
618
  flexWrap: 'nowrap',
622
619
  gap: 8,
623
- }, children: [fixedGroups, movableGroups.map((group) => (_jsx(MovableGroupButtons, { group: group }, group.key)))] }), (config.images.linked || config.images.embedded) && (_jsx(ImageDialog, { mode: "insert", opened: imageDialogOpen, onSubmit: insertImage, onClose: closeImageDialog })), config.links && (_jsx(LinkDialog, { opened: linkDialogOpen, initialUrl: state.linkUrl, showTextField: linkNeedsText, onSubmit: applyLink, onRemove: state.isLink ? removeLink : undefined, onClose: closeLinkDialog })), drafts && _jsx(DraftsDialog, { opened: draftsOpen, locale: locale, onClose: () => setDraftsOpen(false), ...drafts })] }));
620
+ }, children: [fixedGroups, movableGroups.map((group) => (_jsx(MovableGroupButtons, { group: group }, group.key)))] }), (config.images.linked || config.images.embedded) && (_jsx(ImageDialog, { mode: "insert", opened: imageDialogOpen, onSubmit: insertImage, onClose: closeImageDialog })), config.links && (_jsx(LinkDialog, { opened: linkDialogOpen, initialUrl: state.linkUrl, showTextField: linkNeedsText, onSubmit: applyLink, onRemove: state.isLink ? removeLink : undefined, onClose: closeLinkDialog }))] }));
624
621
  }
@@ -13,6 +13,8 @@ export interface Strings {
13
13
  placeholder: string;
14
14
  /** aria-label on the contenteditable itself. */
15
15
  contentLabel: string;
16
+ /** window.confirm() prompt shown by EditorRef.confirmDiscard() when there are unsaved changes. */
17
+ confirmDiscard: string;
16
18
  };
17
19
  common: {
18
20
  cancel: string;
@@ -23,8 +25,6 @@ export interface Strings {
23
25
  /** aria-label on the toolbar's own role="toolbar" container. */
24
26
  ariaLabel: string;
25
27
  save: string;
26
- /** Opens the list of autosaved drafts. */
27
- drafts: string;
28
28
  undo: string;
29
29
  redo: string;
30
30
  formattingLabel: string;
@@ -72,42 +72,6 @@ export interface Strings {
72
72
  right: string;
73
73
  };
74
74
  };
75
- /** The popup `EditorRef.confirmDiscard()` shows when the user is about to leave with unsaved changes (lexical-editor-spec.md §6.4). */
76
- leaveDialog: {
77
- title: string;
78
- message: string;
79
- save: string;
80
- saveDraft: string;
81
- discard: string;
82
- stay: string;
83
- /** Shown when a draft could not be stored (document too large, or storage unavailable). */
84
- saveDraftFailed: string;
85
- };
86
- /** Autosave drafts (lexical-editor-spec.md §6.2): the restore banner and the drafts list dialog. */
87
- drafts: {
88
- /** Banner shown when a newer unsaved draft of this document is found; `when` is a formatted date/time. */
89
- bannerMessage: (when: string) => string;
90
- restore: string;
91
- ignore: string;
92
- remove: string;
93
- dialogTitle: string;
94
- intro: string;
95
- empty: string;
96
- /** Shown for a draft with no text (e.g. only an image). */
97
- noText: string;
98
- thisDocument: string;
99
- untitled: string;
100
- documentLabel: (id: string) => string;
101
- earlierUntitled: string;
102
- earlierVersionOf: (id: string) => string;
103
- savedAt: (when: string) => string;
104
- size: (kb: number) => string;
105
- replacePrompt: string;
106
- replace: string;
107
- deletePrompt: string;
108
- delete: string;
109
- close: string;
110
- };
111
75
  link: {
112
76
  menuLabel: string;
113
77
  noUrl: string;
@@ -1 +1 @@
1
- {"version":3,"file":"strings.d.ts","sourceRoot":"","sources":["../../src/i18n/strings.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"strings.d.ts","sourceRoot":"","sources":["../../src/i18n/strings.ts"],"names":[],"mappings":"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"}