namirasoft-site-react 1.4.69 → 1.4.70

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 (43) hide show
  1. package/dist/components/NSBarAction.js +3 -2
  2. package/dist/components/NSBarAction.js.map +1 -1
  3. package/dist/components/NSBarTitle.js +2 -1
  4. package/dist/components/NSBarTitle.js.map +1 -1
  5. package/dist/components/NSBoxBooleans.js +2 -1
  6. package/dist/components/NSBoxBooleans.js.map +1 -1
  7. package/dist/components/NSFilterBox.js +2 -1
  8. package/dist/components/NSFilterBox.js.map +1 -1
  9. package/dist/components/NSGroupedList.js +2 -1
  10. package/dist/components/NSGroupedList.js.map +1 -1
  11. package/dist/components/NSHeader.js +3 -2
  12. package/dist/components/NSHeader.js.map +1 -1
  13. package/dist/components/NSLayout.js +2 -1
  14. package/dist/components/NSLayout.js.map +1 -1
  15. package/dist/components/NSRange.js +2 -1
  16. package/dist/components/NSRange.js.map +1 -1
  17. package/dist/components/NSRepeater.js +2 -1
  18. package/dist/components/NSRepeater.js.map +1 -1
  19. package/dist/components/NSTabPage.d.ts +1 -1
  20. package/dist/components/NSTabPage.js +3 -2
  21. package/dist/components/NSTabPage.js.map +1 -1
  22. package/dist/components/NSTimelineMonthly.js +3 -2
  23. package/dist/components/NSTimelineMonthly.js.map +1 -1
  24. package/dist/main.d.ts +2 -1
  25. package/dist/main.js +2 -1
  26. package/dist/main.js.map +1 -1
  27. package/dist/utils/generateUniqId.d.ts +1 -0
  28. package/dist/utils/generateUniqId.js +2 -0
  29. package/dist/utils/generateUniqId.js.map +1 -0
  30. package/package.json +1 -1
  31. package/src/components/NSBarAction.tsx +4 -3
  32. package/src/components/NSBarTitle.tsx +2 -1
  33. package/src/components/NSBoxBooleans.tsx +3 -2
  34. package/src/components/NSFilterBox.tsx +3 -2
  35. package/src/components/NSGroupedList.tsx +22 -13
  36. package/src/components/NSHeader.tsx +215 -214
  37. package/src/components/NSLayout.tsx +4 -3
  38. package/src/components/NSRange.tsx +2 -1
  39. package/src/components/NSRepeater.tsx +2 -1
  40. package/src/components/NSTabPage.tsx +5 -4
  41. package/src/components/NSTimelineMonthly.tsx +4 -3
  42. package/src/main.ts +2 -1
  43. package/src/utils/generateUniqId.ts +1 -0
@@ -1,6 +1,7 @@
1
1
  import React from "react";
2
2
  import { IBaseComponentProps } from "../props/IBaseComponentProps";
3
3
  import { NSBoxBoolean } from "./NSBoxBoolean";
4
+ import { generateUniqId } from "../utils/generateUniqId";
4
5
 
5
6
  export interface NSBoxBooleansProps extends IBaseComponentProps
6
7
  {
@@ -142,13 +143,13 @@ export class NSBoxBooleans extends React.Component<NSBoxBooleansProps, NSboxBool
142
143
  onChanged={this.onMarkAllChecked}
143
144
  />
144
145
  {
145
- this.props.items.map((e, index) =>
146
+ this.props.items.map((e) =>
146
147
  <NSBoxBoolean
147
148
  id={e.value}
148
149
  title={e.text}
149
150
  required={false}
150
151
  checked={this.state.values.includes(e.value)}
151
- key={index}
152
+ key={generateUniqId()}
152
153
  style={{ width: "272px" }}
153
154
  onChanged={this.onItemChecked}
154
155
  />
@@ -6,6 +6,7 @@ import { FilterItem, FilterItemColumnType, FilterItemOperator } from 'namirasoft
6
6
  import { NSGroupedList, INSGroupedListProps_Group } from './NSGroupedList';
7
7
  import { NSButton } from './NSButton';
8
8
  import Styles from './NSFilterBox.module.css';
9
+ import { generateUniqId } from '../utils/generateUniqId';
9
10
 
10
11
  export interface INSFilterBoxProps extends IBaseComponentProps
11
12
  {
@@ -226,10 +227,10 @@ export class NSFilterBox extends Component<INSFilterBoxProps, INSFilterBoxState>
226
227
  }
227
228
  <div className={Styles.ns_selected_list_parent}>
228
229
  {
229
- this.state.filterItems.map((item, index) =>
230
+ this.state.filterItems.map((item) =>
230
231
  <NSFilterItem
231
232
  item={item}
232
- key={index}
233
+ key={generateUniqId()}
233
234
  removeSelected={() => this.removeFilterItem(item)}
234
235
  />
235
236
  )
@@ -2,6 +2,7 @@
2
2
  import { Component, createRef } from 'react';
3
3
  import { IBaseComponentProps } from '../props/IBaseComponentProps';
4
4
  import Styles from "./NSGroupedList.module.css";
5
+ import { generateUniqId } from '../utils/generateUniqId';
5
6
 
6
7
  export interface INSGroupedListProps extends IBaseComponentProps
7
8
  {
@@ -29,7 +30,8 @@ interface INSGroupedListState
29
30
  isVisible: boolean;
30
31
  }
31
32
 
32
- export class NSGroupedList extends Component<INSGroupedListProps, INSGroupedListState> {
33
+ export class NSGroupedList extends Component<INSGroupedListProps, INSGroupedListState>
34
+ {
33
35
  private groupListRef = createRef<HTMLDivElement>();
34
36
 
35
37
  constructor(props: INSGroupedListProps)
@@ -40,7 +42,7 @@ export class NSGroupedList extends Component<INSGroupedListProps, INSGroupedList
40
42
  };
41
43
  this.handleClickOutside = this.handleClickOutside.bind(this);
42
44
  this.hide = this.hide.bind(this);
43
- this.show = this.show.bind(this);
45
+ this.show = this.show.bind(this);
44
46
  }
45
47
 
46
48
  override componentDidMount()
@@ -48,36 +50,43 @@ export class NSGroupedList extends Component<INSGroupedListProps, INSGroupedList
48
50
  document.addEventListener('mousedown', this.handleClickOutside);
49
51
  }
50
52
 
51
- override componentWillUnmount() {
53
+ override componentWillUnmount()
54
+ {
52
55
  document.removeEventListener('mousedown', this.handleClickOutside);
53
56
  }
54
57
 
55
- handleClickOutside(event: MouseEvent) {
56
- if (this.groupListRef.current && !this.groupListRef.current.contains(event.target as Node)) {
58
+ handleClickOutside(event: MouseEvent)
59
+ {
60
+ if (this.groupListRef.current && !this.groupListRef.current.contains(event.target as Node))
61
+ {
57
62
  this.hide();
58
63
  }
59
64
  }
60
65
 
61
- hide() {
66
+ hide()
67
+ {
62
68
  this.setState({ isVisible: false });
63
69
  }
64
70
 
65
- show() {
71
+ show()
72
+ {
66
73
  this.setState({ isVisible: true }, () =>
67
74
  {
68
75
  console.log("State after show:", this.state);
69
76
  });
70
77
  }
71
78
 
72
- override render() {
73
- if (!this.state.isVisible) {
79
+ override render()
80
+ {
81
+ if (!this.state.isVisible)
82
+ {
74
83
  return null;
75
84
  }
76
85
 
77
86
  return (
78
87
  <div ref={this.groupListRef} className={Styles.ns_group_list_parent}>
79
- {this.props.groups.map((group, index) => (
80
- <ul key={index} className={Styles.ns_group_list}>
88
+ {this.props.groups.map((group) => (
89
+ <ul key={generateUniqId()} className={Styles.ns_group_list}>
81
90
  <div className='d-flex w-100 justify-content-between align-items-center'>
82
91
  <span className={Styles.ns_group_category}>{group.text}
83
92
  <img
@@ -89,8 +98,8 @@ export class NSGroupedList extends Component<INSGroupedListProps, INSGroupedList
89
98
  />
90
99
  </span>
91
100
  </div>
92
- {group.items.map((item, index) => (
93
- <li key={index} onClick={() => this.props.onClick(group.name, item.name)}>
101
+ {group.items.map((item) => (
102
+ <li key={generateUniqId()} onClick={() => this.props.onClick(group.name, item.name)}>
94
103
  <div className={Styles.ns_group_item}>
95
104
  <span>{item.text && <span>{item.text}</span>}</span>
96
105
  <span style={item.text_bold ? { fontWeight: 'bold' } : {}}>
@@ -9,243 +9,244 @@ import { IHeaderProps } from "../props/IHeaderProps";
9
9
  import { IStorageLocal, CacheService } from "namirasoft-core";
10
10
  import { EnvService } from 'namirasoft-core'
11
11
  import { INSRouterProps } from "../routing/INSRouterProps";
12
+ import { generateUniqId } from "../utils/generateUniqId";
12
13
  export interface INSHeaderProps extends IBaseComponentProps, INSRouterProps
13
14
  {
14
- scope: string;
15
- name: string;
16
- logo: string;
17
- nav?: IBaseComponentProps;
18
- header: IHeaderProps;
19
- isLoggedIn: () => boolean;
15
+ scope: string;
16
+ name: string;
17
+ logo: string;
18
+ nav?: IBaseComponentProps;
19
+ header: IHeaderProps;
20
+ isLoggedIn: () => boolean;
20
21
  }
21
22
 
22
23
  export interface NSHeaderState
23
24
  {
24
- filters: FilterLinkFullRow[];
25
- selected: FilterLinkFullRow | null;
26
- showNavbar: boolean;
25
+ filters: FilterLinkFullRow[];
26
+ selected: FilterLinkFullRow | null;
27
+ showNavbar: boolean;
27
28
  }
28
29
 
29
30
  export class NSHeader extends React.Component<INSHeaderProps, NSHeaderState>
30
31
  {
31
- private cache: CacheService<{
32
- rows: FilterLinkFullRow[];
33
- count: number;
34
- }>;
32
+ private cache: CacheService<{
33
+ rows: FilterLinkFullRow[];
34
+ count: number;
35
+ }>;
35
36
 
36
- constructor(props: INSHeaderProps)
37
- {
38
- super(props);
39
- this.state = {
40
- filters: [],
41
- selected: null,
42
- showNavbar: false
43
- };
44
- this.hasChild = this.hasChild.bind(this);
45
- this.onMenuItemToggled = this.onMenuItemToggled.bind(this);
46
- this.render_menu = this.render_menu.bind(this);
47
- this.render_menuItem = this.render_menuItem.bind(this);
48
- this.handleShowNavbar = this.handleShowNavbar.bind(this);
49
- this.cache = new CacheService<{
50
- rows: FilterLinkFullRow[];
51
- count: number;
52
- }>("ns-header", 720, new IStorageLocal(), async () =>
53
- {
54
- let REACT_APP_BASE_URL_API_LINK = new EnvService("REACT_APP_BASE_URL_API_LINK", true).getString();
55
- let server = new NamirasoftAPILinkServer(REACT_APP_BASE_URL_API_LINK, props.notifier.onError);
56
- return server.filter.ListFilterLinks(this.props.scope, this.props.name, null, null, null);
57
- }, () => { });
58
- }
59
- override componentDidMount(): void
60
- {
61
- this.cache.get().then(filters =>
62
- {
63
- this.setState({ filters: filters.rows });
64
- }).catch(() => { });
65
- }
66
- private onMenuItemToggled(checked: boolean, selected: FilterLinkFullRow)
67
- {
68
- if (checked)
69
- this.setState({ selected });
70
- }
71
- private getFilters(): FilterLinkFullRow[]
72
- {
73
- let loggedin = this.props.isLoggedIn();
74
- let ans = this.state.filters?.filter(f =>
75
- {
76
- if (f.link)
77
- {
78
- if (loggedin)
79
- return f.link.private;
80
- return f.link.public;
81
- }
82
- return true;
83
- }) ?? [];
37
+ constructor(props: INSHeaderProps)
38
+ {
39
+ super(props);
40
+ this.state = {
41
+ filters: [],
42
+ selected: null,
43
+ showNavbar: false
44
+ };
45
+ this.hasChild = this.hasChild.bind(this);
46
+ this.onMenuItemToggled = this.onMenuItemToggled.bind(this);
47
+ this.render_menu = this.render_menu.bind(this);
48
+ this.render_menuItem = this.render_menuItem.bind(this);
49
+ this.handleShowNavbar = this.handleShowNavbar.bind(this);
50
+ this.cache = new CacheService<{
51
+ rows: FilterLinkFullRow[];
52
+ count: number;
53
+ }>("ns-header", 720, new IStorageLocal(), async () =>
54
+ {
55
+ let REACT_APP_BASE_URL_API_LINK = new EnvService("REACT_APP_BASE_URL_API_LINK", true).getString();
56
+ let server = new NamirasoftAPILinkServer(REACT_APP_BASE_URL_API_LINK, props.notifier.onError);
57
+ return server.filter.ListFilterLinks(this.props.scope, this.props.name, null, null, null);
58
+ }, () => { });
59
+ }
60
+ override componentDidMount(): void
61
+ {
62
+ this.cache.get().then(filters =>
63
+ {
64
+ this.setState({ filters: filters.rows });
65
+ }).catch(() => { });
66
+ }
67
+ private onMenuItemToggled(checked: boolean, selected: FilterLinkFullRow)
68
+ {
69
+ if (checked)
70
+ this.setState({ selected });
71
+ }
72
+ private getFilters(): FilterLinkFullRow[]
73
+ {
74
+ let loggedin = this.props.isLoggedIn();
75
+ let ans = this.state.filters?.filter(f =>
76
+ {
77
+ if (f.link)
78
+ {
79
+ if (loggedin)
80
+ return f.link.private;
81
+ return f.link.public;
82
+ }
83
+ return true;
84
+ }) ?? [];
84
85
 
85
- while (true)
86
- {
87
- let old_length = ans.length;
88
- let old = ans;
89
- ans = ans.filter(f =>
90
- {
91
- if (f.link?.url)
92
- return true;
93
- return old.filter(x => x.parent_id === f.id).length > 0;
94
- });
95
- let new_length = ans.length;
96
- if (old_length === new_length)
97
- break;
98
- }
86
+ while (true)
87
+ {
88
+ let old_length = ans.length;
89
+ let old = ans;
90
+ ans = ans.filter(f =>
91
+ {
92
+ if (f.link?.url)
93
+ return true;
94
+ return old.filter(x => x.parent_id === f.id).length > 0;
95
+ });
96
+ let new_length = ans.length;
97
+ if (old_length === new_length)
98
+ break;
99
+ }
99
100
 
100
- return ans;
101
- }
102
- private hasChild(id: number): boolean
103
- {
104
- return this.getFilters().filter(f => f.parent_id === id).length > 0;
105
- }
106
- handleShowNavbar(): void
107
- {
108
- this.setState({ showNavbar: !this.state.showNavbar });
109
- }
110
- override render()
111
- {
112
- let nav: IBaseComponentProps | undefined = this.props.nav;
113
- if (!nav)
114
- nav = { style: {} };
115
- if (!nav.style)
116
- nav.style = {};
117
- if (!nav.style?.backgroundColor)
118
- nav.style.backgroundColor = "rgba(20, 27, 92, 1)";
119
- return (
120
- <header id={this.props.id}
121
- className={`${Styles.ns_header} ${this.props.classList?.join(" ")}`}
122
- style={this.props.style}
123
- >
124
- <nav
125
- id={this.props.nav?.id}
126
- className={`${Styles.ns_navbar} ${this.props.nav?.classList?.join(" ")}`}
127
- style={nav?.style}
128
- >
129
- <div className={`${Styles.ns_navbar_parent_content} container`}>
130
- <a className="me-2" href="/">
131
- <img
132
- src={this.props.logo}
133
- alt="Logo"
134
- width={48}
135
- height={48}
136
- />
101
+ return ans;
102
+ }
103
+ private hasChild(id: number): boolean
104
+ {
105
+ return this.getFilters().filter(f => f.parent_id === id).length > 0;
106
+ }
107
+ handleShowNavbar(): void
108
+ {
109
+ this.setState({ showNavbar: !this.state.showNavbar });
110
+ }
111
+ override render()
112
+ {
113
+ let nav: IBaseComponentProps | undefined = this.props.nav;
114
+ if (!nav)
115
+ nav = { style: {} };
116
+ if (!nav.style)
117
+ nav.style = {};
118
+ if (!nav.style?.backgroundColor)
119
+ nav.style.backgroundColor = "rgba(20, 27, 92, 1)";
120
+ return (
121
+ <header id={this.props.id}
122
+ className={`${Styles.ns_header} ${this.props.classList?.join(" ")}`}
123
+ style={this.props.style}
124
+ >
125
+ <nav
126
+ id={this.props.nav?.id}
127
+ className={`${Styles.ns_navbar} ${this.props.nav?.classList?.join(" ")}`}
128
+ style={nav?.style}
129
+ >
130
+ <div className={`${Styles.ns_navbar_parent_content} container`}>
131
+ <a className="me-2" href="/">
132
+ <img
133
+ src={this.props.logo}
134
+ alt="Logo"
135
+ width={48}
136
+ height={48}
137
+ />
137
138
  </a>
138
- { this.props.header.logo_title &&
139
+ {this.props.header.logo_title &&
139
140
  <h2 className={`${Styles.ns_navbar_title} mb-0 flex-shrink-0`}>
140
141
  {this.props.header.logo_title}
141
- </h2>
142
+ </h2>
142
143
  }
143
144
  <div className={`${Styles.ns_navbar_content} `} >
144
- <div className={`${Styles.ns_navbar_elements} ${this.state.showNavbar && Styles.ns_navbar_active}`}>
145
- {this.render_menu(0, null)}
146
- </div>
147
- {
148
- this.props.header &&
149
- <div className="d-flex gap-3 align-items-center">
150
- <span className={Styles.ns_navbar_title}>{this.props.header?.title}</span>
151
- {
152
- this.props.header.icons.map((icon, index) =>
145
+ <div className={`${Styles.ns_navbar_elements} ${this.state.showNavbar && Styles.ns_navbar_active}`}>
146
+ {this.render_menu(0, null)}
147
+ </div>
148
+ {
149
+ this.props.header &&
150
+ <div className="d-flex gap-3 align-items-center">
151
+ <span className={Styles.ns_navbar_title}>{this.props.header?.title}</span>
152
+ {
153
+ this.props.header.icons.map((icon) =>
153
154
  <div
154
- key={index}
155
+ key={generateUniqId()}
155
156
  title={icon.tooltip}
156
- className={Styles.ns_header_icon}
157
+ className={Styles.ns_header_icon}
157
158
  >
158
- <img
159
- src={icon.src}
160
- alt={icon.alt}
161
- width={20}
162
- height={20}
159
+ <img
160
+ src={icon.src}
161
+ alt={icon.alt}
162
+ width={20}
163
+ height={20}
163
164
  onClick={() => icon.onClicked(icon)}
164
- />
165
- {
166
- icon.count !== 0 && icon.count &&
165
+ />
166
+ {
167
+ icon.count !== 0 && icon.count &&
167
168
  <div
168
169
  className={Styles.ns_navbar_notification_count}
169
170
  onClick={() => icon.onClicked(icon)}
170
- >
171
- {
172
- icon.count < 100 ? icon.count : "+99"
173
- }
174
- </div>
175
- }
176
- {
177
- icon.children
178
- }
179
- </div>
180
- )
181
- }
182
- </div>
183
- }
184
- <div className={Styles.ns_navbar_menu_icon} onClick={this.handleShowNavbar}>
185
- <img
186
- src=
187
- {
188
- this.state.showNavbar ?
189
- "https://static.namirasoft.com/image/concept/close/white.svg"
190
- : "https://static.namirasoft.com/image/concept/menu/burger-white.svg"
191
- }
192
- alt="Menu Icon"
193
- width={24}
194
- height={24}
195
- />
196
- </div>
197
- </div>
198
- </div>
199
- </nav>
200
- </header>
201
- );
202
- }
203
- private render_menu(level: number, parent_id: number | null)
204
- {
205
- let fs: FilterLinkFullRow[] = this.getFilters().filter(f => f.parent_id === parent_id);
206
- return (
207
- <div className={`me-auto nav ${Styles.ns_navbar_items_container}`} >
208
- {(fs?.map(f => this.render_menuItem(level, f)))}
209
- </div>
210
- );
211
- }
212
- private render_menuItem(level: number, filter: FilterLinkFullRow)
213
- {
214
- if (this.hasChild(filter.id))
215
- {
216
- let sub_menus = <></>;
217
- if (level === 0)
218
- if (this.state.selected)
219
- {
220
- sub_menus =
221
- <div
222
- id={`dropdown_items${filter.id}`}>
223
- {this.render_menu(1, this.state.selected.id)}
224
- </div >
225
- }
226
- return <NavDropdown
227
- onToggle={(checked) => this.onMenuItemToggled(checked, filter)}
228
- className={level === 0 ? Styles.ns_navbar_first_level_item : Styles.ns_navbar_second_level_item}
229
- title={filter.name}
230
- key={filter.id}
231
- id={`dropdown_parent${filter.id}`}>
232
- {sub_menus}
233
- </NavDropdown >;
234
- }
235
- else
236
- {
237
- let href = filter.link?.url;
238
- if (process.env.REACT_APP_STANDALONE)
239
- if (href)
240
- {
241
- let url = new URL(href);
242
- url.host = window.location.host;
243
- url.protocol = window.location.protocol;
244
- href = url.toString();
245
- }
246
- return (
247
- <a key={filter.id} className={`${Styles.ns_navbar_items_link} ${level === 0 ? Styles.ns_navbar_first_level_item : Styles.ns_navbar_second_level_item}`} href={href}>{filter.name}</a>
248
- );
249
- }
250
- }
171
+ >
172
+ {
173
+ icon.count < 100 ? icon.count : "+99"
174
+ }
175
+ </div>
176
+ }
177
+ {
178
+ icon.children
179
+ }
180
+ </div>
181
+ )
182
+ }
183
+ </div>
184
+ }
185
+ <div className={Styles.ns_navbar_menu_icon} onClick={this.handleShowNavbar}>
186
+ <img
187
+ src=
188
+ {
189
+ this.state.showNavbar ?
190
+ "https://static.namirasoft.com/image/concept/close/white.svg"
191
+ : "https://static.namirasoft.com/image/concept/menu/burger-white.svg"
192
+ }
193
+ alt="Menu Icon"
194
+ width={24}
195
+ height={24}
196
+ />
197
+ </div>
198
+ </div>
199
+ </div>
200
+ </nav>
201
+ </header>
202
+ );
203
+ }
204
+ private render_menu(level: number, parent_id: number | null)
205
+ {
206
+ let fs: FilterLinkFullRow[] = this.getFilters().filter(f => f.parent_id === parent_id);
207
+ return (
208
+ <div className={`me-auto nav ${Styles.ns_navbar_items_container}`} >
209
+ {(fs?.map(f => this.render_menuItem(level, f)))}
210
+ </div>
211
+ );
212
+ }
213
+ private render_menuItem(level: number, filter: FilterLinkFullRow)
214
+ {
215
+ if (this.hasChild(filter.id))
216
+ {
217
+ let sub_menus = <></>;
218
+ if (level === 0)
219
+ if (this.state.selected)
220
+ {
221
+ sub_menus =
222
+ <div
223
+ id={`dropdown_items${filter.id}`}>
224
+ {this.render_menu(1, this.state.selected.id)}
225
+ </div >
226
+ }
227
+ return <NavDropdown
228
+ onToggle={(checked) => this.onMenuItemToggled(checked, filter)}
229
+ className={level === 0 ? Styles.ns_navbar_first_level_item : Styles.ns_navbar_second_level_item}
230
+ title={filter.name}
231
+ key={filter.id}
232
+ id={`dropdown_parent${filter.id}`}>
233
+ {sub_menus}
234
+ </NavDropdown >;
235
+ }
236
+ else
237
+ {
238
+ let href = filter.link?.url;
239
+ if (process.env.REACT_APP_STANDALONE)
240
+ if (href)
241
+ {
242
+ let url = new URL(href);
243
+ url.host = window.location.host;
244
+ url.protocol = window.location.protocol;
245
+ href = url.toString();
246
+ }
247
+ return (
248
+ <a key={filter.id} className={`${Styles.ns_navbar_items_link} ${level === 0 ? Styles.ns_navbar_first_level_item : Styles.ns_navbar_second_level_item}`} href={href}>{filter.name}</a>
249
+ );
250
+ }
251
+ }
251
252
  }
@@ -11,6 +11,7 @@ import { INSBarTitleProps, NSBarTitle } from './NSBarTitle';
11
11
  import { NSSpace, NSSpaceSizeType } from './NSSpace';
12
12
  import { INSRouterProps } from '../routing/INSRouterProps';
13
13
  import { INSBarAlertProps, NSBarAlert } from './NSBarAlert';
14
+ import { generateUniqId } from '../utils/generateUniqId';
14
15
 
15
16
  export interface INSLayoutProps extends IBaseComponentProps, INSRouterProps
16
17
  {
@@ -70,8 +71,8 @@ export function NSLayout(props: INSLayoutProps)
70
71
  props.notifications.length !== 0 &&
71
72
  <>
72
73
  {
73
- props.notifications.map((notification, index) =>
74
- <Fragment key={index}>
74
+ props.notifications.map((notification) =>
75
+ <Fragment key={generateUniqId()}>
75
76
  <NSBarNotification {...notification} />
76
77
  </Fragment>
77
78
  )
@@ -79,7 +80,7 @@ export function NSLayout(props: INSLayoutProps)
79
80
  </>
80
81
  }
81
82
  {
82
- alerts.length !== 0 && alerts.map((alert, index) => <NSBarAlert key={index} {...alert} />)
83
+ alerts.length !== 0 && alerts.map((alert) => <NSBarAlert key={generateUniqId()} {...alert} />)
83
84
  }
84
85
  {
85
86
  isValidAction(props.action) && <NSBarAction {...props.action} />
@@ -3,6 +3,7 @@ import Styles from './NSRange.module.css';
3
3
  import { IBaseComponentProps } from '../props/IBaseComponentProps';
4
4
 
5
5
  import { Color } from "../Color";
6
+ import { generateUniqId } from '../utils/generateUniqId';
6
7
 
7
8
  export interface NSRangeRow
8
9
  {
@@ -60,7 +61,7 @@ export function NSRange(props: INSRangeProps)
60
61
  {
61
62
  props.data?.map((data, index) =>
62
63
  <span
63
- key={index}
64
+ key={generateUniqId()}
64
65
  className={Styles.ns_range_time_line}
65
66
  style={{
66
67
  background: Color.getColor(data?.percentage),
@@ -1,4 +1,5 @@
1
1
  import { Component, createRef, Fragment, ReactNode } from 'react';
2
+ import { generateUniqId } from '../utils/generateUniqId';
2
3
 
3
4
  export interface NSRepeaterProps<ItemType, ValueType>
4
5
  {
@@ -166,7 +167,7 @@ export class NSRepeater<ItemType, ValueType> extends Component<NSRepeaterProps<I
166
167
  {
167
168
  if (this.state.items[index])
168
169
  return this.props.createItem(i++, ref, this.onChange, this.onDelete);
169
- return <Fragment key={index}></Fragment>;
170
+ return <Fragment key={generateUniqId()}></Fragment>;
170
171
  }
171
172
  )
172
173
  }