plain-design 1.0.0-beta.1 → 1.0.0-beta.10

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 (59) hide show
  1. package/dist/plain-design.commonjs.min.js +11 -2
  2. package/dist/plain-design.min.css +3 -1
  3. package/dist/plain-design.min.js +11 -2
  4. package/dist/report.html +2 -2
  5. package/package.json +4 -4
  6. package/src/packages/build.ts +1 -1
  7. package/src/packages/components/Application/theme/theme.ts +1 -1
  8. package/src/packages/components/ColorPicker/sub/ColorSlider.tsx +8 -5
  9. package/src/packages/components/ColorPicker/sub/ColorSvPanel.tsx +7 -4
  10. package/src/packages/components/Dialog/index.tsx +2 -1
  11. package/src/packages/components/Dialog/useDialogMovable.tsx +7 -4
  12. package/src/packages/components/Dialog/utils/dialog.mouse.ts +4 -2
  13. package/src/packages/components/Input/useMultipleInput.tsx +5 -2
  14. package/src/packages/components/Input/useTextareaInput.tsx +10 -5
  15. package/src/packages/components/InputNumber/NumberResize.tsx +6 -2
  16. package/src/packages/components/Layout/index.tsx +31 -0
  17. package/src/packages/components/Layout/layout.scss +227 -0
  18. package/src/packages/components/Layout/layout.utils.ts +3 -0
  19. package/src/packages/components/LayoutSection/index.tsx +67 -0
  20. package/src/packages/components/LayoutSection/useLayoutSectionResizer.tsx +184 -0
  21. package/src/{pages/index/PageThemeUtils.tsx → packages/components/PageThemeUtils/index.tsx} +6 -4
  22. package/src/packages/components/Popup/index.tsx +20 -8
  23. package/src/packages/components/Rate/index.tsx +3 -1
  24. package/src/packages/components/Scroll/HorizontalScrollbar.tsx +7 -3
  25. package/src/packages/components/Scroll/VerticalScrollbar.tsx +7 -3
  26. package/src/packages/components/Slider/useSliderDotDragier.tsx +7 -4
  27. package/src/packages/components/Table/table/head/useHeadCellResize.ts +8 -3
  28. package/src/packages/components/Table/table/use/useTableDraggier.col.tsx +10 -5
  29. package/src/packages/components/Table/table/use/useTableDraggier.row.tsx +11 -6
  30. package/src/packages/components/ThemePrimaryColors/index.ts +5 -0
  31. package/src/packages/components/Tree/RenderTreeNode.tsx +2 -1
  32. package/src/packages/components/Tree/tree.scss +34 -8
  33. package/src/packages/components/TreeCore/TreeCore.type.tsx +2 -0
  34. package/src/packages/components/TreeCore/createTreeCore.tsx +5 -1
  35. package/src/packages/components/TreeCore/createTreeDraggier.tsx +9 -5
  36. package/src/packages/components/TreeCore/createTreeProps.ts +1 -0
  37. package/src/packages/components/TreeNodeWithMenu/index.tsx +53 -0
  38. package/src/packages/components/TreeNodeWithMenu/tree-node-with-menu.scss +38 -0
  39. package/src/packages/components/createProvider/index.ts +5 -0
  40. package/src/packages/components/nextPopupId/index.ts +5 -0
  41. package/src/packages/components/useImage/ImageService.tsx +7 -4
  42. package/src/packages/components/usePopupManager/index.ts +5 -0
  43. package/src/packages/components/usePopupTrigger/index.tsx +5 -0
  44. package/src/packages/components/useReferenceTrigger/index.tsx +5 -0
  45. package/src/packages/components/useTooltip/index.tsx +2 -0
  46. package/src/packages/components/useWatchAutoClear/index.ts +5 -0
  47. package/src/packages/entry.tsx +29 -0
  48. package/src/packages/utils/ClientZoom.ts +24 -2
  49. package/src/packages/utils/useMove.tsx +10 -4
  50. package/src/pages/index/App.tsx +3 -2
  51. package/src/pages/index/app.scss +5 -0
  52. package/src/pages/index/components/normal/DemoLayout.tsx +144 -0
  53. package/src/pages/index/components/normal/DemoLoading.tsx +3 -0
  54. package/src/pages/index/components/normal/DemoTree.tsx +71 -2
  55. package/src/pages/index/components/service/DemoPopupService.tsx +6 -3
  56. package/src/pages/index/home/AppHead.tsx +4 -4
  57. package/src/pages/index/home/menus.tsx +1 -0
  58. package/src/pages/index/home/plain-design.png +0 -0
  59. package/src/pages/index/main.tsx +0 -4
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "plain-design",
3
- "version": "1.0.0-beta.1",
3
+ "version": "1.0.0-beta.10",
4
4
  "description": "",
5
5
  "main": "dist/plain-design.min.js",
6
6
  "module": "dist/plain-design.commonjs.min.js",
@@ -20,8 +20,8 @@
20
20
  "exceljs": "^4.2.1",
21
21
  "file-saver": "^2.0.5",
22
22
  "plain-design-composition": "^0.0.167",
23
- "react": "^17.0.1",
24
- "react-dom": "^17.0.1"
23
+ "react": "^18.0.1",
24
+ "react-dom": "^18.0.1"
25
25
  },
26
26
  "resolutions": {
27
27
  "@types/react": "18.2.4",
@@ -32,7 +32,7 @@
32
32
  "@types/react-transition-group": "^4.4.1",
33
33
  "color": "^4.2.3",
34
34
  "dayjs": "^1.10.4",
35
- "plain-icons": "0.0.6",
35
+ "plain-icons": "0.0.7",
36
36
  "plain-utils": "^0.1.48",
37
37
  "react-flip-move": "^3.0.4",
38
38
  "react-transition-group": "^4.4.1"
@@ -3,7 +3,7 @@ import Plain from './index';
3
3
  import allIcons from 'plain-icons/dist/icons.js';
4
4
 
5
5
  // @ts-ignore
6
- Plain.Icon.PlainIcon.props.getIcon.default = (icon: string) => {
6
+ Plain.Icon.PlainIcon.use.options.props.getIcon.default = (icon: string) => {
7
7
  const iconMeta = (allIcons as any)[icon];
8
8
  if (!iconMeta) {
9
9
  throw new Error(`getIcon: can't find icon match ${icon}`);
@@ -203,7 +203,7 @@ export function createThemeConfigurationData(prefix: string | null, config?: Dee
203
203
 
204
204
  const baseColorList: Record<tGenerateBaseColorList<iThemeBaseColors>, string> = (() => {
205
205
  const colors = {} as any;
206
- Object.keys(BaseColors).forEach((colorName) => {
206
+ Object.keys(base).forEach((colorName) => {
207
207
  const baseColor = (base as any)[colorName];
208
208
  if (!baseColor) {return;}
209
209
  ThemeColorNum.forEach(i => {
@@ -5,6 +5,7 @@ import {createEffects} from "plain-utils/utils/createEffects";
5
5
  import {disabledUserSelect} from "plain-utils/dom/disabledUserSelect";
6
6
  import {enableUserSelect} from "plain-utils/dom/enableUserSelect";
7
7
  import './color-slider.scss';
8
+ import {ClientZoom} from "../../ClientZoom";
8
9
 
9
10
  export const ColorSlider = designComponent({
10
11
  name: 'color-slider',
@@ -110,12 +111,13 @@ export const ColorSlider = designComponent({
110
111
  };
111
112
  const handler = {
112
113
  onMousedown: (e: iMouseEvent) => {
113
- utils.setOffsetX(e.nativeEvent.offsetX);
114
+ const { clientX, clientY, offsetX } = ClientZoom.getClientPosition(e);
115
+ utils.setOffsetX(offsetX);
114
116
  staticState = {
115
117
  start: {
116
- x: e.clientX,
117
- y: e.clientY,
118
- offsetX: e.nativeEvent.offsetX,
118
+ x: clientX,
119
+ y: clientY,
120
+ offsetX: offsetX,
119
121
  }
120
122
  };
121
123
  draggierEffects.push(() => staticState = null);
@@ -129,7 +131,8 @@ export const ColorSlider = designComponent({
129
131
  },
130
132
  onMousemove: (e: MouseEvent) => {
131
133
  if (!staticState) {return;}
132
- const durX = e.clientX - staticState.start.x;
134
+ const { clientX } = ClientZoom.getClientPosition(e);
135
+ const durX = clientX - staticState.start.x;
133
136
  const newOffsetX = durX + staticState.start.offsetX;
134
137
  utils.setOffsetX(newOffsetX);
135
138
  },
@@ -5,6 +5,7 @@ import {disabledUserSelect} from "plain-utils/dom/disabledUserSelect";
5
5
  import {enableUserSelect} from "plain-utils/dom/enableUserSelect";
6
6
  import {getRgbColor} from "../../../utils/color.utils";
7
7
  import Color from 'color';
8
+ import {ClientZoom} from "../../..";
8
9
 
9
10
  export const ColorSvPanel = designComponent({
10
11
  name: 'color-sv-panel',
@@ -71,14 +72,16 @@ export const ColorSvPanel = designComponent({
71
72
  document.body.addEventListener('mousemove', handler.mousemove);
72
73
  document.body.addEventListener('mouseup', handler.mouseup);
73
74
  disabledUserSelect();
74
- methods.updatePosition(e.nativeEvent.offsetX, e.nativeEvent.offsetY);
75
- state.startX = e.clientX;
76
- state.startY = e.clientY;
75
+ const { offsetX, offsetY, clientX, clientY } = ClientZoom.getClientPosition(e);
76
+ methods.updatePosition(offsetX, offsetY);
77
+ state.startX = clientX;
78
+ state.startY = clientY;
77
79
  state.tempSaturation = state.saturation as number;
78
80
  state.tempValue = state.val as number;
79
81
  },
80
82
  mousemove: (e: MouseEvent) => {
81
- methods.updatePosition(e.clientX - state.startX, e.clientY - state.startY, false);
83
+ const { clientX, clientY } = ClientZoom.getClientPosition(e);
84
+ methods.updatePosition(clientX - state.startX, clientY - state.startY, false);
82
85
  },
83
86
  mouseup: () => {
84
87
  document.body.removeEventListener('mousemove', handler.mousemove);
@@ -42,6 +42,7 @@ export const Dialog = designComponent({
42
42
 
43
43
  noContentPadding: { type: Boolean }, // 去掉内容默认内边距
44
44
  noHead: { type: Boolean, }, // 去掉默认弹框标题
45
+ noFoot: { type: Boolean }, // 去掉底部内容
45
46
  noMask: { type: Boolean }, // 去掉遮罩
46
47
  noClose: { type: Boolean }, // 去掉关闭按钮
47
48
 
@@ -417,7 +418,7 @@ export const Dialog = designComponent({
417
418
  <div className="dialog-body">
418
419
  {slots.default()}
419
420
  </div>
420
- {(!!props.confirmButton || !!props.cancelButton || slots.foot.isExist()) && (
421
+ {!props.noFoot && (!!props.confirmButton || !!props.cancelButton || slots.foot.isExist()) && (
421
422
  <div className="dialog-foot">
422
423
  {slots.foot()}
423
424
  {(() => {
@@ -1,4 +1,5 @@
1
1
  import {watchEffect} from "plain-design-composition";
2
+ import {ClientZoom} from "../..";
2
3
 
3
4
  export function useDialogMovable({ refs, movable }: { refs: { head: HTMLElement | undefined | null, content: HTMLElement | undefined | null }, movable: { value: boolean } }) {
4
5
 
@@ -20,9 +21,10 @@ export function useDialogMovable({ refs, movable }: { refs: { head: HTMLElement
20
21
 
21
22
  const handler = {
22
23
  mousedown: (e: MouseEvent) => {
24
+ const { clientX, clientY } = ClientZoom.getClientPosition(e);
23
25
  staticState.start = {
24
- x: e.clientX,
25
- y: e.clientY,
26
+ x: clientX,
27
+ y: clientY,
26
28
  left: staticState.move.left,
27
29
  top: staticState.move.top,
28
30
  };
@@ -30,8 +32,9 @@ export function useDialogMovable({ refs, movable }: { refs: { head: HTMLElement
30
32
  document.documentElement.addEventListener('mouseup', handler.mouseup);
31
33
  },
32
34
  mousemove: (e: MouseEvent) => {
33
- staticState.move.x = e.clientX;
34
- staticState.move.y = e.clientY;
35
+ const { clientX, clientY } = ClientZoom.getClientPosition(e);
36
+ staticState.move.x = clientX;
37
+ staticState.move.y = clientY;
35
38
 
36
39
  const durX = staticState.move.x - staticState.start.x;
37
40
  const durY = staticState.move.y - staticState.start.y;
@@ -1,12 +1,14 @@
1
1
  import {isSSR} from "../../../utils/isSSR";
2
+ import {ClientZoom} from "../../..";
2
3
 
3
4
  export const DialogMouse = (() => {
4
5
  const state = { x: 0, y: 0 };
5
6
 
6
7
  if (!isSSR()) {
7
8
  document.documentElement.addEventListener('mousedown', e => {
8
- state.x = e.clientX;
9
- state.y = e.clientY;
9
+ const { clientX, clientY } = ClientZoom.getClientPosition(e);
10
+ state.x = clientX;
11
+ state.y = clientY;
10
12
  }, true);
11
13
  }
12
14
 
@@ -6,6 +6,7 @@ import {getKey, KEY} from "../KeyboardService";
6
6
  import {delay} from "plain-utils/utils/delay";
7
7
  import {createEffectiveHandler} from "../../utils/createEffectiveHandler";
8
8
  import {createEffects} from "plain-utils/utils/createEffects";
9
+ import {ClientZoom} from "../..";
9
10
 
10
11
  /**
11
12
  * 渲染多值输入框
@@ -140,9 +141,10 @@ function useDragHorizontalScroll(getEl: () => HTMLElement | null | undefined) {
140
141
 
141
142
  const handler = {
142
143
  mousedown: (e: MouseEvent) => {
144
+ const { clientX } = ClientZoom.getClientPosition(e);
143
145
  staticState.isDragging = false;
144
146
  staticState.start = {
145
- x: e.clientX,
147
+ x: clientX,
146
148
  left: staticState.el!.scrollLeft,
147
149
  width: staticState.el!.scrollWidth,
148
150
  };
@@ -150,7 +152,8 @@ function useDragHorizontalScroll(getEl: () => HTMLElement | null | undefined) {
150
152
  document.documentElement.addEventListener('mouseup', handler.mouseup, true);
151
153
  },
152
154
  mousemove: (e: MouseEvent) => {
153
- staticState.move.x = e.clientX;
155
+ const { clientX } = ClientZoom.getClientPosition(e);
156
+ staticState.move.x = clientX;
154
157
  const durX = staticState.move.x - staticState.start.x;
155
158
  if (!staticState.isDragging) {
156
159
  if (Math.abs(durX) > 5) {
@@ -1,7 +1,10 @@
1
1
  import {iInputCompositionData} from "./input.utils";
2
- import {iKeyboardEvent, reactive, useClasses, useStyles} from "plain-design-composition";
2
+ import {fixInputCursor, iKeyboardEvent, reactive, useClasses, useStyles} from "plain-design-composition";
3
3
  import {unit} from "plain-utils/string/unit";
4
4
  import {createEffects} from "plain-utils/utils/createEffects";
5
+ import {ClientZoom} from "../ClientZoom";
6
+
7
+ const _Textarea = fixInputCursor('textarea')
5
8
 
6
9
  export function useTextareaInput(data: iInputCompositionData) {
7
10
 
@@ -61,7 +64,7 @@ export function useTextareaInput(data: iInputCompositionData) {
61
64
  ))}
62
65
  {!model.value && <>&nbsp;</>}
63
66
  </span>
64
- <textarea
67
+ <_Textarea
65
68
  ref={handler.onRef}
66
69
  value={model.value}
67
70
  onInput={handler.onInput}
@@ -95,8 +98,10 @@ function useTextareaResize({ hooks, onResize }: iInputCompositionData & { onResi
95
98
  const handler = {
96
99
  textarea: null as null | HTMLInputElement,
97
100
  mousedown: (e: MouseEvent) => {
98
- const { offsetX, offsetY, clientY, target: { offsetWidth, offsetHeight } } = e as any;
99
- if (!(offsetWidth - offsetX < 12 && offsetHeight - offsetY < 12)) {
101
+ const { offsetX, offsetY, clientY } = ClientZoom.getClientPosition(e);
102
+ let { offsetWidth, offsetHeight } = e.target as any;
103
+ const dragSize = 12
104
+ if (!(offsetWidth - offsetX < dragSize && offsetHeight - offsetY < dragSize)) {
100
105
  return;
101
106
  }
102
107
  staticState.isDragging = false;
@@ -108,7 +113,7 @@ function useTextareaResize({ hooks, onResize }: iInputCompositionData & { onResi
108
113
  document.documentElement.addEventListener('mouseup', handler.mouseup);
109
114
  },
110
115
  mousemove: (e: MouseEvent) => {
111
- const { clientY } = e;
116
+ const { clientY } = ClientZoom.getClientPosition(e);
112
117
  staticState.move = { y: clientY };
113
118
  const durY = staticState.move.y - staticState.start.y;
114
119
  if (!staticState.isDragging) {
@@ -2,6 +2,7 @@ import {designComponent, getComponentCls, iHTMLDivElement, iMouseEvent, useRefs}
2
2
  import {Icon} from "../Icon";
3
3
  import {createEffects} from "plain-utils/utils/createEffects";
4
4
  import {addClass} from "plain-utils/dom/addClass";
5
+ import {ClientZoom} from "../ClientZoom";
5
6
 
6
7
  export const NumberResize = designComponent({
7
8
  name: "number-resize",
@@ -35,6 +36,8 @@ export const NumberResize = designComponent({
35
36
 
36
37
  const handler = {
37
38
  onMousedown: (e: iMouseEvent) => {
39
+ const { clientY } = ClientZoom.getClientPosition(e);
40
+
38
41
  event.emit.onMouseDown(e);
39
42
  const el = refs.el!.cloneNode(true) as HTMLDivElement;
40
43
  const { top, left, height, width } = refs.el!.getBoundingClientRect();
@@ -50,7 +53,7 @@ export const NumberResize = designComponent({
50
53
  addClass(el, 'number-resize-dragging');
51
54
 
52
55
  staticState = {
53
- startY: e.clientY,
56
+ startY: clientY,
54
57
  startValue: props.value == null ? 0 : props.value,
55
58
  el,
56
59
  startTop: top,
@@ -71,7 +74,8 @@ export const NumberResize = designComponent({
71
74
  },
72
75
  onMousemove: (e: MouseEvent) => {
73
76
  if (!staticState) {return;}
74
- const durY = (e.clientY - staticState.startY);
77
+ const { clientY } = ClientZoom.getClientPosition(e);
78
+ const durY = (clientY - staticState.startY);
75
79
  const elMoveTop = staticState.startTop + durY;
76
80
  staticState.el.style.transform = `translate3d(${staticState.startLeft}px,${elMoveTop}px,0)`;
77
81
  const newValue = Math.ceil(staticState.startValue + (durY * -1) / unit) * props.step;
@@ -0,0 +1,31 @@
1
+ import {designComponent, getComponentCls, useClassCache} from "plain-design-composition";
2
+ import './layout.scss';
3
+
4
+ export const Layout = designComponent({
5
+ name: 'layout',
6
+ props: {
7
+ vertical: { type: Boolean }
8
+ },
9
+ provideRefer: true,
10
+ slots: ['default'],
11
+ setup({ props, slots }) {
12
+
13
+ const classes = useClassCache(() => [
14
+ getComponentCls('layout'),
15
+ {
16
+ 'layout-vertical': props.vertical,
17
+ }
18
+ ]);
19
+
20
+ return {
21
+ refer: { props },
22
+ render: () => (
23
+ <div className={classes.value}>
24
+ {slots.default()}
25
+ </div>
26
+ )
27
+ };
28
+ },
29
+ });
30
+
31
+ export default Layout;
@@ -0,0 +1,227 @@
1
+ $resize-width: 12px;
2
+
3
+ @include comp(layout) {
4
+ display: flex;
5
+ align-items: stretch;
6
+ justify-content: space-between;
7
+
8
+ &.layout-vertical {
9
+ flex-direction: column;
10
+ }
11
+
12
+ & > .#{componentName(layout-section)} {
13
+ &.layout-section-position-center {
14
+ flex: 1;
15
+ position: relative;
16
+ z-index: 1;
17
+ }
18
+
19
+ &.layout-section-position-top, &.layout-section-position-bottom, &.layout-section-position-left, &.layout-section-position-right {
20
+ position: relative;
21
+ flex-shrink: 0;
22
+ flex-grow: 0;
23
+ z-index: 2;
24
+
25
+ & > .layout-section-inner {
26
+ overflow: hidden;
27
+ }
28
+
29
+ &.layout-section-fixed {
30
+ & > .layout-section-inner {
31
+ position: absolute;
32
+ top: 0;
33
+ left: 0;
34
+ right: 0;
35
+ bottom: 0;
36
+ }
37
+ }
38
+
39
+
40
+ & > .layout-section-separator {
41
+ user-select: none;
42
+ }
43
+
44
+ & > .layout-section-collapse-btn {
45
+ opacity: 0;
46
+ transition: all ease 0.3s;
47
+ cursor: pointer;
48
+ }
49
+
50
+ &:hover {
51
+ & > .layout-section-collapse-btn {
52
+ opacity: 1;
53
+ }
54
+ }
55
+ }
56
+
57
+ /*---------------------------------------horizontal-------------------------------------------*/
58
+
59
+ &.layout-section-position-left, &.layout-section-position-right {
60
+
61
+ & > .layout-section-separator {
62
+ cursor: col-resize;
63
+ }
64
+
65
+ &.layout-section-collapse {
66
+ width: 0 !important;
67
+
68
+ & > .layout-section-collapse-btn {
69
+ opacity: 1;
70
+ }
71
+
72
+ &.layout-section-position-left {
73
+ & > .layout-section-collapse-btn {
74
+ border-top-left-radius: 0;
75
+ border-bottom-left-radius: 0;
76
+ right: -$resize-width;
77
+ }
78
+ }
79
+
80
+ &.layout-section-position-right {
81
+ & > .layout-section-collapse-btn {
82
+ border-top-right-radius: 0;
83
+ border-bottom-right-radius: 0;
84
+ left: -$resize-width;
85
+ }
86
+ }
87
+ }
88
+ }
89
+
90
+ &.layout-section-position-left {
91
+ & > .layout-section-separator {
92
+ position: absolute;
93
+ right: 0;
94
+ width: 4px;
95
+ top: 0;
96
+ bottom: 0;
97
+ border-right: solid 1px plv(border-color);
98
+ }
99
+
100
+ & > .layout-section-collapse-btn {
101
+ position: absolute;
102
+ right: calc(#{$resize-width} / 2 * -1);
103
+ top: calc(50% - #{$resize-width} * 3 / 2);
104
+ font-size: $resize-width;
105
+ height: calc(#{$resize-width} * 3);
106
+ width: $resize-width;
107
+ display: flex;
108
+ align-items: center;
109
+ justify-content: center;
110
+ background-color: plv(background-color);
111
+ border-radius: 100px;
112
+ box-shadow: 0 2px 5px plv(secondary-4);
113
+ }
114
+ }
115
+
116
+ &.layout-section-position-right {
117
+ & > .layout-section-separator {
118
+ position: absolute;
119
+ left: 0;
120
+ width: 4px;
121
+ top: 0;
122
+ bottom: 0;
123
+ border-left: solid 1px plv(border-color);
124
+ }
125
+
126
+ & > .layout-section-collapse-btn {
127
+ position: absolute;
128
+ left: calc(#{$resize-width} / 2 * -1);
129
+ top: calc(50% - #{$resize-width} * 3 / 2);
130
+ font-size: $resize-width;
131
+ height: calc(#{$resize-width} * 3);
132
+ width: $resize-width;
133
+ display: flex;
134
+ align-items: center;
135
+ justify-content: center;
136
+ background-color: plv(background-color);
137
+ border-radius: 100px;
138
+ box-shadow: 0 2px 5px plv(secondary-4);
139
+ }
140
+ }
141
+
142
+ /*---------------------------------------vertical-------------------------------------------*/
143
+
144
+ &.layout-section-position-top, &.layout-section-position-bottom {
145
+
146
+ & > .layout-section-separator {
147
+ cursor: row-resize;
148
+ }
149
+
150
+ &.layout-section-collapse {
151
+ height: 0 !important;
152
+
153
+ & > .layout-section-collapse-btn {
154
+ opacity: 1;
155
+ }
156
+
157
+ &.layout-section-position-top {
158
+ & > .layout-section-collapse-btn {
159
+ border-top-left-radius: 0;
160
+ border-top-right-radius: 0;
161
+ bottom: -$resize-width;
162
+ }
163
+ }
164
+
165
+ &.layout-section-position-bottom {
166
+ & > .layout-section-collapse-btn {
167
+ border-bottom-left-radius: 0;
168
+ border-bottom-right-radius: 0;
169
+ top: -$resize-width;
170
+ }
171
+ }
172
+ }
173
+ }
174
+
175
+ &.layout-section-position-top {
176
+ & > .layout-section-separator {
177
+ position: absolute;
178
+ bottom: 0;
179
+ height: 4px;
180
+ left: 0;
181
+ right: 0;
182
+ border-bottom: solid 1px plv(border-color);
183
+ }
184
+
185
+ & > .layout-section-collapse-btn {
186
+ position: absolute;
187
+ bottom: calc(#{$resize-width} / 2 * -1);
188
+ left: calc(50% - #{$resize-width} * 3 / 2);
189
+ font-size: $resize-width;
190
+ width: calc(#{$resize-width} * 3);
191
+ height: $resize-width;
192
+ display: flex;
193
+ align-items: center;
194
+ justify-content: center;
195
+ background-color: plv(background-color);
196
+ border-radius: 100px;
197
+ box-shadow: 0 2px 5px plv(secondary-4);
198
+ }
199
+ }
200
+
201
+ &.layout-section-position-bottom {
202
+ & > .layout-section-separator {
203
+ position: absolute;
204
+ top: 0;
205
+ height: 4px;
206
+ left: 0;
207
+ right: 0;
208
+ border-top: solid 1px plv(border-color);
209
+ }
210
+
211
+ & > .layout-section-collapse-btn {
212
+ position: absolute;
213
+ top: calc(#{$resize-width} / 2 * -1);
214
+ left: calc(50% - #{$resize-width} * 3 / 2);
215
+ font-size: $resize-width;
216
+ width: calc(#{$resize-width} * 3);
217
+ height: $resize-width;
218
+ display: flex;
219
+ align-items: center;
220
+ justify-content: center;
221
+ background-color: plv(background-color);
222
+ border-radius: 100px;
223
+ box-shadow: 0 2px 5px plv(secondary-4);
224
+ }
225
+ }
226
+ }
227
+ }
@@ -0,0 +1,3 @@
1
+ import {createEnum} from "plain-utils/utils/createEnum";
2
+
3
+ export const eLayoutSectionPosition = createEnum(['top', 'left', 'right', 'bottom', 'center'] as const);
@@ -0,0 +1,67 @@
1
+ import {designComponent, getComponentCls, iHTMLDivElement, onMounted, PropType, useClassCache, useModel, useRefs, useStyleCache} from "plain-design-composition";
2
+ import {unit} from "plain-utils/string/unit";
3
+ import Layout from "../Layout";
4
+ import {eLayoutSectionPosition} from "../Layout/layout.utils";
5
+ import {useLayoutSectionResizer} from "./useLayoutSectionResizer";
6
+
7
+ export const LayoutSection = designComponent({
8
+ name: 'layout-section',
9
+ props: {
10
+ position: { type: String as PropType<typeof eLayoutSectionPosition.TYPE>, default: eLayoutSectionPosition.center },
11
+ modelValue: { type: Number },
12
+ collapse: { type: Boolean }
13
+ },
14
+ emits: {
15
+ onUpdateModelValue: (val?: number) => true,
16
+ onUpdateCollapse: (val?: boolean) => true,
17
+ },
18
+ slots: ['default'],
19
+ setup({ props, slots, event }) {
20
+
21
+ const layout = Layout.use.inject();
22
+
23
+ const { refs, onRef } = useRefs({ el: iHTMLDivElement });
24
+
25
+ const model = useModel(() => props.modelValue, event.emit.onUpdateModelValue);
26
+
27
+ const collapseModel = useModel(() => props.collapse, event.emit.onUpdateCollapse);
28
+
29
+ const classes = useClassCache(() => [
30
+ getComponentCls('layout-section'),
31
+ `layout-section-position-${props.position}`,
32
+ {
33
+ 'layout-section-fixed': !!model.value,
34
+ 'layout-section-collapse': collapseModel.value,
35
+ }
36
+ ]);
37
+
38
+ const styles = useStyleCache(style => {
39
+ if (!!model.value) {
40
+ if (layout.props.vertical) {
41
+ style.height = unit(model.value);
42
+ } else {
43
+ style.width = unit(model.value);
44
+ }
45
+ }
46
+ });
47
+
48
+ const resizer = useLayoutSectionResizer({ props, model, collapseModel });
49
+
50
+ onMounted(() => {
51
+ if (!props.modelValue && props.position !== eLayoutSectionPosition.center) {
52
+ model.value = (layout.props.vertical ? refs.el!.offsetHeight : refs.el!.offsetWidth) + 1;
53
+ }
54
+ });
55
+
56
+ return () => (
57
+ <div className={classes.value} ref={onRef.el} style={styles.value}>
58
+ <div className="layout-section-inner">
59
+ {slots.default()}
60
+ </div>
61
+ {resizer.render()}
62
+ </div>
63
+ );
64
+ },
65
+ });
66
+
67
+ export default LayoutSection;