@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.
Files changed (72) hide show
  1. package/build/lowcode/assets-daily.json +11 -11
  2. package/build/lowcode/assets-dev.json +2 -2
  3. package/build/lowcode/assets-prod.json +11 -11
  4. package/build/lowcode/index.js +1 -1
  5. package/build/lowcode/meta.js +7 -7
  6. package/build/lowcode/preview.js +9 -9
  7. package/build/lowcode/render/default/view.css +1 -1
  8. package/build/lowcode/render/default/view.js +20 -20
  9. package/build/lowcode/view.css +1 -1
  10. package/build/lowcode/view.js +24 -24
  11. package/es/components/PisellLayouts/index.d.ts +9 -5
  12. package/es/components/PisellLayouts/index.js +5 -3
  13. package/es/components/dataSourceComponents/dataSourceSubForm/index.js +18 -5
  14. package/es/components/dataSourceComponents/dataSourceSubForm/schema-full-example.json +38 -32
  15. package/es/components/dataSourceComponents/fields/RecordListWrapper/WithMode.js +58 -26
  16. package/es/components/dataSourceComponents/fields/Tabs/Tabs.js +1 -1
  17. package/es/components/dataSourceComponents/fields/Tabs/Tabs.less +2 -1
  18. package/es/components/pisellFloorMapLayout/PisellFloorMapLayout.d.ts +12 -0
  19. package/es/components/pisellFloorMapLayout/PisellFloorMapLayout.js +264 -0
  20. package/es/components/pisellFloorMapLayout/PisellFloorMapLayout.less +7 -0
  21. package/es/components/pisellFloorMapLayout/PisellFloorMapLayout.stories.d.ts +42 -0
  22. package/es/components/pisellFloorMapLayout/PisellFloorMapLayout.stories.js +1234 -0
  23. package/es/components/pisellFloorMapLayout/components/ItemLayer.d.ts +36 -0
  24. package/es/components/pisellFloorMapLayout/components/ItemLayer.js +121 -0
  25. package/es/components/pisellFloorMapLayout/components/ItemLayer.less +19 -0
  26. package/es/components/pisellFloorMapLayout/components/MapLayer.d.ts +23 -0
  27. package/es/components/pisellFloorMapLayout/components/MapLayer.js +74 -0
  28. package/es/components/pisellFloorMapLayout/components/MapLayer.less +7 -0
  29. package/es/components/pisellFloorMapLayout/components/ViewControls.d.ts +22 -0
  30. package/es/components/pisellFloorMapLayout/components/ViewControls.js +59 -0
  31. package/es/components/pisellFloorMapLayout/components/ViewControls.less +76 -0
  32. package/es/components/pisellFloorMapLayout/components/index.d.ts +7 -0
  33. package/es/components/pisellFloorMapLayout/components/index.js +6 -0
  34. package/es/components/pisellFloorMapLayout/index.d.ts +6 -0
  35. package/es/components/pisellFloorMapLayout/index.js +5 -0
  36. package/es/components/pisellFloorMapLayout/types.d.ts +197 -0
  37. package/es/components/pisellFloorMapLayout/types.js +1 -0
  38. package/es/components/pisellMultipleSelect/components/EditView.js +3 -3
  39. package/es/index.d.ts +4 -3
  40. package/es/index.js +1 -0
  41. package/lib/components/PisellLayouts/index.d.ts +9 -5
  42. package/lib/components/PisellLayouts/index.js +2 -0
  43. package/lib/components/dataSourceComponents/dataSourceSubForm/index.js +16 -3
  44. package/lib/components/dataSourceComponents/dataSourceSubForm/schema-full-example.json +38 -32
  45. package/lib/components/dataSourceComponents/fields/RecordListWrapper/WithMode.js +49 -21
  46. package/lib/components/dataSourceComponents/fields/Tabs/Tabs.js +1 -1
  47. package/lib/components/dataSourceComponents/fields/Tabs/Tabs.less +2 -1
  48. package/lib/components/pisellFloorMapLayout/PisellFloorMapLayout.d.ts +12 -0
  49. package/lib/components/pisellFloorMapLayout/PisellFloorMapLayout.js +257 -0
  50. package/lib/components/pisellFloorMapLayout/PisellFloorMapLayout.less +7 -0
  51. package/lib/components/pisellFloorMapLayout/PisellFloorMapLayout.stories.d.ts +42 -0
  52. package/lib/components/pisellFloorMapLayout/PisellFloorMapLayout.stories.js +755 -0
  53. package/lib/components/pisellFloorMapLayout/components/ItemLayer.d.ts +36 -0
  54. package/lib/components/pisellFloorMapLayout/components/ItemLayer.js +153 -0
  55. package/lib/components/pisellFloorMapLayout/components/ItemLayer.less +19 -0
  56. package/lib/components/pisellFloorMapLayout/components/MapLayer.d.ts +23 -0
  57. package/lib/components/pisellFloorMapLayout/components/MapLayer.js +103 -0
  58. package/lib/components/pisellFloorMapLayout/components/MapLayer.less +7 -0
  59. package/lib/components/pisellFloorMapLayout/components/ViewControls.d.ts +22 -0
  60. package/lib/components/pisellFloorMapLayout/components/ViewControls.js +89 -0
  61. package/lib/components/pisellFloorMapLayout/components/ViewControls.less +76 -0
  62. package/lib/components/pisellFloorMapLayout/components/index.d.ts +7 -0
  63. package/lib/components/pisellFloorMapLayout/components/index.js +35 -0
  64. package/lib/components/pisellFloorMapLayout/index.d.ts +6 -0
  65. package/lib/components/pisellFloorMapLayout/index.js +29 -0
  66. package/lib/components/pisellFloorMapLayout/types.d.ts +197 -0
  67. package/lib/components/pisellFloorMapLayout/types.js +17 -0
  68. package/lib/index.d.ts +4 -3
  69. package/lib/index.js +3 -0
  70. package/lowcode/data-source-form/utils.ts +3 -0
  71. package/lowcode/pisell-floor-map-layout/meta.ts +1511 -0
  72. package/package.json +4 -3
@@ -16,17 +16,21 @@
16
16
  declare const PisellLayouts: {
17
17
  BasicGrid: <T>(props: import("../PisellBasicGrid").PisellBasicGridProps<T>) => JSX.Element;
18
18
  ScrollView: import("react").ForwardRefExoticComponent<Omit<import("../PisellScrollView").PisellScrollViewProps, "ref"> & import("react").RefAttributes<import("../PisellScrollView").PisellScrollViewRef>>;
19
+ FloorMapLayout: <T_1 extends import("../pisellFloorMapLayout").FloorMapItemBase = import("../pisellFloorMapLayout").FloorMapItemBase>(props: import("../pisellFloorMapLayout").PisellFloorMapLayoutProps<T_1> & {
20
+ ref?: import("react").Ref<import("../pisellFloorMapLayout").PisellFloorMapLayoutRef> | undefined;
21
+ }) => import("react").ReactElement<any, string | import("react").JSXElementConstructor<any>>;
19
22
  Layout: import("../pisellLayout").CompoundedComponent;
20
23
  Content: import("react").FC<import("../pisellLayout/content").PisellContentProps>;
21
24
  Footer: import("react").FC<import("../pisellLayout/footer").PisellFooterProps>;
22
25
  Header: import("react").FC<import("../pisellLayout/header").PisellHeaderProps>;
23
26
  Sider: import("react").FC<import("../pisellLayout/sider").PisellSiderProps>;
24
- Container: <T_1 extends import("../pisellContainer").RenderType>(props: import("../pisellContainer").PisellContainerProps<T_1>) => any;
27
+ Container: <T_2 extends import("../pisellContainer").RenderType>(props: import("../pisellContainer").PisellContainerProps<T_2>) => any;
25
28
  Row: (props: import("../pisellRow").PisellRowProps) => JSX.Element;
26
29
  ViewGrid: import("react").FC<import("../pisellViewGrid").PisellViewGridProps>;
27
30
  };
28
31
  export default PisellLayouts;
29
- export type { PisellBasicGridProps, } from '../PisellBasicGrid';
30
- export type { PisellScrollViewProps, } from '../PisellScrollView';
31
- export type { PisellLayoutProps, CompoundedComponent, } from '../pisellLayout';
32
- export type { PisellRowProps, } from '../pisellRow';
32
+ export type { PisellBasicGridProps } from '../PisellBasicGrid';
33
+ export type { PisellScrollViewProps } from '../PisellScrollView';
34
+ export type { PisellFloorMapLayoutProps, PisellFloorMapLayoutRef, } from '../pisellFloorMapLayout';
35
+ export type { PisellLayoutProps, CompoundedComponent } from '../pisellLayout';
36
+ export type { PisellRowProps } from '../pisellRow';
@@ -1,14 +1,14 @@
1
1
  /**
2
2
  * PisellLayouts 命名空间
3
3
  * 布局组件集合
4
- *
4
+ *
5
5
  * @example
6
6
  * import { PisellLayouts } from '@pisell/materials';
7
- *
7
+ *
8
8
  * <PisellLayouts.BasicGrid columns={3} gap={16}>
9
9
  * {items.map(item => <Card key={item.id} {...item} />)}
10
10
  * </PisellLayouts.BasicGrid>
11
- *
11
+ *
12
12
  * <PisellLayouts.ScrollView direction="horizontal">
13
13
  * <Content />
14
14
  * </PisellLayouts.ScrollView>
@@ -16,6 +16,7 @@
16
16
 
17
17
  import PisellBasicGrid from "../PisellBasicGrid";
18
18
  import PisellScrollView from "../PisellScrollView";
19
+ import { PisellFloorMapLayout } from "../pisellFloorMapLayout";
19
20
  import PisellLayout from "../pisellLayout";
20
21
  import PisellContent from "../pisellLayout/content";
21
22
  import PisellFooter from "../pisellLayout/footer";
@@ -29,6 +30,7 @@ import PisellViewGrid from "../pisellViewGrid";
29
30
  var PisellLayouts = {
30
31
  BasicGrid: PisellBasicGrid,
31
32
  ScrollView: PisellScrollView,
33
+ FloorMapLayout: PisellFloorMapLayout,
32
34
  Layout: PisellLayout,
33
35
  Content: PisellContent,
34
36
  Footer: PisellFooter,
@@ -10,7 +10,7 @@ function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key i
10
10
  function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : String(i); }
11
11
  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); }
12
12
  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); }
13
- import React, { useEffect, useMemo } from 'react';
13
+ import React, { useEffect, useMemo, useRef, forwardRef, useImperativeHandle } from 'react';
14
14
  import { Form } from 'antd';
15
15
  import { useMemoizedFn } from 'ahooks';
16
16
  import classNames from 'classnames';
@@ -141,8 +141,9 @@ var normalizeRecordSchema = function normalizeRecordSchema(xRecordSchema) {
141
141
  *
142
142
  * 值结构: { field1: v1, field2: v2 }
143
143
  */
144
- var DataSourceSubForm = function DataSourceSubForm(props) {
145
- var _props$value = props.value,
144
+ var DataSourceSubForm = /*#__PURE__*/forwardRef(function (props, ref) {
145
+ var activeKey = props.activeKey,
146
+ _props$value = props.value,
146
147
  value = _props$value === void 0 ? {} : _props$value,
147
148
  onChange = props.onChange,
148
149
  children = props.children,
@@ -155,6 +156,7 @@ var DataSourceSubForm = function DataSourceSubForm(props) {
155
156
  var _Form$useForm = Form.useForm(),
156
157
  _Form$useForm2 = _slicedToArray(_Form$useForm, 1),
157
158
  innerForm = _Form$useForm2[0];
159
+ var activeKeyRef = useRef(activeKey);
158
160
 
159
161
  /** 确保 value 是对象 */
160
162
  var safeValue = useMemo(function () {
@@ -163,11 +165,22 @@ var DataSourceSubForm = function DataSourceSubForm(props) {
163
165
  }
164
166
  return {};
165
167
  }, [value]);
168
+ useImperativeHandle(ref, function () {
169
+ return {
170
+ getFieldsValue: function getFieldsValue() {
171
+ return innerForm.getFieldsValue();
172
+ }
173
+ };
174
+ });
166
175
 
167
176
  /** 当外部 value 变化时,同步到内部 Form */
168
177
  useEffect(function () {
178
+ if (activeKeyRef.current !== activeKey) {
179
+ activeKeyRef.current = activeKey;
180
+ innerForm.resetFields();
181
+ }
169
182
  innerForm.setFieldsValue(safeValue);
170
- }, [safeValue, innerForm]);
183
+ }, [safeValue, innerForm, activeKey]);
171
184
 
172
185
  /** 内部 Form 值变化 -> 通知外部 */
173
186
  var handleValuesChange = useMemoizedFn(function (_, allValues) {
@@ -257,5 +270,5 @@ var DataSourceSubForm = function DataSourceSubForm(props) {
257
270
  className: classNames('pisell-data-source-sub-form', className),
258
271
  style: style
259
272
  }, renderFormContent());
260
- };
273
+ });
261
274
  export default DataSourceSubForm;
@@ -319,20 +319,23 @@
319
319
  "x-component-props": {
320
320
  "direction": "horizontal"
321
321
  },
322
- "enum": [
323
- {
324
- "label": "上架",
325
- "value": "active"
326
- },
327
- {
328
- "label": "下架",
329
- "value": "inactive"
330
- },
331
- {
332
- "label": "待审核",
333
- "value": "pending"
334
- }
335
- ]
322
+ "x-data-source": {
323
+ "type": "default",
324
+ "options": [
325
+ {
326
+ "label": "上架",
327
+ "value": "active"
328
+ },
329
+ {
330
+ "label": "下架",
331
+ "value": "inactive"
332
+ },
333
+ {
334
+ "label": "待审核",
335
+ "value": "pending"
336
+ }
337
+ ]
338
+ }
336
339
  }
337
340
  },
338
341
  {
@@ -344,24 +347,27 @@
344
347
  "x-component-props": {
345
348
  "direction": "vertical"
346
349
  },
347
- "enum": [
348
- {
349
- "label": "支持退换",
350
- "value": "returnable"
351
- },
352
- {
353
- "label": "支持货到付款",
354
- "value": "cod"
355
- },
356
- {
357
- "label": "支持发票",
358
- "value": "invoice"
359
- },
360
- {
361
- "label": "支持分期",
362
- "value": "installment"
363
- }
364
- ]
350
+ "x-data-source": {
351
+ "type": "default",
352
+ "options": [
353
+ {
354
+ "label": "支持退换",
355
+ "value": "returnable"
356
+ },
357
+ {
358
+ "label": "支持货到付款",
359
+ "value": "cod"
360
+ },
361
+ {
362
+ "label": "支持发票",
363
+ "value": "invoice"
364
+ },
365
+ {
366
+ "label": "支持分期",
367
+ "value": "installment"
368
+ }
369
+ ]
370
+ }
365
371
  }
366
372
  },
367
373
  {
@@ -10,7 +10,7 @@ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len
10
10
  function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t.return && (u = t.return(), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }
11
11
  function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
12
12
  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); }
13
- import React, { useEffect, useMemo, useState } from 'react';
13
+ import React, { useEffect, useMemo, useState, useRef } from 'react';
14
14
  import { withMode } from "../../dataSourceForm/utils";
15
15
  import ReadPretty from "./ReadPretty";
16
16
  import Tabs from "../Tabs/Tabs";
@@ -39,6 +39,9 @@ var RecordListWrapperBase = function RecordListWrapperBase(props) {
39
39
  renderMode = props.renderMode,
40
40
  __designMode = props.__designMode,
41
41
  defaultValue = props.defaultValue;
42
+ var isMounted = useRef(false);
43
+ var dataSourceSubFormRef = useRef(null);
44
+
42
45
  /** value 是 Map: { optionValue: { field1: v1 } } */
43
46
  var safeValue = useMemo(function () {
44
47
  if (value && _typeof(value) === 'object' && !Array.isArray(value)) {
@@ -77,6 +80,29 @@ var RecordListWrapperBase = function RecordListWrapperBase(props) {
77
80
  }
78
81
  }, [options]);
79
82
 
83
+ /**
84
+ * 初始化所有 option 的值:
85
+ * 以字段 schema 中的 uiSchema.default 作为每个 option 的默认值模板,
86
+ * 已有值(safeValue)优先覆盖,确保已填写的数据不丢失。
87
+ * 仅执行一次(由 isMounted 守卫),避免重复触发 onChange。
88
+ */
89
+ useEffect(function () {
90
+ if (isMounted.current) {
91
+ return;
92
+ }
93
+ if ((options === null || options === void 0 ? void 0 : options.length) > 0 && dataSourceSubFormRef.current) {
94
+ var _dataSourceSubFormRef, _dataSourceSubFormRef2, _dataSourceSubFormRef3;
95
+ var defaultValues = (_dataSourceSubFormRef = (_dataSourceSubFormRef2 = (_dataSourceSubFormRef3 = dataSourceSubFormRef.current).getFieldsValue) === null || _dataSourceSubFormRef2 === void 0 ? void 0 : _dataSourceSubFormRef2.call(_dataSourceSubFormRef3)) !== null && _dataSourceSubFormRef !== void 0 ? _dataSourceSubFormRef : {};
96
+ var completeValue = options.reduce(function (acc, option) {
97
+ if (option.value === null || option.value === undefined) return acc;
98
+ acc[String(option.value)] = _objectSpread(_objectSpread({}, defaultValues), safeValue[String(option.value)] || {});
99
+ return acc;
100
+ }, {});
101
+ _onChange === null || _onChange === void 0 || _onChange(completeValue);
102
+ isMounted.current = true;
103
+ }
104
+ }, [options, safeValue]);
105
+
80
106
  // ---- 上部: 插槽区域 ----
81
107
  var renderTopSlot = function renderTopSlot() {
82
108
  var slotElement = topSlot || slot;
@@ -96,6 +122,14 @@ var RecordListWrapperBase = function RecordListWrapperBase(props) {
96
122
  label: (_o$label = o.label) !== null && _o$label !== void 0 ? _o$label : String(o.value)
97
123
  });
98
124
  });
125
+ if (!options.length) {
126
+ return /*#__PURE__*/React.createElement("div", {
127
+ style: {
128
+ color: '#999',
129
+ fontSize: 16
130
+ }
131
+ }, "\u6682\u65E0\u9009\u9879\uFF0C\u8BF7\u914D\u7F6E\u6570\u636E\u6E90\u3002");
132
+ }
99
133
  return /*#__PURE__*/React.createElement(Tabs, {
100
134
  options: tabOptions,
101
135
  value: activeKey,
@@ -108,31 +142,29 @@ var RecordListWrapperBase = function RecordListWrapperBase(props) {
108
142
 
109
143
  // ---- 下部: 委托给 DataSourceSubForm ----
110
144
  var renderBottom = function renderBottom() {
111
- if (!options.length) {
112
- return /*#__PURE__*/React.createElement("div", {
113
- style: {
114
- color: '#999',
115
- fontSize: 12
116
- }
117
- }, "No options available. Configure xDataSource options first.");
118
- }
119
- return (
120
- /*#__PURE__*/
121
- /**
122
- * key={activeKey}:Tab 切换时强制重新挂载 DataSourceSubForm,
123
- * 使其用新的 value 初始化内部 Form,避免手动 setFieldsValue。
124
- */
125
- React.createElement(DataSourceSubForm, {
126
- key: activeKey,
127
- value: safeValue[activeKey],
128
- onChange: function onChange(recordValue) {
129
- return _onChange === null || _onChange === void 0 ? void 0 : _onChange(_objectSpread(_objectSpread({}, safeValue), {}, _defineProperty({}, activeKey, recordValue)));
130
- },
131
- xRecordSchema: xRecordSchema,
132
- renderMode: renderMode,
133
- __designMode: __designMode
134
- }, children)
135
- );
145
+ return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(DataSourceSubForm, {
146
+ activeKey: activeKey,
147
+ value: safeValue[activeKey],
148
+ onChange: function onChange(recordValue) {
149
+ return _onChange === null || _onChange === void 0 ? void 0 : _onChange(_objectSpread(_objectSpread({}, safeValue || {}), {}, _defineProperty({}, activeKey, recordValue || {})));
150
+ },
151
+ xRecordSchema: xRecordSchema,
152
+ renderMode: renderMode,
153
+ __designMode: __designMode
154
+ }, children), /*#__PURE__*/React.createElement("div", {
155
+ style: {
156
+ width: '100%',
157
+ height: 0,
158
+ visibility: 'hidden',
159
+ overflow: 'hidden'
160
+ }
161
+ }, /*#__PURE__*/React.createElement(DataSourceSubForm, {
162
+ key: "record-list-wrapper-default-value-form",
163
+ ref: dataSourceSubFormRef,
164
+ xRecordSchema: xRecordSchema,
165
+ renderMode: renderMode,
166
+ __designMode: __designMode
167
+ }, children)));
136
168
  };
137
169
  return /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement("div", {
138
170
  style: {
@@ -58,7 +58,7 @@ var Tabs = function Tabs(_ref) {
58
58
  };
59
59
  var tabItems = useMemo(function () {
60
60
  return options.map(function (option) {
61
- var isActive = selectedValue === option.value;
61
+ var isActive = selectedValue != null && selectedValue !== undefined && String(selectedValue) === String(option.value);
62
62
  var isDisabled = disabled || option.disabled;
63
63
  return /*#__PURE__*/React.createElement("div", {
64
64
  key: option.value,
@@ -7,10 +7,11 @@
7
7
  border-radius: 8px;
8
8
  padding: 2px;
9
9
  gap: 2px;
10
- flex-wrap: wrap;
10
+ flex-wrap: nowrap;
11
11
  box-sizing: border-box;
12
12
  color: rgba(0, 0, 0, .65);
13
13
  background-color: rgba(0, 0, 0, .04);
14
+ overflow-x: auto;
14
15
 
15
16
  &-item {
16
17
  min-height: 36px;
@@ -0,0 +1,12 @@
1
+ /**
2
+ * PisellFloorMapLayout - 空间布局视图
3
+ * 在二维平面按坐标渲染资源,支持缩放/平移/复位,仅负责展示与交互
4
+ */
5
+ import React from 'react';
6
+ import type { FloorMapItemBase, PisellFloorMapLayoutProps, PisellFloorMapLayoutRef } from './types';
7
+ import './PisellFloorMapLayout.less';
8
+ declare const PisellFloorMapLayout: <T extends FloorMapItemBase = FloorMapItemBase>(props: PisellFloorMapLayoutProps<T> & {
9
+ ref?: React.Ref<PisellFloorMapLayoutRef> | undefined;
10
+ }) => React.ReactElement;
11
+ export { PisellFloorMapLayout };
12
+ export default PisellFloorMapLayout;
@@ -0,0 +1,264 @@
1
+ function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }
2
+ function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
3
+ function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t.return && (u = t.return(), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }
4
+ function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
5
+ function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it.return != null) it.return(); } finally { if (didErr) throw err; } } }; }
6
+ function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
7
+ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }
8
+ /**
9
+ * PisellFloorMapLayout - 空间布局视图
10
+ * 在二维平面按坐标渲染资源,支持缩放/平移/复位,仅负责展示与交互
11
+ */
12
+ import React, { useMemo, useRef, useImperativeHandle, useCallback, useState } from 'react';
13
+ import classNames from 'classnames';
14
+ import { TransformWrapper, TransformComponent } from 'react-zoom-pan-pinch';
15
+ import MapLayer from "./components/MapLayer";
16
+ import ItemLayer from "./components/ItemLayer";
17
+ import ViewControls from "./components/ViewControls";
18
+ import "./PisellFloorMapLayout.less";
19
+ var PREFIX = 'pisell-floor-map-layout';
20
+
21
+ /** 默认每格像素 */
22
+ var DEFAULT_CELL_SIZE = 64;
23
+
24
+ /** 默认 item 间距(像素) */
25
+ var DEFAULT_ITEM_GAP = 8;
26
+
27
+ /**
28
+ * 将 mapLayer.gap 解析为像素数
29
+ */
30
+ function gapToPx(gap) {
31
+ if (gap === undefined) return DEFAULT_ITEM_GAP;
32
+ if (typeof gap === 'number') return gap;
33
+ var match = String(gap).match(/^(\d+(?:\.\d+)?)\s*px?$/i);
34
+ return match ? Number(match[1]) : DEFAULT_ITEM_GAP;
35
+ }
36
+
37
+ /**
38
+ * 根据 items 计算内容区像素宽高
39
+ * - cell:按格子数 + cellSize + itemGap 计算
40
+ * - pixel:按 item 的 x/y/width/height 像素取边界
41
+ */
42
+ function getContentSize(items, cellSize, itemGap, itemUnit) {
43
+ if (!items.length) {
44
+ if (itemUnit === 'pixel') {
45
+ return {
46
+ contentWidth: cellSize * 4,
47
+ contentHeight: cellSize * 3
48
+ };
49
+ }
50
+ var _g = itemGap;
51
+ return {
52
+ contentWidth: 4 * (cellSize + _g) + _g,
53
+ contentHeight: 3 * (cellSize + _g) + _g
54
+ };
55
+ }
56
+ if (itemUnit === 'pixel') {
57
+ var maxRight = 0;
58
+ var maxBottom = 0;
59
+ var _iterator = _createForOfIteratorHelper(items),
60
+ _step;
61
+ try {
62
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
63
+ var _item$width, _item$height;
64
+ var item = _step.value;
65
+ var w = (_item$width = item.width) !== null && _item$width !== void 0 ? _item$width : cellSize;
66
+ var h = (_item$height = item.height) !== null && _item$height !== void 0 ? _item$height : cellSize;
67
+ maxRight = Math.max(maxRight, item.x + w);
68
+ maxBottom = Math.max(maxBottom, item.y + h);
69
+ }
70
+ } catch (err) {
71
+ _iterator.e(err);
72
+ } finally {
73
+ _iterator.f();
74
+ }
75
+ return {
76
+ contentWidth: maxRight,
77
+ contentHeight: maxBottom
78
+ };
79
+ }
80
+ var maxX = 0;
81
+ var maxY = 0;
82
+ var _iterator2 = _createForOfIteratorHelper(items),
83
+ _step2;
84
+ try {
85
+ for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
86
+ var _item$width2, _item$height2;
87
+ var _item = _step2.value;
88
+ var _w = (_item$width2 = _item.width) !== null && _item$width2 !== void 0 ? _item$width2 : 1;
89
+ var _h = (_item$height2 = _item.height) !== null && _item$height2 !== void 0 ? _item$height2 : 1;
90
+ maxX = Math.max(maxX, _item.x + _w);
91
+ maxY = Math.max(maxY, _item.y + _h);
92
+ }
93
+ } catch (err) {
94
+ _iterator2.e(err);
95
+ } finally {
96
+ _iterator2.f();
97
+ }
98
+ var g = itemGap;
99
+ return {
100
+ contentWidth: maxX * (cellSize + g) + g,
101
+ contentHeight: maxY * (cellSize + g) + g
102
+ };
103
+ }
104
+ function PisellFloorMapLayoutInner(props, ref) {
105
+ var className = props.className,
106
+ style = props.style,
107
+ items = props.items,
108
+ renderItem = props.renderItem,
109
+ rowKey = props.rowKey,
110
+ mapLayer = props.mapLayer,
111
+ cellSizeProp = props.cellSize,
112
+ _props$itemUnit = props.itemUnit,
113
+ itemUnit = _props$itemUnit === void 0 ? 'cell' : _props$itemUnit,
114
+ _props$layoutMode = props.layoutMode,
115
+ layoutMode = _props$layoutMode === void 0 ? 'free' : _props$layoutMode,
116
+ gridLayout = props.gridLayout,
117
+ _props$zoom = props.zoom,
118
+ zoom = _props$zoom === void 0 ? {} : _props$zoom,
119
+ _props$pan = props.pan,
120
+ pan = _props$pan === void 0 ? {} : _props$pan,
121
+ _props$controls = props.controls,
122
+ controls = _props$controls === void 0 ? {} : _props$controls,
123
+ _props$enableHover = props.enableHover,
124
+ enableHover = _props$enableHover === void 0 ? true : _props$enableHover,
125
+ onItemClick = props.onItemClick,
126
+ onItemHover = props.onItemHover,
127
+ onItemLeave = props.onItemLeave;
128
+
129
+ /** 缩放平移库暴露的 API,由 TransformWrapper 的 render 参数注入 */
130
+ var transformRef = useRef(null);
131
+ var containerRef = useRef(null);
132
+ var cellSize = cellSizeProp !== null && cellSizeProp !== void 0 ? cellSizeProp : DEFAULT_CELL_SIZE;
133
+ var itemGap = useMemo(function () {
134
+ return gapToPx(mapLayer === null || mapLayer === void 0 ? void 0 : mapLayer.gap);
135
+ }, [mapLayer === null || mapLayer === void 0 ? void 0 : mapLayer.gap]);
136
+ var _useMemo = useMemo(function () {
137
+ return getContentSize(items, cellSize, itemGap, itemUnit);
138
+ }, [items, cellSize, itemGap, itemUnit]),
139
+ contentWidth = _useMemo.contentWidth,
140
+ contentHeight = _useMemo.contentHeight;
141
+ var zoomConfig = useMemo(function () {
142
+ var _zoom$defaultScale, _zoom$min, _zoom$max, _zoom$step;
143
+ return {
144
+ initialScale: (_zoom$defaultScale = zoom.defaultScale) !== null && _zoom$defaultScale !== void 0 ? _zoom$defaultScale : 1,
145
+ minScale: (_zoom$min = zoom.min) !== null && _zoom$min !== void 0 ? _zoom$min : 0.5,
146
+ maxScale: (_zoom$max = zoom.max) !== null && _zoom$max !== void 0 ? _zoom$max : 2,
147
+ step: (_zoom$step = zoom.step) !== null && _zoom$step !== void 0 ? _zoom$step : 0.1
148
+ };
149
+ }, [zoom.defaultScale, zoom.min, zoom.max, zoom.step]);
150
+ var _useState = useState(zoomConfig.initialScale),
151
+ _useState2 = _slicedToArray(_useState, 2),
152
+ scale = _useState2[0],
153
+ setScale = _useState2[1];
154
+ var fitBounds = useCallback(function () {
155
+ var _zoom$max2;
156
+ var ctx = transformRef.current;
157
+ var container = containerRef.current;
158
+ if (!ctx || !container) return;
159
+ var wrapper = container.querySelector('.react-transform-wrapper');
160
+ if (!wrapper) return;
161
+ var wrapperRect = wrapper.getBoundingClientRect();
162
+ var scale = Math.min(wrapperRect.width / contentWidth, wrapperRect.height / contentHeight, (_zoom$max2 = zoom.max) !== null && _zoom$max2 !== void 0 ? _zoom$max2 : 2);
163
+ var x = (wrapperRect.width - contentWidth * scale) / 2;
164
+ var y = (wrapperRect.height - contentHeight * scale) / 2;
165
+ ctx.setTransform(x, y, scale);
166
+ }, [contentWidth, contentHeight, zoom.max]);
167
+ useImperativeHandle(ref, function () {
168
+ return {
169
+ zoomIn: function zoomIn() {
170
+ var _transformRef$current;
171
+ return (_transformRef$current = transformRef.current) === null || _transformRef$current === void 0 ? void 0 : _transformRef$current.zoomIn();
172
+ },
173
+ zoomOut: function zoomOut() {
174
+ var _transformRef$current2;
175
+ return (_transformRef$current2 = transformRef.current) === null || _transformRef$current2 === void 0 ? void 0 : _transformRef$current2.zoomOut();
176
+ },
177
+ reset: function reset() {
178
+ var _transformRef$current3;
179
+ return (_transformRef$current3 = transformRef.current) === null || _transformRef$current3 === void 0 ? void 0 : _transformRef$current3.resetTransform();
180
+ },
181
+ fitBounds: fitBounds
182
+ };
183
+ }, [fitBounds]);
184
+ var controlsApi = useMemo(function () {
185
+ return {
186
+ zoomIn: function zoomIn() {
187
+ var _transformRef$current4;
188
+ return (_transformRef$current4 = transformRef.current) === null || _transformRef$current4 === void 0 ? void 0 : _transformRef$current4.zoomIn();
189
+ },
190
+ zoomOut: function zoomOut() {
191
+ var _transformRef$current5;
192
+ return (_transformRef$current5 = transformRef.current) === null || _transformRef$current5 === void 0 ? void 0 : _transformRef$current5.zoomOut();
193
+ },
194
+ resetTransform: function resetTransform() {
195
+ var _transformRef$current6;
196
+ return (_transformRef$current6 = transformRef.current) === null || _transformRef$current6 === void 0 ? void 0 : _transformRef$current6.resetTransform();
197
+ },
198
+ fitBounds: fitBounds
199
+ };
200
+ }, [fitBounds]);
201
+ return /*#__PURE__*/React.createElement("div", {
202
+ ref: containerRef,
203
+ className: classNames(PREFIX, className),
204
+ style: style
205
+ }, /*#__PURE__*/React.createElement(TransformWrapper, {
206
+ initialScale: zoomConfig.initialScale,
207
+ minScale: zoomConfig.minScale,
208
+ maxScale: zoomConfig.maxScale,
209
+ step: zoomConfig.step,
210
+ panning: {
211
+ disabled: !pan.enabled
212
+ },
213
+ doubleClick: {
214
+ disabled: true
215
+ },
216
+ onTransformed: function onTransformed(_, state) {
217
+ return setScale(state.scale);
218
+ }
219
+ }, function (ctx) {
220
+ transformRef.current = ctx;
221
+ return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(TransformComponent, {
222
+ wrapperStyle: {
223
+ width: '100%',
224
+ height: '100%',
225
+ backgroundColor: '#F2F4F7',
226
+ overflow: 'visible'
227
+ },
228
+ contentStyle: {
229
+ width: contentWidth,
230
+ height: contentHeight,
231
+ minWidth: contentWidth,
232
+ minHeight: contentHeight,
233
+ position: 'relative',
234
+ overflow: 'visible',
235
+ backgroundColor: '#F2F4F7'
236
+ }
237
+ }, /*#__PURE__*/React.createElement(MapLayer, {
238
+ config: mapLayer,
239
+ contentWidth: contentWidth,
240
+ contentHeight: contentHeight,
241
+ cellSize: cellSize
242
+ }), /*#__PURE__*/React.createElement(ItemLayer, {
243
+ items: items,
244
+ renderItem: renderItem,
245
+ rowKey: rowKey,
246
+ cellSize: cellSize,
247
+ itemUnit: itemUnit,
248
+ itemGap: itemGap,
249
+ contentWidth: contentWidth,
250
+ contentHeight: contentHeight,
251
+ enableHover: enableHover,
252
+ onItemClick: onItemClick,
253
+ onItemHover: onItemHover,
254
+ onItemLeave: onItemLeave
255
+ })), /*#__PURE__*/React.createElement(ViewControls, {
256
+ api: controlsApi,
257
+ config: controls,
258
+ scale: scale
259
+ }));
260
+ }));
261
+ }
262
+ var PisellFloorMapLayout = /*#__PURE__*/React.forwardRef(PisellFloorMapLayoutInner);
263
+ export { PisellFloorMapLayout };
264
+ export default PisellFloorMapLayout;
@@ -0,0 +1,7 @@
1
+ .pisell-floor-map-layout {
2
+ position: relative;
3
+ width: 100%;
4
+ height: 400px;
5
+ overflow: hidden;
6
+ background: #fafafa;
7
+ }