@pisell/materials 1.0.1055 → 1.0.1057
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/lowcode/assets-daily.json +11 -11
- package/build/lowcode/assets-dev.json +2 -2
- package/build/lowcode/assets-prod.json +11 -11
- package/build/lowcode/index.js +1 -1
- package/build/lowcode/meta.js +7 -7
- package/build/lowcode/preview.js +9 -9
- package/build/lowcode/render/default/view.css +1 -1
- package/build/lowcode/render/default/view.js +20 -20
- package/build/lowcode/view.css +1 -1
- package/build/lowcode/view.js +24 -24
- package/es/components/PisellLayouts/index.d.ts +9 -5
- package/es/components/PisellLayouts/index.js +5 -3
- package/es/components/dataSourceComponents/dataSourceSubForm/index.js +18 -5
- package/es/components/dataSourceComponents/dataSourceSubForm/schema-full-example.json +38 -32
- package/es/components/dataSourceComponents/fields/RecordListWrapper/WithMode.js +58 -26
- package/es/components/dataSourceComponents/fields/Tabs/Tabs.js +1 -1
- package/es/components/dataSourceComponents/fields/Tabs/Tabs.less +2 -1
- package/es/components/pisellFloorMapLayout/PisellFloorMapLayout.d.ts +12 -0
- package/es/components/pisellFloorMapLayout/PisellFloorMapLayout.js +264 -0
- package/es/components/pisellFloorMapLayout/PisellFloorMapLayout.less +7 -0
- package/es/components/pisellFloorMapLayout/PisellFloorMapLayout.stories.d.ts +42 -0
- package/es/components/pisellFloorMapLayout/PisellFloorMapLayout.stories.js +1234 -0
- package/es/components/pisellFloorMapLayout/components/ItemLayer.d.ts +36 -0
- package/es/components/pisellFloorMapLayout/components/ItemLayer.js +121 -0
- package/es/components/pisellFloorMapLayout/components/ItemLayer.less +19 -0
- package/es/components/pisellFloorMapLayout/components/MapLayer.d.ts +23 -0
- package/es/components/pisellFloorMapLayout/components/MapLayer.js +74 -0
- package/es/components/pisellFloorMapLayout/components/MapLayer.less +7 -0
- package/es/components/pisellFloorMapLayout/components/ViewControls.d.ts +22 -0
- package/es/components/pisellFloorMapLayout/components/ViewControls.js +59 -0
- package/es/components/pisellFloorMapLayout/components/ViewControls.less +76 -0
- package/es/components/pisellFloorMapLayout/components/index.d.ts +7 -0
- package/es/components/pisellFloorMapLayout/components/index.js +6 -0
- package/es/components/pisellFloorMapLayout/index.d.ts +6 -0
- package/es/components/pisellFloorMapLayout/index.js +5 -0
- package/es/components/pisellFloorMapLayout/types.d.ts +197 -0
- package/es/components/pisellFloorMapLayout/types.js +1 -0
- package/es/components/pisellMultipleSelect/components/EditView.js +3 -3
- package/es/index.d.ts +4 -3
- package/es/index.js +1 -0
- package/lib/components/PisellLayouts/index.d.ts +9 -5
- package/lib/components/PisellLayouts/index.js +2 -0
- package/lib/components/dataSourceComponents/dataSourceSubForm/index.js +16 -3
- package/lib/components/dataSourceComponents/dataSourceSubForm/schema-full-example.json +38 -32
- package/lib/components/dataSourceComponents/fields/RecordListWrapper/WithMode.js +49 -21
- package/lib/components/dataSourceComponents/fields/Tabs/Tabs.js +1 -1
- package/lib/components/dataSourceComponents/fields/Tabs/Tabs.less +2 -1
- package/lib/components/pisellFloorMapLayout/PisellFloorMapLayout.d.ts +12 -0
- package/lib/components/pisellFloorMapLayout/PisellFloorMapLayout.js +257 -0
- package/lib/components/pisellFloorMapLayout/PisellFloorMapLayout.less +7 -0
- package/lib/components/pisellFloorMapLayout/PisellFloorMapLayout.stories.d.ts +42 -0
- package/lib/components/pisellFloorMapLayout/PisellFloorMapLayout.stories.js +755 -0
- package/lib/components/pisellFloorMapLayout/components/ItemLayer.d.ts +36 -0
- package/lib/components/pisellFloorMapLayout/components/ItemLayer.js +153 -0
- package/lib/components/pisellFloorMapLayout/components/ItemLayer.less +19 -0
- package/lib/components/pisellFloorMapLayout/components/MapLayer.d.ts +23 -0
- package/lib/components/pisellFloorMapLayout/components/MapLayer.js +103 -0
- package/lib/components/pisellFloorMapLayout/components/MapLayer.less +7 -0
- package/lib/components/pisellFloorMapLayout/components/ViewControls.d.ts +22 -0
- package/lib/components/pisellFloorMapLayout/components/ViewControls.js +89 -0
- package/lib/components/pisellFloorMapLayout/components/ViewControls.less +76 -0
- package/lib/components/pisellFloorMapLayout/components/index.d.ts +7 -0
- package/lib/components/pisellFloorMapLayout/components/index.js +35 -0
- package/lib/components/pisellFloorMapLayout/index.d.ts +6 -0
- package/lib/components/pisellFloorMapLayout/index.js +29 -0
- package/lib/components/pisellFloorMapLayout/types.d.ts +197 -0
- package/lib/components/pisellFloorMapLayout/types.js +17 -0
- package/lib/index.d.ts +4 -3
- package/lib/index.js +3 -0
- package/lowcode/data-source-form/utils.ts +3 -0
- package/lowcode/pisell-floor-map-layout/meta.ts +1511 -0
- package/package.json +4 -3
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ItemLayer - 楼层图展示层
|
|
3
|
+
* 按 items 的 (x, y) 与 cellSize 定位,用 renderItem 渲染每项内容
|
|
4
|
+
*/
|
|
5
|
+
import React from 'react';
|
|
6
|
+
import type { FloorMapItemBase, FloorMapItemUnit } from '../types';
|
|
7
|
+
import './ItemLayer.less';
|
|
8
|
+
export interface ItemLayerProps<T extends FloorMapItemBase> {
|
|
9
|
+
/** 资源列表 */
|
|
10
|
+
items: T[];
|
|
11
|
+
/** 每项渲染函数 */
|
|
12
|
+
renderItem: (item: T, index: number) => React.ReactNode;
|
|
13
|
+
/** 每项 key */
|
|
14
|
+
rowKey?: string | ((item: T, index: number) => string);
|
|
15
|
+
/** 每格像素尺寸(cell 单位时用;pixel 单位时作为缺省宽高) */
|
|
16
|
+
cellSize: number;
|
|
17
|
+
/** item 坐标与尺寸单位:cell 格子数,pixel 像素 */
|
|
18
|
+
itemUnit?: FloorMapItemUnit;
|
|
19
|
+
/** item 之间的间距(像素),仅 cell 单位时生效 */
|
|
20
|
+
itemGap?: number;
|
|
21
|
+
/** 内容区总宽度(像素),由 items 推导或外部传入 */
|
|
22
|
+
contentWidth: number;
|
|
23
|
+
/** 内容区总高度(像素) */
|
|
24
|
+
contentHeight: number;
|
|
25
|
+
/** 是否启用 hover 事件 */
|
|
26
|
+
enableHover?: boolean;
|
|
27
|
+
/** 点击回调 */
|
|
28
|
+
onItemClick?: (item: T, index: number, e: React.MouseEvent<HTMLElement>) => void;
|
|
29
|
+
/** hover 进入 */
|
|
30
|
+
onItemHover?: (item: T, index: number, e: React.MouseEvent<HTMLElement>) => void;
|
|
31
|
+
/** hover 离开 */
|
|
32
|
+
onItemLeave?: (item: T, index: number, e: React.MouseEvent<HTMLElement>) => void;
|
|
33
|
+
className?: string;
|
|
34
|
+
}
|
|
35
|
+
export declare function ItemLayer<T extends FloorMapItemBase>(props: ItemLayerProps<T>): JSX.Element;
|
|
36
|
+
export default ItemLayer;
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
|
|
2
|
+
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
|
3
|
+
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
|
|
4
|
+
function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
|
5
|
+
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : String(i); }
|
|
6
|
+
function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
|
|
7
|
+
/**
|
|
8
|
+
* ItemLayer - 楼层图展示层
|
|
9
|
+
* 按 items 的 (x, y) 与 cellSize 定位,用 renderItem 渲染每项内容
|
|
10
|
+
*/
|
|
11
|
+
import React, { useMemo } from 'react';
|
|
12
|
+
import classNames from 'classnames';
|
|
13
|
+
import "./ItemLayer.less";
|
|
14
|
+
var PREFIX = 'pisell-floor-map-layout';
|
|
15
|
+
function getItemKey(item, index, rowKey) {
|
|
16
|
+
var _rowKey;
|
|
17
|
+
if (!rowKey) return item.id;
|
|
18
|
+
if (typeof rowKey === 'string') return String((_rowKey = item[rowKey]) !== null && _rowKey !== void 0 ? _rowKey : item.id);
|
|
19
|
+
return rowKey(item, index);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* 根据形状返回 item 容器的 style(clip-path / border-radius)
|
|
24
|
+
*/
|
|
25
|
+
function getShapeStyle() {
|
|
26
|
+
var shape = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'rect';
|
|
27
|
+
switch (shape) {
|
|
28
|
+
case 'circle':
|
|
29
|
+
return {
|
|
30
|
+
borderRadius: '50%'
|
|
31
|
+
};
|
|
32
|
+
case 'triangle':
|
|
33
|
+
return {
|
|
34
|
+
clipPath: 'polygon(50% 0%, 0% 100%, 100% 100%)'
|
|
35
|
+
};
|
|
36
|
+
case 'polygon':
|
|
37
|
+
case 'custom':
|
|
38
|
+
return {};
|
|
39
|
+
default:
|
|
40
|
+
return {};
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
export function ItemLayer(props) {
|
|
44
|
+
var items = props.items,
|
|
45
|
+
renderItem = props.renderItem,
|
|
46
|
+
rowKey = props.rowKey,
|
|
47
|
+
cellSize = props.cellSize,
|
|
48
|
+
_props$itemUnit = props.itemUnit,
|
|
49
|
+
itemUnit = _props$itemUnit === void 0 ? 'cell' : _props$itemUnit,
|
|
50
|
+
_props$itemGap = props.itemGap,
|
|
51
|
+
itemGap = _props$itemGap === void 0 ? 0 : _props$itemGap,
|
|
52
|
+
contentWidth = props.contentWidth,
|
|
53
|
+
contentHeight = props.contentHeight,
|
|
54
|
+
_props$enableHover = props.enableHover,
|
|
55
|
+
enableHover = _props$enableHover === void 0 ? true : _props$enableHover,
|
|
56
|
+
onItemClick = props.onItemClick,
|
|
57
|
+
onItemHover = props.onItemHover,
|
|
58
|
+
onItemLeave = props.onItemLeave,
|
|
59
|
+
className = props.className;
|
|
60
|
+
var itemNodes = useMemo(function () {
|
|
61
|
+
var isPixel = itemUnit === 'pixel';
|
|
62
|
+
var g = itemGap;
|
|
63
|
+
return items.map(function (item, index) {
|
|
64
|
+
var left;
|
|
65
|
+
var top;
|
|
66
|
+
var width;
|
|
67
|
+
var height;
|
|
68
|
+
if (isPixel) {
|
|
69
|
+
var _item$width, _item$height;
|
|
70
|
+
width = (_item$width = item.width) !== null && _item$width !== void 0 ? _item$width : cellSize;
|
|
71
|
+
height = (_item$height = item.height) !== null && _item$height !== void 0 ? _item$height : cellSize;
|
|
72
|
+
left = item.x;
|
|
73
|
+
top = item.y;
|
|
74
|
+
} else {
|
|
75
|
+
var _item$width2, _item$height2;
|
|
76
|
+
var w = (_item$width2 = item.width) !== null && _item$width2 !== void 0 ? _item$width2 : 1;
|
|
77
|
+
var h = (_item$height2 = item.height) !== null && _item$height2 !== void 0 ? _item$height2 : 1;
|
|
78
|
+
left = g > 0 ? item.x * (cellSize + g) + g : item.x * cellSize;
|
|
79
|
+
top = g > 0 ? item.y * (cellSize + g) + g : item.y * cellSize;
|
|
80
|
+
width = g > 0 ? w * cellSize + (w - 1) * g : w * cellSize;
|
|
81
|
+
height = g > 0 ? h * cellSize + (h - 1) * g : h * cellSize;
|
|
82
|
+
}
|
|
83
|
+
var key = getItemKey(item, index, rowKey);
|
|
84
|
+
var shapeStyle = getShapeStyle(item.shape);
|
|
85
|
+
return /*#__PURE__*/React.createElement("div", {
|
|
86
|
+
key: key,
|
|
87
|
+
className: classNames("".concat(PREFIX, "-item"), _defineProperty({}, "".concat(PREFIX, "-item-hoverable"), enableHover)),
|
|
88
|
+
style: _objectSpread({
|
|
89
|
+
position: 'absolute',
|
|
90
|
+
left: left,
|
|
91
|
+
top: top,
|
|
92
|
+
width: width,
|
|
93
|
+
height: height,
|
|
94
|
+
boxSizing: 'border-box'
|
|
95
|
+
}, shapeStyle),
|
|
96
|
+
onClick: function onClick(e) {
|
|
97
|
+
return onItemClick === null || onItemClick === void 0 ? void 0 : onItemClick(item, index, e);
|
|
98
|
+
},
|
|
99
|
+
onMouseEnter: function onMouseEnter(e) {
|
|
100
|
+
return onItemHover === null || onItemHover === void 0 ? void 0 : onItemHover(item, index, e);
|
|
101
|
+
},
|
|
102
|
+
onMouseLeave: function onMouseLeave(e) {
|
|
103
|
+
return onItemLeave === null || onItemLeave === void 0 ? void 0 : onItemLeave(item, index, e);
|
|
104
|
+
}
|
|
105
|
+
}, renderItem(item, index));
|
|
106
|
+
});
|
|
107
|
+
}, [items, renderItem, rowKey, cellSize, itemUnit, itemGap, enableHover, onItemClick, onItemHover, onItemLeave]);
|
|
108
|
+
return /*#__PURE__*/React.createElement("div", {
|
|
109
|
+
className: classNames("".concat(PREFIX, "-item-layer"), className),
|
|
110
|
+
style: {
|
|
111
|
+
position: 'absolute',
|
|
112
|
+
left: 0,
|
|
113
|
+
top: 0,
|
|
114
|
+
width: contentWidth,
|
|
115
|
+
height: contentHeight,
|
|
116
|
+
minWidth: contentWidth,
|
|
117
|
+
minHeight: contentHeight
|
|
118
|
+
}
|
|
119
|
+
}, itemNodes);
|
|
120
|
+
}
|
|
121
|
+
export default ItemLayer;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
.pisell-floor-map-layout-item-layer {
|
|
2
|
+
position: absolute;
|
|
3
|
+
left: 0;
|
|
4
|
+
top: 0;
|
|
5
|
+
z-index: 1;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
.pisell-floor-map-layout-item {
|
|
9
|
+
/* 必须裁剪在格子内,避免内容溢出到格子外导致位置错乱 */
|
|
10
|
+
overflow: hidden;
|
|
11
|
+
cursor: pointer;
|
|
12
|
+
z-index: 0;
|
|
13
|
+
|
|
14
|
+
&-hoverable:hover {
|
|
15
|
+
outline: 2px solid rgba(24, 144, 255, 0.5);
|
|
16
|
+
outline-offset: -2px;
|
|
17
|
+
z-index: 1;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MapLayer - 楼层图底层
|
|
3
|
+
* 负责背景(无/纯色/图片/SVG)、网格线、padding、gap
|
|
4
|
+
*/
|
|
5
|
+
import React from 'react';
|
|
6
|
+
import type { FloorMapLayerConfig } from '../types';
|
|
7
|
+
import './MapLayer.less';
|
|
8
|
+
export interface MapLayerProps {
|
|
9
|
+
/** 底层配置 */
|
|
10
|
+
config?: FloorMapLayerConfig;
|
|
11
|
+
/** 内容区域宽度(逻辑单位或像素,用于网格线计算) */
|
|
12
|
+
contentWidth?: number;
|
|
13
|
+
/** 内容区域高度 */
|
|
14
|
+
contentHeight?: number;
|
|
15
|
+
/** 每格像素尺寸(用于网格线间距) */
|
|
16
|
+
cellSize?: number;
|
|
17
|
+
/** 子节点(展示层会叠在上方) */
|
|
18
|
+
children?: React.ReactNode;
|
|
19
|
+
/** 自定义类名 */
|
|
20
|
+
className?: string;
|
|
21
|
+
}
|
|
22
|
+
export declare function MapLayer(props: MapLayerProps): JSX.Element;
|
|
23
|
+
export default MapLayer;
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
|
|
2
|
+
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
|
3
|
+
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
|
|
4
|
+
function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
|
5
|
+
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : String(i); }
|
|
6
|
+
function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
|
|
7
|
+
/**
|
|
8
|
+
* MapLayer - 楼层图底层
|
|
9
|
+
* 负责背景(无/纯色/图片/SVG)、网格线、padding、gap
|
|
10
|
+
*/
|
|
11
|
+
import React from 'react';
|
|
12
|
+
import classNames from 'classnames';
|
|
13
|
+
import "./MapLayer.less";
|
|
14
|
+
var PREFIX = 'pisell-floor-map-layout';
|
|
15
|
+
/**
|
|
16
|
+
* 解析 padding/gap 为 CSS 值
|
|
17
|
+
*/
|
|
18
|
+
function toCssSize(v) {
|
|
19
|
+
if (v === undefined) return undefined;
|
|
20
|
+
return typeof v === 'number' ? "".concat(v, "px") : v;
|
|
21
|
+
}
|
|
22
|
+
export function MapLayer(props) {
|
|
23
|
+
var _props$config = props.config,
|
|
24
|
+
config = _props$config === void 0 ? {} : _props$config,
|
|
25
|
+
_props$contentWidth = props.contentWidth,
|
|
26
|
+
contentWidth = _props$contentWidth === void 0 ? 0 : _props$contentWidth,
|
|
27
|
+
_props$contentHeight = props.contentHeight,
|
|
28
|
+
contentHeight = _props$contentHeight === void 0 ? 0 : _props$contentHeight,
|
|
29
|
+
_props$cellSize = props.cellSize,
|
|
30
|
+
cellSize = _props$cellSize === void 0 ? 64 : _props$cellSize,
|
|
31
|
+
children = props.children,
|
|
32
|
+
className = props.className;
|
|
33
|
+
var _config$backgroundTyp = config.backgroundType,
|
|
34
|
+
backgroundType = _config$backgroundTyp === void 0 ? 'none' : _config$backgroundTyp,
|
|
35
|
+
backgroundColor = config.backgroundColor,
|
|
36
|
+
backgroundImage = config.backgroundImage,
|
|
37
|
+
backgroundSvg = config.backgroundSvg,
|
|
38
|
+
_config$showGrid = config.showGrid,
|
|
39
|
+
showGrid = _config$showGrid === void 0 ? false : _config$showGrid,
|
|
40
|
+
padding = config.padding,
|
|
41
|
+
gap = config.gap;
|
|
42
|
+
var paddingCss = toCssSize(padding);
|
|
43
|
+
var gapCss = toCssSize(gap);
|
|
44
|
+
var backgroundStyle = {};
|
|
45
|
+
if (backgroundType === 'color' && backgroundColor) {
|
|
46
|
+
backgroundStyle.backgroundColor = backgroundColor;
|
|
47
|
+
}
|
|
48
|
+
if (backgroundType === 'image' && backgroundImage) {
|
|
49
|
+
backgroundStyle.backgroundImage = "url(".concat(backgroundImage, ")");
|
|
50
|
+
backgroundStyle.backgroundSize = 'cover';
|
|
51
|
+
backgroundStyle.backgroundPosition = 'center';
|
|
52
|
+
}
|
|
53
|
+
if (backgroundType === 'svg' && backgroundSvg) {
|
|
54
|
+
var isUrl = backgroundSvg.startsWith('http') || backgroundSvg.startsWith('/');
|
|
55
|
+
backgroundStyle.backgroundImage = isUrl ? "url(".concat(backgroundSvg, ")") : "url(\"data:image/svg+xml,".concat(encodeURIComponent(backgroundSvg), "\")");
|
|
56
|
+
backgroundStyle.backgroundSize = 'cover';
|
|
57
|
+
backgroundStyle.backgroundPosition = 'center';
|
|
58
|
+
}
|
|
59
|
+
var containerStyle = {
|
|
60
|
+
padding: paddingCss,
|
|
61
|
+
gap: gapCss
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
/** 网格线:用 CSS 线性渐变模拟 */
|
|
65
|
+
var gridStyle = showGrid ? {
|
|
66
|
+
backgroundImage: "\n linear-gradient(to right, rgba(0,0,0,0.08) 1px, transparent 1px),\n linear-gradient(to bottom, rgba(0,0,0,0.08) 1px, transparent 1px)\n ",
|
|
67
|
+
backgroundSize: "".concat(cellSize, "px ").concat(cellSize, "px")
|
|
68
|
+
} : {};
|
|
69
|
+
return /*#__PURE__*/React.createElement("div", {
|
|
70
|
+
className: classNames("".concat(PREFIX, "-map-layer"), className),
|
|
71
|
+
style: _objectSpread(_objectSpread(_objectSpread({}, backgroundStyle), containerStyle), gridStyle)
|
|
72
|
+
}, children);
|
|
73
|
+
}
|
|
74
|
+
export default MapLayer;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/// <reference types="react" />
|
|
2
|
+
import type { FloorMapControlsConfig } from '../types';
|
|
3
|
+
import './ViewControls.less';
|
|
4
|
+
/** 从 react-zoom-pan-pinch 拿到的控制 API(由主组件传入) */
|
|
5
|
+
export interface ViewControlsApi {
|
|
6
|
+
zoomIn: () => void;
|
|
7
|
+
zoomOut: () => void;
|
|
8
|
+
resetTransform: () => void;
|
|
9
|
+
/** 区域定位,可能由主组件基于 items 计算后封装 */
|
|
10
|
+
fitBounds?: () => void;
|
|
11
|
+
}
|
|
12
|
+
export interface ViewControlsProps {
|
|
13
|
+
/** 控制 API */
|
|
14
|
+
api: ViewControlsApi;
|
|
15
|
+
/** 显隐配置 */
|
|
16
|
+
config?: FloorMapControlsConfig;
|
|
17
|
+
/** 当前缩放比例(1 = 100%),用于 Stepper 展示 */
|
|
18
|
+
scale?: number;
|
|
19
|
+
className?: string;
|
|
20
|
+
}
|
|
21
|
+
export declare function ViewControls(props: ViewControlsProps): JSX.Element;
|
|
22
|
+
export default ViewControls;
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ViewControls - 内置视图控制按钮:缩放(Stepper)、复位、区域定位
|
|
3
|
+
*/
|
|
4
|
+
import React from 'react';
|
|
5
|
+
import classNames from 'classnames';
|
|
6
|
+
import { MinusOutlined, PlusOutlined } from '@ant-design/icons';
|
|
7
|
+
import "./ViewControls.less";
|
|
8
|
+
var PREFIX = 'pisell-floor-map-layout';
|
|
9
|
+
|
|
10
|
+
/** 从 react-zoom-pan-pinch 拿到的控制 API(由主组件传入) */
|
|
11
|
+
|
|
12
|
+
export function ViewControls(props) {
|
|
13
|
+
var api = props.api,
|
|
14
|
+
_props$config = props.config,
|
|
15
|
+
config = _props$config === void 0 ? {} : _props$config,
|
|
16
|
+
_props$scale = props.scale,
|
|
17
|
+
scale = _props$scale === void 0 ? 1 : _props$scale,
|
|
18
|
+
className = props.className;
|
|
19
|
+
var showZoom = config.showZoom !== false;
|
|
20
|
+
var showReset = config.showReset === true;
|
|
21
|
+
var showFitBounds = config.showFitBounds === true;
|
|
22
|
+
var scalePercent = Math.round(scale * 100);
|
|
23
|
+
return /*#__PURE__*/React.createElement("div", {
|
|
24
|
+
className: classNames("".concat(PREFIX, "-view-controls"), className)
|
|
25
|
+
}, showZoom && /*#__PURE__*/React.createElement("div", {
|
|
26
|
+
className: "".concat(PREFIX, "-view-controls-zoom-stepper")
|
|
27
|
+
}, /*#__PURE__*/React.createElement("button", {
|
|
28
|
+
type: "button",
|
|
29
|
+
className: "".concat(PREFIX, "-view-controls-zoom-stepper-btn"),
|
|
30
|
+
onClick: function onClick() {
|
|
31
|
+
return api.zoomOut();
|
|
32
|
+
},
|
|
33
|
+
"aria-label": "\u7F29\u5C0F"
|
|
34
|
+
}, /*#__PURE__*/React.createElement(MinusOutlined, null)), /*#__PURE__*/React.createElement("span", {
|
|
35
|
+
className: "".concat(PREFIX, "-view-controls-zoom-stepper-value")
|
|
36
|
+
}, scalePercent, "%"), /*#__PURE__*/React.createElement("button", {
|
|
37
|
+
type: "button",
|
|
38
|
+
className: "".concat(PREFIX, "-view-controls-zoom-stepper-btn"),
|
|
39
|
+
onClick: function onClick() {
|
|
40
|
+
return api.zoomIn();
|
|
41
|
+
},
|
|
42
|
+
"aria-label": "\u653E\u5927"
|
|
43
|
+
}, /*#__PURE__*/React.createElement(PlusOutlined, null))), showReset && /*#__PURE__*/React.createElement("button", {
|
|
44
|
+
type: "button",
|
|
45
|
+
className: "".concat(PREFIX, "-view-controls-btn"),
|
|
46
|
+
onClick: function onClick() {
|
|
47
|
+
return api.resetTransform();
|
|
48
|
+
},
|
|
49
|
+
"aria-label": "\u590D\u4F4D"
|
|
50
|
+
}, "\u27F2"), showFitBounds && api.fitBounds && /*#__PURE__*/React.createElement("button", {
|
|
51
|
+
type: "button",
|
|
52
|
+
className: "".concat(PREFIX, "-view-controls-btn"),
|
|
53
|
+
onClick: function onClick() {
|
|
54
|
+
return api.fitBounds();
|
|
55
|
+
},
|
|
56
|
+
"aria-label": "\u533A\u57DF\u5B9A\u4F4D"
|
|
57
|
+
}, "\u229E"));
|
|
58
|
+
}
|
|
59
|
+
export default ViewControls;
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/* Figma 14131:6265:缩放在左下角;Figma 14004:1149 Stepper 样式 */
|
|
2
|
+
.pisell-floor-map-layout-view-controls {
|
|
3
|
+
position: absolute;
|
|
4
|
+
left: 12px;
|
|
5
|
+
bottom: 12px;
|
|
6
|
+
z-index: 10;
|
|
7
|
+
display: flex;
|
|
8
|
+
flex-direction: column;
|
|
9
|
+
gap: 6px;
|
|
10
|
+
|
|
11
|
+
/* Stepper:胶囊形 [减] 数值% [加] */
|
|
12
|
+
&-zoom-stepper {
|
|
13
|
+
display: flex;
|
|
14
|
+
align-items: center;
|
|
15
|
+
height: 56px;
|
|
16
|
+
padding: 0 4px;
|
|
17
|
+
background: #fff;
|
|
18
|
+
border: 1px solid #98a2b3;
|
|
19
|
+
border-radius: 100px;
|
|
20
|
+
box-shadow: 0 12px 16px -4px rgba(16, 24, 40, 0.08), 0 4px 6px -2px rgba(16, 24, 40, 0.03);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
&-zoom-stepper-btn {
|
|
24
|
+
width: 52px;
|
|
25
|
+
height: 52px;
|
|
26
|
+
display: flex;
|
|
27
|
+
align-items: center;
|
|
28
|
+
justify-content: center;
|
|
29
|
+
padding: 0;
|
|
30
|
+
border: none;
|
|
31
|
+
border-radius: 50%;
|
|
32
|
+
background: transparent;
|
|
33
|
+
cursor: pointer;
|
|
34
|
+
color: #101828;
|
|
35
|
+
font-size: 18px;
|
|
36
|
+
|
|
37
|
+
&:hover {
|
|
38
|
+
background: #f2f4f7;
|
|
39
|
+
color: #101828;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
&-zoom-stepper-value {
|
|
44
|
+
min-width: 56px;
|
|
45
|
+
padding: 0 8px;
|
|
46
|
+
text-align: center;
|
|
47
|
+
font-family: Inter, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
|
|
48
|
+
font-weight: 600;
|
|
49
|
+
font-size: 18px;
|
|
50
|
+
line-height: 1;
|
|
51
|
+
color: #101828;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
&-btn {
|
|
55
|
+
width: 32px;
|
|
56
|
+
height: 32px;
|
|
57
|
+
display: flex;
|
|
58
|
+
align-items: center;
|
|
59
|
+
justify-content: center;
|
|
60
|
+
padding: 0;
|
|
61
|
+
border: 1px solid rgba(0, 0, 0, 0.1);
|
|
62
|
+
border-radius: 4px;
|
|
63
|
+
background: #fff;
|
|
64
|
+
cursor: pointer;
|
|
65
|
+
font-size: 18px;
|
|
66
|
+
line-height: 1;
|
|
67
|
+
color: rgba(0, 0, 0, 0.65);
|
|
68
|
+
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
|
|
69
|
+
|
|
70
|
+
&:hover {
|
|
71
|
+
color: #1890ff;
|
|
72
|
+
border-color: #1890ff;
|
|
73
|
+
background: #e6f7ff;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PisellFloorMapLayout 组件入口
|
|
3
|
+
* 空间布局视图:在二维平面按坐标渲染资源,支持缩放/平移/复位
|
|
4
|
+
*/
|
|
5
|
+
export { PisellFloorMapLayout } from './PisellFloorMapLayout';
|
|
6
|
+
export type { PisellFloorMapLayoutProps, PisellFloorMapLayoutRef, FloorMapItemBase, FloorMapItemUnit, FloorMapLayerConfig, FloorMapZoomConfig, FloorMapPanConfig, FloorMapControlsConfig, FloorMapItemShape, FloorMapBackgroundType, FloorMapPanBoundary, FloorMapLayoutMode, FloorMapGridLayoutConfig, } from './types';
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
import type { CSSProperties, MouseEvent as ReactMouseEvent, ReactNode } from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* 资源项形状
|
|
4
|
+
* @description 展示层支持的基础形状
|
|
5
|
+
*/
|
|
6
|
+
export declare type FloorMapItemShape = 'rect' | 'circle' | 'triangle' | 'polygon' | 'custom';
|
|
7
|
+
/**
|
|
8
|
+
* 底层背景类型
|
|
9
|
+
* @description 地图底层的展示方式
|
|
10
|
+
*/
|
|
11
|
+
export declare type FloorMapBackgroundType = 'none' | 'color' | 'image' | 'svg';
|
|
12
|
+
/**
|
|
13
|
+
* 平移边界策略
|
|
14
|
+
* @description 拖拽/手势平移时的边界行为
|
|
15
|
+
*/
|
|
16
|
+
export declare type FloorMapPanBoundary = 'none' | 'clamp' | 'bounce';
|
|
17
|
+
/**
|
|
18
|
+
* 资源项坐标/尺寸单位
|
|
19
|
+
* - cell:x/y/width/height 为格子数,由 cellSize 转为像素
|
|
20
|
+
* - pixel:x/y/width/height 为像素
|
|
21
|
+
*/
|
|
22
|
+
export declare type FloorMapItemUnit = 'cell' | 'pixel';
|
|
23
|
+
/**
|
|
24
|
+
* 资源项基础类型
|
|
25
|
+
* @description 每个资源至少包含 id 与坐标 (x, y),其余由外部扩展。
|
|
26
|
+
* 单位由布局的 itemUnit 决定:cell 时为格子数,pixel 时为像素。
|
|
27
|
+
*/
|
|
28
|
+
export interface FloorMapItemBase {
|
|
29
|
+
/** 唯一标识 */
|
|
30
|
+
id: string;
|
|
31
|
+
/** 坐标 x(cell 时为格子索引,pixel 时为像素) */
|
|
32
|
+
x: number;
|
|
33
|
+
/** 坐标 y */
|
|
34
|
+
y: number;
|
|
35
|
+
/** 宽度(可选;cell 时为格子数,pixel 时为像素,缺省时 cell 为 1,pixel 为 cellSize) */
|
|
36
|
+
width?: number;
|
|
37
|
+
/** 高度(可选) */
|
|
38
|
+
height?: number;
|
|
39
|
+
/** 形状,默认 rect */
|
|
40
|
+
shape?: FloorMapItemShape;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* 底层(MapLayer)配置
|
|
44
|
+
*/
|
|
45
|
+
export interface FloorMapLayerConfig {
|
|
46
|
+
/** 背景类型 */
|
|
47
|
+
backgroundType?: FloorMapBackgroundType;
|
|
48
|
+
/** 纯色背景时的颜色(backgroundType 为 color 时有效) */
|
|
49
|
+
backgroundColor?: string;
|
|
50
|
+
/** 图片背景 URL(backgroundType 为 image 时有效) */
|
|
51
|
+
backgroundImage?: string;
|
|
52
|
+
/** SVG 背景内容或 URL(backgroundType 为 svg 时有效) */
|
|
53
|
+
backgroundSvg?: string;
|
|
54
|
+
/** 是否显示网格线,默认 false */
|
|
55
|
+
showGrid?: boolean;
|
|
56
|
+
/** 底层内边距(如 16 或 "16px") */
|
|
57
|
+
padding?: number | string;
|
|
58
|
+
/** 格子/元素间距 */
|
|
59
|
+
gap?: number | string;
|
|
60
|
+
/** 坐标吸附间隔(逻辑单位),0 表示不吸附 */
|
|
61
|
+
snapStep?: number;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* 缩放配置
|
|
65
|
+
*/
|
|
66
|
+
export interface FloorMapZoomConfig {
|
|
67
|
+
/** 默认缩放比例,如 1 表示 100% */
|
|
68
|
+
defaultScale?: number;
|
|
69
|
+
/** 最小缩放,默认 0.5 (50%) */
|
|
70
|
+
min?: number;
|
|
71
|
+
/** 最大缩放,默认 2 (200%) */
|
|
72
|
+
max?: number;
|
|
73
|
+
/** 缩放步进,默认 0.1 (10%) */
|
|
74
|
+
step?: number;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* 平移配置
|
|
78
|
+
*/
|
|
79
|
+
export interface FloorMapPanConfig {
|
|
80
|
+
/** 是否允许平移,默认 false */
|
|
81
|
+
enabled?: boolean;
|
|
82
|
+
/** 边界策略,默认 none */
|
|
83
|
+
boundary?: FloorMapPanBoundary;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* 视图控制显隐(默认仅显示放大/缩小,复位与区域定位需配置开启)
|
|
87
|
+
*/
|
|
88
|
+
export interface FloorMapControlsConfig {
|
|
89
|
+
/** 是否显示缩放按钮(+ / −),默认 true */
|
|
90
|
+
showZoom?: boolean;
|
|
91
|
+
/** 是否显示复位按钮,默认 false */
|
|
92
|
+
showReset?: boolean;
|
|
93
|
+
/** 是否显示区域定位(fitBounds)按钮,默认 false */
|
|
94
|
+
showFitBounds?: boolean;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* 布局模式(规则网格 vs 完全自由坐标)
|
|
98
|
+
*/
|
|
99
|
+
export declare type FloorMapLayoutMode = 'grid' | 'free';
|
|
100
|
+
/**
|
|
101
|
+
* 规则网格布局配置(layoutMode 为 grid 时可用)
|
|
102
|
+
*/
|
|
103
|
+
export interface FloorMapGridLayoutConfig {
|
|
104
|
+
/** 每行列数 */
|
|
105
|
+
columns?: number;
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* PisellFloorMapLayout 组件 Props
|
|
109
|
+
* @template T - 资源项类型,需继承 FloorMapItemBase 或兼容 id/x/y
|
|
110
|
+
*/
|
|
111
|
+
export interface PisellFloorMapLayoutProps<T extends FloorMapItemBase = FloorMapItemBase> {
|
|
112
|
+
/**
|
|
113
|
+
* 自定义类名
|
|
114
|
+
*/
|
|
115
|
+
className?: string;
|
|
116
|
+
/**
|
|
117
|
+
* 自定义样式(作用于最外层容器)
|
|
118
|
+
*/
|
|
119
|
+
style?: CSSProperties;
|
|
120
|
+
/**
|
|
121
|
+
* 资源列表;每项至少包含 id、x、y
|
|
122
|
+
*/
|
|
123
|
+
items: T[];
|
|
124
|
+
/**
|
|
125
|
+
* 每个资源项的渲染函数;内容与样式由调用方完全控制
|
|
126
|
+
*/
|
|
127
|
+
renderItem: (item: T, index: number) => ReactNode;
|
|
128
|
+
/**
|
|
129
|
+
* 指定每项的唯一 key,默认使用 item.id
|
|
130
|
+
*/
|
|
131
|
+
rowKey?: string | ((item: T, index: number) => string);
|
|
132
|
+
/**
|
|
133
|
+
* 底层(地图层)配置:背景、网格、padding、gap、吸附
|
|
134
|
+
*/
|
|
135
|
+
mapLayer?: FloorMapLayerConfig;
|
|
136
|
+
/**
|
|
137
|
+
* 每格像素尺寸(itemUnit 为 cell 时:逻辑 1 单位对应的像素;为 pixel 时:缺省宽高的默认像素)
|
|
138
|
+
* @default 64
|
|
139
|
+
*/
|
|
140
|
+
cellSize?: number;
|
|
141
|
+
/**
|
|
142
|
+
* item 坐标与尺寸单位:cell 格子数,pixel 像素
|
|
143
|
+
* @default 'cell'
|
|
144
|
+
*/
|
|
145
|
+
itemUnit?: FloorMapItemUnit;
|
|
146
|
+
/**
|
|
147
|
+
* 布局模式:grid 规则网格,free 完全按坐标
|
|
148
|
+
* @default 'free'
|
|
149
|
+
*/
|
|
150
|
+
layoutMode?: FloorMapLayoutMode;
|
|
151
|
+
/**
|
|
152
|
+
* 规则网格时的配置(列数等)
|
|
153
|
+
*/
|
|
154
|
+
gridLayout?: FloorMapGridLayoutConfig;
|
|
155
|
+
/**
|
|
156
|
+
* 缩放配置
|
|
157
|
+
*/
|
|
158
|
+
zoom?: FloorMapZoomConfig;
|
|
159
|
+
/**
|
|
160
|
+
* 平移配置
|
|
161
|
+
*/
|
|
162
|
+
pan?: FloorMapPanConfig;
|
|
163
|
+
/**
|
|
164
|
+
* 视图控制按钮显隐
|
|
165
|
+
*/
|
|
166
|
+
controls?: FloorMapControlsConfig;
|
|
167
|
+
/**
|
|
168
|
+
* 是否开启 hover 高亮或 hover 事件,默认 true
|
|
169
|
+
*/
|
|
170
|
+
enableHover?: boolean;
|
|
171
|
+
/**
|
|
172
|
+
* 资源项点击回调
|
|
173
|
+
*/
|
|
174
|
+
onItemClick?: (item: T, index: number, event: ReactMouseEvent<HTMLElement>) => void;
|
|
175
|
+
/**
|
|
176
|
+
* 资源项鼠标进入
|
|
177
|
+
*/
|
|
178
|
+
onItemHover?: (item: T, index: number, event: ReactMouseEvent<HTMLElement>) => void;
|
|
179
|
+
/**
|
|
180
|
+
* 资源项鼠标离开
|
|
181
|
+
*/
|
|
182
|
+
onItemLeave?: (item: T, index: number, event: ReactMouseEvent<HTMLElement>) => void;
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* PisellFloorMapLayout Ref 方法
|
|
186
|
+
* @description 供外部调用缩放、复位、区域定位等
|
|
187
|
+
*/
|
|
188
|
+
export interface PisellFloorMapLayoutRef {
|
|
189
|
+
/** 放大 */
|
|
190
|
+
zoomIn: () => void;
|
|
191
|
+
/** 缩小 */
|
|
192
|
+
zoomOut: () => void;
|
|
193
|
+
/** 复位到默认缩放与位置 */
|
|
194
|
+
reset: () => void;
|
|
195
|
+
/** 区域定位:使所有 items 落在视口内 */
|
|
196
|
+
fitBounds: () => void;
|
|
197
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|