@humandialog/forms.svelte 1.4.6 → 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.
- package/components/Fab.svelte +76 -26
- package/components/Fab.svelte.d.ts +1 -0
- package/components/Floating_container.svelte +20 -4
- package/components/combo/combo.source.svelte +3 -0
- package/components/combo/combo.source.svelte.d.ts +2 -0
- package/components/combo/combo.svelte +118 -118
- package/components/contextmenu.svelte +22 -6
- package/components/document/editor.svelte +33 -13
- package/components/document/editor.svelte.d.ts +12 -3
- package/components/document/internal/palette.row.svelte +1 -3
- package/components/document/internal/palette.svelte +63 -36
- package/components/icon.svelte +42 -9
- package/components/icon.svelte.d.ts +3 -3
- package/components/menu.d.ts +1 -0
- package/components/menu.js +6 -0
- package/components/tag.svelte +23 -9
- package/components/tag.svelte.d.ts +1 -0
- package/components/tags.palette.svelte +237 -0
- package/components/tags.palette.svelte.d.ts +38 -0
- package/components/tags.svelte +46 -15
- package/console.svelte +82 -3
- package/desk.svelte +43 -26
- package/horizontal.toolbar.svelte +11 -5
- package/index.d.ts +2 -2
- package/index.js +2 -2
- package/modal.svelte +4 -5
- package/package.json +3 -2
- package/stores.d.ts +3 -0
- package/stores.js +12 -0
- package/tenant.members.svelte +1 -1
- package/updates.d.ts +2 -1
- package/updates.js +19 -1
- package/utils.js +24 -4
- package/vertical.toolbar.svelte +23 -5
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
import Tag from './tag.svelte'
|
|
3
|
+
import {FaPlus} from 'svelte-icons/fa'
|
|
4
|
+
import TagColorsPalette from './tag.colors.svelte'
|
|
5
|
+
import { tick } from 'svelte';
|
|
6
|
+
import { isDeviceSmallerThan } from '../utils';
|
|
7
|
+
|
|
8
|
+
export let usedTags = []
|
|
9
|
+
export let allTags = []
|
|
10
|
+
|
|
11
|
+
export let onSelect;
|
|
12
|
+
export let onNewTag = undefined;
|
|
13
|
+
|
|
14
|
+
export let onHide = undefined
|
|
15
|
+
export let onSizeChanged = undefined
|
|
16
|
+
|
|
17
|
+
let allowNewTags = onNewTag != undefined;
|
|
18
|
+
|
|
19
|
+
let userClass = $$props.class ?? '';
|
|
20
|
+
|
|
21
|
+
const TAGS_PALETTE = 0
|
|
22
|
+
const COLORS_PALETTE = 1
|
|
23
|
+
let view = TAGS_PALETTE;
|
|
24
|
+
|
|
25
|
+
$: notUsedTags = getNotUsedTags()
|
|
26
|
+
$: filteredTags = filterTags(notUsedTags, '')
|
|
27
|
+
|
|
28
|
+
export function reload(props)
|
|
29
|
+
{
|
|
30
|
+
if(props && props.usedTags)
|
|
31
|
+
usedTags = props.usedTags
|
|
32
|
+
|
|
33
|
+
if(props && props.allTags)
|
|
34
|
+
allTags = props.allTags
|
|
35
|
+
|
|
36
|
+
if(props && props.onSelect)
|
|
37
|
+
onSelect = props.onSelect
|
|
38
|
+
|
|
39
|
+
if(props && props.onNewTag)
|
|
40
|
+
onNewTag = props.onNewTag
|
|
41
|
+
|
|
42
|
+
allowNewTags = onNewTag != undefined;
|
|
43
|
+
|
|
44
|
+
view = TAGS_PALETTE;
|
|
45
|
+
inputText = ''
|
|
46
|
+
|
|
47
|
+
notUsedTags = getNotUsedTags()
|
|
48
|
+
filteredTags = filterTags(notUsedTags, '')
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
let gap = 'gap-2';
|
|
52
|
+
let s = "md"
|
|
53
|
+
switch(s)
|
|
54
|
+
{
|
|
55
|
+
case 'md':
|
|
56
|
+
gap = 'gap-3 sm:gap-2'
|
|
57
|
+
break;
|
|
58
|
+
|
|
59
|
+
case 'sm':
|
|
60
|
+
gap = 'gap-2 sm:gap-2'
|
|
61
|
+
break;
|
|
62
|
+
|
|
63
|
+
case 'xs':
|
|
64
|
+
gap = 'gap-2 sm:gap-1'
|
|
65
|
+
break;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function getNotUsedTags()
|
|
69
|
+
{
|
|
70
|
+
let result = allTags.filter(e => {
|
|
71
|
+
const label = e.label;
|
|
72
|
+
let idx = usedTags.findIndex(f => f.label == label)
|
|
73
|
+
if(idx < 0)
|
|
74
|
+
return true;
|
|
75
|
+
else
|
|
76
|
+
return false;
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
return result;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function onTagSelected(tag)
|
|
83
|
+
{
|
|
84
|
+
if(onSelect)
|
|
85
|
+
onSelect(tag, tag.label, tag.label)
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
let inputText = '';
|
|
89
|
+
function onTextInput(e)
|
|
90
|
+
{
|
|
91
|
+
filteredTags = filterTags(notUsedTags, inputText)
|
|
92
|
+
|
|
93
|
+
// don't know if needed. we'll see
|
|
94
|
+
//await tick();
|
|
95
|
+
//if(onSizeChanged)
|
|
96
|
+
// onSizeChanged();
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
function filterTags(tags, inputText)
|
|
100
|
+
{
|
|
101
|
+
if(!inputText)
|
|
102
|
+
return [...tags];
|
|
103
|
+
else
|
|
104
|
+
{
|
|
105
|
+
const filterText = inputText.toLowerCase()
|
|
106
|
+
return tags.filter(e => e.label && e.label.toLowerCase().includes( filterText ))
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
function onKeyDown(e)
|
|
111
|
+
{
|
|
112
|
+
switch(e.key)
|
|
113
|
+
{
|
|
114
|
+
case 'Enter':
|
|
115
|
+
if(filteredTags.length > 0)
|
|
116
|
+
{
|
|
117
|
+
inputText = ''
|
|
118
|
+
onTagSelected(filteredTags[0])
|
|
119
|
+
if(onHide)
|
|
120
|
+
onHide()
|
|
121
|
+
}
|
|
122
|
+
else if(allowNewTags)
|
|
123
|
+
{
|
|
124
|
+
onAddTag(undefined)
|
|
125
|
+
}
|
|
126
|
+
break;
|
|
127
|
+
|
|
128
|
+
case 'Escape':
|
|
129
|
+
if(inputText)
|
|
130
|
+
{
|
|
131
|
+
inputText = ''
|
|
132
|
+
filteredTags = filterTags(notUsedTags, inputText)
|
|
133
|
+
}
|
|
134
|
+
else
|
|
135
|
+
{
|
|
136
|
+
if(onHide)
|
|
137
|
+
onHide()
|
|
138
|
+
}
|
|
139
|
+
break;
|
|
140
|
+
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
function onTextBlur(e)
|
|
147
|
+
{
|
|
148
|
+
if(isDeviceSmallerThan("sm")) // blur when virtual keyboard is visible means 'OK' button pressed
|
|
149
|
+
{
|
|
150
|
+
if((filteredTags.length == 0) && allowNewTags)
|
|
151
|
+
{
|
|
152
|
+
onAddTag(undefined)
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
else
|
|
156
|
+
{
|
|
157
|
+
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
async function onAddTag(e)
|
|
162
|
+
{
|
|
163
|
+
if(inputText && onNewTag)
|
|
164
|
+
{
|
|
165
|
+
view = COLORS_PALETTE
|
|
166
|
+
await tick();
|
|
167
|
+
if(onSizeChanged)
|
|
168
|
+
onSizeChanged();
|
|
169
|
+
}
|
|
170
|
+
else if(onHide)
|
|
171
|
+
onHide();
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
function onNewTagColorSelected(color)
|
|
175
|
+
{
|
|
176
|
+
if(inputText && onNewTag)
|
|
177
|
+
onNewTag(inputText, inputText, color)
|
|
178
|
+
|
|
179
|
+
inputText = ''
|
|
180
|
+
|
|
181
|
+
if(onHide)
|
|
182
|
+
onHide();
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
</script>
|
|
186
|
+
|
|
187
|
+
{#if view==TAGS_PALETTE}
|
|
188
|
+
<menu class="{userClass} flex flex-column {gap} flex-wrap mr-1 sm:mr-0 sm:w-72">
|
|
189
|
+
<p class="flex flex-row {gap} flex-wrap ">
|
|
190
|
+
{#key filteredTags}
|
|
191
|
+
{#if filteredTags.length > 0}
|
|
192
|
+
{#each filteredTags as tag (tag.label)}
|
|
193
|
+
<Tag name={tag.label} color={tag.color} {s}
|
|
194
|
+
onCustomClick={(e) => onTagSelected(tag)}/>
|
|
195
|
+
{/each}
|
|
196
|
+
{:else if allowNewTags}
|
|
197
|
+
<p>Create tag:</p>
|
|
198
|
+
{:else}
|
|
199
|
+
<p>No tags</p>
|
|
200
|
+
{/if}
|
|
201
|
+
|
|
202
|
+
{/key}
|
|
203
|
+
</p>
|
|
204
|
+
|
|
205
|
+
<section class="flex flex-row {gap} w-full">
|
|
206
|
+
|
|
207
|
+
<input type="text" name="text" id="text"
|
|
208
|
+
autocomplete="off"
|
|
209
|
+
class="block bg-stone-100 dark:bg-stone-800 flex-1"
|
|
210
|
+
bind:value={inputText}
|
|
211
|
+
on:input={onTextInput}
|
|
212
|
+
on:blur={onTextBlur}
|
|
213
|
+
on:keydown={onKeyDown}
|
|
214
|
+
placeholder="Type to filter or create tag">
|
|
215
|
+
{#if allowNewTags}
|
|
216
|
+
<button class="block w-5 h-5 mt-0.5 ml-auto mr-2
|
|
217
|
+
text-stone-600 hover:text-stone-800 hover:bg-stone-200 active:bg-stone-200 border-stone-200
|
|
218
|
+
dark:text-stone-300 dark:hover:text-white dark:hover:bg-stone-800 dark:active:bg-stone-600 dark:border-stone-600"
|
|
219
|
+
class:hidden={inputText.length == 0}
|
|
220
|
+
on:click={onAddTag}>
|
|
221
|
+
<FaPlus/>
|
|
222
|
+
</button>
|
|
223
|
+
{/if}
|
|
224
|
+
</section>
|
|
225
|
+
</menu>
|
|
226
|
+
|
|
227
|
+
{:else if view == COLORS_PALETTE}
|
|
228
|
+
<TagColorsPalette onSelect={onNewTagColorSelected}/>
|
|
229
|
+
{/if}
|
|
230
|
+
|
|
231
|
+
<style>
|
|
232
|
+
|
|
233
|
+
input:focus {
|
|
234
|
+
outline: 0px solid transparent;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
</style>
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/** @typedef {typeof __propDef.props} TagsProps */
|
|
2
|
+
/** @typedef {typeof __propDef.events} TagsEvents */
|
|
3
|
+
/** @typedef {typeof __propDef.slots} TagsSlots */
|
|
4
|
+
export default class Tags extends SvelteComponentTyped<{
|
|
5
|
+
[x: string]: any;
|
|
6
|
+
onSelect: any;
|
|
7
|
+
onHide?: any;
|
|
8
|
+
onSizeChanged?: any;
|
|
9
|
+
reload?: ((props: any) => void) | undefined;
|
|
10
|
+
usedTags?: any[] | undefined;
|
|
11
|
+
allTags?: any[] | undefined;
|
|
12
|
+
onNewTag?: any;
|
|
13
|
+
}, {
|
|
14
|
+
[evt: string]: CustomEvent<any>;
|
|
15
|
+
}, {}> {
|
|
16
|
+
get reload(): (props: any) => void;
|
|
17
|
+
}
|
|
18
|
+
export type TagsProps = typeof __propDef.props;
|
|
19
|
+
export type TagsEvents = typeof __propDef.events;
|
|
20
|
+
export type TagsSlots = typeof __propDef.slots;
|
|
21
|
+
import { SvelteComponentTyped } from "svelte";
|
|
22
|
+
declare const __propDef: {
|
|
23
|
+
props: {
|
|
24
|
+
[x: string]: any;
|
|
25
|
+
onSelect: any;
|
|
26
|
+
onHide?: any;
|
|
27
|
+
onSizeChanged?: any;
|
|
28
|
+
reload?: ((props: any) => void) | undefined;
|
|
29
|
+
usedTags?: any[] | undefined;
|
|
30
|
+
allTags?: any[] | undefined;
|
|
31
|
+
onNewTag?: any;
|
|
32
|
+
};
|
|
33
|
+
events: {
|
|
34
|
+
[evt: string]: CustomEvent<any>;
|
|
35
|
+
};
|
|
36
|
+
slots: {};
|
|
37
|
+
};
|
|
38
|
+
export {};
|
package/components/tags.svelte
CHANGED
|
@@ -3,8 +3,10 @@ import Tag from "./tag.svelte";
|
|
|
3
3
|
import FaPlus from "svelte-icons/fa/FaPlus.svelte";
|
|
4
4
|
import Combo from "./combo/combo.svelte";
|
|
5
5
|
import ComboItem from "./combo/combo.item.svelte";
|
|
6
|
+
import TagsPalette from "./tags.palette.svelte";
|
|
6
7
|
import { contextItemsStore, data_tick_store, contextTypesStore, tagsReloader } from "../stores.js";
|
|
7
8
|
import { informModification, pushChanges } from "../updates.js";
|
|
9
|
+
import { showFloatingToolbar } from "./menu";
|
|
8
10
|
export let tags = "";
|
|
9
11
|
export let getGlobalTags;
|
|
10
12
|
export let self = null;
|
|
@@ -67,6 +69,7 @@ function setup(...args) {
|
|
|
67
69
|
}
|
|
68
70
|
let addComboVisible = false;
|
|
69
71
|
let addCombo;
|
|
72
|
+
let rootElement;
|
|
70
73
|
export async function show(event, hideCallback) {
|
|
71
74
|
if (event) {
|
|
72
75
|
event.stopPropagation();
|
|
@@ -79,7 +82,25 @@ export async function show(event, hideCallback) {
|
|
|
79
82
|
if (hideCallback)
|
|
80
83
|
hideCallback();
|
|
81
84
|
};
|
|
82
|
-
|
|
85
|
+
let owner = rootElement;
|
|
86
|
+
let rect = owner.getBoundingClientRect();
|
|
87
|
+
if (tagsTable.length == 0) {
|
|
88
|
+
const m = 15;
|
|
89
|
+
rect.x -= m;
|
|
90
|
+
rect.width += 2 * m;
|
|
91
|
+
rect.y -= m;
|
|
92
|
+
rect.height += 2 * m;
|
|
93
|
+
}
|
|
94
|
+
showFloatingToolbar(
|
|
95
|
+
rect,
|
|
96
|
+
TagsPalette,
|
|
97
|
+
{
|
|
98
|
+
usedTags: tagsTable,
|
|
99
|
+
allTags: globalTagsTable,
|
|
100
|
+
onSelect: onSelectTag,
|
|
101
|
+
onNewTag: getCreateTagCallback()
|
|
102
|
+
}
|
|
103
|
+
);
|
|
83
104
|
}
|
|
84
105
|
function applyChange() {
|
|
85
106
|
if (onSelect)
|
|
@@ -97,6 +118,9 @@ function applyChange() {
|
|
|
97
118
|
changed(value);
|
|
98
119
|
}
|
|
99
120
|
function onSelectTag(itm, key, name) {
|
|
121
|
+
const idx = tagsTable.findIndex((e) => e.label == key);
|
|
122
|
+
if (idx >= 0)
|
|
123
|
+
return;
|
|
100
124
|
tags += `#${key} `;
|
|
101
125
|
tagsTable = decomposeTags(tags, globalTagsTable);
|
|
102
126
|
applyChange();
|
|
@@ -106,10 +130,13 @@ function onRemoveTag(tag) {
|
|
|
106
130
|
tagsTable = decomposeTags(tags, globalTagsTable);
|
|
107
131
|
applyChange();
|
|
108
132
|
}
|
|
109
|
-
function onNewTagCreated(key, name) {
|
|
133
|
+
function onNewTagCreated(key, name, color = "") {
|
|
110
134
|
tags += `#${key} `;
|
|
111
135
|
let globalTags = getGlobalTags();
|
|
112
|
-
|
|
136
|
+
if (color)
|
|
137
|
+
globalTags += `#${key}:${color} `;
|
|
138
|
+
else
|
|
139
|
+
globalTags += `#${key} `;
|
|
113
140
|
globalTagsTable = decomposeTags(globalTags);
|
|
114
141
|
tagsTable = decomposeTags(tags, globalTagsTable);
|
|
115
142
|
applyChange();
|
|
@@ -201,17 +228,21 @@ switch (s) {
|
|
|
201
228
|
}
|
|
202
229
|
</script>
|
|
203
230
|
|
|
204
|
-
<section class="{userClass} flex flex-row {gap} flex-wrap mr-1 sm:mr-0">
|
|
231
|
+
<section class="{userClass} flex flex-row {gap} flex-wrap mr-1 sm:mr-0" bind:this={rootElement}>
|
|
205
232
|
<p class="flex flex-row {gap} flex-wrap ">
|
|
206
|
-
{#
|
|
207
|
-
{#
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
233
|
+
{#if tagsTable.length > 0}
|
|
234
|
+
{#each tagsTable as tag}
|
|
235
|
+
{#if isEditable}
|
|
236
|
+
<Tag name={tag.label} color={tag.color} {s}
|
|
237
|
+
onRemove={(e) => {onRemoveTag(tag.label)}}
|
|
238
|
+
onColor={canChangeColor ? onColorizeTag : null}/>
|
|
239
|
+
{:else}
|
|
240
|
+
<Tag name={tag.label} color={tag.color} {s}/>
|
|
241
|
+
{/if}
|
|
242
|
+
{/each}
|
|
243
|
+
{:else}
|
|
244
|
+
<!--p>​</p-->
|
|
245
|
+
{/if}
|
|
215
246
|
</p>
|
|
216
247
|
|
|
217
248
|
{#if isEditable}
|
|
@@ -223,7 +254,7 @@ switch (s) {
|
|
|
223
254
|
</button>
|
|
224
255
|
{/if}
|
|
225
256
|
{:else}
|
|
226
|
-
|
|
257
|
+
<!--Combo compact={true}
|
|
227
258
|
inContext='data'
|
|
228
259
|
onSelect={onSelectTag}
|
|
229
260
|
onNewItemCreated={getCreateTagCallback()}
|
|
@@ -234,7 +265,7 @@ switch (s) {
|
|
|
234
265
|
{#each not_used_tags as tag}
|
|
235
266
|
<ComboItem key={tag.label}/>
|
|
236
267
|
{/each}
|
|
237
|
-
</Combo
|
|
268
|
+
</Combo-->
|
|
238
269
|
{/if}
|
|
239
270
|
{/if}
|
|
240
271
|
</section>
|
package/console.svelte
CHANGED
|
@@ -9,6 +9,8 @@
|
|
|
9
9
|
let inputElement;
|
|
10
10
|
let protocol = 'cons';
|
|
11
11
|
let protoButtonBorderClass = ''
|
|
12
|
+
let history = []
|
|
13
|
+
let currentHistoryElementIdx = -1
|
|
12
14
|
|
|
13
15
|
async function onKeyDown(e)
|
|
14
16
|
{
|
|
@@ -32,18 +34,74 @@
|
|
|
32
34
|
input = input.replace('self', navItem)
|
|
33
35
|
}
|
|
34
36
|
|
|
37
|
+
const req = input;
|
|
38
|
+
input = "";
|
|
39
|
+
|
|
35
40
|
const apiVer = $session.configuration.api_version;
|
|
36
|
-
const result = await reef.fetch(`/${protocol}/${apiVer}/${
|
|
41
|
+
const result = await reef.fetch(`/${protocol}/${apiVer}/${req}`)
|
|
37
42
|
const res = await result.text();
|
|
38
43
|
prevLines = [...prevLines, res]
|
|
39
|
-
|
|
40
44
|
|
|
41
|
-
|
|
45
|
+
updateHistory(req)
|
|
42
46
|
}
|
|
43
47
|
else if(e.key == 'Esc' || e.key == 'Escape')
|
|
44
48
|
{
|
|
45
49
|
input = "";
|
|
46
50
|
}
|
|
51
|
+
else if(e.key == 'ArrowUp')
|
|
52
|
+
{
|
|
53
|
+
if(history.length > 0)
|
|
54
|
+
{
|
|
55
|
+
if(currentHistoryElementIdx < 0)
|
|
56
|
+
{
|
|
57
|
+
currentHistoryElementIdx = history.length-1
|
|
58
|
+
input = history[currentHistoryElementIdx]
|
|
59
|
+
}
|
|
60
|
+
else if(currentHistoryElementIdx > 0)
|
|
61
|
+
{
|
|
62
|
+
currentHistoryElementIdx--;
|
|
63
|
+
input = history[currentHistoryElementIdx]
|
|
64
|
+
}
|
|
65
|
+
else
|
|
66
|
+
{
|
|
67
|
+
|
|
68
|
+
}
|
|
69
|
+
moveCursorAtEnd()
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
else if(e.key == 'ArrowDown')
|
|
73
|
+
{
|
|
74
|
+
if(history.length > 0)
|
|
75
|
+
{
|
|
76
|
+
if(currentHistoryElementIdx >= 0)
|
|
77
|
+
{
|
|
78
|
+
currentHistoryElementIdx++
|
|
79
|
+
if(currentHistoryElementIdx >= history.length)
|
|
80
|
+
{
|
|
81
|
+
currentHistoryElementIdx = -1
|
|
82
|
+
input = ''
|
|
83
|
+
}
|
|
84
|
+
else
|
|
85
|
+
input = history[currentHistoryElementIdx]
|
|
86
|
+
}
|
|
87
|
+
moveCursorAtEnd()
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
function updateHistory(command)
|
|
94
|
+
{
|
|
95
|
+
const idx = history.findIndex(c => c == command)
|
|
96
|
+
if(idx < 0)
|
|
97
|
+
history.push(command)
|
|
98
|
+
else
|
|
99
|
+
{
|
|
100
|
+
history.splice(idx, 1)
|
|
101
|
+
history.push(command)
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
currentHistoryElementIdx = -1
|
|
47
105
|
}
|
|
48
106
|
|
|
49
107
|
function getNav(contextLevel)
|
|
@@ -67,9 +125,30 @@
|
|
|
67
125
|
return navItem;
|
|
68
126
|
}
|
|
69
127
|
|
|
128
|
+
function moveCursorAtEnd()
|
|
129
|
+
{
|
|
130
|
+
return;
|
|
131
|
+
setTimeout( () =>
|
|
132
|
+
{
|
|
133
|
+
const sel = window.getSelection();
|
|
134
|
+
if(!sel)
|
|
135
|
+
return;
|
|
136
|
+
if(sel.focusNode == inputElement)
|
|
137
|
+
console.log(sel.focusOffset)
|
|
138
|
+
//sel.setPosition(inputElement, input.length)
|
|
139
|
+
}, 100)
|
|
140
|
+
}
|
|
141
|
+
|
|
70
142
|
afterUpdate(() =>
|
|
71
143
|
{
|
|
72
144
|
inputElement?.scrollIntoView();
|
|
145
|
+
|
|
146
|
+
//const selection = window.getSelection()
|
|
147
|
+
//if(selection?.focusNode == inputElement)
|
|
148
|
+
//{
|
|
149
|
+
// selection?.setPosition(inputElement, input.length-1)
|
|
150
|
+
//}
|
|
151
|
+
|
|
73
152
|
})
|
|
74
153
|
|
|
75
154
|
|
package/desk.svelte
CHANGED
|
@@ -17,12 +17,13 @@
|
|
|
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'
|
|
24
24
|
import { afterUpdate, onMount } from 'svelte';
|
|
25
25
|
import {location} from 'svelte-spa-router'
|
|
26
|
+
import {FaCopy, FaTimes} from 'svelte-icons/fa'
|
|
26
27
|
|
|
27
28
|
export let layout;
|
|
28
29
|
|
|
@@ -129,17 +130,31 @@
|
|
|
129
130
|
|
|
130
131
|
if(tools_visible)
|
|
131
132
|
{
|
|
132
|
-
tools_visibility = "hidden sm:block sm:fixed"
|
|
133
|
-
//fab_base_visibility = "fixed sm:hidden"
|
|
134
|
-
fab_visibility_mode = FAB_VISIBLE_ON_MOBILE
|
|
135
|
-
|
|
136
|
-
content_top = 'top-[50px] sm:top-[40px]'
|
|
137
133
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
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
|
+
}
|
|
143
158
|
}
|
|
144
159
|
else
|
|
145
160
|
{
|
|
@@ -413,11 +428,7 @@
|
|
|
413
428
|
<Operations bind:this={operationsComponent} />
|
|
414
429
|
</div>
|
|
415
430
|
|
|
416
|
-
|
|
417
|
-
<!--div class="{fab_visibility} left-3 {fab_bottom} mb-1 cursor-pointer z-10"-->
|
|
418
|
-
<Fab bind:this={fabComponent}/>
|
|
419
|
-
<!---/div-->
|
|
420
|
-
{/if}
|
|
431
|
+
|
|
421
432
|
|
|
422
433
|
<!--#######################################################-->
|
|
423
434
|
<!--## CONTENT ##################-->
|
|
@@ -437,7 +448,11 @@
|
|
|
437
448
|
</Configurable>
|
|
438
449
|
</div>
|
|
439
450
|
|
|
440
|
-
|
|
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}
|
|
441
456
|
|
|
442
457
|
<!--###########################################################-->
|
|
443
458
|
<!--## BOTTOM SIDEBAR ###############################-->
|
|
@@ -457,17 +472,19 @@
|
|
|
457
472
|
<section class="fixed left-2 sm:left-auto sm:right-2 bottom-2 flex flex-col gap-2">
|
|
458
473
|
{#if $alerts && $alerts.length > 0}
|
|
459
474
|
{#each $alerts as alert, idx}
|
|
460
|
-
<Alert class="bg-red-900/40 shadow-lg shadow-stone-400 dark:shadow-black flex flex-row">
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
</button>
|
|
465
|
-
<p>
|
|
475
|
+
<Alert class="bg-red-900/40 shadow-lg shadow-stone-400 dark:shadow-black flex flex-row-reverse sm:flex-row">
|
|
476
|
+
{@const text_max_width = is_small ? '60vw' : '75vw'}
|
|
477
|
+
|
|
478
|
+
<p class="flex-none truncate" style="max-width: {text_max_width}">
|
|
466
479
|
{alert.msg}
|
|
467
480
|
</p>
|
|
468
|
-
<button class="
|
|
481
|
+
<button class="block sm:ml-auto w-3 mx-1"
|
|
482
|
+
on:click={() => {navigator.clipboard.writeText(alert.msg)}}>
|
|
483
|
+
<FaCopy/>
|
|
484
|
+
</button>
|
|
485
|
+
<button class="block w-3 mx-1"
|
|
469
486
|
on:click={() => {removeAlert(alert)}}>
|
|
470
|
-
|
|
487
|
+
<FaTimes/>
|
|
471
488
|
</button>
|
|
472
489
|
</Alert>
|
|
473
490
|
{/each}
|
|
@@ -477,7 +494,7 @@
|
|
|
477
494
|
<!-- #########################################################-->
|
|
478
495
|
<!-- ## MODAL DIALOG #########################################-->
|
|
479
496
|
<!-- #########################################################-->
|
|
480
|
-
<div id="__hd_svelte_modal_root" class="z-30">
|
|
497
|
+
<div id="__hd_svelte_modal_root" class="z-30 sm:z-40">
|
|
481
498
|
<!-- after <Modal/> component is shown it's rettached to above div
|
|
482
499
|
see: modal.svelte afterUpdate -->
|
|
483
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( {
|
|
@@ -305,12 +311,12 @@
|
|
|
305
311
|
{#if definedTabs && definedTabs.length > 0}
|
|
306
312
|
{#each definedTabs as tab}
|
|
307
313
|
<button class="w-12 sm:w-10 h-full flex justify-center items-center text-stone-300 hover:text-stone-100" on:click={tab.onclick}>
|
|
308
|
-
<Icon
|
|
314
|
+
<Icon s="xl" component={tab.icon}/>
|
|
309
315
|
</button>
|
|
310
316
|
{/each}
|
|
311
317
|
{:else}
|
|
312
318
|
<button class="w-12 sm:w-10 h-full flex justify-center items-center text-stone-300 hover:text-stone-100" on:click|stopPropagation={toggle_navigator}>
|
|
313
|
-
<Icon
|
|
319
|
+
<Icon s="xl" component={icon}/>
|
|
314
320
|
</button>
|
|
315
321
|
{/if}
|
|
316
322
|
</div>
|
|
@@ -324,7 +330,7 @@
|
|
|
324
330
|
{#if user_is_in_multiple_groups}
|
|
325
331
|
<button class="h-full w-12 sm:w-10 px-0 flex justify-center items-center text-stone-300 hover:text-stone-100"
|
|
326
332
|
on:click|stopPropagation={show_groups}>
|
|
327
|
-
<Icon
|
|
333
|
+
<Icon s="xl" component={FaUsers} />
|
|
328
334
|
</button>
|
|
329
335
|
{/if}
|
|
330
336
|
|
|
@@ -332,7 +338,7 @@
|
|
|
332
338
|
class="h-full w-12 sm:w-10 px-0 flex justify-center items-center text-stone-300 hover:text-stone-100"
|
|
333
339
|
on:click|stopPropagation={show_options}>
|
|
334
340
|
|
|
335
|
-
<Icon
|
|
341
|
+
<Icon s="xl" component={FaCog} />
|
|
336
342
|
</button>
|
|
337
343
|
</div>
|
|
338
344
|
|