From 8721dc723458b170d70a39fff71da9cfe027a3ed Mon Sep 17 00:00:00 2001 From: Mikhail Preyskurantov <5574159+mpreyskurantov@users.noreply.github.com> Date: Sun, 1 Mar 2026 21:29:46 +0200 Subject: [PATCH] skeleton --- apps/demos/configs/Angular/config.js | 1 + packages/devextreme-angular/src/index.ts | 1 + packages/devextreme-angular/src/ui/all.ts | 3 + .../src/ui/skeleton/index.ts | 391 ++++++++++++++++++ .../src/ui/skeleton/nested/index.ts | 2 + .../src/ui/skeleton/nested/ng-package.json | 5 + .../ui/skeleton/nested/root-complex-option.ts | 83 ++++ .../src/ui/skeleton/ng-package.json | 5 + .../make-angular-metadata.ts | 1 + packages/devextreme-react/src/index.ts | 1 + packages/devextreme-react/src/skeleton.ts | 89 ++++ packages/devextreme-vue/src/index.ts | 1 + packages/devextreme-vue/src/skeleton.ts | 130 ++++++ .../build/gulp/modules_metadata.json | 6 + .../js/__internal/ui/skeleton/skeleton.ts | 9 + .../devextreme/js/integration/jquery.d.ts | 7 + packages/devextreme/js/ui/skeleton.d.ts | 75 ++++ packages/devextreme/js/ui/skeleton.js | 5 + packages/devextreme/js/ui/skeleton_types.d.ts | 6 + packages/devextreme/ts/dx.all.d.ts | 48 +++ 20 files changed, 869 insertions(+) create mode 100644 packages/devextreme-angular/src/ui/skeleton/index.ts create mode 100644 packages/devextreme-angular/src/ui/skeleton/nested/index.ts create mode 100644 packages/devextreme-angular/src/ui/skeleton/nested/ng-package.json create mode 100644 packages/devextreme-angular/src/ui/skeleton/nested/root-complex-option.ts create mode 100644 packages/devextreme-angular/src/ui/skeleton/ng-package.json create mode 100644 packages/devextreme-react/src/skeleton.ts create mode 100644 packages/devextreme-vue/src/skeleton.ts create mode 100644 packages/devextreme/js/__internal/ui/skeleton/skeleton.ts create mode 100644 packages/devextreme/js/ui/skeleton.d.ts create mode 100644 packages/devextreme/js/ui/skeleton.js create mode 100644 packages/devextreme/js/ui/skeleton_types.d.ts diff --git a/apps/demos/configs/Angular/config.js b/apps/demos/configs/Angular/config.js index daf8948d74f5..d989766f00b6 100644 --- a/apps/demos/configs/Angular/config.js +++ b/apps/demos/configs/Angular/config.js @@ -64,6 +64,7 @@ const componentNames = [ 'scheduler', 'scroll-view', 'select-box', + 'skeleton', 'slider', 'sortable', 'sparkline', diff --git a/packages/devextreme-angular/src/index.ts b/packages/devextreme-angular/src/index.ts index e7a33f1eb8ac..00f6ed65abf0 100644 --- a/packages/devextreme-angular/src/index.ts +++ b/packages/devextreme-angular/src/index.ts @@ -62,6 +62,7 @@ export { DxSankeyComponent, DxSankeyModule } from 'devextreme-angular/ui/sankey' export { DxSchedulerComponent, DxSchedulerModule } from 'devextreme-angular/ui/scheduler'; export { DxScrollViewComponent, DxScrollViewModule } from 'devextreme-angular/ui/scroll-view'; export { DxSelectBoxComponent, DxSelectBoxModule } from 'devextreme-angular/ui/select-box'; +export { DxSkeletonComponent, DxSkeletonModule } from 'devextreme-angular/ui/skeleton'; export { DxSliderComponent, DxSliderModule } from 'devextreme-angular/ui/slider'; export { DxSortableComponent, DxSortableModule } from 'devextreme-angular/ui/sortable'; export { DxSparklineComponent, DxSparklineModule } from 'devextreme-angular/ui/sparkline'; diff --git a/packages/devextreme-angular/src/ui/all.ts b/packages/devextreme-angular/src/ui/all.ts index 4e9def085bff..1377c5f0bbed 100644 --- a/packages/devextreme-angular/src/ui/all.ts +++ b/packages/devextreme-angular/src/ui/all.ts @@ -58,6 +58,7 @@ import { DxSankeyModule } from 'devextreme-angular/ui/sankey'; import { DxSchedulerModule } from 'devextreme-angular/ui/scheduler'; import { DxScrollViewModule } from 'devextreme-angular/ui/scroll-view'; import { DxSelectBoxModule } from 'devextreme-angular/ui/select-box'; +import { DxSkeletonModule } from 'devextreme-angular/ui/skeleton'; import { DxSliderModule } from 'devextreme-angular/ui/slider'; import { DxSortableModule } from 'devextreme-angular/ui/sortable'; import { DxSparklineModule } from 'devextreme-angular/ui/sparkline'; @@ -145,6 +146,7 @@ import { DxTemplateModule } from 'devextreme-angular/core'; DxSchedulerModule, DxScrollViewModule, DxSelectBoxModule, + DxSkeletonModule, DxSliderModule, DxSortableModule, DxSparklineModule, @@ -231,6 +233,7 @@ import { DxTemplateModule } from 'devextreme-angular/core'; DxSchedulerModule, DxScrollViewModule, DxSelectBoxModule, + DxSkeletonModule, DxSliderModule, DxSortableModule, DxSparklineModule, diff --git a/packages/devextreme-angular/src/ui/skeleton/index.ts b/packages/devextreme-angular/src/ui/skeleton/index.ts new file mode 100644 index 000000000000..4b95b0ad7538 --- /dev/null +++ b/packages/devextreme-angular/src/ui/skeleton/index.ts @@ -0,0 +1,391 @@ +/* tslint:disable:max-line-length */ + + +import { + TransferState, + Component, + NgModule, + ElementRef, + NgZone, + PLATFORM_ID, + Inject, + + Input, + Output, + OnDestroy, + EventEmitter +} from '@angular/core'; + + +import { ContentReadyEvent, SkeletonComplexType } from 'devextreme/ui/skeleton'; +import { EventInfo } from 'devextreme/common/core/events'; + +import DxSkeleton from 'devextreme/ui/skeleton'; + + +import { + DxComponent, + DxTemplateHost, + DxIntegrationModule, + DxTemplateModule, + NestedOptionHost, + WatcherHelper, +} from 'devextreme-angular/core'; + + +import { DxoSkeletonRootComplexOptionModule } from 'devextreme-angular/ui/skeleton/nested'; + + + +@Component({ + selector: 'dx-skeleton', + standalone: true, + template: '', + host: { ngSkipHydration: 'true' }, + imports: [ DxIntegrationModule ], + providers: [ + DxTemplateHost, + WatcherHelper, + NestedOptionHost + ] +}) +export class DxSkeletonComponent extends DxComponent implements OnDestroy { + + instance: DxSkeleton = null; + + + @Input() + get accessKey(): string | undefined { + return this._getOption('accessKey'); + } + set accessKey(value: string | undefined) { + this._setOption('accessKey', value); + } + + + + @Input() + get activeStateEnabled(): boolean { + return this._getOption('activeStateEnabled'); + } + set activeStateEnabled(value: boolean) { + this._setOption('activeStateEnabled', value); + } + + + + @Input() + get disabled(): boolean { + return this._getOption('disabled'); + } + set disabled(value: boolean) { + this._setOption('disabled', value); + } + + + + @Input() + get elementAttr(): Record { + return this._getOption('elementAttr'); + } + set elementAttr(value: Record) { + this._setOption('elementAttr', value); + } + + + + @Input() + get focusStateEnabled(): boolean { + return this._getOption('focusStateEnabled'); + } + set focusStateEnabled(value: boolean) { + this._setOption('focusStateEnabled', value); + } + + + + @Input() + get height(): number | string | undefined { + return this._getOption('height'); + } + set height(value: number | string | undefined) { + this._setOption('height', value); + } + + + + @Input() + get hint(): string | undefined { + return this._getOption('hint'); + } + set hint(value: string | undefined) { + this._setOption('hint', value); + } + + + + @Input() + get hoverStateEnabled(): boolean { + return this._getOption('hoverStateEnabled'); + } + set hoverStateEnabled(value: boolean) { + this._setOption('hoverStateEnabled', value); + } + + + + @Input() + get rootComplexOption(): SkeletonComplexType { + return this._getOption('rootComplexOption'); + } + set rootComplexOption(value: SkeletonComplexType) { + this._setOption('rootComplexOption', value); + } + + + + @Input() + get rootPrimitiveOption(): number { + return this._getOption('rootPrimitiveOption'); + } + set rootPrimitiveOption(value: number) { + this._setOption('rootPrimitiveOption', value); + } + + + + @Input() + get rtlEnabled(): boolean { + return this._getOption('rtlEnabled'); + } + set rtlEnabled(value: boolean) { + this._setOption('rtlEnabled', value); + } + + + + @Input() + get tabIndex(): number { + return this._getOption('tabIndex'); + } + set tabIndex(value: number) { + this._setOption('tabIndex', value); + } + + + + @Input() + get visible(): boolean { + return this._getOption('visible'); + } + set visible(value: boolean) { + this._setOption('visible', value); + } + + + + @Input() + get width(): number | string | undefined { + return this._getOption('width'); + } + set width(value: number | string | undefined) { + this._setOption('width', value); + } + + /** + + * [descr:undefined] + + + */ + @Output() onContentReady: EventEmitter; + + /** + + * [descr:undefined] + + + */ + @Output() onDisposing: EventEmitter>; + + /** + + * [descr:undefined] + + + */ + @Output() onInitialized: EventEmitter; + + /** + + * [descr:undefined] + + + */ + @Output() onOptionChanged: EventEmitter; + + /** + + * This member supports the internal infrastructure and is not intended to be used directly from your code. + + */ + @Output() accessKeyChange: EventEmitter; + + /** + + * This member supports the internal infrastructure and is not intended to be used directly from your code. + + */ + @Output() activeStateEnabledChange: EventEmitter; + + /** + + * This member supports the internal infrastructure and is not intended to be used directly from your code. + + */ + @Output() disabledChange: EventEmitter; + + /** + + * This member supports the internal infrastructure and is not intended to be used directly from your code. + + */ + @Output() elementAttrChange: EventEmitter>; + + /** + + * This member supports the internal infrastructure and is not intended to be used directly from your code. + + */ + @Output() focusStateEnabledChange: EventEmitter; + + /** + + * This member supports the internal infrastructure and is not intended to be used directly from your code. + + */ + @Output() heightChange: EventEmitter; + + /** + + * This member supports the internal infrastructure and is not intended to be used directly from your code. + + */ + @Output() hintChange: EventEmitter; + + /** + + * This member supports the internal infrastructure and is not intended to be used directly from your code. + + */ + @Output() hoverStateEnabledChange: EventEmitter; + + /** + + * This member supports the internal infrastructure and is not intended to be used directly from your code. + + */ + @Output() rootComplexOptionChange: EventEmitter; + + /** + + * This member supports the internal infrastructure and is not intended to be used directly from your code. + + */ + @Output() rootPrimitiveOptionChange: EventEmitter; + + /** + + * This member supports the internal infrastructure and is not intended to be used directly from your code. + + */ + @Output() rtlEnabledChange: EventEmitter; + + /** + + * This member supports the internal infrastructure and is not intended to be used directly from your code. + + */ + @Output() tabIndexChange: EventEmitter; + + /** + + * This member supports the internal infrastructure and is not intended to be used directly from your code. + + */ + @Output() visibleChange: EventEmitter; + + /** + + * This member supports the internal infrastructure and is not intended to be used directly from your code. + + */ + @Output() widthChange: EventEmitter; + + + + + constructor(elementRef: ElementRef, ngZone: NgZone, templateHost: DxTemplateHost, + _watcherHelper: WatcherHelper, + optionHost: NestedOptionHost, + transferState: TransferState, + @Inject(PLATFORM_ID) platformId: any) { + + super(elementRef, ngZone, templateHost, _watcherHelper, transferState, platformId); + + this._createEventEmitters([ + { subscribe: 'contentReady', emit: 'onContentReady' }, + { subscribe: 'disposing', emit: 'onDisposing' }, + { subscribe: 'initialized', emit: 'onInitialized' }, + { subscribe: 'optionChanged', emit: 'onOptionChanged' }, + { emit: 'accessKeyChange' }, + { emit: 'activeStateEnabledChange' }, + { emit: 'disabledChange' }, + { emit: 'elementAttrChange' }, + { emit: 'focusStateEnabledChange' }, + { emit: 'heightChange' }, + { emit: 'hintChange' }, + { emit: 'hoverStateEnabledChange' }, + { emit: 'rootComplexOptionChange' }, + { emit: 'rootPrimitiveOptionChange' }, + { emit: 'rtlEnabledChange' }, + { emit: 'tabIndexChange' }, + { emit: 'visibleChange' }, + { emit: 'widthChange' } + ]); + optionHost.setHost(this); + } + + protected _createInstance(element, options) { + + return new DxSkeleton(element, options); + } + + + ngOnDestroy() { + this._destroyWidget(); + } + +} + +@NgModule({ + imports: [ + DxSkeletonComponent, + DxoSkeletonRootComplexOptionModule, + DxIntegrationModule, + DxTemplateModule + ], + exports: [ + DxSkeletonComponent, + DxoSkeletonRootComplexOptionModule, + DxTemplateModule + ] +}) +export class DxSkeletonModule { } + +export * from 'devextreme-angular/ui/skeleton/nested'; + +import type * as DxSkeletonTypes from "devextreme/ui/skeleton_types"; +export { DxSkeletonTypes }; + + diff --git a/packages/devextreme-angular/src/ui/skeleton/nested/index.ts b/packages/devextreme-angular/src/ui/skeleton/nested/index.ts new file mode 100644 index 000000000000..c34a8e4e56b8 --- /dev/null +++ b/packages/devextreme-angular/src/ui/skeleton/nested/index.ts @@ -0,0 +1,2 @@ +export * from './root-complex-option'; + diff --git a/packages/devextreme-angular/src/ui/skeleton/nested/ng-package.json b/packages/devextreme-angular/src/ui/skeleton/nested/ng-package.json new file mode 100644 index 000000000000..3360c83b3395 --- /dev/null +++ b/packages/devextreme-angular/src/ui/skeleton/nested/ng-package.json @@ -0,0 +1,5 @@ +{ + "lib": { + "entryFile": "index.ts" + } +} \ No newline at end of file diff --git a/packages/devextreme-angular/src/ui/skeleton/nested/root-complex-option.ts b/packages/devextreme-angular/src/ui/skeleton/nested/root-complex-option.ts new file mode 100644 index 000000000000..80e5726cfa84 --- /dev/null +++ b/packages/devextreme-angular/src/ui/skeleton/nested/root-complex-option.ts @@ -0,0 +1,83 @@ +/* tslint:disable:max-line-length */ + + +import { + Component, + OnInit, + OnDestroy, + NgModule, + Host, + SkipSelf, + Input +} from '@angular/core'; + + + + + +import { + DxIntegrationModule, + NestedOptionHost, +} from 'devextreme-angular/core'; +import { NestedOption } from 'devextreme-angular/core'; + + +@Component({ + selector: 'dxo-skeleton-root-complex-option', + standalone: true, + template: '', + styles: [''], + imports: [ DxIntegrationModule ], + providers: [NestedOptionHost] +}) +export class DxoSkeletonRootComplexOptionComponent extends NestedOption implements OnDestroy, OnInit { + @Input() + get prop1(): string { + return this._getOption('prop1'); + } + set prop1(value: string) { + this._setOption('prop1', value); + } + + @Input() + get prop2(): boolean { + return this._getOption('prop2'); + } + set prop2(value: boolean) { + this._setOption('prop2', value); + } + + + protected get _optionPath() { + return 'rootComplexOption'; + } + + + constructor(@SkipSelf() @Host() parentOptionHost: NestedOptionHost, + @Host() optionHost: NestedOptionHost) { + super(); + parentOptionHost.setNestedOption(this); + optionHost.setHost(this, this._fullOptionPath.bind(this)); + } + + + ngOnInit() { + this._addRecreatedComponent(); + } + + ngOnDestroy() { + this._addRemovedOption(this._getOptionPath()); + } + + +} + +@NgModule({ + imports: [ + DxoSkeletonRootComplexOptionComponent + ], + exports: [ + DxoSkeletonRootComplexOptionComponent + ], +}) +export class DxoSkeletonRootComplexOptionModule { } diff --git a/packages/devextreme-angular/src/ui/skeleton/ng-package.json b/packages/devextreme-angular/src/ui/skeleton/ng-package.json new file mode 100644 index 000000000000..3360c83b3395 --- /dev/null +++ b/packages/devextreme-angular/src/ui/skeleton/ng-package.json @@ -0,0 +1,5 @@ +{ + "lib": { + "entryFile": "index.ts" + } +} \ No newline at end of file diff --git a/packages/devextreme-metadata/make-angular-metadata.ts b/packages/devextreme-metadata/make-angular-metadata.ts index a1ce7efcf366..a3ae6c36a910 100644 --- a/packages/devextreme-metadata/make-angular-metadata.ts +++ b/packages/devextreme-metadata/make-angular-metadata.ts @@ -63,6 +63,7 @@ Ng.makeMetadata({ removeMembers(/\/scheduler:dxSchedulerOptions\.editing\.form/), removeMembers(/\/scheduler:dxSchedulerOptions\.editing\.popup/), removeMembers(/\/scheduler:dxSchedulerOptions\.resources\.icon/), + removeMembers(/\/skeleton:/), removeMembers(/\/stepper:/), removeMembers(/\/speech_to_text:/), removeMembers(/\/tree_list:dxTreeListColumnButton.onClick/), diff --git a/packages/devextreme-react/src/index.ts b/packages/devextreme-react/src/index.ts index a80e1dfff0bf..331c19edc415 100644 --- a/packages/devextreme-react/src/index.ts +++ b/packages/devextreme-react/src/index.ts @@ -58,6 +58,7 @@ export { Sankey } from "./sankey"; export { Scheduler } from "./scheduler"; export { ScrollView } from "./scroll-view"; export { SelectBox } from "./select-box"; +export { Skeleton } from "./skeleton"; export { Slider } from "./slider"; export { Sortable } from "./sortable"; export { Sparkline } from "./sparkline"; diff --git a/packages/devextreme-react/src/skeleton.ts b/packages/devextreme-react/src/skeleton.ts new file mode 100644 index 000000000000..fd6af83d43ed --- /dev/null +++ b/packages/devextreme-react/src/skeleton.ts @@ -0,0 +1,89 @@ +"use client" +import * as React from "react"; +import { memo, forwardRef, useImperativeHandle, useRef, useMemo, ForwardedRef, Ref, ReactElement } from "react"; +import dxSkeleton, { + Properties +} from "devextreme/ui/skeleton"; + +import { Component as BaseComponent, IHtmlOptions, ComponentRef, NestedComponentMeta } from "./core/component"; +import NestedOption from "./core/nested-option"; + +import type { ContentReadyEvent } from "devextreme/ui/skeleton"; + +type ReplaceFieldTypes = { + [P in keyof TSource]: P extends keyof TReplacement ? TReplacement[P] : TSource[P]; +} + +type ISkeletonOptionsNarrowedEvents = { + onContentReady?: ((e: ContentReadyEvent) => void); +} + +type ISkeletonOptions = React.PropsWithChildren & IHtmlOptions> + +interface SkeletonRef { + instance: () => dxSkeleton; +} + +const Skeleton = memo( + forwardRef( + (props: React.PropsWithChildren, ref: ForwardedRef) => { + const baseRef = useRef(null); + + useImperativeHandle(ref, () => ( + { + instance() { + return baseRef.current?.getInstance(); + } + } + ), []); + + const independentEvents = useMemo(() => (["onContentReady","onDisposing","onInitialized"]), []); + + const expectedChildren = useMemo(() => ({ + rootComplexOption: { optionName: "rootComplexOption", isCollectionItem: false } + }), []); + + return ( + React.createElement(BaseComponent>, { + WidgetClass: dxSkeleton, + ref: baseRef, + independentEvents, + expectedChildren, + ...props, + }) + ); + }, + ), +) as (props: React.PropsWithChildren & { ref?: Ref }) => ReactElement | null; + + +// owners: +// Skeleton +type IRootComplexOptionProps = React.PropsWithChildren<{ + prop1?: string; + prop2?: boolean; +}> +const _componentRootComplexOption = (props: IRootComplexOptionProps) => { + return React.createElement(NestedOption, { + ...props, + elementDescriptor: { + OptionName: "rootComplexOption", + }, + }); +}; + +const RootComplexOption = Object.assign(_componentRootComplexOption, { + componentType: "option", +}); + +export default Skeleton; +export { + Skeleton, + ISkeletonOptions, + SkeletonRef, + RootComplexOption, + IRootComplexOptionProps +}; +import type * as SkeletonTypes from 'devextreme/ui/skeleton_types'; +export { SkeletonTypes }; + diff --git a/packages/devextreme-vue/src/index.ts b/packages/devextreme-vue/src/index.ts index 3a0395e25650..841964632df3 100644 --- a/packages/devextreme-vue/src/index.ts +++ b/packages/devextreme-vue/src/index.ts @@ -57,6 +57,7 @@ export { DxSankey } from "./sankey"; export { DxScheduler } from "./scheduler"; export { DxScrollView } from "./scroll-view"; export { DxSelectBox } from "./select-box"; +export { DxSkeleton } from "./skeleton"; export { DxSlider } from "./slider"; export { DxSortable } from "./sortable"; export { DxSparkline } from "./sparkline"; diff --git a/packages/devextreme-vue/src/skeleton.ts b/packages/devextreme-vue/src/skeleton.ts new file mode 100644 index 000000000000..f64b1715105d --- /dev/null +++ b/packages/devextreme-vue/src/skeleton.ts @@ -0,0 +1,130 @@ +import { PropType } from "vue"; +import { defineComponent } from "vue"; +import { prepareComponentConfig } from "./core/index"; +import Skeleton, { Properties } from "devextreme/ui/skeleton"; +import DOMComponent from "devextreme/core/dom_component"; +import { + ContentReadyEvent, + SkeletonComplexType, +} from "devextreme/ui/skeleton"; +import { + EventInfo, +} from "devextreme/common/core/events"; +import { + Component, +} from "devextreme/core/component"; +import { prepareConfigurationComponentConfig } from "./core/index"; + +type AccessibleOptions = Pick; + +interface DxSkeleton extends AccessibleOptions { + readonly instance?: Skeleton; +} + +const componentConfig = { + props: { + accessKey: String, + activeStateEnabled: Boolean, + disabled: Boolean, + elementAttr: Object as PropType>, + focusStateEnabled: Boolean, + height: [Number, String], + hint: String, + hoverStateEnabled: Boolean, + onContentReady: Function as PropType<((e: ContentReadyEvent) => void)>, + onDisposing: Function as PropType<((e: EventInfo) => void)>, + onInitialized: Function as PropType<((e: { component: Component, element: any }) => void)>, + onOptionChanged: Function as PropType<((e: { component: DOMComponent, element: any, fullName: string, model: any, name: string, previousValue: any, value: any }) => void)>, + rootComplexOption: Object as PropType>, + rootPrimitiveOption: Number, + rtlEnabled: Boolean, + tabIndex: Number, + visible: Boolean, + width: [Number, String] + }, + emits: { + "update:isActive": null, + "update:hoveredElement": null, + "update:accessKey": null, + "update:activeStateEnabled": null, + "update:disabled": null, + "update:elementAttr": null, + "update:focusStateEnabled": null, + "update:height": null, + "update:hint": null, + "update:hoverStateEnabled": null, + "update:onContentReady": null, + "update:onDisposing": null, + "update:onInitialized": null, + "update:onOptionChanged": null, + "update:rootComplexOption": null, + "update:rootPrimitiveOption": null, + "update:rtlEnabled": null, + "update:tabIndex": null, + "update:visible": null, + "update:width": null, + }, + computed: { + instance(): Skeleton { + return (this as any).$_instance; + } + }, + beforeCreate() { + (this as any).$_WidgetClass = Skeleton; + (this as any).$_hasAsyncTemplate = true; + (this as any).$_expectedChildren = { + rootComplexOption: { isCollectionItem: false, optionName: "rootComplexOption" } + }; + } +}; + +prepareComponentConfig(componentConfig); + +const DxSkeleton = defineComponent(componentConfig); + + +const DxRootComplexOptionConfig = { + emits: { + "update:isActive": null, + "update:hoveredElement": null, + "update:prop1": null, + "update:prop2": null, + }, + props: { + prop1: String, + prop2: Boolean + } +}; + +prepareConfigurationComponentConfig(DxRootComplexOptionConfig); + +const DxRootComplexOption = defineComponent(DxRootComplexOptionConfig); + +(DxRootComplexOption as any).$_optionName = "rootComplexOption"; + +export default DxSkeleton; +export { + DxSkeleton, + DxRootComplexOption +}; +import type * as DxSkeletonTypes from "devextreme/ui/skeleton_types"; +export { DxSkeletonTypes }; diff --git a/packages/devextreme/build/gulp/modules_metadata.json b/packages/devextreme/build/gulp/modules_metadata.json index 6ec06d899a89..61038fe945e0 100644 --- a/packages/devextreme/build/gulp/modules_metadata.json +++ b/packages/devextreme/build/gulp/modules_metadata.json @@ -518,6 +518,12 @@ "default": { "path": "ui.dxSelectBox", "isWidget": true } } }, + { + "name": "ui/skeleton", + "exports": { + "default": { "path": "ui.dxSkeleton", "isWidget": true } + } + }, { "name": "ui/set_template_engine", "exports": { diff --git a/packages/devextreme/js/__internal/ui/skeleton/skeleton.ts b/packages/devextreme/js/__internal/ui/skeleton/skeleton.ts new file mode 100644 index 000000000000..edfb5c5a5d93 --- /dev/null +++ b/packages/devextreme/js/__internal/ui/skeleton/skeleton.ts @@ -0,0 +1,9 @@ +import registerComponent from '@js/core/component_registrator'; +import type { Properties } from '@js/ui/skeleton'; +import Widget from '@ts/core/widget/widget'; + +class Skeleton extends Widget { } + +registerComponent('dxSkeleton', Skeleton); + +export default Skeleton; diff --git a/packages/devextreme/js/integration/jquery.d.ts b/packages/devextreme/js/integration/jquery.d.ts index 5c31efce76e9..8f31a5f853b7 100644 --- a/packages/devextreme/js/integration/jquery.d.ts +++ b/packages/devextreme/js/integration/jquery.d.ts @@ -46,6 +46,7 @@ import dxResponsiveBox, { Properties as ResponsiveBoxProperties } from '../ui/re import dxScheduler, { Properties as SchedulerProperties } from '../ui/scheduler'; import dxScrollView, { Properties as ScrollViewProperties } from '../ui/scroll_view'; import dxSelectBox, { Properties as SelectBoxProperties } from '../ui/select_box'; +import dxSkeleton, { Properties as SkeletonProperties } from '../ui/skeleton'; import dxSlider, { Properties as SliderProperties } from '../ui/slider'; import dxSplitter, { Properties as SplitterProperties } from '../ui/splitter'; import dxStepper, { Properties as StepperProperties } from '../ui/stepper'; @@ -456,6 +457,12 @@ declare global { dxSelectBox(options: string): any; dxSelectBox(options: string, ...params: any[]): any; + dxSkeleton(): JQuery; + dxSkeleton(options: 'instance'): dxSkeleton; + dxSkeleton(options: SkeletonProperties): JQuery; + dxSkeleton(options: string): any; + dxSkeleton(options: string, ...params: any[]): any; + dxSlider(): JQuery; dxSlider(options: 'instance'): dxSlider; dxSlider(options: SliderProperties): JQuery; diff --git a/packages/devextreme/js/ui/skeleton.d.ts b/packages/devextreme/js/ui/skeleton.d.ts new file mode 100644 index 000000000000..f80f01fc7586 --- /dev/null +++ b/packages/devextreme/js/ui/skeleton.d.ts @@ -0,0 +1,75 @@ +import Widget, { WidgetOptions } from './widget/ui.widget'; +import { EventInfo } from '../events'; + +/** + * @docid _ui_skeleton_ContentReadyEvent + * @public + * @type object + * @inherits EventInfo + */ +export type ContentReadyEvent = EventInfo; + +/** + * @docid + * @public + */ +export type SkeletonComplexType = { + /** + * @docid + * @public + */ + prop1: string; + /** + * @docid + * @public + */ + prop2: boolean; +}; + +/** + * @docid + * @deprecated use Properties instead + * @namespace DevExpress.ui + * @public + */ +export interface dxSkeletonOptions extends WidgetOptions { + /** + * @docid + * @public + */ + rootPrimitiveOption?: number; + /** + * @docid + * @public + */ + rootComplexOption?: SkeletonComplexType; +} + +/** + * @docid + * @inherits Widget + * @namespace DevExpress.ui + * @public + */ +export default class dxSkeleton extends Widget { } + +/** @public */ +export type Properties = dxSkeletonOptions; + +/** @public */ +export type ExplicitTypes = { + Properties: Properties; +}; + +/// #DEBUG +/** + * @hidden + */ +type Events = { + /** + * @docid dxSkeletonOptions.onContentReady + * @type_function_param1 e:{ui/skeleton:ContentReadyEvent} + */ + onContentReady?: ((e: ContentReadyEvent) => void); +}; +/// #ENDDEBUG diff --git a/packages/devextreme/js/ui/skeleton.js b/packages/devextreme/js/ui/skeleton.js new file mode 100644 index 000000000000..1b28ce896b29 --- /dev/null +++ b/packages/devextreme/js/ui/skeleton.js @@ -0,0 +1,5 @@ +import Skeleton from '../__internal/ui/skeleton/skeleton'; + +export default Skeleton; + +// STYLE skeleton diff --git a/packages/devextreme/js/ui/skeleton_types.d.ts b/packages/devextreme/js/ui/skeleton_types.d.ts new file mode 100644 index 000000000000..d0214f8308b1 --- /dev/null +++ b/packages/devextreme/js/ui/skeleton_types.d.ts @@ -0,0 +1,6 @@ +export { + ContentReadyEvent, + SkeletonComplexType, + dxSkeletonOptions, + Properties, +} from './skeleton'; diff --git a/packages/devextreme/ts/dx.all.d.ts b/packages/devextreme/ts/dx.all.d.ts index 9bc8df6b0803..56ed27f9a901 100644 --- a/packages/devextreme/ts/dx.all.d.ts +++ b/packages/devextreme/ts/dx.all.d.ts @@ -357,6 +357,12 @@ declare global { dxSelectBox(options: string): any; dxSelectBox(options: string, ...params: any[]): any; + dxSkeleton(): JQuery; + dxSkeleton(options: 'instance'): DevExpress.ui.dxSkeleton; + dxSkeleton(options: DevExpress.ui.dxSkeleton.Properties): JQuery; + dxSkeleton(options: string): any; + dxSkeleton(options: string, ...params: any[]): any; + dxSlider(): JQuery; dxSlider(options: 'instance'): DevExpress.ui.dxSlider; dxSlider(options: DevExpress.ui.dxSlider.Properties): JQuery; @@ -27463,6 +27469,48 @@ declare module DevExpress.ui { */ dropDownOptions?: DevExpress.ui.dxPopup.Properties; } + /** + * [descr:dxSkeleton] + */ + export class dxSkeleton extends Widget {} + module dxSkeleton { + /** + * [descr:_ui_skeleton_ContentReadyEvent] + */ + export type ContentReadyEvent = + DevExpress.common.core.events.EventInfo; + export type ExplicitTypes = { + Properties: Properties; + }; + export type Properties = dxSkeletonOptions; + /** + * [descr:SkeletonComplexType] + */ + export type SkeletonComplexType = { + /** + * [descr:SkeletonComplexType.prop1] + */ + prop1: string; + /** + * [descr:SkeletonComplexType.prop2] + */ + prop2: boolean; + }; + } + /** + * [descr:dxSkeletonOptions] + * @deprecated [depNote:dxSkeletonOptions] + */ + export interface dxSkeletonOptions extends WidgetOptions { + /** + * [descr:dxSkeletonOptions.rootPrimitiveOption] + */ + rootPrimitiveOption?: number; + /** + * [descr:dxSkeletonOptions.rootComplexOption] + */ + rootComplexOption?: DevExpress.ui.dxSkeleton.SkeletonComplexType; + } /** * [descr:dxSlider] */