@ajsf/material 22.3.3 → 22.5.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/README.md +2 -0
- package/fesm2022/ajsf-material.mjs +70 -28
- package/fesm2022/ajsf-material.mjs.map +1 -1
- package/package.json +2 -2
- package/types/ajsf-material.d.ts +27 -22
package/README.md
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# @ajsf/material
|
|
2
2
|
|
|
3
|
+
[](https://sonarcloud.io/summary/new_code?id=hamzahamidi_ajsf)
|
|
4
|
+
|
|
3
5
|
Angular Material framework for [AJSF](https://github.com/hamzahamidi/ajsf#readme), which builds Angular forms from JSON Schema.
|
|
4
6
|
|
|
5
7
|
## Getting started
|
|
@@ -63,10 +63,10 @@ class FlexLayoutRootComponent {
|
|
|
63
63
|
baseline: 'baseline', stretch: 'stretch',
|
|
64
64
|
}; }
|
|
65
65
|
getFlexBasis(node) {
|
|
66
|
-
return
|
|
66
|
+
return node?.options?.fxFlex || this.getFlexAttribute(node, 'flex-basis');
|
|
67
67
|
}
|
|
68
68
|
getMaxWidth(node) {
|
|
69
|
-
const fxFlex =
|
|
69
|
+
const fxFlex = node?.options?.fxFlex;
|
|
70
70
|
return fxFlex && `${fxFlex}`.trim().endsWith('%') ? fxFlex : null;
|
|
71
71
|
}
|
|
72
72
|
getAlignSelf(node) {
|
|
@@ -79,14 +79,14 @@ class FlexLayoutRootComponent {
|
|
|
79
79
|
return options.order || options.fxFlexOrder || null;
|
|
80
80
|
}
|
|
81
81
|
getOffset(node) {
|
|
82
|
-
return
|
|
82
|
+
return node?.options?.fxFlexOffset || null;
|
|
83
83
|
}
|
|
84
84
|
// Set attributes for flexbox child
|
|
85
85
|
// (container attributes are set in flex-layout-section.component)
|
|
86
86
|
getFlexAttribute(node, attribute) {
|
|
87
87
|
const index = ['flex-grow', 'flex-shrink', 'flex-basis'].indexOf(attribute);
|
|
88
|
-
return (
|
|
89
|
-
|
|
88
|
+
return (node.options?.flex || '').split(/\s+/)[index] ||
|
|
89
|
+
node.options?.[attribute] || ['1', '1', 'auto'][index];
|
|
90
90
|
}
|
|
91
91
|
showWidget(layoutNode) {
|
|
92
92
|
return this.jsf.evaluateCondition(layoutNode, this.dataIndex);
|
|
@@ -201,7 +201,7 @@ class FlexLayoutSectionComponent {
|
|
|
201
201
|
'space-evenly': 'space-evenly', stretch: 'stretch', baseline: 'baseline',
|
|
202
202
|
}; }
|
|
203
203
|
fxAlign(position) {
|
|
204
|
-
const value = `${
|
|
204
|
+
const value = `${this.options?.fxLayoutAlign || ''}`.trim().split(/\s+/)[position];
|
|
205
205
|
return FlexLayoutSectionComponent.ALIGN[value] || null;
|
|
206
206
|
}
|
|
207
207
|
getJustifyContent() {
|
|
@@ -223,10 +223,11 @@ class FlexLayoutSectionComponent {
|
|
|
223
223
|
case 'display':
|
|
224
224
|
return flexActive ? 'flex' : 'initial';
|
|
225
225
|
case 'flex-direction':
|
|
226
|
-
case 'flex-wrap':
|
|
226
|
+
case 'flex-wrap': {
|
|
227
227
|
const index = ['flex-direction', 'flex-wrap'].indexOf(attribute);
|
|
228
228
|
return (this.options['flex-flow'] || '').split(/\s+/)[index] ||
|
|
229
229
|
this.options[attribute] || ['column', 'nowrap'][index];
|
|
230
|
+
}
|
|
230
231
|
case 'justify-content':
|
|
231
232
|
case 'align-items':
|
|
232
233
|
case 'align-content':
|
|
@@ -574,7 +575,7 @@ class MaterialAddReferenceComponent {
|
|
|
574
575
|
}
|
|
575
576
|
get showAddButton() {
|
|
576
577
|
return !this.layoutNode.arrayItem ||
|
|
577
|
-
this.layoutIndex
|
|
578
|
+
this.layoutIndex.at(-1) < this.options.maxItems;
|
|
578
579
|
}
|
|
579
580
|
addItem(event) {
|
|
580
581
|
event.preventDefault();
|
|
@@ -1409,6 +1410,26 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImpor
|
|
|
1409
1410
|
type: Input
|
|
1410
1411
|
}] } });
|
|
1411
1412
|
|
|
1413
|
+
function hasTemplateExpression(text) {
|
|
1414
|
+
let start = -1;
|
|
1415
|
+
for (let index = 0; index < text.length; index += 1) {
|
|
1416
|
+
const character = text[index];
|
|
1417
|
+
if (character === '\n' || character === '\r' || character === '\u2028' || character === '\u2029') {
|
|
1418
|
+
start = -1;
|
|
1419
|
+
continue;
|
|
1420
|
+
}
|
|
1421
|
+
if (start === -1 && character === '{' && text[index + 1] === '{') {
|
|
1422
|
+
start = index;
|
|
1423
|
+
}
|
|
1424
|
+
else if (start !== -1 && character === '}' && text[index + 1] === '}') {
|
|
1425
|
+
if (index > start + 2) {
|
|
1426
|
+
return true;
|
|
1427
|
+
}
|
|
1428
|
+
start = -1;
|
|
1429
|
+
}
|
|
1430
|
+
}
|
|
1431
|
+
return false;
|
|
1432
|
+
}
|
|
1412
1433
|
class MaterialDesignFrameworkComponent {
|
|
1413
1434
|
constructor(changeDetector, jsf) {
|
|
1414
1435
|
this.changeDetector = changeDetector;
|
|
@@ -1431,11 +1452,15 @@ class MaterialDesignFrameworkComponent {
|
|
|
1431
1452
|
return false;
|
|
1432
1453
|
}
|
|
1433
1454
|
// If array length <= minItems, don't allow removing any items
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1455
|
+
if (this.parentArray.items.length - 1 <= this.parentArray.options.minItems) {
|
|
1456
|
+
return false;
|
|
1457
|
+
}
|
|
1458
|
+
// For removable list items, allow removing any item
|
|
1459
|
+
if (this.layoutNode.arrayItemType === 'list') {
|
|
1460
|
+
return true;
|
|
1461
|
+
}
|
|
1462
|
+
// For removable tuple items, only allow removing last item in list
|
|
1463
|
+
return this.layoutIndex.at(-1) === this.parentArray.items.length - 2;
|
|
1439
1464
|
}
|
|
1440
1465
|
ngOnInit() {
|
|
1441
1466
|
this.initializeFramework();
|
|
@@ -1465,7 +1490,7 @@ class MaterialDesignFrameworkComponent {
|
|
|
1465
1490
|
if (!['$ref', 'advancedfieldset', 'authfieldset', 'button', 'card',
|
|
1466
1491
|
'checkbox', 'expansion-panel', 'help', 'message', 'msg', 'section',
|
|
1467
1492
|
'submit', 'tabarray', 'tabs'].includes(this.layoutNode.type) &&
|
|
1468
|
-
|
|
1493
|
+
hasTemplateExpression(this.widgetOptions.title || '')) {
|
|
1469
1494
|
this.dynamicTitle = this.widgetOptions.title;
|
|
1470
1495
|
this.updateTitle();
|
|
1471
1496
|
}
|
|
@@ -1486,17 +1511,17 @@ class MaterialDesignFrameworkComponent {
|
|
|
1486
1511
|
}
|
|
1487
1512
|
}
|
|
1488
1513
|
updateTitle() {
|
|
1489
|
-
this.widgetLayoutNode.options.title = this.jsf.parseText(this.dynamicTitle, this.jsf.getFormControlValue(this), this.jsf.getFormControlGroup(this).value, this.dataIndex
|
|
1514
|
+
this.widgetLayoutNode.options.title = this.jsf.parseText(this.dynamicTitle, this.jsf.getFormControlValue(this), this.jsf.getFormControlGroup(this).value, this.dataIndex.at(-1));
|
|
1490
1515
|
}
|
|
1491
1516
|
removeItem() {
|
|
1492
1517
|
this.jsf.removeItem(this);
|
|
1493
1518
|
}
|
|
1494
1519
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: MaterialDesignFrameworkComponent, deps: [{ token: i0.ChangeDetectorRef }, { token: i1.JsonSchemaFormService }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
1495
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.6", type: MaterialDesignFrameworkComponent, isStandalone: false, selector: "material-design-framework", inputs: { layoutNode: "layoutNode", layoutIndex: "layoutIndex", dataIndex: "dataIndex" }, usesOnChanges: true, ngImport: i0, template: "<div\n [class.array-item]=\"widgetLayoutNode?.arrayItem && widgetLayoutNode?.type !== '$ref'\"\n [orderable]=\"isOrderable\"\n [dataIndex]=\"dataIndex\"\n [layoutIndex]=\"layoutIndex\"\n [layoutNode]=\"widgetLayoutNode\">\n @if (showRemoveButton) {\n <svg\n
|
|
1520
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.6", type: MaterialDesignFrameworkComponent, isStandalone: false, selector: "material-design-framework", inputs: { layoutNode: "layoutNode", layoutIndex: "layoutIndex", dataIndex: "dataIndex" }, usesOnChanges: true, ngImport: i0, template: "<div\n [class.array-item]=\"widgetLayoutNode?.arrayItem && widgetLayoutNode?.type !== '$ref'\"\n [orderable]=\"isOrderable\"\n [dataIndex]=\"dataIndex\"\n [layoutIndex]=\"layoutIndex\"\n [layoutNode]=\"widgetLayoutNode\">\n @if (showRemoveButton) {\n <button\n type=\"button\"\n class=\"close-button\"\n aria-label=\"Remove item\"\n (click)=\"removeItem()\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n height=\"18\" width=\"18\" viewBox=\"0 0 24 24\"\n aria-hidden=\"true\">\n <path\n d=\"M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12 19 6.41z\"/>\n </svg>\n </button>\n }\n <select-widget-widget\n [dataIndex]=\"dataIndex\"\n [layoutIndex]=\"layoutIndex\"\n [layoutNode]=\"widgetLayoutNode\"></select-widget-widget>\n</div>\n@if (widgetLayoutNode?.arrayItem && widgetLayoutNode?.type !== '$ref') {\n <div class=\"spacer\"></div>\n}\n", styles: [".array-item{border-radius:2px;box-shadow:0 3px 1px -2px #0003,0 2px 2px #00000024,0 1px 5px #0000001f;padding:6px;position:relative;transition:box-shadow .28s cubic-bezier(.4,0,.2,1)}.close-button{background:transparent;border:0;cursor:pointer;padding:0;position:absolute;top:6px;right:6px;fill:#0006;opacity:0;pointer-events:none;z-index:500}.close-button:hover{fill:#000c}.array-item:hover>.close-button,.array-item:focus-within>.close-button{opacity:1;pointer-events:auto}.spacer{margin:6px 0}[draggable=true]:hover{box-shadow:0 5px 5px -3px #0003,0 8px 10px 1px #00000024,0 3px 14px 2px #0000001f;cursor:move;z-index:10}[draggable=true].drag-target-top{box-shadow:0 -2px #000;position:relative;z-index:20}[draggable=true].drag-target-bottom{box-shadow:0 2px #000;position:relative;z-index:20}\n"], dependencies: [{ kind: "component", type: i1.SelectWidgetComponent, selector: "select-widget-widget", inputs: ["layoutNode", "layoutIndex", "dataIndex"] }, { kind: "directive", type: i1.OrderableDirective, selector: "[orderable]", inputs: ["orderable", "layoutNode", "layoutIndex", "dataIndex"] }], changeDetection: i0.ChangeDetectionStrategy.Eager }); }
|
|
1496
1521
|
}
|
|
1497
1522
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: MaterialDesignFrameworkComponent, decorators: [{
|
|
1498
1523
|
type: Component,
|
|
1499
|
-
args: [{ selector: 'material-design-framework', changeDetection: ChangeDetectionStrategy.Eager, standalone: false, template: "<div\n [class.array-item]=\"widgetLayoutNode?.arrayItem && widgetLayoutNode?.type !== '$ref'\"\n [orderable]=\"isOrderable\"\n [dataIndex]=\"dataIndex\"\n [layoutIndex]=\"layoutIndex\"\n [layoutNode]=\"widgetLayoutNode\">\n @if (showRemoveButton) {\n <svg\n
|
|
1524
|
+
args: [{ selector: 'material-design-framework', changeDetection: ChangeDetectionStrategy.Eager, standalone: false, template: "<div\n [class.array-item]=\"widgetLayoutNode?.arrayItem && widgetLayoutNode?.type !== '$ref'\"\n [orderable]=\"isOrderable\"\n [dataIndex]=\"dataIndex\"\n [layoutIndex]=\"layoutIndex\"\n [layoutNode]=\"widgetLayoutNode\">\n @if (showRemoveButton) {\n <button\n type=\"button\"\n class=\"close-button\"\n aria-label=\"Remove item\"\n (click)=\"removeItem()\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n height=\"18\" width=\"18\" viewBox=\"0 0 24 24\"\n aria-hidden=\"true\">\n <path\n d=\"M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12 19 6.41z\"/>\n </svg>\n </button>\n }\n <select-widget-widget\n [dataIndex]=\"dataIndex\"\n [layoutIndex]=\"layoutIndex\"\n [layoutNode]=\"widgetLayoutNode\"></select-widget-widget>\n</div>\n@if (widgetLayoutNode?.arrayItem && widgetLayoutNode?.type !== '$ref') {\n <div class=\"spacer\"></div>\n}\n", styles: [".array-item{border-radius:2px;box-shadow:0 3px 1px -2px #0003,0 2px 2px #00000024,0 1px 5px #0000001f;padding:6px;position:relative;transition:box-shadow .28s cubic-bezier(.4,0,.2,1)}.close-button{background:transparent;border:0;cursor:pointer;padding:0;position:absolute;top:6px;right:6px;fill:#0006;opacity:0;pointer-events:none;z-index:500}.close-button:hover{fill:#000c}.array-item:hover>.close-button,.array-item:focus-within>.close-button{opacity:1;pointer-events:auto}.spacer{margin:6px 0}[draggable=true]:hover{box-shadow:0 5px 5px -3px #0003,0 8px 10px 1px #00000024,0 3px 14px 2px #0000001f;cursor:move;z-index:10}[draggable=true].drag-target-top{box-shadow:0 -2px #000;position:relative;z-index:20}[draggable=true].drag-target-bottom{box-shadow:0 2px #000;position:relative;z-index:20}\n"] }]
|
|
1500
1525
|
}], ctorParameters: () => [{ type: i0.ChangeDetectorRef }, { type: i1.JsonSchemaFormService }], propDecorators: { layoutNode: [{
|
|
1501
1526
|
type: Input
|
|
1502
1527
|
}], layoutIndex: [{
|
|
@@ -1968,7 +1993,13 @@ class MaterialOneOfComponent {
|
|
|
1968
1993
|
const type = this.layoutNode.type;
|
|
1969
1994
|
this.isFieldset = (type === 'selectfieldset' || type === 'optionfieldset')
|
|
1970
1995
|
&& Array.isArray(this.layoutNode.items) && this.layoutNode.items.length > 0;
|
|
1971
|
-
|
|
1996
|
+
this.initializeSelectList();
|
|
1997
|
+
this.initializeFieldsetValueMap();
|
|
1998
|
+
this.initializeControl();
|
|
1999
|
+
this.selectInitialFieldsetValue();
|
|
2000
|
+
}
|
|
2001
|
+
initializeSelectList() {
|
|
2002
|
+
if (this.isFieldset && !this.hasExplicitFieldsetOptions()) {
|
|
1972
2003
|
this.selectList = this.layoutNode.items.map((item, i) => ({
|
|
1973
2004
|
name: item.options?.legend || item.options?.title || item.name || `Option ${i + 1}`,
|
|
1974
2005
|
value: i
|
|
@@ -1977,26 +2008,37 @@ class MaterialOneOfComponent {
|
|
|
1977
2008
|
else {
|
|
1978
2009
|
this.selectList = buildTitleMap(this.options.titleMap || this.options.enumNames, this.options.enum, !!this.options.required, !!this.options.flatList);
|
|
1979
2010
|
}
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
|
|
1988
|
-
|
|
2011
|
+
}
|
|
2012
|
+
initializeFieldsetValueMap() {
|
|
2013
|
+
if (!this.isFieldset || !this.hasExplicitFieldsetOptions()) {
|
|
2014
|
+
return;
|
|
2015
|
+
}
|
|
2016
|
+
let index = 0;
|
|
2017
|
+
for (const entry of this.selectList) {
|
|
2018
|
+
if (entry.value == null || entry.value === '') {
|
|
2019
|
+
continue;
|
|
1989
2020
|
}
|
|
2021
|
+
if (index === 0) {
|
|
2022
|
+
this.selectedValue = entry.value;
|
|
2023
|
+
}
|
|
2024
|
+
this.fieldsetValueMap.set(entry.value, index++);
|
|
1990
2025
|
}
|
|
1991
|
-
|
|
2026
|
+
}
|
|
2027
|
+
initializeControl() {
|
|
2028
|
+
if (!this.isFieldset || this.hasExplicitFieldsetOptions()) {
|
|
1992
2029
|
this.jsf.initializeControl(this, !this.options.readonly);
|
|
1993
2030
|
}
|
|
2031
|
+
}
|
|
2032
|
+
selectInitialFieldsetValue() {
|
|
1994
2033
|
if (this.isFieldset && this.controlValue != null) {
|
|
1995
2034
|
this.selectedValue = this.controlValue;
|
|
1996
2035
|
this._selectedItem = this.fieldsetValueMap.get(this.controlValue)
|
|
1997
2036
|
?? (typeof this.controlValue === 'number' ? this.controlValue : 0);
|
|
1998
2037
|
}
|
|
1999
2038
|
}
|
|
2039
|
+
hasExplicitFieldsetOptions() {
|
|
2040
|
+
return this.options.titleMap || this.options.enum;
|
|
2041
|
+
}
|
|
2000
2042
|
selectChild(event) {
|
|
2001
2043
|
this.selectedValue = event.value;
|
|
2002
2044
|
this._selectedItem =
|