Skip to content

Commit

Permalink
Merge branch 'dev'
Browse files Browse the repository at this point in the history
  • Loading branch information
foolishchow committed Apr 16, 2024
2 parents c486178 + 79fbadf commit 6bcc7c6
Show file tree
Hide file tree
Showing 18 changed files with 4,843 additions and 40 deletions.
1 change: 1 addition & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
"**/Thumbs.db": true,
"**/node_modules": true,
},
"editor.formatOnSave": true,
"[typescript]": {
"editor.defaultFormatter": "vscode.typescript-language-features"
},
Expand Down
2 changes: 2 additions & 0 deletions element/examples/api/time-picker/control.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,13 @@ const FormBuilder = useFormBuilder<BaseInfo>()
if (hour === 18) {
return makeRange(31, 59)
}
return []
},
disabledSeconds(hour: number, minute: number) {
if (hour === 18 && minute === 30) {
return makeRange(1, 59)
}
return []
}
}
})
Expand Down
17 changes: 10 additions & 7 deletions element/package.json
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
{
"name": "vform-element",
"version": "2.0.0-alpha.5",
"version": "2.0.1",
"description": "基于 Vue3 和 Element-plus 的动态表单组件",
"keywords": [
"Vue3","element-plus","form","动态表单"
"Vue3",
"element-plus",
"form",
"动态表单"
],
"main": "lib/index.cjs.js",
"module": "lib/index.es.js",
"upkg":"lib/index.umd.js",
"upkg": "lib/index.umd.js",
"types": "lib/index.d.ts",
"author": "foolishchow",
"license": "MIT",
Expand All @@ -24,7 +27,7 @@
},
"dependencies": {
"vue-types": "~3.0.2",
"vue":"~3.2.34"
"vue": "~3.2.34"
},
"devDependencies": {
"@element-plus/icons-vue": "^1.1.4",
Expand All @@ -40,13 +43,13 @@
"tslib": "^2.4.0",
"typescript": "^4.5.4",
"vitepress": "^0.22.4",
"vitepress-live-demo":"0.0.6",
"vitepress-theme-document":"0.0.1",
"vitepress-live-demo": "0.0.6",
"vitepress-theme-document": "0.0.1",
"vue-tsc": "^0.34.7"
},
"files": [
"lib",
"package.json",
"README.md"
]
}
}
37 changes: 29 additions & 8 deletions element/src/form/builder.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { createVForm, VForm } from './index';
import type { VFormItem, VFormItemTypes } from './renders';
import type { Merge } from './type-merge';
import type { _DynamicDef, DeepKey, DynamicDef } from './types';
import type { _DynamicDef, DeepKey, DynamicDef } from './types';
import { wrapDynamic } from './utils';

export type BuildTypes = Exclude<keyof VFormItemTypes & string, 'form' | 'build' | 'merge'>
Expand All @@ -24,15 +24,15 @@ interface Builder_Items<Type extends BuildTypes, T extends object, Configed exte
type MergeResult<
Source extends object, SourceConfig,
IncommingConfig
> = keyof IncommingConfig extends DeepKey<Source>
? Builder<Source, Merge<IncommingConfig, SourceConfig>>
: never
> = keyof IncommingConfig extends DeepKey<Source>
? Builder<Source, Merge<IncommingConfig, SourceConfig>>
: never

interface Builder_Merger<T extends object, Configed = {}> {
<U extends object, _Configed extends object>(builder: Builder<U, _Configed>): MergeResult<T, Configed, _Configed>
}

type Builder_Methods = 'form'|'build' | 'merge' | BuildTypes
type Builder_Methods = 'form' | 'build' | 'merge' | BuildTypes

type BuilderInstance<Type extends Builder_Methods, T extends object, Configed extends object = {}> =
| Type extends 'form' ? Builder_Form<T>
Expand Down Expand Up @@ -64,13 +64,13 @@ export function useFormBuilder<T extends object>(data?: T): Builder<T> {
return (target._configs ?? []).map(wrapDynamic)
}
}
if(prototype == 'merge'){
return function(toMerge:any){
if (prototype == 'merge') {
return function (toMerge: any) {
target._configs.push(...toMerge.$raw)
return receiver
}
}
if(prototype == '$raw'){
if (prototype == '$raw') {
return target._configs ?? []
}
return (config: ProxyedConfig<T>) => {
Expand All @@ -85,3 +85,24 @@ export function useFormBuilder<T extends object>(data?: T): Builder<T> {
}


interface Normal_Builder_Items<Type extends BuildTypes, T extends object> {
<Key extends DeepKey<T> = never>(
config: DynamicDef<T, VFormItemTypes<T, Key>[Type]>
): NormalBuilder<T>
}

type NormalBuilderInstance<Type extends Builder_Methods, T extends object> =
| Type extends 'form' ? Builder_Form<T>
: Type extends 'build' ? Builder_<T, {}>
: Type extends 'merge' ? Builder_Merger<T, {}>
: Type extends BuildTypes ? Normal_Builder_Items<Type, T>
: never

export type NormalBuilder<T extends object> = {
readonly [Type in Builder_Methods]: NormalBuilderInstance<Type, T>
}

export function useNormalFormBuilder<T extends object>(data?: T): NormalBuilder<T> {
return useFormBuilder(data) as any
}

2 changes: 1 addition & 1 deletion element/src/form/renders/cascader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ registerRender({
render: (props, item) => {
return <ElCascader {...mergeProps(props.form, item.props) as Omit<VCascaderProps, 'props'>}
modelValue={getWithTransfer(props.form, item.dataIndex, item?.transfer)}
onUpdate:modelValue={e => setWithTransfer(props.form, item.dataIndex, e, item?.transfer)}
onUpdate:modelValue={e => setWithTransfer(props.form, item.dataIndex, e as any, item?.transfer)}
v-slots={item.slots}
/>
}
Expand Down
6 changes: 3 additions & 3 deletions element/src/form/renders/checkbox-group.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ type VCheckboxGroupProps = VueProps<typeof ElCheckboxGroup>
export interface VCheckboxGroupItem<
T extends object,
Key extends DeepKey<T> = DeepKey<T>,
> extends VBaseItem<T, Key> {
> extends VBaseItem<T, Key> {
/**
* 类型 cascader
*/
Expand Down Expand Up @@ -69,7 +69,7 @@ registerRender({
optionsNodes = options.map((option, index) => {
return <ElCheckboxButton
key={index}
label={dotGet(option, optionConfig.label as any)}
label={dotGet(option, optionConfig.value as any)}
disabled={dotGet(option, optionConfig.disabled as any)}
name={dotGet(option, optionConfig.name as any)}
>
Expand All @@ -92,7 +92,7 @@ registerRender({
}
return <ElCheckboxGroup {...mergeProps(props.form, item.props) as VCheckboxGroupProps}
modelValue={getWithTransfer(props.form, item.dataIndex, item?.transfer)}
onUpdate:modelValue={e => setWithTransfer(props.form, item.dataIndex, e, item?.transfer)}
onUpdate:modelValue={e => setWithTransfer(props.form, item.dataIndex, e as any, item?.transfer)}
>
{optionsNodes}
{item.slots?.default?.()}
Expand Down
2 changes: 1 addition & 1 deletion element/src/form/renders/color-picker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ registerRender({
return <ElColorPicker
{...mergeProps(props.form, item.props)}
modelValue={getWithTransfer(props.form, item.dataIndex, item?.transfer)}
onUpdate:modelValue={e => setWithTransfer(props.form, item.dataIndex, e, item?.transfer)}
onUpdate:modelValue={e => setWithTransfer(props.form, item.dataIndex, e as any, item?.transfer)}
/>
}
})
5 changes: 3 additions & 2 deletions element/src/form/renders/input-number.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ export interface VInputNumberItem<T extends object, Key extends DeepKey<T> = Dee
* `element-plus InputNumber`的属性
*/
props?: VPropDef<T, InputNumberProps>
transfer?: VTransfer<Into<T, Key>, string | number>
}

registerRender({
Expand All @@ -24,9 +25,9 @@ registerRender({
// @ts-ignore
return <ElInputNumber {...mergeProps(props.form, item.props)}
// v-model:value={props.form[item.dataIndex as any]}
modelValue={getWithTransfer(props.form, item.dataIndex)}
modelValue={getWithTransfer(props.form, item.dataIndex, item.transfer)}
// @ts-ignore
onUpdate:modelValue={e => setWithTransfer(props.form, item.dataIndex, e)}
onUpdate:modelValue={e => setWithTransfer(props.form, item.dataIndex, e, item.transfer)}
// v-model:value={props.form[item.dataIndex]}
/>
}
Expand Down
7 changes: 4 additions & 3 deletions element/src/form/renders/input.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { ElInput } from 'element-plus'
import type { DeepKey, VPropDef, VueProps } from '../types';
import type { DeepKey, Into, VPropDef, VTransfer, VueProps } from '../types';
import { registerRender } from '../register'
import { getWithTransfer, mergeProps, setWithTransfer } from '../utils'
import type { VBaseItem } from '.';
Expand All @@ -22,15 +22,16 @@ export interface VInputItem<T extends object, Key extends DeepKey<T> = DeepKey<T
prepend?: JSX.Element | { (): JSX.Element | string }
append?: JSX.Element | { (): JSX.Element | string }
}
transfer?: VTransfer<Into<T, Key>, string>
}
registerRender({
type: 'Input',
render(props, item) {
return () => {
// @ts-ignore
return <ElInput {...mergeProps(props.form, item.props)}
modelValue={getWithTransfer(props.form, item.dataIndex)}
onUpdate:modelValue={e => setWithTransfer(props.form, item.dataIndex, e as any)}
modelValue={getWithTransfer(props.form, item.dataIndex, item.transfer)}
onUpdate:modelValue={e => setWithTransfer(props.form, item.dataIndex, e as any, item.transfer)}
v-slots={item.slots}
/>
}
Expand Down
4 changes: 2 additions & 2 deletions element/src/form/renders/radio-group.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ type VRadioGroupProps = VueProps<typeof ElRadioGroup>
export interface VRadioGroupItem<
T extends object,
Key extends DeepKey<T> = DeepKey<T>,
> extends VBaseItem<T, Key> {
> extends VBaseItem<T, Key> {
/**
* 类型 cascader
*/
Expand Down Expand Up @@ -68,7 +68,7 @@ registerRender({
optionsNodes = options.map((option, index) => {
return <ElRadioButton
key={index}
label={dotGet(option, optionProps.label as any)}
label={dotGet(option, optionProps.value as any)}
disabled={dotGet(option, optionProps.disabled as any)}
name={dotGet(option, optionProps.name as any)}
>
Expand Down
2 changes: 1 addition & 1 deletion element/src/form/renders/select-v2.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ registerRender({
type: 'SelectV2',
render: (props, item) => {
return <ElSelectV2
{...mergeProps(props.form, item.props)}
{...mergeProps(props.form, item.props) as any}
modelValue={getWithTransfer(props.form, item.dataIndex)}
onUpdate:modelValue={e => setWithTransfer(props.form, item.dataIndex, e as any)}
v-slots={item.slots}
Expand Down
2 changes: 1 addition & 1 deletion element/src/form/renders/select.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ function renderOption<T extends object>(item: VSelectItem<T>, index: number, opt
if (isGroupOption(item, option)) {
const label = item.slots?.optionGroup ? item.slots?.optionGroup(option, index) : dotGet(option as any, optionConfig.label as any)
return <ElOptionGroup label={label} key={index}>
{renderOptions(item, optionConfig, dotGet(option, item.optionConfig?.children ?? 'children'))}
{renderOptions(item, optionConfig, dotGet(option, item.optionConfig?.children as any ?? 'children'))}
</ElOptionGroup>
}
if (item.slots?.option) {
Expand Down
2 changes: 1 addition & 1 deletion element/src/form/renders/slider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ registerRender({
render(props, item) {
return <ElSlider {...mergeProps(props.form, item.props)}
modelValue={getWithTransfer(props.form, item.dataIndex, item?.transfer)}
onUpdate:modelValue={e => setWithTransfer(props.form, item.dataIndex, e, item?.transfer)}
onUpdate:modelValue={e => setWithTransfer(props.form, item.dataIndex, e as any, item?.transfer)}
/>
}
})
Expand Down
61 changes: 55 additions & 6 deletions element/src/form/types.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,61 @@
import type { ButtonProps, FormProps } from 'element-plus'
import type { VFormItem } from './renders';

type Primitive = string | number | boolean | bigint | symbol | null | undefined;


export type DeepKey<T> = 0 extends 1 & T ? any
: T extends Primitive ? never
: T extends (infer Data)[]
? Data extends Primitive
? `${number}`
: `${number}.${DeepKey<Data>}`
: T extends object
? {
[Key in keyof T & (string | number)]: `${Key}` | `${Key}.${DeepKey<T[Key]>}`
}[keyof T & (string | number)]
: never;


type Got<T, Key> = T extends Primitive ? unknown
: T extends (infer Item)[]
? Key extends `${number}` ? Item : unknown
: Key extends keyof T ? T[Key] : unknown

export type Into<T, Key extends string> = 0 extends 1 & T ? any
: T extends Primitive ? unknown
: Key extends `${infer Start}.${infer End}`
? Into<Got<T, Start>, End>
: Got<T, Key>

type UserInfo = {
name: string,
info: {
age: number
books: {
bookName: string
}[]
favor: {
bookName: {
dest: string
chapter: number
}
}
}
}

type ddd = '0' extends `${number}` ? true : false
type ss = DeepKey<string[]>




export type isAny<Data> = 0 extends 1 & Data ? true : false;
export type DeepKey<Data> = Data extends (infer T)[] ? DeepKey<T> : 0 extends 1 & Data ? string : _DeepKeyOf<Data>
// export type DeepKey<Data> = Data extends (infer T)[] ? DeepKey<T> : 0 extends 1 & Data ? string : _DeepKeyOf<Data>
export type _DeepKeyOf<Data> = 0 extends 1 & Data
? never
: Data extends (infer T)[]
? _DeepKeyOf<T>
? `[${number}]${_DeepKeyOf<T>}`
: Data extends object
? {
[Key in keyof Data & (string | number)]: `${Key}` | `${Key}.${_DeepKeyOf<Data[Key]>}`
Expand All @@ -18,10 +66,11 @@ export type DeepFlatten<Data, Keys extends string = DeepKey<Data>> = {
[key in Keys]: Into<Data, key>
}

export type Into<T extends Record<keyof any, any>, Key extends string> =
Key extends `${infer Start}.${infer End}` ?
Start extends keyof T ? Into<T[Start], End> : never
: Key extends keyof T ? T[Key] : never
// export type Into<T, Key extends string> =
// T extends Record<keyof any, any> ?
// Key extends `${infer Start}.${infer End}` ?
// Start extends keyof T ? Into<T[Start], End> : never
// : Key extends keyof T ? T[Key] : never : never

export type InstanceOf<T> = T extends { new(...args: any[]): infer U } ? U : never

Expand Down
2 changes: 1 addition & 1 deletion element/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export { useFormBuilder } from './form/builder'
export { useFormBuilder, type Builder, type NormalBuilder, useNormalFormBuilder } from './form/builder'
export { lazyComputed } from './form/utils'
export { registerRender, registerDefaultLabelRender } from './form/register'
export * from './form/renders'
Expand Down
2 changes: 1 addition & 1 deletion element/src/utils/vue-types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ export const PropTypes = {
/**
* `Object` 类型
*/
object<T>() {
object<T extends object>() {
return object<T>()
},
/**
Expand Down
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "v-from",
"version": "0.0.1",
"description": "v-from",
"private":true,
"private": true,
"author": "foolishchow",
"license": "MIT",
"workspaces": [
Expand All @@ -16,6 +16,7 @@
"scripts": {
"serve": "lerna run serve --parallel",
"watch": "lerna run watch --parallel",
"dev": "lerna run dev --parallel",
"b": "lerna bootstrap"
}
}
}
Loading

0 comments on commit 6bcc7c6

Please sign in to comment.