@wener/console
Version:
Base console UI toolkit
484 lines (483 loc) • 24.1 kB
JavaScript
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;