{"version":3,"file":"List.mjs","names":["formMessages"],"sources":["../../../src/base-ui/FormKit/List.tsx"],"sourcesContent":["'use client';\n\nimport { PlusIcon, XIcon } from 'lucide-react';\nimport { cloneElement, memo, type ReactElement, type ReactNode, useCallback, useRef } from 'react';\n\nimport ActionIcon from '@/base-ui/ActionIcon';\nimport formMessages from '@/i18n/resources/en/form';\nimport { useTranslation } from '@/i18n/useTranslation';\n\nimport { useFormKitContext } from './context';\nimport FormField from './Field';\nimport { getInternals } from './instance';\nimport type { FieldValidate } from './schema';\nimport { listStyles } from './style';\nimport { useStoreSelector } from './useStoreSelector';\n\nexport interface FormListField {\n  index: number;\n  key: string;\n  name: string;\n}\n\nexport interface FormListRenderProps {\n  add: (item?: unknown) => void;\n  fields: FormListField[];\n  move: (from: number, to: number) => void;\n  remove: (index: number) => void;\n}\n\nexport interface FormListColumn {\n  children: ReactElement;\n  flex?: number;\n  name: string;\n  required?: boolean | string;\n  title?: ReactNode;\n  validate?: FieldValidate;\n}\n\nexport interface FormListProps {\n  addText?: ReactNode;\n  children?: (props: FormListRenderProps) => ReactNode;\n  columns?: FormListColumn[];\n  emptyText?: ReactNode;\n  name: string;\n  newItem?: unknown;\n}\n\nlet rowSeed = 0;\nconst nextRowKey = () => `row-${(rowSeed += 1)}`;\n\nconst createItem = (newItem: unknown) =>\n  typeof newItem === 'function'\n    ? newItem()\n    : newItem && typeof newItem === 'object'\n      ? structuredClone(newItem)\n      : (newItem ?? {});\n\nconst labelFor = (column: FormListColumn, index: number) =>\n  (column.children as ReactElement<{ 'aria-label'?: string }>).props['aria-label'] ??\n  (typeof column.title === 'string' ? `${column.title} ${index + 1}` : undefined);\n\nconst FormList = memo<FormListProps>(({ addText, children, columns, emptyText, name, newItem }) => {\n  const { form } = useFormKitContext();\n  const { engine } = getInternals(form);\n  const { t } = useTranslation(formMessages);\n  const length = useStoreSelector(engine, (e) => {\n    const value = e.getValue(name);\n    return Array.isArray(value) ? value.length : 0;\n  });\n\n  const keysRef = useRef<string[]>([]);\n  const keys = keysRef.current;\n  if (keys.length > length) keys.length = length;\n  while (keys.length < length) keys.push(nextRowKey());\n\n  const add = useCallback(\n    (item?: unknown) => {\n      keysRef.current.push(nextRowKey());\n      engine.pushItem(name, item);\n    },\n    [engine, name],\n  );\n  const remove = useCallback(\n    (index: number) => {\n      keysRef.current.splice(index, 1);\n      engine.removeItem(name, index);\n    },\n    [engine, name],\n  );\n  const move = useCallback(\n    (from: number, to: number) => {\n      const [moved] = keysRef.current.splice(from, 1);\n      keysRef.current.splice(to, 0, moved);\n      engine.moveItem(name, from, to);\n    },\n    [engine, name],\n  );\n\n  const fields = keys.map((key, index) => ({ index, key, name: `${name}.${index}` }));\n\n  if (children || !columns) return <>{children?.({ add, fields, move, remove })}</>;\n\n  const gridTemplateColumns = `${columns.map((c) => `minmax(0, ${c.flex ?? 1}fr)`).join(' ')} 36px`;\n  const addButton = (\n    <button className={listStyles.add} type=\"button\" onClick={() => add(createItem(newItem))}>\n      <PlusIcon size={14} />\n      {addText ?? t('form.list.add')}\n    </button>\n  );\n\n  return (\n    <div className={listStyles.table}>\n      <div className={listStyles.head} style={{ gridTemplateColumns }}>\n        {columns.map((column) => (\n          <div className={listStyles.title} key={column.name}>\n            {column.title}\n          </div>\n        ))}\n      </div>\n      {fields.length === 0 ? (\n        <div className={listStyles.empty}>\n          <span>{emptyText ?? t('form.list.empty')}</span>\n          {addButton}\n        </div>\n      ) : (\n        <>\n          {fields.map((field) => (\n            <div className={listStyles.row} key={field.key} style={{ gridTemplateColumns }}>\n              {columns.map((column) => (\n                <div className={listStyles.cell} key={column.name}>\n                  <FormField\n                    bare\n                    name={`${field.name}.${column.name}`}\n                    required={column.required}\n                    validate={column.validate}\n                  >\n                    {cloneElement(column.children as ReactElement<any>, {\n                      'aria-label': labelFor(column, field.index),\n                    })}\n                  </FormField>\n                </div>\n              ))}\n              <ActionIcon\n                aria-label={t('form.list.remove')}\n                icon={XIcon}\n                size={'small'}\n                title={t('form.list.remove')}\n                onClick={() => remove(field.index)}\n              />\n            </div>\n          ))}\n          <div className={listStyles.foot}>{addButton}</div>\n        </>\n      )}\n    </div>\n  );\n});\n\nFormList.displayName = 'FormList';\n\nexport default FormList;\n"],"mappings":";;;;;;;;;;;;;AA+CA,IAAI,UAAU;AACd,MAAM,mBAAmB,OAAQ,WAAW;AAE5C,MAAM,cAAc,YAClB,OAAO,YAAY,aACf,QAAQ,IACR,WAAW,OAAO,YAAY,WAC5B,gBAAgB,OAAO,IACtB,WAAW,CAAC;AAErB,MAAM,YAAY,QAAwB,UACvC,OAAO,SAAqD,MAAM,kBAClE,OAAO,OAAO,UAAU,WAAW,GAAG,OAAO,MAAM,GAAG,QAAQ,MAAM,KAAA;AAEvE,MAAM,WAAW,MAAqB,EAAE,SAAS,UAAU,SAAS,WAAW,MAAM,cAAc;CACjG,MAAM,EAAE,SAAS,kBAAkB;CACnC,MAAM,EAAE,WAAW,aAAa,IAAI;CACpC,MAAM,EAAE,MAAM,eAAeA,YAAY;CACzC,MAAM,SAAS,iBAAiB,SAAS,MAAM;EAC7C,MAAM,QAAQ,EAAE,SAAS,IAAI;EAC7B,OAAO,MAAM,QAAQ,KAAK,IAAI,MAAM,SAAS;CAC/C,CAAC;CAED,MAAM,UAAU,OAAiB,CAAC,CAAC;CACnC,MAAM,OAAO,QAAQ;CACrB,IAAI,KAAK,SAAS,QAAQ,KAAK,SAAS;CACxC,OAAO,KAAK,SAAS,QAAQ,KAAK,KAAK,WAAW,CAAC;CAEnD,MAAM,MAAM,aACT,SAAmB;EAClB,QAAQ,QAAQ,KAAK,WAAW,CAAC;EACjC,OAAO,SAAS,MAAM,IAAI;CAC5B,GACA,CAAC,QAAQ,IAAI,CACf;CACA,MAAM,SAAS,aACZ,UAAkB;EACjB,QAAQ,QAAQ,OAAO,OAAO,CAAC;EAC/B,OAAO,WAAW,MAAM,KAAK;CAC/B,GACA,CAAC,QAAQ,IAAI,CACf;CACA,MAAM,OAAO,aACV,MAAc,OAAe;EAC5B,MAAM,CAAC,SAAS,QAAQ,QAAQ,OAAO,MAAM,CAAC;EAC9C,QAAQ,QAAQ,OAAO,IAAI,GAAG,KAAK;EACnC,OAAO,SAAS,MAAM,MAAM,EAAE;CAChC,GACA,CAAC,QAAQ,IAAI,CACf;CAEA,MAAM,SAAS,KAAK,KAAK,KAAK,WAAW;EAAE;EAAO;EAAK,MAAM,GAAG,KAAK,GAAG;CAAQ,EAAE;CAElF,IAAI,YAAY,CAAC,SAAS,OAAO,oBAAA,YAAA,EAAA,UAAG,WAAW;EAAE;EAAK;EAAQ;EAAM;CAAO,CAAC,EAAI,CAAA;CAEhF,MAAM,sBAAsB,GAAG,QAAQ,KAAK,MAAM,aAAa,EAAE,QAAQ,EAAE,IAAI,CAAC,CAAC,KAAK,GAAG,EAAE;CAC3F,MAAM,YACJ,qBAAC,UAAD;EAAQ,WAAW,WAAW;EAAK,MAAK;EAAS,eAAe,IAAI,WAAW,OAAO,CAAC;EAAvF,UAAA,CACE,oBAAC,UAAD,EAAU,MAAM,GAAK,CAAA,GACpB,WAAW,EAAE,eAAe,CACvB;;CAGV,OACE,qBAAC,OAAD;EAAK,WAAW,WAAW;EAA3B,UAAA,CACE,oBAAC,OAAD;GAAK,WAAW,WAAW;GAAM,OAAO,EAAE,oBAAoB;GAC3D,UAAA,QAAQ,KAAK,WACZ,oBAAC,OAAD;IAAK,WAAW,WAAW;IACxB,UAAA,OAAO;GACL,GAFkC,OAAO,IAEzC,CACN;EACE,CAAA,GACJ,OAAO,WAAW,IACjB,qBAAC,OAAD;GAAK,WAAW,WAAW;GAA3B,UAAA,CACE,oBAAC,QAAD,EAAA,UAAO,aAAa,EAAE,iBAAiB,EAAQ,CAAA,GAC9C,SACE;EAEL,CAAA,IAAA,qBAAA,YAAA,EAAA,UAAA,CACG,OAAO,KAAK,UACX,qBAAC,OAAD;GAAK,WAAW,WAAW;GAAqB,OAAO,EAAE,oBAAoB;GAA7E,UAAA,CACG,QAAQ,KAAK,WACZ,oBAAC,OAAD;IAAK,WAAW,WAAW;IACzB,UAAA,oBAAC,WAAD;KACE,MAAA;KACA,MAAM,GAAG,MAAM,KAAK,GAAG,OAAO;KAC9B,UAAU,OAAO;KACjB,UAAU,OAAO;KAEhB,UAAA,aAAa,OAAO,UAA+B,EAClD,cAAc,SAAS,QAAQ,MAAM,KAAK,EAC5C,CAAC;IACQ,CAAA;GACR,GAXiC,OAAO,IAWxC,CACN,GACD,oBAAC,YAAD;IACE,cAAY,EAAE,kBAAkB;IAChC,MAAM;IACN,MAAM;IACN,OAAO,EAAE,kBAAkB;IAC3B,eAAe,OAAO,MAAM,KAAK;GAClC,CAAA,CACE;EAtBgC,GAAA,MAAM,GAsBtC,CACN,GACD,oBAAC,OAAD;GAAK,WAAW,WAAW;GAAO,UAAA;EAAe,CAAA,CACjD,EAAA,CAAA,CAED;;AAET,CAAC;AAED,SAAS,cAAc"}