Skip to content

Hossny37/RoboByteFrontBuilder

Repository files navigation

robobyte-front-builder

A low-code UI Builder, Report Builder, Print Layout Designer, and Navigation Extension API for Next.js applications.

npm version license github


📚 Documentation

Document Audience What it covers
README.md (this file) Everyone Public surface, provider props, every component's inspector schema, action-scope tables, troubleshooting, changelog. The exhaustive reference.
INTEGRATION.md Host-app developers next.config.js setup, peer deps, page wrapper pattern, provider bridge, print layout integration steps.
docs/ReportViewer.md Host-app developers Embedding <ReportViewer> in regular React (cancellation, memo'd filters, viewerActions, master/detail patterns).
docs/fetchReportData.md Host-app developers Calling fetchReportDataByPageId directly from host code (hooks, KPI counters, XLSX export, paginated cursors).
docs/printLayout.md Host-app developers Triggering print layouts via PrintDialog ref API, recommended PrintProvider + usePrintLayout() pattern.
training/00-index.md AI sessions / schema authors Component catalog index — categories and one-page refs for every component the builder ships.
training/35-reportViewer.md AI sessions / schema authors Full AI manual for the reportViewer component (Calculation scope, action arrays, filter shape, recipes).
training/48-fetchReportData.md AI sessions / schema authors In-builder Calculation reference for the auto-injected fetchReportData helper.
training/49-printLayout.md AI sessions / schema authors In-builder Calculation reference for openPrintLayout / closePrintLayout.
RoboByteBuilder_User_Manual.docx End users Visual user manual for the builder UI. Ships inside the package.

Pair convention. Most features have two manuals: a docs/ one for host-app React code (consumer of the package) and a training/ one for AI sessions emitting builder schemas / Calculation code. They cross-link each other; pick the audience that matches your task.


Table of Contents

  1. What's included
  2. Requirements
  3. Installation
  4. Peer dependencies
  5. next.config.js setup
  6. Provider setup
  7. Builder pages
  8. Navigation Extension API
  9. Provider props reference
  10. AG Grid theme
  11. fetchReportDataByPageId
  12. ReportViewer as a component
  13. Data Grid component
  14. Dialog component
  15. Popover component
  16. Excel Upload component
  17. Wizard component
  18. Repeater component
  19. Menu component
  20. View Renderer component
  21. Layout Grid component
  22. Breadcrumb component
  23. Print Layout Builder
  24. Calculation Scope Reference
  25. KPI Component Actions
  26. Global Data Store
  27. Dark / Light theme
  28. Syncing local changes
  29. Troubleshooting
  30. Publishing
  31. Changelog

What's included

  • UI Builder — drag-and-drop canvas for building data-driven views with 50+ components
  • Report Builder — design and preview paginated reports with AG Grid
  • Print Layout Designer — multi-zone print templates (header / body pages / footer)
  • Navigator Builder — configure sidebar navigation
  • Viewer — production read-only renderer for saved UI Builder views
  • Navigation Extension API — inject nav items from the host app without forking the package
  • KPI Components — 12 ready-to-use metric visualisations (gauge, trend, bullet chart, rating, countdown, …)
  • Timer Engine — configurable auto-refresh timers per view
  • Undo / Redo / Copy / Paste — full clipboard and history support in the builder
  • Global Data Store — cross-route reactive state that survives client-side navigations

Requirements

Dependency Version
Node.js ≥ 18
React / React DOM ≥ 18
Next.js ≥ 13
@mui/material ≥ 7
AG Grid ≥ 33

Installation

npm install robobyte-front-builder

Peer dependencies

Only the libraries that must be shared as a single instance are declared as peerDependencies — React, MUI, Emotion, and AG Grid. Everything else ships inside the package so the host app doesn't need to install them manually.

npm install \
  react react-dom next \
  @mui/material @mui/icons-material @mui/lab @mui/system \
  @mui/x-data-grid @mui/x-date-pickers @mui/x-internals @mui/x-virtualizer \
  @emotion/react @emotion/styled \
  ag-grid-community ag-grid-enterprise ag-grid-react \
  xlsx react-hot-toast

Why only these? React and MUI use context and module registries that break if two copies exist in the same app (hooks errors, theme not applied, AG Grid license warnings). xlsx is required by the Excel Upload component and is resolved from the host app's node_modules because the builder source is transpiled in the host's webpack context. Everything else — dayjs, lodash, recharts, etc. — can safely run from the package's own node_modules copy with no side effects.


next.config.js setup

Two things are required: transpile the package and set up the context-aware bare-alias webpack plugin so that bare imports like services/*, context/*, etc. resolve to the correct source tree.

const path = require('path')
const withTM = require('next-transpile-modules')(['robobyte-front-builder'])

const hostSrc    = path.resolve(__dirname, 'src')
const builderSrc = path.resolve(__dirname, 'node_modules/robobyte-front-builder/src')

module.exports = withTM({
  webpack(config, { isServer }) {
    if (isServer) {
      config.resolve.conditionNames = ['require', 'node', 'default']
    }

    const { NormalModuleReplacementPlugin } = require('webpack')

    // Package-owned services — always resolved from the package
    const packageOwnedServices = [
      'services/reportData/fetchReportData',
    ]
    packageOwnedServices.forEach(mod => {
      config.plugins.push(
        new NormalModuleReplacementPlugin(
          new RegExp(`^${mod.replace(/\//g, '\\/')}(\\.js)?$`),
          resource => { resource.request = path.join(builderSrc, mod) }
        )
      )
    })

    // Context-aware bare alias routing
    config.plugins.push(
      new NormalModuleReplacementPlugin(
        /^(services|views|context|src|pages)(\/|$)/,
        resource => {
          const isBuilder =
            resource.context.includes('robobyte-front-builder') ||
            resource.context.includes('RoboByteFrontBuilder')
          const root = isBuilder ? builderSrc : hostSrc
          resource.request = resource.request.replace(
            /^(services|views|context|src|pages)(\/|$)/,
            (_, prefix, sep) =>
              prefix === 'src'
                ? root + sep
                : path.join(root, prefix) + sep
          )
        }
      )
    )

    return config
  },
})

Restart the dev server whenever next.config.js changes — hot-reload does not apply to webpack plugin changes.


Provider setup (_app.js)

Wrap the component tree with RoboByteFrontBuilderProvider. Bridge your host auth context into it so the package attaches auth headers to every API call.

import { RoboByteFrontBuilderProvider } from 'robobyte-front-builder'

function RoboByteBridge({ children }) {
  const auth = useContext(YourAuthContext)
  return (
    <RoboByteFrontBuilderProvider
      baseURL={process.env.NEXT_PUBLIC_API_BASE_URL}
      apiURL={process.env.NEXT_PUBLIC_API_URL}
      user={auth.user}
      accessToken={auth.accessToken}
      agGridLicenseKey={process.env.NEXT_PUBLIC_AG_GRID_LICENSE_KEY}
      // Optional: Quartz theme overrides applied to every <AgGridReact>
      // in the package. Merged on top of the package defaults — see the
      // "AG Grid theme" section for the full list of params and the
      // programmatic API. Omit to use the package defaults.
      agGridTheme={{ accentColor: '#3b82f6' }}
    >
      {children}
    </RoboByteFrontBuilderProvider>
  )
}

export default function App({ Component, pageProps }) {
  const getLayout = Component.getLayout ?? (page => page)
  return (
    <YourAuthProvider>
      <RoboByteBridge>
        {getLayout(<Component {...pageProps} />)}
      </RoboByteBridge>
    </YourAuthProvider>
  )
}

Builder pages

All builder routes live under the /builders/ prefix. Create a thin wrapper page in your host app for each route.

Route Package export
/builders/ui UIBuilderPage
/builders/ui/views ViewsList
/builders/report ReportBuilderPage
/builders/report/list ReportsList
/builders/report/viewer ReportViewer
/builders/report/reportsPermissions ReportsCard
/builders/navigator NavigatorBuilderPage
/viewer/[id] ViewerPage
/printBuilder PrintBuilderPage
/printBuilder/layouts PrintLayoutsList

Page wrapper pattern

Use explicit import + static property assignment. A bare export { X as default } does not reliably carry getLayout, acl, authGuard across package boundaries in Next.js.

// pages/builders/report/viewer/index.jsx
import { ReportViewer } from 'robobyte-front-builder'
import BlankLayout from 'src/@core/layouts/BlankLayout'
import PermissionsSubjects from 'src/configs/Permissions/PermissionsSubjects.json'

ReportViewer.getLayout  = page => <BlankLayout>{page}</BlankLayout>
ReportViewer.acl        = { action: 'view', subject: PermissionsSubjects.Free }
ReportViewer.authGuard  = true
ReportViewer.guestGuard = false
export default ReportViewer

Viewer page (/viewer/[id])

import { useContext } from 'react'
import { ViewerPage, SystemContext } from 'robobyte-front-builder'
import { YourNavContext } from 'src/context/YourNavContext'

function SystemContextBridge({ children }) {
  const { nav } = useContext(YourNavContext)
  return (
    <SystemContext.Provider value={{ nav }}>
      {children}
    </SystemContext.Provider>
  )
}

export default function ViewerRoute() {
  return (
    <SystemContextBridge>
      <ViewerPage />
    </SystemContextBridge>
  )
}

ViewerRoute.authGuard  = true
ViewerRoute.guestGuard = false

Navigation Extension API

Option A — Static items via the Provider

<RoboByteFrontBuilderProvider
  navExtensions={[
    {
      id: 'host-analytics',
      title: 'Analytics',
      icon: 'ChartBar',
      type: 'static',
      path: '/analytics',
      insertAt: 'end',
    },
  ]}
>
  ...
</RoboByteFrontBuilderProvider>

Option B — Dynamic items via useNavExtension hook

import { useNavExtension } from 'robobyte-front-builder'

function MyFeaturePlugin() {
  useNavExtension(
    [{ id: 'my-feature', title: 'My Feature', icon: 'StarOutline', type: 'static', path: '/my-feature', insertAt: 'start' }],
    'my-feature-plugin'
  )
  return null
}

Nav item shape

Field Type Required Description
id string yes Stable unique identifier
title string yes Display label
icon string no mdi-material-ui icon name
type 'static' | 'dynamic' | 'external' yes Route type
path string for static Absolute path
viewId number for dynamic Registered view ID
externalUrl string for external Full URL, opens in new tab
insertAt 'start' | 'end' | number | { afterId } | { beforeId } no Placement (default 'end')
children NavItem[] no Collapsible group
action / subject string no CASL ACL visibility

Provider props reference

Prop Type Description
baseURL string Root API server URL
apiURL string /api prefix URL
user object Current user object from your auth context
accessToken string Bearer token attached to every service call
agGridLicenseKey string AG Grid Enterprise license key — the provider calls LicenseManager.setLicenseKey() and registers all enterprise modules internally
agGridTheme object Quartz theme overrides applied to every <AgGridReact> in the package. Merged on top of DEFAULT_AG_THEME_PARAMS. Example: { accentColor: '#3b82f6', headerHeight: 32 }. See AG Grid theme.
navExtensions array Static nav items to inject into the sidebar
endpoints object Full-URL overrides per endpoint group + name

AG Grid note: Do not call LicenseManager or ModuleRegistry in the host app — the provider handles it entirely.


AG Grid theme

Every <AgGridReact> in the package — reportViewer, dataGrid, the role-permission editor, the navigator picker — reads its theme from a single context. The default lives in code at src/lib/agGridTheme.js and can be overridden in two places:

1. Host-app override via the provider

Pass an object of Quartz params to agGridTheme. The object is merged on top of the package defaults — keys you set win, everything else falls back.

<RoboByteFrontBuilderProvider
  agGridTheme={{
    accentColor:  '#3b82f6',
    headerHeight: 32,
    fontFamily:   'inherit',
  }}
  /* …other props… */
>
  <App />
</RoboByteFrontBuilderProvider>

See the AG Grid Quartz theming reference for the full list of params.

2. Package-wide default

Open src/lib/agGridTheme.js and edit DEFAULT_AG_THEME_PARAMS. Affects every consumer of robobyte-front-builder that doesn't supply its own agGridTheme.

Programmatic use

import {
  DEFAULT_AG_THEME_PARAMS,   // frozen params object
  DEFAULT_AG_THEME,          // pre-built Quartz theme
  buildAgGridTheme,          // (overrides) => Quartz theme
  AgGridThemeProvider,       // standalone provider (no other dependencies)
  useAgGridTheme,            // hook returning the resolved theme
} from 'robobyte-front-builder'

// In a host component that renders its own AG Grid:
import { AgGridReact } from 'ag-grid-react'
function MyGrid() {
  const theme = useAgGridTheme()
  return <AgGridReact theme={theme} columnDefs={[...]} />
}

The hook falls back to DEFAULT_AG_THEME when called outside RoboByteFrontBuilderProvider, so isolated grids still render correctly.

Future plan. A "system settings" path will eventually layer between DEFAULT_AG_THEME_PARAMS and the host's agGridTheme prop, letting admins customize the theme without a code change. The provider API will stay the same.


fetchReportDataByPageId

Fetches report data by pageId without any AG Grid dependency. Always imported from the package path — the NormalModuleReplacementPlugin in next.config.js routes it to the package's canonical implementation.

import fetchReportDataByPageId from 'services/reportData/fetchReportData'

const result = await fetchReportDataByPageId({
  pageId,          // required
  filter,          // { Tfilter, TFilter, customFilterCode, ... }
  isDataOnly,      // return raw rows only (default false)
  dataAsObject,    // key rows by unique id (default false)
  isPagination,    // server-side pagination (default true)
  isSingle,        // return first row only (default false)
  globalParams,    // override selectionParams by index
  page,            // page number (default 1)
  pageSize,        // page size (default 50)
  authContext,
  context,
})

if (result.success) {
  console.log(result.rows)
  console.log(result.total)
}

customFilterCode

const filter = {
  customFilterCode: `
    if (authContext?.user?.shopId) {
      customFilter.push({ field: 'ShopId', value: authContext.user.shopId, operation: 'Equal' })
    }
  `
}

ReportViewer as a component

ReportViewer can be rendered inline anywhere — not only as a full page:

import { ReportViewer } from 'robobyte-front-builder'

<ReportViewer
  pageId="your-page-id"
  minimized={true}
  noHeader={true}
  filter={{ Tfilter: [...] }}
  height="400px"
/>
Prop Type Description
id string Report ID
pageId string Report page ID
filter object External filter
minimized bool Removes padding and box shadow
noHeader bool Hides the report title and studio button
height string Grid height (default 85vh)
isSingle bool Return only the first row
dataAsObject bool Key rows by unique id
setData function Callback receiving the loaded rows
setOutGridApi function Callback receiving the AG Grid API instance
refresh any Change this value to force a data reload
actions array Custom row action buttons
columnsConfig array Column overrides
globalParams array Override selectionParams by index
sessionId string Load filter payload from localStorage
updateRef ref Ref for programmatic updates

Data Grid component

The Data Grid wraps AG Grid Enterprise and is configurable entirely from the builder inspector.

Inspector — Main tab

Field Description
Key Reference key for reportRefs access
Data Key Key to read/write row data in page data
Columns Expression returning an AG Grid colDef[] array
Extra Columns Visual editor for adding new columns on top of data-driven ones
Columns Config Visual editor for overriding existing column properties by field name
Row Actions Visual editor for per-row action buttons
Add Button Label Label for the add-row button (default "Add")
New Row Template Code returning the default object for a new row
Read Only Expression — when truthy, disables all editing
Show Add Button Toggle the add-row button
Show Delete Col Toggle the delete-row column
Height Grid height expression (e.g. '400px', '60vh')
Row Selection none / single / multiple
Pagination Enable client-side pagination
Page Size Rows per page

reportRefs API

const grid = reportRefs['myGridKey']
grid.getRows()              // current row data array
grid.setRows(arr)           // replace all rows
grid.addRow(obj)            // append a row
grid.updateRow(index, obj)  // update a row by index
grid.deleteRow(index)       // delete a row by index
grid.getGridApi()           // raw AG Grid API instance

Dialog component

Renders a hidden MUI Dialog opened programmatically via openDialog(key) / closeDialog(key).

Inspector — Main tab

Field Description
Key Identifier used to open/close — must be unique on the page
View ID When set, renders a full embedded view inside the dialog body
Title Dialog title bar text (expression)
Hide Title Bar Hides the entire title bar
Max Width xs / sm / md / lg / xl
Full Width Stretch to max width breakpoint
Full Screen Full-screen mode
Show Close Button Shows the × icon
Close on Backdrop Closes when user clicks outside
Action Buttons Footer buttons, each with its own Calculation code

Usage

// Open with optional seed data
openDialog('confirmDelete')
openDialog('editUser', { userId: row.id, name: row.name })

// Close
closeDialog('confirmDelete')

Isolated data store

Each dialog gets its own data / setData scope. To read or write the parent page state from inside a dialog use pageData and pageSetData:

// Inside a dialog action:
pageSetData(prev => ({ ...prev, lastEdited: data.userId }))

Popover component

A self-contained trigger (button, icon button, or text) that opens a floating panel. No openDialog call needed.

Inspector — Main tab

Field Description
Trigger Type button / icon-button / text
Trigger Label Label text
Placement bottom-start, bottom, bottom-end, top-start, etc.
Trigger On click (default) or hover
Controlled Open Expression — overrides the internal open/close state
Close On Content Click Closes when any child inside is clicked

Excel Upload component

Lets users upload .xlsx, .xls, or .csv files, map columns to field names, and access the result in actions.

Display variants

Variant Description
dropzone Large dashed drop zone with drag & drop
button Compact outlined button
icon Icon-only button

Actions

Event newValue Notes
onUpload { fileName, headers, rowCount } Fires after parsing, before the mapping dialog
onMapped Array<object> Fires before data is saved — return a modified array to override
onClear [] Fires when the user clears the data

reportRefs API

const uploader = reportRefs['myUploaderKey']
uploader.rows          // current mapped rows
uploader.setRows(arr)  // replace stored rows
uploader.clear()       // clear all stored rows

Wizard component

A MUI Stepper with optional validation, async lifecycle hooks, and controlled or uncontrolled step state.

Inspector props — Wizard

Prop Type Default Description
orientation 'horizontal' | 'vertical' 'horizontal' Stepper orientation
linear boolean true Prevent skipping ahead
hideNavigation boolean false Hide Back / Next / Finish buttons
key string 'wizardStep' data key written with the current step index
activeStep number | expression When set, wizard is controlled by data[key]
onStepChange JS action Receives { from, to, direction, goToStep, nextStep, prevStep }
onFinish JS action Runs when user clicks Finish on the last step

Inspector props — Wizard Step

Prop Type Description
label string Step label in the stepper header
optional boolean Marks the step as optional
onEnter JS action Fires when this step becomes active
onNext JS action Return false to block navigation (validation)

Navigation helpers

goToStep(n)   // jump to step n (0-based)
nextStep()    // advance one step
prevStep()    // go back one step

Repeater component

Renders a list of identical template items from a static array, a dynamic count, or a fetched API endpoint.

Mode How to configure
Static items Set items to a static or expression array
Count Set count to a number; optionally dataKey to store values
Endpoint Set endpoint + serviceId or widgetId

Expressions inside a Repeater

Variable Value
dataItem The current array element
itemIndex Zero-based item index
form[key] The current item's scoped form value

Menu component

Renders a MUI Tabs bar in two modes: navigation mode (items-based, each tab is a link/action) and tab-panel mode (tabs-based, each tab owns a drop zone).

Prop Type Description
items array Navigation items { title, icon?, href? } — enables navigation mode
tabs array Tab panel items { label, icon? } — enables tab-panel mode
vertical boolean Render tabs vertically
justified boolean Stretch tabs to fill full width

View Renderer component

Embeds a saved builder view inline inside another view, with isolated or shared state.

Prop Type Description
viewId string Required. ID of the saved view to embed
isolated boolean true = own data/form/refs, false = shares parent state
initialData expression Seed data passed on mount (isolated mode only)
externalData expression Additional data merged on every parent re-render
heightMode 'auto' | 'fixed' 'fixed' enables a pixel height with scroll
height number Pixel height when heightMode is 'fixed'

Layout Grid component

A CSS Grid container whose column count, gap, and per-cell styling are configured in the builder inspector.

Prop Type Default Description
cols number 2 Number of equal-width columns
gap number px 8 Column gap
rowGap number px same as gap Row gap
cellMinHeight number/string Default min-height for every cell
cellPadding number/string Inner padding for every cell
cellBackgroundColor color Background color for every cell
cellBorder string CSS border shorthand for every cell
cellBorderRadius number/string Border radius for every cell
cellBoxShadow string Box-shadow for every cell
cellJustifyContent string Flexbox justify-content inside every cell
cellAlignItems string Flexbox align-items inside every cell

Breadcrumb component

Renders a MUI Breadcrumbs navigation trail.

{
  "type": "breadcrumb",
  "props": {
    "main": {
      "items": {
        "valueType": "value",
        "value": [
          { "label": "Home",    "href": "/" },
          { "label": "Reports", "href": "/reports" },
          { "label": "Q1 2025" }
        ]
      }
    }
  }
}

Print Layout Builder

⚠️ Preview — needs more testing. Functional but not production-ready.

Design reusable print layouts with configurable headers, footers, multi-page bodies, watermarks, and page numbering.

Backend API endpoints required

Method URL Description
POST UiBuilderModule/PrintLayout Create a new layout
PUT UiBuilderModule/PrintLayout Update an existing layout
GET UiBuilderModule/PrintLayout/GetAll List all layouts
GET UiBuilderModule/PrintLayout/GetById?id=<id> Fetch by ID
DELETE UiBuilderModule/PrintLayout?id=<id> Delete a layout

Triggering print from a view

openPrintLayout('your-layout-id', {
  invoiceNumber: data.invoiceNumber,
  customerName:  data.customer.name,
  lines:         data.lines,
})

Page numbering format

Use {page} and {pages} tokens in the Format field:

Page {page} of {pages}   →  Page 1 of 4

Calculation Scope Reference

Every Calculation function receives the same set of variables:

Core state

Variable Description
form Form field values (read-only snapshot)
data Reactive page state
setData Write page state — setData(prev => ({ ...prev, key: value }))
dataRef Mutable non-reactive store
reportRefs Map of { [key]: ref } for every Data Grid / Excel Upload on the page

Dialog / layout

Variable Description
openDialog(key, data?) Open a dialog, optionally seeding its isolated state
closeDialog(key) Close a dialog
openPrintLayout(layoutId, data?) Open the print preview
closePrintLayout() Close the active print preview

Navigation & routing

Variable Description
router Next.js router — router.push('/path'), router.query, etc.
urlParams { query, pathname, asPath } snapshot

Global store

Variable Description
globalData Cross-route global state (read)
setGlobalData(updater) Write global state — shallow-merges by default

Services

Variable Description
GetService Authenticated GET
PostService Authenticated POST
UpdateService Authenticated PUT
PatchService Authenticated PATCH
DeleteService Authenticated DELETE
fetchReportData Fetch report data by pageId

Helpers

Variable Description
showToast(message, type?) 'success' | 'error' | 'warning' | 'info' | 'loading'

Parent page scope (inside dialogs / embedded views)

Variable Description
page.data Parent page's reactive state
page.setData Write to the parent page's state
page.dataRef Parent page's non-reactive store
page.reportRefs Parent page's grid refs

Repeater-only

Variable Description
dataItem The current repeated item
itemIndex Zero-based iteration index

KPI Component Actions

KPI components support interaction events configured in the inspector Main tab → Actions section.

Component Event Click-context variables
Metric onClick clickedValue
Rating onChange newValue, clickedValue
Chart onDataClick clickedItem, clickedValue, clickedField, clickedLabel, clickedIndex
HeatmapGrid onCellClick clickedItem, clickedValue, clickedRow, clickedCol, clickedRowIndex, clickedColIndex
Timeline onItemClick clickedItem, clickedIndex, clickedLabel, clickedStatus, clickedValue
StepStage onStepClick clickedItem, clickedIndex, clickedId, clickedLabel, clickedStatus
TagList onTagClick clickedItem, clickedTag, clickedLabel, clickedValue, clickedIndex

Global Data Store

A module-level reactive singleton that survives client-side navigations.

In Calculation functions

// Read
console.log(globalData.selectedUser)

// Write
setGlobalData(prev => ({ ...prev, selectedUser: clickedItem }))

// Navigate — globalData persists to the next page
router.push('/user-detail')

In React components

import { useGlobalStore } from 'robobyte-front-builder'

function MyComponent() {
  const { globalData, setGlobalData } = useGlobalStore()
  return <p>Selected: {globalData.selectedUser?.name}</p>
}

Resetting on logout

import { resetGlobalData } from 'robobyte-front-builder'

function handleLogout() {
  resetGlobalData()
  // ... your auth logout
}

API

Export Description
useGlobalStore() React hook — { globalData, setGlobalData }
getGlobalData() Synchronous read from non-React code
setGlobalData(updater) Write from anywhere
subscribeGlobal(fn) Subscribe to changes — returns unsubscribe function
resetGlobalData() Reset to {} and notify all subscribers

Dark / Light theme

Both the UI Builder and Print Layout Builder support dark and light modes (default: dark). A toggle button (☀️ / 🌙) is available in each builder's toolbar. The choice is persisted in localStorage under rbb:builderThemeMode. The theme is scoped to the builder pages only and does not affect the rest of the host application.


Syncing local changes

When using file: path, node_modules/robobyte-front-builder is a copy, not a symlink. After editing source files, sync manually:

SRC=RoboByteFrontBuilder/src
PKG=YourApp/node_modules/robobyte-front-builder/src

cp $SRC/lib/index.js $PKG/lib/index.js
cp $SRC/lib/providers/RoboByteFrontBuilderProvider.jsx $PKG/lib/providers/RoboByteFrontBuilderProvider.jsx
cp $SRC/services/reportData/fetchReportData.js $PKG/services/reportData/fetchReportData.js
# ... add other files as needed

Hot-reload picks up all file changes automatically. Only next.config.js changes require a dev server restart.


Troubleshooting

"Module not found: Can't resolve 'xlsx'"
→ Install xlsx in the host app: npm install xlsx --legacy-peer-deps

"Cannot find module 'services/...'"
→ Ensure the NormalModuleReplacementPlugin is configured in next.config.js

AG Grid table not showing / license warning
→ Pass agGridLicenseKey to RoboByteFrontBuilderProvider. Do not call LicenseManager or ModuleRegistry in the host app.

AG Grid error #200 — IntegratedChartsModule not registered
→ The provider registers IntegratedChartsModule.with(AgChartsEnterpriseModule) automatically. Ensure ag-charts-enterprise is installed in the package.

AG Grid theme override not applying
→ Pass it via <RoboByteFrontBuilderProvider agGridTheme={{ … }}>, not as a theme={…} prop on individual <AgGridReact> instances rendered by the package. Internal grids ignore per-instance themes; the provider's context is the single source of truth. See the AG Grid theme section.

ReportViewer renders at half width
→ The outer Box in reportViewer/index.js must use display: 'block', not display: 'flex'.

Static props (getLayout, acl) not picked up from package exports
→ Use the explicit import + assignment pattern. Bare export { X as default } does not carry static properties across package boundaries.

Duplicate React / MUI hook errors
→ Pin react, react-dom, and @mui/material to the host app's copies via config.resolve.alias in next.config.js.

Old routes returning 404
→ Check that host-app pages exist under /builders/... and that old paths have getServerSideProps = () => ({ notFound: true }) stubs.


Publishing

npm login          # one-time setup

npm version patch  # 1.0.x — bug fixes
npm version minor  # 1.x.0 — new features
npm version major  # x.0.0 — breaking changes

npm publish

Dry run (verify what will be published without actually publishing):

npm publish --dry-run

Changelog

1.0.25

  • Centralized AG Grid theme. Every <AgGridReact> in the package (reportViewer, dataGrid, role-permission editor, navigator picker) now reads its Quartz theme from a single context. Host apps can override package-wide theme params (accent color, header height, fonts, border radius, etc.) via the new agGridTheme prop on RoboByteFrontBuilderProvider. Defaults live in src/lib/agGridTheme.js. New exports: DEFAULT_AG_THEME_PARAMS, DEFAULT_AG_THEME, buildAgGridTheme, AgGridThemeProvider, useAgGridTheme.
  • <ReportViewer> redesigned toolbar. Single-row toolbar: title + caption on the left; collapsible search, Filter (outlined button), Refresh (outlined button), and configurable viewer actions on the right. Auto-refresh interval, "Load all data" toggle, and Excel export moved into the side tool panel under Display Settings. Search popover navigable by keyboard (↑ ↓ Home End Enter Esc).
  • <ReportViewer> new inspector fields. title, caption, viewerActions (array of page-level action buttons appended after Filter/Refresh), debug (renders a floating bug icon with a popover showing resolved pageId/id/builder model id/etc. — hidden in production by default).
  • Print Layout integration. Host apps can now trigger print layouts directly via the imperative PrintDialog ref API — see docs/printLayout.md for the recommended PrintProvider pattern with usePrintLayout().
  • Public exports expanded. fetchReportDataByPageId now exported from the package surface (import { fetchReportDataByPageId } from 'robobyte-front-builder'); the legacy bare-alias path still works.
  • Unsaved changes guard. Builder pages now warn on tab close / refresh / in-app navigation when the schema has unsaved edits. BuilderProvider exposes loadSchema(schema) (clears history baseline), markClean() (post-save reset), and isDirty.
  • Session log + AI fine-tune pipeline. Every successful save (UI Builder + Print Builder) is auto-logged to localStorage with the full schema. New Session Logs toolbar dialog lets developers add training prompts to entries and export a Together AI-ready JSONL. Together is now a first-class AI provider in /api/ai.

1.0.21

  • Added Timer Engine — configurable auto-refresh timers per view
  • Added full Undo / Redo history with keyboard shortcuts (Ctrl+Z / Ctrl+Y)
  • Added Cut / Copy / Paste with system clipboard support (Ctrl+X / Ctrl+C / Ctrl+V)
  • Added Undo / Redo buttons to the viewer toolbar
  • Expanded KPI suite: Gauge, BulletChart, ColorScale, Rating, Countdown, AvatarGroup, StepStage
  • Print Layout designer: multi-zone canvas, @page CSS, print dialog

1.0.20

  • KPI components: Metric, Trend, Badge, StatusDot, IconBox, Sparkline, MiniBarChart, Donut, Funnel, HeatmapGrid, TagList, Timeline, ComparisonBars
  • Threshold engine and number formatting utilities
  • Dark / light theme toggle in UI builder and Print Layout builder

1.0.x

  • UI Builder, Report Builder, Navigator Builder, Print Builder initial releases
  • Navigation Extension API
  • AG Grid and MUI data grid integration
  • Drag-and-drop canvas with 50+ components
  • Global Data Store

License & third-party components

robobyte-front-builder itself is released under the MIT License — the source code in this repository is free to use, modify, and distribute, including in commercial products.

Important: this package depends on third-party libraries with their own licenses. The MIT license applies only to this package's source code; it does not relicense or waive obligations under those third-party licenses.

AG Grid Enterprise — commercial license required for production

The report and grid components use AG Grid Enterprise features (server-side row model, side tool panel, status bar, integrated charts, master/detail). The ag-grid-enterprise package is a commercial product owned by AG Grid Ltd:

  • Development: AG Grid Enterprise works without a license key, but renders a watermark and prints a console warning. Fine for local dev and evaluation.
  • Production deployment: requires a paid AG Grid Enterprise license. See ag-grid.com/license-pricing for the current terms.

Pass your license key via the provider — the package calls LicenseManager.setLicenseKey() and registers AllEnterpriseModule + IntegratedChartsModule.with(AgChartsEnterpriseModule) internally:

<RoboByteFrontBuilderProvider
  agGridLicenseKey={process.env.NEXT_PUBLIC_AG_GRID_LICENSE_KEY}
  // …other props…
></RoboByteFrontBuilderProvider>

MUI X — free vs. Pro / Premium tiers

@mui/x-data-grid, @mui/x-date-pickers, and related packages have a free MIT tier and paid Pro / Premium tiers. This package uses only the free tier. If you swap in @mui/x-data-grid-pro or @mui/x-date-pickers-pro in your host app, comply with MUI's commercial license: mui.com/pricing.

Everything else

All other runtime and peer dependencies are open-source under permissive licenses (MIT, Apache 2.0, ISC, BSD). Run npm ls --omit dev for the full dependency graph and a tool like license-checker for a license enumeration.

A condensed version of this notice lives in the LICENSE file shipped with the package.


Full user manual: RoboByteBuilder_User_Manual.docx (included in the package)

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors