-
Notifications
You must be signed in to change notification settings - Fork 2.5k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
51 changed files
with
829 additions
and
885 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
import { createDecorator, Barrier } from '@alilc/lowcode-shared'; | ||
|
||
/** | ||
* 生命周期阶段 | ||
*/ | ||
export const enum LifecyclePhase { | ||
/** | ||
* 开始 | ||
*/ | ||
Starting = 1, | ||
/** | ||
* 已就绪 | ||
*/ | ||
Ready = 2, | ||
/** | ||
* 销毁中 | ||
*/ | ||
Destroying = 3, | ||
} | ||
|
||
export interface ILifeCycleService { | ||
/** | ||
* A flag indicating in what phase of the lifecycle we currently are. | ||
*/ | ||
phase: LifecyclePhase; | ||
|
||
setPhase(phase: LifecyclePhase): void; | ||
|
||
/** | ||
* Returns a promise that resolves when a certain lifecycle phase | ||
* has started. | ||
*/ | ||
when(phase: LifecyclePhase): Promise<void>; | ||
|
||
onWillDestory(): void; | ||
} | ||
|
||
export const ILifeCycleService = createDecorator<ILifeCycleService>('lifeCycleService'); | ||
|
||
export class LifeCycleService implements ILifeCycleService { | ||
private readonly phaseWhen = new Map<LifecyclePhase, Barrier>(); | ||
|
||
private _phase = LifecyclePhase.Starting; | ||
|
||
get phase(): LifecyclePhase { | ||
return this._phase; | ||
} | ||
|
||
setPhase(value: LifecyclePhase) { | ||
if (value < this._phase) { | ||
throw new Error('Lifecycle cannot go backwards'); | ||
} | ||
|
||
if (this._phase === value) { | ||
return; | ||
} | ||
|
||
this._phase = value; | ||
|
||
const barrier = this.phaseWhen.get(this._phase); | ||
if (barrier) { | ||
barrier.open(); | ||
this.phaseWhen.delete(this._phase); | ||
} | ||
} | ||
|
||
async when(phase: LifecyclePhase): Promise<void> { | ||
if (phase <= this._phase) { | ||
return; | ||
} | ||
|
||
let barrier = this.phaseWhen.get(phase); | ||
if (!barrier) { | ||
barrier = new Barrier(); | ||
this.phaseWhen.set(phase, barrier); | ||
} | ||
|
||
await barrier.wait(); | ||
} | ||
|
||
onWillDestory(): void {} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
export interface ITheme { | ||
type: string; | ||
|
||
value: string; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
import { Disposable, Events, type IDisposable, createDecorator } from '@alilc/lowcode-shared'; | ||
import { type ITheme } from './theme'; | ||
|
||
export interface IThemeService extends IDisposable { | ||
getTheme(): ITheme; | ||
|
||
onDidColorThemeChange: Events.Event<ITheme>; | ||
} | ||
|
||
export const IThemeService = createDecorator<IThemeService>('themeService'); | ||
|
||
export class ThemeService extends Disposable implements IThemeService { | ||
private _activeTheme: ITheme; | ||
|
||
private _onDidColorThemeChange = this._addDispose(new Events.Emitter<ITheme>()); | ||
onDidColorThemeChange = this._onDidColorThemeChange.event; | ||
|
||
getTheme(): ITheme { | ||
return this._activeTheme; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,60 +1,9 @@ | ||
import { createRenderer } from '@alilc/lowcode-renderer-core'; | ||
import { type Root, createRoot } from 'react-dom/client'; | ||
import { type IRendererContext, RendererContext, getRenderInstancesByAccessor } from './context'; | ||
import { ApplicationView, boosts } from '../app'; | ||
import { type ReactAppOptions } from './types'; | ||
import { App, type AppOptions } from '../app'; | ||
|
||
export const createApp = async (options: ReactAppOptions) => { | ||
return createRenderer(async (service) => { | ||
const contextValue: IRendererContext = service.invokeFunction((accessor) => { | ||
return { | ||
options, | ||
...getRenderInstancesByAccessor(accessor), | ||
}; | ||
}); | ||
export const createApp = async (options: AppOptions) => { | ||
const app = new App(options); | ||
|
||
contextValue.boostsManager.extend(boosts.toExpose()); | ||
await app.startup(); | ||
|
||
let root: Root | undefined; | ||
|
||
return { | ||
async mount(containerOrId) { | ||
if (root) return; | ||
|
||
const defaultId = contextValue.schema.get<string>('config.targetRootID', 'app'); | ||
const rootElement = normalizeContainer(containerOrId, defaultId); | ||
|
||
root = createRoot(rootElement); | ||
root.render( | ||
<RendererContext.Provider value={contextValue}> | ||
<ApplicationView /> | ||
</RendererContext.Provider>, | ||
); | ||
}, | ||
unmount() { | ||
if (root) { | ||
root.unmount(); | ||
root = undefined; | ||
} | ||
}, | ||
}; | ||
})(options); | ||
return app; | ||
}; | ||
|
||
function normalizeContainer(container: Element | string | undefined, defaultId: string): Element { | ||
let result: Element | undefined = undefined; | ||
|
||
if (typeof container === 'string') { | ||
const el = document.getElementById(container); | ||
if (el) result = el; | ||
} else if (container instanceof window.Element) { | ||
result = container; | ||
} | ||
|
||
if (!result) { | ||
result = document.createElement('div'); | ||
result.id = defaultId; | ||
} | ||
|
||
return result; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,53 +1,38 @@ | ||
import { createRenderer } from '@alilc/lowcode-renderer-core'; | ||
import { type ComponentTreeRoot } from '@alilc/lowcode-shared'; | ||
import { type FunctionComponent } from 'react'; | ||
import { type StringDictionary, type ComponentTree } from '@alilc/lowcode-shared'; | ||
import { CodeRuntime } from '@alilc/lowcode-renderer-core'; | ||
import { FunctionComponent, ComponentType } from 'react'; | ||
import { | ||
type LowCodeComponentProps, | ||
createComponent as createSchemaComponent, | ||
} from '../runtime/createComponent'; | ||
import { type IRendererContext, RendererContext, getRenderInstancesByAccessor } from './context'; | ||
import { type ReactAppOptions } from './types'; | ||
|
||
interface Render { | ||
toComponent(): FunctionComponent<LowCodeComponentProps>; | ||
type ComponentOptions as SchemaComponentOptions, | ||
reactiveStateFactory, | ||
} from '../runtime'; | ||
import { type ComponentsAccessor } from '../app'; | ||
|
||
export interface ComponentOptions extends SchemaComponentOptions { | ||
schema: ComponentTree; | ||
componentsRecord: Record<string, ComponentType>; | ||
codeScope?: StringDictionary; | ||
} | ||
|
||
export async function createComponent(options: ReactAppOptions) { | ||
const creator = createRenderer<Render>((service) => { | ||
const contextValue: IRendererContext = service.invokeFunction((accessor) => { | ||
return { | ||
options, | ||
...getRenderInstancesByAccessor(accessor), | ||
}; | ||
}); | ||
|
||
const componentsTree = contextValue.schema.get<ComponentTreeRoot>('componentsTree.0'); | ||
|
||
if (!componentsTree) { | ||
throw new Error('componentsTree is required'); | ||
} | ||
|
||
const LowCodeComponent = createSchemaComponent(componentsTree, { | ||
displayName: componentsTree.componentName, | ||
...options.component, | ||
}); | ||
|
||
function Component(props: LowCodeComponentProps) { | ||
return ( | ||
<RendererContext.Provider value={contextValue}> | ||
<LowCodeComponent {...props} /> | ||
</RendererContext.Provider> | ||
); | ||
} | ||
|
||
return { | ||
toComponent() { | ||
return Component; | ||
}, | ||
}; | ||
export function createComponent( | ||
options: ComponentOptions, | ||
): FunctionComponent<LowCodeComponentProps> { | ||
const { schema, componentsRecord, modelOptions, codeScope, ...componentOptions } = options; | ||
const codeRuntime = new CodeRuntime(codeScope); | ||
const components: ComponentsAccessor = { | ||
getComponent(componentName) { | ||
return componentsRecord[componentName] as any; | ||
}, | ||
}; | ||
|
||
const LowCodeComponent = createSchemaComponent(schema, codeRuntime, components, { | ||
...componentOptions, | ||
modelOptions: { | ||
...modelOptions, | ||
stateCreator: modelOptions.stateCreator ?? reactiveStateFactory, | ||
}, | ||
}); | ||
|
||
const render = await creator(options); | ||
|
||
return render.toComponent(); | ||
return LowCodeComponent; | ||
} |
Oops, something went wrong.