Files
klz-cables.com/.pnpm-store/v10/files/4a/02aa2abd0d9f22c31facac48699372e3612601fbdaa1131e0a0f5daa06bb4f370b33a0ad1f249e7dc96817a49cbe8cbfce3d6ef4297c8d28c42a9497841c8e
Marc Mintel 5397309103
Some checks failed
Build & Deploy / 🔍 Prepare (push) Successful in 20s
Build & Deploy / 🧪 QA (push) Failing after 34s
Build & Deploy / 🏗️ Build (push) Has started running
Build & Deploy / 🚀 Deploy (push) Has been cancelled
Build & Deploy / 🧪 Smoke Test (push) Has been cancelled
Build & Deploy / ⚡ Lighthouse (push) Has been cancelled
Build & Deploy / 🔔 Notify (push) Has been cancelled
fix(products): fix breadcrumbs and product filtering (backport from main)
2026-02-24 16:04:21 +01:00

474 lines
16 KiB
Plaintext

'use client';
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import { getTranslation } from '@payloadcms/translations';
import React, { Fragment, useCallback, useMemo } from 'react';
import { toast } from 'sonner';
import { Banner } from '../../elements/Banner/index.js';
import { Button } from '../../elements/Button/index.js';
import { clipboardCopy, clipboardPaste } from '../../elements/ClipboardAction/clipboardUtilities.js';
import { ClipboardAction } from '../../elements/ClipboardAction/index.js';
import { mergeFormStateFromClipboard, reduceFormStateByPath } from '../../elements/ClipboardAction/mergeFormStateFromClipboard.js';
import { DraggableSortableItem } from '../../elements/DraggableSortable/DraggableSortableItem/index.js';
import { DraggableSortable } from '../../elements/DraggableSortable/index.js';
import { DrawerToggler } from '../../elements/Drawer/index.js';
import { useDrawerSlug } from '../../elements/Drawer/useDrawerSlug.js';
import { ErrorPill } from '../../elements/ErrorPill/index.js';
import { RenderCustomComponent } from '../../elements/RenderCustomComponent/index.js';
import { useForm, useFormSubmitted } from '../../forms/Form/context.js';
import { extractRowsAndCollapsedIDs, toggleAllRows } from '../../forms/Form/rowHelpers.js';
import { NullifyLocaleField } from '../../forms/NullifyField/index.js';
import { useField } from '../../forms/useField/index.js';
import { withCondition } from '../../forms/withCondition/index.js';
import { useConfig } from '../../providers/Config/index.js';
import { useDocumentInfo } from '../../providers/DocumentInfo/index.js';
import { useLocale } from '../../providers/Locale/index.js';
import { useTranslation } from '../../providers/Translation/index.js';
import { scrollToID } from '../../utilities/scrollToID.js';
import './index.scss';
import { FieldDescription } from '../FieldDescription/index.js';
import { FieldError } from '../FieldError/index.js';
import { FieldLabel } from '../FieldLabel/index.js';
import { mergeFieldStyles } from '../mergeFieldStyles.js';
import { fieldBaseClass } from '../shared/index.js';
import { BlockRow } from './BlockRow.js';
import { BlocksDrawer } from './BlocksDrawer/index.js';
const baseClass = 'blocks-field';
const BlocksFieldComponent = props => {
const {
i18n,
t
} = useTranslation();
const {
field,
field: {
name,
type,
admin: {
className,
description,
isSortable = true
} = {},
blockReferences,
blocks,
label,
labels: labelsFromProps,
localized,
maxRows,
minRows: minRowsProp,
required
},
path: pathFromProps,
permissions,
readOnly,
schemaPath: schemaPathFromProps,
validate
} = props;
const schemaPath = schemaPathFromProps ?? name;
const minRows = minRowsProp ?? required ? 1 : 0;
const {
setDocFieldPreferences
} = useDocumentInfo();
const {
addFieldRow,
dispatchFields,
getFields,
moveFieldRow,
removeFieldRow,
replaceState,
setModified
} = useForm();
const {
code: locale
} = useLocale();
const {
config: {
localization
},
config
} = useConfig();
const drawerSlug = useDrawerSlug('blocks-drawer');
const submitted = useFormSubmitted();
const labels = {
plural: t('fields:blocks'),
singular: t('fields:block'),
...labelsFromProps
};
const editingDefaultLocale = (() => {
if (localization && localization.fallback) {
const defaultLocale = localization.defaultLocale;
return locale === defaultLocale;
}
return true;
})();
const memoizedValidate = useCallback((value, options) => {
// alternative locales can be null
if (!editingDefaultLocale && value === null) {
return true;
}
if (typeof validate === 'function') {
return validate(value, {
...options,
maxRows,
minRows,
required
});
}
}, [maxRows, minRows, required, validate, editingDefaultLocale]);
const {
blocksFilterOptions,
customComponents: {
AfterInput,
BeforeInput,
Description,
Error,
Label
} = {},
disabled,
errorPaths,
path,
rows = [],
showError,
valid,
value: value_0
} = useField({
hasRows: true,
potentiallyStalePath: pathFromProps,
validate: memoizedValidate
});
const {
clientBlocks,
clientBlocksAfterFilter: clientBlocksAfterFilter_0
} = useMemo(() => {
let resolvedBlocks = [];
if (!blockReferences) {
resolvedBlocks = blocks;
} else {
for (const blockReference of blockReferences) {
const block = typeof blockReference === 'string' ? config.blocksMap[blockReference] : blockReference;
if (block) {
resolvedBlocks.push(block);
}
}
}
if (Array.isArray(blocksFilterOptions)) {
const clientBlocksAfterFilter = resolvedBlocks.filter(block_0 => {
const blockSlug = typeof block_0 === 'string' ? block_0 : block_0.slug;
return blocksFilterOptions.includes(blockSlug);
});
return {
clientBlocks: resolvedBlocks,
clientBlocksAfterFilter
};
}
return {
clientBlocks: resolvedBlocks,
clientBlocksAfterFilter: resolvedBlocks
};
}, [blockReferences, blocks, blocksFilterOptions, config.blocksMap]);
const addRow = useCallback((rowIndex, blockType) => {
addFieldRow({
blockType,
path,
rowIndex,
schemaPath
});
setTimeout(() => {
scrollToID(`${path}-row-${rowIndex + 1}`);
}, 0);
}, [addFieldRow, path, schemaPath]);
const duplicateRow = useCallback(rowIndex_0 => {
dispatchFields({
type: 'DUPLICATE_ROW',
path,
rowIndex: rowIndex_0
});
setModified(true);
setTimeout(() => {
scrollToID(`${path}-row-${rowIndex_0 + 1}`);
}, 0);
}, [dispatchFields, path, setModified]);
const removeRow = useCallback(rowIndex_1 => {
removeFieldRow({
path,
rowIndex: rowIndex_1
});
}, [path, removeFieldRow]);
const moveRow = useCallback((moveFromIndex, moveToIndex) => {
moveFieldRow({
moveFromIndex,
moveToIndex,
path
});
}, [moveFieldRow, path]);
const toggleCollapseAll = useCallback(collapsed => {
const {
collapsedIDs,
updatedRows
} = toggleAllRows({
collapsed,
rows
});
dispatchFields({
type: 'SET_ALL_ROWS_COLLAPSED',
path,
updatedRows
});
setDocFieldPreferences(path, {
collapsed: collapsedIDs
});
}, [dispatchFields, path, rows, setDocFieldPreferences]);
const setCollapse = useCallback((rowID, collapsed_0) => {
const {
collapsedIDs: collapsedIDs_0,
updatedRows: updatedRows_0
} = extractRowsAndCollapsedIDs({
collapsed: collapsed_0,
rowID,
rows
});
dispatchFields({
type: 'SET_ROW_COLLAPSED',
path,
updatedRows: updatedRows_0
});
setDocFieldPreferences(path, {
collapsed: collapsedIDs_0
});
}, [dispatchFields, path, rows, setDocFieldPreferences]);
const copyRow = useCallback(rowIndex_2 => {
const clipboardResult = clipboardCopy({
type,
blocks: clientBlocks,
getDataToCopy: () => reduceFormStateByPath({
formState: {
...getFields()
},
path,
rowIndex: rowIndex_2
}),
path,
rowIndex: rowIndex_2,
t
});
if (typeof clipboardResult === 'string') {
toast.error(clipboardResult);
} else {
toast.success(t('general:copied'));
}
}, [clientBlocks, path, t, type, getFields]);
const pasteRow = useCallback(rowIndex_3 => {
const pasteArgs = {
onPaste: dataFromClipboard => {
const formState = {
...getFields()
};
const newState = mergeFormStateFromClipboard({
dataFromClipboard,
formState,
path,
rowIndex: rowIndex_3
});
replaceState(newState);
setModified(true);
},
path,
schemaBlocks: clientBlocks,
t
};
const clipboardResult_0 = clipboardPaste(pasteArgs);
if (typeof clipboardResult_0 === 'string') {
toast.error(clipboardResult_0);
}
}, [clientBlocks, getFields, path, replaceState, setModified, t]);
const pasteBlocks = useCallback(dataFromClipboard_0 => {
const formState_0 = {
...getFields()
};
const newState_0 = mergeFormStateFromClipboard({
dataFromClipboard: dataFromClipboard_0,
formState: formState_0,
path
});
replaceState(newState_0);
setModified(true);
}, [getFields, path, replaceState, setModified]);
const hasMaxRows = maxRows && rows.length >= maxRows;
const fieldErrorCount = errorPaths.length;
const fieldHasErrors = submitted && fieldErrorCount + (valid ? 0 : 1) > 0;
const showMinRows = rows.length < minRows || required && rows.length === 0;
const showRequired = readOnly && rows.length === 0;
const styles = useMemo(() => mergeFieldStyles(field), [field]);
return /*#__PURE__*/_jsxs("div", {
className: [fieldBaseClass, baseClass, className, fieldHasErrors ? `${baseClass}--has-error` : `${baseClass}--has-no-error`].filter(Boolean).join(' '),
id: `field-${path?.replace(/\./g, '__')}`,
style: styles,
children: [showError && /*#__PURE__*/_jsx(RenderCustomComponent, {
CustomComponent: Error,
Fallback: /*#__PURE__*/_jsx(FieldError, {
path: path,
showError: showError
})
}), /*#__PURE__*/_jsxs("header", {
className: `${baseClass}__header`,
children: [/*#__PURE__*/_jsxs("div", {
className: `${baseClass}__header-wrap`,
children: [/*#__PURE__*/_jsxs("div", {
className: `${baseClass}__heading-with-error`,
children: [/*#__PURE__*/_jsx("h3", {
children: /*#__PURE__*/_jsx(RenderCustomComponent, {
CustomComponent: Label,
Fallback: /*#__PURE__*/_jsx(FieldLabel, {
as: "span",
label: label,
localized: localized,
path: path,
required: required
})
})
}), fieldHasErrors && fieldErrorCount > 0 && /*#__PURE__*/_jsx(ErrorPill, {
count: fieldErrorCount,
i18n: i18n,
withMessage: true
})]
}), /*#__PURE__*/_jsxs("ul", {
className: `${baseClass}__header-actions`,
children: [rows.length > 0 && /*#__PURE__*/_jsxs(Fragment, {
children: [/*#__PURE__*/_jsx("li", {
children: /*#__PURE__*/_jsx("button", {
className: `${baseClass}__header-action`,
onClick: () => toggleCollapseAll(true),
type: "button",
children: t('fields:collapseAll')
})
}), /*#__PURE__*/_jsx("li", {
children: /*#__PURE__*/_jsx("button", {
className: `${baseClass}__header-action`,
onClick: () => toggleCollapseAll(false),
type: "button",
children: t('fields:showAll')
})
})]
}), /*#__PURE__*/_jsx("li", {
children: /*#__PURE__*/_jsx(ClipboardAction, {
allowCopy: rows?.length > 0,
allowPaste: !readOnly,
blocks: clientBlocks,
className: `${baseClass}__header-action`,
disabled: disabled,
getDataToCopy: () => reduceFormStateByPath({
formState: {
...getFields()
},
path
}),
onPaste: pasteBlocks,
path: path,
type: type
})
})]
})]
}), /*#__PURE__*/_jsx(RenderCustomComponent, {
CustomComponent: Description,
Fallback: /*#__PURE__*/_jsx(FieldDescription, {
description: description,
path: path
})
})]
}), BeforeInput, /*#__PURE__*/_jsx(NullifyLocaleField, {
fieldValue: value_0,
localized: localized,
path: path,
readOnly: readOnly
}), (rows.length > 0 || !valid && (showRequired || showMinRows)) && /*#__PURE__*/_jsxs(DraggableSortable, {
className: `${baseClass}__rows`,
ids: rows.map(row => row.id),
onDragEnd: ({
moveFromIndex: moveFromIndex_0,
moveToIndex: moveToIndex_0
}) => moveRow(moveFromIndex_0, moveToIndex_0),
children: [rows.map((row_0, i) => {
const {
blockType: blockType_0,
isLoading
} = row_0;
const blockConfig = config.blocksMap[blockType_0] ?? clientBlocks.find(block_1 => block_1.slug === blockType_0);
if (blockConfig) {
const rowPath = `${path}.${i}`;
const rowErrorCount = errorPaths.filter(errorPath => errorPath.startsWith(rowPath + '.')).length;
return /*#__PURE__*/_jsx(DraggableSortableItem, {
disabled: readOnly || disabled || !isSortable,
id: row_0.id,
children: draggableSortableItemProps => /*#__PURE__*/_jsx(BlockRow, {
...draggableSortableItemProps,
addRow: addRow,
block: blockConfig,
// Pass all blocks, not just clientBlocksAfterFilter, as existing blocks should still be displayed even if they don't match the new filter
blocks: clientBlocks,
copyRow: copyRow,
duplicateRow: duplicateRow,
errorCount: rowErrorCount,
fields: blockConfig.fields,
hasMaxRows: hasMaxRows,
isLoading: isLoading,
isSortable: isSortable,
Label: rows?.[i]?.customComponents?.RowLabel,
labels: labels,
moveRow: moveRow,
parentPath: path,
pasteRow: pasteRow,
path: rowPath,
permissions: permissions,
readOnly: readOnly || disabled,
removeRow: removeRow,
row: row_0,
rowCount: rows.length,
rowIndex: i,
schemaPath: schemaPath + blockConfig.slug,
setCollapse: setCollapse
})
}, row_0.id);
}
return null;
}), !editingDefaultLocale && /*#__PURE__*/_jsxs(React.Fragment, {
children: [showMinRows && /*#__PURE__*/_jsx(Banner, {
type: "error",
children: t('validation:requiresAtLeast', {
count: minRows,
label: getTranslation(minRows > 1 ? labels.plural : labels.singular, i18n) || t(minRows > 1 ? 'general:row' : 'general:rows')
})
}), showRequired && /*#__PURE__*/_jsx(Banner, {
children: t('validation:fieldHasNo', {
label: getTranslation(labels.plural, i18n)
})
})]
})]
}), !hasMaxRows && /*#__PURE__*/_jsxs(Fragment, {
children: [/*#__PURE__*/_jsx(DrawerToggler, {
className: `${baseClass}__drawer-toggler`,
disabled: readOnly || disabled,
slug: drawerSlug,
children: /*#__PURE__*/_jsx(Button, {
buttonStyle: "icon-label",
disabled: readOnly || disabled,
el: "span",
icon: "plus",
iconPosition: "left",
iconStyle: "with-border",
children: t('fields:addLabel', {
label: getTranslation(labels.singular, i18n)
})
})
}), /*#__PURE__*/_jsx(BlocksDrawer, {
addRow: addRow,
addRowIndex: rows?.length || 0,
// Only allow choosing filtered blocks
blocks: clientBlocksAfterFilter_0,
drawerSlug: drawerSlug,
labels: labels
})]
}), AfterInput]
});
};
export const BlocksField = withCondition(BlocksFieldComponent);
//# sourceMappingURL=index.js.map