<script lang="ts">
import {
  cloneVNode,
  createElementBlock,
  defineComponent,
  getCurrentInstance,
  h,
  InjectionKey,
  onMounted,
  provide,
  shallowRef,
  SlotsType,
  VNode,
} from "vue";

export const clientOnlySymbol: InjectionKey<boolean> =
  Symbol.for("nuxt:client-only");

export default defineComponent({
  name: "ClientOnly",
  inheritAttrs: false,
  props: ["fallback", "placeholder", "placeholderTag", "fallbackTag"],
  ...(import.meta.env.DEV && {
    slots: Object as SlotsType<{
      default?: () => VNode[];

      /**
       * Specify a content to be rendered on the server and displayed until `<ClientOnly>` is mounted in the browser.
       */
      fallback?: () => VNode[];
      placeholder?: () => VNode[];
    }>,
  }),
  setup(props, { slots, attrs }) {
    const mounted = shallowRef(false);
    onMounted(() => {
      mounted.value = true;
    });
    // 这里没什么用，先去掉
    // const vm = getCurrentInstance();
    // if (vm) {
    //   vm._nuxtClientOnly = true;
    // }
    provide(clientOnlySymbol, true);
    return () => {
      if (mounted.value) {
        const vnodes = slots.default?.();
        if (vnodes && vnodes.length === 1) {
          return [cloneVNode(vnodes[0]!, attrs)];
        }
        return vnodes;
      }
      const slot = slots.fallback || slots.placeholder;
      if (slot) {
        return h(slot);
      }
      const fallbackStr = props.fallback || props.placeholder || "";
      const fallbackTag = props.fallbackTag || props.placeholderTag || "span";
      return createElementBlock(fallbackTag, attrs, fallbackStr);
    };
  },
});
</script>
