/* * Copyright 2025 coze-dev Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /* eslint-disable @typescript-eslint/no-explicit-any */ import React, { useState } from 'react'; import { IconCozPlus, IconCozMinus } from '@coze-arch/coze-design/icons'; import { IconButton } from '@coze-arch/coze-design'; import type { Setter } from '../types'; import type { Field } from './types'; import { ColumnTitles } from './column-titles'; import { ArraySetterItemContextProvider } from './array-context'; import styles from './array.module.less'; export interface ArrayOptions { disableAdd?: boolean; getDefaultAppendValue?: () => any; fields?: Field[]; /** The maximum number of imported parameters, if not provided, defaults to the maximum integer value */ maxItems?: number; /** The minimum number of imported parameters, if not provided, the default is 0 */ minItems?: number; /** Can a single item be deleted? */ disableDeleteItem?: ((value: unknown, index: number) => boolean) | boolean; } // eslint-disable-next-line complexity export const Array: Setter, ArrayOptions> = ({ value = [], readonly = false, children, onChange, context, disableAdd = false, getDefaultAppendValue, fields = [], maxItems = Number.MAX_SAFE_INTEGER, minItems = 0, disableDeleteItem = () => false, }) => { const [currentAddIndex, setCurrentAddIndex] = useState(); const { node, meta } = context || {}; // The value returned by the backend may be null, and it will not be assigned to [] at this time. Here is the bottom line again. const originValue = value || []; const add = () => { const defaultValue = getDefaultAppendValue?.() || {}; setCurrentAddIndex(originValue.length); onChange?.([...originValue, defaultValue]); }; const remove = (index: number) => { const newValue = [...originValue]; newValue.splice(index, 1); onChange?.(newValue); }; const showAddButton = !disableAdd && !readonly && originValue?.length < maxItems; const calcShowDeleteButton = (item: unknown, index: number) => { const globalEnableDelete = !readonly && originValue?.length > minItems; if (typeof disableDeleteItem === 'undefined') { return globalEnableDelete; } if (typeof disableDeleteItem === 'boolean') { return globalEnableDelete && !disableDeleteItem; } return globalEnableDelete && !disableDeleteItem(item, index); }; const columns = [...fields, ...(readonly ? [] : [{ label: '', width: 24 }])]; return (
{fields.length > 0 && } {React.Children.toArray(children).map((child, index) => { const showDeleteButton = calcShowDeleteButton( originValue[index], index, ); return (
{child}
{showDeleteButton ? ( } size="small" color="secondary" onClick={() => remove(index)} /> ) : null}
); })}
{showAddButton ? ( } onClick={() => add()} data-testid={`playground.node.${node?.id}.${meta?.name}.addbutton`} /> ) : null}
); };