-
Notifications
You must be signed in to change notification settings - Fork 44
/
Copy pathField.svelte
125 lines (105 loc) · 2.93 KB
/
Field.svelte
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
<script>
import { onMount, setContext } from 'svelte'
import { writable } from 'svelte/store'
import { omit } from '../utils'
/** Type (color) of the field and help message. Also adds a matching icon.
* @svelte-prop {String} [type]
* @values $$colors$$
* */
export let type = ''
/** Label for input
* @svelte-prop {String} [label]
* */
export let label = null
/** Same as native <code>for</code> on label
* @svelte-prop {String} [labelFor]
* */
export let labelFor = ''
/** Message to show beneath input
* @svelte-prop {String} [message]
* */
export let message = ''
/** Direct child components/elements of Field will be grouped horizontally
* @svelte-prop {Boolean} grouped=false
* */
export let grouped = false
/** Allow grouped controls to cover multiple lines
* @svelte-prop {Boolean} groupMultiline=false
* */
export let groupMultiline = false
/** Alter the alignment of the field
* @svelte-prop {String} [position]
* @values is-centered, is-right
* */
export let position = ''
/** Automatically attach child controls together
* @svelte-prop {Boolean} addons=true
* */
export let addons = true
export let expanded = false
const typeStore = writable('')
setContext('type', () => typeStore)
$: $typeStore = type
let el
let labelEl
let messageEl
let fieldType = ''
let hasIcons = false
let iconType = ''
let mounted = false
let newPosition = ''
// Determine the icon type
$: {
if (['is-danger', 'is-success'].includes(type)) {
iconType = type
}
}
$: {
if (grouped) fieldType = 'is-grouped'
else if (mounted) {
const childNodes = Array.prototype.filter.call(el.children, c => !([labelEl, messageEl].includes(c)))
if (childNodes.length > 1 && addons) {
fieldType = 'has-addons'
}
}
}
// Update has-addons-* or is-grouped-* classes based on position prop
$: {
if (position) {
const pos = position.split('-')
if (pos.length >= 1) {
const prefix = grouped ? 'is-grouped-' : 'has-addons-'
newPosition = prefix + pos[1]
}
}
}
$: props = { ...omit($$props, 'addons', 'class', 'expanded', 'grouped', 'label', 'labelFor', 'position', 'type') }
onMount(() => {
mounted = true
})
</script>
<style lang="scss">
.field {
&.is-grouped {
.field {
flex-shrink: 0;
&:not(:last-child) {
margin-right: 0.75rem;
}
&.is-expanded {
flex-grow: 1;
flex-shrink: 1;
}
}
}
}
</style>
<div {...props} class="field {type} {fieldType} {newPosition} {$$props.class || ''}" class:is-expanded={expanded} class:is-grouped-multiline={groupMultiline} bind:this={el}>
{#if label}
<label for={labelFor} class="label" bind:this={labelEl}>{label}</label>
{/if}
<slot statusType={type} />
{#if message}
<p class="help {type}" bind:this={messageEl}>{message}</p>
{/if}
</div>