@fiscozen/input 0.1.15 → 0.1.16
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/package.json +5 -4
- package/src/FzInput.vue +49 -20
- package/src/types.ts +26 -1
- package/src/useInputStyle.ts +34 -15
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fiscozen/input",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.16",
|
|
4
4
|
"description": "Design System Input component",
|
|
5
5
|
"main": "src/index.ts",
|
|
6
6
|
"type": "module",
|
|
@@ -10,7 +10,8 @@
|
|
|
10
10
|
"tailwindcss": "^3.4.1",
|
|
11
11
|
"vue": "^3.4.13",
|
|
12
12
|
"@fiscozen/composables": "^0.1.36",
|
|
13
|
-
"@fiscozen/
|
|
13
|
+
"@fiscozen/button": "^0.1.12",
|
|
14
|
+
"@fiscozen/icons": "^0.1.28"
|
|
14
15
|
},
|
|
15
16
|
"devDependencies": {
|
|
16
17
|
"@rushstack/eslint-patch": "^1.3.3",
|
|
@@ -28,9 +29,9 @@
|
|
|
28
29
|
"vite-plugin-dts": "^3.8.3",
|
|
29
30
|
"vitest": "^1.2.0",
|
|
30
31
|
"vue-tsc": "^1.8.25",
|
|
32
|
+
"@fiscozen/tsconfig": "^0.1.0",
|
|
31
33
|
"@fiscozen/eslint-config": "^0.1.0",
|
|
32
|
-
"@fiscozen/prettier-config": "^0.1.0"
|
|
33
|
-
"@fiscozen/tsconfig": "^0.1.0"
|
|
34
|
+
"@fiscozen/prettier-config": "^0.1.0"
|
|
34
35
|
},
|
|
35
36
|
"license": "MIT",
|
|
36
37
|
"scripts": {
|
package/src/FzInput.vue
CHANGED
|
@@ -24,23 +24,26 @@
|
|
|
24
24
|
:class="leftIconClass"
|
|
25
25
|
/>
|
|
26
26
|
</slot>
|
|
27
|
-
<
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
27
|
+
<div class="flex flex-col space-around min-w-0">
|
|
28
|
+
<span v-if="!showNormalPlaceholder" class="text-xs text-gray-300 grow-0 overflow-hidden text-ellipsis whitespace-nowrap">{{ placeholder }}</span>
|
|
29
|
+
<input
|
|
30
|
+
:type="type"
|
|
31
|
+
:required="required ? required : false"
|
|
32
|
+
:disabled="disabled"
|
|
33
|
+
:readonly="readonly"
|
|
34
|
+
:placeholder="showNormalPlaceholder ? placeholder : ''"
|
|
35
|
+
v-model="model"
|
|
36
|
+
:id="uniqueId"
|
|
37
|
+
ref="inputRef"
|
|
38
|
+
:class="[staticInputClass, computedInputClass]"
|
|
39
|
+
:pattern="pattern"
|
|
40
|
+
:name
|
|
41
|
+
:maxlength
|
|
42
|
+
@blur="(e) => $emit('blur', e)"
|
|
43
|
+
@focus="(e) => $emit('focus', e)"
|
|
44
|
+
@paste="(e) => $emit('paste', e)"
|
|
45
|
+
/>
|
|
46
|
+
</div>
|
|
44
47
|
<slot name="right-icon">
|
|
45
48
|
<FzIcon
|
|
46
49
|
v-if="valid"
|
|
@@ -49,13 +52,22 @@
|
|
|
49
52
|
class="text-semantic-success"
|
|
50
53
|
/>
|
|
51
54
|
<FzIcon
|
|
52
|
-
v-if="rightIcon"
|
|
55
|
+
v-if="rightIcon && !rightIconButton"
|
|
53
56
|
:name="rightIcon"
|
|
54
57
|
:size="size"
|
|
55
58
|
:variant="rightIconVariant"
|
|
56
59
|
@click.stop="emit('fzinput:right-icon-click')"
|
|
57
60
|
:class="rightIconClass"
|
|
58
61
|
/>
|
|
62
|
+
<FzIconButton
|
|
63
|
+
v-if="rightIcon && rightIconButton"
|
|
64
|
+
:iconName="rightIcon"
|
|
65
|
+
:size="mappedSize"
|
|
66
|
+
:iconVariant="rightIconVariant"
|
|
67
|
+
:variant="disabled ? 'invisible' : rightIconButtonVariant"
|
|
68
|
+
@click.stop="emit('fzinput:right-icon-click')"
|
|
69
|
+
:class="[{'bg-grey-100 !text-gray-300': disabled}, rightIconClass]"
|
|
70
|
+
/>
|
|
59
71
|
</slot>
|
|
60
72
|
</div>
|
|
61
73
|
<div
|
|
@@ -83,15 +95,18 @@
|
|
|
83
95
|
</template>
|
|
84
96
|
|
|
85
97
|
<script setup lang="ts">
|
|
86
|
-
import { Ref, ref } from "vue";
|
|
98
|
+
import { computed, toRefs, Ref, ref } from "vue";
|
|
87
99
|
import { FzInputProps } from "./types";
|
|
88
100
|
import { FzIcon } from "@fiscozen/icons";
|
|
101
|
+
import { FzIconButton } from "@fiscozen/button";
|
|
89
102
|
import useInputStyle from "./useInputStyle";
|
|
90
103
|
|
|
91
104
|
const props = withDefaults(defineProps<FzInputProps>(), {
|
|
92
105
|
size: "md",
|
|
93
106
|
error: false,
|
|
94
107
|
type: "text",
|
|
108
|
+
rightIconButtonVariant: 'invisible',
|
|
109
|
+
variant: 'normal'
|
|
95
110
|
});
|
|
96
111
|
|
|
97
112
|
const model = defineModel();
|
|
@@ -104,10 +119,24 @@ const {
|
|
|
104
119
|
computedContainerClass,
|
|
105
120
|
computedLabelClass,
|
|
106
121
|
staticInputClass,
|
|
122
|
+
computedInputClass,
|
|
107
123
|
computedHelpClass,
|
|
108
124
|
computedErrorClass,
|
|
109
125
|
containerWidth,
|
|
110
|
-
|
|
126
|
+
showNormalPlaceholder
|
|
127
|
+
} = useInputStyle(toRefs(props), containerRef, model);
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
const sizeMap = {
|
|
131
|
+
xl: 'lg',
|
|
132
|
+
lg: 'md',
|
|
133
|
+
md: 'sm',
|
|
134
|
+
sm: 'xs',
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
const mappedSize = computed(() => {
|
|
138
|
+
return sizeMap[props.size];
|
|
139
|
+
});
|
|
111
140
|
|
|
112
141
|
const emit = defineEmits([
|
|
113
142
|
"input",
|
package/src/types.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { IconButtonVariant } from "@fiscozen/button";
|
|
2
|
+
import { IconSize , IconVariant } from "@fiscozen/icons";
|
|
2
3
|
|
|
3
4
|
type FzInputProps = {
|
|
4
5
|
/**
|
|
@@ -13,6 +14,10 @@ type FzInputProps = {
|
|
|
13
14
|
* The placeholder displayed in the input
|
|
14
15
|
*/
|
|
15
16
|
placeholder?: string;
|
|
17
|
+
/**
|
|
18
|
+
* Secondary - floating like placeholder
|
|
19
|
+
*/
|
|
20
|
+
secondaryPlaceholder?: string;
|
|
16
21
|
/**
|
|
17
22
|
* If set to true, the input is required
|
|
18
23
|
*/
|
|
@@ -33,14 +38,30 @@ type FzInputProps = {
|
|
|
33
38
|
* Left icon variant
|
|
34
39
|
*/
|
|
35
40
|
leftIconVariant?: IconVariant;
|
|
41
|
+
/**
|
|
42
|
+
* Left icon button variant
|
|
43
|
+
*/
|
|
44
|
+
leftIconButtonVariant?: IconButtonVariant;
|
|
36
45
|
/**
|
|
37
46
|
* Right icon name
|
|
38
47
|
*/
|
|
39
48
|
rightIcon?: string;
|
|
49
|
+
/**
|
|
50
|
+
* Right icon name
|
|
51
|
+
*/
|
|
52
|
+
rightIconSize?: IconSize;
|
|
40
53
|
/**
|
|
41
54
|
* Right icon variant
|
|
42
55
|
*/
|
|
43
56
|
rightIconVariant?: IconVariant;
|
|
57
|
+
/**
|
|
58
|
+
* Right icon button vs normal icon
|
|
59
|
+
*/
|
|
60
|
+
rightIconButton?: boolean;
|
|
61
|
+
/**
|
|
62
|
+
* Right icon button variant
|
|
63
|
+
*/
|
|
64
|
+
rightIconButtonVariant?: IconButtonVariant;
|
|
44
65
|
/**
|
|
45
66
|
* The input type
|
|
46
67
|
*/
|
|
@@ -49,6 +70,10 @@ type FzInputProps = {
|
|
|
49
70
|
* If set to true, the input is valid
|
|
50
71
|
*/
|
|
51
72
|
valid?: boolean;
|
|
73
|
+
/**
|
|
74
|
+
* Input variant
|
|
75
|
+
*/
|
|
76
|
+
variant?: 'normal' | 'floating-label';
|
|
52
77
|
/**
|
|
53
78
|
* Pattern to validate the input
|
|
54
79
|
*/
|
package/src/useInputStyle.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import { computed, Ref } from "vue";
|
|
1
|
+
import { computed, ToRefs, Ref } from "vue";
|
|
2
2
|
import { FzInputProps } from "./types";
|
|
3
3
|
|
|
4
4
|
export default function useInputStyle(
|
|
5
|
-
props: FzInputProps
|
|
5
|
+
props: ToRefs<FzInputProps>,
|
|
6
6
|
container: Ref<HTMLElement | null>,
|
|
7
|
+
model: Ref<string>
|
|
7
8
|
) {
|
|
8
9
|
const containerWidth = computed(() =>
|
|
9
10
|
container.value ? `${container.value.clientWidth}px` : "auto",
|
|
@@ -15,37 +16,53 @@ export default function useInputStyle(
|
|
|
15
16
|
lg: "h-40 text-lg",
|
|
16
17
|
};
|
|
17
18
|
|
|
18
|
-
const staticContainerClass = `flex justify-between w-full items-center px-10 border-1 rounded gap-8 text-left has-[:focus]:border-blue-600`;
|
|
19
|
+
const staticContainerClass = `flex justify-between w-full items-center px-10 border-1 rounded gap-8 text-left has-[:focus]:border-blue-600 relative`;
|
|
19
20
|
|
|
20
21
|
const computedContainerClass = computed(() => [
|
|
21
|
-
mapContainerClass[props.size!],
|
|
22
|
+
props.variant?.value === 'normal' ? mapContainerClass[props.size?.value!] : 'h-40 pr-6',
|
|
22
23
|
evaluateProps(),
|
|
23
24
|
]);
|
|
24
25
|
|
|
25
26
|
const computedLabelClass = computed(() => [
|
|
26
|
-
props.disabled ? "text-grey-300" : "text-core-black",
|
|
27
|
+
props.disabled?.value ? "text-grey-300" : "text-core-black",
|
|
27
28
|
]);
|
|
28
29
|
|
|
29
30
|
const staticInputClass = `peer w-full bg-transparent border-0 focus:outline-none cursor-[inherit] focus:ring-0 truncate`;
|
|
30
31
|
|
|
32
|
+
const textSizeMap = {
|
|
33
|
+
xl: 'text-lg',
|
|
34
|
+
lg: 'text-base',
|
|
35
|
+
md: 'text-sm',
|
|
36
|
+
sm: 'text-xs'
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const showNormalPlaceholder = computed(() => {
|
|
40
|
+
return !(props.variant?.value === 'floating-label') ||
|
|
41
|
+
((props.variant?.value === 'floating-label') && !model.value)
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
const computedInputClass = computed(() => [
|
|
45
|
+
props.variant?.value === 'floating-label' ? textSizeMap[props.size?.value] : '',
|
|
46
|
+
]);
|
|
47
|
+
|
|
31
48
|
const computedHelpClass = computed(() => [
|
|
32
|
-
props.size === "sm" ? "text-xs" : "",
|
|
33
|
-
props.size === "md" ? "text-sm" : "",
|
|
34
|
-
props.size === "lg" ? "text-base" : "",
|
|
35
|
-
props.disabled ? "text-grey-300" : "text-grey-500",
|
|
49
|
+
props.size?.value === "sm" ? "text-xs" : "",
|
|
50
|
+
props.size?.value === "md" ? "text-sm" : "",
|
|
51
|
+
props.size?.value === "lg" ? "text-base" : "",
|
|
52
|
+
props.disabled?.value ? "text-grey-300" : "text-grey-500",
|
|
36
53
|
]);
|
|
37
54
|
const computedErrorClass = computed(() => [
|
|
38
|
-
props.size === "sm" ? "text-xs" : "",
|
|
39
|
-
props.size === "md" ? "text-sm" : "",
|
|
40
|
-
props.size === "lg" ? "text-base" : "",
|
|
41
|
-
props.disabled ? "text-grey-300" : "text-core-black",
|
|
55
|
+
props.size?.value === "sm" ? "text-xs" : "",
|
|
56
|
+
props.size?.value === "md" ? "text-sm" : "",
|
|
57
|
+
props.size?.value === "lg" ? "text-base" : "",
|
|
58
|
+
props.disabled?.value ? "text-grey-300" : "text-core-black",
|
|
42
59
|
]);
|
|
43
60
|
|
|
44
61
|
const evaluateProps = () => {
|
|
45
62
|
switch (true) {
|
|
46
|
-
case props.disabled:
|
|
63
|
+
case props.disabled?.value:
|
|
47
64
|
return "bg-grey-100 border-grey-100 text-grey-300 cursor-not-allowed";
|
|
48
|
-
case props.error:
|
|
65
|
+
case props.error?.value:
|
|
49
66
|
return "border-semantic-error bg-white text-core-black cursor-text";
|
|
50
67
|
default:
|
|
51
68
|
return "border-grey-300 bg-white text-core-black cursor-text";
|
|
@@ -57,8 +74,10 @@ export default function useInputStyle(
|
|
|
57
74
|
computedContainerClass,
|
|
58
75
|
computedLabelClass,
|
|
59
76
|
staticInputClass,
|
|
77
|
+
computedInputClass,
|
|
60
78
|
computedHelpClass,
|
|
61
79
|
computedErrorClass,
|
|
62
80
|
containerWidth,
|
|
81
|
+
showNormalPlaceholder
|
|
63
82
|
};
|
|
64
83
|
}
|