From cb9ad8388ef87ed7a29d2a2413e9fad4a07efd05 Mon Sep 17 00:00:00 2001 From: Roman Semenov Date: Fri, 25 Oct 2024 03:21:53 +0400 Subject: [PATCH] remove renovation --- .../js/renovation/component_wrapper/button.ts | 138 -------- .../devextreme/js/renovation/ui/button.tsx | 315 ------------------ .../js/renovation/ui/common/icon.tsx | 63 ---- .../js/renovation/ui/common/ink_ripple.tsx | 50 --- 4 files changed, 566 deletions(-) delete mode 100644 packages/devextreme/js/renovation/component_wrapper/button.ts delete mode 100644 packages/devextreme/js/renovation/ui/button.tsx delete mode 100644 packages/devextreme/js/renovation/ui/common/icon.tsx delete mode 100644 packages/devextreme/js/renovation/ui/common/ink_ripple.tsx diff --git a/packages/devextreme/js/renovation/component_wrapper/button.ts b/packages/devextreme/js/renovation/component_wrapper/button.ts deleted file mode 100644 index f5aa3ab13e5c..000000000000 --- a/packages/devextreme/js/renovation/component_wrapper/button.ts +++ /dev/null @@ -1,138 +0,0 @@ -/* eslint-disable @typescript-eslint/no-unsafe-member-access */ -// eslint-disable-next-line import/named -import { dxElementWrapper } from '../../core/renderer'; -import ValidationEngine from '../../ui/validation_engine'; -import Component from './common/component'; -import type { Button } from '../ui/button'; -import { Option } from './common/types'; -import { getImageSourceType } from '../../core/utils/icon'; - -export default class ButtonWrapper extends Component { - _clickAction!: (...args) => unknown; - - // eslint-disable-next-line @typescript-eslint/no-explicit-any - get _validationGroupConfig(): any { - // eslint-disable-next-line @typescript-eslint/no-unsafe-return - return ValidationEngine.getGroupConfig(this._findGroup()); - } - - getDefaultTemplateNames(): string[] { - return ['content']; - } - - getSupportedKeyNames(): string[] { - return ['space', 'enter']; - } - - getProps(): Record { - const props = super.getProps(); - - props.onClick = ({ event }): void => { - this._clickAction({ event, validationGroup: this._validationGroupConfig }); - }; - - const iconType = getImageSourceType(props.icon); - if (iconType === 'svg') { - props.iconTemplate = this._createTemplateComponent(() => props.icon); - } - - return props; - } - - get _templatesInfo(): Record { - return { template: 'content' }; - } - - _toggleActiveState(_: HTMLElement, value: boolean): void { - const button = this.viewRef as Button; - value ? button.activate() : button.deactivate(); - } - - // eslint-disable-next-line @typescript-eslint/no-explicit-any - _getSubmitAction(): any { - let needValidate = true; - let validationStatus = 'valid'; - - // eslint-disable-next-line @typescript-eslint/no-explicit-any - return (this as any)._createAction(({ event, submitInput }) => { - if (needValidate) { - const validationGroup = this._validationGroupConfig; - - if (validationGroup !== undefined && validationGroup !== '') { - const validationResult = validationGroup.validate(); - - validationStatus = validationResult.status; - - if (validationResult.status === 'pending') { - needValidate = false; - this.option('disabled', true); - - validationResult.complete.then(({ status }) => { - this.option('disabled', false); - - validationStatus = status; - validationStatus === 'valid' && submitInput.click(); - needValidate = true; - }); - } - } - } - - validationStatus !== 'valid' && event.preventDefault(); - event.stopPropagation(); - }); - } - - _initializeComponent(): void { - super._initializeComponent(); - this._addAction('onSubmit', this._getSubmitAction()); - this._clickAction = this._createClickAction(); - } - - _initMarkup(): void { - super._initMarkup(); - - const $content = (this.$element() as unknown as dxElementWrapper).find('.dx-button-content').first(); - const $template = $content.children().filter('.dx-template-wrapper'); - const $input = $content.children().filter('.dx-button-submit-input'); - - if ($template.length) { - $template.addClass('dx-button-content'); - $template.append($input); - $content.replaceWith($template); - } - } - - _patchOptionValues(options: Record): Record { - return super._patchOptionValues({ ...options, templateData: options._templateData }); - } - - // eslint-disable-next-line @typescript-eslint/no-explicit-any - _findGroup(): any { - const $element = this.$element(); - const validationGroup = this.option('validationGroup'); - return validationGroup !== undefined && validationGroup !== '' - ? validationGroup - // eslint-disable-next-line @typescript-eslint/no-explicit-any - : (ValidationEngine as any).findGroup($element, (this as any)._modelByElement($element)); - } - - _createClickAction(): (...args) => unknown { - return this._createActionByOption('onClick', { - excludeValidators: ['readOnly'], - }); - } - - _optionChanged(option: Option): void { - switch (option.name) { - case 'onClick': - this._clickAction = this._createClickAction(); - break; - default: - break; - } - - super._optionChanged(option); - } -} -/* eslint-enable @typescript-eslint/no-unsafe-member-access */ diff --git a/packages/devextreme/js/renovation/ui/button.tsx b/packages/devextreme/js/renovation/ui/button.tsx deleted file mode 100644 index a7d20c6e1d29..000000000000 --- a/packages/devextreme/js/renovation/ui/button.tsx +++ /dev/null @@ -1,315 +0,0 @@ -import { - Component, - ComponentBindings, - Effect, - Event, - JSXComponent, - Method, - OneWay, - Ref, - Template, - Slot, - RefObject, -} from '@devextreme-generator/declarations'; -import { createDefaultOptionRules } from '../../core/options/utils'; -import devices from '../../core/devices'; -import { isMaterial, current } from '../../ui/themes'; -import { click } from '../../events/short'; -import { combineClasses } from '../utils/combine_classes'; -import { getImageSourceType } from '../../core/utils/icon'; -import { camelize } from '../../core/utils/inflector'; -import { Icon } from './common/icon'; -import { InkRipple, InkRippleConfig } from './common/ink_ripple'; -import { Widget } from './common/widget'; -import { BaseWidgetProps } from './common/base_props'; -// eslint-disable-next-line import/no-cycle -import BaseComponent from '../component_wrapper/button'; -import messageLocalization from '../../localization/message'; -import { EffectReturn } from '../utils/effect_return'; - -const stylingModes = ['outlined', 'text', 'contained']; - -const getCssClasses = (model: ButtonProps): string => { - const { - text, icon, stylingMode, type, iconPosition, - } = model; - const isValidStylingMode = stylingMode && stylingModes.includes(stylingMode); - const classesMap = { - 'dx-button': true, - [`dx-button-mode-${isValidStylingMode ? stylingMode : 'contained'}`]: true, - [`dx-button-${type ?? 'normal'}`]: true, - 'dx-button-has-text': !!text, - 'dx-button-has-icon': !!icon, - 'dx-button-icon-right': iconPosition !== 'left', - }; - - return combineClasses(classesMap); -}; -export const viewFunction = (viewModel: Button): JSX.Element => { - const { - children, iconPosition, text, - template: ButtonTemplate, - iconTemplate: IconTemplate, - } = viewModel.props; - const renderText = !ButtonTemplate && !children && text !== ''; - const isIconLeft = iconPosition === 'left'; - const iconComponent = !ButtonTemplate && !children && (viewModel.iconSource || IconTemplate) - && ( - - ); - - return ( - -
- {ButtonTemplate && ()} - {!ButtonTemplate && children} - {isIconLeft && iconComponent} - {renderText && ({text})} - {!isIconLeft && iconComponent} - {viewModel.props.useSubmitBehavior - && } - {viewModel.props.useInkRipple - && ( - - )} -
-
- ); -}; - -@ComponentBindings() -export class ButtonProps extends BaseWidgetProps { - @OneWay() activeStateEnabled = true; - - @OneWay() hoverStateEnabled = true; - - @OneWay() icon = ''; - - @OneWay() iconPosition?: string = 'left'; - - @Event({ - actionConfig: { excludeValidators: ['readOnly'] }, - }) - onClick?: (e: { event: Event }) => void; - - @Event() onSubmit?: (e: { event: Event; submitInput: HTMLInputElement | null }) => void; - - @OneWay() pressed?: boolean; - - @OneWay() stylingMode: 'outlined' | 'text' | 'contained' = 'contained'; - - @Template() template?: (props: { data: { icon?: string; text?: string } }) => JSX.Element; - - @Template() iconTemplate?: (props) => JSX.Element; - - @Slot() children?: JSX.Element; - - @OneWay() text = ''; - - @OneWay() type: 'danger' | 'default' | 'normal' | 'success' = 'normal'; - - @OneWay() useInkRipple = false; - - @OneWay() useSubmitBehavior = false; - - @OneWay() templateData?: Record = {}; -} - -export const defaultOptionRules = createDefaultOptionRules([{ - device: (): boolean => devices.real().deviceType === 'desktop' && !devices.isSimulator(), - options: { focusStateEnabled: true }, -}, { - // eslint-disable-next-line import/no-named-as-default-member - device: (): boolean => isMaterial(current()), - options: { useInkRipple: true }, -}]); -@Component({ - defaultOptionRules, - jQuery: { - component: BaseComponent, - register: true, - }, - view: viewFunction, -}) - -export class Button extends JSXComponent(ButtonProps) { - @Ref() contentRef!: RefObject; - - @Ref() inkRippleRef!: RefObject; - - @Ref() submitInputRef!: RefObject; - - @Ref() widgetRef!: RefObject; - - @Method() - focus(): void { - this.widgetRef.current!.focus(); - } - - @Method() - activate(): void { - this.widgetRef.current!.activate(); - } - - @Method() - deactivate(): void { - this.widgetRef.current!.deactivate(); - } - - @Effect() - submitEffect(): EffectReturn { - const namespace = 'UIFeedback'; - const { useSubmitBehavior, onSubmit } = this.props; - - if (useSubmitBehavior && onSubmit) { - click.on(this.submitInputRef.current, - (event) => onSubmit({ event, submitInput: this.submitInputRef.current }), - { namespace }); - - return (): void => click.off(this.submitInputRef.current, { namespace }); - } - - return undefined; - } - - onActive(event: Event): void { - const { useInkRipple } = this.props; - - useInkRipple && this.inkRippleRef.current!.showWave({ - element: this.contentRef.current!, event, - }); - } - - onInactive(event: Event): void { - const { useInkRipple } = this.props; - - useInkRipple && this.inkRippleRef.current!.hideWave({ - element: this.contentRef.current!, event, - }); - } - - onWidgetClick(event: Event): void { - const { - onClick, - useSubmitBehavior, - } = this.props; - - onClick?.({ event }); - useSubmitBehavior && this.submitInputRef.current!.click(); - } - - keyDown(e: { - originalEvent: Event & { cancel: boolean }; - keyName: string; - which: string; - }): Event | undefined { - const { onKeyDown } = this.props; - const { originalEvent, keyName, which } = e; - - const result: Event & { cancel: boolean } = onKeyDown?.(e); - if (result?.cancel) { - return result; - } - - if (keyName === 'space' || which === 'space' || keyName === 'enter' || which === 'enter') { - (originalEvent as Event).preventDefault(); - this.emitClickEvent(); - } - - return undefined; - } - - emitClickEvent(): void { - this.contentRef.current!.click(); - } - - get aria(): Record { - const { text, icon } = this.props; - - let label = text ?? ''; - - if (!text && icon) { - const iconSource = getImageSourceType(icon); - - switch (iconSource) { - case 'image': { - const notURLRegexp = /^(?!(?:https?:\/\/)|(?:ftp:\/\/)|(?:www\.))[^\s]+$/; - const isPathToImage = !icon.includes('base64') && notURLRegexp.test(icon); - label = isPathToImage ? icon.replace(/.+\/([^.]+)\..+$/, '$1') : ''; - break; - } - case 'dxIcon': - label = messageLocalization.format(camelize(icon, true)) || icon; - break; - case 'fontIcon': - label = icon; - break; - case 'svg': { - const titleRegexp = /(.*?)<\/title>/; - const title = titleRegexp.exec(icon)?.[1] ?? ''; - label = title; - break; - } - default: - break; - } - } - - return { - role: 'button', - ...label ? { label } : {}, - }; - } - - get cssClasses(): string { - return getCssClasses(this.props); - } - - get iconSource(): string { - const { icon } = this.props; - - return icon ?? ''; - } - - get inkRippleConfig(): InkRippleConfig { - const { text, icon } = this.props; - return !text && icon ? { - isCentered: true, - useHoldAnimation: false, - waveSizeCoefficient: 1, - } : {}; - } - - get buttonTemplateData(): Record<string, unknown> { - const { icon, text, templateData } = this.props; - return { icon, text, ...templateData }; - } -} diff --git a/packages/devextreme/js/renovation/ui/common/icon.tsx b/packages/devextreme/js/renovation/ui/common/icon.tsx deleted file mode 100644 index 4a582f4d8128..000000000000 --- a/packages/devextreme/js/renovation/ui/common/icon.tsx +++ /dev/null @@ -1,63 +0,0 @@ -import { - Component, ComponentBindings, JSXComponent, OneWay, Fragment, Template, -} from '@devextreme-generator/declarations'; -import { getImageSourceType } from '../../../core/utils/icon'; -import { combineClasses } from '../../utils/combine_classes'; - -export const viewFunction = ({ - sourceType, - iconClassName, - props: { source, iconTemplate: IconTemplate }, -}: Icon): JSX.Element => ( - <Fragment> - {sourceType === 'dxIcon' && (<i className={iconClassName} />)} - {sourceType === 'fontIcon' && (<i className={iconClassName} />)} - {sourceType === 'image' && (<img className={iconClassName} alt="" src={source} />)} - {IconTemplate && (<i className={iconClassName}><IconTemplate /></i>)} - </Fragment> -); - -@ComponentBindings() -export class IconProps { - @OneWay() position?: string = 'left'; - - @OneWay() source?: string = ''; - - @Template() iconTemplate?: (props) => JSX.Element; -} - -@Component({ - defaultOptionRules: null, - view: viewFunction, -}) -export class Icon extends JSXComponent(IconProps) { - get sourceType(): string | false { - return getImageSourceType(this.props.source); - } - - get cssClass(): string { - return this.props.position !== 'left' ? 'dx-icon-right' : ''; - } - - get iconClassName(): string { - const generalClasses = { - 'dx-icon': true, - [this.cssClass]: !!this.cssClass, - }; - const { source } = this.props; - - if (this.sourceType === 'dxIcon') { - return combineClasses({ ...generalClasses, [`dx-icon-${source}`]: true }); - } - if (this.sourceType === 'fontIcon') { - return combineClasses({ ...generalClasses, [String(source)]: !!source }); - } - if (this.sourceType === 'image') { - return combineClasses(generalClasses); - } - if (this.sourceType === 'svg') { - return combineClasses({ ...generalClasses, 'dx-svg-icon': true }); - } - return ''; - } -} diff --git a/packages/devextreme/js/renovation/ui/common/ink_ripple.tsx b/packages/devextreme/js/renovation/ui/common/ink_ripple.tsx deleted file mode 100644 index e1a297e84bd4..000000000000 --- a/packages/devextreme/js/renovation/ui/common/ink_ripple.tsx +++ /dev/null @@ -1,50 +0,0 @@ -import { - Component, ComponentBindings, JSXComponent, OneWay, Method, -} from '@devextreme-generator/declarations'; -import { initConfig, showWave, hideWave } from '../../../ui/widget/utils.ink_ripple'; - -// TODO: remake old ink ripple in new JSX component -export const viewFunction = (model: InkRipple): JSX.Element => ( - <div - className="dx-inkripple" - {...model.restAttributes} // eslint-disable-line react/jsx-props-no-spreading - /> -); - -export interface InkRippleConfig { - isCentered?: boolean; - useHoldAnimation?: boolean; - waveSizeCoefficient?: number; - wavesNumber?: number; - durations?: { - showingScale: number; - hidingScale: number; - hidingOpacity: number; - }; -} - -@ComponentBindings() -export class InkRippleProps { - @OneWay() config?: InkRippleConfig = {}; -} - -@Component({ - defaultOptionRules: null, - view: viewFunction, -}) -export class InkRipple extends JSXComponent(InkRippleProps) { - @Method() - hideWave(opts: { element?: HTMLElement; event: Event }): void { - hideWave(this.getConfig, opts); - } - - @Method() - showWave(opts: { element?: HTMLElement; event: Event; wave?: number }): void { - showWave(this.getConfig, opts); - } - - get getConfig(): InkRippleConfig { - const { config } = this.props; - return initConfig(config); - } -}