robobyte-front-builder 1.0.26 → 1.0.27

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.
Files changed (81) hide show
  1. package/LICENSE +65 -0
  2. package/README.md +57 -0
  3. package/docs/ReportViewer.md +581 -0
  4. package/docs/fetchReportData.md +379 -0
  5. package/docs/printLayout.md +405 -0
  6. package/package.json +29 -1
  7. package/training/00-index.md +168 -0
  8. package/training/01-input.md +144 -0
  9. package/training/02-checkbox.md +107 -0
  10. package/training/03-dropdown.md +135 -0
  11. package/training/04-datepicker.md +139 -0
  12. package/training/05-radio.md +123 -0
  13. package/training/06-number.md +133 -0
  14. package/training/07-textarea.md +114 -0
  15. package/training/08-richtext.md +112 -0
  16. package/training/09-tag.md +110 -0
  17. package/training/10-time.md +107 -0
  18. package/training/11-toggle.md +108 -0
  19. package/training/12-signature.md +107 -0
  20. package/training/13-autocomplete.md +134 -0
  21. package/training/14-button.md +168 -0
  22. package/training/15-label.md +138 -0
  23. package/training/16-header.md +128 -0
  24. package/training/17-divider.md +96 -0
  25. package/training/18-image.md +105 -0
  26. package/training/19-link.md +108 -0
  27. package/training/20-banner.md +122 -0
  28. package/training/21-progress-circle.md +101 -0
  29. package/training/22-progress-line.md +93 -0
  30. package/training/23-menu.md +139 -0
  31. package/training/24-popover.md +114 -0
  32. package/training/25-layout.md +116 -0
  33. package/training/26-layout-cell.md +143 -0
  34. package/training/27-card.md +87 -0
  35. package/training/28-wizard.md +126 -0
  36. package/training/29-wizard-step.md +92 -0
  37. package/training/30-repeater.md +123 -0
  38. package/training/31-dialog.md +131 -0
  39. package/training/32-breadcrumb.md +121 -0
  40. package/training/33-dataGrid.md +129 -0
  41. package/training/34-dataTableViewer.md +115 -0
  42. package/training/35-reportViewer.md +673 -0
  43. package/training/36-viewRenderer.md +110 -0
  44. package/training/37-treeView.md +170 -0
  45. package/training/38-kpi-metric.md +148 -0
  46. package/training/39-kpi-trend.md +105 -0
  47. package/training/40-kpi-badge.md +112 -0
  48. package/training/41-kpi-statusDot.md +118 -0
  49. package/training/42-kpi-iconBox.md +114 -0
  50. package/training/43-kpi-gauge.md +143 -0
  51. package/training/44-kpi-bulletChart.md +126 -0
  52. package/training/45-kpi-colorScale.md +143 -0
  53. package/training/46-kpi-rating.md +125 -0
  54. package/training/47-kpi-countdown.md +151 -0
  55. package/training/48-fetchReportData.md +276 -0
  56. package/training/49-printLayout.md +215 -0
  57. package/training/examples/01-login-form.json +176 -0
  58. package/training/examples/02-contact-form.json +141 -0
  59. package/training/examples/03-kpi-cards-row.json +123 -0
  60. package/training/examples/04-settings-toggles.json +153 -0
  61. package/training/examples/05-user-profile-card.json +136 -0
  62. package/training/examples/06-date-range-filter.json +108 -0
  63. package/training/examples/07-search-bar-results.json +130 -0
  64. package/training/examples/08-notification-settings.json +131 -0
  65. package/training/examples/09-employee-profile-form.json +259 -0
  66. package/training/examples/10-invoice-form.json +241 -0
  67. package/training/examples/11-dashboard-overview.json +251 -0
  68. package/training/examples/12-registration-wizard.json +154 -0
  69. package/training/examples/13-product-catalog.json +168 -0
  70. package/training/examples/14-data-table-with-filters.json +180 -0
  71. package/training/examples/15-tabbed-profile.json +92 -0
  72. package/training/examples/16-kpi-full-row.json +203 -0
  73. package/training/examples/17-tree-detail-view.json +139 -0
  74. package/training/examples/18-employee-management.json +233 -0
  75. package/training/examples/19-sales-dashboard.json +272 -0
  76. package/training/examples/20-checkout-wizard.json +225 -0
  77. package/training/examples/21-analytics-page.json +222 -0
  78. package/training/examples/22-hr-onboarding.json +222 -0
  79. package/training/examples/23-document-browser.json +241 -0
  80. package/training/examples/24-order-management.json +290 -0
  81. package/training/examples/25-crm-contact-page.json +272 -0
@@ -0,0 +1,405 @@
1
+ # Print Layouts — Calling Them From Host-App Code
2
+
3
+ > **Scope.** This document covers triggering a print layout **from outside the UI Builder** — from a regular page, action handler, dialog, hook, or anywhere else in host-app code.
4
+ >
5
+ > The layout *itself* is designed in the **Print Layout Builder** at `/printBuilder` and persisted via the backend. This guide only covers how the host renders + prints a saved layout, not how to design one.
6
+ >
7
+ > If you're triggering print from inside the builder's Calculation runtime (`actionsConfig.code`, `viewerActions.code`, `onSubmit`, etc.), use the auto-injected `openPrintLayout(layoutId, data)` — see [`training/49-printLayout.md`](../training/49-printLayout.md) for the full Calculation-scope reference (data shape, when to fire, recipes for row / viewer / form-submit triggers, pitfalls). This doc is for everything else: regular host-app React, dialogs, hooks, pages outside any builder context.
8
+
9
+ ---
10
+
11
+ ## 1. Quick start
12
+
13
+ ```jsx
14
+ import { useRef } from 'react'
15
+ import PrintDialog from 'views/builder/viewer/PrintDialog'
16
+
17
+ export default function InvoicesPage() {
18
+ // 1. Allocate a ref the dialog will register itself on.
19
+ const printDialogRef = useRef(null)
20
+
21
+ // 2. Build the minimum viewerContext the dialog needs.
22
+ const viewerContext = {
23
+ printDialogRef,
24
+ data: {}, // becomes printData inside the layout
25
+ setData: () => {},
26
+ form: {},
27
+ setForm: () => {},
28
+ mode: 'preview',
29
+ isEditMode: false,
30
+ isPreviewMode: true,
31
+ isPrintContext: true,
32
+ }
33
+
34
+ // 3. Mount the dialog once. It stays hidden until you open it.
35
+ // 4. Open it from anywhere with the saved layout id + the data the
36
+ // layout should render against.
37
+ return (
38
+ <>
39
+ <Button
40
+ variant='contained'
41
+ onClick={() =>
42
+ printDialogRef.current?.open('invoice-layout-id', {
43
+ invoiceNumber: 'INV-1042',
44
+ customerName: 'Acme Corp',
45
+ lines: [{ sku: 'A', qty: 2 }, { sku: 'B', qty: 5 }],
46
+ })
47
+ }
48
+ >
49
+ Print Invoice
50
+ </Button>
51
+
52
+ <PrintDialog viewerContext={viewerContext} />
53
+ </>
54
+ )
55
+ }
56
+ ```
57
+
58
+ The dialog fetches the layout by `id`, renders the multi-zone preview, exposes a Print button, injects print CSS for `@page`, and on print fills in page numbers / clones fixed header & footer per page.
59
+
60
+ ---
61
+
62
+ ## 2. Prerequisites
63
+
64
+ ### 2.1 The layout exists on the backend
65
+
66
+ You design the layout in the host app's `/printBuilder` (the page wrapper for `PrintBuilderPage`), give it a title, and save it. The backend persists it as `{ id, title, value: JSON-stringified-schema }` under `Endpoints.PrintLayout.*`. The dialog fetches it on `open(layoutId, data)`.
67
+
68
+ ### 2.2 `<RoboByteFrontBuilderProvider>` at app root
69
+
70
+ `PrintDialog` uses `Services.GetService` to fetch the layout, which reads `apiURL` and `accessToken` from the provider. AG Grid (for `reportViewer` zones inside a layout) also reads its license from the provider. Without the provider, the fetch and any embedded grids fail silently.
71
+
72
+ ### 2.3 `next.config.js` bare-alias resolution
73
+
74
+ The import path is bare-aliased — `views/builder/viewer/PrintDialog`. Your host's `next.config.js` `NormalModuleReplacementPlugin` resolves `views/*` to the package's source when the importing file is inside the package, and to the host's source otherwise. See [INTEGRATION.md](../INTEGRATION.md). When importing `PrintDialog` from **host** code, you need to point the alias at the package explicitly because the importing file is in the host tree.
75
+
76
+ The simplest cross-tree import is to add this to your host's `package.json` `dependencies` and just import via package subpath:
77
+
78
+ ```js
79
+ // works wherever next-transpile-modules is active
80
+ import PrintDialog from 'robobyte-front-builder/src/views/builder/viewer/PrintDialog'
81
+ ```
82
+
83
+ Or expose it from your host via `next.config.js`:
84
+
85
+ ```js
86
+ // next.config.js — point bare 'views/builder/viewer/PrintDialog' at the package
87
+ const packageOwned = [
88
+ 'services/reportData/fetchReportData',
89
+ 'views/builder/viewer/PrintDialog', // ← add this
90
+ ]
91
+ packageOwned.forEach(mod => {
92
+ config.plugins.push(
93
+ new NormalModuleReplacementPlugin(
94
+ new RegExp(`^${mod.replace(/\//g, '\\/')}(\\.jsx?)?$`),
95
+ resource => { resource.request = path.join(builderSrc, mod) }
96
+ )
97
+ )
98
+ })
99
+ ```
100
+
101
+ After that, `import PrintDialog from 'views/builder/viewer/PrintDialog'` works from any host file.
102
+
103
+ ---
104
+
105
+ ## 3. How it works
106
+
107
+ The dialog is a **mounted-but-hidden** React component that exposes an imperative ref:
108
+
109
+ ```ts
110
+ printDialogRef.current = {
111
+ open(layoutId: string, data?: object): void, // fetch + open
112
+ openWithSchema(schema: object, data?: object): void, // open with a pre-loaded schema
113
+ close(): void,
114
+ }
115
+ ```
116
+
117
+ When `open(layoutId, data)` is called:
118
+
119
+ 1. The dialog calls `Endpoints.PrintLayout.Get.GetById?id=layoutId` and parses the schema.
120
+ 2. It stores `data` as the `printData` (read inside the layout as `data` in any Calculation / expression).
121
+ 3. It opens a full-screen `<Dialog>` showing a multi-page preview built by `PrintPreviewCanvas`, plus a "Print" button.
122
+ 4. Print CSS for `@page` (margins, paper size, header / footer height) is injected globally so `Ctrl+P` from inside the dialog respects the layout's settings.
123
+ 5. When the user clicks Print, the dialog closes, page numbers are filled in (`{page}` / `{pages}` tokens), fixed header / footer zones are cloned per body page, then `window.print()` is fired. An `afterprint` event listener cleans everything up.
124
+
125
+ Because the print mechanism uses the browser's native `window.print()`, the user gets the OS print dialog — no PDF library, no server round-trip. Saving as PDF is just "Save to PDF" in the OS print dialog.
126
+
127
+ ---
128
+
129
+ ## 4. The `data` you pass to `open(...)`
130
+
131
+ The second argument to `open` becomes the layout's `data` scope. Inside the layout (designed in the builder), expressions and Calculations read this object as `data`:
132
+
133
+ ```js
134
+ // In the layout, a label component's text expression:
135
+ data.invoiceNumber // → 'INV-1042'
136
+ data.lines.reduce((sum, l) => sum + l.qty, 0) // → 7
137
+ ```
138
+
139
+ There are no constraints on shape — pass whatever the layout's bindings expect. A typical pattern:
140
+
141
+ ```js
142
+ printDialogRef.current.open('invoice-layout', {
143
+ // header
144
+ invoiceNumber: order.id,
145
+ invoiceDate: formatDate(order.createdAt),
146
+ customerName: order.customer.name,
147
+ customerAddr: order.customer.address,
148
+
149
+ // body
150
+ lines: order.lines,
151
+ subtotal: order.subtotal,
152
+ tax: order.tax,
153
+ total: order.total,
154
+
155
+ // footer
156
+ notes: order.notes,
157
+ })
158
+ ```
159
+
160
+ > **Tip.** Keep a clear contract between the layout designer and the caller. The layout's Settings tab has a "Test Data" JSON field — the designer uses that to preview against representative data; that same shape is what the caller should pass at runtime.
161
+
162
+ ---
163
+
164
+ ## 5. Three mounting patterns
165
+
166
+ ### 5.1 Mount per page (simplest)
167
+
168
+ Allocate the ref + mount the dialog where you need it. Best when print is page-specific.
169
+
170
+ ```jsx
171
+ function OrdersPage() {
172
+ const printDialogRef = useRef(null)
173
+ const ctx = {
174
+ printDialogRef,
175
+ data: {}, setData: () => {}, form: {}, setForm: () => {},
176
+ mode: 'preview', isEditMode: false, isPreviewMode: true, isPrintContext: true,
177
+ }
178
+
179
+ const printOrder = (order) =>
180
+ printDialogRef.current?.open('order-layout-id', { order })
181
+
182
+ return (
183
+ <>
184
+ <OrdersTable onPrint={printOrder} />
185
+ <PrintDialog viewerContext={ctx} />
186
+ </>
187
+ )
188
+ }
189
+ ```
190
+
191
+ ### 5.2 Mount at app root (cleanest for multi-page apps)
192
+
193
+ If you want `printLayout(id, data)` callable from anywhere, mount once at the `_app.js` level and put the ref + helper in a context.
194
+
195
+ ```jsx
196
+ // host: contexts/PrintContext.jsx
197
+ import { createContext, useContext, useRef, useCallback } from 'react'
198
+ import PrintDialog from 'views/builder/viewer/PrintDialog'
199
+
200
+ const PrintCtx = createContext({ openPrintLayout: () => {} })
201
+
202
+ export function PrintProvider({ children }) {
203
+ const printDialogRef = useRef(null)
204
+
205
+ const openPrintLayout = useCallback((layoutId, data) => {
206
+ if (!printDialogRef.current) {
207
+ console.warn('[openPrintLayout] PrintDialog is not mounted yet')
208
+ return
209
+ }
210
+ printDialogRef.current.open(layoutId, data)
211
+ }, [])
212
+
213
+ const closePrintLayout = useCallback(() => {
214
+ printDialogRef.current?.close()
215
+ }, [])
216
+
217
+ const viewerContext = {
218
+ printDialogRef,
219
+ data: {}, setData: () => {}, form: {}, setForm: () => {},
220
+ mode: 'preview', isEditMode: false, isPreviewMode: true, isPrintContext: true,
221
+ }
222
+
223
+ return (
224
+ <PrintCtx.Provider value={{ openPrintLayout, closePrintLayout }}>
225
+ {children}
226
+ <PrintDialog viewerContext={viewerContext} />
227
+ </PrintCtx.Provider>
228
+ )
229
+ }
230
+
231
+ export const usePrintLayout = () => useContext(PrintCtx)
232
+ ```
233
+
234
+ ```jsx
235
+ // host: pages/_app.js
236
+ <RoboByteFrontBuilderProvider {...}>
237
+ <PrintProvider>
238
+ <Component {...pageProps} />
239
+ </PrintProvider>
240
+ </RoboByteFrontBuilderProvider>
241
+ ```
242
+
243
+ ```jsx
244
+ // any host page
245
+ import { usePrintLayout } from '@/contexts/PrintContext'
246
+
247
+ function InvoiceRow({ invoice }) {
248
+ const { openPrintLayout } = usePrintLayout()
249
+ return (
250
+ <Button onClick={() => openPrintLayout('invoice-layout', invoice)}>
251
+ Print
252
+ </Button>
253
+ )
254
+ }
255
+ ```
256
+
257
+ > This is the recommended pattern for any non-trivial host app — every page gets `usePrintLayout()` without re-mounting the dialog.
258
+
259
+ ### 5.3 With a preloaded schema (skip the fetch)
260
+
261
+ If your host already has the layout's schema in memory — e.g. from a custom backend bundle, a fixture, or a recently-saved layout — bypass the API fetch and call `openWithSchema(schema, data)`:
262
+
263
+ ```jsx
264
+ const someSchema = await fetch('/api/my-cached-layout').then(r => r.json())
265
+ printDialogRef.current.openWithSchema(someSchema, { invoiceId: 42 })
266
+ ```
267
+
268
+ This is what the Print Builder's "Test Print" button uses — the in-progress schema isn't on the server yet, so it gets pushed in directly.
269
+
270
+ ---
271
+
272
+ ## 6. Discovering and listing layouts
273
+
274
+ If users should pick a layout at runtime, two paths:
275
+
276
+ ### 6.1 Embed the built-in `PrintLayoutsList` page
277
+
278
+ ```jsx
279
+ import { PrintLayoutsList } from 'robobyte-front-builder'
280
+
281
+ <PrintLayoutsList />
282
+ ```
283
+
284
+ Renders the same list view as `/printBuilder/layouts` — browse, preview, delete.
285
+
286
+ ### 6.2 Roll your own with the endpoint
287
+
288
+ ```jsx
289
+ import { Services, Endpoints } from 'services/Endpoints'
290
+
291
+ async function loadLayouts() {
292
+ const r = await Services.GetService(Endpoints.PrintLayout.Get.GetAll, false, {})
293
+ return r?.data ?? [] // [{ id, title, value }, ...]
294
+ }
295
+ ```
296
+
297
+ `value` is the JSON-stringified schema. Pass `id` to `printDialogRef.current.open(id, data)` to render.
298
+
299
+ ---
300
+
301
+ ## 7. Recipes
302
+
303
+ ### 7.1 Print right after a save
304
+
305
+ ```js
306
+ async function saveAndPrint(orderDraft) {
307
+ const r = await PostService(Endpoints.Orders.Post.Create, true, orderDraft)
308
+ if (r?.data) {
309
+ openPrintLayout('order-layout', { ...orderDraft, id: r.data.id })
310
+ }
311
+ }
312
+ ```
313
+
314
+ ### 7.2 Print a filtered grid (no per-row template)
315
+
316
+ For "print the report exactly as it is on screen", let the user click the **PDF export** icon in the report toolbar — it uses `jspdf-autotable` and respects current filters / columns. Use `openPrintLayout` only when you have a designed template the data should populate.
317
+
318
+ ### 7.3 Bulk print one layout per selected row
319
+
320
+ ```js
321
+ function bulkPrint(rows) {
322
+ // Print one at a time — opening multiple PrintDialogs at once would race.
323
+ // Easiest pattern: concat into a single layout that accepts an array.
324
+ openPrintLayout('packing-slips', { slips: rows })
325
+ }
326
+ ```
327
+
328
+ The layout iterates `data.slips` via a `repeater` and the print engine paginates automatically.
329
+
330
+ ### 7.4 Programmatic close (e.g. cancel from a parent)
331
+
332
+ ```js
333
+ printDialogRef.current?.close()
334
+ // OR via the provider pattern:
335
+ const { closePrintLayout } = usePrintLayout()
336
+ closePrintLayout()
337
+ ```
338
+
339
+ ### 7.5 Print a layout from a `<reportViewer>` viewer action
340
+
341
+ If you've wired the `PrintProvider` (section 5.2), pull `openPrintLayout` from the hook inside your `viewerActions` `onClick`:
342
+
343
+ ```jsx
344
+ import { usePrintLayout } from '@/contexts/PrintContext'
345
+
346
+ function OrdersReport() {
347
+ const { openPrintLayout } = usePrintLayout()
348
+ const [api, setApi] = useState(null)
349
+
350
+ const viewerActions = [
351
+ {
352
+ label: 'Print Selected',
353
+ icon: 'PrintOutlined',
354
+ variant: 'contained',
355
+ onClick: () => {
356
+ const selected = api?.getSelectedRows() ?? []
357
+ if (selected.length === 0) return
358
+ openPrintLayout('order-layout', { orders: selected })
359
+ },
360
+ },
361
+ ]
362
+
363
+ return (
364
+ <ReportViewer pageId='ORDERS' setOutGridApi={setApi} viewerActions={viewerActions} />
365
+ )
366
+ }
367
+ ```
368
+
369
+ ---
370
+
371
+ ## 8. Pitfalls
372
+
373
+ - **Ref not registered yet.** `PrintDialog` registers `printDialogRef.current` in a `useEffect` after mount. Calling `open()` before the first render completes throws "PrintDialog is not mounted". In practice this only matters for SSR — wrap calls in `useEffect` or `requestAnimationFrame` if you must trigger on first paint.
374
+ - **Multiple mounted dialogs.** Each `<PrintDialog>` instance writes to its own ref. Mounting two with the same ref is undefined; mounting two with different refs is fine but you'll have stacking print CSS. Use the provider pattern (section 5.2) to enforce a single instance.
375
+ - **Provider missing.** Without `<RoboByteFrontBuilderProvider>`, `Services.GetService` has no base URL or auth — the layout fetch fails silently and the dialog stays in its loading state.
376
+ - **The `viewerContext` shape matters.** The dialog reads `printDialogRef` from it. The other fields (`data`, `setData`, `form`, …) are forwarded to every zone's render context. Pass at least the keys shown in section 1 — missing keys will show up as `undefined` inside the layout's expressions.
377
+ - **`data` is the layout's runtime scope, not arbitrary metadata.** Inside the layout, every Calculation and expression reads `data.x`. If you pass `{ order: {...} }`, expressions need to write `data.order.x`. Match the shape the designer designed against.
378
+ - **Saving as PDF is a browser print operation.** There's no programmatic "save to PDF" — it goes through the OS print dialog. Users on Chromium pick "Save as PDF"; users on Safari pick the print → PDF flow. If you need server-rendered PDFs, that's out of scope for this package.
379
+ - **`@page` settings only kick in after the first `open` of a session.** The CSS is injected on schema load. If you change the layout's `settings.margins` and call `open` again, the new CSS replaces the old. Don't try to set `@page` from outside the layout.
380
+ - **Print preview shows the AG Grid as a static HTML table.** When a layout includes a `reportViewer`, the print path fetches **all rows with `isPagination: false`** and renders a plain table (AG Grid virtualization breaks under `window.print()`). For very large reports, expect the print preview to take several seconds to populate.
381
+
382
+ ---
383
+
384
+ ## 9. Cheat sheet
385
+
386
+ 1. Import: `import PrintDialog from 'views/builder/viewer/PrintDialog'` (bare alias; add the package-owned plugin rule in `next.config.js` if you're importing from host code).
387
+ 2. Allocate `const printDialogRef = useRef(null)`.
388
+ 3. Mount `<PrintDialog viewerContext={{ printDialogRef, data: {}, setData: () => {}, form: {}, setForm: () => {}, mode: 'preview', isEditMode: false, isPreviewMode: true, isPrintContext: true }} />` once in your tree.
389
+ 4. Call `printDialogRef.current.open('layout-id', dataObject)` to fetch + show.
390
+ 5. Or `printDialogRef.current.openWithSchema(schema, dataObject)` if you already have the schema in memory.
391
+ 6. Call `printDialogRef.current.close()` to dismiss.
392
+ 7. For multi-page apps: wrap once in a `PrintProvider` and expose `usePrintLayout()` (section 5.2).
393
+ 8. The `dataObject` becomes `data` inside the layout — match the shape the designer designed against.
394
+
395
+ ---
396
+
397
+ ## Cross-references
398
+
399
+ - **In-builder usage** (`openPrintLayout` auto-injected into Calculation scope): [`training/49-printLayout.md`](../training/49-printLayout.md). Also covered briefly in README's *Calculation Scope Reference* and *Print Layout Builder* sections.
400
+ - **Designing layouts**: visit `/printBuilder` in the host app (the `PrintBuilderPage` re-export).
401
+ - **Listing / managing saved layouts**: `<PrintLayoutsList />` (re-export), or roll your own via `Endpoints.PrintLayout.Get.GetAll`.
402
+ - **Host-app integration**: [INTEGRATION.md](../INTEGRATION.md) for `next.config.js`, peer deps, provider setup.
403
+ - **AG Grid theme customization** (relevant for `reportViewer` zones inside a print layout): README → *AG Grid theme*.
404
+ - **`<ReportViewer>` host-app usage**: [docs/ReportViewer.md](./ReportViewer.md).
405
+ - **`fetchReportDataByPageId` host-app usage**: [docs/fetchReportData.md](./fetchReportData.md).
package/package.json CHANGED
@@ -1,7 +1,31 @@
1
1
  {
2
2
  "name": "robobyte-front-builder",
3
- "version": "1.0.26",
3
+ "version": "1.0.27",
4
4
  "description": "RoboByte low-code UI builder, Report builder, and navigation extension system",
5
+ "keywords": [
6
+ "low-code",
7
+ "ui-builder",
8
+ "report-builder",
9
+ "print-layout",
10
+ "next.js",
11
+ "react",
12
+ "ag-grid",
13
+ "mui",
14
+ "drag-and-drop",
15
+ "schema-driven",
16
+ "form-builder",
17
+ "navigation"
18
+ ],
19
+ "homepage": "https://github.com/Hossny37/RoboByteFrontBuilder#readme",
20
+ "repository": {
21
+ "type": "git",
22
+ "url": "git+https://github.com/Hossny37/RoboByteFrontBuilder.git"
23
+ },
24
+ "bugs": {
25
+ "url": "https://github.com/Hossny37/RoboByteFrontBuilder/issues"
26
+ },
27
+ "license": "MIT",
28
+ "author": "Hossny37",
5
29
  "main": "src/lib/index.js",
6
30
  "files": [
7
31
  "src",
@@ -9,7 +33,11 @@
9
33
  "styles",
10
34
  "next.config.js",
11
35
  "jsconfig.json",
36
+ "LICENSE",
12
37
  "INTEGRATION.md",
38
+ "docs",
39
+ "training/*.md",
40
+ "training/examples",
13
41
  "RoboByteBuilder_User_Manual.docx"
14
42
  ],
15
43
  "exports": {
@@ -0,0 +1,168 @@
1
+ # RoboByte Front Builder — Component Training Reference
2
+
3
+ Complete reference for all components. Use these files to train a local AI model to generate valid builder schemas.
4
+
5
+ ---
6
+
7
+ ## Schema Structure
8
+
9
+ Every schema follows this structure:
10
+ ```json
11
+ {
12
+ "root": { "type": "layout", "props": { "cols": 1 }, "children": [ ... ] },
13
+ "dialogs": [],
14
+ "actions": [],
15
+ "timers": []
16
+ }
17
+ ```
18
+
19
+ - **Root is always a `layout`** — never use `container` (banned).
20
+ - Direct children of `layout` must be `layout-cell` nodes.
21
+ - Each `layout-cell` contains one component (or a nested `layout` for complex layouts).
22
+
23
+ ### Prop Wrapping (internal)
24
+ In the actual builder schema, props are wrapped in `{ valueType: 'value', value: ... }` objects. The AI generates **simplified** schemas (flat props), and the `schemaTransformer` wraps them automatically:
25
+
26
+ ```json
27
+ // AI generates:
28
+ { "type": "input", "props": { "key": "name", "label": "Name" }, "style": { "width": "100%" } }
29
+
30
+ // Builder stores internally:
31
+ { "id": "cmp_xxx", "type": "input", "props": { "main": { "key": { "valueType": "value", "value": "name" }, "label": { "valueType": "value", "value": "Name" } }, "style": { "width": { "valueType": "value", "value": "100%" } }, "advanced": {} }, "children": [] }
32
+ ```
33
+
34
+ ---
35
+
36
+ ## Component Categories
37
+
38
+ ### Field Components (Form Inputs)
39
+ | File | Component | Purpose |
40
+ |------|-----------|---------|
41
+ | 01-input.md | `input` | Single-line text input |
42
+ | 02-checkbox.md | `checkbox` | Boolean checkbox |
43
+ | 03-dropdown.md | `dropdown` | Select from list |
44
+ | 04-datepicker.md | `datepicker` | Date selection |
45
+ | 05-radio.md | `radio` | Mutually exclusive options |
46
+ | 06-number.md | `number` | Numeric input with formatting |
47
+ | 07-textarea.md | `textarea` | Multi-line text |
48
+ | 08-richtext.md | `richtext` | WYSIWYG HTML editor |
49
+ | 09-tag.md | `tag` | Multi-value chip input |
50
+ | 10-time.md | `time` | Time picker |
51
+ | 11-toggle.md | `toggle` | On/off switch |
52
+ | 12-signature.md | `signature` | Canvas signature pad |
53
+ | 13-autocomplete.md | `autocomplete` | Searchable select with async |
54
+
55
+ ### Display Components
56
+ | File | Component | Purpose |
57
+ |------|-----------|---------|
58
+ | 14-button.md | `button` | Action button (submit/reset/custom) |
59
+ | 15-label.md | `label` | Body text display (MUI Typography) |
60
+ | 16-header.md | `header` | Heading text h1–h6 |
61
+ | 17-divider.md | `divider` | Horizontal/vertical separator line |
62
+ | 18-image.md | `image` | Image from URL |
63
+ | 19-link.md | `link` | Clickable hyperlink |
64
+ | 20-banner.md | `banner` | Alert/notification banner |
65
+ | 21-progress-circle.md | `progress-circle` | Circular progress indicator |
66
+ | 22-progress-line.md | `progress-line` | Horizontal progress bar |
67
+ | 23-menu.md | `menu` | Tab navigation bar |
68
+ | 24-popover.md | `popover` | Floating panel triggered by button |
69
+
70
+ ### Structure Components
71
+ | File | Component | Purpose |
72
+ |------|-----------|---------|
73
+ | 25-layout.md | `layout` | CSS Grid container (PRIMARY STRUCTURE) |
74
+ | 26-layout-cell.md | `layout-cell` | Grid cell (child of layout) |
75
+ | 27-card.md | `card` | MUI card with title/subheader |
76
+ | 28-wizard.md | `wizard` | Multi-step stepper form |
77
+ | 29-wizard-step.md | `wizard-step` | Single step inside wizard |
78
+ | 30-repeater.md | `repeater` | Repeat template per data array item |
79
+ | 31-dialog.md | `dialog` | Modal overlay |
80
+ | 32-breadcrumb.md | `breadcrumb` | Navigation trail or step indicator |
81
+
82
+ ### Data Components
83
+ | File | Component | Purpose |
84
+ |------|-----------|---------|
85
+ | 33-dataGrid.md | `dataGrid` | AG Grid editable table |
86
+ | 34-dataTableViewer.md | `dataTableViewer` | Simple read-only HTML table |
87
+ | 35-reportViewer.md | `reportViewer` | Server-fetched AG Grid report |
88
+ | 36-viewRenderer.md | `viewRenderer` | Embed another saved view |
89
+ | 37-treeView.md | `treeView` | Hierarchical tree component |
90
+
91
+ ### KPI Components
92
+ | File | Component | Purpose |
93
+ |------|-----------|---------|
94
+ | 38-kpi-metric.md | `kpi-metric` | Single numeric KPI value |
95
+ | 39-kpi-trend.md | `kpi-trend` | Delta/change with direction icon |
96
+ | 40-kpi-badge.md | `kpi-badge` | Colored status chip/badge |
97
+ | 41-kpi-statusDot.md | `kpi-statusDot` | Small status indicator dot |
98
+ | 42-kpi-iconBox.md | `kpi-iconBox` | Boxed icon with threshold coloring |
99
+ | 43-kpi-gauge.md | `kpi-gauge` | Semicircular arc gauge |
100
+ | 44-kpi-bulletChart.md | `kpi-bulletChart` | Bullet chart (actual vs target) |
101
+ | 45-kpi-colorScale.md | `kpi-colorScale` | Color-scale bar with markers |
102
+ | 46-kpi-rating.md | `kpi-rating` | Star/heart/circle rating |
103
+ | 47-kpi-countdown.md | `kpi-countdown` | Countdown timer to a target date |
104
+
105
+ ---
106
+
107
+ ## Universal Style Props (available on every component's style tab)
108
+
109
+ Every component style tab supports two escape-hatch props for arbitrary CSS:
110
+
111
+ | Prop | Type | Notes |
112
+ |------|------|-------|
113
+ | `elementStyle` | expression | CSS **object** merged at highest priority onto the component wrapper. E.g. `{ outline: '2px solid #f00', transition: 'all 0.2s' }`. |
114
+ | `elementCss` | expression | CSS **string** merged at highest priority. Use when you need shorthand syntax that's hard to express as a JS object. E.g. `"outline: 2px solid red; background: linear-gradient(135deg, #667eea, #764ba2)"`. |
115
+
116
+ > `elementCss` takes effect after `elementStyle`. Both are processed and merged last, so they override ALL other style tab settings.
117
+
118
+ ---
119
+
120
+ ## Critical Rules
121
+
122
+ 1. **Root must be `layout`** — never `container` (banned).
123
+ 2. **`layout` children must be `layout-cell`** — no other components directly.
124
+ 3. **One component per cell** for multi-column layouts (`cols ≥ 2`). For single-column (`cols: 1`), cells can contain nested layouts.
125
+ 4. **Use `style` key** (not inside `props`) for layout-cell visual styling: `backgroundColor`, `padding`, `borderRadius`, `boxShadow`.
126
+ 5. **Use `props` key** for component behavior props: `key`, `label`, `value`, etc.
127
+ 6. **Data is accessed via expressions**: `data.fieldName`, `form.fieldName`, `dataItem.field` (inside repeater).
128
+ 7. **Dialogs are siblings of root**, not nested inside it.
129
+ 8. **KPI components are leaf nodes** — they have no children.
130
+
131
+ ---
132
+
133
+ ## Quick Decision Guide
134
+
135
+ | Need | Component |
136
+ |------|-----------|
137
+ | Text input | `input` |
138
+ | Multi-line text | `textarea` |
139
+ | Rich formatted text | `richtext` |
140
+ | Number with formatting | `number` |
141
+ | Date | `datepicker` |
142
+ | Time | `time` |
143
+ | Yes/No toggle | `toggle` or `checkbox` |
144
+ | Select one from list | `dropdown` (small list) or `autocomplete` (large/async) |
145
+ | Select multiple | `dropdown` + `multiple: true` or `tag` |
146
+ | Select mutually exclusive (visible) | `radio` |
147
+ | Signature capture | `signature` |
148
+ | Display text | `label` |
149
+ | Display heading | `header` |
150
+ | Display number/metric | `kpi-metric` |
151
+ | Display status | `kpi-badge` or `kpi-statusDot` |
152
+ | Display trend | `kpi-trend` |
153
+ | Display gauge | `kpi-gauge` |
154
+ | Display progress | `progress-line` or `progress-circle` |
155
+ | Display table (static) | `dataTableViewer` |
156
+ | Display table (server) | `reportViewer` |
157
+ | Editable table | `dataGrid` |
158
+ | Tree hierarchy | `treeView` |
159
+ | Embed another view | `viewRenderer` |
160
+ | Repeat a template | `repeater` |
161
+ | Multi-step form | `wizard` + `wizard-step` |
162
+ | Tabs | `menu` |
163
+ | Modal | `dialog` |
164
+ | Floating panel | `popover` |
165
+ | Navigation trail | `breadcrumb` |
166
+ | Alert/notification | `banner` |
167
+ | Action button | `button` |
168
+ | Page structure | `layout` + `layout-cell` |