@inshapardaz/likhari-react 0.1.8 → 0.1.9-dev.94

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.
Files changed (35) hide show
  1. package/dist/EditorRoot.d.ts +60 -0
  2. package/dist/EditorRoot.d.ts.map +1 -1
  3. package/dist/EditorRoot.js +183 -10
  4. package/dist/components/DraftRestore.d.ts +24 -0
  5. package/dist/components/DraftRestore.d.ts.map +1 -0
  6. package/dist/components/DraftRestore.js +61 -0
  7. package/dist/components/DraftsDialog.d.ts +25 -0
  8. package/dist/components/DraftsDialog.d.ts.map +1 -0
  9. package/dist/components/DraftsDialog.js +66 -0
  10. package/dist/components/LeaveDialog.d.ts +22 -0
  11. package/dist/components/LeaveDialog.d.ts.map +1 -0
  12. package/dist/components/LeaveDialog.js +15 -0
  13. package/dist/components/TableDialog.d.ts +17 -0
  14. package/dist/components/TableDialog.d.ts.map +1 -0
  15. package/dist/components/TableDialog.js +33 -0
  16. package/dist/components/Toolbar.d.ts +4 -1
  17. package/dist/components/Toolbar.d.ts.map +1 -1
  18. package/dist/components/Toolbar.js +31 -5
  19. package/dist/i18n/strings.d.ts +45 -2
  20. package/dist/i18n/strings.d.ts.map +1 -1
  21. package/dist/i18n/strings.js +117 -3
  22. package/dist/index.d.ts +2 -1
  23. package/dist/index.d.ts.map +1 -1
  24. package/dist/nodes.d.ts.map +1 -1
  25. package/dist/nodes.js +4 -0
  26. package/dist/persistence/draftStorage.d.ts +55 -0
  27. package/dist/persistence/draftStorage.d.ts.map +1 -0
  28. package/dist/persistence/draftStorage.js +198 -0
  29. package/dist/persistence/draftUi.d.ts +9 -0
  30. package/dist/persistence/draftUi.d.ts.map +1 -0
  31. package/dist/persistence/draftUi.js +23 -0
  32. package/dist/theme/editor.css +105 -0
  33. package/dist/theme/editorTheme.d.ts.map +1 -1
  34. package/dist/theme/editorTheme.js +5 -0
  35. package/package.json +2 -1
@@ -0,0 +1,33 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useEffect, useState } from 'react';
3
+ import { Button, Checkbox, Group, Modal, NumberInput } from '@mantine/core';
4
+ import { useUiStrings } from '../i18n/useStrings.js';
5
+ import { usePortalTarget } from '../PortalTargetContext.js';
6
+ const MIN_DIMENSION = 1;
7
+ const MAX_DIMENSION = 20;
8
+ const DEFAULT_ROWS = 3;
9
+ const DEFAULT_COLUMNS = 3;
10
+ /**
11
+ * Insert-table dialog: rows x columns and an optional header row. Cell
12
+ * merge/split is intentionally not offered anywhere in this dialog or the
13
+ * table it creates — see the comment on `TablePlugin` in `EditorRoot.tsx`.
14
+ */
15
+ export function TableDialog({ opened, onSubmit, onClose }) {
16
+ const strings = useUiStrings();
17
+ const portalTarget = usePortalTarget();
18
+ const [rows, setRows] = useState(DEFAULT_ROWS);
19
+ const [columns, setColumns] = useState(DEFAULT_COLUMNS);
20
+ const [headerRow, setHeaderRow] = useState(true);
21
+ useEffect(() => {
22
+ if (!opened)
23
+ return;
24
+ setRows(DEFAULT_ROWS);
25
+ setColumns(DEFAULT_COLUMNS);
26
+ setHeaderRow(true);
27
+ }, [opened]);
28
+ const handleSubmit = (e) => {
29
+ e.preventDefault();
30
+ onSubmit({ rows, columns, headerRow });
31
+ };
32
+ return (_jsx(Modal, { opened: opened, onClose: onClose, title: strings.tableDialog.title, centered: true, size: "sm", portalProps: { target: portalTarget }, children: _jsxs("form", { onSubmit: handleSubmit, children: [_jsxs(Group, { grow: true, align: "flex-end", children: [_jsx(NumberInput, { label: strings.tableDialog.rows, min: MIN_DIMENSION, max: MAX_DIMENSION, value: rows, onChange: (v) => setRows(typeof v === 'number' ? v : DEFAULT_ROWS), "data-autofocus": true }), _jsx(NumberInput, { label: strings.tableDialog.columns, min: MIN_DIMENSION, max: MAX_DIMENSION, value: columns, onChange: (v) => setColumns(typeof v === 'number' ? v : DEFAULT_COLUMNS) })] }), _jsx(Checkbox, { mt: "sm", label: strings.tableDialog.headerRow, checked: headerRow, onChange: (e) => setHeaderRow(e.currentTarget.checked) }), _jsxs(Group, { justify: "flex-end", gap: "xs", mt: "md", children: [_jsx(Button, { variant: "default", onClick: onClose, children: strings.common.cancel }), _jsx(Button, { type: "submit", children: strings.common.insert })] })] }) }));
33
+ }
@@ -1,3 +1,4 @@
1
+ import { type DraftsToolbarOptions } from './DraftsDialog.js';
1
2
  import type { ResolvedEditorFeatureConfig } from '@inshapardaz/likhari-core';
2
3
  import { type FontOption } from '../fonts/index.js';
3
4
  import type { Locale } from '../i18n/strings.js';
@@ -12,6 +13,8 @@ export interface ToolbarProps {
12
13
  direction?: 'ltr' | 'rtl';
13
14
  /** UI locale — picks the translated strings for labels, tooltips and menu items. */
14
15
  locale?: Locale;
16
+ /** Autosave drafts: when set, the toolbar offers a Drafts button that lists and restores them. */
17
+ drafts?: DraftsToolbarOptions;
15
18
  }
16
- export declare function Toolbar({ config, onSave, isDirty, showSave, fontOptions, direction, locale }: ToolbarProps): import("react").JSX.Element;
19
+ export declare function Toolbar({ config, onSave, isDirty, showSave, fontOptions, direction, locale, drafts }: ToolbarProps): import("react").JSX.Element;
17
20
  //# sourceMappingURL=Toolbar.d.ts.map
@@ -1 +1 @@
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"}
1
+ {"version":3,"file":"Toolbar.d.ts","sourceRoot":"","sources":["../../src/components/Toolbar.tsx"],"names":[],"mappings":"AA8CA,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;AAwUvD,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,+BAszBxJ"}
@@ -8,16 +8,20 @@ import { $createParagraphNode } from 'lexical';
8
8
  import { $createHeadingNode, $createQuoteNode, $isHeadingNode, $isQuoteNode } from '@lexical/rich-text';
9
9
  import { $isListNode, INSERT_CHECK_LIST_COMMAND, INSERT_ORDERED_LIST_COMMAND, INSERT_UNORDERED_LIST_COMMAND, REMOVE_LIST_COMMAND, } from '@lexical/list';
10
10
  import { $findMatchingParent, $insertNodeToNearestRoot } from '@lexical/utils';
11
+ import { INSERT_HORIZONTAL_RULE_COMMAND } from '@lexical/react/LexicalHorizontalRuleNode';
11
12
  import { ImageDialog } from '../image/ImageDialog.js';
12
13
  import { $createImageNode } from '../image/ImageNode.js';
14
+ import { TableDialog } from './TableDialog.js';
15
+ import { INSERT_TABLE_COMMAND } from '@lexical/table';
13
16
  import { $createLinkNode, $isLinkNode, TOGGLE_LINK_COMMAND } from '@lexical/link';
14
17
  import { LinkDialog } from './LinkDialog.js';
18
+ import { DraftsDialog } from './DraftsDialog.js';
15
19
  import { normalizeLinkUrl } from '../utils/linkUrl.js';
16
20
  import { CANVAS_FONT_DEFAULTS, DEFAULT_FONT_OPTIONS, FONT_SIZES_PX } from '../fonts/index.js';
17
21
  import { setStyleProperty } from '../utils/style.js';
18
22
  import { useStrings } from '../i18n/useStrings.js';
19
23
  import { usePortalTarget } from '../PortalTargetContext.js';
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';
24
+ 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, IconSeparatorHorizontal, IconSparkles, IconStrikethrough, IconSubscript, IconSuperscript, IconTable, IconTextSize, IconTypography, IconUnderline, IconWand, } from '@tabler/icons-react';
21
25
  /** Sentinel for "no inline style": Lexical returns the default it is given when
22
26
  * the selection has none, so this tells "unstyled" (show the canvas default)
23
27
  * apart from "styled with a value the dropdown doesn't list" (show nothing). */
@@ -119,11 +123,12 @@ function LinkMenuItems({ url, onEdit, onRemove, strings }) {
119
123
  // Not a URL the editor would accept (e.g. loaded from a document): show it, don't make it clickable.
120
124
  _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 })] }));
121
125
  }
122
- export function Toolbar({ config, onSave, isDirty, showSave, fontOptions = DEFAULT_FONT_OPTIONS, direction = 'ltr', locale = 'en' }) {
126
+ export function Toolbar({ config, onSave, isDirty, showSave, fontOptions = DEFAULT_FONT_OPTIONS, direction = 'ltr', locale = 'en', drafts }) {
123
127
  const [editor] = useLexicalComposerContext();
124
128
  const [state, setState] = useState(INITIAL_STATE);
125
129
  const strings = useStrings(locale);
126
130
  const portalTarget = usePortalTarget();
131
+ const [draftsOpen, setDraftsOpen] = useState(false);
127
132
  // Responsive "priority+" overflow: the toolbar's outer container and a
128
133
  // hidden nowrap clone (rendered with every movable group forced inline)
129
134
  // are both measured; whenever the clone's natural width exceeds the
@@ -273,6 +278,26 @@ export function Toolbar({ config, onSave, isDirty, showSave, fontOptions = DEFAU
273
278
  });
274
279
  closeImageDialog();
275
280
  };
281
+ const [tableDialogOpen, setTableDialogOpen] = useState(false);
282
+ const openTableDialog = () => {
283
+ snapshotSelection();
284
+ setTableDialogOpen(true);
285
+ };
286
+ const closeTableDialog = () => {
287
+ setTableDialogOpen(false);
288
+ editor.focus();
289
+ };
290
+ const insertTable = ({ rows, columns, headerRow }) => {
291
+ const saved = menuSelectionRef.current;
292
+ if (saved)
293
+ editor.update(() => $setSelection(saved.clone()), { discrete: true });
294
+ editor.dispatchCommand(INSERT_TABLE_COMMAND, {
295
+ rows: String(rows),
296
+ columns: String(columns),
297
+ includeHeaders: { rows: headerRow, columns: false },
298
+ });
299
+ closeTableDialog();
300
+ };
276
301
  /** Applies a font property per `config.font.scope`: to the selection, to
277
302
  * every text node in the document, or (for 'both') to the selection when
278
303
  * there is a range and to the whole document when there isn't. */
@@ -426,7 +451,7 @@ export function Toolbar({ config, onSave, isDirty, showSave, fontOptions = DEFAU
426
451
  const showFormattingGroup = headingLevels.length > 0 || config.lists.bullet || config.lists.numbered || config.lists.check || config.blocks.quote;
427
452
  const showInlineGroup = fmt.bold || fmt.italic || fmt.underline;
428
453
  const showAlignGroup = config.alignment.start || config.alignment.center || config.alignment.justify || config.alignment.left || config.alignment.right;
429
- const showStubInsertGroup = config.images.linked || config.images.embedded || config.poetry.enabled;
454
+ const showStubInsertGroup = config.images.linked || config.images.embedded || config.tables || config.blocks.horizontalRule || config.poetry.enabled;
430
455
  const showLanguageGroup = config.language.autocorrect || config.language.textCleanup || config.language.spellCheck;
431
456
  // The "script & cleanup" and "indent/outdent" groups (UI spec §3.3) render
432
457
  // as normal inline toolbar groups whenever there's room, and only move
@@ -584,6 +609,7 @@ export function Toolbar({ config, onSave, isDirty, showSave, fontOptions = DEFAU
584
609
  // the toolbar's own layout width.
585
610
  const fixedGroups = [
586
611
  showSave && (_jsx("div", { className: "likhari-toolbar-group", children: _jsx(ToolbarButton, { icon: IconDeviceFloppy, title: strings.toolbar.save, dirty: Boolean(isDirty), onClick: onSave }) }, "save")),
612
+ drafts && (_jsx("div", { className: "likhari-toolbar-group", children: _jsx(ToolbarButton, { icon: IconHistory, title: strings.toolbar.drafts, onClick: () => setDraftsOpen(true) }) }, "drafts")),
587
613
  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")),
588
614
  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")),
589
615
  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")),
@@ -595,7 +621,7 @@ export function Toolbar({ config, onSave, isDirty, showSave, fontOptions = DEFAU
595
621
  restoreSelection();
596
622
  openLinkDialog();
597
623
  }, onRemove: removeLink, strings: strings }) })] })) : (_jsx(ToolbarButton, { icon: IconLink, title: strings.toolbar.insertLink, onClick: openLinkDialog })) }, "link")),
598
- showStubInsertGroup && (_jsxs("div", { className: "likhari-toolbar-group likhari-toolbar-group--collapse-tablet", children: [(config.images.linked || config.images.embedded) && (_jsx(ToolbarButton, { icon: IconPhoto, title: strings.toolbar.insertImage, onClick: openImageDialog })), config.poetry.enabled && _jsx(StubButton, { icon: IconFeather, title: strings.toolbar.poetryBlocks, comingSoon: strings.toolbar.comingSoon })] }, "stubInsert")),
624
+ showStubInsertGroup && (_jsxs("div", { className: "likhari-toolbar-group likhari-toolbar-group--collapse-tablet", children: [(config.images.linked || config.images.embedded) && (_jsx(ToolbarButton, { icon: IconPhoto, title: strings.toolbar.insertImage, onClick: openImageDialog })), config.tables && _jsx(ToolbarButton, { icon: IconTable, title: strings.toolbar.insertTable, onClick: openTableDialog }), config.blocks.horizontalRule && (_jsx(ToolbarButton, { icon: IconSeparatorHorizontal, title: strings.toolbar.insertHorizontalRule, onClick: () => editor.dispatchCommand(INSERT_HORIZONTAL_RULE_COMMAND, undefined) })), config.poetry.enabled && _jsx(StubButton, { icon: IconFeather, title: strings.toolbar.poetryBlocks, comingSoon: strings.toolbar.comingSoon })] }, "stubInsert")),
599
625
  showLanguageGroup && (_jsxs("div", { className: "likhari-toolbar-group likhari-toolbar-group--collapse-tablet", children: [config.language.autocorrect && _jsx(StubButton, { icon: IconWand, title: strings.toolbar.autocorrect, comingSoon: strings.toolbar.comingSoon }), config.language.textCleanup && _jsx(StubButton, { icon: IconSparkles, title: strings.toolbar.textCleanup, comingSoon: strings.toolbar.comingSoon }), config.language.spellCheck && _jsx(StubButton, { icon: IconAbc, title: strings.toolbar.spellChecker, comingSoon: strings.toolbar.comingSoon })] }, "language")),
600
626
  ];
601
627
  return (_jsxs("div", { className: "likhari-toolbar", role: "toolbar", "aria-label": strings.toolbar.ariaLabel, ref: toolbarContainerRef, children: [fixedGroups, movableGroups
@@ -617,5 +643,5 @@ export function Toolbar({ config, onSave, isDirty, showSave, fontOptions = DEFAU
617
643
  display: 'flex',
618
644
  flexWrap: 'nowrap',
619
645
  gap: 8,
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 }))] }));
646
+ }, 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.tables && _jsx(TableDialog, { opened: tableDialogOpen, onSubmit: insertTable, onClose: closeTableDialog }), 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 })] }));
621
647
  }
@@ -13,8 +13,6 @@ 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;
18
16
  };
19
17
  common: {
20
18
  cancel: string;
@@ -25,6 +23,8 @@ export interface Strings {
25
23
  /** aria-label on the toolbar's own role="toolbar" container. */
26
24
  ariaLabel: string;
27
25
  save: string;
26
+ /** Opens the list of autosaved drafts. */
27
+ drafts: string;
28
28
  undo: string;
29
29
  redo: string;
30
30
  formattingLabel: string;
@@ -40,6 +40,8 @@ export interface Strings {
40
40
  linkOptions: string;
41
41
  insertLink: string;
42
42
  insertImage: string;
43
+ insertTable: string;
44
+ insertHorizontalRule: string;
43
45
  poetryBlocks: string;
44
46
  comingSoon: (label: string) => string;
45
47
  autocorrect: string;
@@ -72,6 +74,41 @@ export interface Strings {
72
74
  right: string;
73
75
  };
74
76
  };
77
+ /** The popup `EditorRef.confirmDiscard()` shows when the user is about to leave with unsaved changes (lexical-editor-spec.md §6.4). */
78
+ leaveDialog: {
79
+ title: string;
80
+ message: string;
81
+ save: string;
82
+ saveDraft: string;
83
+ discard: string;
84
+ /** Shown when a draft could not be stored (document too large, or storage unavailable). */
85
+ saveDraftFailed: string;
86
+ };
87
+ /** Autosave drafts (lexical-editor-spec.md §6.2): the restore banner and the drafts list dialog. */
88
+ drafts: {
89
+ /** Banner shown when a newer unsaved draft of this document is found; `when` is a formatted date/time. */
90
+ bannerMessage: (when: string) => string;
91
+ restore: string;
92
+ ignore: string;
93
+ remove: string;
94
+ dialogTitle: string;
95
+ intro: string;
96
+ empty: string;
97
+ /** Shown for a draft with no text (e.g. only an image). */
98
+ noText: string;
99
+ thisDocument: string;
100
+ untitled: string;
101
+ documentLabel: (id: string) => string;
102
+ earlierUntitled: string;
103
+ earlierVersionOf: (id: string) => string;
104
+ savedAt: (when: string) => string;
105
+ size: (kb: number) => string;
106
+ replacePrompt: string;
107
+ replace: string;
108
+ deletePrompt: string;
109
+ delete: string;
110
+ close: string;
111
+ };
75
112
  link: {
76
113
  menuLabel: string;
77
114
  noUrl: string;
@@ -88,6 +125,12 @@ export interface Strings {
88
125
  invalidUrl: string;
89
126
  apply: string;
90
127
  };
128
+ tableDialog: {
129
+ title: string;
130
+ rows: string;
131
+ columns: string;
132
+ headerRow: string;
133
+ };
91
134
  imageDialog: {
92
135
  titleInsert: string;
93
136
  titleEdit: 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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"}
@@ -8,7 +8,6 @@ const en = {
8
8
  editor: {
9
9
  placeholder: 'Start writing…',
10
10
  contentLabel: 'Editor content',
11
- confirmDiscard: 'You have unsaved changes. Discard them?',
12
11
  },
13
12
  common: {
14
13
  cancel: 'Cancel',
@@ -18,6 +17,7 @@ const en = {
18
17
  toolbar: {
19
18
  ariaLabel: 'Formatting',
20
19
  save: 'Save',
20
+ drafts: 'Drafts',
21
21
  undo: 'Undo',
22
22
  redo: 'Redo',
23
23
  formattingLabel: 'Formatting',
@@ -33,6 +33,8 @@ const en = {
33
33
  linkOptions: 'Link options',
34
34
  insertLink: 'Insert link (Ctrl+K)',
35
35
  insertImage: 'Insert image',
36
+ insertTable: 'Insert table',
37
+ insertHorizontalRule: 'Insert horizontal rule',
36
38
  poetryBlocks: 'Poetry blocks',
37
39
  comingSoon: (label) => `${label} (coming soon)`,
38
40
  autocorrect: 'Auto-correct',
@@ -65,6 +67,36 @@ const en = {
65
67
  right: 'Align right',
66
68
  },
67
69
  },
70
+ leaveDialog: {
71
+ title: 'Unsaved changes',
72
+ message: 'You have unsaved changes. What would you like to do before leaving?',
73
+ save: 'Save',
74
+ saveDraft: 'Save draft',
75
+ discard: 'Discard',
76
+ saveDraftFailed: "The draft couldn't be saved (the document may be too large, or browser storage is unavailable).",
77
+ },
78
+ drafts: {
79
+ bannerMessage: (when) => `An unsaved draft of this document from ${when} was found.`,
80
+ restore: 'Restore',
81
+ ignore: 'Ignore',
82
+ remove: 'Remove draft',
83
+ dialogTitle: 'Saved drafts',
84
+ intro: 'Drafts are saved in this browser as you type, and removed when you save.',
85
+ empty: 'No drafts yet.',
86
+ noText: '(no text)',
87
+ thisDocument: 'Current document',
88
+ untitled: 'Untitled draft',
89
+ documentLabel: (id) => `Document “${id}”`,
90
+ earlierUntitled: 'Earlier version of an untitled draft',
91
+ earlierVersionOf: (id) => `Earlier version of “${id}”`,
92
+ savedAt: (when) => `Saved ${when}`,
93
+ size: (kb) => `${kb} KB`,
94
+ replacePrompt: 'Replace the current content with this draft?',
95
+ replace: 'Replace',
96
+ deletePrompt: 'Delete this draft?',
97
+ delete: 'Delete',
98
+ close: 'Close',
99
+ },
68
100
  link: {
69
101
  menuLabel: 'Link',
70
102
  noUrl: '(no URL)',
@@ -81,6 +113,12 @@ const en = {
81
113
  invalidUrl: 'Enter a valid http(s), mailto, tel or relative URL',
82
114
  apply: 'Apply',
83
115
  },
116
+ tableDialog: {
117
+ title: 'Insert table',
118
+ rows: 'Rows',
119
+ columns: 'Columns',
120
+ headerRow: 'Header row',
121
+ },
84
122
  imageDialog: {
85
123
  titleInsert: 'Insert image',
86
124
  titleEdit: 'Edit image',
@@ -144,7 +182,6 @@ const ur = {
144
182
  editor: {
145
183
  placeholder: 'لکھنا شروع کریں…',
146
184
  contentLabel: 'ایڈیٹر کا مواد',
147
- confirmDiscard: 'آپ کی غیر محفوظ شدہ تبدیلیاں ہیں۔ کیا انہیں رد کر دیا جائے؟',
148
185
  },
149
186
  common: {
150
187
  cancel: 'منسوخ کریں',
@@ -154,6 +191,7 @@ const ur = {
154
191
  toolbar: {
155
192
  ariaLabel: 'فارمیٹنگ',
156
193
  save: 'محفوظ کریں',
194
+ drafts: 'مسودے',
157
195
  undo: 'کالعدم کریں',
158
196
  redo: 'دوبارہ کریں',
159
197
  formattingLabel: 'فارمیٹنگ',
@@ -169,6 +207,8 @@ const ur = {
169
207
  linkOptions: 'لنک کے اختیارات',
170
208
  insertLink: 'لنک شامل کریں (Ctrl+K)',
171
209
  insertImage: 'تصویر شامل کریں',
210
+ insertTable: 'جدول شامل کریں',
211
+ insertHorizontalRule: 'افقی لکیر شامل کریں',
172
212
  poetryBlocks: 'شاعری کے بلاکس',
173
213
  comingSoon: (label) => `${label} (جلد آ رہا ہے)`,
174
214
  autocorrect: 'خودکار تصحیح',
@@ -201,6 +241,36 @@ const ur = {
201
241
  right: 'دائیں سیدھ',
202
242
  },
203
243
  },
244
+ leaveDialog: {
245
+ title: 'غیر محفوظ شدہ تبدیلیاں',
246
+ message: 'آپ کی تبدیلیاں محفوظ نہیں ہوئیں۔ جانے سے پہلے آپ کیا کرنا چاہیں گے؟',
247
+ save: 'محفوظ کریں',
248
+ saveDraft: 'مسودہ محفوظ کریں',
249
+ discard: 'رد کریں',
250
+ saveDraftFailed: 'مسودہ محفوظ نہیں ہو سکا (دستاویز بہت بڑی ہو سکتی ہے، یا براؤزر کا اسٹوریج دستیاب نہیں)۔',
251
+ },
252
+ drafts: {
253
+ bannerMessage: (when) => `اس دستاویز کا ایک غیر محفوظ شدہ مسودہ (${when}) ملا ہے۔`,
254
+ restore: 'بحال کریں',
255
+ ignore: 'نظر انداز کریں',
256
+ remove: 'مسودہ ہٹائیں',
257
+ dialogTitle: 'محفوظ شدہ مسودے',
258
+ intro: 'لکھتے وقت مسودے اس براؤزر میں خود بخود محفوظ ہوتے ہیں اور محفوظ کرنے پر ہٹا دیے جاتے ہیں۔',
259
+ empty: 'ابھی کوئی مسودہ نہیں۔',
260
+ noText: '(کوئی متن نہیں)',
261
+ thisDocument: 'موجودہ دستاویز',
262
+ untitled: 'بلا عنوان مسودہ',
263
+ documentLabel: (id) => `دستاویز «${id}»`,
264
+ earlierUntitled: 'ایک بلا عنوان مسودے کا پرانا ورژن',
265
+ earlierVersionOf: (id) => `«${id}» کا پرانا ورژن`,
266
+ savedAt: (when) => `محفوظ شدہ: ${when}`,
267
+ size: (kb) => `${kb} کے بی`,
268
+ replacePrompt: 'موجودہ مواد کو اس مسودے سے بدل دیں؟',
269
+ replace: 'بدل دیں',
270
+ deletePrompt: 'یہ مسودہ حذف کریں؟',
271
+ delete: 'حذف کریں',
272
+ close: 'بند کریں',
273
+ },
204
274
  link: {
205
275
  menuLabel: 'لنک',
206
276
  noUrl: '(کوئی یو آر ایل نہیں)',
@@ -217,6 +287,12 @@ const ur = {
217
287
  invalidUrl: 'براہِ کرم ایک درست http(s)، mailto، tel یا رشتہ دار یو آر ایل درج کریں',
218
288
  apply: 'لاگو کریں',
219
289
  },
290
+ tableDialog: {
291
+ title: 'جدول شامل کریں',
292
+ rows: 'قطاریں',
293
+ columns: 'کالم',
294
+ headerRow: 'سرِ فہرست قطار',
295
+ },
220
296
  imageDialog: {
221
297
  titleInsert: 'تصویر شامل کریں',
222
298
  titleEdit: 'تصویر میں ترمیم کریں',
@@ -280,7 +356,6 @@ const paShahmukhi = {
280
356
  editor: {
281
357
  placeholder: 'لکھنا شروع کرو…',
282
358
  contentLabel: 'ایڈیٹر دی سامگری',
283
- confirmDiscard: 'تہاڈیاں کجھ تبدیلیاں سنبھالیاں نئیں گئیاں۔ کی ایہناں نوں رد کر دیئے؟',
284
359
  },
285
360
  common: {
286
361
  cancel: 'رد کرو',
@@ -290,6 +365,7 @@ const paShahmukhi = {
290
365
  toolbar: {
291
366
  ariaLabel: 'فارمیٹنگ',
292
367
  save: 'سنبھالو',
368
+ drafts: 'سودھے',
293
369
  undo: 'پہلاں جیہا کرو',
294
370
  redo: 'مُڑ کرو',
295
371
  formattingLabel: 'فارمیٹنگ',
@@ -305,6 +381,8 @@ const paShahmukhi = {
305
381
  linkOptions: 'لنک دے اختیار',
306
382
  insertLink: 'لنک پاؤ (Ctrl+K)',
307
383
  insertImage: 'تصویر پاؤ',
384
+ insertTable: 'ٹیبل پاؤ',
385
+ insertHorizontalRule: 'لیٹی لکیر پاؤ',
308
386
  poetryBlocks: 'شاعری بلاک',
309
387
  comingSoon: (label) => `${label} (چھیتی آ رہا اے)`,
310
388
  autocorrect: 'خودکار درستی',
@@ -337,6 +415,36 @@ const paShahmukhi = {
337
415
  right: 'سجے سیدھ',
338
416
  },
339
417
  },
418
+ leaveDialog: {
419
+ title: 'غیر محفوظ تبدیلیاں',
420
+ message: 'تہاڈیاں تبدیلیاں سنبھالیاں نئیں گئیاں۔ جان توں پہلاں تسی کی کرنا چاہو گے؟',
421
+ save: 'سنبھالو',
422
+ saveDraft: 'سودھا سنبھالو',
423
+ discard: 'رد کرو',
424
+ saveDraftFailed: 'سودھا سنبھالیا نئیں جا سکیا (دستاویز بہت وڈی ہو سکدی اے، یا براؤزر دی سٹوریج نئیں اے)۔',
425
+ },
426
+ drafts: {
427
+ bannerMessage: (when) => `ایس دستاویز دا اک غیر محفوظ سودھا (${when}) لبھیا اے۔`,
428
+ restore: 'بحال کرو',
429
+ ignore: 'نظر انداز کرو',
430
+ remove: 'سودھا ہٹاؤ',
431
+ dialogTitle: 'سنبھالے ہوئے سودھے',
432
+ intro: 'لکھدیاں ہویاں سودھے ایس براؤزر وچ آپ سنبھلدے نیں تے سنبھالن تے ہٹ جاندے نیں۔',
433
+ empty: 'ہلے کوئی سودھا نئیں۔',
434
+ noText: '(کوئی متن نئیں)',
435
+ thisDocument: 'موجودہ دستاویز',
436
+ untitled: 'بنا ناں دا سودھا',
437
+ documentLabel: (id) => `دستاویز «${id}»`,
438
+ earlierUntitled: 'اک بنا ناں دے سودھے دا پرانا ورژن',
439
+ earlierVersionOf: (id) => `«${id}» دا پرانا ورژن`,
440
+ savedAt: (when) => `سنبھالیا: ${when}`,
441
+ size: (kb) => `${kb} کے بی`,
442
+ replacePrompt: 'موجودہ مواد نوں ایس سودھے نال بدل دیئے؟',
443
+ replace: 'بدل دیو',
444
+ deletePrompt: 'ایہ سودھا مٹا دیئے؟',
445
+ delete: 'مٹاؤ',
446
+ close: 'بند کرو',
447
+ },
340
448
  link: {
341
449
  menuLabel: 'لنک',
342
450
  noUrl: '(کوئی یو آر ایل نئیں)',
@@ -353,6 +461,12 @@ const paShahmukhi = {
353
461
  invalidUrl: 'کِرپا کر کے صحیح http(s)، mailto، tel یا نسبتی یو آر ایل پاؤ',
354
462
  apply: 'لاگو کرو',
355
463
  },
464
+ tableDialog: {
465
+ title: 'ٹیبل پاؤ',
466
+ rows: 'قطاراں',
467
+ columns: 'کالم',
468
+ headerRow: 'سرکڑی قطار',
469
+ },
356
470
  imageDialog: {
357
471
  titleInsert: 'تصویر پاؤ',
358
472
  titleEdit: 'تصویر وچ تبدیلی کرو',
package/dist/index.d.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  export { EditorRoot } from './EditorRoot.js';
2
- export type { EditorRootProps, EditorRef, EditorInitialContent } from './EditorRoot.js';
2
+ export type { EditorRootProps, EditorRef, EditorInitialContent, NavigationGuardMode } from './EditorRoot.js';
3
+ export type { DraftRestoreMode } from './components/DraftRestore.js';
3
4
  export { defaultMantineTheme } from './theme/mantineTheme.js';
4
5
  export { ImageNode, $createImageNode, $isImageNode } from './image/ImageNode.js';
5
6
  export type { ImagePayload, ImageLinkType, SerializedImageNode } from './image/ImageNode.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,YAAY,EAAE,eAAe,EAAE,SAAS,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AACrF,OAAO,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAC3D,OAAO,EAAE,SAAS,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAC9E,YAAY,EAAE,YAAY,EAAE,aAAa,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAC1F,OAAO,EAAE,oBAAoB,EAAE,qBAAqB,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AACrF,YAAY,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAC1C,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,QAAQ,CAAC;AACzF,YAAY,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,YAAY,EAAE,eAAe,EAAE,SAAS,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AAC1G,YAAY,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAClE,OAAO,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAC3D,OAAO,EAAE,SAAS,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAC9E,YAAY,EAAE,YAAY,EAAE,aAAa,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAC1F,OAAO,EAAE,oBAAoB,EAAE,qBAAqB,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AACrF,YAAY,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAC1C,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,QAAQ,CAAC;AACzF,YAAY,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"nodes.d.ts","sourceRoot":"","sources":["../src/nodes.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAOlD;;;;;;;;GAQG;AACH,eAAO,MAAM,YAAY,EAAE,KAAK,CAAC,WAAW,CAAC,EAQ5C,CAAC"}
1
+ {"version":3,"file":"nodes.d.ts","sourceRoot":"","sources":["../src/nodes.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAQlD;;;;;;;;GAQG;AACH,eAAO,MAAM,YAAY,EAAE,KAAK,CAAC,WAAW,CAAC,EAW5C,CAAC"}
package/dist/nodes.js CHANGED
@@ -2,6 +2,7 @@ import { HeadingNode, QuoteNode } from '@lexical/rich-text';
2
2
  import { ListItemNode, ListNode } from '@lexical/list';
3
3
  import { LinkNode } from '@lexical/link';
4
4
  import { HorizontalRuleNode } from '@lexical/react/LexicalHorizontalRuleNode';
5
+ import { TableCellNode, TableNode, TableRowNode } from '@lexical/table';
5
6
  import { ImageNode } from './image/ImageNode.js';
6
7
  /**
7
8
  * Node types registered on the editor at construction time. Per
@@ -19,5 +20,8 @@ export const EDITOR_NODES = [
19
20
  ListItemNode,
20
21
  LinkNode,
21
22
  HorizontalRuleNode,
23
+ TableNode,
24
+ TableRowNode,
25
+ TableCellNode,
22
26
  ImageNode,
23
27
  ];
@@ -0,0 +1,55 @@
1
+ /**
2
+ * Autosave-to-localStorage drafts (lexical-editor-spec.md §6.2). Each draft is
3
+ * keyed by an id: the host's `documentId` when it gives one (§6.1), otherwise
4
+ * a generated unique id, so editors without a `documentId` never overwrite each
5
+ * other's drafts. Every function is a no-op (never throws) when `localStorage`
6
+ * is unavailable (SSR, privacy mode) or a stored value is corrupt — autosave is
7
+ * best-effort, never a hard dependency.
8
+ */
9
+ export interface StoredDraft {
10
+ /** Lexical JSON (as produced by `EditorState.toJSON()`, stringified). */
11
+ json: string;
12
+ /** `Date.now()` at write time — lets a host distinguish a stale draft from a genuinely recent one. */
13
+ savedAt: number;
14
+ /** Bumped only if the stored shape itself changes; lets old drafts be recognised/discarded across an upgrade. */
15
+ version: 1;
16
+ /** First words of the text, for listing drafts without parsing every document. */
17
+ preview?: string;
18
+ /** Set on a draft archived from `documentId` (the id it was an earlier version of). */
19
+ sourceId?: string;
20
+ }
21
+ export interface DraftEntry {
22
+ id: string;
23
+ draft: StoredDraft;
24
+ }
25
+ export declare function draftKey(id: string): string;
26
+ /** A new unique id for a draft whose editor has no `documentId`. */
27
+ export declare function createDraftId(): string;
28
+ /** Whether an id came from createDraftId() rather than a host's `documentId`. */
29
+ export declare function isGeneratedDraftId(id: string): boolean;
30
+ /** One-line text preview of a Lexical JSON document ('' when it has no text). */
31
+ export declare function extractPreview(json: string): string;
32
+ /** Whether a Lexical JSON document has any text or image (a blank one isn't worth a draft). */
33
+ export declare function hasDraftContent(json: string): boolean;
34
+ export declare function readDraft(id: string): StoredDraft | null;
35
+ /**
36
+ * Best-effort write; returns whether the draft was actually stored (callers that
37
+ * promise the user a saved draft must check). Skips (rather than throwing) when `json` exceeds
38
+ * `maxBytes` — localStorage has a shared ~5-10MB per-origin ceiling (§6.2), so a
39
+ * single large document (e.g. embedded base64 images) must not be allowed to
40
+ * autosave past a caller-configured limit — or when the write itself fails
41
+ * (quota exceeded, privacy mode).
42
+ */
43
+ export declare function writeDraft(id: string, json: string, maxBytes: number, sourceId?: string): boolean;
44
+ export declare function clearDraft(id: string): void;
45
+ /** Every stored draft, newest first. */
46
+ export declare function listDrafts(): DraftEntry[];
47
+ /**
48
+ * Keeps a draft that is about to be overwritten or ignored: copies it to a new
49
+ * generated id (remembering `sourceId`) so it stays in the drafts list.
50
+ * Returns the new id, or null if nothing could be copied.
51
+ */
52
+ export declare function archiveDraft(id: string): string | null;
53
+ /** Deletes the oldest drafts beyond `max`, never touching `keepIds`. */
54
+ export declare function pruneDrafts(max: number, keepIds?: string[]): void;
55
+ //# sourceMappingURL=draftStorage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"draftStorage.d.ts","sourceRoot":"","sources":["../../src/persistence/draftStorage.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAKH,MAAM,WAAW,WAAW;IAC1B,yEAAyE;IACzE,IAAI,EAAE,MAAM,CAAC;IACb,sGAAsG;IACtG,OAAO,EAAE,MAAM,CAAC;IAChB,iHAAiH;IACjH,OAAO,EAAE,CAAC,CAAC;IACX,kFAAkF;IAClF,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,uFAAuF;IACvF,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,WAAW,CAAC;CACpB;AAED,wBAAgB,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAE3C;AAED,oEAAoE;AACpE,wBAAgB,aAAa,IAAI,MAAM,CAOtC;AAED,iFAAiF;AACjF,wBAAgB,kBAAkB,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAEtD;AAgDD,iFAAiF;AACjF,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEnD;AAED,+FAA+F;AAC/F,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAErD;AAaD,wBAAgB,SAAS,CAAC,EAAE,EAAE,MAAM,GAAG,WAAW,GAAG,IAAI,CAQxD;AAED;;;;;;;GAOG;AACH,wBAAgB,UAAU,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAgBjG;AAED,wBAAgB,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAQ3C;AAED,wCAAwC;AACxC,wBAAgB,UAAU,IAAI,UAAU,EAAE,CAezC;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAWtD;AAED,wEAAwE;AACxE,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,GAAE,MAAM,EAAO,GAAG,IAAI,CAQrE"}