feature: implement notify component
This commit is contained in:
parent
2bb868f4c8
commit
38d56ff5f4
|
@ -6,104 +6,107 @@ import { useClear } from './composition/use-clear';
|
||||||
import { useTextBox } from './composition/use-text-box';
|
import { useTextBox } from './composition/use-text-box';
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: 'FButtonEdit',
|
name: 'FButtonEdit',
|
||||||
props: buttonEditProps,
|
props: buttonEditProps,
|
||||||
emits: [
|
emits: [
|
||||||
'updateExtendInfo',
|
'updateExtendInfo',
|
||||||
'clear',
|
'clear',
|
||||||
'change',
|
'change',
|
||||||
'click',
|
'click',
|
||||||
'clickButton',
|
'clickButton',
|
||||||
'blur',
|
'blur',
|
||||||
'focus',
|
'focus',
|
||||||
'mouseEnterIcon',
|
'mouseEnterIcon',
|
||||||
'mouseLeaveIcon',
|
'mouseLeaveIcon',
|
||||||
'keyup',
|
'keyup',
|
||||||
'keydown',
|
'keydown',
|
||||||
'inputClick',
|
'inputClick',
|
||||||
'input',
|
'input',
|
||||||
'update:modelValue',
|
'update:modelValue',
|
||||||
],
|
],
|
||||||
setup(props: ButtonEditProps, context: SetupContext) {
|
setup(props: ButtonEditProps, context: SetupContext) {
|
||||||
const modelValue = ref(props.modelValue);
|
const modelValue = ref(props.modelValue);
|
||||||
const { buttonClass, onClickButton, onMouseEnterButton, onMouseLeaveButton } = useButton(props, context);
|
const { buttonClass, onClickButton, onMouseEnterButton, onMouseLeaveButton } = useButton(props, context);
|
||||||
const displayText = ref('');
|
const displayText = ref('');
|
||||||
const {
|
const {
|
||||||
hasFocusedTextBox,
|
hasFocusedTextBox,
|
||||||
isTextBoxReadonly,
|
isTextBoxReadonly,
|
||||||
textBoxClass,
|
textBoxClass,
|
||||||
textBoxPlaceholder,
|
textBoxPlaceholder,
|
||||||
textBoxTitle,
|
textBoxTitle,
|
||||||
onBlurTextBox,
|
onBlurTextBox,
|
||||||
onClickTextBox,
|
onClickTextBox,
|
||||||
onFocusTextBox,
|
onFocusTextBox,
|
||||||
onInput,
|
onInput,
|
||||||
onKeyDownTextBox,
|
onKeyDownTextBox,
|
||||||
onKeyUpTextBox,
|
onKeyUpTextBox,
|
||||||
onMouseDownTextBox,
|
onMouseDownTextBox,
|
||||||
onTextBoxValueChange,
|
onTextBoxValueChange,
|
||||||
} = useTextBox(props, context, modelValue, displayText);
|
} = useTextBox(props, context, modelValue, displayText);
|
||||||
|
|
||||||
const { enableClearButton, showClearButton, onClearValue, onMouseEnterTextBox, onMouseLeaveTextBox } = useClear(
|
const { enableClearButton, showClearButton, onClearValue, onMouseEnterTextBox, onMouseLeaveTextBox } = useClear(
|
||||||
props,
|
props,
|
||||||
context,
|
context,
|
||||||
modelValue,
|
modelValue,
|
||||||
hasFocusedTextBox,
|
hasFocusedTextBox,
|
||||||
displayText
|
displayText
|
||||||
);
|
);
|
||||||
|
|
||||||
const inputGroupClass = computed(() => ({
|
const inputGroupClass = computed(() => ({
|
||||||
'input-group': true,
|
'input-group': true,
|
||||||
'f-state-disable': props.disable,
|
'f-state-disable': props.disable,
|
||||||
'f-state-editable': props.editable && !props.disable && !props.readonly,
|
'f-state-editable': props.editable && !props.disable && !props.readonly,
|
||||||
'f-state-readonly': props.readonly && !props.disable,
|
'f-state-readonly': props.readonly && !props.disable,
|
||||||
'f-state-focus': hasFocusedTextBox,
|
'f-state-focus': hasFocusedTextBox,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
return (
|
return (
|
||||||
<div class="f-cmp-inputgroup" id={props.id}>
|
<div class="f-cmp-inputgroup" id={props.id}>
|
||||||
<div class={[props.customClass, inputGroupClass.value]} onMouseenter={onMouseEnterTextBox} onMouseleave={onMouseLeaveTextBox}>
|
<div
|
||||||
<input
|
class={[props.customClass, inputGroupClass.value]}
|
||||||
name="input-group-value"
|
onMouseenter={onMouseEnterTextBox}
|
||||||
autocomplete={'' + props.autoComplete}
|
onMouseleave={onMouseLeaveTextBox}>
|
||||||
class={textBoxClass.value}
|
<input
|
||||||
disabled={props.disable}
|
name="input-group-value"
|
||||||
maxlength={props.maxLength}
|
autocomplete={'' + props.autoComplete}
|
||||||
minlength={props.minLength}
|
class={textBoxClass.value}
|
||||||
placeholder={textBoxPlaceholder.value}
|
disabled={props.disable}
|
||||||
readonly={isTextBoxReadonly.value}
|
maxlength={props.maxLength}
|
||||||
tabindex={props.tabIndex}
|
minlength={props.minLength}
|
||||||
title={textBoxTitle.value}
|
placeholder={textBoxPlaceholder.value}
|
||||||
type={props.inputType}
|
readonly={isTextBoxReadonly.value}
|
||||||
value={modelValue.value}
|
tabindex={props.tabIndex}
|
||||||
onBlur={onBlurTextBox}
|
title={textBoxTitle.value}
|
||||||
onChange={onTextBoxValueChange}
|
type={props.inputType}
|
||||||
onClick={onClickTextBox}
|
value={modelValue.value}
|
||||||
onFocus={onFocusTextBox}
|
onBlur={onBlurTextBox}
|
||||||
onInput={onInput}
|
onChange={onTextBoxValueChange}
|
||||||
onKeydown={onKeyDownTextBox}
|
onClick={onClickTextBox}
|
||||||
onKeyup={onKeyUpTextBox}
|
onFocus={onFocusTextBox}
|
||||||
onMousedown={onMouseDownTextBox}
|
onInput={onInput}
|
||||||
/>
|
onKeydown={onKeyDownTextBox}
|
||||||
<div class={buttonClass.value}>
|
onKeyup={onKeyUpTextBox}
|
||||||
{enableClearButton.value && (
|
onMousedown={onMouseDownTextBox}
|
||||||
<span class="input-group-text input-group-clear" v-show={showClearButton.value} onClick={onClearValue}>
|
/>
|
||||||
<i class="f-icon modal_close"></i>
|
<div class={buttonClass.value}>
|
||||||
</span>
|
{enableClearButton.value && (
|
||||||
)}
|
<span class="input-group-text input-group-clear" v-show={showClearButton.value} onClick={onClearValue}>
|
||||||
{props.buttonContent && (
|
<i class="f-icon modal_close"></i>
|
||||||
<span
|
</span>
|
||||||
class="input-group-text input-group-append-button"
|
)}
|
||||||
onClick={onClickButton}
|
{props.buttonContent && (
|
||||||
onMouseenter={onMouseEnterButton}
|
<span
|
||||||
onMouseleave={onMouseLeaveButton}
|
class="input-group-text input-group-append-button"
|
||||||
v-html={props.buttonContent}></span>
|
onClick={onClickButton}
|
||||||
)}
|
onMouseenter={onMouseEnterButton}
|
||||||
</div>
|
onMouseleave={onMouseLeaveButton}
|
||||||
</div>
|
v-html={props.buttonContent}></span>
|
||||||
</div>
|
)}
|
||||||
);
|
</div>
|
||||||
};
|
</div>
|
||||||
},
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
|
@ -3,79 +3,79 @@ import { ExtractPropTypes, PropType } from 'vue';
|
||||||
type TextAlignment = 'left' | 'center' | 'right';
|
type TextAlignment = 'left' | 'center' | 'right';
|
||||||
|
|
||||||
export const buttonEditProps = {
|
export const buttonEditProps = {
|
||||||
/**
|
/**
|
||||||
* 组件标识
|
* 组件标识
|
||||||
*/
|
*/
|
||||||
id: String,
|
id: String,
|
||||||
/**
|
/**
|
||||||
* 扩展按钮显示内容,这是一段现在扩展按钮中的html标签
|
* 扩展按钮显示内容,这是一段现在扩展按钮中的html标签
|
||||||
*/
|
*/
|
||||||
buttonContent: { type: String, default: '<i class="f-icon f-icon-lookup"></i>' },
|
buttonContent: { type: String, default: '<i class="f-icon f-icon-lookup"></i>' },
|
||||||
/**
|
/**
|
||||||
* 启用输入框自动完成功能
|
* 启用输入框自动完成功能
|
||||||
*/
|
*/
|
||||||
autoComplete: { type: Boolean, default: false },
|
autoComplete: { type: Boolean, default: false },
|
||||||
/**
|
/**
|
||||||
* 组件自定义样式
|
* 组件自定义样式
|
||||||
*/
|
*/
|
||||||
customClass: { type: String, default: '' },
|
customClass: { type: String, default: '' },
|
||||||
/**
|
/**
|
||||||
* 禁用组件,既不允许在输入框中录入,也不允许点击扩展按钮。
|
* 禁用组件,既不允许在输入框中录入,也不允许点击扩展按钮。
|
||||||
*/
|
*/
|
||||||
disable: { type: Boolean, default: false },
|
disable: { type: Boolean, default: false },
|
||||||
/**
|
/**
|
||||||
* 允许在输入框中录入文本。
|
* 允许在输入框中录入文本。
|
||||||
*/
|
*/
|
||||||
editable: { type: Boolean, default: true },
|
editable: { type: Boolean, default: true },
|
||||||
/**
|
/**
|
||||||
* 显示清空文本按钮
|
* 显示清空文本按钮
|
||||||
*/
|
*/
|
||||||
enableClear: { type: Boolean, default: false },
|
enableClear: { type: Boolean, default: false },
|
||||||
/**
|
/**
|
||||||
* 组件值
|
* 组件值
|
||||||
*/
|
*/
|
||||||
modelValue:{type:String,default:''},
|
modelValue: { type: String, default: '' },
|
||||||
/**
|
/**
|
||||||
* 将组件设置为只读,既不允许在输入框中录入,也不允许点击扩展按钮,但是允许复制输入框中的内容。
|
* 将组件设置为只读,既不允许在输入框中录入,也不允许点击扩展按钮,但是允许复制输入框中的内容。
|
||||||
*/
|
*/
|
||||||
readonly: { type: Boolean, default: false },
|
readonly: { type: Boolean, default: false },
|
||||||
/**
|
/**
|
||||||
* 文本对齐方式
|
* 文本对齐方式
|
||||||
*/
|
*/
|
||||||
textAlign: { type: String as PropType<TextAlignment>, default: 'left' },
|
textAlign: { type: String as PropType<TextAlignment>, default: 'left' },
|
||||||
/**
|
/**
|
||||||
* 禁用组件时,是否显示扩展按钮
|
* 禁用组件时,是否显示扩展按钮
|
||||||
*/
|
*/
|
||||||
showButtonWhenDisabled: { type: Boolean, default: false },
|
showButtonWhenDisabled: { type: Boolean, default: false },
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 显示输入框的标签
|
* 显示输入框的标签
|
||||||
*/
|
*/
|
||||||
enableTitle: { type: Boolean, default: false },
|
enableTitle: { type: Boolean, default: false },
|
||||||
/**
|
/**
|
||||||
* 输入框类型
|
* 输入框类型
|
||||||
*/
|
*/
|
||||||
inputType: { type: String, default: 'text' },
|
inputType: { type: String, default: 'text' },
|
||||||
/**
|
/**
|
||||||
* 显示输入框提示信息
|
* 显示输入框提示信息
|
||||||
*/
|
*/
|
||||||
forcePlaceholder: { type: Boolean, default: false },
|
forcePlaceholder: { type: Boolean, default: false },
|
||||||
/**
|
/**
|
||||||
* 输入框提示文本
|
* 输入框提示文本
|
||||||
*/
|
*/
|
||||||
placeholder: { type: String, default: '' },
|
placeholder: { type: String, default: '' },
|
||||||
/**
|
/**
|
||||||
* 输入框最小长度
|
* 输入框最小长度
|
||||||
*/
|
*/
|
||||||
minLength: Number,
|
minLength: Number,
|
||||||
/**
|
/**
|
||||||
* 输入框最大长度
|
* 输入框最大长度
|
||||||
*/
|
*/
|
||||||
maxLength: Number,
|
maxLength: Number,
|
||||||
/**
|
/**
|
||||||
* 输入框Tab键索引
|
* 输入框Tab键索引
|
||||||
*/
|
*/
|
||||||
tabIndex: Number,
|
tabIndex: Number,
|
||||||
};
|
};
|
||||||
|
|
||||||
export type ButtonEditProps = ExtractPropTypes<typeof buttonEditProps>;
|
export type ButtonEditProps = ExtractPropTypes<typeof buttonEditProps>;
|
||||||
|
|
|
@ -3,37 +3,37 @@ import { computed, SetupContext } from 'vue';
|
||||||
import { ButtonEditProps } from '../button-edit.props';
|
import { ButtonEditProps } from '../button-edit.props';
|
||||||
|
|
||||||
export function useButton(props: ButtonEditProps, context: SetupContext): UseButton {
|
export function useButton(props: ButtonEditProps, context: SetupContext): UseButton {
|
||||||
const buttonClass = computed(() => ({
|
const buttonClass = computed(() => ({
|
||||||
'input-group-append': true,
|
'input-group-append': true,
|
||||||
'append-force-show': props.showButtonWhenDisabled && (props.readonly || props.disable),
|
'append-force-show': props.showButtonWhenDisabled && (props.readonly || props.disable),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const canClickAppendButton = computed(() => props.showButtonWhenDisabled || ((!props.editable || !props.readonly) && !props.disable));
|
const canClickAppendButton = computed(() => props.showButtonWhenDisabled || ((!props.editable || !props.readonly) && !props.disable));
|
||||||
|
|
||||||
function onClickButton($event: Event) {
|
function onClickButton($event: Event) {
|
||||||
if (canClickAppendButton.value) {
|
if (canClickAppendButton.value) {
|
||||||
context.emit('clickButton', { origin: $event, value: props.modelValue });
|
context.emit('clickButton', { origin: $event, value: props.modelValue });
|
||||||
|
}
|
||||||
|
$event.stopPropagation();
|
||||||
}
|
}
|
||||||
$event.stopPropagation();
|
|
||||||
}
|
|
||||||
|
|
||||||
function onMouseEnterButton($event: MouseEvent) {
|
function onMouseEnterButton($event: MouseEvent) {
|
||||||
context.emit('mouseEnterIcon', $event);
|
context.emit('mouseEnterIcon', $event);
|
||||||
}
|
}
|
||||||
|
|
||||||
function onMouseLeaveButton($event: MouseEvent) {
|
function onMouseLeaveButton($event: MouseEvent) {
|
||||||
context.emit('mouseLeaveIcon', $event);
|
context.emit('mouseLeaveIcon', $event);
|
||||||
}
|
}
|
||||||
|
|
||||||
function onMouseOverButton() {
|
function onMouseOverButton() {
|
||||||
context.emit('mouseOverButton');
|
context.emit('mouseOverButton');
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
buttonClass,
|
buttonClass,
|
||||||
onClickButton,
|
onClickButton,
|
||||||
onMouseEnterButton,
|
onMouseEnterButton,
|
||||||
onMouseLeaveButton,
|
onMouseLeaveButton,
|
||||||
onMouseOverButton,
|
onMouseOverButton,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,64 +4,64 @@ import { UseClear } from './types';
|
||||||
import { useTextBox } from './use-text-box';
|
import { useTextBox } from './use-text-box';
|
||||||
|
|
||||||
export function useClear(
|
export function useClear(
|
||||||
props: ButtonEditProps,
|
props: ButtonEditProps,
|
||||||
context: SetupContext,
|
context: SetupContext,
|
||||||
modelValue: Ref<string>,
|
modelValue: Ref<string>,
|
||||||
hasFocusedTextBox: ComputedRef<boolean>,
|
hasFocusedTextBox: ComputedRef<boolean>,
|
||||||
displayText: Ref<string>
|
displayText: Ref<string>
|
||||||
): UseClear {
|
): UseClear {
|
||||||
const showClearButton = ref(false);
|
const showClearButton = ref(false);
|
||||||
const enableClearButton = computed(() => props.enableClear && !props.readonly && !props.disable);
|
const enableClearButton = computed(() => props.enableClear && !props.readonly && !props.disable);
|
||||||
const { changeTextBoxValue } = useTextBox(props, context, modelValue, displayText);
|
const { changeTextBoxValue } = useTextBox(props, context, modelValue, displayText);
|
||||||
|
|
||||||
function toggleClearIcon(isShow: boolean) {
|
function toggleClearIcon(isShow: boolean) {
|
||||||
showClearButton.value = isShow;
|
showClearButton.value = isShow;
|
||||||
}
|
}
|
||||||
|
|
||||||
watch(displayText, () => {
|
watch(displayText, () => {
|
||||||
if (hasFocusedTextBox.value) {
|
if (hasFocusedTextBox.value) {
|
||||||
toggleClearIcon(!!displayText.value);
|
toggleClearIcon(!!displayText.value);
|
||||||
} else {
|
} else {
|
||||||
toggleClearIcon(false);
|
toggleClearIcon(false);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
function onClearValue($event: Event) {
|
function onClearValue($event: Event) {
|
||||||
const flag1 = !props.readonly && !props.disable && props.editable;
|
const flag1 = !props.readonly && !props.disable && props.editable;
|
||||||
const flag2 = !props.editable;
|
const flag2 = !props.editable;
|
||||||
$event.stopPropagation();
|
$event.stopPropagation();
|
||||||
if (flag1 || flag2) {
|
if (flag1 || flag2) {
|
||||||
changeTextBoxValue('', false);
|
changeTextBoxValue('', false);
|
||||||
toggleClearIcon(!showClearButton.value);
|
toggleClearIcon(!showClearButton.value);
|
||||||
context.emit('clear');
|
context.emit('clear');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
function onMouseEnterTextBox($event: Event) {
|
function onMouseEnterTextBox($event: Event) {
|
||||||
if (!enableClearButton.value) {
|
if (!enableClearButton.value) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
if (!modelValue.value) {
|
||||||
|
toggleClearIcon(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if ((!props.editable || !props.readonly) && !props.disable) {
|
||||||
|
toggleClearIcon(true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (!modelValue.value) {
|
|
||||||
toggleClearIcon(false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if ((!props.editable || !props.readonly) && !props.disable) {
|
|
||||||
toggleClearIcon(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function onMouseLeaveTextBox($event: Event) {
|
function onMouseLeaveTextBox($event: Event) {
|
||||||
if (!enableClearButton.value) {
|
if (!enableClearButton.value) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
toggleClearIcon(false);
|
||||||
}
|
}
|
||||||
toggleClearIcon(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
enableClearButton,
|
enableClearButton,
|
||||||
showClearButton,
|
showClearButton,
|
||||||
onClearValue,
|
onClearValue,
|
||||||
onMouseEnterTextBox,
|
onMouseEnterTextBox,
|
||||||
onMouseLeaveTextBox,
|
onMouseLeaveTextBox,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,59 +1,118 @@
|
||||||
import { computed, defineComponent, SetupContext } from 'vue';
|
import { computed, defineComponent, ref, SetupContext, watch } from 'vue';
|
||||||
import { NotifyData } from '../notify.props';
|
import { NotifyButton, NotifyData } from '../notify.props';
|
||||||
import { ToastProps, toastProps } from './toast.props';
|
import { ToastProps, toastProps } from './toast.props';
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: 'Toast',
|
name: 'Toast',
|
||||||
props: toastProps,
|
props: toastProps,
|
||||||
emits: [],
|
emits: ['close', 'click'],
|
||||||
setup: (props: ToastProps, context: SetupContext) => {
|
setup: (props: ToastProps, context: SetupContext) => {
|
||||||
const toastClass = computed(() => ({
|
const animateIn = ref(props.animate);
|
||||||
toast: true,
|
const animateEnd = 'fadeOut';
|
||||||
}));
|
const toast = computed(() => {
|
||||||
|
return props.options as NotifyData;
|
||||||
|
});
|
||||||
|
const showingToast = ref(false);
|
||||||
|
|
||||||
const toast = computed(() => {
|
const toastClass = computed(() => {
|
||||||
return {} as NotifyData;
|
const classObject = {
|
||||||
});
|
animated: showingToast.value,
|
||||||
|
toast: true,
|
||||||
|
};
|
||||||
|
classObject[props.animate] = false;
|
||||||
|
classObject[animateEnd] = showingToast.value;
|
||||||
|
classObject[toast.value.type] = true;
|
||||||
|
if (toast.value.theme) {
|
||||||
|
classObject[toast.value.theme] = true;
|
||||||
|
}
|
||||||
|
return classObject;
|
||||||
|
});
|
||||||
|
|
||||||
const toastIconClass = computed(() => ({
|
const toastIconClass = computed(() => {
|
||||||
'f-icon': true,
|
const hasSpecialToastType = toast.value && toast.value.type;
|
||||||
}));
|
const iconType = hasSpecialToastType ? toast.value.type.replace('toasty-type-', '') : 'default';
|
||||||
|
const iconTypeName = `f-icon-${iconType}`;
|
||||||
|
const classObject = { 'f-icon': true };
|
||||||
|
classObject[iconTypeName] = true;
|
||||||
|
return classObject;
|
||||||
|
});
|
||||||
|
|
||||||
const shouldShowTips = computed(() => toast.value.title || toast.value.msg);
|
const shouldShowTips = computed(() => toast.value.title || toast.value.msg);
|
||||||
|
|
||||||
const shouldShowTitle = computed(() => toast.value.title && toast.value.msg);
|
const shouldShowTitle = computed(() => toast.value.title && toast.value.msg);
|
||||||
|
|
||||||
const shouldShowCloseButton = computed(() => {
|
const shouldShowCloseButton = computed(() => {
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
|
|
||||||
function onCloseToast($event: Event) {}
|
const shouldShowButtonsInTitle = computed(() => !!toast.value.buttons || !!context.slots.default);
|
||||||
|
|
||||||
return () => {
|
function onCloseToast($event: Event) {
|
||||||
return (
|
$event.stopPropagation();
|
||||||
<div class={toastClass}>
|
$event.preventDefault();
|
||||||
{shouldShowCloseButton.value && (
|
showingToast.value = false;
|
||||||
<button class="toast-close f-btn-icon f-bare" onClick={onCloseToast}>
|
setTimeout(() => {
|
||||||
<span class="f-icon modal_close"></span>
|
context.emit('close', toast.value);
|
||||||
</button>
|
}, 200);
|
||||||
)}
|
}
|
||||||
{shouldShowTips.value && (
|
|
||||||
<section class="modal-tips">
|
function onClickButton($event: Event, notifyButton: NotifyButton) {}
|
||||||
<div class="float-left modal-tips-iconwrap">
|
|
||||||
<span class={toastIconClass}></span>
|
function getNotifyButtonClass(notifyButton: NotifyButton) {
|
||||||
</div>
|
return `f-preten-link ${notifyButton.customClass ? notifyButton.customClass : ''}`;
|
||||||
<div class="modal-tips-content">
|
}
|
||||||
{shouldShowTitle.value && (
|
|
||||||
<>
|
watch(animateIn, () => {
|
||||||
<h5 class="toast-title modal-tips-title" v-html={toast.value.title}></h5>
|
const animateInClass = animateIn.value || 'bounceInRight';
|
||||||
<p class="toast-msg" v-html={toast.value.msg}></p>
|
const animateOutClass = 'fadeOut';
|
||||||
</>
|
});
|
||||||
)}
|
|
||||||
</div>
|
const renderNotifyButtons = () => {
|
||||||
</section>
|
return (
|
||||||
)}
|
<>
|
||||||
</div>
|
<div class="after-toast-msg text-right">
|
||||||
);
|
{!context.slots.default &&
|
||||||
};
|
toast.value.buttons?.map((notifyButton: NotifyButton) => {
|
||||||
},
|
return (
|
||||||
|
<span
|
||||||
|
class={getNotifyButtonClass(notifyButton)}
|
||||||
|
onClick={($event) => onClickButton($event, notifyButton)}>
|
||||||
|
{notifyButton.text}
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
{context.slots.default && context.slots.default()}
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
return (
|
||||||
|
<div class={toastClass}>
|
||||||
|
{shouldShowCloseButton.value && (
|
||||||
|
<button class="toast-close f-btn-icon f-bare" onClick={onCloseToast}>
|
||||||
|
<span class="f-icon modal_close"></span>
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
|
{shouldShowTips.value && (
|
||||||
|
<section class="modal-tips">
|
||||||
|
<div class="float-left modal-tips-iconwrap">
|
||||||
|
<span class={toastIconClass}></span>
|
||||||
|
</div>
|
||||||
|
<div class="modal-tips-content">
|
||||||
|
{shouldShowTitle.value && (
|
||||||
|
<>
|
||||||
|
<h5 class="toast-title modal-tips-title" v-html={toast.value.title}></h5>
|
||||||
|
<p class="toast-msg" v-html={toast.value.msg}></p>
|
||||||
|
{shouldShowButtonsInTitle.value && renderNotifyButtons()}
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
import { ExtractPropTypes, PropType } from 'vue';
|
import { ExtractPropTypes, PropType } from 'vue';
|
||||||
import { ToastyAnimate } from '../notify.props';
|
import { NotifyData, ToastyAnimate } from '../notify.props';
|
||||||
|
|
||||||
export const toastProps = {
|
export const toastProps = {
|
||||||
animate: { type: String as PropType<ToastyAnimate>, default: 'fadeIn' },
|
animate: { type: String as PropType<ToastyAnimate>, default: 'fadeIn' },
|
||||||
|
options: { type: Object as PropType<NotifyData> },
|
||||||
};
|
};
|
||||||
|
|
||||||
export type ToastProps = ExtractPropTypes<typeof toastProps>;
|
export type ToastProps = ExtractPropTypes<typeof toastProps>;
|
||||||
|
|
|
@ -1,35 +1,37 @@
|
||||||
import { computed, defineComponent, SetupContext } from 'vue';
|
import { computed, defineComponent, ref, SetupContext } from 'vue';
|
||||||
import { NotifyContainerComponent } from './notify-container.component';
|
import { NotifyContainerComponent } from './notify-container.component';
|
||||||
import { NotifyData, NotifyProps, notifyProps } from './notify.props';
|
import { NotifyData, NotifyProps, notifyProps } from './notify.props';
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: 'Notify',
|
name: 'Notify',
|
||||||
props: notifyProps,
|
props: notifyProps,
|
||||||
emits: [],
|
emits: [],
|
||||||
setup(props: NotifyProps, context: SetupContext) {
|
setup(props: NotifyProps, context: SetupContext) {
|
||||||
const notifyClass = computed(() => ({
|
const notifyClass = computed(() => ({
|
||||||
'farris-notify': true,
|
'farris-notify': true,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const notifyStyle = computed(() => ({
|
const notifyStyle = computed(() => ({
|
||||||
left: '',
|
left: '',
|
||||||
right: '',
|
right: '',
|
||||||
top: '',
|
top: '',
|
||||||
bottom: '',
|
bottom: '',
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const toasts = computed(() => {
|
const toasts = computed(() => {
|
||||||
return props.toasts ? props.toasts : [];
|
return props.toasts ? props.toasts : [];
|
||||||
});
|
});
|
||||||
|
|
||||||
return () => {
|
|
||||||
return (
|
|
||||||
<div id={props.id} class={notifyClass.value} style={notifyStyle.value}>
|
return () => {
|
||||||
{toasts.value.map((toastData: NotifyData) => {
|
return (
|
||||||
return <f-toast v-model={toastData} animate={props.animate} onClose={} onClick={}></f-toast>;
|
<div id={props.id} class={notifyClass.value} style={notifyStyle.value}>
|
||||||
})}
|
{toasts.value.map((toastData: NotifyData) => {
|
||||||
</div>
|
return <f-toast v-model={toastData} animate={props.animate} onClose={} onClick={}></f-toast>;
|
||||||
);
|
})}
|
||||||
};
|
</div>
|
||||||
},
|
);
|
||||||
|
};
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,44 +1,45 @@
|
||||||
|
import { NotifyData } from './notify.props';
|
||||||
import { ExtractPropTypes, PropType } from 'vue';
|
import { ExtractPropTypes, PropType } from 'vue';
|
||||||
|
|
||||||
export type NotifyPosition = 'bottom-right' | 'bottom-left' | 'top-right' | 'top-left' | 'top-center' | 'bottom-center' | 'center-center';
|
export type NotifyPosition = 'bottom-right' | 'bottom-left' | 'top-right' | 'top-left' | 'top-center' | 'bottom-center' | 'center-center';
|
||||||
|
|
||||||
export type ToastyAnimate =
|
export type ToastyAnimate =
|
||||||
| 'bounceInRight'
|
| 'bounceInRight'
|
||||||
| 'bounceInLeft'
|
| 'bounceInLeft'
|
||||||
| 'bounceInRight'
|
| 'bounceInRight'
|
||||||
| 'bounceInLeft'
|
| 'bounceInLeft'
|
||||||
| 'bounceInDown'
|
| 'bounceInDown'
|
||||||
| 'bounceInUp'
|
| 'bounceInUp'
|
||||||
| 'bounceIn'
|
| 'bounceIn'
|
||||||
| 'fadeIn';
|
| 'fadeIn';
|
||||||
|
|
||||||
export interface NotifyButton {
|
export interface NotifyButton {
|
||||||
customClass?: string;
|
customClass?: string;
|
||||||
text: string;
|
text: string;
|
||||||
disable?: boolean;
|
disable?: boolean;
|
||||||
onClick?: ($event: Event, component: any) => any;
|
onClick?: ($event: Event, component: any) => any;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface NotifyData {
|
export interface NotifyData {
|
||||||
type: string;
|
type: string;
|
||||||
title?: string;
|
title?: string;
|
||||||
msg?: string;
|
msg?: string;
|
||||||
/** 按钮列表模板 */
|
/** 按钮列表模板 */
|
||||||
buttons?: Array<NotifyButton>;
|
buttons?: Array<NotifyButton>;
|
||||||
showClose?: boolean;
|
showClose?: boolean;
|
||||||
theme?: string;
|
theme?: string;
|
||||||
timeout?: number;
|
timeout?: number;
|
||||||
onAdd?: () => void;
|
onAdd?: () => void;
|
||||||
onRemove?: () => void;
|
onRemove?: () => void;
|
||||||
id?: number | string;
|
id?: number | string;
|
||||||
}
|
}
|
||||||
|
|
||||||
// export interface NotifyData extends NotifyOptions {}
|
// export interface NotifyData extends NotifyOptions {}
|
||||||
|
|
||||||
export const notifyProps = {
|
export const notifyProps = {
|
||||||
id: { type: String },
|
id: { type: String },
|
||||||
animate: { type: String as PropType<ToastyAnimate>, default: 'fadeIn' },
|
animate: { type: String as PropType<ToastyAnimate>, default: 'fadeIn' },
|
||||||
position: { type: String as PropType<NotifyPosition>, default: 'toasty-position-top-center' },
|
position: { type: String as PropType<NotifyPosition>, default: 'toasty-position-top-center' },
|
||||||
toasts: { type: Array<NotifyData> },
|
toasts: { type: Array<NotifyData> },
|
||||||
};
|
};
|
||||||
export type NotifyProps = ExtractPropTypes<typeof notifyProps>;
|
export type NotifyProps = ExtractPropTypes<typeof notifyProps>;
|
||||||
|
|
Loading…
Reference in New Issue