@rws-framework/client 2.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.bin/add-v.sh +10 -0
- package/.eslintrc.json +53 -0
- package/.setup/.eslintrc.json +11 -0
- package/.setup/tsconfig.json +29 -0
- package/README.md +691 -0
- package/_rws_externals.js +40 -0
- package/_tools.js +317 -0
- package/console.js +87 -0
- package/declarations.d.ts +9 -0
- package/docs/.nojekyll +1 -0
- package/docs/assets/26e93147f10415a0ed4a.svg +6 -0
- package/docs/assets/75c9471662e97ee24f29.svg +7 -0
- package/docs/assets/db90e4df2373980c497d.svg +9 -0
- package/docs/assets/hierarchy.css +1 -0
- package/docs/assets/hierarchy.js +1 -0
- package/docs/assets/highlight.css +120 -0
- package/docs/assets/main.js +59 -0
- package/docs/assets/navigation.js +1 -0
- package/docs/assets/search.js +1 -0
- package/docs/assets/style.css +1414 -0
- package/docs/classes/ApiServiceInstance.html +20 -0
- package/docs/classes/DOMServiceInstance.html +10 -0
- package/docs/classes/NotifyServiceInstance.html +12 -0
- package/docs/classes/RWSClient.html +11 -0
- package/docs/classes/RWSRouter.html +9 -0
- package/docs/classes/RWSService.html +7 -0
- package/docs/classes/RWSUploader.html +35 -0
- package/docs/classes/RWSViewComponent.html +24 -0
- package/docs/classes/RouterComponent.html +31 -0
- package/docs/classes/RoutingServiceInstance.html +13 -0
- package/docs/classes/UtilsServiceInstance.html +11 -0
- package/docs/classes/WSServiceInstance.html +32 -0
- package/docs/functions/RWSView.html +1 -0
- package/docs/functions/ngAttr.html +1 -0
- package/docs/functions/registerRWSComponents.html +1 -0
- package/docs/functions/renderRouteComponent.html +1 -0
- package/docs/hierarchy.html +1 -0
- package/docs/index.html +53 -0
- package/docs/interfaces/IRWSAssetShowOptions.html +1 -0
- package/docs/interfaces/IRWSConfig.html +11 -0
- package/docs/interfaces/IRWSDecoratorOptions.html +4 -0
- package/docs/interfaces/IRWSHttpRoute.html +3 -0
- package/docs/interfaces/IRWSPrefixedHTTProutes.html +3 -0
- package/docs/interfaces/IRoutingEvent.html +3 -0
- package/docs/modules.html +39 -0
- package/docs/types/DOMOutputType.html +1 -0
- package/docs/types/IRWSBackendRoute.html +1 -0
- package/docs/types/IRWSFrontRoutes.html +1 -0
- package/docs/types/IRWSRouteResult.html +1 -0
- package/docs/types/IRWSWebsocketStatus.html +1 -0
- package/docs/types/NotifyLogType.html +1 -0
- package/docs/types/NotifyUiType.html +1 -0
- package/docs/types/RWSNotify.html +1 -0
- package/docs/types/RouteReturn.html +1 -0
- package/docs/variables/ApiService.html +1 -0
- package/docs/variables/DOMService.html +1 -0
- package/docs/variables/NotifyService.html +1 -0
- package/docs/variables/RoutingService.html +1 -0
- package/docs/variables/UtilsService.html +1 -0
- package/docs/variables/WSService.html +1 -0
- package/docs/variables/_ROUTING_EVENT_NAME.html +1 -0
- package/package.json +93 -0
- package/package.webpack.config.js +17 -0
- package/rws.webpack.config.js +260 -0
- package/src/client.ts +304 -0
- package/src/components/_attrs/angular-attr.ts +64 -0
- package/src/components/_attrs/sanitize-html.ts +81 -0
- package/src/components/_component.ts +290 -0
- package/src/components/_container.ts +16 -0
- package/src/components/_decorator.ts +112 -0
- package/src/components/_design_system.ts +6 -0
- package/src/components/index.ts +9 -0
- package/src/components/progress/component.ts +55 -0
- package/src/components/progress/styles/layout.scss +91 -0
- package/src/components/progress/template.html +25 -0
- package/src/components/router/component.ts +67 -0
- package/src/components/uploader/component.ts +75 -0
- package/src/components/uploader/styles/layout.scss +105 -0
- package/src/components/uploader/template.html +17 -0
- package/src/hmr.ts +19 -0
- package/src/index.ts +98 -0
- package/src/interfaces/IRWSConfig.ts +24 -0
- package/src/interfaces/IRWSUser.ts +7 -0
- package/src/interfaces/IRWSViewComponent.ts +37 -0
- package/src/interfaces/RWSWindow.ts +39 -0
- package/src/routing/_router.ts +59 -0
- package/src/routing/index.ts +7 -0
- package/src/run.ts +35 -0
- package/src/service_worker/src/_service_worker.ts +88 -0
- package/src/service_worker/tsconfig.json +21 -0
- package/src/service_worker/webpack.config.js +67 -0
- package/src/services/ApiService.ts +241 -0
- package/src/services/ConfigService.ts +107 -0
- package/src/services/DOMService.ts +91 -0
- package/src/services/NotifyService.ts +49 -0
- package/src/services/RoutingService.ts +46 -0
- package/src/services/ServiceWorkerService.ts +60 -0
- package/src/services/UtilsService.ts +103 -0
- package/src/services/WSService.ts +218 -0
- package/src/services/_service.ts +50 -0
- package/src/services/_ws_handlers/ConnectionHandler.ts +52 -0
- package/src/services/_ws_handlers/EventHandler.ts +28 -0
- package/src/services/_ws_handlers/MessageHandler.ts +49 -0
- package/src/styles/includes.scss +102 -0
- package/src/types/RWSNotify.ts +7 -0
- package/tsconfig.json +27 -0
- package/typedoc.json +13 -0
- package/webpack/after/copy.js +73 -0
- package/webpack/after/sw.js +14 -0
- package/webpack/index.js +11 -0
- package/webpack/rws_after_plugin.js +80 -0
- package/webpack/rws_fast_css_loader.js +16 -0
- package/webpack/rws_fast_html_loader.js +4 -0
- package/webpack/rws_fast_scss_loader.js +50 -0
- package/webpack/rws_fast_ts_loader.js +134 -0
- package/webpack/rws_plugin.js +337 -0
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { Observable, AttributeConfiguration, DecoratorAttributeConfiguration } from '@microsoft/fast-element';
|
|
2
|
+
import RWSViewComponent from '../_component';
|
|
3
|
+
|
|
4
|
+
type TargetType = RWSViewComponent; // Use a more generic type for the target to ensure compatibility
|
|
5
|
+
|
|
6
|
+
function ngAttr(configOrTarget?: DecoratorAttributeConfiguration | TargetType, prop?: string): void | any
|
|
7
|
+
{
|
|
8
|
+
if (arguments.length > 1) {
|
|
9
|
+
// Decorator used directly without factory invocation
|
|
10
|
+
// Apply the decorator immediately without returning anything
|
|
11
|
+
applyDecorator(configOrTarget as RWSViewComponent, prop!);
|
|
12
|
+
} else {
|
|
13
|
+
// Decorator factory invocation
|
|
14
|
+
const config = configOrTarget as AttributeConfiguration;
|
|
15
|
+
// Return a function that applies the decorator, conforming to TypeScript's expectations for decorator factories
|
|
16
|
+
return (target: TargetType, property: string) => applyDecorator(target, property, config);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function applyDecorator(target: TargetType, prop: string, config: AttributeConfiguration | any = {}): void
|
|
21
|
+
{
|
|
22
|
+
if (arguments.length > 1) {
|
|
23
|
+
config.property = prop;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
AttributeConfiguration.locate(target.constructor).push(config);
|
|
27
|
+
modifyPropertyDescriptor(target, prop);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
function modifyPropertyDescriptor(target: any, propertyKey: string): void {
|
|
33
|
+
const privatePropName = `_${String(propertyKey)}`;
|
|
34
|
+
Object.defineProperty(target, privatePropName, {
|
|
35
|
+
writable: true,
|
|
36
|
+
value: target[propertyKey],
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
Object.defineProperty(target, propertyKey, {
|
|
40
|
+
get() {
|
|
41
|
+
const value: string = this[privatePropName];
|
|
42
|
+
return isNgValue(value) ? null : value;
|
|
43
|
+
},
|
|
44
|
+
set(value: any) {
|
|
45
|
+
if (typeof value === 'string' && isNgValue(value)) {
|
|
46
|
+
this[privatePropName] = null; // Set to null if condition is met
|
|
47
|
+
} else {
|
|
48
|
+
this[privatePropName] = value;
|
|
49
|
+
}
|
|
50
|
+
Observable.notify(this, propertyKey);
|
|
51
|
+
},
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function isNgValue(input: string): boolean {
|
|
56
|
+
// Regular expression to match AngularJS template variable notation
|
|
57
|
+
const angularJsVariablePattern = /\{\{([^}]+)\}\}/;
|
|
58
|
+
|
|
59
|
+
// Test the input string for the pattern and return the result
|
|
60
|
+
return angularJsVariablePattern.test(input);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
export { ngAttr };
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { Observable, AttributeConfiguration } from '@microsoft/fast-element';
|
|
2
|
+
import RWSViewComponent from '../_component';
|
|
3
|
+
import DOMService from '../../services/DOMService';
|
|
4
|
+
import RWSContainer from '../_container';
|
|
5
|
+
import { IOptions } from 'sanitize-html';
|
|
6
|
+
|
|
7
|
+
import * as he from 'he';
|
|
8
|
+
|
|
9
|
+
type SanitizeOptions = IOptions & { fullEncode?: boolean }
|
|
10
|
+
|
|
11
|
+
const heOpt: he.EncodeOptions = {
|
|
12
|
+
useNamedReferences: false,
|
|
13
|
+
encodeEverything: true,
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function enc(html: string): string
|
|
17
|
+
{
|
|
18
|
+
return he.encode(html, heOpt);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
const transformAnyTag = (tagName: string, attribs: { [key: string]: string }) => {
|
|
23
|
+
// Example: Wrap the original tag with `span` and indicate the original tag name in a data attribute
|
|
24
|
+
return {
|
|
25
|
+
tagName: 'span', // Change this to any tag you want to transform to
|
|
26
|
+
attribs: {
|
|
27
|
+
...attribs,
|
|
28
|
+
'data-original-tag': tagName
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
function sanitizedAttr(configOrTarget?: SanitizeOptions | RWSViewComponent, prop?: string): void | any
|
|
34
|
+
{
|
|
35
|
+
if (arguments.length > 1) {
|
|
36
|
+
// Decorator used directly without factory invocation
|
|
37
|
+
// Apply the decorator immediately without returning anything
|
|
38
|
+
applyDecorator(configOrTarget as RWSViewComponent, prop!);
|
|
39
|
+
} else {
|
|
40
|
+
// Decorator factory invocation
|
|
41
|
+
const config = configOrTarget as SanitizeOptions;
|
|
42
|
+
// Return a function that applies the decorator, conforming to TypeScript's expectations for decorator factories
|
|
43
|
+
return (target: RWSViewComponent, property: string) => applyDecorator(target, property, config);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function applyDecorator(target: RWSViewComponent, prop: string, config: SanitizeOptions = null): void
|
|
48
|
+
{
|
|
49
|
+
if(config.fullEncode){
|
|
50
|
+
const encAllOpts = {transformTags: { '*' : transformAnyTag }, textFilter: function(text: string, tagName?: string) { return tagName ? `${enc('<')}${tagName}${enc('>')}${text}${enc('</')}${tagName}${enc('>')}` : text; }}
|
|
51
|
+
config = {...config, ...encAllOpts}
|
|
52
|
+
delete config.fullEncode;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
modifyPropertyDescriptor(target, prop, config as IOptions);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function modifyPropertyDescriptor(target: any, propertyKey: string, config: IOptions = null): void {
|
|
59
|
+
const privatePropName = `_${String(propertyKey)}`;
|
|
60
|
+
Object.defineProperty(target, privatePropName, {
|
|
61
|
+
writable: true,
|
|
62
|
+
value: target[propertyKey],
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
Object.defineProperty(target, propertyKey, {
|
|
66
|
+
get() {
|
|
67
|
+
return this[privatePropName];
|
|
68
|
+
},
|
|
69
|
+
set(value: any) {
|
|
70
|
+
if (typeof value === 'string') {
|
|
71
|
+
this[privatePropName] = RWSContainer().get(DOMService).sanitizeHTML(value, null, config);
|
|
72
|
+
} else {
|
|
73
|
+
this[privatePropName] = null;
|
|
74
|
+
}
|
|
75
|
+
Observable.notify(this, propertyKey);
|
|
76
|
+
},
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
export { sanitizedAttr };
|
|
@@ -0,0 +1,290 @@
|
|
|
1
|
+
import { ViewTemplate, ElementStyles, observable, html, Constructable, PartialFASTElementDefinition, attr } from '@microsoft/fast-element';
|
|
2
|
+
import { FoundationElement, FoundationElementDefinition, FoundationElementRegistry, InterfaceSymbol, Key, OverrideFoundationElementDefinition } from '@microsoft/fast-foundation';
|
|
3
|
+
import ConfigService, { ConfigServiceInstance } from '../services/ConfigService';
|
|
4
|
+
import UtilsService, { UtilsServiceInstance } from '../services/UtilsService';
|
|
5
|
+
import DOMService, { DOMServiceInstance, DOMOutputType } from '../services/DOMService';
|
|
6
|
+
import ApiService, { ApiServiceInstance } from '../services/ApiService';
|
|
7
|
+
import NotifyService, { NotifyServiceInstance } from '../services/NotifyService';
|
|
8
|
+
import RoutingService, { RoutingServiceInstance } from '../services/RoutingService';
|
|
9
|
+
import WSService, { WSServiceInstance } from '../services/WSService';
|
|
10
|
+
import { IRWSViewComponent, IAssetShowOptions } from '../interfaces/IRWSViewComponent';
|
|
11
|
+
import { DI, inject } from '@microsoft/fast-foundation';
|
|
12
|
+
import { provideRWSDesignSystem } from './_design_system';
|
|
13
|
+
import RWSWindow, { RWSWindowComponentEntry, RWSWindowComponentInterface, loadRWSRichWindow } from '../interfaces/RWSWindow';
|
|
14
|
+
import RWSContainer from './_container';
|
|
15
|
+
import {RWSInject, applyConstructor, applyProp} from './_decorator';
|
|
16
|
+
|
|
17
|
+
import 'reflect-metadata';
|
|
18
|
+
|
|
19
|
+
interface IFastDefinition {
|
|
20
|
+
name: string;
|
|
21
|
+
template: ViewTemplate;
|
|
22
|
+
styles?: ElementStyles;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
type ComposeMethodType<
|
|
26
|
+
T extends FoundationElementDefinition,
|
|
27
|
+
K extends Constructable<RWSViewComponent>
|
|
28
|
+
> = (this: K, elementDefinition: T) => (overrideDefinition?: OverrideFoundationElementDefinition<T>) => FoundationElementRegistry<FoundationElementDefinition, T>;
|
|
29
|
+
|
|
30
|
+
export interface IWithCompose<T extends RWSViewComponent> {
|
|
31
|
+
[key: string]: any
|
|
32
|
+
new (...args: any[]): T;
|
|
33
|
+
definition?: IFastDefinition
|
|
34
|
+
defineComponent: <T extends RWSViewComponent>(this: IWithCompose<T>) => void
|
|
35
|
+
isDefined<T extends RWSViewComponent>(this: IWithCompose<T>): boolean
|
|
36
|
+
compose: ComposeMethodType<FoundationElementDefinition, Constructable<T>>;
|
|
37
|
+
define<TType extends Function>(type: TType, nameOrDef?: string | PartialFASTElementDefinition | undefined): TType;
|
|
38
|
+
_verbose: boolean;
|
|
39
|
+
_toInject: {[key: string]: any};
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
abstract class RWSViewComponent extends FoundationElement implements IRWSViewComponent {
|
|
43
|
+
__isLoading: boolean = true;
|
|
44
|
+
private static instances: RWSViewComponent[] = [];
|
|
45
|
+
static fileList: string[] = [];
|
|
46
|
+
|
|
47
|
+
@attr routeParams: Record<string, string> = {};
|
|
48
|
+
|
|
49
|
+
static autoLoadFastElement = true;
|
|
50
|
+
static _defined: { [key: string]: boolean } = {};
|
|
51
|
+
static _toInject: any[] = [];
|
|
52
|
+
static _verbose: boolean = false;
|
|
53
|
+
|
|
54
|
+
@observable trashIterator: number = 0;
|
|
55
|
+
@observable fileAssets: {
|
|
56
|
+
[key: string]: ViewTemplate
|
|
57
|
+
} = {};
|
|
58
|
+
|
|
59
|
+
constructor(
|
|
60
|
+
@RWSInject(ConfigService) protected config: ConfigServiceInstance,
|
|
61
|
+
@RWSInject(RoutingService) protected routingService: RoutingServiceInstance,
|
|
62
|
+
@RWSInject(DOMService) protected domService: DOMServiceInstance,
|
|
63
|
+
@RWSInject(UtilsService) protected utilsService: UtilsServiceInstance,
|
|
64
|
+
@RWSInject(ApiService) protected apiService: ApiServiceInstance,
|
|
65
|
+
@RWSInject(WSService) protected wsService: WSServiceInstance,
|
|
66
|
+
@RWSInject(NotifyService) protected notifyService: NotifyServiceInstance
|
|
67
|
+
) {
|
|
68
|
+
super();
|
|
69
|
+
applyConstructor(this);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
connectedCallback() {
|
|
73
|
+
super.connectedCallback();
|
|
74
|
+
applyConstructor(this);
|
|
75
|
+
|
|
76
|
+
// console.trace(this.config);
|
|
77
|
+
|
|
78
|
+
if (!(this.constructor as IWithCompose<this>).definition && (this.constructor as IWithCompose<this>).autoLoadFastElement) {
|
|
79
|
+
throw new Error('RWS component is not named. Add `static definition = {name, template};`');
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
try {
|
|
83
|
+
(this.constructor as IWithCompose<this>).fileList.forEach((file: string) => {
|
|
84
|
+
if (this.fileAssets[file]) {
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
this.utilsService.getFileContents(this.config.get('pubPrefix') + file).then((response: string) => {
|
|
88
|
+
this.fileAssets = { ...this.fileAssets, [file]: html`${response}` };
|
|
89
|
+
});
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
} catch (e: Error | any) {
|
|
93
|
+
console.error('Error loading file content:', e.message);
|
|
94
|
+
console.error(e.stack);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
RWSViewComponent.instances.push(this);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
observe(callback: (component: this, node: Node, observer: MutationObserver) => Promise<void>, condition: (component: this, node: Node) => boolean = null, observeRemoved: boolean = false)
|
|
101
|
+
{
|
|
102
|
+
const observer = new MutationObserver((mutationsList, observer) => {
|
|
103
|
+
for(const mutation of mutationsList) {
|
|
104
|
+
if (mutation.type === 'childList') {
|
|
105
|
+
const mutationObserveType: NodeList = observeRemoved ? mutation.removedNodes : mutation.addedNodes
|
|
106
|
+
mutationObserveType.forEach(node => {
|
|
107
|
+
if ((condition !== null && condition(this, node))) {
|
|
108
|
+
callback(this, node, observer);
|
|
109
|
+
}else if(condition === null){
|
|
110
|
+
callback(this, node, observer);
|
|
111
|
+
}
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
observer.observe(this.getShadowRoot(), { childList: true, subtree: true });
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
passRouteParams(routeParams: Record<string, string> = null) {
|
|
121
|
+
if (routeParams) {
|
|
122
|
+
this.routeParams = routeParams;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
showAsset(assetName: string, options: IAssetShowOptions = {}): ViewTemplate<any, any> {
|
|
127
|
+
|
|
128
|
+
if (!this.fileAssets[assetName]) {
|
|
129
|
+
return html`<span></span>`;
|
|
130
|
+
throw new Error(`File asset "${assetName}" not declared in component "${(this.constructor as IWithCompose<this>).definition.name}"`);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
return this.fileAssets[assetName];
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
on<T>(type: string, listener: (event: CustomEvent<T>) => any) {
|
|
137
|
+
this.addEventListener(type, (baseEvent: Event) => {
|
|
138
|
+
listener(baseEvent as CustomEvent<T>);
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
$emitDown<T>(eventName: string, payload: T) {
|
|
143
|
+
this.$emit(eventName, payload, {
|
|
144
|
+
bubbles: true,
|
|
145
|
+
composed: true
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
parse$<T extends Element>(input: NodeListOf<T>, directReturn: boolean = false): DOMOutputType<T> {
|
|
150
|
+
return this.domService.parse$<T>(input, directReturn);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
$<T extends Element>(selectors: string, directReturn: boolean = false): DOMOutputType<T> {
|
|
154
|
+
return this.domService.$<T>(this.getShadowRoot(), selectors, directReturn);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
async loadingString<T, C>(item: T, addContent: (cnt: C | { output: string }, paste?: boolean, error?: boolean) => void, shouldStop: (stopItem: T, addContent: (cnt: C | { output: string }, paste?: boolean, error?: boolean) => void) => Promise<boolean>) {
|
|
158
|
+
let dots = 1;
|
|
159
|
+
const maxDots = 3; // Maximum number of dots
|
|
160
|
+
const interval = setInterval(async () => {
|
|
161
|
+
const dotsString = '. '.repeat(dots);
|
|
162
|
+
|
|
163
|
+
const doesItStop = await shouldStop(item, addContent);
|
|
164
|
+
|
|
165
|
+
if (doesItStop) {
|
|
166
|
+
addContent({ output: '' }, true);
|
|
167
|
+
clearInterval(interval);
|
|
168
|
+
} else {
|
|
169
|
+
addContent({ output: `${dotsString}` }, true);
|
|
170
|
+
|
|
171
|
+
dots = (dots % (maxDots)) + 1;
|
|
172
|
+
}
|
|
173
|
+
}, 500);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
async onDOMLoad(): Promise<void> {
|
|
177
|
+
return new Promise<void>((resolve) => {
|
|
178
|
+
if (this.getShadowRoot() !== null && this.getShadowRoot() !== undefined) {
|
|
179
|
+
resolve();
|
|
180
|
+
} else {
|
|
181
|
+
// If shadowRoot is not yet available, use MutationObserver to wait for it
|
|
182
|
+
const observer = new MutationObserver(() => {
|
|
183
|
+
if (this.getShadowRoot() !== null && this.getShadowRoot() !== undefined) {
|
|
184
|
+
observer.disconnect();
|
|
185
|
+
resolve();
|
|
186
|
+
}
|
|
187
|
+
});
|
|
188
|
+
observer.observe(this, { childList: true, subtree: true });
|
|
189
|
+
}
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
|
|
194
|
+
protected getShadowRoot(): ShadowRoot {
|
|
195
|
+
const shRoot: ShadowRoot | null = this.shadowRoot;
|
|
196
|
+
|
|
197
|
+
if (!shRoot) {
|
|
198
|
+
throw new Error(`Component ${(this.constructor as IWithCompose<this>).definition.name} lacks shadow root. If you wish to have component without shadow root extend your class with FASTElement`);
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
return shRoot;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
forceReload() {
|
|
205
|
+
this.trashIterator += 1;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
hotReplacedCallback() {
|
|
209
|
+
this.forceReload();
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
sendEventToOutside<T>(eventName: string, data: T) {
|
|
213
|
+
const event = new CustomEvent<T>(eventName, {
|
|
214
|
+
detail: data,
|
|
215
|
+
bubbles: true,
|
|
216
|
+
composed: true
|
|
217
|
+
});
|
|
218
|
+
|
|
219
|
+
this.$emit(eventName, event);
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
|
|
223
|
+
static hotReplacedCallback() {
|
|
224
|
+
this.getInstances().forEach(instance => instance.forceReload());
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
static isDefined<T extends RWSViewComponent>(this: IWithCompose<T>): boolean
|
|
228
|
+
{
|
|
229
|
+
const richWindow: RWSWindow = loadRWSRichWindow();
|
|
230
|
+
|
|
231
|
+
if(!this.definition){
|
|
232
|
+
return false;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
return Object.keys(richWindow.RWS.components).includes(this.definition.name);
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
static defineComponent<T extends RWSViewComponent>(this: IWithCompose<T>): void
|
|
239
|
+
{
|
|
240
|
+
if(this.isDefined()){
|
|
241
|
+
if(this._verbose){
|
|
242
|
+
console.warn(`Component ${this.name} is already declared`);
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
return;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
const richWindow = loadRWSRichWindow();
|
|
249
|
+
|
|
250
|
+
if (!this.definition) {
|
|
251
|
+
throw new Error('RWS component is not named. Add `static definition = {name, template};`');
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
const composedComp = this.compose({
|
|
255
|
+
baseName: this.definition.name,
|
|
256
|
+
template: this.definition.template,
|
|
257
|
+
styles: this.definition.styles
|
|
258
|
+
}) as RWSWindowComponentInterface;
|
|
259
|
+
|
|
260
|
+
if (!richWindow.RWS) {
|
|
261
|
+
throw new Error('RWS client not initialized');
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
richWindow.RWS.components[this.definition.name] = {
|
|
265
|
+
interface: composedComp,
|
|
266
|
+
component: this
|
|
267
|
+
};
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
static getDefinition(tagName: string, htmlTemplate: ViewTemplate, styles: ElementStyles = null) {
|
|
271
|
+
const def: IFastDefinition = {
|
|
272
|
+
name: tagName,
|
|
273
|
+
template: htmlTemplate
|
|
274
|
+
};
|
|
275
|
+
|
|
276
|
+
if (styles) {
|
|
277
|
+
def.styles = styles;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
return def;
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
private static getInstances(): RWSViewComponent[] {
|
|
284
|
+
return RWSViewComponent.instances;
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
export default RWSViewComponent;
|
|
289
|
+
|
|
290
|
+
export { IAssetShowOptions, IRWSViewComponent }
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { DI } from '@microsoft/fast-foundation';
|
|
2
|
+
import RWSWindow, {loadRWSRichWindow} from '../interfaces/RWSWindow'
|
|
3
|
+
|
|
4
|
+
import 'reflect-metadata';
|
|
5
|
+
|
|
6
|
+
export default () => {
|
|
7
|
+
const richWindow = loadRWSRichWindow();
|
|
8
|
+
|
|
9
|
+
if(richWindow.RWS.container){
|
|
10
|
+
return richWindow.RWS.container;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
richWindow.RWS.container = DI.getOrCreateDOMContainer(richWindow.RWS.container_node);
|
|
14
|
+
|
|
15
|
+
return richWindow.RWS.container;
|
|
16
|
+
};
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { DI, InterfaceSymbol, inject, Key } from '@microsoft/fast-foundation';
|
|
2
|
+
import RWSViewComponent, { IWithCompose } from './_component';
|
|
3
|
+
import RWSContainer from './_container';
|
|
4
|
+
import 'reflect-metadata';
|
|
5
|
+
|
|
6
|
+
type Constructor<T = any> = new (...args: any[]) => T;
|
|
7
|
+
|
|
8
|
+
interface RWSDecoratorOptions {
|
|
9
|
+
template?: string,
|
|
10
|
+
styles?: string,
|
|
11
|
+
fastElementOptions?: any,
|
|
12
|
+
ignorePackaging?: boolean
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
type InjectDecoratorReturnType = (target: any, key?: string | number | undefined, parameterIndex?: number) => void;
|
|
16
|
+
|
|
17
|
+
const _PARAMTYPES_METADATA_KEY = 'design:paramtypes';
|
|
18
|
+
|
|
19
|
+
function RWSInject<T extends RWSViewComponent>(dependencyClass: Key): InjectDecoratorReturnType {
|
|
20
|
+
return (target: IWithCompose<T>, key?: keyof IWithCompose<T>, parameterIndex?: number) => {
|
|
21
|
+
const loadedDependency = RWSContainer().get(dependencyClass);
|
|
22
|
+
const paramNames = getFunctionParamNames(target.prototype.constructor);
|
|
23
|
+
target.prototype.constructor._toInject[paramNames[parameterIndex]] = loadedDependency;
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function RWSView<T extends RWSViewComponent>(name: string, data?: RWSDecoratorOptions): (type: any) => void {
|
|
28
|
+
return (constructor: T) => {
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function RWSIgnore(params: { mergeToApp?: boolean } = null): () => void {
|
|
33
|
+
return () => { };
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function getFunctionParamNames(func: Function): string[] {
|
|
37
|
+
// Convert the function to its string form and extract the parameter names
|
|
38
|
+
const funcStr = func.toString().replace(/((\/\/.*$)|(\/\*[\s\S]*?\*\/)|(\s))/mg, '');
|
|
39
|
+
return funcStr.slice(funcStr.indexOf('(')+1, funcStr.indexOf(')')).split(',');
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
function getParentConstructor(instance: any): any
|
|
44
|
+
{
|
|
45
|
+
const proto = Object.getPrototypeOf(instance.constructor.prototype);
|
|
46
|
+
if (proto && proto.constructor) {
|
|
47
|
+
return proto.constructor;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
return null;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const applyConstructor = (component: RWSViewComponent): void => {
|
|
54
|
+
let mainConstructor = component.constructor;
|
|
55
|
+
const parent = getParentConstructor(component);
|
|
56
|
+
|
|
57
|
+
if(!mainConstructor.length){
|
|
58
|
+
mainConstructor = parent;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
let topConstructor = mainConstructor;
|
|
62
|
+
|
|
63
|
+
if( parent && parent.name === RWSViewComponent.name){
|
|
64
|
+
topConstructor = parent;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const existingInjectedDependencies = (topConstructor as IWithCompose<RWSViewComponent>)._toInject;
|
|
68
|
+
|
|
69
|
+
Object.keys(existingInjectedDependencies).forEach((depKey: string) => {
|
|
70
|
+
const loadedDependency = existingInjectedDependencies[depKey];
|
|
71
|
+
if(!(component as any)[depKey]){
|
|
72
|
+
(component as any)[depKey] = loadedDependency;
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
const applyProp = (component: RWSViewComponent, propName: string | symbol): any => {
|
|
78
|
+
let mainConstructor = component.constructor;
|
|
79
|
+
const parent = getParentConstructor(component);
|
|
80
|
+
|
|
81
|
+
if(!mainConstructor.length){
|
|
82
|
+
mainConstructor = parent;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
let topConstructor = mainConstructor;
|
|
86
|
+
|
|
87
|
+
if( parent && parent.name === RWSViewComponent.name){
|
|
88
|
+
topConstructor = parent;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
if(typeof propName !== 'string'){
|
|
92
|
+
propName = propName.toString();
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
const existingInjectedDependencies = (topConstructor as IWithCompose<RWSViewComponent>)._toInject;
|
|
96
|
+
|
|
97
|
+
// console.log(propName);
|
|
98
|
+
if(!Object.keys(existingInjectedDependencies).includes(propName)){
|
|
99
|
+
return null;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
const loadedDependency = existingInjectedDependencies[propName];
|
|
103
|
+
|
|
104
|
+
if(!(component as any)[propName]){
|
|
105
|
+
(component as any)[propName] = loadedDependency;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
return loadedDependency;
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
export { RWSView, RWSDecoratorOptions, RWSIgnore, RWSInject, applyConstructor, applyProp }
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { RWSView, RWSViewComponent, observable, attr } from '../../index';
|
|
2
|
+
import {
|
|
3
|
+
nullableNumberConverter,
|
|
4
|
+
} from "@microsoft/fast-element";
|
|
5
|
+
|
|
6
|
+
@RWSView('rws-progress')
|
|
7
|
+
class RWSProgress extends RWSViewComponent {
|
|
8
|
+
|
|
9
|
+
@attr({ converter: nullableNumberConverter })
|
|
10
|
+
public value: number | null;
|
|
11
|
+
protected valueChanged(): void {
|
|
12
|
+
this.updatePercentComplete();
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
@attr({ converter: nullableNumberConverter })
|
|
17
|
+
public min: number;
|
|
18
|
+
protected minChanged(): void {
|
|
19
|
+
if (this.$fastController.isConnected) {
|
|
20
|
+
this.updatePercentComplete();
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
@attr({ converter: nullableNumberConverter })
|
|
26
|
+
public max: number;
|
|
27
|
+
protected maxChanged(): void {
|
|
28
|
+
if (this.$fastController.isConnected) {
|
|
29
|
+
this.updatePercentComplete();
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
@observable
|
|
35
|
+
public percentComplete: number = 0;
|
|
36
|
+
|
|
37
|
+
public connectedCallback(): void {
|
|
38
|
+
super.connectedCallback();
|
|
39
|
+
this.updatePercentComplete();
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
private updatePercentComplete(): void {
|
|
43
|
+
const min: number = typeof this.min === "number" ? this.min : 0;
|
|
44
|
+
const max: number = typeof this.max === "number" ? this.max : 100;
|
|
45
|
+
const value: number = typeof this.value === "number" ? this.value : 0;
|
|
46
|
+
const range: number = max - min;
|
|
47
|
+
|
|
48
|
+
this.percentComplete =
|
|
49
|
+
range === 0 ? 0 : Math.fround(((value - min) / range) * 100);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
RWSProgress.defineComponent();
|
|
54
|
+
|
|
55
|
+
export { RWSProgress };
|