Skip to content

Commit

Permalink
feat(tabs): support keep-alive
Browse files Browse the repository at this point in the history
  • Loading branch information
chizukicn committed Nov 22, 2023
1 parent 6227082 commit b84a4d4
Show file tree
Hide file tree
Showing 6 changed files with 67 additions and 24 deletions.
8 changes: 3 additions & 5 deletions packages/core/src/item/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import type { ActivateEvent, ElementLike } from "@hoci/shared";
import { defineHookComponent, defineHookProps, valuePropType } from "@hoci/shared";
import type { PropType } from "vue";
import { computed, renderSlot, watch } from "vue";
import { computed, watch } from "vue";
import { tryOnScopeDispose } from "@vueuse/core";
import { cls } from "tslx";
import { useSelectionContext } from "../selection";
Expand Down Expand Up @@ -56,12 +56,10 @@ export const useSelectionItem = defineHookComponent({
});

function render() {
return renderSlot(slots, "default", {
return slots.default?.({
active: context.isActive(props.value),
activate
}, () => {
return label.value;
});
}) ?? ((label.value).filter(Boolean)) as ElementLike;
}

let remove = () => {};
Expand Down
4 changes: 3 additions & 1 deletion packages/core/src/selection/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
defineHookComponent,
defineHookEmits,
defineHookProps,
getFirstChilld,
labelPropType,
useSharedConfig,
valuePropType
Expand Down Expand Up @@ -232,11 +233,12 @@ export const useSelectionList = defineHookComponent({
}));



const renderItem = () => {
const children = options
.filter((e) => actives.includes(e.value))
.map((e) => e.render());
return props.multiple ? children : children[0];
return props.multiple ? children : getFirstChilld(children);
};

const slotData: HiSelectionSlotData = {
Expand Down
35 changes: 27 additions & 8 deletions packages/core/src/tabs/component.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { defineComponent, h, renderSlot } from "vue";
import type { KeepAliveProps, PropType } from "vue";
import { KeepAlive, defineComponent, h, renderSlot } from "vue";
import { classPropType } from "@hoci/shared";
import { selectionProps, useSelectionList } from "../selection";

Expand All @@ -8,9 +9,6 @@ export const HiTabs = defineComponent({
headerClass: {
type: classPropType
},
contentClass: {
type: classPropType
},
as: {
type: String,
default: "div"
Expand All @@ -22,20 +20,41 @@ export const HiTabs = defineComponent({
contentAs: {
type: String,
default: "div"
},
contentClass: {
type: classPropType
},
keepAlive: {
type: [Boolean, Object] as PropType<boolean | KeepAliveProps>,
default: false
}
},
setup(props, context) {
const selection = useSelectionList(props, context);

return () => {
const content = selection.renderItem();
let component = selection.renderItem();
if (props.keepAlive) {
component = h(KeepAlive, {
...(typeof props.keepAlive == "object" ? props.keepAlive : {})
}, component);
}

if (context.slots.content) {
component = context.slots.content({
component
});
} else {
component = h(props.contentAs, {
class: props.contentClass
}, component);
}

return h(props.as, [
h(props.headerAs, {
class: props.headerClass
}, renderSlot(context.slots, "default")),
h(props.contentAs, {
class: props.contentClass
}, content)
component
]);
};
}
Expand Down
9 changes: 9 additions & 0 deletions packages/shared/src/utils/dom.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import type { ElementLike } from "../types";

export const getFirstChilld = (children: ElementLike[]): ElementLike => {
const first = children[0];
if (Array.isArray(first) && first.length === 1) {
return getFirstChilld(first);
}
return first;
};
1 change: 1 addition & 0 deletions packages/shared/src/utils/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export * from "./is";
export * from "./raf";
export * from "./dom";
34 changes: 24 additions & 10 deletions playground/src/app.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,13 @@ import { defineComponent, reactive, ref } from "vue";
import { HiAffix, HiConfigProvider, HiIcon, HiItem, HiSelection, HiSwitch, HiTabPane, HiTabs } from "hoci";
import hociSvg from "./assets/hoci.svg";
const Tab1 = defineComponent(() => {
return () => <div class="p-4">
<HiSwitch as="span" class="cursor-pointer duration-200 select-none" activeClass="text-hex-f00">Tab 1</HiSwitch>
</div>;
const Tab1 = defineComponent({
name: "Tab1",
setup() {
return () => <div class="p-4">
<HiSwitch as="span" class="cursor-pointer duration-200 select-none" activeClass="text-hex-f00">Tab 1</HiSwitch>
</div>;
}
});
export default defineComponent(() => {
Expand Down Expand Up @@ -46,16 +49,27 @@ export default defineComponent(() => {
<hi-icon class="text-green rounded w-12 h-12" src={hociSvg}/>
<HiIcon size={0} class="text-green rounded w-12 h-12" src={hociSvg}/>
<HiTabs
keepAlive
headerClass="flex space-x-3"
itemClass="b-1 b-solid px-2 b-gray-3 rounded cursor-pointer"
activeClass="b-transparent bg-blue-3 text-white"
v-model={selectedIndex.value} class="mt-12">
<HiTabPane value={1} label="tab1">
<Tab1/>
</HiTabPane>
<HiTabPane value={2} label="tab2">
这是Tab 2
</HiTabPane>
{
{
default() {
return <>
<HiTabPane value={1} label="tab1">
<Tab1/>
</HiTabPane>
<HiTabPane value={2} label="tab2">
<div class="p-4">
<HiSwitch as="span" class="cursor-pointer duration-200 select-none" activeClass="text-hex-f00">Tab 2</HiSwitch>
</div>
</HiTabPane>
</>;
}
}
}
</HiTabs>
<HiAffix class="my-1" as="div" offset={30}>
<div class="inline-block p-4 bg-blue-200" >
Expand Down

0 comments on commit b84a4d4

Please sign in to comment.