@ajf/calendars 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/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,4 +1,169 @@
|
|
|
1
|
-
# Advanced JSON
|
|
1
|
+
# Advanced JSON Forms (AJF)
|
|
2
2
|
|
|
3
|
+
Define a form as JSON, render it with Angular.
|
|
3
4
|
|
|
4
|
-
|
|
5
|
+
AJF is Gnucoop's framework for data collection: a form is a JSON schema — slides, fields,
|
|
6
|
+
validation rules, visibility conditions and formulas — and AJF turns that schema into a working
|
|
7
|
+
Angular form, a read-only view of the collected data, a visual form builder, and reports over the
|
|
8
|
+
results.
|
|
9
|
+
|
|
10
|
+
Built for and with Angular 18 and Angular Material 18.
|
|
11
|
+
|
|
12
|
+
## Packages
|
|
13
|
+
|
|
14
|
+
| Package | Contains |
|
|
15
|
+
|---|---|
|
|
16
|
+
| `@ajf/core` | The framework-agnostic half: schema and interfaces (`AjfForm`, `AjfNode`, `AjfField`), serialization, validation, the renderer service, reports, PDF/DOCX export. No UI. |
|
|
17
|
+
| `@ajf/material` | The Angular Material half: the components that render what core defines, plus the visual form builder. |
|
|
18
|
+
| `@ajf/calendars` | Ethiopian calendar support. |
|
|
19
|
+
| `ajf-examples` | Canonical usage examples. |
|
|
20
|
+
|
|
21
|
+
Both libraries are split into secondary entry points, imported individually:
|
|
22
|
+
|
|
23
|
+
```ts
|
|
24
|
+
import {AjfFormSerializer} from '@ajf/core/forms';
|
|
25
|
+
import {AjfFormsModule} from '@ajf/material/forms';
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
`@ajf/core` ships `forms`, `models`, `reports`, `transloco`, `common`, `utils`, `page-slider`,
|
|
29
|
+
`page-break`, `node-icon`, `table`, `text`, `chart`, `echarts`, `graph`, `map`, `heat-map`, `image`,
|
|
30
|
+
`pdfmake`, and one entry point per complex field (`audio`, `barcode`, `calendar`, `checkbox-group`,
|
|
31
|
+
`file-input`, `geolocation`, `range`, `signature`, `time`). `@ajf/material` mirrors the ones that
|
|
32
|
+
have a UI and adds `form-builder`.
|
|
33
|
+
|
|
34
|
+
## Install
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
yarn add @ajf/core @ajf/material
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Angular 18.2 and Angular Material 18.2 are peer dependencies.
|
|
41
|
+
|
|
42
|
+
## Quick start
|
|
43
|
+
|
|
44
|
+
```ts
|
|
45
|
+
import {AjfTranslocoModule} from '@ajf/core/transloco';
|
|
46
|
+
import {AjfFormsModule} from '@ajf/material/forms';
|
|
47
|
+
|
|
48
|
+
@NgModule({
|
|
49
|
+
imports: [AjfFormsModule, AjfTranslocoModule.forRoot()],
|
|
50
|
+
})
|
|
51
|
+
export class AppModule {}
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
```ts
|
|
55
|
+
import {AjfForm, AjfFormActionEvent, AjfFormSerializer} from '@ajf/core/forms';
|
|
56
|
+
|
|
57
|
+
@Component({
|
|
58
|
+
template: '<ajf-form [form]="form" (formAction)="onAction($event)"></ajf-form>',
|
|
59
|
+
})
|
|
60
|
+
export class MyFormComponent {
|
|
61
|
+
form: AjfForm = AjfFormSerializer.fromJson(schema, context);
|
|
62
|
+
|
|
63
|
+
onAction({action, value}: AjfFormActionEvent): void {
|
|
64
|
+
// action is 'save' for the built-in button, or whatever you passed to
|
|
65
|
+
// onFormAction(); value is the collected data.
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
`schema` is the JSON definition; `context` is the initial values. The renderer needs a height to
|
|
71
|
+
lay its slides out — give the host element one, or a positioned container.
|
|
72
|
+
|
|
73
|
+
For view mode, pass the same form with `[readonly]="true"`: the renderer swaps every field for its
|
|
74
|
+
read-only counterpart and renders the values as flat text.
|
|
75
|
+
|
|
76
|
+
## Fields
|
|
77
|
+
|
|
78
|
+
`AjfFieldType`: `String`, `Text`, `Number`, `Boolean`, `SingleChoice`, `MultipleChoice`, `Formula`,
|
|
79
|
+
`Empty`, `DateRange`, `DateInput`, `Time`, `Table`, `Geolocation`, `Barcode`, `File`, `Image`,
|
|
80
|
+
`VideoUrl`, `Range`, `Signature`, `Audio`.
|
|
81
|
+
|
|
82
|
+
Custom field types are registered on `AjfFieldService.registerCustomField()`.
|
|
83
|
+
|
|
84
|
+
Conditions (`AjfCondition`) and formulas (`AjfFormula`) are plain JavaScript strings evaluated at
|
|
85
|
+
runtime, with the current form's field names in scope: `pet_type === 'cat'`, `amount * 0.05`.
|
|
86
|
+
Register your own functions for those expressions with `AjfValidationService`.
|
|
87
|
+
|
|
88
|
+
## Rendering
|
|
89
|
+
|
|
90
|
+
Every field is laid out as a row — `label + type name | control | hint or error` — by a single
|
|
91
|
+
component, `AjfFieldRow`. Above the slides sits one header bar carrying the slide number and title,
|
|
92
|
+
a completion counter, a jump menu, paging, the form's outstanding issues, and a slot for your own
|
|
93
|
+
action buttons:
|
|
94
|
+
|
|
95
|
+
```html
|
|
96
|
+
<ajf-form [form]="form">
|
|
97
|
+
<button ajfFormTopToolbarButtons mat-button>Save draft</button>
|
|
98
|
+
<button ajfFormSaveButton mat-flat-button>Save</button>
|
|
99
|
+
</ajf-form>
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
## Theming
|
|
103
|
+
|
|
104
|
+
The renderer paints itself from `--ajf-*` CSS custom properties, and each colour token falls through
|
|
105
|
+
Angular Material's system variables before landing on AJF's own default. There are four levels,
|
|
106
|
+
cheapest first:
|
|
107
|
+
|
|
108
|
+
1. **Nothing.** The built-in palette, light and dark.
|
|
109
|
+
2. **An M3 Material theme.** Build it with `use-system-variables: true` and the whole renderer
|
|
110
|
+
follows, with no other wiring.
|
|
111
|
+
3. **Any Material theme, M2 or M3.** One include:
|
|
112
|
+
|
|
113
|
+
```scss
|
|
114
|
+
@use '@angular/material' as mat;
|
|
115
|
+
@use '@ajf/material/forms/theming' as ajf-forms;
|
|
116
|
+
|
|
117
|
+
:root {
|
|
118
|
+
@include mat.all-component-themes($theme);
|
|
119
|
+
@include ajf-forms.theme($theme);
|
|
120
|
+
}
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
4. **Setting the tokens yourself**, e.g. `--ajf-accent`, `--ajf-surface`, `--ajf-control-h`.
|
|
124
|
+
|
|
125
|
+
Dark mode follows `prefers-color-scheme`, and an `.ajf-dark` or `.ajf-light` class on any ancestor
|
|
126
|
+
overrides it.
|
|
127
|
+
|
|
128
|
+
## Internationalisation
|
|
129
|
+
|
|
130
|
+
`@ajf/core/transloco` wraps [`@ngneat/transloco`](https://ngneat.github.io/transloco/) and ships
|
|
131
|
+
translations for Arabic, English, Ethiopian, French, Italian, Portuguese, Spanish and Ukrainian.
|
|
132
|
+
Import `AjfTranslocoModule.forRoot()` once in your app root.
|
|
133
|
+
|
|
134
|
+
## Development
|
|
135
|
+
|
|
136
|
+
Requires Node >= 18.17 and **yarn** (enforced through `.npmrc`).
|
|
137
|
+
|
|
138
|
+
```bash
|
|
139
|
+
yarn install
|
|
140
|
+
yarn dev-app # the demo playground at http://localhost:4200
|
|
141
|
+
yarn build # build every library into dist/
|
|
142
|
+
yarn lint
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
Tests:
|
|
146
|
+
|
|
147
|
+
```bash
|
|
148
|
+
yarn test # unit tests, watch mode
|
|
149
|
+
yarn test:ci # unit tests, once
|
|
150
|
+
ng test core # one project at a time
|
|
151
|
+
yarn e2e-material # Cypress, starts the e2e host app
|
|
152
|
+
yarn e2e-core
|
|
153
|
+
yarn e2e-calendars
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
`projects/dev-app` is the playground — one lazy-loaded module per feature, including a full form
|
|
157
|
+
demo with `readonly` and dark-mode switches. `projects/e2e-app` hosts the Cypress suites.
|
|
158
|
+
|
|
159
|
+
`CLAUDE.md` documents the internals: the core/material split, the two patterns for field
|
|
160
|
+
components, the token layer, and a checklist for adding a field type.
|
|
161
|
+
|
|
162
|
+
## Links
|
|
163
|
+
|
|
164
|
+
- Repository: https://github.com/gnucoop/ajf
|
|
165
|
+
- Changelog: [CHANGELOG.md](CHANGELOG.md)
|
|
166
|
+
|
|
167
|
+
## License
|
|
168
|
+
|
|
169
|
+
AGPL-3.0-or-later. See the license headers in each source file.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ajf/calendars",
|
|
3
|
-
"version": "18.
|
|
3
|
+
"version": "18.5.0",
|
|
4
4
|
"description": "",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
},
|
|
14
14
|
"homepage": "https://github.com/gnucoop/ajf#readme",
|
|
15
15
|
"peerDependencies": {
|
|
16
|
-
"@ajf/core": "18.
|
|
16
|
+
"@ajf/core": "18.5.0",
|
|
17
17
|
"@angular/core": "^18.2.13",
|
|
18
18
|
"date-fns": "^2.28.0"
|
|
19
19
|
},
|