norma-library 0.6.76 → 0.6.78

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 (36) hide show
  1. package/.storybook/preview.ts +5 -0
  2. package/dist/esm/components/Modal.js +1 -1
  3. package/dist/esm/components/Modal.js.map +1 -1
  4. package/dist/esm/components/Tabs.js +1 -1
  5. package/dist/esm/components/Tabs.js.map +1 -1
  6. package/dist/esm/components/UncontrolledTable/components/index.d.ts +4 -2
  7. package/dist/esm/components/UncontrolledTable/components/index.js +4 -2
  8. package/dist/esm/components/UncontrolledTable/components/index.js.map +1 -1
  9. package/dist/esm/components/UncontrolledTable/components/row/DraggableRow.d.ts +3 -0
  10. package/dist/esm/components/UncontrolledTable/components/row/DraggableRow.js +23 -0
  11. package/dist/esm/components/UncontrolledTable/components/row/DraggableRow.js.map +1 -0
  12. package/dist/esm/components/UncontrolledTable/components/row/RowDragHandleCell.d.ts +3 -0
  13. package/dist/esm/components/UncontrolledTable/components/row/RowDragHandleCell.js +15 -0
  14. package/dist/esm/components/UncontrolledTable/components/row/RowDragHandleCell.js.map +1 -0
  15. package/dist/esm/components/UncontrolledTable/components/row/SimpleRow.d.ts +3 -0
  16. package/dist/esm/components/UncontrolledTable/components/row/SimpleRow.js +13 -0
  17. package/dist/esm/components/UncontrolledTable/components/row/SimpleRow.js.map +1 -0
  18. package/dist/esm/components/UncontrolledTable/components/row/styles.d.ts +2 -0
  19. package/dist/esm/components/UncontrolledTable/components/row/styles.js +12 -0
  20. package/dist/esm/components/UncontrolledTable/components/row/styles.js.map +1 -0
  21. package/dist/esm/components/UncontrolledTable/index.js +86 -50
  22. package/dist/esm/components/UncontrolledTable/index.js.map +1 -1
  23. package/dist/esm/components/UncontrolledTable/interface.d.ts +6 -4
  24. package/package.json +4 -1
  25. package/src/components/Modal.tsx +1 -1
  26. package/src/components/Tabs.tsx +1 -1
  27. package/src/components/UncontrolledTable/components/index.tsx +6 -2
  28. package/src/components/UncontrolledTable/components/row/DraggableRow.tsx +34 -0
  29. package/src/components/UncontrolledTable/components/row/RowDragHandleCell.tsx +17 -0
  30. package/src/components/UncontrolledTable/components/row/SimpleRow.tsx +26 -0
  31. package/src/components/UncontrolledTable/index.tsx +191 -105
  32. package/src/components/UncontrolledTable/interface.ts +6 -4
  33. package/src/stories/ModalStatus.stories.tsx +1 -0
  34. package/src/stories/UncontrolledTable.stories.tsx +464 -206
  35. package/src/components/UncontrolledTable/components/tbody/index.tsx +0 -33
  36. /package/src/components/UncontrolledTable/components/{tbody → row}/styles.tsx +0 -0
@@ -10,7 +10,21 @@ import {
10
10
  TableOptions,
11
11
  } from '@tanstack/react-table';
12
12
 
13
- import { Pagination, Header, TBody } from './components';
13
+ import {
14
+ DndContext,
15
+ MouseSensor,
16
+ closestCenter,
17
+ type DragEndEvent,
18
+ type UniqueIdentifier,
19
+ useSensor,
20
+ useSensors,
21
+ TouchSensor,
22
+ KeyboardSensor,
23
+ } from '@dnd-kit/core';
24
+ import { restrictToVerticalAxis } from '@dnd-kit/modifiers';
25
+ import { arrayMove, SortableContext, verticalListSortingStrategy } from '@dnd-kit/sortable';
26
+
27
+ import { Pagination, Header, SimpleRow, DraggableRow, RowDragHandleCell } from './components';
14
28
  import { UncontrolledTableProps } from './interface';
15
29
  import useClickOutside from '../../hooks/useClickOutside';
16
30
 
@@ -35,6 +49,8 @@ const UncontrolledTable = (props: UncontrolledTableProps) => {
35
49
  tableClassName,
36
50
  stickyHeader,
37
51
  stickyHeaderP,
52
+ draggable,
53
+ onDragEnd,
38
54
  } = props;
39
55
 
40
56
  const [openFilterDialog, setOpenFilterDialog] = useState('');
@@ -44,10 +60,27 @@ const UncontrolledTable = (props: UncontrolledTableProps) => {
44
60
  const [orderSmallest, setOrderSmallest] = useState(false);
45
61
  const [orderLargest, setOrderLargest] = useState(false);
46
62
 
63
+ const _columns: any[] = useMemo(() => {
64
+ return draggable
65
+ ? [
66
+ {
67
+ id: 'drag',
68
+ header: '',
69
+ cell: ({ row }: { row: any }) => <RowDragHandleCell rowId={row.id}/>,
70
+ disableMenu: true,
71
+ },
72
+ ...columns.map((column) => ({
73
+ ...column,
74
+ disableMenu: true,
75
+ })),
76
+ ]
77
+ : columns;
78
+ }, [columns]);
79
+
47
80
  const reactTableConfig = useMemo(() => {
48
81
  const config: TableOptions<unknown> = {
49
- columns: columns as any,
50
82
  data,
83
+ columns: _columns,
51
84
  state: {
52
85
  sorting: sorting,
53
86
  columnFilters: filterByColumn,
@@ -59,16 +92,40 @@ const UncontrolledTable = (props: UncontrolledTableProps) => {
59
92
  onSortingChange: setSorting,
60
93
  onColumnFiltersChange: setFilterByColumn,
61
94
  manualPagination: true,
95
+ getRowId: (row: any) => row.id,
96
+ debugTable: true,
97
+ debugHeaders: true,
98
+ debugColumns: true,
62
99
  };
63
100
 
64
101
  return config;
65
- }, [data, sorting, filterByColumn, columns, pagination]);
102
+ }, [data, sorting, filterByColumn, _columns, pagination]);
66
103
 
67
104
  const table = useReactTable(reactTableConfig);
68
105
  const filterRef = useRef<HTMLDivElement>(null);
69
106
 
70
107
  useClickOutside(filterRef, () => setOpenFilterDialog(''));
71
108
 
109
+ const handleDragEnd = (event: DragEndEvent) => {
110
+ const { active, over } = event;
111
+
112
+
113
+ if (active && over && active.id !== over.id && onDragEnd) {
114
+ const oldIndex = dataIds.indexOf(active.id);
115
+ const newIndex = dataIds.indexOf(over.id);
116
+
117
+ const _data = arrayMove(data, oldIndex, newIndex);
118
+ onDragEnd(_data);
119
+ }
120
+ };
121
+
122
+ const sensors = useSensors(useSensor(MouseSensor, {}), useSensor(TouchSensor, {}), useSensor(KeyboardSensor, {}));
123
+
124
+ const dataIds = useMemo<UniqueIdentifier[]>(
125
+ () => data?.map((item: { id: UniqueIdentifier }) => item.id) || [],
126
+ [data],
127
+ );
128
+
72
129
  return (
73
130
  <S.Container>
74
131
  <Header
@@ -89,128 +146,157 @@ const UncontrolledTable = (props: UncontrolledTableProps) => {
89
146
  hideColumns={props.hideColumns}
90
147
  onColumnVisibilityChange={props.onColumnVisibilityChange}
91
148
  />
92
- <S.Table className={tableClassName || ''}>
93
- <S.Thead $sticky={stickyHeader} $stickyTopP={stickyHeaderP}>
94
- {table.getHeaderGroups().map((headerGroup: any) => (
95
- <S.TableRow key={headerGroup.id}>
96
- {headerGroup.headers.map((header: any) => (
97
- <S.Th key={header.id}>
98
- <S.ColumnContent
99
- onClick={() => {
100
- if (!header?.column?.columnDef?.disableMenu)
101
- setOpenFilterDialog(header.column.columnDef.accessorKey);
102
- }}
103
- >
104
- <S.TextColumn>
105
- {!header.isPlaceholder && flexRender(header.column.columnDef.header, header.getContext())}
106
- </S.TextColumn>
107
- {!header?.column?.columnDef?.disableMenu && (
108
- <S.IconFilterDialog>
109
- <svg fill="#666" focusable="false" aria-hidden="true" viewBox="0 0 24 24">
110
- <path d="m7 10 5 5 5-5z" />
111
- </svg>
112
- </S.IconFilterDialog>
113
- )}
114
- </S.ColumnContent>
115
- {openFilterDialog === header.column.columnDef.accessorKey && (
116
- <S.FilterDialog ref={filterRef}>
117
- <S.ListFilterDialog>
118
- <S.OptionFilterDialog
119
- style={{
120
- background: orderSmallest ? 'rgba(0, 0, 0, 0.04)' : '',
121
- }}
122
- onClick={() => {
123
- onSortClick && onSortClick(header.column.columnDef.accessorKey, 'asc');
124
- setOpenFilterDialog('');
125
- }}
126
- >
127
- <div className="icon">
128
- <svg
129
- fill="#666"
130
- stroke="currentColor"
131
- strokeWidth="1.5"
132
- viewBox="0 0 24 24"
133
- xmlns="http://www.w3.org/2000/svg"
134
- aria-hidden="true"
135
- width="20"
136
- height="20"
137
- >
138
- <path
139
- strokeLinecap="round"
140
- strokeLinejoin="round"
141
- d="M12 4.5v15m0 0l6.75-6.75M12 19.5l-6.75-6.75"
142
- />
143
- </svg>
144
- </div>
145
- <p>{labels?.orderAsc || 'Menor primeiro'}</p>
146
- </S.OptionFilterDialog>
147
- <S.OptionFilterDialog
148
- style={{
149
- background: orderLargest ? 'rgba(0, 0, 0, 0.04)' : '',
150
- }}
151
- onClick={() => {
152
- onSortClick && onSortClick(header.column.columnDef.accessorKey, 'desc');
153
- setOpenFilterDialog('');
154
- }}
155
- >
156
- <div className="icon rotate">
157
- <svg
158
- fill="#666"
159
- stroke="currentColor"
160
- strokeWidth="1.5"
161
- viewBox="0 0 24 24"
162
- xmlns="http://www.w3.org/2000/svg"
163
- aria-hidden="true"
164
- width="20"
165
- height="20"
166
- >
167
- <path
168
- strokeLinecap="round"
169
- strokeLinejoin="round"
170
- d="M12 4.5v15m0 0l6.75-6.75M12 19.5l-6.75-6.75"
171
- ></path>
172
- </svg>
173
- </div>
174
- <p>{labels?.orderDesc || 'Maior primeiro'}</p>
175
- </S.OptionFilterDialog>
176
- {!header?.column?.columnDef?.nofilter && (
149
+ <DndContext
150
+ collisionDetection={closestCenter}
151
+ modifiers={[restrictToVerticalAxis]}
152
+ onDragEnd={handleDragEnd}
153
+ sensors={sensors}
154
+ >
155
+ <S.Table className={tableClassName || ''}>
156
+ <S.Thead $sticky={stickyHeader} $stickyTopP={stickyHeaderP}>
157
+ {table.getHeaderGroups().map((headerGroup: any) => (
158
+ <S.TableRow key={headerGroup.id}>
159
+ {headerGroup.headers.map((header: any) => (
160
+ <S.Th key={header.id}>
161
+ <S.ColumnContent
162
+ onClick={() => {
163
+ if (!header?.column?.columnDef?.disableMenu)
164
+ setOpenFilterDialog(header.column.columnDef.accessorKey);
165
+ }}
166
+ >
167
+ <S.TextColumn>
168
+ {!header.isPlaceholder && flexRender(header.column.columnDef.header, header.getContext())}
169
+ </S.TextColumn>
170
+ {!header?.column?.columnDef?.disableMenu && (
171
+ <S.IconFilterDialog>
172
+ <svg fill="#666" focusable="false" aria-hidden="true" viewBox="0 0 24 24">
173
+ <path d="m7 10 5 5 5-5z" />
174
+ </svg>
175
+ </S.IconFilterDialog>
176
+ )}
177
+ </S.ColumnContent>
178
+ {openFilterDialog === header.column.columnDef.accessorKey && (
179
+ <S.FilterDialog ref={filterRef}>
180
+ <S.ListFilterDialog>
177
181
  <S.OptionFilterDialog
182
+ style={{
183
+ background: orderSmallest ? 'rgba(0, 0, 0, 0.04)' : '',
184
+ }}
178
185
  onClick={() => {
179
- onFilterClick && onFilterClick(header.column.columnDef.accessorKey);
186
+ onSortClick && onSortClick(header.column.columnDef.accessorKey, 'asc');
180
187
  setOpenFilterDialog('');
181
188
  }}
182
189
  >
183
190
  <div className="icon">
184
191
  <svg
185
- fill="none"
192
+ fill="#666"
186
193
  stroke="currentColor"
187
194
  strokeWidth="1.5"
188
195
  viewBox="0 0 24 24"
189
196
  xmlns="http://www.w3.org/2000/svg"
190
197
  aria-hidden="true"
191
- width="16"
192
- height="16"
198
+ width="20"
199
+ height="20"
193
200
  >
194
201
  <path
195
202
  strokeLinecap="round"
196
203
  strokeLinejoin="round"
197
- d="M12 3c2.755 0 5.455.232 8.083.678.533.09.917.556.917 1.096v1.044a2.25 2.25 0 01-.659 1.591l-5.432 5.432a2.25 2.25 0 00-.659 1.591v2.927a2.25 2.25 0 01-1.244 2.013L9.75 21v-6.568a2.25 2.25 0 00-.659-1.591L3.659 7.409A2.25 2.25 0 013 5.818V4.774c0-.54.384-1.006.917-1.096A48.32 48.32 0 0112 3z"
204
+ d="M12 4.5v15m0 0l6.75-6.75M12 19.5l-6.75-6.75"
205
+ />
206
+ </svg>
207
+ </div>
208
+ <p>{labels?.orderAsc || 'Menor primeiro'}</p>
209
+ </S.OptionFilterDialog>
210
+ <S.OptionFilterDialog
211
+ style={{
212
+ background: orderLargest ? 'rgba(0, 0, 0, 0.04)' : '',
213
+ }}
214
+ onClick={() => {
215
+ onSortClick && onSortClick(header.column.columnDef.accessorKey, 'desc');
216
+ setOpenFilterDialog('');
217
+ }}
218
+ >
219
+ <div className="icon rotate">
220
+ <svg
221
+ fill="#666"
222
+ stroke="currentColor"
223
+ strokeWidth="1.5"
224
+ viewBox="0 0 24 24"
225
+ xmlns="http://www.w3.org/2000/svg"
226
+ aria-hidden="true"
227
+ width="20"
228
+ height="20"
229
+ >
230
+ <path
231
+ strokeLinecap="round"
232
+ strokeLinejoin="round"
233
+ d="M12 4.5v15m0 0l6.75-6.75M12 19.5l-6.75-6.75"
198
234
  ></path>
199
235
  </svg>
200
236
  </div>
201
- <p>{labels?.filter || 'Filtrar por'}</p>
237
+ <p>{labels?.orderDesc || 'Maior primeiro'}</p>
202
238
  </S.OptionFilterDialog>
203
- )}
204
- </S.ListFilterDialog>
205
- </S.FilterDialog>
206
- )}
207
- </S.Th>
208
- ))}
209
- </S.TableRow>
210
- ))}
211
- </S.Thead>
212
- <TBody table={table} onClick={onClick} onMouseOver={onMouseOver} onMouseOut={onMouseOut} />
213
- </S.Table>
239
+ {!header?.column?.columnDef?.nofilter && (
240
+ <S.OptionFilterDialog
241
+ onClick={() => {
242
+ onFilterClick && onFilterClick(header.column.columnDef.accessorKey);
243
+ setOpenFilterDialog('');
244
+ }}
245
+ >
246
+ <div className="icon">
247
+ <svg
248
+ fill="none"
249
+ stroke="currentColor"
250
+ strokeWidth="1.5"
251
+ viewBox="0 0 24 24"
252
+ xmlns="http://www.w3.org/2000/svg"
253
+ aria-hidden="true"
254
+ width="16"
255
+ height="16"
256
+ >
257
+ <path
258
+ strokeLinecap="round"
259
+ strokeLinejoin="round"
260
+ d="M12 3c2.755 0 5.455.232 8.083.678.533.09.917.556.917 1.096v1.044a2.25 2.25 0 01-.659 1.591l-5.432 5.432a2.25 2.25 0 00-.659 1.591v2.927a2.25 2.25 0 01-1.244 2.013L9.75 21v-6.568a2.25 2.25 0 00-.659-1.591L3.659 7.409A2.25 2.25 0 013 5.818V4.774c0-.54.384-1.006.917-1.096A48.32 48.32 0 0112 3z"
261
+ ></path>
262
+ </svg>
263
+ </div>
264
+ <p>{labels?.filter || 'Filtrar por'}</p>
265
+ </S.OptionFilterDialog>
266
+ )}
267
+ </S.ListFilterDialog>
268
+ </S.FilterDialog>
269
+ )}
270
+ </S.Th>
271
+ ))}
272
+ </S.TableRow>
273
+ ))}
274
+ </S.Thead>
275
+ <tbody>
276
+ <SortableContext items={dataIds} strategy={verticalListSortingStrategy}>
277
+ {table.getRowModel().rows.map((row: any) => {
278
+ return draggable ? (
279
+ <DraggableRow
280
+ key={row.id}
281
+ row={row}
282
+ onClick={onClick}
283
+ onMouseOver={onMouseOver}
284
+ onMouseOut={onMouseOut}
285
+ />
286
+ ) : (
287
+ <SimpleRow
288
+ key={row.id}
289
+ row={row}
290
+ onClick={onClick}
291
+ onMouseOver={onMouseOver}
292
+ onMouseOut={onMouseOut}
293
+ />
294
+ );
295
+ })}
296
+ </SortableContext>
297
+ </tbody>
298
+ </S.Table>
299
+ </DndContext>
214
300
  {pagination && (
215
301
  <Pagination
216
302
  pagination={pagination}
@@ -24,17 +24,19 @@ export interface UncontrolledTableProps {
24
24
  totalPages: number;
25
25
  showClearFields?: boolean;
26
26
  customTotalResults?: string;
27
- onChangePage: (pagination: Pagination) => void;
28
- onClearFieldsClick?: () => void;
29
- onFilterClick?: (column: string) => void;
30
- onSortClick?: (column: string, direction: string) => void;
31
27
  labels?: Labels;
32
28
  tableClassName?: string;
33
29
  stickyHeader?: boolean;
34
30
  stickyHeaderP?: number;
35
31
  customIcons?: React.ReactNode[];
36
32
  hideColumns?: string[];
33
+ draggable?: boolean;
34
+ onChangePage: (pagination: Pagination) => void;
35
+ onClearFieldsClick?: () => void;
36
+ onFilterClick?: (column: string) => void;
37
+ onSortClick?: (column: string, direction: string) => void;
37
38
  onColumnVisibilityChange?: (columnId: string, isVisible: boolean) => void;
39
+ onDragEnd?: (data: any[]) => void;
38
40
  }
39
41
 
40
42
  export interface ColumnsTable {
@@ -11,6 +11,7 @@ const actions: OnAction[] = [
11
11
  },
12
12
  {
13
13
  label: 'Entendi',
14
+ variant: 'contained',
14
15
  action: () => {},
15
16
  },
16
17
  ];