From 717a9f68fc08cdd093860dfc19336e5de0182d80 Mon Sep 17 00:00:00 2001 From: Ryan Wang Date: Thu, 21 Apr 2022 15:48:59 +0800 Subject: [PATCH] feat: add space component and test case Signed-off-by: Ryan Wang --- src/components/base/space/Space.vue | 65 +++++++ .../base/space/__tests__/Space.spec.ts | 48 +++++ src/components/base/space/index.ts | 1 + src/components/base/space/interface.ts | 9 + src/core/icons.ts | 3 + src/router/menus.config.ts | 3 +- src/views/ViewComponents.vue | 173 ++++++++++++------ 7 files changed, 248 insertions(+), 54 deletions(-) create mode 100644 src/components/base/space/Space.vue create mode 100644 src/components/base/space/__tests__/Space.spec.ts create mode 100644 src/components/base/space/index.ts create mode 100644 src/components/base/space/interface.ts diff --git a/src/components/base/space/Space.vue b/src/components/base/space/Space.vue new file mode 100644 index 000000000..ab41b2b50 --- /dev/null +++ b/src/components/base/space/Space.vue @@ -0,0 +1,65 @@ + + + diff --git a/src/components/base/space/__tests__/Space.spec.ts b/src/components/base/space/__tests__/Space.spec.ts new file mode 100644 index 000000000..3854ac0ce --- /dev/null +++ b/src/components/base/space/__tests__/Space.spec.ts @@ -0,0 +1,48 @@ +import { describe, expect, it } from "vitest"; +import { VSpace } from "../index"; +import { mount } from "@vue/test-utils"; +import { SpacingSize } from "../interface"; + +describe("Space", () => { + it("should render", function () { + expect(VSpace).toBeDefined(); + }); + + it("should work with spacing prop", function () { + Object.keys(SpacingSize).forEach((key: string) => { + const wrapper = mount(VSpace, { + propsData: { + spacing: key, + }, + }); + expect(wrapper.attributes()["style"]).toContain( + `gap: ${SpacingSize[key]}px` + ); + wrapper.unmount(); + }); + }); + + it("should work with direction prop", function () { + ["row", "column"].forEach((direction: string) => { + const wrapper = mount(VSpace, { + propsData: { + direction: direction, + }, + }); + expect(wrapper.classes()).toContain(`space-direction-${direction}`); + wrapper.unmount(); + }); + }); + + it("should work with align prop", function () { + ["center", "start", "end", "stretch"].forEach((align: string) => { + const wrapper = mount(VSpace, { + propsData: { + align: align, + }, + }); + expect(wrapper.classes()).toContain(`space-align-${align}`); + wrapper.unmount(); + }); + }); +}); diff --git a/src/components/base/space/index.ts b/src/components/base/space/index.ts new file mode 100644 index 000000000..b8e3132ef --- /dev/null +++ b/src/components/base/space/index.ts @@ -0,0 +1 @@ +export { default as VSpace } from "./Space.vue"; diff --git a/src/components/base/space/interface.ts b/src/components/base/space/interface.ts new file mode 100644 index 000000000..6b50d11a8 --- /dev/null +++ b/src/components/base/space/interface.ts @@ -0,0 +1,9 @@ +export type Spacing = "xs" | "sm" | "md" | "lg"; +export type Direction = "row" | "column"; +export type Align = "start" | "end" | "center" | "stretch"; +export const SpacingSize: Record = { + xs: 10, + sm: 12, + md: 16, + lg: 20, +}; diff --git a/src/core/icons.ts b/src/core/icons.ts index 68e9524fa..72118d447 100644 --- a/src/core/icons.ts +++ b/src/core/icons.ts @@ -22,6 +22,8 @@ import IconSettings from "~icons/ri/settings-4-line"; import IconPlug from "~icons/ri/plug-2-line"; // @ts-ignore import IconEye from "~icons/ri/eye-line"; +// @ts-ignore +import IconFolder from "~icons/ri/folder-2-line"; export { IconDashboard, IconArrowRight, @@ -35,4 +37,5 @@ export { IconSettings, IconPlug, IconEye, + IconFolder, }; diff --git a/src/router/menus.config.ts b/src/router/menus.config.ts index 75fef32e7..27cba210e 100644 --- a/src/router/menus.config.ts +++ b/src/router/menus.config.ts @@ -10,6 +10,7 @@ import { IconPlug, IconSettings, IconUserSettings, + IconFolder, } from "@/core/icons"; import type { Component } from "vue"; @@ -57,7 +58,7 @@ export const menus: MenuGroupType[] = [ { name: "附件", path: "/attachment", - icon: IconDashboard, + icon: IconFolder, }, ], }, diff --git a/src/views/ViewComponents.vue b/src/views/ViewComponents.vue index a5b3f652a..34a4c0eda 100644 --- a/src/views/ViewComponents.vue +++ b/src/views/ViewComponents.vue @@ -5,76 +5,89 @@

Button

Type:

- Primary - Secondary - Danger - Default + + Primary + Secondary + Danger + Default +

Size:

- Large - Default - sm - xs + + Large + Default + sm + xs +

Circle:

- lg - d - sm - xs + + lg + d + sm + xs +

Block:

- Primary - Secondary - Danger + + Primary + Secondary + Danger +

Disabled:

- Primary - Secondary - Danger + + Primary + Secondary + Danger +

Loading:

- - Primary - - - Secondary - - - Danger - - Default + + + {{ buttonLoading ? "停止" : "启动" }} + + Primary + + Secondary + + Danger + Default +

Icon:

- - - Large - - - - Default - - - - sm - - - - xs - + + + + Large + + + + Default + + + + sm + + + + xs + +
@@ -193,6 +206,44 @@
+
+

Space

+
+ + + + +
Control:
+ 确定 + 取消 +
+
+
@@ -206,7 +257,13 @@ import { VOption, VSelect } from "@/components/base/select"; import { VTextarea } from "@/components/base/textarea"; import { VRadio, VRadioGroup } from "@/components/base/radio"; import { VCheckbox, VCheckboxGroup } from "@/components/base/checkbox"; -import { ref } from "vue"; +import { VSpace } from "@/components/base/space"; +import { reactive, ref } from "vue"; +import type { + Align, + Direction, + Spacing, +} from "@/components/base/space/interface"; const buttonLoading = ref(true); const inputValue = ref(); @@ -215,6 +272,16 @@ const radioValue = ref("apple"); const checkboxValue = ref(false); const checkboxGroupValue = ref(["apple"]); +const spaceState = reactive<{ + direction: Direction; + spacing: Spacing; + align: Align; +}>({ + direction: "row", + spacing: "xs", + align: "center", +}); + const selectData = [ { value: "1",