@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.
Files changed (54) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/README.md +5 -0
  3. package/actions/httpPrefix.js +10 -0
  4. package/actions/index.js +3 -0
  5. package/actions/resizer.js +50 -0
  6. package/actions/show.js +12 -0
  7. package/components/Checkbox/Component.svelte +78 -0
  8. package/components/Checkbox/README.md +52 -0
  9. package/components/Checkbox/index.js +1 -0
  10. package/components/CheckboxGroup/Component.svelte +114 -0
  11. package/components/CheckboxGroup/README.md +89 -0
  12. package/components/CheckboxGroup/index.js +1 -0
  13. package/components/DropdownSelector/Component.svelte +82 -0
  14. package/components/DropdownSelector/README.md +75 -0
  15. package/components/DropdownSelector/index.js +1 -0
  16. package/components/InputField/Component.svelte +76 -0
  17. package/components/InputField/README.md +89 -0
  18. package/components/InputField/index.js +1 -0
  19. package/components/LinkSelector/Component.svelte +133 -0
  20. package/components/LinkSelector/README.md +93 -0
  21. package/components/LinkSelector/index.js +1 -0
  22. package/components/ListSelector/Component.svelte +72 -0
  23. package/components/ListSelector/README.md +96 -0
  24. package/components/ListSelector/index.js +1 -0
  25. package/components/NodeSelector/Component.svelte +81 -0
  26. package/components/NodeSelector/README.md +90 -0
  27. package/components/NodeSelector/index.js +1 -0
  28. package/components/NumberSpinner/Component.svelte +65 -0
  29. package/components/NumberSpinner/README.md +57 -0
  30. package/components/NumberSpinner/index.js +1 -0
  31. package/components/Panel/Component.svelte +33 -0
  32. package/components/Panel/README.md +25 -0
  33. package/components/Panel/index.js +1 -0
  34. package/components/RadioGroup/Component.svelte +105 -0
  35. package/components/RadioGroup/README.md +74 -0
  36. package/components/RadioGroup/index.js +1 -0
  37. package/components/SelectField/Component.svelte +37 -0
  38. package/components/SelectField/README.md +67 -0
  39. package/components/SelectField/index.js +1 -0
  40. package/components/TextList/Component.svelte +267 -0
  41. package/components/TextList/README.md +57 -0
  42. package/components/TextList/index.js +1 -0
  43. package/components/TextList/internal/Sortable.svelte +43 -0
  44. package/createConfigApp/index.js +17 -0
  45. package/index.js +16 -0
  46. package/package.json +29 -0
  47. package/server/createAppData/index.js +8 -0
  48. package/server/index.js +3 -0
  49. package/utils/addPrefix.js +8 -0
  50. package/utils/generateId.js +12 -0
  51. package/utils/index.js +5 -0
  52. package/utils/onSave.js +8 -0
  53. package/utils/pluckPrefix.js +21 -0
  54. package/utils/setupComponent.js +4 -0
package/CHANGELOG.md ADDED
@@ -0,0 +1,8 @@
1
+ # Changelog
2
+ All notable changes to this project will be documented in this file.
3
+
4
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
5
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
+
7
+ ## [1.0.0] - 2020-11-20
8
+ - Initial release!
package/README.md ADDED
@@ -0,0 +1,5 @@
1
+ # @soleil-se/config-svelte
2
+
3
+ A collection of Svelte components and utilities for WebApp, RESTApp and Widget configurations.
4
+
5
+ [Documentation](https://docs.soleil.se/packages/config-svelte) | [Changelog](https://docs.soleil.se/packages/config-svelte/changelog)
@@ -0,0 +1,10 @@
1
+ export default function httpPrefix(node) {
2
+ const addPrefix = () => {
3
+ const { type, value } = node;
4
+ if (type === 'url' && value && !/^(https?):\/\//i.test(value) && ('http://'.indexOf(value) === -1 && 'https://'.indexOf(value) === -1)) {
5
+ /* eslint-disable-next-line no-param-reassign */
6
+ node.value = `https://${value}`;
7
+ }
8
+ };
9
+ node.addEventListener('input', addPrefix);
10
+ }
@@ -0,0 +1,3 @@
1
+ export { default as httpPrefix } from './httpPrefix';
2
+ export { default as resizer } from './resizer';
3
+ export { default as show } from './show';
@@ -0,0 +1,50 @@
1
+ const resizer = (element) => {
2
+ const targetElement = element.parentNode;
3
+
4
+ let mousePos;
5
+ const targetMinHeight = parseInt(window
6
+ .getComputedStyle(targetElement)
7
+ .getPropertyValue('min-height')
8
+ .replace('px', ''), 10);
9
+
10
+ const disableScrolling = () => {
11
+ const x = window.scrollX;
12
+ const y = window.scrollY;
13
+ window.onscroll = () => { window.scrollTo(x, y); };
14
+ };
15
+
16
+ const enableScrolling = () => {
17
+ window.onscroll = () => {};
18
+ };
19
+
20
+ const resizeElement = (e) => {
21
+ const offset = e.y - mousePos;
22
+ mousePos = e.y;
23
+ const targetHeight = parseInt(getComputedStyle(targetElement).height, 10);
24
+ const targetOffset = targetElement.getBoundingClientRect().top;
25
+
26
+ if (e.y > (targetOffset + targetMinHeight)) {
27
+ // eslint-disable-next-line no-param-reassign
28
+ targetElement.style.height = `${targetHeight + offset}px`;
29
+ }
30
+ };
31
+
32
+ const stopResize = (e) => {
33
+ e.preventDefault();
34
+ enableScrolling();
35
+ window.removeEventListener('mousemove', resizeElement, false);
36
+ window.removeEventListener('mouseup', stopResize, false);
37
+ };
38
+
39
+ const startResize = (e) => {
40
+ e.preventDefault();
41
+ disableScrolling();
42
+ mousePos = e.y;
43
+ window.addEventListener('mousemove', resizeElement, false);
44
+ window.addEventListener('mouseup', stopResize, false);
45
+ };
46
+
47
+ element.addEventListener('mousedown', startResize, false);
48
+ };
49
+
50
+ export default resizer;
@@ -0,0 +1,12 @@
1
+ export default function show(element, initialShow) {
2
+ const toggle = (isVisible) => {
3
+ /* eslint-disable-next-line no-param-reassign */
4
+ element.style.display = isVisible ? 'block' : 'none';
5
+ };
6
+ toggle(initialShow);
7
+ return {
8
+ update(updatedShow) {
9
+ toggle(updatedShow);
10
+ },
11
+ };
12
+ }
@@ -0,0 +1,78 @@
1
+ <script>
2
+ import { createEventDispatcher } from 'svelte';
3
+ import { generateId } from '../../utils';
4
+
5
+ const values = window.CONFIG_VALUES || {};
6
+ const dispatch = createEventDispatcher();
7
+
8
+ export let id = generateId();
9
+ export let label;
10
+ export let name;
11
+ export let disabled = false;
12
+ export let checked = false;
13
+ export let value;
14
+ value = name ? values[name] ?? value ?? checked : value;
15
+
16
+ let className = '';
17
+ export { className as class };
18
+
19
+ const onChange = () => {
20
+ dispatch('input', value);
21
+ dispatch('change', value);
22
+ };
23
+ </script>
24
+
25
+ <div class="form-group {className}">
26
+ <input
27
+ bind:checked={value}
28
+ {name}
29
+ {id}
30
+ {disabled}
31
+ class="sr-only"
32
+ type="checkbox"
33
+ data-value-type="boolean"
34
+ on:change={onChange}
35
+ />
36
+ <label for={id} class="checkbox-inline" class:disabled> {label} </label>
37
+ </div>
38
+
39
+ <style lang="scss">
40
+ label {
41
+ position: relative;
42
+ padding-left: 0;
43
+
44
+ &::before {
45
+ position: relative;
46
+ top: 2px;
47
+ float: left;
48
+ width: 16px;
49
+ height: 16px;
50
+ margin-right: 5px;
51
+ border: 1px solid #cacece;
52
+ border-radius: 3px;
53
+ content: '';
54
+ }
55
+
56
+ :global(.focus-visible) + &::before {
57
+ box-shadow: 0 0 0 0.2rem rgba(66, 139, 202, 0.4);
58
+ }
59
+
60
+ input:checked + &::before {
61
+ background-color: #428bca;
62
+ background-image: url('data:image/svg+xml, %3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20fill%3D%22white%22%20width%3D%2224%22%20height%3D%2224%22%20viewBox%3D%220%200%2024%2024%22%3E%3Cpath%20d%3D%22M20.285%202l-11.285%2011.567-5.286-5.011-3.714%203.716%209%208.728%2015-15.285z%22%20%2F%3E%3C%2Fsvg%3E');
63
+ background-repeat: no-repeat;
64
+ background-position: 50%;
65
+ background-size: 10px;
66
+ border-color: transparent;
67
+ }
68
+
69
+ &.disabled {
70
+ cursor: not-allowed;
71
+ opacity: 0.7;
72
+ }
73
+ }
74
+
75
+ input {
76
+ margin: -1px;
77
+ }
78
+ </style>
@@ -0,0 +1,52 @@
1
+ # Checkbox
2
+
3
+ ## Props
4
+
5
+ ```javascript
6
+ export let id = generateId();
7
+ export let label;
8
+ export let name;
9
+ export let disabled = false;
10
+ export let checked = false;
11
+ export let value;
12
+ ```
13
+
14
+ ## Default value
15
+ Use checked attribute if the checkbox should be checked as default
16
+ ```svelte
17
+ <Checkbox name="checkbox" label="Checkbox" checked />
18
+ ```
19
+ ## Examples
20
+
21
+ ### Standard
22
+
23
+ ```svelte
24
+ <script>
25
+ import { Panel, Checkbox } from '@soleil-se/svelte-config';
26
+ </script>
27
+
28
+ <Panel heading="Inställningar">
29
+ <Checkbox name="checkbox" label="Checkbox" />
30
+ </Panel>
31
+ ```
32
+
33
+ ### Advanced
34
+
35
+ ```svelte
36
+ <script>
37
+ import { Panel, Checkbox } from '@soleil-se/svelte-config';
38
+ import { onSave } from '@soleil-se/svelte-config/utils';
39
+
40
+ const values = {
41
+ checkbox: '',
42
+ ...window.CONFIG_VALUES
43
+ };
44
+
45
+ onSave(() => values);
46
+
47
+ </script>
48
+
49
+ <Panel heading="Inställningar">
50
+ <Checkbox bind:value={values.checkbox} label="Checkbox" />
51
+ </Panel>
52
+ ```
@@ -0,0 +1 @@
1
+ export { default } from './Component.svelte';
@@ -0,0 +1,114 @@
1
+ <script>
2
+ import { createEventDispatcher } from 'svelte';
3
+ import { generateId } from '../../utils';
4
+
5
+ const values = window.CONFIG_VALUES || {};
6
+ const dispatch = createEventDispatcher();
7
+
8
+ export let id = generateId();
9
+ export let name;
10
+ export let options;
11
+ export let legend;
12
+ export let disabled = false;
13
+ export let value = [];
14
+ value = name ? values[name] || value : value;
15
+
16
+ let className = '';
17
+ export { className as class };
18
+
19
+ $: isChecked = (option) => value.includes(option.value || option);
20
+
21
+ $: isDisabled = (option) => {
22
+ if (Array.isArray(disabled)) return disabled.includes(option.value || option);
23
+ return disabled;
24
+ };
25
+
26
+ const onChange = () => {
27
+ dispatch('input', value);
28
+ dispatch('change', value);
29
+ };
30
+ </script>
31
+
32
+ <fieldset class="form-group {className}">
33
+ <legend>{legend}</legend>
34
+ {#each options as option, index}
35
+ <input
36
+ id={`${id}_${index}`}
37
+ bind:group={value}
38
+ class="sr-only"
39
+ value={option.value || option}
40
+ type="checkbox"
41
+ disabled={isDisabled(option)}
42
+ on:change={onChange}
43
+ />
44
+ <label
45
+ for={`${id}_${index}`}
46
+ class="checkbox-inline"
47
+ class:disabled={isDisabled(option)}
48
+ class:checked={isChecked(option)}
49
+ >
50
+ {option.label || option}
51
+ </label>
52
+ {/each}
53
+ </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
+
63
+ <style lang="scss">
64
+ fieldset {
65
+ margin-top: 0;
66
+ }
67
+
68
+ legend {
69
+ margin-bottom: 7px;
70
+ font-weight: bold;
71
+ font-size: 14px;
72
+ border-bottom: 0;
73
+ }
74
+
75
+ label {
76
+ position: relative;
77
+ padding-right: 5px;
78
+ padding-left: 0;
79
+
80
+ &::before {
81
+ position: relative;
82
+ top: 2px;
83
+ float: left;
84
+ width: 16px;
85
+ height: 16px;
86
+ margin-right: 5px;
87
+ border: 1px solid #cacece;
88
+ border-radius: 3px;
89
+ content: '';
90
+ }
91
+
92
+ :global(.focus-visible) + &::before {
93
+ box-shadow: 0 0 0 0.2rem rgba(66, 139, 202, 0.4);
94
+ }
95
+
96
+ input:checked + &::before {
97
+ background-color: #428bca;
98
+ background-image: url('data:image/svg+xml, %3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20fill%3D%22white%22%20width%3D%2224%22%20height%3D%2224%22%20viewBox%3D%220%200%2024%2024%22%3E%3Cpath%20d%3D%22M20.285%202l-11.285%2011.567-5.286-5.011-3.714%203.716%209%208.728%2015-15.285z%22%20%2F%3E%3C%2Fsvg%3E');
99
+ background-repeat: no-repeat;
100
+ background-position: 50%;
101
+ background-size: 10px;
102
+ border-color: transparent;
103
+ }
104
+
105
+ &.disabled {
106
+ cursor: not-allowed;
107
+ opacity: 0.7;
108
+ }
109
+ }
110
+
111
+ input {
112
+ margin: -1px;
113
+ }
114
+ </style>
@@ -0,0 +1,89 @@
1
+ # CheckboxGroup
2
+
3
+ ## Props
4
+ ```javascript
5
+ // ID, generates automatically if nothing is passed
6
+ export let id = generateId();
7
+ // If SiteVision default functions for getting and setting config is used name must be set
8
+ export let name;
9
+ // Array of options, ['value1', 'value2'] or [{ label: 'Value 1', value: 'value1' }, { label: 'Value 2', value: 'value2' }].
10
+ export let options;
11
+ // Fieldset legend
12
+ export let legend;
13
+ // Disable input, or provide an array of disabled options: ['value1'].
14
+ export let disabled = false;
15
+ // Used if bound to value.
16
+ export let value;
17
+ ```
18
+
19
+ ## Default value
20
+ Use the value prop to set a default value when not binding the value:
21
+ ```svelte
22
+ <CheckboxGroup
23
+ name="checkboxGroup1"
24
+ legend="Checkboxgrupp 1"
25
+ options={['Värde 1', 'Värde 2', 'Värde 3']}
26
+ value="{['Värde 2', 'Värde 3']}"
27
+ />
28
+ ```
29
+
30
+ ## Example
31
+
32
+ ### Standard
33
+ ```svelte
34
+ <script>
35
+ import { Panel, CheckboxGroup } from '@soleil-se/svelte-config';
36
+ </script>
37
+
38
+ <Panel heading="Inställningar">
39
+ <CheckboxGroup
40
+ name="checkboxGroup1"
41
+ legend="Checkboxgrupp 1"
42
+ options={['Värde 1', 'Värde 2', 'Värde 3']}
43
+ />
44
+ <CheckboxGroup
45
+ name="checkboxGroup2"
46
+ legend="Checkboxgrupp 2"
47
+ options={[
48
+ { label: 'Värde 1', value: 'value1'},
49
+ { label: 'Värde 2', value: 'value2'},
50
+ { label: 'Värde 3', value: 'value3'},
51
+ ]}
52
+ />
53
+ </Panel>
54
+
55
+ ```
56
+
57
+ ### Advanced
58
+ ```svelte
59
+ <script>
60
+ import { Panel, CheckboxGroup } from '@soleil-se/svelte-config';
61
+ import { onSave } from '@soleil-se/svelte-config/utils';
62
+
63
+ const values = {
64
+ checkboxGroup1: [],
65
+ checkboxGroup2: [],
66
+ ...window.CONFIG_VALUES
67
+ };
68
+
69
+ onSave(() => values);
70
+
71
+ </script>
72
+
73
+ <Panel heading="Inställningar">
74
+ <CheckboxGroup
75
+ bind:value={values.checkboxGroup1}
76
+ legend="Checkboxgrupp 1"
77
+ options={['Värde 1', 'Värde 2', 'Värde 3']}
78
+ />
79
+ <CheckboxGroup
80
+ bind:value={values.checkboxGroup2}
81
+ legend="Checkboxgrupp 2"
82
+ options={[
83
+ { label: 'Värde 1', value: 'value1'},
84
+ { label: 'Värde 2', value: 'value2'},
85
+ { label: 'Värde 3', value: 'value3'},
86
+ ]}
87
+ />
88
+ </Panel>
89
+ ```
@@ -0,0 +1 @@
1
+ export { default } from './Component.svelte';
@@ -0,0 +1,82 @@
1
+ <script>
2
+ import { createEventDispatcher, onMount } from 'svelte';
3
+ import { generateId, setupComponent } from '../../utils';
4
+
5
+ const values = window.CONFIG_VALUES || {};
6
+ const dispatch = createEventDispatcher();
7
+
8
+ export let id = generateId();
9
+ export let label;
10
+ export let name = undefined;
11
+ export let type;
12
+ export let selectable = [];
13
+ export let required = false;
14
+ export let disabled = false;
15
+ export let value = '';
16
+ value = name ? values[name] ?? value : value;
17
+
18
+ let className = '';
19
+ export { className as class };
20
+
21
+ let hidden = true;
22
+
23
+ onMount(() => {
24
+ setupComponent(id)
25
+ .on('change', (e) => {
26
+ value = e.val || value;
27
+ dispatch('input', value);
28
+ dispatch('change', value);
29
+ })
30
+ .on('sv:loaded', ({ target }) => {
31
+ hidden = false;
32
+ jQuery(target)
33
+ .val(value)
34
+ .trigger('change');
35
+ });
36
+ });
37
+ </script>
38
+
39
+ <div class="form-group {className}" {hidden}>
40
+ <label for={id} class="control-label {required ? 'control-label--required' : ''}">{label}</label>
41
+ <select
42
+ {id}
43
+ {name}
44
+ {required}
45
+ {disabled}
46
+ data-component={type}
47
+ data-removable
48
+ data-types={[...selectable].join(',')}
49
+ />
50
+ <slot />
51
+ </div>
52
+
53
+ <style global>
54
+ .select2-container .select2-choice {
55
+ height: 34px;
56
+ padding-left: 12px;
57
+ line-height: 32px;
58
+ border: 1px solid #ccc;
59
+ box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
60
+ }
61
+
62
+ .select2-container .select2-choice .select2-arrow b {
63
+ background-position-y: 3px;
64
+ }
65
+
66
+ .select2-container .select2-choice abbr {
67
+ top: 9px;
68
+ }
69
+
70
+ .select2-container.select2-container-disabled .select2-choice {
71
+ background-color: white;
72
+ background-image: none;
73
+ border: 1px solid #ccc;
74
+ cursor: not-allowed;
75
+ opacity: 0.7;
76
+ }
77
+
78
+ .select2-container.select2-container-disabed .select2-choice .select2-arrow {
79
+ background-color: white;
80
+ border-left: 1px solid #aaa;
81
+ }
82
+ </style>
@@ -0,0 +1,75 @@
1
+ # DropdownSelector
2
+
3
+ <!-- TOC -->
4
+
5
+ - [Props](#props)
6
+ - [Example](#example)
7
+ - [Standard](#standard)
8
+ - [Advanced](#advanced)
9
+ - [Selectable types](#selectable-types)
10
+
11
+ <!-- /TOC -->
12
+
13
+ ## Props
14
+
15
+ ```javascript
16
+ export let id = generateId();
17
+ export let label; // Required
18
+ export let name = undefined;
19
+ export let type; // Required
20
+ export let selectable = [];
21
+ export let required = false;
22
+ export let disabled = false;
23
+ export let value = '';
24
+ ```
25
+
26
+ ## Example
27
+
28
+ ### Standard
29
+ ```svelte
30
+ <script>
31
+ import { Panel, DropdownSelector } from '@soleil-se/svelte-config';
32
+ </script>
33
+
34
+ <Panel heading="Inställningar">
35
+ <DropdownSelector name="metadata" type="metadata-selector" label="Metadata" />
36
+ </Panel>
37
+ ```
38
+
39
+ ### Advanced
40
+
41
+ ```svelte
42
+ <script>
43
+ import { Panel, DropdownSelector } from '@soleil-se/svelte-config';
44
+ import { onSave } from '@soleil-se/svelte-config/utils';
45
+
46
+ const values = {
47
+ metadata: '',
48
+ ...window.CONFIG_VALUES
49
+ };
50
+
51
+ onSave(() => values);
52
+
53
+ </script>
54
+
55
+ <Panel heading="Inställningar">
56
+ <DropdownSelector bind:value={values.metadata} type="metadata-selector" label="Metadata" />
57
+ </Panel>
58
+ ```
59
+
60
+ ## Selectable types
61
+ > :exclamation: Since SiteVision 7.0 :exclamation:
62
+
63
+ Filter what types should be selectable. See available types here:
64
+ https://developer.sitevision.se/docs/webapps/configuration#h-Types
65
+
66
+ Accepts an Array or String.
67
+ ```svelte
68
+ <DropdownSelector
69
+ name="metadata"
70
+ type="metadata-selector"
71
+ label="Metadata"
72
+ selectable="sv:metadataLinkDefinition"
73
+ selectable={['sv:metadataLinkDefinition', 'sv:metadataDateDefinition']}
74
+ />
75
+ ```
@@ -0,0 +1 @@
1
+ export { default } from './Component.svelte';
@@ -0,0 +1,76 @@
1
+ <script>
2
+ /* eslint-disable no-undef-init */
3
+ import { createEventDispatcher } from 'svelte';
4
+ import { httpPrefix } from '../../actions';
5
+ import { generateId } from '../../utils';
6
+
7
+ const values = window.CONFIG_VALUES || {};
8
+ const dispatch = createEventDispatcher();
9
+
10
+ export let id = generateId();
11
+ export let label;
12
+ export let type = 'text';
13
+ export let name = undefined;
14
+ export let required = false;
15
+ export let disabled = false;
16
+ export let readonly = false;
17
+ export let maxlength = undefined;
18
+ export let pattern = undefined;
19
+ export let rows = 3;
20
+ export let value = '';
21
+ value = name ? values[name] ?? value : value;
22
+
23
+ let className = '';
24
+ export { className as class };
25
+
26
+ $: isTextarea = type === 'textarea';
27
+ $: required = required && !disabled && !readonly;
28
+
29
+ const onInput = ({ target }) => {
30
+ value = type.match(/^(number|range)$/) ? +target.value : target.value;
31
+ dispatch('input', value);
32
+ dispatch('change', value);
33
+ };
34
+ </script>
35
+
36
+ <div class="form-group {className}">
37
+ <label for={id} class="control-label {required ? 'control-label--required' : ''}">{label}</label>
38
+ {#if isTextarea}
39
+ <textarea
40
+ class="form-control"
41
+ {id}
42
+ {name}
43
+ {required}
44
+ {maxlength}
45
+ {disabled}
46
+ {readonly}
47
+ {value}
48
+ {rows}
49
+ on:input={onInput}
50
+ />
51
+ {:else}
52
+ <input
53
+ class="form-control"
54
+ {id}
55
+ {name}
56
+ {type}
57
+ {required}
58
+ {maxlength}
59
+ {disabled}
60
+ {readonly}
61
+ {pattern}
62
+ {value}
63
+ use:httpPrefix
64
+ on:input={onInput}
65
+ />
66
+ {/if}
67
+ <slot />
68
+ </div>
69
+
70
+ <style>
71
+ .form-control[disabled],
72
+ .form-control[readonly] {
73
+ background-color: white;
74
+ opacity: 0.7;
75
+ }
76
+ </style>