| @@ -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 | } | |||
| @@ -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. | 
        
             | 
        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. | 
        
             | 
        461 | "version": "1.0.3", | |
| 462 | 
            
                        "resolved": "https://registry.npmjs.org/@implab/dojo-typings/-/dojo-typings-1.0. | 
        
             | 
        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. | 
        
             | 
        7033 | "version": "1.0.3", | |
| 7034 | 
            
                        "resolved": "https://registry.npmjs.org/@implab/dojo-typings/-/dojo-typings-1.0. | 
        
             | 
        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. | 
        
             | 
        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:  | 
        
             | 
        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?:  | 
        
             | 
        4 | (result?: unknown): void; | |
| 5 | 
            
                error(err:  | 
        
             | 
        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 | 
        
             | 
        140 | const proxy = (m: (...args: unknown[]) => unknown) => function (this: dojo._base.DeclareCreatedObject) { | |
| 141 | 
            
                        const f = this.getInherited({ callee: m | 
        
             | 
        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:  | 
        
             | 
        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 | 
            
                        } | 
        
             | 
        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]) =>  | 
        
             | 
        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 ( | 
        
             | 
        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 ( | 
        
             | 
        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?:  | 
        
             | 
        13 | (result?: unknown): void; | |
| 14 | 
            
                error(err:  | 
        
             | 
        14 | error(err: unknown): void; | |
| 15 | } | 
             | 
        15 | } | |
| 16 | 
             | 
        16 | |||
| 17 | 
            
            export function bundle<T extends object>(nls: T, locales?: MapOf< | 
        
             | 
        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:  | 
        
             | 
        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:  | 
        
             | 
        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:  | 
        
             | 
        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 =  | 
        
             | 
        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 =  | 
        
             | 
        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]) =>  | 
        
             | 
        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]) =>  | 
        
             | 
        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 | 
        
             | 
        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  | 
        
             | 
        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< | 
        
             | 
        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 | 
            
                ) | 
        
             | 
        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:  | 
        
             | 
        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 | 
        
             | 
        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) =>  | 
        
             | 
        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?:  | 
        
             | 
        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  | 
        
             | 
        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:  | 
        
             | 
        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:  | 
        
             | 
        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:  | 
        
             | 
        17 | protected _create(attrs: object, children: unknown[]) { | |
| 18 | 
            
                    const _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 =  | 
        
             | 
        6 | private _children: unknown[] = []; | |
| 7 | 
             | 
        7 | |||
| 8 | 
            
                private _created | 
        
             | 
        8 | private _created = false; | |
| 9 | 
             | 
        9 | |||
| 10 | 
            
                visitNext(v:  | 
        
             | 
        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:  | 
        
             | 
        52 | const isObservable = <T>(v: ArrayLike<T>): v is ArrayLike<T> & ObservableResults<T> => | |
| 53 | 
            
                v && (typeof (v as  | 
        
             | 
        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:  | 
        
             | 
        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 | 
            
             | 
        
             | 
        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 | 
            
             | 
        
             | 
        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( | 
        
             | 
        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:  | 
        
             | 
        50 | type ElementAttrNames<E> = NotMatchingMemberKeys<E, (...args: unknown[]) => unknown>; | |
| 44 | 
             | 
        51 | |||
| 45 | 
            
                type ElementAttrType<E, K extends  | 
        
             | 
        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) =>  | 
        
             | 
        63 | ((evt: Event) => unknown) extends E[K] ? K : | |
| 57 | 
            
                        E[K] extends ((...args:  | 
        
             | 
        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]:  | 
        
             | 
        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? | 
        
             | 
        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 | 
            
             | 
        
             | 
        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={ | 
        
             | 
        45 | <Frame ref={this._setFrameElement}> | |
| 37 | 
            
                            <span class="up-button" onclick={ | 
        
             | 
        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(ev | 
        
             | 
        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:  | 
        
             | 
        26 | export function isObservable<T>(v: unknown): v is ObservableResults<T> { | |
| 26 | 
            
                return v && (typeof (v as  | 
        
             | 
        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:  | 
        
             | 
        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:  | 
        
             | 
        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 | NO CONTENT: file was removed | 
             | 
        NO CONTENT: file was removed | 
| 1 | NO CONTENT: file was removed | 
             | 
        NO CONTENT: file was removed | 
| 1 | NO CONTENT: file was removed | 
             | 
        NO CONTENT: file was removed | 
| 1 | NO CONTENT: file was removed | 
             | 
        NO CONTENT: file was removed | 
        
        General Comments 0
    
    
  
  
                      You need to be logged in to leave comments.
                      Login now
                    
                