This commit is contained in:
2022-11-14 11:56:21 +08:00
commit 0a63adba99
337 changed files with 25661 additions and 0 deletions

View File

@@ -0,0 +1,403 @@
@import "../dropdown/index.less";
@import "../popper/index.less";
.layui-nav .layui-show.layui-anim-upbit .layui-show.layui-anim-upbit {
top: 0px;
left: calc(100% + 5px);
}
.layui-nav .layui-show.layui-anim-upbit .left-nav.layui-show.layui-anim-upbit,
.layui-nav .layui-show.layui-anim-upbit .left-nav .layui-show.layui-anim-upbit {
top: 0px;
left: calc(-100% - 20px);
}
.layui-nav .layui-show.layui-anim-upbit .layui-nav-item {
height: 40px;
display: block;
line-height: 40px;
}
.layui-nav .layui-show.layui-anim-upbit .layui-nav-item.layui-this {
background-color: whitesmoke;
}
.layui-nav .layui-show.layui-anim-upbit .layui-nav-item.layui-this:after {
display: none;
}
.layui-nav {
position: relative;
padding: 0 20px;
background-color: #393d49;
color: #fff;
border-radius: 2px;
font-size: 0;
}
.layui-nav * {
font-size: 14px;
}
.layui-nav .layui-nav-item {
position: relative;
display: inline-block;
vertical-align: middle;
line-height: 60px;
}
.layui-nav .layui-nav-item > a {
display: block;
padding: 0 30px;
* {
color: rgba(255, 255, 255, 0.7);
}
}
.layui-nav .layui-nav-item.layui-this > a {
* {
color: #fff;
}
}
.layui-nav .layui-this:after,
.layui-nav-bar {
content: "";
position: absolute;
left: 0;
top: 0;
width: 0;
height: 3px;
background-color: var(--global-checked-color);
transition: all 0.2s;
-webkit-transition: all 0.2s;
pointer-events: none;
}
.layui-nav-bar {
z-index: 1000;
}
.layui-nav[lay-bar="disabled"] .layui-nav-bar {
display: none;
}
.layui-nav .layui-this:after {
top: auto;
bottom: 0;
width: 100%;
}
.layui-nav-img {
width: 30px;
height: 30px;
margin-right: 5px;
border-radius: 50%;
}
.layui-nav .layui-nav-more {
position: absolute;
top: 0;
right: 8px;
left: auto !important;
margin-top: 0;
font-size: 12.5px !important;
cursor: pointer;
transition: all 0.2s;
-webkit-transition: all 0.2s;
}
.layui-nav .layui-nav-mored,
.layui-nav-itemed > a .layui-nav-more {
transform: rotate(180deg);
}
.layui-nav-child {
display: none;
position: absolute;
left: 0;
top: 65px;
min-width: 100%;
line-height: 36px;
padding: 5px 0;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.12);
border: 1px solid #eee;
background-color: #fff;
z-index: 100;
border-radius: 2px;
white-space: nowrap;
}
.layui-nav .layui-nav-child a {
color: #666;
color: rgba(0, 0, 0, 0.8);
}
.layui-nav .layui-nav-child a:hover {
background-color: #f6f6f6;
color: rgba(0, 0, 0, 0.8);
}
.layui-nav-child dd {
margin: 1px 0;
position: relative;
}
.layui-nav-child dd.layui-this {
background-color: #f6f6f6;
color: #000;
}
.layui-nav-child dd.layui-this:after {
display: none;
}
.layui-nav-child-r {
left: auto;
right: 0;
}
.layui-nav-child-c {
text-align: center;
}
.layui-nav.layui-nav-collapse {
width: 60px;
span {
display: none;
}
.layui-nav-item > a {
text-overflow: clip;
}
.layui-nav-more {
display: none;
}
}
.layui-nav-tree {
padding: 0;
width: 200px;
transition: all .3s;
}
.layui-nav-tree .layui-nav-item {
width: 100%;
display: block;
box-sizing: border-box;
line-height: 42px;
}
.layui-nav-tree .layui-nav-item > a {
height: 40px;
line-height: 40px;
position: relative;
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
padding: 5px 23px 5px 23px;
}
.layui-nav-tree .layui-nav-item * {
color: rgba(255, 255, 255, 0.7);
}
.layui-nav-tree .layui-nav-more {
right: 15px;
}
.layui-nav-tree .layui-nav-item > a .layui-nav-more {
padding: 5px 0;
}
.layui-nav-tree .layui-nav-item span {
margin-left: 3px;
}
.layui-nav-tree .layui-nav-bar {
width: 5px;
height: 0;
background-color: var(--global-primary-color);
}
.layui-nav-tree .layui-this,
.layui-nav-tree .layui-nav-child dd.layui-this,
.layui-nav-tree .layui-this > a:hover {
background-color: var(--global-primary-color);
color: #fff;
}
.layui-nav-tree .layui-this:after {
display: none;
}
.layui-nav-itemed > a,
.layui-nav-tree .layui-nav-title a,
.layui-nav-tree .layui-nav-title a:hover {
color: #fff !important;
}
.layui-nav-tree .layui-nav-child {
top: 0;
z-index: 0;
border: none;
box-shadow: none;
position: relative;
}
.layui-nav-tree .layui-nav-child dd {
margin: 0;
}
.layui-nav-tree .layui-nav-child a {
color: #fff;
color: rgba(255, 255, 255, 0.7);
}
.layui-nav-tree .layui-nav-child,
.layui-nav-tree .layui-nav-child a:hover {
background: 0 0;
color: #fff;
}
.layui-nav-tree .layui-nav-child {
display: block;
background-color: rgba(0, 0, 0, 0.2);
}
.layui-nav-itemed > .layui-nav-child > .layui-this > .layui-nav-child {
display: block;
}
.layui-nav-side {
position: fixed;
top: 0;
bottom: 0;
left: 0;
overflow-x: hidden;
z-index: 999;
}
.layui-nav-light {
background-color: #ffffff;
* {
color: grey !important;
}
.layui-nav-child {
background-color: rgba(0, 0, 0, 0.02);
}
}
.layui-nav-tree {
padding-top: 5px;
padding-bottom: 5px;
}
.layui-nav-tree .layui-this * {
color: white !important;
}
.layui-nav-tree.inverted .layui-this,
.layui-nav-tree.inverted .layui-this:hover {
border-radius: var(--global-border-radius);
margin: 0px 6px;
width: auto;
}
.layui-nav-tree.inverted .layui-this > a,
.layui-nav-tree.inverted .layui-this:hover > a {
border-radius: var(--global-border-radius);
}
.layui-nav-tree.inverted .layui-this > a {
padding: 5px 17px 5px 17px;
}
.layui-nav-tree.not-level {
.layui-nav-child {
background-color: transparent;
}
}
/* popup menu 样式开始 */
.layui-sub-menu-popup-content {
border: unset;
border-radius: 2px;
background-color: #393d49;
.layui-nav-item {
width: 100%;
* {
color: rgba(255, 255, 255, 0.7)
}
> a {
display: flex;
align-items: center;
text-overflow: ellipsis;
padding: 5px 15px 5px 15px;
font-size: 13.5px;
min-height: 30px;
min-width: 60px;
.layui-sub-menu-icon {
margin-top: 2px;
margin-right: 8px;
.layui-icon {
font-size: 14px;
}
}
}
span {
display: inline-block;
margin-left: 0;
}
.layui-nav-more {
position: relative;
display: inline-block;
font-size: 12.5px !important;
margin-top: 0;
margin-left: 25px;
padding: 0;
right: -8px;
.layui-icon {
font-size: 14px;
}
}
}
.layui-this {
background-color: var(--global-primary-color);
}
// fix style
.layui-dropdown {
display: block;
width: -moz-available;
width: -webkit-fill-available;
width: fill-available;
width: 100%;
}
}
.layui-sub-menu-popup-theme {
&-light {
background-color: #FFF;
.layui-this {
* {
color: whitesmoke !important;
}
}
.layui-nav-item {
* {
color: gray;
}
}
}
}
/* popup menu 样式结束 */

View File

@@ -0,0 +1,5 @@
import { withInstall, WithInstallType } from "../../utils";
import Component from "./index.vue";
const component: WithInstallType<typeof Component> = withInstall(Component);
export default component;

View File

@@ -0,0 +1,112 @@
<script lang="ts">
export default {
name: "LayMenu",
};
</script>
<script setup lang="ts">
import { computed, ComputedRef, provide, Ref, ref, watch } from "vue";
import { provideLevel } from "./useLevel";
import "./index.less";
export interface MenuProps {
selectedKey?: string;
openKeys?: string[];
tree?: boolean;
theme?: string;
inverted?: boolean | string;
level?: boolean | string;
collapse?: boolean | string;
collapseTransition?: boolean | string;
indent?: boolean | string; // 菜单栏是否缩进
}
const emit = defineEmits([
"update:selectedKey",
"update:openKeys",
"changeSelectedKey",
"changeOpenKeys",
]);
const props = withDefaults(defineProps<MenuProps>(), {
selectedKey: "",
openKeys: () => [],
tree: false,
theme: "dark",
inverted: false,
level: true,
collapse: false,
collapseTransition: true,
indent: false,
});
const isTree: ComputedRef<boolean> = computed(() => props.tree);
const isCollapse: ComputedRef<boolean | string> = computed(
() => props.collapse
);
const isCollapseTransition: ComputedRef = computed(
() => props.collapseTransition
);
const oldOpenKeys: Ref = ref<string[]>(props.openKeys);
const menuTheme = computed(() => props.theme);
const openKeys = computed({
get() {
return props.collapse ? [] : props.openKeys;
},
set(val) {
emit("update:openKeys", val);
emit("changeOpenKeys", val);
},
});
const selectedKey = computed({
get() {
return props.selectedKey;
},
set(val) {
emit("update:selectedKey", val);
emit("changeSelectedKey", val);
},
});
const indent = computed(() => {
return props.indent;
});
watch(
() => props.collapse,
() => {
if (props.collapse) {
oldOpenKeys.value = props.openKeys;
openKeys.value = [];
} else {
openKeys.value = oldOpenKeys.value;
}
}
);
provideLevel(1);
provide("isTree", isTree);
provide("selectedKey", selectedKey);
provide("openKeys", openKeys);
provide("isCollapse", isCollapse);
provide("isCollapseTransition", isCollapseTransition);
provide("menuTheme", menuTheme);
provide("indent", indent);
</script>
<template>
<ul
class="layui-nav"
:class="[
level ? '' : 'not-level',
inverted ? 'inverted' : '',
tree ? 'layui-nav-tree' : '',
theme === 'dark' ? 'layui-nav-dark' : 'layui-nav-light',
collapse ? 'layui-nav-collapse' : '',
]"
>
<slot></slot>
</ul>
</template>

View File

@@ -0,0 +1,39 @@
import {
computed,
inject,
provide,
reactive,
Ref,
isRef,
ComputedRef,
UnwrapNestedRefs,
} from "vue";
export const LevelInjectionKey = Symbol("menuLevelKey");
export function provideLevel(level: Ref<number> | number) {
const computedLevel = computed(() => (isRef(level) ? level.value : level));
provide(
LevelInjectionKey,
reactive({
level: computedLevel,
})
);
}
export default function useLevel(props?: { provideNextLevel?: boolean }) {
const { provideNextLevel } = props || {};
const levelContext = inject(LevelInjectionKey) as UnwrapNestedRefs<{
level: ComputedRef<number>;
}>;
const level = computed(() => levelContext.level || 1);
if (provideNextLevel) {
const nextLevel = computed(() => level.value + 1);
provideLevel(nextLevel);
}
return {
level,
};
}

View File

@@ -0,0 +1,18 @@
// 处理菜单栏缩进
export function indentHandle(obj: {
indent: boolean | string;
level: number;
basePadding?: number;
isTree?: boolean;
}) {
const { indent, level, basePadding = 0, isTree } = obj;
const least: number = level - 1; // 第一层不缩进
if (isTree && indent && least > 0) {
const px =
typeof indent === "boolean"
? `${basePadding + 10 * least}px` // css样式表对<a>设定了23基础边距
: indent.replace(/\d+/g, (s) => (basePadding + least * +s).toString());
return `padding-left: ${px}`;
}
return "";
}