##// END OF EJS Templates
linting
cin -
r109:4a375b9c654a default
parent child
Show More
@@ -0,0 +1,1
1 .eslintrc.js No newline at end of file
@@ -0,0 +1,39
1 module.exports = {
2 root: true,
3 extends: [
4 "plugin:react/recommended",
5 "eslint:recommended",
6 "plugin:@typescript-eslint/eslint-recommended",
7 "plugin:@typescript-eslint/recommended",
8 "plugin:@typescript-eslint/recommended-requiring-type-checking"
9 ],
10 parser: "@typescript-eslint/parser",
11 parserOptions: {
12 ecmaFeatures: {
13 jsx: true
14 },
15 ecmaVersion: 5,
16 tsconfigRootDir: __dirname + "/src",
17 project: [
18 "tsconfig.eslint.json",
19 "*/tsconfig.json"
20 ]
21 },
22 plugins: [
23 "react",
24 "@typescript-eslint"
25 ],
26 rules: {
27 "react/react-in-jsx-scope": "off",
28 "react/no-unknown-property": "off",
29 "@typescript-eslint/no-empty-function": "off",
30 "max-classes-per-file": [
31 "error",
32 { "ignoreExpressions": true, "max": 1 }
33 ],
34 "@typescript-eslint/prefer-readonly": ["error"],
35 "semi": "off",
36 "@typescript-eslint/semi": ["error"]
37
38 }
39 }
@@ -0,0 +1,39
1 module.exports = {
2 root: true,
3 extends: [
4 "plugin:react/recommended",
5 "eslint:recommended",
6 "plugin:@typescript-eslint/eslint-recommended",
7 "plugin:@typescript-eslint/recommended",
8 "plugin:@typescript-eslint/recommended-requiring-type-checking"
9 ],
10 parser: "@typescript-eslint/parser",
11 parserOptions: {
12 ecmaFeatures: {
13 jsx: true
14 },
15 ecmaVersion: 5,
16 tsconfigRootDir: __dirname + "/src",
17 project: [
18 "tsconfig.eslint.json",
19 "*/tsconfig.json"
20 ]
21 },
22 plugins: [
23 "react",
24 "@typescript-eslint"
25 ],
26 rules: {
27 "react/react-in-jsx-scope": "off",
28 "react/no-unknown-property": "off",
29 "@typescript-eslint/no-empty-function": "off",
30 "max-classes-per-file": [
31 "error",
32 { "ignoreExpressions": true, "max": 1 }
33 ],
34 "@typescript-eslint/prefer-readonly": ["error"],
35 "semi": "off",
36 "@typescript-eslint/semi": ["error"],
37 "react/jsx-key": "off"
38 }
39 }
@@ -0,0 +1,3
1 {
2 "extends": "../tsconfig",
3 } No newline at end of file
@@ -10,7 +10,7
10 "license": "BSD-2-Clause",
10 "license": "BSD-2-Clause",
11 "devDependencies": {
11 "devDependencies": {
12 "@implab/core-amd": "^1.4.0",
12 "@implab/core-amd": "^1.4.0",
13 "@implab/dojo-typings": "1.0.0",
13 "@implab/dojo-typings": "1.0.3",
14 "@types/chai": "4.1.3",
14 "@types/chai": "4.1.3",
15 "@types/requirejs": "2.1.31",
15 "@types/requirejs": "2.1.31",
16 "@types/tap": "15.0.7",
16 "@types/tap": "15.0.7",
@@ -458,9 +458,9
458 "dev": true
458 "dev": true
459 },
459 },
460 "node_modules/@implab/dojo-typings": {
460 "node_modules/@implab/dojo-typings": {
461 "version": "1.0.0",
461 "version": "1.0.3",
462 "resolved": "https://registry.npmjs.org/@implab/dojo-typings/-/dojo-typings-1.0.0.tgz",
462 "resolved": "https://registry.npmjs.org/@implab/dojo-typings/-/dojo-typings-1.0.3.tgz",
463 "integrity": "sha512-B2kvlKJgvyIQAl/k1pVyNmtp4ADvBDCs4Lw/qfBC+Sz/ft4c7EuRXmN/+2dhWrd6A5SMjEgex5oeq6Ja2ntrig==",
463 "integrity": "sha512-oyCiuU5ay9MfvdQtZNJSeV30jKufdiLBAcq6rn360pww2hzdqvWEeoU9/New8fMzyNiaEumOlgbcS11EVIH+Jg==",
464 "dev": true
464 "dev": true
465 },
465 },
466 "node_modules/@istanbuljs/load-nyc-config": {
466 "node_modules/@istanbuljs/load-nyc-config": {
@@ -7030,9 +7030,9
7030 "dev": true
7030 "dev": true
7031 },
7031 },
7032 "@implab/dojo-typings": {
7032 "@implab/dojo-typings": {
7033 "version": "1.0.0",
7033 "version": "1.0.3",
7034 "resolved": "https://registry.npmjs.org/@implab/dojo-typings/-/dojo-typings-1.0.0.tgz",
7034 "resolved": "https://registry.npmjs.org/@implab/dojo-typings/-/dojo-typings-1.0.3.tgz",
7035 "integrity": "sha512-B2kvlKJgvyIQAl/k1pVyNmtp4ADvBDCs4Lw/qfBC+Sz/ft4c7EuRXmN/+2dhWrd6A5SMjEgex5oeq6Ja2ntrig==",
7035 "integrity": "sha512-oyCiuU5ay9MfvdQtZNJSeV30jKufdiLBAcq6rn360pww2hzdqvWEeoU9/New8fMzyNiaEumOlgbcS11EVIH+Jg==",
7036 "dev": true
7036 "dev": true
7037 },
7037 },
7038 "@istanbuljs/load-nyc-config": {
7038 "@istanbuljs/load-nyc-config": {
@@ -25,7 +25,7
25 "@types/yaml": "1.2.0",
25 "@types/yaml": "1.2.0",
26 "@types/tap": "15.0.7",
26 "@types/tap": "15.0.7",
27 "dojo": "1.16.0",
27 "dojo": "1.16.0",
28 "@implab/dojo-typings": "1.0.0",
28 "@implab/dojo-typings": "1.0.3",
29 "@typescript-eslint/eslint-plugin": "^5.23.0",
29 "@typescript-eslint/eslint-plugin": "^5.23.0",
30 "@typescript-eslint/parser": "^5.23.0",
30 "@typescript-eslint/parser": "^5.23.0",
31 "eslint": "^8.23.0",
31 "eslint": "^8.23.0",
@@ -3,31 +3,18 import { argumentNotEmptyString, isPromi
3
3
4 export type LocaleProvider<T> = () => PromiseOrValue<T | { default: T }>;
4 export type LocaleProvider<T> = () => PromiseOrValue<T | { default: T }>;
5
5
6 type ResolveCallback<T> = () => PromiseOrValue<T>;
7
8 function when<T, T2>(value: PromiseOrValue<T>, cb: (v: T) => PromiseOrValue<T2>): PromiseOrValue<T2> {
6 function when<T, T2>(value: PromiseOrValue<T>, cb: (v: T) => PromiseOrValue<T2>): PromiseOrValue<T2> {
9 return isPromise(value) ?
7 return isPromise(value) ?
10 value.then(cb) :
8 value.then(cb) :
11 cb(value);
9 cb(value);
12 }
10 }
13
11
14 function isCallback<T>(v: ResolveCallback<T> | PromiseOrValue<T>): v is ResolveCallback<T> {
12 const chainObjects = <T extends object, T2 extends object>(o1: T, o2: T2) =>
15 return typeof v === "function";
13 mixin(Object.create(o1) as T, o2);
16 }
14 export class NlsBundle<T extends object> {
15 private readonly _locales: MapOf<LocaleProvider<Partial<T>>>;
17
16
18 function chainObjects<T extends object>(o1: T, o2: T) {
17 private readonly _default: T;
19 if (!o1)
20 return o2;
21 if (!o2)
22 return o1;
23
24 return mixin(Object.create(o1) as T, o2);
25 }
26
27 export class NlsBundle<T extends object> {
28 private _locales: MapOf<LocaleProvider<Partial<T>>>;
29
30 private _default: T;
31
18
32 private _cache: MapOf<PromiseOrValue<T>>;
19 private _cache: MapOf<PromiseOrValue<T>>;
33
20
@@ -65,9 +52,7 export class NlsBundle<T extends object>
65 });
52 });
66 }
53 }
67
54
68 _loadPackage(localeData: any) {
55 _loadPackage(localeData: LocaleProvider<Partial<T>>) {
69 if (isCallback(localeData))
56 return when(localeData(), data => data && "default" in data ? data.default : data);
70 return when(localeData(), data => data && "default" in data ? data.default : data);
71 return localeData;
72 }
57 }
73 }
58 }
@@ -1,8 +1,8
1 import inject from "./dom-inject";
1 import inject from "./dom-inject";
2
2
3 interface OnLoad {
3 interface OnLoad {
4 (result?: any): void;
4 (result?: unknown): void;
5 error(err: any): void;
5 error(err: unknown): void;
6 }
6 }
7
7
8 const plugin = {
8 const plugin = {
@@ -137,9 +137,10 export function djclass<T extends Abstra
137
137
138 // proxy - фабрика для создания прокси-методов, которые внутри
138 // proxy - фабрика для создания прокси-методов, которые внутри
139 // себя вызовут this.inherited с правильными параметрами.
139 // себя вызовут this.inherited с правильными параметрами.
140 const proxy = (m: (...args: unknown[]) => unknown) => function (this: dojo._base.DeclareCreatedObject, ...args: unknown[]) {
140 const proxy = (m: (...args: unknown[]) => unknown) => function (this: dojo._base.DeclareCreatedObject) {
141 const f = this.getInherited({ callee: m, ...args, length: args.length });
141 const f = this.getInherited({ callee: m } as unknown as IArguments);
142 return f ? f.apply(this, args) as unknown : undefined;
142 // eslint-disable-next-line prefer-rest-params
143 return f ? f.apply(this, arguments) as unknown : undefined;
143
144
144 // так сделать можно только dojo 1.15+
145 // так сделать можно только dojo 1.15+
145 // return this.inherited(m, arguments);
146 // return this.inherited(m, arguments);
@@ -153,7 +154,7 export function djclass<T extends Abstra
153 each(target.prototype, (m: unknown, p: string) => {
154 each(target.prototype, (m: unknown, p: string) => {
154 if (typeof m === "function" &&
155 if (typeof m === "function" &&
155 p !== "constructor" &&
156 p !== "constructor" &&
156 Object.prototype.hasOwnProperty.call(target, p)
157 Object.prototype.hasOwnProperty.call(target.prototype, p)
157 ) {
158 ) {
158 nbp[p] = proxy(m as (...args: unknown[]) => unknown);
159 nbp[p] = proxy(m as (...args: unknown[]) => unknown);
159 }
160 }
@@ -224,18 +225,18 export function bind(params: NodeBindSpe
224 target[makeSetterName(name) as K /** hack to not go insane) */] = params;
225 target[makeSetterName(name) as K /** hack to not go insane) */] = params;
225 };
226 };
226 } else {
227 } else {
227 return <K extends string,
228 return <K extends string>(target: Record<K | "_set", unknown>, name: K) => {
228 T extends { [p in K]: p extends "_set" ? (name: p, v: unknown) => void : unknown; }> (target: T, name: K) => {
229 target[name] = undefined;
229 target[name] = undefined as T[K];
230
230 target[makeSetterName(name) as K] = function (this: T, v: unknown) {
231 target[makeSetterName(name) as K] = function (this: typeof target, v: unknown) {
231 this._set(name, v);
232 (this._set as (n: K, v: unknown) => void)(name, v);
232 const inner = this[params.member] as Record<string, unknown>;
233 const inner = this[params.member as K] as Record<string, unknown>;
233 if (typeof inner.set === "function")
234 if (typeof inner.set === "function")
234 inner.set(params.property, v);
235 inner.set(params.property, v);
235 } as T[K];
236 };
236 if (params.getter)
237 if (params.getter)
237 target[makeGetterName(name)] = function () {
238 target[makeGetterName(name) as K] = function (this: typeof target) {
238 const inner = this[params.member] as Record<string, unknown>;
239 const inner = this[params.member as K] as Record<string, unknown>;
239 if (typeof inner.get === "function")
240 if (typeof inner.get === "function")
240 return inner.get(params.property) as unknown;
241 return inner.get(params.property) as unknown;
241 };
242 };
@@ -6,7 +6,7 import { mixin } from "@implab/core-amd/
6 const trace = TraceSource.get(mid);
6 const trace = TraceSource.get(mid);
7
7
8
8
9 function on<T extends keyof HTMLElementEventMap>(node: HTMLElement, eventName: T, handler: (this: HTMLElement, ev: HTMLElementEventMap[T]) => any): () => void {
9 function on<T extends keyof HTMLElementEventMap>(node: HTMLElement, eventName: T, handler: (this: HTMLElement, ev: HTMLElementEventMap[T]) => unknown): () => void {
10 // Add an event listener to a DOM node
10 // Add an event listener to a DOM node
11 node.addEventListener(eventName, handler, false);
11 node.addEventListener(eventName, handler, false);
12
12
@@ -57,7 +57,7 class DomInject {
57
57
58 async injectScript(url: string) {
58 async injectScript(url: string) {
59 let d = this._map[url];
59 let d = this._map[url];
60 if (!d) {
60 if (d === undefined) {
61 trace.log("js {0}", url);
61 trace.log("js {0}", url);
62 d = this._inject("script", {
62 d = this._inject("script", {
63 type: "text/javascript",
63 type: "text/javascript",
@@ -77,7 +77,7 class DomInject {
77
77
78 async injectStylesheet(url: string) {
78 async injectStylesheet(url: string) {
79 let d = this._map[url];
79 let d = this._map[url];
80 if (!d) {
80 if (d === undefined) {
81 trace.log("js {0}", url);
81 trace.log("js {0}", url);
82 d = this._inject("link", {
82 d = this._inject("link", {
83 type: "text/css",
83 type: "text/css",
@@ -1,6 +1,6
1 import { id as mid} from "module";
1 import { id as mid} from "module";
2 import { MapOf } from "@implab/core-amd/interfaces";
2 import { MapOf } from "@implab/core-amd/interfaces";
3 import { NlsBundle } from "./NlsBundle";
3 import { LocaleProvider, NlsBundle } from "./NlsBundle";
4 import { isPromise } from "@implab/core-amd/safe";
4 import { isPromise } from "@implab/core-amd/safe";
5 import { locale as sysLocale } from "dojo/_base/kernel";
5 import { locale as sysLocale } from "dojo/_base/kernel";
6 import { TraceSource } from "@implab/core-amd/log/TraceSource";
6 import { TraceSource } from "@implab/core-amd/log/TraceSource";
@@ -10,11 +10,11 const trace = TraceSource.get(mid);
10 trace.debug("Current sysLocale: {0}", sysLocale);
10 trace.debug("Current sysLocale: {0}", sysLocale);
11
11
12 export interface OnLoad {
12 export interface OnLoad {
13 (result?: any): void;
13 (result?: unknown): void;
14 error(err: any): void;
14 error(err: unknown): void;
15 }
15 }
16
16
17 export function bundle<T extends object>(nls: T, locales?: MapOf<any>) {
17 export function bundle<T extends object>(nls: T, locales?: MapOf<LocaleProvider<object>>) {
18 const nlsBundle = new NlsBundle(nls, locales);
18 const nlsBundle = new NlsBundle(nls, locales);
19
19
20 const fn = (_locale?: string) => {
20 const fn = (_locale?: string) => {
@@ -28,7 +28,7 export function bundle<T extends object>
28 };
28 };
29
29
30 fn.define = (pack: Partial<T>) => pack;
30 fn.define = (pack: Partial<T>) => pack;
31 fn.load = async (id: string, require: Require, cb: OnLoad, config: any) => {
31 fn.load = async (id: string, require: Require, cb: OnLoad, config: {isBuild?: boolean}) => {
32 const locale = id || sysLocale;
32 const locale = id || sysLocale;
33 if (config && config.isBuild) {
33 if (config && config.isBuild) {
34 cb();
34 cb();
@@ -74,17 +74,17 const sink = <T>(consumer: Partial<Obser
74 next: next ? next.bind(consumer) : noop,
74 next: next ? next.bind(consumer) : noop,
75 error: error ? error.bind(consumer) : noop,
75 error: error ? error.bind(consumer) : noop,
76 complete: complete ? complete.bind(consumer) : noop
76 complete: complete ? complete.bind(consumer) : noop
77 }
77 };
78 };
78 };
79
79
80 const fuse = <T>({ next, error, complete }: Sink<T>) => {
80 const fuse = <T>({ next, error, complete }: Sink<T>) => {
81 let done = false;
81 let done = false;
82 return {
82 return {
83 next: (value: T) => { !done && next(value) },
83 next: (value: T) => { !done && next(value); },
84 error: (e: unknown) => { !done && (done = true, error(e)) },
84 error: (e: unknown) => { !done && (done = true, error(e)); },
85 complete: () => { !done && (done = true, complete()) }
85 complete: () => { !done && (done = true, complete()); }
86 }
86 };
87 }
87 };
88
88
89 const _observe = <T>(producer: Producer<T>): Observable<T> => ({
89 const _observe = <T>(producer: Producer<T>): Observable<T> => ({
90 subscribe: (consumer: Partial<Observer<T>>) => ({
90 subscribe: (consumer: Partial<Observer<T>>) => ({
@@ -12,7 +12,7 import djAttr = require("dojo/dom-attr")
12 import djClass = require("dojo/dom-class");
12 import djClass = require("dojo/dom-class");
13 import { AnimationAttrs, WatchForRendition } from "./tsx/WatchForRendition";
13 import { AnimationAttrs, WatchForRendition } from "./tsx/WatchForRendition";
14
14
15 export function createElement<T extends Constructor | string | ((props: any) => Element)>(elementType: T, ...args: any[]): Rendition {
15 export function createElement<T extends Constructor | string | ((props: object) => Element)>(elementType: T, ...args: unknown[]): Rendition {
16 if (typeof elementType === "string") {
16 if (typeof elementType === "string") {
17 const ctx = new HtmlRendition(elementType);
17 const ctx = new HtmlRendition(elementType);
18 if (args)
18 if (args)
@@ -26,17 +26,17 export function createElement<T extends
26
26
27 return ctx;
27 return ctx;
28 } else if (typeof elementType === "function") {
28 } else if (typeof elementType === "function") {
29 const ctx = new FunctionRendition(elementType as (props: any) => Element);
29 const ctx = new FunctionRendition(elementType as (props: unknown) => Element);
30 if (args)
30 if (args)
31 args.forEach(x => ctx.visitNext(x));
31 args.forEach(x => ctx.visitNext(x));
32
32
33 return ctx;
33 return ctx;
34 } else {
34 } else {
35 throw new Error(`The element type '${elementType}' is unsupported`);
35 throw new Error(`The element type '${String(elementType)}' is unsupported`);
36 }
36 }
37 }
37 }
38
38
39 export interface EventDetails<T = any> {
39 export interface EventDetails<T = unknown> {
40 detail: T;
40 detail: T;
41 }
41 }
42
42
@@ -56,7 +56,7 export interface QueryResultUpdate<T> {
56 newIndex: number;
56 newIndex: number;
57 }
57 }
58
58
59 export type DojoMouseEvent<T = any> = MouseEvent & EventSelector & EventDetails<T>;
59 export type DojoMouseEvent<T = unknown> = MouseEvent & EventSelector & EventDetails<T>;
60
60
61 type StatefulProps<T> = T extends Stateful<infer A> ? A :
61 type StatefulProps<T> = T extends Stateful<infer A> ? A :
62 T extends _WidgetBase ? T : never;
62 T extends _WidgetBase ? T : never;
@@ -73,7 +73,7 type StatefulProps<T> = T extends Statef
73 export function watch<W extends _WidgetBase, K extends keyof W>(
73 export function watch<W extends _WidgetBase, K extends keyof W>(
74 target: W,
74 target: W,
75 prop: K,
75 prop: K,
76 render: (model: W[K]) => any
76 render: (model: W[K]) => unknown
77 ): Rendition;
77 ): Rendition;
78 /**
78 /**
79 * Observers the property and calls render callback each change.
79 * Observers the property and calls render callback each change.
@@ -86,7 +86,7 export function watch<W extends _WidgetB
86 export function watch<T extends Stateful, K extends keyof StatefulProps<T>>(
86 export function watch<T extends Stateful, K extends keyof StatefulProps<T>>(
87 target: T,
87 target: T,
88 prop: K,
88 prop: K,
89 render: (model: StatefulProps<T>[K]) => any
89 render: (model: StatefulProps<T>[K]) => unknown
90 ): Rendition;
90 ): Rendition;
91 export function watch<V>(subj: Subscribable<V>, render: (model: V) => unknown): Rendition;
91 export function watch<V>(subj: Subscribable<V>, render: (model: V) => unknown): Rendition;
92 export function watch(
92 export function watch(
@@ -98,7 +98,7 export function watch(
98 return new WatchRendition(
98 return new WatchRendition(
99 render,
99 render,
100 observe(({next}) => {
100 observe(({next}) => {
101 const h = target.watch<any>(
101 const h = target.watch(
102 prop,
102 prop,
103 (_prop, oldValue, newValue) => oldValue !== newValue && next(newValue)
103 (_prop, oldValue, newValue) => oldValue !== newValue && next(newValue)
104 );
104 );
@@ -118,7 +118,7 export const watchFor = <T>(source: T[]
118 subject: source,
118 subject: source,
119 component: render
119 component: render
120 });
120 });
121 }
121 };
122
122
123
123
124 export const prop: {
124 export const prop: {
@@ -132,7 +132,7 export const prop: {
132 );
132 );
133 next(target.get(name));
133 next(target.get(name));
134 return () => h.remove();
134 return () => h.remove();
135 })
135 });
136 };
136 };
137
137
138 export const attach = <W extends DjxWidgetBase, K extends keyof W>(target: W, name: K) => (v: W[K]) => target.set(name, v);
138 export const attach = <W extends DjxWidgetBase, K extends keyof W>(target: W, name: K) => (v: W[K]) => target.set(name, v);
@@ -140,7 +140,7 export const attach = <W extends DjxWidg
140 export const bind = <K extends string, T>(attr: K, subj: Subscribable<T>) => {
140 export const bind = <K extends string, T>(attr: K, subj: Subscribable<T>) => {
141 let h = { unsubscribe() { } };
141 let h = { unsubscribe() { } };
142
142
143 return <E extends (HTMLElement & { [p in K]: T }) | { set(name: K, value: T): void; }>(el: E | undefined) => {
143 return (el: Element | { set(name: K, value: T): void; } | undefined) => {
144 if (el) {
144 if (el) {
145 if (isElementNode(el)) {
145 if (isElementNode(el)) {
146 h = subj.subscribe({
146 h = subj.subscribe({
@@ -154,7 +154,7 export const bind = <K extends string, T
154 } else {
154 } else {
155 h.unsubscribe();
155 h.unsubscribe();
156 }
156 }
157 }
157 };
158 };
158 };
159
159
160 export const toggleClass = (className: string, subj: Subscribable<boolean>) => {
160 export const toggleClass = (className: string, subj: Subscribable<boolean>) => {
@@ -168,8 +168,8 export const toggleClass = (className: s
168 } else {
168 } else {
169 h.unsubscribe();
169 h.unsubscribe();
170 }
170 }
171 }
171 };
172 }
172 };
173
173
174 export const all = <T, A extends JSX.Ref<T>[]>(...cbs: A): JSX.Ref<T> => (arg: T | undefined) => cbs.forEach(cb => cb(arg));
174 export const all = <T, A extends JSX.Ref<T>[]>(...cbs: A): JSX.Ref<T> => (arg: T | undefined) => cbs.forEach(cb => cb(arg));
175
175
@@ -185,13 +185,14 export const all = <T, A extends JSX.Ref
185 */
185 */
186 export const on = <E extends string>(...eventNames: E[]) =>
186 export const on = <E extends string>(...eventNames: E[]) =>
187 <K extends string,
187 <K extends string,
188 T extends DjxWidgetBase<any, { [p in E]: EV }>,
188 T extends DjxWidgetBase<object, { [p in E]: EV }>,
189 EV extends Event
189 EV extends Event
190 >(
190 >(
191 target: T,
191 target: T,
192 key: K,
192 key: K,
193 // eslint-disable-next-line @typescript-eslint/no-unused-vars
193 _descriptor: TypedPropertyDescriptor<(eventObj: EV) => void> | TypedPropertyDescriptor<() => void>
194 _descriptor: TypedPropertyDescriptor<(eventObj: EV) => void> | TypedPropertyDescriptor<() => void>
194 ): any => {
195 ) => {
195 const handlers = eventNames.map(eventName => ({ eventName, handlerMethod: key }));
196 const handlers = eventNames.map(eventName => ({ eventName, handlerMethod: key }));
196 target._eventHandlers = target._eventHandlers ? target._eventHandlers.concat(handlers) : handlers;
197 target._eventHandlers = target._eventHandlers ? target._eventHandlers.concat(handlers) : handlers;
197 };
198 };
@@ -17,7 +17,8 export interface EventArgs {
17 composed?: boolean;
17 composed?: boolean;
18 }
18 }
19
19
20 export interface DjxWidgetBase<Attrs = {}, Events extends { [name in keyof Events]: Event } = {}> extends
20 // eslint-disable-next-line @typescript-eslint/no-unused-vars
21 export interface DjxWidgetBase<Attrs = object, Events extends { [name in keyof Events]: Event } = object> extends
21 _WidgetBase<Events> {
22 _WidgetBase<Events> {
22
23
23 /** This property is declared only for type inference to work, it is never assigned
24 /** This property is declared only for type inference to work, it is never assigned
@@ -32,7 +33,7 export interface DjxWidgetBase<Attrs = {
32 */
33 */
33 _eventHandlers: Array<{
34 _eventHandlers: Array<{
34 eventName: string,
35 eventName: string,
35 handlerMethod: keyof any;
36 handlerMethod: string;
36 }>;
37 }>;
37 }
38 }
38
39
@@ -43,7 +44,8 type _super = {
43 };
44 };
44
45
45 @djclass
46 @djclass
46 export abstract class DjxWidgetBase<Attrs = {}, Events = {}> extends djbase<_super, _AttachMixin>(_WidgetBase, _AttachMixin) {
47 // eslint-disable-next-line @typescript-eslint/no-unused-vars
48 export abstract class DjxWidgetBase<Attrs = object, Events = object> extends djbase<_super, _AttachMixin>(_WidgetBase, _AttachMixin) {
47 private readonly _scope = new Scope();
49 private readonly _scope = new Scope();
48
50
49 buildRendering() {
51 buildRendering() {
@@ -68,29 +70,29 export abstract class DjxWidgetBase<Attr
68 }
70 }
69 }
71 }
70
72
71 abstract render(): Rendition<HTMLElement>;
73 abstract render(): Rendition;
72
74
73 private _connectEventHandlers() {
75 private _connectEventHandlers() {
74 if (this._eventHandlers)
76 if (this._eventHandlers)
75 this._eventHandlers.forEach(({ eventName, handlerMethod }) => {
77 this._eventHandlers.forEach(({ eventName, handlerMethod }) => {
76 const handler = this[handlerMethod as keyof this];
78 const handler = this[handlerMethod as keyof this];
77 if (typeof handler === "function")
79 if (typeof handler === "function")
78 on(this.domNode, eventName, handler.bind(this));
80 on(this.domNode, eventName, handler.bind(this) as (...args: unknown[]) => unknown);
79 });
81 });
80 }
82 }
81
83
82 _processTemplateNode<T extends (Element | Node | _WidgetBase)>(
84 _processTemplateNode<T extends (Element | Node | _WidgetBase)>(
83 baseNode: T,
85 baseNode: T,
84 getAttrFunc: (baseNode: T, attr: string) => any,
86 getAttrFunc: (baseNode: T, attr: string) => string,
85 // tslint:disable-next-line: ban-types
87 // tslint:disable-next-line: ban-types
86 attachFunc: (node: T, type: string, func?: Function) => dojo.Handle
88 attachFunc: (node: T, type: string, func?: (...args: unknown[]) => unknown) => dojo.Handle
87 ): boolean {
89 ): boolean {
88 if (isNode(baseNode)) {
90 if (isNode(baseNode)) {
89 const w = registry.byNode(baseNode);
91 const w = registry.byNode(baseNode);
90 if (w) {
92 if (w) {
91 // from dijit/_WidgetsInTemplateMixin
93 // from dijit/_WidgetsInTemplateMixin
92 this._processTemplateNode(w,
94 this._processTemplateNode(w,
93 (n, p) => n.get(p as any), // callback to get a property of a widget
95 (n, p) => String(n.get(p as keyof typeof n)), // callback to get a property of a widget
94 (widget, type, callback) => {
96 (widget, type, callback) => {
95 if (!callback)
97 if (!callback)
96 throw new Error("The callback must be specified");
98 throw new Error("The callback must be specified");
@@ -101,7 +103,7 export abstract class DjxWidgetBase<Attr
101 return widget.connect(widget, type, callback as EventListener);
103 return widget.connect(widget, type, callback as EventListener);
102 } else {
104 } else {
103 // 1.x may never hit this branch, but it's the default for 2.0
105 // 1.x may never hit this branch, but it's the default for 2.0
104 return widget.on(type, callback);
106 return widget.on(type as keyof GlobalEventHandlersEventMap, callback);
105 }
107 }
106
108
107 });
109 });
@@ -109,7 +111,8 export abstract class DjxWidgetBase<Attr
109 return false;
111 return false;
110 }
112 }
111 }
113 }
112 return super._processTemplateNode(baseNode, getAttrFunc, attachFunc);
114 // eslint-disable-next-line @typescript-eslint/ban-types
115 return super._processTemplateNode(baseNode, getAttrFunc, attachFunc as (node: T, type: string, func?: Function) => dojo.Handle);
113 }
116 }
114
117
115 /** Starts current widget and all its supporting widgets (placed outside
118 /** Starts current widget and all its supporting widgets (placed outside
@@ -3,19 +3,19 import { getItemDom } from "./render";
3 import { RenditionBase } from "./RenditionBase";
3 import { RenditionBase } from "./RenditionBase";
4
4
5 export class FunctionRendition extends RenditionBase<Node> {
5 export class FunctionRendition extends RenditionBase<Node> {
6 private _component: (...args: any[]) => any;
6 private readonly _component: (...args: unknown[]) => unknown;
7
7
8 private _node: Node | undefined;
8 private _node: Node | undefined;
9
9
10 constructor(component: (...args: any[]) => any) {
10 constructor(component: (...args: unknown[]) => unknown) {
11 super();
11 super();
12 argumentNotNull(component, "component");
12 argumentNotNull(component, "component");
13
13
14 this._component = component;
14 this._component = component;
15 }
15 }
16
16
17 protected _create(attrs: object, children: any[]) {
17 protected _create(attrs: object, children: unknown[]) {
18 const _attrs: any = attrs || {};
18 const _attrs = attrs || {};
19 const _children = children.map(x => getItemDom(x));
19 const _children = children.map(x => getItemDom(x));
20 this._node = getItemDom(
20 this._node = getItemDom(
21 this._component.call(null, { ..._attrs, children: _children }));
21 this._component.call(null, { ..._attrs, children: _children }));
@@ -3,11 +3,11 import { isPlainObject, DojoNodePosition
3 export abstract class RenditionBase<TNode extends Node> implements Rendition<TNode> {
3 export abstract class RenditionBase<TNode extends Node> implements Rendition<TNode> {
4 private _attrs = {};
4 private _attrs = {};
5
5
6 private _children = new Array();
6 private _children: unknown[] = [];
7
7
8 private _created: boolean = false;
8 private _created = false;
9
9
10 visitNext(v: any) {
10 visitNext(v: unknown) {
11 if (this._created)
11 if (this._created)
12 throw new Error("The Element is already created");
12 throw new Error("The Element is already created");
13
13
@@ -30,7 +30,7 export class Scope implements IDestroyab
30 } catch {
30 } catch {
31 // guard
31 // guard
32 }
32 }
33 }
33 };
34
34
35 this._cleanup.forEach(guard);
35 this._cleanup.forEach(guard);
36 this._cleanup.length = 0;
36 this._cleanup.length = 0;
@@ -49,10 +49,10 export interface WatchForRenditionAttrs<
49 component: (arg: T, index: number) => unknown;
49 component: (arg: T, index: number) => unknown;
50 }
50 }
51
51
52 const isObservable = <T>(v: PromiseLike<ArrayLike<T>> | ArrayLike<T>): v is ArrayLike<T> & ObservableResults<T> =>
52 const isObservable = <T>(v: ArrayLike<T>): v is ArrayLike<T> & ObservableResults<T> =>
53 v && (typeof (v as any).observe === "function");
53 v && (typeof (v as { observe?: unknown; }).observe === "function");
54
54
55 const noop = () => {};
55 const noop = () => { };
56
56
57 const fadeIn = (nodes: Node[]) => Promise.all(nodes
57 const fadeIn = (nodes: Node[]) => Promise.all(nodes
58 .filter(isElementNode)
58 .filter(isElementNode)
@@ -112,7 +112,7 export class WatchForRendition<T> extend
112 if (isSubsribable<QueryResultUpdate<T>>(result)) {
112 if (isSubsribable<QueryResultUpdate<T>>(result)) {
113 let animate = false;
113 let animate = false;
114 const subscription = result.subscribe({
114 const subscription = result.subscribe({
115 next: ({item, prevIndex, newIndex}) => this._onItemUpdated({ item, prevIndex, newIndex, animate })
115 next: ({ item, prevIndex, newIndex }) => this._onItemUpdated({ item, prevIndex, newIndex, animate })
116 });
116 });
117 scope.own(subscription);
117 scope.own(subscription);
118 animate = this._animate;
118 animate = this._animate;
@@ -127,7 +127,7 export class WatchForRendition<T> extend
127 this._ct = new Cancellation(cancel => scope.own(cancel));
127 this._ct = new Cancellation(cancel => scope.own(cancel));
128 }
128 }
129
129
130 private _onItemUpdated = (item: RenderTask<T>) => {
130 private readonly _onItemUpdated = (item: RenderTask<T>) => {
131 if (!this._renderTasks.length) {
131 if (!this._renderTasks.length) {
132 // schedule a new job
132 // schedule a new job
133 this._renderTasks.push(item);
133 this._renderTasks.push(item);
@@ -136,7 +136,7 export class WatchForRendition<T> extend
136 // update existing job
136 // update existing job
137 this._renderTasks.push(item);
137 this._renderTasks.push(item);
138 }
138 }
139 }
139 };
140
140
141 private async _render() {
141 private async _render() {
142 // fork
142 // fork
@@ -149,7 +149,7 export class WatchForRendition<T> extend
149 this._renderTasks.length = 0;
149 this._renderTasks.length = 0;
150 }
150 }
151
151
152 _onRenderItem = ({ item, newIndex, prevIndex, animate: _animate }: RenderTask<T>) => {
152 private readonly _onRenderItem = ({ item, newIndex, prevIndex, animate: _animate }: RenderTask<T>) => {
153 const animate = _animate && prevIndex !== newIndex;
153 const animate = _animate && prevIndex !== newIndex;
154
154
155 if (prevIndex > -1) {
155 if (prevIndex > -1) {
@@ -205,7 +205,7 export class WatchForRendition<T> extend
205 if (animate)
205 if (animate)
206 this._animateIn(nodes).catch(e => trace.error(e));
206 this._animateIn(nodes).catch(e => trace.error(e));
207 }
207 }
208 }
208 };
209
209
210 protected _getDomNode() {
210 protected _getDomNode() {
211 if (!this._node)
211 if (!this._node)
@@ -17,7 +17,7 export interface _Widget {
17 addChild?(widget: unknown, index?: number): void;
17 addChild?(widget: unknown, index?: number): void;
18 }
18 }
19
19
20 export type _WidgetCtor = new (attrs: {}, srcNode?: string | Node) => _Widget;
20 export type _WidgetCtor = new (attrs: object, srcNode?: string | Node) => _Widget;
21
21
22 export class WidgetRendition extends RenditionBase<Node> {
22 export class WidgetRendition extends RenditionBase<Node> {
23 readonly widgetClass: _WidgetCtor;
23 readonly widgetClass: _WidgetCtor;
@@ -14,11 +14,11 interface Context {
14
14
15 let _context: Context = {
15 let _context: Context = {
16 scope: Scope.dummy
16 scope: Scope.dummy
17 }
17 };
18
18
19 const guard = (cb: () => unknown) => {
19 const guard = (cb: () => unknown) => {
20 try {
20 try {
21 const result = cb()
21 const result = cb();
22 if (isPromise(result)) {
22 if (isPromise(result)) {
23 const warn = (ret: unknown) => trace.error("The callback {0} competed asynchronously. result = {1}", cb, ret);
23 const warn = (ret: unknown) => trace.error("The callback {0} competed asynchronously. result = {1}", cb, ret);
24 result.then(warn, warn);
24 result.then(warn, warn);
@@ -26,7 +26,7 const guard = (cb: () => unknown) => {
26 } catch (e) {
26 } catch (e) {
27 trace.error(e);
27 trace.error(e);
28 }
28 }
29 }
29 };
30
30
31 export const beginRender = (scope: IScope = getScope()) => {
31 export const beginRender = (scope: IScope = getScope()) => {
32 const prev = _context;
32 const prev = _context;
@@ -35,7 +35,7 export const beginRender = (scope: IScop
35 hooks: []
35 hooks: []
36 };
36 };
37 return endRender(prev);
37 return endRender(prev);
38 }
38 };
39
39
40 /**
40 /**
41 * Completes render operation
41 * Completes render operation
@@ -46,7 +46,7 const endRender = (prev: Context) => ()
46 hooks.forEach(guard);
46 hooks.forEach(guard);
47
47
48 _context = prev;
48 _context = prev;
49 }
49 };
50
50
51 export const renderHook = (hook: () => void) => {
51 export const renderHook = (hook: () => void) => {
52 const { hooks } = _context;
52 const { hooks } = _context;
@@ -54,7 +54,7 export const renderHook = (hook: () => v
54 hooks.push(hook);
54 hooks.push(hook);
55 else
55 else
56 guard(hook);
56 guard(hook);
57 }
57 };
58
58
59 export const refHook = <T>(value: T, ref: JSX.Ref<T>) => {
59 export const refHook = <T>(value: T, ref: JSX.Ref<T>) => {
60 const { hooks, scope } = _context;
60 const { hooks, scope } = _context;
@@ -64,7 +64,7 export const refHook = <T>(value: T, ref
64 guard(() => ref(value));
64 guard(() => ref(value));
65
65
66 scope.own(() => ref(undefined));
66 scope.own(() => ref(undefined));
67 }
67 };
68
68
69 /** Returns the current scope */
69 /** Returns the current scope */
70 export const getScope = () => _context.scope;
70 export const getScope = () => _context.scope;
@@ -80,7 +80,7 export const render = (rendition: unknow
80 } finally {
80 } finally {
81 complete();
81 complete();
82 }
82 }
83 }
83 };
84
84
85 /** Renders DOM element for different types of the argument. */
85 /** Renders DOM element for different types of the argument. */
86 export const getItemDom = (v: unknown) => {
86 export const getItemDom = (v: unknown) => {
@@ -107,6 +107,6 export const getItemDom = (v: unknown) =
107 return fragment;
107 return fragment;
108 } else {
108 } else {
109 // bug: explicit error otherwise
109 // bug: explicit error otherwise
110 throw new Error("Invalid parameter: " + v);
110 throw new Error(`Invalid parameter: ${String(v)}`);
111 }
111 }
112 }
112 };
@@ -1,81 +1,89
1 // eslint-disable-next-line @typescript-eslint/triple-slash-reference
1 /// <reference path="./css-plugin.d.ts"/>
2 /// <reference path="./css-plugin.d.ts"/>
2
3
3 declare namespace JSX {
4 import { Rendition } from "./tsx/traits";
4
5 type Ref<T> = ((value: T | undefined) => void);
6
5
7 interface DjxIntrinsicAttributes<E> {
6 declare global {
8 /** alias for className */
7 namespace JSX {
9 class: string;
8
9 type Ref<T> = ((value: T | undefined) => void);
10
11 type Element = Rendition;
10
12
11 /** specifies the name of the property in the widget where the the
13 interface DjxIntrinsicAttributes<E> {
12 * reference to the current object will be stored
14 /** alias for className */
13 */
15 class?: string;
14 "data-dojo-attach-point": string;
15
16
16 /** specifies handlers map for the events */
17 /** specifies the name of the property in the widget where the the
17 "data-dojo-attach-event": string;
18 * reference to the current object will be stored
19 */
20 "data-dojo-attach-point"?: string;
18
21
19 ref: Ref<E>;
22 /** specifies handlers map for the events */
23 "data-dojo-attach-event"?: string;
20
24
21 /** @deprecated */
25 ref?: Ref<E>;
22 [attr: string]: any;
23 }
24
26
25 interface DjxIntrinsicElements {
27 /** @deprecated */
26 }
28 [attr: string]: unknown;
29 }
27
30
28 type RecursivePartial<T> = T extends string | number | boolean | null | undefined | Function ?
31 // eslint-disable-next-line @typescript-eslint/no-empty-interface
29 T :
32 interface DjxIntrinsicElements {
30 { [k in keyof T]?: RecursivePartial<T[k]> };
33 }
34
35 type RecursivePartial<T> = T extends string | number | boolean | null | undefined | ((...args: unknown[]) => unknown) ?
36 T :
37 { [k in keyof T]?: RecursivePartial<T[k]> };
31
38
32 type MatchingMemberKeys<T, U> = {
39 type MatchingMemberKeys<T, U> = {
33 [K in keyof T]: T[K] extends U ? K : never;
40 [K in keyof T]: T[K] extends U ? K : never;
34 }[keyof T];
41 }[keyof T];
35 type NotMatchingMemberKeys<T, U> = {
42 type NotMatchingMemberKeys<T, U> = {
36 [K in keyof T]: T[K] extends U ? never : K;
43 [K in keyof T]: T[K] extends U ? never : K;
37 }[keyof T];
44 }[keyof T];
38
45
39 type ExtractMembers<T, U> = Pick<T, MatchingMemberKeys<T, U>>;
46 type ExtractMembers<T, U> = Pick<T, MatchingMemberKeys<T, U>>;
40
47
41 type ExcludeMembers<T, U> = Pick<T, NotMatchingMemberKeys<T, U>>;
48 type ExcludeMembers<T, U> = Pick<T, NotMatchingMemberKeys<T, U>>;
42
49
43 type ElementAttrNames<E> = NotMatchingMemberKeys<E, (...args: any[]) => any>;
50 type ElementAttrNames<E> = NotMatchingMemberKeys<E, (...args: unknown[]) => unknown>;
44
51
45 type ElementAttrType<E, K extends keyof any> = K extends keyof E ? RecursivePartial<E[K]> : string;
52 type ElementAttrType<E, K extends string | symbol> = K extends keyof E ? RecursivePartial<E[K]> : string;
46
53
47
54
48 type ElementAttrNamesBlacklist = "children" | "getRootNode" | keyof EventTarget;
55 type ElementAttrNamesBlacklist = "children" | "getRootNode" | keyof EventTarget;
49
56
50 /** This type extracts keys of the specified parameter E by the following rule:
57 /** This type extracts keys of the specified parameter E by the following rule:
51 * 1. skips all ElementAttrNamesBlacklist
58 * 1. skips all ElementAttrNamesBlacklist
52 * 2. skips all methods except with the signature of event handlers
59 * 2. skips all methods except with the signature of event handlers
53 */
60 */
54 type AssignableElementAttrNames<E> = {
61 type AssignableElementAttrNames<E> = {
55 [K in keyof E]: K extends ElementAttrNamesBlacklist ? never :
62 [K in keyof E]: K extends ElementAttrNamesBlacklist ? never :
56 ((evt: Event) => any) extends E[K] ? K :
63 ((evt: Event) => unknown) extends E[K] ? K :
57 E[K] extends ((...args: any[]) => any) ? never :
64 E[K] extends ((...args: unknown[]) => unknown) ? never :
58 K;
65 K;
59 }[keyof E];
66 }[keyof E];
60
67
61 type LaxElement<E extends object> =
68 type LaxElement<E extends object> =
62 Pick<E, AssignableElementAttrNames<E>> &
69 RecursivePartial<Pick<E, AssignableElementAttrNames<E>>> &
63 DjxIntrinsicAttributes<E>;
70 DjxIntrinsicAttributes<E>;
64
71
65 type LaxIntrinsicElementsMap = {
72 type LaxIntrinsicElementsMap = {
66 [tag in keyof HTMLElementTagNameMap]: LaxElement<HTMLElementTagNameMap[tag]>
73 [tag in keyof HTMLElementTagNameMap]: LaxElement<HTMLElementTagNameMap[tag]>
67 } & DjxIntrinsicElements;
74 } & DjxIntrinsicElements;
68
75
69 type IntrinsicElements = {
76 type IntrinsicElements = {
70 [tag in keyof LaxIntrinsicElementsMap]: RecursivePartial<LaxIntrinsicElementsMap[tag]>;
77 [tag in keyof LaxIntrinsicElementsMap]: LaxIntrinsicElementsMap[tag];
71 }
78 };
72
79
73 interface ElementChildrenAttribute {
80 interface ElementChildrenAttribute {
74 children: {};
81 children: unknown;
75 }
82 }
76
83
77 interface IntrinsicClassAttributes<T> {
84 interface IntrinsicClassAttributes<T> {
78 ref?: (value: T) => void;
85 ref?: Ref<T>;
79 children?: unknown;
86 children?: unknown;
87 }
80 }
88 }
81 }
89 } No newline at end of file
@@ -2,6 +2,7 import { djbase, djclass, bind, prototyp
2
2
3 import { DjxWidgetBase } from "../tsx/DjxWidgetBase";
3 import { DjxWidgetBase } from "../tsx/DjxWidgetBase";
4 import { createElement, on } from "../tsx";
4 import { createElement, on } from "../tsx";
5 import { argumentNotNull } from "@implab/core-amd/safe";
5
6
6 interface MyWidgetAttrs {
7 interface MyWidgetAttrs {
7 title: string;
8 title: string;
@@ -19,6 +20,12 interface MyWidgetEvents {
19 };
20 };
20 }
21 }
21
22
23 interface FrameProps {
24 ref?: JSX.Ref<HTMLDivElement>;
25 children?: unknown[];
26 }
27
28 const Frame = ({children, ref}: FrameProps) => <div ref={ref} >{children}</div>;
22
29
23 @djclass
30 @djclass
24 export class MyWidget extends djbase(DjxWidgetBase as AbstractConstructor<DjxWidgetBase<MyWidgetAttrs, MyWidgetEvents>>) {
31 export class MyWidget extends djbase(DjxWidgetBase as AbstractConstructor<DjxWidgetBase<MyWidgetAttrs, MyWidgetEvents>>) {
@@ -29,31 +36,40 export class MyWidget extends djbase(Djx
29 @prototype(0)
36 @prototype(0)
30 counter = 0;
37 counter = 0;
31
38
39 frameNode?: HTMLDivElement;
40
32 render() {
41 render() {
33 const Frame = ({children, ref}: {ref: JSX.Ref<HTMLDivElement>, children: unknown[]}) => <div ref={ref} >{children}</div>;
42
34 return <div className="myWidget" onsubmit={e => this._onSubmit(e)} tabIndex={3} style={{ alignContent: "center", border: "1px solid" }} >
43 return <div className="myWidget" onsubmit={this._onSubmit} tabIndex={3} style={{ alignContent: "center", border: "1px solid" }} >
35 <h1 data-dojo-attach-point="titleNode"></h1>
44 <h1 data-dojo-attach-point="titleNode"></h1>
36 <Frame ref={ v => {}}>
45 <Frame ref={this._setFrameElement}>
37 <span class="up-button" onclick={e => this._onIncClick(e)}>[+]</span>
46 <span class="up-button" onclick={this._onIncClick}>[+]</span>
38 <span class="down-button" onclick={() => this._onDecClick()}>[-]</span>
47 <span class="down-button" onclick={() => this._onDecClick()}>[-]</span>
39 </Frame>
48 </Frame>
40 </div>;
49 </div>;
41 }
50 }
42
51
52 private readonly _setFrameElement = (node?: HTMLDivElement) => {
53 this.frameNode = node;
54 };
55
43 postCreate() {
56 postCreate() {
44 super.postCreate();
57 super.postCreate();
45
58
46 this.on("click", () => {});
59 this.on("click", () => {});
47 }
60 }
48
61
49 _onSubmit(e: Event) {
62 private readonly _onSubmit = (evt: Event) => {
50 }
63 argumentNotNull(evt, "evt");
64 };
51
65
52 _onIncClick(e: MouseEvent) {
66 private readonly _onIncClick = (evt: MouseEvent) => {
67 argumentNotNull(evt, "evt");
68
53 this.set("counter", this.counter + 1);
69 this.set("counter", this.counter + 1);
54
70
55 this.emit("count-inc", { bubbles: false });
71 this.emit("count-inc", { bubbles: false });
56 }
72 };
57
73
58 _onDecClick() {
74 _onDecClick() {
59 this.emit("count-dec", { bubbles: false, detail: this.counter });
75 this.emit("count-dec", { bubbles: false, detail: this.counter });
@@ -61,10 +77,11 export class MyWidget extends djbase(Djx
61
77
62 @on("count-inc")
78 @on("count-inc")
63 private _onCounterInc(evt: Event & { detail: number; x?: number; }) {
79 private _onCounterInc(evt: Event & { detail: number; x?: number; }) {
80 argumentNotNull(evt, "evt");
64 }
81 }
65
82
66 @on("click", "keydown")
83 @on("click", "keydown")
67 protected _onClick(event: MouseEvent | KeyboardEvent) {
84 protected _onClick(evt: MouseEvent | KeyboardEvent) {
68
85 argumentNotNull(evt, "evt");
69 }
86 }
70 } No newline at end of file
87 }
@@ -1,6 +1,7
1 {
1 {
2 "extends": "../tsconfig",
2 "extends": "../tsconfig",
3 "compilerOptions": {
3 "compilerOptions": {
4 "baseUrl": ".",
4 "noUnusedLocals": false,
5 "noUnusedLocals": false,
5 //"rootDir": "ts",
6 //"rootDir": "ts",
6 "rootDirs": [
7 "rootDirs": [
@@ -9,6 +10,11
9 "../main/ts",
10 "../main/ts",
10 "../main/typings"
11 "../main/typings"
11 ],
12 ],
12 "types": ["requirejs", "../main/typings", "@implab/dojo-typings"]
13 "types": [
14 "requirejs",
15 "../main/typings",
16 "@implab/dojo-typings",
17 "@implab/dojo-typings/dojo/NodeList-fx"
18 ]
13 }
19 }
14 } No newline at end of file
20 }
@@ -1,10 +1,9
1 {
1 {
2 "extends": "./tsconfig.json",
2 //"extends": "./tsconfig.json",
3 "compilerOptions": {
3 "compilerOptions": {
4 // ensure that nobody can accidentally use this config for a build
4 // ensure that nobody can accidentally use this config for a build
5 "noEmit": true
5 "noEmit": true,
6 },
6 },
7 "include": [
7 "include": [
8 "ts"
9 ]
8 ]
10 } No newline at end of file
9 }
@@ -1,7 +1,7
1 import MainWidget from "./view/MainWidget";
1 import MainWidget from "./view/MainWidget";
2 import "@implab/djx/css!dojo/resources/dojo.css"
2 import "@implab/djx/css!dojo/resources/dojo.css";
3 import "@implab/djx/css!dijit/themes/dijit.css"
3 import "@implab/djx/css!dijit/themes/dijit.css";
4 import "@implab/djx/css!dijit/themes/tundra/tundra.css"
4 import "@implab/djx/css!dijit/themes/tundra/tundra.css";
5
5
6 const w = new MainWidget();
6 const w = new MainWidget();
7 w.placeAt(document.body); No newline at end of file
7 w.placeAt(document.body);
@@ -5,6 +5,7 import { Contact } from "./Contact";
5 import { Uuid } from "@implab/core-amd/Uuid";
5 import { Uuid } from "@implab/core-amd/Uuid";
6 import { Observable as RxjsObservable } from "rxjs";
6 import { Observable as RxjsObservable } from "rxjs";
7 import { QueryResultUpdate } from "@implab/djx/tsx";
7 import { QueryResultUpdate } from "@implab/djx/tsx";
8 import {isPromise} from "@implab/core-amd/safe";
8
9
9 type AppointmentRecord = Omit<Appointment, "getMembers"> & {id: string};
10 type AppointmentRecord = Omit<Appointment, "getMembers"> & {id: string};
10
11
@@ -22,13 +23,13 export interface ObservableResults<T> {
22 }
23 }
23
24
24
25
25 export function isObservable<T>(v: PromiseLike<ArrayLike<T>> | ArrayLike<T>): v is ArrayLike<T> & ObservableResults<T> {
26 export function isObservable<T>(v: unknown): v is ObservableResults<T> {
26 return v && (typeof (v as any).observe === "function");
27 return !!v && (typeof (v as {observe?: unknown}).observe === "function");
27 }
28 }
28
29
29 export function observe<T>(results: T[], includeObjectUpdates?: boolean): RxjsObservable<QueryResultUpdate<T>>;
30 export function observe<T>(results: T[], includeObjectUpdates?: boolean): RxjsObservable<QueryResultUpdate<T>>;
30 export function observe<T>(results: PromiseLike<T[]>, includeObjectUpdates?: boolean): PromiseLike<RxjsObservable<QueryResultUpdate<T>>>;
31 export function observe<T>(results: PromiseLike<T[]>, includeObjectUpdates?: boolean): PromiseLike<RxjsObservable<QueryResultUpdate<T>>>;
31 export function observe(results: any, includeObjectUpdates = true) {
32 export function observe(results: unknown[] | PromiseLike<unknown[]>, includeObjectUpdates = true) {
32 // results может быть асинхронным, т.е. до завершения
33 // results может быть асинхронным, т.е. до завершения
33 // получения результатов store может быть обновлен. В любом
34 // получения результатов store может быть обновлен. В любом
34 // случае, если между подключением хотя бы одного наблюдателя
35 // случае, если между подключением хотя бы одного наблюдателя
@@ -41,7 +42,7 export function observe(results: any, in
41 // о необработанной ошибке в Promise при обращении к методам
42 // о необработанной ошибке в Promise при обращении к методам
42 // обновления (add,put,remove)
43 // обновления (add,put,remove)
43
44
44 const _subscribe = (items: any[]) => new RxjsObservable<QueryResultUpdate<any>>(subscriber => {
45 const _subscribe = (items: unknown[]) => new RxjsObservable<QueryResultUpdate<unknown>>(subscriber => {
45 items
46 items
46 .forEach((value, newIndex) => subscriber.next({ item: value, newIndex, prevIndex: -1}));
47 .forEach((value, newIndex) => subscriber.next({ item: value, newIndex, prevIndex: -1}));
47
48
@@ -72,11 +73,11 export function observe(results: any, in
72
73
73
74
74 export class MainContext {
75 export class MainContext {
75 private _appointments = new Observable(new Memory<AppointmentRecord>());
76 private readonly _appointments = new Observable(new Memory<AppointmentRecord>());
76
77
77 private _contacts = new Observable(new Memory<ContactRecord>());
78 private readonly _contacts = new Observable(new Memory<ContactRecord>());
78
79
79 private _members = new Observable(new Memory<MemberRecord>());
80 private readonly _members = new Observable(new Memory<MemberRecord>());
80
81
81 createAppointment(title: string, startAt: Date, duration: number, members: Member[]) {
82 createAppointment(title: string, startAt: Date, duration: number, members: Member[]) {
82 const id = Uuid();
83 const id = Uuid();
@@ -91,16 +92,16 export class MainContext {
91 this._members.add({
92 this._members.add({
92 appointmentId: id,
93 appointmentId: id,
93 ...member
94 ...member
94 }, {id: Uuid()})
95 }, {id: Uuid()}) as void
95 );
96 );
96 }
97 }
97
98
98 queryAppointments(dateFrom: Date, dateTo: Date) {
99 queryAppointments(dateFrom: Date, dateTo: Date) {
99 this._appointments.query().map()
100 //this._appointments.query().map()
100 }
101 }
101
102
102 private _mapAppointment = ({startAt, title, duration, id}: AppointmentRecord) => ({
103 private readonly _mapAppointment = ({startAt, title, duration, id}: AppointmentRecord) => ({
103
104
104 })
105 });
105
106
106 }
107 }
@@ -5,6 +5,8 import ProgressBar from "./ProgressBar";
5 import Button = require("dijit/form/Button");
5 import Button = require("dijit/form/Button");
6 import { interval } from "rxjs";
6 import { interval } from "rxjs";
7
7
8 const Counter = ({ children }: { children: unknown[] }) => <span>Counter: {children}</span>;
9
8 @djclass
10 @djclass
9 export default class MainWidget extends djbase(DjxWidgetBase) {
11 export default class MainWidget extends djbase(DjxWidgetBase) {
10
12
@@ -21,7 +23,6 export default class MainWidget extends
21 paused = false;
23 paused = false;
22
24
23 render() {
25 render() {
24 const Counter = ({ children }: { children: unknown[] }) => <span>Counter: {children}</span>;
25
26
26 return <div className="tundra">
27 return <div className="tundra">
27 <h2 ref={attach(this, "titleNode")}>Hi!</h2>
28 <h2 ref={attach(this, "titleNode")}>Hi!</h2>
@@ -31,7 +32,6 export default class MainWidget extends
31 <Counter><input ref={all(
32 <Counter><input ref={all(
32 bind("value", prop(this, "count")
33 bind("value", prop(this, "count")
33 .map(x => x/10)
34 .map(x => x/10)
34 .map(String)
35 ),
35 ),
36 attach(this, "counterNode")
36 attach(this, "counterNode")
37 )} /> <span>s</span></Counter>,
37 )} /> <span>s</span></Counter>,
@@ -71,11 +71,11 export default class MainWidget extends
71 });
71 });
72 }
72 }
73
73
74 private _onPauseClick = () => {
74 private readonly _onPauseClick = () => {
75 this.set("paused", !this.paused);
75 this.set("paused", !this.paused);
76 }
76 };
77
77
78 private _onToggleCounterClick = () => {
78 private readonly _onToggleCounterClick = () => {
79 this.set("showCounter", !this.showCounter);
79 this.set("showCounter", !this.showCounter);
80 }
80 };
81 }
81 }
@@ -0,0 +1,1
1 /* noop */ No newline at end of file
@@ -5,6 +5,5
5 "noEmit": true
5 "noEmit": true
6 },
6 },
7 "include": [
7 "include": [
8 "ts"
9 ]
8 ]
10 } No newline at end of file
9 }
@@ -1,35 +0,0
1 {
2 "root": true,
3 "extends": [
4 "plugin:react/recommended",
5 "eslint:recommended",
6 "plugin:@typescript-eslint/eslint-recommended",
7 "plugin:@typescript-eslint/recommended",
8 "plugin:@typescript-eslint/recommended-requiring-type-checking"
9 ],
10 "parser": "@typescript-eslint/parser",
11 "parserOptions": {
12 "ecmaFeatures": {
13 "jsx": true
14 },
15 "ecmaVersion": 5,
16 "tsconfigRootDir": "djx/src",
17 "project": ["tsconfig.eslint.json", "*/tsconfig.json"]
18 },
19 "plugins": [
20 "@typescript-eslint"
21 ],
22 "rules": {
23 "react/react-in-jsx-scope": "off",
24 "react/no-unknown-property": "off",
25 "@typescript-eslint/no-empty-function": "off",
26 "max-classes-per-file": [
27 "error",
28 { "ignoreExpressions": true, "max": 1 }
29 ],
30 "@typescript-eslint/prefer-readonly": ["error"],
31 "semi": "off",
32 "@typescript-eslint/semi": ["error"]
33
34 }
35 }
@@ -1,9 +0,0
1 import { bundle } from "../i18n";
2
3 export default bundle({
4 greeting: (name: string) => `Hello, ${name}!`,
5 goodbye: (name: string) => `Bye, ${name}!`
6 }, {
7 ru: () => import("./ru/foo")
8 });
9
@@ -1,6 +0,0
1 import foo from "../foo";
2
3 export default foo.define({
4 greeting: (name: string) => `Привет, ${name}`,
5 goodbye: (name: string) => `Пока, ${name}`
6 });
@@ -1,33 +0,0
1 {
2 "root": true,
3 "extends": [
4 "plugin:react/recommended",
5 "eslint:recommended",
6 "plugin:@typescript-eslint/eslint-recommended",
7 "plugin:@typescript-eslint/recommended",
8 "plugin:@typescript-eslint/recommended-requiring-type-checking"
9 ],
10 "parser": "@typescript-eslint/parser",
11 "parserOptions": {
12 "ecmaFeatures": {
13 "jsx": true
14 },
15 "ecmaVersion": 5,
16 "tsconfigRootDir": "src",
17 "project": ["tsconfig.eslint.json", "*/tsconfig.json"]
18 },
19 "plugins": [
20 "@typescript-eslint"
21 ],
22 "rules": {
23 "@typescript-eslint/no-empty-function": "off",
24 "max-classes-per-file": [
25 "error",
26 { "ignoreExpressions": true, "max": 1 }
27 ],
28 "@typescript-eslint/prefer-readonly": ["error"],
29 "semi": "off",
30 "@typescript-eslint/semi": ["error"]
31
32 }
33 }
General Comments 0
You need to be logged in to leave comments. Login now