feature: implament some event handlers and rename component to button-edit

This commit is contained in:
Sagi 2022-09-16 23:36:27 +08:00
parent 8298f7e64f
commit b7ef12bb60
13 changed files with 324 additions and 156 deletions

View File

@ -1,39 +1,59 @@
import { defineComponent, computed } from 'vue';
import { defineComponent, computed, toRefs } from 'vue';
import type { SetupContext } from 'vue';
import { InputGroupProps, inputGroupProps } from './input-group.props';
import { useAppendButton } from './composition/use-append-button';
import { buttonEditProps, ButtonEditProps } from './button-edit.props';
import { useButton } from './composition/use-button';
import { useClear } from './composition/use-clear';
import { useTextBox } from './composition/use-text-box';
export default defineComponent({
name: 'FInputGroup',
props: inputGroupProps,
setup(props: InputGroupProps, context: SetupContext) {
const inputGroupClass = computed(() => ({
'input-group': true,
'f-state-disable': props.disable,
'f-state-editable': props.editable && !props.disable && !props.readonly,
'f-state-readonly': props.readonly && !props.disable,
}));
name: 'FButtonEdit',
props: buttonEditProps,
emits: [
'updateExtendInfo',
'clear',
'change',
'clickHandle',
'blurHandle',
'focusHandle',
'enterHandle',
'iconMouseEnter',
'iconMouseLeave',
'keyupHandle',
'keydownHandle',
'inputClick',
'input',
'update:modelValue',
],
setup(props: ButtonEditProps, context: SetupContext) {
const { modelValue } = toRefs(props);
const { inputGroupAppendClass, onClickAppendButton, onMouseEnterIcon, onMouseLeaveIcon } = useAppendButton(props, context);
const { buttonClass, onClickButton, onMouseEnterButton, onMouseLeaveButton } = useButton(props, context);
const { showClearButton, onClearValue } = useClear(props, context);
const { showClearButton, onClearValue, onMouseEnterTextBox, onMouseLeaveTextBox } = useClear(props, context);
const {
hasFocusedTextBox,
isTextBoxReadonly,
textBoxClass,
textBoxPlaceholder,
textBoxTitle,
onBlurTextBox,
onClickTextBox,
onEnterTextBox,
onFocusTextBox,
onInput,
onMouseDownTextBox,
onMouseOverTextBox,
onTextBoxValueChange,
} = useTextBox(props, context);
const inputGroupClass = computed(() => ({
'input-group': true,
'f-state-disable': props.disable,
'f-state-editable': props.editable && !props.disable && !props.readonly,
'f-state-readonly': props.readonly && !props.disable,
'f-state-focus': hasFocusedTextBox,
}));
return () => {
return (
<div class="f-cmp-inputgroup" id={props.id}>
@ -50,19 +70,21 @@ export default defineComponent({
tabindex={props.tabIndex}
title={textBoxTitle.value}
type={props.inputType}
value={modelValue.value}
onBlur={onBlurTextBox}
onClick={onClickTextBox}
onFocus={onFocusTextBox}
onKeydown={onEnterTextBox}
onInput={onInput}
onKeydown={onMouseEnterTextBox}
onMousedown={onMouseDownTextBox}
/>
<div class={inputGroupAppendClass.value}>
<div class={buttonClass.value}>
{showClearButton.value && (
<span class="input-group-text input-group-clear">
<i class="f-icon modal_close"></i>
</span>
)}
{props.appendButtonContent && <span class="input-group-text" v-html={props.appendButtonContent}></span>}
{props.buttonContent && <span class="input-group-text" v-html={props.buttonContent}></span>}
</div>
</div>
</div>

View File

@ -2,7 +2,7 @@ import { ExtractPropTypes, PropType } from 'vue';
type TextAlignment = 'left' | 'center' | 'right';
export const inputGroupProps = {
export const buttonEditProps = {
/**
*
*/
@ -10,7 +10,7 @@ export const inputGroupProps = {
/**
* html标签
*/
appendButtonContent: { type: String, default: '<i class="f-icon f-icon-lookup"></i>' },
buttonContent: { type: String, default: '<i class="f-icon f-icon-lookup"></i>' },
/**
*
*/
@ -31,6 +31,10 @@ export const inputGroupProps = {
*
*/
enableClear: { type: Boolean, default: false },
/**
*
*/
modelValue:{type:String,default:''},
/**
*
*/
@ -60,7 +64,6 @@ export const inputGroupProps = {
*
*/
placeholder: { type: String, default: '' },
/**
*
*/
@ -75,4 +78,4 @@ export const inputGroupProps = {
tabIndex: Number,
};
export type InputGroupProps = ExtractPropTypes<typeof inputGroupProps>;
export type ButtonEditProps = ExtractPropTypes<typeof buttonEditProps>;

View File

@ -0,0 +1,89 @@
import { ComputedRef } from 'vue';
export interface UseButton {
/**
* Class
*/
buttonClass: ComputedRef<Record<string, boolean | undefined>>;
/**
*
*/
onClickButton: ($event: Event) => void;
/**
*
*/
onMouseEnterButton: ($event: MouseEvent) => void;
/**
*
*/
onMouseLeaveButton: ($event: MouseEvent) => void;
/**
*
*/
onMouseOverButton: () => void;
}
export interface UseClear {
/**
*
*/
showClearButton: ComputedRef<boolean>;
/**
*
*/
onClearValue: ($event: Event) => void;
/**
*
*/
onMouseEnterTextBox: ($event: KeyboardEvent) => void;
onMouseLeaveTextBox: ($event: Event) => void;
}
export interface UseTextBox {
hasFocusedTextBox: ComputedRef<boolean>;
/**
*
*/
isTextBoxReadonly: ComputedRef<boolean>;
/**
* Class
*/
textBoxClass: ComputedRef<Record<string, boolean | undefined>>;
/**
*
*/
textBoxPlaceholder: ComputedRef<string>;
/**
*
*/
textBoxTitle: ComputedRef<string>;
/**
*
*/
onBlurTextBox: ($event: Event) => void;
/**
*
*/
onClickTextBox: ($event: Event) => void;
/**
*
*/
onFocusTextBox: ($event: Event) => void;
/**
*
*/
onInput: ($event: Event) => void;
/**
*
*/
onMouseDownTextBox: ($event: MouseEvent) => void;
/**
*
*/
onMouseOverTextBox: ($event: Event) => void;
/**
*
*/
onTextBoxValueChange: (value: string, emit: boolean) => void;
}

View File

@ -0,0 +1,38 @@
import { UseButton } from './types';
import { computed, SetupContext } from 'vue';
import { ButtonEditProps } from '../button-edit.props';
export function useButton(props: ButtonEditProps, context: SetupContext): UseButton {
const buttonClass = computed(() => ({
'input-group-append': true,
'append-force-show': props.showButtonWhenDisabled && (props.readonly || props.disable),
}));
const canClickAppendButton = computed(() => props.showButtonWhenDisabled || ((!props.editable || !props.readonly) && !props.disable));
function onClickButton($event: Event) {
if (canClickAppendButton.value) {
context.emit('clickButton', { origin: $event, value: this.value });
}
$event.stopPropagation();
}
function onMouseEnterButton($event: MouseEvent) {
context.emit('mouseEnter', $event);
}
function onMouseLeaveButton($event: MouseEvent) {
context.emit('mouseLeaveIcon', $event);
}
function onMouseOverButton() {
context.emit('mouseOverButton');
}
return {
buttonClass,
onClickButton,
onMouseEnterButton,
onMouseLeaveButton,
onMouseOverButton,
};
}

View File

@ -0,0 +1,57 @@
import { computed, ref, SetupContext } from 'vue';
import { ButtonEditProps } from '../button-edit.props';
import { UseClear } from './types';
import { useTextBox } from './use-text-box';
export function useClear(props: ButtonEditProps, context: SetupContext): UseClear {
const hasShownClearButton = ref(false);
const showClearButton = computed(() => props.enableClear && !props.readonly && !props.disable);
const { onTextBoxValueChange } = useTextBox(props, context);
function toggleClearIcon($event: any, isShow = false) {
const display = isShow ? '' : 'none';
const clearIcon = $event.target.querySelector('.input-group-clear');
if (clearIcon) {
clearIcon.style.display = display;
}
}
function onClearValue($event: Event) {
const flag1 = !props.readonly && !props.disable && props.editable;
const flag2 = !props.editable;
$event.stopPropagation();
if (flag1 || flag2) {
onTextBoxValueChange('', false);
hasShownClearButton.value = false;
context.emit('clear');
}
}
function onMouseEnterTextBox($event: Event) {
if (this.value) {
if (!props.editable) {
if (!props.disable) {
hasShownClearButton.value = true;
}
} else if (!props.readonly && !props.disable) {
hasShownClearButton.value = true;
}
}
if (hasShownClearButton.value) {
this.toggleClearIcon($event, true);
}
}
function onMouseLeaveTextBox($event: Event) {
hasShownClearButton.value = false;
toggleClearIcon($event, false);
}
return {
showClearButton,
onClearValue,
onMouseEnterTextBox,
onMouseLeaveTextBox,
};
}

View File

@ -0,0 +1,90 @@
import { isContext } from 'vm';
import { computed, ref, SetupContext, watch } from 'vue';
import { ButtonEditProps } from '../button-edit.props';
import { UseTextBox } from './types';
export function useTextBox(props: ButtonEditProps, context: SetupContext): UseTextBox {
const textBoxTitle = computed(() => (props.enableTitle ? props.modelValue : ''));
const textBoxPlaceholder = computed(() => ((props.disable || props.readonly) && !props.forcePlaceholder ? '' : props.placeholder));
const isTextBoxReadonly = computed(() => props.readonly || !props.editable);
let focusState = false;
const hasFocusedTextBox = computed(() => focusState);
const textBoxClass = computed(() => ({
'text-left': props.textAlign === 'left',
'text-center': props.textAlign === 'center',
'text-right': props.textAlign === 'right',
'form-control': true,
'f-utils-fill': true,
}));
watch(
() => props.modelValue,
(value: string) => context.emit('change', value)
);
function onBlurTextBox($event: Event) {
focusState = false;
context.emit('blur', $event);
$event.stopPropagation();
}
function onClickTextBox($event: Event) {
context.emit('click', $event);
}
function onFocusTextBox($event: Event) {
if (props.disable) {
return;
}
focusState = true;
if (!isTextBoxReadonly.value) {
context.emit('focus', $event);
}
}
function onInput($event: Event) {
context.emit('input', ($event.target as HTMLInputElement).value);
context.emit('update:modelValue', ($event.target as HTMLInputElement).value);
}
function onMouseDownTextBox($event: MouseEvent) {
const target = $event.target as HTMLElement;
if (target.tagName !== 'INPUT') {
$event.preventDefault();
}
$event.stopPropagation();
}
function onMouseOverTextBox($event: Event) {
console.log('on onMouseOverInExtentInfo');
}
function onTextBoxValueChange(newValue: string, emit = true) {
if (props.modelValue !== newValue) {
props.modelValue = newValue;
if (emit) {
context.emit('change', newValue);
}
}
}
return {
hasFocusedTextBox,
isTextBoxReadonly,
textBoxClass,
textBoxPlaceholder,
textBoxTitle,
onBlurTextBox,
onClickTextBox,
onFocusTextBox,
onInput,
onMouseDownTextBox,
onMouseOverTextBox,
onTextBoxValueChange,
};
}

View File

@ -1,27 +0,0 @@
import { ComputedRef } from 'vue';
export interface UseAppendButton {
inputGroupAppendClass: ComputedRef<Record<string, boolean | undefined>>;
onClickAppendButton: ($event: Event) => void;
onMouseEnterIcon: ($event: MouseEvent) => void;
onMouseLeaveIcon: ($event: MouseEvent) => void;
}
export interface UseClear {
showClearButton: ComputedRef<boolean>;
onClearValue: ($event: Event) => void;
}
export interface UseTextBox {
isTextBoxReadonly: ComputedRef<boolean>;
textBoxClass: ComputedRef<Record<string, boolean | undefined>>;
textBoxPlaceholder: ComputedRef<string>;
textBoxTitle: ComputedRef<string>;
onBlurTextBox: ($event: Event) => void;
onClickTextBox: ($event: Event) => void;
onEnterTextBox: ($event: KeyboardEvent) => void;
onFocusTextBox: ($event: Event) => void;
onMouseDownTextBox: ($event: MouseEvent) => void;
onMouseOverTextBox: ($event: Event) => void;
onTextBoxValueChange: (value: string, emit: boolean) => void;
}

View File

@ -1,27 +0,0 @@
import { computed, SetupContext } from 'vue';
import { InputGroupProps } from '../input-group.props';
export function useAppendButton(props: InputGroupProps, setupContext: SetupContext) {
const inputGroupAppendClass = computed(() => ({
'input-group-append': true,
'append-force-show': props.showButtonWhenDisabled && (props.readonly || props.disable),
}));
function onMouseEnterIcon(e: MouseEvent) {
console.log('on onIconMouseEnter');
}
function onMouseLeaveIcon(e: MouseEvent) {
console.log('on onIconMouseLeave');
}
function onClickAppendButton(event: Event) {
console.log('on onClickHandle');
}
return {
inputGroupAppendClass,
onClickAppendButton,
onMouseEnterIcon,
onMouseLeaveIcon
};
}

View File

@ -1,16 +0,0 @@
import { computed, SetupContext } from 'vue';
import { InputGroupProps } from '../input-group.props';
import { UseClear } from './types';
export function useClear(props: InputGroupProps, setupContext: SetupContext): UseClear {
const showClearButton = computed(() => props.enableClear && !props.readonly && !props.disable);
function onClearValue($event: Event) {
console.log('on onClearValue');
}
return {
showClearButton,
onClearValue
};
}

View File

@ -1,61 +0,0 @@
import { computed, SetupContext } from 'vue';
import { InputGroupProps } from '../input-group.props';
import { UseTextBox } from './types';
export function useTextBox(props: InputGroupProps, setupContext: SetupContext): UseTextBox {
const textBoxTitle = computed(() => (props.enableTitle ? '' : ''));
const textBoxPlaceholder = computed(() => ((props.disable || props.readonly) && !props.forcePlaceholder ? '' : props.placeholder));
const isTextBoxReadonly = computed(() => props.readonly || !props.editable);
const textBoxClass = computed(() => ({
'text-left': props.textAlign === 'left',
'text-center': props.textAlign === 'center',
'text-right': props.textAlign === 'right',
'form-control': true,
'f-utils-fill': true,
}));
function onBlurTextBox($event: Event) {
console.log('on blur');
}
function onClickTextBox($event: Event) {
console.log('on onInputClick');
}
function onEnterTextBox($event: KeyboardEvent) {
console.log('on onEnter');
}
function onFocusTextBox($event: Event) {
console.log('on onInputFocus');
}
function onMouseDownTextBox($event: MouseEvent) {
console.log('on onMousedown');
}
function onMouseOverTextBox($event: Event) {
console.log('on onMouseOverInExtentInfo');
}
function onTextBoxValueChange(val: string, emit = true) {
console.log('on onValueChange');
}
return {
isTextBoxReadonly,
textBoxClass,
textBoxPlaceholder,
textBoxTitle,
onBlurTextBox,
onClickTextBox,
onEnterTextBox,
onFocusTextBox,
onMouseDownTextBox,
onMouseOverTextBox,
onTextBoxValueChange
};
}

View File

@ -2,8 +2,8 @@
// This starter template is using Vue 3 <script setup> SFCs
// Check out https://vuejs.org/api/sfc-script-setup.html#script-setup
import { ref } from "vue";
import HelloWorld from './components/hello-world.vue'
import InputGroup from "../components/input-group/src/input-group.component";
import HelloWorld from './components/hello-world.vue';
import ButtonEdit from "../components/button-edit/src/button-edit.component";
const canEdit = ref(true);
const canAutoComplete = ref(false);
@ -24,7 +24,7 @@ const canAutoComplete = ref(false);
<input type="checkbox" id="checkbox" v-model="canAutoComplete" />
<label for="checkbox">auto complete:{{ canAutoComplete }}</label>
<HelloWorld msg="Vite + Vue" />
<InputGroup :editable="canEdit" :auto-complete="canAutoComplete" :enable-clear="true"></InputGroup>
<ButtonEdit :editable="canEdit" :auto-complete="canAutoComplete" :enable-clear="true"></ButtonEdit>
</template>
<style scoped>