@soleil-se/config-svelte 1.3.0 → 1.4.0
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/CHANGELOG.md +20 -1
- package/actions/resizer.js +3 -3
- package/components/CheckboxGroup/Component.svelte +2 -8
- package/components/ImageSelector/Component.svelte +8 -1
- package/components/LinkSelector/api/getSavedValue.js +6 -8
- package/components/ListSelector/Component.svelte +2 -1
- package/components/TextList/Component.svelte +27 -175
- package/components/TextList/internal/Item.svelte +119 -0
- package/components/TextList/internal/Sortable.svelte +45 -33
- package/package.json +5 -5
- package/yarn-error.log +15395 -18
package/CHANGELOG.md
CHANGED
|
@@ -5,7 +5,26 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
-
## [1.
|
|
8
|
+
## [1.4.0] - 2021-05-19
|
|
9
|
+
|
|
10
|
+
## Changed
|
|
11
|
+
|
|
12
|
+
- TextList component rewrite.
|
|
13
|
+
- Remove CheckboxGroup value workaround as it's not needed.
|
|
14
|
+
|
|
15
|
+
## Fixed
|
|
16
|
+
|
|
17
|
+
- Type shorthand for ListSelector.
|
|
18
|
+
- Was possible to circumvent alt-text requirement in ImageSelector
|
|
19
|
+
|
|
20
|
+
## [1.3.1] - 2021-04-29
|
|
21
|
+
|
|
22
|
+
## Fixed
|
|
23
|
+
|
|
24
|
+
- Default value for LinkSelector type is not set.
|
|
25
|
+
- ImageSelector does not clear alt-text from image archive.
|
|
26
|
+
|
|
27
|
+
## [1.3.0] - 2021-04-28
|
|
9
28
|
|
|
10
29
|
## Added
|
|
11
30
|
|
package/actions/resizer.js
CHANGED
|
@@ -20,11 +20,11 @@ const resizer = (element) => {
|
|
|
20
20
|
const resizeElement = (e) => {
|
|
21
21
|
const offset = e.y - mousePos;
|
|
22
22
|
mousePos = e.y;
|
|
23
|
-
const targetHeight = parseInt(getComputedStyle(targetElement).height, 10);
|
|
24
|
-
const targetOffset = targetElement.getBoundingClientRect().top;
|
|
25
23
|
|
|
24
|
+
const targetOffset = targetElement.getBoundingClientRect().top;
|
|
26
25
|
if (e.y > (targetOffset + targetMinHeight)) {
|
|
27
|
-
|
|
26
|
+
const targetHeight = parseInt(getComputedStyle(targetElement).height, 10);
|
|
27
|
+
// eslint-disable-next-line no-param-reassign
|
|
28
28
|
targetElement.style.height = `${targetHeight + offset}px`;
|
|
29
29
|
}
|
|
30
30
|
};
|
|
@@ -37,6 +37,7 @@
|
|
|
37
37
|
bind:group={value}
|
|
38
38
|
class="sr-only"
|
|
39
39
|
value={option.value || option}
|
|
40
|
+
{name}
|
|
40
41
|
type="checkbox"
|
|
41
42
|
disabled={isDisabled(option)}
|
|
42
43
|
on:change={onChange}
|
|
@@ -51,14 +52,6 @@
|
|
|
51
52
|
</label>
|
|
52
53
|
{/each}
|
|
53
54
|
</fieldset>
|
|
54
|
-
<!-- Workaround to properly save values as array when using name -->
|
|
55
|
-
{#if name}
|
|
56
|
-
<select {value} multiple {name} class="sr-only" aria-hidden="true">
|
|
57
|
-
{#each value as option}
|
|
58
|
-
<option>{option}</option>
|
|
59
|
-
{/each}
|
|
60
|
-
</select>
|
|
61
|
-
{/if}
|
|
62
55
|
|
|
63
56
|
<style lang="scss">
|
|
64
57
|
fieldset {
|
|
@@ -111,4 +104,5 @@
|
|
|
111
104
|
input {
|
|
112
105
|
margin: -1px;
|
|
113
106
|
}
|
|
107
|
+
|
|
114
108
|
</style>
|
|
@@ -24,13 +24,18 @@
|
|
|
24
24
|
|
|
25
25
|
const dispatch = createEventDispatcher();
|
|
26
26
|
|
|
27
|
+
const setCustomValidity = () => {
|
|
28
|
+
validationEl?.setCustomValidity(imageArchiveAlt ? '' : 'Bilden saknar beskrivning (alt-text). Klicka på bilden ovan och skriv texten i fältet Bildbeskrivning.');
|
|
29
|
+
};
|
|
30
|
+
|
|
27
31
|
const onChange = async () => {
|
|
28
32
|
if (node) {
|
|
29
33
|
const response = await fetch(`/rest-api/1/1/${node}/properties`).then((res) => res.json());
|
|
30
34
|
imageArchiveAlt = response.alt || '';
|
|
31
35
|
|
|
32
|
-
|
|
36
|
+
setCustomValidity();
|
|
33
37
|
} else {
|
|
38
|
+
imageArchiveAlt = '';
|
|
34
39
|
validationEl?.setCustomValidity('');
|
|
35
40
|
}
|
|
36
41
|
triggerInput(validationEl);
|
|
@@ -45,6 +50,7 @@
|
|
|
45
50
|
} else {
|
|
46
51
|
customAlt = alt;
|
|
47
52
|
alt = undefined;
|
|
53
|
+
setCustomValidity();
|
|
48
54
|
}
|
|
49
55
|
};
|
|
50
56
|
|
|
@@ -75,4 +81,5 @@
|
|
|
75
81
|
div {
|
|
76
82
|
margin-top: -10px;
|
|
77
83
|
}
|
|
84
|
+
|
|
78
85
|
</style>
|
|
@@ -4,16 +4,14 @@ const getDefaultValue = (types) => ({
|
|
|
4
4
|
value: '',
|
|
5
5
|
});
|
|
6
6
|
|
|
7
|
-
export default function getSavedValue({ value, name, types }) {
|
|
7
|
+
export default function getSavedValue({ value = {}, name, types }) {
|
|
8
8
|
const values = window.CONFIG_VALUES || {};
|
|
9
9
|
|
|
10
|
+
const defaultValue = getDefaultValue(types);
|
|
11
|
+
|
|
10
12
|
return {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
type: values[`${name}Type`],
|
|
15
|
-
newWindow: values[`${name}NewWindow`],
|
|
16
|
-
value: values[`${name}Value`],
|
|
17
|
-
} : {}),
|
|
13
|
+
type: value.type || values[`${name}Type`] || defaultValue.type,
|
|
14
|
+
newWindow: value.newWindow || values[`${name}NewWindow`] || defaultValue.newWindow,
|
|
15
|
+
value: value.value || values[`${name}Value`] || defaultValue.value,
|
|
18
16
|
};
|
|
19
17
|
}
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
dispatch('change', value);
|
|
24
24
|
};
|
|
25
25
|
|
|
26
|
-
$: component = type.endsWith('-list') ? type : `${type}-
|
|
26
|
+
$: component = type.endsWith('-list') ? type : `${type}-list`;
|
|
27
27
|
|
|
28
28
|
onMount(() => {
|
|
29
29
|
const element = setupComponent(id)[0];
|
|
@@ -71,4 +71,5 @@
|
|
|
71
71
|
background-color: rgba(255, 255, 255, 0.3);
|
|
72
72
|
cursor: not-allowed;
|
|
73
73
|
}
|
|
74
|
+
|
|
74
75
|
</style>
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
<script>
|
|
2
|
-
import { createEventDispatcher
|
|
2
|
+
import { createEventDispatcher } from 'svelte';
|
|
3
3
|
import { generateId } from '../../utils';
|
|
4
4
|
import { resizer } from '../../actions';
|
|
5
5
|
import Sortable from './internal/Sortable.svelte';
|
|
6
|
+
import Item from './internal/Item.svelte';
|
|
6
7
|
import DataHolder from './internal/DataHolder.svelte';
|
|
7
8
|
|
|
8
9
|
const values = window.CONFIG_VALUES || {};
|
|
@@ -20,18 +21,14 @@
|
|
|
20
21
|
id: generateId(),
|
|
21
22
|
value: '',
|
|
22
23
|
edit: false,
|
|
23
|
-
focus: false,
|
|
24
|
-
hover: false,
|
|
25
24
|
...props,
|
|
26
25
|
});
|
|
27
26
|
|
|
28
27
|
let addButtonElement;
|
|
29
|
-
|
|
30
|
-
let dragging = false;
|
|
28
|
+
|
|
31
29
|
let items = value.map((val) => createItem({ value: val }));
|
|
32
30
|
|
|
33
|
-
$:
|
|
34
|
-
$: isEditing = editIndex > -1;
|
|
31
|
+
$: isEditing = items.findIndex(({ edit }) => edit) > -1;
|
|
35
32
|
|
|
36
33
|
const onChange = () => {
|
|
37
34
|
value = items.filter(({ edit }) => !edit).map((item) => item.value);
|
|
@@ -42,72 +39,29 @@
|
|
|
42
39
|
const addItem = async () => {
|
|
43
40
|
if (!isEditing) {
|
|
44
41
|
items = items.concat(createItem({ edit: true }));
|
|
45
|
-
await tick();
|
|
46
42
|
}
|
|
47
|
-
itemElements[editIndex].querySelector('input').focus();
|
|
48
|
-
};
|
|
49
|
-
|
|
50
|
-
const editItem = async (index) => {
|
|
51
|
-
items = items.map((item) => ({ ...item, edit: false }));
|
|
52
|
-
items[index].edit = true;
|
|
53
|
-
items[index].oldValue = items[index].value;
|
|
54
|
-
|
|
55
|
-
await tick();
|
|
56
|
-
itemElements[index].querySelector('input').focus();
|
|
57
43
|
};
|
|
58
44
|
|
|
59
|
-
const
|
|
60
|
-
items.
|
|
61
|
-
items = items;
|
|
62
|
-
onChange();
|
|
45
|
+
const onEdit = async ({ detail }) => {
|
|
46
|
+
items = items.map((item) => ({ ...item, edit: item.id === detail }));
|
|
63
47
|
};
|
|
64
48
|
|
|
65
|
-
const
|
|
66
|
-
items
|
|
67
|
-
delete items[index].oldValue;
|
|
68
|
-
|
|
69
|
-
if (!items[index].value) {
|
|
70
|
-
removeItem(index);
|
|
71
|
-
}
|
|
72
|
-
|
|
49
|
+
const onRemove = ({ detail }) => {
|
|
50
|
+
items = items.filter((item) => item.id !== detail);
|
|
73
51
|
onChange();
|
|
74
52
|
};
|
|
75
53
|
|
|
76
|
-
const
|
|
54
|
+
const onUpdate = ({ detail }) => {
|
|
55
|
+
const index = items.findIndex((item) => item.id === detail.id);
|
|
77
56
|
if (items[index]) {
|
|
78
|
-
items[index] =
|
|
79
|
-
|
|
80
|
-
...props,
|
|
81
|
-
};
|
|
82
|
-
}
|
|
83
|
-
};
|
|
84
|
-
|
|
85
|
-
const abortEdit = (index) => {
|
|
86
|
-
items[index].edit = false;
|
|
87
|
-
items[index].value = items[index].oldValue;
|
|
88
|
-
delete items[index].oldValue;
|
|
89
|
-
|
|
90
|
-
if (!items[index].value) {
|
|
91
|
-
removeItem(index);
|
|
92
|
-
}
|
|
93
|
-
};
|
|
94
|
-
|
|
95
|
-
const handleKeypress = (index, { keyCode }) => {
|
|
96
|
-
// Enter
|
|
97
|
-
if (keyCode === 13) {
|
|
98
|
-
saveEdit(index);
|
|
99
|
-
addButtonElement.focus();
|
|
100
|
-
}
|
|
101
|
-
// Esc
|
|
102
|
-
if (keyCode === 27) {
|
|
103
|
-
abortEdit(index);
|
|
104
|
-
addButtonElement.focus();
|
|
57
|
+
items[index].value = detail.value;
|
|
58
|
+
items[index].edit = false;
|
|
105
59
|
}
|
|
60
|
+
onChange();
|
|
106
61
|
};
|
|
107
62
|
|
|
108
|
-
const
|
|
63
|
+
const onFinalize = ({ detail }) => {
|
|
109
64
|
items = detail;
|
|
110
|
-
dragging = false;
|
|
111
65
|
onChange();
|
|
112
66
|
};
|
|
113
67
|
</script>
|
|
@@ -116,68 +70,14 @@
|
|
|
116
70
|
<label for={id} class="control-label {required ? 'control-label--required' : ''}">{label}</label>
|
|
117
71
|
<div class="list-component">
|
|
118
72
|
<div class="list-component__list-wrapper ui-resizable">
|
|
119
|
-
<Sortable
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
{#each items as item, index (item.id)}
|
|
128
|
-
<li
|
|
129
|
-
bind:this={itemElements[index]}
|
|
130
|
-
class="list-component__item"
|
|
131
|
-
class:focus={item.focus}
|
|
132
|
-
class:hover={item.hover}
|
|
133
|
-
on:mouseenter={() => updateItem(index, { hover: !dragging })}
|
|
134
|
-
on:mouseleave={() => updateItem(index, { hover: dragging })}
|
|
135
|
-
>
|
|
136
|
-
{#if item.edit}
|
|
137
|
-
<div class="form-group">
|
|
138
|
-
<div class="input-group">
|
|
139
|
-
<input
|
|
140
|
-
{id}
|
|
141
|
-
bind:value={item.value}
|
|
142
|
-
type="text"
|
|
143
|
-
class="form-control"
|
|
144
|
-
on:keypress={(e) => handleKeypress(index, e)}
|
|
145
|
-
/>
|
|
146
|
-
|
|
147
|
-
<span class="input-group-btn">
|
|
148
|
-
<button class="btn btn-default" type="button" on:click={() => saveEdit(index)}>
|
|
149
|
-
<i class="glyphicons ok-2" />
|
|
150
|
-
</button>
|
|
151
|
-
<button class="btn btn-default" type="button" on:click={() => abortEdit(index)}>
|
|
152
|
-
<i class="glyphicons remove-2" />
|
|
153
|
-
</button>
|
|
154
|
-
</span>
|
|
155
|
-
</div>
|
|
156
|
-
</div>
|
|
157
|
-
{:else}
|
|
158
|
-
<div on:dblclick={() => editItem(index)}>
|
|
159
|
-
<span class="item-name">{item.value}</span>
|
|
160
|
-
<div class="list-component__item-actions">
|
|
161
|
-
<button
|
|
162
|
-
on:click={() => editItem(index)}
|
|
163
|
-
on:focusin={() => updateItem(index, { focus: true })}
|
|
164
|
-
on:focusout={() => updateItem(index, { focus: false })}
|
|
165
|
-
>
|
|
166
|
-
<i class="glyphicons edit" />
|
|
167
|
-
</button>
|
|
168
|
-
<button
|
|
169
|
-
on:click={() => removeItem(index)}
|
|
170
|
-
on:focusin={() => updateItem(index, { focus: true })}
|
|
171
|
-
on:focusout={() => updateItem(index, { focus: false })}
|
|
172
|
-
>
|
|
173
|
-
<i class="glyphicons remove-2" />
|
|
174
|
-
</button>
|
|
175
|
-
<i class="glyphicons move" />
|
|
176
|
-
</div>
|
|
177
|
-
</div>
|
|
178
|
-
{/if}
|
|
179
|
-
</li>
|
|
180
|
-
{/each}
|
|
73
|
+
<Sortable {items} on:finalize={onFinalize} let:item>
|
|
74
|
+
<Item
|
|
75
|
+
{...item}
|
|
76
|
+
on:edit={onEdit}
|
|
77
|
+
on:remove={onRemove}
|
|
78
|
+
on:update={onUpdate}
|
|
79
|
+
on:enter={() => addButtonElement.focus()}
|
|
80
|
+
/>
|
|
181
81
|
</Sortable>
|
|
182
82
|
<div use:resizer class="ui-resizable-handle ui-resizable-s" />
|
|
183
83
|
</div>
|
|
@@ -186,7 +86,7 @@
|
|
|
186
86
|
class="list-component__add-item btn btn-link"
|
|
187
87
|
on:click={addItem}
|
|
188
88
|
>
|
|
189
|
-
<i class="glyphicons plus" />
|
|
89
|
+
<i class="glyphicons plus" aria-hidden="true" />
|
|
190
90
|
Lägg till...
|
|
191
91
|
</button>
|
|
192
92
|
</div>
|
|
@@ -196,58 +96,9 @@
|
|
|
196
96
|
<DataHolder {id} {name} {value} {required} />
|
|
197
97
|
</div>
|
|
198
98
|
|
|
199
|
-
<style lang="scss"
|
|
200
|
-
.list-
|
|
201
|
-
|
|
202
|
-
height: 120px;
|
|
203
|
-
min-height: 90px;
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
& &__item {
|
|
207
|
-
&:focus {
|
|
208
|
-
.glyphicons {
|
|
209
|
-
display: inline-block;
|
|
210
|
-
}
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
&:hover {
|
|
214
|
-
background-color: white;
|
|
215
|
-
|
|
216
|
-
.glyphicons {
|
|
217
|
-
display: none;
|
|
218
|
-
}
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
&.chosen,
|
|
222
|
-
&.focus,
|
|
223
|
-
&.hover {
|
|
224
|
-
background-color: #f5f5f5;
|
|
225
|
-
|
|
226
|
-
.glyphicons {
|
|
227
|
-
display: inline-block;
|
|
228
|
-
}
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
.dragging &:not(.chosen) {
|
|
232
|
-
&:hover {
|
|
233
|
-
background-color: white;
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
.glyphicons {
|
|
237
|
-
display: none;
|
|
238
|
-
}
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
&-actions {
|
|
242
|
-
button {
|
|
243
|
-
padding: 0;
|
|
244
|
-
background: none;
|
|
245
|
-
border: none;
|
|
246
|
-
-webkit-appearance: none;
|
|
247
|
-
appearance: none;
|
|
248
|
-
}
|
|
249
|
-
}
|
|
250
|
-
}
|
|
99
|
+
<style lang="scss">
|
|
100
|
+
.list-component__list-wrapper {
|
|
101
|
+
min-height: 120px;
|
|
251
102
|
}
|
|
252
103
|
|
|
253
104
|
.disabled-overlay {
|
|
@@ -259,4 +110,5 @@
|
|
|
259
110
|
background-color: rgba(255, 255, 255, 0.3);
|
|
260
111
|
cursor: not-allowed;
|
|
261
112
|
}
|
|
113
|
+
|
|
262
114
|
</style>
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
import { tick, createEventDispatcher, onMount } from 'svelte';
|
|
3
|
+
|
|
4
|
+
export let id;
|
|
5
|
+
export let value;
|
|
6
|
+
export let edit = false;
|
|
7
|
+
|
|
8
|
+
const dispatch = createEventDispatcher();
|
|
9
|
+
|
|
10
|
+
let oldValue;
|
|
11
|
+
let inputElement;
|
|
12
|
+
|
|
13
|
+
const editItem = async () => {
|
|
14
|
+
oldValue = value;
|
|
15
|
+
dispatch('edit', id);
|
|
16
|
+
await tick();
|
|
17
|
+
inputElement.focus();
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
const removeItem = () => {
|
|
21
|
+
dispatch('remove', id);
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
const updateItem = () => {
|
|
25
|
+
if (!value) {
|
|
26
|
+
removeItem();
|
|
27
|
+
} else {
|
|
28
|
+
dispatch('update', { id, value });
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
const abortEdit = () => {
|
|
33
|
+
value = oldValue;
|
|
34
|
+
dispatch('edit');
|
|
35
|
+
if (!value) {
|
|
36
|
+
removeItem();
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
const handleKeypress = ({ keyCode }) => {
|
|
41
|
+
// Enter
|
|
42
|
+
if (edit && keyCode === 13) {
|
|
43
|
+
updateItem();
|
|
44
|
+
dispatch('enter');
|
|
45
|
+
}
|
|
46
|
+
// Esc
|
|
47
|
+
if (edit && keyCode === 27) {
|
|
48
|
+
abortEdit();
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
onMount(() => {
|
|
53
|
+
if (edit) inputElement.focus();
|
|
54
|
+
});
|
|
55
|
+
</script>
|
|
56
|
+
|
|
57
|
+
{#if edit}
|
|
58
|
+
<div class="form-group">
|
|
59
|
+
<div class="input-group">
|
|
60
|
+
<input
|
|
61
|
+
{id}
|
|
62
|
+
bind:value
|
|
63
|
+
type="text"
|
|
64
|
+
class="form-control"
|
|
65
|
+
on:keypress={handleKeypress}
|
|
66
|
+
bind:this={inputElement}
|
|
67
|
+
/>
|
|
68
|
+
|
|
69
|
+
<span class="input-group-btn">
|
|
70
|
+
<button class="btn btn-default" type="button" on:click={updateItem}>
|
|
71
|
+
<i class="glyphicons ok-2" />
|
|
72
|
+
</button>
|
|
73
|
+
<button class="btn btn-default" type="button" on:click={abortEdit}>
|
|
74
|
+
<i class="glyphicons remove-2" />
|
|
75
|
+
</button>
|
|
76
|
+
</span>
|
|
77
|
+
</div>
|
|
78
|
+
</div>
|
|
79
|
+
{:else}
|
|
80
|
+
<div on:dblclick={editItem}>
|
|
81
|
+
<span class="item-name">{value}</span>
|
|
82
|
+
<div class="list-component__item-actions">
|
|
83
|
+
<button on:click={editItem}>
|
|
84
|
+
<i class="glyphicons edit" aria-hidden="true" />
|
|
85
|
+
</button>
|
|
86
|
+
<button on:click={removeItem}>
|
|
87
|
+
<i class="glyphicons remove-2" aria-hidden="true" />
|
|
88
|
+
</button>
|
|
89
|
+
<i class="glyphicons move" aria-hidden="true" />
|
|
90
|
+
</div>
|
|
91
|
+
</div>
|
|
92
|
+
{/if}
|
|
93
|
+
|
|
94
|
+
<style lang="scss">
|
|
95
|
+
button {
|
|
96
|
+
&:focus {
|
|
97
|
+
outline: none;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
&:focus-visible {
|
|
101
|
+
outline: 2px solid #66afe9;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
.list-component__item-actions {
|
|
106
|
+
button {
|
|
107
|
+
padding: 0;
|
|
108
|
+
background: none;
|
|
109
|
+
border: none;
|
|
110
|
+
-webkit-appearance: none;
|
|
111
|
+
appearance: none;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
:global(li:focus-within) & i {
|
|
115
|
+
display: inline-block;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
</style>
|
|
@@ -1,43 +1,55 @@
|
|
|
1
1
|
<script>
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
2
|
+
import { createEventDispatcher } from 'svelte';
|
|
3
|
+
import { dndzone } from 'svelte-dnd-action';
|
|
4
|
+
import { flip } from 'svelte/animate';
|
|
5
|
+
|
|
6
|
+
export let items;
|
|
4
7
|
|
|
5
8
|
const dispatch = createEventDispatcher();
|
|
6
9
|
|
|
7
|
-
|
|
10
|
+
$: dragDisabled = items.some(({ edit }) => edit);
|
|
8
11
|
|
|
9
|
-
|
|
12
|
+
const onConsider = (e) => {
|
|
13
|
+
items = e.detail.items;
|
|
14
|
+
};
|
|
10
15
|
|
|
11
|
-
|
|
12
|
-
dispatch('
|
|
13
|
-
}
|
|
16
|
+
const onFinalize = (e) => {
|
|
17
|
+
dispatch('finalize', e.detail.items);
|
|
18
|
+
};
|
|
14
19
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
async function onEnd({ oldIndex, newIndex }) {
|
|
20
|
-
const copy = [...items];
|
|
21
|
-
const [item] = copy.splice(oldIndex, 1);
|
|
22
|
-
copy.splice(newIndex, 0, item);
|
|
23
|
-
await tick();
|
|
24
|
-
dispatch('end', copy);
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
onMount(() => {
|
|
28
|
-
Sortable.create(element, {
|
|
29
|
-
ghostClass: 'ghost',
|
|
30
|
-
chosenClass: 'chosen',
|
|
31
|
-
dragClass: 'drag',
|
|
32
|
-
filter: '.form-group',
|
|
33
|
-
preventOnFilter: false,
|
|
34
|
-
onChoose,
|
|
35
|
-
onStart,
|
|
36
|
-
onEnd,
|
|
37
|
-
});
|
|
38
|
-
});
|
|
20
|
+
const transformDraggedElement = (el) => {
|
|
21
|
+
// eslint-disable-next-line no-param-reassign
|
|
22
|
+
el.style.backgroundColor = '#f5f5f5';
|
|
23
|
+
};
|
|
39
24
|
</script>
|
|
40
25
|
|
|
41
|
-
<ul
|
|
42
|
-
|
|
26
|
+
<ul
|
|
27
|
+
use:dndzone={{
|
|
28
|
+
items,
|
|
29
|
+
flipDurationMs: 100,
|
|
30
|
+
dropFromOthersDisabled: true,
|
|
31
|
+
transformDraggedElement,
|
|
32
|
+
dropTargetStyle: {},
|
|
33
|
+
autoAriaDisabled: true,
|
|
34
|
+
dragDisabled,
|
|
35
|
+
}}
|
|
36
|
+
on:consider={onConsider}
|
|
37
|
+
on:finalize={onFinalize}
|
|
38
|
+
class="list-component__list"
|
|
39
|
+
>
|
|
40
|
+
{#each items as item (item.id)}
|
|
41
|
+
<li class="list-component__item" animate:flip={{ duration: 100 }}>
|
|
42
|
+
<slot {item} />
|
|
43
|
+
</li>
|
|
44
|
+
{/each}
|
|
43
45
|
</ul>
|
|
46
|
+
|
|
47
|
+
<style>
|
|
48
|
+
ul:focus,
|
|
49
|
+
ul :global(li.focus-visible) {
|
|
50
|
+
position: relative;
|
|
51
|
+
z-index: 1;
|
|
52
|
+
outline: 2px solid #66afe9;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
</style>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@soleil-se/config-svelte",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.4.0",
|
|
4
4
|
"main": "./index.js",
|
|
5
5
|
"module": "./index.js",
|
|
6
6
|
"svelte": "./index.js",
|
|
@@ -8,14 +8,14 @@
|
|
|
8
8
|
"license": "UNLICENSED",
|
|
9
9
|
"sideEffects": false,
|
|
10
10
|
"peerDependencies": {
|
|
11
|
-
"svelte": "^3.
|
|
11
|
+
"svelte": "^3.38.2"
|
|
12
12
|
},
|
|
13
13
|
"devDependencies": {
|
|
14
|
-
"svelte": "^3.
|
|
14
|
+
"svelte": "^3.38.2"
|
|
15
15
|
},
|
|
16
16
|
"dependencies": {
|
|
17
|
-
"focus-visible": "^5.
|
|
18
|
-
"
|
|
17
|
+
"focus-visible": "^5.2.0",
|
|
18
|
+
"svelte-dnd-action": "^0.9.8"
|
|
19
19
|
},
|
|
20
20
|
"homepage": "https://docs.soleil.se/packages/config-svelte",
|
|
21
21
|
"description": "A collection of Svelte components and utilities for WebApp, RESTApp and Widget configurations.",
|