namirasoft-site-react 1.4.467 → 1.4.469

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,8 +1,8 @@
1
1
  .ns_table {
2
2
  display: flex;
3
3
  flex-direction: column;
4
- color: rgba(20, 27, 92, 1);
5
4
  overflow-x: auto;
5
+ color: rgba(20, 27, 92);
6
6
  }
7
7
 
8
8
  .ns_search_input {
@@ -23,7 +23,6 @@
23
23
  z-index: -1;
24
24
  }
25
25
 
26
-
27
26
  .ns_table thead {
28
27
  clip: rect(0 0 0 0);
29
28
  position: fixed;
@@ -37,12 +36,12 @@
37
36
  transition: all 0.2s ease-in-out;
38
37
  }
39
38
 
40
- /* .ns_table th {
41
- margin: 8px;
42
- } */
39
+ .ns_table tbody tr {
40
+ cursor: pointer;
41
+ }
43
42
 
44
43
  .ns_table td {
45
- display: -webkit-box;
44
+ display: flex;
46
45
  flex-direction: row;
47
46
  gap: 16px;
48
47
  margin: 8px;
@@ -52,7 +51,7 @@
52
51
  align-items: center;
53
52
  color: #000;
54
53
  height: max-content;
55
- max-height: 50px;
54
+ max-height: 3rem;
56
55
  line-clamp: 2;
57
56
  -webkit-line-clamp: 2;
58
57
  -webkit-box-orient: vertical;
@@ -70,20 +69,20 @@
70
69
  min-width: 30%;
71
70
  }
72
71
 
73
- .ns_tbody tr:nth-child(odd):hover {
74
- background-color: rgb(184 190 240 / 57%);
72
+ .ns_tbody tr:nth-child(odd) {
73
+ background-color: #f5f5f5;
75
74
  }
76
75
 
77
- .ns_tbody tr:nth-child(even):hover {
78
- background-color: rgb(184 190 240 / 57%);
76
+ .ns_tbody tr:nth-child(even) {
77
+ background-color: #ffffff;
79
78
  }
80
79
 
81
- .ns_tbody tr:nth-child(odd) {
82
- background-color: #eaeaea;
80
+ .ns_tbody tr:hover {
81
+ background-color: rgb(184, 190, 240, 0.32);
83
82
  }
84
83
 
85
- .ns_tbody tr:nth-child(even) {
86
- background-color: #ffffff;
84
+ .ns_tbody tr.ns_selected {
85
+ background-color: rgb(184, 190, 240, 0.64);
87
86
  }
88
87
 
89
88
  .ns_table_footer {
@@ -150,13 +149,7 @@
150
149
  gap: 16px;
151
150
  }
152
151
 
153
- @media screen and (min-width: 992px) {
154
- .ns_table tr {
155
- border-radius: 8px;
156
- }
157
- }
158
-
159
- @media screen and (max-width: 992px) {
152
+ @media screen and (max-width: 991px) {
160
153
  .ns_table td {
161
154
  width: auto;
162
155
  }
@@ -164,48 +157,81 @@
164
157
 
165
158
  @media screen and (min-width: 992px) {
166
159
  .ns_table {
167
- color: #000000;
168
- background-color: white;
169
- display: flex;
160
+ border-radius: 0.5rem;
170
161
  justify-content: center;
162
+ color: #000;
163
+ }
164
+
165
+ .ns_table::-webkit-scrollbar {
166
+ height: 0.375rem;
167
+ border-radius: 0.25rem;
168
+ }
169
+
170
+ .ns_table::-webkit-scrollbar-track {
171
+ border-radius: 0.25rem;
172
+ background: #f0f0f0;
173
+ }
174
+
175
+ .ns_table::-webkit-scrollbar-thumb {
176
+ border-radius: 0.25rem;
177
+ background: #888;
178
+ }
179
+
180
+ .ns_table::-webkit-scrollbar-thumb:hover {
181
+ background: #555;
171
182
  }
172
183
 
173
184
  .ns_table thead {
174
185
  position: static;
175
- background-color: rgba(20, 27, 92, 1);
186
+ min-width: max-content;
176
187
  border-top-left-radius: 8px;
177
188
  border-top-right-radius: 8px;
178
- min-width: max-content;
189
+ }
190
+
191
+ .ns_table thead tr {
192
+ background-color: rgba(20, 27, 92);
179
193
  }
180
194
 
181
195
  .ns_table tbody {
182
- background-color: rgba(255, 255, 255, 1);
196
+ max-height: 32rem;
183
197
  min-width: max-content;
198
+ background-color: #fff;
184
199
  }
185
200
 
186
201
  .ns_table tr {
187
- display: grid;
188
- grid-auto-flow: column;
189
- grid-auto-columns: max-content;
190
- padding: 16px 8px;
191
202
  margin: 0;
203
+ border: 1px solid transparent;
192
204
  border-radius: 0;
193
- border-bottom: 1px solid rgba(20, 27, 92, 0.3);
194
- background-color: transparent;
205
+ padding: 4px 8px;
206
+ display: grid;
195
207
  align-items: center;
208
+ grid-auto-flow: column;
209
+ grid-auto-columns: max-content;
210
+ }
211
+
212
+ .ns_table tr.ns_selected,
213
+ .ns_table tr.ns_last_selected {
214
+ border-color: rgba(20, 27, 92);
215
+ }
216
+
217
+ .ns_table tr.ns_selected+tr,
218
+ .ns_table tr.ns_last_selected+tr {
219
+ border-top-color: transparent;
196
220
  }
197
221
 
198
222
  .ns_table th {
199
- font-size: 16px;
200
- font-weight: 300;
201
- color: #ffffff;
202
- padding: 0;
203
223
  margin: 8px;
224
+ padding: 0;
225
+ font-size: 16px;
226
+ font-weight: 500;
227
+ line-height: 1.5rem;
228
+ color: #fff;
204
229
  }
205
230
 
206
231
  .ns_table td {
207
- text-align: left;
208
232
  align-items: flex-start;
233
+ line-height: 1.5rem;
234
+ text-align: left;
209
235
  }
210
236
 
211
237
  .ns_table td::before {
@@ -1,4 +1,4 @@
1
- import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { BaseColumnFormatter } from "./BaseColumnFormatter";
3
3
  export class BaseURLImageFormatter extends BaseColumnFormatter {
4
4
  constructor(width = "250px") {
@@ -7,8 +7,8 @@ export class BaseURLImageFormatter extends BaseColumnFormatter {
7
7
  }
8
8
  format(value, _, __, printable) {
9
9
  if (!printable) {
10
- return (_jsxs("div", { style: { display: "flex", alignItems: "center" }, children: [value.image.url &&
11
- _jsxs(_Fragment, { children: ["\u00A0", _jsx("img", { src: value.image.url, alt: value.image.alt, style: { width: "20px", height: "20px" } })] }), _jsx("a", { href: value.href, target: "_blank", rel: "noreferrer", style: { width: "max-content" }, children: value.text })] }));
10
+ return (_jsxs("div", { style: { display: "flex", alignItems: "center", gap: "4px" }, children: [value.image.url &&
11
+ _jsx("img", { src: value.image.url, alt: value.image.alt, style: { width: "20px", height: "20px" } }), _jsx("a", { href: value.href, target: "_blank", rel: "noreferrer", style: { width: "max-content" }, children: value.text })] }));
12
12
  }
13
13
  return value.text;
14
14
  }
@@ -1 +1 @@
1
- {"version":3,"file":"BaseURLImageFormatter.js","sourceRoot":"","sources":["../../src/formatter/BaseURLImageFormatter.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAE5D,MAAM,OAAO,qBAAsB,SAAQ,mBAAmB;IAE1D,YAAY,QAAgB,OAAO;QAE/B,KAAK,EAAE,CAAC;QACR,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;IACvB,CAAC;IACQ,MAAM,CAAC,KAIf,EAAE,CAAmB,EAAE,EAAsB,EAAE,SAAmB;QAE/D,IAAI,CAAC,SAAS,EACd,CAAC;YACG,OAAO,CACH,eAAK,KAAK,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,QAAQ,EAAE,aAE7C,KAAK,CAAC,KAAK,CAAC,GAAG;wBACf,wCAEI,cAAK,GAAG,EAAE,KAAK,CAAC,KAAK,CAAC,GAAG,EAAE,GAAG,EAAE,KAAK,CAAC,KAAK,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAI,IAC9F,EAEP,YAAG,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,MAAM,EAAC,QAAQ,EAAC,GAAG,EAAC,YAAY,EAAC,KAAK,EAAE,EAAE,KAAK,EAAE,aAAa,EAAE,YAAG,KAAK,CAAC,IAAI,GAAK,IACpG,CACV,CAAC;QACN,CAAC;QACD,OAAO,KAAK,CAAC,IAAI,CAAC;IACtB,CAAC;CACJ"}
1
+ {"version":3,"file":"BaseURLImageFormatter.js","sourceRoot":"","sources":["../../src/formatter/BaseURLImageFormatter.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAE5D,MAAM,OAAO,qBAAsB,SAAQ,mBAAmB;IAE1D,YAAY,QAAgB,OAAO;QAE/B,KAAK,EAAE,CAAC;QACR,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;IACvB,CAAC;IACQ,MAAM,CAAC,KAIf,EAAE,CAAmB,EAAE,EAAsB,EAAE,SAAmB;QAE/D,IAAI,CAAC,SAAS,EACd,CAAC;YACG,OAAO,CACH,eAAK,KAAK,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,QAAQ,EAAE,GAAG,EAAE,KAAK,EAAE,aAEzD,KAAK,CAAC,KAAK,CAAC,GAAG;wBACf,cAAK,GAAG,EAAE,KAAK,CAAC,KAAK,CAAC,GAAG,EAAE,GAAG,EAAE,KAAK,CAAC,KAAK,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAI,EAEjG,YAAG,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,MAAM,EAAC,QAAQ,EAAC,GAAG,EAAC,YAAY,EAAC,KAAK,EAAE,EAAE,KAAK,EAAE,aAAa,EAAE,YAAG,KAAK,CAAC,IAAI,GAAK,IACpG,CACV,CAAC;QACN,CAAC;QACD,OAAO,KAAK,CAAC,IAAI,CAAC;IACtB,CAAC;CACJ"}
@@ -10,7 +10,7 @@ export class EmailFormatter extends BaseColumnFormatter {
10
10
  format(value, column, row, printable) {
11
11
  return this.formatter.format({
12
12
  text: value,
13
- href: `email:${value}`,
13
+ href: `mailto:${value}`,
14
14
  image: { url: "https://static.namirasoft.com/image/concept/type/email.png", alt: "phone" }
15
15
  }, column, row, printable);
16
16
  }
@@ -1 +1 @@
1
- {"version":3,"file":"EmailFormatter.js","sourceRoot":"","sources":["../../src/formatter/EmailFormatter.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAEhE,MAAM,OAAO,cAAe,SAAQ,mBAAmB;IAGnD,YAAY,QAAgB,OAAO;QAE/B,KAAK,EAAE,CAAC;QAHJ,cAAS,GAA0B,IAAI,qBAAqB,EAAE,CAAC;QAInE,IAAI,CAAC,iBAAiB,GAAG,IAAI,CAAC;QAC9B,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;IACvB,CAAC;IACQ,MAAM,CAAC,KAAU,EAAE,MAAuB,EAAE,GAAsB,EAAE,SAAkB;QAE3F,OAAO,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC;YACzB,IAAI,EAAE,KAAK;YACX,IAAI,EAAE,SAAS,KAAK,EAAE;YACtB,KAAK,EAAE,EAAE,GAAG,EAAE,4DAA4D,EAAE,GAAG,EAAE,OAAO,EAAE;SAC7F,EAAE,MAAM,EAAE,GAAG,EAAE,SAAS,CAAC,CAAC;IAC/B,CAAC;CACJ"}
1
+ {"version":3,"file":"EmailFormatter.js","sourceRoot":"","sources":["../../src/formatter/EmailFormatter.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAEhE,MAAM,OAAO,cAAe,SAAQ,mBAAmB;IAGnD,YAAY,QAAgB,OAAO;QAE/B,KAAK,EAAE,CAAC;QAHJ,cAAS,GAA0B,IAAI,qBAAqB,EAAE,CAAC;QAInE,IAAI,CAAC,iBAAiB,GAAG,IAAI,CAAC;QAC9B,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;IACvB,CAAC;IACQ,MAAM,CAAC,KAAU,EAAE,MAAuB,EAAE,GAAsB,EAAE,SAAkB;QAE3F,OAAO,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC;YACzB,IAAI,EAAE,KAAK;YACX,IAAI,EAAE,UAAU,KAAK,EAAE;YACvB,KAAK,EAAE,EAAE,GAAG,EAAE,4DAA4D,EAAE,GAAG,EAAE,OAAO,EAAE;SAC7F,EAAE,MAAM,EAAE,GAAG,EAAE,SAAS,CAAC,CAAC;IAC/B,CAAC;CACJ"}
package/package.json CHANGED
@@ -8,7 +8,7 @@
8
8
  "framework": "npm",
9
9
  "application": "package",
10
10
  "private": false,
11
- "version": "1.4.467",
11
+ "version": "1.4.469",
12
12
  "author": "Amir Abolhasani",
13
13
  "license": "MIT",
14
14
  "main": "./dist/main.js",
@@ -21,7 +21,7 @@
21
21
  "copy": "copyfiles -u 1 src/**/*.html src/**/*.css src/**/*.svg src/**/*.png src/**/*.jpg dist/"
22
22
  },
23
23
  "dependencies": {
24
- "@ant-design/charts": "^2.6.4",
24
+ "@ant-design/charts": "^2.6.5",
25
25
  "@babel/plugin-proposal-private-property-in-object": "^7.21.11",
26
26
  "@types/node": "^24.5.2",
27
27
  "@types/react": "^18.3.12",
package/src/App.tsx CHANGED
@@ -1,17 +1,14 @@
1
1
  import 'bootstrap/dist/css/bootstrap.min.css';
2
- import { Component, createRef } from 'react';
2
+ import { Component } from 'react';
3
3
  import './App.css';
4
- import { NSBoxEntity } from './components/NSBoxEntity';
5
4
  import { NSLayout } from './components/NSLayout';
6
- import { NSSection } from './components/NSSection';
7
- import { NSButtonBlue, NSColumn } from './main';
5
+ import { EmailFormatter, IntegerFormatter, NSTable, PhoneFormatter, StringFormatter, StringFormatterSizeType } from './main';
6
+ import { NSSplitter } from './components/NSSplitter';
8
7
 
9
8
  interface AppProps { }
10
9
 
11
10
  export class App extends Component<AppProps>
12
11
  {
13
- private Box = createRef<NSBoxEntity<{ id: string, value: string }>>();
14
-
15
12
  override render()
16
13
  {
17
14
  return (
@@ -34,37 +31,43 @@ export class App extends Component<AppProps>
34
31
  notifier={{} as any}
35
32
  scope=''
36
33
  >
37
- <NSSection style={{ paddingTop: "3rem" }}>
38
- <NSColumn>
39
- <NSBoxEntity<{ id: string, value: string }>
40
- ref={this.Box}
41
- title="Test Entity Box"
42
- getTitle={item => item.value}
43
- getValue={item => item.value}
44
- multiple
45
- required
46
- table_name="product"
47
- defaultValue={["Mohammad"]}
48
- list={async () => ({
49
- rows: [
50
- { id: "a1", value: "Amin" },
51
- { id: "b2", value: "Negar" },
52
- { id: "c3", value: "Hadis" },
53
- { id: "d4", value: "Lida" },
54
- ],
55
- count: 4,
56
- })}
57
- getSort={() => null}
58
- />
59
- <NSButtonBlue
60
- title='Set Value'
61
- onClick={{
62
- action: () => this.Box.current?.setValue(["Milad"]),
63
- showLoading: false
34
+ <NSSplitter
35
+ master_content={
36
+ <NSTable<{ id: string, first_name: string, last_name: string, age: number, phone: string, email: string, bio: string }>
37
+ name='users'
38
+ checkbox
39
+ getRows={async () =>
40
+ {
41
+ return {
42
+ count: 10,
43
+ rows: [
44
+ { id: "a1", first_name: "Amin", last_name: "Pasban", age: 27, phone: "09117579093", email: "amin.cj0077@gmail.com", bio: "Loves literature and writing, constantly seeking." },
45
+ { id: "a2", first_name: "Sara", last_name: "Moradi", age: 24, phone: "09123456781", email: "sara.moradi@example.com", bio: "Passionate about design and technology, enjoys." },
46
+ { id: "a3", first_name: "Reza", last_name: "Karimi", age: 31, phone: "09129876542", email: "reza.karimi@example.com", bio: "Software engineer with experience in backend system." },
47
+ { id: "a4", first_name: "Niloofar", last_name: "Ahmadi", age: 29, phone: "09351234567", email: "niloofar.ahmadi@example.com", bio: "Enthusiastic about art and photography." },
48
+ { id: "a5", first_name: "Hossein", last_name: "Bagheri", age: 35, phone: "09134561234", email: "hossein.bagheri@example.com", bio: "Expert in finance and investment, passionate about." },
49
+ { id: "a6", first_name: "Maryam", last_name: "Shahbazi", age: 26, phone: "09141239876", email: "maryam.shahbazi@example.com", bio: "Loves literature and writing, constantly seeking." },
50
+ { id: "a7", first_name: "Ali", last_name: "Rostami", age: 28, phone: "09151237654", email: "ali.rostami@example.com", bio: "Tech enthusiast and full-stack developer, enjoys contributing." },
51
+ { id: "a8", first_name: "Fatemeh", last_name: "Jafari", age: 30, phone: "09361234589", email: "fatemeh.jafari@example.com", bio: "Interested in psychology and self-development, spends." },
52
+ { id: "a9", first_name: "Mohammad", last_name: "Esfandiari", age: 33, phone: "09162348752", email: "mohammad.esfandiari@example.com", bio: "Specialized in marketing strategies, creative thinker." },
53
+ { id: "b1", first_name: "Elham", last_name: "Khosravi", age: 25, phone: "09203456781", email: "elham.khosravi@example.com", bio: "Graphic designer with a flair for modern art." }
54
+ ]
55
+ }
64
56
  }}
57
+ getRowKey={(item) => item.value.id}
58
+ columns={[
59
+ { index: 0, name: "id", text: "ID", table: { name: "users", text: "users" }, formatter: new StringFormatter(StringFormatterSizeType.Word) },
60
+ { index: 0, name: "first_name", text: "First Name", table: { name: "users", text: "users" }, formatter: new StringFormatter(StringFormatterSizeType.TwoWords) },
61
+ { index: 0, name: "last_name", text: "Last Name", table: { name: "users", text: "users" }, formatter: new StringFormatter(StringFormatterSizeType.TwoWords) },
62
+ { index: 0, name: "age", text: "Age", table: { name: "users", text: "users" }, formatter: new IntegerFormatter() },
63
+ { index: 0, name: "phone", text: "Phone Number", table: { name: "users", text: "users" }, formatter: new PhoneFormatter() },
64
+ { index: 0, name: "email", text: "Email Address", table: { name: "users", text: "users" }, formatter: new EmailFormatter() },
65
+ { index: 0, name: "bio", text: "Bio", table: { name: "users", text: "users" }, formatter: new StringFormatter(StringFormatterSizeType.Description) },
66
+ ]}
65
67
  />
66
- </NSColumn>
67
- </NSSection>
68
+ }
69
+ detail_content={<></>}
70
+ />
68
71
  </NSLayout>
69
72
  );
70
73
  }
@@ -0,0 +1,73 @@
1
+ .ns_splitter_gutter {
2
+ display: none;
3
+ }
4
+
5
+ @media only screen and (min-width: 992px) {
6
+ .ns_splitter {
7
+ height: calc(100dvh - 5.5rem);
8
+ min-height: 40rem;
9
+ border: 1px solid #e1e1e1;
10
+ border-radius: 1rem;
11
+ display: flex;
12
+ flex-direction: column;
13
+ background-color: #fff;
14
+ }
15
+
16
+ .ns_splitter.ns_splitter_resizing,
17
+ .ns_splitter.ns_splitter_resizing * {
18
+ cursor: row-resize !important;
19
+ }
20
+
21
+ .ns_splitter_master,
22
+ .ns_splitter_detail {
23
+ margin: 0.5rem 0;
24
+ padding: 0 0.5rem;
25
+ flex-grow: 1;
26
+ flex-basis: calc(50% - 0.25rem);
27
+ overflow: auto;
28
+
29
+ }
30
+
31
+ .ns_splitter_master::-webkit-scrollbar,
32
+ .ns_splitter_detail::-webkit-scrollbar {
33
+ width: 0.375rem;
34
+ border-radius: 0.25rem;
35
+ }
36
+
37
+ .ns_splitter_master::-webkit-scrollbar-track,
38
+ .ns_splitter_detail::-webkit-scrollbar-track {
39
+ border-radius: 0.25rem;
40
+ background: #f0f0f0;
41
+ }
42
+
43
+ .ns_splitter_master::-webkit-scrollbar-thumb,
44
+ .ns_splitter_detail::-webkit-scrollbar-thumb {
45
+ border-radius: 0.25rem;
46
+ background: #888;
47
+ }
48
+
49
+ .ns_splitter_master::-webkit-scrollbar-thumb:hover,
50
+ .ns_splitter_detail::-webkit-scrollbar-thumb:hover {
51
+ background: #555;
52
+ }
53
+
54
+ .ns_splitter_gutter {
55
+ position: relative;
56
+ width: 100%;
57
+ height: 0.25rem;
58
+ outline: none;
59
+ border: none;
60
+ padding: 0;
61
+ display: flex;
62
+ justify-content: center;
63
+ background-color: #e1e1e1;
64
+ cursor: row-resize !important;
65
+ }
66
+
67
+ .ns_splitter_gutter_handle {
68
+ width: 1.5rem;
69
+ height: 0.25rem;
70
+ border-radius: 0.125rem;
71
+ background-color: #9a9a9a;
72
+ }
73
+ }
@@ -0,0 +1,99 @@
1
+ import { Component, createRef, ReactNode } from "react";
2
+ import Styles from "./NSSplitter.module.css";
3
+
4
+ export interface NSSplitterProps
5
+ {
6
+ master_content?: ReactNode;
7
+ detail_content?: ReactNode;
8
+ }
9
+
10
+ export class NSSplitter extends Component<NSSplitterProps>
11
+ {
12
+ private SplitterRef = createRef<HTMLElement>();
13
+ private MasterPaneRef = createRef<HTMLDivElement>();
14
+ private DetailPaneRef = createRef<HTMLDivElement>();
15
+ private AnimationFrame: number | null = null;
16
+
17
+ constructor(props: NSSplitterProps)
18
+ {
19
+ super(props);
20
+ this.handleMouseDown = this.handleMouseDown.bind(this);
21
+ this.handleMouseUp = this.handleMouseUp.bind(this);
22
+ this.handleMouseMove = this.handleMouseMove.bind(this);
23
+ }
24
+
25
+ handleMouseDown()
26
+ {
27
+ this.SplitterRef.current?.addEventListener("mousemove", this.handleMouseMove);
28
+ this.SplitterRef.current?.classList.add(Styles.ns_splitter_resizing);
29
+ window.addEventListener("mouseup", this.handleMouseUp);
30
+ }
31
+
32
+ handleMouseUp()
33
+ {
34
+ this.SplitterRef.current?.removeEventListener("mousemove", this.handleMouseMove);
35
+ this.SplitterRef.current?.classList.remove(Styles.ns_splitter_resizing);
36
+ window.removeEventListener("mouseup", this.handleMouseUp)
37
+ }
38
+
39
+ handleMouseMove(event: MouseEvent)
40
+ {
41
+ if (this.AnimationFrame) return;
42
+
43
+ this.AnimationFrame = requestAnimationFrame(() =>
44
+ {
45
+ this.AnimationFrame = null;
46
+
47
+ let splitter_el = this.SplitterRef.current;
48
+ let master_el = this.MasterPaneRef.current;
49
+ let detail_el = this.DetailPaneRef.current;
50
+
51
+ if (!splitter_el || !master_el || !detail_el) return;
52
+
53
+ let delta = event.clientY - master_el.getBoundingClientRect().bottom;
54
+
55
+ let master_el_percent = ((master_el.clientHeight + delta) * 100) / (splitter_el.clientHeight - 16);
56
+ master_el_percent = Math.max(20, Math.min(master_el_percent, 80));
57
+ master_el_percent = +master_el_percent.toFixed(2);
58
+
59
+ master_el.style.flexBasis = `calc(${master_el_percent}% - 4px)`;
60
+ detail_el.style.flexBasis = `calc(${100 - master_el_percent}% - 4px)`;
61
+ });
62
+ }
63
+
64
+ override render()
65
+ {
66
+ return (
67
+ <section
68
+ ref={this.SplitterRef}
69
+ className={Styles.ns_splitter}
70
+ >
71
+ <div
72
+ ref={this.MasterPaneRef}
73
+ className={Styles.ns_splitter_master}
74
+ >
75
+ {this.props.master_content}
76
+ </div>
77
+
78
+ {
79
+ this.props.detail_content &&
80
+ <>
81
+ <button
82
+ className={Styles.ns_splitter_gutter}
83
+ onMouseDown={this.handleMouseDown}
84
+ >
85
+ <span className={Styles.ns_splitter_gutter_handle}></span>
86
+ </button>
87
+
88
+ <div
89
+ ref={this.DetailPaneRef}
90
+ className={Styles.ns_splitter_detail}
91
+ >
92
+ {this.props.detail_content}
93
+ </div>
94
+ </>
95
+ }
96
+ </section>
97
+ )
98
+ }
99
+ }