@softheon/armature 21.2.1 → 21.2.2
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/b2b/README.md +255 -0
- package/fesm2022/softheon-armature-b2b.mjs +1198 -0
- package/fesm2022/softheon-armature-b2b.mjs.map +1 -0
- package/fesm2022/softheon-armature.mjs +21 -5
- package/fesm2022/softheon-armature.mjs.map +1 -1
- package/package.json +10 -2
- package/types/softheon-armature-b2b.d.ts +584 -0
- package/types/softheon-armature.d.ts +8 -2
package/b2b/README.md
ADDED
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
# @softheon/armature/b2b
|
|
2
|
+
|
|
3
|
+
Secondary entry point for B2B components in the `@softheon/armature` library. Optional B2B components with zero added bundle cost.
|
|
4
|
+
|
|
5
|
+
## Architecture
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
@softheon/armature/b2b
|
|
9
|
+
├─ SofB2BModule (NgModule wrapper — optional)
|
|
10
|
+
├─ SofB2BJsonEditorComponent (standalone, root editor)
|
|
11
|
+
│ └─ SofB2BJsonNodeComponent (standalone, recursive renderer)
|
|
12
|
+
└─ Utilities
|
|
13
|
+
├─ json-path.utils.ts (flatten / unflatten / path parsing)
|
|
14
|
+
├─ json-tree.utils.ts (tree build / reconstruct / array clone & reindex)
|
|
15
|
+
├─ json-filter.utils.ts (search filtering)
|
|
16
|
+
└─ json-schema.utils.ts (JSON Schema parsing — internal)
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Quick Start
|
|
20
|
+
|
|
21
|
+
### 1. Install the type dependency (optional)
|
|
22
|
+
|
|
23
|
+
The `[schema]` input uses `JsonSchema`, an alias for `JSONSchema7` from `@types/json-schema`. Add it as a devDependency if you plan to use schema-driven field configuration:
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
npm install --save-dev @types/json-schema
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
### 2. Import the component
|
|
30
|
+
|
|
31
|
+
`SofB2BJsonEditorComponent` is standalone — import it directly or use `SofB2BModule`:
|
|
32
|
+
|
|
33
|
+
```typescript
|
|
34
|
+
import { SofB2BJsonEditorComponent } from '@softheon/armature/b2b';
|
|
35
|
+
|
|
36
|
+
// Option A — standalone component
|
|
37
|
+
@Component({
|
|
38
|
+
standalone: true,
|
|
39
|
+
imports: [SofB2BJsonEditorComponent],
|
|
40
|
+
})
|
|
41
|
+
export class MyComponent {}
|
|
42
|
+
|
|
43
|
+
// Option B — NgModule
|
|
44
|
+
import { SofB2BModule } from '@softheon/armature/b2b';
|
|
45
|
+
|
|
46
|
+
@NgModule({
|
|
47
|
+
imports: [SofB2BModule],
|
|
48
|
+
})
|
|
49
|
+
export class MyModule {}
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
### 3. Use in template
|
|
53
|
+
|
|
54
|
+
Pass a `JsonObject` (any nested JSON object) directly — no pre-processing required:
|
|
55
|
+
|
|
56
|
+
```html
|
|
57
|
+
<sof-b2b-json-editor
|
|
58
|
+
[data]="rawData"
|
|
59
|
+
[schema]="jsonSchema"
|
|
60
|
+
[readOnly]="false"
|
|
61
|
+
[debounceMs]="1500"
|
|
62
|
+
[searchTerm]="searchTerm"
|
|
63
|
+
(dataChanged)="onDataChanged($event)"
|
|
64
|
+
(parseError)="onParseError($event)"
|
|
65
|
+
[emptyMessage]="'editor.data.empty' | translate"
|
|
66
|
+
[noResultsMessage]="'editor.data.no-results' | translate">
|
|
67
|
+
</sof-b2b-json-editor>
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
### 4. Handle changes
|
|
71
|
+
|
|
72
|
+
The `(dataChanged)` output emits the full reconstructed `JsonObject` after the debounce period:
|
|
73
|
+
|
|
74
|
+
```typescript
|
|
75
|
+
import { JsonObject } from '@softheon/armature/b2b';
|
|
76
|
+
|
|
77
|
+
onDataChanged(data: JsonObject): void {
|
|
78
|
+
// data is the full reconstructed JSON object
|
|
79
|
+
this.myService.save(data);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
onParseError(error: string): void {
|
|
83
|
+
// Display the error in your own snackbar/toast/etc.
|
|
84
|
+
this.snackbar.open(error, 'Dismiss');
|
|
85
|
+
}
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
## API Reference
|
|
89
|
+
|
|
90
|
+
### SofB2BJsonEditorComponent inputs
|
|
91
|
+
|
|
92
|
+
| Input | Type | Default | Description |
|
|
93
|
+
| ------------------ | ------------ | ----------------------- | --------------------------------------------------------------------------- |
|
|
94
|
+
| `data` | `JsonObject` | `{}` | Raw nested JSON object. Pass a **new object reference** to trigger updates. |
|
|
95
|
+
| `schema` | `JsonSchema` | `undefined` | Optional JSON Schema (Draft 7+). Parsed internally into field configs. |
|
|
96
|
+
| `readOnly` | `boolean` | `false` | Disables editing; fields render as plaintext. |
|
|
97
|
+
| `debounceMs` | `number` | `1500` | Debounce delay before `dataChanged` emits. |
|
|
98
|
+
| `searchTerm` | `string` | `''` | Filters tree nodes (min 2 chars to activate). |
|
|
99
|
+
| `emptyMessage` | `string` | `'No data to display.'` | Message shown when `data` is empty. |
|
|
100
|
+
| `noResultsMessage` | `string` | `'No results found.'` | Message shown when search returns no matches. |
|
|
101
|
+
|
|
102
|
+
### SofB2BJsonEditorComponent outputs
|
|
103
|
+
|
|
104
|
+
| Output | Type | Description |
|
|
105
|
+
| ------------- | ------------ | --------------------------------------------------------------------------------------- |
|
|
106
|
+
| `dataChanged` | `JsonObject` | Emits the reconstructed JSON object after debounce. Suppressed when `readOnly` is true. |
|
|
107
|
+
| `parseError` | `string` | Emits error message strings for parsing/validation failures. |
|
|
108
|
+
|
|
109
|
+
### SofB2BJsonEditorComponent public methods
|
|
110
|
+
|
|
111
|
+
| Method | Description |
|
|
112
|
+
| ------------ | --------------------------------------------- |
|
|
113
|
+
| `openAll()` | Programmatically opens all top-level panels. |
|
|
114
|
+
| `closeAll()` | Programmatically closes all top-level panels. |
|
|
115
|
+
|
|
116
|
+
## Models
|
|
117
|
+
|
|
118
|
+
### JsonObject (input & output)
|
|
119
|
+
|
|
120
|
+
```typescript
|
|
121
|
+
interface JsonObject {
|
|
122
|
+
[key: string]: JsonValue;
|
|
123
|
+
}
|
|
124
|
+
type JsonValue = string | number | boolean | null | JsonValue[] | JsonObject;
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
### JsonSchema (schema input)
|
|
128
|
+
|
|
129
|
+
The `[schema]` input accepts a `JsonSchema` type — an alias for `JSONSchema7` from `@types/json-schema` (Draft 7):
|
|
130
|
+
|
|
131
|
+
```typescript
|
|
132
|
+
import { JsonSchema } from '@softheon/armature/b2b';
|
|
133
|
+
|
|
134
|
+
const schema: JsonSchema = {
|
|
135
|
+
type: 'object',
|
|
136
|
+
properties: {
|
|
137
|
+
Theme: { type: 'string', enum: ['dark', 'light'] },
|
|
138
|
+
MaxRetries: { type: 'integer', title: 'Max Retries' },
|
|
139
|
+
Enabled: { type: 'boolean' },
|
|
140
|
+
},
|
|
141
|
+
};
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
## Utility Functions
|
|
145
|
+
|
|
146
|
+
All utilities are importable from the entry point:
|
|
147
|
+
|
|
148
|
+
```typescript
|
|
149
|
+
import {
|
|
150
|
+
type JsonSchema,
|
|
151
|
+
unflattenJson,
|
|
152
|
+
normalizeToEntries,
|
|
153
|
+
parsePath,
|
|
154
|
+
buildNodesFromEntries,
|
|
155
|
+
flattenNamespaces,
|
|
156
|
+
filterNamespaces,
|
|
157
|
+
validateDuplicateKeys,
|
|
158
|
+
parseJsonSchema,
|
|
159
|
+
} from '@softheon/armature/b2b';
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
| Function | Description |
|
|
163
|
+
| -------------------------- | ------------------------------------------------------------------ |
|
|
164
|
+
| `unflattenJson(entries)` | Reconstructs nested JSON from `JsonEntry[]`. |
|
|
165
|
+
| `normalizeToEntries()` | Flattens a `JsonObject` into `JsonEntry[]` with dot/bracket paths. |
|
|
166
|
+
| `parsePath(key)` | Splits a dot/bracket path into segments. |
|
|
167
|
+
| `filterNamespaces()` | Filters a namespace tree by search term. |
|
|
168
|
+
| `validateDuplicateKeys()` | Detects duplicate keys in `JsonEntry[]` and returns error strings. |
|
|
169
|
+
| `parseJsonSchema()` | Parses a JSON Schema into a flat `Record<string, FieldConfig>`. |
|
|
170
|
+
|
|
171
|
+
## Key Path Notation
|
|
172
|
+
|
|
173
|
+
Internally, the editor uses path notation for keys:
|
|
174
|
+
|
|
175
|
+
| Pattern | Example | Meaning |
|
|
176
|
+
| -------------- | ----------------------------- | ------------------------- |
|
|
177
|
+
| Dot notation | `BillingInformation.PlanName` | Object property access |
|
|
178
|
+
| Bracket index | `Invoice.Payments[0].Amount` | Array element access |
|
|
179
|
+
| Quoted bracket | `["Discount Amount"]` | Special characters in key |
|
|
180
|
+
|
|
181
|
+
## Read-Only Mode
|
|
182
|
+
|
|
183
|
+
When `readOnly` is `true`:
|
|
184
|
+
|
|
185
|
+
- All scalar fields render as plaintext (no inputs)
|
|
186
|
+
- Toggle switches are disabled
|
|
187
|
+
- The debounce subscription is never created (no wasted cycles)
|
|
188
|
+
- `dataChanged` never emits
|
|
189
|
+
|
|
190
|
+
```html
|
|
191
|
+
<sof-b2b-json-editor [data]="myData" [readOnly]="true"></sof-b2b-json-editor>
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
## Search Filtering
|
|
195
|
+
|
|
196
|
+
Pass a `searchTerm` to filter the tree. Filtering activates at 2+ characters and recursively prunes namespaces/nodes that don't match:
|
|
197
|
+
|
|
198
|
+
```html
|
|
199
|
+
<sof-b2b-json-editor [data]="myData" [searchTerm]="userSearchInput"></sof-b2b-json-editor>
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
## Array Add / Remove
|
|
203
|
+
|
|
204
|
+
When a schema is provided and an array field has at least one item, the editor renders interactive add/remove controls:
|
|
205
|
+
|
|
206
|
+
- **Add button** — appears at the bottom of expanded arrays. Labeled "Add [Singular]" (e.g. "Add Payment"). Clones the first item's structure and values.
|
|
207
|
+
- **Remove button** — a trash icon on each array item header, visible on hover. Cannot remove the last remaining item (minimum 1).
|
|
208
|
+
- **Read-only mode** — add/remove buttons are hidden entirely (not disabled).
|
|
209
|
+
- **Empty arrays** — arrays with zero items and no schema display a grayed-out "(no schema)" label and are non-interactive.
|
|
210
|
+
|
|
211
|
+
All add/remove changes flow through the existing debounced `dataChanged` pipeline.
|
|
212
|
+
|
|
213
|
+
## Dirty Field Detection
|
|
214
|
+
|
|
215
|
+
Scalar fields that have been edited display a blue label to indicate unsaved changes:
|
|
216
|
+
|
|
217
|
+
- The editor tracks each field's **original value** (the value when the tree was first built).
|
|
218
|
+
- When a field's current value differs from its original, the label turns blue (`--primary-color`).
|
|
219
|
+
- Resetting a field back to its original value removes the dirty indicator.
|
|
220
|
+
- Newly added array items are **not** marked dirty — their original value is set to the cloned value.
|
|
221
|
+
|
|
222
|
+
## JSON Schema Support
|
|
223
|
+
|
|
224
|
+
The editor accepts a standard JSON Schema (Draft 7+) directly via its `[schema]` input and uses it to configure field types, labels, and dropdown options automatically.
|
|
225
|
+
|
|
226
|
+
### Schema keyword mapping
|
|
227
|
+
|
|
228
|
+
| JSON Schema keyword | Editor behaviour | Notes |
|
|
229
|
+
| ------------------- | ----------------------- | ----------------------------------------------- |
|
|
230
|
+
| `type: "string"` | `<input type="text">` | |
|
|
231
|
+
| `type: "number"` | `<input type="number">` | |
|
|
232
|
+
| `type: "integer"` | `<input type="number">` | |
|
|
233
|
+
| `type: "boolean"` | `<mat-slide-toggle>` | |
|
|
234
|
+
| `enum` | `<mat-select>` | Values are converted to strings for option list |
|
|
235
|
+
| `$id` | Label override | Last URI segment or fragment extracted |
|
|
236
|
+
| `title` | Label override | Used when `$id` is absent |
|
|
237
|
+
| `description` | Placeholder text | |
|
|
238
|
+
| `properties` | _(recurse)_ | Builds dot-notation path prefix |
|
|
239
|
+
| `items` | _(recurse)_ | Applies element schema to array paths |
|
|
240
|
+
|
|
241
|
+
Nullable types like `["string", "null"]` are supported — the first non-null type is used.
|
|
242
|
+
|
|
243
|
+
### Depth limit
|
|
244
|
+
|
|
245
|
+
Schema recursion stops at 20 levels (matching the tree builder's `MAX_DEPTH`) and logs a console warning.
|
|
246
|
+
|
|
247
|
+
## Testing
|
|
248
|
+
|
|
249
|
+
```bash
|
|
250
|
+
# Run B2B tests
|
|
251
|
+
npm run testB2B
|
|
252
|
+
|
|
253
|
+
# Or directly via ng
|
|
254
|
+
ng test b2b
|
|
255
|
+
```
|