UNPKG

@wener/console

Version:
484 lines (483 loc) 24.1 kB
function _define_property(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } function _object_spread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; var ownKeys = Object.keys(source); if (typeof Object.getOwnPropertySymbols === "function") { ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) { return Object.getOwnPropertyDescriptor(source, sym).enumerable; })); } ownKeys.forEach(function (key) { _define_property(target, key, source[key]); }); } return target; } function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) { symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); } keys.push.apply(keys, symbols); } return keys; } function _object_spread_props(target, source) { source = source != null ? source : {}; if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; } function _object_without_properties(source, excluded) { if (source == null) return {}; var target = {}, sourceKeys, key, i; if (typeof Reflect !== "undefined" && Reflect.ownKeys) { sourceKeys = Reflect.ownKeys(source); for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } return target; } target = _object_without_properties_loose(source, excluded); if (Object.getOwnPropertySymbols) { sourceKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; } function _object_without_properties_loose(source, excluded) { if (source == null) return {}; var target = {}, sourceKeys = Object.getOwnPropertyNames(source), key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } return target; } import { useCallback, useRef } from "react"; import { Panel, PanelGroup } from "react-resizable-panels"; import { useVirtualizer } from "@tanstack/react-virtual"; import { cn } from "@wener/console"; import { HeaderContentFooterLayout } from "@wener/console/components"; import { ActionIcon } from "../icons/ActionIcon.js"; import { LeftContentRightLayout } from "../LeftContentRightLayout.js"; import { PanelResizeLineHandle } from "../ResizablePanel/index.js"; import { Tabs } from "../Tabs.js"; import { MeasureSize } from "./MeasureSize.js"; var _rightConfig = { defaultSize: 30, minSize: 20, maxSize: 60, collapsible: true }; var _leftConfig = { defaultSize: 15, minSize: 10, maxSize: 35, collapsible: true }; (function (DataViewLayout) { DataViewLayout.Composite = function (_0) { var header = _0.header, footer = _0.footer, leftPanel = _0.leftPanel, children = _0.children, rightPanel = _0.rightPanel, left = _0.left, right = _0.right, props = _object_without_properties(_0, [ "header", "footer", "leftPanel", "children", "rightPanel", "left", "right" ]); /* ┌─────────────────────────────────────────────────────────┐ │ Header │ ├──────────┬─────────────────────────┬────────────────────┤ │ │ │ │ │ Left │ Content │ Right │ │ Panel │ ┌────────┐ │ Panel │ │ │ │Children│ │ │ │(optional)│ └────────┘ │ (optional) │ │ │ ┌────────┐ │ │ │ │ │ Footer │ │ │ │ │ └────────┘ │ │ └──────────┴─────────────────────────┴────────────────────┘ */ var hasLeftPanel = Boolean(left || leftPanel); var hasRightPanel = Boolean(right || rightPanel); return /*#__PURE__*/ React.createElement(HeaderContentFooterLayout, _object_spread({ header: header }, props), /*#__PURE__*/ React.createElement(PanelGroup, { direction: "horizontal" }, hasLeftPanel && (left !== null && left !== void 0 ? left : /*#__PURE__*/ React.createElement(DataViewLayout.LeftPanel, null, leftPanel)), /*#__PURE__*/ React.createElement(Panel, { id: "content", order: 2 }, /*#__PURE__*/ React.createElement(HeaderContentFooterLayout, { footer: footer }, children)), hasRightPanel && (right !== null && right !== void 0 ? right : /*#__PURE__*/ React.createElement(DataViewLayout.RightPanel, null, rightPanel)))); }; DataViewLayout.LeftPanel = function (param) { var children = param.children; return /*#__PURE__*/ React.createElement(React.Fragment, null, /*#__PURE__*/ React.createElement(Panel, _object_spread({ id: "left", order: 1, className: "relative" }, _leftConfig), children), /*#__PURE__*/ React.createElement(PanelResizeLineHandle, null)); }; DataViewLayout.RightPanel = function (_0) { var children = _0.children, props = _object_without_properties(_0, [ "children" ]); return /*#__PURE__*/ React.createElement(React.Fragment, null, /*#__PURE__*/ React.createElement(PanelResizeLineHandle, null), /*#__PURE__*/ React.createElement(Panel, _object_spread({ id: "right", order: 3, className: "relative" }, _rightConfig, props), children)); }; DataViewLayout.Header = function (_0) { var loading = _0.loading, children = _0.children, className = _0.className, prefix = _0.prefix, suffix = _0.suffix, title = _0.title, filter = _0.filter, actions = _0.actions, props = _object_without_properties(_0, [ "loading", "children", "className", "prefix", "suffix", "title", "filter", "actions" ]); /* ┌────────────────────────────────────────────────────────┐ │ [prefix] Title [filter] [actions] [suffix] │ │ │ │ └── flex-1 spacer ──┘ │ └────────────────────────────────────────────────────────┘ */ var parts = [ prefix ]; if (title) { parts.push(typeof title === "string" ? /*#__PURE__*/ React.createElement("div", { "data-loading": loading || null, className: cn("px-2 font-semibold data-loading:animate-pulse") }, title) : title); } parts.push(filter); // Actions and suffix typically go to the right if (actions || suffix) { parts.push(/*#__PURE__*/ React.createElement("div", { className: "flex-1", key: "spacer" })); parts.push(actions, suffix); } return /*#__PURE__*/ React.createElement("header", _object_spread({ className: cn("bg-base-100 z-30 flex flex-wrap items-center gap-2 border-b p-2", className) }, props), parts.filter(Boolean), children); }; DataViewLayout.Footer = function (_0) { var children = _0.children, className = _0.className, props = _object_without_properties(_0, [ "children", "className" ]); /* ┌────────────────────────────────────────────────────────┐ │ [children - flex layout with gap-2] │ │ │ │ Typical usage: │ │ <PageInfo /> <PageNav /> <CustomContent /> │ └────────────────────────────────────────────────────────┘ */ return /*#__PURE__*/ React.createElement(LeftContentRightLayout, _object_spread({ className: cn("z-10 px-4 py-2", className) }, props)); }; DataViewLayout.Sidebar = function (_0) { var title = _0.title, header = _0.header, footer = _0.footer, children = _0.children, className = _0.className, props = _object_without_properties(_0, [ "title", "header", "footer", "children", "className" ]); /* ┌─────────────────────────────┐ │ Title/Header │ ← header (fixed) ├─────────────────────────────┤ │ │ │ Children │ ← children (scrollable) │ (scrollable content) │ │ │ ├─────────────────────────────┤ │ Footer │ ← footer (fixed, optional) └─────────────────────────────┘ */ return /*#__PURE__*/ React.createElement("aside", _object_spread({ className: cn("flex h-full flex-col", className) }, props), (title || header) && /*#__PURE__*/ React.createElement("div", { className: "bg-base-100 flex-none border-b p-2" }, typeof title === "string" ? /*#__PURE__*/ React.createElement("h3", { className: "font-semibold" }, title) : title || header), /*#__PURE__*/ React.createElement("div", { className: "flex-1 overflow-auto p-2" }, children), footer && /*#__PURE__*/ React.createElement("div", { className: "bg-base-100 flex-none border-t p-2" }, footer)); }; DataViewLayout.Summary = function (_0) { var title = _0.title, description = _0.description, tabs = _0.tabs, activeTab = _0.activeTab, onTabChange = _0.onTabChange, header = _0.header, footer = _0.footer, children = _0.children, className = _0.className, onClose = _0.onClose, props = _object_without_properties(_0, [ "title", "description", "tabs", "activeTab", "onTabChange", "header", "footer", "children", "className", "onClose" ]); /* ┌─────────────────────────────┐ │ Title [×]│ ← Header (title, description, close button) │ Description │ ├─────────────────────────────┤ │ Children Content │ ← children (fixed, optional, always before tabs) ├─────────────────────────────┤ │ Tab1 | Tab2 | Tab3 │ ← Tabs (optional, uses Tabs.Composite) ├─────────────────────────────┤ │ │ │ Tab Content │ ← Active tab content (scrollable, only if tabs exist) │ (scrollable) │ │ │ ├─────────────────────────────┤ │ Footer │ ← Footer (fixed, optional) └─────────────────────────────┘ */ return /*#__PURE__*/ React.createElement("aside", _object_spread({ className: cn("flex h-full flex-col", className) }, props), (title || header || onClose) && /*#__PURE__*/ React.createElement("div", { className: "bg-base-100 flex-none border-b p-2" }, /*#__PURE__*/ React.createElement("div", { className: "flex items-center gap-2" }, /*#__PURE__*/ React.createElement("div", { className: "flex-1" }, typeof title === "string" ? /*#__PURE__*/ React.createElement("h3", { className: "font-semibold" }, title) : title || header, description && /*#__PURE__*/ React.createElement("div", { className: "text-base-content/60 mt-1 text-sm" }, typeof description === "string" ? /*#__PURE__*/ React.createElement("p", null, description) : description)), onClose && /*#__PURE__*/ React.createElement("button", { type: "button", className: "btn btn-circle btn-ghost btn-xs", onClick: onClose, title: "\u5173\u95ED" }, /*#__PURE__*/ React.createElement(ActionIcon.Close, null)))), children && /*#__PURE__*/ React.createElement("div", { className: "bg-base-100 flex-none border-b p-2" }, children), tabs && tabs.length > 0 && /*#__PURE__*/ React.createElement("div", { className: "flex flex-1 flex-col" }, /*#__PURE__*/ React.createElement(Tabs.Composite, { tabs: tabs, activeTab: activeTab, onTabChange: onTabChange, variant: "border", className: "flex-1" })), footer && /*#__PURE__*/ React.createElement("div", { className: "bg-base-100 flex-none border-t p-2" }, footer)); }; DataViewLayout.ListItem = function (_0) { var selected = _0.selected, onSelectedChange = _0.onSelectedChange, header = _0.header, title = _0.title, prefix = _0.prefix, suffix = _0.suffix, trailing = _0.trailing, description = _0.description, onTitleClick = _0.onTitleClick, actions = _0.actions, meta = _0.meta, children = _0.children, className = _0.className, props = _object_without_properties(_0, [ "selected", "onSelectedChange", "header", "title", "prefix", "suffix", "trailing", "description", "onTitleClick", "actions", "meta", "children", "className" ]); /* ┌─────────────────────────────────────────────────────────────┐ │ [✓] [header] | title [suffix] [trailing] │ │ description │ │ Actions · Meta: Created by Jane • 1 day ago │ │ children │ └─────────────────────────────────────────────────────────────┘ */ return /*#__PURE__*/ React.createElement("div", _object_spread_props(_object_spread({}, props), { className: cn("group/item hover:bg-base-200/30 flex gap-2 border-b p-2", className) }), onSelectedChange && /*#__PURE__*/ React.createElement("div", { className: "flex items-start pt-1 opacity-0 group-hover/item:opacity-100" }, /*#__PURE__*/ React.createElement("input", { type: "checkbox", className: "checkbox checkbox-sm", checked: selected !== null && selected !== void 0 ? selected : false, onChange: function (e) { return onSelectedChange === null || onSelectedChange === void 0 ? void 0 : onSelectedChange(e.target.checked); } })), /*#__PURE__*/ React.createElement("div", { className: "flex flex-1 flex-col gap-1" }, header, (title || suffix || trailing || prefix) && /*#__PURE__*/ React.createElement("div", { className: "flex flex-wrap items-center gap-2" }, prefix, title && /*#__PURE__*/ React.createElement("div", { className: cn("font-medium", onTitleClick && "hover:text-primary cursor-pointer"), onClick: onTitleClick }, title), suffix, /*#__PURE__*/ React.createElement("div", { className: "flex-1" }), trailing && /*#__PURE__*/ React.createElement("div", { className: "flex items-center" }, trailing)), description, (actions || meta) && /*#__PURE__*/ React.createElement("div", { className: "flex items-center gap-2 pt-1" }, actions ? /*#__PURE__*/ React.createElement("div", { className: "flex gap-1" }, actions) : /*#__PURE__*/ React.createElement("div", null), /*#__PURE__*/ React.createElement("div", { className: "flex-1" }), meta && /*#__PURE__*/ React.createElement("div", { className: "text-base-content/60 text-xs" }, meta)), children)); }; DataViewLayout.List = function (_0) { var data = _0.data, renderItem = _0.renderItem, _0_estimatedItemSize = _0.estimatedItemSize, estimatedItemSize = _0_estimatedItemSize === void 0 ? 80 : _0_estimatedItemSize, _0_overscan = _0.overscan, overscan = _0_overscan === void 0 ? 5 : _0_overscan, className = _0.className, onScroll = _0.onScroll, props = _object_without_properties(_0, [ "data", "renderItem", "estimatedItemSize", "overscan", "className", "onScroll" ]); var parentRef = useRef(null); var virtualizer = useVirtualizer({ count: data.length, getScrollElement: function () { return parentRef.current; }, estimateSize: function () { return estimatedItemSize; }, overscan: overscan }); return /*#__PURE__*/ React.createElement(MeasureSize.Root, { value: useCallback(function () { return virtualizer.measure; }, [ virtualizer ]) }, /*#__PURE__*/ React.createElement("div", _object_spread({ ref: parentRef, className: cn("h-full overflow-auto", className), onScroll: onScroll }, props), /*#__PURE__*/ React.createElement("div", { className: "relative w-full", style: { height: "".concat(virtualizer.getTotalSize(), "px") } }, virtualizer.getVirtualItems().map(function (virtualItem) { var item = data[virtualItem.index]; return /*#__PURE__*/ React.createElement("div", { key: virtualItem.key, "data-index": virtualItem.index, ref: virtualizer.measureElement, style: { position: "absolute", top: 0, left: 0, width: "100%", transform: "translateY(".concat(virtualItem.start, "px)") } }, renderItem({ item: item, index: virtualItem.index, style: {} })); })))); }; DataViewLayout.SummaryTab = function (_0) { var header = _0.header, title = _0.title, footer = _0.footer, footerActions = _0.footerActions, footerInfo = _0.footerInfo, children = _0.children, className = _0.className, props = _object_without_properties(_0, [ "header", "title", "footer", "footerActions", "footerInfo", "children", "className" ]); /* ┌─────────────────────────────────────────┐ │ header | [title] │ ← Header 区域 ├─────────────────────────────────────────┤ │ │ │ children │ ← Content 区域 │ │ ├─────────────────────────────────────────┤ │ [footer] actions flex-1 info │ ← Footer 区域 └─────────────────────────────────────────┘ */ if (!header && !footer && !title && !footerActions && !footerInfo) { return /*#__PURE__*/ React.createElement("div", _object_spread({ className: cn("p-4", className) }, props), children); } // 构建 footer 内容 var footerContent = footer || footerActions || footerInfo ? /*#__PURE__*/ React.createElement("div", { className: "border-t p-4" }, footer ? footer : /*#__PURE__*/ React.createElement("div", { className: "flex items-center gap-2" }, footerActions && /*#__PURE__*/ React.createElement("div", { className: "flex gap-1" }, footerActions), /*#__PURE__*/ React.createElement("div", { className: "flex-1" }), footerInfo && /*#__PURE__*/ React.createElement("div", { className: "text-base-content/60 text-xs" }, footerInfo))) : null; return /*#__PURE__*/ React.createElement(HeaderContentFooterLayout, _object_spread({ header: (header || title) && /*#__PURE__*/ React.createElement("div", { className: "flex items-center justify-between border-b p-4" }, header, title && /*#__PURE__*/ React.createElement("div", { className: "font-semibold" }, title)), footer: footerContent, className: className }, props), /*#__PURE__*/ React.createElement("div", { className: "p-4" }, children)); }; })(DataViewLayout || (DataViewLayout = {})); export var DataViewLayout;