@k2b/ui 0.34.0 → 0.36.0
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/browser/actions/Dropdown.js +1 -0
- package/dist/browser/actions/Dropdown.js.map +1 -1
- package/dist/browser/content/MapView.js +128 -13
- package/dist/browser/content/MapView.js.map +1 -1
- package/dist/browser/content/MapViewFrame.js +1 -1
- package/dist/browser/content/MapViewFrame.js.map +1 -1
- package/dist/browser/content/MatchText.js +61 -0
- package/dist/browser/content/MatchText.js.map +1 -0
- package/dist/browser/content/index.js +2 -0
- package/dist/browser/content/index.js.map +1 -1
- package/dist/browser/content/map-view-glyphs.js +23 -0
- package/dist/browser/content/map-view-glyphs.js.map +1 -0
- package/dist/browser/content/map-view-live.js +45 -22
- package/dist/browser/content/map-view-live.js.map +1 -1
- package/dist/browser/content/map-view-snapshot.js +191 -0
- package/dist/browser/content/map-view-snapshot.js.map +1 -0
- package/dist/browser/content/map-view-types.js.map +1 -1
- package/dist/browser/inputs/Combobox.js +139 -62
- package/dist/browser/inputs/Combobox.js.map +1 -1
- package/dist/browser/inputs/TextInput.js +1 -1
- package/dist/browser/inputs/TextInput.js.map +1 -1
- package/dist/browser/layout/AppWorkspace.js +73 -70
- package/dist/browser/layout/AppWorkspace.js.map +1 -1
- package/dist/browser/layout/ScrollArea.js +4 -1
- package/dist/browser/layout/ScrollArea.js.map +1 -1
- package/dist/browser/text-editor/TextEditor.js +1358 -0
- package/dist/browser/text-editor/TextEditor.js.map +1 -0
- package/dist/browser/text-editor/clipboard-html.js +152 -0
- package/dist/browser/text-editor/clipboard-html.js.map +1 -0
- package/dist/browser/text-editor/clipboard-loading.js +68 -0
- package/dist/browser/text-editor/clipboard-loading.js.map +1 -0
- package/dist/browser/text-editor/clipboard.js +51 -0
- package/dist/browser/text-editor/clipboard.js.map +1 -0
- package/dist/browser/text-editor/engine.js +125 -0
- package/dist/browser/text-editor/engine.js.map +1 -0
- package/dist/browser/text-editor/format.js +218 -0
- package/dist/browser/text-editor/format.js.map +1 -0
- package/dist/browser/text-editor/formatted.js +164 -0
- package/dist/browser/text-editor/formatted.js.map +1 -0
- package/dist/browser/text-editor/language.js +19 -0
- package/dist/browser/text-editor/language.js.map +1 -0
- package/dist/browser/text-editor/markdown-table.js +563 -0
- package/dist/browser/text-editor/markdown-table.js.map +1 -0
- package/dist/browser/text-editor/messages.js +233 -0
- package/dist/browser/text-editor/messages.js.map +1 -0
- package/dist/browser/text-editor/paste.js +115 -0
- package/dist/browser/text-editor/paste.js.map +1 -0
- package/dist/browser/text-editor/table.js +1760 -0
- package/dist/browser/text-editor/table.js.map +1 -0
- package/dist/browser/text-editor.js +5 -0
- package/dist/browser/text-editor.js.map +1 -0
- package/dist/ssr/actions/Dropdown.js +1 -0
- package/dist/ssr/actions/Dropdown.js.map +1 -1
- package/dist/ssr/content/MapView.js +128 -13
- package/dist/ssr/content/MapView.js.map +1 -1
- package/dist/ssr/content/MapViewFrame.js +1 -1
- package/dist/ssr/content/MapViewFrame.js.map +1 -1
- package/dist/ssr/content/MatchText.js +56 -0
- package/dist/ssr/content/MatchText.js.map +1 -0
- package/dist/ssr/content/index.js +2 -0
- package/dist/ssr/content/index.js.map +1 -1
- package/dist/ssr/content/map-view-glyphs.js +23 -0
- package/dist/ssr/content/map-view-glyphs.js.map +1 -0
- package/dist/ssr/content/map-view-snapshot.js +191 -0
- package/dist/ssr/content/map-view-snapshot.js.map +1 -0
- package/dist/ssr/content/map-view-types.js.map +1 -1
- package/dist/ssr/inputs/Combobox.js +66 -20
- package/dist/ssr/inputs/Combobox.js.map +1 -1
- package/dist/ssr/inputs/TextInput.js.map +1 -1
- package/dist/ssr/layout/AppWorkspace.js +1 -1
- package/dist/ssr/layout/AppWorkspace.js.map +1 -1
- package/dist/ssr/layout/ScrollArea.js +4 -1
- package/dist/ssr/layout/ScrollArea.js.map +1 -1
- package/dist/ssr/text-editor/TextEditor.js +1155 -0
- package/dist/ssr/text-editor/TextEditor.js.map +1 -0
- package/dist/ssr/text-editor/clipboard-html.js +152 -0
- package/dist/ssr/text-editor/clipboard-html.js.map +1 -0
- package/dist/ssr/text-editor/clipboard-loading.js +68 -0
- package/dist/ssr/text-editor/clipboard-loading.js.map +1 -0
- package/dist/ssr/text-editor/clipboard.js +51 -0
- package/dist/ssr/text-editor/clipboard.js.map +1 -0
- package/dist/ssr/text-editor/engine.js +125 -0
- package/dist/ssr/text-editor/engine.js.map +1 -0
- package/dist/ssr/text-editor/format.js +218 -0
- package/dist/ssr/text-editor/format.js.map +1 -0
- package/dist/ssr/text-editor/formatted.js +164 -0
- package/dist/ssr/text-editor/formatted.js.map +1 -0
- package/dist/ssr/text-editor/language.js +19 -0
- package/dist/ssr/text-editor/language.js.map +1 -0
- package/dist/ssr/text-editor/markdown-table.js +563 -0
- package/dist/ssr/text-editor/markdown-table.js.map +1 -0
- package/dist/ssr/text-editor/messages.js +233 -0
- package/dist/ssr/text-editor/messages.js.map +1 -0
- package/dist/ssr/text-editor/paste.js +115 -0
- package/dist/ssr/text-editor/paste.js.map +1 -0
- package/dist/ssr/text-editor/table.js +1760 -0
- package/dist/ssr/text-editor/table.js.map +1 -0
- package/dist/ssr/text-editor.js +5 -0
- package/dist/ssr/text-editor.js.map +1 -0
- package/dist/styles.css +1 -1
- package/dist/types/actions/Dropdown.d.ts +2 -0
- package/dist/types/content/MapViewFrame.d.ts +1 -1
- package/dist/types/content/MatchText.d.ts +21 -0
- package/dist/types/content/index.d.ts +3 -1
- package/dist/types/content/map-view-glyphs.d.ts +5 -0
- package/dist/types/content/map-view-live.d.ts +1 -1
- package/dist/types/content/map-view-snapshot.d.ts +13 -0
- package/dist/types/content/map-view-types.d.ts +15 -0
- package/dist/types/inputs/Combobox.d.ts +12 -0
- package/dist/types/inputs/TextInput.d.ts +2 -1
- package/dist/types/layout/AppWorkspace.d.ts +4 -1
- package/dist/types/layout/ScrollArea.d.ts +2 -0
- package/dist/types/text-editor/TextEditor.d.ts +69 -0
- package/dist/types/text-editor/clipboard-html.d.ts +9 -0
- package/dist/types/text-editor/clipboard-loading.d.ts +8 -0
- package/dist/types/text-editor/clipboard.d.ts +20 -0
- package/dist/types/text-editor/engine.d.ts +34 -0
- package/dist/types/text-editor/format.d.ts +34 -0
- package/dist/types/text-editor/formatted.d.ts +1 -0
- package/dist/types/text-editor/language.d.ts +8 -0
- package/dist/types/text-editor/markdown-table.d.ts +105 -0
- package/dist/types/text-editor/messages.d.ts +113 -0
- package/dist/types/text-editor/paste.d.ts +6 -0
- package/dist/types/text-editor/table.d.ts +81 -0
- package/dist/types/text-editor.d.ts +4 -0
- package/package.json +24 -3
|
@@ -0,0 +1,1155 @@
|
|
|
1
|
+
import { ssrStyleProperty as _$ssrStyleProperty } from "solid-js/web";
|
|
2
|
+
import { ssrStyle as _$ssrStyle } from "solid-js/web";
|
|
3
|
+
import { ssrAttribute as _$ssrAttribute } from "solid-js/web";
|
|
4
|
+
import { memo as _$memo } from "solid-js/web";
|
|
5
|
+
import { ssr as _$ssr } from "solid-js/web";
|
|
6
|
+
import { escape as _$escape } from "solid-js/web";
|
|
7
|
+
import { createComponent as _$createComponent } from "solid-js/web";
|
|
8
|
+
var _tmpl$ = ["<div class=\"k2b-ste-size-picker\">", "", "</div>"],
|
|
9
|
+
_tmpl$2 = "<i class=\"ti ti-table\" aria-hidden=\"true\"></i>",
|
|
10
|
+
_tmpl$3 = ["<div", " popover=\"auto\" class=\"k2b-ste-size-popover\" role=\"dialog\"", " tabindex=\"-1\"><div class=\"k2b-ste-size-grid\" role=\"group\"", ">", "</div><div class=\"k2b-ste-size-caption\" role=\"status\">", "</div></div>"],
|
|
11
|
+
_tmpl$4 = ["<div class=\"k2b-ste-size-row\">", "</div>"],
|
|
12
|
+
_tmpl$5 = ["<button type=\"button\" tabindex=\"-1\"", "></button>"],
|
|
13
|
+
_tmpl$6 = ["<label class=\"k2b-ste-recovery-label\">", "<textarea class=\"k2b-ste-recovery\" readonly", "></textarea></label>"],
|
|
14
|
+
_tmpl$7 = ["<i", " aria-hidden=\"true\"></i>"],
|
|
15
|
+
_tmpl$8 = "<i class=\"ti ti-chevron-down\" aria-hidden=\"true\"></i>",
|
|
16
|
+
_tmpl$9 = ["<div class=\"k2b-ste-table-sheet-heading\"><span", ">", "</span>", "</div>"],
|
|
17
|
+
_tmpl$0 = ["<i class=\"", "\" aria-hidden=\"true\"></i>"],
|
|
18
|
+
_tmpl$1 = ["<span class=\"k2b-ste-check\"", "><i class=\"ti ti-alert-triangle\" aria-hidden=\"true\"></i>", "</span>"],
|
|
19
|
+
_tmpl$10 = ["<div class=\"k2b-ste-status\" role=\"status\"><span>", "</span>", "</div>"],
|
|
20
|
+
_tmpl$11 = ["<div class=\"k2b-ste-toolbar-slot\">", "</div>"],
|
|
21
|
+
_tmpl$12 = ["<div class=\"k2b-ste-loading\" role=\"status\"", ">", "</div>"],
|
|
22
|
+
_tmpl$13 = ["<div class=\"k2b-ste-floating-menu\"", " style=\"", "\">", "</div>"],
|
|
23
|
+
_tmpl$14 = "<i class=\"ti ti-x\" aria-hidden=\"true\"></i>",
|
|
24
|
+
_tmpl$15 = ["<div class=\"k2b-ste-notice\"><div class=\"k2b-ste-notice-content\">", "", "</div>", "</div>"],
|
|
25
|
+
_tmpl$16 = ["<div class=\"", "\"", "><span class=\"k2b-ste-announcement\" role=\"status\" aria-live=\"polite\" aria-atomic=\"true\">", "</span>", "", "", "<div", "", "></div>", "<div role=\"status\" aria-live=\"polite\" aria-atomic=\"true\">", "</div></div>"],
|
|
26
|
+
_tmpl$17 = ["<div><span style=\"", "\"></span></div>"],
|
|
27
|
+
_tmpl$18 = ["<span>", "</span>"];
|
|
28
|
+
import { history, historyKeymap, redo, undo } from "@codemirror/commands";
|
|
29
|
+
import { EditorView, keymap } from "@codemirror/view";
|
|
30
|
+
import { clipboard } from "@k2b/stdlib/solid";
|
|
31
|
+
import { createEffect, createSignal, createUniqueId, For, onCleanup, onMount, Show, untrack } from "solid-js";
|
|
32
|
+
import { Button, IconButton } from "../actions/Button";
|
|
33
|
+
import { Dropdown } from "../actions/Dropdown";
|
|
34
|
+
import { SegmentedControl } from "../actions/SegmentedControl";
|
|
35
|
+
import { Toolbar } from "../actions/Toolbar";
|
|
36
|
+
import { Kbd } from "../content/Kbd";
|
|
37
|
+
import { dialogCore } from "../feedback/dialog-core";
|
|
38
|
+
import { NumberInput } from "../inputs/NumberInput";
|
|
39
|
+
import { LocaleProvider, useLocale } from "../intl/locale";
|
|
40
|
+
import { formatShortcut, keyboardPlatform } from "../intl/shortcut";
|
|
41
|
+
import BottomSheet, { bottomSheetAdaptiveOptions } from "../layout/BottomSheet";
|
|
42
|
+
import { createTextEditor } from "./engine";
|
|
43
|
+
import { commands, formatLabels } from "./format";
|
|
44
|
+
import { findTables, inspectTableStructure } from "./markdown-table";
|
|
45
|
+
import { textEditorMessages } from "./messages";
|
|
46
|
+
import { copyTable, editTableSource, formatActiveCell, runMenuAction, runTableAction, tableActionEnabled } from "./table";
|
|
47
|
+
/** Shared table-size control: pointer grid on desktop, large fields in a phone sheet. */
|
|
48
|
+
export function TableSizePicker(props) {
|
|
49
|
+
const locale = useLocale();
|
|
50
|
+
const t = () => textEditorMessages.resolve([locale()]).t;
|
|
51
|
+
const [rows, setRows] = createSignal(3);
|
|
52
|
+
const [columns, setColumns] = createSignal(3);
|
|
53
|
+
const [expanded, setExpanded] = createSignal(false);
|
|
54
|
+
const id = createUniqueId();
|
|
55
|
+
const abort = new AbortController();
|
|
56
|
+
let disposed = false;
|
|
57
|
+
onCleanup(() => {
|
|
58
|
+
disposed = true;
|
|
59
|
+
abort.abort();
|
|
60
|
+
});
|
|
61
|
+
let trigger;
|
|
62
|
+
let popup;
|
|
63
|
+
const reset = () => {
|
|
64
|
+
setRows(Math.min(3, props.maxRows));
|
|
65
|
+
setColumns(Math.min(3, props.maxColumns));
|
|
66
|
+
};
|
|
67
|
+
const choose = (r, c) => {
|
|
68
|
+
popup.hidePopover();
|
|
69
|
+
if (!disposed && !props.disabled) props.onPick({
|
|
70
|
+
rows: r,
|
|
71
|
+
columns: c
|
|
72
|
+
});
|
|
73
|
+
};
|
|
74
|
+
const open = async () => {
|
|
75
|
+
if (disposed || props.disabled || expanded()) return;
|
|
76
|
+
reset();
|
|
77
|
+
if (!window.matchMedia("(max-width: 47.999rem)").matches) {
|
|
78
|
+
popup.showPopover();
|
|
79
|
+
const anchor = trigger.getBoundingClientRect(),
|
|
80
|
+
box = popup.getBoundingClientRect();
|
|
81
|
+
popup.style.left = `${Math.max(8, Math.min(anchor.left, innerWidth - box.width - 8))}px`;
|
|
82
|
+
popup.style.top = `${Math.max(8, anchor.top > box.height + 8 ? anchor.top - box.height - 8 : Math.min(anchor.bottom + 8, innerHeight - box.height - 8))}px`;
|
|
83
|
+
popup.focus();
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
setExpanded(true);
|
|
87
|
+
const chosen = await dialogCore.open((close, context) => _$createComponent(LocaleProvider, {
|
|
88
|
+
get locale() {
|
|
89
|
+
return locale();
|
|
90
|
+
},
|
|
91
|
+
get children() {
|
|
92
|
+
return _$createComponent(BottomSheet, {
|
|
93
|
+
get onDismiss() {
|
|
94
|
+
return context.requestDismiss;
|
|
95
|
+
},
|
|
96
|
+
get children() {
|
|
97
|
+
return [_$createComponent(BottomSheet.Header, {
|
|
98
|
+
get title() {
|
|
99
|
+
return t().insertTable;
|
|
100
|
+
},
|
|
101
|
+
get close() {
|
|
102
|
+
return context.requestDismiss;
|
|
103
|
+
}
|
|
104
|
+
}), _$createComponent(BottomSheet.Body, {
|
|
105
|
+
get children() {
|
|
106
|
+
return _$ssr(_tmpl$, _$escape(_$createComponent(NumberInput, {
|
|
107
|
+
get label() {
|
|
108
|
+
return t().rows;
|
|
109
|
+
},
|
|
110
|
+
get value() {
|
|
111
|
+
return rows();
|
|
112
|
+
},
|
|
113
|
+
onValueChange: setRows,
|
|
114
|
+
min: 1,
|
|
115
|
+
get max() {
|
|
116
|
+
return props.maxRows;
|
|
117
|
+
},
|
|
118
|
+
step: 1
|
|
119
|
+
})), _$escape(_$createComponent(NumberInput, {
|
|
120
|
+
get label() {
|
|
121
|
+
return t().columns;
|
|
122
|
+
},
|
|
123
|
+
get value() {
|
|
124
|
+
return columns();
|
|
125
|
+
},
|
|
126
|
+
onValueChange: setColumns,
|
|
127
|
+
min: 1,
|
|
128
|
+
get max() {
|
|
129
|
+
return props.maxColumns;
|
|
130
|
+
},
|
|
131
|
+
step: 1
|
|
132
|
+
})));
|
|
133
|
+
}
|
|
134
|
+
}), _$createComponent(BottomSheet.Footer, {
|
|
135
|
+
get children() {
|
|
136
|
+
return _$createComponent(Button, {
|
|
137
|
+
get disabled() {
|
|
138
|
+
return !rows() || !columns();
|
|
139
|
+
},
|
|
140
|
+
onClick: () => {
|
|
141
|
+
const r = rows(),
|
|
142
|
+
c = columns();
|
|
143
|
+
if (r && c) close({
|
|
144
|
+
rows: r,
|
|
145
|
+
columns: c
|
|
146
|
+
});
|
|
147
|
+
},
|
|
148
|
+
get children() {
|
|
149
|
+
return t().insertSize({
|
|
150
|
+
rows: rows() ?? 0,
|
|
151
|
+
columns: columns() ?? 0
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
})];
|
|
157
|
+
}
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
}), {
|
|
161
|
+
...bottomSheetAdaptiveOptions,
|
|
162
|
+
ariaLabel: t().insertTable,
|
|
163
|
+
history: true,
|
|
164
|
+
signal: abort.signal
|
|
165
|
+
});
|
|
166
|
+
setExpanded(false);
|
|
167
|
+
if (chosen && !disposed && !props.disabled) props.onPick(chosen);
|
|
168
|
+
};
|
|
169
|
+
onMount(() => props.onReady?.(() => void open()));
|
|
170
|
+
const keyboard = event => {
|
|
171
|
+
const directions = {
|
|
172
|
+
ArrowUp: [-1, 0],
|
|
173
|
+
ArrowDown: [1, 0],
|
|
174
|
+
ArrowLeft: [0, -1],
|
|
175
|
+
ArrowRight: [0, 1]
|
|
176
|
+
};
|
|
177
|
+
const direction = directions[event.key];
|
|
178
|
+
if (direction) {
|
|
179
|
+
event.preventDefault();
|
|
180
|
+
setRows(Math.max(1, Math.min(Math.min(9, props.maxRows), (rows() ?? 1) + direction[0])));
|
|
181
|
+
setColumns(Math.max(1, Math.min(Math.min(10, props.maxColumns), (columns() ?? 1) + direction[1])));
|
|
182
|
+
} else if (event.key === "Enter" || event.key === " ") {
|
|
183
|
+
event.preventDefault();
|
|
184
|
+
choose(rows() ?? 1, columns() ?? 1);
|
|
185
|
+
} else if (event.key === "Escape") trigger.focus();
|
|
186
|
+
};
|
|
187
|
+
return [_$createComponent(IconButton, {
|
|
188
|
+
variant: "ghost",
|
|
189
|
+
get ["class"]() {
|
|
190
|
+
return props.class;
|
|
191
|
+
},
|
|
192
|
+
get size() {
|
|
193
|
+
return props.size ?? "sm";
|
|
194
|
+
},
|
|
195
|
+
get disabled() {
|
|
196
|
+
return props.disabled;
|
|
197
|
+
},
|
|
198
|
+
get label() {
|
|
199
|
+
return t().insertTable;
|
|
200
|
+
},
|
|
201
|
+
"aria-haspopup": "dialog",
|
|
202
|
+
"aria-controls": id,
|
|
203
|
+
get ["aria-expanded"]() {
|
|
204
|
+
return expanded();
|
|
205
|
+
},
|
|
206
|
+
get tooltip() {
|
|
207
|
+
return t().insertTable;
|
|
208
|
+
},
|
|
209
|
+
onMouseDown: event => event.preventDefault(),
|
|
210
|
+
onClick: () => void open(),
|
|
211
|
+
get children() {
|
|
212
|
+
return _$ssr(_tmpl$2);
|
|
213
|
+
}
|
|
214
|
+
}), _$ssr(_tmpl$3, _$ssrAttribute("id", _$escape(id, true), false), _$ssrAttribute("aria-label", _$escape(t().insertTable, true), false), _$ssrAttribute("aria-label", _$escape(t().insertTable, true), false), _$escape(_$createComponent(For, {
|
|
215
|
+
get each() {
|
|
216
|
+
return Array.from({
|
|
217
|
+
length: Math.min(9, props.maxRows)
|
|
218
|
+
}, (_, index) => index + 1);
|
|
219
|
+
},
|
|
220
|
+
children: r => _$ssr(_tmpl$4, _$escape(_$createComponent(For, {
|
|
221
|
+
get each() {
|
|
222
|
+
return Array.from({
|
|
223
|
+
length: Math.min(10, props.maxColumns)
|
|
224
|
+
}, (_, index) => index + 1);
|
|
225
|
+
},
|
|
226
|
+
children: c => _$ssr(_tmpl$5, _$ssrAttribute("aria-label", _$escape(t().insertSize({
|
|
227
|
+
rows: r,
|
|
228
|
+
columns: c
|
|
229
|
+
}), true), false) + _$ssrAttribute("data-selected", r <= (rows() ?? 0) && c <= (columns() ?? 0) ? "true" : _$escape(undefined, true), false))
|
|
230
|
+
})))
|
|
231
|
+
})), _$escape(t().insertSize({
|
|
232
|
+
rows: rows() ?? 0,
|
|
233
|
+
columns: columns() ?? 0
|
|
234
|
+
})))];
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
/** Shared table controls for a host-owned toolbar (`toolbar={false}`). */
|
|
238
|
+
|
|
239
|
+
const toolbar = [["bold", "bold"], ["italic", "italic"], ["heading", "heading"], ["bulletList", "list"], ["orderedList", "list-numbers"], ["quote", "quote"], ["link", "link"], ["code", "code"], ["table", "table"], ["rule", "separator"]];
|
|
240
|
+
const actionIcons = {
|
|
241
|
+
rowAbove: "row-insert-top",
|
|
242
|
+
rowBelow: "row-insert-bottom",
|
|
243
|
+
colLeft: "column-insert-left",
|
|
244
|
+
colRight: "column-insert-right",
|
|
245
|
+
alignLeft: "align-left",
|
|
246
|
+
alignCenter: "align-center",
|
|
247
|
+
alignRight: "align-right",
|
|
248
|
+
deleteRow: "row-remove",
|
|
249
|
+
deleteCol: "column-remove",
|
|
250
|
+
moveRowUp: "arrow-up",
|
|
251
|
+
moveRowDown: "arrow-down",
|
|
252
|
+
moveColLeft: "arrow-left",
|
|
253
|
+
moveColRight: "arrow-right",
|
|
254
|
+
toggleHeader: "table-row",
|
|
255
|
+
deleteTable: "trash"
|
|
256
|
+
};
|
|
257
|
+
const isInlineCommand = command => inlineCommands.has(command);
|
|
258
|
+
const shortcuts = {
|
|
259
|
+
bold: "mod+b",
|
|
260
|
+
italic: "mod+i",
|
|
261
|
+
link: "mod+k"
|
|
262
|
+
};
|
|
263
|
+
const inlineCommands = new Set(["bold", "italic", "code", "link", "strike"]);
|
|
264
|
+
|
|
265
|
+
/** A Markdown text field with app-injected collaboration and a directly editable table view. */
|
|
266
|
+
export function TextEditor(props) {
|
|
267
|
+
const locale = useLocale();
|
|
268
|
+
const t = () => textEditorMessages.resolve([locale()]).t;
|
|
269
|
+
const [mode, setMode] = createSignal(props.mode ?? "formatted");
|
|
270
|
+
const [ready, setReady] = createSignal(false);
|
|
271
|
+
const [recovery, setRecovery] = createSignal();
|
|
272
|
+
const [notice, setNotice] = createSignal();
|
|
273
|
+
const [cell, setCell] = createSignal();
|
|
274
|
+
const [localSource, setLocalSource] = createSignal(false);
|
|
275
|
+
const [announcement, setAnnouncement] = createSignal("");
|
|
276
|
+
const [check, setCheck] = createSignal(false);
|
|
277
|
+
const [missingSeparator, setMissingSeparator] = createSignal(false);
|
|
278
|
+
const [active, setActive] = createSignal(false);
|
|
279
|
+
const [documentRevision, setDocumentRevision] = createSignal(0);
|
|
280
|
+
const [phoneMenu, setPhoneMenu] = createSignal(false);
|
|
281
|
+
const [platform, setPlatform] = createSignal("other");
|
|
282
|
+
createEffect(() => {
|
|
283
|
+
const target = cell();
|
|
284
|
+
target?.setAttribute("data-active", "");
|
|
285
|
+
onCleanup(() => target?.removeAttribute("data-active"));
|
|
286
|
+
});
|
|
287
|
+
let disposed = false;
|
|
288
|
+
onCleanup(() => {
|
|
289
|
+
disposed = true;
|
|
290
|
+
const text = recovery();
|
|
291
|
+
if (text !== undefined) detachedRecovery(text);
|
|
292
|
+
});
|
|
293
|
+
// A local draft can outlive an island during navigation. Keep its recovery
|
|
294
|
+
// surface in the shared dialog root so disposal never silently drops it.
|
|
295
|
+
const detachedRecovery = text => {
|
|
296
|
+
const language = locale();
|
|
297
|
+
const labels = t();
|
|
298
|
+
const beforeUnload = event => {
|
|
299
|
+
event.preventDefault();
|
|
300
|
+
event.returnValue = "";
|
|
301
|
+
};
|
|
302
|
+
window.addEventListener("beforeunload", beforeUnload);
|
|
303
|
+
const show = () => void dialogCore.open((close, context) => {
|
|
304
|
+
context.setDismissHandler(() => {});
|
|
305
|
+
return _$createComponent(LocaleProvider, {
|
|
306
|
+
locale: language,
|
|
307
|
+
get children() {
|
|
308
|
+
return _$createComponent(BottomSheet, {
|
|
309
|
+
handle: false,
|
|
310
|
+
onDismiss: () => {},
|
|
311
|
+
get children() {
|
|
312
|
+
return [_$createComponent(BottomSheet.Header, {
|
|
313
|
+
get title() {
|
|
314
|
+
return labels.recoveredInput;
|
|
315
|
+
}
|
|
316
|
+
}), _$createComponent(BottomSheet.Body, {
|
|
317
|
+
get children() {
|
|
318
|
+
return _$ssr(_tmpl$6, _$escape(labels.recoveredInput), _$ssrAttribute("value", _$escape(text, true), false));
|
|
319
|
+
}
|
|
320
|
+
}), _$createComponent(BottomSheet.Footer, {
|
|
321
|
+
get children() {
|
|
322
|
+
return _$createComponent(Button, {
|
|
323
|
+
variant: "ghost",
|
|
324
|
+
onClick: () => close("discard"),
|
|
325
|
+
get children() {
|
|
326
|
+
return labels.discardRecovery;
|
|
327
|
+
}
|
|
328
|
+
});
|
|
329
|
+
}
|
|
330
|
+
})];
|
|
331
|
+
}
|
|
332
|
+
});
|
|
333
|
+
}
|
|
334
|
+
});
|
|
335
|
+
}, {
|
|
336
|
+
...bottomSheetAdaptiveOptions,
|
|
337
|
+
ariaLabel: labels.recoveredInput
|
|
338
|
+
}).then(result => {
|
|
339
|
+
if (result === "discard") window.removeEventListener("beforeunload", beforeUnload);
|
|
340
|
+
// The shared dialog root closes on each island disposal. Retain the
|
|
341
|
+
// draft across subsequent navigation until the person explicitly discards it.
|
|
342
|
+
else queueMicrotask(show);
|
|
343
|
+
});
|
|
344
|
+
show();
|
|
345
|
+
};
|
|
346
|
+
let menuOpen = false;
|
|
347
|
+
let pointerAnchor;
|
|
348
|
+
let floatingTrigger;
|
|
349
|
+
const tableTriggers = new Set();
|
|
350
|
+
let frame = 0;
|
|
351
|
+
const [menuPosition, setMenuPosition] = createSignal({
|
|
352
|
+
left: "0px",
|
|
353
|
+
top: "0px"
|
|
354
|
+
});
|
|
355
|
+
let root;
|
|
356
|
+
let mount;
|
|
357
|
+
let editor;
|
|
358
|
+
const menuBlocked = () => !!props.loading || !ready() || recovery() !== undefined;
|
|
359
|
+
const blocked = () => !!props.readOnly || menuBlocked();
|
|
360
|
+
const updateCheck = () => {
|
|
361
|
+
const issue = mode() === "plain" ? {
|
|
362
|
+
extraCells: false,
|
|
363
|
+
missingSeparator: false
|
|
364
|
+
} : inspectTableStructure(editor?.view.state.doc.toString() ?? props.initialValue ?? "");
|
|
365
|
+
const needsCheck = issue.extraCells || issue.missingSeparator;
|
|
366
|
+
setMissingSeparator(issue.missingSeparator);
|
|
367
|
+
setCheck(needsCheck);
|
|
368
|
+
props.onTableCheck?.(needsCheck);
|
|
369
|
+
};
|
|
370
|
+
const positionMenu = () => {
|
|
371
|
+
const target = cell();
|
|
372
|
+
if (!target) return;
|
|
373
|
+
const wrap = target.closest(".k2b-ste-table");
|
|
374
|
+
const table = wrap?.querySelector("table");
|
|
375
|
+
if (!target.isConnected || !wrap || !table || mode() !== "formatted") {
|
|
376
|
+
menuOpen = false;
|
|
377
|
+
setCell(undefined);
|
|
378
|
+
checkFocus();
|
|
379
|
+
return;
|
|
380
|
+
}
|
|
381
|
+
const rect = target.getBoundingClientRect();
|
|
382
|
+
const bounds = root.getBoundingClientRect();
|
|
383
|
+
const right = Math.min(table.getBoundingClientRect().right, wrap.getBoundingClientRect().right);
|
|
384
|
+
const position = props.readOnly ? {
|
|
385
|
+
left: `${wrap.getBoundingClientRect().left - bounds.left}px`,
|
|
386
|
+
top: `${wrap.getBoundingClientRect().bottom - bounds.top - (window.matchMedia("(max-width: 47.999rem)").matches ? 44 : 0)}px`
|
|
387
|
+
} : {
|
|
388
|
+
left: `${right - bounds.left - 24}px`,
|
|
389
|
+
top: `${rect.top - bounds.top + (rect.height - 24) / 2}px`
|
|
390
|
+
};
|
|
391
|
+
setMenuPosition(pointerAnchor ?? position);
|
|
392
|
+
};
|
|
393
|
+
const schedulePosition = () => {
|
|
394
|
+
if (!frame) frame = requestAnimationFrame(() => {
|
|
395
|
+
frame = 0;
|
|
396
|
+
positionMenu();
|
|
397
|
+
});
|
|
398
|
+
};
|
|
399
|
+
const unavailable = () => !!props.host?.structure && !props.host.structure.available();
|
|
400
|
+
const actionDisabled = action => {
|
|
401
|
+
documentRevision();
|
|
402
|
+
const wrap = cell()?.closest(".k2b-ste-table");
|
|
403
|
+
return blocked() || !editor || !wrap || !tableActionEnabled(editor.view, wrap, action);
|
|
404
|
+
};
|
|
405
|
+
const isMove = action => action.startsWith("move");
|
|
406
|
+
const runAction = action => {
|
|
407
|
+
const wrap = cell()?.closest(".k2b-ste-table");
|
|
408
|
+
const focused = document.activeElement;
|
|
409
|
+
const menuElement = focused instanceof HTMLElement ? focused.closest('[role="menu"]') : null;
|
|
410
|
+
if (editor && wrap && !actionDisabled(action)) runMenuAction(editor.view, wrap, action);
|
|
411
|
+
// The phone move sheet remains usable for another move. Local structural
|
|
412
|
+
// focus belongs to the cell only after the menu has closed.
|
|
413
|
+
if (isMove(action) && focused instanceof HTMLElement && menuElement) {
|
|
414
|
+
const restore = () => {
|
|
415
|
+
if (disposed || !menuElement.isConnected) return;
|
|
416
|
+
const target = focused.isConnected && !focused.matches(":disabled") ? focused : menuElement.querySelector('[role^="menuitem"]:not(:disabled)');
|
|
417
|
+
target?.focus({
|
|
418
|
+
preventScroll: true
|
|
419
|
+
});
|
|
420
|
+
};
|
|
421
|
+
restore();
|
|
422
|
+
queueMicrotask(restore);
|
|
423
|
+
}
|
|
424
|
+
};
|
|
425
|
+
const moveKeys = {
|
|
426
|
+
moveRowUp: "alt+arrowup",
|
|
427
|
+
moveRowDown: "alt+arrowdown",
|
|
428
|
+
moveColLeft: "alt+arrowleft",
|
|
429
|
+
moveColRight: "alt+arrowright"
|
|
430
|
+
};
|
|
431
|
+
const shortActionLabels = {
|
|
432
|
+
rowAbove: "menuAbove",
|
|
433
|
+
rowBelow: "menuBelow",
|
|
434
|
+
moveRowUp: "menuUp",
|
|
435
|
+
moveRowDown: "menuDown",
|
|
436
|
+
deleteRow: "menuDelete",
|
|
437
|
+
colLeft: "menuInsertLeft",
|
|
438
|
+
colRight: "menuInsertRight",
|
|
439
|
+
moveColLeft: "menuMoveLeft",
|
|
440
|
+
moveColRight: "menuMoveRight",
|
|
441
|
+
deleteCol: "menuDelete"
|
|
442
|
+
};
|
|
443
|
+
const menuRow = () => {
|
|
444
|
+
documentRevision();
|
|
445
|
+
return t().menuRow(Number(cell()?.dataset.r ?? 0));
|
|
446
|
+
};
|
|
447
|
+
const menuColumn = () => {
|
|
448
|
+
documentRevision();
|
|
449
|
+
const column = Number(cell()?.dataset.c ?? 0);
|
|
450
|
+
const header = cell()?.closest(".k2b-ste-table")?.querySelector(`.k2b-ste-cell[data-r="0"][data-c="${column}"]`);
|
|
451
|
+
return t().menuColumn(header?.dataset.raw || t().column(column + 1));
|
|
452
|
+
};
|
|
453
|
+
const menuHeading = () => `${menuRow()} · ${menuColumn()}`;
|
|
454
|
+
const actionItem = (action, choice) => ({
|
|
455
|
+
get label() {
|
|
456
|
+
return phoneMenu() && action in shortActionLabels ? t()[shortActionLabels[action]] : t()[action];
|
|
457
|
+
},
|
|
458
|
+
icon: `ti ti-${actionIcons[action]}`,
|
|
459
|
+
get disabled() {
|
|
460
|
+
return actionDisabled(action);
|
|
461
|
+
},
|
|
462
|
+
immediate: true,
|
|
463
|
+
trailing: moveKeys[action] ? _$createComponent(Kbd, {
|
|
464
|
+
get keys() {
|
|
465
|
+
return moveKeys[action];
|
|
466
|
+
}
|
|
467
|
+
}) : action === "rowBelow" ? _$createComponent(Kbd, {
|
|
468
|
+
keys: "enter"
|
|
469
|
+
}) : undefined,
|
|
470
|
+
variant: action === "deleteRow" || action === "deleteCol" || action === "deleteTable" ? "danger" : undefined,
|
|
471
|
+
closeOnSelect: !isMove(action),
|
|
472
|
+
action: () => runAction(action),
|
|
473
|
+
...choice
|
|
474
|
+
});
|
|
475
|
+
const [copying, setCopying] = createSignal(false);
|
|
476
|
+
const tableCopy = clipboard.createWriter({
|
|
477
|
+
write: ({
|
|
478
|
+
view,
|
|
479
|
+
wrap,
|
|
480
|
+
format
|
|
481
|
+
}) => copyTable(view, wrap, format)
|
|
482
|
+
});
|
|
483
|
+
const copy = async format => {
|
|
484
|
+
const wrap = cell()?.closest(".k2b-ste-table");
|
|
485
|
+
if (!editor || !wrap || copying()) return;
|
|
486
|
+
setCopying(true);
|
|
487
|
+
setNotice({
|
|
488
|
+
message: t().copyingTable
|
|
489
|
+
});
|
|
490
|
+
const success = await tableCopy.copy({
|
|
491
|
+
view: editor.view,
|
|
492
|
+
wrap,
|
|
493
|
+
format
|
|
494
|
+
});
|
|
495
|
+
if (disposed) return;
|
|
496
|
+
setCopying(false);
|
|
497
|
+
setNotice({
|
|
498
|
+
message: success ? format === "table" ? t().copiedTable : t().copiedMarkdown : t().copyFailed
|
|
499
|
+
});
|
|
500
|
+
};
|
|
501
|
+
const copyItems = () => [{
|
|
502
|
+
get label() {
|
|
503
|
+
return phoneMenu() && !props.readOnly ? t().menuCopy : t().copyTable;
|
|
504
|
+
},
|
|
505
|
+
icon: "ti ti-copy",
|
|
506
|
+
get disabled() {
|
|
507
|
+
return copying();
|
|
508
|
+
},
|
|
509
|
+
immediate: true,
|
|
510
|
+
action: () => {
|
|
511
|
+
void copy("table");
|
|
512
|
+
}
|
|
513
|
+
}, {
|
|
514
|
+
get label() {
|
|
515
|
+
return phoneMenu() && !props.readOnly ? t().menuMarkdown : t().copyMarkdown;
|
|
516
|
+
},
|
|
517
|
+
icon: "ti ti-markdown",
|
|
518
|
+
get disabled() {
|
|
519
|
+
return copying();
|
|
520
|
+
},
|
|
521
|
+
immediate: true,
|
|
522
|
+
action: () => {
|
|
523
|
+
void copy("markdown");
|
|
524
|
+
}
|
|
525
|
+
}];
|
|
526
|
+
const items = () => {
|
|
527
|
+
if (props.readOnly) return copyItems();
|
|
528
|
+
const align = () => {
|
|
529
|
+
documentRevision();
|
|
530
|
+
return cell()?.parentElement?.style.textAlign || "left";
|
|
531
|
+
};
|
|
532
|
+
return [{
|
|
533
|
+
get sectionLabel() {
|
|
534
|
+
return menuHeading();
|
|
535
|
+
},
|
|
536
|
+
items: []
|
|
537
|
+
}, {
|
|
538
|
+
get sectionLabel() {
|
|
539
|
+
return menuRow();
|
|
540
|
+
},
|
|
541
|
+
items: ["rowAbove", "rowBelow", "moveRowUp", "moveRowDown", "deleteRow"].map(action => actionItem(action))
|
|
542
|
+
}, {
|
|
543
|
+
get sectionLabel() {
|
|
544
|
+
return menuColumn();
|
|
545
|
+
},
|
|
546
|
+
items: ["colLeft", "colRight", "moveColLeft", "moveColRight"].map(action => actionItem(action))
|
|
547
|
+
}, {
|
|
548
|
+
sectionLabel: t().alignment,
|
|
549
|
+
layout: "row",
|
|
550
|
+
items: ["alignLeft", "alignCenter", "alignRight"].map((action, index) => actionItem(action, {
|
|
551
|
+
choice: "radio",
|
|
552
|
+
class: "k2b-ste-align-choice",
|
|
553
|
+
ariaLabel: t()[action],
|
|
554
|
+
checked: () => align() === ["left", "center", "right"][index]
|
|
555
|
+
}))
|
|
556
|
+
}, {
|
|
557
|
+
items: [actionItem("deleteCol")]
|
|
558
|
+
}, {
|
|
559
|
+
sectionLabel: t().table,
|
|
560
|
+
items: [actionItem("toggleHeader", {
|
|
561
|
+
choice: "checkbox",
|
|
562
|
+
class: "k2b-ste-header-choice",
|
|
563
|
+
checked: () => {
|
|
564
|
+
documentRevision();
|
|
565
|
+
return cell()?.closest(".k2b-ste-table")?.dataset.header === "true";
|
|
566
|
+
}
|
|
567
|
+
}), {
|
|
568
|
+
label: t().editMarkdown,
|
|
569
|
+
icon: "ti ti-markdown",
|
|
570
|
+
action: () => {
|
|
571
|
+
const wrap = cell()?.closest(".k2b-ste-table");
|
|
572
|
+
if (editor && wrap) editTableSource(editor.view, wrap);
|
|
573
|
+
}
|
|
574
|
+
}, ...copyItems(), actionItem("deleteTable"), ...(unavailable() ? [{
|
|
575
|
+
label: t().structureUnavailable,
|
|
576
|
+
disabled: true
|
|
577
|
+
}] : [])]
|
|
578
|
+
}];
|
|
579
|
+
};
|
|
580
|
+
const preserveSelection = event => event.preventDefault();
|
|
581
|
+
const menuChange = open => {
|
|
582
|
+
menuOpen = open;
|
|
583
|
+
};
|
|
584
|
+
const menuClose = () => {
|
|
585
|
+
menuOpen = false;
|
|
586
|
+
pointerAnchor = undefined;
|
|
587
|
+
schedulePosition();
|
|
588
|
+
queueMicrotask(() => {
|
|
589
|
+
if (disposed) return;
|
|
590
|
+
const focused = document.activeElement;
|
|
591
|
+
if (focused instanceof HTMLElement && focused.matches(".k2b-ste-cell-menu, .k2b-ste-table-tool")) cell()?.focus();
|
|
592
|
+
checkFocus();
|
|
593
|
+
});
|
|
594
|
+
};
|
|
595
|
+
const menu = (floating, trigger) => // A sheet owns its item inventory until it closes. Replace that owner when
|
|
596
|
+
// edit access changes so an already open sheet cannot retain edit entries.
|
|
597
|
+
_$createComponent(Show, {
|
|
598
|
+
get when() {
|
|
599
|
+
return props.readOnly ? "read" : "write";
|
|
600
|
+
},
|
|
601
|
+
keyed: true,
|
|
602
|
+
children: _access => _$createComponent(Dropdown, {
|
|
603
|
+
get items() {
|
|
604
|
+
return items();
|
|
605
|
+
},
|
|
606
|
+
phone: "sheet",
|
|
607
|
+
get sheetTop() {
|
|
608
|
+
return props.readOnly ? undefined : close => _$ssr(_tmpl$9, _$ssrAttribute("title", _$escape(menuHeading(), true), false), _$escape(menuHeading()), _$escape(_$createComponent(Button, {
|
|
609
|
+
variant: "ghost",
|
|
610
|
+
onClick: close,
|
|
611
|
+
get children() {
|
|
612
|
+
return t().done;
|
|
613
|
+
}
|
|
614
|
+
})));
|
|
615
|
+
},
|
|
616
|
+
menuClass: "k2b-ste-table-menu",
|
|
617
|
+
get position() {
|
|
618
|
+
return floating ? "right-start" : trigger?.position ?? "bottom-right";
|
|
619
|
+
},
|
|
620
|
+
width: "18rem",
|
|
621
|
+
get label() {
|
|
622
|
+
return _$memo(() => !!props.readOnly)() ? t().copyTable : t().tableMenu;
|
|
623
|
+
},
|
|
624
|
+
get disabled() {
|
|
625
|
+
return menuBlocked() || localSource() || !cell()?.isConnected;
|
|
626
|
+
},
|
|
627
|
+
onOpenChange: menuChange,
|
|
628
|
+
onClose: menuClose,
|
|
629
|
+
get children() {
|
|
630
|
+
return _$createComponent(Dropdown.Trigger, {
|
|
631
|
+
get ["class"]() {
|
|
632
|
+
return floating ? props.readOnly ? "k2b-ste-cell-menu k2b-ste-copy-menu" : "k2b-ste-cell-menu" : `k2b-ste-tool k2b-ste-table-tool ${trigger?.class ?? ""}`;
|
|
633
|
+
},
|
|
634
|
+
variant: "ghost",
|
|
635
|
+
get size() {
|
|
636
|
+
return trigger?.size ?? "sm";
|
|
637
|
+
},
|
|
638
|
+
get iconOnly() {
|
|
639
|
+
return _$memo(() => !!!trigger?.text)() && !props.readOnly;
|
|
640
|
+
},
|
|
641
|
+
get label() {
|
|
642
|
+
return trigger?.text ?? (props.readOnly ? t().copyTable : t().tableMenu);
|
|
643
|
+
},
|
|
644
|
+
"aria-pressed": !floating ? true : undefined,
|
|
645
|
+
onMouseDown: preserveSelection,
|
|
646
|
+
get children() {
|
|
647
|
+
return [_$ssr(_tmpl$7, _$ssrAttribute("class", props.readOnly ? "ti ti-copy" : floating ? "ti ti-dots" : "ti ti-table", false)), trigger?.text ?? (props.readOnly ? t().copyTable : undefined), _$createComponent(Show, {
|
|
648
|
+
get when() {
|
|
649
|
+
return trigger?.text;
|
|
650
|
+
},
|
|
651
|
+
get children() {
|
|
652
|
+
return _$ssr(_tmpl$8);
|
|
653
|
+
}
|
|
654
|
+
})];
|
|
655
|
+
}
|
|
656
|
+
});
|
|
657
|
+
}
|
|
658
|
+
})
|
|
659
|
+
});
|
|
660
|
+
const runFormat = command => {
|
|
661
|
+
if (!editor || blocked()) return;
|
|
662
|
+
if (cell()?.isConnected && isInlineCommand(command) && formatActiveCell(editor.view, command)) return;
|
|
663
|
+
commands[command](editor.view);
|
|
664
|
+
};
|
|
665
|
+
const checkFocus = () => {
|
|
666
|
+
if (disposed) return;
|
|
667
|
+
// A host toolbar sits outside this root. Native popover focus moves before
|
|
668
|
+
// its toggle callback, but Dropdown already exposes its synchronous state.
|
|
669
|
+
if (menuOpen || [...tableTriggers, floatingTrigger].some(trigger => trigger?.isConnected && trigger.getAttribute("aria-expanded") === "true")) return;
|
|
670
|
+
const focused = document.activeElement;
|
|
671
|
+
setLocalSource(focused instanceof HTMLElement && !!focused.closest(".k2b-ste-table-source"));
|
|
672
|
+
const inside = focused instanceof Node && root.contains(focused);
|
|
673
|
+
setActive(inside);
|
|
674
|
+
if (!inside || focused === editor?.view.contentDOM) setCell(undefined);else if (!cell()?.isConnected) setCell(undefined);
|
|
675
|
+
};
|
|
676
|
+
const formatMenu = command => _$createComponent(Dropdown, {
|
|
677
|
+
phone: "sheet",
|
|
678
|
+
get label() {
|
|
679
|
+
return t()[command];
|
|
680
|
+
},
|
|
681
|
+
get disabled() {
|
|
682
|
+
return blocked() || command === "heading" && !!cell();
|
|
683
|
+
},
|
|
684
|
+
onOpenChange: menuChange,
|
|
685
|
+
onClose: menuClose,
|
|
686
|
+
get items() {
|
|
687
|
+
return command === "heading" ? [{
|
|
688
|
+
items: ["heading1", "heading2", "heading3"].map((name, index) => ({
|
|
689
|
+
label: t()[name],
|
|
690
|
+
icon: `ti ti-h-${index + 1}`,
|
|
691
|
+
action: () => runFormat(name)
|
|
692
|
+
}))
|
|
693
|
+
}] : [{
|
|
694
|
+
label: t().inlineCode,
|
|
695
|
+
icon: "ti ti-code",
|
|
696
|
+
action: () => runFormat("code")
|
|
697
|
+
}, {
|
|
698
|
+
label: t().codeBlock,
|
|
699
|
+
icon: "ti ti-source-code",
|
|
700
|
+
disabled: !!cell(),
|
|
701
|
+
action: () => runFormat("codeBlock")
|
|
702
|
+
}, {
|
|
703
|
+
label: t().strike,
|
|
704
|
+
icon: "ti ti-strikethrough",
|
|
705
|
+
trailing: _$createComponent(Kbd, {
|
|
706
|
+
keys: "mod+shift+x"
|
|
707
|
+
}),
|
|
708
|
+
action: () => runFormat("strike")
|
|
709
|
+
}];
|
|
710
|
+
},
|
|
711
|
+
get children() {
|
|
712
|
+
return _$createComponent(Dropdown.Trigger, {
|
|
713
|
+
"class": "k2b-ste-tool",
|
|
714
|
+
variant: "ghost",
|
|
715
|
+
size: "sm",
|
|
716
|
+
iconOnly: true,
|
|
717
|
+
get label() {
|
|
718
|
+
return t()[command];
|
|
719
|
+
},
|
|
720
|
+
onMouseDown: preserveSelection,
|
|
721
|
+
get children() {
|
|
722
|
+
return _$ssr(_tmpl$0, `ti ti-${_$escape(command, true)}`);
|
|
723
|
+
}
|
|
724
|
+
});
|
|
725
|
+
}
|
|
726
|
+
});
|
|
727
|
+
const selectMode = next => {
|
|
728
|
+
const restoreEditorFocus = !!editor?.view.contentDOM.contains(document.activeElement);
|
|
729
|
+
menuOpen = false;
|
|
730
|
+
setCell(undefined);
|
|
731
|
+
setMode(next);
|
|
732
|
+
props.onModeChange?.(next);
|
|
733
|
+
if (restoreEditorFocus) queueMicrotask(() => editor?.view.focus());
|
|
734
|
+
};
|
|
735
|
+
onMount(() => {
|
|
736
|
+
setPlatform(keyboardPlatform());
|
|
737
|
+
const menuMedia = window.matchMedia("(max-width: 47.999rem)");
|
|
738
|
+
const menuViewport = () => setPhoneMenu(menuMedia.matches);
|
|
739
|
+
menuViewport();
|
|
740
|
+
menuMedia.addEventListener("change", menuViewport);
|
|
741
|
+
onCleanup(() => menuMedia.removeEventListener("change", menuViewport));
|
|
742
|
+
// A standalone editor has no binding history; collaboration supplies its own instead.
|
|
743
|
+
const nativeHistory = !props.host?.undo;
|
|
744
|
+
editor = createTextEditor({
|
|
745
|
+
parent: mount,
|
|
746
|
+
doc: props.initialValue,
|
|
747
|
+
mode: mode(),
|
|
748
|
+
label: props.label,
|
|
749
|
+
readOnly: props.readOnly,
|
|
750
|
+
placeholder: props.placeholder,
|
|
751
|
+
presentation: props.presentation,
|
|
752
|
+
extensions: [nativeHistory ? [history(), keymap.of(historyKeymap)] : [], formatLabels.of({
|
|
753
|
+
get link() {
|
|
754
|
+
return t().link;
|
|
755
|
+
},
|
|
756
|
+
column: column => t().column(column)
|
|
757
|
+
}), EditorView.updateListener.of(update => {
|
|
758
|
+
schedulePosition();
|
|
759
|
+
if (update.docChanged) queueMicrotask(() => setDocumentRevision(revision => revision + 1));
|
|
760
|
+
}), props.extensions ?? []],
|
|
761
|
+
host: {
|
|
762
|
+
...props.host,
|
|
763
|
+
undo: props.host?.undo ?? (() => editor && undo(editor.view)),
|
|
764
|
+
redo: props.host?.redo ?? (() => editor && redo(editor.view)),
|
|
765
|
+
boundary: props.host?.boundary ?? (() => {}),
|
|
766
|
+
cellLabel: (row, column, name) => t().cellLabel({
|
|
767
|
+
row,
|
|
768
|
+
column,
|
|
769
|
+
name
|
|
770
|
+
}),
|
|
771
|
+
actionLabel: name => t()[name],
|
|
772
|
+
sourceLabels: () => ({
|
|
773
|
+
edit: t().editMarkdown,
|
|
774
|
+
valid: t().markdownValid,
|
|
775
|
+
invalid: t().markdownInvalid,
|
|
776
|
+
changed: t().markdownChanged,
|
|
777
|
+
structural: t().markdownStructural,
|
|
778
|
+
applying: t().applyingTable,
|
|
779
|
+
applyFailed: t().markdownApplyFailed,
|
|
780
|
+
done: phoneMenu() ? t().done : t().showTable,
|
|
781
|
+
discard: t().discardMarkdown,
|
|
782
|
+
continue: t().continueMarkdown,
|
|
783
|
+
line: t().markdownLine,
|
|
784
|
+
separator: (header, separator) => t().markdownSeparator({
|
|
785
|
+
header,
|
|
786
|
+
separator
|
|
787
|
+
}),
|
|
788
|
+
extra: t().markdownExtra,
|
|
789
|
+
complete: t().completeColumns
|
|
790
|
+
}),
|
|
791
|
+
maxLength: props.maxLength,
|
|
792
|
+
maxPasteCells: props.maxPasteCells ?? 2000,
|
|
793
|
+
onRecovery: text => {
|
|
794
|
+
if (disposed) detachedRecovery(text);else setRecovery(previous => previous === undefined ? text : `${previous}\n\n${text}`);
|
|
795
|
+
},
|
|
796
|
+
onError: code => setNotice({
|
|
797
|
+
message: t()[code]
|
|
798
|
+
})
|
|
799
|
+
},
|
|
800
|
+
onChange: text => {
|
|
801
|
+
props.onChange?.(text);
|
|
802
|
+
queueMicrotask(updateCheck);
|
|
803
|
+
},
|
|
804
|
+
onDroppedImages: (count, files) => {
|
|
805
|
+
if (props.onDroppedImages?.(count, files) !== true) setNotice({
|
|
806
|
+
message: t().imageHint,
|
|
807
|
+
images: true
|
|
808
|
+
});
|
|
809
|
+
}
|
|
810
|
+
});
|
|
811
|
+
const focus = event => {
|
|
812
|
+
if (!(event instanceof CustomEvent) || !(event.detail.cell instanceof HTMLElement)) return;
|
|
813
|
+
setActive(true);
|
|
814
|
+
if (!menuOpen) pointerAnchor = undefined;
|
|
815
|
+
setCell(event.detail.cell);
|
|
816
|
+
positionMenu();
|
|
817
|
+
};
|
|
818
|
+
const structureAnnouncement = event => {
|
|
819
|
+
if (!(event instanceof CustomEvent)) return;
|
|
820
|
+
const detail = event.detail;
|
|
821
|
+
if (detail && typeof detail === "object" && "rows" in detail && "columns" in detail && typeof detail.rows === "number" && typeof detail.columns === "number") setAnnouncement(t().tableChanged({
|
|
822
|
+
rows: detail.rows,
|
|
823
|
+
columns: detail.columns
|
|
824
|
+
}));
|
|
825
|
+
};
|
|
826
|
+
const focusChange = () => queueMicrotask(checkFocus);
|
|
827
|
+
let pointerCheck;
|
|
828
|
+
const pointer = event => {
|
|
829
|
+
if (event.target instanceof Node && root.contains(event.target)) setActive(true);
|
|
830
|
+
// After the press moved focus: a host toolbar control that keeps focus in the cell keeps it active.
|
|
831
|
+
else if (!menuOpen) {
|
|
832
|
+
clearTimeout(pointerCheck);
|
|
833
|
+
pointerCheck = setTimeout(checkFocus);
|
|
834
|
+
}
|
|
835
|
+
};
|
|
836
|
+
const keyboardMenu = event => {
|
|
837
|
+
if (menuBlocked()) return;
|
|
838
|
+
focus(event);
|
|
839
|
+
if (event instanceof CustomEvent) {
|
|
840
|
+
const bounds = root.getBoundingClientRect();
|
|
841
|
+
const anchor = event.detail.anchor instanceof HTMLElement ? event.detail.anchor.getBoundingClientRect() : undefined;
|
|
842
|
+
if (anchor || typeof event.detail.x === "number") {
|
|
843
|
+
pointerAnchor = {
|
|
844
|
+
left: `${(anchor?.left ?? event.detail.x) - bounds.left}px`,
|
|
845
|
+
top: `${(anchor?.bottom ?? event.detail.y) - bounds.top}px`
|
|
846
|
+
};
|
|
847
|
+
positionMenu();
|
|
848
|
+
}
|
|
849
|
+
}
|
|
850
|
+
queueMicrotask(() => {
|
|
851
|
+
if (disposed || !cell()?.isConnected) return;
|
|
852
|
+
const tableTrigger = [...tableTriggers].find(trigger => trigger.isConnected);
|
|
853
|
+
const trigger = (window.matchMedia("(max-width: 47.999rem)").matches && tableTrigger?.isConnected ? tableTrigger : undefined) ?? floatingTrigger;
|
|
854
|
+
trigger?.click();
|
|
855
|
+
});
|
|
856
|
+
};
|
|
857
|
+
const mutations = new MutationObserver(schedulePosition);
|
|
858
|
+
mutations.observe(mount, {
|
|
859
|
+
childList: true,
|
|
860
|
+
subtree: true,
|
|
861
|
+
characterData: true
|
|
862
|
+
});
|
|
863
|
+
const resize = new ResizeObserver(schedulePosition);
|
|
864
|
+
resize.observe(mount);
|
|
865
|
+
// Safari blurs a contenteditable on mouse-down without focusing the radio.
|
|
866
|
+
// Keep the caret and phone toolbar stationary until the view switch runs.
|
|
867
|
+
const viewMouseDown = event => {
|
|
868
|
+
if (event.target instanceof Element && event.target.closest(".k2b-ste-views")) event.preventDefault();
|
|
869
|
+
};
|
|
870
|
+
root.addEventListener("mousedown", viewMouseDown);
|
|
871
|
+
document.addEventListener("focusin", focusChange);
|
|
872
|
+
document.addEventListener("pointerdown", pointer);
|
|
873
|
+
root.addEventListener("k2b-ste-table-structure", structureAnnouncement);
|
|
874
|
+
root.addEventListener("k2b-ste-cell-focus", focus);
|
|
875
|
+
root.addEventListener("k2b-ste-cell-blur", focusChange);
|
|
876
|
+
root.addEventListener("k2b-ste-cell-menu", keyboardMenu);
|
|
877
|
+
const tableScroll = event => {
|
|
878
|
+
if (menuOpen && event.target instanceof HTMLElement && event.target.classList.contains("k2b-ste-table") && floatingTrigger?.getAttribute("aria-expanded") === "true") floatingTrigger.click();
|
|
879
|
+
schedulePosition();
|
|
880
|
+
};
|
|
881
|
+
window.addEventListener("scroll", tableScroll, true);
|
|
882
|
+
window.addEventListener("resize", schedulePosition);
|
|
883
|
+
const viewport = window.visualViewport;
|
|
884
|
+
const keyboard = () => root.style.setProperty("--k2b-ste-keyboard", `${Math.max(0, window.innerHeight - (viewport?.height ?? window.innerHeight) - (viewport?.offsetTop ?? 0))}px`);
|
|
885
|
+
viewport?.addEventListener("resize", keyboard);
|
|
886
|
+
viewport?.addEventListener("scroll", keyboard);
|
|
887
|
+
keyboard();
|
|
888
|
+
setReady(true);
|
|
889
|
+
updateCheck();
|
|
890
|
+
props.onReady?.(editor, {
|
|
891
|
+
tableActive: () => mode() === "formatted" && !!cell()?.isConnected,
|
|
892
|
+
TableMenu: trigger => menu(false, trigger),
|
|
893
|
+
formatCell: format => !!editor && !blocked() && !!cell()?.isConnected && formatActiveCell(editor.view, format),
|
|
894
|
+
notify: message => setNotice({
|
|
895
|
+
message
|
|
896
|
+
})
|
|
897
|
+
});
|
|
898
|
+
onCleanup(() => {
|
|
899
|
+
clearTimeout(pointerCheck);
|
|
900
|
+
mutations.disconnect();
|
|
901
|
+
resize.disconnect();
|
|
902
|
+
cancelAnimationFrame(frame);
|
|
903
|
+
root.removeEventListener("mousedown", viewMouseDown);
|
|
904
|
+
document.removeEventListener("focusin", focusChange);
|
|
905
|
+
document.removeEventListener("pointerdown", pointer);
|
|
906
|
+
root.removeEventListener("k2b-ste-table-structure", structureAnnouncement);
|
|
907
|
+
root.removeEventListener("k2b-ste-cell-focus", focus);
|
|
908
|
+
root.removeEventListener("k2b-ste-cell-blur", focusChange);
|
|
909
|
+
root.removeEventListener("k2b-ste-cell-menu", keyboardMenu);
|
|
910
|
+
window.removeEventListener("scroll", tableScroll, true);
|
|
911
|
+
window.removeEventListener("resize", schedulePosition);
|
|
912
|
+
viewport?.removeEventListener("resize", keyboard);
|
|
913
|
+
viewport?.removeEventListener("scroll", keyboard);
|
|
914
|
+
editor?.destroy();
|
|
915
|
+
});
|
|
916
|
+
});
|
|
917
|
+
createEffect(() => {
|
|
918
|
+
if (props.mode !== undefined) setMode(props.mode);
|
|
919
|
+
});
|
|
920
|
+
createEffect(() => {
|
|
921
|
+
if (ready()) {
|
|
922
|
+
const next = mode();
|
|
923
|
+
// Rendering the grid consults reactive host availability. Those reads
|
|
924
|
+
// must not turn a history notification into a nested mode reconfigure.
|
|
925
|
+
untrack(() => {
|
|
926
|
+
menuOpen = false;
|
|
927
|
+
setCell(undefined);
|
|
928
|
+
editor?.setMode(next);
|
|
929
|
+
updateCheck();
|
|
930
|
+
});
|
|
931
|
+
}
|
|
932
|
+
});
|
|
933
|
+
createEffect(() => {
|
|
934
|
+
const label = props.label;
|
|
935
|
+
if (ready()) untrack(() => editor?.setLabel(label));
|
|
936
|
+
});
|
|
937
|
+
createEffect(() => {
|
|
938
|
+
const readOnly = !!props.readOnly || !!props.loading || recovery() !== undefined;
|
|
939
|
+
if (ready()) untrack(() => editor?.setReadOnly(readOnly));
|
|
940
|
+
});
|
|
941
|
+
createEffect(() => {
|
|
942
|
+
documentRevision();
|
|
943
|
+
const disabled = blocked() || unavailable();
|
|
944
|
+
if (ready()) root.querySelectorAll(".k2b-ste-addColumn").forEach(button => {
|
|
945
|
+
button.disabled = disabled;
|
|
946
|
+
});
|
|
947
|
+
});
|
|
948
|
+
return _$ssr(_tmpl$16, `k2b-text-editor ${_$escape(props.class ?? "", true)}`, _$ssrAttribute("data-mode", _$escape(mode(), true), false) + _$ssrAttribute("data-readonly", props.readOnly ? "true" : _$escape(undefined, true), false) + _$ssrAttribute("data-active", active() ? "true" : _$escape(undefined, true), false) + _$ssrAttribute("aria-busy", _$escape(props.loading || !ready(), true), false), _$escape(announcement()), _$escape(_$createComponent(Show, {
|
|
949
|
+
get when() {
|
|
950
|
+
return !props.presentation || "status" in props || check();
|
|
951
|
+
},
|
|
952
|
+
get children() {
|
|
953
|
+
return _$ssr(_tmpl$10, _$escape(props.status), _$escape(_$createComponent(Show, {
|
|
954
|
+
get when() {
|
|
955
|
+
return check();
|
|
956
|
+
},
|
|
957
|
+
get children() {
|
|
958
|
+
return [_$ssr(_tmpl$1, _$ssrAttribute("title", missingSeparator() ? _$escape(t().checkSeparatorDetail, true) : _$escape(t().checkTableDetail, true), false), _$escape(t().checkTable)), _$createComponent(Button, {
|
|
959
|
+
size: "sm",
|
|
960
|
+
variant: "ghost",
|
|
961
|
+
get disabled() {
|
|
962
|
+
return blocked() || !missingSeparator() && unavailable();
|
|
963
|
+
},
|
|
964
|
+
get hidden() {
|
|
965
|
+
return props.readOnly;
|
|
966
|
+
},
|
|
967
|
+
get tooltip() {
|
|
968
|
+
return _$memo(() => !!missingSeparator())() ? t().checkSeparatorDetail : _$memo(() => !!unavailable())() ? t().structureUnavailable : t().checkTableDetail;
|
|
969
|
+
},
|
|
970
|
+
onMouseDown: preserveSelection,
|
|
971
|
+
onClick: () => {
|
|
972
|
+
if (!editor) return;
|
|
973
|
+
if (missingSeparator()) {
|
|
974
|
+
selectMode("source");
|
|
975
|
+
queueMicrotask(() => editor?.view.focus());
|
|
976
|
+
return;
|
|
977
|
+
}
|
|
978
|
+
const table = findTables(editor.view.state.doc.toString()).find(table => table.lines.some(row => row.cells.length > table.columns));
|
|
979
|
+
if (table) runTableAction(editor.view, table.from, 0, 0, "completeColumns");
|
|
980
|
+
},
|
|
981
|
+
get children() {
|
|
982
|
+
return missingSeparator() ? t().reviewMarkdown : t().completeColumns;
|
|
983
|
+
}
|
|
984
|
+
})];
|
|
985
|
+
}
|
|
986
|
+
})));
|
|
987
|
+
}
|
|
988
|
+
})), _$escape(_$createComponent(Show, {
|
|
989
|
+
get when() {
|
|
990
|
+
return _$memo(() => !!(!props.readOnly && mode() !== "plain"))() && props.toolbar !== false;
|
|
991
|
+
},
|
|
992
|
+
get children() {
|
|
993
|
+
return _$ssr(_tmpl$11, _$escape(_$createComponent(Toolbar, {
|
|
994
|
+
"class": "k2b-ste-toolbar",
|
|
995
|
+
get label() {
|
|
996
|
+
return t().formatting;
|
|
997
|
+
},
|
|
998
|
+
get children() {
|
|
999
|
+
return [_$createComponent(For, {
|
|
1000
|
+
get each() {
|
|
1001
|
+
return [toolbar.slice(0, 3), toolbar.slice(3, 6), toolbar.slice(6)];
|
|
1002
|
+
},
|
|
1003
|
+
children: group => _$createComponent(Toolbar.Group, {
|
|
1004
|
+
"class": "k2b-ste-tool-group",
|
|
1005
|
+
get children() {
|
|
1006
|
+
return _$createComponent(For, {
|
|
1007
|
+
each: group,
|
|
1008
|
+
children: ([command, icon]) => command === "heading" || command === "code" ? formatMenu(command) : _$createComponent(Show, {
|
|
1009
|
+
get when() {
|
|
1010
|
+
return _$memo(() => !!(command === "table" && mode() === "formatted"))() && cell()?.isConnected;
|
|
1011
|
+
},
|
|
1012
|
+
get fallback() {
|
|
1013
|
+
return _$createComponent(IconButton, {
|
|
1014
|
+
"class": "k2b-ste-tool",
|
|
1015
|
+
variant: "ghost",
|
|
1016
|
+
size: "sm",
|
|
1017
|
+
get label() {
|
|
1018
|
+
return t()[command];
|
|
1019
|
+
},
|
|
1020
|
+
get tooltip() {
|
|
1021
|
+
return _$memo(() => !!shortcuts[command])() ? `${t()[command]} (${formatShortcut(shortcuts[command] ?? "", {
|
|
1022
|
+
platform: platform(),
|
|
1023
|
+
locale: locale()
|
|
1024
|
+
}).label})` : t()[command];
|
|
1025
|
+
},
|
|
1026
|
+
get disabled() {
|
|
1027
|
+
return blocked() || !!cell() && !inlineCommands.has(command) && command !== "table";
|
|
1028
|
+
},
|
|
1029
|
+
onMouseDown: preserveSelection,
|
|
1030
|
+
onClick: () => runFormat(command),
|
|
1031
|
+
get children() {
|
|
1032
|
+
return _$ssr(_tmpl$0, `ti ti-${_$escape(icon, true)}`);
|
|
1033
|
+
}
|
|
1034
|
+
});
|
|
1035
|
+
},
|
|
1036
|
+
get children() {
|
|
1037
|
+
return menu(false);
|
|
1038
|
+
}
|
|
1039
|
+
})
|
|
1040
|
+
});
|
|
1041
|
+
}
|
|
1042
|
+
})
|
|
1043
|
+
}), _$createComponent(SegmentedControl, {
|
|
1044
|
+
"class": "k2b-ste-views",
|
|
1045
|
+
size: "sm",
|
|
1046
|
+
get ariaLabel() {
|
|
1047
|
+
return t().view;
|
|
1048
|
+
},
|
|
1049
|
+
get value() {
|
|
1050
|
+
return mode() === "source" ? "source" : "formatted";
|
|
1051
|
+
},
|
|
1052
|
+
get options() {
|
|
1053
|
+
return [{
|
|
1054
|
+
value: "formatted",
|
|
1055
|
+
label: t().formatted,
|
|
1056
|
+
icon: "ti ti-typography"
|
|
1057
|
+
}, {
|
|
1058
|
+
value: "source",
|
|
1059
|
+
label: t().source,
|
|
1060
|
+
icon: "ti ti-markdown"
|
|
1061
|
+
}];
|
|
1062
|
+
},
|
|
1063
|
+
onValueChange: selectMode
|
|
1064
|
+
})];
|
|
1065
|
+
}
|
|
1066
|
+
})));
|
|
1067
|
+
}
|
|
1068
|
+
})), _$escape(_$createComponent(Show, {
|
|
1069
|
+
get when() {
|
|
1070
|
+
return props.loading || !ready();
|
|
1071
|
+
},
|
|
1072
|
+
get children() {
|
|
1073
|
+
return _$ssr(_tmpl$12, _$ssrAttribute("aria-label", _$escape(t().loading, true), false), _$escape(_$createComponent(For, {
|
|
1074
|
+
each: [82, 100, 68, 0, 96, 74],
|
|
1075
|
+
children: width => _$ssr(_tmpl$17, _$ssrStyleProperty("width:", `${_$escape(width, true)}%`))
|
|
1076
|
+
})));
|
|
1077
|
+
}
|
|
1078
|
+
})), _$ssrAttribute("class", props.presentation ? "k2b-ste-app-host" : "k2b-ste-host", false), _$ssrAttribute("hidden", props.loading || !ready(), true), _$escape(_$createComponent(Show, {
|
|
1079
|
+
get when() {
|
|
1080
|
+
return _$memo(() => !!(cell() && mode() === "formatted"))() && !menuBlocked();
|
|
1081
|
+
},
|
|
1082
|
+
get children() {
|
|
1083
|
+
return _$ssr(_tmpl$13, _$ssrAttribute("data-readonly", props.readOnly ? "true" : _$escape(undefined, true), false), _$ssrStyle(menuPosition()), _$escape(menu(true)));
|
|
1084
|
+
}
|
|
1085
|
+
})), _$escape(_$createComponent(Show, {
|
|
1086
|
+
get when() {
|
|
1087
|
+
return notice() || recovery() !== undefined;
|
|
1088
|
+
},
|
|
1089
|
+
get children() {
|
|
1090
|
+
return _$ssr(_tmpl$15, _$escape(_$createComponent(Show, {
|
|
1091
|
+
get when() {
|
|
1092
|
+
return notice();
|
|
1093
|
+
},
|
|
1094
|
+
get children() {
|
|
1095
|
+
return _$createComponent(Show, {
|
|
1096
|
+
get when() {
|
|
1097
|
+
return _$memo(() => !!notice()?.images)() && props.onAttachImages;
|
|
1098
|
+
},
|
|
1099
|
+
get fallback() {
|
|
1100
|
+
return _$ssr(_tmpl$18, _$escape(notice()?.message));
|
|
1101
|
+
},
|
|
1102
|
+
get children() {
|
|
1103
|
+
return _$createComponent(Button, {
|
|
1104
|
+
size: "sm",
|
|
1105
|
+
variant: "ghost",
|
|
1106
|
+
get disabled() {
|
|
1107
|
+
return blocked();
|
|
1108
|
+
},
|
|
1109
|
+
onClick: () => props.onAttachImages?.(),
|
|
1110
|
+
get children() {
|
|
1111
|
+
return notice()?.message;
|
|
1112
|
+
}
|
|
1113
|
+
});
|
|
1114
|
+
}
|
|
1115
|
+
});
|
|
1116
|
+
}
|
|
1117
|
+
})), _$escape(_$createComponent(Show, {
|
|
1118
|
+
get when() {
|
|
1119
|
+
return recovery() !== undefined;
|
|
1120
|
+
},
|
|
1121
|
+
get children() {
|
|
1122
|
+
return [_$ssr(_tmpl$6, _$escape(t().recoveredInput), _$ssrAttribute("value", _$escape(recovery(), true), false)), _$createComponent(Button, {
|
|
1123
|
+
size: "sm",
|
|
1124
|
+
variant: "ghost",
|
|
1125
|
+
onClick: () => {
|
|
1126
|
+
setRecovery(undefined);
|
|
1127
|
+
if (notice()?.message === t().cellRemoved) setNotice(undefined);
|
|
1128
|
+
},
|
|
1129
|
+
get children() {
|
|
1130
|
+
return t().discardRecovery;
|
|
1131
|
+
}
|
|
1132
|
+
})];
|
|
1133
|
+
}
|
|
1134
|
+
})), _$escape(_$createComponent(Show, {
|
|
1135
|
+
get when() {
|
|
1136
|
+
return notice();
|
|
1137
|
+
},
|
|
1138
|
+
get children() {
|
|
1139
|
+
return _$createComponent(IconButton, {
|
|
1140
|
+
size: "sm",
|
|
1141
|
+
variant: "ghost",
|
|
1142
|
+
get label() {
|
|
1143
|
+
return t().dismiss;
|
|
1144
|
+
},
|
|
1145
|
+
onClick: () => setNotice(undefined),
|
|
1146
|
+
get children() {
|
|
1147
|
+
return _$ssr(_tmpl$14);
|
|
1148
|
+
}
|
|
1149
|
+
});
|
|
1150
|
+
}
|
|
1151
|
+
})));
|
|
1152
|
+
}
|
|
1153
|
+
})));
|
|
1154
|
+
}
|
|
1155
|
+
//# sourceMappingURL=TextEditor.js.map
|