UNPKG

alinea

Version:

[![npm](https://img.shields.io/npm/v/alinea.svg)](https://npmjs.org/package/alinea) [![install size](https://packagephobia.com/badge?p=alinea)](https://packagephobia.com/result?p=alinea)

296 lines (292 loc) 9.53 kB
import { CSS, DndContext, DragOverlay, KeyboardSensor, LayoutMeasuringStrategy, PointerSensor, SortableContext, closestCenter, defaultAnimateLayoutChanges, defaultDropAnimation, sortableKeyboardCoordinates, useSensor, useSensors, useSortable, verticalListSortingStrategy } from "../../chunks/chunk-XMYBRQEU.js"; import "../../chunks/chunk-U5RRZUYZ.js"; // src/input/list/ListField.browser.tsx import { Field, Type } from "alinea/core"; import { entries } from "alinea/core/util/Objects"; import { FormRow } from "alinea/dashboard/atoms/FormAtoms"; import { InputForm } from "alinea/dashboard/editor/InputForm"; import { useField } from "alinea/dashboard/editor/UseField"; import { Create } from "alinea/dashboard/view/Create"; import { IconButton } from "alinea/dashboard/view/IconButton"; import { InputLabel } from "alinea/dashboard/view/InputLabel"; import { fromModule, Icon, TextLabel } from "alinea/ui"; import { IcOutlineList } from "alinea/ui/icons/IcOutlineList"; import IcRoundAdd from "alinea/ui/icons/IcRoundAdd"; import { IcRoundClose } from "alinea/ui/icons/IcRoundClose"; import { IcRoundDragHandle } from "alinea/ui/icons/IcRoundDragHandle"; import { IcRoundKeyboardArrowDown } from "alinea/ui/icons/IcRoundKeyboardArrowDown"; import { IcRoundKeyboardArrowUp } from "alinea/ui/icons/IcRoundKeyboardArrowUp"; import { Sink } from "alinea/ui/Sink"; import { useState } from "react"; import { list as createList } from "./ListField.js"; // src/input/list/ListInput.module.scss var ListInput_module_default = { "root": "alinea-ListInput", "root-inner": "alinea-ListInput-inner", "rootInner": "alinea-ListInput-inner", "row": "alinea-ListInput-row", "is-dragging": "alinea-ListInput-is-dragging", "isDragging": "alinea-ListInput-is-dragging", "is-overlay": "alinea-ListInput-is-overlay", "isOverlay": "alinea-ListInput-is-overlay", "insert": "alinea-ListInput-insert", "is-first": "alinea-ListInput-is-first", "isFirst": "alinea-ListInput-is-first", "is-open": "alinea-ListInput-is-open", "isOpen": "alinea-ListInput-is-open", "insert-icon": "alinea-ListInput-insert-icon", "insertIcon": "alinea-ListInput-insert-icon", "create": "alinea-ListInput-create", "is-inline": "alinea-ListInput-is-inline", "isInline": "alinea-ListInput-is-inline" }; // src/input/list/ListField.browser.tsx export * from "./ListField.js"; import { Fragment, jsx, jsxs } from "react/jsx-runtime"; var list = Field.provideView(ListInput, createList); var styles = fromModule(ListInput_module_default); function animateLayoutChanges(args) { const { isSorting, wasSorting } = args; if (isSorting || wasSorting) return defaultAnimateLayoutChanges(args); return true; } function ListInputRowSortable(props) { const { onCreate } = props; const { attributes, listeners, setNodeRef, transform, transition, isDragging } = useSortable({ animateLayoutChanges, id: props.row.id }); const style = { transform: CSS.Transform.toString(transform), transition: transition || void 0 }; return /* @__PURE__ */ jsx( ListInputRow, { ...props, rootRef: setNodeRef, style, handle: listeners, ...attributes, isDragging, onCreate } ); } function ListInputRow({ row, schema, onMove, onDelete, handle, rootRef, isDragging, isDragOverlay, onCreate, firstRow, ...rest }) { const type = schema[row.type]; const [showInsert, setShowInsert] = useState(false); if (!type) return null; return /* @__PURE__ */ jsxs( "div", { className: styles.row({ dragging: isDragging, overlay: isDragOverlay }), ref: rootRef, ...rest, children: [ !isDragOverlay && /* @__PURE__ */ jsx( ListInsertRow, { open: showInsert, first: Boolean(firstRow), onInsert: () => setShowInsert(!showInsert) } ), showInsert && /* @__PURE__ */ jsx( ListCreateRow, { inline: true, schema, onCreate: (type2) => { onCreate(type2); setShowInsert(false); } } ), /* @__PURE__ */ jsxs(Sink.Header, { children: [ /* @__PURE__ */ jsx(Sink.Options, { style: { zIndex: 1 }, children: /* @__PURE__ */ jsx( IconButton, { icon: Type.meta(type).icon || IcRoundDragHandle, ...handle, style: { cursor: handle ? "grab" : "grabbing" } } ) }), /* @__PURE__ */ jsx(Sink.Title, { children: /* @__PURE__ */ jsx(TextLabel, { label: Type.label(type) }) }), /* @__PURE__ */ jsxs(Sink.Options, { children: [ /* @__PURE__ */ jsx( IconButton, { icon: IcRoundKeyboardArrowUp, onClick: () => onMove?.(-1) } ), /* @__PURE__ */ jsx( IconButton, { icon: IcRoundKeyboardArrowDown, onClick: () => onMove?.(1) } ), /* @__PURE__ */ jsx(IconButton, { icon: IcRoundClose, onClick: onDelete }) ] }) ] }), /* @__PURE__ */ jsx(Sink.Content, { children: /* @__PURE__ */ jsx(InputForm, { type }) }) ] } ); } function ListCreateRow({ schema, inline, onCreate }) { return /* @__PURE__ */ jsx("div", { className: styles.create({ inline }), children: /* @__PURE__ */ jsx(Create.Root, { children: entries(schema).map(([key, type]) => { return /* @__PURE__ */ jsx( Create.Button, { icon: Type.meta(type).icon, onClick: () => onCreate(key), children: /* @__PURE__ */ jsx(TextLabel, { label: Type.label(type) }) }, key ); }) }) }); } function ListInsertRow({ first, open, onInsert }) { return /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ jsx("div", { className: styles.insert({ open, first }), children: /* @__PURE__ */ jsx("button", { className: styles.insert.icon(), onClick: onInsert, children: /* @__PURE__ */ jsx(Icon, { icon: open ? IcRoundKeyboardArrowUp : IcRoundAdd }) }) }) }); } var layoutMeasuringConfig = { strategy: LayoutMeasuringStrategy.Always }; function ListInput({ field }) { const { options, value, mutator, label } = useField(field); const schema = options.schema; const rows = value; const ids = rows.map((row) => row.id); const [dragging, setDragging] = useState(null); const sensors = useSensors( useSensor(PointerSensor), useSensor(KeyboardSensor, { coordinateGetter: sortableKeyboardCoordinates }) ); function handleDragStart(event) { const { active } = event; setDragging(rows.find((row) => row.id === active.id) || null); } function handleDragEnd(event) { const { active, over } = event; if (!over || active.id === over.id) return; mutator.move(ids.indexOf(active.id), ids.indexOf(over.id)); setDragging(null); } return /* @__PURE__ */ jsx( DndContext, { sensors, collisionDetection: closestCenter, onDragStart: handleDragStart, onDragEnd: handleDragEnd, layoutMeasuring: layoutMeasuringConfig, children: /* @__PURE__ */ jsx(InputLabel, { ...options, icon: IcOutlineList, children: /* @__PURE__ */ jsx("div", { className: styles.root(), children: /* @__PURE__ */ jsxs("div", { className: styles.root.inner({ inline: options.inline }), children: [ /* @__PURE__ */ jsx(SortableContext, { items: ids, strategy: verticalListSortingStrategy, children: /* @__PURE__ */ jsxs(Sink.Root, { children: [ rows.map((row, i) => { const type = options.schema[row.type]; return /* @__PURE__ */ jsx( FormRow, { field, rowId: row.id, type, children: /* @__PURE__ */ jsx( ListInputRowSortable, { row, schema, onMove: (direction) => mutator.move(i, i + direction), onDelete: () => mutator.remove(row.id), onCreate: (type2) => { mutator.push({ type: type2 }, i); }, firstRow: i === 0 } ) }, row.id ); }), /* @__PURE__ */ jsx( ListCreateRow, { schema, onCreate: (type) => { mutator.push({ type }); } } ) ] }) }), /* @__PURE__ */ jsx( DragOverlay, { dropAnimation: { ...defaultDropAnimation, dragSourceOpacity: 0.5 }, children: dragging ? /* @__PURE__ */ jsx( FormRow, { field, rowId: dragging.id, type: options.schema[dragging.type], children: /* @__PURE__ */ jsx( ListInputRow, { row: dragging, schema, isDragOverlay: true }, "overlay" ) }, "overlay" ) : null } ) ] }) }) }) } ); } export { ListInput, list };