@mosaicoo/form-angular 0.6.0 → 0.8.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.
@@ -83,6 +83,76 @@ interface CatalogGroup {
83
83
  }
84
84
  declare const DEFAULT_CATALOG: CatalogGroup[];
85
85
 
86
+ /**
87
+ * Reusable blocks: a named node subtree (an address group, a payment panel,
88
+ * a compliance section) that can be dropped into any form. Blocks are plain
89
+ * schema fragments — serializable, portable and free of runtime state.
90
+ *
91
+ * The designer keeps them locally by default; hosts that want blocks shared
92
+ * across users bind `[blocks]` and persist `(blocksChanged)` themselves.
93
+ */
94
+ interface FormBlock {
95
+ id: string;
96
+ label: string;
97
+ /** Schema subtree; keys are regenerated on insert to stay unique. */
98
+ node: FieldNode;
99
+ }
100
+
101
+ /**
102
+ * Every visible string of the designer, so hosts can localize the authoring
103
+ * experience the same way they already localize the runtime. Override
104
+ * partially — unset entries fall back to English.
105
+ *
106
+ * The palette itself is DATA: translate `DEFAULT_CATALOG` (or supply your own
107
+ * groups) and pass it through the `[catalog]` input.
108
+ */
109
+ interface DesignerLabels {
110
+ undo: string;
111
+ redo: string;
112
+ moveUp: string;
113
+ moveDown: string;
114
+ duplicate: string;
115
+ delete: string;
116
+ saveBlock: string;
117
+ workspace: string;
118
+ panels: string;
119
+ presets: string;
120
+ resetLayout: string;
121
+ moveLeft: string;
122
+ moveRight: string;
123
+ hidePanel: string;
124
+ import: string;
125
+ export: string;
126
+ preview: string;
127
+ design: string;
128
+ cancel: string;
129
+ close: string;
130
+ importTitle: string;
131
+ importPlaceholder: string;
132
+ importError: string;
133
+ exportTitle: string;
134
+ canvasEmpty: string;
135
+ selectField: string;
136
+ testData: string;
137
+ panelFields: string;
138
+ panelStructure: string;
139
+ panelProperties: string;
140
+ noFields: string;
141
+ }
142
+ declare const DESIGNER_LABELS_EN: DesignerLabels;
143
+
144
+ /**
145
+ * Drop-target identity shared by the canvas and the node components.
146
+ * A target is a position in a parent's children list, optionally bound to a
147
+ * column of a `columns` container.
148
+ */
149
+ interface DropTarget {
150
+ path: NodePath;
151
+ /** Column index when the parent lays children out in columns. */
152
+ column?: number;
153
+ }
154
+ declare function dropId(target: DropTarget): string;
155
+
86
156
  /**
87
157
  * Designer workspace layout.
88
158
  *
@@ -126,6 +196,42 @@ declare class FormDesignerComponent {
126
196
  readonly source: _angular_core.InputSignal<unknown>;
127
197
  /** Extra palette groups contributed by the host. */
128
198
  readonly extraCatalog: _angular_core.InputSignal<CatalogGroup[]>;
199
+ /** Replaces the built-in palette (e.g. a translated DEFAULT_CATALOG). */
200
+ readonly catalogOverride: _angular_core.InputSignal<CatalogGroup[] | null>;
201
+ /** Designer texts; partial overrides fall back to English. */
202
+ readonly labels: _angular_core.InputSignalWithTransform<{
203
+ undo: string;
204
+ redo: string;
205
+ moveUp: string;
206
+ moveDown: string;
207
+ duplicate: string;
208
+ delete: string;
209
+ saveBlock: string;
210
+ workspace: string;
211
+ panels: string;
212
+ presets: string;
213
+ resetLayout: string;
214
+ moveLeft: string;
215
+ moveRight: string;
216
+ hidePanel: string;
217
+ import: string;
218
+ export: string;
219
+ preview: string;
220
+ design: string;
221
+ cancel: string;
222
+ close: string;
223
+ importTitle: string;
224
+ importPlaceholder: string;
225
+ importError: string;
226
+ exportTitle: string;
227
+ canvasEmpty: string;
228
+ selectField: string;
229
+ testData: string;
230
+ panelFields: string;
231
+ panelStructure: string;
232
+ panelProperties: string;
233
+ noFields: string;
234
+ }, Partial<DesignerLabels>>;
129
235
  /** Emitted after every committed edit (undo/redo included). */
130
236
  readonly schemaChanged: _angular_core.OutputEmitterRef<FormSchema>;
131
237
  readonly draft: _angular_core.WritableSignal<FormSchema>;
@@ -155,8 +261,19 @@ declare class FormDesignerComponent {
155
261
  dock(panel: PanelId, side: DockSide): void;
156
262
  applyPreset(id: string): void;
157
263
  resetLayout(): void;
264
+ /** Live drag state of a dock splitter. */
265
+ private resizing;
266
+ startResize(side: 'left' | 'right', event: PointerEvent): void;
267
+ onResizeMove(event: PointerEvent): void;
268
+ endResize(): void;
158
269
  isGroupOpen(label: string): boolean;
159
270
  toggleGroup(label: string): void;
271
+ /** Saved blocks (host-controlled when `[blocks]` is bound). */
272
+ readonly blocks: _angular_core.InputSignal<FormBlock[] | null>;
273
+ readonly blocksChanged: _angular_core.OutputEmitterRef<FormBlock[]>;
274
+ private readonly localBlocks;
275
+ readonly effectiveBlocks: _angular_core.Signal<FormBlock[]>;
276
+ /** Palette = built-ins + host extras + saved blocks as a group. */
160
277
  readonly catalog: _angular_core.Signal<CatalogGroup[]>;
161
278
  readonly diagnostics: _angular_core.Signal<SchemaDiagnostic[]>;
162
279
  readonly exportedJson: _angular_core.Signal<string>;
@@ -181,13 +298,30 @@ declare class FormDesignerComponent {
181
298
  duplicateSelected(): void;
182
299
  moveSelected(delta: -1 | 1): void;
183
300
  applyPatch(event: InspectorPatch): void;
301
+ /** Saves the selected node (with its subtree) as a reusable block. */
302
+ saveAsBlock(): void;
303
+ removeBlock(id: string): void;
304
+ isBlockEntry(entry: CatalogEntry): boolean;
305
+ blockIdOf(entry: CatalogEntry): string;
306
+ /** What is being dragged: a palette entry or an existing node. */
307
+ private readonly dragging;
308
+ /** Drop zone highlighted while hovering (see `dropId`). */
309
+ readonly dropTarget: _angular_core.WritableSignal<string | null>;
310
+ startEntryDrag(entry: CatalogEntry, event: DragEvent): void;
311
+ startNodeDrag(path: NodePath, event?: DragEvent): void;
312
+ endDrag(): void;
313
+ allowDrop(target: DropTarget, event?: DragEvent): void;
314
+ /** Drops onto `target` — the position (and column) the node should occupy. */
315
+ drop(target: DropTarget, event?: DragEvent): void;
316
+ isDropTarget(target: DropTarget): boolean;
317
+ isDragging(): boolean;
184
318
  select(path: NodePath | null): void;
185
319
  isSelectedPath(path: NodePath): boolean;
186
320
  openExport(): void;
187
321
  doImport(raw: string): void;
188
322
  onKeydown(event: KeyboardEvent): void;
189
323
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<FormDesignerComponent, never>;
190
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<FormDesignerComponent, "mform-designer", never, { "schema": { "alias": "schema"; "required": false; "isSignal": true; }; "source": { "alias": "source"; "required": false; "isSignal": true; }; "extraCatalog": { "alias": "extraCatalog"; "required": false; "isSignal": true; }; }, { "schemaChanged": "schemaChanged"; }, never, never, true, never>;
324
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<FormDesignerComponent, "mform-designer", never, { "schema": { "alias": "schema"; "required": false; "isSignal": true; }; "source": { "alias": "source"; "required": false; "isSignal": true; }; "extraCatalog": { "alias": "extraCatalog"; "required": false; "isSignal": true; }; "catalogOverride": { "alias": "catalog"; "required": false; "isSignal": true; }; "labels": { "alias": "labels"; "required": false; "isSignal": true; }; "blocks": { "alias": "blocks"; "required": false; "isSignal": true; }; }, { "schemaChanged": "schemaChanged"; "blocksChanged": "blocksChanged"; }, never, never, true, never>;
191
325
  }
192
326
 
193
327
  /**
@@ -195,13 +329,24 @@ declare class FormDesignerComponent {
195
329
  * leaf rendering to the RUNTIME `<mform-node>` so what you see is what the
196
330
  * renderer will produce. Canvas controls are non-interactive — testing
197
331
  * happens in Preview mode.
332
+ *
333
+ * Drop zones sit between children (and inside each column), so fields can be
334
+ * dragged INTO containers, not just reordered at the root.
198
335
  */
199
336
  declare class DesignerNodeComponent {
200
337
  readonly node: _angular_core.InputSignal<FieldNode>;
201
338
  readonly path: _angular_core.InputSignal<NodePath>;
202
339
  readonly engine: _angular_core.InputSignal<FormEngine>;
203
340
  readonly selected: _angular_core.InputSignal<NodePath | null>;
341
+ /** True while something is being dragged (reveals the drop zones). */
342
+ readonly dragging: _angular_core.InputSignal<boolean>;
343
+ /** Id of the drop zone currently hovered. */
344
+ readonly activeDrop: _angular_core.InputSignal<string | null>;
204
345
  readonly selectNode: _angular_core.OutputEmitterRef<NodePath>;
346
+ readonly nodeDragStart: _angular_core.OutputEmitterRef<NodePath>;
347
+ readonly dragOverTarget: _angular_core.OutputEmitterRef<DropTarget>;
348
+ readonly dropOnTarget: _angular_core.OutputEmitterRef<DropTarget>;
349
+ readonly dragFinished: _angular_core.OutputEmitterRef<void>;
205
350
  readonly activeTab: _angular_core.WritableSignal<number>;
206
351
  container(): ContainerField;
207
352
  chip(): string;
@@ -210,9 +355,13 @@ declare class DesignerNodeComponent {
210
355
  columnsTemplate(): string;
211
356
  onSelect(event: Event): void;
212
357
  setTab(index: number, event: Event): void;
358
+ isOver(path: NodePath, column?: number): boolean;
359
+ onDragStart(path: NodePath, event: Event): void;
360
+ onDragOver(path: NodePath, column: number | undefined, event: DragEvent): void;
361
+ onDrop(path: NodePath, column: number | undefined, event: DragEvent): void;
213
362
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<DesignerNodeComponent, never>;
214
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<DesignerNodeComponent, "mform-designer-node", never, { "node": { "alias": "node"; "required": true; "isSignal": true; }; "path": { "alias": "path"; "required": true; "isSignal": true; }; "engine": { "alias": "engine"; "required": true; "isSignal": true; }; "selected": { "alias": "selected"; "required": false; "isSignal": true; }; }, { "selectNode": "selectNode"; }, never, never, true, never>;
363
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<DesignerNodeComponent, "mform-designer-node", never, { "node": { "alias": "node"; "required": true; "isSignal": true; }; "path": { "alias": "path"; "required": true; "isSignal": true; }; "engine": { "alias": "engine"; "required": true; "isSignal": true; }; "selected": { "alias": "selected"; "required": false; "isSignal": true; }; "dragging": { "alias": "dragging"; "required": false; "isSignal": true; }; "activeDrop": { "alias": "activeDrop"; "required": false; "isSignal": true; }; }, { "selectNode": "selectNode"; "nodeDragStart": "nodeDragStart"; "dragOverTarget": "dragOverTarget"; "dropOnTarget": "dropOnTarget"; "dragFinished": "dragFinished"; }, never, never, true, never>;
215
364
  }
216
365
 
217
- export { DEFAULT_CATALOG, DEFAULT_LAYOUT, DesignerNodeComponent, FormDesignerComponent, InspectorComponent, PANEL_LABELS, WORKSPACE_PRESETS };
218
- export type { CatalogEntry, CatalogGroup, DockSide, InspectorPatch, PanelId, WorkspaceLayout, WorkspacePreset };
366
+ export { DEFAULT_CATALOG, DEFAULT_LAYOUT, DESIGNER_LABELS_EN, DesignerNodeComponent, FormDesignerComponent, InspectorComponent, PANEL_LABELS, WORKSPACE_PRESETS, dropId };
367
+ export type { CatalogEntry, CatalogGroup, DesignerLabels, DockSide, DropTarget, FormBlock, InspectorPatch, PanelId, WorkspaceLayout, WorkspacePreset };
@@ -72,11 +72,21 @@ declare class FormNodeComponent {
72
72
  readonly childScope: _angular_core.Signal<string>;
73
73
  rowScope(index: number): string;
74
74
  visible(): boolean;
75
- containerLayout(): 'columns' | 'tabs' | 'array' | 'block';
75
+ containerLayout(): 'columns' | 'tabs' | 'accordion' | 'array' | 'block';
76
+ /** Open accordion sections; the first one starts expanded. */
77
+ private readonly openSections;
78
+ isSectionOpen(index: number): boolean;
79
+ toggleSection(index: number): void;
76
80
  columns(): FieldNode[][];
77
81
  columnsTemplate(): string;
78
82
  value(): unknown;
79
83
  stringValue(): string;
84
+ /** Tracks focus so numeric formatting steps aside during typing. */
85
+ readonly focused: _angular_core.WritableSignal<boolean>;
86
+ onFocus(): void;
87
+ onBlur(): void;
88
+ /** Numeric inputs stay `text` when formatted (a number input rejects `R$`). */
89
+ numericFormatted(): boolean;
80
90
  mapValue(): Record<string, unknown>;
81
91
  rows(): unknown[];
82
92
  required(): boolean;
@@ -113,6 +123,15 @@ declare class FormNodeComponent {
113
123
  private refTimer;
114
124
  /** Label of the chosen option (falls back to the raw value). */
115
125
  readonly refLabel: _angular_core.WritableSignal<string | null>;
126
+ /** Last query typed, replayed when `refreshOn` invalidates the results. */
127
+ private refQuery;
128
+ private refRefreshKey;
129
+ /**
130
+ * `refreshOn` for autocomplete: when the observed data changes, cached
131
+ * results are dropped so the next search runs against the new context
132
+ * (e.g. properties filtered by the selected client).
133
+ */
134
+ private watchReferenceRefresh;
116
135
  refDisplay(): string;
117
136
  refSearch(event: Event): void;
118
137
  private refResolve;
@@ -192,7 +211,11 @@ declare class FormRendererComponent {
192
211
  readonly errorSummary: _angular_core.WritableSignal<FieldError[]>;
193
212
  constructor();
194
213
  previousStep(): void;
195
- nextStep(): void;
214
+ /**
215
+ * Advances only when the step is valid INCLUDING async rules, so a
216
+ * server-side check can still block the transition.
217
+ */
218
+ nextStep(): Promise<void>;
196
219
  onSubmit(event: Event): Promise<void>;
197
220
  /** Finds the wizard step that owns a (possibly row-indexed) data path. */
198
221
  private stepIndexForPath;