@humandialog/forms.svelte 1.8.1 → 1.8.2
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/components/kanban/internal/kanban.card.svelte +19 -35
- package/components/list/internal/list.element.svelte +35 -69
- package/components/list/internal/list.inserter.svelte +0 -36
- package/components/list/list.svelte +1 -4
- package/components/list/list.svelte.d.ts +0 -3
- package/components/r.editable.svelte +1 -3
- package/desk.svelte +2 -2
- package/package.json +1 -1
- package/updates.js +1 -1
- package/utils.js +33 -48
|
@@ -11,11 +11,13 @@ import {
|
|
|
11
11
|
informModification,
|
|
12
12
|
pushChanges,
|
|
13
13
|
startEditing,
|
|
14
|
-
Ricon
|
|
14
|
+
Ricon,
|
|
15
|
+
focusEditable
|
|
15
16
|
} from "../../..";
|
|
16
17
|
import { FaRegFileAlt } from "svelte-icons/fa";
|
|
17
18
|
import Properties from "./kanban.props.svelte";
|
|
18
19
|
import { KanbanCardTop, KanbanCardMiddle, KanbanCardBottom } from "../Kanban";
|
|
20
|
+
import Editable from "../../r.editable.svelte";
|
|
19
21
|
export let item;
|
|
20
22
|
let definition = getContext("rKanban-definition");
|
|
21
23
|
$:
|
|
@@ -97,28 +99,15 @@ function setSelectionAtEnd(element) {
|
|
|
97
99
|
let topProps;
|
|
98
100
|
let middleProps;
|
|
99
101
|
let bottomProps;
|
|
100
|
-
let titleElement;
|
|
101
|
-
let summaryElement;
|
|
102
102
|
let summaryPlaceholder = false;
|
|
103
103
|
export async function editProperty(field) {
|
|
104
104
|
if (field == "Title") {
|
|
105
|
-
|
|
106
|
-
startEditing(titleElement);
|
|
107
|
-
} else {
|
|
108
|
-
titleElement.focus();
|
|
109
|
-
await tick();
|
|
110
|
-
setSelectionAtEnd(titleElement);
|
|
111
|
-
}
|
|
105
|
+
focusEditable("#__or_kanban_ctrl_Title");
|
|
112
106
|
} else if (field == "Summary") {
|
|
113
|
-
if (
|
|
114
|
-
summaryElement.focus();
|
|
115
|
-
await tick();
|
|
116
|
-
setSelectionAtEnd(summaryElement);
|
|
117
|
-
} else {
|
|
107
|
+
if (!focusEditable("#__or_kanban_ctrl_Summary")) {
|
|
118
108
|
summaryPlaceholder = true;
|
|
119
109
|
await tick();
|
|
120
|
-
|
|
121
|
-
summaryElement.focus();
|
|
110
|
+
focusEditable("#__or_kanban_ctrl_Summary");
|
|
122
111
|
}
|
|
123
112
|
} else {
|
|
124
113
|
const property = definition.properties.find((p) => p.name == field);
|
|
@@ -209,23 +198,22 @@ function showAttachementIcon() {
|
|
|
209
198
|
{@const showIcon = showAttachementIcon()}
|
|
210
199
|
<!-- whitespace-nowrap overflow-clip -->
|
|
211
200
|
<h4 class = "font-semibold relative"
|
|
212
|
-
use:editable={{
|
|
213
|
-
action: (text) => onTitleChanged(text),
|
|
214
|
-
active: false,
|
|
215
|
-
readonly: definition.titleReadOnly,
|
|
216
|
-
onFinish: (d) => {titleElement.blur()},
|
|
217
|
-
onSoftEnter: async (text) => { onTitleChanged(text); await editProperty('Summary') }
|
|
218
|
-
}}
|
|
219
201
|
use:conditionalClick={{
|
|
220
202
|
condition: hasOpen,
|
|
221
|
-
callback: performOpen}}
|
|
222
|
-
bind:this={titleElement}>
|
|
203
|
+
callback: performOpen}}>
|
|
223
204
|
{#if isLinkLike}
|
|
224
205
|
<a class= "font-semibold" href={getHRef()} use:link>
|
|
225
|
-
{item
|
|
206
|
+
<Editable self={item}
|
|
207
|
+
a={definition.titleAttrib}
|
|
208
|
+
readonly={definition.titleReadOnly}
|
|
209
|
+
focusOnClick={false}
|
|
210
|
+
id="__or_kanban_ctrl_Title"/>
|
|
226
211
|
</a>
|
|
227
212
|
{:else}
|
|
228
|
-
{item
|
|
213
|
+
<Editable self={item}
|
|
214
|
+
a={definition.titleAttrib}
|
|
215
|
+
readonly={definition.titleReadOnly}
|
|
216
|
+
id="__or_kanban_ctrl_Title"/>
|
|
229
217
|
{/if}
|
|
230
218
|
|
|
231
219
|
|
|
@@ -258,13 +246,9 @@ function showAttachementIcon() {
|
|
|
258
246
|
{#if item[definition.summaryAttrib] || summaryPlaceholder}
|
|
259
247
|
{#key item[definition.summaryAttrib]}
|
|
260
248
|
{#if isCardActive}
|
|
261
|
-
<figcaption
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
readonly: definition.summaryReadOnly,
|
|
265
|
-
onFinish: (d) => {summaryPlaceholder = false}}}
|
|
266
|
-
bind:this={summaryElement}>
|
|
267
|
-
{item[definition.summaryAttrib]}
|
|
249
|
+
<figcaption><Editable self={item}
|
|
250
|
+
a={definition.summaryAttrib}
|
|
251
|
+
id="__or_kanban_ctrl_Summary"/>
|
|
268
252
|
</figcaption>
|
|
269
253
|
{:else}
|
|
270
254
|
<figcaption>
|
|
@@ -8,7 +8,8 @@ import {
|
|
|
8
8
|
editable,
|
|
9
9
|
startEditing,
|
|
10
10
|
addActiveItem,
|
|
11
|
-
removeActiveItem
|
|
11
|
+
removeActiveItem,
|
|
12
|
+
focusEditable
|
|
12
13
|
} from "../../../utils";
|
|
13
14
|
import { showGridMenu, showMenu } from "../../menu";
|
|
14
15
|
import { pushChanges, informModification } from "../../../updates";
|
|
@@ -16,12 +17,10 @@ import { isDeviceSmallerThan } from "../../../utils";
|
|
|
16
17
|
import Circle from "../../ricons/circle.svelte";
|
|
17
18
|
import CircleCheck from "../../ricons/circle-check.svelte";
|
|
18
19
|
import Ricon from "../../r.icon.svelte";
|
|
19
|
-
import Spinner from "../../delayed.spinner.svelte";
|
|
20
20
|
import { rList_definition, rList_property_type } from "../List";
|
|
21
21
|
import { push, link } from "svelte-spa-router";
|
|
22
|
-
import { FaExternalLinkAlt, FaRegCircle, FaRegCheckCircle } from "svelte-icons/fa/";
|
|
23
|
-
import Tags from "../../tags.svelte";
|
|
24
22
|
import { ext } from "../../../i18n";
|
|
23
|
+
import Editable from "../../r.editable.svelte";
|
|
25
24
|
export let item;
|
|
26
25
|
export let element_title = "";
|
|
27
26
|
export let list_properties = void 0;
|
|
@@ -188,21 +187,12 @@ export function editProperty(field) {
|
|
|
188
187
|
}
|
|
189
188
|
}
|
|
190
189
|
async function force_editing(field) {
|
|
191
|
-
let element_id =
|
|
192
|
-
|
|
193
|
-
if (!element_node) {
|
|
190
|
+
let element_id = `#__or_list_ctrl_${getItemKey(item)}_${field}`;
|
|
191
|
+
if (!focusEditable(element_id)) {
|
|
194
192
|
placeholder = field;
|
|
195
193
|
await tick();
|
|
196
|
-
|
|
197
|
-
if (!element_node)
|
|
198
|
-
return;
|
|
194
|
+
focusEditable(element_id);
|
|
199
195
|
}
|
|
200
|
-
if (!element_node.classList.contains("editable")) {
|
|
201
|
-
return;
|
|
202
|
-
}
|
|
203
|
-
startEditing(element_node, () => {
|
|
204
|
-
placeholder = "";
|
|
205
|
-
});
|
|
206
196
|
}
|
|
207
197
|
function setSelectionAtEnd(element) {
|
|
208
198
|
const textNode = element.childNodes[0];
|
|
@@ -408,36 +398,30 @@ async function onDownloadFile(e) {
|
|
|
408
398
|
href={element_href}
|
|
409
399
|
on:click={onDownloadFile}>
|
|
410
400
|
|
|
411
|
-
<h4 class="-indent-8"
|
|
412
|
-
id="__or_list_ctrl_{getItemKey(item)}_Title"
|
|
413
|
-
use:editable={{
|
|
414
|
-
action: (text) => {change_property(element_title, text)},
|
|
415
|
-
active: false,
|
|
416
|
-
readonly: title_readonly,
|
|
417
|
-
onSoftEnter: (text) => {change_name(text); editProperty('Summary')}
|
|
418
|
-
}}>
|
|
401
|
+
<h4 class="-indent-8">
|
|
419
402
|
<div class="inline-block w-4 h-4 ml-0 mr-4 align-baseline
|
|
420
403
|
text-stone-700 dark:text-stone-400 ">
|
|
421
404
|
<Ricon icon={isDownloading ? 'loader-circle' : element_icon} />
|
|
422
|
-
</div
|
|
405
|
+
</div><Editable self={item}
|
|
406
|
+
a={element_title}
|
|
407
|
+
id="__or_list_ctrl_{getItemKey(item)}_Title"
|
|
408
|
+
readonly={title_readonly}
|
|
409
|
+
focusOnClick={false}/>
|
|
423
410
|
</h4>
|
|
424
411
|
</a>
|
|
425
412
|
{:else if element_href}
|
|
426
413
|
<a class="sm:hover:cursor-pointer"
|
|
427
414
|
href={element_href} use:link>
|
|
428
415
|
|
|
429
|
-
<h4 class="-indent-8 "
|
|
430
|
-
id="__or_list_ctrl_{getItemKey(item)}_Title"
|
|
431
|
-
use:editable={{
|
|
432
|
-
action: (text) => {change_property(element_title, text)},
|
|
433
|
-
active: false,
|
|
434
|
-
readonly: title_readonly,
|
|
435
|
-
onSoftEnter: (text) => {change_name(text); editProperty('Summary')}
|
|
436
|
-
}}>
|
|
416
|
+
<h4 class="-indent-8 ">
|
|
437
417
|
<div class="inline-block w-4 h-4 ml-0 mr-4 align-baseline
|
|
438
418
|
text-stone-700 dark:text-stone-400 ">
|
|
439
419
|
<Ricon icon={element_icon} />
|
|
440
|
-
</div
|
|
420
|
+
</div><Editable self={item}
|
|
421
|
+
a={element_title}
|
|
422
|
+
id="__or_list_ctrl_{getItemKey(item)}_Title"
|
|
423
|
+
readonly={title_readonly}
|
|
424
|
+
focusOnClick={false}/>
|
|
441
425
|
</h4>
|
|
442
426
|
</a>
|
|
443
427
|
{:else if element_open_handler}
|
|
@@ -445,33 +429,26 @@ async function onDownloadFile(e) {
|
|
|
445
429
|
href="/#"
|
|
446
430
|
on:click|preventDefault={() => element_open_handler(item)}>
|
|
447
431
|
|
|
448
|
-
<h4 class="-indent-8"
|
|
449
|
-
id="__or_list_ctrl_{getItemKey(item)}_Title"
|
|
450
|
-
use:editable={{
|
|
451
|
-
action: (text) => {change_property(element_title, text)},
|
|
452
|
-
active: false,
|
|
453
|
-
readonly: title_readonly,
|
|
454
|
-
onSoftEnter: (text) => {change_name(text); editProperty('Summary')}
|
|
455
|
-
}}>
|
|
432
|
+
<h4 class="-indent-8">
|
|
456
433
|
<div class="inline-block w-4 h-4 ml-0 mr-4 align-baseline
|
|
457
434
|
text-stone-700 dark:text-stone-400 ">
|
|
458
435
|
<Ricon icon={element_icon} />
|
|
459
|
-
</div
|
|
436
|
+
</div><Editable self={item}
|
|
437
|
+
a={element_title}
|
|
438
|
+
id="__or_list_ctrl_{getItemKey(item)}_Title"
|
|
439
|
+
readonly={title_readonly}
|
|
440
|
+
focusOnClick={false}/>
|
|
460
441
|
</h4>
|
|
461
442
|
</a>
|
|
462
443
|
{:else}
|
|
463
|
-
<h4 class="-indent-8
|
|
464
|
-
id="__or_list_ctrl_{getItemKey(item)}_Title"
|
|
465
|
-
use:editable={{
|
|
466
|
-
action: (text) => {change_property(element_title, text)},
|
|
467
|
-
active: false,
|
|
468
|
-
readonly: title_readonly,
|
|
469
|
-
onSoftEnter: (text) => {change_name(text); editProperty('Summary')}
|
|
470
|
-
}}>
|
|
444
|
+
<h4 class="-indent-8">
|
|
471
445
|
<div class="inline-block w-4 h-4 ml-0 mr-4 align-baseline
|
|
472
446
|
text-stone-700 dark:text-stone-400 ">
|
|
473
447
|
<Ricon icon={element_icon} />
|
|
474
|
-
</div
|
|
448
|
+
</div><Editable self={item}
|
|
449
|
+
a={element_title}
|
|
450
|
+
id="__or_list_ctrl_{getItemKey(item)}_Title"
|
|
451
|
+
readonly={title_readonly}/>
|
|
475
452
|
</h4>
|
|
476
453
|
{/if}
|
|
477
454
|
|
|
@@ -485,25 +462,14 @@ async function onDownloadFile(e) {
|
|
|
485
462
|
</figcaption>
|
|
486
463
|
-------------------------------->
|
|
487
464
|
|
|
488
|
-
{#if summary && (item[summary])}
|
|
489
|
-
<figcaption
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
active: true
|
|
494
|
-
}}>{item[summary]}
|
|
495
|
-
</figcaption>
|
|
496
|
-
|
|
497
|
-
{:else if placeholder=='Summary'}
|
|
498
|
-
<figcaption id="__or_list_ctrl_{getItemKey(item)}_Summary"
|
|
499
|
-
use:editable={{
|
|
500
|
-
action: (text) => {change_property(summary, text)},
|
|
501
|
-
readonly: summary_readonly,
|
|
502
|
-
onFinish: (d) => {placeholder='';},
|
|
503
|
-
active: true
|
|
504
|
-
}}>
|
|
465
|
+
{#if (summary && (item[summary])) || (placeholder=='Summary')}
|
|
466
|
+
<figcaption><Editable self={item}
|
|
467
|
+
a={summary}
|
|
468
|
+
id="__or_list_ctrl_{getItemKey(item)}_Summary"
|
|
469
|
+
readonly={summary_readonly} />
|
|
505
470
|
</figcaption>
|
|
506
471
|
{/if}
|
|
472
|
+
|
|
507
473
|
</figure>
|
|
508
474
|
</div>
|
|
509
475
|
|
|
@@ -59,39 +59,3 @@ async function onSummaryChanged(text) {
|
|
|
59
59
|
{/if}
|
|
60
60
|
</figure>
|
|
61
61
|
|
|
62
|
-
|
|
63
|
-
<!--section class=" my-1 w-full text-base text-stone-700 dark:text-stone-400 cursor-default rounded-md border border-transparent bg-stone-200 dark:bg-stone-700">
|
|
64
|
-
<div class="flex flex-row">
|
|
65
|
-
{#if icon}
|
|
66
|
-
|
|
67
|
-
<div class="h-5 w-5 sm:h-4 sm:w-4 mt-2 sm:mt-1.5 ml-2"></div>
|
|
68
|
-
{/if}
|
|
69
|
-
|
|
70
|
-
<p class=" ml-3 py-1
|
|
71
|
-
text-base font-semibold min-h-[1.75rem]
|
|
72
|
-
sm:min-h-[1.25rem]
|
|
73
|
-
whitespace-nowrap overflow-clip flex-none w-1/2 sm:w-1/3" tabindex="0"
|
|
74
|
-
bind:this={titleElement}
|
|
75
|
-
use:editable={{
|
|
76
|
-
action: (text) => onInsert(text, ''),
|
|
77
|
-
active: false,
|
|
78
|
-
onSoftEnter: softEnter
|
|
79
|
-
}} >
|
|
80
|
-
</p>
|
|
81
|
-
</div>
|
|
82
|
-
|
|
83
|
-
{#if editSummary}
|
|
84
|
-
<p bind:this={summaryElement}
|
|
85
|
-
class=" ml-10 sm:ml-9
|
|
86
|
-
sm:min-h-[1rem]
|
|
87
|
-
text-sm min-h-[1.5rem]
|
|
88
|
-
text-stone-400"
|
|
89
|
-
use:editable={{
|
|
90
|
-
action: onSummaryChanged,
|
|
91
|
-
active: false,
|
|
92
|
-
onFinish: (d) => {editSummary=false}
|
|
93
|
-
}}>
|
|
94
|
-
{summary}
|
|
95
|
-
</p>
|
|
96
|
-
{/if}
|
|
97
|
-
</section-->
|
|
@@ -411,10 +411,7 @@ function read_from_def(propName) {
|
|
|
411
411
|
{selectionKey}
|
|
412
412
|
bind:this={rows[i]}
|
|
413
413
|
>
|
|
414
|
-
|
|
415
|
-
<span slot="left" let:element>
|
|
416
|
-
<slot name="left" {element}/>
|
|
417
|
-
</span>
|
|
414
|
+
|
|
418
415
|
</ListElement>
|
|
419
416
|
|
|
420
417
|
{#if show_insertion_row_after_element == element}
|
package/desk.svelte
CHANGED
|
@@ -430,12 +430,12 @@
|
|
|
430
430
|
left-0 bottom-[50px]
|
|
431
431
|
sm:left-[40px] sm:top-0
|
|
432
432
|
w-full sm:w-[320px]
|
|
433
|
-
h-[calc(
|
|
433
|
+
h-[calc(100svh-50px)] sm:h-full
|
|
434
434
|
|
|
435
435
|
z-30 overflow-x-hidden
|
|
436
436
|
|
|
437
437
|
bg-stone-50 dark:bg-stone-900
|
|
438
|
-
border-
|
|
438
|
+
border-t sm:border-t-0 sm:border-r border-stone-300 dark:border-stone-300/50
|
|
439
439
|
sm:shadow-lg sm:shadow-stone-500
|
|
440
440
|
sm:dark:shadow-black">
|
|
441
441
|
|
package/package.json
CHANGED
package/updates.js
CHANGED
package/utils.js
CHANGED
|
@@ -366,8 +366,8 @@ export function editable(node, params)
|
|
|
366
366
|
|
|
367
367
|
let observer = null;
|
|
368
368
|
let has_changed = false;
|
|
369
|
+
let org_text = '';
|
|
369
370
|
|
|
370
|
-
const org_text = node.textContent;
|
|
371
371
|
const blur_listener = async (e) =>
|
|
372
372
|
{
|
|
373
373
|
if(currentEditable == node)
|
|
@@ -403,13 +403,9 @@ export function editable(node, params)
|
|
|
403
403
|
{
|
|
404
404
|
case 'Esc':
|
|
405
405
|
case 'Escape':
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
e.preventDefault();
|
|
410
|
-
|
|
411
|
-
await finish_editing({ cancel: true });
|
|
412
|
-
}
|
|
406
|
+
e.stopPropagation();
|
|
407
|
+
e.preventDefault();
|
|
408
|
+
await finish_editing({ cancel: true });
|
|
413
409
|
break;
|
|
414
410
|
|
|
415
411
|
case 'Enter':
|
|
@@ -447,16 +443,17 @@ export function editable(node, params)
|
|
|
447
443
|
const cancel = params.cancel ?? false;
|
|
448
444
|
const incremental = params.incremental ?? false;
|
|
449
445
|
|
|
446
|
+
node.removeEventListener("blur", blur_listener);
|
|
447
|
+
node.removeEventListener("keydown", key_listener);
|
|
448
|
+
node.removeEventListener("save", save_listener);
|
|
449
|
+
|
|
450
450
|
if(!active)
|
|
451
|
-
{
|
|
452
|
-
node.removeEventListener("blur", blur_listener);
|
|
453
|
-
node.removeEventListener("keydown", key_listener);
|
|
454
|
-
node.removeEventListener("save", save_listener);
|
|
455
451
|
node.contentEditable = "false"
|
|
452
|
+
else
|
|
453
|
+
node.blur()
|
|
456
454
|
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
}
|
|
455
|
+
let sel = window.getSelection();
|
|
456
|
+
sel.removeAllRanges();
|
|
460
457
|
|
|
461
458
|
if(cancel)
|
|
462
459
|
{
|
|
@@ -468,17 +465,11 @@ export function editable(node, params)
|
|
|
468
465
|
}
|
|
469
466
|
else if(action)
|
|
470
467
|
{
|
|
471
|
-
if(
|
|
468
|
+
if(has_changed)
|
|
472
469
|
{
|
|
473
|
-
|
|
474
|
-
{
|
|
475
|
-
has_changed = false;
|
|
476
|
-
await action(node.textContent)
|
|
477
|
-
}
|
|
478
|
-
|
|
479
|
-
}
|
|
480
|
-
else
|
|
470
|
+
has_changed = false;
|
|
481
471
|
await action(node.textContent)
|
|
472
|
+
}
|
|
482
473
|
}
|
|
483
474
|
|
|
484
475
|
const finish_event = new CustomEvent("finish", {
|
|
@@ -505,12 +496,6 @@ export function editable(node, params)
|
|
|
505
496
|
const edit_listener = async (e) =>
|
|
506
497
|
{
|
|
507
498
|
node.contentEditable = "true"
|
|
508
|
-
node.addEventListener("blur", blur_listener);
|
|
509
|
-
node.addEventListener("keydown", key_listener);
|
|
510
|
-
|
|
511
|
-
currentEditable = node;
|
|
512
|
-
node.addEventListener("save", save_listener)
|
|
513
|
-
|
|
514
499
|
node.focus();
|
|
515
500
|
|
|
516
501
|
/*await tick();
|
|
@@ -543,6 +528,8 @@ export function editable(node, params)
|
|
|
543
528
|
onSingleChange(node.textContent)
|
|
544
529
|
});
|
|
545
530
|
|
|
531
|
+
org_text = node.textContent;
|
|
532
|
+
|
|
546
533
|
observer.observe( node, {
|
|
547
534
|
childList: true,
|
|
548
535
|
attributes: true,
|
|
@@ -553,28 +540,26 @@ export function editable(node, params)
|
|
|
553
540
|
node.classList.add("editable")
|
|
554
541
|
node.classList.add("focus:outline-none")
|
|
555
542
|
|
|
543
|
+
node.addEventListener('focus', focus_listener);
|
|
544
|
+
node.addEventListener("edit", edit_listener);
|
|
545
|
+
|
|
546
|
+
if(onFinish)
|
|
547
|
+
node.addEventListener("finish", (e) => { onFinish(e.detail) })
|
|
548
|
+
|
|
556
549
|
if(active)
|
|
557
|
-
{
|
|
558
550
|
node.contentEditable = "true"
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
{
|
|
563
|
-
node.addEventListener("finish", (e) => { onFinish(e.detail) })
|
|
564
|
-
}
|
|
565
|
-
}
|
|
566
|
-
else
|
|
567
|
-
{
|
|
568
|
-
node.addEventListener("edit", edit_listener);
|
|
551
|
+
|
|
552
|
+
return {
|
|
553
|
+
destroy() {
|
|
569
554
|
|
|
570
|
-
|
|
571
|
-
|
|
555
|
+
node.removeEventListener("edit", edit_listener)
|
|
556
|
+
node.removeEventListener('focus', focus_listener);
|
|
557
|
+
if(onFinish)
|
|
558
|
+
node.removeEventListener("finish", (e) => { onFinish(e.detail) })
|
|
572
559
|
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
}};
|
|
577
|
-
}
|
|
560
|
+
node.classList.remove("editable")
|
|
561
|
+
|
|
562
|
+
}};
|
|
578
563
|
}
|
|
579
564
|
|
|
580
565
|
export function startEditing(element, finish_callback)
|