@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.
@@ -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
- if (isLinkLike) {
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 (!!summaryElement) {
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
- if (!!summaryElement)
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[definition.titleAttrib]}
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[definition.titleAttrib]}
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 use:editable={{
262
- action: (text) => onSummaryChanged(text),
263
- active: true,
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 = `__or_list_ctrl_${getItemKey(item)}_${field}`;
192
- let element_node = document.getElementById(element_id);
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
- element_node = document.getElementById(element_id);
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>{translated_element_title}
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>{translated_element_title}
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>{translated_element_title}
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>{translated_element_title}
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 id="__or_list_ctrl_{getItemKey(item)}_Summary" use:editable={{
490
- action: (text) => {change_property(summary, text)},
491
- readonly: summary_readonly,
492
- onFinish: (d) => {placeholder='';},
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
- }}>&nbsp;
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}
@@ -43,9 +43,6 @@ declare const __propDef: {
43
43
  };
44
44
  slots: {
45
45
  default: {};
46
- left: {
47
- element: any;
48
- };
49
46
  };
50
47
  };
51
48
  export type ListProps = typeof __propDef.props;
@@ -64,9 +64,7 @@
64
64
  }}
65
65
  on:focus={focus}
66
66
  on:blur={blur}
67
- >
68
- {ext(self[a])}
69
- </span>
67
+ >{ext(self[a])}</span>
70
68
 
71
69
  <!--style>
72
70
  span:empty:focus::before {
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(100vh-100px)] sm:h-full
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-2 sm:border-r border-stone-300 dark:border-stone-300/50
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@humandialog/forms.svelte",
3
- "version": "1.8.1",
3
+ "version": "1.8.2",
4
4
  "description": "Basic Svelte UI components for Object Reef applications",
5
5
  "devDependencies": {
6
6
  "@playwright/test": "^1.28.1",
package/updates.js CHANGED
@@ -203,7 +203,7 @@ update_request_ticket.subscribe(async (v) => {
203
203
  {
204
204
  modified_items_map.clear();
205
205
  unsavedModificationsTicket.set( get(unsavedModificationsTicket) + 1 )
206
-
206
+
207
207
  afterPushCallbacks.forEach( cb => cb())
208
208
  afterPushCallbacks = []
209
209
  }
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
- if(!active)
407
- {
408
- e.stopPropagation();
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
- let sel = window.getSelection();
458
- sel.removeAllRanges();
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(active)
468
+ if(has_changed)
472
469
  {
473
- if(has_changed)
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
- node.addEventListener('focus', focus_listener);
560
-
561
- if(onFinish)
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
- return {
571
- destroy() {
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
- node.removeEventListener("edit", edit_listener)
574
- node.classList.remove("editable")
575
- node.contentEditable = "false"
576
- }};
577
- }
560
+ node.classList.remove("editable")
561
+
562
+ }};
578
563
  }
579
564
 
580
565
  export function startEditing(element, finish_callback)