@nascentdigital/funnel-core 4.4.16 → 4.4.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/schema/Collection.d.ts +14 -9
- package/dist/schema/CollectionModel.d.ts +1 -2
- package/dist/schema/CollectionModel.js +10 -16
- package/dist/schema/Page.d.ts +1 -2
- package/dist/schema/PageModel.js +2 -2
- package/dist/schema/PageSnapshot.d.ts +1 -1
- package/dist/types/UndefinedToNull.d.ts +1 -0
- package/dist/types/UndefinedToNull.js +2 -0
- package/dist/types/index.d.ts +1 -0
- package/dist/types/index.js +1 -0
- package/dist/ui/block-layout/BlockLayout.d.ts +1 -1
- package/dist/ui/block-layout/BlockLayout.js +10 -5
- package/dist/ui/fields/Field.d.ts +4 -0
- package/dist/ui/fields/Field.js +33 -3
- package/dist/ui/fields/errors.json +4 -2
- package/dist/ui/fields/index.d.ts +1 -0
- package/dist/ui/fields/index.js +1 -0
- package/package.json +1 -1
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Tagged } from 'type-fest';
|
|
2
2
|
import { Language } from '../regionalization';
|
|
3
|
+
import { UndefinedToNull } from '../types';
|
|
3
4
|
import { Asset } from './Asset';
|
|
4
5
|
import type { ChangeSet } from './ChangeSet';
|
|
5
6
|
import type { CollectionSnapshot } from './CollectionSnapshot';
|
|
@@ -31,16 +32,20 @@ export declare namespace Collection {
|
|
|
31
32
|
type GroupId = Tagged<string, 'funnel.Collection.GroupId'>;
|
|
32
33
|
type Type = Tagged<string, 'funnel.Collection.Type'>;
|
|
33
34
|
type State = 'draft' | 'published' | 'unpublished';
|
|
34
|
-
type Update = Update.
|
|
35
|
+
type Update = Update.Collection | Update.ObjectInsert | Update.ArrayInsert | Update.ArrayDelete | Update.ArrayReorder | Update.Value;
|
|
35
36
|
namespace Update {
|
|
36
|
-
type
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
37
|
+
type Collection = Collection.Name | Collection.Tags | Collection.Errors;
|
|
38
|
+
namespace Collection {
|
|
39
|
+
type Factory<TProp extends keyof Data> = {
|
|
40
|
+
type: 'collection';
|
|
41
|
+
property: TProp;
|
|
42
|
+
value: UndefinedToNull<Data[TProp]>;
|
|
43
|
+
};
|
|
44
|
+
export type Name = Factory<'name'>;
|
|
45
|
+
export type Tags = Factory<'tags'>;
|
|
46
|
+
export type Errors = Factory<'errors'>;
|
|
47
|
+
export {};
|
|
48
|
+
}
|
|
44
49
|
type Value = {
|
|
45
50
|
type: 'value';
|
|
46
51
|
path: string[];
|
|
@@ -12,8 +12,7 @@ export declare class CollectionModel {
|
|
|
12
12
|
* @param updates - a collection of updates to be applied to this collection.
|
|
13
13
|
*/
|
|
14
14
|
update(updates: ReadonlyArray<Collection.Update>): void;
|
|
15
|
-
private
|
|
16
|
-
private updateTags;
|
|
15
|
+
private updateCollection;
|
|
17
16
|
private updateObjectInsert;
|
|
18
17
|
private updateArrayInsert;
|
|
19
18
|
private updateArrayDelete;
|
|
@@ -34,11 +34,8 @@ class CollectionModel {
|
|
|
34
34
|
// apply updates
|
|
35
35
|
updates.forEach(update => {
|
|
36
36
|
switch (update.type) {
|
|
37
|
-
case '
|
|
38
|
-
this.
|
|
39
|
-
break;
|
|
40
|
-
case 'tags':
|
|
41
|
-
this.updateTags(update);
|
|
37
|
+
case 'collection':
|
|
38
|
+
this.updateCollection(update);
|
|
42
39
|
break;
|
|
43
40
|
case 'object.insert':
|
|
44
41
|
this.updateObjectInsert(update);
|
|
@@ -57,18 +54,15 @@ class CollectionModel {
|
|
|
57
54
|
break;
|
|
58
55
|
}
|
|
59
56
|
});
|
|
60
|
-
// finally, sync the model
|
|
61
|
-
this.sync();
|
|
62
|
-
}
|
|
63
|
-
updateName(update) {
|
|
64
|
-
// replace name
|
|
65
|
-
const { data: collection } = this;
|
|
66
|
-
collection.name = update.name;
|
|
67
57
|
}
|
|
68
|
-
|
|
69
|
-
//
|
|
70
|
-
const
|
|
71
|
-
|
|
58
|
+
updateCollection(update) {
|
|
59
|
+
// clear value if updated value is null
|
|
60
|
+
const collection = this.data;
|
|
61
|
+
// if (update.value === null) {
|
|
62
|
+
// delete collection[update.property]
|
|
63
|
+
// }
|
|
64
|
+
// update value
|
|
65
|
+
collection[update.property] = update.value;
|
|
72
66
|
}
|
|
73
67
|
updateObjectInsert(_a) {
|
|
74
68
|
var { value } = _a, update = __rest(_a, ["value"]);
|
package/dist/schema/Page.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { StringKeyOf, Tagged } from 'type-fest';
|
|
2
2
|
import { Language, Localized } from '../regionalization';
|
|
3
|
-
import { PartialBy } from '../types';
|
|
3
|
+
import { PartialBy, UndefinedToNull } from '../types';
|
|
4
4
|
import { Asset } from './Asset';
|
|
5
5
|
import { Block } from './Block';
|
|
6
6
|
import type { ChangeSet } from './ChangeSet';
|
|
@@ -50,7 +50,6 @@ export declare namespace Page {
|
|
|
50
50
|
namespace Update {
|
|
51
51
|
type Page = Page.Name | Page.Tags | Page.Slug | Page.Url | Page.Preview | Page.Errors | Page.Publication;
|
|
52
52
|
namespace Page {
|
|
53
|
-
type UndefinedToNull<T> = T extends undefined ? null : T;
|
|
54
53
|
type Factory<TProp extends keyof Data> = {
|
|
55
54
|
type: 'page';
|
|
56
55
|
property: TProp;
|
package/dist/schema/PageModel.js
CHANGED
|
@@ -98,12 +98,12 @@ class PageModel {
|
|
|
98
98
|
});
|
|
99
99
|
}
|
|
100
100
|
updatePage(update) {
|
|
101
|
-
// clear value
|
|
101
|
+
// clear value if updated value is null
|
|
102
102
|
const page = this.data;
|
|
103
103
|
if (update.value === null) {
|
|
104
104
|
delete page[update.property];
|
|
105
105
|
}
|
|
106
|
-
// update value
|
|
106
|
+
// otherwise update value
|
|
107
107
|
else {
|
|
108
108
|
page[update.property] = update.value;
|
|
109
109
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Tagged } from 'type-fest';
|
|
2
2
|
import { RequiredBy } from '../types';
|
|
3
3
|
import type { Page } from './Page';
|
|
4
|
-
export type PageSnapshot = RequiredBy<Pick<Page.Data
|
|
4
|
+
export type PageSnapshot = RequiredBy<Pick<Page.Data<any>, Exclude<Page.Data.Props.Id, 'id'> | Page.Data.Props.Content | 'createdOn' | 'updatedOn' | 'changeSetId' | 'publication'>, 'changeSetId'> & {
|
|
5
5
|
id: PageSnapshot.Id;
|
|
6
6
|
};
|
|
7
7
|
export declare namespace PageSnapshot {
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export type UndefinedToNull<T> = T extends undefined ? null : T;
|
package/dist/types/index.d.ts
CHANGED
package/dist/types/index.js
CHANGED
|
@@ -85,7 +85,7 @@ export declare namespace BlockLayout {
|
|
|
85
85
|
namespace FullBleed {
|
|
86
86
|
function parse(value: string, fallback?: boolean): boolean;
|
|
87
87
|
}
|
|
88
|
-
type MobileOrder = 'first' | 'last';
|
|
88
|
+
type MobileOrder = 'first' | 'last' | 'auto';
|
|
89
89
|
namespace MobileOrder {
|
|
90
90
|
const values: ReadonlyArray<MobileOrder>;
|
|
91
91
|
function parse(value: string, fallback?: MobileOrder): MobileOrder | undefined;
|
|
@@ -216,14 +216,19 @@ var BlockLayout;
|
|
|
216
216
|
(function (ResponsiveValue) {
|
|
217
217
|
function parse({ element, property, parser, fallback: fallbackRaw }) {
|
|
218
218
|
var _a, _b;
|
|
219
|
+
// capture base
|
|
220
|
+
const { attributes } = element;
|
|
221
|
+
const fallbackBase = typeof fallbackRaw === 'string' || typeof fallbackRaw === 'boolean'
|
|
222
|
+
? fallbackRaw
|
|
223
|
+
: fallbackRaw.base;
|
|
224
|
+
const base = parser(attributes[property], fallbackBase);
|
|
219
225
|
// normalize the fallback
|
|
220
226
|
const fallback = typeof fallbackRaw === 'string' || typeof fallbackRaw === 'boolean'
|
|
221
|
-
? { base
|
|
222
|
-
: { base
|
|
227
|
+
? { base, mobile: base, desktop: base }
|
|
228
|
+
: { base, mobile: (_a = fallbackRaw.mobile) !== null && _a !== void 0 ? _a : base, desktop: (_b = fallbackRaw.desktop) !== null && _b !== void 0 ? _b : base };
|
|
223
229
|
// fetch the values from the element
|
|
224
|
-
const { attributes } = element;
|
|
225
230
|
return {
|
|
226
|
-
base
|
|
231
|
+
base,
|
|
227
232
|
mobile: parser(attributes[`${property}Mobile`], fallback.mobile),
|
|
228
233
|
desktop: parser(attributes[`${property}Desktop`], fallback.desktop)
|
|
229
234
|
};
|
|
@@ -375,7 +380,7 @@ function parsePanel(element) {
|
|
|
375
380
|
}
|
|
376
381
|
function parseItemAttributes(attributes) {
|
|
377
382
|
return {
|
|
378
|
-
mobileOrder: BlockLayout.MobileOrder.parse(attributes['mobileOrder']),
|
|
383
|
+
mobileOrder: BlockLayout.MobileOrder.parse(attributes['mobileOrder'], 'auto'),
|
|
379
384
|
alignX: BlockLayout.Alignment.parse(attributes['alignX'], 'start'),
|
|
380
385
|
alignY: BlockLayout.Alignment.parse(attributes['alignY'], 'start'),
|
|
381
386
|
size: BlockLayout.Size.parse(attributes['size'], 'full')
|
|
@@ -17,6 +17,7 @@ export declare class Field<TSchema extends Schema.Field.Type = Schema.Field.Type
|
|
|
17
17
|
private _sandboxed;
|
|
18
18
|
private _sandboxedValue;
|
|
19
19
|
private readonly _validator;
|
|
20
|
+
private _customValidator?;
|
|
20
21
|
private _errors;
|
|
21
22
|
private _optIn?;
|
|
22
23
|
private _optOut?;
|
|
@@ -29,6 +30,8 @@ export declare class Field<TSchema extends Schema.Field.Type = Schema.Field.Type
|
|
|
29
30
|
get error(): FieldValidator.Error | undefined;
|
|
30
31
|
getErrors(level: FieldValidator.Error.Level): readonly FieldValidator.Error[];
|
|
31
32
|
get errors(): ReadonlyArray<FieldValidator.Error>;
|
|
33
|
+
get customValidator(): FieldValidator | undefined;
|
|
34
|
+
set customValidator(validator: FieldValidator | undefined);
|
|
32
35
|
get defaultValue(): Field.Value<TSchema> | undefined;
|
|
33
36
|
get initialValue(): Field.Value<TSchema> | undefined;
|
|
34
37
|
get hasValue(): boolean;
|
|
@@ -71,6 +74,7 @@ export declare namespace Field {
|
|
|
71
74
|
publishedValue?: Value<TSchema>;
|
|
72
75
|
initialValue?: Value<TSchema>;
|
|
73
76
|
required: boolean;
|
|
77
|
+
customValidator?: FieldValidator;
|
|
74
78
|
};
|
|
75
79
|
type Value<TSchema extends Schema.Field.Type = Schema.Field.Type> = Schema.Field.Data<TSchema>;
|
|
76
80
|
interface Event extends EventBus.Event<'Field', Event.Type> {
|
package/dist/ui/fields/Field.js
CHANGED
|
@@ -56,8 +56,12 @@ class Field {
|
|
|
56
56
|
this._editing = false;
|
|
57
57
|
this._sandboxed = false;
|
|
58
58
|
this._validator = FieldValidator_1.FieldValidator.create(this);
|
|
59
|
+
this._customValidator = args.customValidator;
|
|
59
60
|
// validate
|
|
60
61
|
this._errors = this._validator.validate(this, this._initialValue);
|
|
62
|
+
if (this._customValidator) {
|
|
63
|
+
this._errors = [...this._errors, ...this._customValidator.validate(this, this._initialValue)];
|
|
64
|
+
}
|
|
61
65
|
}
|
|
62
66
|
get events$() {
|
|
63
67
|
return this.eventBus.events$.pipe((0, rxjs_1.filter)(Field.Event.filter), (0, rxjs_1.filter)(e => e.field === this));
|
|
@@ -82,11 +86,32 @@ class Field {
|
|
|
82
86
|
return FieldValidator_1.FieldValidator.Error.mostRelevant(this._errors);
|
|
83
87
|
}
|
|
84
88
|
getErrors(level) {
|
|
85
|
-
|
|
89
|
+
// filter with fixed validator
|
|
90
|
+
const { _errors, _validator, _customValidator } = this;
|
|
91
|
+
let errors = _validator.filter(_errors, level);
|
|
92
|
+
// then with custom (if available)
|
|
93
|
+
if (_customValidator) {
|
|
94
|
+
errors = _customValidator.filter(errors, level);
|
|
95
|
+
}
|
|
96
|
+
// return errors
|
|
97
|
+
return errors;
|
|
86
98
|
}
|
|
87
99
|
get errors() {
|
|
88
100
|
return this._errors;
|
|
89
101
|
}
|
|
102
|
+
get customValidator() {
|
|
103
|
+
return this._customValidator;
|
|
104
|
+
}
|
|
105
|
+
set customValidator(validator) {
|
|
106
|
+
// ignore if unchanged
|
|
107
|
+
if (this._customValidator === validator) {
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
// update validator
|
|
111
|
+
this._customValidator = validator;
|
|
112
|
+
// revalidate
|
|
113
|
+
this.validate();
|
|
114
|
+
}
|
|
90
115
|
get defaultValue() {
|
|
91
116
|
// no default if it's not required
|
|
92
117
|
const { schema } = this;
|
|
@@ -231,8 +256,13 @@ class Field {
|
|
|
231
256
|
delete this._shouldFocus;
|
|
232
257
|
}
|
|
233
258
|
validate(silent = false) {
|
|
234
|
-
// validate (
|
|
235
|
-
const
|
|
259
|
+
// validate (use custom if available)
|
|
260
|
+
const { _value, _validator, customValidator } = this;
|
|
261
|
+
let errors = _validator.validate(this, _value);
|
|
262
|
+
if (customValidator) {
|
|
263
|
+
errors = [...errors, ...customValidator.validate(this, _value)];
|
|
264
|
+
}
|
|
265
|
+
// skip if nothing has changed
|
|
236
266
|
if (utils_1.Value.equals(errors, this._errors)) {
|
|
237
267
|
return this._errors;
|
|
238
268
|
}
|
|
@@ -18,7 +18,8 @@
|
|
|
18
18
|
"date.maxDate": "${label} cannot be after ${maxDate}",
|
|
19
19
|
"timestamp": "${label} is not a valid date/time",
|
|
20
20
|
"timestamp.minTime": "${label} cannot be before ${minTime}",
|
|
21
|
-
"timestamp.maxTime": "${label} cannot be after ${maxTime}"
|
|
21
|
+
"timestamp.maxTime": "${label} cannot be after ${maxTime}",
|
|
22
|
+
"duplicate": "${label} is already in use"
|
|
22
23
|
},
|
|
23
24
|
"fr": {
|
|
24
25
|
"required": "${label} is required",
|
|
@@ -39,6 +40,7 @@
|
|
|
39
40
|
"date.maxDate": "${label} cannot be after ${maxDate}",
|
|
40
41
|
"timestamp": "${label} is not a valid date/time",
|
|
41
42
|
"timestamp.minTime": "${label} cannot be before ${minTime}",
|
|
42
|
-
"timestamp.maxTime": "${label} cannot be after ${maxTime}"
|
|
43
|
+
"timestamp.maxTime": "${label} cannot be after ${maxTime}",
|
|
44
|
+
"duplicate": "${label} est déjà utilisé"
|
|
43
45
|
}
|
|
44
46
|
}
|
package/dist/ui/fields/index.js
CHANGED
|
@@ -21,3 +21,4 @@ __exportStar(require("./FieldModel"), exports);
|
|
|
21
21
|
__exportStar(require("./FieldSerializer"), exports);
|
|
22
22
|
__exportStar(require("./FieldValidator"), exports);
|
|
23
23
|
__exportStar(require("./ObjectField"), exports);
|
|
24
|
+
__exportStar(require("./validators/ValidatorHelper"), exports);
|