All files / src createSmartForm.ts

87.5% Statements 91/104
92.3% Branches 12/13
90% Functions 9/10
87.5% Lines 91/104

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 1051x 1x 1x 1x 1x 1x 1x 1x 1x 5x 5x 5x 5x 5x 5x 5x 5x 5x 1x 1x 1x 1x 5x 5x 1x 1x 3x 3x 3x 3x 1x 1x 1x 1x 1x 1x 1x 1x 1x 2x 2x 2x 2x 2x 2x 2x 2x                   2x 2x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 2x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x         1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 2x 2x 2x 2x 2x  
import { App, markRaw, Component } from 'vue'
import { CustomCompData, FormItemData, PreDefineCompData } from './types'
 
interface SmartForm {
  predefinedComponents: Map<string, Component>
  install: (app: App) => void
}
 
export function createSmartForm(): SmartForm {
  const smartForm: SmartForm = markRaw({
    install(app: App) {
      setActiveSmartForm(smartForm)
    },
    predefinedComponents: new Map(),
  })
 
  return smartForm
}
 
let activeSmartForm: SmartForm
 
export const setActiveSmartForm = (s: SmartForm) => {
  activeSmartForm = s
}
 
export const getActiveSmartForm = (): SmartForm => {
  // const currentInstance = getCurrentInstance()
  // return (currentInstance && inject(SmartFormSymbol)) ||
  return activeSmartForm
}
 
type Comp = {
  component: Component
  modelValueKey?: string
}
 
// const SmartFormSymbol: InjectionKey<SmartForm> = Symbol('SmartFormSymbol')
 
export const defineFormType = <A extends string, C extends Component>(
  alias: A,
  comp: C
) => {
  const sf = getActiveSmartForm()
  //todo check name
  sf.predefinedComponents.set(alias, comp)
 
  const usePredefineComponentType = (
    options: POptions<A, C>
  ): PreDefineCompData<A, C> => {
    return {
      ...options,
      component: markRaw(comp),
      type: 'PREDEFINE',
      alias: alias,
    }
  }
  return usePredefineComponentType
}
 
export const defineFormTypes = <C extends Record<string, Comp>>(compMap: C) => {
  const useDefineSchema = () => {
    Object.entries(compMap).forEach(([k, c]) => defineFormType(k, c.component))
 
    const sf = getActiveSmartForm()
 
    const defineSchema = <T extends keyof C & string>(
      options: (POptions<T, C[T]['component']> | CustomCompData)[]
    ): FormItemData[] => {
      return options.map((c) => {
        if (isValidAlias(sf.predefinedComponents, c)) {
          return {
            modelValueKey: compMap[c.alias].modelValueKey,
            ...c,
            component: markRaw(sf.predefinedComponents.get(c.alias)!),
            type: 'PREDEFINE',
            alias: c.alias,
          } as FormItemData
        } else if (c.type === 'CUSTOM') {
          return c
        } else {
          throw new Error(
            'type error, please use `defineFormType` or `useCustomItem`'
          )
        }
      })
    }
 
    return defineSchema
  }
 
  return useDefineSchema
}
 
export type POptions<A extends string, C = any> = Omit<
  PreDefineCompData<A, C>,
  'component' | 'type'
>
 
const isValidAlias = <T extends string>(
  map: SmartForm['predefinedComponents'],
  p: any
): p is POptions<T> => {
  return map.has(p.alias)
}