namirasoft-site-react 1.4.556 → 1.4.558

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.
@@ -1,15 +1,29 @@
1
- import { Component, ReactNode } from "react";
1
+ import { Component, MouseEvent as ReactMouseEvent, ReactNode } from "react";
2
2
  export interface NSSplitterProps {
3
3
  master_content?: ReactNode;
4
4
  detail_content?: ReactNode;
5
+ storage_key?: string;
5
6
  }
6
7
  export declare class NSSplitter extends Component<NSSplitterProps> {
7
8
  private SplitterRef;
8
9
  private MasterPaneRef;
9
- private DetailPaneRef;
10
+ private GutterRef;
10
11
  private AnimationFrame;
12
+ private DragOffset;
13
+ private HasUserResized;
14
+ private MediaQuery;
15
+ private Storage;
11
16
  constructor(props: NSSplitterProps);
12
- handleMouseDown(): void;
17
+ componentDidMount(): void;
18
+ componentDidUpdate(prevProps: NSSplitterProps): void;
19
+ componentWillUnmount(): void;
20
+ handleViewportChange(): void;
21
+ updateLayout(force: boolean): void;
22
+ applyHeight(height: number): void;
23
+ loadStoredHeight(): number | null;
24
+ saveStoredHeight(height: number): void;
25
+ adjustMasterToViewport(): void;
26
+ handleMouseDown(event: ReactMouseEvent): void;
13
27
  handleMouseUp(): void;
14
28
  handleMouseMove(event: MouseEvent): void;
15
29
  render(): import("react").JSX.Element;
@@ -1,48 +1,139 @@
1
1
  import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { Component, createRef } from "react";
3
+ import { IStorageLocal } from "namirasoft-core";
3
4
  import Styles from "./NSSplitter.module.css";
5
+ const MIN_MASTER_HEIGHT = 238;
4
6
  export class NSSplitter extends Component {
5
7
  constructor(props) {
6
8
  super(props);
7
9
  this.SplitterRef = createRef();
8
10
  this.MasterPaneRef = createRef();
9
- this.DetailPaneRef = createRef();
11
+ this.GutterRef = createRef();
10
12
  this.AnimationFrame = null;
13
+ this.DragOffset = 0;
14
+ this.HasUserResized = false;
15
+ this.MediaQuery = null;
16
+ this.Storage = new IStorageLocal();
11
17
  this.handleMouseDown = this.handleMouseDown.bind(this);
12
18
  this.handleMouseUp = this.handleMouseUp.bind(this);
13
19
  this.handleMouseMove = this.handleMouseMove.bind(this);
20
+ this.handleViewportChange = this.handleViewportChange.bind(this);
14
21
  }
15
- handleMouseDown() {
22
+ componentDidMount() {
23
+ this.MediaQuery = window.matchMedia("(min-width: 992px)");
24
+ this.MediaQuery.addEventListener("change", this.handleViewportChange);
25
+ window.addEventListener("resize", this.handleViewportChange);
26
+ if (this.loadStoredHeight() !== null)
27
+ this.HasUserResized = true;
28
+ this.updateLayout(true);
29
+ }
30
+ componentDidUpdate(prevProps) {
31
+ let had_detail = !!prevProps.detail_content;
32
+ let has_detail = !!this.props.detail_content;
33
+ if (had_detail !== has_detail) {
34
+ this.HasUserResized = false;
35
+ this.updateLayout(true);
36
+ }
37
+ }
38
+ componentWillUnmount() {
39
+ var _a;
40
+ (_a = this.MediaQuery) === null || _a === void 0 ? void 0 : _a.removeEventListener("change", this.handleViewportChange);
41
+ window.removeEventListener("resize", this.handleViewportChange);
42
+ window.removeEventListener("mousemove", this.handleMouseMove);
43
+ window.removeEventListener("mouseup", this.handleMouseUp);
44
+ if (this.AnimationFrame)
45
+ cancelAnimationFrame(this.AnimationFrame);
46
+ }
47
+ handleViewportChange() {
48
+ this.updateLayout(false);
49
+ }
50
+ updateLayout(force) {
51
+ let master_el = this.MasterPaneRef.current;
52
+ if (!master_el || !this.MediaQuery)
53
+ return;
54
+ if (this.MediaQuery.matches && this.props.detail_content) {
55
+ let stored = this.loadStoredHeight();
56
+ if (stored !== null)
57
+ this.applyHeight(Math.max(MIN_MASTER_HEIGHT, stored));
58
+ else if (force || !this.HasUserResized)
59
+ this.adjustMasterToViewport();
60
+ }
61
+ else {
62
+ master_el.style.height = "";
63
+ master_el.style.minHeight = "";
64
+ }
65
+ }
66
+ applyHeight(height) {
67
+ let master_el = this.MasterPaneRef.current;
68
+ if (master_el) {
69
+ master_el.style.height = height + "px";
70
+ master_el.style.minHeight = height + "px";
71
+ }
72
+ }
73
+ loadStoredHeight() {
74
+ let key = this.props.storage_key;
75
+ if (!key)
76
+ return null;
77
+ let raw = this.Storage.get(key, "");
78
+ if (!raw)
79
+ return null;
80
+ let value = parseInt(raw, 10);
81
+ if (isNaN(value))
82
+ return null;
83
+ return value;
84
+ }
85
+ saveStoredHeight(height) {
86
+ let key = this.props.storage_key;
87
+ if (!key)
88
+ return;
89
+ this.Storage.set(key, String(height));
90
+ }
91
+ adjustMasterToViewport() {
16
92
  var _a, _b;
17
- (_a = this.SplitterRef.current) === null || _a === void 0 ? void 0 : _a.addEventListener("mousemove", this.handleMouseMove);
18
- (_b = this.SplitterRef.current) === null || _b === void 0 ? void 0 : _b.classList.add(Styles.ns_splitter_resizing);
93
+ let master_el = this.MasterPaneRef.current;
94
+ if (!master_el)
95
+ return;
96
+ let master_top = master_el.getBoundingClientRect().top;
97
+ let gutter_height = (_b = (_a = this.GutterRef.current) === null || _a === void 0 ? void 0 : _a.offsetHeight) !== null && _b !== void 0 ? _b : 0;
98
+ let height = Math.max(MIN_MASTER_HEIGHT, window.innerHeight - master_top - gutter_height);
99
+ this.applyHeight(height);
100
+ }
101
+ handleMouseDown(event) {
102
+ var _a;
103
+ let master_el = this.MasterPaneRef.current;
104
+ if (!master_el)
105
+ return;
106
+ this.DragOffset = event.clientY - master_el.getBoundingClientRect().bottom;
107
+ window.addEventListener("mousemove", this.handleMouseMove);
19
108
  window.addEventListener("mouseup", this.handleMouseUp);
109
+ (_a = this.SplitterRef.current) === null || _a === void 0 ? void 0 : _a.classList.add(Styles.ns_splitter_resizing);
20
110
  }
21
111
  handleMouseUp() {
22
- var _a, _b;
23
- (_a = this.SplitterRef.current) === null || _a === void 0 ? void 0 : _a.removeEventListener("mousemove", this.handleMouseMove);
24
- (_b = this.SplitterRef.current) === null || _b === void 0 ? void 0 : _b.classList.remove(Styles.ns_splitter_resizing);
112
+ var _a;
113
+ window.removeEventListener("mousemove", this.handleMouseMove);
25
114
  window.removeEventListener("mouseup", this.handleMouseUp);
115
+ (_a = this.SplitterRef.current) === null || _a === void 0 ? void 0 : _a.classList.remove(Styles.ns_splitter_resizing);
116
+ let master_el = this.MasterPaneRef.current;
117
+ if (master_el)
118
+ this.saveStoredHeight(master_el.offsetHeight);
26
119
  }
27
120
  handleMouseMove(event) {
28
121
  if (this.AnimationFrame)
29
122
  return;
30
123
  this.AnimationFrame = requestAnimationFrame(() => {
31
124
  this.AnimationFrame = null;
32
- let splitter_el = this.SplitterRef.current;
33
125
  let master_el = this.MasterPaneRef.current;
34
- if (!splitter_el || !master_el)
126
+ if (!master_el)
35
127
  return;
36
- let delta = event.clientY - master_el.getBoundingClientRect().bottom;
37
- let master_el_height = master_el.clientHeight + delta - 12;
38
- master_el_height = +Math.max(238, Math.min(master_el_height, 538)).toFixed(0);
39
- master_el.style.height = master_el_height + "px";
40
- master_el.style.minHeight = master_el_height + "px";
128
+ let master_top = master_el.getBoundingClientRect().top;
129
+ let height = Math.max(MIN_MASTER_HEIGHT, event.clientY - this.DragOffset - master_top);
130
+ this.applyHeight(height);
131
+ this.HasUserResized = true;
41
132
  });
42
133
  }
43
134
  render() {
44
135
  return (_jsxs("section", { ref: this.SplitterRef, className: Styles.ns_splitter, children: [_jsx("div", { ref: this.MasterPaneRef, className: Styles.ns_splitter_master, children: this.props.master_content }), this.props.detail_content &&
45
- _jsxs(_Fragment, { children: [_jsx("button", { className: Styles.ns_splitter_gutter, onMouseDown: this.handleMouseDown, children: _jsx("span", { className: Styles.ns_splitter_gutter_handle }) }), _jsx("div", { ref: this.DetailPaneRef, className: Styles.ns_splitter_detail, children: this.props.detail_content })] })] }));
136
+ _jsxs(_Fragment, { children: [_jsx("button", { ref: this.GutterRef, className: Styles.ns_splitter_gutter, onMouseDown: this.handleMouseDown, children: _jsx("span", { className: Styles.ns_splitter_gutter_handle }) }), _jsx("div", { className: Styles.ns_splitter_detail, children: this.props.detail_content })] })] }));
46
137
  }
47
138
  }
48
139
  //# sourceMappingURL=NSSplitter.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"NSSplitter.js","sourceRoot":"","sources":["../../src/components/NSSplitter.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"NSSplitter.js","sourceRoot":"","sources":["../../src/components/NSSplitter.tsx"],"names":[],"mappings":"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"}
@@ -12,6 +12,7 @@
12
12
  .ns_splitter.ns_splitter_resizing,
13
13
  .ns_splitter.ns_splitter_resizing * {
14
14
  cursor: row-resize !important;
15
+ user-select: none !important;
15
16
  }
16
17
 
17
18
  .ns_splitter_master,
package/package.json CHANGED
@@ -8,7 +8,7 @@
8
8
  "framework": "npm",
9
9
  "application": "package",
10
10
  "private": false,
11
- "version": "1.4.556",
11
+ "version": "1.4.558",
12
12
  "author": "Amir Abolhasani",
13
13
  "license": "MIT",
14
14
  "main": "./dist/main.js",
@@ -24,7 +24,7 @@
24
24
  "@ant-design/icons": "^6.2.5",
25
25
  "@babel/plugin-proposal-private-property-in-object": "^7.21.11",
26
26
  "@babel/plugin-transform-private-property-in-object": "^7.29.7",
27
- "@types/node": "^25.9.3",
27
+ "@types/node": "^26.0.0",
28
28
  "@types/react": "^18.3.12",
29
29
  "@types/react-bootstrap": "^1.1.0",
30
30
  "@types/react-dom": "^18.3.1",
@@ -12,6 +12,7 @@
12
12
  .ns_splitter.ns_splitter_resizing,
13
13
  .ns_splitter.ns_splitter_resizing * {
14
14
  cursor: row-resize !important;
15
+ user-select: none !important;
15
16
  }
16
17
 
17
18
  .ns_splitter_master,
@@ -1,18 +1,26 @@
1
- import { Component, createRef, ReactNode } from "react";
1
+ import { Component, createRef, MouseEvent as ReactMouseEvent, ReactNode } from "react";
2
+ import { IStorageLocal } from "namirasoft-core";
2
3
  import Styles from "./NSSplitter.module.css";
3
4
 
5
+ const MIN_MASTER_HEIGHT = 238;
6
+
4
7
  export interface NSSplitterProps
5
8
  {
6
9
  master_content?: ReactNode;
7
10
  detail_content?: ReactNode;
11
+ storage_key?: string;
8
12
  }
9
13
 
10
14
  export class NSSplitter extends Component<NSSplitterProps>
11
15
  {
12
16
  private SplitterRef = createRef<HTMLElement>();
13
17
  private MasterPaneRef = createRef<HTMLDivElement>();
14
- private DetailPaneRef = createRef<HTMLDivElement>();
18
+ private GutterRef = createRef<HTMLButtonElement>();
15
19
  private AnimationFrame: number | null = null;
20
+ private DragOffset = 0;
21
+ private HasUserResized = false;
22
+ private MediaQuery: MediaQueryList | null = null;
23
+ private Storage = new IStorageLocal();
16
24
 
17
25
  constructor(props: NSSplitterProps)
18
26
  {
@@ -20,20 +28,145 @@ export class NSSplitter extends Component<NSSplitterProps>
20
28
  this.handleMouseDown = this.handleMouseDown.bind(this);
21
29
  this.handleMouseUp = this.handleMouseUp.bind(this);
22
30
  this.handleMouseMove = this.handleMouseMove.bind(this);
31
+ this.handleViewportChange = this.handleViewportChange.bind(this);
23
32
  }
24
33
 
25
- handleMouseDown()
34
+ override componentDidMount()
26
35
  {
27
- this.SplitterRef.current?.addEventListener("mousemove", this.handleMouseMove);
28
- this.SplitterRef.current?.classList.add(Styles.ns_splitter_resizing);
36
+ this.MediaQuery = window.matchMedia("(min-width: 992px)");
37
+ this.MediaQuery.addEventListener("change", this.handleViewportChange);
38
+ window.addEventListener("resize", this.handleViewportChange);
39
+
40
+ if (this.loadStoredHeight() !== null)
41
+ this.HasUserResized = true;
42
+
43
+ this.updateLayout(true);
44
+ }
45
+
46
+ override componentDidUpdate(prevProps: NSSplitterProps)
47
+ {
48
+ let had_detail = !!prevProps.detail_content;
49
+ let has_detail = !!this.props.detail_content;
50
+
51
+ if (had_detail !== has_detail)
52
+ {
53
+ this.HasUserResized = false;
54
+ this.updateLayout(true);
55
+ }
56
+ }
57
+
58
+ override componentWillUnmount()
59
+ {
60
+ this.MediaQuery?.removeEventListener("change", this.handleViewportChange);
61
+ window.removeEventListener("resize", this.handleViewportChange);
62
+ window.removeEventListener("mousemove", this.handleMouseMove);
63
+ window.removeEventListener("mouseup", this.handleMouseUp);
64
+
65
+ if (this.AnimationFrame) cancelAnimationFrame(this.AnimationFrame);
66
+ }
67
+
68
+ handleViewportChange()
69
+ {
70
+ this.updateLayout(false);
71
+ }
72
+
73
+ updateLayout(force: boolean)
74
+ {
75
+ let master_el = this.MasterPaneRef.current;
76
+
77
+ if (!master_el || !this.MediaQuery) return;
78
+
79
+ if (this.MediaQuery.matches && this.props.detail_content)
80
+ {
81
+ let stored = this.loadStoredHeight();
82
+
83
+ if (stored !== null)
84
+ this.applyHeight(Math.max(MIN_MASTER_HEIGHT, stored));
85
+ else if (force || !this.HasUserResized)
86
+ this.adjustMasterToViewport();
87
+ }
88
+ else
89
+ {
90
+ master_el.style.height = "";
91
+ master_el.style.minHeight = "";
92
+ }
93
+ }
94
+
95
+ applyHeight(height: number)
96
+ {
97
+ let master_el = this.MasterPaneRef.current;
98
+
99
+ if (master_el) {
100
+ master_el.style.height = height + "px";
101
+ master_el.style.minHeight = height + "px";
102
+ }
103
+ }
104
+
105
+ loadStoredHeight(): number | null
106
+ {
107
+ let key = this.props.storage_key;
108
+
109
+ if (!key)
110
+ return null;
111
+
112
+ let raw = this.Storage.get(key, "");
113
+
114
+ if (!raw)
115
+ return null;
116
+
117
+ let value = parseInt(raw, 10);
118
+
119
+ if (isNaN(value))
120
+ return null;
121
+
122
+ return value;
123
+ }
124
+
125
+ saveStoredHeight(height: number)
126
+ {
127
+ let key = this.props.storage_key;
128
+
129
+ if (!key) return;
130
+
131
+ this.Storage.set(key, String(height));
132
+ }
133
+
134
+ adjustMasterToViewport()
135
+ {
136
+ let master_el = this.MasterPaneRef.current;
137
+
138
+ if (!master_el) return;
139
+
140
+ let master_top = master_el.getBoundingClientRect().top;
141
+ let gutter_height = this.GutterRef.current?.offsetHeight ?? 0;
142
+ let height = Math.max(MIN_MASTER_HEIGHT, window.innerHeight - master_top - gutter_height);
143
+
144
+ this.applyHeight(height);
145
+ }
146
+
147
+ handleMouseDown(event: ReactMouseEvent)
148
+ {
149
+ let master_el = this.MasterPaneRef.current;
150
+
151
+ if (!master_el) return;
152
+
153
+ this.DragOffset = event.clientY - master_el.getBoundingClientRect().bottom;
154
+
155
+ window.addEventListener("mousemove", this.handleMouseMove);
29
156
  window.addEventListener("mouseup", this.handleMouseUp);
157
+ this.SplitterRef.current?.classList.add(Styles.ns_splitter_resizing);
30
158
  }
31
159
 
32
160
  handleMouseUp()
33
161
  {
34
- this.SplitterRef.current?.removeEventListener("mousemove", this.handleMouseMove);
162
+ window.removeEventListener("mousemove", this.handleMouseMove);
163
+ window.removeEventListener("mouseup", this.handleMouseUp);
35
164
  this.SplitterRef.current?.classList.remove(Styles.ns_splitter_resizing);
36
- window.removeEventListener("mouseup", this.handleMouseUp)
165
+
166
+ let master_el = this.MasterPaneRef.current;
167
+
168
+ if (master_el)
169
+ this.saveStoredHeight(master_el.offsetHeight);
37
170
  }
38
171
 
39
172
  handleMouseMove(event: MouseEvent)
@@ -44,17 +177,15 @@ export class NSSplitter extends Component<NSSplitterProps>
44
177
  {
45
178
  this.AnimationFrame = null;
46
179
 
47
- let splitter_el = this.SplitterRef.current;
48
180
  let master_el = this.MasterPaneRef.current;
49
181
 
50
- if (!splitter_el || !master_el) return;
182
+ if (!master_el) return;
51
183
 
52
- let delta = event.clientY - master_el.getBoundingClientRect().bottom;
53
- let master_el_height = master_el.clientHeight + delta - 12;
54
- master_el_height = +Math.max(238, Math.min(master_el_height, 538)).toFixed(0);
184
+ let master_top = master_el.getBoundingClientRect().top;
185
+ let height = Math.max(MIN_MASTER_HEIGHT, event.clientY - this.DragOffset - master_top);
55
186
 
56
- master_el.style.height = master_el_height + "px";
57
- master_el.style.minHeight = master_el_height + "px";
187
+ this.applyHeight(height);
188
+ this.HasUserResized = true;
58
189
  });
59
190
  }
60
191
 
@@ -76,16 +207,14 @@ export class NSSplitter extends Component<NSSplitterProps>
76
207
  this.props.detail_content &&
77
208
  <>
78
209
  <button
210
+ ref={this.GutterRef}
79
211
  className={Styles.ns_splitter_gutter}
80
212
  onMouseDown={this.handleMouseDown}
81
213
  >
82
214
  <span className={Styles.ns_splitter_gutter_handle}></span>
83
215
  </button>
84
216
 
85
- <div
86
- ref={this.DetailPaneRef}
87
- className={Styles.ns_splitter_detail}
88
- >
217
+ <div className={Styles.ns_splitter_detail}>
89
218
  {this.props.detail_content}
90
219
  </div>
91
220
  </>