namirasoft-site-react 1.4.535 → 1.4.538

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 (35) hide show
  1. package/dist/NSBoxBuilder.js +1 -1
  2. package/dist/NSBoxBuilder.js.map +1 -1
  3. package/dist/components/NSBarAction.d.ts +3 -1
  4. package/dist/components/NSBarAction.js +2 -2
  5. package/dist/components/NSBarAction.js.map +1 -1
  6. package/dist/components/NSBoxDate.d.ts +8 -8
  7. package/dist/components/NSBoxDate.js +25 -8
  8. package/dist/components/NSBoxDate.js.map +1 -1
  9. package/dist/components/NSBoxDateRange.d.ts +2 -2
  10. package/dist/components/NSBoxDateRange.js +16 -10
  11. package/dist/components/NSBoxDateRange.js.map +1 -1
  12. package/dist/components/NSBoxDateRangeBase.d.ts +4 -4
  13. package/dist/components/NSBoxDateRangeBase.js +15 -9
  14. package/dist/components/NSBoxDateRangeBase.js.map +1 -1
  15. package/dist/components/NSBoxDateTimeRange.d.ts +2 -2
  16. package/dist/components/NSBoxDateTimeRange.js +11 -15
  17. package/dist/components/NSBoxDateTimeRange.js.map +1 -1
  18. package/dist/components/NSBoxTimeRange.d.ts +28 -13
  19. package/dist/components/NSBoxTimeRange.js +80 -18
  20. package/dist/components/NSBoxTimeRange.js.map +1 -1
  21. package/dist/components/NSLayout.d.ts +4 -4
  22. package/dist/components/NSLayout.js +5 -5
  23. package/dist/components/NSLayout.js.map +1 -1
  24. package/dist/components/NSTable.js +9 -0
  25. package/dist/components/NSTable.js.map +1 -1
  26. package/package.json +2 -2
  27. package/src/NSBoxBuilder.tsx +1 -1
  28. package/src/components/NSBarAction.tsx +7 -3
  29. package/src/components/NSBoxDate.tsx +40 -23
  30. package/src/components/NSBoxDateRange.tsx +17 -9
  31. package/src/components/NSBoxDateRangeBase.tsx +19 -13
  32. package/src/components/NSBoxDateTimeRange.tsx +11 -15
  33. package/src/components/NSBoxTimeRange.tsx +155 -30
  34. package/src/components/NSLayout.tsx +8 -8
  35. package/src/components/NSTable.tsx +11 -0
@@ -13,8 +13,8 @@ import { safeMenuMenuItem } from './NSMenuButton';
13
13
 
14
14
  export interface NSBoxDateRangeValue
15
15
  {
16
- from: string;
17
- to: string;
16
+ from: Date;
17
+ to: Date;
18
18
  }
19
19
 
20
20
  export interface NSBoxDateRangePreset
@@ -85,7 +85,7 @@ export abstract class NSBoxDateRangeBase<TProps extends NSBoxDateRangeBaseProps<
85
85
  }
86
86
 
87
87
  protected abstract getFormat(): string;
88
- protected abstract getBuiltinPresets(): { label: string; title: string; from: string; to: string }[];
88
+ protected abstract getBuiltinPresets(): { label: string; title: string; from: Date; to: Date }[];
89
89
  protected abstract renderPicker(): React.ReactNode;
90
90
 
91
91
  protected toDayjsValue(): [Dayjs, Dayjs] | null
@@ -96,12 +96,11 @@ export abstract class NSBoxDateRangeBase<TProps extends NSBoxDateRangeBaseProps<
96
96
  return [dayjs(value.from), dayjs(value.to)];
97
97
  }
98
98
 
99
- private isInRange(from: string, to: string): boolean
99
+ private isInRange(from: Date, to: Date): boolean
100
100
  {
101
- const fmt = this.getFormat();
102
101
  const { minDate, maxDate } = this.props;
103
- if (minDate && from < TimeOperation.format(minDate, fmt)) return false;
104
- if (maxDate && to > TimeOperation.format(maxDate, fmt)) return false;
102
+ if (minDate && from < minDate) return false;
103
+ if (maxDate && to > maxDate) return false;
105
104
  return true;
106
105
  }
107
106
 
@@ -117,8 +116,8 @@ export abstract class NSBoxDateRangeBase<TProps extends NSBoxDateRangeBaseProps<
117
116
  .map(p => ({
118
117
  shortName: p.shortName,
119
118
  title: p.title,
120
- from: TimeOperation.format(p.getFrom(), this.getFormat()),
121
- to: TimeOperation.format(p.getTo(), this.getFormat()),
119
+ from: p.getFrom(),
120
+ to: p.getTo(),
122
121
  }))
123
122
  .filter(p => this.isInRange(p.from, p.to));
124
123
 
@@ -128,7 +127,8 @@ export abstract class NSBoxDateRangeBase<TProps extends NSBoxDateRangeBaseProps<
128
127
  <div className={Styles.ns_preset_container}>
129
128
  {builtinPresets.map(p =>
130
129
  {
131
- const isActive = this.state.value?.from === p.from && this.state.value?.to === p.to;
130
+ const isActive = this.state.value?.from.getTime() === p.from.getTime()
131
+ && this.state.value?.to.getTime() === p.to.getTime();
132
132
  return (
133
133
  <button
134
134
  key={p.label}
@@ -144,7 +144,8 @@ export abstract class NSBoxDateRangeBase<TProps extends NSBoxDateRangeBaseProps<
144
144
  {showDivider && <div className={Styles.ns_preset_divider} />}
145
145
  {resolvedCustom.map(p =>
146
146
  {
147
- const isActive = this.state.value?.from === p.from && this.state.value?.to === p.to;
147
+ const isActive = this.state.value?.from.getTime() === p.from.getTime()
148
+ && this.state.value?.to.getTime() === p.to.getTime();
148
149
  return (
149
150
  <button
150
151
  key={p.shortName}
@@ -163,11 +164,14 @@ export abstract class NSBoxDateRangeBase<TProps extends NSBoxDateRangeBaseProps<
163
164
 
164
165
  override render()
165
166
  {
167
+ const fmt = this.getFormat();
166
168
  let menu = safeMenuMenuItem(this.props, () => { });
167
169
  if (!menu.builtin.copy)
168
170
  menu.builtin.copy = {
169
171
  enabled: true,
170
- getValue: () => this.state.value ? `${this.state.value.from} to ${this.state.value.to}` : '',
172
+ getValue: () => this.state.value
173
+ ? `${TimeOperation.format(this.state.value.from, fmt)} to ${TimeOperation.format(this.state.value.to, fmt)}`
174
+ : '',
171
175
  };
172
176
 
173
177
  const showPresets = this.props.preset || (this.props.presets && this.props.presets.length > 0);
@@ -177,7 +181,9 @@ export abstract class NSBoxDateRangeBase<TProps extends NSBoxDateRangeBaseProps<
177
181
  ref={this.NSBoxBaseLayout_Main}
178
182
  {...this.props}
179
183
  menu={menu}
180
- getValue={() => this.state.value ? `${this.state.value.from} - ${this.state.value.to}` : null}
184
+ getValue={() => this.state.value
185
+ ? `${TimeOperation.format(this.state.value.from, fmt)} - ${TimeOperation.format(this.state.value.to, fmt)}`
186
+ : null}
181
187
  >
182
188
  <div className={Styles.ns_wrapper}>
183
189
  {this.renderPicker()}
@@ -15,50 +15,46 @@ export class NSBoxDateTimeRange extends NSBoxDateRangeBase<NSBoxDateTimeRangePro
15
15
 
16
16
  getError(): string | null
17
17
  {
18
- const fmt = this.getFormat();
19
- const { title, required } = this.props;
18
+ const { title, required, minDate, maxDate } = this.props;
20
19
  const { value } = this.state;
21
20
  if (required && (!value || !value.from || !value.to))
22
21
  return `${title} is required.`;
23
- const minDate = this.props.minDate ? TimeOperation.format(this.props.minDate, fmt) : undefined;
24
- const maxDate = this.props.maxDate ? TimeOperation.format(this.props.maxDate, fmt) : undefined;
25
22
  if (minDate && value?.from && value.from < minDate)
26
- return `${title} (from) must not be before ${minDate}.`;
23
+ return `${title} (from) must not be before ${TimeOperation.format(minDate, this.getFormat())}.`;
27
24
  if (maxDate && value?.to && value.to > maxDate)
28
- return `${title} (to) must not be after ${maxDate}.`;
25
+ return `${title} (to) must not be after ${TimeOperation.format(maxDate, this.getFormat())}.`;
29
26
  return null;
30
27
  }
31
28
 
32
29
  protected getBuiltinPresets()
33
30
  {
34
- const fmt = this.getFormat();
35
31
  const now = new Date();
36
32
  now.setSeconds(0, 0);
37
- const to = TimeOperation.format(now, fmt);
38
33
  return [
39
- { label: '1H', title: 'Last 1 Hour', from: TimeOperation.format(TimeOperation.hoursAgo(1, now), fmt), to },
40
- { label: '6H', title: 'Last 6 Hours', from: TimeOperation.format(TimeOperation.hoursAgo(6, now), fmt), to },
41
- { label: '12H', title: 'Last 12 Hours', from: TimeOperation.format(TimeOperation.hoursAgo(12, now), fmt), to },
42
- { label: '1D', title: 'Last 1 Day', from: TimeOperation.format(TimeOperation.daysAgo(1, now), fmt), to },
43
- { label: '1W', title: 'Last 1 Week', from: TimeOperation.format(TimeOperation.weeksAgo(1, now), fmt), to },
34
+ { label: '1H', title: 'Last 1 Hour', from: TimeOperation.hoursAgo(1, now), to: now },
35
+ { label: '6H', title: 'Last 6 Hours', from: TimeOperation.hoursAgo(6, now), to: now },
36
+ { label: '12H', title: 'Last 12 Hours', from: TimeOperation.hoursAgo(12, now), to: now },
37
+ { label: '1D', title: 'Last 1 Day', from: TimeOperation.daysAgo(1, now), to: now },
38
+ { label: '1W', title: 'Last 1 Week', from: TimeOperation.weeksAgo(1, now), to: now },
44
39
  ];
45
40
  }
46
41
 
47
42
  protected renderPicker()
48
43
  {
44
+ const fmt = this.getFormat();
49
45
  return (
50
46
  <DatePicker.RangePicker
51
47
  className={`${StylesNSBox.ns_box_input} ${Styles.ns_picker}`}
52
48
  variant="borderless"
53
49
  showTime
54
50
  value={this.toDayjsValue()}
55
- format={this.getFormat()}
51
+ format={fmt}
56
52
  minDate={this.props.minDate ? dayjs(this.props.minDate) : undefined}
57
53
  maxDate={this.props.maxDate ? dayjs(this.props.maxDate) : undefined}
58
54
  onChange={(_, dateStrings) =>
59
55
  {
60
56
  if (dateStrings?.[0] && dateStrings?.[1])
61
- this.setValue({ from: dateStrings[0], to: dateStrings[1] });
57
+ this.setValue({ from: dayjs(dateStrings[0], fmt).toDate(), to: dayjs(dateStrings[1], fmt).toDate() });
62
58
  else
63
59
  this.setValue(null);
64
60
  }}
@@ -4,21 +4,53 @@ import { TimePicker } from 'antd';
4
4
  import type { Dayjs } from 'dayjs';
5
5
  import dayjs from 'dayjs';
6
6
  import { TimeOperation } from 'namirasoft-core';
7
+ import { Component, createRef } from 'react';
8
+ import { IBaseComponentProps } from '../props/IBaseComponentProps';
9
+ import { IValidationProps } from '../props/IValidationProps';
7
10
  import { Validator } from '../Validator';
11
+ import { INSBox } from './INSBox';
8
12
  import StylesNSBox from './NSBox.module.css';
9
- import { NSBoxDateRangeBase, NSBoxDateRangeBaseProps } from './NSBoxDateRangeBase';
13
+ import { INSBoxBaseLayoutProps, NSBoxBaseLayout } from './NSBoxBaseLayout';
10
14
  import Styles from './NSBoxDateRangeBase.module.css';
15
+ import { NSBoxDateRangePreset } from './NSBoxDateRangeBase';
16
+ import { safeMenuMenuItem } from './NSMenuButton';
11
17
 
12
- export interface NSBoxTimeRangeProps extends NSBoxDateRangeBaseProps<NSBoxTimeRange>
18
+ export interface NSBoxTimeRangeValue
13
19
  {
20
+ from: string;
21
+ to: string;
22
+ }
23
+
24
+ export interface NSBoxTimeRangeProps extends IBaseComponentProps, IValidationProps, INSBoxBaseLayoutProps<NSBoxTimeRange, NSBoxTimeRangeValue>
25
+ {
26
+ preset?: boolean;
27
+ presets?: NSBoxDateRangePreset[];
14
28
  maxRangeSeconds?: number;
15
29
  }
16
30
 
17
- export class NSBoxTimeRange extends NSBoxDateRangeBase<NSBoxTimeRangeProps>
31
+ export interface NSBoxTimeRangeState
18
32
  {
19
- protected getFormat()
33
+ value: NSBoxTimeRangeValue | null;
34
+ }
35
+
36
+ export class NSBoxTimeRange extends Component<NSBoxTimeRangeProps, NSBoxTimeRangeState> implements INSBox
37
+ {
38
+ NSBoxBaseLayout_Main = createRef<NSBoxBaseLayout>();
39
+ private static readonly FORMAT = 'HH:mm:ss';
40
+
41
+ constructor(props: NSBoxTimeRangeProps)
42
+ {
43
+ super(props);
44
+ this.state = { value: props.defaultValue ?? null };
45
+ this.isEmpty = this.isEmpty.bind(this);
46
+ this.getError = this.getError.bind(this);
47
+ this.getValue = this.getValue.bind(this);
48
+ this.setValue = this.setValue.bind(this);
49
+ }
50
+
51
+ isEmpty(value: NSBoxTimeRangeValue): boolean
20
52
  {
21
- return 'HH:mm:ss';
53
+ return !value || !value.from || !value.to;
22
54
  }
23
55
 
24
56
  getError(): string | null
@@ -29,12 +61,10 @@ export class NSBoxTimeRange extends NSBoxDateRangeBase<NSBoxTimeRangeProps>
29
61
  return `${title} is required.`;
30
62
 
31
63
  const fromErr = Validator.getErrorTime(title, value?.from, false);
32
- if (fromErr)
33
- return fromErr;
64
+ if (fromErr) return fromErr;
34
65
 
35
66
  const toErr = Validator.getErrorTime(title, value?.to, false);
36
- if (toErr)
37
- return toErr;
67
+ if (toErr) return toErr;
38
68
 
39
69
  if (maxRangeSeconds && value?.from && value?.to)
40
70
  {
@@ -50,9 +80,40 @@ export class NSBoxTimeRange extends NSBoxDateRangeBase<NSBoxTimeRangeProps>
50
80
  return null;
51
81
  }
52
82
 
53
- protected getBuiltinPresets()
83
+ getValue(checkError: boolean = true): NSBoxTimeRangeValue | null
84
+ {
85
+ if (this.props.nullable)
86
+ if (this.NSBoxBaseLayout_Main.current?.isNull())
87
+ return null;
88
+ return NSBoxBaseLayout.checkGetValue(this, checkError, () => this.state.value);
89
+ }
90
+
91
+ setValue(value: NSBoxTimeRangeValue | null, callback?: () => void): void
92
+ {
93
+ if (this.props.nullable)
94
+ this.NSBoxBaseLayout_Main.current?.setNull(value == null);
95
+ this.setState({ value }, () =>
96
+ {
97
+ this.props.onChanged?.(this);
98
+ callback?.();
99
+ });
100
+ }
101
+
102
+ setDisabled(disabled: boolean): void
103
+ {
104
+ this.NSBoxBaseLayout_Main.current?.setDisabled(disabled);
105
+ }
106
+
107
+ private toDayjsValue(): [Dayjs, Dayjs] | null
54
108
  {
55
- const fmt = this.getFormat();
109
+ const { value } = this.state;
110
+ if (!value?.from || !value?.to) return null;
111
+ return [dayjs(value.from, NSBoxTimeRange.FORMAT), dayjs(value.to, NSBoxTimeRange.FORMAT)];
112
+ }
113
+
114
+ private getBuiltinPresets(): { label: string; title: string; from: string; to: string }[]
115
+ {
116
+ const fmt = NSBoxTimeRange.FORMAT;
56
117
  const now = new Date();
57
118
  now.setSeconds(0, 0);
58
119
  const to = TimeOperation.format(now, fmt);
@@ -65,30 +126,94 @@ export class NSBoxTimeRange extends NSBoxDateRangeBase<NSBoxTimeRangeProps>
65
126
  ];
66
127
  }
67
128
 
68
- protected override toDayjsValue(): [Dayjs, Dayjs] | null
129
+ private renderPresets(): React.ReactNode
69
130
  {
70
- const { value } = this.state;
71
- if (!value?.from || !value?.to)
72
- return null;
73
- return [dayjs(value.from, 'HH:mm:ss'), dayjs(value.to, 'HH:mm:ss')];
131
+ const { preset, presets: customPresets } = this.props;
132
+ const fmt = NSBoxTimeRange.FORMAT;
133
+
134
+ const builtinPresets = preset ? this.getBuiltinPresets() : [];
135
+
136
+ const resolvedCustom = (customPresets ?? []).map(p => ({
137
+ shortName: p.shortName,
138
+ title: p.title,
139
+ from: TimeOperation.format(p.getFrom(), fmt),
140
+ to: TimeOperation.format(p.getTo(), fmt),
141
+ }));
142
+
143
+ const showDivider = builtinPresets.length > 0 && resolvedCustom.length > 0;
144
+
145
+ return (
146
+ <div className={Styles.ns_preset_container}>
147
+ {builtinPresets.map(p =>
148
+ {
149
+ const isActive = this.state.value?.from === p.from && this.state.value?.to === p.to;
150
+ return (
151
+ <button
152
+ key={p.label}
153
+ type="button"
154
+ title={p.title}
155
+ className={`${Styles.ns_preset_btn} ${isActive ? Styles.ns_preset_btn_active : ''}`}
156
+ onClick={() => this.setValue({ from: p.from, to: p.to })}
157
+ >
158
+ {p.label}
159
+ </button>
160
+ );
161
+ })}
162
+ {showDivider && <div className={Styles.ns_preset_divider} />}
163
+ {resolvedCustom.map(p =>
164
+ {
165
+ const isActive = this.state.value?.from === p.from && this.state.value?.to === p.to;
166
+ return (
167
+ <button
168
+ key={p.shortName}
169
+ type="button"
170
+ title={p.title}
171
+ className={`${Styles.ns_preset_btn} ${isActive ? Styles.ns_preset_btn_active : ''}`}
172
+ onClick={() => this.setValue({ from: p.from, to: p.to })}
173
+ >
174
+ {p.shortName}
175
+ </button>
176
+ );
177
+ })}
178
+ </div>
179
+ );
74
180
  }
75
181
 
76
- protected renderPicker()
182
+ override render()
77
183
  {
184
+ let menu = safeMenuMenuItem(this.props, () => { });
185
+ if (!menu.builtin.copy)
186
+ menu.builtin.copy = {
187
+ enabled: true,
188
+ getValue: () => this.state.value ? `${this.state.value.from} to ${this.state.value.to}` : '',
189
+ };
190
+
191
+ const showPresets = this.props.preset || (this.props.presets && this.props.presets.length > 0);
192
+
78
193
  return (
79
- <TimePicker.RangePicker
80
- className={`${StylesNSBox.ns_box_input} ${Styles.ns_picker}`}
81
- variant="borderless"
82
- value={this.toDayjsValue()}
83
- format={this.getFormat()}
84
- onChange={(_, timeStrings) =>
85
- {
86
- if (timeStrings?.[0] && timeStrings?.[1])
87
- this.setValue({ from: timeStrings[0], to: timeStrings[1] });
88
- else
89
- this.setValue(null);
90
- }}
91
- />
194
+ <NSBoxBaseLayout
195
+ ref={this.NSBoxBaseLayout_Main}
196
+ {...this.props}
197
+ menu={menu}
198
+ getValue={() => this.state.value ? `${this.state.value.from} - ${this.state.value.to}` : null}
199
+ >
200
+ <div className={Styles.ns_wrapper}>
201
+ <TimePicker.RangePicker
202
+ className={`${StylesNSBox.ns_box_input} ${Styles.ns_picker}`}
203
+ variant="borderless"
204
+ value={this.toDayjsValue()}
205
+ format={NSBoxTimeRange.FORMAT}
206
+ onChange={(_, timeStrings) =>
207
+ {
208
+ if (timeStrings?.[0] && timeStrings?.[1])
209
+ this.setValue({ from: timeStrings[0], to: timeStrings[1] });
210
+ else
211
+ this.setValue(null);
212
+ }}
213
+ />
214
+ </div>
215
+ {showPresets && this.renderPresets()}
216
+ </NSBoxBaseLayout>
92
217
  );
93
218
  }
94
219
  }
@@ -1,16 +1,16 @@
1
- import Styles from './NSLayout.module.css';
2
1
  import { Fragment, ReactNode } from 'react';
3
- import { NSHeader } from './NSHeader';
4
- import { NSFooter } from './NSFooter';
2
+ import { IBackgroundProps } from '../props/IBackgroundProps';
5
3
  import { IBaseComponentProps } from '../props/IBaseComponentProps';
6
- import { NSBarNotification, NSBarNotificationProps } from './NSBarNotification';
7
4
  import { IHeaderRightProps } from '../props/IHeaderRightProps';
8
- import { NSBarActionProps, NSBarAction, isValidAction } from './NSBarAction';
9
- import { NSBarTitleProps, NSBarTitle } from './NSBarTitle';
10
5
  import { NSRouterMakerProps } from '../routing/NSRouterMakerProps';
11
- import { NSBarAlertProps, NSBarAlert } from './NSBarAlert';
6
+ import { NSBarAction, NSBarActionProps, isValidAction } from './NSBarAction';
7
+ import { NSBarAlert, NSBarAlertProps } from './NSBarAlert';
8
+ import { NSBarNotification, NSBarNotificationProps } from './NSBarNotification';
9
+ import { NSBarTitle, NSBarTitleProps } from './NSBarTitle';
10
+ import { NSFooter } from './NSFooter';
11
+ import { NSHeader } from './NSHeader';
12
+ import Styles from './NSLayout.module.css';
12
13
  import { NSSpace, NSSpaceSizeType } from './NSSpace';
13
- import { IBackgroundProps } from '../props/IBackgroundProps';
14
14
 
15
15
  export interface NSLayoutProps extends IBaseComponentProps, NSRouterMakerProps
16
16
  {
@@ -219,6 +219,17 @@ export class NSTable<RowType> extends Component<NSTableProps<RowType>, NSTableSt
219
219
  {
220
220
  let columns: TableColumnInfo[] = [];
221
221
  this.foreachColumn(visible, c => columns.push(c));
222
+ if (visible === true)
223
+ {
224
+ let vs = this.getVisibleColumns();
225
+ if (vs.length > 0)
226
+ columns.sort((a, b) =>
227
+ {
228
+ let ai = vs.findIndex(v => v.table === a.table.name && v.column === a.name);
229
+ let bi = vs.findIndex(v => v.table === b.table.name && v.column === b.name);
230
+ return ai - bi;
231
+ });
232
+ }
222
233
  return columns;
223
234
  }
224
235
  private showModal(description: string, title?: string)