##// END OF EJS Templates
Слияние
cin -
r92:43e5b8181346 merge default
parent child
Show More
@@ -0,0 +1,25
1 {
2 "env": {
3 "browser": true,
4 "amd": true
5 },
6 "parserOptions": {
7 "ecmaFeatures": {
8 "jsx": true
9 },
10 "sourceType": "script"
11 },
12 "extends": "eslint:recommended",
13 "rules": {
14 "no-const-assign": "warn",
15 "no-this-before-super": "warn",
16 "no-undef": "error",
17 "no-unreachable": "warn",
18 "no-unused-vars": "warn",
19 "constructor-super": "warn",
20 "valid-typeof": "warn",
21 "semi" : "warn",
22 "no-invalid-this" : "error",
23 "no-console": "off"
24 }
25 } No newline at end of file
@@ -0,0 +1,48
1 {
2 "extends": "tslint:recommended",
3 "defaultSeverity": "warn",
4 "rules": {
5 "align": [
6 true,
7 "parameters",
8 "statements"
9 ],
10 "interface-name": [
11 false
12 ],
13 "max-line-length": [
14 true,
15 185
16 ],
17 "quotemark": [true, "double", "avoid-escape"],
18 "member-access": false,
19 "semicolon": [true, "always", "ignore-bound-class-methods"],
20 "no-bitwise": false,
21 "no-empty": false,
22 "no-namespace": false,
23 "ordered-imports": false,
24 "no-return-await": true,
25 "no-floating-promises": true,
26 "one-line": [
27 true,
28 "check-open-brace",
29 "check-catch",
30 "check-whitespace"
31 ],
32 "object-literal-sort-keys": false,
33 "trailing-comma": [
34 true,
35 {
36 "singleline": "never",
37 "multiline": "never"
38 }
39 ],
40 "variable-name": false,
41 "curly": false,
42 "array-type": false,
43 "arrow-parens": [
44 true,
45 "ban-single-arg-parens"
46 ]
47 }
48 } No newline at end of file
@@ -25,3 +25,12 d4f0cdae9577caa605d9317d0ceb93f7b67895f3
25 25 1a0018655d1c3dafc16ae50971cb535b8555e246 v1.1.0
26 26 ff3695b0a48f00155ad6c3d7e000fe185ee6f95a v1.1.1
27 27 c276b9b7fa833242d1bf75eeeaae9924feee51e8 v1.1.2
28 fdde09e66c009f4950ec69a393a8e789725da758 v1.2.0
29 16678c6055f20ce1a49bdca5e6dabce88ee8deed v1.2.1
30 bc7556143fe536e3df374bc0070146311884284e v1.2.2
31 e5bb5e80ce96fc4ca0fbbf0b5390443a616e99fa v1.2.3
32 cc5be30e84f8a0d9a8e25447651576d9e46ab154 v1.2.4
33 2807ab11174c7446830d91d5f1b652a18c6ecae5 v1.2.5
34 35a7b6319ebe24973fe10b8d82c19d3d86857b4e v1.2.6
35 70058deb750dc18fcd9be83c28cb8371530fffd8 v1.2.7
36 367f8caa5bf8fd2d4a56a6cff40be31ab82a2727 v1.2.8
@@ -13,6 +13,7 typescript {
13 13 module = "amd"
14 14 it.target = "es5"
15 15 experimentalDecorators = true
16 noUnusedLocals = true
16 17 jsx = "react"
17 18 jsxFactory = "createElement"
18 19 moduleResolution = "node"
@@ -40,7 +41,7 configureTsMain {
40 41 "dojo/*" : [ "typings/dojo/*" ],
41 42 "dijit/*" : [ "typings/dijit/*" ]
42 43 ]*/
43 types = ["requirejs", "dojo-typings"]
44 types = ["requirejs", "@implab/dojo-typings"]
44 45 }
45 46 }
46 47
@@ -10,12 +10,11
10 10 "license": "BSD-2-Clause",
11 11 "devDependencies": {
12 12 "@implab/core-amd": "^1.4.0",
13 "@implab/dojo-typings": "1.0.0",
13 14 "@types/chai": "4.1.3",
14 15 "@types/requirejs": "2.1.31",
15 16 "@types/yaml": "1.2.0",
16 "chai": "4.2.0",
17 17 "dojo": "1.16.0",
18 "dojo-typings": "~1.11.9",
19 18 "eslint": "6.8.0",
20 19 "requirejs": "2.3.6",
21 20 "tslint": "^6.1.3",
@@ -62,6 +61,12
62 61 "integrity": "sha512-gaJX1mhri7YpmXDTAYELZnmTznzXYpk2AI7Decsttdi6xY+bqGgH24q0AFcKrx8RY2jfsFXxDdf0fITz2HpBbw==",
63 62 "dev": true
64 63 },
64 "node_modules/@implab/dojo-typings": {
65 "version": "1.0.0",
66 "resolved": "https://registry.npmjs.org/@implab/dojo-typings/-/dojo-typings-1.0.0.tgz",
67 "integrity": "sha512-B2kvlKJgvyIQAl/k1pVyNmtp4ADvBDCs4Lw/qfBC+Sz/ft4c7EuRXmN/+2dhWrd6A5SMjEgex5oeq6Ja2ntrig==",
68 "dev": true
69 },
65 70 "node_modules/@types/chai": {
66 71 "version": "4.1.3",
67 72 "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.1.3.tgz",
@@ -152,15 +157,6
152 157 "sprintf-js": "~1.0.2"
153 158 }
154 159 },
155 "node_modules/assertion-error": {
156 "version": "1.1.0",
157 "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz",
158 "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==",
159 "dev": true,
160 "engines": {
161 "node": "*"
162 }
163 },
164 160 "node_modules/astral-regex": {
165 161 "version": "1.0.0",
166 162 "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz",
@@ -204,23 +200,6
204 200 "node": ">=6"
205 201 }
206 202 },
207 "node_modules/chai": {
208 "version": "4.2.0",
209 "resolved": "https://registry.npmjs.org/chai/-/chai-4.2.0.tgz",
210 "integrity": "sha512-XQU3bhBukrOsQCuwZndwGcCVQHyZi53fQ6Ys1Fym7E4olpIqqZZhhoFJoaKVvV17lWQoXYwgWN2nF5crA8J2jw==",
211 "dev": true,
212 "dependencies": {
213 "assertion-error": "^1.1.0",
214 "check-error": "^1.0.2",
215 "deep-eql": "^3.0.1",
216 "get-func-name": "^2.0.0",
217 "pathval": "^1.1.0",
218 "type-detect": "^4.0.5"
219 },
220 "engines": {
221 "node": ">=4"
222 }
223 },
224 203 "node_modules/chalk": {
225 204 "version": "2.4.2",
226 205 "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
@@ -241,15 +220,6
241 220 "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==",
242 221 "dev": true
243 222 },
244 "node_modules/check-error": {
245 "version": "1.0.2",
246 "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz",
247 "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=",
248 "dev": true,
249 "engines": {
250 "node": "*"
251 }
252 },
253 223 "node_modules/cli-cursor": {
254 224 "version": "3.1.0",
255 225 "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz",
@@ -329,18 +299,6
329 299 "ms": "^2.1.1"
330 300 }
331 301 },
332 "node_modules/deep-eql": {
333 "version": "3.0.1",
334 "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz",
335 "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==",
336 "dev": true,
337 "dependencies": {
338 "type-detect": "^4.0.0"
339 },
340 "engines": {
341 "node": ">=0.12"
342 }
343 },
344 302 "node_modules/deep-is": {
345 303 "version": "0.1.3",
346 304 "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz",
@@ -374,15 +332,6
374 332 "integrity": "sha512-DUiXyoLK6vMF5BPr/qiMLTxDMfiM9qlzN1jxfDsVfuvB/CwhYpNxA/M4mbqKN8PCVGLmccXBJbfmFJPP5+zmzw==",
375 333 "dev": true
376 334 },
377 "node_modules/dojo-typings": {
378 "version": "1.11.9",
379 "resolved": "https://registry.npmjs.org/dojo-typings/-/dojo-typings-1.11.9.tgz",
380 "integrity": "sha512-mh8w+Mau2Y1QfTEszEAdO7j6ycNhYxF/Ing6nAk1eUg6NxjeT0viVHjICMd9sU3U463vM2G+KfBBK5grk3/Mlw==",
381 "dev": true,
382 "dependencies": {
383 "@types/chai": "^4.0.4"
384 }
385 },
386 335 "node_modules/emoji-regex": {
387 336 "version": "8.0.0",
388 337 "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
@@ -640,15 +589,6
640 589 "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=",
641 590 "dev": true
642 591 },
643 "node_modules/get-func-name": {
644 "version": "2.0.0",
645 "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz",
646 "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=",
647 "dev": true,
648 "engines": {
649 "node": "*"
650 }
651 },
652 592 "node_modules/glob": {
653 593 "version": "7.1.6",
654 594 "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz",
@@ -1020,15 +960,6
1020 960 "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==",
1021 961 "dev": true
1022 962 },
1023 "node_modules/pathval": {
1024 "version": "1.1.0",
1025 "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.0.tgz",
1026 "integrity": "sha1-uULm1L3mUwBe9rcTYd74cn0GReA=",
1027 "dev": true,
1028 "engines": {
1029 "node": "*"
1030 }
1031 },
1032 963 "node_modules/prelude-ls": {
1033 964 "version": "1.1.2",
1034 965 "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz",
@@ -1427,15 +1358,6
1427 1358 "node": ">= 0.8.0"
1428 1359 }
1429 1360 },
1430 "node_modules/type-detect": {
1431 "version": "4.0.8",
1432 "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz",
1433 "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==",
1434 "dev": true,
1435 "engines": {
1436 "node": ">=4"
1437 }
1438 },
1439 1361 "node_modules/type-fest": {
1440 1362 "version": "0.8.1",
1441 1363 "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz",
@@ -1561,6 +1483,12
1561 1483 "integrity": "sha512-gaJX1mhri7YpmXDTAYELZnmTznzXYpk2AI7Decsttdi6xY+bqGgH24q0AFcKrx8RY2jfsFXxDdf0fITz2HpBbw==",
1562 1484 "dev": true
1563 1485 },
1486 "@implab/dojo-typings": {
1487 "version": "1.0.0",
1488 "resolved": "https://registry.npmjs.org/@implab/dojo-typings/-/dojo-typings-1.0.0.tgz",
1489 "integrity": "sha512-B2kvlKJgvyIQAl/k1pVyNmtp4ADvBDCs4Lw/qfBC+Sz/ft4c7EuRXmN/+2dhWrd6A5SMjEgex5oeq6Ja2ntrig==",
1490 "dev": true
1491 },
1564 1492 "@types/chai": {
1565 1493 "version": "4.1.3",
1566 1494 "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.1.3.tgz",
@@ -1636,12 +1564,6
1636 1564 "sprintf-js": "~1.0.2"
1637 1565 }
1638 1566 },
1639 "assertion-error": {
1640 "version": "1.1.0",
1641 "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz",
1642 "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==",
1643 "dev": true
1644 },
1645 1567 "astral-regex": {
1646 1568 "version": "1.0.0",
1647 1569 "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz",
@@ -1676,20 +1598,6
1676 1598 "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
1677 1599 "dev": true
1678 1600 },
1679 "chai": {
1680 "version": "4.2.0",
1681 "resolved": "https://registry.npmjs.org/chai/-/chai-4.2.0.tgz",
1682 "integrity": "sha512-XQU3bhBukrOsQCuwZndwGcCVQHyZi53fQ6Ys1Fym7E4olpIqqZZhhoFJoaKVvV17lWQoXYwgWN2nF5crA8J2jw==",
1683 "dev": true,
1684 "requires": {
1685 "assertion-error": "^1.1.0",
1686 "check-error": "^1.0.2",
1687 "deep-eql": "^3.0.1",
1688 "get-func-name": "^2.0.0",
1689 "pathval": "^1.1.0",
1690 "type-detect": "^4.0.5"
1691 }
1692 },
1693 1601 "chalk": {
1694 1602 "version": "2.4.2",
1695 1603 "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
@@ -1707,12 +1615,6
1707 1615 "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==",
1708 1616 "dev": true
1709 1617 },
1710 "check-error": {
1711 "version": "1.0.2",
1712 "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz",
1713 "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=",
1714 "dev": true
1715 },
1716 1618 "cli-cursor": {
1717 1619 "version": "3.1.0",
1718 1620 "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz",
@@ -1785,15 +1687,6
1785 1687 "ms": "^2.1.1"
1786 1688 }
1787 1689 },
1788 "deep-eql": {
1789 "version": "3.0.1",
1790 "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz",
1791 "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==",
1792 "dev": true,
1793 "requires": {
1794 "type-detect": "^4.0.0"
1795 }
1796 },
1797 1690 "deep-is": {
1798 1691 "version": "0.1.3",
1799 1692 "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz",
@@ -1821,15 +1714,6
1821 1714 "integrity": "sha512-DUiXyoLK6vMF5BPr/qiMLTxDMfiM9qlzN1jxfDsVfuvB/CwhYpNxA/M4mbqKN8PCVGLmccXBJbfmFJPP5+zmzw==",
1822 1715 "dev": true
1823 1716 },
1824 "dojo-typings": {
1825 "version": "1.11.9",
1826 "resolved": "https://registry.npmjs.org/dojo-typings/-/dojo-typings-1.11.9.tgz",
1827 "integrity": "sha512-mh8w+Mau2Y1QfTEszEAdO7j6ycNhYxF/Ing6nAk1eUg6NxjeT0viVHjICMd9sU3U463vM2G+KfBBK5grk3/Mlw==",
1828 "dev": true,
1829 "requires": {
1830 "@types/chai": "^4.0.4"
1831 }
1832 },
1833 1717 "emoji-regex": {
1834 1718 "version": "8.0.0",
1835 1719 "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
@@ -2035,12 +1919,6
2035 1919 "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=",
2036 1920 "dev": true
2037 1921 },
2038 "get-func-name": {
2039 "version": "2.0.0",
2040 "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz",
2041 "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=",
2042 "dev": true
2043 },
2044 1922 "glob": {
2045 1923 "version": "7.1.6",
2046 1924 "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz",
@@ -2345,12 +2223,6
2345 2223 "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==",
2346 2224 "dev": true
2347 2225 },
2348 "pathval": {
2349 "version": "1.1.0",
2350 "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.0.tgz",
2351 "integrity": "sha1-uULm1L3mUwBe9rcTYd74cn0GReA=",
2352 "dev": true
2353 },
2354 2226 "prelude-ls": {
2355 2227 "version": "1.1.2",
2356 2228 "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz",
@@ -2668,12 +2540,6
2668 2540 "prelude-ls": "~1.1.2"
2669 2541 }
2670 2542 },
2671 "type-detect": {
2672 "version": "4.0.8",
2673 "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz",
2674 "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==",
2675 "dev": true
2676 },
2677 2543 "type-fest": {
2678 2544 "version": "0.8.1",
2679 2545 "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz",
@@ -23,9 +23,8
23 23 "@types/chai": "4.1.3",
24 24 "@types/requirejs": "2.1.31",
25 25 "@types/yaml": "1.2.0",
26 "chai": "4.2.0",
27 26 "dojo": "1.16.0",
28 "dojo-typings": "~1.11.9",
27 "@implab/dojo-typings": "1.0.0",
29 28 "eslint": "6.8.0",
30 29 "requirejs": "2.3.6",
31 30 "tslint": "^6.1.3",
@@ -1,9 +1,5
1 1 import { MapOf, PromiseOrValue } from "@implab/core-amd/interfaces";
2 2 import { argumentNotEmptyString, isPromise, mixin } from "@implab/core-amd/safe";
3 import { id as mid } from "module";
4 import { TraceSource } from "@implab/core-amd/log/TraceSource";
5
6 const trace = TraceSource.get(mid);
7 3
8 4 export type LocaleProvider<T> = () => PromiseOrValue<T | { default: T }>;
9 5
@@ -19,10 +15,6 function isCallback<T>(v: ResolveCallbac
19 15 return typeof v === "function";
20 16 }
21 17
22 function defaultResolver(module: string) {
23 return import(module).then(x => x && x.default ? x.default : x);
24 }
25
26 18 function chainObjects<T extends object>(o1: T, o2: T) {
27 19 if (!o1)
28 20 return o2;
@@ -1,7 +1,6
1 1 import declare = require("dojo/_base/declare");
2 2 import { each } from "@implab/core-amd/safe";
3 3 import { Constructor } from "@implab/core-amd/interfaces";
4 import dojo = require("dojo/_base/kernel");
5 4
6 5 // declare const declare: any;
7 6
@@ -121,10 +120,8 export function djclass<T extends Abstra
121 120
122 121 // проверка того, что класс унаследован от специальной заглушки
123 122 if (isMockConstructor(bc)) {
124 // t - базовый класс, объявленный при помощи dojo/_base/declare
125 const t = bc.bases;
126
127 const cls = declare(bc.bases, target.prototype);
123 // bc.bases - базовый класс, объявленный при помощи dojo/_base/declare
124 const cls = declare<any>(bc.bases, target.prototype);
128 125
129 126 // bc - базовый класс, bc.prototype используется как super
130 127 // при вызове базовых методов. Нужно создать bc.prototype
@@ -94,7 +94,7 class DomInject {
94 94 throw e;
95 95 }
96 96 }
97 };
97 }
98 98
99 99 const instance = new DomInject();
100 100 export default instance;
@@ -1,8 +1,11
1 import { Constructor } from "@implab/core-amd/interfaces";
1 import { Constructor, IDestroyable, IRemovable } from "@implab/core-amd/interfaces";
2 2 import { HtmlRendition } from "./tsx/HtmlRendition";
3 3 import { WidgetRendition } from "./tsx/WidgetRendition";
4 import { isWidgetConstructor, Rendition } from "./tsx/traits";
4 import { destroy, isWidgetConstructor, Rendition } from "./tsx/traits";
5 5 import { FunctionRendition } from "./tsx/FunctionRendition";
6 import Stateful = require("dojo/Stateful");
7 import _WidgetBase = require("dijit/_WidgetBase");
8 import { DjxWidgetBase } from "./tsx/DjxWidgetBase";
6 9
7 10 export function createElement<T extends Constructor | string | ((props: any) => Element)>(elementType: T, ...args: any[]): Rendition {
8 11 if (typeof elementType === "string") {
@@ -38,3 +41,79 export interface EventSelector {
38 41 }
39 42
40 43 export type DojoMouseEvent<T = any> = MouseEvent & EventSelector & EventDetails<T>;
44
45 type StatefulProps<T> = T extends Stateful<infer A> ? A : never;
46
47 type CleanFn = (instance: IRemovable | IDestroyable) => void;
48
49 /**
50 * Observers the property and calls render callback each change.
51 *
52 * @param target The target object which property will be observed.
53 * @param prop The name of the property.
54 * @param render The callback which will be called every time the value is changed
55 * @param cleanupOrOwner The object with method `own` or an callback to register lifecycle for the observer.
56 * @returns Rendition which is created instantly
57 */
58 export function watch<W extends _WidgetBase, K extends keyof W>(
59 target: W,
60 prop: K,
61 render: (model: W[K]) => any,
62 cleanupOrOwner?: { own: CleanFn } | CleanFn
63 ): Rendition;
64 /**
65 * Observers the property and calls render callback each change.
66 *
67 * @param target The target object which property will be observed.
68 * @param prop The name of the property.
69 * @param render The callback which will be called every time the value is changed
70 * @param cleanupOrOwner The object with method `own` or an callback to register lifecycle for the observer.
71 * @returns Rendition which is created instantly
72 */
73 export function watch<T extends Stateful, K extends keyof StatefulProps<T>>(
74 target: T,
75 prop: K,
76 render: (model: StatefulProps<T>[K]) => any,
77 cleanupOrOwner?: { own: CleanFn } | CleanFn
78 ): Rendition;
79 export function watch<T extends Stateful, K extends keyof StatefulProps<T> & string>(
80 target: T,
81 prop: K,
82 render: (model: StatefulProps<T>[K]) => any,
83 cleanupOrOwner: { own: CleanFn } | CleanFn = () => { }
84 ) {
85 let rendition = new FunctionRendition(() => render(target.get(prop)));
86 const _own = cleanupOrOwner instanceof Function ? cleanupOrOwner : (x: IRemovable) => cleanupOrOwner.own(x);
87 _own(target.watch(prop, (_name, oldValue, newValue) => {
88 if (oldValue !== newValue) {
89 const newRendition = new FunctionRendition(() => render(newValue));
90 newRendition.placeAt(rendition.getDomNode(), "replace");
91 destroy(rendition.getDomNode());
92 rendition = newRendition;
93 }
94 }));
95 return rendition;
96 }
97
98 /** Decorates the method which will be registered as the handle for the specified event.
99 * This decorator can be applied to DjxWidgetBase subclass methods.
100 *
101 * ```
102 * @on("click")
103 * _onClick(eventObj: MouseEvent) {
104 * // ...
105 * }
106 * ```
107 */
108 export const on = <E extends string>(...eventNames: E[]) =>
109 <K extends string,
110 T extends DjxWidgetBase<any, { [p in E]: EV }>,
111 EV extends Event
112 >(
113 target: T,
114 key: K,
115 _descriptor: TypedPropertyDescriptor<(eventObj: EV) => void> | TypedPropertyDescriptor<() => void>
116 ): any => {
117 const handlers = eventNames.map(eventName => ({ eventName, handlerMethod: key }))
118 target._eventHandlers = target._eventHandlers ? target._eventHandlers.concat(handlers) : handlers;
119 };
@@ -1,8 +1,9
1 1 import { djbase, djclass } from "../declare";
2 2 import _WidgetBase = require("dijit/_WidgetBase");
3 3 import _AttachMixin = require("dijit/_AttachMixin");
4 import { Rendition, isNode, startupWidgets } from "./traits";
4 import { Rendition, isNode } from "./traits";
5 5 import registry = require("dijit/registry");
6 import on = require("dojo/on");
6 7
7 8 // type Handle = dojo.Handle;
8 9
@@ -14,18 +15,31 export interface EventArgs {
14 15 composed?: boolean;
15 16 }
16 17
17 export interface DjxWidgetBase<Attrs = any, Events extends { [name in keyof Events]: Event } = any> {
18 set<K extends keyof Attrs & string>(key: K, value: Attrs[K]): this;
19 set(props: Partial<Attrs>): this;
20 get<K extends keyof Attrs & string>(key: K): Attrs[K];
18 export interface DjxWidgetBase<Attrs = {}, Events extends { [name in keyof Events]: Event } = {}> extends
19 _WidgetBase<Events> {
20
21 /** This property is declared only for type inference to work, it is never assigned
22 * and should not be used.
23 */
24 readonly _eventMap: Events & GlobalEventHandlersEventMap;
21 25
22 on<K extends keyof Events & string>(eventName: K, cb: (evt: Events[K]) => void): dojo.WatchHandle;
23
24 emit<K extends keyof Events & string>(eventName: K, evt: Omit<Events[K], keyof Event> & EventArgs): void;
26 /** The list of pairs of event and method names. When the widget is created all methods from
27 * this list will be connected to corresponding events.
28 *
29 * This property is maintained in the prototype
30 */
31 _eventHandlers: Array<{
32 eventName: string,
33 handlerMethod: keyof any;
34 }>;
25 35 }
26 36
37 type _super = {
38 startup(): void;
39 };
40
27 41 @djclass
28 export abstract class DjxWidgetBase<Attrs = any, Events = any> extends djbase(_WidgetBase, _AttachMixin) {
42 export abstract class DjxWidgetBase<Attrs = {}, Events = {}> extends djbase<_super, _AttachMixin>(_WidgetBase, _AttachMixin) {
29 43
30 44 buildRendering() {
31 45 this.domNode = this.render().getDomNode();
@@ -36,6 +50,9 export abstract class DjxWidgetBase<Attr
36 50 const src = this.srcNodeRef;
37 51 const dest = this.containerNode;
38 52
53 // the donNode is constructed now we need to connect event handlers
54 this._connectEventHandlers();
55
39 56 if (src && dest) {
40 57 while (src.firstChild)
41 58 dest.appendChild(src.firstChild);
@@ -44,9 +61,18 export abstract class DjxWidgetBase<Attr
44 61
45 62 abstract render(): Rendition<HTMLElement>;
46 63
64 private _connectEventHandlers() {
65 if (this._eventHandlers)
66 this._eventHandlers.forEach(({ eventName, handlerMethod }) => {
67 const handler = this[handlerMethod as keyof this];
68 if (typeof handler === "function")
69 on(this.domNode, eventName, handler.bind(this));
70 });
71 }
72
47 73 _processTemplateNode<T extends (Element | Node | _WidgetBase)>(
48 74 baseNode: T,
49 getAttrFunc: (baseNode: T, attr: string) => string,
75 getAttrFunc: (baseNode: T, attr: string) => any,
50 76 // tslint:disable-next-line: ban-types
51 77 attachFunc: (node: T, type: string, func?: Function) => dojo.Handle
52 78 ): boolean {
@@ -55,7 +81,7 export abstract class DjxWidgetBase<Attr
55 81 if (w) {
56 82 // from dijit/_WidgetsInTemplateMixin
57 83 this._processTemplateNode(w,
58 (n, p) => n.get(p), // callback to get a property of a widget
84 (n, p) => n.get(p as any), // callback to get a property of a widget
59 85 (widget, type, callback) => {
60 86 if (!callback)
61 87 throw new Error("The callback must be specified");
@@ -90,7 +90,7 export abstract class RenditionBase<TNod
90 90 items.push(collection[i]);
91 91 }
92 92 return items;
93 }
93 };
94 94
95 95 const startup = (node: Node) => {
96 96 if (node.parentNode) {
@@ -100,9 +100,9 export abstract class RenditionBase<TNod
100 100 }
101 101 if (isInPage(node))
102 102 startupWidgets(node);
103 }
103 };
104 104
105 const startupPending = isDocumentFragmentNode(domNode) ? collect(domNode.children) : [domNode]
105 const startupPending = isDocumentFragmentNode(domNode) ? collect(domNode.children) : [domNode];
106 106
107 107 dom.place(domNode, refNode, position);
108 108
@@ -111,7 +111,7 export class WidgetRendition extends Ren
111 111 // fix the dojo startup behavior when the widget is placed
112 112 // directly to the document and doesn't have any enclosing widgets
113 113 const parentWidget = instance.domNode.parentNode ?
114 registry.getEnclosingWidget(instance.domNode.parentNode) : null
114 registry.getEnclosingWidget(instance.domNode.parentNode) : null;
115 115 if (!parentWidget && isInPage(instance.domNode) && typeof instance.startup === "function")
116 116 instance.startup();
117 117 } else {
@@ -60,7 +60,7 export function isWidget(v: any): v is _
60 60 }
61 61
62 62 export function isRendition(v: any): v is Rendition {
63 return typeof v === "object" && typeof v.getDomElement === "function";
63 return v && typeof v.getDomElement === "function";
64 64 }
65 65
66 66 /**
@@ -107,9 +107,9 export function destroy(target: Node | I
107 107 } else if (isDestroyable(target)) {
108 108 target.destroy();
109 109 } else if (isNode(target)) {
110 const self = registry.byNode(target);
111 if (self) {
112 self.destroyRecursive();
110 const w = isElementNode(target) ? registry.byNode(target) : undefined;
111 if (w) {
112 w.destroyRecursive();
113 113 } else {
114 114 registry.findWidgets(target).forEach(destroy);
115 115 dom.destroy(target);
@@ -145,4 +145,4 export function startupWidgets(target: N
145 145 if(target.startup)
146 146 target.startup();
147 147 }
148 } No newline at end of file
148 }
@@ -7,7 +7,7
7 7 "typings"
8 8 ],
9 9 "types": [
10 "requirejs", "./typings", "dojo-typings"
10 "requirejs", "./typings", "@implab/dojo-typings"
11 11 ]
12 12 }
13 13 }
@@ -1,5 +1,4
1 1 /// <reference path="./css.d.ts"/>
2 /// <reference path="./dijit.d.ts"/>
3 2
4 3 declare namespace JSX {
5 4
@@ -1,5 +1,6
1 1 import { Baz } from "./mock/Baz";
2 2
3 // tslint:disable-next-line: no-console
3 4 console.log("Declare tests");
4 5
5 6 const baz = new Baz();
@@ -7,4 +8,5 const baz = new Baz();
7 8 const data: string[] = [];
8 9 baz.writeHello(data);
9 10
11 // tslint:disable-next-line: no-console
10 12 console.log(data.join("\n"));
@@ -1,7 +1,6
1 1 import { test } from "./TestTraits";
2 2 import { delay } from "@implab/core-amd/safe";
3 3 import { assert } from "chai";
4 import css = require("@implab/djx/css!my.css");
5 4
6 5 test("simple", (ok, fail, log) => {
7 6 setTimeout(() => {
@@ -1,7 +1,7
1 1 import { djbase, djclass, bind, prototype, AbstractConstructor } from "../declare";
2 2
3 3 import { DjxWidgetBase } from "../tsx/DjxWidgetBase";
4 import { createElement } from "../tsx";
4 import { createElement, on } from "../tsx";
5 5
6 6 interface MyWidgetAttrs {
7 7 title: string;
@@ -10,9 +10,13 interface MyWidgetAttrs {
10 10 }
11 11
12 12 interface MyWidgetEvents {
13 "count-inc": Event;
13 "count-inc": Event & {
14 detail: number;
15 };
14 16
15 "count-dec": Event;
17 "count-dec": Event & {
18 detail: number;
19 };
16 20 }
17 21
18 22
@@ -36,15 +40,31 export class MyWidget extends djbase(Djx
36 40 </div>;
37 41 }
38 42
43 postCreate() {
44 super.postCreate();
45
46 this.on("click", () => {});
47 }
48
39 49 _onSubmit(e: Event) {
40
41 50 }
42 51
43 52 _onIncClick(e: MouseEvent) {
53 this.set("counter", this.counter + 1);
54
44 55 this.emit("count-inc", { bubbles: false });
45 56 }
46 57
47 58 _onDecClick() {
48 this.emit("count-dec", { bubbles: false });
59 this.emit("count-dec", { bubbles: false, detail: this.counter });
60 }
61
62 @on("count-inc")
63 _onCounterInc(evt: Event & { detail: number; x?: number; }) {
49 64 }
65
66 @on("click", "keydown")
67 protected _onClick(event: MouseEvent | KeyboardEvent) {
68
50 69 }
70 } No newline at end of file
@@ -8,6 +8,6
8 8 "../main/ts",
9 9 "../main/typings"
10 10 ],
11 "types": ["requirejs", "../main/typings", "dojo-typings"]
11 "types": ["requirejs", "../main/typings", "@implab/dojo-typings"]
12 12 }
13 13 } No newline at end of file
@@ -6,8 +6,10
6 6 "types": [],
7 7 "experimentalDecorators": true,
8 8 "jsxFactory": "createElement",
9 "target": "ES5",
9 10 //"skipLibCheck": true,
10 11 "jsx": "react",
11 "lib": ["es5", "es2015.promise", "es2015.symbol", "es2015.iterable", "dom", "scripthost"]
12 "lib": ["es5", "es2015.promise", "es2015.symbol", "es2015.iterable", "dom", "scripthost"],
13 "noUnusedLocals": true
12 14 }
13 15 } No newline at end of file
@@ -14,5 +14,4
14 14
15 15 rootProject.name = 'implabjs-djx'
16 16
17 include 'djx'
18 include 'playground' No newline at end of file
17 include 'djx' No newline at end of file
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
General Comments 0
You need to be logged in to leave comments. Login now