@redseed/redseed-ui-vue3 1.0.7 → 1.0.9
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/index.js +36 -18
- package/package.json +1 -1
- package/src/components/Button/ButtonSlot.vue +8 -2
- package/src/components/Form/FormRegister.vue +112 -0
- package/src/components/Form/FormSlot.vue +30 -0
- package/src/components/FormField/FormFieldCheckbox.vue +77 -0
- package/src/components/FormField/FormFieldEmail.vue +44 -0
- package/src/components/FormField/FormFieldHidden.vue +25 -0
- package/src/components/FormField/FormFieldPassword.vue +66 -0
- package/src/components/FormField/FormFieldPasswordToggle.vue +59 -0
- package/src/components/FormField/FormFieldSlot.vue +68 -0
- package/src/components/FormField/FormFieldText.vue +44 -0
- package/src/components/Social/SignUpWithGoogle.vue +125 -0
- /package/src/components/Button/{ButtonSecondaryLIghtRounded.vue → ButtonSecondaryLightRounded.vue} +0 -0
package/index.js
CHANGED
|
@@ -1,29 +1,47 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
1
|
+
import ButtonPrimary from './src/components/Button/ButtonPrimary.vue'
|
|
2
|
+
import ButtonPrimaryLight from './src/components/Button/ButtonPrimaryLight.vue'
|
|
3
|
+
import ButtonPrimaryLightRounded from './src/components/Button/ButtonPrimaryLightRounded.vue'
|
|
4
|
+
import ButtonPrimaryRounded from './src/components/Button/ButtonPrimaryRounded.vue'
|
|
5
|
+
import ButtonSecondary from './src/components/Button/ButtonSecondary.vue'
|
|
6
|
+
import ButtonSecondaryLight from './src/components/Button/ButtonSecondaryLight.vue'
|
|
7
|
+
import ButtonSecondaryLightRounded from './src/components/Button/ButtonSecondaryLightRounded.vue'
|
|
8
|
+
import ButtonSecondaryRounded from './src/components/Button/ButtonSecondaryRounded.vue'
|
|
9
|
+
import ButtonSlot from './src/components/Button/ButtonSlot.vue'
|
|
10
10
|
import Card from './src/components/Card/Card.vue'
|
|
11
|
+
import FormRegister from './src/components/Form/FormRegister.vue'
|
|
12
|
+
import FormFieldEmail from './src/components/FormField/FormFieldEmail.vue'
|
|
13
|
+
import FormFieldPassword from './src/components/FormField/FormFieldPassword.vue'
|
|
14
|
+
import FormFieldPasswordToggle from './src/components/FormField/FormFieldPasswordToggle.vue'
|
|
15
|
+
import FormFieldCheckbox from './src/components/FormField/FormFieldCheckbox.vue'
|
|
16
|
+
import FormFieldHidden from './src/components/FormField/FormFieldHidden.vue'
|
|
17
|
+
import FormFieldText from './src/components/FormField/FormFieldText.vue'
|
|
18
|
+
import FormFieldSlot from './src/components/FormField/FormFieldSlot.vue'
|
|
11
19
|
import Image from './src/components/Image/Image.vue'
|
|
12
20
|
import MessageBox from './src/components/MessageBox/MessageBox.vue'
|
|
13
21
|
import TwoColumnLayout from './src/components/TwoColumnLayout/TwoColumnLayout.vue'
|
|
22
|
+
import SignUpWithGoogle from './src/components/Social/SignUpWithGoogle.vue'
|
|
14
23
|
|
|
15
24
|
export {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
+
ButtonPrimary,
|
|
26
|
+
ButtonPrimaryLight,
|
|
27
|
+
ButtonPrimaryLightRounded,
|
|
28
|
+
ButtonPrimaryRounded,
|
|
29
|
+
ButtonSecondary,
|
|
30
|
+
ButtonSecondaryLight,
|
|
31
|
+
ButtonSecondaryLightRounded,
|
|
32
|
+
ButtonSecondaryRounded,
|
|
33
|
+
ButtonSlot,
|
|
25
34
|
Card,
|
|
35
|
+
FormRegister,
|
|
36
|
+
FormFieldEmail,
|
|
37
|
+
FormFieldPassword,
|
|
38
|
+
FormFieldPasswordToggle,
|
|
39
|
+
FormFieldCheckbox,
|
|
40
|
+
FormFieldHidden,
|
|
41
|
+
FormFieldText,
|
|
42
|
+
FormFieldSlot,
|
|
26
43
|
Image,
|
|
27
44
|
MessageBox,
|
|
28
45
|
TwoColumnLayout,
|
|
46
|
+
SignUpWithGoogle,
|
|
29
47
|
}
|
package/package.json
CHANGED
|
@@ -40,10 +40,16 @@ const props = defineProps({
|
|
|
40
40
|
type: Boolean,
|
|
41
41
|
default: false,
|
|
42
42
|
},
|
|
43
|
+
submit: {
|
|
44
|
+
type: Boolean,
|
|
45
|
+
default: false,
|
|
46
|
+
},
|
|
43
47
|
})
|
|
44
48
|
|
|
45
49
|
const defaultSize = computed(() => !props.xs && !props.sm && !props.md && !props.lg)
|
|
46
50
|
|
|
51
|
+
const type = computed(() => props.submit ? 'submit' : 'button')
|
|
52
|
+
|
|
47
53
|
const buttonSlotClass = computed(() => [
|
|
48
54
|
'button-slot',
|
|
49
55
|
{
|
|
@@ -87,7 +93,7 @@ const buttonSlotIconClass = computed(() => [
|
|
|
87
93
|
<template>
|
|
88
94
|
<button
|
|
89
95
|
:class="buttonSlotClass"
|
|
90
|
-
type="
|
|
96
|
+
:type="type"
|
|
91
97
|
v-bind="$attrs"
|
|
92
98
|
>
|
|
93
99
|
<span v-if="$slots.icon"
|
|
@@ -103,7 +109,7 @@ const buttonSlotIconClass = computed(() => [
|
|
|
103
109
|
<style lang="scss" scoped>
|
|
104
110
|
.button-slot {
|
|
105
111
|
// default shape and control
|
|
106
|
-
@apply w-fit h-fit inline-flex items-center justify-center select-none outline-none rounded border transition;
|
|
112
|
+
@apply w-fit h-fit inline-flex items-center justify-center select-none outline-none rounded border font-semibold transition;
|
|
107
113
|
// default colors
|
|
108
114
|
@apply bg-black/80 text-white ring-black/20 border-black/80;
|
|
109
115
|
// default hover state
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
<script setup>
|
|
2
|
+
import { ref } from 'vue'
|
|
3
|
+
import ButtonPrimary from '../Button/ButtonPrimary.vue'
|
|
4
|
+
import FormFieldCheckbox from '../FormField/FormFieldCheckbox.vue'
|
|
5
|
+
import FormFieldEmail from '../FormField/FormFieldEmail.vue'
|
|
6
|
+
import FormFieldPasswordToggle from '../FormField/FormFieldPasswordToggle.vue'
|
|
7
|
+
import FormFieldText from '../FormField/FormFieldText.vue'
|
|
8
|
+
import FormSlot from './FormSlot.vue'
|
|
9
|
+
|
|
10
|
+
const props = defineProps({
|
|
11
|
+
form: {
|
|
12
|
+
type: Object,
|
|
13
|
+
default: {
|
|
14
|
+
name: '',
|
|
15
|
+
email: '',
|
|
16
|
+
password: '',
|
|
17
|
+
},
|
|
18
|
+
},
|
|
19
|
+
})
|
|
20
|
+
|
|
21
|
+
const formRef = ref(props.form)
|
|
22
|
+
</script>
|
|
23
|
+
<template>
|
|
24
|
+
<FormSlot class="form-register">
|
|
25
|
+
<template #image v-if="$slots.image">
|
|
26
|
+
<slot name="image"></slot>
|
|
27
|
+
</template>
|
|
28
|
+
|
|
29
|
+
<slot name="social"></slot>
|
|
30
|
+
|
|
31
|
+
<div v-if="$slots.social"
|
|
32
|
+
class="form-register__or-container"
|
|
33
|
+
>
|
|
34
|
+
<div class="form-register__or-line">
|
|
35
|
+
<div class="form-register__or">
|
|
36
|
+
<slot name="or">
|
|
37
|
+
or
|
|
38
|
+
</slot>
|
|
39
|
+
</div>
|
|
40
|
+
</div>
|
|
41
|
+
</div>
|
|
42
|
+
|
|
43
|
+
<slot name="name"
|
|
44
|
+
formRef="formRef"
|
|
45
|
+
>
|
|
46
|
+
<FormFieldText
|
|
47
|
+
v-model="formRef.name"
|
|
48
|
+
>
|
|
49
|
+
<template #label>
|
|
50
|
+
Name
|
|
51
|
+
</template>
|
|
52
|
+
</FormFieldText>
|
|
53
|
+
</slot>
|
|
54
|
+
|
|
55
|
+
<FormFieldEmail
|
|
56
|
+
v-model="formRef.email"
|
|
57
|
+
>
|
|
58
|
+
<template #label>
|
|
59
|
+
Email
|
|
60
|
+
</template>
|
|
61
|
+
</FormFieldEmail>
|
|
62
|
+
|
|
63
|
+
<FormFieldPasswordToggle
|
|
64
|
+
v-model="formRef.password"
|
|
65
|
+
>
|
|
66
|
+
<template #label>
|
|
67
|
+
Password
|
|
68
|
+
</template>
|
|
69
|
+
</FormFieldPasswordToggle>
|
|
70
|
+
|
|
71
|
+
<FormFieldCheckbox>
|
|
72
|
+
<template #label>
|
|
73
|
+
<slot name="terms"></slot>
|
|
74
|
+
</template>
|
|
75
|
+
</FormFieldCheckbox>
|
|
76
|
+
|
|
77
|
+
<slot name="submit"
|
|
78
|
+
formRef="formRef"
|
|
79
|
+
>
|
|
80
|
+
<ButtonPrimary full lg submit>
|
|
81
|
+
<template #label>
|
|
82
|
+
<slot name="submit-label">
|
|
83
|
+
Register
|
|
84
|
+
</slot>
|
|
85
|
+
</template>
|
|
86
|
+
</ButtonPrimary>
|
|
87
|
+
</slot>
|
|
88
|
+
|
|
89
|
+
<div v-if="$slots.signin" class="form-register__signin">
|
|
90
|
+
<slot name="signin"></slot>
|
|
91
|
+
</div>
|
|
92
|
+
</FormSlot>
|
|
93
|
+
</template>
|
|
94
|
+
<style lang="scss" scoped>
|
|
95
|
+
.form-register {
|
|
96
|
+
&__or-container {
|
|
97
|
+
@apply w-full relative flex justify-center mb-2;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
&__or-line {
|
|
101
|
+
@apply after:content-[''] after:absolute after:top-1/2 after:left-0 after:bg-gray-300 after:h-px after:w-full;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
&__or {
|
|
105
|
+
@apply relative z-1 bg-white px-6;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
&__signin {
|
|
109
|
+
@apply text-sm pt-4;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
</style>
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
<script setup>
|
|
2
|
+
</script>
|
|
3
|
+
<template>
|
|
4
|
+
<div class="form-slot">
|
|
5
|
+
<div v-if="$slots.image" class="form-slot__image">
|
|
6
|
+
<slot name="image" />
|
|
7
|
+
</div>
|
|
8
|
+
|
|
9
|
+
<div class="form-slot__content">
|
|
10
|
+
<slot />
|
|
11
|
+
</div>
|
|
12
|
+
</div>
|
|
13
|
+
</template>
|
|
14
|
+
<style lang="scss" scoped>
|
|
15
|
+
.form-slot {
|
|
16
|
+
@apply flex flex-col sm:justify-center items-center;
|
|
17
|
+
@apply text-base text-gray-700;
|
|
18
|
+
|
|
19
|
+
&__image {
|
|
20
|
+
@apply mb-8;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
&__content {
|
|
24
|
+
@apply w-full sm:max-w-md px-10 xs:px-12 md:px-16 py-10 bg-white shadow-md overflow-hidden rounded-lg;
|
|
25
|
+
> * {
|
|
26
|
+
@apply first:mt-0 mt-4;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
</style>
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
<script setup>
|
|
2
|
+
import { ref, computed } from 'vue'
|
|
3
|
+
import FormFieldSlot from './FormFieldSlot.vue'
|
|
4
|
+
import { CheckIcon } from '@heroicons/vue/24/outline'
|
|
5
|
+
|
|
6
|
+
const emit = defineEmits(['update:checked'])
|
|
7
|
+
|
|
8
|
+
const props = defineProps({
|
|
9
|
+
checked: {
|
|
10
|
+
type: [Array, Boolean],
|
|
11
|
+
default: false,
|
|
12
|
+
},
|
|
13
|
+
value: {
|
|
14
|
+
type: String,
|
|
15
|
+
default: null,
|
|
16
|
+
},
|
|
17
|
+
})
|
|
18
|
+
|
|
19
|
+
const iconChecked = ref(false)
|
|
20
|
+
|
|
21
|
+
const proxyChecked = computed({
|
|
22
|
+
get() {
|
|
23
|
+
iconChecked.value = props.checked
|
|
24
|
+
return props.checked
|
|
25
|
+
},
|
|
26
|
+
|
|
27
|
+
set(val) {
|
|
28
|
+
iconChecked.value = val
|
|
29
|
+
emit('update:checked', val)
|
|
30
|
+
},
|
|
31
|
+
})
|
|
32
|
+
</script>
|
|
33
|
+
<template>
|
|
34
|
+
<FormFieldSlot class="form-field-checkbox">
|
|
35
|
+
<template #label>
|
|
36
|
+
<div class="form-field-checkbox__checkbox">
|
|
37
|
+
<div class="form-field-checkbox__check">
|
|
38
|
+
<CheckIcon v-if="iconChecked" class="form-field-checkbox__icon"></CheckIcon>
|
|
39
|
+
<input
|
|
40
|
+
v-model="proxyChecked"
|
|
41
|
+
v-bind="$attrs"
|
|
42
|
+
type="checkbox"
|
|
43
|
+
:value="value"
|
|
44
|
+
>
|
|
45
|
+
</div>
|
|
46
|
+
<div v-if="$slots.label"
|
|
47
|
+
class="form-field-checkbox__label"
|
|
48
|
+
>
|
|
49
|
+
<slot name="label"></slot>
|
|
50
|
+
</div>
|
|
51
|
+
</div>
|
|
52
|
+
</template>
|
|
53
|
+
<template #error v-if="$slots.error">
|
|
54
|
+
<slot name="error"></slot>
|
|
55
|
+
</template>
|
|
56
|
+
</FormFieldSlot>
|
|
57
|
+
</template>
|
|
58
|
+
<style lang="scss" scoped>
|
|
59
|
+
.form-field-checkbox {
|
|
60
|
+
&__checkbox {
|
|
61
|
+
@apply flex;
|
|
62
|
+
}
|
|
63
|
+
&__label {
|
|
64
|
+
@apply ml-2;
|
|
65
|
+
}
|
|
66
|
+
&__check {
|
|
67
|
+
@apply w-6 h-6 shrink-0 relative bg-white;
|
|
68
|
+
|
|
69
|
+
input {
|
|
70
|
+
@apply appearance-none absolute inset-0 rounded transition shadow-sm;
|
|
71
|
+
@apply border border-gray-300;
|
|
72
|
+
@apply focus:border-gray-300 focus:ring focus:ring-gray-300 focus:ring-opacity-50;
|
|
73
|
+
@apply invalid:border-red-500 invalid:ring invalid:ring-red-500 invalid:ring-opacity-20;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
</style>
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
<script setup>
|
|
2
|
+
import { ref } from 'vue'
|
|
3
|
+
import FormFieldSlot from './FormFieldSlot.vue'
|
|
4
|
+
|
|
5
|
+
// Apply all attributes to the input element, not the wrapper div
|
|
6
|
+
defineOptions({
|
|
7
|
+
inheritAttrs: false,
|
|
8
|
+
})
|
|
9
|
+
|
|
10
|
+
const props = defineProps({
|
|
11
|
+
modelValue: [
|
|
12
|
+
String,
|
|
13
|
+
Number
|
|
14
|
+
], //vue3 specific v-model pattern
|
|
15
|
+
})
|
|
16
|
+
|
|
17
|
+
defineEmits(['update:modelValue']) //vue3 specific v-model pattern
|
|
18
|
+
|
|
19
|
+
const input = ref(null)
|
|
20
|
+
</script>
|
|
21
|
+
<template>
|
|
22
|
+
<FormFieldSlot
|
|
23
|
+
class="form-field-email"
|
|
24
|
+
:id="$attrs.id"
|
|
25
|
+
>
|
|
26
|
+
<template #label v-if="$slots.label">
|
|
27
|
+
<slot name="label"></slot>
|
|
28
|
+
</template>
|
|
29
|
+
<input ref="input"
|
|
30
|
+
v-bind="$attrs"
|
|
31
|
+
type="email"
|
|
32
|
+
:value="modelValue"
|
|
33
|
+
@input="$emit('update:modelValue', $event.target.value)"
|
|
34
|
+
>
|
|
35
|
+
<template #help v-if="$slots.help">
|
|
36
|
+
<slot name="help"></slot>
|
|
37
|
+
</template>
|
|
38
|
+
<template #error v-if="$slots.error">
|
|
39
|
+
<slot name="error"></slot>
|
|
40
|
+
</template>
|
|
41
|
+
</FormFieldSlot>
|
|
42
|
+
</template>
|
|
43
|
+
<style lang="scss" scoped>
|
|
44
|
+
</style>
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
<script setup>
|
|
2
|
+
import { ref } from 'vue'
|
|
3
|
+
import FormFieldSlot from './FormFieldSlot.vue'
|
|
4
|
+
|
|
5
|
+
// Apply all attributes to the input element, not the wrapper div
|
|
6
|
+
defineOptions({
|
|
7
|
+
inheritAttrs: false,
|
|
8
|
+
})
|
|
9
|
+
|
|
10
|
+
const input = ref(null)
|
|
11
|
+
</script>
|
|
12
|
+
<template>
|
|
13
|
+
<FormFieldSlot
|
|
14
|
+
class="form-field-hidden"
|
|
15
|
+
>
|
|
16
|
+
<input ref="input"
|
|
17
|
+
type="hidden"
|
|
18
|
+
>
|
|
19
|
+
<template #error v-if="$slots.error">
|
|
20
|
+
<slot name="error"></slot>
|
|
21
|
+
</template>
|
|
22
|
+
</FormFieldSlot>
|
|
23
|
+
</template>
|
|
24
|
+
<style lang="scss" scoped>
|
|
25
|
+
</style>
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
<script setup>
|
|
2
|
+
import { ref } from 'vue'
|
|
3
|
+
import FormFieldSlot from './FormFieldSlot.vue'
|
|
4
|
+
|
|
5
|
+
// Apply all attributes to the input element, not the wrapper div
|
|
6
|
+
defineOptions({
|
|
7
|
+
inheritAttrs: false,
|
|
8
|
+
})
|
|
9
|
+
|
|
10
|
+
const props = defineProps({
|
|
11
|
+
modelValue: [
|
|
12
|
+
String,
|
|
13
|
+
Number
|
|
14
|
+
], //vue3 specific v-model pattern
|
|
15
|
+
})
|
|
16
|
+
|
|
17
|
+
defineEmits(['update:modelValue']) //vue3 specific v-model pattern
|
|
18
|
+
|
|
19
|
+
const input = ref(null)
|
|
20
|
+
</script>
|
|
21
|
+
<template>
|
|
22
|
+
<FormFieldSlot
|
|
23
|
+
class="form-field-password"
|
|
24
|
+
:id="$attrs.id"
|
|
25
|
+
>
|
|
26
|
+
<template #label v-if="$slots.label">
|
|
27
|
+
<slot name="label"></slot>
|
|
28
|
+
</template>
|
|
29
|
+
|
|
30
|
+
<div :class="{
|
|
31
|
+
'form-field-password__group': true,
|
|
32
|
+
'form-field-password__group--toggle': $slots.toggle,
|
|
33
|
+
}">
|
|
34
|
+
<input ref="input"
|
|
35
|
+
type="password"
|
|
36
|
+
v-bind="$attrs"
|
|
37
|
+
:value="modelValue"
|
|
38
|
+
@input="$emit('update:modelValue', $event.target.value)"
|
|
39
|
+
>
|
|
40
|
+
|
|
41
|
+
<slot name="toggle"></slot>
|
|
42
|
+
</div>
|
|
43
|
+
|
|
44
|
+
<template #help v-if="$slots.help">
|
|
45
|
+
<slot name="help"></slot>
|
|
46
|
+
</template>
|
|
47
|
+
|
|
48
|
+
<template #error v-if="$slots.error">
|
|
49
|
+
<slot name="error"></slot>
|
|
50
|
+
</template>
|
|
51
|
+
</FormFieldSlot>
|
|
52
|
+
</template>
|
|
53
|
+
<style lang="scss" scoped>
|
|
54
|
+
.form-field-password {
|
|
55
|
+
@apply relative;
|
|
56
|
+
|
|
57
|
+
&__group {
|
|
58
|
+
@apply relative;
|
|
59
|
+
&--toggle {
|
|
60
|
+
input {
|
|
61
|
+
@apply pr-12;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
</style>
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
<script setup>
|
|
2
|
+
import { ref } from 'vue'
|
|
3
|
+
import FormFieldPassword from './FormFieldPassword.vue'
|
|
4
|
+
import { EyeIcon, EyeSlashIcon } from '@heroicons/vue/24/outline'
|
|
5
|
+
|
|
6
|
+
// Apply all attributes to the input element, not the wrapper div
|
|
7
|
+
defineOptions({
|
|
8
|
+
inheritAttrs: false,
|
|
9
|
+
})
|
|
10
|
+
|
|
11
|
+
const show = ref(false)
|
|
12
|
+
|
|
13
|
+
function togglePassword() {
|
|
14
|
+
show.value = !show.value
|
|
15
|
+
}
|
|
16
|
+
</script>
|
|
17
|
+
<template>
|
|
18
|
+
<FormFieldPassword
|
|
19
|
+
v-bind="$attrs"
|
|
20
|
+
:type="show ? 'text' : 'password'"
|
|
21
|
+
>
|
|
22
|
+
<template #label v-if="$slots.label">
|
|
23
|
+
<slot name="label"></slot>
|
|
24
|
+
</template>
|
|
25
|
+
|
|
26
|
+
<template #toggle>
|
|
27
|
+
<div class="form-field-password__toggle"
|
|
28
|
+
@click="togglePassword"
|
|
29
|
+
>
|
|
30
|
+
<EyeIcon v-if="!show"
|
|
31
|
+
class="form-field-password__toggle-icon"
|
|
32
|
+
></EyeIcon>
|
|
33
|
+
<EyeSlashIcon v-if="show"
|
|
34
|
+
class="form-field-password__toggle-icon"
|
|
35
|
+
></EyeSlashIcon>
|
|
36
|
+
</div>
|
|
37
|
+
</template>
|
|
38
|
+
|
|
39
|
+
<template #help v-if="$slots.help">
|
|
40
|
+
<slot name="help"></slot>
|
|
41
|
+
</template>
|
|
42
|
+
|
|
43
|
+
<template #error v-if="$slots.error">
|
|
44
|
+
<slot name="error"></slot>
|
|
45
|
+
</template>
|
|
46
|
+
</FormFieldPassword>
|
|
47
|
+
</template>
|
|
48
|
+
<style lang="scss" scoped>
|
|
49
|
+
.form-field-password {
|
|
50
|
+
&__toggle {
|
|
51
|
+
@apply absolute top-px bottom-px right-px rounded-tr rounded-br;
|
|
52
|
+
@apply flex items-center justify-center px-3 select-none cursor-pointer;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
&__toggle-icon {
|
|
56
|
+
@apply w-5 h-5;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
</style>
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
<script setup>
|
|
2
|
+
import { computed, useAttrs } from 'vue'
|
|
3
|
+
|
|
4
|
+
// Apply all attributes to the input element, not the wrapper div
|
|
5
|
+
defineOptions({
|
|
6
|
+
inheritAttrs: false,
|
|
7
|
+
})
|
|
8
|
+
|
|
9
|
+
const attrs = useAttrs()
|
|
10
|
+
|
|
11
|
+
const formFieldSlotClass = computed(() => [
|
|
12
|
+
'form-field-slot',
|
|
13
|
+
attrs.class
|
|
14
|
+
])
|
|
15
|
+
</script>
|
|
16
|
+
<template>
|
|
17
|
+
<div :class="formFieldSlotClass">
|
|
18
|
+
<div v-if="$slots.label"
|
|
19
|
+
class="form-field-slot__label"
|
|
20
|
+
>
|
|
21
|
+
<label
|
|
22
|
+
:for="$attrs.id"
|
|
23
|
+
>
|
|
24
|
+
<slot name="label"></slot>
|
|
25
|
+
</label>
|
|
26
|
+
</div>
|
|
27
|
+
<slot></slot>
|
|
28
|
+
<div v-if="$slots.help"
|
|
29
|
+
class="form-field-slot__help"
|
|
30
|
+
>
|
|
31
|
+
<slot name="help"></slot>
|
|
32
|
+
</div>
|
|
33
|
+
<div v-if="$slots.error"
|
|
34
|
+
class="form-field-slot__error"
|
|
35
|
+
>
|
|
36
|
+
<slot name="error"></slot>
|
|
37
|
+
</div>
|
|
38
|
+
</div>
|
|
39
|
+
</template>
|
|
40
|
+
<style lang="scss" scoped>
|
|
41
|
+
.form-field-slot {
|
|
42
|
+
@apply flex flex-col space-y-1 border-0 bg-transparent p-0;
|
|
43
|
+
|
|
44
|
+
&__label {
|
|
45
|
+
label {
|
|
46
|
+
@apply block font-medium text-base text-gray-700;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
&__help {
|
|
51
|
+
@apply text-xs text-gray-500;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
&__error {
|
|
55
|
+
@apply text-sm text-red-500;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
</style>
|
|
59
|
+
<style lang="scss">
|
|
60
|
+
.form-field-slot {
|
|
61
|
+
input:not([type='checkbox']):not([type='radio']) {
|
|
62
|
+
@apply block w-full border rounded shadow-sm text-base transition py-2 px-3;
|
|
63
|
+
@apply bg-white placeholder-gray-300 border-gray-300;
|
|
64
|
+
@apply focus:ring focus:ring-gray-300 focus:ring-opacity-50 focus:outline-none ring-0 focus:bg-white focus:border-gray-400;
|
|
65
|
+
@apply invalid:border-red-500 invalid:ring invalid:ring-red-500 invalid:ring-opacity-20;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
</style>
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
<script setup>
|
|
2
|
+
import { ref } from 'vue'
|
|
3
|
+
import FormFieldSlot from './FormFieldSlot.vue'
|
|
4
|
+
|
|
5
|
+
// Apply all attributes to the input element, not the wrapper div
|
|
6
|
+
defineOptions({
|
|
7
|
+
inheritAttrs: false,
|
|
8
|
+
})
|
|
9
|
+
|
|
10
|
+
const props = defineProps({
|
|
11
|
+
modelValue: [
|
|
12
|
+
String,
|
|
13
|
+
Number
|
|
14
|
+
], //vue3 specific v-model pattern
|
|
15
|
+
})
|
|
16
|
+
|
|
17
|
+
defineEmits(['update:modelValue']) //vue3 specific v-model pattern
|
|
18
|
+
|
|
19
|
+
const input = ref(null)
|
|
20
|
+
</script>
|
|
21
|
+
<template>
|
|
22
|
+
<FormFieldSlot
|
|
23
|
+
class="form-field-text"
|
|
24
|
+
:id="$attrs.id"
|
|
25
|
+
>
|
|
26
|
+
<template #label v-if="$slots.label">
|
|
27
|
+
<slot name="label"></slot>
|
|
28
|
+
</template>
|
|
29
|
+
<input ref="input"
|
|
30
|
+
v-bind="$attrs"
|
|
31
|
+
type="text"
|
|
32
|
+
:value="modelValue"
|
|
33
|
+
@input="$emit('update:modelValue', $event.target.value)"
|
|
34
|
+
>
|
|
35
|
+
<template #help v-if="$slots.help">
|
|
36
|
+
<slot name="help"></slot>
|
|
37
|
+
</template>
|
|
38
|
+
<template #error v-if="$slots.error">
|
|
39
|
+
<slot name="error"></slot>
|
|
40
|
+
</template>
|
|
41
|
+
</FormFieldSlot>
|
|
42
|
+
</template>
|
|
43
|
+
<style lang="scss" scoped>
|
|
44
|
+
</style>
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
<script setup>
|
|
2
|
+
</script>
|
|
3
|
+
<template>
|
|
4
|
+
<button class="gsi-material-button">
|
|
5
|
+
<div class="gsi-material-button-state"></div>
|
|
6
|
+
<div class="gsi-material-button-content-wrapper">
|
|
7
|
+
<div class="gsi-material-button-icon">
|
|
8
|
+
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48" xmlns:xlink="http://www.w3.org/1999/xlink" style="display: block;">
|
|
9
|
+
<path fill="#EA4335" d="M24 9.5c3.54 0 6.71 1.22 9.21 3.6l6.85-6.85C35.9 2.38 30.47 0 24 0 14.62 0 6.51 5.38 2.56 13.22l7.98 6.19C12.43 13.72 17.74 9.5 24 9.5z"></path>
|
|
10
|
+
<path fill="#4285F4" d="M46.98 24.55c0-1.57-.15-3.09-.38-4.55H24v9.02h12.94c-.58 2.96-2.26 5.48-4.78 7.18l7.73 6c4.51-4.18 7.09-10.36 7.09-17.65z"></path>
|
|
11
|
+
<path fill="#FBBC05" d="M10.53 28.59c-.48-1.45-.76-2.99-.76-4.59s.27-3.14.76-4.59l-7.98-6.19C.92 16.46 0 20.12 0 24c0 3.88.92 7.54 2.56 10.78l7.97-6.19z"></path>
|
|
12
|
+
<path fill="#34A853" d="M24 48c6.48 0 11.93-2.13 15.89-5.81l-7.73-6c-2.15 1.45-4.92 2.3-8.16 2.3-6.26 0-11.57-4.22-13.47-9.91l-7.98 6.19C6.51 42.62 14.62 48 24 48z"></path>
|
|
13
|
+
<path fill="none" d="M0 0h48v48H0z"></path>
|
|
14
|
+
</svg>
|
|
15
|
+
</div>
|
|
16
|
+
<span class="gsi-material-button-contents">Sign up with Google</span>
|
|
17
|
+
<span style="display: none;">Sign up with Google</span>
|
|
18
|
+
</div>
|
|
19
|
+
</button>
|
|
20
|
+
</template>
|
|
21
|
+
<style scoped>
|
|
22
|
+
.gsi-material-button {
|
|
23
|
+
-moz-user-select: none;
|
|
24
|
+
-webkit-user-select: none;
|
|
25
|
+
-ms-user-select: none;
|
|
26
|
+
-webkit-appearance: none;
|
|
27
|
+
background-color: WHITE;
|
|
28
|
+
background-image: none;
|
|
29
|
+
border: 1px solid #d1d5db;
|
|
30
|
+
-webkit-border-radius: 4px;
|
|
31
|
+
border-radius: 4px;
|
|
32
|
+
-webkit-box-sizing: border-box;
|
|
33
|
+
box-sizing: border-box;
|
|
34
|
+
color: #1f1f1f;
|
|
35
|
+
cursor: pointer;
|
|
36
|
+
font-family: 'Roboto', arial, sans-serif;
|
|
37
|
+
font-size: 14px;
|
|
38
|
+
height: 40px;
|
|
39
|
+
letter-spacing: 0.25px;
|
|
40
|
+
outline: none;
|
|
41
|
+
overflow: hidden;
|
|
42
|
+
padding: 0 12px;
|
|
43
|
+
position: relative;
|
|
44
|
+
text-align: center;
|
|
45
|
+
-webkit-transition: background-color .218s, border-color .218s, box-shadow .218s;
|
|
46
|
+
transition: background-color .218s, border-color .218s, box-shadow .218s;
|
|
47
|
+
vertical-align: middle;
|
|
48
|
+
white-space: nowrap;
|
|
49
|
+
width: 100%;
|
|
50
|
+
max-width: 400px;
|
|
51
|
+
min-width: min-content;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
.gsi-material-button .gsi-material-button-icon {
|
|
55
|
+
height: 20px;
|
|
56
|
+
margin-right: 12px;
|
|
57
|
+
min-width: 20px;
|
|
58
|
+
width: 20px;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
.gsi-material-button .gsi-material-button-content-wrapper {
|
|
62
|
+
-webkit-align-items: center;
|
|
63
|
+
align-items: center;
|
|
64
|
+
display: flex;
|
|
65
|
+
-webkit-flex-direction: row;
|
|
66
|
+
flex-direction: row;
|
|
67
|
+
-webkit-flex-wrap: nowrap;
|
|
68
|
+
flex-wrap: nowrap;
|
|
69
|
+
height: 100%;
|
|
70
|
+
justify-content: space-between;
|
|
71
|
+
position: relative;
|
|
72
|
+
width: 100%;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
.gsi-material-button .gsi-material-button-contents {
|
|
76
|
+
-webkit-flex-grow: 1;
|
|
77
|
+
flex-grow: 1;
|
|
78
|
+
font-family: 'Roboto', arial, sans-serif;
|
|
79
|
+
font-weight: 500;
|
|
80
|
+
overflow: hidden;
|
|
81
|
+
text-overflow: ellipsis;
|
|
82
|
+
vertical-align: top;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
.gsi-material-button .gsi-material-button-state {
|
|
86
|
+
-webkit-transition: opacity .218s;
|
|
87
|
+
transition: opacity .218s;
|
|
88
|
+
bottom: 0;
|
|
89
|
+
left: 0;
|
|
90
|
+
opacity: 0;
|
|
91
|
+
position: absolute;
|
|
92
|
+
right: 0;
|
|
93
|
+
top: 0;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
.gsi-material-button:disabled {
|
|
97
|
+
cursor: default;
|
|
98
|
+
background-color: #ffffff61;
|
|
99
|
+
border-color: #1f1f1f1f;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
.gsi-material-button:disabled .gsi-material-button-contents {
|
|
103
|
+
opacity: 38%;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
.gsi-material-button:disabled .gsi-material-button-icon {
|
|
107
|
+
opacity: 38%;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
.gsi-material-button:not(:disabled):active .gsi-material-button-state,
|
|
111
|
+
.gsi-material-button:not(:disabled):focus .gsi-material-button-state {
|
|
112
|
+
background-color: #303030;
|
|
113
|
+
opacity: 12%;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
.gsi-material-button:not(:disabled):hover {
|
|
117
|
+
-webkit-box-shadow: 0 1px 2px 0 rgba(60, 64, 67, .30), 0 1px 3px 1px rgba(60, 64, 67, .15);
|
|
118
|
+
box-shadow: 0 1px 2px 0 rgba(60, 64, 67, .30), 0 1px 3px 1px rgba(60, 64, 67, .15);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
.gsi-material-button:not(:disabled):hover .gsi-material-button-state {
|
|
122
|
+
background-color: #ffffff;
|
|
123
|
+
opacity: 8%;
|
|
124
|
+
}
|
|
125
|
+
</style>
|
/package/src/components/Button/{ButtonSecondaryLIghtRounded.vue → ButtonSecondaryLightRounded.vue}
RENAMED
|
File without changes
|