@humandialog/forms.svelte 0.5.10 → 0.5.12
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/document/internal/palette.row.svelte +4 -1
- package/components/document/internal/palette.row.svelte.d.ts +1 -0
- package/components/document/internal/palette.svelte +99 -19
- package/components/document/internal/palette.svelte.d.ts +6 -1
- package/components/document/rich.edit.svelte +65 -24
- package/components/document/rich.edit.svelte.d.ts +2 -0
- package/components/kanban/Kanban.d.ts +2 -0
- package/components/kanban/Kanban.js +2 -0
- package/components/kanban/internal/kanban.card.svelte +60 -21
- package/components/kanban/kanban.title.svelte +4 -0
- package/components/kanban/kanban.title.svelte.d.ts +2 -0
- package/components/list/internal/list.element.svelte +64 -32
- package/horizontal.toolbar.svelte +12 -5
- package/index.d.ts +1 -1
- package/index.js +1 -1
- package/package.json +2 -2
- package/tenant.members.svelte +3 -3
- package/utils.d.ts +2 -0
- package/utils.js +23 -0
- package/vertical.toolbar.svelte +12 -5
|
@@ -12,7 +12,10 @@ $:
|
|
|
12
12
|
</script>
|
|
13
13
|
|
|
14
14
|
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
|
15
|
-
<div id={id} class="font-medium m-0 p-0 text-sm w-full text-left flex flew-row cursor-context-menu {active_class} {cl}"
|
|
15
|
+
<div id={id} class="font-medium m-0 p-0 text-sm w-full text-left flex flew-row cursor-context-menu {active_class} {cl}"
|
|
16
|
+
on:click
|
|
17
|
+
on:mousemove
|
|
18
|
+
on:mousedown>
|
|
16
19
|
<div class="flex items-center justify-center" style:width={`${icon_placeholder_size*0.25}rem`}>
|
|
17
20
|
{#if cmd.icon}
|
|
18
21
|
<Icon size={icon_size} component={cmd.icon}/>
|
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
<script>import { tick } from "svelte";
|
|
3
3
|
import Pallete_row from "./palette.row.svelte";
|
|
4
4
|
import { createEventDispatcher } from "svelte";
|
|
5
|
+
import Icon from "../../icon.svelte";
|
|
6
|
+
import { isDeviceSmallerThan } from "../../../utils.js";
|
|
5
7
|
export let commands;
|
|
6
8
|
export let width_px = 400;
|
|
7
9
|
export let max_height_px = 500;
|
|
@@ -9,8 +11,22 @@ let visible = false;
|
|
|
9
11
|
let css_style = "";
|
|
10
12
|
let filtered_commands = [...commands];
|
|
11
13
|
let current_command = filtered_commands.length ? filtered_commands[0] : null;
|
|
14
|
+
let isToolbox = false;
|
|
12
15
|
const dispatch = createEventDispatcher();
|
|
16
|
+
let toolboxX;
|
|
17
|
+
let toolboxY;
|
|
18
|
+
export function showAsToolbox(rect) {
|
|
19
|
+
isToolbox = true;
|
|
20
|
+
visible = true;
|
|
21
|
+
const margin = 15;
|
|
22
|
+
const windowWidth = window.innerWidth - 2 * margin;
|
|
23
|
+
toolboxX = margin;
|
|
24
|
+
toolboxY = rect.bottom + margin;
|
|
25
|
+
css_style = `position: fixed; left:${toolboxX}px; top:${toolboxY}px;`;
|
|
26
|
+
dispatch("palette_shown");
|
|
27
|
+
}
|
|
13
28
|
export function show(x, y, up = false) {
|
|
29
|
+
isToolbox = false;
|
|
14
30
|
css_style = `width: ${width_px}px; max-height:${max_height_px}px; position: fixed; left:${x}px; top:${y}px;`;
|
|
15
31
|
if (up)
|
|
16
32
|
css_style += " transform: translate(0, -100%);";
|
|
@@ -18,6 +34,7 @@ export function show(x, y, up = false) {
|
|
|
18
34
|
dispatch("palette_shown");
|
|
19
35
|
}
|
|
20
36
|
export function show_fullscreen(_width_px, _height_px) {
|
|
37
|
+
isToolbox = false;
|
|
21
38
|
width_px = _width_px;
|
|
22
39
|
max_height_px = _height_px;
|
|
23
40
|
css_style = `position: fixed; left: 0px; top: 0px; width: ${_width_px}px; height: ${_height_px}px; z-index: 1055;`;
|
|
@@ -26,6 +43,7 @@ export function show_fullscreen(_width_px, _height_px) {
|
|
|
26
43
|
}
|
|
27
44
|
export function hide() {
|
|
28
45
|
visible = false;
|
|
46
|
+
isToolbox = false;
|
|
29
47
|
dispatch("palette_hidden");
|
|
30
48
|
}
|
|
31
49
|
export function execute_selected_command() {
|
|
@@ -84,7 +102,6 @@ async function execute_mouse_click(on_choice) {
|
|
|
84
102
|
if (!visible)
|
|
85
103
|
return;
|
|
86
104
|
dispatch("palette_mouse_click");
|
|
87
|
-
await tick();
|
|
88
105
|
hide();
|
|
89
106
|
on_choice();
|
|
90
107
|
}
|
|
@@ -100,24 +117,87 @@ function update_current_command(cmd) {
|
|
|
100
117
|
rows.find((r) => r.cmd == cmd).is_highlighted = true;
|
|
101
118
|
current_command = cmd;
|
|
102
119
|
}
|
|
120
|
+
function buttonMousedown(e) {
|
|
121
|
+
e.preventDefault();
|
|
122
|
+
}
|
|
123
|
+
let isMoving = false;
|
|
124
|
+
let beforeTrackingClient = null;
|
|
125
|
+
let beforeTrackingPos = null;
|
|
126
|
+
function mousedown(e) {
|
|
127
|
+
if (e.touches.length != 1)
|
|
128
|
+
return;
|
|
129
|
+
const touch = e.touches.item(0);
|
|
130
|
+
beforeTrackingClient = new DOMPoint(touch.clientX, touch.clientY);
|
|
131
|
+
beforeTrackingPos = new DOMPoint(toolboxX, toolboxY);
|
|
132
|
+
isMoving = true;
|
|
133
|
+
}
|
|
134
|
+
function mousemove(e) {
|
|
135
|
+
if (isMoving && beforeTrackingClient && beforeTrackingPos) {
|
|
136
|
+
if (e.touches.length != 1)
|
|
137
|
+
return;
|
|
138
|
+
const touch = e.touches.item(0);
|
|
139
|
+
const trackDelta = new DOMPoint(touch.clientX - beforeTrackingClient.x, touch.clientY - beforeTrackingClient.y);
|
|
140
|
+
toolboxX = beforeTrackingPos.x + trackDelta.x;
|
|
141
|
+
css_style = `position: fixed; left:${toolboxX}px; top:${toolboxY}px;`;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
function mouseup(e) {
|
|
145
|
+
isMoving = false;
|
|
146
|
+
beforeTrackingClient = null;
|
|
147
|
+
beforeTrackingPos = null;
|
|
148
|
+
}
|
|
103
149
|
</script>
|
|
104
150
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
{
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
151
|
+
{#if isToolbox}
|
|
152
|
+
<menu class=" not-prose 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
|
|
153
|
+
z-30
|
|
154
|
+
flex flex-row flex-nowrap"
|
|
155
|
+
style={css_style}
|
|
156
|
+
hidden={!visible}
|
|
157
|
+
on:touchstart={mousedown}
|
|
158
|
+
on:touchmove={mousemove}
|
|
159
|
+
on:touchend={mouseup}>
|
|
160
|
+
{#if filtered_commands && filtered_commands.length}
|
|
161
|
+
{#each filtered_commands as cmd, idx (cmd.caption)}
|
|
162
|
+
{@const id = "cpi_" + idx}
|
|
163
|
+
{@const mobile = isDeviceSmallerThan("sm")}
|
|
164
|
+
{@const icon_placeholder_size = mobile ? 12 : 10}
|
|
165
|
+
<button class="font-medium m-0 py-2 pr-4 text-lg sm:text-sm w-full text-left flex flex-row cursor-context-menu focus:outline-none"
|
|
166
|
+
{id}
|
|
167
|
+
bind:this={rows[idx]}
|
|
168
|
+
on:click={ () => { execute_mouse_click(cmd.on_choice); }}
|
|
169
|
+
on:mousedown={buttonMousedown}>
|
|
170
|
+
|
|
171
|
+
<div class="flex items-center justify-center mt-1 sm:mt-0.5" style:width={`${icon_placeholder_size*0.25}rem`}>
|
|
172
|
+
{#if cmd.icon}
|
|
173
|
+
{@const cc = mobile ? 7 : 6}
|
|
174
|
+
{@const icon_size = icon_placeholder_size - cc}
|
|
175
|
+
<Icon size={icon_size} component={cmd.icon}/>
|
|
176
|
+
{/if}
|
|
177
|
+
</div>
|
|
178
|
+
</button>
|
|
179
|
+
{/each}
|
|
180
|
+
{/if}
|
|
181
|
+
</menu>
|
|
182
|
+
{:else}
|
|
183
|
+
<div class="not-prose 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 z-30"
|
|
184
|
+
hidden={!visible}
|
|
185
|
+
style={css_style}>
|
|
186
|
+
{#if filtered_commands && filtered_commands.length}
|
|
187
|
+
{#each filtered_commands as cmd, idx (cmd.caption)}
|
|
188
|
+
{@const id = "cpi_" + idx}
|
|
189
|
+
<Pallete_row {id}
|
|
190
|
+
cmd={cmd}
|
|
191
|
+
is_highlighted={cmd == current_command}
|
|
192
|
+
on:click={ () => { execute_mouse_click(cmd.on_choice); }}
|
|
193
|
+
on:mousemove={ () => { on_mouse_over(cmd); }}
|
|
194
|
+
on:mousedown={buttonMousedown}
|
|
195
|
+
bind:this={rows[idx]}
|
|
196
|
+
/>
|
|
197
|
+
{/each}
|
|
198
|
+
{:else}
|
|
199
|
+
<p class="text-sm text-stone-500">No results</p>
|
|
200
|
+
{/if}
|
|
122
201
|
|
|
123
|
-
</div>
|
|
202
|
+
</div>
|
|
203
|
+
{/if}
|
|
@@ -5,6 +5,7 @@ declare const __propDef: {
|
|
|
5
5
|
commands: Document_command[];
|
|
6
6
|
width_px?: number | undefined;
|
|
7
7
|
max_height_px?: number | undefined;
|
|
8
|
+
showAsToolbox?: ((rect: DOMRect) => void) | undefined;
|
|
8
9
|
show?: ((x: number, y: number, up?: boolean) => void) | undefined;
|
|
9
10
|
show_fullscreen?: ((_width_px: number, _height_px: number) => void) | undefined;
|
|
10
11
|
hide?: (() => void) | undefined;
|
|
@@ -20,12 +21,13 @@ declare const __propDef: {
|
|
|
20
21
|
} & {
|
|
21
22
|
[evt: string]: CustomEvent<any>;
|
|
22
23
|
};
|
|
23
|
-
slots: {};
|
|
24
|
+
slots: {};
|
|
24
25
|
};
|
|
25
26
|
export type PaletteProps = typeof __propDef.props;
|
|
26
27
|
export type PaletteEvents = typeof __propDef.events;
|
|
27
28
|
export type PaletteSlots = typeof __propDef.slots;
|
|
28
29
|
export default class Palette extends SvelteComponentTyped<PaletteProps, PaletteEvents, PaletteSlots> {
|
|
30
|
+
get showAsToolbox(): (rect: DOMRect) => void;
|
|
29
31
|
get show(): (x: number, y: number, up?: boolean) => void;
|
|
30
32
|
get show_fullscreen(): (_width_px: number, _height_px: number) => void;
|
|
31
33
|
get hide(): () => void;
|
|
@@ -63,5 +65,8 @@ export default class Palette extends SvelteComponentTyped<PaletteProps, PaletteE
|
|
|
63
65
|
get undefined(): any;
|
|
64
66
|
/**accessor*/
|
|
65
67
|
set undefined(_: any);
|
|
68
|
+
get undefined(): any;
|
|
69
|
+
/**accessor*/
|
|
70
|
+
set undefined(_: any);
|
|
66
71
|
}
|
|
67
72
|
export {};
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
<script>import { Selection_helper } from "./internal/Selection_helper";
|
|
2
|
-
import { getContext, onDestroy, onMount } from "svelte";
|
|
2
|
+
import { afterUpdate, getContext, onDestroy, onMount } from "svelte";
|
|
3
3
|
import { Selection_range, Selection_edge } from "./internal/Selection_range";
|
|
4
4
|
import { data_tick_store, contextItemsStore, contextTypesStore } from "../../stores.js";
|
|
5
5
|
import { informModification, pushChanges } from "../../updates.js";
|
|
6
|
-
import { parseWidthDirective } from "../../utils.js";
|
|
6
|
+
import { isDeviceSmallerThan, parseWidthDirective } from "../../utils.js";
|
|
7
7
|
import Palette from "./internal/palette.svelte";
|
|
8
8
|
import FaFont from "svelte-icons/fa/FaFont.svelte";
|
|
9
9
|
import FaRemoveFormat from "svelte-icons/fa/FaRemoveFormat.svelte";
|
|
@@ -13,6 +13,7 @@ import FaComments from "svelte-icons/fa/FaComment.svelte";
|
|
|
13
13
|
import FaQuote from "svelte-icons/fa/FaQuoteRight.svelte";
|
|
14
14
|
import FaWarn from "svelte-icons/fa/FaExclamationTriangle.svelte";
|
|
15
15
|
import FaInfo from "svelte-icons/fa/FaInfo.svelte";
|
|
16
|
+
import { showMenu } from "../menu";
|
|
16
17
|
export let value = "";
|
|
17
18
|
export let placeholder = "";
|
|
18
19
|
export let self = null;
|
|
@@ -62,8 +63,12 @@ else
|
|
|
62
63
|
px-2.5`;
|
|
63
64
|
let last_tick = -1;
|
|
64
65
|
$: {
|
|
65
|
-
if (last_tick < $data_tick_store)
|
|
66
|
-
|
|
66
|
+
if (last_tick < $data_tick_store) {
|
|
67
|
+
if (has_changed_value)
|
|
68
|
+
saveData();
|
|
69
|
+
else
|
|
70
|
+
setup_source();
|
|
71
|
+
}
|
|
67
72
|
}
|
|
68
73
|
function setup_source() {
|
|
69
74
|
last_tick = $data_tick_store;
|
|
@@ -80,6 +85,8 @@ function setup_source() {
|
|
|
80
85
|
if (!value)
|
|
81
86
|
value = "<p>\u200B</p>";
|
|
82
87
|
has_changed_value = false;
|
|
88
|
+
if (stored_selection)
|
|
89
|
+
set_selection(stored_selection);
|
|
83
90
|
}
|
|
84
91
|
onMount(() => {
|
|
85
92
|
if (!editable_div)
|
|
@@ -95,6 +102,9 @@ onMount(() => {
|
|
|
95
102
|
subtree: true
|
|
96
103
|
});
|
|
97
104
|
}
|
|
105
|
+
return () => {
|
|
106
|
+
on_blur();
|
|
107
|
+
};
|
|
98
108
|
});
|
|
99
109
|
onDestroy(() => {
|
|
100
110
|
if (!editable_div)
|
|
@@ -166,9 +176,12 @@ const on_keydown = (event) => {
|
|
|
166
176
|
} else {
|
|
167
177
|
event.cancelBubble = true;
|
|
168
178
|
event.preventDefault();
|
|
169
|
-
if (is_multiline())
|
|
170
|
-
|
|
171
|
-
|
|
179
|
+
if (is_multiline()) {
|
|
180
|
+
if (event.shiftKey)
|
|
181
|
+
insert_character_at_caret_position("\n");
|
|
182
|
+
else
|
|
183
|
+
insert_new_line();
|
|
184
|
+
} else
|
|
172
185
|
move_cursor_to_next_editable_element();
|
|
173
186
|
}
|
|
174
187
|
break;
|
|
@@ -176,6 +189,11 @@ const on_keydown = (event) => {
|
|
|
176
189
|
store_node_text_and_position();
|
|
177
190
|
show_command_palette();
|
|
178
191
|
break;
|
|
192
|
+
case "Tab":
|
|
193
|
+
event.cancelBubble = true;
|
|
194
|
+
event.preventDefault();
|
|
195
|
+
insert_character_at_caret_position(" ");
|
|
196
|
+
break;
|
|
179
197
|
case "Backspace":
|
|
180
198
|
if (is_range_selected()) {
|
|
181
199
|
if (is_multi_range_selection()) {
|
|
@@ -715,7 +733,7 @@ function set_tag_and_class_for_paragraph(node, tag, css_class) {
|
|
|
715
733
|
while (node && node.nodeType !== Node.ELEMENT_NODE)
|
|
716
734
|
node = node.parentNode;
|
|
717
735
|
if (!node)
|
|
718
|
-
return;
|
|
736
|
+
return false;
|
|
719
737
|
let element = node;
|
|
720
738
|
if (element.tagName == tag.toUpperCase()) {
|
|
721
739
|
element.className = css_class;
|
|
@@ -737,7 +755,7 @@ function set_tag_and_class_for_paragraph(node, tag, css_class) {
|
|
|
737
755
|
function do_format(tag, css_class) {
|
|
738
756
|
const elem = editable_div;
|
|
739
757
|
const editableElem = editable_div;
|
|
740
|
-
let
|
|
758
|
+
let stored_selection2 = Selection_helper.get_selection(elem);
|
|
741
759
|
let sel = window.getSelection();
|
|
742
760
|
let should_restore_selection = false;
|
|
743
761
|
if (sel.isCollapsed || sel.focusNode === sel.anchorNode) {
|
|
@@ -766,7 +784,28 @@ function do_format(tag, css_class) {
|
|
|
766
784
|
} while (node);
|
|
767
785
|
}
|
|
768
786
|
if (should_restore_selection) {
|
|
769
|
-
const range = Selection_helper.create_range(editableElem,
|
|
787
|
+
const range = Selection_helper.create_range(editableElem, stored_selection2.begin.absolute_index, stored_selection2.end.absolute_index);
|
|
788
|
+
set_selection(range);
|
|
789
|
+
}
|
|
790
|
+
}
|
|
791
|
+
function insert_character_at_caret_position(what_to_insert) {
|
|
792
|
+
if (is_range_selected()) {
|
|
793
|
+
console.log("Unsupported");
|
|
794
|
+
return false;
|
|
795
|
+
} else {
|
|
796
|
+
let sel;
|
|
797
|
+
sel = window.getSelection();
|
|
798
|
+
const focusNode = sel.focusNode;
|
|
799
|
+
const wholeText = focusNode.textContent;
|
|
800
|
+
const carretPos = sel.focusOffset;
|
|
801
|
+
let leftPart = wholeText.substring(0, carretPos);
|
|
802
|
+
let rightPart = wholeText.substring(carretPos);
|
|
803
|
+
focusNode.textContent = leftPart + what_to_insert + rightPart;
|
|
804
|
+
let pos = carretPos + 1;
|
|
805
|
+
let range = new Range();
|
|
806
|
+
range.collapse(true);
|
|
807
|
+
range.setStart(focusNode, pos);
|
|
808
|
+
range.setEnd(focusNode, pos);
|
|
770
809
|
set_selection(range);
|
|
771
810
|
}
|
|
772
811
|
}
|
|
@@ -879,7 +918,10 @@ function show_command_palette() {
|
|
|
879
918
|
y = rect.y - (preferred_palette_height - bottom_space);
|
|
880
919
|
} else
|
|
881
920
|
show_fullscreen = true;
|
|
882
|
-
|
|
921
|
+
const isSmallDevice = isDeviceSmallerThan("sm");
|
|
922
|
+
if (isSmallDevice) {
|
|
923
|
+
palette.showAsToolbox(rect);
|
|
924
|
+
} else if (show_fullscreen)
|
|
883
925
|
palette.show_fullscreen(client_rect.width, client_rect.height);
|
|
884
926
|
else
|
|
885
927
|
palette.show(x, y, show_above);
|
|
@@ -899,25 +941,18 @@ function navigate_command_palette(key) {
|
|
|
899
941
|
else if (key == "ArrowUp")
|
|
900
942
|
palette.navigate_up();
|
|
901
943
|
}
|
|
944
|
+
let stored_selection = void 0;
|
|
902
945
|
function on_selection_changed() {
|
|
946
|
+
let active_range = Selection_helper.get_selection(editable_div);
|
|
947
|
+
stored_selection = window.getSelection()?.getRangeAt(0);
|
|
903
948
|
}
|
|
904
949
|
let intervalId = 0;
|
|
905
950
|
function on_focus() {
|
|
906
|
-
if (pushChangesImmediately) {
|
|
907
|
-
intervalId = setInterval(
|
|
908
|
-
() => {
|
|
909
|
-
saveData();
|
|
910
|
-
},
|
|
911
|
-
2e3
|
|
912
|
-
);
|
|
913
|
-
}
|
|
914
951
|
}
|
|
915
952
|
function on_blur() {
|
|
916
953
|
let active_range = Selection_helper.get_selection(editable_div);
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
intervalId = 0;
|
|
920
|
-
}
|
|
954
|
+
console.log("rich.edit: on_blur", active_range?.begin?.absolute_index);
|
|
955
|
+
stored_selection = void 0;
|
|
921
956
|
if (onBlur) {
|
|
922
957
|
onBlur();
|
|
923
958
|
onBlur = void 0;
|
|
@@ -927,6 +962,12 @@ function on_blur() {
|
|
|
927
962
|
$data_tick_store = last_tick;
|
|
928
963
|
}
|
|
929
964
|
}
|
|
965
|
+
export function save() {
|
|
966
|
+
if (saveData()) {
|
|
967
|
+
last_tick = $data_tick_store + 1;
|
|
968
|
+
$data_tick_store = last_tick;
|
|
969
|
+
}
|
|
970
|
+
}
|
|
930
971
|
function saveData() {
|
|
931
972
|
if (item && a && has_changed_value) {
|
|
932
973
|
item[a] = changed_value;
|
|
@@ -977,7 +1018,7 @@ let commands = [
|
|
|
977
1018
|
on:keydown={on_keydown}
|
|
978
1019
|
on:mouseup={on_mouseup}
|
|
979
1020
|
class="{cs} {appearance_class}
|
|
980
|
-
prose prose-base sm:prose-base dark:prose-invert {additional_class} overflow-y-auto"
|
|
1021
|
+
prose prose-base sm:prose-base dark:prose-invert {additional_class} overflow-y-auto whitespace-pre-wrap"
|
|
981
1022
|
on:blur={on_blur}
|
|
982
1023
|
on:focus={on_focus}
|
|
983
1024
|
on:focus
|
|
@@ -13,6 +13,7 @@ declare const __propDef: {
|
|
|
13
13
|
pushChangesImmediately?: boolean | undefined;
|
|
14
14
|
run?: ((onStop?: undefined) => void) | undefined;
|
|
15
15
|
getFormattingOperations?: ((withCaptions?: boolean) => any[]) | undefined;
|
|
16
|
+
save?: (() => void) | undefined;
|
|
16
17
|
};
|
|
17
18
|
events: {
|
|
18
19
|
focus: FocusEvent;
|
|
@@ -28,5 +29,6 @@ export type RichSlots = typeof __propDef.slots;
|
|
|
28
29
|
export default class Rich extends SvelteComponentTyped<RichProps, RichEvents, RichSlots> {
|
|
29
30
|
get run(): (onStop?: undefined) => void;
|
|
30
31
|
get getFormattingOperations(): (withCaptions?: boolean) => any[];
|
|
32
|
+
get save(): () => void;
|
|
31
33
|
}
|
|
32
34
|
export {};
|
|
@@ -16,6 +16,8 @@ export declare class rKanban_definition {
|
|
|
16
16
|
titleAttrib: string;
|
|
17
17
|
titleOnChange: Function | undefined;
|
|
18
18
|
titleReadOnly: boolean;
|
|
19
|
+
titleHref: string | undefined;
|
|
20
|
+
titleHrefFunc: Function | undefined;
|
|
19
21
|
summaryAttrib: string;
|
|
20
22
|
summaryOnChange: Function | undefined;
|
|
21
23
|
summaryReadOnly: boolean;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
<script>import { getContext, tick } from "svelte";
|
|
2
|
+
import { push } from "svelte-spa-router";
|
|
2
3
|
import {
|
|
3
4
|
contextItemsStore,
|
|
4
5
|
isActive,
|
|
@@ -8,7 +9,8 @@ import {
|
|
|
8
9
|
editable,
|
|
9
10
|
showFloatingToolbar,
|
|
10
11
|
informModification,
|
|
11
|
-
pushChanges
|
|
12
|
+
pushChanges,
|
|
13
|
+
startEditing
|
|
12
14
|
} from "../../..";
|
|
13
15
|
import { FaArrowsAlt, FaTrash, FaPlus, FaExternalLinkAlt } from "svelte-icons/fa";
|
|
14
16
|
import MoveOperations from "./kanban.move.menu.svelte";
|
|
@@ -24,6 +26,8 @@ $:
|
|
|
24
26
|
selectedClass = isCardSelected ? "!border-blue-300" : "";
|
|
25
27
|
$:
|
|
26
28
|
focusedClass = isCardActive ? "bg-stone-100 dark:bg-stone-700" : "";
|
|
29
|
+
$:
|
|
30
|
+
isLinkLike = isCardActive && (!!definition.titleHref || !!definition.titleHrefFunc);
|
|
27
31
|
function calculate_active(...args) {
|
|
28
32
|
return isActive("props", item);
|
|
29
33
|
}
|
|
@@ -96,9 +100,13 @@ let summaryElement;
|
|
|
96
100
|
let summaryPlaceholder = false;
|
|
97
101
|
export async function editProperty(field) {
|
|
98
102
|
if (field == "Title") {
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
103
|
+
if (isLinkLike) {
|
|
104
|
+
startEditing(titleElement);
|
|
105
|
+
} else {
|
|
106
|
+
titleElement.focus();
|
|
107
|
+
await tick();
|
|
108
|
+
setSelectionAtEnd(titleElement);
|
|
109
|
+
}
|
|
102
110
|
} else if (field == "Summary") {
|
|
103
111
|
if (!!summaryElement) {
|
|
104
112
|
summaryElement.focus();
|
|
@@ -127,6 +135,19 @@ export async function editProperty(field) {
|
|
|
127
135
|
}
|
|
128
136
|
}
|
|
129
137
|
}
|
|
138
|
+
function followDefinedHRef() {
|
|
139
|
+
let link = getHRef();
|
|
140
|
+
if (link)
|
|
141
|
+
push(link);
|
|
142
|
+
}
|
|
143
|
+
function getHRef() {
|
|
144
|
+
if (definition.titleHref)
|
|
145
|
+
return definition.titleHref;
|
|
146
|
+
else if (definition.titleHrefFunc)
|
|
147
|
+
return definition.titleHrefFunc(item);
|
|
148
|
+
else
|
|
149
|
+
return "";
|
|
150
|
+
}
|
|
130
151
|
</script>
|
|
131
152
|
|
|
132
153
|
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
|
@@ -162,25 +183,43 @@ export async function editProperty(field) {
|
|
|
162
183
|
|
|
163
184
|
|
|
164
185
|
{#if isCardActive}
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
186
|
+
{#if isLinkLike}
|
|
187
|
+
<h3 class=" text-lg font-semibold min-h-[1.75rem]
|
|
188
|
+
sm:text-sm sm:font-semibold sm:min-h-[1.25rem]
|
|
189
|
+
whitespace-nowrap overflow-clip truncate w-full sm:flex-none
|
|
190
|
+
relative
|
|
191
|
+
sm:hover:cursor-pointer underline"
|
|
192
|
+
on:click|stopPropagation={followDefinedHRef}
|
|
193
|
+
use:editable={{
|
|
194
|
+
action: (text) => onTitleChanged(text),
|
|
195
|
+
active: false,
|
|
196
|
+
readonly: definition.titleReadOnly,
|
|
197
|
+
onFinish: (d) => {titleElement.blur()}}}
|
|
198
|
+
bind:this={titleElement}>
|
|
199
|
+
{item[definition.titleAttrib]}
|
|
200
|
+
</h3>
|
|
201
|
+
{:else}
|
|
202
|
+
<h3 class=" text-lg font-semibold min-h-[1.75rem]
|
|
203
|
+
sm:text-sm sm:font-semibold sm:min-h-[1.25rem]
|
|
204
|
+
whitespace-nowrap overflow-clip truncate w-full sm:flex-none
|
|
205
|
+
relative"
|
|
206
|
+
use:editable={{
|
|
207
|
+
action: (text) => onTitleChanged(text),
|
|
208
|
+
active: true,
|
|
209
|
+
readonly: definition.titleReadOnly,
|
|
210
|
+
onFinish: (d) => {titleElement.blur()}}}
|
|
211
|
+
bind:this={titleElement}>
|
|
212
|
+
{item[definition.titleAttrib]}
|
|
176
213
|
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
214
|
+
{#if definition.onOpen}
|
|
215
|
+
<button class="absolute top-1 right-0 w-5 h-5 sm:w-3 sm:h-3"
|
|
216
|
+
on:click={(e) => definition.onOpen(item)}>
|
|
217
|
+
<FaExternalLinkAlt/>
|
|
218
|
+
</button>
|
|
219
|
+
{/if}
|
|
220
|
+
</h3>
|
|
182
221
|
{/if}
|
|
183
|
-
|
|
222
|
+
|
|
184
223
|
{:else}
|
|
185
224
|
<h3 class=" text-lg font-semibold min-h-[1.75rem]
|
|
186
225
|
sm:text-sm sm:font-semibold sm:min-h-[1.25rem]
|
|
@@ -2,9 +2,13 @@
|
|
|
2
2
|
export let a;
|
|
3
3
|
export let onChange = void 0;
|
|
4
4
|
export let readOnly = false;
|
|
5
|
+
export let href = void 0;
|
|
6
|
+
export let hrefFunc = void 0;
|
|
5
7
|
let definition = getContext("rKanban-definition");
|
|
6
8
|
definition.titleAttrib = a;
|
|
7
9
|
definition.titleOnChange = onChange;
|
|
8
10
|
definition.titleReadOnly = readOnly;
|
|
11
|
+
definition.titleHref = href;
|
|
12
|
+
definition.titleHrefFunc = hrefFunc;
|
|
9
13
|
</script>
|
|
10
14
|
|
|
@@ -36,7 +36,7 @@ $:
|
|
|
36
36
|
$:
|
|
37
37
|
focused_class = is_row_active ? "bg-stone-200 dark:bg-stone-700" : "";
|
|
38
38
|
$:
|
|
39
|
-
is_link_like =
|
|
39
|
+
is_link_like = is_row_active && (!!definition.title_href || !!definition.title_href_func);
|
|
40
40
|
if (!typename) {
|
|
41
41
|
if (item.$type)
|
|
42
42
|
typename = item.$type;
|
|
@@ -117,18 +117,24 @@ function on_active_row_clicked(e, part) {
|
|
|
117
117
|
}
|
|
118
118
|
} else if (click_on_empty_space) {
|
|
119
119
|
if (definition.title_href || definition.title_href_func) {
|
|
120
|
-
let link = "";
|
|
121
|
-
if (definition.title_href)
|
|
122
|
-
link = definition.title_href;
|
|
123
|
-
else if (definition.title_href_func)
|
|
124
|
-
link = definition.title_href_func(item);
|
|
125
|
-
if (link)
|
|
126
|
-
push(link);
|
|
127
120
|
} else {
|
|
128
121
|
}
|
|
129
122
|
} else {
|
|
130
123
|
}
|
|
131
124
|
}
|
|
125
|
+
function followDefinedHRef() {
|
|
126
|
+
let link = getHRef();
|
|
127
|
+
if (link)
|
|
128
|
+
push(link);
|
|
129
|
+
}
|
|
130
|
+
function getHRef() {
|
|
131
|
+
if (definition.title_href)
|
|
132
|
+
return definition.title_href;
|
|
133
|
+
else if (definition.title_href_func)
|
|
134
|
+
return definition.title_href_func(item);
|
|
135
|
+
else
|
|
136
|
+
return "";
|
|
137
|
+
}
|
|
132
138
|
function activate_row(e, item2) {
|
|
133
139
|
activateItem("props", item2, toolbarOperations(item2));
|
|
134
140
|
if (e)
|
|
@@ -174,8 +180,19 @@ async function force_editing(field) {
|
|
|
174
180
|
if (!element_node.classList.contains("editable")) {
|
|
175
181
|
return;
|
|
176
182
|
}
|
|
177
|
-
|
|
178
|
-
|
|
183
|
+
if (field == "Title") {
|
|
184
|
+
if (is_link_like) {
|
|
185
|
+
startEditing(element_node, () => {
|
|
186
|
+
placeholder = "";
|
|
187
|
+
});
|
|
188
|
+
} else {
|
|
189
|
+
element_node.focus();
|
|
190
|
+
setSelectionAtEnd(element_node);
|
|
191
|
+
}
|
|
192
|
+
} else {
|
|
193
|
+
element_node.focus();
|
|
194
|
+
setSelectionAtEnd(element_node);
|
|
195
|
+
}
|
|
179
196
|
}
|
|
180
197
|
function setSelectionAtEnd(element) {
|
|
181
198
|
const textNode = element.childNodes[0];
|
|
@@ -214,43 +231,58 @@ export function scrollToView() {
|
|
|
214
231
|
<slot name="left" element={item}/>
|
|
215
232
|
|
|
216
233
|
<div class="ml-3 w-full py-1"
|
|
217
|
-
class:sm:hover:cursor-pointer={is_link_like}
|
|
218
234
|
use:selectable={item}
|
|
219
235
|
on:click={(e) => {activate_row(e, item)}}
|
|
220
236
|
role="row"
|
|
221
237
|
tabindex="0">
|
|
222
238
|
<div class="block sm:flex sm:flex-row" on:click={(e) => on_active_row_clicked(e, 'top')}>
|
|
223
239
|
|
|
224
|
-
|
|
225
|
-
{#key item[title]}
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
240
|
+
{#if is_row_active}
|
|
241
|
+
{#key item[title]} <!-- Wymusza pełne wyrenderowanie zwłasza po zmiane z pustego na tekst -->
|
|
242
|
+
{#if is_link_like}
|
|
243
|
+
<p class=" text-lg font-semibold min-h-[1.75rem]
|
|
244
|
+
sm:text-sm sm:font-semibold sm:min-h-[1.25rem]
|
|
245
|
+
whitespace-nowrap overflow-clip w-full sm:flex-none sm:w-2/3
|
|
246
|
+
sm:hover:cursor-pointer underline"
|
|
247
|
+
id="__hd_list_ctrl_{item[item_key]}_Title"
|
|
248
|
+
on:click|stopPropagation={followDefinedHRef}
|
|
249
|
+
use:editable={{
|
|
250
|
+
action: (text) => {change_name(text)},
|
|
251
|
+
active: false,
|
|
252
|
+
readonly: definition.title_readonly,
|
|
253
|
+
}}
|
|
254
|
+
>
|
|
235
255
|
{element_title}
|
|
256
|
+
</p>
|
|
257
|
+
{:else}
|
|
258
|
+
<p class=" text-lg font-semibold min-h-[1.75rem]
|
|
259
|
+
sm:text-sm sm:font-semibold sm:min-h-[1.25rem]
|
|
260
|
+
whitespace-nowrap overflow-clip w-full sm:flex-none sm:w-2/3"
|
|
261
|
+
id="__hd_list_ctrl_{item[item_key]}_Title"
|
|
262
|
+
use:editable={{
|
|
263
|
+
action: (text) => {change_name(text)},
|
|
264
|
+
active: true,
|
|
265
|
+
readonly: definition.title_readonly,
|
|
266
|
+
}}>
|
|
267
|
+
{element_title}
|
|
236
268
|
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
269
|
+
{#if definition.onOpen}
|
|
270
|
+
<button class="ml-3 w-5 h-5 sm:w-3 sm:h-3"
|
|
271
|
+
on:click={(e) => definition.onOpen(item)}>
|
|
272
|
+
<FaExternalLinkAlt/>
|
|
273
|
+
</button>
|
|
274
|
+
{/if}
|
|
275
|
+
</p>
|
|
276
|
+
{/if}
|
|
244
277
|
{/key}
|
|
245
|
-
|
|
278
|
+
{:else}
|
|
246
279
|
<p class=" text-lg font-semibold min-h-[1.75rem]
|
|
247
280
|
sm:text-sm sm:font-semibold sm:min-h-[1.25rem]
|
|
248
281
|
whitespace-nowrap overflow-clip w-full sm:flex-none sm:w-2/3"
|
|
249
282
|
id="__hd_list_ctrl_{item[item_key]}_Title">
|
|
250
283
|
{element_title}
|
|
251
284
|
</p>
|
|
252
|
-
|
|
253
|
-
|
|
285
|
+
{/if}
|
|
254
286
|
|
|
255
287
|
|
|
256
288
|
<section class="hidden sm:block w-full sm:flex-none sm:w-1/3">
|
|
@@ -130,11 +130,18 @@
|
|
|
130
130
|
if(config.customOperations && Array.isArray(config.customOperations) && config.customOperations.length > 0)
|
|
131
131
|
{
|
|
132
132
|
config.customOperations.forEach( o => {
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
133
|
+
let add = true;
|
|
134
|
+
if(o.condition)
|
|
135
|
+
add = o.condition();
|
|
136
|
+
|
|
137
|
+
if(add)
|
|
138
|
+
{
|
|
139
|
+
options.push({
|
|
140
|
+
caption: o.caption,
|
|
141
|
+
icon: o.icon,
|
|
142
|
+
action: o.action
|
|
143
|
+
})
|
|
144
|
+
}
|
|
138
145
|
})
|
|
139
146
|
}
|
|
140
147
|
|
package/index.d.ts
CHANGED
|
@@ -51,7 +51,7 @@ export { default as KanbanComboProperty } from './components/kanban/kanban.combo
|
|
|
51
51
|
export { default as KanbanTagsProperty } from './components/kanban/kanban.tags.svelte';
|
|
52
52
|
export { default as KanbanCallbacks } from './components/kanban/kanban.callbacks.svelte';
|
|
53
53
|
export { KanbanColumnTop, KanbanColumnBottom } from './components/kanban/Kanban';
|
|
54
|
-
export { selectItem, activateItem, clearActiveItem, isActive, isSelected, getActive, editable, startEditing, selectable, handleSelect, isDeviceSmallerThan } from './utils';
|
|
54
|
+
export { selectItem, activateItem, clearActiveItem, isActive, isSelected, getActive, editable, startEditing, saveCurrentEditable, selectable, handleSelect, isDeviceSmallerThan } from './utils';
|
|
55
55
|
export { mainViewReloader, reloadMainView } from './stores.js';
|
|
56
56
|
export { data_tick_store, // tmp
|
|
57
57
|
hasSelectedItem, hasDataItem, setNavigatorTitle } from "./stores";
|
package/index.js
CHANGED
|
@@ -57,7 +57,7 @@ export { default as KanbanComboProperty } from './components/kanban/kanban.combo
|
|
|
57
57
|
export { default as KanbanTagsProperty } from './components/kanban/kanban.tags.svelte';
|
|
58
58
|
export { default as KanbanCallbacks } from './components/kanban/kanban.callbacks.svelte';
|
|
59
59
|
export { KanbanColumnTop, KanbanColumnBottom } from './components/kanban/Kanban';
|
|
60
|
-
export { selectItem, activateItem, clearActiveItem, isActive, isSelected, getActive, editable, startEditing, selectable, handleSelect, isDeviceSmallerThan } from './utils';
|
|
60
|
+
export { selectItem, activateItem, clearActiveItem, isActive, isSelected, getActive, editable, startEditing, saveCurrentEditable, selectable, handleSelect, isDeviceSmallerThan } from './utils';
|
|
61
61
|
export { mainViewReloader, reloadMainView } from './stores.js';
|
|
62
62
|
export { data_tick_store, // tmp
|
|
63
63
|
hasSelectedItem, hasDataItem, setNavigatorTitle } from "./stores";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@humandialog/forms.svelte",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.12",
|
|
4
4
|
"description": "Basic Svelte UI components for Object Reef applications",
|
|
5
5
|
"devDependencies": {
|
|
6
6
|
"@playwright/test": "^1.28.1",
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
},
|
|
27
27
|
"type": "module",
|
|
28
28
|
"dependencies": {
|
|
29
|
-
"@humandialog/auth.svelte": "^1.
|
|
29
|
+
"@humandialog/auth.svelte": "^1.5.1",
|
|
30
30
|
"flowbite-svelte": "^0.29.13",
|
|
31
31
|
"svelte-icons": "^2.1.0",
|
|
32
32
|
"svelte-spa-router": "^3.3.0"
|
package/tenant.members.svelte
CHANGED
|
@@ -442,9 +442,9 @@
|
|
|
442
442
|
|
|
443
443
|
<ListComboProperty name='Privileges' a='auth_group' onSelect={on_change_privileges}>
|
|
444
444
|
<ComboItem name='None' key={0} />
|
|
445
|
-
<ComboItem name='Can
|
|
446
|
-
<ComboItem name='Can
|
|
447
|
-
<ComboItem name='
|
|
445
|
+
<ComboItem name='Can see' key={1} />
|
|
446
|
+
<ComboItem name='Can invite' key={3} />
|
|
447
|
+
<ComboItem name='Can fully manage' key={7} />
|
|
448
448
|
</ListComboProperty>
|
|
449
449
|
|
|
450
450
|
{#if showFiles}
|
package/utils.d.ts
CHANGED
|
@@ -9,6 +9,7 @@ export function editable(node: any, params: any): {
|
|
|
9
9
|
destroy(): void;
|
|
10
10
|
} | undefined;
|
|
11
11
|
export function startEditing(element: any, finish_callback: any): void;
|
|
12
|
+
export function saveCurrentEditable(): void;
|
|
12
13
|
export function selectable(node: any, itm: any): {
|
|
13
14
|
destroy(): void;
|
|
14
15
|
};
|
|
@@ -33,3 +34,4 @@ export namespace SCREEN_SIZES {
|
|
|
33
34
|
const lg: number;
|
|
34
35
|
const xl: number;
|
|
35
36
|
}
|
|
37
|
+
export let currentEditable: null;
|
package/utils.js
CHANGED
|
@@ -97,6 +97,8 @@ export function getActive(context_level)
|
|
|
97
97
|
return null;
|
|
98
98
|
}
|
|
99
99
|
|
|
100
|
+
export let currentEditable = null;
|
|
101
|
+
|
|
100
102
|
export function editable(node, params)
|
|
101
103
|
{
|
|
102
104
|
let action;
|
|
@@ -122,6 +124,9 @@ export function editable(node, params)
|
|
|
122
124
|
const org_text = node.textContent;
|
|
123
125
|
const blur_listener = async (e) =>
|
|
124
126
|
{
|
|
127
|
+
if(currentEditable == node)
|
|
128
|
+
currentEditable = null;
|
|
129
|
+
|
|
125
130
|
let cancel = !node.textContent
|
|
126
131
|
if(observer)
|
|
127
132
|
observer.disconnect();
|
|
@@ -170,6 +175,7 @@ export function editable(node, params)
|
|
|
170
175
|
{
|
|
171
176
|
node.removeEventListener("blur", blur_listener);
|
|
172
177
|
node.removeEventListener("keydown", key_listener);
|
|
178
|
+
node.removeEventListener("save", save_listener);
|
|
173
179
|
node.contentEditable = "false"
|
|
174
180
|
|
|
175
181
|
let sel = window.getSelection();
|
|
@@ -206,11 +212,20 @@ export function editable(node, params)
|
|
|
206
212
|
node.removeEventListener("finish", (e) => {});
|
|
207
213
|
}
|
|
208
214
|
|
|
215
|
+
const save_listener = async (e) =>
|
|
216
|
+
{
|
|
217
|
+
if(has_changed)
|
|
218
|
+
await action(node.textContent)
|
|
219
|
+
}
|
|
220
|
+
|
|
209
221
|
const edit_listener = async (e) =>
|
|
210
222
|
{
|
|
211
223
|
node.contentEditable = "true"
|
|
212
224
|
node.addEventListener("blur", blur_listener);
|
|
213
225
|
node.addEventListener("keydown", key_listener);
|
|
226
|
+
|
|
227
|
+
currentEditable = node;
|
|
228
|
+
node.addEventListener("save", save_listener)
|
|
214
229
|
|
|
215
230
|
node.focus();
|
|
216
231
|
|
|
@@ -235,6 +250,8 @@ export function editable(node, params)
|
|
|
235
250
|
node.addEventListener("blur", blur_listener);
|
|
236
251
|
node.addEventListener("keydown", key_listener);
|
|
237
252
|
has_changed = false;
|
|
253
|
+
currentEditable = node;
|
|
254
|
+
node.addEventListener("save", save_listener)
|
|
238
255
|
|
|
239
256
|
observer = new MutationObserver(() => { has_changed = true; });
|
|
240
257
|
observer.observe( node, {
|
|
@@ -298,6 +315,12 @@ export function startEditing(element, finish_callback)
|
|
|
298
315
|
}
|
|
299
316
|
}
|
|
300
317
|
|
|
318
|
+
export function saveCurrentEditable()
|
|
319
|
+
{
|
|
320
|
+
if(currentEditable)
|
|
321
|
+
currentEditable.dispatchEvent(new Event("save"))
|
|
322
|
+
}
|
|
323
|
+
|
|
301
324
|
export function selectable(node, itm)
|
|
302
325
|
{
|
|
303
326
|
const select_listener = (e) =>
|
package/vertical.toolbar.svelte
CHANGED
|
@@ -98,11 +98,18 @@
|
|
|
98
98
|
if(config.customOperations && Array.isArray(config.customOperations) && config.customOperations.length > 0)
|
|
99
99
|
{
|
|
100
100
|
config.customOperations.forEach( o => {
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
101
|
+
let add = true;
|
|
102
|
+
if(o.condition)
|
|
103
|
+
add = o.condition();
|
|
104
|
+
|
|
105
|
+
if(add)
|
|
106
|
+
{
|
|
107
|
+
options.push({
|
|
108
|
+
caption: o.caption,
|
|
109
|
+
icon: o.icon,
|
|
110
|
+
action: o.action
|
|
111
|
+
})
|
|
112
|
+
}
|
|
106
113
|
})
|
|
107
114
|
}
|
|
108
115
|
|