@cratis/scene.engine 4.7.0 → 4.9.0
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/BindingDiagnostic.ts +11 -0
- package/BindingScope.ts +16 -0
- package/dist/cjs/index.js +12 -0
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/resolveBindingExpression.js +51 -0
- package/dist/cjs/resolveBindingExpression.js.map +1 -0
- package/dist/cjs/templateApplicability.js +68 -0
- package/dist/cjs/templateApplicability.js.map +1 -0
- package/dist/cjs/validateBindingExpression.js +70 -0
- package/dist/cjs/validateBindingExpression.js.map +1 -0
- package/dist/cjs/validateNavigationDestinations.js +48 -0
- package/dist/cjs/validateNavigationDestinations.js.map +1 -0
- package/dist/esm/BindingDiagnostic.d.ts +6 -0
- package/dist/esm/BindingDiagnostic.d.ts.map +1 -0
- package/dist/esm/BindingDiagnostic.js +2 -0
- package/dist/esm/BindingDiagnostic.js.map +1 -0
- package/dist/esm/BindingScope.d.ts +6 -0
- package/dist/esm/BindingScope.d.ts.map +1 -0
- package/dist/esm/BindingScope.js +2 -0
- package/dist/esm/BindingScope.js.map +1 -0
- package/dist/esm/index.d.ts +6 -0
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js +4 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/resolveBindingExpression.d.ts +5 -0
- package/dist/esm/resolveBindingExpression.d.ts.map +1 -0
- package/dist/esm/resolveBindingExpression.js +48 -0
- package/dist/esm/resolveBindingExpression.js.map +1 -0
- package/dist/esm/templateApplicability.d.ts +8 -0
- package/dist/esm/templateApplicability.d.ts.map +1 -0
- package/dist/esm/templateApplicability.js +63 -0
- package/dist/esm/templateApplicability.js.map +1 -0
- package/dist/esm/tsconfig.tsbuildinfo +1 -1
- package/dist/esm/validateBindingExpression.d.ts +8 -0
- package/dist/esm/validateBindingExpression.d.ts.map +1 -0
- package/dist/esm/validateBindingExpression.js +68 -0
- package/dist/esm/validateBindingExpression.js.map +1 -0
- package/dist/esm/validateNavigationDestinations.d.ts +10 -0
- package/dist/esm/validateNavigationDestinations.d.ts.map +1 -0
- package/dist/esm/validateNavigationDestinations.js +46 -0
- package/dist/esm/validateNavigationDestinations.js.map +1 -0
- package/index.ts +6 -0
- package/package.json +3 -3
- package/resolveBindingExpression.ts +55 -0
- package/templateApplicability.ts +75 -0
- package/validateBindingExpression.ts +78 -0
- package/validateNavigationDestinations.ts +43 -0
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
// Copyright (c) Cratis. All rights reserved.
|
|
2
|
+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* A binding validation problem that preserves the authored model and tells a designer what to fix.
|
|
6
|
+
*/
|
|
7
|
+
export interface BindingDiagnostic {
|
|
8
|
+
code: string;
|
|
9
|
+
message: string;
|
|
10
|
+
path?: string;
|
|
11
|
+
}
|
package/BindingScope.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
// Copyright (c) Cratis. All rights reserved.
|
|
2
|
+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Runtime values available to resolve typed bindings.
|
|
6
|
+
*/
|
|
7
|
+
export interface BindingScope {
|
|
8
|
+
/** Inherited effective data context for the element. */
|
|
9
|
+
dataContext?: unknown;
|
|
10
|
+
|
|
11
|
+
/** Query results keyed by the model's query binding name. */
|
|
12
|
+
queryResults?: Record<string, unknown>;
|
|
13
|
+
|
|
14
|
+
/** Component output properties keyed by stable element id. */
|
|
15
|
+
componentOutputs?: Record<string, Record<string, unknown>>;
|
|
16
|
+
}
|
package/dist/cjs/index.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
var resolveBindingExpression = require('./resolveBindingExpression.js');
|
|
4
|
+
var validateBindingExpression = require('./validateBindingExpression.js');
|
|
3
5
|
var renderElement = require('./renderElement.js');
|
|
4
6
|
var elementKind = require('./elementKind.js');
|
|
5
7
|
var panelKind = require('./panelKind.js');
|
|
@@ -20,11 +22,13 @@ var packageVersionRange = require('./packageVersionRange.js');
|
|
|
20
22
|
var resolvePackageDependencies = require('./resolvePackageDependencies.js');
|
|
21
23
|
var packageCatalog = require('./packageCatalog.js');
|
|
22
24
|
var resolveScreenTemplates = require('./resolveScreenTemplates.js');
|
|
25
|
+
var templateApplicability = require('./templateApplicability.js');
|
|
23
26
|
var buildStarterProfile = require('./buildStarterProfile.js');
|
|
24
27
|
var incompatibleStarterThemes = require('./incompatibleStarterThemes.js');
|
|
25
28
|
var runActions = require('./runActions.js');
|
|
26
29
|
var resolveBehaviors = require('./resolveBehaviors.js');
|
|
27
30
|
var resolveStrings = require('./resolveStrings.js');
|
|
31
|
+
var validateNavigationDestinations = require('./validateNavigationDestinations.js');
|
|
28
32
|
var diagnostics = require('./editing/diagnostics.js');
|
|
29
33
|
var nodeIds = require('./editing/nodeIds.js');
|
|
30
34
|
var layoutTypeDescriptors = require('./editing/layoutTypeDescriptors.js');
|
|
@@ -45,6 +49,9 @@ var collectIconUsages = require('./editing/collectIconUsages.js');
|
|
|
45
49
|
|
|
46
50
|
|
|
47
51
|
|
|
52
|
+
exports.createBindingResolver = resolveBindingExpression.createBindingResolver;
|
|
53
|
+
exports.resolveBindingExpression = resolveBindingExpression.resolveBindingExpression;
|
|
54
|
+
exports.validateBindingExpression = validateBindingExpression.validateBindingExpression;
|
|
48
55
|
exports.renderElement = renderElement.renderElement;
|
|
49
56
|
exports.isContentControl = elementKind.isContentControl;
|
|
50
57
|
exports.isExternalComponent = elementKind.isExternalComponent;
|
|
@@ -88,6 +95,10 @@ exports.packagesOfKind = packageCatalog.packagesOfKind;
|
|
|
88
95
|
exports.toComponentCatalog = packageCatalog.toComponentCatalog;
|
|
89
96
|
exports.isScreenTemplateResolutionValid = resolveScreenTemplates.isScreenTemplateResolutionValid;
|
|
90
97
|
exports.resolveScreenTemplates = resolveScreenTemplates.resolveScreenTemplates;
|
|
98
|
+
exports.filterApplicableScreenTemplates = templateApplicability.filterApplicableScreenTemplates;
|
|
99
|
+
exports.validateDialogTemplateApplicability = templateApplicability.validateDialogTemplateApplicability;
|
|
100
|
+
exports.validateLayoutApplicability = templateApplicability.validateLayoutApplicability;
|
|
101
|
+
exports.validateScreenTemplateApplicability = templateApplicability.validateScreenTemplateApplicability;
|
|
91
102
|
exports.buildStarterProfile = buildStarterProfile.buildStarterProfile;
|
|
92
103
|
exports.incompatibleStarterThemes = incompatibleStarterThemes.incompatibleStarterThemes;
|
|
93
104
|
exports.InteractionStop = runActions.InteractionStop;
|
|
@@ -100,6 +111,7 @@ exports.resolveIntervalBehaviors = resolveBehaviors.resolveIntervalBehaviors;
|
|
|
100
111
|
exports.isStringsReference = resolveStrings.isStringsReference;
|
|
101
112
|
exports.resolveStringsInElement = resolveStrings.resolveStringsInElement;
|
|
102
113
|
exports.resolveStringsValue = resolveStrings.resolveStringsValue;
|
|
114
|
+
exports.validateNavigationDestinations = validateNavigationDestinations.validateNavigationDestinations;
|
|
103
115
|
exports.errorDiagnostic = diagnostics.errorDiagnostic;
|
|
104
116
|
exports.hasErrors = diagnostics.hasErrors;
|
|
105
117
|
exports.warningDiagnostic = diagnostics.warningDiagnostic;
|
package/dist/cjs/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var scene_model = require('@cratis/scene.model');
|
|
4
|
+
|
|
5
|
+
// Copyright (c) Cratis. All rights reserved.
|
|
6
|
+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
|
7
|
+
/**
|
|
8
|
+
* Resolves a typed binding against the shared runtime binding scope.
|
|
9
|
+
*/ function resolveBindingExpression(binding, scope) {
|
|
10
|
+
const kind = binding.kind ?? scene_model.BindingSourceKind.DataContext;
|
|
11
|
+
if (kind === scene_model.BindingSourceKind.Literal) return binding.value;
|
|
12
|
+
const source = sourceValue(binding, scope, kind);
|
|
13
|
+
const value = readPath(source, sourcePath(binding, kind));
|
|
14
|
+
if (value !== null && value !== undefined) return value;
|
|
15
|
+
if (binding.nullBehavior === scene_model.BindingNullBehavior.Preserve) return undefined;
|
|
16
|
+
if (binding.nullBehavior === scene_model.BindingNullBehavior.Clear) return null;
|
|
17
|
+
return value;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Creates a legacy resolver function from a binding scope.
|
|
21
|
+
*/ function createBindingResolver(scope) {
|
|
22
|
+
return (binding)=>resolveBindingExpression(binding, scope);
|
|
23
|
+
}
|
|
24
|
+
function sourceValue(binding, scope, kind) {
|
|
25
|
+
switch(kind){
|
|
26
|
+
case scene_model.BindingSourceKind.DataContext:
|
|
27
|
+
return scope.dataContext;
|
|
28
|
+
case scene_model.BindingSourceKind.QueryResult:
|
|
29
|
+
return binding.query ? scope.queryResults?.[binding.query] : undefined;
|
|
30
|
+
case scene_model.BindingSourceKind.ComponentProperty:
|
|
31
|
+
return binding.componentId ? scope.componentOutputs?.[binding.componentId] : undefined;
|
|
32
|
+
case scene_model.BindingSourceKind.Literal:
|
|
33
|
+
return binding.value;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
function sourcePath(binding, kind) {
|
|
37
|
+
if (kind === scene_model.BindingSourceKind.ComponentProperty) return binding.componentPropertyPath ?? binding.path;
|
|
38
|
+
return binding.path;
|
|
39
|
+
}
|
|
40
|
+
function readPath(source, path) {
|
|
41
|
+
if (!path) return source;
|
|
42
|
+
return path.split('.').reduce((current, segment)=>{
|
|
43
|
+
if (current === null || current === undefined) return undefined;
|
|
44
|
+
if (typeof current !== 'object') return undefined;
|
|
45
|
+
return current[segment];
|
|
46
|
+
}, source);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
exports.createBindingResolver = createBindingResolver;
|
|
50
|
+
exports.resolveBindingExpression = resolveBindingExpression;
|
|
51
|
+
//# sourceMappingURL=resolveBindingExpression.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolveBindingExpression.js","sources":["../../resolveBindingExpression.ts"],"sourcesContent":["// Copyright (c) Cratis. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\nimport { BindingExpression, BindingNullBehavior, BindingSourceKind } from '@cratis/scene.model';\nimport { BindingScope } from './BindingScope';\n\n/**\n * Resolves a typed binding against the shared runtime binding scope.\n */\nexport function resolveBindingExpression(binding: BindingExpression, scope: BindingScope): unknown {\n const kind = binding.kind ?? BindingSourceKind.DataContext;\n if (kind === BindingSourceKind.Literal) return binding.value;\n\n const source = sourceValue(binding, scope, kind);\n const value = readPath(source, sourcePath(binding, kind));\n if (value !== null && value !== undefined) return value;\n\n if (binding.nullBehavior === BindingNullBehavior.Preserve) return undefined;\n if (binding.nullBehavior === BindingNullBehavior.Clear) return null;\n return value;\n}\n\n/**\n * Creates a legacy resolver function from a binding scope.\n */\nexport function createBindingResolver(scope: BindingScope): (binding: BindingExpression) => unknown {\n return binding => resolveBindingExpression(binding, scope);\n}\n\nfunction sourceValue(binding: BindingExpression, scope: BindingScope, kind: BindingSourceKind): unknown {\n switch (kind) {\n case BindingSourceKind.DataContext:\n return scope.dataContext;\n case BindingSourceKind.QueryResult:\n return binding.query ? scope.queryResults?.[binding.query] : undefined;\n case BindingSourceKind.ComponentProperty:\n return binding.componentId ? scope.componentOutputs?.[binding.componentId] : undefined;\n case BindingSourceKind.Literal:\n return binding.value;\n }\n}\n\nfunction sourcePath(binding: BindingExpression, kind: BindingSourceKind): string {\n if (kind === BindingSourceKind.ComponentProperty) return binding.componentPropertyPath ?? binding.path;\n return binding.path;\n}\n\nfunction readPath(source: unknown, path: string): unknown {\n if (!path) return source;\n return path.split('.').reduce<unknown>((current, segment) => {\n if (current === null || current === undefined) return undefined;\n if (typeof current !== 'object') return undefined;\n return (current as Record<string, unknown>)[segment];\n }, source);\n}\n"],"names":["resolveBindingExpression","binding","scope","kind","BindingSourceKind","DataContext","Literal","value","source","sourceValue","readPath","sourcePath","undefined","nullBehavior","BindingNullBehavior","Preserve","Clear","createBindingResolver","dataContext","QueryResult","query","queryResults","ComponentProperty","componentId","componentOutputs","componentPropertyPath","path","split","reduce","current","segment"],"mappings":";;;;AAAA;AACA;AAKA;;AAEC,IACM,SAASA,wBAAAA,CAAyBC,OAA0B,EAAEC,KAAmB,EAAA;AACpF,IAAA,MAAMC,IAAAA,GAAOF,OAAAA,CAAQE,IAAI,IAAIC,8BAAkBC,WAAW;AAC1D,IAAA,IAAIF,SAASC,6BAAAA,CAAkBE,OAAO,EAAE,OAAOL,QAAQM,KAAK;IAE5D,MAAMC,MAAAA,GAASC,WAAAA,CAAYR,OAAAA,EAASC,KAAAA,EAAOC,IAAAA,CAAAA;AAC3C,IAAA,MAAMI,KAAAA,GAAQG,QAAAA,CAASF,MAAAA,EAAQG,UAAAA,CAAWV,OAAAA,EAASE,IAAAA,CAAAA,CAAAA;AACnD,IAAA,IAAII,KAAAA,KAAU,IAAA,IAAQA,KAAAA,KAAUK,SAAAA,EAAW,OAAOL,KAAAA;AAElD,IAAA,IAAIN,QAAQY,YAAY,KAAKC,+BAAAA,CAAoBC,QAAQ,EAAE,OAAOH,SAAAA;AAClE,IAAA,IAAIX,QAAQY,YAAY,KAAKC,+BAAAA,CAAoBE,KAAK,EAAE,OAAO,IAAA;IAC/D,OAAOT,KAAAA;AACX;AAEA;;IAGO,SAASU,qBAAAA,CAAsBf,KAAmB,EAAA;IACrD,OAAOD,CAAAA,OAAAA,GAAWD,wBAAAA,CAAyBC,OAAAA,EAASC,KAAAA,CAAAA;AACxD;AAEA,SAASO,WAAAA,CAAYR,OAA0B,EAAEC,KAAmB,EAAEC,IAAuB,EAAA;IACzF,OAAQA,IAAAA;AACJ,QAAA,KAAKC,8BAAkBC,WAAW;AAC9B,YAAA,OAAOH,MAAMgB,WAAW;AAC5B,QAAA,KAAKd,8BAAkBe,WAAW;YAC9B,OAAOlB,OAAAA,CAAQmB,KAAK,GAAGlB,KAAAA,CAAMmB,YAAY,GAAGpB,OAAAA,CAAQmB,KAAK,CAAC,GAAGR,SAAAA;AACjE,QAAA,KAAKR,8BAAkBkB,iBAAiB;YACpC,OAAOrB,OAAAA,CAAQsB,WAAW,GAAGrB,KAAAA,CAAMsB,gBAAgB,GAAGvB,OAAAA,CAAQsB,WAAW,CAAC,GAAGX,SAAAA;AACjF,QAAA,KAAKR,8BAAkBE,OAAO;AAC1B,YAAA,OAAOL,QAAQM,KAAK;AAC5B;AACJ;AAEA,SAASI,UAAAA,CAAWV,OAA0B,EAAEE,IAAuB,EAAA;IACnE,IAAIA,IAAAA,KAASC,8BAAkBkB,iBAAiB,EAAE,OAAOrB,OAAAA,CAAQwB,qBAAqB,IAAIxB,OAAAA,CAAQyB,IAAI;AACtG,IAAA,OAAOzB,QAAQyB,IAAI;AACvB;AAEA,SAAShB,QAAAA,CAASF,MAAe,EAAEkB,IAAY,EAAA;IAC3C,IAAI,CAACA,MAAM,OAAOlB,MAAAA;AAClB,IAAA,OAAOkB,KAAKC,KAAK,CAAC,KAAKC,MAAM,CAAU,CAACC,OAAAA,EAASC,OAAAA,GAAAA;AAC7C,QAAA,IAAID,OAAAA,KAAY,IAAA,IAAQA,OAAAA,KAAYjB,SAAAA,EAAW,OAAOA,SAAAA;QACtD,IAAI,OAAOiB,OAAAA,KAAY,QAAA,EAAU,OAAOjB,SAAAA;QACxC,OAAQiB,OAAmC,CAACC,OAAAA,CAAQ;IACxD,CAAA,EAAGtB,MAAAA,CAAAA;AACP;;;"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var scene_model = require('@cratis/scene.model');
|
|
4
|
+
|
|
5
|
+
// Copyright (c) Cratis. All rights reserved.
|
|
6
|
+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
|
7
|
+
/** Validates application-shell selection without introducing a competing shell model. */ function validateLayoutApplicability(layout, scope) {
|
|
8
|
+
return layout ? validateRole(layout.name, 'Layout', layout.metadata, scope) : [];
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Validates selection at any depth of the application hierarchy, including qualified fitsSlot names.
|
|
12
|
+
* Undefined represents outlet-only composition and is valid. Invalid author input is never rewritten.
|
|
13
|
+
*/ function validateScreenTemplateApplicability(template, scope, container) {
|
|
14
|
+
if (!template) return [];
|
|
15
|
+
const problems = validateRole(template.name, 'ScreenTemplate', template.metadata, scope);
|
|
16
|
+
if (template.fitsSlot !== undefined) {
|
|
17
|
+
const separator = template.fitsSlot.lastIndexOf('.');
|
|
18
|
+
const qualifier = separator < 0 ? undefined : template.fitsSlot.slice(0, separator);
|
|
19
|
+
const slot = separator < 0 ? template.fitsSlot : template.fitsSlot.slice(separator + 1);
|
|
20
|
+
if (!container || qualifier !== undefined && qualifier !== container.name || !container.slots.some((candidate)=>candidate.name === slot)) {
|
|
21
|
+
problems.push(`Template '${template.name}' does not fit slot '${template.fitsSlot}' on '${container?.name ?? '(no container)'}'`);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
return problems;
|
|
25
|
+
}
|
|
26
|
+
/** Validates an overlay template separately from slot-based screen composition. */ function validateDialogTemplateApplicability(template, scope) {
|
|
27
|
+
return template ? validateRole(template.name, 'DialogTemplate', template.metadata, scope) : [];
|
|
28
|
+
}
|
|
29
|
+
/** The shared picker predicate uses exactly the same rules as validation on apply. */ function filterApplicableScreenTemplates(templates, scope, container) {
|
|
30
|
+
return templates.filter((template)=>validateScreenTemplateApplicability(template, scope, container).length === 0);
|
|
31
|
+
}
|
|
32
|
+
function validateRole(name, kind, metadata, scope) {
|
|
33
|
+
const problems = [];
|
|
34
|
+
if (!Object.values(scene_model.TemplateScope).includes(scope)) {
|
|
35
|
+
problems.push(`Template '${name}' has unknown target scope '${scope}'`);
|
|
36
|
+
} else if (kind === 'Layout' !== (scope === scene_model.TemplateScope.Application)) {
|
|
37
|
+
problems.push(`Template '${name}' of kind '${kind}' cannot be applied at scope '${scope}'`);
|
|
38
|
+
}
|
|
39
|
+
if (metadata?.type === 'ApplicationShell' && kind !== 'Layout') {
|
|
40
|
+
problems.push(`Template '${name}' of type 'ApplicationShell' must be a Layout`);
|
|
41
|
+
}
|
|
42
|
+
if (metadata?.type === 'Dialog' && kind !== 'DialogTemplate') {
|
|
43
|
+
problems.push(`Template '${name}' of type 'Dialog' must be a DialogTemplate`);
|
|
44
|
+
}
|
|
45
|
+
if (kind === 'Layout' && [
|
|
46
|
+
'Workspace',
|
|
47
|
+
'List',
|
|
48
|
+
'Detail',
|
|
49
|
+
'Form'
|
|
50
|
+
].includes(metadata?.type ?? '')) {
|
|
51
|
+
problems.push(`Template '${name}' of type '${metadata?.type}' must not be a Layout`);
|
|
52
|
+
}
|
|
53
|
+
for (const declaredScope of metadata?.scopes ?? []){
|
|
54
|
+
if (!Object.values(scene_model.TemplateScope).includes(declaredScope)) {
|
|
55
|
+
problems.push(`Template '${name}' declares unknown scope '${declaredScope}'`);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
if (metadata?.scopes !== undefined && !metadata.scopes.includes(scope)) {
|
|
59
|
+
problems.push(`Template '${name}' does not declare scope '${scope}'`);
|
|
60
|
+
}
|
|
61
|
+
return problems;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
exports.filterApplicableScreenTemplates = filterApplicableScreenTemplates;
|
|
65
|
+
exports.validateDialogTemplateApplicability = validateDialogTemplateApplicability;
|
|
66
|
+
exports.validateLayoutApplicability = validateLayoutApplicability;
|
|
67
|
+
exports.validateScreenTemplateApplicability = validateScreenTemplateApplicability;
|
|
68
|
+
//# sourceMappingURL=templateApplicability.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"templateApplicability.js","sources":["../../templateApplicability.ts"],"sourcesContent":["// Copyright (c) Cratis. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\nimport { DialogTemplate, Layout, ScreenTemplate, TemplateMetadata, TemplateScope } from '@cratis/scene.model';\n\ntype TemplateKind = 'Layout' | 'ScreenTemplate' | 'DialogTemplate';\ntype TemplateContainer = Pick<Layout, 'name' | 'slots'>;\n\n/** Validates application-shell selection without introducing a competing shell model. */\nexport function validateLayoutApplicability(layout: Layout | undefined, scope: TemplateScope): string[] {\n return layout ? validateRole(layout.name, 'Layout', layout.metadata, scope) : [];\n}\n\n/**\n * Validates selection at any depth of the application hierarchy, including qualified fitsSlot names.\n * Undefined represents outlet-only composition and is valid. Invalid author input is never rewritten.\n */\nexport function validateScreenTemplateApplicability(\n template: ScreenTemplate | undefined,\n scope: TemplateScope,\n container?: TemplateContainer,\n): string[] {\n if (!template) return [];\n const problems = validateRole(template.name, 'ScreenTemplate', template.metadata, scope);\n if (template.fitsSlot !== undefined) {\n const separator = template.fitsSlot.lastIndexOf('.');\n const qualifier = separator < 0 ? undefined : template.fitsSlot.slice(0, separator);\n const slot = separator < 0 ? template.fitsSlot : template.fitsSlot.slice(separator + 1);\n if (!container || (qualifier !== undefined && qualifier !== container.name) || !container.slots.some(candidate => candidate.name === slot)) {\n problems.push(`Template '${template.name}' does not fit slot '${template.fitsSlot}' on '${container?.name ?? '(no container)'}'`);\n }\n }\n return problems;\n}\n\n/** Validates an overlay template separately from slot-based screen composition. */\nexport function validateDialogTemplateApplicability(template: DialogTemplate | undefined, scope: TemplateScope): string[] {\n return template ? validateRole(template.name, 'DialogTemplate', template.metadata, scope) : [];\n}\n\n/** The shared picker predicate uses exactly the same rules as validation on apply. */\nexport function filterApplicableScreenTemplates(\n templates: readonly ScreenTemplate[],\n scope: TemplateScope,\n container?: TemplateContainer,\n): ScreenTemplate[] {\n return templates.filter(template => validateScreenTemplateApplicability(template, scope, container).length === 0);\n}\n\nfunction validateRole(name: string, kind: TemplateKind, metadata: TemplateMetadata | undefined, scope: TemplateScope): string[] {\n const problems: string[] = [];\n if (!Object.values(TemplateScope).includes(scope)) {\n problems.push(`Template '${name}' has unknown target scope '${scope}'`);\n } else if ((kind === 'Layout') !== (scope === TemplateScope.Application)) {\n problems.push(`Template '${name}' of kind '${kind}' cannot be applied at scope '${scope}'`);\n }\n if (metadata?.type === 'ApplicationShell' && kind !== 'Layout') {\n problems.push(`Template '${name}' of type 'ApplicationShell' must be a Layout`);\n }\n if (metadata?.type === 'Dialog' && kind !== 'DialogTemplate') {\n problems.push(`Template '${name}' of type 'Dialog' must be a DialogTemplate`);\n }\n if (kind === 'Layout' && ['Workspace', 'List', 'Detail', 'Form'].includes(metadata?.type ?? '')) {\n problems.push(`Template '${name}' of type '${metadata?.type}' must not be a Layout`);\n }\n for (const declaredScope of metadata?.scopes ?? []) {\n if (!Object.values(TemplateScope).includes(declaredScope)) {\n problems.push(`Template '${name}' declares unknown scope '${declaredScope}'`);\n }\n }\n if (metadata?.scopes !== undefined && !metadata.scopes.includes(scope)) {\n problems.push(`Template '${name}' does not declare scope '${scope}'`);\n }\n return problems;\n}\n"],"names":["validateLayoutApplicability","layout","scope","validateRole","name","metadata","validateScreenTemplateApplicability","template","container","problems","fitsSlot","undefined","separator","lastIndexOf","qualifier","slice","slot","slots","some","candidate","push","validateDialogTemplateApplicability","filterApplicableScreenTemplates","templates","filter","length","kind","Object","values","TemplateScope","includes","Application","type","declaredScope","scopes"],"mappings":"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"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var scene_model = require('@cratis/scene.model');
|
|
4
|
+
var resolveBindingExpression = require('./resolveBindingExpression.js');
|
|
5
|
+
|
|
6
|
+
// Copyright (c) Cratis. All rights reserved.
|
|
7
|
+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
|
8
|
+
/**
|
|
9
|
+
* Validates one binding against available runtime scope and optional component dependency stack.
|
|
10
|
+
*/ function validateBindingExpression(binding, scope, options = {}) {
|
|
11
|
+
const diagnostics = [];
|
|
12
|
+
const kind = binding.kind ?? scene_model.BindingSourceKind.DataContext;
|
|
13
|
+
if (kind === scene_model.BindingSourceKind.QueryResult && !binding.query) {
|
|
14
|
+
diagnostics.push(problem('missingQuery', 'Query result bindings must name the query they read from.', 'query'));
|
|
15
|
+
}
|
|
16
|
+
if (kind === scene_model.BindingSourceKind.ComponentProperty) {
|
|
17
|
+
if (!binding.componentId) {
|
|
18
|
+
diagnostics.push(problem('missingComponent', 'Component property bindings must name the source component id.', 'componentId'));
|
|
19
|
+
} else if (!scope.componentOutputs?.[binding.componentId]) {
|
|
20
|
+
diagnostics.push(problem('unknownComponent', `No component output scope exists for '${binding.componentId}'.`, 'componentId'));
|
|
21
|
+
}
|
|
22
|
+
if (binding.componentId && options.targetElementId === binding.componentId) {
|
|
23
|
+
diagnostics.push(problem('bindingCycle', `Component '${binding.componentId}' cannot bind to its own output.`, 'componentId'));
|
|
24
|
+
}
|
|
25
|
+
if (binding.componentId && options.resolvingElementIds?.includes(binding.componentId)) {
|
|
26
|
+
diagnostics.push(problem('bindingCycle', `Binding to '${binding.componentId}' would create a component binding cycle.`, 'componentId'));
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
if (binding.mode === scene_model.BindingMode.TwoWay && kind !== scene_model.BindingSourceKind.ComponentProperty) {
|
|
30
|
+
diagnostics.push(problem('unsupportedTwoWayBinding', 'Two-way bindings require a component output source.', 'mode'));
|
|
31
|
+
}
|
|
32
|
+
if (binding.expectedValueType !== undefined) {
|
|
33
|
+
const value = resolveBindingExpression.resolveBindingExpression(binding, scope);
|
|
34
|
+
if (!matchesExpectedType(value, binding.expectedValueType)) {
|
|
35
|
+
diagnostics.push(problem('bindingTypeMismatch', `Binding value does not match expected ${binding.expectedValueType}.`, 'expectedValueType'));
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
return diagnostics;
|
|
39
|
+
}
|
|
40
|
+
function problem(code, message, path) {
|
|
41
|
+
return {
|
|
42
|
+
code,
|
|
43
|
+
message,
|
|
44
|
+
path
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
function matchesExpectedType(value, type) {
|
|
48
|
+
if (value === null || value === undefined) return true;
|
|
49
|
+
switch(type){
|
|
50
|
+
case scene_model.PropertyValueType.String:
|
|
51
|
+
case scene_model.PropertyValueType.Enum:
|
|
52
|
+
case scene_model.PropertyValueType.Icon:
|
|
53
|
+
case scene_model.PropertyValueType.Destination:
|
|
54
|
+
case scene_model.PropertyValueType.QueryReference:
|
|
55
|
+
return typeof value === 'string' || typeof value === 'object' && !Array.isArray(value);
|
|
56
|
+
case scene_model.PropertyValueType.Number:
|
|
57
|
+
return typeof value === 'number' && !Number.isNaN(value);
|
|
58
|
+
case scene_model.PropertyValueType.Boolean:
|
|
59
|
+
return typeof value === 'boolean';
|
|
60
|
+
case scene_model.PropertyValueType.Collection:
|
|
61
|
+
return Array.isArray(value);
|
|
62
|
+
case scene_model.PropertyValueType.Object:
|
|
63
|
+
return typeof value === 'object' && !Array.isArray(value);
|
|
64
|
+
case scene_model.PropertyValueType.Json:
|
|
65
|
+
return true;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
exports.validateBindingExpression = validateBindingExpression;
|
|
70
|
+
//# sourceMappingURL=validateBindingExpression.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validateBindingExpression.js","sources":["../../validateBindingExpression.ts"],"sourcesContent":["// Copyright (c) Cratis. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\nimport { BindingExpression, BindingMode, BindingSourceKind, PropertyValueType } from '@cratis/scene.model';\nimport { BindingDiagnostic } from './BindingDiagnostic';\nimport { BindingScope } from './BindingScope';\nimport { resolveBindingExpression } from './resolveBindingExpression';\n\n/**\n * Validates one binding against available runtime scope and optional component dependency stack.\n */\nexport function validateBindingExpression(\n binding: BindingExpression,\n scope: BindingScope,\n options: { targetElementId?: string; resolvingElementIds?: string[] } = {},\n): BindingDiagnostic[] {\n const diagnostics: BindingDiagnostic[] = [];\n const kind = binding.kind ?? BindingSourceKind.DataContext;\n\n if (kind === BindingSourceKind.QueryResult && !binding.query) {\n diagnostics.push(problem('missingQuery', 'Query result bindings must name the query they read from.', 'query'));\n }\n\n if (kind === BindingSourceKind.ComponentProperty) {\n if (!binding.componentId) {\n diagnostics.push(problem('missingComponent', 'Component property bindings must name the source component id.', 'componentId'));\n } else if (!scope.componentOutputs?.[binding.componentId]) {\n diagnostics.push(problem('unknownComponent', `No component output scope exists for '${binding.componentId}'.`, 'componentId'));\n }\n\n if (binding.componentId && options.targetElementId === binding.componentId) {\n diagnostics.push(problem('bindingCycle', `Component '${binding.componentId}' cannot bind to its own output.`, 'componentId'));\n }\n\n if (binding.componentId && options.resolvingElementIds?.includes(binding.componentId)) {\n diagnostics.push(problem('bindingCycle', `Binding to '${binding.componentId}' would create a component binding cycle.`, 'componentId'));\n }\n }\n\n if (binding.mode === BindingMode.TwoWay && kind !== BindingSourceKind.ComponentProperty) {\n diagnostics.push(problem('unsupportedTwoWayBinding', 'Two-way bindings require a component output source.', 'mode'));\n }\n\n if (binding.expectedValueType !== undefined) {\n const value = resolveBindingExpression(binding, scope);\n if (!matchesExpectedType(value, binding.expectedValueType)) {\n diagnostics.push(problem('bindingTypeMismatch', `Binding value does not match expected ${binding.expectedValueType}.`, 'expectedValueType'));\n }\n }\n\n return diagnostics;\n}\n\nfunction problem(code: string, message: string, path?: string): BindingDiagnostic {\n return { code, message, path };\n}\n\nfunction matchesExpectedType(value: unknown, type: PropertyValueType): boolean {\n if (value === null || value === undefined) return true;\n switch (type) {\n case PropertyValueType.String:\n case PropertyValueType.Enum:\n case PropertyValueType.Icon:\n case PropertyValueType.Destination:\n case PropertyValueType.QueryReference:\n return typeof value === 'string' || (typeof value === 'object' && !Array.isArray(value));\n case PropertyValueType.Number:\n return typeof value === 'number' && !Number.isNaN(value);\n case PropertyValueType.Boolean:\n return typeof value === 'boolean';\n case PropertyValueType.Collection:\n return Array.isArray(value);\n case PropertyValueType.Object:\n return typeof value === 'object' && !Array.isArray(value);\n case PropertyValueType.Json:\n return true;\n }\n}\n"],"names":["validateBindingExpression","binding","scope","options","diagnostics","kind","BindingSourceKind","DataContext","QueryResult","query","push","problem","ComponentProperty","componentId","componentOutputs","targetElementId","resolvingElementIds","includes","mode","BindingMode","TwoWay","expectedValueType","undefined","value","resolveBindingExpression","matchesExpectedType","code","message","path","type","PropertyValueType","String","Enum","Icon","Destination","QueryReference","Array","isArray","Number","isNaN","Boolean","Collection","Object","Json"],"mappings":"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"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// Copyright (c) Cratis. All rights reserved.
|
|
4
|
+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
|
5
|
+
/**
|
|
6
|
+
* Validates destinations against the outlet/route declarations owned by layouts and templates.
|
|
7
|
+
*/ function validateNavigationDestinations(destinations, surfaces = {}) {
|
|
8
|
+
const diagnostics = [];
|
|
9
|
+
const outlets = new Set();
|
|
10
|
+
const routes = new Set();
|
|
11
|
+
for (const surface of [
|
|
12
|
+
...surfaces.layouts ?? [],
|
|
13
|
+
...surfaces.screenTemplates ?? []
|
|
14
|
+
]){
|
|
15
|
+
for (const outlet of surface.outlets ?? []){
|
|
16
|
+
if (outlets.has(outlet.name)) diagnostics.push({
|
|
17
|
+
code: 'duplicateOutlet',
|
|
18
|
+
message: `Outlet '${outlet.name}' is declared more than once.`
|
|
19
|
+
});
|
|
20
|
+
outlets.add(outlet.name);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
for (const destination of destinations){
|
|
24
|
+
if (destination.outlet && !outlets.has(destination.outlet)) {
|
|
25
|
+
diagnostics.push({
|
|
26
|
+
code: 'missingOutlet',
|
|
27
|
+
message: `Destination targets missing outlet '${destination.outlet}'.`
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
if (destination.route) {
|
|
31
|
+
if (routes.has(destination.route)) diagnostics.push({
|
|
32
|
+
code: 'duplicateRoute',
|
|
33
|
+
message: `Route '${destination.route}' is used by more than one destination.`
|
|
34
|
+
});
|
|
35
|
+
routes.add(destination.route);
|
|
36
|
+
}
|
|
37
|
+
if (!destination.screen && !destination.module && !destination.route && !destination.dialog) {
|
|
38
|
+
diagnostics.push({
|
|
39
|
+
code: 'unavailableTarget',
|
|
40
|
+
message: 'Destination must name a screen, stable identity, route or dialog.'
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
return diagnostics;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
exports.validateNavigationDestinations = validateNavigationDestinations;
|
|
48
|
+
//# sourceMappingURL=validateNavigationDestinations.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validateNavigationDestinations.js","sources":["../../validateNavigationDestinations.ts"],"sourcesContent":["// Copyright (c) Cratis. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\nimport { DestinationReference, Layout, ScreenTemplate } from '@cratis/scene.model';\n\nexport interface NavigationDestinationDiagnostic {\n code: string;\n message: string;\n}\n\n/**\n * Validates destinations against the outlet/route declarations owned by layouts and templates.\n */\nexport function validateNavigationDestinations(\n destinations: DestinationReference[],\n surfaces: { layouts?: Layout[]; screenTemplates?: ScreenTemplate[] } = {},\n): NavigationDestinationDiagnostic[] {\n const diagnostics: NavigationDestinationDiagnostic[] = [];\n const outlets = new Set<string>();\n const routes = new Set<string>();\n\n for (const surface of [...(surfaces.layouts ?? []), ...(surfaces.screenTemplates ?? [])]) {\n for (const outlet of surface.outlets ?? []) {\n if (outlets.has(outlet.name)) diagnostics.push({ code: 'duplicateOutlet', message: `Outlet '${outlet.name}' is declared more than once.` });\n outlets.add(outlet.name);\n }\n }\n\n for (const destination of destinations) {\n if (destination.outlet && !outlets.has(destination.outlet)) {\n diagnostics.push({ code: 'missingOutlet', message: `Destination targets missing outlet '${destination.outlet}'.` });\n }\n if (destination.route) {\n if (routes.has(destination.route)) diagnostics.push({ code: 'duplicateRoute', message: `Route '${destination.route}' is used by more than one destination.` });\n routes.add(destination.route);\n }\n if (!destination.screen && !destination.module && !destination.route && !destination.dialog) {\n diagnostics.push({ code: 'unavailableTarget', message: 'Destination must name a screen, stable identity, route or dialog.' });\n }\n }\n\n return diagnostics;\n}\n"],"names":["validateNavigationDestinations","destinations","surfaces","diagnostics","outlets","Set","routes","surface","layouts","screenTemplates","outlet","has","name","push","code","message","add","destination","route","screen","module","dialog"],"mappings":";;AAAA;AACA;AASA;;AAEC,IACM,SAASA,8BAAAA,CACZC,YAAoC,EACpCC,QAAAA,GAAuE,EAAE,EAAA;AAEzE,IAAA,MAAMC,cAAiD,EAAE;AACzD,IAAA,MAAMC,UAAU,IAAIC,GAAAA,EAAAA;AACpB,IAAA,MAAMC,SAAS,IAAID,GAAAA,EAAAA;AAEnB,IAAA,KAAK,MAAME,OAAAA,IAAW;WAAKL,QAAAA,CAASM,OAAO,IAAI,EAAE;WAAON,QAAAA,CAASO,eAAe,IAAI;KAAI,CAAE;AACtF,QAAA,KAAK,MAAMC,MAAAA,IAAUH,OAAAA,CAAQH,OAAO,IAAI,EAAE,CAAE;YACxC,IAAIA,OAAAA,CAAQO,GAAG,CAACD,MAAAA,CAAOE,IAAI,CAAA,EAAGT,WAAAA,CAAYU,IAAI,CAAC;gBAAEC,IAAAA,EAAM,iBAAA;AAAmBC,gBAAAA,OAAAA,EAAS,CAAC,QAAQ,EAAEL,OAAOE,IAAI,CAAC,6BAA6B;AAAE,aAAA,CAAA;YACzIR,OAAAA,CAAQY,GAAG,CAACN,MAAAA,CAAOE,IAAI,CAAA;AAC3B,QAAA;AACJ,IAAA;IAEA,KAAK,MAAMK,eAAehB,YAAAA,CAAc;QACpC,IAAIgB,WAAAA,CAAYP,MAAM,IAAI,CAACN,QAAQO,GAAG,CAACM,WAAAA,CAAYP,MAAM,CAAA,EAAG;AACxDP,YAAAA,WAAAA,CAAYU,IAAI,CAAC;gBAAEC,IAAAA,EAAM,eAAA;AAAiBC,gBAAAA,OAAAA,EAAS,CAAC,oCAAoC,EAAEE,YAAYP,MAAM,CAAC,EAAE;AAAE,aAAA,CAAA;AACrH,QAAA;QACA,IAAIO,WAAAA,CAAYC,KAAK,EAAE;YACnB,IAAIZ,MAAAA,CAAOK,GAAG,CAACM,WAAAA,CAAYC,KAAK,CAAA,EAAGf,WAAAA,CAAYU,IAAI,CAAC;gBAAEC,IAAAA,EAAM,gBAAA;AAAkBC,gBAAAA,OAAAA,EAAS,CAAC,OAAO,EAAEE,YAAYC,KAAK,CAAC,uCAAuC;AAAE,aAAA,CAAA;YAC5JZ,MAAAA,CAAOU,GAAG,CAACC,WAAAA,CAAYC,KAAK,CAAA;AAChC,QAAA;AACA,QAAA,IAAI,CAACD,WAAAA,CAAYE,MAAM,IAAI,CAACF,WAAAA,CAAYG,MAAM,IAAI,CAACH,YAAYC,KAAK,IAAI,CAACD,WAAAA,CAAYI,MAAM,EAAE;AACzFlB,YAAAA,WAAAA,CAAYU,IAAI,CAAC;gBAAEC,IAAAA,EAAM,mBAAA;gBAAqBC,OAAAA,EAAS;AAAoE,aAAA,CAAA;AAC/H,QAAA;AACJ,IAAA;IAEA,OAAOZ,WAAAA;AACX;;"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"BindingDiagnostic.d.ts","sourceRoot":"","sources":["../../BindingDiagnostic.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,iBAAiB;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;CACjB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"BindingDiagnostic.js","sourceRoot":"","sources":["../../BindingDiagnostic.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"BindingScope.d.ts","sourceRoot":"","sources":["../../BindingScope.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,YAAY;IAEzB,WAAW,CAAC,EAAE,OAAO,CAAC;IAGtB,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAGvC,gBAAgB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;CAC9D"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"BindingScope.js","sourceRoot":"","sources":["../../BindingScope.ts"],"names":[],"mappings":""}
|
package/dist/esm/index.d.ts
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
export * from './Renderer';
|
|
2
2
|
export * from './BindingResolver';
|
|
3
|
+
export * from './BindingScope';
|
|
4
|
+
export * from './BindingDiagnostic';
|
|
5
|
+
export * from './resolveBindingExpression';
|
|
6
|
+
export * from './validateBindingExpression';
|
|
3
7
|
export * from './renderElement';
|
|
4
8
|
export * from './elementKind';
|
|
5
9
|
export * from './panelKind';
|
|
@@ -18,11 +22,13 @@ export * from './packageVersionRange';
|
|
|
18
22
|
export * from './resolvePackageDependencies';
|
|
19
23
|
export * from './packageCatalog';
|
|
20
24
|
export * from './resolveScreenTemplates';
|
|
25
|
+
export * from './templateApplicability';
|
|
21
26
|
export * from './buildStarterProfile';
|
|
22
27
|
export * from './incompatibleStarterThemes';
|
|
23
28
|
export * from './ActionDispatcher';
|
|
24
29
|
export * from './runActions';
|
|
25
30
|
export * from './resolveBehaviors';
|
|
26
31
|
export * from './resolveStrings';
|
|
32
|
+
export * from './validateNavigationDestinations';
|
|
27
33
|
export * from './editing';
|
|
28
34
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/esm/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../index.ts"],"names":[],"mappings":"AAGA,cAAc,YAAY,CAAC;AAC3B,cAAc,mBAAmB,CAAC;AAClC,cAAc,iBAAiB,CAAC;AAChC,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC;AAC5B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,uBAAuB,CAAC;AACtC,cAAc,SAAS,CAAC;AACxB,cAAc,wBAAwB,CAAC;AACvC,cAAc,oBAAoB,CAAC;AACnC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,+BAA+B,CAAC;AAC9C,cAAc,mCAAmC,CAAC;AAClD,cAAc,0BAA0B,CAAC;AACzC,cAAc,sBAAsB,CAAC;AACrC,cAAc,oBAAoB,CAAC;AACnC,cAAc,uBAAuB,CAAC;AACtC,cAAc,8BAA8B,CAAC;AAC7C,cAAc,kBAAkB,CAAC;AACjC,cAAc,0BAA0B,CAAC;AACzC,cAAc,uBAAuB,CAAC;AACtC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,oBAAoB,CAAC;AACnC,cAAc,cAAc,CAAC;AAC7B,cAAc,oBAAoB,CAAC;AACnC,cAAc,kBAAkB,CAAC;AACjC,cAAc,WAAW,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../index.ts"],"names":[],"mappings":"AAGA,cAAc,YAAY,CAAC;AAC3B,cAAc,mBAAmB,CAAC;AAClC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,qBAAqB,CAAC;AACpC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,iBAAiB,CAAC;AAChC,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC;AAC5B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,uBAAuB,CAAC;AACtC,cAAc,SAAS,CAAC;AACxB,cAAc,wBAAwB,CAAC;AACvC,cAAc,oBAAoB,CAAC;AACnC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,+BAA+B,CAAC;AAC9C,cAAc,mCAAmC,CAAC;AAClD,cAAc,0BAA0B,CAAC;AACzC,cAAc,sBAAsB,CAAC;AACrC,cAAc,oBAAoB,CAAC;AACnC,cAAc,uBAAuB,CAAC;AACtC,cAAc,8BAA8B,CAAC;AAC7C,cAAc,kBAAkB,CAAC;AACjC,cAAc,0BAA0B,CAAC;AACzC,cAAc,yBAAyB,CAAC;AACxC,cAAc,uBAAuB,CAAC;AACtC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,oBAAoB,CAAC;AACnC,cAAc,cAAc,CAAC;AAC7B,cAAc,oBAAoB,CAAC;AACnC,cAAc,kBAAkB,CAAC;AACjC,cAAc,kCAAkC,CAAC;AACjD,cAAc,WAAW,CAAC"}
|
package/dist/esm/index.js
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
export { createBindingResolver, resolveBindingExpression } from './resolveBindingExpression.js';
|
|
2
|
+
export { validateBindingExpression } from './validateBindingExpression.js';
|
|
1
3
|
export { renderElement } from './renderElement.js';
|
|
2
4
|
export { isContentControl, isExternalComponent, isItemsControl, isPanel } from './elementKind.js';
|
|
3
5
|
export { isCanvas, isDockPanel, isGrid, isStackPanel, isWrapPanel } from './panelKind.js';
|
|
@@ -18,11 +20,13 @@ export { isVersionSatisfiedBy } from './packageVersionRange.js';
|
|
|
18
20
|
export { resolvePackageDependencies } from './resolvePackageDependencies.js';
|
|
19
21
|
export { availablePackagesFor, baseComponentLibraries, componentsForPackages, packagesOfKind, toComponentCatalog } from './packageCatalog.js';
|
|
20
22
|
export { isScreenTemplateResolutionValid, resolveScreenTemplates } from './resolveScreenTemplates.js';
|
|
23
|
+
export { filterApplicableScreenTemplates, validateDialogTemplateApplicability, validateLayoutApplicability, validateScreenTemplateApplicability } from './templateApplicability.js';
|
|
21
24
|
export { buildStarterProfile } from './buildStarterProfile.js';
|
|
22
25
|
export { incompatibleStarterThemes } from './incompatibleStarterThemes.js';
|
|
23
26
|
export { InteractionStop, runActions, runBindings } from './runActions.js';
|
|
24
27
|
export { resolveApplicationTriggerBehaviors, resolveBehaviors, resolveEventBehaviors, resolveIntervalBehaviors } from './resolveBehaviors.js';
|
|
25
28
|
export { isStringsReference, resolveStringsInElement, resolveStringsValue } from './resolveStrings.js';
|
|
29
|
+
export { validateNavigationDestinations } from './validateNavigationDestinations.js';
|
|
26
30
|
export { errorDiagnostic, hasErrors, warningDiagnostic } from './editing/diagnostics.js';
|
|
27
31
|
export { dialogTemplateNodeId, elementNodeId, flowNodeId, freeformNodeId, layoutNodeId, ownerArrangementId, placementNodeId, scopeInstanceId, scopeNodeId, screenNodeId, screenTemplateNodeId, slotNodeId } from './editing/nodeIds.js';
|
|
28
32
|
export { layoutTypeDescriptors, placementProperties, templateProperties } from './editing/layoutTypeDescriptors.js';
|
package/dist/esm/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { BindingExpression } from '@cratis/scene.model';
|
|
2
|
+
import { BindingScope } from './BindingScope';
|
|
3
|
+
export declare function resolveBindingExpression(binding: BindingExpression, scope: BindingScope): unknown;
|
|
4
|
+
export declare function createBindingResolver(scope: BindingScope): (binding: BindingExpression) => unknown;
|
|
5
|
+
//# sourceMappingURL=resolveBindingExpression.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolveBindingExpression.d.ts","sourceRoot":"","sources":["../../resolveBindingExpression.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,iBAAiB,EAA0C,MAAM,qBAAqB,CAAC;AAChG,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAK9C,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,iBAAiB,EAAE,KAAK,EAAE,YAAY,GAAG,OAAO,CAWjG;AAKD,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,YAAY,GAAG,CAAC,OAAO,EAAE,iBAAiB,KAAK,OAAO,CAElG"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { BindingSourceKind, BindingNullBehavior } from '@cratis/scene.model';
|
|
2
|
+
|
|
3
|
+
// Copyright (c) Cratis. All rights reserved.
|
|
4
|
+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
|
5
|
+
/**
|
|
6
|
+
* Resolves a typed binding against the shared runtime binding scope.
|
|
7
|
+
*/ function resolveBindingExpression(binding, scope) {
|
|
8
|
+
const kind = binding.kind ?? BindingSourceKind.DataContext;
|
|
9
|
+
if (kind === BindingSourceKind.Literal) return binding.value;
|
|
10
|
+
const source = sourceValue(binding, scope, kind);
|
|
11
|
+
const value = readPath(source, sourcePath(binding, kind));
|
|
12
|
+
if (value !== null && value !== undefined) return value;
|
|
13
|
+
if (binding.nullBehavior === BindingNullBehavior.Preserve) return undefined;
|
|
14
|
+
if (binding.nullBehavior === BindingNullBehavior.Clear) return null;
|
|
15
|
+
return value;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Creates a legacy resolver function from a binding scope.
|
|
19
|
+
*/ function createBindingResolver(scope) {
|
|
20
|
+
return (binding)=>resolveBindingExpression(binding, scope);
|
|
21
|
+
}
|
|
22
|
+
function sourceValue(binding, scope, kind) {
|
|
23
|
+
switch(kind){
|
|
24
|
+
case BindingSourceKind.DataContext:
|
|
25
|
+
return scope.dataContext;
|
|
26
|
+
case BindingSourceKind.QueryResult:
|
|
27
|
+
return binding.query ? scope.queryResults?.[binding.query] : undefined;
|
|
28
|
+
case BindingSourceKind.ComponentProperty:
|
|
29
|
+
return binding.componentId ? scope.componentOutputs?.[binding.componentId] : undefined;
|
|
30
|
+
case BindingSourceKind.Literal:
|
|
31
|
+
return binding.value;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
function sourcePath(binding, kind) {
|
|
35
|
+
if (kind === BindingSourceKind.ComponentProperty) return binding.componentPropertyPath ?? binding.path;
|
|
36
|
+
return binding.path;
|
|
37
|
+
}
|
|
38
|
+
function readPath(source, path) {
|
|
39
|
+
if (!path) return source;
|
|
40
|
+
return path.split('.').reduce((current, segment)=>{
|
|
41
|
+
if (current === null || current === undefined) return undefined;
|
|
42
|
+
if (typeof current !== 'object') return undefined;
|
|
43
|
+
return current[segment];
|
|
44
|
+
}, source);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export { createBindingResolver, resolveBindingExpression };
|
|
48
|
+
//# sourceMappingURL=resolveBindingExpression.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolveBindingExpression.js","sources":["../../resolveBindingExpression.ts"],"sourcesContent":["// Copyright (c) Cratis. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\nimport { BindingExpression, BindingNullBehavior, BindingSourceKind } from '@cratis/scene.model';\nimport { BindingScope } from './BindingScope';\n\n/**\n * Resolves a typed binding against the shared runtime binding scope.\n */\nexport function resolveBindingExpression(binding: BindingExpression, scope: BindingScope): unknown {\n const kind = binding.kind ?? BindingSourceKind.DataContext;\n if (kind === BindingSourceKind.Literal) return binding.value;\n\n const source = sourceValue(binding, scope, kind);\n const value = readPath(source, sourcePath(binding, kind));\n if (value !== null && value !== undefined) return value;\n\n if (binding.nullBehavior === BindingNullBehavior.Preserve) return undefined;\n if (binding.nullBehavior === BindingNullBehavior.Clear) return null;\n return value;\n}\n\n/**\n * Creates a legacy resolver function from a binding scope.\n */\nexport function createBindingResolver(scope: BindingScope): (binding: BindingExpression) => unknown {\n return binding => resolveBindingExpression(binding, scope);\n}\n\nfunction sourceValue(binding: BindingExpression, scope: BindingScope, kind: BindingSourceKind): unknown {\n switch (kind) {\n case BindingSourceKind.DataContext:\n return scope.dataContext;\n case BindingSourceKind.QueryResult:\n return binding.query ? scope.queryResults?.[binding.query] : undefined;\n case BindingSourceKind.ComponentProperty:\n return binding.componentId ? scope.componentOutputs?.[binding.componentId] : undefined;\n case BindingSourceKind.Literal:\n return binding.value;\n }\n}\n\nfunction sourcePath(binding: BindingExpression, kind: BindingSourceKind): string {\n if (kind === BindingSourceKind.ComponentProperty) return binding.componentPropertyPath ?? binding.path;\n return binding.path;\n}\n\nfunction readPath(source: unknown, path: string): unknown {\n if (!path) return source;\n return path.split('.').reduce<unknown>((current, segment) => {\n if (current === null || current === undefined) return undefined;\n if (typeof current !== 'object') return undefined;\n return (current as Record<string, unknown>)[segment];\n }, source);\n}\n"],"names":["resolveBindingExpression","binding","scope","kind","BindingSourceKind","DataContext","Literal","value","source","sourceValue","readPath","sourcePath","undefined","nullBehavior","BindingNullBehavior","Preserve","Clear","createBindingResolver","dataContext","QueryResult","query","queryResults","ComponentProperty","componentId","componentOutputs","componentPropertyPath","path","split","reduce","current","segment"],"mappings":";;AAAA;AACA;AAKA;;AAEC,IACM,SAASA,wBAAAA,CAAyBC,OAA0B,EAAEC,KAAmB,EAAA;AACpF,IAAA,MAAMC,IAAAA,GAAOF,OAAAA,CAAQE,IAAI,IAAIC,kBAAkBC,WAAW;AAC1D,IAAA,IAAIF,SAASC,iBAAAA,CAAkBE,OAAO,EAAE,OAAOL,QAAQM,KAAK;IAE5D,MAAMC,MAAAA,GAASC,WAAAA,CAAYR,OAAAA,EAASC,KAAAA,EAAOC,IAAAA,CAAAA;AAC3C,IAAA,MAAMI,KAAAA,GAAQG,QAAAA,CAASF,MAAAA,EAAQG,UAAAA,CAAWV,OAAAA,EAASE,IAAAA,CAAAA,CAAAA;AACnD,IAAA,IAAII,KAAAA,KAAU,IAAA,IAAQA,KAAAA,KAAUK,SAAAA,EAAW,OAAOL,KAAAA;AAElD,IAAA,IAAIN,QAAQY,YAAY,KAAKC,mBAAAA,CAAoBC,QAAQ,EAAE,OAAOH,SAAAA;AAClE,IAAA,IAAIX,QAAQY,YAAY,KAAKC,mBAAAA,CAAoBE,KAAK,EAAE,OAAO,IAAA;IAC/D,OAAOT,KAAAA;AACX;AAEA;;IAGO,SAASU,qBAAAA,CAAsBf,KAAmB,EAAA;IACrD,OAAOD,CAAAA,OAAAA,GAAWD,wBAAAA,CAAyBC,OAAAA,EAASC,KAAAA,CAAAA;AACxD;AAEA,SAASO,WAAAA,CAAYR,OAA0B,EAAEC,KAAmB,EAAEC,IAAuB,EAAA;IACzF,OAAQA,IAAAA;AACJ,QAAA,KAAKC,kBAAkBC,WAAW;AAC9B,YAAA,OAAOH,MAAMgB,WAAW;AAC5B,QAAA,KAAKd,kBAAkBe,WAAW;YAC9B,OAAOlB,OAAAA,CAAQmB,KAAK,GAAGlB,KAAAA,CAAMmB,YAAY,GAAGpB,OAAAA,CAAQmB,KAAK,CAAC,GAAGR,SAAAA;AACjE,QAAA,KAAKR,kBAAkBkB,iBAAiB;YACpC,OAAOrB,OAAAA,CAAQsB,WAAW,GAAGrB,KAAAA,CAAMsB,gBAAgB,GAAGvB,OAAAA,CAAQsB,WAAW,CAAC,GAAGX,SAAAA;AACjF,QAAA,KAAKR,kBAAkBE,OAAO;AAC1B,YAAA,OAAOL,QAAQM,KAAK;AAC5B;AACJ;AAEA,SAASI,UAAAA,CAAWV,OAA0B,EAAEE,IAAuB,EAAA;IACnE,IAAIA,IAAAA,KAASC,kBAAkBkB,iBAAiB,EAAE,OAAOrB,OAAAA,CAAQwB,qBAAqB,IAAIxB,OAAAA,CAAQyB,IAAI;AACtG,IAAA,OAAOzB,QAAQyB,IAAI;AACvB;AAEA,SAAShB,QAAAA,CAASF,MAAe,EAAEkB,IAAY,EAAA;IAC3C,IAAI,CAACA,MAAM,OAAOlB,MAAAA;AAClB,IAAA,OAAOkB,KAAKC,KAAK,CAAC,KAAKC,MAAM,CAAU,CAACC,OAAAA,EAASC,OAAAA,GAAAA;AAC7C,QAAA,IAAID,OAAAA,KAAY,IAAA,IAAQA,OAAAA,KAAYjB,SAAAA,EAAW,OAAOA,SAAAA;QACtD,IAAI,OAAOiB,OAAAA,KAAY,QAAA,EAAU,OAAOjB,SAAAA;QACxC,OAAQiB,OAAmC,CAACC,OAAAA,CAAQ;IACxD,CAAA,EAAGtB,MAAAA,CAAAA;AACP;;"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { DialogTemplate, Layout, ScreenTemplate, TemplateScope } from '@cratis/scene.model';
|
|
2
|
+
type TemplateContainer = Pick<Layout, 'name' | 'slots'>;
|
|
3
|
+
export declare function validateLayoutApplicability(layout: Layout | undefined, scope: TemplateScope): string[];
|
|
4
|
+
export declare function validateScreenTemplateApplicability(template: ScreenTemplate | undefined, scope: TemplateScope, container?: TemplateContainer): string[];
|
|
5
|
+
export declare function validateDialogTemplateApplicability(template: DialogTemplate | undefined, scope: TemplateScope): string[];
|
|
6
|
+
export declare function filterApplicableScreenTemplates(templates: readonly ScreenTemplate[], scope: TemplateScope, container?: TemplateContainer): ScreenTemplate[];
|
|
7
|
+
export {};
|
|
8
|
+
//# sourceMappingURL=templateApplicability.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"templateApplicability.d.ts","sourceRoot":"","sources":["../../templateApplicability.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,cAAc,EAAE,MAAM,EAAE,cAAc,EAAoB,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAG9G,KAAK,iBAAiB,GAAG,IAAI,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC;AAGxD,wBAAgB,2BAA2B,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,EAAE,KAAK,EAAE,aAAa,GAAG,MAAM,EAAE,CAEtG;AAMD,wBAAgB,mCAAmC,CAC/C,QAAQ,EAAE,cAAc,GAAG,SAAS,EACpC,KAAK,EAAE,aAAa,EACpB,SAAS,CAAC,EAAE,iBAAiB,GAC9B,MAAM,EAAE,CAYV;AAGD,wBAAgB,mCAAmC,CAAC,QAAQ,EAAE,cAAc,GAAG,SAAS,EAAE,KAAK,EAAE,aAAa,GAAG,MAAM,EAAE,CAExH;AAGD,wBAAgB,+BAA+B,CAC3C,SAAS,EAAE,SAAS,cAAc,EAAE,EACpC,KAAK,EAAE,aAAa,EACpB,SAAS,CAAC,EAAE,iBAAiB,GAC9B,cAAc,EAAE,CAElB"}
|