@angular-wave/angular.ts 0.0.11 → 0.0.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (79) hide show
  1. package/dist/angular-ts.esm.js +1 -1
  2. package/dist/angular-ts.umd.js +1 -1
  3. package/package.json +4 -1
  4. package/src/exts/messages.md +30 -30
  5. package/src/index.js +1 -0
  6. package/src/public.js +2 -0
  7. package/src/router/adapter/directives/stateDirectives.js +695 -0
  8. package/src/router/adapter/directives/viewDirective.js +514 -0
  9. package/src/router/adapter/injectables.js +314 -0
  10. package/src/router/adapter/interface.js +1 -0
  11. package/src/router/adapter/locationServices.js +84 -0
  12. package/src/router/adapter/services.js +126 -0
  13. package/src/router/adapter/stateFilters.js +43 -0
  14. package/src/router/adapter/stateProvider.js +137 -0
  15. package/src/router/adapter/statebuilders/onEnterExitRetain.js +30 -0
  16. package/src/router/adapter/statebuilders/views.js +146 -0
  17. package/src/router/adapter/templateFactory.js +218 -0
  18. package/src/router/adapter/viewScroll.js +31 -0
  19. package/src/router/core/common/common.js +496 -0
  20. package/src/router/core/common/coreservices.js +15 -0
  21. package/src/router/core/common/glob.js +75 -0
  22. package/src/router/core/common/hof.js +194 -0
  23. package/src/router/core/common/predicates.js +44 -0
  24. package/src/router/core/common/queue.js +41 -0
  25. package/src/router/core/common/safeConsole.js +38 -0
  26. package/src/router/core/common/strings.js +141 -0
  27. package/src/router/core/common/trace.js +232 -0
  28. package/src/router/core/globals.js +29 -0
  29. package/src/router/core/hooks/coreResolvables.js +33 -0
  30. package/src/router/core/hooks/ignoredTransition.js +25 -0
  31. package/src/router/core/hooks/invalidTransition.js +14 -0
  32. package/src/router/core/hooks/lazyLoad.js +102 -0
  33. package/src/router/core/hooks/onEnterExitRetain.js +55 -0
  34. package/src/router/core/hooks/redirectTo.js +36 -0
  35. package/src/router/core/hooks/resolve.js +57 -0
  36. package/src/router/core/hooks/updateGlobals.js +30 -0
  37. package/src/router/core/hooks/url.js +25 -0
  38. package/src/router/core/hooks/views.js +39 -0
  39. package/src/router/core/interface.js +3 -0
  40. package/src/router/core/params/README.md +8 -0
  41. package/src/router/core/params/param.js +232 -0
  42. package/src/router/core/params/paramType.js +139 -0
  43. package/src/router/core/params/paramTypes.js +163 -0
  44. package/src/router/core/params/stateParams.js +35 -0
  45. package/src/router/core/path/pathNode.js +77 -0
  46. package/src/router/core/path/pathUtils.js +199 -0
  47. package/src/router/core/resolve/interface.js +10 -0
  48. package/src/router/core/resolve/resolvable.js +124 -0
  49. package/src/router/core/resolve/resolveContext.js +211 -0
  50. package/src/router/core/router.js +203 -0
  51. package/src/router/core/state/README.md +21 -0
  52. package/src/router/core/state/stateBuilder.js +332 -0
  53. package/src/router/core/state/stateMatcher.js +65 -0
  54. package/src/router/core/state/stateObject.js +117 -0
  55. package/src/router/core/state/stateQueueManager.js +89 -0
  56. package/src/router/core/state/stateRegistry.js +175 -0
  57. package/src/router/core/state/stateService.js +592 -0
  58. package/src/router/core/state/targetState.js +159 -0
  59. package/src/router/core/transition/hookBuilder.js +127 -0
  60. package/src/router/core/transition/hookRegistry.js +175 -0
  61. package/src/router/core/transition/interface.js +14 -0
  62. package/src/router/core/transition/rejectFactory.js +122 -0
  63. package/src/router/core/transition/transition.js +739 -0
  64. package/src/router/core/transition/transitionEventType.js +27 -0
  65. package/src/router/core/transition/transitionHook.js +199 -0
  66. package/src/router/core/transition/transitionService.js +311 -0
  67. package/src/router/core/url/interface.js +1 -0
  68. package/src/router/core/url/urlConfig.js +165 -0
  69. package/src/router/core/url/urlMatcher.js +548 -0
  70. package/src/router/core/url/urlMatcherFactory.js +123 -0
  71. package/src/router/core/url/urlRouter.js +115 -0
  72. package/src/router/core/url/urlRule.js +202 -0
  73. package/src/router/core/url/urlRules.js +348 -0
  74. package/src/router/core/url/urlService.js +268 -0
  75. package/src/router/core/view/interface.js +1 -0
  76. package/src/router/core/view/view.js +312 -0
  77. package/src/router/router.js +58 -0
  78. package/test/module-test.html +6 -2
  79. package/test/module-test.js +0 -0
@@ -0,0 +1,232 @@
1
+ import { extend, filter, map, allTrueR, find } from "../common/common";
2
+ import { prop } from "../common/hof";
3
+ import {
4
+ isInjectable,
5
+ isDefined,
6
+ isString,
7
+ isArray,
8
+ isUndefined,
9
+ } from "../common/predicates";
10
+ import { services } from "../common/coreservices";
11
+ import { ParamType } from "./paramType";
12
+ const hasOwn = Object.prototype.hasOwnProperty;
13
+ const isShorthand = (cfg) =>
14
+ ["value", "type", "squash", "array", "dynamic"].filter(hasOwn.bind(cfg || {}))
15
+ .length === 0;
16
+ var DefType;
17
+ (function (DefType) {
18
+ DefType[(DefType["PATH"] = 0)] = "PATH";
19
+ DefType[(DefType["SEARCH"] = 1)] = "SEARCH";
20
+ DefType[(DefType["CONFIG"] = 2)] = "CONFIG";
21
+ })(DefType || (DefType = {}));
22
+ export { DefType };
23
+ function getParamDeclaration(paramName, location, state) {
24
+ const noReloadOnSearch =
25
+ (state.reloadOnSearch === false && location === DefType.SEARCH) ||
26
+ undefined;
27
+ const dynamic = find([state.dynamic, noReloadOnSearch], isDefined);
28
+ const defaultConfig = isDefined(dynamic) ? { dynamic } : {};
29
+ const paramConfig = unwrapShorthand(
30
+ state && state.params && state.params[paramName],
31
+ );
32
+ return extend(defaultConfig, paramConfig);
33
+ }
34
+ function unwrapShorthand(cfg) {
35
+ cfg = isShorthand(cfg) ? { value: cfg } : cfg;
36
+ getStaticDefaultValue["__cacheable"] = true;
37
+ function getStaticDefaultValue() {
38
+ return cfg.value;
39
+ }
40
+ const $$fn = isInjectable(cfg.value) ? cfg.value : getStaticDefaultValue;
41
+ return extend(cfg, { $$fn });
42
+ }
43
+ function getType(cfg, urlType, location, id, paramTypes) {
44
+ if (cfg.type && urlType && urlType.name !== "string")
45
+ throw new Error(`Param '${id}' has two type configurations.`);
46
+ if (
47
+ cfg.type &&
48
+ urlType &&
49
+ urlType.name === "string" &&
50
+ paramTypes.type(cfg.type)
51
+ )
52
+ return paramTypes.type(cfg.type);
53
+ if (urlType) return urlType;
54
+ if (!cfg.type) {
55
+ const type =
56
+ location === DefType.CONFIG
57
+ ? "any"
58
+ : location === DefType.PATH
59
+ ? "path"
60
+ : location === DefType.SEARCH
61
+ ? "query"
62
+ : "string";
63
+ return paramTypes.type(type);
64
+ }
65
+ return cfg.type instanceof ParamType ? cfg.type : paramTypes.type(cfg.type);
66
+ }
67
+ /** returns false, true, or the squash value to indicate the "default parameter url squash policy". */
68
+ function getSquashPolicy(config, isOptional, defaultPolicy) {
69
+ const squash = config.squash;
70
+ if (!isOptional || squash === false) return false;
71
+ if (!isDefined(squash) || squash == null) return defaultPolicy;
72
+ if (squash === true || isString(squash)) return squash;
73
+ throw new Error(
74
+ `Invalid squash policy: '${squash}'. Valid policies: false, true, or arbitrary string`,
75
+ );
76
+ }
77
+ function getReplace(config, arrayMode, isOptional, squash) {
78
+ const defaultPolicy = [
79
+ { from: "", to: isOptional || arrayMode ? undefined : "" },
80
+ { from: null, to: isOptional || arrayMode ? undefined : "" },
81
+ ];
82
+ const replace = isArray(config.replace) ? config.replace : [];
83
+ if (isString(squash)) replace.push({ from: squash, to: undefined });
84
+ const configuredKeys = map(replace, prop("from"));
85
+ return filter(
86
+ defaultPolicy,
87
+ (item) => configuredKeys.indexOf(item.from) === -1,
88
+ ).concat(replace);
89
+ }
90
+ export class Param {
91
+ static values(params, values = {}) {
92
+ const paramValues = {};
93
+ for (const param of params) {
94
+ paramValues[param.id] = param.value(values[param.id]);
95
+ }
96
+ return paramValues;
97
+ }
98
+ /**
99
+ * Finds [[Param]] objects which have different param values
100
+ *
101
+ * Filters a list of [[Param]] objects to only those whose parameter values differ in two param value objects
102
+ *
103
+ * @param params: The list of Param objects to filter
104
+ * @param values1: The first set of parameter values
105
+ * @param values2: the second set of parameter values
106
+ *
107
+ * @returns any Param objects whose values were different between values1 and values2
108
+ */
109
+ static changed(params, values1 = {}, values2 = {}) {
110
+ return params.filter(
111
+ (param) => !param.type.equals(values1[param.id], values2[param.id]),
112
+ );
113
+ }
114
+ /**
115
+ * Checks if two param value objects are equal (for a set of [[Param]] objects)
116
+ *
117
+ * @param params The list of [[Param]] objects to check
118
+ * @param values1 The first set of param values
119
+ * @param values2 The second set of param values
120
+ *
121
+ * @returns true if the param values in values1 and values2 are equal
122
+ */
123
+ static equals(params, values1 = {}, values2 = {}) {
124
+ return Param.changed(params, values1, values2).length === 0;
125
+ }
126
+ /** Returns true if a the parameter values are valid, according to the Param definitions */
127
+ static validates(params, values = {}) {
128
+ return params
129
+ .map((param) => param.validates(values[param.id]))
130
+ .reduce(allTrueR, true);
131
+ }
132
+ constructor(id, type, location, urlConfig, state) {
133
+ const config = getParamDeclaration(id, location, state);
134
+ type = getType(config, type, location, id, urlConfig.paramTypes);
135
+ const arrayMode = getArrayMode();
136
+ type = arrayMode
137
+ ? type.$asArray(arrayMode, location === DefType.SEARCH)
138
+ : type;
139
+ const isOptional =
140
+ config.value !== undefined || location === DefType.SEARCH;
141
+ const dynamic = isDefined(config.dynamic)
142
+ ? !!config.dynamic
143
+ : !!type.dynamic;
144
+ const raw = isDefined(config.raw) ? !!config.raw : !!type.raw;
145
+ const squash = getSquashPolicy(
146
+ config,
147
+ isOptional,
148
+ urlConfig.defaultSquashPolicy(),
149
+ );
150
+ const replace = getReplace(config, arrayMode, isOptional, squash);
151
+ const inherit = isDefined(config.inherit)
152
+ ? !!config.inherit
153
+ : !!type.inherit;
154
+ // array config: param name (param[]) overrides default settings. explicit config overrides param name.
155
+ function getArrayMode() {
156
+ const arrayDefaults = {
157
+ array: location === DefType.SEARCH ? "auto" : false,
158
+ };
159
+ const arrayParamNomenclature = id.match(/\[\]$/) ? { array: true } : {};
160
+ return extend(arrayDefaults, arrayParamNomenclature, config).array;
161
+ }
162
+ extend(this, {
163
+ id,
164
+ type,
165
+ location,
166
+ isOptional,
167
+ dynamic,
168
+ raw,
169
+ squash,
170
+ replace,
171
+ inherit,
172
+ array: arrayMode,
173
+ config,
174
+ });
175
+ }
176
+ isDefaultValue(value) {
177
+ return this.isOptional && this.type.equals(this.value(), value);
178
+ }
179
+ /**
180
+ * [Internal] Gets the decoded representation of a value if the value is defined, otherwise, returns the
181
+ * default value, which may be the result of an injectable function.
182
+ */
183
+ value(value) {
184
+ /**
185
+ * [Internal] Get the default value of a parameter, which may be an injectable function.
186
+ */
187
+ const getDefaultValue = () => {
188
+ if (this._defaultValueCache) return this._defaultValueCache.defaultValue;
189
+ if (!services.$injector)
190
+ throw new Error(
191
+ "Injectable functions cannot be called at configuration time",
192
+ );
193
+ const defaultValue = services.$injector.invoke(this.config.$$fn);
194
+ if (
195
+ defaultValue !== null &&
196
+ defaultValue !== undefined &&
197
+ !this.type.is(defaultValue)
198
+ )
199
+ throw new Error(
200
+ `Default value (${defaultValue}) for parameter '${this.id}' is not an instance of ParamType (${this.type.name})`,
201
+ );
202
+ if (this.config.$$fn["__cacheable"]) {
203
+ this._defaultValueCache = { defaultValue };
204
+ }
205
+ return defaultValue;
206
+ };
207
+ const replaceSpecialValues = (val) => {
208
+ for (const tuple of this.replace) {
209
+ if (tuple.from === val) return tuple.to;
210
+ }
211
+ return val;
212
+ };
213
+ value = replaceSpecialValues(value);
214
+ return isUndefined(value) ? getDefaultValue() : this.type.$normalize(value);
215
+ }
216
+ isSearch() {
217
+ return this.location === DefType.SEARCH;
218
+ }
219
+ validates(value) {
220
+ // There was no parameter value, but the param is optional
221
+ if ((isUndefined(value) || value === null) && this.isOptional) return true;
222
+ // The value was not of the correct ParamType, and could not be decoded to the correct ParamType
223
+ const normalized = this.type.$normalize(value);
224
+ if (!this.type.is(normalized)) return false;
225
+ // The value was of the correct type, but when encoded, did not match the ParamType's regexp
226
+ const encoded = this.type.encode(normalized);
227
+ return !(isString(encoded) && !this.type.pattern.exec(encoded));
228
+ }
229
+ toString() {
230
+ return `{Param:${this.id} ${this.type} squash: '${this.squash}' optional: ${this.isOptional}}`;
231
+ }
232
+ }
@@ -0,0 +1,139 @@
1
+ import { extend, filter, map } from "../common/common";
2
+ import { isArray, isDefined } from "../common/predicates";
3
+ /**
4
+ * An internal class which implements [[ParamTypeDefinition]].
5
+ *
6
+ * A [[ParamTypeDefinition]] is a plain javascript object used to register custom parameter types.
7
+ * When a param type definition is registered, an instance of this class is created internally.
8
+ *
9
+ * This class has naive implementations for all the [[ParamTypeDefinition]] methods.
10
+ *
11
+ * Used by [[UrlMatcher]] when matching or formatting URLs, or comparing and validating parameter values.
12
+ *
13
+ * #### Example:
14
+ * ```js
15
+ * var paramTypeDef = {
16
+ * decode: function(val) { return parseInt(val, 10); },
17
+ * encode: function(val) { return val && val.toString(); },
18
+ * equals: function(a, b) { return this.is(a) && a === b; },
19
+ * is: function(val) { return angular.isNumber(val) && isFinite(val) && val % 1 === 0; },
20
+ * pattern: /\d+/
21
+ * }
22
+ *
23
+ * var paramType = new ParamType(paramTypeDef);
24
+ * ```
25
+ */
26
+ export class ParamType {
27
+ /**
28
+ * @param def A configuration object which contains the custom type definition. The object's
29
+ * properties will override the default methods and/or pattern in `ParamType`'s public interface.
30
+ * @returns a new ParamType object
31
+ */
32
+ constructor(def) {
33
+ /** @inheritdoc */
34
+ this.pattern = /.*/;
35
+ /** @inheritdoc */
36
+ this.inherit = true;
37
+ extend(this, def);
38
+ }
39
+ // consider these four methods to be "abstract methods" that should be overridden
40
+ /** @inheritdoc */
41
+ is(val, key) {
42
+ return true;
43
+ }
44
+ /** @inheritdoc */
45
+ encode(val, key) {
46
+ return val;
47
+ }
48
+ /** @inheritdoc */
49
+ decode(val, key) {
50
+ return val;
51
+ }
52
+ /** @inheritdoc */
53
+ equals(a, b) {
54
+ // tslint:disable-next-line:triple-equals
55
+ return a == b;
56
+ }
57
+ $subPattern() {
58
+ const sub = this.pattern.toString();
59
+ return sub.substr(1, sub.length - 2);
60
+ }
61
+ toString() {
62
+ return `{ParamType:${this.name}}`;
63
+ }
64
+ /** Given an encoded string, or a decoded object, returns a decoded object */
65
+ $normalize(val) {
66
+ return this.is(val) ? val : this.decode(val);
67
+ }
68
+ /**
69
+ * Wraps an existing custom ParamType as an array of ParamType, depending on 'mode'.
70
+ * e.g.:
71
+ * - urlmatcher pattern "/path?{queryParam[]:int}"
72
+ * - url: "/path?queryParam=1&queryParam=2
73
+ * - $stateParams.queryParam will be [1, 2]
74
+ * if `mode` is "auto", then
75
+ * - url: "/path?queryParam=1 will create $stateParams.queryParam: 1
76
+ * - url: "/path?queryParam=1&queryParam=2 will create $stateParams.queryParam: [1, 2]
77
+ */
78
+ $asArray(mode, isSearch) {
79
+ if (!mode) return this;
80
+ if (mode === "auto" && !isSearch)
81
+ throw new Error("'auto' array mode is for query parameters only");
82
+ return new ArrayType(this, mode);
83
+ }
84
+ }
85
+ /** Wraps up a `ParamType` object to handle array values. */
86
+ function ArrayType(type, mode) {
87
+ // Wrap non-array value as array
88
+ function arrayWrap(val) {
89
+ return isArray(val) ? val : isDefined(val) ? [val] : [];
90
+ }
91
+ // Unwrap array value for "auto" mode. Return undefined for empty array.
92
+ function arrayUnwrap(val) {
93
+ switch (val.length) {
94
+ case 0:
95
+ return undefined;
96
+ case 1:
97
+ return mode === "auto" ? val[0] : val;
98
+ default:
99
+ return val;
100
+ }
101
+ }
102
+ // Wraps type (.is/.encode/.decode) functions to operate on each value of an array
103
+ function arrayHandler(callback, allTruthyMode) {
104
+ return function handleArray(val) {
105
+ if (isArray(val) && val.length === 0) return val;
106
+ const arr = arrayWrap(val);
107
+ const result = map(arr, callback);
108
+ return allTruthyMode === true
109
+ ? filter(result, (x) => !x).length === 0
110
+ : arrayUnwrap(result);
111
+ };
112
+ }
113
+ // Wraps type (.equals) functions to operate on each value of an array
114
+ function arrayEqualsHandler(callback) {
115
+ return function handleArray(val1, val2) {
116
+ const left = arrayWrap(val1),
117
+ right = arrayWrap(val2);
118
+ if (left.length !== right.length) return false;
119
+ for (let i = 0; i < left.length; i++) {
120
+ if (!callback(left[i], right[i])) return false;
121
+ }
122
+ return true;
123
+ };
124
+ }
125
+ ["encode", "decode", "equals", "$normalize"].forEach((name) => {
126
+ const paramTypeFn = type[name].bind(type);
127
+ const wrapperFn = name === "equals" ? arrayEqualsHandler : arrayHandler;
128
+ this[name] = wrapperFn(paramTypeFn);
129
+ });
130
+ extend(this, {
131
+ dynamic: type.dynamic,
132
+ name: type.name,
133
+ pattern: type.pattern,
134
+ inherit: type.inherit,
135
+ raw: type.raw,
136
+ is: arrayHandler(type.is.bind(type), true),
137
+ $arrayMode: mode,
138
+ });
139
+ }
@@ -0,0 +1,163 @@
1
+ import {
2
+ fromJson,
3
+ toJson,
4
+ identity,
5
+ equals,
6
+ inherit,
7
+ map,
8
+ extend,
9
+ pick,
10
+ } from "../common/common";
11
+ import { isDefined, isNullOrUndefined } from "../common/predicates";
12
+ import { is } from "../common/hof";
13
+ import { services } from "../common/coreservices";
14
+ import { ParamType } from "./paramType";
15
+ /**
16
+ * A registry for parameter types.
17
+ *
18
+ * This registry manages the built-in (and custom) parameter types.
19
+ *
20
+ * The built-in parameter types are:
21
+ *
22
+ * - [[string]]
23
+ * - [[path]]
24
+ * - [[query]]
25
+ * - [[hash]]
26
+ * - [[int]]
27
+ * - [[bool]]
28
+ * - [[date]]
29
+ * - [[json]]
30
+ * - [[any]]
31
+ *
32
+ * To register custom parameter types, use [[UrlConfig.type]], i.e.,
33
+ *
34
+ * ```js
35
+ * router.urlService.config.type(customType)
36
+ * ```
37
+ */
38
+ export class ParamTypes {
39
+ constructor() {
40
+ this.enqueue = true;
41
+ this.typeQueue = [];
42
+ this.defaultTypes = pick(ParamTypes.prototype, [
43
+ "hash",
44
+ "string",
45
+ "query",
46
+ "path",
47
+ "int",
48
+ "bool",
49
+ "date",
50
+ "json",
51
+ "any",
52
+ ]);
53
+ // Register default types. Store them in the prototype of this.types.
54
+ const makeType = (definition, name) =>
55
+ new ParamType(extend({ name }, definition));
56
+ this.types = inherit(map(this.defaultTypes, makeType), {});
57
+ }
58
+ dispose() {
59
+ this.types = {};
60
+ }
61
+ /**
62
+ * Registers a parameter type
63
+ *
64
+ * End users should call [[UrlMatcherFactory.type]], which delegates to this method.
65
+ */
66
+ type(name, definition, definitionFn) {
67
+ if (!isDefined(definition)) return this.types[name];
68
+ if (this.types.hasOwnProperty(name))
69
+ throw new Error(`A type named '${name}' has already been defined.`);
70
+ this.types[name] = new ParamType(extend({ name }, definition));
71
+ if (definitionFn) {
72
+ this.typeQueue.push({ name, def: definitionFn });
73
+ if (!this.enqueue) this._flushTypeQueue();
74
+ }
75
+ return this;
76
+ }
77
+ _flushTypeQueue() {
78
+ while (this.typeQueue.length) {
79
+ const type = this.typeQueue.shift();
80
+ if (type.pattern)
81
+ throw new Error("You cannot override a type's .pattern at runtime.");
82
+ extend(this.types[type.name], services.$injector.invoke(type.def));
83
+ }
84
+ }
85
+ }
86
+ function initDefaultTypes() {
87
+ const makeDefaultType = (def) => {
88
+ const valToString = (val) => (val != null ? val.toString() : val);
89
+ const defaultTypeBase = {
90
+ encode: valToString,
91
+ decode: valToString,
92
+ is: is(String),
93
+ pattern: /.*/,
94
+ // tslint:disable-next-line:triple-equals
95
+ equals: (a, b) => a == b, // allow coersion for null/undefined/""
96
+ };
97
+ return extend({}, defaultTypeBase, def);
98
+ };
99
+ // Default Parameter Type Definitions
100
+ extend(ParamTypes.prototype, {
101
+ string: makeDefaultType({}),
102
+ path: makeDefaultType({
103
+ pattern: /[^/]*/,
104
+ }),
105
+ query: makeDefaultType({}),
106
+ hash: makeDefaultType({
107
+ inherit: false,
108
+ }),
109
+ int: makeDefaultType({
110
+ decode: (val) => parseInt(val, 10),
111
+ is: function (val) {
112
+ return !isNullOrUndefined(val) && this.decode(val.toString()) === val;
113
+ },
114
+ pattern: /-?\d+/,
115
+ }),
116
+ bool: makeDefaultType({
117
+ encode: (val) => (val && 1) || 0,
118
+ decode: (val) => parseInt(val, 10) !== 0,
119
+ is: is(Boolean),
120
+ pattern: /0|1/,
121
+ }),
122
+ date: makeDefaultType({
123
+ encode: function (val) {
124
+ return !this.is(val)
125
+ ? undefined
126
+ : [
127
+ val.getFullYear(),
128
+ ("0" + (val.getMonth() + 1)).slice(-2),
129
+ ("0" + val.getDate()).slice(-2),
130
+ ].join("-");
131
+ },
132
+ decode: function (val) {
133
+ if (this.is(val)) return val;
134
+ const match = this.capture.exec(val);
135
+ return match ? new Date(match[1], match[2] - 1, match[3]) : undefined;
136
+ },
137
+ is: (val) => val instanceof Date && !isNaN(val.valueOf()),
138
+ equals(l, r) {
139
+ return ["getFullYear", "getMonth", "getDate"].reduce(
140
+ (acc, fn) => acc && l[fn]() === r[fn](),
141
+ true,
142
+ );
143
+ },
144
+ pattern: /[0-9]{4}-(?:0[1-9]|1[0-2])-(?:0[1-9]|[1-2][0-9]|3[0-1])/,
145
+ capture: /([0-9]{4})-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])/,
146
+ }),
147
+ json: makeDefaultType({
148
+ encode: toJson,
149
+ decode: fromJson,
150
+ is: is(Object),
151
+ equals: equals,
152
+ pattern: /[^/]*/,
153
+ }),
154
+ // does not encode/decode
155
+ any: makeDefaultType({
156
+ encode: identity,
157
+ decode: identity,
158
+ is: () => true,
159
+ equals: equals,
160
+ }),
161
+ });
162
+ }
163
+ initDefaultTypes();
@@ -0,0 +1,35 @@
1
+ import { extend, ancestors } from "../common/common";
2
+ export class StateParams {
3
+ constructor(params = {}) {
4
+ extend(this, params);
5
+ }
6
+ /**
7
+ * Merges a set of parameters with all parameters inherited between the common parents of the
8
+ * current state and a given destination state.
9
+ *
10
+ * @param {Object} newParams The set of parameters which will be composited with inherited params.
11
+ * @param {Object} $current Internal definition of object representing the current state.
12
+ * @param {Object} $to Internal definition of object representing state to transition to.
13
+ */
14
+ $inherit(newParams, $current, $to) {
15
+ const parents = ancestors($current, $to),
16
+ inherited = {},
17
+ inheritList = [];
18
+ for (const i in parents) {
19
+ if (!parents[i] || !parents[i].params) continue;
20
+ const parentParams = parents[i].params;
21
+ const parentParamsKeys = Object.keys(parentParams);
22
+ if (!parentParamsKeys.length) continue;
23
+ for (const j in parentParamsKeys) {
24
+ if (
25
+ parentParams[parentParamsKeys[j]].inherit == false ||
26
+ inheritList.indexOf(parentParamsKeys[j]) >= 0
27
+ )
28
+ continue;
29
+ inheritList.push(parentParamsKeys[j]);
30
+ inherited[parentParamsKeys[j]] = this[parentParamsKeys[j]];
31
+ }
32
+ }
33
+ return extend({}, inherited, newParams);
34
+ }
35
+ }
@@ -0,0 +1,77 @@
1
+ import { extend, applyPairs, find } from "../common/common";
2
+ import { propEq } from "../common/hof";
3
+ import { Param } from "../params/param";
4
+ /**
5
+ * A node in a [[TreeChanges]] path
6
+ *
7
+ * For a [[TreeChanges]] path, this class holds the stateful information for a single node in the path.
8
+ * Each PathNode corresponds to a state being entered, exited, or retained.
9
+ * The stateful information includes parameter values and resolve data.
10
+ */
11
+ export class PathNode {
12
+ constructor(stateOrNode) {
13
+ if (stateOrNode instanceof PathNode) {
14
+ const node = stateOrNode;
15
+ this.state = node.state;
16
+ this.paramSchema = node.paramSchema.slice();
17
+ this.paramValues = extend({}, node.paramValues);
18
+ this.resolvables = node.resolvables.slice();
19
+ this.views = node.views && node.views.slice();
20
+ } else {
21
+ const state = stateOrNode;
22
+ this.state = state;
23
+ this.paramSchema = state.parameters({ inherit: false });
24
+ this.paramValues = {};
25
+ this.resolvables = state.resolvables.map((res) => res.clone());
26
+ }
27
+ }
28
+ clone() {
29
+ return new PathNode(this);
30
+ }
31
+ /** Sets [[paramValues]] for the node, from the values of an object hash */
32
+ applyRawParams(params) {
33
+ const getParamVal = (paramDef) => [
34
+ paramDef.id,
35
+ paramDef.value(params[paramDef.id]),
36
+ ];
37
+ this.paramValues = this.paramSchema.reduce(
38
+ (memo, pDef) => applyPairs(memo, getParamVal(pDef)),
39
+ {},
40
+ );
41
+ return this;
42
+ }
43
+ /** Gets a specific [[Param]] metadata that belongs to the node */
44
+ parameter(name) {
45
+ return find(this.paramSchema, propEq("id", name));
46
+ }
47
+ /**
48
+ * @returns true if the state and parameter values for another PathNode are
49
+ * equal to the state and param values for this PathNode
50
+ */
51
+ equals(node, paramsFn) {
52
+ const diff = this.diff(node, paramsFn);
53
+ return diff && diff.length === 0;
54
+ }
55
+ /**
56
+ * Finds Params with different parameter values on another PathNode.
57
+ *
58
+ * Given another node (of the same state), finds the parameter values which differ.
59
+ * Returns the [[Param]] (schema objects) whose parameter values differ.
60
+ *
61
+ * Given another node for a different state, returns `false`
62
+ *
63
+ * @param node The node to compare to
64
+ * @param paramsFn A function that returns which parameters should be compared.
65
+ * @returns The [[Param]]s which differ, or null if the two nodes are for different states
66
+ */
67
+ diff(node, paramsFn) {
68
+ if (this.state !== node.state) return false;
69
+ const params = paramsFn ? paramsFn(this) : this.paramSchema;
70
+ return Param.changed(params, this.paramValues, node.paramValues);
71
+ }
72
+ }
73
+ /**
74
+ * Returns a clone of the PathNode
75
+ * @deprecated use instance method `node.clone()`
76
+ */
77
+ PathNode.clone = (node) => node.clone();