@postxl/generators 1.1.0 → 1.2.0

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 (169) hide show
  1. package/dist/backend-core/template/apps/api/src/e2e.ts +13 -4
  2. package/dist/e2e/e2e.generator.js +2 -14
  3. package/dist/e2e/e2e.generator.js.map +1 -1
  4. package/dist/e2e/generators/docker-sh.generator.d.ts +2 -0
  5. package/dist/e2e/generators/docker-sh.generator.js +25 -0
  6. package/dist/e2e/generators/docker-sh.generator.js.map +1 -0
  7. package/dist/frontend-core/frontend.generator.d.ts +0 -58
  8. package/dist/frontend-core/frontend.generator.js +6 -172
  9. package/dist/frontend-core/frontend.generator.js.map +1 -1
  10. package/dist/frontend-core/template/README.md +1 -1
  11. package/dist/frontend-core/template/src/components/admin/table-filter.tsx +1 -5
  12. package/dist/frontend-core/template/src/components/ui/color-mode-toggle/color-mode-toggle.tsx +10 -4
  13. package/dist/frontend-core/template/src/context-providers/auth-context-provider.tsx +2 -5
  14. package/dist/frontend-core/template/src/pages/dashboard/dashboard.page.tsx +2 -3
  15. package/dist/frontend-core/template/src/pages/error/default-error.page.tsx +1 -1
  16. package/dist/frontend-core/template/src/pages/error/not-found-error.page.tsx +1 -1
  17. package/dist/frontend-core/template/src/styles/styles.css +13 -1
  18. package/dist/frontend-core/template/tsconfig.json +2 -0
  19. package/dist/frontend-core/types/component.d.ts +1 -1
  20. package/dist/frontend-forms/generators/discriminated-union/fields.generator.js +4 -6
  21. package/dist/frontend-forms/generators/discriminated-union/fields.generator.js.map +1 -1
  22. package/dist/frontend-forms/generators/discriminated-union/inputs.generator.js +1 -1
  23. package/dist/frontend-forms/generators/discriminated-union/inputs.generator.js.map +1 -1
  24. package/dist/frontend-forms/generators/enum/inputs.generator.js +1 -1
  25. package/dist/frontend-forms/generators/enum/inputs.generator.js.map +1 -1
  26. package/dist/frontend-forms/generators/model/forms.generator.js +8 -12
  27. package/dist/frontend-forms/generators/model/forms.generator.js.map +1 -1
  28. package/dist/frontend-forms/generators/model/inputs.generator.js +2 -6
  29. package/dist/frontend-forms/generators/model/inputs.generator.js.map +1 -1
  30. package/dist/frontend-forms/template/src/components/ui/field/field.tsx +1 -4
  31. package/dist/frontend-tables/generators/model-table.generator.js +1 -5
  32. package/dist/frontend-tables/generators/model-table.generator.js.map +1 -1
  33. package/package.json +3 -2
  34. package/dist/e2e/template/scripts/docker.sh +0 -17
  35. package/dist/frontend-core/template/src/components/ui/accordion/accordion.stories.tsx +0 -47
  36. package/dist/frontend-core/template/src/components/ui/accordion/accordion.tsx +0 -52
  37. package/dist/frontend-core/template/src/components/ui/admin-sidebar/admin-sidebar.tsx +0 -195
  38. package/dist/frontend-core/template/src/components/ui/alert/alert.stories.tsx +0 -61
  39. package/dist/frontend-core/template/src/components/ui/alert/alert.tsx +0 -45
  40. package/dist/frontend-core/template/src/components/ui/alert-dialog/alert-dialog.stories.tsx +0 -52
  41. package/dist/frontend-core/template/src/components/ui/alert-dialog/alert-dialog.tsx +0 -105
  42. package/dist/frontend-core/template/src/components/ui/avatar/avatar.stories.tsx +0 -30
  43. package/dist/frontend-core/template/src/components/ui/avatar/avatar.tsx +0 -39
  44. package/dist/frontend-core/template/src/components/ui/badge/badge.stories.tsx +0 -78
  45. package/dist/frontend-core/template/src/components/ui/badge/badge.tsx +0 -48
  46. package/dist/frontend-core/template/src/components/ui/breadcrumb/breadcrumb.stories.tsx +0 -67
  47. package/dist/frontend-core/template/src/components/ui/breadcrumb/breadcrumb.tsx +0 -85
  48. package/dist/frontend-core/template/src/components/ui/button/button.stories.tsx +0 -150
  49. package/dist/frontend-core/template/src/components/ui/button/button.tsx +0 -68
  50. package/dist/frontend-core/template/src/components/ui/calendar/calendar.stories.tsx +0 -160
  51. package/dist/frontend-core/template/src/components/ui/calendar/calendar.tsx +0 -293
  52. package/dist/frontend-core/template/src/components/ui/card/card.stories.tsx +0 -77
  53. package/dist/frontend-core/template/src/components/ui/card/card.tsx +0 -45
  54. package/dist/frontend-core/template/src/components/ui/card-hover/card-hover.stories.tsx +0 -29
  55. package/dist/frontend-core/template/src/components/ui/card-hover/card-hover.tsx +0 -28
  56. package/dist/frontend-core/template/src/components/ui/carousel/carousel.stories.tsx +0 -154
  57. package/dist/frontend-core/template/src/components/ui/carousel/carousel.tsx +0 -227
  58. package/dist/frontend-core/template/src/components/ui/checkbox/checkbox.stories.tsx +0 -106
  59. package/dist/frontend-core/template/src/components/ui/checkbox/checkbox.tsx +0 -88
  60. package/dist/frontend-core/template/src/components/ui/checkbox/shadcn-checkbox.stories.tsx +0 -90
  61. package/dist/frontend-core/template/src/components/ui/checkbox/shadcn-checkbox.tsx +0 -54
  62. package/dist/frontend-core/template/src/components/ui/collapse/collapse.stories.tsx +0 -52
  63. package/dist/frontend-core/template/src/components/ui/collapse/collapse.tsx +0 -9
  64. package/dist/frontend-core/template/src/components/ui/combobox/combobox.stories.tsx +0 -207
  65. package/dist/frontend-core/template/src/components/ui/combobox/combobox.tsx +0 -79
  66. package/dist/frontend-core/template/src/components/ui/command/command.stories.tsx +0 -186
  67. package/dist/frontend-core/template/src/components/ui/command/command.tsx +0 -165
  68. package/dist/frontend-core/template/src/components/ui/command-palette/command-palette.stories.tsx +0 -160
  69. package/dist/frontend-core/template/src/components/ui/command-palette/command-palette.tsx +0 -134
  70. package/dist/frontend-core/template/src/components/ui/content-frame/content-frame.stories.tsx +0 -198
  71. package/dist/frontend-core/template/src/components/ui/content-frame/content-frame.tsx +0 -100
  72. package/dist/frontend-core/template/src/components/ui/context-menu/context-menu.stories.tsx +0 -78
  73. package/dist/frontend-core/template/src/components/ui/context-menu/context-menu.tsx +0 -179
  74. package/dist/frontend-core/template/src/components/ui/data-grid/cell-variants/cell-variant-types.ts +0 -11
  75. package/dist/frontend-core/template/src/components/ui/data-grid/cell-variants/checkbox-cell.tsx +0 -116
  76. package/dist/frontend-core/template/src/components/ui/data-grid/cell-variants/date-cell.tsx +0 -157
  77. package/dist/frontend-core/template/src/components/ui/data-grid/cell-variants/gantt-cell.tsx +0 -82
  78. package/dist/frontend-core/template/src/components/ui/data-grid/cell-variants/long-text-cell.tsx +0 -180
  79. package/dist/frontend-core/template/src/components/ui/data-grid/cell-variants/multi-select-cell.tsx +0 -280
  80. package/dist/frontend-core/template/src/components/ui/data-grid/cell-variants/number-cell.tsx +0 -169
  81. package/dist/frontend-core/template/src/components/ui/data-grid/cell-variants/react-node-cell.tsx +0 -33
  82. package/dist/frontend-core/template/src/components/ui/data-grid/cell-variants/select-cell.tsx +0 -175
  83. package/dist/frontend-core/template/src/components/ui/data-grid/cell-variants/short-text-cell.tsx +0 -138
  84. package/dist/frontend-core/template/src/components/ui/data-grid/cell-variants/utils/gantt-timeline.tsx +0 -92
  85. package/dist/frontend-core/template/src/components/ui/data-grid/cell-variants/utils/gantt-timerange-picker.tsx +0 -330
  86. package/dist/frontend-core/template/src/components/ui/data-grid/data-grid-cell-wrapper.tsx +0 -212
  87. package/dist/frontend-core/template/src/components/ui/data-grid/data-grid-cell.tsx +0 -157
  88. package/dist/frontend-core/template/src/components/ui/data-grid/data-grid-column-header.tsx +0 -340
  89. package/dist/frontend-core/template/src/components/ui/data-grid/data-grid-context-menu.tsx +0 -271
  90. package/dist/frontend-core/template/src/components/ui/data-grid/data-grid-row.tsx +0 -123
  91. package/dist/frontend-core/template/src/components/ui/data-grid/data-grid-search.tsx +0 -211
  92. package/dist/frontend-core/template/src/components/ui/data-grid/data-grid-types.ts +0 -159
  93. package/dist/frontend-core/template/src/components/ui/data-grid/data-grid-utils.ts +0 -67
  94. package/dist/frontend-core/template/src/components/ui/data-grid/data-grid-view-menu.tsx +0 -360
  95. package/dist/frontend-core/template/src/components/ui/data-grid/data-grid.stories.tsx +0 -780
  96. package/dist/frontend-core/template/src/components/ui/data-grid/data-grid.tsx +0 -217
  97. package/dist/frontend-core/template/src/components/ui/data-grid/hooks/use-callback-ref.ts +0 -22
  98. package/dist/frontend-core/template/src/components/ui/data-grid/hooks/use-data-grid.tsx +0 -1892
  99. package/dist/frontend-core/template/src/components/ui/data-grid/hooks/use-debounced-callback.ts +0 -19
  100. package/dist/frontend-core/template/src/components/ui/data-grid/styles.css +0 -3
  101. package/dist/frontend-core/template/src/components/ui/data-table/context-menu-simple.tsx +0 -141
  102. package/dist/frontend-core/template/src/components/ui/data-table/data-table.stories.tsx +0 -146
  103. package/dist/frontend-core/template/src/components/ui/data-table/data-table.tsx +0 -447
  104. package/dist/frontend-core/template/src/components/ui/data-table/renderers/country-array-cell-renderer.tsx +0 -77
  105. package/dist/frontend-core/template/src/components/ui/data-table/renderers/country-cell-renderer.tsx +0 -56
  106. package/dist/frontend-core/template/src/components/ui/data-table/renderers/favorite-cell-renderer.tsx +0 -68
  107. package/dist/frontend-core/template/src/components/ui/data-table/renderers/links-cell-renderer.tsx +0 -205
  108. package/dist/frontend-core/template/src/components/ui/data-table/utils/columns.ts +0 -351
  109. package/dist/frontend-core/template/src/components/ui/data-table/utils/data-table.utils.ts +0 -49
  110. package/dist/frontend-core/template/src/components/ui/date-picker/date-picker.stories.tsx +0 -149
  111. package/dist/frontend-core/template/src/components/ui/date-picker/date-picker.tsx +0 -30
  112. package/dist/frontend-core/template/src/components/ui/dialog/dialog.stories.tsx +0 -80
  113. package/dist/frontend-core/template/src/components/ui/dialog/dialog.tsx +0 -134
  114. package/dist/frontend-core/template/src/components/ui/drawer/drawer.stories.tsx +0 -104
  115. package/dist/frontend-core/template/src/components/ui/drawer/drawer.tsx +0 -87
  116. package/dist/frontend-core/template/src/components/ui/dropdown-menu/dropdown-menu.stories.tsx +0 -168
  117. package/dist/frontend-core/template/src/components/ui/dropdown-menu/dropdown-menu.tsx +0 -225
  118. package/dist/frontend-core/template/src/components/ui/input/input.stories.tsx +0 -141
  119. package/dist/frontend-core/template/src/components/ui/input/input.tsx +0 -47
  120. package/dist/frontend-core/template/src/components/ui/label/label.stories.tsx +0 -41
  121. package/dist/frontend-core/template/src/components/ui/label/label.tsx +0 -20
  122. package/dist/frontend-core/template/src/components/ui/loader/loader.stories.tsx +0 -45
  123. package/dist/frontend-core/template/src/components/ui/loader/loader.tsx +0 -17
  124. package/dist/frontend-core/template/src/components/ui/mark-value-renderer/mark-value-renderer.stories.tsx +0 -114
  125. package/dist/frontend-core/template/src/components/ui/mark-value-renderer/mark-value-renderer.tsx +0 -48
  126. package/dist/frontend-core/template/src/components/ui/menubar/menu.stories.tsx +0 -134
  127. package/dist/frontend-core/template/src/components/ui/menubar/menubar.tsx +0 -208
  128. package/dist/frontend-core/template/src/components/ui/modal/modal.stories.tsx +0 -297
  129. package/dist/frontend-core/template/src/components/ui/modal/modal.tsx +0 -80
  130. package/dist/frontend-core/template/src/components/ui/navigation-menu/navigation-menu.stories.tsx +0 -213
  131. package/dist/frontend-core/template/src/components/ui/navigation-menu/navigation-menu.tsx +0 -142
  132. package/dist/frontend-core/template/src/components/ui/pagination/pagination.stories.tsx +0 -49
  133. package/dist/frontend-core/template/src/components/ui/pagination/pagination.tsx +0 -84
  134. package/dist/frontend-core/template/src/components/ui/popover/popover.stories.tsx +0 -82
  135. package/dist/frontend-core/template/src/components/ui/popover/popover.tsx +0 -55
  136. package/dist/frontend-core/template/src/components/ui/progress/progress.stories.tsx +0 -80
  137. package/dist/frontend-core/template/src/components/ui/progress/progress.tsx +0 -17
  138. package/dist/frontend-core/template/src/components/ui/radio-group/radio-group.stories.tsx +0 -154
  139. package/dist/frontend-core/template/src/components/ui/radio-group/radio-group.tsx +0 -68
  140. package/dist/frontend-core/template/src/components/ui/resizable/resizable.stories.tsx +0 -73
  141. package/dist/frontend-core/template/src/components/ui/resizable/resizeable.tsx +0 -38
  142. package/dist/frontend-core/template/src/components/ui/scroll-area/scroll-area.stories.tsx +0 -55
  143. package/dist/frontend-core/template/src/components/ui/scroll-area/scroll-area.tsx +0 -39
  144. package/dist/frontend-core/template/src/components/ui/select/select.stories.tsx +0 -297
  145. package/dist/frontend-core/template/src/components/ui/select/select.tsx +0 -227
  146. package/dist/frontend-core/template/src/components/ui/separator/separator.tsx +0 -21
  147. package/dist/frontend-core/template/src/components/ui/separator/seperator.stories.tsx +0 -25
  148. package/dist/frontend-core/template/src/components/ui/sheet/sheet.stories.tsx +0 -45
  149. package/dist/frontend-core/template/src/components/ui/sheet/sheet.tsx +0 -107
  150. package/dist/frontend-core/template/src/components/ui/skeleton/skeleton.stories.tsx +0 -26
  151. package/dist/frontend-core/template/src/components/ui/skeleton/skeleton.tsx +0 -7
  152. package/dist/frontend-core/template/src/components/ui/slider/slider.stories.tsx +0 -101
  153. package/dist/frontend-core/template/src/components/ui/slider/slider.tsx +0 -98
  154. package/dist/frontend-core/template/src/components/ui/spinner/spinner.stories.tsx +0 -19
  155. package/dist/frontend-core/template/src/components/ui/spinner/spinner.tsx +0 -21
  156. package/dist/frontend-core/template/src/components/ui/switch/switch.stories.tsx +0 -33
  157. package/dist/frontend-core/template/src/components/ui/switch/switch.tsx +0 -28
  158. package/dist/frontend-core/template/src/components/ui/tabs/tabs.stories.tsx +0 -215
  159. package/dist/frontend-core/template/src/components/ui/tabs/tabs.tsx +0 -70
  160. package/dist/frontend-core/template/src/components/ui/textarea/textarea.stories.tsx +0 -138
  161. package/dist/frontend-core/template/src/components/ui/textarea/textarea.tsx +0 -40
  162. package/dist/frontend-core/template/src/components/ui/toast/toast.mdx +0 -31
  163. package/dist/frontend-core/template/src/components/ui/toast/toast.stories.tsx +0 -89
  164. package/dist/frontend-core/template/src/components/ui/toggle/toggle.stories.tsx +0 -65
  165. package/dist/frontend-core/template/src/components/ui/toggle/toggle.tsx +0 -38
  166. package/dist/frontend-core/template/src/components/ui/toggle-group/toggle-group.stories.tsx +0 -85
  167. package/dist/frontend-core/template/src/components/ui/toggle-group/toggle-group.tsx +0 -54
  168. package/dist/frontend-core/template/src/components/ui/tooltip/tooltip.stories.tsx +0 -29
  169. package/dist/frontend-core/template/src/components/ui/tooltip/tooltip.tsx +0 -29
@@ -1,123 +0,0 @@
1
- import { flexRender, type Row } from '@tanstack/react-table'
2
- import type { Virtualizer } from '@tanstack/react-virtual'
3
-
4
- import * as React from 'react'
5
-
6
- import type { CellPosition, RowHeightValue } from '@components/ui/data-grid/data-grid-types'
7
- import { getCommonPinningStyles, getLineCount } from '@components/ui/data-grid/data-grid-utils'
8
- import { useComposedRefs } from '@lib/compose-refs'
9
- import { cn } from '@lib/utils'
10
-
11
- type DataGridRowProps<TData> = {
12
- row: Row<TData>
13
- rowVirtualizer: Virtualizer<HTMLDivElement, Element>
14
- virtualRowIndex: number
15
- rowMapRef: React.RefObject<Map<number, HTMLDivElement>>
16
- rowHeight: RowHeightValue
17
- focusedCell: CellPosition | null
18
- } & React.ComponentProps<'div'>
19
-
20
- export const DataGridRow = React.memo(DataGridRowImpl, (prev, next) => {
21
- if (prev.row.id !== next.row.id) {
22
- return false
23
- }
24
-
25
- // Check if the actual row data has changed
26
- if (prev.row.original !== next.row.original) {
27
- return false
28
- }
29
-
30
- const prevRowIndex = prev.virtualRowIndex
31
- const nextRowIndex = next.virtualRowIndex
32
-
33
- const prevHasFocus = prev.focusedCell?.rowIndex === prevRowIndex
34
- const nextHasFocus = next.focusedCell?.rowIndex === nextRowIndex
35
-
36
- if (prevHasFocus !== nextHasFocus) {
37
- return false
38
- }
39
-
40
- if (nextHasFocus && prevHasFocus) {
41
- const prevFocusedCol = prev.focusedCell?.columnId
42
- const nextFocusedCol = next.focusedCell?.columnId
43
- if (prevFocusedCol !== nextFocusedCol) {
44
- return false
45
- }
46
- }
47
-
48
- return next.rowVirtualizer.isScrolling
49
- }) as typeof DataGridRowImpl
50
-
51
- function DataGridRowImpl<TData>({
52
- row,
53
- virtualRowIndex,
54
- rowVirtualizer,
55
- rowMapRef,
56
- rowHeight,
57
- focusedCell,
58
- ref,
59
- className,
60
- ...props
61
- }: DataGridRowProps<TData>) {
62
- const rowRef = useComposedRefs(ref, (node) => {
63
- if (node && typeof virtualRowIndex !== 'undefined') {
64
- rowVirtualizer.measureElement(node)
65
- rowMapRef.current.set(virtualRowIndex, node)
66
- }
67
- })
68
-
69
- const isRowSelected = row.getIsSelected()
70
-
71
- return (
72
- <div
73
- key={row.id}
74
- role="row"
75
- aria-rowindex={virtualRowIndex + 2}
76
- aria-selected={isRowSelected}
77
- data-index={virtualRowIndex}
78
- data-slot="grid-row"
79
- ref={rowRef}
80
- tabIndex={-1}
81
- className={cn(
82
- 'absolute flex w-full border-b h-[calc(var(--data-grid-line-height)*(var(--line-count))+12px)]',
83
- className,
84
- )}
85
- style={{ '--line-count': `${getLineCount(rowHeight)}` } as React.CSSProperties}
86
- {...props}
87
- >
88
- {row.getVisibleCells().map((cell, colIndex) => {
89
- const isCellFocused = focusedCell?.rowIndex === virtualRowIndex && focusedCell?.columnId === cell.column.id
90
-
91
- return (
92
- <div
93
- key={cell.id}
94
- role="gridcell"
95
- aria-colindex={colIndex + 1}
96
- data-highlighted={isCellFocused ? '' : undefined}
97
- data-slot="grid-cell"
98
- tabIndex={-1}
99
- className={cn({
100
- 'border-r': cell.column.id !== 'select',
101
- })}
102
- style={{
103
- ...getCommonPinningStyles({ column: cell.column }),
104
- width: `calc(var(--col-${cell.column.id}-size) * 1px)`,
105
- }}
106
- >
107
- {typeof cell.column.columnDef.header === 'function' ? (
108
- <div
109
- className={cn('size-full px-3 py-1.5', {
110
- 'bg-accent-foreground/10': isRowSelected,
111
- })}
112
- >
113
- {flexRender(cell.column.columnDef.cell, cell.getContext())}
114
- </div>
115
- ) : (
116
- flexRender(cell.column.columnDef.cell, cell.getContext())
117
- )}
118
- </div>
119
- )
120
- })}
121
- </div>
122
- )
123
- }
@@ -1,211 +0,0 @@
1
- import { ChevronDownIcon, ChevronUpIcon, Cross2Icon } from '@radix-ui/react-icons'
2
-
3
- import * as React from 'react'
4
-
5
- import { Button } from '@components/ui/button/button'
6
- import type { SearchState } from '@components/ui/data-grid/data-grid-types'
7
- import { useDebouncedCallback } from '@components/ui/data-grid/hooks/use-debounced-callback'
8
- import { Input } from '@components/ui/input/input'
9
-
10
- type DataGridSearchProps = {} & SearchState
11
-
12
- export const DataGridSearch = React.memo(DataGridSearchImpl, (prev, next) => {
13
- if (prev.searchOpen !== next.searchOpen) {
14
- return false
15
- }
16
-
17
- if (!next.searchOpen) {
18
- return true
19
- }
20
-
21
- if (prev.searchQuery !== next.searchQuery || prev.matchIndex !== next.matchIndex) {
22
- return false
23
- }
24
-
25
- if (prev.searchMatches.length !== next.searchMatches.length) {
26
- return false
27
- }
28
-
29
- for (let i = 0; i < prev.searchMatches.length; i++) {
30
- const prevMatch = prev.searchMatches[i]
31
- const nextMatch = next.searchMatches[i]
32
-
33
- if (!prevMatch || !nextMatch) {
34
- return false
35
- }
36
-
37
- if (prevMatch.rowIndex !== nextMatch.rowIndex || prevMatch.columnId !== nextMatch.columnId) {
38
- return false
39
- }
40
- }
41
-
42
- return true
43
- })
44
-
45
- function DataGridSearchImpl({
46
- searchMatches,
47
- matchIndex,
48
- searchOpen,
49
- onSearchOpenChange,
50
- searchQuery,
51
- onSearchQueryChange,
52
- onSearch,
53
- onNavigateToNextMatch,
54
- onNavigateToPrevMatch,
55
- }: DataGridSearchProps) {
56
- const inputRef = React.useRef<HTMLInputElement>(null)
57
-
58
- React.useEffect(() => {
59
- if (searchOpen) {
60
- requestAnimationFrame(() => {
61
- inputRef.current?.focus()
62
- })
63
- }
64
- }, [searchOpen])
65
-
66
- React.useEffect(() => {
67
- if (!searchOpen) {
68
- return
69
- }
70
-
71
- function onEscape(event: KeyboardEvent) {
72
- if (event.key === 'Escape') {
73
- event.preventDefault()
74
- onSearchOpenChange(false)
75
- }
76
- }
77
-
78
- document.addEventListener('keydown', onEscape)
79
- return () => document.removeEventListener('keydown', onEscape)
80
- }, [searchOpen, onSearchOpenChange])
81
-
82
- const onKeyDown = React.useCallback(
83
- (event: React.KeyboardEvent) => {
84
- event.stopPropagation()
85
-
86
- if (event.key === 'Enter') {
87
- event.preventDefault()
88
- if (event.shiftKey) {
89
- onNavigateToPrevMatch()
90
- } else {
91
- onNavigateToNextMatch()
92
- }
93
- }
94
- },
95
- [onNavigateToNextMatch, onNavigateToPrevMatch],
96
- )
97
-
98
- const debouncedSearch = useDebouncedCallback((query: string) => {
99
- onSearch(query)
100
- }, 150)
101
-
102
- const onChange = React.useCallback(
103
- (event: React.ChangeEvent<HTMLInputElement>) => {
104
- const value = event.target.value
105
- onSearchQueryChange(value)
106
- debouncedSearch(value)
107
- },
108
- [onSearchQueryChange, debouncedSearch],
109
- )
110
-
111
- const onTriggerPointerDown = React.useCallback((event: React.PointerEvent<HTMLButtonElement>) => {
112
- // prevent implicit pointer capture
113
- const target = event.target
114
- if (!(target instanceof HTMLElement)) {
115
- return
116
- }
117
- if (target.hasPointerCapture(event.pointerId)) {
118
- target.releasePointerCapture(event.pointerId)
119
- }
120
-
121
- // Only prevent default if we're not clicking on the input
122
- // This allows text selection in the input while still preventing focus stealing elsewhere
123
- if (
124
- event.button === 0 &&
125
- event.ctrlKey === false &&
126
- event.pointerType === 'mouse' &&
127
- !(event.target instanceof HTMLInputElement)
128
- ) {
129
- event.preventDefault()
130
- }
131
- }, [])
132
-
133
- const onPrevMatchPointerDown = React.useCallback(
134
- (event: React.PointerEvent<HTMLButtonElement>) => onTriggerPointerDown(event),
135
- [onTriggerPointerDown],
136
- )
137
-
138
- const onNextMatchPointerDown = React.useCallback(
139
- (event: React.PointerEvent<HTMLButtonElement>) => onTriggerPointerDown(event),
140
- [onTriggerPointerDown],
141
- )
142
-
143
- const onClose = React.useCallback(() => {
144
- onSearchOpenChange(false)
145
- }, [onSearchOpenChange])
146
-
147
- if (!searchOpen) {
148
- return null
149
- }
150
-
151
- return (
152
- <div
153
- role="search"
154
- data-slot="grid-search"
155
- className="fade-in-0 slide-in-from-top-2 absolute top-4 right-4 z-50 flex animate-in flex-col gap-2 rounded-lg border border-border bg-background p-2 shadow-lg"
156
- >
157
- <div className="flex items-center gap-2">
158
- <Input
159
- autoComplete="off"
160
- autoCorrect="off"
161
- autoCapitalize="off"
162
- spellCheck={false}
163
- placeholder="Find in table..."
164
- className="h-8 w-64"
165
- ref={inputRef}
166
- value={searchQuery}
167
- onChange={onChange}
168
- onKeyDown={onKeyDown}
169
- />
170
- <div className="flex items-center gap-1">
171
- <Button
172
- aria-label="Previous match"
173
- variant="ghost"
174
- size="icon"
175
- className="size-7"
176
- onClick={onNavigateToPrevMatch}
177
- onPointerDown={onPrevMatchPointerDown}
178
- disabled={searchMatches.length === 0}
179
- >
180
- <ChevronUpIcon />
181
- </Button>
182
- <Button
183
- aria-label="Next match"
184
- variant="ghost"
185
- size="icon"
186
- className="size-7"
187
- onClick={onNavigateToNextMatch}
188
- onPointerDown={onNextMatchPointerDown}
189
- disabled={searchMatches.length === 0}
190
- >
191
- <ChevronDownIcon />
192
- </Button>
193
- <Button aria-label="Close search" variant="ghost" size="icon" className="size-7" onClick={onClose}>
194
- <Cross2Icon />
195
- </Button>
196
- </div>
197
- </div>
198
- <div className="flex items-center gap-1 whitespace-nowrap text-muted-foreground">
199
- {searchMatches.length > 0 ? (
200
- <span>
201
- {matchIndex + 1} of {searchMatches.length}
202
- </span>
203
- ) : searchQuery ? (
204
- <span>No results</span>
205
- ) : (
206
- <span>Type to search</span>
207
- )}
208
- </div>
209
- </div>
210
- )
211
- }
@@ -1,159 +0,0 @@
1
- import { Column, RowData } from '@tanstack/react-table'
2
-
3
- import { ISODateRange } from './cell-variants/utils/gantt-timerange-picker'
4
-
5
- export type RowHeightValue = 'short' | 'medium' | 'tall' | 'extra-tall'
6
-
7
- export type CellSelectOption = {
8
- label: string
9
- value: string
10
- }
11
-
12
- export type Cell =
13
- | {
14
- variant: 'short-text'
15
- }
16
- | {
17
- variant: 'long-text'
18
- }
19
- | {
20
- variant: 'number'
21
- min?: number
22
- max?: number
23
- step?: number
24
- prefix?: string
25
- suffix?: string
26
- fallbackValue?: string
27
- }
28
- | {
29
- variant: 'select'
30
- options: CellSelectOption[]
31
- hasSearch?: boolean
32
- }
33
- | {
34
- variant: 'multi-select'
35
- options: CellSelectOption[]
36
- }
37
- | {
38
- variant: 'checkbox'
39
- }
40
- | {
41
- variant: 'date'
42
- }
43
- | {
44
- variant: 'react-node'
45
- }
46
- | {
47
- variant: 'gantt'
48
- timelineStart: Date
49
- timelineEnd: Date
50
- dateRangeFrom?: Date
51
- dateRangeTo?: Date
52
- onRangeChange?: (values: ISODateRange | undefined) => void
53
- }
54
-
55
- export type UpdateCell = {
56
- rowIndex: number
57
- columnId: string
58
- value: unknown
59
- }
60
-
61
- export type ColumnMenuRendererFunction<TData extends RowData, TValue> = (args: {
62
- column: Column<TData, TValue>
63
- open?: boolean
64
- onOpenChange?: (open: boolean) => void
65
- }) => React.ReactNode
66
-
67
- declare module '@tanstack/react-table' {
68
- // biome-ignore lint/correctness/noUnusedVariables lint/correctness/noUnusedVariables: TData and TValue are used in the ColumnMeta interface
69
- // eslint-disable-next-line @typescript-eslint/consistent-type-definitions
70
- interface ColumnMeta<TData extends RowData, TValue> {
71
- label?: string
72
- cell?: Cell
73
- align?: 'left' | 'right' | 'center'
74
- className?: string | ((row: TData) => string | undefined)
75
- editable?: boolean | ((row: TData) => boolean)
76
- headerMenuFooter?: React.ReactNode | ColumnMenuRendererFunction<TData, TValue>
77
- headerCustomComponent?: React.ReactNode | ColumnMenuRendererFunction<TData, TValue>
78
- }
79
- // biome-ignore lint/correctness/noUnusedVariables: TData is used in the TableMeta interface
80
- // eslint-disable-next-line @typescript-eslint/consistent-type-definitions, @typescript-eslint/no-unused-vars
81
- interface TableMeta<TData extends RowData> {
82
- dataGridRef?: React.RefObject<HTMLElement | null>
83
- focusedCell?: CellPosition | null
84
- editingCell?: CellPosition | null
85
- selectionState?: SelectionState
86
- searchOpen?: boolean
87
- isScrolling?: boolean
88
- getIsCellSelected?: (rowIndex: number, columnId: string) => boolean
89
- getIsSearchMatch?: (rowIndex: number, columnId: string) => boolean
90
- getIsActiveSearchMatch?: (rowIndex: number, columnId: string) => boolean
91
- onDataUpdate?: (props: UpdateCell | UpdateCell[]) => void
92
- /**
93
- * Called for each individual cell update. Receives a single UpdateCell.
94
- * Use this to implement field-level updates (id + column + value).
95
- */
96
- onCellChange?: (update: UpdateCell) => void
97
- onRowsDelete?: (rowIndices: number[]) => void | Promise<void>
98
- onColumnClick?: (columnId: string) => void
99
- onCellClick?: (rowIndex: number, columnId: string, event?: React.MouseEvent) => void
100
- onCellDoubleClick?: (rowIndex: number, columnId: string) => void
101
- onCellMouseDown?: (rowIndex: number, columnId: string, event: React.MouseEvent) => void
102
- onCellMouseEnter?: (rowIndex: number, columnId: string, event: React.MouseEvent) => void
103
- onCellMouseUp?: () => void
104
- onCellContextMenu?: (rowIndex: number, columnId: string, event: React.MouseEvent) => void
105
- onCellEditingStart?: (rowIndex: number, columnId: string) => void
106
- onCellEditingStop?: (opts?: { direction?: NavigationDirection; moveToNextRow?: boolean }) => void
107
- contextMenu?: ContextMenuState
108
- onContextMenuOpenChange?: (open: boolean) => void
109
- rowHeight?: RowHeightValue
110
- onRowHeightChange?: (value: RowHeightValue) => void
111
- onRowSelect?: (rowIndex: number, checked: boolean, shiftKey: boolean) => void
112
- }
113
- }
114
-
115
- export type CellPosition = {
116
- rowIndex: number
117
- columnId: string
118
- }
119
-
120
- export type CellRange = {
121
- start: CellPosition
122
- end: CellPosition
123
- }
124
-
125
- export type SelectionState = {
126
- selectedCells: Set<string>
127
- selectionRange: CellRange | null
128
- isSelecting: boolean
129
- }
130
-
131
- export type ContextMenuState = {
132
- open: boolean
133
- x: number
134
- y: number
135
- }
136
-
137
- export type NavigationDirection =
138
- | 'up'
139
- | 'down'
140
- | 'left'
141
- | 'right'
142
- | 'home'
143
- | 'end'
144
- | 'ctrl+home'
145
- | 'ctrl+end'
146
- | 'pageup'
147
- | 'pagedown'
148
-
149
- export type SearchState = {
150
- searchMatches: CellPosition[]
151
- matchIndex: number
152
- searchOpen: boolean
153
- onSearchOpenChange: (open: boolean) => void
154
- searchQuery: string
155
- onSearchQueryChange: (query: string) => void
156
- onSearch: (query: string) => void
157
- onNavigateToNextMatch: () => void
158
- onNavigateToPrevMatch: () => void
159
- }
@@ -1,67 +0,0 @@
1
- import type { Column } from '@tanstack/react-table'
2
-
3
- import type { CellPosition, RowHeightValue } from '@components/ui/data-grid/data-grid-types'
4
-
5
- export function getCellKey(rowIndex: number, columnId: string) {
6
- return `${rowIndex}:${columnId}`
7
- }
8
-
9
- export function parseCellKey(cellKey: string): Required<CellPosition> {
10
- const parts = cellKey.split(':')
11
- const rowIndexStr = parts[0]
12
- const columnId = parts[1]
13
- if (rowIndexStr && columnId) {
14
- const rowIndex = parseInt(rowIndexStr, 10)
15
- if (!Number.isNaN(rowIndex)) {
16
- return { rowIndex, columnId }
17
- }
18
- }
19
- return { rowIndex: 0, columnId: '' }
20
- }
21
-
22
- export function getRowHeightValue(rowHeight: RowHeightValue): number {
23
- // TODO: Make lineHeight configurable / use css variable: --data-grid-line-height
24
- const lineHeight = 16
25
-
26
- return lineHeight * getLineCount(rowHeight) + 12
27
- }
28
-
29
- export function getLineCount(rowHeight: RowHeightValue): number {
30
- const lineCountMap: Record<RowHeightValue, number> = {
31
- short: 1,
32
- medium: 2,
33
- tall: 3,
34
- 'extra-tall': 4,
35
- }
36
-
37
- return lineCountMap[rowHeight]
38
- }
39
-
40
- export function getCommonPinningStyles<TData>({
41
- column,
42
- withBorder = false,
43
- }: {
44
- column: Column<TData>
45
- withBorder?: boolean
46
- }): React.CSSProperties {
47
- const isPinned = column.getIsPinned()
48
- const isLastLeftPinnedColumn = isPinned === 'left' && column.getIsLastColumn('left')
49
- const isFirstRightPinnedColumn = isPinned === 'right' && column.getIsFirstColumn('right')
50
-
51
- return {
52
- boxShadow: withBorder
53
- ? isLastLeftPinnedColumn
54
- ? '-4px 0 4px var(--border) inset'
55
- : isFirstRightPinnedColumn
56
- ? '4px 0 -4px var(--border) inset'
57
- : undefined
58
- : undefined,
59
- left: isPinned === 'left' ? `${column.getStart('left')}px` : undefined,
60
- right: isPinned === 'right' ? `${column.getAfter('right')}px` : undefined,
61
- opacity: isPinned ? 0.97 : 1,
62
- position: isPinned ? 'sticky' : 'relative',
63
- background: isPinned ? 'var(--background)' : 'var(--background)',
64
- width: column.getSize(),
65
- zIndex: isPinned ? 1 : undefined,
66
- }
67
- }