@postxl/generators 1.1.1 → 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 (161) hide show
  1. package/dist/frontend-core/frontend.generator.d.ts +0 -58
  2. package/dist/frontend-core/frontend.generator.js +6 -172
  3. package/dist/frontend-core/frontend.generator.js.map +1 -1
  4. package/dist/frontend-core/template/README.md +1 -1
  5. package/dist/frontend-core/template/src/components/admin/table-filter.tsx +1 -5
  6. package/dist/frontend-core/template/src/components/ui/color-mode-toggle/color-mode-toggle.tsx +10 -4
  7. package/dist/frontend-core/template/src/pages/dashboard/dashboard.page.tsx +2 -3
  8. package/dist/frontend-core/template/src/pages/error/default-error.page.tsx +1 -1
  9. package/dist/frontend-core/template/src/pages/error/not-found-error.page.tsx +1 -1
  10. package/dist/frontend-core/template/src/styles/styles.css +13 -1
  11. package/dist/frontend-core/template/tsconfig.json +2 -0
  12. package/dist/frontend-core/types/component.d.ts +1 -1
  13. package/dist/frontend-forms/generators/discriminated-union/fields.generator.js +4 -6
  14. package/dist/frontend-forms/generators/discriminated-union/fields.generator.js.map +1 -1
  15. package/dist/frontend-forms/generators/discriminated-union/inputs.generator.js +1 -1
  16. package/dist/frontend-forms/generators/discriminated-union/inputs.generator.js.map +1 -1
  17. package/dist/frontend-forms/generators/enum/inputs.generator.js +1 -1
  18. package/dist/frontend-forms/generators/enum/inputs.generator.js.map +1 -1
  19. package/dist/frontend-forms/generators/model/forms.generator.js +8 -12
  20. package/dist/frontend-forms/generators/model/forms.generator.js.map +1 -1
  21. package/dist/frontend-forms/generators/model/inputs.generator.js +2 -6
  22. package/dist/frontend-forms/generators/model/inputs.generator.js.map +1 -1
  23. package/dist/frontend-forms/template/src/components/ui/field/field.tsx +1 -4
  24. package/dist/frontend-tables/generators/model-table.generator.js +1 -5
  25. package/dist/frontend-tables/generators/model-table.generator.js.map +1 -1
  26. package/package.json +3 -2
  27. package/dist/frontend-core/template/src/components/ui/accordion/accordion.stories.tsx +0 -47
  28. package/dist/frontend-core/template/src/components/ui/accordion/accordion.tsx +0 -52
  29. package/dist/frontend-core/template/src/components/ui/admin-sidebar/admin-sidebar.tsx +0 -195
  30. package/dist/frontend-core/template/src/components/ui/alert/alert.stories.tsx +0 -61
  31. package/dist/frontend-core/template/src/components/ui/alert/alert.tsx +0 -45
  32. package/dist/frontend-core/template/src/components/ui/alert-dialog/alert-dialog.stories.tsx +0 -52
  33. package/dist/frontend-core/template/src/components/ui/alert-dialog/alert-dialog.tsx +0 -105
  34. package/dist/frontend-core/template/src/components/ui/avatar/avatar.stories.tsx +0 -30
  35. package/dist/frontend-core/template/src/components/ui/avatar/avatar.tsx +0 -39
  36. package/dist/frontend-core/template/src/components/ui/badge/badge.stories.tsx +0 -78
  37. package/dist/frontend-core/template/src/components/ui/badge/badge.tsx +0 -48
  38. package/dist/frontend-core/template/src/components/ui/breadcrumb/breadcrumb.stories.tsx +0 -67
  39. package/dist/frontend-core/template/src/components/ui/breadcrumb/breadcrumb.tsx +0 -85
  40. package/dist/frontend-core/template/src/components/ui/button/button.stories.tsx +0 -150
  41. package/dist/frontend-core/template/src/components/ui/button/button.tsx +0 -68
  42. package/dist/frontend-core/template/src/components/ui/calendar/calendar.stories.tsx +0 -160
  43. package/dist/frontend-core/template/src/components/ui/calendar/calendar.tsx +0 -293
  44. package/dist/frontend-core/template/src/components/ui/card/card.stories.tsx +0 -77
  45. package/dist/frontend-core/template/src/components/ui/card/card.tsx +0 -45
  46. package/dist/frontend-core/template/src/components/ui/card-hover/card-hover.stories.tsx +0 -29
  47. package/dist/frontend-core/template/src/components/ui/card-hover/card-hover.tsx +0 -28
  48. package/dist/frontend-core/template/src/components/ui/carousel/carousel.stories.tsx +0 -154
  49. package/dist/frontend-core/template/src/components/ui/carousel/carousel.tsx +0 -227
  50. package/dist/frontend-core/template/src/components/ui/checkbox/checkbox.stories.tsx +0 -106
  51. package/dist/frontend-core/template/src/components/ui/checkbox/checkbox.tsx +0 -88
  52. package/dist/frontend-core/template/src/components/ui/checkbox/shadcn-checkbox.stories.tsx +0 -90
  53. package/dist/frontend-core/template/src/components/ui/checkbox/shadcn-checkbox.tsx +0 -54
  54. package/dist/frontend-core/template/src/components/ui/collapse/collapse.stories.tsx +0 -52
  55. package/dist/frontend-core/template/src/components/ui/collapse/collapse.tsx +0 -9
  56. package/dist/frontend-core/template/src/components/ui/combobox/combobox.stories.tsx +0 -207
  57. package/dist/frontend-core/template/src/components/ui/combobox/combobox.tsx +0 -79
  58. package/dist/frontend-core/template/src/components/ui/command/command.stories.tsx +0 -186
  59. package/dist/frontend-core/template/src/components/ui/command/command.tsx +0 -165
  60. package/dist/frontend-core/template/src/components/ui/command-palette/command-palette.stories.tsx +0 -160
  61. package/dist/frontend-core/template/src/components/ui/command-palette/command-palette.tsx +0 -134
  62. package/dist/frontend-core/template/src/components/ui/content-frame/content-frame.stories.tsx +0 -198
  63. package/dist/frontend-core/template/src/components/ui/content-frame/content-frame.tsx +0 -100
  64. package/dist/frontend-core/template/src/components/ui/context-menu/context-menu.stories.tsx +0 -78
  65. package/dist/frontend-core/template/src/components/ui/context-menu/context-menu.tsx +0 -179
  66. package/dist/frontend-core/template/src/components/ui/data-grid/cell-variants/cell-variant-types.ts +0 -11
  67. package/dist/frontend-core/template/src/components/ui/data-grid/cell-variants/checkbox-cell.tsx +0 -116
  68. package/dist/frontend-core/template/src/components/ui/data-grid/cell-variants/date-cell.tsx +0 -157
  69. package/dist/frontend-core/template/src/components/ui/data-grid/cell-variants/gantt-cell.tsx +0 -82
  70. package/dist/frontend-core/template/src/components/ui/data-grid/cell-variants/long-text-cell.tsx +0 -180
  71. package/dist/frontend-core/template/src/components/ui/data-grid/cell-variants/multi-select-cell.tsx +0 -280
  72. package/dist/frontend-core/template/src/components/ui/data-grid/cell-variants/number-cell.tsx +0 -169
  73. package/dist/frontend-core/template/src/components/ui/data-grid/cell-variants/react-node-cell.tsx +0 -33
  74. package/dist/frontend-core/template/src/components/ui/data-grid/cell-variants/select-cell.tsx +0 -175
  75. package/dist/frontend-core/template/src/components/ui/data-grid/cell-variants/short-text-cell.tsx +0 -138
  76. package/dist/frontend-core/template/src/components/ui/data-grid/cell-variants/utils/gantt-timeline.tsx +0 -92
  77. package/dist/frontend-core/template/src/components/ui/data-grid/cell-variants/utils/gantt-timerange-picker.tsx +0 -330
  78. package/dist/frontend-core/template/src/components/ui/data-grid/data-grid-cell-wrapper.tsx +0 -212
  79. package/dist/frontend-core/template/src/components/ui/data-grid/data-grid-cell.tsx +0 -157
  80. package/dist/frontend-core/template/src/components/ui/data-grid/data-grid-column-header.tsx +0 -340
  81. package/dist/frontend-core/template/src/components/ui/data-grid/data-grid-context-menu.tsx +0 -271
  82. package/dist/frontend-core/template/src/components/ui/data-grid/data-grid-row.tsx +0 -123
  83. package/dist/frontend-core/template/src/components/ui/data-grid/data-grid-search.tsx +0 -211
  84. package/dist/frontend-core/template/src/components/ui/data-grid/data-grid-types.ts +0 -159
  85. package/dist/frontend-core/template/src/components/ui/data-grid/data-grid-utils.ts +0 -67
  86. package/dist/frontend-core/template/src/components/ui/data-grid/data-grid-view-menu.tsx +0 -360
  87. package/dist/frontend-core/template/src/components/ui/data-grid/data-grid.stories.tsx +0 -780
  88. package/dist/frontend-core/template/src/components/ui/data-grid/data-grid.tsx +0 -217
  89. package/dist/frontend-core/template/src/components/ui/data-grid/hooks/use-callback-ref.ts +0 -22
  90. package/dist/frontend-core/template/src/components/ui/data-grid/hooks/use-data-grid.tsx +0 -1892
  91. package/dist/frontend-core/template/src/components/ui/data-grid/hooks/use-debounced-callback.ts +0 -19
  92. package/dist/frontend-core/template/src/components/ui/data-grid/styles.css +0 -3
  93. package/dist/frontend-core/template/src/components/ui/data-table/context-menu-simple.tsx +0 -141
  94. package/dist/frontend-core/template/src/components/ui/data-table/data-table.stories.tsx +0 -146
  95. package/dist/frontend-core/template/src/components/ui/data-table/data-table.tsx +0 -447
  96. package/dist/frontend-core/template/src/components/ui/data-table/renderers/country-array-cell-renderer.tsx +0 -77
  97. package/dist/frontend-core/template/src/components/ui/data-table/renderers/country-cell-renderer.tsx +0 -56
  98. package/dist/frontend-core/template/src/components/ui/data-table/renderers/favorite-cell-renderer.tsx +0 -68
  99. package/dist/frontend-core/template/src/components/ui/data-table/renderers/links-cell-renderer.tsx +0 -205
  100. package/dist/frontend-core/template/src/components/ui/data-table/utils/columns.ts +0 -351
  101. package/dist/frontend-core/template/src/components/ui/data-table/utils/data-table.utils.ts +0 -49
  102. package/dist/frontend-core/template/src/components/ui/date-picker/date-picker.stories.tsx +0 -149
  103. package/dist/frontend-core/template/src/components/ui/date-picker/date-picker.tsx +0 -30
  104. package/dist/frontend-core/template/src/components/ui/dialog/dialog.stories.tsx +0 -80
  105. package/dist/frontend-core/template/src/components/ui/dialog/dialog.tsx +0 -134
  106. package/dist/frontend-core/template/src/components/ui/drawer/drawer.stories.tsx +0 -104
  107. package/dist/frontend-core/template/src/components/ui/drawer/drawer.tsx +0 -87
  108. package/dist/frontend-core/template/src/components/ui/dropdown-menu/dropdown-menu.stories.tsx +0 -168
  109. package/dist/frontend-core/template/src/components/ui/dropdown-menu/dropdown-menu.tsx +0 -225
  110. package/dist/frontend-core/template/src/components/ui/input/input.stories.tsx +0 -141
  111. package/dist/frontend-core/template/src/components/ui/input/input.tsx +0 -47
  112. package/dist/frontend-core/template/src/components/ui/label/label.stories.tsx +0 -41
  113. package/dist/frontend-core/template/src/components/ui/label/label.tsx +0 -20
  114. package/dist/frontend-core/template/src/components/ui/loader/loader.stories.tsx +0 -45
  115. package/dist/frontend-core/template/src/components/ui/loader/loader.tsx +0 -17
  116. package/dist/frontend-core/template/src/components/ui/mark-value-renderer/mark-value-renderer.stories.tsx +0 -114
  117. package/dist/frontend-core/template/src/components/ui/mark-value-renderer/mark-value-renderer.tsx +0 -48
  118. package/dist/frontend-core/template/src/components/ui/menubar/menu.stories.tsx +0 -134
  119. package/dist/frontend-core/template/src/components/ui/menubar/menubar.tsx +0 -208
  120. package/dist/frontend-core/template/src/components/ui/modal/modal.stories.tsx +0 -297
  121. package/dist/frontend-core/template/src/components/ui/modal/modal.tsx +0 -80
  122. package/dist/frontend-core/template/src/components/ui/navigation-menu/navigation-menu.stories.tsx +0 -213
  123. package/dist/frontend-core/template/src/components/ui/navigation-menu/navigation-menu.tsx +0 -142
  124. package/dist/frontend-core/template/src/components/ui/pagination/pagination.stories.tsx +0 -49
  125. package/dist/frontend-core/template/src/components/ui/pagination/pagination.tsx +0 -84
  126. package/dist/frontend-core/template/src/components/ui/popover/popover.stories.tsx +0 -82
  127. package/dist/frontend-core/template/src/components/ui/popover/popover.tsx +0 -55
  128. package/dist/frontend-core/template/src/components/ui/progress/progress.stories.tsx +0 -80
  129. package/dist/frontend-core/template/src/components/ui/progress/progress.tsx +0 -17
  130. package/dist/frontend-core/template/src/components/ui/radio-group/radio-group.stories.tsx +0 -154
  131. package/dist/frontend-core/template/src/components/ui/radio-group/radio-group.tsx +0 -68
  132. package/dist/frontend-core/template/src/components/ui/resizable/resizable.stories.tsx +0 -73
  133. package/dist/frontend-core/template/src/components/ui/resizable/resizeable.tsx +0 -38
  134. package/dist/frontend-core/template/src/components/ui/scroll-area/scroll-area.stories.tsx +0 -55
  135. package/dist/frontend-core/template/src/components/ui/scroll-area/scroll-area.tsx +0 -39
  136. package/dist/frontend-core/template/src/components/ui/select/select.stories.tsx +0 -297
  137. package/dist/frontend-core/template/src/components/ui/select/select.tsx +0 -227
  138. package/dist/frontend-core/template/src/components/ui/separator/separator.tsx +0 -21
  139. package/dist/frontend-core/template/src/components/ui/separator/seperator.stories.tsx +0 -25
  140. package/dist/frontend-core/template/src/components/ui/sheet/sheet.stories.tsx +0 -45
  141. package/dist/frontend-core/template/src/components/ui/sheet/sheet.tsx +0 -107
  142. package/dist/frontend-core/template/src/components/ui/skeleton/skeleton.stories.tsx +0 -26
  143. package/dist/frontend-core/template/src/components/ui/skeleton/skeleton.tsx +0 -7
  144. package/dist/frontend-core/template/src/components/ui/slider/slider.stories.tsx +0 -101
  145. package/dist/frontend-core/template/src/components/ui/slider/slider.tsx +0 -98
  146. package/dist/frontend-core/template/src/components/ui/spinner/spinner.stories.tsx +0 -19
  147. package/dist/frontend-core/template/src/components/ui/spinner/spinner.tsx +0 -21
  148. package/dist/frontend-core/template/src/components/ui/switch/switch.stories.tsx +0 -33
  149. package/dist/frontend-core/template/src/components/ui/switch/switch.tsx +0 -28
  150. package/dist/frontend-core/template/src/components/ui/tabs/tabs.stories.tsx +0 -215
  151. package/dist/frontend-core/template/src/components/ui/tabs/tabs.tsx +0 -70
  152. package/dist/frontend-core/template/src/components/ui/textarea/textarea.stories.tsx +0 -138
  153. package/dist/frontend-core/template/src/components/ui/textarea/textarea.tsx +0 -40
  154. package/dist/frontend-core/template/src/components/ui/toast/toast.mdx +0 -31
  155. package/dist/frontend-core/template/src/components/ui/toast/toast.stories.tsx +0 -89
  156. package/dist/frontend-core/template/src/components/ui/toggle/toggle.stories.tsx +0 -65
  157. package/dist/frontend-core/template/src/components/ui/toggle/toggle.tsx +0 -38
  158. package/dist/frontend-core/template/src/components/ui/toggle-group/toggle-group.stories.tsx +0 -85
  159. package/dist/frontend-core/template/src/components/ui/toggle-group/toggle-group.tsx +0 -54
  160. package/dist/frontend-core/template/src/components/ui/tooltip/tooltip.stories.tsx +0 -29
  161. package/dist/frontend-core/template/src/components/ui/tooltip/tooltip.tsx +0 -29
@@ -1,330 +0,0 @@
1
- /* Modified DateRangePicker based DateRangePicker by John Polacek (https://github.com/johnpolacek/date-range-picker-for-shadcn) (MIT License) */
2
-
3
- import { CalendarIcon, Cross2Icon } from '@radix-ui/react-icons'
4
-
5
- import React, { useEffect, useState } from 'react'
6
-
7
- import { Button } from '@components/ui/button/button'
8
- import { Calendar } from '@components/ui/calendar/calendar'
9
- import { Popover, PopoverContent, PopoverTrigger } from '@components/ui/popover/popover'
10
- import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@components/ui/select/select'
11
- import { cn } from '@lib/utils'
12
-
13
- export type GanttTimerangePickerProps = {
14
- initialDateFrom?: Date
15
- initialDateTo?: Date
16
- // onRangeChange now receives ISO string date range (UTC-normalized) or undefined
17
- onRangeChange?: (values: ISODateRange | undefined) => void
18
- timelineStart?: Date
19
- timelineEnd?: Date
20
- }
21
-
22
- type DateRange = {
23
- from?: Date
24
- to?: Date
25
- }
26
-
27
- // ISODateRange with ISO string dates for UTC-normalized range for querying
28
- export type ISODateRange = {
29
- from?: string
30
- to?: string
31
- }
32
-
33
- // reusable helper: convert an ISO UTC-normalized date string back to a local Date
34
- export const isoToLocalDate = (iso?: string): Date | undefined => {
35
- if (!iso) {
36
- return undefined
37
- }
38
- const d = new Date(iso) // parse ISO instant
39
- // build a local Date that has the same calendar day as the UTC date parts
40
- return new Date(d.getUTCFullYear(), d.getUTCMonth(), d.getUTCDate())
41
- }
42
-
43
- // helper to convert internal Date range to ISO strings normalized to UTC start/end of day
44
- const convertRangeToISO = (r?: { from?: Date; to?: Date } | undefined): ISODateRange | undefined => {
45
- if (!(r?.from && r?.to)) {
46
- return undefined
47
- }
48
- const from = r.from
49
- const to = r.to
50
-
51
- const fromIso = new Date(
52
- Date.UTC(from.getUTCFullYear(), from.getUTCMonth(), from.getUTCDate(), 0, 0, 0, 0),
53
- ).toISOString()
54
- const toIso = new Date(
55
- Date.UTC(to.getUTCFullYear(), to.getUTCMonth(), to.getUTCDate(), 23, 59, 59, 999),
56
- ).toISOString()
57
-
58
- return { from: fromIso, to: toIso }
59
- }
60
-
61
- type Preset = {
62
- name: string
63
- label: string
64
- }
65
-
66
- const PRESETS: Preset[] = [
67
- { name: 'sinceStart', label: 'Since timeline start' },
68
- { name: 'thisYear', label: 'This year' },
69
- { name: 'nextFullYear', label: 'Next full year' },
70
- { name: 'next1Year', label: 'Next 1 year' },
71
- { name: 'next2Year', label: 'Next 2 years' },
72
- { name: 'next3Year', label: 'Next 3 years' },
73
- { name: 'untilEnd', label: 'Until timeline end' },
74
- ]
75
-
76
- export const GanttTimerangePicker = ({
77
- initialDateFrom,
78
- initialDateTo,
79
- onRangeChange,
80
- timelineStart,
81
- timelineEnd,
82
- }: GanttTimerangePickerProps) => {
83
- const [range, setRange] = useState<DateRange | undefined>(
84
- initialDateFrom || initialDateTo ? { from: initialDateFrom, to: initialDateTo } : undefined,
85
- )
86
- const [isOpen, setIsOpen] = useState(false)
87
- const [selectedPreset, setSelectedPreset] = useState<string | undefined>(undefined)
88
- const [isSmallScreen, setIsSmallScreen] = useState(
89
- globalThis.window === undefined ? false : globalThis.window.innerWidth < 960,
90
- )
91
-
92
- // listen to window resize events to enable a small screen mode
93
- useEffect(() => {
94
- const handleResize = (): void => {
95
- setIsSmallScreen(globalThis.window.innerWidth < 960)
96
- }
97
- globalThis.window.addEventListener('resize', handleResize)
98
- // Clean up event listener on unmount
99
- return () => {
100
- globalThis.window.removeEventListener('resize', handleResize)
101
- }
102
- }, [])
103
-
104
- const getPresetRange = (presetName: string, timelineStart?: Date, timelineEnd?: Date): DateRange => {
105
- const preset = PRESETS.find(({ name }) => name === presetName)
106
- if (!preset) {
107
- throw new Error(`Unknown date range preset: ${presetName}`)
108
- }
109
- const from = new Date()
110
- const to = new Date()
111
-
112
- switch (preset.name) {
113
- case 'sinceStart':
114
- if (timelineStart) {
115
- from.setFullYear(timelineStart.getFullYear(), timelineStart.getMonth(), timelineStart.getDate())
116
- }
117
- from.setHours(0, 0, 0, 0)
118
- to.setHours(23, 59, 59, 999)
119
- break
120
- case 'thisYear':
121
- from.setFullYear(from.getFullYear(), 0, 1)
122
- from.setHours(0, 0, 0, 0)
123
- to.setFullYear(to.getFullYear(), 11, 31)
124
- to.setHours(23, 59, 59, 999)
125
- break
126
- case 'nextFullYear':
127
- from.setFullYear(from.getFullYear() + 1, 0, 1)
128
- from.setHours(0, 0, 0, 0)
129
- to.setFullYear(to.getFullYear() + 1, 11, 31)
130
- to.setHours(23, 59, 59, 999)
131
- break
132
- case 'next1Year':
133
- from.setHours(0, 0, 0, 0)
134
- to.setFullYear(to.getFullYear() + 1)
135
- to.setHours(23, 59, 59, 999)
136
- break
137
- case 'next2Year':
138
- from.setHours(0, 0, 0, 0)
139
- to.setFullYear(to.getFullYear() + 2)
140
- to.setHours(23, 59, 59, 999)
141
- break
142
- case 'next3Year':
143
- from.setHours(0, 0, 0, 0)
144
- to.setFullYear(to.getFullYear() + 3)
145
- to.setHours(23, 59, 59, 999)
146
- break
147
- case 'untilEnd':
148
- from.setHours(0, 0, 0, 0)
149
- if (timelineEnd) {
150
- to.setFullYear(timelineEnd.getFullYear(), timelineEnd.getMonth(), timelineEnd.getDate())
151
- }
152
- to.setHours(23, 59, 59, 999)
153
- break
154
- }
155
-
156
- return { from, to }
157
- }
158
-
159
- // automatically detect selected preset when range changes (internal Date range)
160
- useEffect(() => {
161
- if (!range?.from || !range.to) {
162
- setSelectedPreset(undefined)
163
- return
164
- }
165
- for (const preset of PRESETS) {
166
- const presetRange = getPresetRange(preset.name, timelineStart, timelineEnd)
167
- if (!presetRange.from || !presetRange.to) {
168
- continue
169
- }
170
-
171
- const normalizedRangeFrom = new Date(range.from)
172
- normalizedRangeFrom.setHours(0, 0, 0, 0)
173
- const normalizedPresetFrom = new Date(presetRange.from)
174
- normalizedPresetFrom.setHours(0, 0, 0, 0)
175
-
176
- const normalizedRangeTo = new Date(range.to)
177
- normalizedRangeTo.setHours(0, 0, 0, 0)
178
- const normalizedPresetTo = new Date(presetRange.to)
179
- normalizedPresetTo.setHours(0, 0, 0, 0)
180
-
181
- if (
182
- normalizedRangeFrom.getTime() === normalizedPresetFrom.getTime() &&
183
- normalizedRangeTo.getTime() === normalizedPresetTo.getTime()
184
- ) {
185
- setSelectedPreset(preset.name)
186
- return
187
- }
188
- }
189
- setSelectedPreset(undefined)
190
- }, [range, timelineStart, timelineEnd])
191
-
192
- return (
193
- <Popover
194
- modal={true}
195
- open={isOpen}
196
- onOpenChange={(isOpen) => {
197
- setIsOpen(isOpen)
198
- // on close, emit ISO-normalized range
199
- if (!isOpen) {
200
- onRangeChange?.(convertRangeToISO(range))
201
- }
202
- }}
203
- >
204
- <PopoverTrigger asChild>
205
- <Button size="iconSm" variant="extraGhost2">
206
- <CalendarIcon className="size-3" />
207
- </Button>
208
- </PopoverTrigger>
209
- <PopoverContent align="start" className="w-auto p-2 m-2 relative">
210
- <div className="flex justify-between items-center">
211
- <span className="pl-2">
212
- {range?.from && range?.to
213
- ? `${range.from.toLocaleDateString()} - ${range.to.toLocaleDateString()} selected`
214
- : 'No range selected'}
215
- </span>
216
- <Button
217
- variant="outline"
218
- size="icon"
219
- className="size-6 rounded"
220
- onClick={() => {
221
- setIsOpen(false)
222
- }}
223
- >
224
- <Cross2Icon className="size-5" />
225
- </Button>
226
- </div>
227
- <div className="flex">
228
- <div className="flex">
229
- <div className="flex flex-col">
230
- {isSmallScreen && (
231
- <Select
232
- defaultValue={selectedPreset}
233
- onValueChange={(value) => {
234
- setRange(getPresetRange(value))
235
- }}
236
- >
237
- <SelectTrigger size="xs" className="w-[180px] mx-auto mt-2">
238
- <SelectValue placeholder="Select..." />
239
- </SelectTrigger>
240
- <SelectContent>
241
- {PRESETS.map((preset) => (
242
- <SelectItem key={preset.name} value={preset.name}>
243
- {preset.label}
244
- </SelectItem>
245
- ))}
246
- </SelectContent>
247
- </Select>
248
- )}
249
- <div className={cn('h-[325px]', isSmallScreen && 'mb-8')}>
250
- <Calendar
251
- mode="range"
252
- showYearNavigation={true}
253
- disabled={(date) =>
254
- (timelineStart ? date < timelineStart : false) || (timelineEnd ? date > timelineEnd : false)
255
- }
256
- onSelect={(value: { from?: Date; to?: Date } | undefined) => {
257
- if (value?.from != null) {
258
- const from = value.from
259
- const to = value.to ?? value.from
260
- // Normalize the range so that from <= to
261
- setRange(to < from ? { from: to, to: from } : { from, to })
262
- }
263
- }}
264
- selected={range?.from && range?.to ? { from: range.from, to: range.to } : undefined}
265
- numberOfMonths={isSmallScreen ? 1 : 2}
266
- defaultMonth={new Date(new Date().setMonth(new Date().getMonth() - (isSmallScreen ? 0 : 1)))}
267
- />
268
- </div>
269
- </div>
270
- </div>
271
- {!isSmallScreen && (
272
- <div className="flex flex-col items-start gap-1 pr-2 pl-12 py-3">
273
- {PRESETS.map((preset) => (
274
- <PresetButton
275
- key={preset.name}
276
- preset={preset.name}
277
- label={preset.label}
278
- isSelected={selectedPreset === preset.name}
279
- onSelect={(presetName) => setRange(getPresetRange(presetName))}
280
- />
281
- ))}
282
- </div>
283
- )}
284
- </div>
285
- <div className="flex gap-2 absolute bottom-3 right-3">
286
- <Button
287
- variant="outlineInvert"
288
- size="smLow"
289
- className=""
290
- onClick={() => {
291
- setRange(undefined)
292
- }}
293
- >
294
- Clear Range
295
- </Button>
296
- <Button
297
- size="smLow"
298
- onClick={() => {
299
- setIsOpen(false)
300
- onRangeChange?.(convertRangeToISO(range))
301
- }}
302
- >
303
- Apply
304
- </Button>
305
- </div>
306
- </PopoverContent>
307
- </Popover>
308
- )
309
- }
310
-
311
- const PresetButton = ({
312
- preset,
313
- label,
314
- isSelected,
315
- onSelect,
316
- }: {
317
- preset: string
318
- label: string
319
- isSelected: boolean
320
- onSelect: (preset: string) => void
321
- }): React.ReactNode => (
322
- <Button
323
- className={`w-full justify-start ${isSelected ? 'pointer-events-none bg-accent' : ''}`}
324
- variant="ghost"
325
- size="smLow"
326
- onClick={() => onSelect(preset)}
327
- >
328
- {label}
329
- </Button>
330
- )
@@ -1,212 +0,0 @@
1
- 'use client'
2
-
3
- import type { Cell, Table } from '@tanstack/react-table'
4
-
5
- import * as React from 'react'
6
-
7
- import { cn } from '@lib/utils'
8
-
9
- type DataGridCellWrapperProps<TData> = {
10
- cell: Cell<TData, unknown>
11
- table: Table<TData>
12
- rowIndex: number
13
- columnId: string
14
- isEditing: boolean
15
- isFocused: boolean
16
- isSelected: boolean
17
- } & React.ComponentProps<'div'>
18
-
19
- export function DataGridCellWrapper<TData>({
20
- cell,
21
- table,
22
- rowIndex,
23
- columnId,
24
- isEditing,
25
- isFocused,
26
- isSelected,
27
- className,
28
- onClick: onClickProp,
29
- onKeyDown: onKeyDownProp,
30
- ...props
31
- }: DataGridCellWrapperProps<TData>) {
32
- const meta = table.options.meta
33
-
34
- const rowOriginal = (cell?.row?.original ?? {}) as any
35
- const colCellMeta = cell?.column?.columnDef?.meta as any
36
- const align: 'left' | 'right' | 'center' = colCellMeta?.align ?? 'left'
37
-
38
- // Normalize editable to a resolver function and memoize to avoid typeof checks per cell
39
- const editableResolver = React.useMemo(() => {
40
- const v = colCellMeta?.editable
41
- if (v === undefined) {
42
- return () => true
43
- }
44
- return typeof v === 'function' ? (v as (row: TData) => boolean) : () => Boolean(v)
45
- }, [colCellMeta?.editable])
46
- const isEditable = editableResolver(rowOriginal)
47
-
48
- // Normalize className to a resolver function and memoize to avoid typeof checks per cell
49
- const classNameResolver = React.useMemo(() => {
50
- const v = colCellMeta?.className
51
- return typeof v === 'function' ? (v as (row: any) => string | undefined) : () => v as string | undefined
52
- }, [colCellMeta?.className])
53
- const colCellClassName = classNameResolver(rowOriginal)
54
-
55
- const isSearchMatch = meta?.getIsSearchMatch?.(rowIndex, columnId) ?? false
56
- const isActiveSearchMatch = meta?.getIsActiveSearchMatch?.(rowIndex, columnId) ?? false
57
-
58
- const onClick = React.useCallback(
59
- (event: React.MouseEvent<HTMLDivElement>) => {
60
- if (!isEditing) {
61
- event.preventDefault()
62
- onClickProp?.(event)
63
- if (isFocused) {
64
- if (isEditable) {
65
- meta?.onCellEditingStart?.(rowIndex, columnId)
66
- }
67
- } else {
68
- meta?.onCellClick?.(rowIndex, columnId, event)
69
- }
70
- }
71
- },
72
- [meta, rowIndex, columnId, isEditing, isFocused, onClickProp, isEditable],
73
- )
74
-
75
- const onContextMenu = React.useCallback(
76
- (event: React.MouseEvent) => {
77
- if (!isEditing) {
78
- meta?.onCellContextMenu?.(rowIndex, columnId, event)
79
- }
80
- },
81
- [meta, rowIndex, columnId, isEditing],
82
- )
83
-
84
- const onMouseDown = React.useCallback(
85
- (event: React.MouseEvent) => {
86
- if (!isEditing) {
87
- meta?.onCellMouseDown?.(rowIndex, columnId, event)
88
- }
89
- },
90
- [meta, rowIndex, columnId, isEditing],
91
- )
92
-
93
- const onMouseEnter = React.useCallback(
94
- (event: React.MouseEvent) => {
95
- if (!isEditing) {
96
- meta?.onCellMouseEnter?.(rowIndex, columnId, event)
97
- }
98
- },
99
- [meta, rowIndex, columnId, isEditing],
100
- )
101
-
102
- const onMouseUp = React.useCallback(() => {
103
- if (!isEditing) {
104
- meta?.onCellMouseUp?.()
105
- }
106
- }, [meta, isEditing])
107
-
108
- const onDoubleClick = React.useCallback(
109
- (event: React.MouseEvent) => {
110
- if (!isEditing) {
111
- event.preventDefault()
112
- if (isEditable) {
113
- meta?.onCellDoubleClick?.(rowIndex, columnId)
114
- }
115
- }
116
- },
117
- [meta, rowIndex, columnId, isEditing, isEditable],
118
- )
119
-
120
- const onKeyDown = React.useCallback(
121
- (event: React.KeyboardEvent<HTMLDivElement>) => {
122
- onKeyDownProp?.(event)
123
-
124
- if (event.defaultPrevented) {
125
- return
126
- }
127
-
128
- if (
129
- event.key === 'ArrowUp' ||
130
- event.key === 'ArrowDown' ||
131
- event.key === 'ArrowLeft' ||
132
- event.key === 'ArrowRight' ||
133
- event.key === 'Home' ||
134
- event.key === 'End' ||
135
- event.key === 'PageUp' ||
136
- event.key === 'PageDown' ||
137
- event.key === 'Tab'
138
- ) {
139
- return
140
- }
141
-
142
- if (isFocused && !isEditing) {
143
- if (event.key === 'F2' || event.key === 'Enter') {
144
- event.preventDefault()
145
- event.stopPropagation()
146
- if (isEditable) {
147
- meta?.onCellEditingStart?.(rowIndex, columnId)
148
- }
149
- return
150
- }
151
-
152
- if (event.key === '') {
153
- event.preventDefault()
154
- event.stopPropagation()
155
- meta?.onCellEditingStart?.(rowIndex, columnId)
156
- return
157
- }
158
-
159
- if (event.key.length === 1 && !event.ctrlKey && !event.metaKey) {
160
- event.preventDefault()
161
- event.stopPropagation()
162
- if (isEditable) {
163
- meta?.onCellEditingStart?.(rowIndex, columnId)
164
- }
165
- }
166
- }
167
- },
168
- [onKeyDownProp, isFocused, isEditing, meta, rowIndex, columnId, isEditable],
169
- )
170
-
171
- const rowHeight = meta?.rowHeight ?? 'short'
172
-
173
- return (
174
- <div
175
- role="button"
176
- data-slot="grid-cell-wrapper"
177
- data-editing={isEditing ? '' : undefined}
178
- data-focused={isFocused ? '' : undefined}
179
- data-selected={isSelected ? '' : undefined}
180
- tabIndex={isFocused && !isEditing ? 0 : -1}
181
- className={cn(
182
- 'size-full px-2 py-1.5 text-sm outline-none -has-data-[slot=checkbox]:pt-2.5', // why has-data-[slot=checkbox] ?
183
- {
184
- 'text-left': align === 'left',
185
- 'text-right': align === 'right',
186
- 'text-center': align === 'center',
187
- },
188
- {
189
- 'ring-1 ring-foreground ring-inset dark:ring-secondary-foreground': isFocused,
190
- 'bg-yellow-100 dark:bg-yellow-900/30': isSearchMatch && !isActiveSearchMatch,
191
- 'bg-orange-200 dark:bg-orange-900/50': isActiveSearchMatch,
192
- 'bg-accent-foreground/10': isSelected && !isEditing,
193
- 'cursor-default': !isEditing,
194
- '**:data-[slot=grid-cell-content]:line-clamp-1': !isEditing && rowHeight === 'short',
195
- '**:data-[slot=grid-cell-content]:line-clamp-2': !isEditing && rowHeight === 'medium',
196
- '**:data-[slot=grid-cell-content]:line-clamp-3': !isEditing && rowHeight === 'tall',
197
- '**:data-[slot=grid-cell-content]:line-clamp-4': !isEditing && rowHeight === 'extra-tall',
198
- },
199
- colCellClassName,
200
- className,
201
- )}
202
- onClick={onClick}
203
- onContextMenu={onContextMenu}
204
- onDoubleClick={onDoubleClick}
205
- onMouseDown={onMouseDown}
206
- onMouseEnter={onMouseEnter}
207
- onMouseUp={onMouseUp}
208
- onKeyDown={onKeyDown}
209
- {...props}
210
- />
211
- )
212
- }
@@ -1,157 +0,0 @@
1
- import type { Cell, Table } from '@tanstack/react-table'
2
-
3
- import { CheckboxCell } from './cell-variants/checkbox-cell'
4
- import { DateCell } from './cell-variants/date-cell'
5
- import { GanttCell } from './cell-variants/gantt-cell'
6
- import { LongTextCell } from './cell-variants/long-text-cell'
7
- import { MultiSelectCell } from './cell-variants/multi-select-cell'
8
- import { NumberCell } from './cell-variants/number-cell'
9
- import { ReactNodeCell } from './cell-variants/react-node-cell'
10
- import { SelectCell } from './cell-variants/select-cell'
11
- import { ShortTextCell } from './cell-variants/short-text-cell'
12
-
13
- type DataGridCellProps<TData> = {
14
- cell: Cell<TData, unknown>
15
- table: Table<TData>
16
- }
17
-
18
- export function DataGridCell<TData>({ cell, table }: DataGridCellProps<TData>) {
19
- const meta = table.options.meta
20
- const originalRowIndex = cell.row.index
21
-
22
- const rows = table.getRowModel().rows
23
- const displayRowIndex = rows.findIndex((row) => row.original === cell.row.original)
24
- const rowIndex = displayRowIndex >= 0 ? displayRowIndex : originalRowIndex
25
- const columnId = cell.column.id
26
-
27
- const isFocused = meta?.focusedCell?.rowIndex === rowIndex && meta?.focusedCell?.columnId === columnId
28
- const isEditing = meta?.editingCell?.rowIndex === rowIndex && meta?.editingCell?.columnId === columnId
29
- const isSelected = meta?.getIsCellSelected?.(rowIndex, columnId) ?? false
30
-
31
- const cellOpts = cell.column.columnDef.meta?.cell
32
- const variant = cellOpts?.variant ?? 'text'
33
-
34
- switch (variant) {
35
- case 'short-text':
36
- return (
37
- <ShortTextCell
38
- cell={cell as Cell<TData, string>}
39
- table={table}
40
- rowIndex={rowIndex}
41
- columnId={columnId}
42
- isEditing={isEditing}
43
- isFocused={isFocused}
44
- isSelected={isSelected}
45
- />
46
- )
47
- case 'long-text':
48
- return (
49
- <LongTextCell
50
- cell={cell as Cell<TData, string>}
51
- table={table}
52
- rowIndex={rowIndex}
53
- columnId={columnId}
54
- isEditing={isEditing}
55
- isFocused={isFocused}
56
- isSelected={isSelected}
57
- />
58
- )
59
- case 'number':
60
- return (
61
- <NumberCell
62
- cell={cell as Cell<TData, number>}
63
- table={table}
64
- rowIndex={rowIndex}
65
- columnId={columnId}
66
- isEditing={isEditing}
67
- isFocused={isFocused}
68
- isSelected={isSelected}
69
- />
70
- )
71
- case 'select':
72
- return (
73
- <SelectCell
74
- cell={cell as Cell<TData, string>}
75
- table={table}
76
- rowIndex={rowIndex}
77
- columnId={columnId}
78
- isEditing={isEditing}
79
- isFocused={isFocused}
80
- isSelected={isSelected}
81
- />
82
- )
83
- case 'multi-select':
84
- return (
85
- <MultiSelectCell
86
- cell={cell as Cell<TData, string[]>}
87
- table={table}
88
- rowIndex={rowIndex}
89
- columnId={columnId}
90
- isEditing={isEditing}
91
- isFocused={isFocused}
92
- isSelected={isSelected}
93
- />
94
- )
95
- case 'checkbox':
96
- return (
97
- <CheckboxCell
98
- cell={cell as Cell<TData, boolean>}
99
- table={table}
100
- rowIndex={rowIndex}
101
- columnId={columnId}
102
- isEditing={isEditing}
103
- isFocused={isFocused}
104
- isSelected={isSelected}
105
- />
106
- )
107
- case 'date':
108
- return (
109
- <DateCell
110
- cell={cell as Cell<TData, string>}
111
- table={table}
112
- rowIndex={rowIndex}
113
- columnId={columnId}
114
- isEditing={isEditing}
115
- isFocused={isFocused}
116
- isSelected={isSelected}
117
- />
118
- )
119
- case 'react-node':
120
- return (
121
- <ReactNodeCell
122
- cell={cell as Cell<TData, React.ReactNode>}
123
- table={table}
124
- rowIndex={rowIndex}
125
- columnId={columnId}
126
- isEditing={isEditing}
127
- isFocused={isFocused}
128
- isSelected={isSelected}
129
- />
130
- )
131
- case 'gantt':
132
- return (
133
- <GanttCell
134
- cell={cell as Cell<TData, { start: Date; end: Date } | null>}
135
- table={table}
136
- rowIndex={rowIndex}
137
- columnId={columnId}
138
- isEditing={isEditing}
139
- isFocused={isFocused}
140
- isSelected={isSelected}
141
- />
142
- )
143
-
144
- default:
145
- return (
146
- <ShortTextCell
147
- cell={cell as Cell<TData, string>}
148
- table={table}
149
- rowIndex={rowIndex}
150
- columnId={columnId}
151
- isEditing={isEditing}
152
- isFocused={isFocused}
153
- isSelected={isSelected}
154
- />
155
- )
156
- }
157
- }