@humandialog/forms.svelte 1.4.7 → 1.4.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,10 +1,19 @@
1
- <script>import { each } from "svelte/internal";
2
- import { contextToolbarOperations, pageToolbarOperations, contextItemsStore, toolsActionsOperations, fabCollapsed } from "../stores.js";
1
+ <script>import { contextToolbarOperations, pageToolbarOperations, leftHandedFAB, toolsActionsOperations, fabCollapsed, bottom_bar_visible_store, main_sidebar_visible_store } from "../stores.js";
3
2
  import { showFloatingToolbar, showMenu, showGridMenu } from "./menu.js";
4
3
  import { FaChevronUp, FaChevronDown, FaChevronLeft, FaChevronRight, FaCircle, FaEllipsisV, FaRegDotCircle, FaDotCircle } from "svelte-icons/fa/";
5
4
  import { isDeviceSmallerThan } from "../utils.js";
5
+ import { tick } from "svelte";
6
+ export let mainPageCoords = void 0;
6
7
  $:
7
- setupCurrentContextOperations($pageToolbarOperations, $contextToolbarOperations, $toolsActionsOperations, $fabCollapsed);
8
+ setupCurrentContextOperations(
9
+ $pageToolbarOperations,
10
+ $contextToolbarOperations,
11
+ $toolsActionsOperations,
12
+ $fabCollapsed,
13
+ $bottom_bar_visible_store,
14
+ $main_sidebar_visible_store,
15
+ $leftHandedFAB
16
+ );
8
17
  let operations = [];
9
18
  let mainOperation = null;
10
19
  let secondaryOperation = null;
@@ -13,7 +22,8 @@ let isExpandable = false;
13
22
  let vToolboxExpanded = false;
14
23
  let hToolboxExpanded = false;
15
24
  let isDirectPositioningMode = false;
16
- function setupCurrentContextOperations(...args) {
25
+ async function setupCurrentContextOperations(...args) {
26
+ await tick();
17
27
  let opVer = 0;
18
28
  let main_FAB_position = "";
19
29
  isDirectPositioningMode = false;
@@ -179,7 +189,6 @@ function getSelectionPos() {
179
189
  return 0;
180
190
  }
181
191
  function calculatePosition(operation) {
182
- const isLeftHanded = false;
183
192
  let result = "";
184
193
  const fab = operation.fab;
185
194
  if (fab.length != 3)
@@ -192,46 +201,62 @@ function calculatePosition(operation) {
192
201
  const width = 55;
193
202
  const height = 55;
194
203
  const margin = 10;
195
- if (!isLeftHanded) {
204
+ let lShift = 0;
205
+ let tShift = 0;
206
+ let rShift = 0;
207
+ let bShift = 0;
208
+ let vMiddle = "50vh";
209
+ if (!isDeviceSmallerThan("sm")) {
210
+ const container = document.getElementById("__hd_svelte_main_content_container");
211
+ if (container) {
212
+ const containerRect = container?.getBoundingClientRect();
213
+ lShift = containerRect.x;
214
+ tShift = containerRect.y;
215
+ bShift = window.innerHeight - containerRect.bottom;
216
+ rShift = window.innerWidth - containerRect.right;
217
+ vMiddle = `${containerRect.x + containerRect.width / 2}px`;
218
+ }
219
+ }
220
+ if (!$leftHandedFAB) {
196
221
  switch (section) {
197
222
  case "M":
198
- result = `right: ${margin + col_no * width}px; bottom: ${margin + row_no * height}px`;
223
+ result = `right: ${rShift + margin + col_no * width}px; bottom: ${bShift + margin + row_no * height}px`;
199
224
  break;
200
225
  case "S":
201
- result = `left: ${margin + col_no * width}px; bottom: ${margin + row_no * height}px`;
226
+ result = `left: ${lShift + margin + col_no * width}px; bottom: ${bShift + margin + row_no * height}px`;
202
227
  break;
203
228
  case "A":
204
- result = `right: ${margin + col_no * width}px; top: calc(50vh - ${row_no * height}px)`;
229
+ result = `right: ${rShift + margin + col_no * width}px; top: calc(${vMiddle} - ${row_no * height}px)`;
205
230
  break;
206
231
  case "C":
207
- result = `left: ${margin + col_no * width}px; top: calc(50vh - ${row_no * height}px)`;
232
+ result = `left: ${lShift + margin + col_no * width}px; top: calc(${vMiddle} - ${row_no * height}px)`;
208
233
  break;
209
234
  case "T":
210
- result = `right: ${margin + col_no * width}px; top: ${margin + row_no * height}px`;
235
+ result = `right: ${rShift + margin + col_no * width}px; top: ${tShift + margin + row_no * height}px`;
211
236
  break;
212
237
  case "F":
213
- result = `left: ${margin + col_no * width}px; top: ${margin + row_no * height}px`;
238
+ result = `left: ${lShift + margin + col_no * width}px; top: ${tShift + margin + row_no * height}px`;
214
239
  break;
215
240
  }
216
241
  } else {
217
242
  switch (section) {
218
243
  case "M":
219
- result = `left: ${margin + col_no * width}px; bottom: ${margin + row_no * height}px`;
244
+ result = `left: ${lShift + margin + col_no * width}px; bottom: ${bShift + margin + row_no * height}px`;
220
245
  break;
221
246
  case "S":
222
- result = `right: ${margin + col_no * width}px; bottom: ${margin + row_no * height}px`;
247
+ result = `right: ${rShift + margin + col_no * width}px; bottom: ${bShift + margin + row_no * height}px`;
223
248
  break;
224
249
  case "A":
225
- result = `left: ${margin + col_no * width}px; top: calc(50vh - ${row_no * height}px)`;
250
+ result = `left: ${lShift + margin + col_no * width}px; top: calc(${vMiddle} - ${row_no * height}px)`;
226
251
  break;
227
252
  case "C":
228
- result = `right: ${margin + col_no * width}px; top: calc(50vh - ${row_no * height}px)`;
253
+ result = `right: ${rShift + margin + col_no * width}px; top: calc(${vMiddle} - ${row_no * height}px)`;
229
254
  break;
230
255
  case "T":
231
- result = `left: ${margin + col_no * width}px; top: ${margin + row_no * height}px`;
256
+ result = `left: ${lShift + margin + col_no * width}px; top: ${tShift + margin + row_no * height}px`;
232
257
  break;
233
258
  case "F":
234
- result = `right: ${margin + col_no * width}px; top: ${margin + row_no * height}px`;
259
+ result = `right: ${rShift + margin + col_no * width}px; top: ${tShift + margin + row_no * height}px`;
235
260
  break;
236
261
  }
237
262
  }
@@ -246,8 +271,13 @@ function operationVisible(operation) {
246
271
  if (operation.fab == "M10")
247
272
  return true;
248
273
  return false;
249
- } else
274
+ } else {
275
+ if (operation.disabledFunc)
276
+ return !operation.disabledFunc();
277
+ else if (operation.disabled)
278
+ return false;
250
279
  return true;
280
+ }
251
281
  }
252
282
  </script>
253
283
 
@@ -266,7 +296,7 @@ function operationVisible(operation) {
266
296
  fixed m-0
267
297
  flex items-center justify-center
268
298
  disable-dbl-tap-zoom
269
- cursor-pointer z-40"
299
+ cursor-pointer z-20"
270
300
  style={position}
271
301
  on:click|stopPropagation={(e) => {on_click(e, operation)}}
272
302
  on:mousedown={mousedown} >
@@ -1,6 +1,7 @@
1
1
  import { SvelteComponentTyped } from "svelte";
2
2
  declare const __propDef: {
3
3
  props: {
4
+ mainPageCoords?: undefined;
4
5
  activateMainOperation?: (() => void) | undefined;
5
6
  };
6
7
  events: {
@@ -2,6 +2,7 @@
2
2
  import { isDeviceSmallerThan } from "../utils";
3
3
  import { pushToolsActionsOperations, popToolsActionsOperations } from "../stores";
4
4
  import { FaTimes } from "svelte-icons/fa";
5
+ import Icon from "./icon.svelte";
5
6
  let x;
6
7
  let y;
7
8
  let visible = false;
@@ -10,6 +11,7 @@ let props = {};
10
11
  let around_rect;
11
12
  let rootElement;
12
13
  let internalElement;
14
+ let closeButtonPos = "";
13
15
  export async function show(around, _toolbar, _props = {}) {
14
16
  if (around instanceof DOMRect) {
15
17
  x = around.left;
@@ -34,7 +36,7 @@ export async function show(around, _toolbar, _props = {}) {
34
36
  props.onSizeChanged = () => onSizeChanged();
35
37
  hide_window_indicator = 0;
36
38
  window.addEventListener("click", on_before_window_click, true);
37
- if (isDeviceSmallerThan("sm")) {
39
+ if (false) {
38
40
  pushToolsActionsOperations({
39
41
  opver: 1,
40
42
  operations: [
@@ -63,7 +65,7 @@ export function isVisible() {
63
65
  return visible;
64
66
  }
65
67
  export function hide() {
66
- if (visible)
68
+ if (false)
67
69
  popToolsActionsOperations();
68
70
  visible = false;
69
71
  cssPosition = calculatePosition(x, y, around_rect, false, false);
@@ -124,6 +126,7 @@ function calculatePosition(x2, y2, around, visible2, fresh) {
124
126
  y2 = screenRect.bottom - maxHeight - margin;
125
127
  result = `left: ${x2}px; top: ${y2}px; width: ${width}px; max-height: ${maxHeight}px; display: block`;
126
128
  }
129
+ closeButtonPos = `right: ${margin}px; top: calc(${y2}px - 1.75rem)`;
127
130
  } else {
128
131
  let myRect = null;
129
132
  if (!fresh) {
@@ -144,15 +147,28 @@ function calculatePosition(x2, y2, around, visible2, fresh) {
144
147
  y2 = screenRect.top;
145
148
  }
146
149
  result = `left:${x2}px; top:${y2}px; width: max-content; height:max-content; display: block`;
150
+ closeButtonPos = ``;
147
151
  }
148
152
  return result;
149
153
  }
150
154
  </script>
151
155
 
152
156
  <div id="__hd_svelte_floating_container"
153
- class="p-2 bg-stone-100 dark:bg-stone-800 rounded-lg shadow-md shadow-stone-500 dark:shadow-black z-30 fixed "
157
+ class="p-2 bg-stone-100 dark:bg-stone-800 rounded-lg shadow-md shadow-stone-500 dark:shadow-black z-40 fixed "
154
158
  style={cssPosition}
155
159
  bind:this={rootElement}>
160
+ {#if closeButtonPos}
161
+ <button class=" fixed w-6 h-6 flex items-center justify-center
162
+ text-stone-500 bg-stone-200/70 hover:bg-stone-200
163
+ focus:outline-none font-medium rounded-full text-sm text-center
164
+ dark:text-stone-500 dark:bg-stone-700/80 dark:hover:bg-stone-700
165
+ focus:ring-4 focus:ring-blue-300 dark:focus:ring-blue-800"
166
+ style={closeButtonPos}
167
+ on:click={ hide }>
168
+ <Icon component={FaTimes} s="md"/>
169
+ </button>
170
+ {/if}
171
+
156
172
  <svelte:component this={toolbar} {...props} bind:this={internalElement} />
157
173
  </div>
158
174
 
@@ -6,6 +6,7 @@ import { rCombo_definition, rCombo_item, cached_sources } from "./combo";
6
6
  import { FaChevronDown, FaTimes } from "svelte-icons/fa";
7
7
  import Icon from "../icon.svelte";
8
8
  import { reef } from "@humandialog/auth.svelte/dist/index.js";
9
+ import { showMenu } from "../menu.js";
9
10
  export let label = "";
10
11
  export let self = null;
11
12
  export let a = "";
@@ -140,13 +141,19 @@ afterUpdate(() => {
140
141
  if (is_dropdown_open && textbox && document.activeElement != textbox)
141
142
  textbox.focus();
142
143
  });
144
+ let closeButtonPos = "";
145
+ let dropdownElement;
143
146
  function dropdown_action(node) {
144
- if (is_dropdown_open)
145
- dropdown_height = node.getBoundingClientRect().height;
147
+ if (is_dropdown_open) {
148
+ const rect = node.getBoundingClientRect();
149
+ dropdown_height = rect.height;
150
+ }
146
151
  return {
147
152
  update() {
148
- if (is_dropdown_open)
149
- dropdown_height = node.getBoundingClientRect().height;
153
+ if (is_dropdown_open) {
154
+ const rect = node.getBoundingClientRect();
155
+ dropdown_height = rect.height;
156
+ }
150
157
  },
151
158
  destroy() {
152
159
  }
@@ -174,58 +181,7 @@ export function show(event, hide_callback) {
174
181
  client_rect.y = 0;
175
182
  client_rect.width = window.innerWidth;
176
183
  client_rect.height = window.innerHeight;
177
- let rect;
178
- if (is_compact)
179
- rect = textbox.getBoundingClientRect();
180
- else
181
- rect = combo.getBoundingClientRect();
182
- let top_space = rect.y;
183
- let bottom_space = client_rect.height - (rect.y + rect.height);
184
- let palette_max_height_px = 500;
185
- let palette_width_px = rect.width;
186
- if (palette_width_px < 120)
187
- palette_width_px = 120;
188
- let preferred_palette_height = dropdown_height > 0 ? dropdown_height : palette_max_height_px;
189
- let preferred_palette_width = palette_width_px;
190
- let x = 0, y = 0;
191
- let show_above = false;
192
- let show_fullscreen = false;
193
- if (client_rect.width < preferred_palette_width)
194
- show_fullscreen = true;
195
- else if (rect.x + preferred_palette_width > client_rect.width)
196
- x = client_rect.width - preferred_palette_width;
197
- else
198
- x = rect.x;
199
- if (client_rect.height < preferred_palette_height)
200
- show_fullscreen = true;
201
- else if (bottom_space >= preferred_palette_height)
202
- y = rect.y + rect.height;
203
- else if (top_space >= preferred_palette_height) {
204
- y = rect.y;
205
- show_above = true;
206
- } else
207
- y = rect.y + rect.height;
208
- if (isDeviceSmallerThan("sm")) {
209
- let screenRect = new DOMRect();
210
- screenRect.x = 0;
211
- screenRect.y = 0;
212
- screenRect.width = window.innerWidth;
213
- screenRect.height = window.innerHeight;
214
- const margin = 5;
215
- const maxHeight = screenRect.height / 2 - margin;
216
- const width = screenRect.width - 2 * margin;
217
- x = margin;
218
- y = screenRect.bottom - margin;
219
- dropdown_position = `position: fixed; left: ${x}px; top: ${y}px; transform: translate(0, -100%); width: ${width}px; max-height: ${maxHeight}px; display: block`;
220
- } else if (show_fullscreen) {
221
- dropdown_position = `position: fixed; left: 0px; top: 0px; width: ${client_rect.width}px; height: ${client_rect.height}px;`;
222
- } else {
223
- dropdown_position = `min-width: ${palette_width_px}px; max-height:${palette_max_height_px}px; position: fixed; left:${x}px; top:${y}px;`;
224
- if (show_above)
225
- dropdown_position += " transform: translate(0, -100%);";
226
- if (!is_compact)
227
- dropdown_position += `width: ${preferred_palette_width}px`;
228
- }
184
+ openDropdownAsMenu();
229
185
  is_dropdown_open = true;
230
186
  if (filtered) {
231
187
  if (!textbox)
@@ -243,7 +199,7 @@ export function show(event, hide_callback) {
243
199
  subtree: true
244
200
  });
245
201
  }
246
- if (isDeviceSmallerThan("sm")) {
202
+ if (false) {
247
203
  pushToolsActionsOperations({
248
204
  opver: 1,
249
205
  operations: [
@@ -264,13 +220,37 @@ export function show(event, hide_callback) {
264
220
  });
265
221
  }
266
222
  }
223
+ function openDropdownAsMenu() {
224
+ let rect;
225
+ if (is_compact)
226
+ rect = textbox.getBoundingClientRect();
227
+ else
228
+ rect = combo.getBoundingClientRect();
229
+ let operations = [];
230
+ if (hasNone)
231
+ operations.push({
232
+ caption: "<none>",
233
+ action: (f) => on_choose(null)
234
+ });
235
+ if (definition && definition.collection)
236
+ source_fetched(definition.collection);
237
+ const _filtered_source = filtered_source ? filtered_source : definition.source;
238
+ _filtered_source.forEach((i) => {
239
+ operations.push({
240
+ caption: i.Name ?? i.Key,
241
+ icon: i.Icon ?? void 0,
242
+ action: (f) => on_choose(i)
243
+ });
244
+ });
245
+ console.log("operations", operations);
246
+ showMenu(rect, operations);
247
+ }
267
248
  export function hide() {
268
249
  if (!is_dropdown_open)
269
250
  return;
270
251
  if (mutation_observer)
271
252
  mutation_observer.disconnect();
272
253
  is_dropdown_open = false;
273
- popToolsActionsOperations();
274
254
  dropdown_position = "display: none;";
275
255
  combo_text = get_combo_text();
276
256
  if (!!textbox)
@@ -464,7 +444,7 @@ function on_input_change() {
464
444
  if (!is_dropdown_open)
465
445
  return;
466
446
  filtered_source = get_filtered_source();
467
- highlighted_option = filtered_source.length > 0 ? filtered_source[0] : null;
447
+ openDropdownAsMenu();
468
448
  }
469
449
  let new_item_option;
470
450
  function get_filtered_source() {
@@ -664,71 +644,91 @@ function on_focus_out(e) {
664
644
 
665
645
  </div>
666
646
 
667
- <div hidden={!is_dropdown_open}
668
- class="not-prose {cs} bg-white dark:bg-stone-800 text-stone-500 dark:text-stone-400 rounded-lg border border-stone-200 dark:border-stone-700 shadow-md overflow-y-auto cursor-pointer z-30"
669
- style={dropdown_position}
670
- use:dropdown_action>
671
- <ul class="py-1">
647
+ <!-- svelte-ignore a11y-click-events-have-key-events -->
648
+ <!--div hidden={!is_dropdown_open}>
649
+ {#if closeButtonPos}
650
+ {#key closeButtonPos}
651
+ <button class=" fixed w-6 h-6 flex items-center justify-center
652
+ text-stone-500 bg-stone-200/70 hover:bg-stone-200
653
+ focus:outline-none font-medium rounded-full text-sm text-center
654
+ dark:text-stone-500 dark:bg-stone-700/80 dark:hover:bg-stone-700
655
+ focus:ring-4 focus:ring-blue-300 dark:focus:ring-blue-800"
656
+ style={closeButtonPos}
657
+ on:click={ hide }>
658
+ <Icon component={FaTimes} s="md"/>
659
+ </button>
660
+ {/key}
661
+ {/if}
672
662
 
673
- {#if definition.source && definition.source.length}
674
- {#if hasNone}
675
- <!-- svelte-ignore a11y-click-events-have-key-events -->
676
- <li class="rounded flex flex-row items-center {font_size}
677
- space-x-10 px-4 py-2 ml-12 sm:ml-0"
678
- class:bg-stone-100={highlighted_option == null}
679
- class:dark:bg-stone-700={highlighted_option == null}
680
- class:dark:hover:bg-stone-700={highlighted_option == null}
681
- on:mousemove={() => on_mouse_move(null)}
682
- on:click|preventDefault|stopPropagation={async () => await on_choose(null)}
683
- tabindex="-1">
663
+ <div class="not-prose {cs} bg-white dark:bg-stone-800 text-stone-500 dark:text-stone-400 rounded-lg border border-stone-200 dark:border-stone-700 shadow-md overflow-y-auto cursor-pointer z-40
664
+ fixed"
665
+ style={dropdown_position}
666
+ bind:this={dropdownElement}
667
+ use:dropdown_action>
668
+
669
+
684
670
 
685
- <h4 class="ml-2">
686
- &lt;none&gt;
687
- </h4>
688
- </li>
689
- {/if}
671
+ <ul class="py-1">
690
672
 
691
- {@const _filtered_source = filtered_source ? filtered_source : definition.source}
692
- {#if _filtered_source.length > 0}
693
- {#each _filtered_source as item (item.Key)}
694
- {@const active=(highlighted_option == item) ? 'bg-stone-400/30 dark:bg-stone-400/30' : ''}
695
- <!-- svelte-ignore a11y-click-events-have-key-events -->
673
+ {#if definition.source && definition.source.length}
674
+ {#if hasNone}
675
+
696
676
  <li class="rounded flex flex-row items-center {font_size}
697
- space-x-10 px-4 py-2 pl-12 sm:pl-2 {active}"
698
- on:mousemove={() => on_mouse_move(item)}
699
- on:click|preventDefault|stopPropagation={async () => await on_choose(item)}
677
+ space-x-10 px-4 py-2 ml-12 sm:ml-0"
678
+ class:bg-stone-100={highlighted_option == null}
679
+ class:dark:bg-stone-700={highlighted_option == null}
680
+ class:dark:hover:bg-stone-700={highlighted_option == null}
681
+ on:mousemove={() => on_mouse_move(null)}
682
+ on:click|preventDefault|stopPropagation={async () => await on_choose(null)}
700
683
  tabindex="-1">
701
684
 
702
- {#if icon}
703
- {#if item.Color}
704
- <Icon s="md" circle={true} color={item.Color}/>
705
- {:else if item.Avatar}
706
- <Icon s="md" circle={true} symbol={item.Avatar}/>
707
- {:else if item.Icon}
708
- <Icon s="md" component={item.Icon}/>
709
- {:else if item.Icon == null}
710
- <div class="w-4 h-4"></div>
711
- {:else if item.Name}
712
- <Icon s="md" circle={true} label={item.Name}/>
713
- {:else}
714
- <Icon s="md" circle={true}/>
715
- {/if}
716
- {/if}
717
- <h4 class="ml-2">
718
- {#if item.Name}
719
- {item.Name}
720
- {:else if item.Key}
721
- {item.Key}
722
- {/if}
685
+ <h4 class="ml-2 text-stone-400 dark:text-stone-500">
686
+ &lt;none&gt;
723
687
  </h4>
724
688
  </li>
725
- {/each}
726
- {:else}
727
- <li class="rounded p-2">No options</li>
689
+ {/if}
690
+
691
+ {@const _filtered_source = filtered_source ? filtered_source : definition.source}
692
+ {#if _filtered_source.length > 0}
693
+ {#each _filtered_source as item (item.Key)}
694
+ {@const active=(highlighted_option == item) ? 'bg-stone-400/30 dark:bg-stone-400/30' : ''}
695
+ <li class="rounded flex flex-row items-center {font_size}
696
+ space-x-10 px-4 py-2 pl-12 sm:pl-2 {active}"
697
+ on:mousemove={() => on_mouse_move(item)}
698
+ on:click|preventDefault|stopPropagation={async () => await on_choose(item)}
699
+ tabindex="-1">
700
+
701
+ {#if icon}
702
+ {#if item.Color}
703
+ <Icon s="md" circle={true} color={item.Color}/>
704
+ {:else if item.Avatar}
705
+ <Icon s="md" circle={true} symbol={item.Avatar}/>
706
+ {:else if item.Icon}
707
+ <Icon s="md" component={item.Icon}/>
708
+ {:else if item.Icon == null}
709
+ <div class="w-4 h-4"></div>
710
+ {:else if item.Name}
711
+ <Icon s="md" circle={true} label={item.Name}/>
712
+ {:else}
713
+ <Icon s="md" circle={true}/>
714
+ {/if}
715
+ {/if}
716
+ <h4 class="ml-2">
717
+ {#if item.Name}
718
+ {item.Name}
719
+ {:else if item.Key}
720
+ {item.Key}
721
+ {/if}
722
+ </h4>
723
+ </li>
724
+ {/each}
725
+ {:else}
726
+ <li class="rounded p-2">No options</li>
727
+ {/if}
728
728
  {/if}
729
- {/if}
730
- </ul>
731
- </div>
729
+ </ul>
730
+ </div>
731
+ </div-->
732
732
  </div>
733
733
  {/if}
734
734
 
@@ -18,6 +18,7 @@ let menu_items = [];
18
18
  let submenus = [];
19
19
  let around_rect;
20
20
  let css_position = "";
21
+ let closeButtonPos = "";
21
22
  $:
22
23
  display = visible ? "block" : "none";
23
24
  function calculatePosition(x2, y2, around, visible2, fresh) {
@@ -53,6 +54,7 @@ function calculatePosition(x2, y2, around, visible2, fresh) {
53
54
  y2 = screenRect.bottom - maxHeight - margin;
54
55
  result = `left: ${x2}px; top: ${y2}px; width: ${width}px; max-height: ${maxHeight}px; display: block`;
55
56
  }
57
+ closeButtonPos = `right: ${margin}px; top: calc(${y2}px - 1.75rem)`;
56
58
  } else {
57
59
  let myRect = null;
58
60
  if (!fresh) {
@@ -86,6 +88,7 @@ function calculatePosition(x2, y2, around, visible2, fresh) {
86
88
  y2 = screenRect.top;
87
89
  }
88
90
  result = `left:${x2}px; top:${y2}px; display: block; min-width: 15rem`;
91
+ closeButtonPos = "";
89
92
  }
90
93
  return result;
91
94
  }
@@ -108,7 +111,7 @@ export async function show(around, _operations) {
108
111
  hide_window_indicator = 0;
109
112
  window.addEventListener("click", on_before_window_click, true);
110
113
  }
111
- if (isDeviceSmallerThan("sm")) {
114
+ if (false) {
112
115
  pushToolsActionsOperations({
113
116
  opver: 1,
114
117
  operations: [
@@ -139,7 +142,7 @@ export function isVisible() {
139
142
  return visible;
140
143
  }
141
144
  export function hide() {
142
- if (visible)
145
+ if (false)
143
146
  popToolsActionsOperations();
144
147
  visible = false;
145
148
  css_position = calculatePosition(x, y, around_rect, false, false);
@@ -324,14 +327,27 @@ function calculateBackground(is_highlighted, active) {
324
327
  }
325
328
  </script>
326
329
 
330
+
327
331
  <div id="__hd_svelte_contextmenu"
328
332
  class=" bg-white dark:bg-stone-800
329
333
  text-stone-800 dark:text-stone-400 rounded-lg border
330
334
  border-stone-200 dark:border-stone-700 shadow-md
331
- z-30 fixed min-w-60 max-h-screen overflow-y-auto"
335
+ z-40 fixed min-w-60 max-h-screen overflow-y-auto"
332
336
  style={css_position}
333
337
  bind:this={menu_root}>
334
338
 
339
+ {#if closeButtonPos}
340
+ <button class=" fixed w-6 h-6 flex items-center justify-center
341
+ text-stone-500 bg-stone-200/70 hover:bg-stone-200
342
+ focus:outline-none font-medium rounded-full text-sm text-center
343
+ dark:text-stone-500 dark:bg-stone-700/80 dark:hover:bg-stone-700
344
+ focus:ring-4 focus:ring-blue-300 dark:focus:ring-blue-800"
345
+ style={closeButtonPos}
346
+ on:click={ hide }>
347
+ <Icon component={FaTimes} s="md"/>
348
+ </button>
349
+ {/if}
350
+
335
351
  {#each operations as operation, index}
336
352
  {@const is_separator = operation.separator}
337
353
  {#if is_separator}
@@ -62,7 +62,8 @@ export let a = "";
62
62
  export let context = "";
63
63
  export let typename = "";
64
64
  export let compact = false;
65
- export let onChange = void 0;
65
+ export let onSingleChange = void 0;
66
+ export let onApplyChanges = void 0;
66
67
  export let onFocusCb = void 0;
67
68
  export let onBlurCb = void 0;
68
69
  export let onAddImage = void 0;
@@ -612,6 +613,10 @@ onMount(() => {
612
613
  if (wasContentChanged) {
613
614
  hasChangedValue = true;
614
615
  changedValue = editor2.getHTML();
616
+ if (onSingleChange)
617
+ onSingleChange(changedValue);
618
+ else
619
+ logChanges();
615
620
  handleImagesChanges(transaction);
616
621
  }
617
622
  refreshToolbarOperations();
@@ -671,32 +676,34 @@ function on_blur() {
671
676
  $data_tick_store = last_tick;
672
677
  }
673
678
  }
674
- export function save() {
679
+ export async function save() {
675
680
  if (saveData()) {
676
681
  last_tick = $data_tick_store + 1;
677
682
  $data_tick_store = last_tick;
678
- refreshToolbarOperations();
679
683
  }
680
684
  }
681
685
  function saveData() {
682
686
  if (!hasChangedValue)
683
687
  return false;
684
688
  hasChangedValue = false;
685
- if (onChange) {
686
- onChange(changedValue);
689
+ if (onApplyChanges) {
690
+ onApplyChanges(changedValue);
687
691
  return true;
688
692
  } else if (item && a) {
689
- item[a] = changedValue;
690
- if (typename)
691
- informModification(item, a, typename);
692
- else
693
- informModification(item, a);
693
+ logChanges();
694
694
  if (pushChangesImmediately)
695
- pushChanges();
695
+ pushChanges(refreshToolbarOperations);
696
696
  return true;
697
697
  }
698
698
  return false;
699
699
  }
700
+ function logChanges() {
701
+ item[a] = changedValue;
702
+ if (typename)
703
+ informModification(item, a, typename);
704
+ else
705
+ informModification(item, a);
706
+ }
700
707
  let palette = null;
701
708
  let is_command_palette_visible = false;
702
709
  function get_selection_bbox() {
@@ -717,7 +724,7 @@ function on_palette_mouse_click() {
717
724
  }
718
725
  function on_palette_shown() {
719
726
  is_command_palette_visible = true;
720
- if (isDeviceSmallerThan("sm")) {
727
+ if (false) {
721
728
  pushToolsActionsOperations({
722
729
  opver: 1,
723
730
  operations: [
@@ -740,8 +747,9 @@ function on_palette_shown() {
740
747
  }
741
748
  }
742
749
  function on_palette_hidden() {
743
- if (is_command_palette_visible)
750
+ if (false)
744
751
  popToolsActionsOperations();
752
+ editor?.commands.focus();
745
753
  is_command_palette_visible = false;
746
754
  }
747
755
  function show_command_palette(cursor_rect) {
@@ -9,7 +9,8 @@ declare const __propDef: {
9
9
  context?: string | undefined;
10
10
  typename?: string | undefined;
11
11
  compact?: boolean | undefined;
12
- onChange?: undefined;
12
+ onSingleChange?: Function | undefined;
13
+ onApplyChanges?: Function | undefined;
13
14
  onFocusCb?: undefined;
14
15
  onBlurCb?: undefined;
15
16
  onAddImage?: undefined;
@@ -42,7 +43,7 @@ declare const __propDef: {
42
43
  tbr: string;
43
44
  }) | undefined;
44
45
  scrollIntoView?: ((param: any) => void) | undefined;
45
- save?: (() => void) | undefined;
46
+ save?: (() => Promise<void>) | undefined;
46
47
  addTemporaryImage?: ((src: any) => void) | undefined;
47
48
  replaceTemporaryImage?: ((temporarySrc: any, dataPath: any) => void) | undefined;
48
49
  removeTemporaryImage?: ((temporarySrc: any) => void) | undefined;
@@ -115,7 +116,7 @@ export default class Editor extends SvelteComponentTyped<EditorProps, EditorEven
115
116
  tbr: string;
116
117
  };
117
118
  get scrollIntoView(): (param: any) => void;
118
- get save(): () => void;
119
+ get save(): () => Promise<void>;
119
120
  get addTemporaryImage(): (src: any) => void;
120
121
  get replaceTemporaryImage(): (temporarySrc: any, dataPath: any) => void;
121
122
  get removeTemporaryImage(): (temporarySrc: any) => void;
@@ -4,6 +4,7 @@ import Pallete_row from "./palette.row.svelte";
4
4
  import { createEventDispatcher } from "svelte";
5
5
  import Icon from "../../icon.svelte";
6
6
  import { isDeviceSmallerThan, UI } from "../../../utils.js";
7
+ import { FaTimes } from "svelte-icons/fa";
7
8
  export let commands;
8
9
  export let width_px = 400;
9
10
  export let max_height_px = 500;
@@ -27,7 +28,7 @@ export function showAsToolbox(rect) {
27
28
  toolboxX = margin;
28
29
  toolboxY = rect.bottom + margin;
29
30
  toolboxY += window.scrollY;
30
- css_style = `position: fixed; left:${toolboxX}px; top:${toolboxY}px;`;
31
+ css_style = `left:${toolboxX}px; top:${toolboxY}px;`;
31
32
  console.log("toolbox: ", css_style);
32
33
  dispatch("palette_shown");
33
34
  }
@@ -48,19 +49,26 @@ afterUpdate(
48
49
  }
49
50
  }
50
51
  );
52
+ let closeButtonPos = "";
51
53
  export function show(x, y, up = false) {
52
54
  isToolbox = false;
53
- css_style = `width: ${width_px}px; max-height:${max_height_px}px; position: fixed; left:${x}px; top:${y}px;`;
55
+ css_style = `width: ${width_px}px; max-height:${max_height_px}px; left:${x}px; top:${y}px;`;
54
56
  if (up)
55
57
  css_style += " transform: translate(0, -100%);";
56
58
  visible = true;
57
59
  dispatch("palette_shown");
60
+ closeButtonPos = "";
61
+ setTimeout(() => {
62
+ const rect = paletteElement.getBoundingClientRect();
63
+ closeButtonPos = `right: ${15}px; top: calc(${rect.y}px - 1.75rem)`;
64
+ }, 0);
65
+ console.trace();
58
66
  }
59
67
  export function show_fullscreen(_width_px, _height_px) {
60
68
  isToolbox = false;
61
69
  width_px = _width_px;
62
70
  max_height_px = _height_px;
63
- css_style = `position: fixed; left: 0px; top: 0px; width: ${_width_px}px; height: ${_height_px}px; z-index: 1055;`;
71
+ css_style = `left: 0px; top: 0px; width: ${_width_px}px; height: ${_height_px}px; z-index: 1055;`;
64
72
  visible = true;
65
73
  dispatch("palette_shown");
66
74
  }
@@ -231,7 +239,7 @@ function mousemove(e) {
231
239
  const touch = e.touches.item(0);
232
240
  const trackDelta = new DOMPoint(touch.clientX - beforeTrackingClient.x, touch.clientY - beforeTrackingClient.y);
233
241
  toolboxX = beforeTrackingPos.x + trackDelta.x;
234
- css_style = `position: fixed; left:${toolboxX}px; top:${toolboxY}px;`;
242
+ css_style = `left:${toolboxX}px; top:${toolboxY}px;`;
235
243
  e.stopPropagation();
236
244
  }
237
245
  }
@@ -250,8 +258,8 @@ function isRowActive(cmd) {
250
258
 
251
259
  {#if isToolbox}
252
260
  <menu class=" bg-white dark:bg-stone-800 text-stone-500 dark:text-stone-400 rounded-lg border border-stone-200 dark:border-stone-700 shadow-md
253
- z-30
254
- flex flex-row flex-nowrap"
261
+ z-40
262
+ flex flex-row flex-nowrap fixed"
255
263
  style={css_style}
256
264
  hidden={!visible}
257
265
  on:touchstart={mousedown}
@@ -287,37 +295,56 @@ function isRowActive(cmd) {
287
295
  {/if}
288
296
  </menu>
289
297
  {:else}
290
- <div class="bg-white dark:bg-stone-800 text-stone-500 dark:text-stone-400 rounded-lg border border-stone-200 dark:border-stone-700 shadow-md overflow-y-auto z-20"
291
- id="__hd_FormattingPalette"
292
- bind:this={paletteElement}
293
- hidden={!visible}
294
- style={css_style} >
295
-
296
- {#if filtered_commands && filtered_commands.length}
297
- {#each filtered_commands as cmd, idx (cmd.caption)}
298
- {#if cmd.separator}
299
- {#if idx>0 && idx<filtered_commands.length-1} <!-- not first or last place -->
300
- <hr class="mx-4 my-1 border-stone-300 dark:border-stone-700"/>
301
- {/if}
302
- {:else}
303
- {@const id = "cpi_" + idx}
304
- {@const active=isRowActive(cmd)}
305
- <Pallete_row {id}
306
- cmd={cmd}
307
- is_highlighted={cmd == current_command}
308
- on:click={ () => { execute_mouse_click(cmd.on_choice); }}
309
- on:mousemove={ () => { on_mouse_over(cmd); }}
310
- on:mousedown={buttonMousedown}
311
- bind:this={rows[idx]}
312
- {active}
313
- />
314
- {/if}
315
- {/each}
316
- {:else}
317
- <p class="text-sm text-stone-500">No results</p>
298
+ <!--div hidden={!visible}-->
299
+
300
+ {#if visible && closeButtonPos}
301
+ {#key closeButtonPos}
302
+ <button class=" fixed w-6 h-6 flex items-center justify-center
303
+ text-stone-500 bg-stone-200/70 hover:bg-stone-200
304
+ focus:outline-none font-medium rounded-full text-sm text-center
305
+ dark:text-stone-500 dark:bg-stone-700/80 dark:hover:bg-stone-700
306
+ focus:ring-4 focus:ring-blue-300 dark:focus:ring-blue-800"
307
+ style={closeButtonPos}
308
+ on:mousedown={buttonMousedown}
309
+ on:click={ () => hide() }>
310
+ <Icon component={FaTimes} s="md"/>
311
+ </button>
312
+ {/key}
318
313
  {/if}
314
+
315
+ <div hidden={!visible}
316
+ class="bg-white dark:bg-stone-800 text-stone-500 dark:text-stone-400 rounded-lg border border-stone-200 dark:border-stone-700 shadow-md overflow-y-auto z-40 fixed"
317
+ id="__hd_FormattingPalette"
318
+ bind:this={paletteElement}
319
+ style={css_style} >
319
320
 
320
- </div>
321
+ {#if filtered_commands && filtered_commands.length}
322
+ {#each filtered_commands as cmd, idx (cmd.caption)}
323
+ {#if cmd.separator}
324
+ {#if idx>0 && idx<filtered_commands.length-1} <!-- not first or last place -->
325
+ <hr class="mx-4 my-1 border-stone-300 dark:border-stone-700"/>
326
+ {/if}
327
+ {:else}
328
+ {@const id = "cpi_" + idx}
329
+ {@const active=isRowActive(cmd)}
330
+ <Pallete_row {id}
331
+ cmd={cmd}
332
+ is_highlighted={cmd == current_command}
333
+ on:click={ () => { execute_mouse_click(cmd.on_choice); }}
334
+ on:mousemove={ () => { on_mouse_over(cmd); }}
335
+ on:mousedown={buttonMousedown}
336
+ bind:this={rows[idx]}
337
+ {active}
338
+ />
339
+ {/if}
340
+ {/each}
341
+ {:else}
342
+ <p class="text-sm text-stone-500">No results</p>
343
+ {/if}
344
+
345
+ </div>
346
+ <!---/div-->
347
+
321
348
 
322
349
  {/if}
323
350
 
package/desk.svelte CHANGED
@@ -17,7 +17,7 @@
17
17
  set_dark_mode_default,
18
18
  sidebar_left_pos,
19
19
  wholeAppReloader,
20
- alerts, removeAlert } from './stores.js'
20
+ alerts, removeAlert, showFABAlways} from './stores.js'
21
21
 
22
22
  //import { AuthorizedView} from '@humandialog/auth.svelte'
23
23
  import { handleSelect, isDeviceSmallerThan, isOnNavigationPage, isOnScreenKeyboardVisible, removeAt, UI } from './utils'
@@ -130,17 +130,31 @@
130
130
 
131
131
  if(tools_visible)
132
132
  {
133
- tools_visibility = "hidden sm:block sm:fixed"
134
- //fab_base_visibility = "fixed sm:hidden"
135
- fab_visibility_mode = FAB_VISIBLE_ON_MOBILE
136
-
137
- content_top = 'top-[50px] sm:top-[40px]'
138
133
 
139
- if(bottom_bar_visible)
140
- content_height = `min-h-[calc(100vh-290px)] sm:h-[calc(100vh-280px)]`
141
- else
142
- content_height = `min-h-[calc(100vh-50px)] sm:h-[calc(100vh-40px)]`
143
-
134
+ const alwaysShowFAB = (!is_small) && $showFABAlways
135
+
136
+ if(alwaysShowFAB)
137
+ {
138
+ fab_visibility_mode = FAB_VISIBLE_ALWAYS
139
+ tools_visibility = "hidden"
140
+ content_top = 'top-[50px] sm:top-[0px]'
141
+
142
+ if(bottom_bar_visible)
143
+ content_height = `min-h-[calc(100vh-290px)] sm:h-[calc(100vh-240px)]`
144
+ else
145
+ content_height = `min-h-[calc(100vh-50px)] sm:h-[calc(100vh-0px)]`
146
+ }
147
+ else
148
+ {
149
+ fab_visibility_mode = FAB_VISIBLE_ON_MOBILE
150
+ tools_visibility = "hidden sm:block sm:fixed"
151
+ content_top = 'top-[50px] sm:top-[40px]'
152
+
153
+ if(bottom_bar_visible)
154
+ content_height = `min-h-[calc(100vh-290px)] sm:h-[calc(100vh-280px)]`
155
+ else
156
+ content_height = `min-h-[calc(100vh-50px)] sm:h-[calc(100vh-40px)]`
157
+ }
144
158
  }
145
159
  else
146
160
  {
@@ -414,11 +428,7 @@
414
428
  <Operations bind:this={operationsComponent} />
415
429
  </div>
416
430
 
417
- {#if is_fab_visible}
418
- <!--div class="{fab_visibility} left-3 {fab_bottom} mb-1 cursor-pointer z-10"-->
419
- <Fab bind:this={fabComponent}/>
420
- <!---/div-->
421
- {/if}
431
+
422
432
 
423
433
  <!--#######################################################-->
424
434
  <!--## CONTENT ##################-->
@@ -438,7 +448,11 @@
438
448
  </Configurable>
439
449
  </div>
440
450
 
441
-
451
+ {#if is_fab_visible}
452
+ <!--div class="{fab_visibility} left-3 {fab_bottom} mb-1 cursor-pointer z-10"-->
453
+ <Fab bind:this={fabComponent} />
454
+ <!---/div-->
455
+ {/if}
442
456
 
443
457
  <!--###########################################################-->
444
458
  <!--## BOTTOM SIDEBAR ###############################-->
@@ -480,7 +494,7 @@
480
494
  <!-- #########################################################-->
481
495
  <!-- ## MODAL DIALOG #########################################-->
482
496
  <!-- #########################################################-->
483
- <div id="__hd_svelte_modal_root" class="z-30">
497
+ <div id="__hd_svelte_modal_root" class="z-30 sm:z-40">
484
498
  <!-- after <Modal/> component is shown it's rettached to above div
485
499
  see: modal.svelte afterUpdate -->
486
500
  </div>
@@ -3,7 +3,7 @@
3
3
  //import GoPrimitiveDot from 'svelte-icons/go/GoPrimitiveDot.svelte'
4
4
  import {showMenu} from './components/menu'
5
5
  import {push, pop, location} from 'svelte-spa-router'
6
- import {contextItemsStore, context_info_store, contextToolbarOperations, data_tick_store} from './stores.js'
6
+ import {contextItemsStore, context_info_store, contextToolbarOperations, data_tick_store, leftHandedFAB} from './stores.js'
7
7
  //import Menu from './components/contextmenu.svelte'
8
8
 
9
9
  import {
@@ -238,6 +238,12 @@
238
238
  });
239
239
  }
240
240
 
241
+ options.push({
242
+ caption: 'Left-handed floating actions',
243
+ icon: $leftHandedFAB ? FaToggleOn : FaToggleOff,
244
+ action: (f) => { $leftHandedFAB = !$leftHandedFAB; }
245
+ })
246
+
241
247
  if(has_selection_details)
242
248
  {
243
249
  options.push( {
package/index.d.ts CHANGED
@@ -59,11 +59,11 @@ export { default as KanbanCallbacks } from './components/kanban/kanban.callbacks
59
59
  export { KanbanColumnTop, KanbanColumnBottom } from './components/kanban/Kanban';
60
60
  export { selectItem, activateItem, clearActiveItem, isActive, isSelected, getActive, editable, startEditing, saveCurrentEditable, selectable, handleSelect, isDeviceSmallerThan, resizeImage, refreshToolbarOperations, isOnScreenKeyboardVisible, randomString, UI, } from './utils';
61
61
  export { getNiceStringDateTime, getFormattedStringDate, getNiceStringDate, dayName, monthName } from './components/date_utils';
62
- export { mainContentPageReloader, reloadMainContentPage, reloadWholeApp, alerts, addAlert, onErrorShowAlert, main_sidebar_visible_store, tagsReloader, reloadVisibleTags, dark_mode_store } from './stores.js';
62
+ export { mainContentPageReloader, reloadMainContentPage, reloadWholeApp, alerts, addAlert, onErrorShowAlert, main_sidebar_visible_store, tagsReloader, reloadVisibleTags, dark_mode_store, showFABAlways } from './stores.js';
63
63
  export { data_tick_store, // tmp
64
64
  hasSelectedItem, hasDataItem, setNavigatorTitle } from "./stores";
65
65
  export { contextToolbarOperations, pageToolbarOperations, contextItemsStore, contextTypesStore } from './stores';
66
- export { informModification, informModificationEx, informItem, pushChanges } from './updates';
66
+ export { informModification, informModificationEx, informItem, pushChanges, hasModifications } from './updates';
67
67
  export { default as IcH1 } from './components/document/internal/h1.icon.svelte';
68
68
  export { default as IcH2 } from './components/document/internal/h2.icon.svelte';
69
69
  export { default as IcH3 } from './components/document/internal/h3.icon.svelte';
package/index.js CHANGED
@@ -65,11 +65,11 @@ export { default as KanbanCallbacks } from './components/kanban/kanban.callbacks
65
65
  export { KanbanColumnTop, KanbanColumnBottom } from './components/kanban/Kanban';
66
66
  export { selectItem, activateItem, clearActiveItem, isActive, isSelected, getActive, editable, startEditing, saveCurrentEditable, selectable, handleSelect, isDeviceSmallerThan, resizeImage, refreshToolbarOperations, isOnScreenKeyboardVisible, randomString, UI, } from './utils';
67
67
  export { getNiceStringDateTime, getFormattedStringDate, getNiceStringDate, dayName, monthName } from './components/date_utils';
68
- export { mainContentPageReloader, reloadMainContentPage, reloadWholeApp, alerts, addAlert, onErrorShowAlert, main_sidebar_visible_store, tagsReloader, reloadVisibleTags, dark_mode_store } from './stores.js';
68
+ export { mainContentPageReloader, reloadMainContentPage, reloadWholeApp, alerts, addAlert, onErrorShowAlert, main_sidebar_visible_store, tagsReloader, reloadVisibleTags, dark_mode_store, showFABAlways } from './stores.js';
69
69
  export { data_tick_store, // tmp
70
70
  hasSelectedItem, hasDataItem, setNavigatorTitle } from "./stores";
71
71
  export { contextToolbarOperations, pageToolbarOperations, contextItemsStore, contextTypesStore } from './stores'; // tmp
72
- export { informModification, informModificationEx, informItem, pushChanges } from './updates'; // tmp
72
+ export { informModification, informModificationEx, informItem, pushChanges, hasModifications } from './updates'; // tmp
73
73
  export { default as IcH1 } from './components/document/internal/h1.icon.svelte';
74
74
  export { default as IcH2 } from './components/document/internal/h2.icon.svelte';
75
75
  export { default as IcH3 } from './components/document/internal/h3.icon.svelte';
package/modal.svelte CHANGED
@@ -19,7 +19,7 @@ export let onCancelCallback = void 0;
19
19
  export function show(on_close_callback = void 0) {
20
20
  open = true;
21
21
  close_callback = on_close_callback;
22
- if (isDeviceSmallerThan("sm")) {
22
+ if (false) {
23
23
  pushToolsActionsOperations({
24
24
  opver: 1,
25
25
  operations: [
@@ -44,7 +44,6 @@ export function hide() {
44
44
  if (!open)
45
45
  return;
46
46
  open = false;
47
- popToolsActionsOperations();
48
47
  }
49
48
  let root;
50
49
  afterUpdate(
@@ -75,7 +74,7 @@ function on_cancel(event) {
75
74
  </script>
76
75
 
77
76
  {#if open}
78
- <div class="relative z-20" aria-labelledby="modal-title" role="dialog" aria-modal="true" bind:this={root}>
77
+ <div class="relative z-30" aria-labelledby="modal-title" role="dialog" aria-modal="true" bind:this={root}>
79
78
  <!--
80
79
  Background backdrop, show/hide based on modal state.
81
80
 
@@ -88,7 +87,7 @@ function on_cancel(event) {
88
87
  -->
89
88
  <div class="fixed w-screen h-screen inset-0 bg-stone-500 dark:bg-stone-800 bg-opacity-75 dark:bg-opacity-75 transition-opacity"></div>
90
89
 
91
- <div class="fixed z-20 inset-0 w-screen overflow-y-auto">
90
+ <div class="fixed z-30 inset-0 w-screen overflow-y-auto">
92
91
  <div class="flex min-h-full items-end justify-center p-4 text-center sm:items-center sm:p-0">
93
92
  <!--
94
93
  Modal panel, show/hide based on modal state.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@humandialog/forms.svelte",
3
- "version": "1.4.7",
3
+ "version": "1.4.8",
4
4
  "description": "Basic Svelte UI components for Object Reef applications",
5
5
  "devDependencies": {
6
6
  "@playwright/test": "^1.28.1",
package/stores.d.ts CHANGED
@@ -49,3 +49,5 @@ export const bottom_bar_visible_store: import("svelte/store").Writable<any>;
49
49
  export const right_sidebar_visible_store: import("svelte/store").Writable<boolean>;
50
50
  export const visible_property_tab_store: import("svelte/store").Writable<string>;
51
51
  export const fabCollapsed: import("svelte/store").Writable<any>;
52
+ export const showFABAlways: import("svelte/store").Writable<any>;
53
+ export const leftHandedFAB: import("svelte/store").Writable<any>;
package/stores.js CHANGED
@@ -160,6 +160,12 @@ export const visible_property_tab_store = writable('');
160
160
  export const fabCollapsed = writable( (localStorage.fabCollapsed && localStorage.fabCollapsed == 'true') || false )
161
161
  fabCollapsed.subscribe( (value) => { localStorage.fabCollapsed = (value ? 'true' : '') } );
162
162
 
163
+ export const showFABAlways = writable( (localStorage.showFABAlways && localStorage.showFABAlways == 'true') || false )
164
+ showFABAlways.subscribe( (value) => { localStorage.showFABAlways = (value ? 'true' : '') } );
165
+
166
+ export const leftHandedFAB = writable( (localStorage.leftHandedFAB && localStorage.leftHandedFAB == 'true') || false )
167
+ leftHandedFAB.subscribe( (value) => { localStorage.leftHandedFAB = (value ? 'true' : '') } );
168
+
163
169
  export function restore_defults()
164
170
  {
165
171
 
@@ -169,6 +175,8 @@ export function restore_defults()
169
175
  right_sidebar_visible_store.set(false);
170
176
  visible_property_tab_store.set('');
171
177
  fabCollapsed.set(false)
178
+ showFABAlways.set(false)
179
+ leftHandedFAB.set(false)
172
180
  }
173
181
 
174
182
  export function toggle_sidebar(index)
package/updates.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  export function informModification(itm: any, field_name: any, type_name?: undefined): boolean;
2
2
  export function informModificationEx(typeName: any, itemId: any, attribName: any, attribValue: any): boolean;
3
+ export function hasModifications(): boolean;
3
4
  export function informItem(itm: any, type_name?: undefined): boolean;
4
- export function pushChanges(): void;
5
+ export function pushChanges(afterPushCallback?: undefined): void;
package/updates.js CHANGED
@@ -51,6 +51,12 @@ export function informModificationEx(typeName, itemId, attribName, attribValue)
51
51
  return true;
52
52
  }
53
53
 
54
+ export function hasModifications()
55
+ {
56
+ //console.log('hasModifications', modified_items_map.size)
57
+ return modified_items_map.size > 0
58
+ }
59
+
54
60
  export function informItem(itm, type_name=undefined)
55
61
  {
56
62
  if(type_name == undefined)
@@ -81,8 +87,15 @@ export function informItem(itm, type_name=undefined)
81
87
 
82
88
  const update_request_ticket = writable(0);
83
89
  let last_update_ticket = 0;
84
- export function pushChanges()
90
+ let afterPushCallbacks = []
91
+
92
+ export function pushChanges(afterPushCallback=undefined)
85
93
  {
94
+ //console.trace()
95
+
96
+ if(afterPushCallback)
97
+ afterPushCallbacks.push(afterPushCallback);
98
+
86
99
  update_request_ticket.update(n => n + 1);
87
100
  }
88
101
 
@@ -140,13 +153,18 @@ update_request_ticket.subscribe(async (v) => {
140
153
  body: JSON.stringify( { Items: changes } )
141
154
  })
142
155
  if (res.ok) {
156
+
143
157
  modified_items_map.clear();
158
+ afterPushCallbacks.forEach( cb => cb())
159
+ afterPushCallbacks = []
144
160
  }
145
161
  else
146
162
  {
147
163
  if(res.status == 400) // basic exception like access rights
148
164
  {
149
165
  modified_items_map.clear();
166
+ afterPushCallbacks.forEach( cb => cb())
167
+ afterPushCallbacks = []
150
168
  }
151
169
 
152
170
  const err = await res.text()
package/utils.js CHANGED
@@ -84,21 +84,32 @@ export function clearActiveItem(context_level)
84
84
 
85
85
  export function refreshToolbarOperations()
86
86
  {
87
+
88
+ let refreshed = false
89
+
87
90
  const contextOperations = get(contextToolbarOperations)
88
91
  if(contextOperations)
89
92
  {
93
+
90
94
  if(Array.isArray(contextOperations))
91
95
  {
92
- if(contextOperations.length)
96
+ if(contextOperations.length > 0)
97
+ {
93
98
  contextToolbarOperations.set([...contextOperations])
99
+ refreshed = true
100
+ }
94
101
  }
95
102
  else
96
103
  {
97
- if(contextOperations.operations.length)
104
+ if(contextOperations.operations && contextOperations.operations.length > 0)
105
+ {
98
106
  contextToolbarOperations.set({...contextOperations})
107
+ refreshed = true
108
+ }
99
109
  }
100
110
  }
101
- else
111
+
112
+ if(!refreshed)
102
113
  {
103
114
  const pageOperations = get(pageToolbarOperations);
104
115
  if(pageOperations)
@@ -108,6 +119,7 @@ export function refreshToolbarOperations()
108
119
  if(pageOperations.length > 0)
109
120
  {
110
121
  pageToolbarOperations.set([...pageOperations])
122
+ refreshed = true
111
123
  }
112
124
  }
113
125
  else
@@ -115,6 +127,7 @@ export function refreshToolbarOperations()
115
127
  if(pageOperations.operations && pageOperations.operations.length > 0)
116
128
  {
117
129
  pageToolbarOperations.set({...pageOperations})
130
+ refreshed = true
118
131
  }
119
132
  }
120
133
  }
@@ -159,6 +172,7 @@ export function editable(node, params)
159
172
  let onRemove = undefined;
160
173
  let onFinish = undefined;
161
174
  let onSoftEnter = undefined;
175
+ let onSingleChange = undefined
162
176
  if(params instanceof Object)
163
177
  {
164
178
  action = params.action ?? params;
@@ -166,6 +180,7 @@ export function editable(node, params)
166
180
  onRemove = params.remove ?? undefined
167
181
  onFinish = params.onFinish ?? undefined
168
182
  onSoftEnter = params.onSoftEnter ?? undefined;
183
+ onSingleChange = params.onSingleChange ?? undefined
169
184
 
170
185
  if(params.readonly)
171
186
  return;
@@ -323,7 +338,12 @@ export function editable(node, params)
323
338
  currentEditable = node;
324
339
  node.addEventListener("save", save_listener)
325
340
 
326
- observer = new MutationObserver(() => { has_changed = true; });
341
+ observer = new MutationObserver(() => {
342
+ has_changed = true;
343
+ if(onSingleChange)
344
+ onSingleChange(node.textContent)
345
+ });
346
+
327
347
  observer.observe( node, {
328
348
  childList: true,
329
349
  attributes: true,
@@ -19,13 +19,15 @@
19
19
  context_info_store,
20
20
  contextToolbarOperations,
21
21
  data_tick_store,
22
- reloadWholeApp
22
+ reloadWholeApp,
23
+ showFABAlways,
24
+ leftHandedFAB
23
25
  } from "./stores.js";
24
26
  import Icon from './components/icon.svelte';
25
27
  import {session, signInHRef, signOutHRef} from '@humandialog/auth.svelte'
26
28
  import { pop, push } from 'svelte-spa-router';
27
29
  import { tick } from 'svelte';
28
- import { popNavigationPage } from './utils';
30
+ import { isDeviceSmallerThan, popNavigationPage } from './utils';
29
31
 
30
32
 
31
33
  export let appConfig = undefined;
@@ -218,6 +220,22 @@
218
220
  });
219
221
  }
220
222
 
223
+ if(!isDeviceSmallerThan("sm"))
224
+ {
225
+ options.push({
226
+ caption: 'Floating actions',
227
+ icon: $showFABAlways ? FaToggleOn : FaToggleOff,
228
+ action: (f) => { $showFABAlways = !$showFABAlways; }
229
+ })
230
+
231
+ options.push({
232
+ caption: 'Left-handed floating actions',
233
+ icon: $leftHandedFAB ? FaToggleOn : FaToggleOff,
234
+ disabled: !$showFABAlways,
235
+ action: (f) => { $leftHandedFAB = !$leftHandedFAB; }
236
+ })
237
+ }
238
+
221
239
  if(has_selection_details)
222
240
  {
223
241
  options.push( {