LCOV - code coverage report
Current view: top level - dashql-app/src/ui/foundations - value_list.tsx Coverage Total Hit
Test: DashQL 915828b Lines: 100.0 % 56 56
Test Date: 2026-11-06 19:30:32

            Line data    Source code
       1              : import * as React from 'react';
       2              : import * as styles from './value_list.module.css';
       3              : 
       4              : import { PlusIcon, XIcon } from './symbol_icon.js';
       5              : 
       6              : import { Dispatch } from '../../utils/variant.js';
       7              : import { classNames } from '../../utils/classnames.js';
       8              : import { TextInput } from './text_input.js';
       9              : import { TextInputAction } from './text_input_action.js';
      10              : import { ButtonSize, IconButton } from './button.js';
      11              : 
      12              : export type ValueListElement = string;
      13              : 
      14              : export type UpdateValueList = (prev: ValueListElement[]) => ValueListElement[];
      15              : 
      16              : interface Props {
      17              :     className?: string;
      18              :     title: string;
      19              :     caption?: string;
      20              :     valueIcon?: React.ElementType;
      21              :     addButtonLabel: string;
      22              :     elements: ValueListElement[];
      23              :     modifyElements: Dispatch<UpdateValueList>;
      24              :     disabled?: boolean;
      25              :     readOnly?: boolean;
      26              : }
      27              : 
      28            1 : export const ValueListBuilder: React.FC<Props> = (props: Props) => {
      29            1 :     const appendElement = () => props.modifyElements(list => {
      30            1 :         const copy = [...list];
      31            1 :         copy.push("");
      32            1 :         return copy;
      33            1 :     });
      34            1 :     const deleteIndex = (index: number) => props.modifyElements(list => {
      35            1 :         const copy = [...list];
      36            1 :         copy.splice(index, 1);
      37            1 :         return copy;
      38            1 :     });
      39            1 :     const modifyElement = (index: number, value: string) => props.modifyElements(list => {
      40            1 :         const copy = [...list];
      41            1 :         copy[index] = value;
      42            1 :         return copy;
      43            1 :     });
      44              : 
      45            1 :     return (
      46            1 :         <div className={classNames(props.className, styles.list)}>
      47            1 :             <div className={styles.list_name}>
      48            1 :                 {props.title}
      49            1 :             </div>
      50            1 :             {props.caption && (
      51            1 :                 <div className={styles.list_caption}>
      52            1 :                     {props.caption}
      53            1 :                 </div>
      54              :             )}
      55            1 :             <IconButton
      56            1 :                 className={styles.add_button}
      57            1 :                 aria-label="Add Entry"
      58            1 :                 onClick={appendElement}
      59            1 :                 disabled={props.disabled}
      60            1 :                 size={ButtonSize.Small}
      61              :             >
      62            1 :                 <PlusIcon />
      63            1 :             </IconButton>
      64            1 :             <div className={styles.list_elements}>
      65            1 :                 {props.elements.map((elem, i) => (
      66            1 :                     <div key={i} className={styles.element}>
      67            1 :                         <TextInput
      68            1 :                             block
      69            1 :                             className={styles.path}
      70            1 :                             value={elem}
      71            1 :                             onChange={(ev: any) => modifyElement(i, ev.target.value)}
      72            1 :                             leadingVisual={props.valueIcon}
      73            1 :                             trailingAction={
      74            1 :                                 <TextInputAction
      75            1 :                                     aria-label="Clear input"
      76            1 :                                     aria-labelledby=""
      77            1 :                                     onClick={() => deleteIndex(i)}
      78              :                                 >
      79            1 :                                     <XIcon />
      80            1 :                                 </TextInputAction>
      81              :                             }
      82            1 :                             disabled={props.disabled}
      83            1 :                             readOnly={props.disabled}
      84            1 :                         />
      85            1 :                     </div>))}
      86            1 :             </div>
      87            1 :         </div>
      88              :     );
      89            1 : };
        

Generated by: LCOV version 2.0-1