alinea
Version:
[](https://npmjs.org/package/alinea) [](https://packagephobia.com/result?p=alinea)
296 lines (292 loc) • 9.53 kB
JavaScript
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
};