@mmlogic/components
v0.1.10
Published
Stencil.js web component library for dynamic forms and virtual-scroll data tables
Maintainers
Readme
@mmlogic/components
A Stencil.js v4 web component library for rendering dynamic forms and paginated data tables from API descriptors. Components are framework-agnostic and work in any HTML/JS environment. An Angular output target is included.
Installation
npm install @mmlogic/componentsUsage
Vanilla HTML / JS
<script type="module" src="node_modules/@mmlogic/components/dist/mosterd-components/mosterd-components.esm.js"></script>
<mrd-form id="my-form"></mrd-form>
<script>
const form = document.getElementById('my-form');
form.layout = { /* ClientLayout descriptor */ };
form.values = { name: 'Alice' };
form.addEventListener('mrdSubmit', e => console.log(e.detail));
</script>Via CDN (unpkg)
<script type="module" src="https://unpkg.com/@mmlogic/components/dist/mosterd-components/mosterd-components.esm.js"></script>Angular
// app.module.ts
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
import { defineCustomElements } from '@mmlogic/components/loader';
defineCustomElements();
@NgModule({ schemas: [CUSTOM_ELEMENTS_SCHEMA] })
export class AppModule {}Components
<mrd-form>
Renders a complete form from a layout descriptor. Handles validation, RTL layout (Arabic locale), and emits the submitted values.
<mrd-form id="form" locale="nl-NL"></mrd-form>form.layout = {
title: 'New order',
items: [
{ type: 'FIELD', field: { name: 'name', label: 'Name', dataType: 'TEXT', required: true } },
{ type: 'FIELD', field: { name: 'amount', label: 'Amount', dataType: 'CURRENCY' } },
]
};
form.addEventListener('mrdSubmit', e => console.log(e.detail.values));
form.addEventListener('mrdCancel', () => console.log('cancelled'));Props
| Prop | Type | Description |
|---|---|---|
| layout | ClientLayout | Form descriptor with title and items |
| values | Record<string, any> | Initial field values |
| locale | string | BCP 47 locale (default: navigator.language) |
| disabled | boolean | Disables all inputs |
Events
| Event | Detail | Description |
|---|---|---|
| mrdSubmit | { values: Record<string, any> } | Form submitted and valid |
| mrdCancel | — | Cancel button clicked |
<mrd-table>
A virtual-scroll paginated table. Only the visible rows (plus a configurable buffer) are rendered in the DOM. Pages are fetched on demand via an event.
<mrd-table id="table"></mrd-table>const table = document.getElementById('table');
table.columns = view.values; // TableColumn[] from dashboard API
table.totalElements = page.totalElements;
table.pageSize = page.size;
table.tableHeight = 500; // px, fixed container height
table.locale = 'nl-NL';
table.defaultSort = view.defaultSort ?? '';
table.addEventListener('mrdLoadPage', async (e) => {
const { page, sort } = e.detail;
const url = `${dataHref}?page=${page}${sort ? '&sort=' + sort : ''}`;
const result = await fetch(url, { headers: { Authorization: `Bearer ${token}` } }).then(r => r.json());
const rows = Object.values(result._embedded ?? {})[0] ?? [];
await table.setPage(page, rows);
});
await table.init();
await table.setPage(0, page0Rows); // inject pre-fetched page 0Props
| Prop | Type | Default | Description |
|---|---|---|---|
| columns | TableColumn[] | [] | Column definitions |
| totalElements | number | 0 | Total records (0 = non-paginated mode using rows prop) |
| pageSize | number | 20 | Records per page |
| rowHeight | number | 36 | Row height in px |
| tableHeight | number | 500 | Container height in px |
| locale | string | navigator.language | Locale for cell formatting |
| defaultSort | string | '' | Initial sort, e.g. "timestamp,desc" or "name" |
| rows | Record[] | [] | Rows for non-paginated mode |
Events
| Event | Detail | Description |
|---|---|---|
| mrdLoadPage | { page: number; sort: string } | Fired when a page needs to be fetched |
Methods
| Method | Description |
|---|---|
| init() | Reset state and render window; call after props are set and before setPage(0, …) |
| setPage(page, rows) | Inject fetched rows for a page number |
Column sorting
Click any column header to sort. Clicking again toggles ASC ↔ DESC. The active column is highlighted and shows ▲ / ▼. The sort value in the mrdLoadPage event is the raw query-param value ("fieldname" or "fieldname,desc").
Field components
Individual input components can be used standalone. Each emits mrdChange and mrdBlur.
| Component | DataType | Description |
|---|---|---|
| <mrd-text-field> | TEXT | Single-line text input |
| <mrd-textarea-field> | TEXTBLOCK | Rich text editor (Quill, lazy-loaded) |
| <mrd-number-field> | INTEGER, DECIMAL, PERCENTAGE | Numeric input |
| <mrd-currency-field> | CURRENCY | Amount + ISO-4217 currency selector |
| <mrd-boolean-field> | BOOLEAN | Toggle switch |
| <mrd-date-field> | DATE | Date picker |
| <mrd-datetime-field> | DATETIME | Date + time picker |
| <mrd-time-field> | TIME | Time picker |
| <mrd-email-field> | EMAIL | Email input with validation |
| <mrd-hyperlink-field> | HYPERLINK | URL input with validation |
| <mrd-list-field> | LIST | Single dropdown or multi-checkbox |
| <mrd-file-field> | FILE | Drag-and-drop file upload |
| <mrd-image-field> | IMAGE | Drag-and-drop image upload with preview |
| <mrd-relation-field> | RELATION | Search (event-driven) or dropdown |
Common props for field components
| Prop | Type | Description |
|---|---|---|
| name | string | Field name, included in mrdChange detail |
| label | string | Visible label |
| value | any | Current value |
| required | boolean | Shows validation error when empty on blur |
| disabled | boolean | Disables the input |
| locale | string | BCP 47 locale for formatting |
Events for field components
| Event | Detail |
|---|---|
| mrdChange | { name: string; value: any } |
| mrdBlur | { name: string; value: any } |
Theming
All visual properties are CSS custom properties. Override them on :root or any ancestor element:
:root {
--mrd-color-primary: #2563eb;
--mrd-color-neutral-100: #f3f4f6;
--mrd-border-radius: 0.375rem;
--mrd-font-size-sm: 0.875rem;
/* see full list in src/global/variables.scss */
}TypeScript types
Types are exported from the package root:
import type { TableColumn } from '@mmlogic/components/dist/types/utils/cell-renderer';
import type { ClientLayout, ClientLayoutItem } from '@mmlogic/components/dist/types/types/client-layout';License
MIT
