@soleil-se/config-svelte 1.0.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 +8 -0
- package/README.md +5 -0
- package/actions/httpPrefix.js +10 -0
- package/actions/index.js +3 -0
- package/actions/resizer.js +50 -0
- package/actions/show.js +12 -0
- package/components/Checkbox/Component.svelte +78 -0
- package/components/Checkbox/README.md +52 -0
- package/components/Checkbox/index.js +1 -0
- package/components/CheckboxGroup/Component.svelte +114 -0
- package/components/CheckboxGroup/README.md +89 -0
- package/components/CheckboxGroup/index.js +1 -0
- package/components/DropdownSelector/Component.svelte +82 -0
- package/components/DropdownSelector/README.md +75 -0
- package/components/DropdownSelector/index.js +1 -0
- package/components/InputField/Component.svelte +76 -0
- package/components/InputField/README.md +89 -0
- package/components/InputField/index.js +1 -0
- package/components/LinkSelector/Component.svelte +133 -0
- package/components/LinkSelector/README.md +93 -0
- package/components/LinkSelector/index.js +1 -0
- package/components/ListSelector/Component.svelte +72 -0
- package/components/ListSelector/README.md +96 -0
- package/components/ListSelector/index.js +1 -0
- package/components/NodeSelector/Component.svelte +81 -0
- package/components/NodeSelector/README.md +90 -0
- package/components/NodeSelector/index.js +1 -0
- package/components/NumberSpinner/Component.svelte +65 -0
- package/components/NumberSpinner/README.md +57 -0
- package/components/NumberSpinner/index.js +1 -0
- package/components/Panel/Component.svelte +33 -0
- package/components/Panel/README.md +25 -0
- package/components/Panel/index.js +1 -0
- package/components/RadioGroup/Component.svelte +105 -0
- package/components/RadioGroup/README.md +74 -0
- package/components/RadioGroup/index.js +1 -0
- package/components/SelectField/Component.svelte +37 -0
- package/components/SelectField/README.md +67 -0
- package/components/SelectField/index.js +1 -0
- package/components/TextList/Component.svelte +267 -0
- package/components/TextList/README.md +57 -0
- package/components/TextList/index.js +1 -0
- package/components/TextList/internal/Sortable.svelte +43 -0
- package/createConfigApp/index.js +17 -0
- package/index.js +16 -0
- package/package.json +29 -0
- package/server/createAppData/index.js +8 -0
- package/server/index.js +3 -0
- package/utils/addPrefix.js +8 -0
- package/utils/generateId.js +12 -0
- package/utils/index.js +5 -0
- package/utils/onSave.js +8 -0
- package/utils/pluckPrefix.js +21 -0
- package/utils/setupComponent.js +4 -0
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
import { createEventDispatcher, tick } from 'svelte';
|
|
3
|
+
import { generateId } from '../../utils';
|
|
4
|
+
import { resizer } from '../../actions';
|
|
5
|
+
import Sortable from './internal/Sortable.svelte';
|
|
6
|
+
|
|
7
|
+
const values = window.CONFIG_VALUES || {};
|
|
8
|
+
const dispatch = createEventDispatcher();
|
|
9
|
+
|
|
10
|
+
export let id = generateId();
|
|
11
|
+
export let label;
|
|
12
|
+
export let required = false;
|
|
13
|
+
export let name = undefined;
|
|
14
|
+
export let disabled = false;
|
|
15
|
+
export let value = [];
|
|
16
|
+
value = name ? values[name] ?? value : value;
|
|
17
|
+
|
|
18
|
+
const createItem = (props) => ({
|
|
19
|
+
id: generateId(),
|
|
20
|
+
value: '',
|
|
21
|
+
edit: false,
|
|
22
|
+
focus: false,
|
|
23
|
+
hover: false,
|
|
24
|
+
...props,
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
let addButtonElement;
|
|
28
|
+
const itemElements = [];
|
|
29
|
+
let dragging = false;
|
|
30
|
+
let items = value.map((val) => createItem({ value: val }));
|
|
31
|
+
|
|
32
|
+
$: editIndex = items.findIndex(({ edit }) => edit);
|
|
33
|
+
$: isEditing = editIndex > -1;
|
|
34
|
+
|
|
35
|
+
const onChange = () => {
|
|
36
|
+
value = items.filter(({ edit }) => !edit).map((item) => item.value);
|
|
37
|
+
dispatch('input', value);
|
|
38
|
+
dispatch('change', value);
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
const addItem = async () => {
|
|
42
|
+
if (!isEditing) {
|
|
43
|
+
items = items.concat(createItem({ edit: true }));
|
|
44
|
+
await tick();
|
|
45
|
+
}
|
|
46
|
+
itemElements[editIndex].querySelector('input').focus();
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
const editItem = async (index) => {
|
|
50
|
+
items = items.map((item) => ({ ...item, edit: false }));
|
|
51
|
+
items[index].edit = true;
|
|
52
|
+
items[index].oldValue = items[index].value;
|
|
53
|
+
|
|
54
|
+
await tick();
|
|
55
|
+
itemElements[index].querySelector('input').focus();
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
const removeItem = (index) => {
|
|
59
|
+
items.splice(index, 1);
|
|
60
|
+
items = items;
|
|
61
|
+
onChange();
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
const saveEdit = (index) => {
|
|
65
|
+
items[index].edit = false;
|
|
66
|
+
delete items[index].oldValue;
|
|
67
|
+
|
|
68
|
+
if (!items[index].value) {
|
|
69
|
+
removeItem(index);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
onChange();
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
const updateItem = (index, props) => {
|
|
76
|
+
items[index] = {
|
|
77
|
+
...items[index],
|
|
78
|
+
...props,
|
|
79
|
+
};
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
const abortEdit = (index) => {
|
|
83
|
+
items[index].edit = false;
|
|
84
|
+
items[index].value = items[index].oldValue;
|
|
85
|
+
delete items[index].oldValue;
|
|
86
|
+
|
|
87
|
+
if (!items[index].value) {
|
|
88
|
+
removeItem(index);
|
|
89
|
+
}
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
const handleKeypress = (index, { keyCode }) => {
|
|
93
|
+
// Enter
|
|
94
|
+
if (keyCode === 13) {
|
|
95
|
+
saveEdit(index);
|
|
96
|
+
addButtonElement.focus();
|
|
97
|
+
}
|
|
98
|
+
// Esc
|
|
99
|
+
if (keyCode === 27) {
|
|
100
|
+
abortEdit(index);
|
|
101
|
+
addButtonElement.focus();
|
|
102
|
+
}
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
const onSortEnd = ({ detail }) => {
|
|
106
|
+
items = detail;
|
|
107
|
+
dragging = false;
|
|
108
|
+
onChange();
|
|
109
|
+
};
|
|
110
|
+
</script>
|
|
111
|
+
|
|
112
|
+
<div class="form-group">
|
|
113
|
+
<label for={id} class="control-label {required ? 'control-label--required' : ''}">{label}</label>
|
|
114
|
+
<div class="list-component">
|
|
115
|
+
<div class="list-component__list-wrapper ui-resizable">
|
|
116
|
+
<Sortable
|
|
117
|
+
class="list-component__list {dragging ? 'dragging' : ''}"
|
|
118
|
+
{items}
|
|
119
|
+
on:start={() => {
|
|
120
|
+
dragging = true;
|
|
121
|
+
}}
|
|
122
|
+
on:end={onSortEnd}
|
|
123
|
+
>
|
|
124
|
+
{#each items as item, index (item.id)}
|
|
125
|
+
<li
|
|
126
|
+
bind:this={itemElements[index]}
|
|
127
|
+
class="list-component__item"
|
|
128
|
+
class:focus={item.focus}
|
|
129
|
+
class:hover={item.hover}
|
|
130
|
+
on:mouseenter={() => updateItem(index, { hover: !dragging })}
|
|
131
|
+
on:mouseleave={() => updateItem(index, { hover: dragging })}
|
|
132
|
+
>
|
|
133
|
+
{#if item.edit}
|
|
134
|
+
<div class="form-group">
|
|
135
|
+
<div class="input-group">
|
|
136
|
+
<input
|
|
137
|
+
{id}
|
|
138
|
+
bind:value={item.value}
|
|
139
|
+
type="text"
|
|
140
|
+
class="form-control"
|
|
141
|
+
on:keypress={(e) => handleKeypress(index, e)}
|
|
142
|
+
/>
|
|
143
|
+
|
|
144
|
+
<span class="input-group-btn">
|
|
145
|
+
<button class="btn btn-default" type="button" on:click={() => saveEdit(index)}>
|
|
146
|
+
<i class="glyphicons ok-2" />
|
|
147
|
+
</button>
|
|
148
|
+
<button class="btn btn-default" type="button" on:click={() => abortEdit(index)}>
|
|
149
|
+
<i class="glyphicons remove-2" />
|
|
150
|
+
</button>
|
|
151
|
+
</span>
|
|
152
|
+
</div>
|
|
153
|
+
</div>
|
|
154
|
+
{:else}
|
|
155
|
+
<div on:dblclick={() => editItem(index)}>
|
|
156
|
+
<span class="item-name">{item.value}</span>
|
|
157
|
+
<div class="list-component__item-actions">
|
|
158
|
+
<button
|
|
159
|
+
on:click={() => editItem(index)}
|
|
160
|
+
on:focusin={() => updateItem(index, { focus: true })}
|
|
161
|
+
on:focusout={() => updateItem(index, { focus: false })}
|
|
162
|
+
>
|
|
163
|
+
<i class="glyphicons edit" />
|
|
164
|
+
</button>
|
|
165
|
+
<button
|
|
166
|
+
on:click={() => removeItem(index)}
|
|
167
|
+
on:focusin={() => updateItem(index, { focus: true })}
|
|
168
|
+
on:focusout={() => updateItem(index, { focus: false })}
|
|
169
|
+
>
|
|
170
|
+
<i class="glyphicons remove-2" />
|
|
171
|
+
</button>
|
|
172
|
+
<i class="glyphicons move" />
|
|
173
|
+
</div>
|
|
174
|
+
</div>
|
|
175
|
+
{/if}
|
|
176
|
+
</li>
|
|
177
|
+
{/each}
|
|
178
|
+
</Sortable>
|
|
179
|
+
<div use:resizer class="ui-resizable-handle ui-resizable-s" />
|
|
180
|
+
</div>
|
|
181
|
+
<button
|
|
182
|
+
bind:this={addButtonElement}
|
|
183
|
+
class="list-component__add-item btn btn-link"
|
|
184
|
+
on:click={addItem}
|
|
185
|
+
>
|
|
186
|
+
<i class="glyphicons plus" />
|
|
187
|
+
Lägg till...
|
|
188
|
+
</button>
|
|
189
|
+
</div>
|
|
190
|
+
{#if disabled}
|
|
191
|
+
<div class="disabled-overlay" />
|
|
192
|
+
{/if}
|
|
193
|
+
<select {id} {value} multiple {name} class="sr-only" aria-hidden="true">
|
|
194
|
+
{#each value as option}
|
|
195
|
+
<option>{option}</option>
|
|
196
|
+
{/each}
|
|
197
|
+
</select>
|
|
198
|
+
</div>
|
|
199
|
+
|
|
200
|
+
<style lang="scss" global>
|
|
201
|
+
:global(html) {
|
|
202
|
+
overflow: hidden;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
.list-component {
|
|
206
|
+
& &__list-wrapper {
|
|
207
|
+
height: 120px;
|
|
208
|
+
min-height: 90px;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
& &__item {
|
|
212
|
+
&:focus {
|
|
213
|
+
.glyphicons {
|
|
214
|
+
display: inline-block;
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
&:hover {
|
|
219
|
+
background-color: white;
|
|
220
|
+
|
|
221
|
+
.glyphicons {
|
|
222
|
+
display: none;
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
&.chosen,
|
|
227
|
+
&.focus,
|
|
228
|
+
&.hover {
|
|
229
|
+
background-color: #f5f5f5;
|
|
230
|
+
|
|
231
|
+
.glyphicons {
|
|
232
|
+
display: inline-block;
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
.dragging &:not(.chosen) {
|
|
237
|
+
&:hover {
|
|
238
|
+
background-color: white;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
.glyphicons {
|
|
242
|
+
display: none;
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
&-actions {
|
|
247
|
+
button {
|
|
248
|
+
padding: 0;
|
|
249
|
+
background: none;
|
|
250
|
+
border: none;
|
|
251
|
+
-webkit-appearance: none;
|
|
252
|
+
appearance: none;
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
.disabled-overlay {
|
|
259
|
+
position: absolute;
|
|
260
|
+
top: 25px;
|
|
261
|
+
bottom: 0;
|
|
262
|
+
z-index: 90;
|
|
263
|
+
width: 100%;
|
|
264
|
+
background-color: rgba(255, 255, 255, 0.3);
|
|
265
|
+
cursor: not-allowed;
|
|
266
|
+
}
|
|
267
|
+
</style>
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# TextList
|
|
2
|
+
|
|
3
|
+
## Props
|
|
4
|
+
```javascript
|
|
5
|
+
export let id = generateId();
|
|
6
|
+
export let label;
|
|
7
|
+
export let required = false;
|
|
8
|
+
export let name = undefined;
|
|
9
|
+
export let disabled = false;
|
|
10
|
+
export let value = [];
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Default value
|
|
14
|
+
Use the value attribute to set a default value:
|
|
15
|
+
```svelte
|
|
16
|
+
<TextList
|
|
17
|
+
name="textList"
|
|
18
|
+
label="Text List"
|
|
19
|
+
value={['Text 1']}
|
|
20
|
+
/>
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Example
|
|
24
|
+
|
|
25
|
+
### Standard
|
|
26
|
+
```svelte
|
|
27
|
+
<script>
|
|
28
|
+
import { Panel, TextList } from '@soleil-se/svelte-config';
|
|
29
|
+
</script>
|
|
30
|
+
|
|
31
|
+
<Panel heading="Inställningar">
|
|
32
|
+
<TextList
|
|
33
|
+
name="textList"
|
|
34
|
+
label="Text List"
|
|
35
|
+
/>
|
|
36
|
+
</Panel>
|
|
37
|
+
```
|
|
38
|
+
### Advanced
|
|
39
|
+
|
|
40
|
+
```svelte
|
|
41
|
+
<script>
|
|
42
|
+
import { Panel, TextList } from '@soleil-se/svelte-config';
|
|
43
|
+
import { onSave } from '@soleil-se/svelte-config/utils';
|
|
44
|
+
|
|
45
|
+
const values = {
|
|
46
|
+
textList: '',
|
|
47
|
+
...window.CONFIG_VALUES
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
onSave(() => values);
|
|
51
|
+
|
|
52
|
+
</script>
|
|
53
|
+
|
|
54
|
+
<Panel heading="Inställningar">
|
|
55
|
+
<TextList bind:value={values.textList} label="Text List" />
|
|
56
|
+
</Panel>
|
|
57
|
+
```
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from './Component.svelte';
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
import { onMount, createEventDispatcher, tick } from 'svelte';
|
|
3
|
+
import { Sortable } from 'sortablejs';
|
|
4
|
+
|
|
5
|
+
const dispatch = createEventDispatcher();
|
|
6
|
+
|
|
7
|
+
export let items = [];
|
|
8
|
+
|
|
9
|
+
let element;
|
|
10
|
+
|
|
11
|
+
function onChoose({ oldIndex }) {
|
|
12
|
+
dispatch('choose', oldIndex);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function onStart() {
|
|
16
|
+
dispatch('start', items);
|
|
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
|
+
});
|
|
39
|
+
</script>
|
|
40
|
+
|
|
41
|
+
<ul bind:this={element} class={$$props.class}>
|
|
42
|
+
<slot />
|
|
43
|
+
</ul>
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import 'focus-visible';
|
|
2
|
+
|
|
3
|
+
export default function createConfigApp(App, { hydrate = true } = {}) {
|
|
4
|
+
window.setValues = (values) => {
|
|
5
|
+
window.CONFIG_VALUES = values;
|
|
6
|
+
const app = new App({
|
|
7
|
+
target: document.querySelector('#app_root, body'),
|
|
8
|
+
props: {
|
|
9
|
+
...window.CONFIG_APP_DATA,
|
|
10
|
+
values,
|
|
11
|
+
},
|
|
12
|
+
hydrate,
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
return app;
|
|
16
|
+
};
|
|
17
|
+
}
|
package/index.js
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export { default as Panel } from './components/Panel';
|
|
2
|
+
export { default as Checkbox } from './components/Checkbox';
|
|
3
|
+
export { default as CheckboxGroup } from './components/CheckboxGroup';
|
|
4
|
+
export { default as DropdownSelector } from './components/DropdownSelector';
|
|
5
|
+
export { default as InputField } from './components/InputField';
|
|
6
|
+
export { default as LinkSelector } from './components/LinkSelector';
|
|
7
|
+
export { default as ListSelector } from './components/ListSelector';
|
|
8
|
+
export { default as NodeSelector } from './components/NodeSelector';
|
|
9
|
+
export { default as NumberSpinner } from './components/NumberSpinner';
|
|
10
|
+
export { default as RadioGroup } from './components/RadioGroup';
|
|
11
|
+
export { default as SelectField } from './components/SelectField';
|
|
12
|
+
export { default as TextList } from './components/TextList';
|
|
13
|
+
|
|
14
|
+
export { default as createConfigApp } from './createConfigApp';
|
|
15
|
+
|
|
16
|
+
export { generateId, onSave, setupComponent } from './utils';
|
package/package.json
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@soleil-se/config-svelte",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"main": "./index.js",
|
|
5
|
+
"module": "./index.js",
|
|
6
|
+
"svelte": "./index.js",
|
|
7
|
+
"author": "Soleil AB",
|
|
8
|
+
"license": "UNLICENSED",
|
|
9
|
+
"sideEffects": false,
|
|
10
|
+
"peerDependencies": {
|
|
11
|
+
"svelte": "^3.26.0"
|
|
12
|
+
},
|
|
13
|
+
"devDependencies": {
|
|
14
|
+
"svelte": "^3.26.0"
|
|
15
|
+
},
|
|
16
|
+
"dependencies": {
|
|
17
|
+
"focus-visible": "^5.1.0",
|
|
18
|
+
"sortablejs": "^1.12.0"
|
|
19
|
+
},
|
|
20
|
+
"homepage": "https://docs.soleil.se/packages/config-svelte",
|
|
21
|
+
"description": "A collection of Svelte components and utilities for WebApp, RESTApp and Widget configurations.",
|
|
22
|
+
"keywords": [
|
|
23
|
+
"Sitevision",
|
|
24
|
+
"WebApp",
|
|
25
|
+
"RESTApp",
|
|
26
|
+
"Widget",
|
|
27
|
+
"Svelte"
|
|
28
|
+
]
|
|
29
|
+
}
|
package/server/index.js
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
const capitalizeFirstLetter = (string) => string.charAt(0).toUpperCase() + string.slice(1);
|
|
2
|
+
|
|
3
|
+
export default function addPrefix(prefix, value) {
|
|
4
|
+
return Object.entries(value).reduce((obj, [key, val]) => ({
|
|
5
|
+
...obj,
|
|
6
|
+
[prefix + capitalizeFirstLetter(key)]: val,
|
|
7
|
+
}), {});
|
|
8
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
const generated = [];
|
|
2
|
+
|
|
3
|
+
const generate = () => Math.random().toString(36).substr(2, 9);
|
|
4
|
+
|
|
5
|
+
export default function generateId(prefix = 'input') {
|
|
6
|
+
const id = `${prefix}_${generate()}`;
|
|
7
|
+
if (generated.includes(id)) {
|
|
8
|
+
return generateId(prefix);
|
|
9
|
+
}
|
|
10
|
+
generated.push(id);
|
|
11
|
+
return id;
|
|
12
|
+
}
|
package/utils/index.js
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { default as generateId } from './generateId';
|
|
2
|
+
export { default as onSave } from './onSave';
|
|
3
|
+
export { default as setupComponent } from './setupComponent';
|
|
4
|
+
export { default as addPrefix } from './addPrefix';
|
|
5
|
+
export { default as pluckPrefix } from './pluckPrefix';
|
package/utils/onSave.js
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
const lowerFirstLetter = (string) => string.charAt(0).toLowerCase() + string.slice(1);
|
|
2
|
+
/**
|
|
3
|
+
* Plucks object properties with prefixed keys, removes the prefix and returns an object with
|
|
4
|
+
* the properties that was prefixed.
|
|
5
|
+
* @export
|
|
6
|
+
* @param {String} prefix A prefix.
|
|
7
|
+
* @param {Object} [values=window.CONFIG_VALUES] Object with values.
|
|
8
|
+
* @returns {Object} An object with plucked properties where prefix is removed from keys.
|
|
9
|
+
*/
|
|
10
|
+
export default function pluckPrefix(prefix, values = window.CONFIG_VALUES) {
|
|
11
|
+
return Object.entries(values).reduce((obj, [key, value]) => {
|
|
12
|
+
if (key.startsWith(prefix)) {
|
|
13
|
+
const newKey = lowerFirstLetter(key.replace(prefix, ''));
|
|
14
|
+
return {
|
|
15
|
+
...obj,
|
|
16
|
+
[newKey]: value,
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
return obj;
|
|
20
|
+
}, {});
|
|
21
|
+
}
|