1- import { useMemo , useRef } from 'react'
1+ import { useEffect , useMemo , useRef } from 'react'
22import { useParams } from 'next/navigation'
33import { Button } from '@/components/emcn/components/button/button'
44import { Trash } from '@/components/emcn/icons/trash'
@@ -60,58 +60,71 @@ export function Table({
6060 // Create refs for input elements
6161 const inputRefs = useRef < Map < string , HTMLInputElement > > ( new Map ( ) )
6262
63+ // Memoized template for empty cells for current columns
64+ const emptyCellsTemplate = useMemo (
65+ ( ) => Object . fromEntries ( columns . map ( ( col ) => [ col , '' ] ) ) ,
66+ [ columns ]
67+ )
68+
69+ /**
70+ * Initialize the table with a default empty row when the component mounts
71+ * and when the current store value is missing or empty.
72+ */
73+ useEffect ( ( ) => {
74+ if ( ! isPreview && ! disabled && ( ! Array . isArray ( storeValue ) || storeValue . length === 0 ) ) {
75+ const initialRow : TableRow = {
76+ id : crypto . randomUUID ( ) ,
77+ cells : { ...emptyCellsTemplate } ,
78+ }
79+ setStoreValue ( [ initialRow ] )
80+ }
81+ } , [ isPreview , disabled , storeValue , setStoreValue , emptyCellsTemplate ] )
82+
6383 // Ensure value is properly typed and initialized
6484 const rows = useMemo ( ( ) => {
65- if ( ! Array . isArray ( value ) ) {
85+ if ( ! Array . isArray ( value ) || value . length === 0 ) {
6686 return [
6787 {
6888 id : crypto . randomUUID ( ) ,
69- cells : Object . fromEntries ( columns . map ( ( col ) => [ col , '' ] ) ) ,
89+ cells : { ... emptyCellsTemplate } ,
7090 } ,
7191 ]
7292 }
7393
74- // Validate and fix each row to ensure proper structure
94+ // Validate and normalize each row without in-place mutation
7595 const validatedRows = value . map ( ( row ) => {
76- // Ensure row has an id
77- if ( ! row . id ) {
78- row . id = crypto . randomUUID ( )
96+ const hasValidCells = row ?. cells && typeof row . cells === 'object'
97+ if ( ! hasValidCells ) {
98+ logger . warn ( 'Fixing malformed table row:' , row )
7999 }
80100
81- // Ensure row has cells object with proper structure
82- if ( ! row . cells || typeof row . cells !== 'object' ) {
83- logger . warn ( 'Fixing malformed table row:' , row )
84- row . cells = Object . fromEntries ( columns . map ( ( col ) => [ col , '' ] ) )
85- } else {
86- // Ensure all required columns exist in cells
87- columns . forEach ( ( col ) => {
88- if ( ! ( col in row . cells ) ) {
89- row . cells [ col ] = ''
90- }
91- } )
101+ const normalizedCells = {
102+ ...emptyCellsTemplate ,
103+ ...( hasValidCells ? row . cells : { } ) ,
92104 }
93105
94- return row
106+ return {
107+ id : row ?. id ?? crypto . randomUUID ( ) ,
108+ cells : normalizedCells ,
109+ }
95110 } )
96111
97112 return validatedRows as TableRow [ ]
98- } , [ value , columns ] )
113+ } , [ value , emptyCellsTemplate ] )
99114
100115 // Helper to update a cell value
101116 const updateCellValue = ( rowIndex : number , column : string , newValue : string ) => {
102117 if ( isPreview || disabled ) return
103118
104119 const updatedRows = [ ...rows ] . map ( ( row , idx ) => {
105120 if ( idx === rowIndex ) {
106- // Ensure the row has a proper cells object
107- if ( ! row . cells || typeof row . cells !== 'object' ) {
108- logger . warn ( 'Fixing malformed row cells during cell change:' , row )
109- row . cells = Object . fromEntries ( columns . map ( ( col ) => [ col , '' ] ) )
110- }
121+ const hasValidCells = row . cells && typeof row . cells === 'object'
122+ const baseCells = hasValidCells ? row . cells : { ...emptyCellsTemplate }
123+ if ( ! hasValidCells ) logger . warn ( 'Fixing malformed row cells during cell change:' , row )
111124
112125 return {
113126 ...row ,
114- cells : { ...row . cells , [ column ] : newValue } ,
127+ cells : { ...baseCells , [ column ] : newValue } ,
115128 }
116129 }
117130 return row
@@ -120,7 +133,7 @@ export function Table({
120133 if ( rowIndex === rows . length - 1 && newValue !== '' ) {
121134 updatedRows . push ( {
122135 id : crypto . randomUUID ( ) ,
123- cells : Object . fromEntries ( columns . map ( ( col ) => [ col , '' ] ) ) ,
136+ cells : { ... emptyCellsTemplate } ,
124137 } )
125138 }
126139
@@ -152,16 +165,12 @@ export function Table({
152165
153166 const renderCell = ( row : TableRow , rowIndex : number , column : string , cellIndex : number ) => {
154167 // Defensive programming: ensure row.cells exists and has the expected structure
155- if ( ! row . cells || typeof row . cells !== 'object' ) {
156- logger . warn ( 'Table row has malformed cells data:' , row )
157- // Create a fallback cells object
158- row = {
159- ...row ,
160- cells : Object . fromEntries ( columns . map ( ( col ) => [ col , '' ] ) ) ,
161- }
162- }
168+ const hasValidCells = row . cells && typeof row . cells === 'object'
169+ if ( ! hasValidCells ) logger . warn ( 'Table row has malformed cells data:' , row )
170+
171+ const cells = hasValidCells ? row . cells : { ...emptyCellsTemplate }
163172
164- const cellValue = row . cells [ column ] || ''
173+ const cellValue = cells [ column ] || ''
165174 const cellKey = `${ rowIndex } -${ column } `
166175
167176 // Get field state and handlers for this cell
0 commit comments