UNPKG

@ducor/react

Version:

admin template ui interface

156 lines (155 loc) 7.72 kB
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) { if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) { if (ar || !(i in from)) { if (!ar) ar = Array.prototype.slice.call(from, 0, i); ar[i] = from[i]; } } return to.concat(ar || Array.prototype.slice.call(from)); }; import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime"; import React, { createContext, memo, useContext, useEffect, useMemo, useState, } from "react"; import _ from "lodash"; import { twJoin, twMerge } from "tailwind-merge"; import { array_swap, uuidv4 } from "@ducor/helpers"; import Button from "../button"; import Flex from "../flex"; import { FormContext } from "."; var ArrayFieldContext = createContext(undefined); export var ArrayFieldItemContext = createContext(undefined); /* * @see https://teslamotors.github.io/informed/getting-started/array-field */ var ArrayField = function (_a) { var _b = _a.name, name = _b === void 0 ? "" : _b, children = _a.children, appendItem = _a.appendItem; // react nodes[ ] var _c = useState([]), chilItems = _c[0], setChildItems = _c[1]; useEffect(function () { setChildItems(children ? __spreadArray([], children, true) : []); }, [children]); var _d = useState(null), activeIndex = _d[0], setActiveIndex = _d[1]; var add = function () { if (React.isValidElement(appendItem)) { // Clone the React element and update its key and index var newElement_1 = React.cloneElement(appendItem, { key: chilItems.length, index: chilItems.length, // Valid now }); // Add the cloned element to the state setChildItems(function (prevItems) { return __spreadArray(__spreadArray([], prevItems, true), [newElement_1], false); }); } }; var hasField = function (key) { return chilItems[key] !== undefined; }; var remove = function (key) { setChildItems(function (prevItems) { return __spreadArray([], __spreadArray([], prevItems.filter(function (ch, k) { return React.isValidElement(ch) && k !== key; }), true).map(function (child, key) { return React.cloneElement(child, { key: key, index: key, // Valid now }); }), true); }); }; var reset = function () { setChildItems(children ? __spreadArray([], children, true) : []); }; var swap = function (sourceIndex, targetIndex) { setChildItems(function (prevCards) { return array_swap(prevCards, sourceIndex, targetIndex); }); }; useEffect(function () { return function () { setChildItems([]); }; }, []); return (_jsxs(ArrayFieldContext.Provider, { value: { name: name, activeIndex: activeIndex, setActiveIndex: setActiveIndex, add: add, remove: remove, reset: reset, swap: swap }, children: [chilItems, _jsxs(Flex, { gap: 2, children: [_jsx(Button, { size: 'sm', type: 'button', variant: 'success', onClick: function () { return add(); }, children: "Add" }), _jsx(Button, { size: 'sm', variant: 'black', type: 'button', onClick: function () { return reset(); }, children: "reset" })] })] })); }; var Item = memo(function (_a) { var children = _a.children, title = _a.title, index = _a.index; var filedMap = useState(new Map())[0]; var _b = useField(), name = _b.name, activeIndex = _b.activeIndex, setActiveIndex = _b.setActiveIndex, remove = _b.remove, swap = _b.swap; // Create a debounced version of the click handler var handleClick = React.useMemo(function () { var debounced = _.debounce(function () { setActiveIndex(activeIndex === index ? null : index); }, 300); return Object.assign(debounced, { cancel: debounced.cancel.bind(debounced), }); }, [activeIndex, index, setActiveIndex]); // Create a debounced version of the remove handler var handleRemove = React.useMemo(function () { var debounced = _.debounce(function () { remove(index); }, 300); return Object.assign(debounced, { cancel: debounced.cancel.bind(debounced), }); }, [index, remove]); // Example usage to clear/cancel debounce React.useEffect(function () { return function () { handleClick.cancel(); handleRemove.cancel(); }; }, [handleClick, handleRemove]); var isActive = activeIndex === index; var value = { isActive: isActive, filedMap: filedMap, groupIndex: index, groupName: name, }; return (_jsx(ArrayFieldItemContext.Provider, { value: value, children: _jsxs("div", { className: 'border mb-1', children: [_jsxs(Flex, { justify: 'between', align: 'center', gap: 2, className: twMerge("p-2 bg-gray-200", isActive && "border-b"), children: [_jsxs(Flex, { gap: 2, children: [_jsx("div", { className: 'cursor-move mx-1', children: _jsx("i", { className: 'feather-move' }) }), _jsx("h5", { children: "[".concat(index, "] ").concat(title) })] }), _jsxs(Flex, { justify: 'end', align: 'center', gap: 1, children: [_jsx(Button, { size: 'sm', onClick: handleClick, children: _jsx("i", { className: isActive ? "feather-eye" : "feather-eye-off" }) }), _jsx(Button, { size: 'sm', variant: 'gray', onClick: handleClick, children: _jsx("i", { className: 'feather-copy' }) }), _jsx(Button, { size: 'sm', variant: 'gray', onClick: function () { return swap(index, index - 1); }, children: _jsx("i", { className: 'feather-chevron-down' }) }), _jsx(Button, { size: 'sm', variant: 'gray', onClick: function () { return swap(index, index + 1); }, children: _jsx("i", { className: 'feather-chevron-up' }) }), _jsx(Button, { size: 'sm', variant: 'danger', onClick: handleRemove, children: _jsx("i", { className: 'feather-trash' }) })] })] }), _jsx("div", { className: twJoin("m-2", isActive ? "" : "hidden"), children: children })] }) })); }); var useField = function () { var context = useContext(ArrayFieldContext); if (!context) { throw new Error("ArrayFieldContext not found"); } return context; }; export var useFieldName = function (name) { var formCtx = useContext(FormContext); var arrayFieldCtx = useContext(ArrayFieldItemContext); if (typeof name !== "string") { throw new Error("Invalid field name: ".concat(name)); } // Use memo to ensure fieldMap isn't recreated on each render var filedMap = useMemo(function () { return (arrayFieldCtx === null || arrayFieldCtx === void 0 ? void 0 : arrayFieldCtx.filedMap) || new Map(); }, [arrayFieldCtx === null || arrayFieldCtx === void 0 ? void 0 : arrayFieldCtx.filedMap]); var _a = arrayFieldCtx || {}, groupName = _a.groupName, groupIndex = _a.groupIndex; var field = filedMap.get(name); if (!field) { var fieldName = groupIndex !== undefined ? "".concat(groupName, "[").concat(groupIndex, "].").concat(name) : name; field = { _uid: uuidv4(), name: fieldName, }; filedMap.set(name, field); // Store the new field in the map } /// form field context if (!formCtx) { // return { // method: undefined, // processing: false, // isDirty: false, // defaultValue: undefined, // value: "", // setValue: () => {}, // error: [], // setError: () => {}, // }; } return { _uid: field._uid, fieldName: field.name, }; }; export default Object.assign(ArrayField, { Item: Item, });