@ajf/material 18.4.0 → 18.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 +167 -2
- package/audio/src/audio-module.d.ts +7 -6
- package/esm2022/audio/src/audio-module.mjs +22 -4
- package/esm2022/audio/src/audio.mjs +6 -6
- package/esm2022/barcode/barcode.mjs +3 -3
- package/esm2022/calendar/calendar.mjs +2 -2
- package/esm2022/checkbox-group/checkbox-group-item.mjs +3 -3
- package/esm2022/form-builder/form-builder-module.mjs +9 -2
- package/esm2022/form-builder/form-builder-service.mjs +63 -20
- package/esm2022/form-builder/form-builder.mjs +73 -9
- package/esm2022/form-builder/node-entry.mjs +3 -3
- package/esm2022/form-builder/node-properties.mjs +3 -13
- package/esm2022/form-builder/node-type-entry.mjs +3 -3
- package/esm2022/form-builder/node-type-groups.pipe.mjs +65 -0
- package/esm2022/form-builder/public_api.mjs +2 -1
- package/esm2022/form-builder/string-identifier-dialog.mjs +44 -60
- package/esm2022/forms/boolean-field.mjs +6 -5
- package/esm2022/forms/current-slide.mjs +92 -0
- package/esm2022/forms/date-input-field.mjs +7 -9
- package/esm2022/forms/display-field.mjs +2 -2
- package/esm2022/forms/empty-field.mjs +3 -3
- package/esm2022/forms/field-row.mjs +117 -0
- package/esm2022/forms/field.mjs +2 -2
- package/esm2022/forms/form.mjs +107 -13
- package/esm2022/forms/forms-module.mjs +26 -3
- package/esm2022/forms/input-field.mjs +6 -8
- package/esm2022/forms/multiple-choice-field.mjs +45 -10
- package/esm2022/forms/public_api.mjs +6 -1
- package/esm2022/forms/range-field.mjs +5 -6
- package/esm2022/forms/rep-strip.mjs +61 -0
- package/esm2022/forms/single-choice-field.mjs +26 -11
- package/esm2022/forms/slide-header.mjs +68 -0
- package/esm2022/forms/slide-stats.mjs +148 -0
- package/esm2022/forms/table-field.mjs +2 -2
- package/esm2022/forms/text-field.mjs +2 -2
- package/esm2022/forms/video-url-field.mjs +6 -8
- package/esm2022/geolocation/geolocation.mjs +4 -6
- package/esm2022/page-slider/page-slider.mjs +3 -3
- package/esm2022/signature/signature.mjs +5 -6
- package/esm2022/time/time-module.mjs +22 -4
- package/esm2022/time/time.mjs +4 -4
- package/fesm2022/ajf-material-audio.mjs +27 -9
- package/fesm2022/ajf-material-audio.mjs.map +1 -1
- package/fesm2022/ajf-material-barcode.mjs +2 -2
- package/fesm2022/ajf-material-barcode.mjs.map +1 -1
- package/fesm2022/ajf-material-calendar.mjs +2 -2
- package/fesm2022/ajf-material-calendar.mjs.map +1 -1
- package/fesm2022/ajf-material-checkbox-group.mjs +2 -2
- package/fesm2022/ajf-material-checkbox-group.mjs.map +1 -1
- package/fesm2022/ajf-material-form-builder.mjs +260 -108
- package/fesm2022/ajf-material-form-builder.mjs.map +1 -1
- package/fesm2022/ajf-material-forms.mjs +712 -99
- package/fesm2022/ajf-material-forms.mjs.map +1 -1
- package/fesm2022/ajf-material-geolocation.mjs +5 -7
- package/fesm2022/ajf-material-geolocation.mjs.map +1 -1
- package/fesm2022/ajf-material-page-slider.mjs +2 -2
- package/fesm2022/ajf-material-page-slider.mjs.map +1 -1
- package/fesm2022/ajf-material-signature.mjs +7 -8
- package/fesm2022/ajf-material-signature.mjs.map +1 -1
- package/fesm2022/ajf-material-time.mjs +24 -6
- package/fesm2022/ajf-material-time.mjs.map +1 -1
- package/form-builder/form-builder-module.d.ts +27 -25
- package/form-builder/form-builder-service.d.ts +25 -0
- package/form-builder/form-builder.d.ts +41 -2
- package/form-builder/node-type-groups.pipe.d.ts +45 -0
- package/form-builder/public_api.d.ts +1 -0
- package/form-builder/string-identifier-dialog.d.ts +10 -16
- package/forms/_theming.scss +142 -0
- package/forms/current-slide.d.ts +61 -0
- package/forms/field-row.d.ts +63 -0
- package/forms/form.d.ts +40 -3
- package/forms/forms-module.d.ts +57 -51
- package/forms/multiple-choice-field.d.ts +15 -1
- package/forms/public_api.d.ts +5 -0
- package/forms/rep-strip.d.ts +52 -0
- package/forms/single-choice-field.d.ts +7 -0
- package/forms/slide-header.d.ts +61 -0
- package/forms/slide-stats.d.ts +76 -0
- package/package.json +2 -2
- package/time/time-module.d.ts +4 -3
|
@@ -23,6 +23,19 @@ import { AjfAttachmentsOrigin, AjfChoicesOrigin, AjfField, AjfFieldType, AjfForm
|
|
|
23
23
|
import { AjfCondition } from '@ajf/core/models';
|
|
24
24
|
import { BehaviorSubject, Observable } from 'rxjs';
|
|
25
25
|
import * as i0 from "@angular/core";
|
|
26
|
+
/**
|
|
27
|
+
* The categories the entries of the form builder field types palette are
|
|
28
|
+
* grouped into, in display order. The values are translation keys, rendered as
|
|
29
|
+
* the header of each group.
|
|
30
|
+
*/
|
|
31
|
+
export declare const AjfFormBuilderNodeTypeCategories: {
|
|
32
|
+
readonly structure: "Structure";
|
|
33
|
+
readonly text: "Text";
|
|
34
|
+
readonly numeric: "Numeric";
|
|
35
|
+
readonly choices: "Choice fields";
|
|
36
|
+
readonly dateTime: "Date & time";
|
|
37
|
+
readonly advanced: "Advanced";
|
|
38
|
+
};
|
|
26
39
|
export interface AjfFormBuilderNodeTypeEntry {
|
|
27
40
|
label: string;
|
|
28
41
|
nodeType: {
|
|
@@ -30,6 +43,13 @@ export interface AjfFormBuilderNodeTypeEntry {
|
|
|
30
43
|
field?: AjfFieldType;
|
|
31
44
|
};
|
|
32
45
|
isSlide?: boolean;
|
|
46
|
+
/**
|
|
47
|
+
* The category the entry belongs to, one of
|
|
48
|
+
* {@link AjfFormBuilderNodeTypeCategories}. Entries sharing a category are
|
|
49
|
+
* rendered under a common header; entries without a category are rendered
|
|
50
|
+
* last, with no header.
|
|
51
|
+
*/
|
|
52
|
+
category?: string;
|
|
33
53
|
}
|
|
34
54
|
export interface AjfFormBuilderNodeEntry {
|
|
35
55
|
node: AjfNode;
|
|
@@ -79,6 +99,11 @@ export type AjfContainerNode = AjfSlide | AjfRepeatingSlide | AjfNodeGroup;
|
|
|
79
99
|
export declare function cleanDefaultValue(value: any, node: AjfField<any>): string | null;
|
|
80
100
|
export declare function flattenNodes(nodes: AjfNode[]): AjfNode[];
|
|
81
101
|
export declare class AjfFormBuilderService {
|
|
102
|
+
/**
|
|
103
|
+
* The node types available in the palette, listed by category in display
|
|
104
|
+
* order. Entries of the same category are rendered under a common header, see
|
|
105
|
+
* {@link AjfFormBuilderNodeTypeCategories}.
|
|
106
|
+
*/
|
|
82
107
|
private _availableNodeTypes;
|
|
83
108
|
/**
|
|
84
109
|
* Available node types
|
|
@@ -20,8 +20,9 @@
|
|
|
20
20
|
*
|
|
21
21
|
*/
|
|
22
22
|
import { AjfChoicesOrigin, AjfForm } from '@ajf/core/forms';
|
|
23
|
+
import { BooleanInput } from '@angular/cdk/coercion';
|
|
23
24
|
import { CdkDrag, CdkDragDrop } from '@angular/cdk/drag-drop';
|
|
24
|
-
import { AfterContentInit, AfterViewChecked, ChangeDetectorRef, ElementRef, OnDestroy } from '@angular/core';
|
|
25
|
+
import { AfterContentInit, AfterViewChecked, ChangeDetectorRef, ElementRef, EventEmitter, OnDestroy } from '@angular/core';
|
|
25
26
|
import { MatDialog } from '@angular/material/dialog';
|
|
26
27
|
import { MatSlideToggleChange } from '@angular/material/slide-toggle';
|
|
27
28
|
import { Observable } from 'rxjs';
|
|
@@ -35,6 +36,32 @@ export declare class AjfFormBuilder implements AfterViewChecked, AfterContentIni
|
|
|
35
36
|
private _form;
|
|
36
37
|
get form(): AjfForm | undefined;
|
|
37
38
|
set form(form: AjfForm | undefined);
|
|
39
|
+
/**
|
|
40
|
+
* True when the slides of the designer are kept expanded. Slides added later
|
|
41
|
+
* follow this state as well.
|
|
42
|
+
* It drives the "expand slides" toggle of the toolbar and can be set by the
|
|
43
|
+
* host, both one-way (`[expandSlides]="true"`) and two-way
|
|
44
|
+
* (`[(expandSlides)]="expanded"`).
|
|
45
|
+
*/
|
|
46
|
+
private _expandSlides;
|
|
47
|
+
get expandSlides(): boolean;
|
|
48
|
+
set expandSlides(expandSlides: boolean);
|
|
49
|
+
/**
|
|
50
|
+
* Emits whenever the slides expansion state is changed from inside the form
|
|
51
|
+
* builder, i.e. by the toolbar controls.
|
|
52
|
+
*/
|
|
53
|
+
readonly expandSlidesChange: EventEmitter<boolean>;
|
|
54
|
+
/**
|
|
55
|
+
* When true the form builder fills the whole height of its container: the
|
|
56
|
+
* field types palette, the designer and the properties panel stretch to the
|
|
57
|
+
* available height and scroll internally, instead of growing with their
|
|
58
|
+
* content. Requires the container to have a definite height.
|
|
59
|
+
*/
|
|
60
|
+
private _fillHeight;
|
|
61
|
+
get fillHeight(): boolean;
|
|
62
|
+
set fillHeight(fillHeight: boolean);
|
|
63
|
+
static ngAcceptInputType_expandSlides: BooleanInput;
|
|
64
|
+
static ngAcceptInputType_fillHeight: BooleanInput;
|
|
38
65
|
/**
|
|
39
66
|
* Called to set form builder validation errors
|
|
40
67
|
*/
|
|
@@ -79,11 +106,23 @@ export declare class AjfFormBuilder implements AfterViewChecked, AfterContentIni
|
|
|
79
106
|
onDrop(event: CdkDragDrop<AjfFormBuilderNodeEntry> | CdkDragDrop<AjfFormBuilderNodeTypeEntry>, content?: boolean): void;
|
|
80
107
|
editChoicesOrigin(choicesOrigin: AjfChoicesOrigin<any>): void;
|
|
81
108
|
editStringIdentifier(): void;
|
|
109
|
+
/**
|
|
110
|
+
* Expands all the slides of the designer and keeps the slides added later expanded.
|
|
111
|
+
*/
|
|
82
112
|
expandAll(): void;
|
|
113
|
+
/**
|
|
114
|
+
* Collapses all the slides of the designer and keeps the slides added later collapsed.
|
|
115
|
+
*/
|
|
83
116
|
collapseAll(): void;
|
|
84
117
|
expandToggle(evt: MatSlideToggleChange): void;
|
|
118
|
+
/**
|
|
119
|
+
* Applies the slides expansion state to the service.
|
|
120
|
+
* @param expanded True to keep the slides expanded
|
|
121
|
+
* @param notify True to emit expandSlidesChange when the state changes
|
|
122
|
+
*/
|
|
123
|
+
private _setSlidesExpanded;
|
|
85
124
|
downloadAsXlsform(): Promise<void>;
|
|
86
125
|
private _setCurrentForm;
|
|
87
126
|
static ɵfac: i0.ɵɵFactoryDeclaration<AjfFormBuilder, never>;
|
|
88
|
-
static ɵcmp: i0.ɵɵComponentDeclaration<AjfFormBuilder, "ajf-form-builder", never, { "form": { "alias": "form"; "required": false; }; }, { "formBuilderValidation": "formBuilderValidation"; }, never, never, false, never>;
|
|
127
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<AjfFormBuilder, "ajf-form-builder", never, { "form": { "alias": "form"; "required": false; }; "expandSlides": { "alias": "expandSlides"; "required": false; }; "fillHeight": { "alias": "fillHeight"; "required": false; }; }, { "expandSlidesChange": "expandSlidesChange"; "formBuilderValidation": "formBuilderValidation"; }, never, never, false, never>;
|
|
89
128
|
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright (C) Gnucoop soc. coop.
|
|
4
|
+
*
|
|
5
|
+
* This file is part of the Advanced JSON forms (ajf).
|
|
6
|
+
*
|
|
7
|
+
* Advanced JSON forms (ajf) is free software: you can redistribute it and/or
|
|
8
|
+
* modify it under the terms of the GNU Affero General Public License as
|
|
9
|
+
* published by the Free Software Foundation, either version 3 of the License,
|
|
10
|
+
* or (at your option) any later version.
|
|
11
|
+
*
|
|
12
|
+
* Advanced JSON forms (ajf) is distributed in the hope that it will be useful,
|
|
13
|
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
14
|
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero
|
|
15
|
+
* General Public License for more details.
|
|
16
|
+
*
|
|
17
|
+
* You should have received a copy of the GNU Affero General Public License
|
|
18
|
+
* along with Advanced JSON forms (ajf).
|
|
19
|
+
* If not, see http://www.gnu.org/licenses/.
|
|
20
|
+
*
|
|
21
|
+
*/
|
|
22
|
+
import { PipeTransform } from '@angular/core';
|
|
23
|
+
import { AjfFormBuilderNodeTypeEntry } from './form-builder-service';
|
|
24
|
+
import * as i0 from "@angular/core";
|
|
25
|
+
/**
|
|
26
|
+
* A group of node types of the palette, rendered under a common header.
|
|
27
|
+
*/
|
|
28
|
+
export interface AjfFormBuilderNodeTypeGroup {
|
|
29
|
+
/**
|
|
30
|
+
* The translation key of the group header. Empty for the group of the entries
|
|
31
|
+
* that have no category, which is rendered without a header.
|
|
32
|
+
*/
|
|
33
|
+
category: string;
|
|
34
|
+
nodeTypes: AjfFormBuilderNodeTypeEntry[];
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Groups the node types of the palette by category, keeping the categories in
|
|
38
|
+
* the order of their first entry. Applied after the search filter, so that the
|
|
39
|
+
* categories left without entries produce no header.
|
|
40
|
+
*/
|
|
41
|
+
export declare class NodeTypeGroupsPipe implements PipeTransform {
|
|
42
|
+
transform(nodeTypes: AjfFormBuilderNodeTypeEntry[]): AjfFormBuilderNodeTypeGroup[];
|
|
43
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<NodeTypeGroupsPipe, never>;
|
|
44
|
+
static ɵpipe: i0.ɵɵPipeDeclaration<NodeTypeGroupsPipe, "nodeTypeGroups", false>;
|
|
45
|
+
}
|
|
@@ -19,30 +19,24 @@
|
|
|
19
19
|
* If not, see http://www.gnu.org/licenses/.
|
|
20
20
|
*
|
|
21
21
|
*/
|
|
22
|
-
import {
|
|
23
|
-
import {
|
|
24
|
-
import {
|
|
25
|
-
import { MatChipInputEvent } from '@angular/material/chips';
|
|
26
|
-
import { MatTableDataSource } from '@angular/material/table';
|
|
22
|
+
import { AjfField } from '@ajf/core/forms';
|
|
23
|
+
import { OnDestroy } from '@angular/core';
|
|
24
|
+
import { FormControl } from '@angular/forms';
|
|
27
25
|
import { Observable } from 'rxjs';
|
|
28
26
|
import { AjfFormBuilderService } from './form-builder-service';
|
|
29
27
|
import * as i0 from "@angular/core";
|
|
30
28
|
export declare class AjfFbStringIdentifierDialogComponent implements OnDestroy {
|
|
31
29
|
private _service;
|
|
32
|
-
|
|
33
|
-
readonly
|
|
34
|
-
readonly
|
|
35
|
-
|
|
36
|
-
|
|
30
|
+
readonly fields$: Observable<AjfField[]>;
|
|
31
|
+
readonly filteredFields$: Observable<AjfField[]>;
|
|
32
|
+
readonly searchFilterCtrl: FormControl<string>;
|
|
33
|
+
selectedFieldNames: string[];
|
|
34
|
+
private _fields;
|
|
35
|
+
private _fieldsSub;
|
|
37
36
|
private _stringIdentifierSub;
|
|
38
|
-
constructor(_service: AjfFormBuilderService
|
|
39
|
-
addRow(): void;
|
|
40
|
-
deleteRow(rowIdx: number): void;
|
|
41
|
-
addValue(row: AjfFormStringIdentifier, evt: MatChipInputEvent, valueInput: HTMLInputElement): void;
|
|
42
|
-
removeValue(row: AjfFormStringIdentifier, value: string): void;
|
|
37
|
+
constructor(_service: AjfFormBuilderService);
|
|
43
38
|
ngOnDestroy(): void;
|
|
44
39
|
saveStringIdentifier(): void;
|
|
45
|
-
selected(row: AjfFormStringIdentifier, evt: MatAutocompleteSelectedEvent): void;
|
|
46
40
|
static ɵfac: i0.ɵɵFactoryDeclaration<AjfFbStringIdentifierDialogComponent, never>;
|
|
47
41
|
static ɵcmp: i0.ɵɵComponentDeclaration<AjfFbStringIdentifierDialogComponent, "ajf-fb-string-identifier-dialog", never, {}, {}, never, never, false, never>;
|
|
48
42
|
}
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
// Public theming API of the AJF form renderer.
|
|
2
|
+
//
|
|
3
|
+
// The renderer paints itself from a set of `--ajf-*` custom properties. Their
|
|
4
|
+
// defaults already follow Angular Material's M3 system variables where a host
|
|
5
|
+
// publishes them, so an application themed with `use-system-variables: true`
|
|
6
|
+
// needs nothing from this file.
|
|
7
|
+
//
|
|
8
|
+
// Everything else -- an M2 theme, a prebuilt theme, or an M3 theme without
|
|
9
|
+
// system variables -- has a theme object but no system variables, and that is
|
|
10
|
+
// what this mixin is for:
|
|
11
|
+
//
|
|
12
|
+
// @use '@angular/material' as mat;
|
|
13
|
+
// @use '@ajf/material/forms/theming' as ajf-forms;
|
|
14
|
+
//
|
|
15
|
+
// $theme: mat.define-light-theme(...); // or mat.define-theme(...)
|
|
16
|
+
//
|
|
17
|
+
// :root {
|
|
18
|
+
// @include mat.all-component-themes($theme);
|
|
19
|
+
// @include ajf-forms.theme($theme);
|
|
20
|
+
// }
|
|
21
|
+
//
|
|
22
|
+
// For a light and a dark theme, include it once per selector -- the renderer's
|
|
23
|
+
// own `.ajf-dark` / `.ajf-light` classes and its `prefers-color-scheme` block
|
|
24
|
+
// only carry the built-in palette, so once you hand it your own colours you also
|
|
25
|
+
// own the switch:
|
|
26
|
+
//
|
|
27
|
+
// .my-dark-theme {
|
|
28
|
+
// @include mat.all-component-colors($dark-theme);
|
|
29
|
+
// @include ajf-forms.theme($dark-theme);
|
|
30
|
+
// }
|
|
31
|
+
//
|
|
32
|
+
// This file emits custom properties only -- no selectors, no component styles --
|
|
33
|
+
// so including it more than once costs nothing but the declarations.
|
|
34
|
+
|
|
35
|
+
@use 'sass:list';
|
|
36
|
+
@use '@angular/material' as mat;
|
|
37
|
+
|
|
38
|
+
/// The M3 colour role behind each token.
|
|
39
|
+
$_m3-roles: (
|
|
40
|
+
bg: surface-container-low,
|
|
41
|
+
surface: surface,
|
|
42
|
+
band: surface-container,
|
|
43
|
+
border: outline-variant,
|
|
44
|
+
border-strong: outline,
|
|
45
|
+
accent: primary,
|
|
46
|
+
accent-fg: on-primary,
|
|
47
|
+
accent-soft: primary-container,
|
|
48
|
+
accent-ink: on-primary-container,
|
|
49
|
+
text: on-surface,
|
|
50
|
+
text-muted: on-surface-variant,
|
|
51
|
+
danger: error,
|
|
52
|
+
danger-bg: error-container,
|
|
53
|
+
);
|
|
54
|
+
|
|
55
|
+
/// The M2 palette/hue pair behind each token. M2 has no container roles, so the
|
|
56
|
+
/// soft surfaces are taken from the theme's background palette and the tinted
|
|
57
|
+
/// ones are mixed from the accent at include time.
|
|
58
|
+
$_m2-colors: (
|
|
59
|
+
bg: (background, background),
|
|
60
|
+
surface: (background, card),
|
|
61
|
+
band: (background, app-bar),
|
|
62
|
+
border: (foreground, divider),
|
|
63
|
+
accent: (primary, default),
|
|
64
|
+
accent-fg: (primary, default-contrast),
|
|
65
|
+
text: (foreground, text),
|
|
66
|
+
text-muted: (foreground, secondary-text),
|
|
67
|
+
danger: (warn, default),
|
|
68
|
+
);
|
|
69
|
+
|
|
70
|
+
/// M2's dividers are far too faint to draw a control box with, so the border a
|
|
71
|
+
/// control carries is mixed from the theme's own text colour instead.
|
|
72
|
+
$_m2-control-border-mix: 32%;
|
|
73
|
+
|
|
74
|
+
@mixin _m3($theme) {
|
|
75
|
+
@each $name, $role in $_m3-roles {
|
|
76
|
+
--ajf-#{$name}: #{mat.get-theme-color($theme, $role)};
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
$primary: mat.get-theme-color($theme, primary);
|
|
80
|
+
$on-primary: mat.get-theme-color($theme, on-primary);
|
|
81
|
+
|
|
82
|
+
--ajf-text-faint: color-mix(
|
|
83
|
+
in srgb,
|
|
84
|
+
#{mat.get-theme-color($theme, on-surface-variant)} 70%,
|
|
85
|
+
transparent
|
|
86
|
+
);
|
|
87
|
+
--ajf-accent-hover: color-mix(in srgb, #{$primary} 85%, #{$on-primary});
|
|
88
|
+
// Sits on the filled accent, so it is tinted with the accent's own contrast.
|
|
89
|
+
--ajf-kbd-bg: color-mix(in srgb, #{$on-primary} 22%, transparent);
|
|
90
|
+
// What a filled button falls back to once disabled: the accent gone, a flat
|
|
91
|
+
// neutral in its place, and the ordinary text colour on top -- readable on
|
|
92
|
+
// either palette, where the accent's contrast colour is not.
|
|
93
|
+
--ajf-disabled-bg: color-mix(
|
|
94
|
+
in srgb,
|
|
95
|
+
#{mat.get-theme-color($theme, on-surface)} 12%,
|
|
96
|
+
#{mat.get-theme-color($theme, surface)}
|
|
97
|
+
);
|
|
98
|
+
--ajf-disabled-fg: color-mix(
|
|
99
|
+
in srgb,
|
|
100
|
+
#{mat.get-theme-color($theme, on-surface)} 65%,
|
|
101
|
+
#{mat.get-theme-color($theme, surface)}
|
|
102
|
+
);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
@mixin _m2($theme) {
|
|
106
|
+
@each $name, $color in $_m2-colors {
|
|
107
|
+
--ajf-#{$name}: #{mat.get-theme-color($theme, list.nth($color, 1), list.nth($color, 2))};
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
$primary: mat.get-theme-color($theme, primary, default);
|
|
111
|
+
$on-primary: mat.get-theme-color($theme, primary, default-contrast);
|
|
112
|
+
$warn: mat.get-theme-color($theme, warn, default);
|
|
113
|
+
$card: mat.get-theme-color($theme, background, card);
|
|
114
|
+
$text: mat.get-theme-color($theme, foreground, text);
|
|
115
|
+
$secondary: mat.get-theme-color($theme, foreground, secondary-text);
|
|
116
|
+
|
|
117
|
+
--ajf-border-strong: color-mix(in srgb, #{$text} #{$_m2-control-border-mix}, #{$card});
|
|
118
|
+
--ajf-accent-soft: color-mix(in srgb, #{$primary} 12%, #{$card});
|
|
119
|
+
--ajf-accent-ink: color-mix(in srgb, #{$primary} 80%, #{$secondary});
|
|
120
|
+
--ajf-accent-hover: color-mix(in srgb, #{$primary} 85%, #{$secondary});
|
|
121
|
+
--ajf-danger-bg: color-mix(in srgb, #{$warn} 10%, #{$card});
|
|
122
|
+
--ajf-text-faint: color-mix(in srgb, #{$secondary} 70%, transparent);
|
|
123
|
+
--ajf-kbd-bg: color-mix(in srgb, #{$on-primary} 22%, transparent);
|
|
124
|
+
// See the M3 branch: disabled, a filled button goes flat neutral and keeps
|
|
125
|
+
// the ordinary text colour.
|
|
126
|
+
--ajf-disabled-bg: color-mix(in srgb, #{$text} 12%, #{$card});
|
|
127
|
+
--ajf-disabled-fg: color-mix(in srgb, #{$text} 65%, #{$card});
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/// Map an Angular Material theme onto the AJF form tokens.
|
|
131
|
+
/// Accepts both an M2 theme (`define-light-theme`, `define-dark-theme`, the
|
|
132
|
+
/// prebuilt themes) and an M3 one (`define-theme`).
|
|
133
|
+
@mixin theme($theme) {
|
|
134
|
+
$version: mat.get-theme-version($theme);
|
|
135
|
+
@if $version == 0 {
|
|
136
|
+
@include _m2($theme);
|
|
137
|
+
} @else if $version == 1 {
|
|
138
|
+
@include _m3($theme);
|
|
139
|
+
} @else {
|
|
140
|
+
@error 'Unsupported Angular Material theme version: #{$version}.';
|
|
141
|
+
}
|
|
142
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright (C) Gnucoop soc. coop.
|
|
4
|
+
*
|
|
5
|
+
* This file is part of the Advanced JSON forms (ajf).
|
|
6
|
+
*
|
|
7
|
+
* Advanced JSON forms (ajf) is free software: you can redistribute it and/or
|
|
8
|
+
* modify it under the terms of the GNU Affero General Public License as
|
|
9
|
+
* published by the Free Software Foundation, either version 3 of the License,
|
|
10
|
+
* or (at your option) any later version.
|
|
11
|
+
*
|
|
12
|
+
* Advanced JSON forms (ajf) is distributed in the hope that it will be useful,
|
|
13
|
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
14
|
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero
|
|
15
|
+
* General Public License for more details.
|
|
16
|
+
*
|
|
17
|
+
* You should have received a copy of the GNU Affero General Public License
|
|
18
|
+
* along with Advanced JSON forms (ajf).
|
|
19
|
+
* If not, see http://www.gnu.org/licenses/.
|
|
20
|
+
*
|
|
21
|
+
*/
|
|
22
|
+
import { AjfSlideInstance } from '@ajf/core/forms';
|
|
23
|
+
import { PipeTransform } from '@angular/core';
|
|
24
|
+
import * as i0 from "@angular/core";
|
|
25
|
+
/** Which slide the page slider is currently showing, and where it sits. */
|
|
26
|
+
export interface AjfCurrentSlide {
|
|
27
|
+
/** Null while a start or end message page is on screen. */
|
|
28
|
+
slide: AjfSlideInstance | null;
|
|
29
|
+
/** The repetition on screen, zero based; 0 for a non-repeating slide. */
|
|
30
|
+
repIndex: number;
|
|
31
|
+
/** How many repetitions the slide has; 0 when it does not repeat. */
|
|
32
|
+
reps: number;
|
|
33
|
+
/** The slide's ordinal among the visible ones, for the header badge. */
|
|
34
|
+
displayNumber: number;
|
|
35
|
+
/** How many visible slides the form has. */
|
|
36
|
+
total: number;
|
|
37
|
+
/**
|
|
38
|
+
* How many pages the slider holds: one per visible slide, one per repetition
|
|
39
|
+
* of a repeating slide, plus the start and end message pages. Nothing to
|
|
40
|
+
* navigate to when this is 1.
|
|
41
|
+
*/
|
|
42
|
+
pages: number;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Resolve the page slider's current page into a slide.
|
|
46
|
+
*
|
|
47
|
+
* The renderer lays out one page per slide, and one page per repetition of a
|
|
48
|
+
* repeating slide, optionally preceded by a start message page -- the same
|
|
49
|
+
* arithmetic the error navigation in `AjfFormRenderer` performs.
|
|
50
|
+
*
|
|
51
|
+
* Impure, because slide visibility and repetition counts are mutated in place.
|
|
52
|
+
* The result is memoized so that the pipe keeps handing back the same object
|
|
53
|
+
* while nothing has moved: returning a fresh one on every check would trip
|
|
54
|
+
* Angular's "expression has changed after it was checked" guard.
|
|
55
|
+
*/
|
|
56
|
+
export declare class AjfCurrentSlidePipe implements PipeTransform {
|
|
57
|
+
private _last;
|
|
58
|
+
transform(slides: AjfSlideInstance[] | null, currentPage: number, hasStartMessage: boolean, hasEndMessage?: boolean): AjfCurrentSlide;
|
|
59
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<AjfCurrentSlidePipe, never>;
|
|
60
|
+
static ɵpipe: i0.ɵɵPipeDeclaration<AjfCurrentSlidePipe, "ajfCurrentSlide", false>;
|
|
61
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright (C) Gnucoop soc. coop.
|
|
4
|
+
*
|
|
5
|
+
* This file is part of the Advanced JSON forms (ajf).
|
|
6
|
+
*
|
|
7
|
+
* Advanced JSON forms (ajf) is free software: you can redistribute it and/or
|
|
8
|
+
* modify it under the terms of the GNU Affero General Public License as
|
|
9
|
+
* published by the Free Software Foundation, either version 3 of the License,
|
|
10
|
+
* or (at your option) any later version.
|
|
11
|
+
*
|
|
12
|
+
* Advanced JSON forms (ajf) is distributed in the hope that it will be useful,
|
|
13
|
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
14
|
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero
|
|
15
|
+
* General Public License for more details.
|
|
16
|
+
*
|
|
17
|
+
* You should have received a copy of the GNU Affero General Public License
|
|
18
|
+
* along with Advanced JSON forms (ajf).
|
|
19
|
+
* If not, see http://www.gnu.org/licenses/.
|
|
20
|
+
*
|
|
21
|
+
*/
|
|
22
|
+
import { AjfFieldInstance } from '@ajf/core/forms';
|
|
23
|
+
import { BooleanInput } from '@angular/cdk/coercion';
|
|
24
|
+
import { ChangeDetectorRef, OnDestroy } from '@angular/core';
|
|
25
|
+
import * as i0 from "@angular/core";
|
|
26
|
+
/**
|
|
27
|
+
* One field of a slide, laid out as a row: type badge, label, control, and a
|
|
28
|
+
* right-hand column carrying either the field description or its validation
|
|
29
|
+
* error.
|
|
30
|
+
*
|
|
31
|
+
* Both the plain and the repeating slide branches of the renderer render through
|
|
32
|
+
* this component, so the row layout is defined in exactly one place.
|
|
33
|
+
*/
|
|
34
|
+
export declare class AjfFieldRow implements OnDestroy {
|
|
35
|
+
private _cdr;
|
|
36
|
+
set instance(instance: AjfFieldInstance);
|
|
37
|
+
get instance(): AjfFieldInstance;
|
|
38
|
+
private _instance;
|
|
39
|
+
private _instanceSub;
|
|
40
|
+
constructor(_cdr: ChangeDetectorRef);
|
|
41
|
+
ngOnDestroy(): void;
|
|
42
|
+
set readonly(readonly: boolean);
|
|
43
|
+
get readonly(): boolean;
|
|
44
|
+
private _readonly;
|
|
45
|
+
/**
|
|
46
|
+
* Rows drop out on the host element rather than inside it, so that a hidden
|
|
47
|
+
* field leaves no empty cell behind when rows are laid out in columns.
|
|
48
|
+
*
|
|
49
|
+
* Three kinds of node carry no information of their own and are kept out of
|
|
50
|
+
* the layout: a container node, which is only a bracket around the fields it
|
|
51
|
+
* holds and has no fieldType to render; a formula field with no label, which
|
|
52
|
+
* only feeds other fields; and a note with no body -- the renderer synthesises
|
|
53
|
+
* one of those to carry a node group's label, and a group is meant to show
|
|
54
|
+
* nothing of itself.
|
|
55
|
+
*/
|
|
56
|
+
get hidden(): boolean;
|
|
57
|
+
/** Notes render their own block and never get a control border around it. */
|
|
58
|
+
get isNote(): boolean;
|
|
59
|
+
get required(): boolean;
|
|
60
|
+
static ngAcceptInputType_readonly: BooleanInput;
|
|
61
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<AjfFieldRow, never>;
|
|
62
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<AjfFieldRow, "ajf-field-row", never, { "instance": { "alias": "instance"; "required": false; }; "readonly": { "alias": "readonly"; "required": false; }; }, {}, never, never, false, never>;
|
|
63
|
+
}
|
package/forms/form.d.ts
CHANGED
|
@@ -19,16 +19,53 @@
|
|
|
19
19
|
* If not, see http://www.gnu.org/licenses/.
|
|
20
20
|
*
|
|
21
21
|
*/
|
|
22
|
-
import { AjfFormRenderer as CoreFormRenderer, AjfFormRendererService,
|
|
22
|
+
import { AjfFieldInstance, AjfFormRenderer as CoreFormRenderer, AjfFormRendererService, AjfSlideInstance } from '@ajf/core/forms';
|
|
23
23
|
import { BooleanInput } from '@angular/cdk/coercion';
|
|
24
|
-
import { ChangeDetectorRef } from '@angular/core';
|
|
24
|
+
import { AfterViewChecked, ChangeDetectorRef, OnDestroy } from '@angular/core';
|
|
25
25
|
import * as i0 from "@angular/core";
|
|
26
|
-
export declare class AjfFormRenderer extends CoreFormRenderer {
|
|
26
|
+
export declare class AjfFormRenderer extends CoreFormRenderer implements AfterViewChecked, OnDestroy {
|
|
27
|
+
/**
|
|
28
|
+
* @deprecated The slide strip has been replaced by the jump menu in the slide
|
|
29
|
+
* header, which is always available. Kept so that existing templates still
|
|
30
|
+
* compile.
|
|
31
|
+
*/
|
|
27
32
|
topBar: boolean;
|
|
33
|
+
/**
|
|
34
|
+
* @deprecated Field rows align their labels and controls on a shared grid, so
|
|
35
|
+
* there is nothing left to centre.
|
|
36
|
+
*/
|
|
28
37
|
centeredFieldsContent: boolean;
|
|
38
|
+
/** How many field rows sit side by side. */
|
|
29
39
|
maxColumns: 1 | 2 | 3;
|
|
40
|
+
/**
|
|
41
|
+
* The page the slider is showing. The slide header is rendered once, above the
|
|
42
|
+
* slider, so it needs to know which slide is on screen; the page slider only
|
|
43
|
+
* reports that imperatively, hence the mirrored property.
|
|
44
|
+
*/
|
|
45
|
+
currentPage: number;
|
|
46
|
+
private _slideList;
|
|
47
|
+
private _validitySubscription;
|
|
48
|
+
private _slidesSubscription;
|
|
49
|
+
private _valueSubscription;
|
|
50
|
+
private _pageSubscription;
|
|
51
|
+
private _pageInit;
|
|
30
52
|
constructor(rendererService: AjfFormRendererService, changeDetectorRef: ChangeDetectorRef);
|
|
53
|
+
ngAfterViewChecked(): void;
|
|
54
|
+
ngOnDestroy(): void;
|
|
31
55
|
fieldStyle(field: AjfFieldInstance): any;
|
|
56
|
+
/** Page to the first page of a slide, from the header's jump menu. */
|
|
57
|
+
goToSlide(slide: AjfSlideInstance): void;
|
|
58
|
+
/** Page to one repetition of the repeating slide currently on screen. */
|
|
59
|
+
goToRep(slide: AjfSlideInstance, repIndex: number): void;
|
|
60
|
+
goToPrevSlide(): void;
|
|
61
|
+
goToNextSlide(): void;
|
|
62
|
+
/**
|
|
63
|
+
* The slider page a slide starts on. `AjfSlideInstance.position` cannot be
|
|
64
|
+
* used directly here: it does not account for a start message page, and this
|
|
65
|
+
* has to agree with the page arithmetic used by `ajfCurrentSlide`.
|
|
66
|
+
*/
|
|
67
|
+
private _pageOf;
|
|
68
|
+
private _slideTo;
|
|
32
69
|
static ngAcceptInputType_fixedOrientation: BooleanInput;
|
|
33
70
|
static ngAcceptInputType_hasEndMessage: BooleanInput;
|
|
34
71
|
static ngAcceptInputType_hasStartMessage: BooleanInput;
|