init
This commit is contained in:
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,145 @@
|
||||
<script lang="ts">
|
||||
import "./index.less";
|
||||
import {
|
||||
computed,
|
||||
Comment,
|
||||
VNode,
|
||||
Fragment,
|
||||
isVNode,
|
||||
createTextVNode,
|
||||
StyleValue,
|
||||
defineComponent,
|
||||
PropType,
|
||||
h,
|
||||
renderSlot,
|
||||
} from "vue";
|
||||
|
||||
type SpaceSize = "lg" | "md" | "sm" | "xs" | number | string;
|
||||
|
||||
export default defineComponent({
|
||||
name: "LaySpace",
|
||||
props: {
|
||||
align: {
|
||||
type: String as PropType<"start" | "end" | "center" | "baseline">,
|
||||
},
|
||||
direction: {
|
||||
type: String as PropType<"horizontal" | "vertical">,
|
||||
default: "horizontal",
|
||||
},
|
||||
fill: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
size: {
|
||||
type: [Number, String, Array] as PropType<
|
||||
SpaceSize | [SpaceSize, SpaceSize]
|
||||
>,
|
||||
default: "sm",
|
||||
},
|
||||
wrap: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
|
||||
setup(props, { slots }) {
|
||||
const computAlign = computed(
|
||||
() => props.align ?? (props.direction === "horizontal" ? "center" : "")
|
||||
);
|
||||
|
||||
const spaceClass = computed(() => [
|
||||
"layui-space",
|
||||
{
|
||||
[`layui-space-align-${computAlign.value}`]: computAlign.value,
|
||||
[`layui-space-${props.direction}`]: props.direction,
|
||||
[`layui-space-wrap`]: props.wrap,
|
||||
[`layui-space-fill`]: props.fill,
|
||||
},
|
||||
]);
|
||||
|
||||
const spaceStyle = computed<StyleValue>(() => {
|
||||
const sizeMap = { xs: "4px", sm: "8px", md: "16px", lg: "24px" };
|
||||
let gap = "";
|
||||
|
||||
if (Array.isArray(props.size)) {
|
||||
gap = props.size
|
||||
.map((size) => {
|
||||
if (typeof size === "number") {
|
||||
return `${size}px`;
|
||||
}
|
||||
if (typeof size === "string") {
|
||||
return sizeMap[size as keyof Omit<SpaceSize, number>] || size;
|
||||
}
|
||||
return size;
|
||||
})
|
||||
.join(" ");
|
||||
} else if (typeof props.size === "string") {
|
||||
gap =
|
||||
sizeMap[props.size as keyof Omit<SpaceSize, string | number>] ||
|
||||
props.size;
|
||||
} else if (typeof props.size === "number") {
|
||||
gap = `${props.size}px`;
|
||||
}
|
||||
|
||||
return {
|
||||
gap,
|
||||
};
|
||||
});
|
||||
|
||||
const itemStyle = computed<StyleValue>(() => [
|
||||
props.fill ? { flexGrow: 1, minWidth: "100%" } : {},
|
||||
]);
|
||||
|
||||
const extractChildren = () => {
|
||||
const result: VNode[] = [];
|
||||
const children = renderSlot(slots, "default").children;
|
||||
const elementData = Array.isArray(children) ? [...children] : [];
|
||||
|
||||
while (elementData.length) {
|
||||
const vnode = elementData.shift();
|
||||
|
||||
if (vnode === null) continue;
|
||||
|
||||
if (Array.isArray(vnode)) {
|
||||
elementData.unshift(...vnode);
|
||||
}
|
||||
|
||||
if (!isVNode(vnode) || vnode.type === Comment) continue;
|
||||
|
||||
if (vnode.type === Fragment && Array.isArray(vnode.children)) {
|
||||
elementData.unshift(vnode.children);
|
||||
} else if (typeof vnode === "string" || typeof vnode === "number") {
|
||||
result.push(createTextVNode(vnode));
|
||||
} else {
|
||||
result.push(vnode);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
return () => {
|
||||
const children = extractChildren();
|
||||
|
||||
return h(
|
||||
"div",
|
||||
{
|
||||
class: spaceClass.value,
|
||||
style: spaceStyle.value,
|
||||
},
|
||||
children.map((child, index) => {
|
||||
return h(
|
||||
"div",
|
||||
{
|
||||
key: child.key ?? `item-${index}`,
|
||||
class: "layui-space-item",
|
||||
style: itemStyle.value,
|
||||
},
|
||||
h(child)
|
||||
);
|
||||
})
|
||||
);
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
@@ -0,0 +1,96 @@
|
||||
::: anchor
|
||||
:::
|
||||
|
||||
::: title 基本介绍
|
||||
:::
|
||||
|
||||
::: describe 预览图片。
|
||||
:::
|
||||
|
||||
::: title 基本使用
|
||||
:::
|
||||
|
||||
::: demo
|
||||
|
||||
<template>
|
||||
<lay-button type="primary" @click="signleImg">图片查看</lay-button>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { layer } from "@layui/layui-vue"
|
||||
|
||||
const signleImg = function() {
|
||||
layer.photos("http://www.pearadmin.com/assets/images/un1.svg")
|
||||
}
|
||||
</script>
|
||||
|
||||
:::
|
||||
|
||||
::: title 设置标题
|
||||
:::
|
||||
|
||||
::: demo
|
||||
|
||||
<template>
|
||||
<lay-button type="primary" @click="signleImg2">图片标题</lay-button>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { layer } from "@layui/layui-vue"
|
||||
|
||||
const signleImg2 = function() {
|
||||
layer.photos({
|
||||
imgList:[{src:'http://www.pearadmin.com/assets/images/un2.svg',alt:'layer for vue'}]
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
:::
|
||||
|
||||
::: title 图片分组
|
||||
:::
|
||||
|
||||
::: demo
|
||||
|
||||
<template>
|
||||
<lay-button type="primary" @click="groupImg">图片分组</lay-button>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { layer } from "@layui/layui-vue"
|
||||
|
||||
const groupImg = function() {
|
||||
layer.photos({
|
||||
imgList:[
|
||||
{ src:'http://www.pearadmin.com/assets/images/un8.svg', alt:'图片1'},
|
||||
{ src:'http://www.pearadmin.com/assets/images/un32.svg', alt:'图片2'}
|
||||
]
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
:::
|
||||
|
||||
::: title 组件方法
|
||||
:::
|
||||
|
||||
```
|
||||
layer.photos(options)
|
||||
```
|
||||
|
||||
::: title 组件属性
|
||||
:::
|
||||
|
||||
::: table
|
||||
|
||||
| 属性 | 描述 | 备注 |
|
||||
| ------------------- | ------ | ----|
|
||||
| options | 选配属性 | { time: 加载时长, icon: 图标 } |
|
||||
|
||||
:::
|
||||
|
||||
::: contributor msg
|
||||
:::
|
||||
|
||||
::: previousNext msg
|
||||
:::
|
||||
@@ -0,0 +1,13 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# An example hook script to verify what is about to be committed.
|
||||
# Called by "git merge" with no arguments. The hook should
|
||||
# exit with non-zero status after issuing an appropriate message to
|
||||
# stderr if it wants to stop the merge commit.
|
||||
#
|
||||
# To enable this hook, rename this file to "pre-merge-commit".
|
||||
|
||||
. git-sh-setup
|
||||
test -x "$GIT_DIR/hooks/pre-commit" &&
|
||||
exec "$GIT_DIR/hooks/pre-commit"
|
||||
:
|
||||
@@ -0,0 +1,107 @@
|
||||
<script lang="ts">
|
||||
export default {
|
||||
name: "LayTextarea",
|
||||
};
|
||||
</script>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { LayIcon } from "@layui/icons-vue";
|
||||
import { computed, ref } from "vue";
|
||||
import "./index.less";
|
||||
|
||||
export interface TextareaProps {
|
||||
name?: string;
|
||||
modelValue?: string;
|
||||
placeholder?: string;
|
||||
disabled?: boolean;
|
||||
showCount?: boolean;
|
||||
allowClear?: boolean;
|
||||
maxlength?: number;
|
||||
}
|
||||
|
||||
const props = defineProps<TextareaProps>();
|
||||
|
||||
interface TextareaEmits {
|
||||
(e: "blur", event: Event): void;
|
||||
(e: "input", value: string): void;
|
||||
(e: "update:modelValue", value: string): void;
|
||||
(e: "change", value: string): void;
|
||||
(e: "focus", event: Event): void;
|
||||
(e: "clear"): void;
|
||||
}
|
||||
|
||||
const emit = defineEmits<TextareaEmits>();
|
||||
const composing = ref(false);
|
||||
|
||||
const onInput = function (event: Event) {
|
||||
const inputElement = event.target as HTMLInputElement;
|
||||
emit("input", inputElement.value);
|
||||
if (composing.value) {
|
||||
return;
|
||||
}
|
||||
emit("update:modelValue", inputElement.value);
|
||||
};
|
||||
|
||||
const onFocus = function (event: Event) {
|
||||
emit("focus", event);
|
||||
};
|
||||
|
||||
const onBlur = function (event: Event) {
|
||||
emit("blur", event);
|
||||
};
|
||||
|
||||
const onChange = (event: Event) => {
|
||||
const inputElement = event.target as HTMLInputElement;
|
||||
emit("change", inputElement.value);
|
||||
};
|
||||
|
||||
const onClear = function () {
|
||||
emit("update:modelValue", "");
|
||||
emit("clear");
|
||||
};
|
||||
|
||||
const onCompositionstart = () => {
|
||||
composing.value = true;
|
||||
};
|
||||
|
||||
const onCompositionend = (event: Event) => {
|
||||
composing.value = false;
|
||||
onInput(event);
|
||||
};
|
||||
|
||||
const hasContent = computed(() => (props.modelValue as string)?.length > 0);
|
||||
|
||||
const wordCount = computed(() => {
|
||||
let count = String(props.modelValue?.length ?? 0);
|
||||
if (props.maxlength) {
|
||||
count += "/" + props.maxlength;
|
||||
}
|
||||
return count;
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="layui-textarea-wrapper">
|
||||
<textarea
|
||||
class="layui-textarea"
|
||||
:value="modelValue"
|
||||
:placeholder="placeholder"
|
||||
:name="name"
|
||||
:disabled="disabled"
|
||||
:maxlength="maxlength"
|
||||
:class="{ 'layui-textarea-disabled': disabled }"
|
||||
@compositionstart="onCompositionstart"
|
||||
@compositionend="onCompositionend"
|
||||
@input="onInput"
|
||||
@focus="onFocus"
|
||||
@change="onChange"
|
||||
@blur="onBlur"
|
||||
></textarea>
|
||||
<span class="layui-textarea-clear" v-if="allowClear && hasContent">
|
||||
<lay-icon type="layui-icon-close-fill" @click="onClear"></lay-icon>
|
||||
</span>
|
||||
<div v-if="showCount" class="layui-texterea-count">
|
||||
{{ wordCount }}
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
Reference in New Issue
Block a user