vue#h TypeScript Examples

The following examples show how to use vue#h. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: hexo-init-fail-modal.ts    From hexon with GNU General Public License v3.0 6 votes vote down vote up
export default function showHexoInitFailModal(text: string) {
  modal.create(
    defineComponent({
      name: "HErrorInfo",
      components: {
        HHexoInitFailModal,
        HBaseModal,
      },
      props: {
        close: Function,
      },
      render() {
        return h(
          HBaseModal,
          {
            onOnClose: this.close,
          },
          () => h(HHexoInitFailModal, { text })
        )
      },
    })
  )
}
Example #2
Source File: diretive.test.ts    From vue-i18n-next with MIT License 6 votes vote down vote up
test('object literal', async () => {
  const i18n = createI18n({
    locale: 'en',
    messages: {
      en: {
        hello: 'hello, {name}!'
      },
      ja: {
        hello: 'こんにちは、{name}!'
      }
    }
  })

  const App = defineComponent({
    setup() {
      // <p v-t="{ path: 'hello', locale: 'ja', args: { name: name.value } }"></p>
      const name = ref('kazupon')
      const t = resolveDirective('t')
      return () => {
        return withDirectives(h('p'), [
          [t!, { path: 'hello', locale: 'ja', args: { name: name.value } }]
        ])
      }
    }
  })
  const wrapper = await mount(App, i18n)

  expect(wrapper.html()).toEqual('<p>こんにちは、kazupon!</p>')
})
Example #3
Source File: diretive.test.ts    From vue-i18n-next with MIT License 6 votes vote down vote up
test('plural', async () => {
  const i18n = createI18n({
    locale: 'en',
    messages: {
      en: {
        banana: 'no bananas | {n} banana | {n} bananas'
      }
    }
  })

  const App = defineComponent({
    setup() {
      // <p v-t="{ path: 'banana', choice: 2 }"></p>
      const t = resolveDirective('t')
      return () => {
        return withDirectives(h('p'), [[t!, { path: 'banana', choice: 2 }]])
      }
    }
  })
  const wrapper = await mount(App, i18n)

  expect(wrapper.html()).toEqual('<p>2 bananas</p>')
})
Example #4
Source File: diretive.test.ts    From vue-i18n-next with MIT License 6 votes vote down vote up
test('preserve modifier', async () => {
  const mockWarn = warn as jest.MockedFunction<typeof warn>
  mockWarn.mockImplementation(() => {})

  const i18n = createI18n({
    locale: 'en',
    messages: {
      en: {
        hello: 'hello!'
      }
    }
  })

  const App = defineComponent({
    setup() {
      // <p v-t.preserve="'hello'"></p>
      const t = resolveDirective('t')
      return () => {
        return withDirectives(h('p'), [[t!, 'hello', '', { preserve: true }]])
      }
    }
  })
  await mount(App, i18n)

  expect(mockWarn).toHaveBeenCalledTimes(1)
  expect(mockWarn.mock.calls[0][0]).toEqual(
    getWarnMessage(I18nWarnCodes.NOT_SUPPORTED_PRESERVE)
  )
})
Example #5
Source File: Translation.test.ts    From vue-i18n-next with MIT License 6 votes vote down vote up
test('component', async () => {
  const i18n = createI18n({
    locale: 'en',
    messages
  })

  const MyComponent = defineComponent({
    setup(props, context: SetupContext) {
      return (): VNodeChild => h('p', context.slots.default!())
    }
  })

  const App = defineComponent({
    data: () => ({ MyComponent }),
    template: `
<i18n-t :tag="MyComponent" class="name" keypath="message.named">
  <template #name>
    <span>kazupon</span>
  </template>
</i18n-t>
`
  })
  const wrapper = await mount(App, i18n)

  expect(wrapper.html()).toEqual(
    `<p class="name">hello, <span>kazupon</span>!</p>`
  )
})
Example #6
Source File: NumberFormat.test.ts    From vue-i18n-next with MIT License 6 votes vote down vote up
test('component', async () => {
  const i18n = createI18n({
    locale: 'en-US',
    numberFormats
  })

  const MyComponent = defineComponent({
    setup(props, context: SetupContext) {
      return (): VNodeChild => h('span', context.slots.default!())
    }
  })

  const App = defineComponent({
    data: () => ({ MyComponent }),
    template: `
<i18n-n :tag="MyComponent" :value="100"></i18n-n>
<i18n-n :tag="MyComponent" :value="100" format="currency"></i18n-n>
<i18n-n :tag="MyComponent" :value="100" format="currency" locale="ja-JP"></i18n-n>
`
  })
  const wrapper = await mount(App, i18n)

  expect(wrapper.html()).toEqual(
    `<span>100</span><span>$100.00</span><span>¥100</span>`
  )
})
Example #7
Source File: DatetimeFormat.test.ts    From vue-i18n-next with MIT License 6 votes vote down vote up
test('component', async () => {
  const i18n = createI18n({
    locale: 'en-US',
    datetimeFormats
  })

  const MyComponent = defineComponent({
    setup(props, context: SetupContext) {
      return (): VNodeChild => h('span', context.slots.default!())
    }
  })

  const App = defineComponent({
    data: () => ({ MyComponent }),
    template: `
<i18n-d :tag="MyComponent" :value="new Date()"></i18n-d>
<i18n-d :tag="MyComponent" :value="new Date()" format="long"></i18n-d>
<i18n-d
  :tag="MyComponent"
  :value="new Date()"
  format="long"
  locale="ja-JP-u-ca-japanese"
></i18n-d>
`
  })
  const wrapper = await mount(App, i18n)

  expect(wrapper.html().includes('span')).toBeTruthy()
})
Example #8
Source File: diretive.test.ts    From vue-i18n-next with MIT License 6 votes vote down vote up
test('legacy mode', async () => {
  const i18n = createI18n({
    legacy: true,
    locale: 'en',
    messages: {
      en: {
        hello: 'hello!'
      }
    }
  })

  const App = defineComponent({
    setup() {
      // <p v-t="'hello'"></p>
      const t = resolveDirective('t')
      return () => {
        return withDirectives(h('p'), [[t!, 'hello']])
      }
    }
  })
  const wrapper = await mount(App, i18n)

  expect(wrapper.html()).toEqual('<p>hello!</p>')
})
Example #9
Source File: helper.ts    From vue-i18n-next with MIT License 6 votes vote down vote up
function compileSlot(template: string) {
  const codegen = compile(template, {
    mode: 'function',
    hoistStatic: true,
    prefixIdentifiers: true
  })

  const render = new Function('Vue', codegen.code)(runtimeDom)

  const ToRender = defineComponent({
    inheritAttrs: false,
    setup(props, { attrs }) {
      return { ...attrs }
    },
    render
  })

  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  return (propsData: any) => h(ToRender, { ...propsData })
}
Example #10
Source File: ssr.test.ts    From vue-i18n-next with MIT License 6 votes vote down vote up
test('composition mode', async () => {
  const i18n = createI18n({
    legacy: false,
    locale: 'en',
    messages: {}
  })

  const App = defineComponent({
    setup() {
      const { t } = useI18n({
        locale: 'ja',
        inheritLocale: false,
        messages: {
          ja: { hello: 'こんにちは!' },
          en: { hello: 'hello!' }
        }
      })
      return () => h('p', t('hello'))
    }
  })
  const app = createSSRApp(App)
  app.use(i18n)

  expect(await renderToString(app)).toMatch(`<p>こんにちは!</p>`)
})
Example #11
Source File: ssr.test.ts    From vue-i18n-next with MIT License 6 votes vote down vote up
test('legacy mode', async () => {
  const i18n = createI18n({
    locale: 'ja',
    messages: {
      ja: { hello: 'こんにちは!' },
      en: { hello: 'hello!' }
    }
  })

  // NOTE: template: `<p>{{ $t('hello') }}</p>`
  const App = () => h('p', i18n.global.t('hello'))
  const app = createSSRApp(App)
  app.use(i18n)

  expect(await renderToString(app)).toMatch(`<p>こんにちは!</p>`)
})
Example #12
Source File: ssr.test.ts    From vue-i18n-next with MIT License 6 votes vote down vote up
test('component: i18n-t', async () => {
  const i18n = createI18n({
    legacy: false,
    locale: 'en',
    messages: {}
  })

  const App = defineComponent({
    setup() {
      useI18n({
        locale: 'ja',
        inheritLocale: false,
        messages: {
          ja: { hello: 'こんにちは!' },
          en: { hello: 'hello!' }
        }
      })
      return () => h(resolveComponent('i18n-t'), { tag: 'p', keypath: 'hello' })
    }
    // template: `<i18n-t tag="p" keypath="hello"/>`
  })
  const app = createSSRApp(App)
  app.use(i18n)

  expect(await renderToString(app)).toMatch(`<p>こんにちは!</p>`)
})
Example #13
Source File: app.ts    From vite-plugin-ssr with MIT License 6 votes vote down vote up
function createApp(pageContext: PageContext) {
  const { Page, pageProps } = pageContext
  const PageWithLayout = defineComponent({
    render() {
      return h(
        PageShell,
        {},
        {
          default() {
            return h(Page, pageProps || {})
          },
        },
      )
    },
  })

  const app = createSSRApp(PageWithLayout)

  // Make `pageContext` available from any Vue component
  setPageContext(app, pageContext)

  return app
}
Example #14
Source File: diretive.test.ts    From vue-i18n-next with MIT License 5 votes vote down vote up
describe('basic', () => {
  test('literal', async () => {
    const i18n = createI18n({
      locale: 'en',
      messages: {
        en: {
          hello: 'hello!'
        }
      }
    })

    const App = defineComponent({
      setup() {
        // <p v-t="'hello'"></p>
        const t = resolveDirective('t')
        return () => {
          return withDirectives(h('p'), [[t!, 'hello']])
        }
      }
    })
    const wrapper = await mount(App, i18n)

    expect(wrapper.html()).toEqual('<p>hello!</p>')
  })

  test('binding', async () => {
    const i18n = createI18n({
      locale: 'en',
      messages: {
        en: {
          hello: 'hello!'
        }
      }
    })

    const App = defineComponent({
      setup() {
        // <p v-t="msg"></p>
        const msg = ref('hello')
        const t = resolveDirective('t')
        return () => {
          return withDirectives(h('p'), [[t!, msg.value]])
        }
      }
    })
    const wrapper = await mount(App, i18n)

    expect(wrapper.html()).toEqual('<p>hello!</p>')
  })
})
Example #15
Source File: diretive.test.ts    From vue-i18n-next with MIT License 5 votes vote down vote up
describe('errors', () => {
  let org: any // eslint-disable-line @typescript-eslint/no-explicit-any
  let spy: any // eslint-disable-line @typescript-eslint/no-explicit-any
  beforeEach(() => {
    org = console.warn
    spy = jest.fn()
    console.warn = spy
  })
  afterEach(() => {
    console.warn = org
  })

  test(errorMessages[I18nErrorCodes.REQUIRED_VALUE], async () => {
    const i18n = createI18n({
      locale: 'en',
      messages: {
        en: {
          hello: 'hello!'
        }
      }
    })

    const App = defineComponent({
      setup() {
        // <p v-t="{ locale: 'ja' }"></p>
        const t = resolveDirective('t')
        return () => {
          return withDirectives(h('p'), [[t!, { locale: 'ja' }]])
        }
      }
    })

    let error: Error | null = null
    try {
      await mount(App, i18n)
    } catch (e) {
      error = e
    }
    expect(error!.message).toEqual(
      format(errorMessages[I18nErrorCodes.REQUIRED_VALUE], 'path')
    )
  })

  test(errorMessages[I18nErrorCodes.INVALID_VALUE], async () => {
    const i18n = createI18n({
      locale: 'en',
      messages: {
        en: {
          hello: 'hello!'
        }
      }
    })

    const App = defineComponent({
      setup() {
        // <p v-t="1"></p>
        const t = resolveDirective('t')
        return () => withDirectives(h('p'), [[t!, 1]])
      }
    })

    let error: Error | null = null
    try {
      await mount(App, i18n)
    } catch (e) {
      error = e
    }
    expect(error!.message).toEqual(errorMessages[I18nErrorCodes.INVALID_VALUE])
  })
})
Example #16
Source File: wc.test.ts    From vue-i18n-next with MIT License 5 votes vote down vote up
test('basic', async () => {
  const i18n = createI18n<false>({
    legacy: false,
    locale: 'en',
    messages: {
      en: {
        hello: 'hello web components!'
      },
      ja: {
        hello: 'こんにちは Web コンポーネント!'
      }
    }
  })

  const Provider = defineCustomElement({
    setup() {
      provide(I18nInjectionKey, i18n)
      return () => h('my-consumer')
    }
  })
  customElements.define('my-provider', Provider)
  const Consumer = defineCustomElement({
    setup() {
      const { t } = useI18n()
      return () => h('div', t('hello'))
    }
  })
  customElements.define('my-consumer', Consumer)

  container.innerHTML = `<my-provider></my-provider>`
  await nextTick()
  const provider = container.childNodes[0] as VueElement
  const consumer = provider.shadowRoot!.childNodes[0] as VueElement
  expect(consumer.shadowRoot!.innerHTML).toBe(
    `<div>hello web components!</div>`
  )

  i18n.global.locale.value = 'ja'
  await nextTick()
  expect(consumer.shadowRoot!.innerHTML).toBe(
    `<div>こんにちは Web コンポーネント!</div>`
  )
})
Example #17
Source File: wc.test.ts    From vue-i18n-next with MIT License 5 votes vote down vote up
test('custom blocks', async () => {
  const i18n = createI18n<false>({
    legacy: false,
    locale: 'en',
    messages: {
      en: {
        hello: 'hello web components!'
      },
      ja: {
        hello: 'こんにちは Web コンポーネント!'
      }
    }
  })

  const Provider = defineCustomElement({
    setup() {
      provide(I18nInjectionKey, i18n)
      return () => h('my-child-block')
    }
  })
  customElements.define('my-provider-block', Provider)
  const Child = defineCustomElement({
    setup() {
      const instance = getCurrentInstance()
      if (instance == null) {
        throw new Error()
      }
      const options = instance.type as ComponentOptions
      options.__i18n = [
        {
          locale: 'en',
          resource: { foo: 'foo!' }
        },
        {
          locale: 'ja',
          resource: { foo: 'ふー!' }
        }
      ]
      const { t } = useI18n({
        inheritLocale: true,
        useScope: 'local'
      })
      return () => h('div', t('foo'))
    }
  })
  customElements.define('my-child-block', Child)

  container.innerHTML = `<my-provider-block></my-provider-block>`
  await nextTick()
  const provider = container.childNodes[0] as VueElement
  const child = provider.shadowRoot!.childNodes[0] as VueElement
  expect(child.shadowRoot!.innerHTML).toBe(`<div>foo!</div>`)

  i18n.global.locale.value = 'ja'
  await nextTick()
  expect(child.shadowRoot!.innerHTML).toBe(`<div>ふー!</div>`)
})
Example #18
Source File: component.ts    From vue3-gettext with MIT License 5 votes vote down vote up
Component = defineComponent({
  // eslint-disable-next-line vue/multi-word-component-names, vue/component-definition-name-casing
  name: "translate",
  props: {
    tag: {
      type: String,
      default: "span",
    },
    // Always use v-bind for dynamically binding the `translateN` prop to data on the parent,
    // i.e.: `:translate-n`.
    translateN: {
      type: Number,
      default: null,
    },
    translatePlural: {
      type: String,
      default: null,
    },
    translateContext: {
      type: String,
      default: null,
    },
    translateParams: {
      type: Object,
      default: null,
    },
    translateComment: {
      type: String,
      default: null,
    },
  },

  setup(props, context) {
    const isPlural = props.translateN !== undefined && props.translatePlural !== undefined;
    if (!isPlural && (props.translateN || props.translatePlural)) {
      throw new Error(
        `\`translate-n\` and \`translate-plural\` attributes must be used together: ${
          context.slots.default?.()[0]?.children
        }.`,
      );
    }

    const root = ref<HTMLElement>();

    const plugin = useGettext();
    const msgid = ref<string | null>(null);

    onMounted(() => {
      if (!msgid.value && root.value) {
        msgid.value = root.value.innerHTML.trim();
      }
    });

    const translation = computed(() => {
      const translatedMsg = translate(plugin).getTranslation(
        msgid.value!,
        props.translateN,
        props.translateContext,
        isPlural ? props.translatePlural : null,
        plugin.current,
      );

      return interpolate(plugin)(translatedMsg, props.translateParams, undefined, getCurrentInstance()?.parent);
    });

    // The text must be wraped inside a root HTML element, so we use a <span> by default.
    return () => {
      if (!msgid.value) {
        return h(props.tag, { ref: root }, context.slots.default ? context.slots.default() : "");
      }
      return h(props.tag, { ref: root, innerHTML: translation.value });
    };
  },
})
Example #19
Source File: utils.ts    From vue3-datagrid with MIT License 5 votes vote down vote up
defineContainer = <Props>(name: string, [...componentProps]: string[] = [], componentOptions: ComponentOptions = {}) => {
  const { modelProp, modelUpdateEvent } = componentOptions;

  /**
  * Create a Vue component wrapper around a Web Component.
  * Note: The `props` here are not all properties on a component.
  * They refer to whatever properties are set on an instance of a component.
  */
  const Container = defineComponent<Props & InputProps>((props, { attrs, slots, emit }) => {
    let modelPropValue = (props as any)[modelProp];
    const containerRef = ref<HTMLElement>();
    const classes = new Set(getComponentClasses(attrs.class));
    const onVnodeBeforeMount = (vnode: VNode) => {
      // Add a listener to tell Vue to update the v-model
      if (vnode.el) {
        vnode.el.addEventListener(modelUpdateEvent.toLowerCase(), (e: Event) => {
          modelPropValue = (e?.target as any)[modelProp];
          emit(UPDATE_VALUE_EVENT, modelPropValue);

          /**
           * We need to emit the change event here
           * rather than on the web component to ensure
           * that any v-model bindings have been updated.
           * Otherwise, the developer will listen on the
           * native web component, but the v-model will
           * not have been updated yet.
           */
          emit(modelUpdateEvent, e);
          e.stopImmediatePropagation();
        });
      }
    };

    const currentInstance = getCurrentInstance();
    const hasRouter = currentInstance?.appContext?.provides[NAV_MANAGER];
    const navManager: NavManager | undefined = hasRouter ? inject(NAV_MANAGER) : undefined;
    const handleRouterLink = (ev: Event) => {
      const { routerLink } = props as any;
      if (!routerLink) return;

      const routerProps = Object.keys(props).filter(p => p.startsWith(ROUTER_PROP_REFIX));

      if (navManager !== undefined) {
        let navigationPayload: any = { event: ev };
        routerProps.forEach(prop => {
          navigationPayload[prop] = (props as any)[prop];
        });
        navManager.navigate(navigationPayload);
      } else {
        console.warn('Tried to navigate, but no router was found. Make sure you have mounted Vue Router.');
      }
    }

    return () => {
      getComponentClasses(attrs.class).forEach(value => {
        classes.add(value);
      });

      const oldClick = (props as any).onClick;
      const handleClick = (ev: Event) => {
        if (oldClick !== undefined) {
          oldClick(ev);
        }
        if (!ev.defaultPrevented) {
          handleRouterLink(ev);
        }
      }

      let propsToAdd = {
        ref: containerRef,
        class: getElementClasses(containerRef, classes),
        onClick: handleClick,
        onVnodeBeforeMount: (modelUpdateEvent) ? onVnodeBeforeMount : undefined
      };

      for (const [prop, value] of Object.entries(props)) {
        if (value !== EMPTY_SENTINEL) {
          propsToAdd[prop] = value;
        }
      }

      if (modelProp) {
        propsToAdd = {
          ...propsToAdd,
          [modelProp]: props.modelValue !== EMPTY_SENTINEL ? props.modelValue : modelPropValue
        }
      }

      return h(name, propsToAdd, slots.default && slots.default());
    }
  });

  Container.displayName = name;
  componentProps.push(ROUTER_LINK_VALUE);
  if (modelProp) {
    componentProps.push(MODEL_VALUE);
    Container.emits = [UPDATE_VALUE_EVENT, modelUpdateEvent];
  }

  Container.props = {};
  for (const componentProp of componentProps) {
	Container.props[componentProp] = { default: EMPTY_SENTINEL };
  }

  return Container;
}
Example #20
Source File: RouteLayoutSource.ts    From convue with MIT License 5 votes vote down vote up
export function createRouterLayout(
  resolve: (layoutName: string) => Promise<Component | { default: Component }>,
) {
  return defineComponent({
    name: 'RouterLayout',

    async beforeRouteEnter(to, _from, next) {
      const name = to.meta.layout || 'default'
      const layoutComp = name
        ? ((await resolve(name)) as any).default
        : undefined

      next((vm: any) => {
        vm.layoutName = name
        if (name && layoutComp)
          vm.layouts[name] = layoutComp
      })
    },

    async beforeRouteUpdate(to, _from, next) {
      try {
        const name = to.meta.layout || 'default'
        if (name && !this.layouts[name])
          this.layouts[name] = ((await resolve(name)) as any).default

        this.layoutName = name
        next()
      }
      catch (error) {
        next(error)
      }
    },

    data() {
      return {
        layoutName: undefined as string | undefined,
        layouts: shallowReactive(
          Object.create(null) as Record<string, Component>,
        ),
      }
    },

    render(): VNode {
      const layout = this.layoutName && this.layouts[this.layoutName]
      if (!layout)
        return h('span')

      return h(layout as ConcreteComponent, {
        key: this.layoutName,
      })
    },
  })
}
Example #21
Source File: Translation.test.ts    From vue-i18n-next with MIT License 5 votes vote down vote up
test('message resolver', async () => {
  const fn = jest.fn()
  const mockMessageResolver = fn as jest.MockedFunction<MessageResolver>
  mockMessageResolver.mockImplementation(
    (obj: unknown, path: Path): PathValue => {
      const msg = (obj as any)[path] // eslint-disable-line @typescript-eslint/no-explicit-any
      return msg != null ? msg : null
    }
  )
  const en = {
    'message.named': 'hello, {name}!'
  }
  const i18n = createI18n({
    locale: 'en',
    messageResolver: fn,
    messages: { en }
  })

  const MyComponent = defineComponent({
    setup(props, context: SetupContext) {
      return (): VNodeChild => h('p', context.slots.default!())
    }
  })

  const App = defineComponent({
    data: () => ({ MyComponent }),
    template: `
<i18n-t :tag="MyComponent" class="name" keypath="message.named">
  <template #name>
    <span>kazupon</span>
  </template>
</i18n-t>
`
  })
  const wrapper = await mount(App, i18n)

  expect(wrapper.html()).toEqual(
    `<p class="name">hello, <span>kazupon</span>!</p>`
  )
  expect(mockMessageResolver).toHaveBeenCalledTimes(1)
  expect(mockMessageResolver.mock.calls[0][0]).toEqual(en)
  expect(mockMessageResolver.mock.calls[0][1]).toEqual('message.named')
})
Example #22
Source File: formatRenderer.ts    From vue-i18n-next with MIT License 5 votes vote down vote up
export function renderFormatter<
  Props extends FormattableProps<Value, Format>,
  Value,
  Format extends FormatOverrideOptions,
  Arg extends FormatOptions,
  Return extends FormatPartReturn
>(
  props: Props,
  context: SetupContext,
  slotKeys: string[],
  partFormatter: (...args: unknown[]) => string | Return[]
): RenderFunction {
  const { slots, attrs } = context

  return (): VNodeChild => {
    const options = { part: true } as Arg
    let overrides = {} as FormatOverrideOptions

    if (props.locale) {
      options.locale = props.locale
    }

    if (isString(props.format)) {
      options.key = props.format
    } else if (isObject(props.format)) {
      // eslint-disable-next-line @typescript-eslint/no-explicit-any
      if (isString((props.format as any).key)) {
        // eslint-disable-next-line @typescript-eslint/no-explicit-any
        options.key = (props.format as any).key
      }
      // Filter out number format options only
      overrides = Object.keys(props.format).reduce((options, prop) => {
        return slotKeys.includes(prop)
          ? assign({}, options, { [prop]: (props.format as any)[prop] }) // eslint-disable-line @typescript-eslint/no-explicit-any
          : options
      }, {})
    }

    const parts = partFormatter(...[props.value, options, overrides])
    let children = [options.key] as VNodeArrayChildren
    if (isArray(parts)) {
      children = parts.map((part, index) => {
        const slot = slots[part.type]
        const node = slot
          ? slot({ [part.type]: part.value, index, parts })
          : [part.value]
        if (isVNode(node)) {
          node[0].key = `${part.type}-${index}`
        }
        return node
      })
    } else if (isString(parts)) {
      children = [parts]
    }

    const assignedAttrs = assign({}, attrs)
    const tag =
      isString(props.tag) || isObject(props.tag)
        ? props.tag
        : getFragmentableTag('span')
    return h(tag, assignedAttrs, children)
  }
}
Example #23
Source File: Translation.ts    From vue-i18n-next with MIT License 5 votes vote down vote up
Translation = /* #__PURE__*/ /* defineComponent */ {
  /* eslint-disable */
  name: 'i18n-t',
  props: assign(
    {
      keypath: {
        type: String,
        required: true
      },
      plural: {
        type: [Number, String],
        // eslint-disable-next-line @typescript-eslint/no-explicit-any
        validator: (val: any): boolean => isNumber(val) || !isNaN(val)
      }
    },
    baseFormatProps
  ),
  /* eslint-enable */
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  setup(props: any, context: any): any {
    const { slots, attrs } = context
    // NOTE: avoid https://github.com/microsoft/rushstack/issues/1050
    const i18n =
      props.i18n ||
      (useI18n({
        useScope: props.scope as 'global' | 'parent',
        __useComponent: true
      }) as Composer & ComposerInternal)
    const keys = Object.keys(slots).filter(key => key !== '_')

    return (): VNodeChild => {
      const options = {} as TranslateOptions
      if (props.locale) {
        options.locale = props.locale
      }
      if (props.plural !== undefined) {
        options.plural = isString(props.plural) ? +props.plural : props.plural
      }
      const arg = getInterpolateArg(context, keys)
      // eslint-disable-next-line @typescript-eslint/no-explicit-any
      const children = (i18n as any)[TransrateVNodeSymbol](
        props.keypath,
        arg,
        options
      )
      const assignedAttrs = assign({}, attrs)
      const tag =
        isString(props.tag) || isObject(props.tag)
          ? props.tag
          : getFragmentableTag('span')
      return h(tag, assignedAttrs, children)
    }
  }
}
Example #24
Source File: utils.ts    From elements with MIT License 5 votes vote down vote up
defineContainer = <Props>(
  name: string,
  defineCustomElement: any,
  componentProps: string[] = [],
  modelProp?: string,
  modelUpdateEvent?: string,
  externalModelUpdateEvent?: string
) => {
  /**
  * Create a Vue component wrapper around a Web Component.
  * Note: The `props` here are not all properties on a component.
  * They refer to whatever properties are set on an instance of a component.
  */

  if (defineCustomElement !== undefined) {
    defineCustomElement();
  }

  const Container = defineComponent<Props & InputProps>((props: any, { attrs, slots, emit }) => {
    let modelPropValue = props[modelProp];
    const containerRef = ref<HTMLElement>();
    const classes = new Set(getComponentClasses(attrs.class));
    const onVnodeBeforeMount = (vnode: VNode) => {
      // Add a listener to tell Vue to update the v-model
      if (vnode.el) {
        const eventsNames = Array.isArray(modelUpdateEvent) ? modelUpdateEvent : [modelUpdateEvent];
        eventsNames.forEach((eventName: string) => {
          vnode.el.addEventListener(eventName.toLowerCase(), (e: Event) => {
            modelPropValue = (e as CustomEvent).detail;
            emit(UPDATE_VALUE_EVENT, modelPropValue);

            /**
             * We need to emit the change event here
             * rather than on the web component to ensure
             * that any v-model bindings have been updated.
             * Otherwise, the developer will listen on the
             * native web component, but the v-model will
             * not have been updated yet.
             */
            if (externalModelUpdateEvent) {
              emit(externalModelUpdateEvent, e);
            }
          });
        });
      }
    };

    const currentInstance = getCurrentInstance();
    const hasRouter = currentInstance?.appContext?.provides[NAV_MANAGER];
    const navManager: NavManager | undefined = hasRouter ? inject(NAV_MANAGER) : undefined;
    const handleRouterLink = (ev: Event) => {
      const { routerLink } = props;
      if (routerLink === EMPTY_PROP) return;

      if (navManager !== undefined) {
        let navigationPayload: any = { event: ev };
        for (const key in props) {
          const value = props[key];
          if (props.hasOwnProperty(key) && key.startsWith(ROUTER_PROP_PREFIX) && value !== EMPTY_PROP) {
            navigationPayload[key] = value;
          }
        }

        navManager.navigate(navigationPayload);
      } else {
        console.warn('Tried to navigate, but no router was found. Make sure you have mounted Vue Router.');
      }
    }

    return () => {
      modelPropValue = props[modelProp];

      getComponentClasses(attrs.class).forEach(value => {
        classes.add(value);
      });

      const oldClick = props.onClick;
      const handleClick = (ev: Event) => {
        if (oldClick !== undefined) {
          oldClick(ev);
        }
        if (!ev.defaultPrevented) {
          handleRouterLink(ev);
        }
      }

      let propsToAdd: any = {
        ref: containerRef,
        class: getElementClasses(containerRef, classes),
        onClick: handleClick,
        onVnodeBeforeMount: (modelUpdateEvent) ? onVnodeBeforeMount : undefined
      };

      /**
       * We can use Object.entries here
       * to avoid the hasOwnProperty check,
       * but that would require 2 iterations
       * where as this only requires 1.
       */
      for (const key in props) {
        const value = props[key];
        if (props.hasOwnProperty(key) && value !== EMPTY_PROP) {
          propsToAdd[key] = value;
        }
      }

      if (modelProp) {
        /**
         * If form value property was set using v-model
         * then we should use that value.
         * Otherwise, check to see if form value property
         * was set as a static value (i.e. no v-model).
         */
        if (props[MODEL_VALUE] !== EMPTY_PROP) {
          propsToAdd = {
            ...propsToAdd,
            [modelProp]: props[MODEL_VALUE]
          }
        } else if (modelPropValue !== EMPTY_PROP) {
          propsToAdd = {
            ...propsToAdd,
            [modelProp]: modelPropValue
          }
        }
      }

      return h(name, propsToAdd, slots.default && slots.default());
    }
  });

  Container.displayName = name;

  Container.props = {
    [ROUTER_LINK_VALUE]: DEFAULT_EMPTY_PROP
  };

  componentProps.forEach(componentProp => {
    Container.props[componentProp] = DEFAULT_EMPTY_PROP;
  });

  if (modelProp) {
    Container.props[MODEL_VALUE] = DEFAULT_EMPTY_PROP;
    Container.emits = [UPDATE_VALUE_EVENT, externalModelUpdateEvent];
  }

  return Container;
}
Example #25
Source File: FormKit.ts    From formkit with MIT License 5 votes vote down vote up
FormKit = defineComponent({
  props,
  emits: {
    /* eslint-disable @typescript-eslint/no-unused-vars */
    input: (_value: any, _node: FormKitNode) => true,
    inputRaw: (_value: any, _node: FormKitNode) => true,
    'update:modelValue': (_value: any) => true,
    node: (node: FormKitNode) => !!node,
    submit: (_data: FormKitGroupValue, _node: FormKitNode) => true,
    submitRaw: (_event: Event, _node: FormKitNode) => true,
    /* eslint-enable @typescript-eslint/no-unused-vars */
  },
  inheritAttrs: false,
  setup(props, context) {
    const node = useInput(props, context)
    if (!node.props.definition) error(600, node)
    if (node.props.definition.component) {
      return () =>
        h(
          node.props.definition?.component as any,
          {
            context: node.context,
          },
          { ...context.slots }
        )
    }
    const schema = ref<FormKitSchemaCondition | FormKitSchemaNode[]>([])
    const generateSchema = () => {
      const schemaDefinition = node.props?.definition?.schema
      if (!schemaDefinition) error(601, node)
      schema.value =
        typeof schemaDefinition === 'function'
          ? schemaDefinition({ ...props.sectionsSchema })
          : schemaDefinition
    }
    generateSchema()

    // If someone emits the schema event, we re-generate the schema
    node.on('schema', generateSchema)

    context.emit('node', node)
    const library = node.props.definition.library as
      | Record<string, ConcreteComponent>
      | undefined

    // Expose the FormKitNode to template refs.
    context.expose({ node })

    return () =>
      h(
        FormKitSchema,
        { schema: schema.value, data: node.context, library },
        { ...context.slots }
      )
  },
})
Example #26
Source File: form.spec.ts    From formkit with MIT License 5 votes vote down vote up
describe('form structure', () => {
  it('renders a form with a button', () => {
    const wrapper = mount(FormKit, {
      props: {
        type: 'form',
        name: 'test_form',
        id: 'foo',
        submitAttrs: {
          id: 'button',
        },
      },
      slots: {
        default: () => h('h1', 'in the form'),
      },
      ...global,
    })
    expect(wrapper.html())
      .toEqual(`<form id="foo" class="formkit-form" name="test_form">
  <h1>in the form</h1>
  <!---->
  <div class="formkit-actions">
    <div class="formkit-outer" data-type="submit">
      <!---->
      <div class="formkit-wrapper"><button type="submit" class="formkit-input" name="submit_1" id="button">
          <!---->Submit
          <!---->
        </button></div>
      <!---->
    </div>
  </div>
</form>`)
  })

  it('outputs the id of the form', () => {
    const id = token()
    const wrapper = mount(FormKit, {
      props: {
        type: 'form',
        id,
      },
      ...global,
    })
    expect(wrapper.find('form').attributes('id')).toBe(id)
  })
})
Example #27
Source File: app.ts    From vite-plugin-ssr with MIT License 5 votes vote down vote up
function createApp(pageContext: PageContext) {
  const { Page } = pageContext

  let rootComponent: Component
  const PageWithWrapper = defineComponent({
    data: () => ({
      Page: markRaw(Page),
      pageProps: markRaw(pageContext.pageProps || {}),
    }),
    created() {
      rootComponent = this
    },
    render() {
      return h(
        PageShell,
        {},
        {
          default: () => {
            return h(this.Page, this.pageProps)
          },
        },
      )
    },
  })

  const app = createSSRApp(PageWithWrapper)

  // We use `app.changePage()` to do Client Routing, see `_default.page.client.js`
  objectAssign(app, {
    changePage: (pageContext: PageContext) => {
      Object.assign(pageContextReactive, pageContext)
      rootComponent.Page = markRaw(pageContext.Page)
      rootComponent.pageProps = markRaw(pageContext.pageProps || {})
    },
  })

  // When doing Client Routing, we mutate pageContext (see usage of `app.changePage()` in `_default.page.client.js`).
  // We therefore use a reactive pageContext.
  const pageContextReactive = reactive(pageContext)

  // Make `pageContext` accessible from any Vue component
  setPageContext(app, pageContextReactive)

  return app
}
Example #28
Source File: index.ts    From vue3-echarts with MIT License 5 votes vote down vote up
render() {
    return h('div', { class: 'vue-echarts' });
  }
Example #29
Source File: index.spec.ts    From css-render with MIT License 4 votes vote down vote up
describe('ssr', () => {
  describe('render to string', () => {
    const Child = defineComponent({
      setup () {
        c('div', {
          color: 'red'
        }).mount({
          id: 'mount-id',
          ssr: useSsrAdapter()
        })
      },
      render () {
        return h('div', null, 'Child')
      }
    })
    const App = defineComponent({
      render () {
        return h(Child)
      }
    })
    const app = createSSRApp(App)
    const { collect } = setup(app)
    it('should work', (done) => {
      renderToString(app).then((v) => {
        expect(collect() + v).toMatchSnapshot()
        done()
      })
    })
  })
  describe('useSsrAdapter', () => {
    const Child = defineComponent({
      setup () {
        c('div', {
          color: 'red'
        }).mount({
          id: 'mount-id',
          ssr: useSsrAdapter()
        })
      },
      render () {
        return h('div', null, 'Child')
      }
    })
    const App = defineComponent({
      render () {
        return h(Child)
      }
    })
    const app = createSSRApp(App)
    const { collect } = setup(app)
    it('should work', (done) => {
      renderToString(app).then((v) => {
        expect(collect() + v).toMatchSnapshot()
        done()
      })
    })
  })
  // uncomment after vue fixes the stream ssr bug
  // describe('render to stream', () => {
  //   it('should work', (done) => {
  //     const app = createSSRApp({
  //       render () {
  //         return [
  //           h(Foo),
  //           h(Suspense, null, {
  //             default: () => h(Bar),
  //             ssFallback: () => 'suspense'
  //           }),
  //           h(Foo)
  //         ]
  //       }
  //     })
  //     const Foo = {
  //       setup () {
  //         c('div', {
  //           color: 'foo'
  //         }).mount({
  //           id: 'foo',
  //           ssr: ssrAdapter
  //         })
  //       },
  //       render: () => h('div', 'foo')
  //     }
  //     const Bar = {
  //       async setup () {
  //         c('div', {
  //           color: 'bar'
  //         }).mount({
  //           id: 'bar',
  //           ssr: ssrAdapter
  //         })
  //         await new Promise((resolve) => setTimeout(resolve, 1000))
  //       },
  //       render: () => {
  //         return [h('div', 'bar'), h(Foo)]
  //       }
  //     }
  //     const { collect } = setup(app)
  //     const rs = renderToStream(app)
  //     let html = ''
  //     rs.on('data', (chunk) => {
  //       html += `${collect()}\n${chunk.toString() as string}`
  //     })
  //     rs.on('end', () => {
  //       expect(html).toMatchSnapshot()
  //       done()
  //     })
  //   })
  // })
})