Skip to content

Commit

Permalink
WPasswordField
Browse files Browse the repository at this point in the history
  • Loading branch information
Woolim Park committed Nov 22, 2023
1 parent d8951e6 commit 3caa367
Show file tree
Hide file tree
Showing 15 changed files with 1,125 additions and 17 deletions.
3 changes: 3 additions & 0 deletions .eslintignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
!.eslintrc.js
drafts
scripts
54 changes: 54 additions & 0 deletions .eslintrc.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
module.exports = {
root: true,
env: {
node: true,
browser: true,
'vue/setup-compiler-macros': true,
},
extends: [
'plugin:vue/vue3-recommended',
'eslint:recommended',
'@vue/typescript/recommended',
'@vue/prettier',
'plugin:storybook/recommended',
],
plugins: ['vue', 'simple-import-sort', 'unused-imports'],
rules: {
'no-console': 'warn',
'no-alert': 'error',
'vue/no-v-html': 'off',
'simple-import-sort/imports': 'error',
'simple-import-sort/exports': 'error',
'unused-imports/no-unused-imports': 'error',
'@typescript-eslint/no-unused-vars': [
'warn',
{
argsIgnorePattern: '^_',
varsIgnorePattern: '^_',
caughtErrorsIgnorePattern: '^_',
},
],
'@typescript-eslint/no-explicit-any': 'off',
'vue/attributes-order': [
'error',
{
order: [
'LIST_RENDERING',
'CONDITIONALS',
'SLOT',
'RENDER_MODIFIERS',
'TWO_WAY_BINDING',
'DEFINITION',
'GLOBAL',
'UNIQUE',
'ATTR_DYNAMIC',
'ATTR_SHORTHAND_BOOL',
'ATTR_STATIC',
'CONTENT',
'OTHER_DIRECTIVES',
'EVENTS',
],
},
],
},
};
6 changes: 6 additions & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
node_modules/**
assets/**
drafts/**
dist/**
scripts/**
public/**
9 changes: 9 additions & 0 deletions .prettierrc.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
module.exports = {
trailingComma: 'all',
tabWidth: 2,
semi: true,
singleQuote: true,
endOfLine: 'auto',
arrowParens: 'always',
printWidth: 100,
};
2 changes: 1 addition & 1 deletion components/WInput/WInput.vue
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ defineExpose<{
<span
v-if="$slots.prepend"
@click="onAppendClick"
class="w-fit p-1 [&_svg]:w-[25px] [&_svg]:h-[25px] ml-3 h-[30px] text-[16px] flex justify-center items-center"
class="w-fit p-1 [&_svg]:w-[25px] [&_svg]:h-[25px] ml-4 h-[30px] text-[16px] flex justify-center items-center"
:class="{ ['cursor-not-allowed']: disabled }"
>
<slot name="prepend" />
Expand Down
17 changes: 17 additions & 0 deletions components/WPasswordField/WPasswordField.story.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<script setup>
import WPasswordField from "./WPasswordField.vue";
import { reactive } from "vue";
const state = reactive({
label: "Password",
value: "",
});
</script>

<template>
<Story title="Form/WPasswordField" :layout="{ type: 'grid', width: 300 }">
<Variant title="default">
<WPasswordField v-model="state.value" :label="state.label" />
</Variant>
</Story>
</template>
73 changes: 73 additions & 0 deletions components/WPasswordField/WPasswordField.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
<script setup lang="ts">
import { EyeIcon, EyeSlashIcon } from '@heroicons/vue/24/solid';
import WInput from '@/components/WInput';
import WLabel from '@/components/WLabel';
import { useIds } from '@/composables/useIds';
import { ref, computed } from 'vue';
import { InputType } from '@/types';
const props = defineProps({
modelValue: { type: String, default: '' },
label: { type: String, default: '' },
disabled: { type: Boolean, default: false },
});
const emit = defineEmits(['update:modelValue']);
const inputType = ref<InputType.TEXT | InputType.PASSWORD>(InputType.PASSWORD);
const id = useIds().get();
const active = ref(false);
const changeInputType = (type: InputType.TEXT | InputType.PASSWORD) => {
inputType.value = type;
};
const onInput = (e: InputEvent) => {
const target = e.target as HTMLInputElement;
emit('update:modelValue', target.value);
};
const validators = [
{ text: 'At least 1 lowercase', type: 'Lowercase', valid: false, regex: /[a-z]/ },
{ text: 'At least 1 uppercase', type: 'Uppercase', valid: false, regex: /[A-Z]/ },
{ text: 'At least 1 digit', type: 'Number', valid: false, regex: /\d/ },
{ text: 'At least 1 special character', type: 'Special', valid: false, regex: /[^A-Za-z0-9]/ },
{ text: 'At least 8 characters', type: 'Length', valid: false, regex: /.{8,}/ },
];
const grade = computed(() => {
const total = validators.filter((v) => props.modelValue.match(v.regex)).length;
return total - 1;
});
</script>
<template>
<div>
<WLabel :for="id">{{ label }}</WLabel>
<WInput
:id="id"
:value="modelValue"
:disabled="disabled"
:type="inputType"
@input="onInput"
@focus="active = true"
@blur="active = false"
>
<template #append>
<EyeSlashIcon
v-if="inputType === InputType.PASSWORD"
@click="changeInputType(InputType.TEXT)"
/>
<EyeIcon v-else @click="changeInputType(InputType.PASSWORD)" />
</template>
</WInput>

<ul class="flex gap-[1px] border-black ml-6 mr-1 mt-2 flex-1 rounded-lg overflow-hidden">
<li
v-for="(_, idx) in validators"
class="bg-white flex-1 h-2 transition-colors"
:class="{
['!bg-rose-300']: 0 === idx && grade === 0,
['!bg-rose-400']: 1 >= idx && grade === 1,
['!bg-orange-300']: 2 >= idx && grade === 2,
['!bg-lime-300']: 3 >= idx && grade === 3,
['!bg-sky-300']: 4 >= idx && grade === 4,
}"
></li>
</ul>
</div>
</template>
1 change: 1 addition & 0 deletions components/WPasswordField/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default } from "./WPasswordField.vue";
2 changes: 1 addition & 1 deletion components/WPhoneField/CountrySelect.vue
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ watch(active, (value) => {
<WInput ref="input" readonly :disabled="disabled" :meh="isPlaying || meh">
<template #prepend>
<i
class="ml-2 mr-1 iti__flag"
class="ml-1 mr-1 iti__flag"
:class="[`iti__${modelValue.toLowerCase()}`, { ['!cursor-not-allowed']: disabled }]"
/>
</template>
Expand Down
1 change: 0 additions & 1 deletion components/WPhoneField/WPhoneField.story.vue
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import { useDebounceFn } from "@vueuse/core";
const state = reactive({
label: "Phone",
type: InputType.TEXT,
value: "",
locale: "en",
errorMessage: "",
Expand Down
1 change: 1 addition & 0 deletions components/WPhoneField/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default } from "./WPhoneField.vue";
2 changes: 1 addition & 1 deletion composables/useMeh.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ const audioPlayer = new Audio("audio");
const statePlaying: { [key: string]: Ref<boolean> } = {};

audioPlayer.src = sound;
audioPlayer.volume = 0;
// audioPlayer.volume = 0;
audioPlayer.addEventListener("pause", function () {
Object.values(statePlaying).forEach((v) => (v.value = false));
});
Expand Down
8 changes: 8 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,18 @@
"@formatjs/intl-getcanonicallocales": "^2.3.0",
"@formatjs/intl-locale": "^3.4.3",
"@heroicons/vue": "^2.0.18",
"@vue/eslint-config-prettier": "^8.0.0",
"@vue/eslint-config-typescript": "^12.0.0",
"@vueuse/components": "^10.6.1",
"@vueuse/core": "^10.6.1",
"color": "^4.2.3",
"eslint": "^8.54.0",
"eslint-plugin-prettier": "^5.0.1",
"eslint-plugin-simple-import-sort": "^10.0.0",
"eslint-plugin-unused-imports": "^3.0.0",
"eslint-plugin-vue": "^9.18.1",
"libphonenumber-js": "^1.10.49",
"prettier": "^3.1.0",
"vue": "^3.3.4"
},
"devDependencies": {
Expand Down
2 changes: 1 addition & 1 deletion tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,5 +28,5 @@
}
},
"include": ["env.d.ts", "**/*.js", "**/*.ts", "**/*.vue", "**/*.d.ts", "**/*.tsx"],
"exclude": ["drafts/"]
"exclude": ["node_modules", "dist", "drafts", "scripts"]
}
Loading

0 comments on commit 3caa367

Please sign in to comment.