@@ -93,6 +93,7 @@ const SET_D_TITLE = 'Editable cells (inline edit + validation)';
9393const SET_E_TITLE = 'Expandable rows (`#detail` slot + nested sub-rows)' ;
9494const SET_F_TITLE = 'Grouping + aggregation (headless `#groupBar`)' ;
9595const SET_G_TITLE = 'Faceted filtering exposure (headless `#filter`)' ;
96+ const SET_H_TITLE = 'Drop-in editor components (`#editor`)' ;
9697
9798// Editing example dataset — one field per built-in editor type (text/number/select/
9899// checkbox) + the `score` field routed through the custom `#editor` scoped slot. The
@@ -363,6 +364,50 @@ export function Demo() {
363364 <Column field="price" header="Price" filterable />
364365 </DataTable>
365366 );
367+ }` ,
368+ } ,
369+ {
370+ title : SET_H_TITLE ,
371+ lang : 'tsx' ,
372+ code : `import { useState } from 'react';
373+ import {
374+ DataTable, Column,
375+ EditorText, EditorNumber, EditorSelect, EditorCheckbox, EditorDate,
376+ } from '@rozie-ui/data-table-react';
377+
378+ export function Demo() {
379+ // OPT-IN drop-in editors fill the #editor slot — DataTable stays the headless
380+ // DEFAULT; the editors are additive named exports. Mark each column editor="custom"
381+ // (the drop-in owns rendering) and dispatch by columnId. Each editor takes the slot
382+ // scope as props ({ columnId, column, row, value, commit, cancel }); EditorSelect
383+ // also takes \`options\`. Use them as-is, or fork one as a template.
384+ const [rows, setRows] = useState(${ EDIT_ROWS } );
385+ const statusOptions = ${ STATUS_OPTIONS } ;
386+ return (
387+ <DataTable
388+ interactionMode="grid"
389+ data={rows}
390+ onDataChange={setRows}
391+ onCellEditCommit={(p) => console.log('cell commit', p)}
392+ // The #editor scoped slot is a render prop on React (the documented edge).
393+ renderEditor={(scope) => {
394+ switch (scope.columnId) {
395+ case 'name': return <EditorText {...scope} />;
396+ case 'qty': return <EditorNumber {...scope} />;
397+ case 'status': return <EditorSelect {...scope} options={statusOptions} />;
398+ case 'active': return <EditorCheckbox {...scope} />;
399+ case 'score': return <EditorDate {...scope} />;
400+ default: return null;
401+ }
402+ }}
403+ >
404+ <Column field="name" header="Name" editable editor="custom" />
405+ <Column field="qty" header="Qty" editable editor="custom" />
406+ <Column field="status" header="Status" editable editor="custom" />
407+ <Column field="active" header="Active" editable editor="custom" />
408+ <Column field="score" header="Score" editable editor="custom" />
409+ </DataTable>
410+ );
366411}` ,
367412 } ,
368413 ] ,
@@ -564,6 +609,46 @@ const columnFilters = ref<{ id: string; value: unknown }[]>([]);
564609 <input v-else type="range" :min="minMax[0]" :max="minMax[1]" />
565610 </template>
566611 </DataTable>
612+ </template>` ,
613+ } ,
614+ {
615+ title : SET_H_TITLE ,
616+ lang : 'vue' ,
617+ code : `<script setup lang="ts">
618+ import { ref } from 'vue';
619+ import DataTable, {
620+ Column, EditorText, EditorNumber, EditorSelect, EditorCheckbox, EditorDate,
621+ } from '@rozie-ui/data-table-vue';
622+
623+ // OPT-IN drop-in editors fill the #editor slot — DataTable stays the headless DEFAULT
624+ // export; the editors are additive named exports. v-bind the whole slot scope through
625+ // to each drop-in ({ columnId, column, row, value, commit, cancel }); EditorSelect also
626+ // takes :options. Use them as-is, or fork one as a template.
627+ const rows = ref(${ EDIT_ROWS } );
628+ const statusOptions = ${ STATUS_OPTIONS } ;
629+ </script>
630+
631+ <template>
632+ <DataTable
633+ interaction-mode="grid"
634+ v-model:data="rows"
635+ @cell-edit-commit="(p) => console.log('cell commit', p)"
636+ >
637+ <Column field="name" header="Name" :editable="true" editor="custom" />
638+ <Column field="qty" header="Qty" :editable="true" editor="custom" />
639+ <Column field="status" header="Status" :editable="true" editor="custom" />
640+ <Column field="active" header="Active" :editable="true" editor="custom" />
641+ <Column field="score" header="Score" :editable="true" editor="custom" />
642+
643+ <!-- One #editor slot, dispatched by columnId, wiring the drop-in editors. -->
644+ <template #editor="scope">
645+ <EditorText v-if="scope.columnId === 'name'" v-bind="scope" />
646+ <EditorNumber v-else-if="scope.columnId === 'qty'" v-bind="scope" />
647+ <EditorSelect v-else-if="scope.columnId === 'status'" v-bind="scope" :options="statusOptions" />
648+ <EditorCheckbox v-else-if="scope.columnId === 'active'" v-bind="scope" />
649+ <EditorDate v-else-if="scope.columnId === 'score'" v-bind="scope" />
650+ </template>
651+ </DataTable>
567652</template>` ,
568653 } ,
569654 ] ,
@@ -742,6 +827,49 @@ const columnFilters = ref<{ id: string; value: unknown }[]>([]);
742827 <input type="range" min={minMax[0]} max={minMax[1]} />
743828 {/if}
744829 {/snippet}
830+ </DataTable>` ,
831+ } ,
832+ {
833+ title : SET_H_TITLE ,
834+ lang : 'svelte' ,
835+ code : `<script lang="ts">
836+ import DataTable, {
837+ Column, EditorText, EditorNumber, EditorSelect, EditorCheckbox, EditorDate,
838+ } from '@rozie-ui/data-table-svelte';
839+
840+ // OPT-IN drop-in editors fill the #editor snippet — DataTable stays the headless
841+ // DEFAULT export; the editors are additive named exports. Spread the snippet scope
842+ // through to each drop-in ({ columnId, column, row, value, commit, cancel });
843+ // EditorSelect also takes \`options\`. Use them as-is, or fork one as a template.
844+ let rows = $state(${ EDIT_ROWS } );
845+ const statusOptions = ${ STATUS_OPTIONS } ;
846+ </script>
847+
848+ <DataTable
849+ interactionMode="grid"
850+ bind:data={rows}
851+ oncelleditcommit={(p) => console.log('cell commit', p)}
852+ >
853+ <Column field="name" header="Name" editable editor="custom" />
854+ <Column field="qty" header="Qty" editable editor="custom" />
855+ <Column field="status" header="Status" editable editor="custom" />
856+ <Column field="active" header="Active" editable editor="custom" />
857+ <Column field="score" header="Score" editable editor="custom" />
858+
859+ <!-- One #editor snippet, dispatched by columnId, wiring the drop-in editors. -->
860+ {#snippet editor(scope)}
861+ {#if scope.columnId === 'name'}
862+ <EditorText {...scope} />
863+ {:else if scope.columnId === 'qty'}
864+ <EditorNumber {...scope} />
865+ {:else if scope.columnId === 'status'}
866+ <EditorSelect {...scope} options={statusOptions} />
867+ {:else if scope.columnId === 'active'}
868+ <EditorCheckbox {...scope} />
869+ {:else if scope.columnId === 'score'}
870+ <EditorDate {...scope} />
871+ {/if}
872+ {/snippet}
745873</DataTable>` ,
746874 } ,
747875 ] ,
@@ -981,6 +1109,63 @@ import { DataTable, Column } from '@rozie-ui/data-table-angular';
9811109export class DemoComponent {
9821110 rows = ${ FACET_ROWS } ;
9831111 columnFilters: { id: string; value: unknown }[] = [];
1112+ }` ,
1113+ } ,
1114+ {
1115+ title : SET_H_TITLE ,
1116+ lang : 'ts' ,
1117+ code : `import { Component } from '@angular/core';
1118+ import {
1119+ DataTable, Column,
1120+ EditorText, EditorNumber, EditorSelect, EditorCheckbox, EditorDate,
1121+ } from '@rozie-ui/data-table-angular';
1122+
1123+ @Component({
1124+ selector: 'app-demo',
1125+ standalone: true,
1126+ imports: [DataTable, Column, EditorText, EditorNumber, EditorSelect, EditorCheckbox, EditorDate],
1127+ template: \`
1128+ <!-- OPT-IN drop-in editors fill the #editor template — DataTable stays the headless
1129+ default; the editors are additive named exports. Each takes the slot scope as
1130+ inputs ([columnId] [column] [row] [value] [commit] [cancel]); EditorSelect also
1131+ takes [options]. Mark each column editor="custom" so the #editor slot drives it. -->
1132+ <DataTable
1133+ interactionMode="grid"
1134+ [(data)]="rows"
1135+ (cell-edit-commit)="onCellCommit($event)"
1136+ >
1137+ <Column field="name" header="Name" [editable]="true" editor="custom" />
1138+ <Column field="qty" header="Qty" [editable]="true" editor="custom" />
1139+ <Column field="status" header="Status" [editable]="true" editor="custom" />
1140+ <Column field="active" header="Active" [editable]="true" editor="custom" />
1141+ <Column field="score" header="Score" [editable]="true" editor="custom" />
1142+
1143+ <ng-template #editor let-columnId="columnId" let-column="column" let-row="row" let-value="value" let-commit="commit" let-cancel="cancel">
1144+ @switch (columnId) {
1145+ @case ('name') {
1146+ <rozie-editor-text [columnId]="columnId" [column]="column" [row]="row" [value]="value" [commit]="commit" [cancel]="cancel" />
1147+ }
1148+ @case ('qty') {
1149+ <rozie-editor-number [columnId]="columnId" [column]="column" [row]="row" [value]="value" [commit]="commit" [cancel]="cancel" />
1150+ }
1151+ @case ('status') {
1152+ <rozie-editor-select [columnId]="columnId" [column]="column" [row]="row" [value]="value" [commit]="commit" [cancel]="cancel" [options]="statusOptions" />
1153+ }
1154+ @case ('active') {
1155+ <rozie-editor-checkbox [columnId]="columnId" [column]="column" [row]="row" [value]="value" [commit]="commit" [cancel]="cancel" />
1156+ }
1157+ @case ('score') {
1158+ <rozie-editor-date [columnId]="columnId" [column]="column" [row]="row" [value]="value" [commit]="commit" [cancel]="cancel" />
1159+ }
1160+ }
1161+ </ng-template>
1162+ </DataTable>
1163+ \`,
1164+ })
1165+ export class DemoComponent {
1166+ rows = ${ EDIT_ROWS } ;
1167+ statusOptions = ${ STATUS_OPTIONS } ;
1168+ onCellCommit(p: unknown) { console.log('cell commit', p); }
9841169}` ,
9851170 } ,
9861171 ] ,
@@ -1184,6 +1369,48 @@ export function Demo() {
11841369 <Column field="price" header="Price" filterable />
11851370 </DataTable>
11861371 );
1372+ }` ,
1373+ } ,
1374+ {
1375+ title : SET_H_TITLE ,
1376+ lang : 'tsx' ,
1377+ code : `import { createSignal, Switch, Match } from 'solid-js';
1378+ import {
1379+ DataTable, Column,
1380+ EditorText, EditorNumber, EditorSelect, EditorCheckbox, EditorDate,
1381+ } from '@rozie-ui/data-table-solid';
1382+
1383+ export function Demo() {
1384+ // OPT-IN drop-in editors fill the #editor slot — DataTable stays the headless
1385+ // default; the editors are additive named exports. Spread the slot scope through to
1386+ // each drop-in ({ columnId, column, row, value, commit, cancel }); EditorSelect also
1387+ // takes \`options\`. Use them as-is, or fork one as a template.
1388+ const [rows, setRows] = createSignal(${ EDIT_ROWS } );
1389+ const statusOptions = ${ STATUS_OPTIONS } ;
1390+ return (
1391+ <DataTable
1392+ interactionMode="grid"
1393+ data={rows()}
1394+ onDataChange={setRows}
1395+ onCellEditCommit={(p) => console.log('cell commit', p)}
1396+ // The #editor scoped slot is a render prop on Solid (the documented edge).
1397+ editorSlot={(scope) => (
1398+ <Switch>
1399+ <Match when={scope.columnId === 'name'}><EditorText {...scope} /></Match>
1400+ <Match when={scope.columnId === 'qty'}><EditorNumber {...scope} /></Match>
1401+ <Match when={scope.columnId === 'status'}><EditorSelect {...scope} options={statusOptions} /></Match>
1402+ <Match when={scope.columnId === 'active'}><EditorCheckbox {...scope} /></Match>
1403+ <Match when={scope.columnId === 'score'}><EditorDate {...scope} /></Match>
1404+ </Switch>
1405+ )}
1406+ >
1407+ <Column field="name" header="Name" editable editor="custom" />
1408+ <Column field="qty" header="Qty" editable editor="custom" />
1409+ <Column field="status" header="Status" editable editor="custom" />
1410+ <Column field="active" header="Active" editable editor="custom" />
1411+ <Column field="score" header="Score" editable editor="custom" />
1412+ </DataTable>
1413+ );
11871414}` ,
11881415 } ,
11891416 ] ,
@@ -1361,6 +1588,48 @@ render(html\`
13611588 <rozie-column field="category" header="Category" filterable></rozie-column>
13621589 <rozie-column field="price" header="Price" filterable></rozie-column>
13631590 </rozie-data-table>
1591+ \`, document.body);` ,
1592+ } ,
1593+ {
1594+ title : SET_H_TITLE ,
1595+ lang : 'ts' ,
1596+ code : `import { html, render } from 'lit';
1597+ // The single side-effect import registers <rozie-data-table> AND the drop-in editor
1598+ // custom elements (<rozie-editor-text>, <rozie-editor-number>, <rozie-editor-select>,
1599+ // <rozie-editor-checkbox>, <rozie-editor-date>). DataTable stays the headless default;
1600+ // the editors are additive.
1601+ import '@rozie-ui/data-table-lit';
1602+
1603+ let rows = ${ EDIT_ROWS } ;
1604+ const statusOptions = ${ STATUS_OPTIONS } ;
1605+
1606+ // The #editor slot is the \`.editor\` property — a function returning a Lit template,
1607+ // dispatched by columnId. Pass the slot scope ({ columnId, column, row, value, commit,
1608+ // cancel }) as element properties; <rozie-editor-select> also takes \`.options\`.
1609+ render(html\`
1610+ <rozie-data-table
1611+ interaction-mode="grid"
1612+ .data=\${rows}
1613+ @data-change=\${(e: CustomEvent) => { rows = e.detail; }}
1614+ @cell-edit-commit=\${(e: CustomEvent) => console.log('cell commit', e.detail)}
1615+ .editor=\${({ columnId, column, row, value, commit, cancel }) => {
1616+ const p = { columnId, column, row, value, commit, cancel };
1617+ switch (columnId) {
1618+ case 'name': return html\`<rozie-editor-text .columnId=\${p.columnId} .column=\${p.column} .row=\${p.row} .value=\${p.value} .commit=\${p.commit} .cancel=\${p.cancel}></rozie-editor-text>\`;
1619+ case 'qty': return html\`<rozie-editor-number .columnId=\${p.columnId} .column=\${p.column} .row=\${p.row} .value=\${p.value} .commit=\${p.commit} .cancel=\${p.cancel}></rozie-editor-number>\`;
1620+ case 'status': return html\`<rozie-editor-select .columnId=\${p.columnId} .column=\${p.column} .row=\${p.row} .value=\${p.value} .commit=\${p.commit} .cancel=\${p.cancel} .options=\${statusOptions}></rozie-editor-select>\`;
1621+ case 'active': return html\`<rozie-editor-checkbox .columnId=\${p.columnId} .column=\${p.column} .row=\${p.row} .value=\${p.value} .commit=\${p.commit} .cancel=\${p.cancel}></rozie-editor-checkbox>\`;
1622+ case 'score': return html\`<rozie-editor-date .columnId=\${p.columnId} .column=\${p.column} .row=\${p.row} .value=\${p.value} .commit=\${p.commit} .cancel=\${p.cancel}></rozie-editor-date>\`;
1623+ default: return null;
1624+ }
1625+ }}
1626+ >
1627+ <rozie-column field="name" header="Name" editable editor="custom"></rozie-column>
1628+ <rozie-column field="qty" header="Qty" editable editor="custom"></rozie-column>
1629+ <rozie-column field="status" header="Status" editable editor="custom"></rozie-column>
1630+ <rozie-column field="active" header="Active" editable editor="custom"></rozie-column>
1631+ <rozie-column field="score" header="Score" editable editor="custom"></rozie-column>
1632+ </rozie-data-table>
13641633\`, document.body);` ,
13651634 } ,
13661635 ] ,
0 commit comments