Skip to content

Commit

Permalink
🎹 Pager: Migrate dom_component_wrapper from R1 (#27822)
Browse files Browse the repository at this point in the history
  • Loading branch information
Raushen authored Jul 26, 2024
1 parent 5dba7e6 commit d4384ba
Show file tree
Hide file tree
Showing 3 changed files with 164 additions and 2 deletions.
162 changes: 162 additions & 0 deletions packages/devextreme/js/__internal/core/r1/dom_component_wrapper.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
/* eslint-disable @typescript-eslint/no-unsafe-return */
/* eslint-disable @typescript-eslint/no-explicit-any */
import {
hasTemplate, InfernoComponent, InfernoEffect, renderTemplate,
} from '@devextreme/runtime/inferno';
import type { ComponentClass } from '@js/core/dom_component';
import type { EventCallback } from '@js/renovation/ui/common/event_callback';
import { getUpdatedOptions } from '@js/renovation/ui/common/utils/get_updated_options';
import type { DisposeEffectReturn } from '@js/renovation/utils/effect_return';
import type { RefObject } from 'inferno';
import { createRef } from 'inferno';

import type DomComponent from '../../../core/dom_component';
import { extend } from '../../../core/utils/extend';
import { ConfigContext } from '../../../renovation/common/config_context';

interface ComponentProps {
className?: string;
itemTemplate?: string | (() => string | HTMLElement);
valueChange?: EventCallback<any>;
}

export interface DomComponentWrapperProps {
componentType: ComponentClass<any>;
templateNames: string[];
componentProps: ComponentProps;
}

const normalizeProps = (props: ComponentProps): ComponentProps => Object
.keys(props).reduce((accumulator, key) => {
if (props[key] !== undefined) {
accumulator[key] = props[key];
}

return accumulator;
}, {});

export class DomComponentWrapper extends InfernoComponent<DomComponentWrapperProps> {
public state: any = {};

public refs: any = null;

private readonly widgetRef: RefObject<HTMLDivElement> = createRef();

private instance: DomComponent | null = null;

private prevProps: ComponentProps | null = null;

constructor(props) {
super(props);
this.getInstance = this.getInstance.bind(this);
this.setupWidget = this.setupWidget.bind(this);
this.updateWidget = this.updateWidget.bind(this);
}

getConfig(): any {
const { id } = (ConfigContext as any);
if (this.context[id]) {
return this.context[id];
}
return (ConfigContext as any).defaultValue;
}

render(): JSX.Element {
return (
<div
ref={this.widgetRef}
className={this.props.componentProps.className}
{...this.props}
/>
);
}

componentWillUpdate(nextProps: DomComponentWrapperProps, nextState, context): void {
super.componentWillUpdate(nextProps, nextState, context);
}

createEffects(): InfernoEffect[] {
return [
new InfernoEffect(this.setupWidget, []),
new InfernoEffect(
this.updateWidget,
[
this.props.componentProps,
this.getConfig(),
this.props.templateNames,
],
)];
}

updateEffects(): void {
const dependency = [this.props.componentProps, this.getConfig(), this.props.templateNames];
this._effects[1]?.update(dependency);
}

setupWidget(): DisposeEffectReturn {
const current = this.widgetRef.current as HTMLDivElement;
// eslint-disable-next-line new-cap
const componentInstance = new this.props.componentType(current, this.getProperties());
this.instance = componentInstance;
return () => {
componentInstance.dispose();
this.instance = null;
};
}

updateWidget(): void {
if (!this.instance) {
return;
}
const updatedOptions = getUpdatedOptions(this.prevProps ?? {}, this.getProperties());
if (updatedOptions.length) {
this.instance.beginUpdate();
updatedOptions.forEach((_ref2) => {
const {
path,
value,
} = _ref2;
this.instance?.option(path, value);
});
this.instance.endUpdate();
}
this.prevProps = this.getProperties();
}

getProperties(): any {
const normalizedProps = normalizeProps(this.props.componentProps);
const {
valueChange,
} = normalizedProps;
const properties = extend({
rtlEnabled: this.getConfig()?.rtlEnabled,
isRenovated: true,
}, normalizedProps);
if (valueChange) {
properties.onValueChanged = (_ref3): any => {
const {
value,
} = _ref3;
return valueChange(value);
};
}
const templates = this.props.templateNames as any;
templates.forEach((name) => {
if (hasTemplate(name, properties, this)) {
properties[name] = (item, index, container): any => {
renderTemplate((this.props.componentProps as any)[name], {
item,
index,
container,
}, this);
};
}
});
return properties;
}

getInstance(): any {
return this.instance;
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React from 'react';
import { shallow } from 'enzyme';
import { NumberBox, NumberBoxProps, viewFunction as NumberBoxView } from '../number_box';
import { DomComponentWrapper } from '../../common/dom_component_wrapper';
import { DomComponentWrapper } from '../../../../__internal/core/r1/dom_component_wrapper';
import LegacyNumberBox from '../../../../ui/number_box';
import { EditorStateProps } from '../common/editor_state_props';
import { EditorLabelProps } from '../common/editor_label_props';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import {
Component, ComponentBindings, JSXComponent, OneWay, TwoWay, React, Event,
} from '@devextreme-generator/declarations';
import LegacyNumberBox from '../../../ui/number_box';
import { DomComponentWrapper } from '../common/dom_component_wrapper';
import { DomComponentWrapper } from '../../../__internal/core/r1/dom_component_wrapper';
import { EventCallback } from '../common/event_callback';
import { EditorProps } from './common/editor';
import { EditorStateProps } from './common/editor_state_props';
Expand Down

0 comments on commit d4384ba

Please sign in to comment.