Merge pull request #568 from smartxworks/fix/windlike-dev

fix: fix the `exampleProperties` type errors
This commit is contained in:
tanbowensg 2022-08-16 15:39:06 +08:00 committed by GitHub
commit 87074162c9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 234 additions and 110 deletions

View File

@ -36,10 +36,10 @@ export const getComponentProps = <
TState,
TMethods,
TSlots extends Record<string, SlotSpec>,
KStyleSlot extends string,
KEvent extends string
KStyleSlots extends ReadonlyArray<string>,
KEvents extends ReadonlyArray<string>
>(
props: T & ComponentImplProps<T, TState, TMethods, TSlots, KStyleSlot, KEvent>
props: T & ComponentImplProps<T, TState, TMethods, TSlots, KStyleSlots, KEvents>
) => {
const {
/* eslint-disable @typescript-eslint/no-unused-vars */

View File

@ -24,7 +24,6 @@ const PropsSpec = Type.Object({
});
export const implementTable = implementRuntimeComponent({
kind: 'Component',
version: 'chakra_ui/v1',
metadata: {
name: 'table',

View File

@ -34,6 +34,7 @@
"dependencies": {},
"devDependencies": {
"@swc/core": "^1.2.121",
"@sinclair/typebox": "^0.21.2",
"@types/jest": "^26.0.23",
"@types/json-schema": "^7.0.7",
"@typescript-eslint/eslint-plugin": "^4.28.1",

View File

@ -1,59 +1,83 @@
import { JSONSchema7 } from 'json-schema';
import type { Static } from '@sinclair/typebox';
import { parseVersion, Version } from './version';
import { ComponentMetadata } from './metadata';
import { MethodSchema } from './method';
import { SlotSpec } from './slot';
type DeepPartial<T> = T extends Record<string, any> | Record<string, any>[]
? Partial<{
[K in keyof T]: DeepPartial<T[K]>;
}>
: T;
type ComponentSpec<
KMethodName extends string,
KStyleSlot extends string,
KSlot extends string,
KEvent extends string
KProperties extends JSONSchema7,
KState extends JSONSchema7,
KMethods extends Record<string, MethodSchema['parameters']>,
KStyleSlots extends ReadonlyArray<string>,
KSlots extends Record<string, SlotSpec>,
KEvents extends ReadonlyArray<string>
> = {
properties: JSONSchema7;
state: JSONSchema7;
methods: Record<KMethodName, MethodSchema['parameters']>;
styleSlots: ReadonlyArray<KStyleSlot>;
slots: Record<KSlot, SlotSpec>;
events: ReadonlyArray<KEvent>;
properties: KProperties;
state: KState;
methods: KMethods;
styleSlots: KStyleSlots;
slots: KSlots;
events: KEvents;
};
export type Component<
KMethodName extends string,
KStyleSlot extends string,
KSlot extends string,
KEvent extends string
KProperties extends JSONSchema7,
KState extends JSONSchema7,
KMethods extends Record<string, MethodSchema['parameters']>,
KStyleSlots extends ReadonlyArray<string>,
KSlots extends Record<string, SlotSpec>,
KEvents extends ReadonlyArray<string>
> = {
version: string;
kind: 'Component';
metadata: ComponentMetadata;
spec: ComponentSpec<KMethodName, KStyleSlot, KSlot, KEvent>;
metadata: ComponentMetadata<DeepPartial<Static<KProperties>>>;
spec: ComponentSpec<KProperties, KState, KMethods, KStyleSlots, KSlots, KEvents>;
};
export type RuntimeComponent<
KMethodName extends string,
KStyleSlot extends string,
KSlot extends string,
KEvent extends string
> = Component<KMethodName, KStyleSlot, KSlot, KEvent> & {
KProperties extends JSONSchema7,
KState extends JSONSchema7,
KMethods extends Record<string, MethodSchema['parameters']>,
KStyleSlots extends ReadonlyArray<string>,
KSlots extends Record<string, SlotSpec>,
KEvents extends ReadonlyArray<string>
> = Component<KProperties, KState, KMethods, KStyleSlots, KSlots, KEvents> & {
parsedVersion: Version;
};
export type CreateComponentOptions<
KMethodName extends string,
KStyleSlot extends string,
KSlot extends string,
KEvent extends string
> = Omit<Component<KMethodName, KStyleSlot, KSlot, KEvent>, 'kind'>;
KProperties extends JSONSchema7,
KState extends JSONSchema7,
KMethods extends Record<string, MethodSchema['parameters']>,
KStyleSlots extends ReadonlyArray<string>,
KSlots extends Record<string, SlotSpec>,
KEvents extends ReadonlyArray<string>
> = Omit<Component<KProperties, KState, KMethods, KStyleSlots, KSlots, KEvents>, 'kind'>;
export function createComponent<
KMethodName extends string,
KStyleSlot extends string,
KSlot extends string,
KEvent extends string
KProperties extends JSONSchema7,
KState extends JSONSchema7,
KMethods extends Record<string, MethodSchema['parameters']>,
KStyleSlots extends ReadonlyArray<string>,
KSlots extends Record<string, SlotSpec>,
KEvents extends ReadonlyArray<string>
>(
options: CreateComponentOptions<KMethodName, KStyleSlot, KSlot, KEvent>
): RuntimeComponent<KMethodName, KStyleSlot, KSlot, KEvent> {
options: CreateComponentOptions<
KProperties,
KState,
KMethods,
KStyleSlots,
KSlots,
KEvents
>
): RuntimeComponent<KProperties, KState, KMethods, KStyleSlots, KSlots, KEvents> {
return {
...options,
kind: 'Component',

View File

@ -1,10 +1,11 @@
import { JSONSchema7Object } from 'json-schema';
export type Metadata<TAnnotations = Record<string, unknown>> = {
export type Metadata<
TAnnotations = Record<string, unknown>,
TExample = Record<string, any>
> = {
name: string;
description?: string;
annotations?: Record<string, any> & TAnnotations;
exampleProperties?: JSONSchema7Object;
exampleProperties?: TExample;
};
type ComponentCategory =
@ -15,7 +16,10 @@ type ComponentCategory =
| 'Advance'
| undefined;
export type ComponentMetadata = Metadata<{ category?: ComponentCategory }> & {
export type ComponentMetadata<TExample = Record<string, any>> = Metadata<
{ category?: ComponentCategory },
TExample
> & {
// TODO:(yanzhen): move to annotations
displayName: string;
icon?: string;

View File

@ -6,7 +6,12 @@ import {
CoreTraitName,
AnyTypePlaceholder,
} from '@sunmao-ui/shared';
import { ComponentSchema, MethodSchema, RuntimeComponent } from '@sunmao-ui/core';
import {
ComponentSchema,
MethodSchema,
RuntimeComponent,
SlotSpec,
} from '@sunmao-ui/core';
import { genComponent, genTrait } from './utils';
import {
ComponentId,
@ -32,10 +37,12 @@ const DynamicStateTrait = [
];
type ComponentSpecModel = RuntimeComponent<
MethodName,
StyleSlotName,
SlotName,
EventName
any,
any,
Record<MethodName, MethodSchema['parameters']>,
ReadonlyArray<StyleSlotName>,
Record<SlotName, SlotSpec>,
ReadonlyArray<EventName>
>;
export class ComponentModel implements IComponentModel {
spec: ComponentSpecModel;

View File

@ -16,9 +16,10 @@ import { CoreComponentName, CORE_VERSION } from '@sunmao-ui/shared';
import { groupBy, sortBy } from 'lodash';
import { EditorServices } from '../../types';
import { ExplorerMenuTabs } from '../../constants/enum';
import { RuntimeComponent } from '@sunmao-ui/core';
import { RuntimeComponent, SlotSpec } from '@sunmao-ui/core';
import { css } from '@emotion/css';
import { ComponentFilter } from './ComponentFilter';
import { JSONSchema7 } from 'json-schema';
type Props = {
services: EditorServices;
@ -26,7 +27,14 @@ type Props = {
type Category = {
name: string;
components: RuntimeComponent<string, string, string, string>[];
components: RuntimeComponent<
any,
any,
Record<string, JSONSchema7 | undefined>,
ReadonlyArray<string>,
Record<string, SlotSpec>,
ReadonlyArray<string>
>[];
};
const PRESET_CATEGORY_ORDER = {

View File

@ -1,4 +1,4 @@
import { RuntimeComponent } from '@sunmao-ui/core';
import { RuntimeComponent, SlotSpec } from '@sunmao-ui/core';
import { RegistryInterface } from '@sunmao-ui/runtime';
import Ajv from 'ajv';
import { PropertiesValidatorRule } from '.';
@ -13,6 +13,7 @@ import {
ValidatorMap,
} from './interfaces';
import { rules } from './rules';
import { JSONSchema7 } from 'json-schema';
export class SchemaValidator implements ISchemaValidator {
private result: ValidateErrorResult[] = [];
@ -22,7 +23,14 @@ export class SchemaValidator implements ISchemaValidator {
private propertiesRules: PropertiesValidatorRule[] = [];
private componentIdSpecMap: Record<
string,
RuntimeComponent<string, string, string, string>
RuntimeComponent<
any,
any,
Record<string, JSONSchema7 | undefined>,
ReadonlyArray<string>,
Record<string, SlotSpec>,
ReadonlyArray<string>
>
> = {};
private ajv!: Ajv;

View File

@ -1,4 +1,4 @@
import { ComponentSchema, RuntimeComponent } from '@sunmao-ui/core';
import { ComponentSchema, RuntimeComponent, SlotSpec } from '@sunmao-ui/core';
import { RegistryInterface } from '@sunmao-ui/runtime';
import Ajv, { ValidateFunction } from 'ajv';
import { AppModel } from '../AppModel/AppModel';
@ -8,6 +8,7 @@ import {
IFieldModel,
ITraitModel,
} from '../AppModel/IAppModel';
import { JSONSchema7 } from 'json-schema';
export interface ValidatorMap {
components: Record<string, ValidateFunction>;
@ -22,7 +23,17 @@ interface BaseValidateContext {
appModel: IAppModel;
ajv: Ajv;
dependencyNames: string[];
componentIdSpecMap: Record<string, RuntimeComponent<string, string, string, string>>;
componentIdSpecMap: Record<
string,
RuntimeComponent<
any,
any,
Record<string, JSONSchema7 | undefined>,
ReadonlyArray<string>,
Record<string, SlotSpec>,
ReadonlyArray<string>
>
>;
}
export interface ComponentValidateContext extends BaseValidateContext {

View File

@ -28,20 +28,20 @@ export const ImplWrapperMain = React.forwardRef<HTMLDivElement, ImplWrapperProps
const { mergeState, subscribeMethods, executeTrait } = useRuntimeFunctions(props);
const [traitResults, setTraitResults] = useState<TraitResult<string, string>[]>(
() => {
return c.traits.map(t =>
executeTrait(
t,
stateManager.deepEval(t.properties, {
evalListItem,
scopeObject: { $slot: slotProps },
fallbackWhenError: () => undefined,
})
)
);
}
);
const [traitResults, setTraitResults] = useState<
TraitResult<ReadonlyArray<string>, ReadonlyArray<string>>[]
>(() => {
return c.traits.map(t =>
executeTrait(
t,
stateManager.deepEval(t.properties, {
evalListItem,
scopeObject: { $slot: slotProps },
fallbackWhenError: () => undefined,
})
)
);
});
useEffect(() => {
return () => {
@ -81,9 +81,15 @@ export const ImplWrapperMain = React.forwardRef<HTMLDivElement, ImplWrapperProps
}, [c.id, c.traits, executeTrait, stateManager, slotProps, evalListItem]);
// reduce traitResults
const propsFromTraits: TraitResult<string, string>['props'] = useMemo(() => {
const propsFromTraits: TraitResult<
ReadonlyArray<string>,
ReadonlyArray<string>
>['props'] = useMemo(() => {
return Array.from(traitResults.values()).reduce(
(prevProps, result: TraitResult<string, string>) => {
(
prevProps,
result: TraitResult<ReadonlyArray<string>, ReadonlyArray<string>>
) => {
if (!result.props) {
return prevProps;
}
@ -96,7 +102,7 @@ export const ImplWrapperMain = React.forwardRef<HTMLDivElement, ImplWrapperProps
}
});
},
{} as TraitResult<string, string>['props']
{} as TraitResult<ReadonlyArray<string>, ReadonlyArray<string>>['props']
);
}, [traitResults]);

View File

@ -23,12 +23,13 @@ export const UnmountImplWrapper = React.forwardRef<HTMLDivElement, ImplWrapperPr
);
const [isHidden, setIsHidden] = useState(() => {
const results: TraitResult<string, string>[] = unmountTraits.map(t => {
const properties = stateManager.deepEval(t.properties, {
scopeObject: { $slot: props.slotProps },
const results: TraitResult<ReadonlyArray<string>, ReadonlyArray<string>>[] =
unmountTraits.map(t => {
const properties = stateManager.deepEval(t.properties, {
scopeObject: { $slot: props.slotProps },
});
return executeTrait(t, properties);
});
return executeTrait(t, properties);
});
return results.some(result => result.unmount);
});

View File

@ -1,4 +1,5 @@
import { parseType } from '@sunmao-ui/core';
import { JSONSchema7 } from 'json-schema';
import { parseType, SlotSpec } from '@sunmao-ui/core';
// components
/* --- core --- */
import CoreText from '../components/core/Text';
@ -36,17 +37,26 @@ import { ImplementedUtilMethod } from '../types/utilMethod';
import { UtilMethodManager } from './UtilMethodManager';
export type SunmaoLib = {
components?: ImplementedRuntimeComponent<string, string, string, string>[];
components?: ImplementedRuntimeComponent<
any,
any,
Record<string, JSONSchema7 | undefined>,
ReadonlyArray<string>,
Record<string, SlotSpec>,
ReadonlyArray<string>
>[];
traits?: ImplementedRuntimeTraitFactory[];
modules?: ImplementedRuntimeModule[];
utilMethods?: UtilMethodFactory[];
};
type AnyImplementedRuntimeComponent = ImplementedRuntimeComponent<
string,
string,
string,
string
any,
any,
Record<string, JSONSchema7 | undefined>,
ReadonlyArray<string>,
Record<string, SlotSpec>,
ReadonlyArray<string>
>;
export type RegistryInterface = InstanceType<typeof Registry>;

View File

@ -1,9 +1,11 @@
import { JSONSchema7 } from 'json-schema';
import { Static } from '@sinclair/typebox';
import {
RuntimeApplication,
RuntimeComponentSchema,
RuntimeComponent,
SlotSpec,
MethodSchema,
} from '@sunmao-ui/core';
import React from 'react';
import { UIServices, ComponentParamsFromApp } from './application';
@ -29,10 +31,10 @@ export type ComponentImplProps<
TState,
TMethods,
TSlots extends Record<string, SlotSpec>,
KStyleSlot extends string,
KEvent extends string
KStyleSlots extends ReadonlyArray<string>,
KEvents extends ReadonlyArray<string>
> = ImplWrapperProps<TProps, string> &
TraitResult<KStyleSlot, KEvent>['props'] &
TraitResult<KStyleSlots, KEvents>['props'] &
RuntimeFunctions<TState, TMethods, TSlots> & {
elementRef?: React.MutableRefObject<any>;
getElement?: (ele: HTMLElement) => void;
@ -40,21 +42,23 @@ export type ComponentImplProps<
export type ComponentImpl<
TProps extends Record<string, unknown> = Record<string, unknown>,
TState = any,
TState = Record<string, any>,
TMethods = Record<string, any>,
TSlots extends Record<string, SlotSpec> = Record<string, any>,
KStyleSlot extends string = string,
KEvent extends string = string
KStyleSlots extends ReadonlyArray<string> = ReadonlyArray<string>,
KEvents extends ReadonlyArray<string> = ReadonlyArray<string>
> = React.FC<
TProps & ComponentImplProps<TProps, TState, TMethods, TSlots, KStyleSlot, KEvent>
TProps & ComponentImplProps<TProps, TState, TMethods, TSlots, KStyleSlots, KEvents>
>;
export type ImplementedRuntimeComponent<
KMethodName extends string,
KStyleSlot extends string,
KSlot extends string,
KEvent extends string
> = RuntimeComponent<KMethodName, KStyleSlot, KSlot, KEvent> & {
KProperties extends JSONSchema7,
KState extends JSONSchema7,
KMethods extends Record<string, MethodSchema['parameters']>,
KStyleSlots extends ReadonlyArray<string>,
KSlots extends Record<string, SlotSpec>,
KEvents extends ReadonlyArray<string>
> = RuntimeComponent<KProperties, KState, KMethods, KStyleSlots, KSlots, KEvents> & {
impl: ComponentImpl<any>;
};

View File

@ -2,11 +2,16 @@ import { RuntimeTrait, RuntimeTraitSchema } from '@sunmao-ui/core';
import { UIServices } from './application';
import { RuntimeFunctions } from './component';
export type TraitResult<KStyleSlot extends string, KEvent extends string> = {
type ToStringUnion<T extends ReadonlyArray<string>> = T[number];
export type TraitResult<
KStyleSlots extends ReadonlyArray<string>,
KEvents extends ReadonlyArray<string>
> = {
props: {
data?: unknown;
customStyle?: Record<KStyleSlot, string>;
callbackMap?: CallbackMap<KEvent>;
customStyle?: Record<ToStringUnion<KStyleSlots>, string>;
callbackMap?: CallbackMap<ToStringUnion<KEvents>>;
componentDidUnmount?: Array<() => void>;
componentDidMount?: Array<() => Function | void>;
componentDidUpdate?: Array<() => Function | void>;
@ -23,7 +28,7 @@ export type TraitImpl<TProperties = any> = (
evalListItem?: boolean;
slotProps?: unknown;
}
) => TraitResult<string, string>;
) => TraitResult<ReadonlyArray<string>, ReadonlyArray<string>>;
export type TraitImplFactory<T = any> = () => TraitImpl<T>;

View File

@ -1,4 +1,5 @@
import { Static } from '@sinclair/typebox';
import { JSONSchema7 } from 'json-schema';
import {
createComponent,
CreateComponentOptions,
@ -7,8 +8,9 @@ import {
TraitSpec,
createUtilMethod,
CreateUtilMethodOptions,
SlotSpec,
MethodSchema,
} from '@sunmao-ui/core';
import { type DeepPartial } from '@sunmao-ui/shared';
import {
ComponentImpl,
ImplementedRuntimeComponent,
@ -25,27 +27,61 @@ type ToMap<U> = {
type ToStringUnion<T extends ReadonlyArray<string>> = T[number];
export function implementRuntimeComponent<
KMethodName extends string,
KStyleSlot extends string,
KSlot extends string,
KStyle extends string,
KEvent extends string,
T extends CreateComponentOptions<KMethodName, KStyleSlot, KSlot, KEvent>
T extends CreateComponentOptions<
T['spec']['properties'] extends JSONSchema7 ? T['spec']['properties'] : JSONSchema7,
T['spec']['state'] extends JSONSchema7 ? T['spec']['state'] : JSONSchema7,
T['spec']['methods'] extends Record<string, MethodSchema['parameters']>
? T['spec']['methods']
: Record<string, MethodSchema['parameters']>,
ToStringUnion<T['spec']['styleSlots']> extends KStyle
? ReadonlyArray<ToStringUnion<T['spec']['styleSlots']>>
: ReadonlyArray<KStyle>,
T['spec']['slots'] extends Record<string, SlotSpec>
? T['spec']['slots']
: Record<string, SlotSpec>,
ToStringUnion<T['spec']['events']> extends KEvent
? ReadonlyArray<ToStringUnion<T['spec']['events']>>
: ReadonlyArray<KEvent>
>
>(
options: T & {
metadata: { exampleProperties: DeepPartial<Static<T['spec']['properties']>> };
}
options: T
): (
impl: ComponentImpl<
Static<T['spec']['properties']> extends Record<string, unknown>
? Static<T['spec']['properties']>
: Record<string, unknown>,
Static<T['spec']['state']>,
Static<T['spec']['state']> extends Record<string, any>
? Static<T['spec']['state']>
: Record<string, any>,
ToMap<T['spec']['methods']>,
T['spec']['slots'],
ToStringUnion<T['spec']['styleSlots']>,
ToStringUnion<T['spec']['events']>
T['spec']['slots'] extends Record<string, SlotSpec>
? T['spec']['slots']
: Record<string, SlotSpec>,
ToStringUnion<T['spec']['styleSlots']> extends KStyle
? ReadonlyArray<ToStringUnion<T['spec']['styleSlots']>>
: ReadonlyArray<KStyle>,
ToStringUnion<T['spec']['events']> extends KEvent
? ReadonlyArray<ToStringUnion<T['spec']['events']>>
: ReadonlyArray<KEvent>
>
) => ImplementedRuntimeComponent<KMethodName, KStyleSlot, KSlot, KEvent> {
) => ImplementedRuntimeComponent<
T['spec']['properties'] extends JSONSchema7 ? T['spec']['properties'] : JSONSchema7,
T['spec']['state'] extends JSONSchema7 ? T['spec']['state'] : JSONSchema7,
T['spec']['methods'] extends Record<string, MethodSchema['parameters']>
? T['spec']['methods']
: Record<string, MethodSchema['parameters']>,
ToStringUnion<T['spec']['styleSlots']> extends KStyle
? ReadonlyArray<ToStringUnion<T['spec']['styleSlots']>>
: ReadonlyArray<KStyle>,
T['spec']['slots'] extends Record<string, SlotSpec>
? T['spec']['slots']
: Record<string, SlotSpec>,
ToStringUnion<T['spec']['events']> extends KEvent
? ReadonlyArray<ToStringUnion<T['spec']['events']>>
: ReadonlyArray<KEvent>
> {
return impl => ({
...createComponent(options),
impl,

View File

@ -1,4 +1,4 @@
export type DeepPartial<T> = T extends Record<string, any>
export type DeepPartial<T> = T extends Record<string, any> | Record<string, any>[]
? Partial<{
[K in keyof T]: DeepPartial<T[K]>;
}>