@cryptlex/web-components 5.3.0 → 5.4.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 (163) hide show
  1. package/dist/components/{ui/alert.d.ts → alert.d.ts} +3 -3
  2. package/dist/components/alert.js +2 -0
  3. package/dist/components/alert.js.map +1 -0
  4. package/dist/components/{ui/avatar.d.ts → avatar.d.ts} +0 -1
  5. package/dist/components/avatar.js +2 -0
  6. package/dist/components/avatar.js.map +1 -0
  7. package/dist/components/{ui/badge.d.ts → badge.d.ts} +0 -1
  8. package/dist/components/badge.js +2 -0
  9. package/dist/components/badge.js.map +1 -0
  10. package/dist/components/{ui/breadcrumbs.d.ts → breadcrumbs.d.ts} +1 -1
  11. package/dist/components/breadcrumbs.js +2 -0
  12. package/dist/components/breadcrumbs.js.map +1 -0
  13. package/dist/components/{ui/button.d.ts → button.d.ts} +5 -5
  14. package/dist/components/button.js +2 -0
  15. package/dist/components/button.js.map +1 -0
  16. package/dist/components/{ui/calendar.d.ts → calendar.d.ts} +2 -3
  17. package/dist/components/calendar.js +2 -0
  18. package/dist/components/calendar.js.map +1 -0
  19. package/dist/components/card.js +2 -0
  20. package/dist/components/card.js.map +1 -0
  21. package/dist/components/{inputs/checkbox.d.ts → checkbox.d.ts} +3 -3
  22. package/dist/components/checkbox.js +2 -0
  23. package/dist/components/checkbox.js.map +1 -0
  24. package/dist/components/{data-table/table-commons.d.ts → data-table-commons.d.ts} +8 -8
  25. package/dist/components/data-table-commons.js +2 -0
  26. package/dist/components/data-table-commons.js.map +1 -0
  27. package/dist/components/{data-table/data-table-filter.d.ts → data-table-filter.d.ts} +3 -3
  28. package/dist/components/data-table-filter.js +2 -0
  29. package/dist/components/data-table-filter.js.map +1 -0
  30. package/dist/components/{data-table/data-table.d.ts → data-table.d.ts} +24 -25
  31. package/dist/components/data-table.js +2 -0
  32. package/dist/components/data-table.js.map +1 -0
  33. package/dist/components/{inputs/date-picker.d.ts → date-picker.d.ts} +3 -3
  34. package/dist/components/date-picker.js +2 -0
  35. package/dist/components/date-picker.js.map +1 -0
  36. package/dist/components/{inputs/datefield.d.ts → datefield.d.ts} +3 -3
  37. package/dist/components/datefield.js +2 -0
  38. package/dist/components/datefield.js.map +1 -0
  39. package/dist/components/{ui/dialog.d.ts → dialog.d.ts} +3 -4
  40. package/dist/components/dialog.js +2 -0
  41. package/dist/components/dialog.js.map +1 -0
  42. package/dist/components/{ui/disclosure.d.ts → disclosure.d.ts} +1 -2
  43. package/dist/components/disclosure.js +2 -0
  44. package/dist/components/disclosure.js.map +1 -0
  45. package/dist/components/{inputs/field.d.ts → field.d.ts} +5 -6
  46. package/dist/components/field.js +2 -0
  47. package/dist/components/field.js.map +1 -0
  48. package/dist/components/id-search.js +2 -0
  49. package/dist/components/id-search.js.map +1 -0
  50. package/dist/components/{inputs/input-otp.d.ts → input-otp.d.ts} +1 -2
  51. package/dist/components/input-otp.js +2 -0
  52. package/dist/components/input-otp.js.map +1 -0
  53. package/dist/components/key-value-card.js +2 -0
  54. package/dist/components/key-value-card.js.map +1 -0
  55. package/dist/components/{ui/list-box.d.ts → list-box.d.ts} +1 -1
  56. package/dist/components/list-box.js +2 -0
  57. package/dist/components/list-box.js.map +1 -0
  58. package/dist/components/loader.js +2 -0
  59. package/dist/components/loader.js.map +1 -0
  60. package/dist/components/{ui/menu.d.ts → menu.d.ts} +5 -6
  61. package/dist/components/menu.js +2 -0
  62. package/dist/components/menu.js.map +1 -0
  63. package/dist/components/{inputs/multi-select.d.ts → multi-select.d.ts} +3 -4
  64. package/dist/components/multi-select.js +2 -0
  65. package/dist/components/multi-select.js.map +1 -0
  66. package/dist/components/{inputs/numberfield.d.ts → numberfield.d.ts} +2 -3
  67. package/dist/components/numberfield.js +2 -0
  68. package/dist/components/numberfield.js.map +1 -0
  69. package/dist/components/{ui/popover.d.ts → popover.d.ts} +1 -1
  70. package/dist/components/popover.js +2 -0
  71. package/dist/components/popover.js.map +1 -0
  72. package/dist/components/{inputs/searchfield.d.ts → searchfield.d.ts} +2 -2
  73. package/dist/components/searchfield.js +2 -0
  74. package/dist/components/searchfield.js.map +1 -0
  75. package/dist/components/select-options.js +2 -0
  76. package/dist/components/select-options.js.map +1 -0
  77. package/dist/components/{inputs/select.d.ts → select.d.ts} +5 -5
  78. package/dist/components/select.js +2 -0
  79. package/dist/components/select.js.map +1 -0
  80. package/dist/components/{ui/sidebar.d.ts → sidebar.d.ts} +4 -5
  81. package/dist/components/sidebar.js +2 -0
  82. package/dist/components/sidebar.js.map +1 -0
  83. package/dist/components/skeleton.js +2 -0
  84. package/dist/components/skeleton.js.map +1 -0
  85. package/dist/components/{ui/sonner.d.ts → sonner.d.ts} +1 -1
  86. package/dist/components/sonner.js +2 -0
  87. package/dist/components/sonner.js.map +1 -0
  88. package/dist/components/table-of-contents.d.ts +9 -0
  89. package/dist/components/table-of-contents.js +2 -0
  90. package/dist/components/table-of-contents.js.map +1 -0
  91. package/dist/components/{ui/table.d.ts → table.d.ts} +0 -1
  92. package/dist/components/table.js +2 -0
  93. package/dist/components/table.js.map +1 -0
  94. package/dist/components/{ui/tabs.d.ts → tabs.d.ts} +1 -1
  95. package/dist/components/tabs.js +2 -0
  96. package/dist/components/tabs.js.map +1 -0
  97. package/dist/components/{inputs/textfield.d.ts → textfield.d.ts} +2 -2
  98. package/dist/components/textfield.js +2 -0
  99. package/dist/components/textfield.js.map +1 -0
  100. package/dist/components/{ui/timeline.d.ts → timeline.d.ts} +3 -3
  101. package/dist/components/timeline.js +2 -0
  102. package/dist/components/timeline.js.map +1 -0
  103. package/dist/components/{ui/tooltip.d.ts → tooltip.d.ts} +1 -1
  104. package/dist/components/tooltip.js +2 -0
  105. package/dist/components/tooltip.js.map +1 -0
  106. package/dist/utils/form-context.d.ts +1 -1
  107. package/dist/utils/form-context.js +2 -5
  108. package/dist/utils/form-context.js.map +1 -0
  109. package/dist/utils/form-hook.d.ts +9 -11
  110. package/dist/utils/form-hook.js +2 -30
  111. package/dist/utils/form-hook.js.map +1 -0
  112. package/dist/utils/primitives.d.ts +16 -2
  113. package/dist/utils/primitives.js +2 -39
  114. package/dist/utils/primitives.js.map +1 -0
  115. package/dist/utils/resource-names.d.ts +1 -13
  116. package/dist/utils/resource-names.js +2 -212
  117. package/dist/utils/resource-names.js.map +1 -0
  118. package/dist/utils/use-mobile.js +2 -15
  119. package/dist/utils/use-mobile.js.map +1 -0
  120. package/lib/utilities.css +1 -1
  121. package/package.json +13 -12
  122. package/dist/components/data-table/data-table-filter.js +0 -112
  123. package/dist/components/data-table/data-table.js +0 -265
  124. package/dist/components/data-table/table-commons.js +0 -137
  125. package/dist/components/inputs/checkbox.js +0 -25
  126. package/dist/components/inputs/date-picker.js +0 -22
  127. package/dist/components/inputs/datefield.js +0 -25
  128. package/dist/components/inputs/field.js +0 -48
  129. package/dist/components/inputs/id-search.js +0 -40
  130. package/dist/components/inputs/input-otp.js +0 -19
  131. package/dist/components/inputs/multi-select.js +0 -18
  132. package/dist/components/inputs/numberfield.js +0 -25
  133. package/dist/components/inputs/searchfield.js +0 -24
  134. package/dist/components/inputs/select-options.js +0 -286
  135. package/dist/components/inputs/select.js +0 -34
  136. package/dist/components/inputs/textfield.js +0 -28
  137. package/dist/components/key-value-card/key-value-card.js +0 -40
  138. package/dist/components/ui/alert.js +0 -18
  139. package/dist/components/ui/avatar.js +0 -5
  140. package/dist/components/ui/badge.js +0 -5
  141. package/dist/components/ui/breadcrumbs.js +0 -28
  142. package/dist/components/ui/button.js +0 -34
  143. package/dist/components/ui/calendar.js +0 -63
  144. package/dist/components/ui/card.js +0 -20
  145. package/dist/components/ui/dialog.js +0 -42
  146. package/dist/components/ui/disclosure.js +0 -20
  147. package/dist/components/ui/list-box.js +0 -24
  148. package/dist/components/ui/loader.js +0 -6
  149. package/dist/components/ui/menu.js +0 -38
  150. package/dist/components/ui/popover.js +0 -14
  151. package/dist/components/ui/sidebar.js +0 -177
  152. package/dist/components/ui/skeleton.js +0 -5
  153. package/dist/components/ui/sonner.js +0 -14
  154. package/dist/components/ui/table.js +0 -26
  155. package/dist/components/ui/tabs.js +0 -25
  156. package/dist/components/ui/timeline.js +0 -31
  157. package/dist/components/ui/tooltip.js +0 -12
  158. /package/dist/components/{ui/card.d.ts → card.d.ts} +0 -0
  159. /package/dist/components/{inputs/id-search.d.ts → id-search.d.ts} +0 -0
  160. /package/dist/components/{key-value-card/key-value-card.d.ts → key-value-card.d.ts} +0 -0
  161. /package/dist/components/{ui/loader.d.ts → loader.d.ts} +0 -0
  162. /package/dist/components/{inputs/select-options.d.ts → select-options.d.ts} +0 -0
  163. /package/dist/components/{ui/skeleton.d.ts → skeleton.d.ts} +0 -0
@@ -1,265 +0,0 @@
1
- "use client";
2
- import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
- import { keepPreviousData, useQuery } from "@tanstack/react-query";
4
- import { createColumnHelper, getCoreRowModel, useReactTable } from "@tanstack/react-table";
5
- import { ArrowDownNarrowWide, ArrowDownWideNarrow, ArrowUpDown, Columns3, GripVertical, Info } from "lucide-react";
6
- import { createContext, useContext, useEffect, useId, useMemo, useState } from "react";
7
- /** Reserved name for actions column */
8
- export const ACTIONS_COLUMN_ID = "tableActions";
9
- /**
10
- * Hook for handling all data-table state. Used in DataTableContext
11
- */
12
- export function useDataTableState({ columns, fetchFn, columnsToHideByDefault = {}, allowSelection = false, filterConfig }) {
13
- const id = useId();
14
- // TODO: Would it be better for this state to be more granular?
15
- const [tableState, _setTableState] = useState({
16
- /** TODO Reflect in URL */
17
- pagination: { pageIndex: 0, pageSize: 20 }, // Pagination state
18
- sorting: [], // Sorting state
19
- /** Ephemeral */
20
- rowSelection: {}, // Row selection state
21
- });
22
- /** TODO Reflect in URL */
23
- const [searchQuery, setSearchQuery] = useState('');
24
- /** TODO Store on browser as preference */
25
- const [columnOrder, setColumnOrder] = useState([]);
26
- // TODO Store on browser
27
- const [columnVisibility, setColumnVisibility] = useState({
28
- id: false,
29
- updatedAt: false,
30
- ...columnsToHideByDefault,
31
- });
32
- const [filters, setFilters] = useState([]);
33
- const mergedFilters = useMemo(() => {
34
- return filters.reduce((acc, current) => {
35
- return merge(acc, current);
36
- }, {});
37
- }, [filters]);
38
- // Update table state with new values
39
- const updateTableState = (updates) => {
40
- _setTableState((prev) => ({ ...prev, ...updates }));
41
- };
42
- const { sorting, rowSelection, pagination, } = tableState;
43
- const query = useQuery({
44
- queryKey: [id, pagination, sorting, searchQuery],
45
- queryFn: () => fetchFn(pagination, sorting, searchQuery, mergedFilters),
46
- placeholderData: keepPreviousData, // Keep previous data while loading new data
47
- retry: 0,
48
- refetchOnWindowFocus: false,
49
- });
50
- useEffect(() => {
51
- // TODO, store in localStorage
52
- }, [columnVisibility]);
53
- const columnHelper = useMemo(() => createColumnHelper(), []);
54
- const metadataColumns = useMemo(() => {
55
- const data = query.data?.data;
56
- if (!data?.length)
57
- return [];
58
- const rowHasMetadata = (row) => row != null &&
59
- typeof row === 'object' &&
60
- 'metadata' in row &&
61
- Array.isArray((row).metadata);
62
- const rowsWithMeta = data.filter(rowHasMetadata);
63
- if (rowsWithMeta.length === 0)
64
- return [];
65
- const keys = Array.from(new Set(rowsWithMeta.flatMap(r => r.metadata?.map(m => m.key) ?? [])));
66
- return keys.map(key => columnHelper.accessor((row) => {
67
- if (rowHasMetadata(row)) {
68
- return row?.metadata?.find(m => m.key === key)?.value ?? '';
69
- }
70
- return '';
71
- }, {
72
- id: key,
73
- header: key, // tooltip header
74
- enableSorting: false,
75
- cell: (info) => {
76
- const value = info.getValue();
77
- // Handle null/undefined values
78
- if (value === null || value === undefined)
79
- return "";
80
- // For primitive types, return the string representation
81
- return String(value);
82
- },
83
- }));
84
- }, [query.data?.data]);
85
- /**
86
- * ID,createdAt and updatedAt will be added by default for all tables
87
- * If selection is allowed, checkbox will be added
88
- * If the dto has metadata, dynamics columns for all the metadata key-value will be added(particular for a view)
89
- * If there are actions for the table, they will be placed fixed at the right side of table.
90
- */
91
- const cols = [
92
- ...(allowSelection ? TABLE_CHECK_BOX_COLUMN : []),
93
- ...TABLE_ID_COLUMN,
94
- ...columns.filter((col) => col.id !== ACTIONS_COLUMN_ID),
95
- ...(metadataColumns.length ? metadataColumns : []),
96
- ...TABLE_DEFAULT_DATE_COLUMNS,
97
- // Actions column
98
- ...columns.filter((col) => col.id === ACTIONS_COLUMN_ID),
99
- ];
100
- // Type-guard for updater
101
- function isUpdaterFunction(updater) {
102
- return typeof updater === "function";
103
- }
104
- // Utility function to resolve updater
105
- function resolveUpdater(updater, currentValue) {
106
- if (isUpdaterFunction(updater)) {
107
- return updater(currentValue);
108
- }
109
- return updater;
110
- }
111
- // Use react-table's hook to create the table instance
112
- const tanTable = useReactTable({
113
- data: query.data?.data ?? [],
114
- columns: cols,
115
- getCoreRowModel: getCoreRowModel(),
116
- rowCount: query.data?.total,
117
- manualPagination: true, // Handle pagination manually since pagination is done server side for data tables
118
- onPaginationChange: (updater) => {
119
- updateTableState({ pagination: resolveUpdater(updater, pagination) });
120
- },
121
- manualSorting: true, // Handle sorting manually since sorting is done server side for data tables
122
- onSortingChange: (updater) => {
123
- updateTableState({ sorting: [...resolveUpdater(updater, sorting)], rowSelection: {} }); // Reset selection when sorting.
124
- },
125
- manualFiltering: true, // Handle filtering manually since filtering is done server side for data tables
126
- onColumnVisibilityChange: (updater) => {
127
- setColumnVisibility(resolveUpdater(updater, columnVisibility));
128
- },
129
- onRowSelectionChange: (updater) => {
130
- updateTableState({ rowSelection: resolveUpdater(updater, rowSelection) });
131
- },
132
- onColumnOrderChange: (updater) => {
133
- setColumnOrder(resolveUpdater(updater, columnOrder));
134
- },
135
- state: {
136
- sorting: sorting,
137
- columnVisibility: columnVisibility,
138
- pagination: pagination,
139
- rowSelection: rowSelection,
140
- columnOrder: columnOrder
141
- },
142
- meta: {
143
- refetch: query.refetch,
144
- },
145
- });
146
- // By default, ColumnDef does not give guarantees of column.id existing. Once useReactTable is called, all columns are assigned IDs.
147
- // This populates the columnIds in the columnOrder state
148
- // TODO, add localStorage access layer for this.
149
- useEffect(() => {
150
- setColumnOrder([...tanTable.getAllLeafColumns().map(c => c.id)]);
151
- }, []);
152
- return { tableState, updateTableState, query, setSearchQuery, searchQuery, tanTable, mergedFilters, filters, setFilters, filterConfig };
153
- }
154
- export const DataTableContext = createContext(null);
155
- export const useDataTable = () => {
156
- const ctx = useContext(DataTableContext);
157
- if (!ctx) {
158
- throw Error("DataTable should be used within DataTableProvider.");
159
- }
160
- return ctx;
161
- };
162
- export function DataTableProvider({ children, ...props }) {
163
- return (_jsx(DataTableContext.Provider, { value: props, children: children }));
164
- }
165
- export function DataTable({ tableActions, className, ...props
166
- // filterableFields,
167
- }) {
168
- // State for managing table data and filters
169
- const { query, tanTable } = useDataTable();
170
- return (_jsx(_Fragment, { children: _jsxs("section", { ...props, className: cn("flex flex-col bg-card", className), children: [_jsx(Actions, { tableActions: tableActions }), _jsxs("div", { className: "w-full overflow-auto border-x grow min-h-table relative", tabIndex: 0, children: [query.isLoading && (_jsx(TableOverlay, { className: "cursor-wait", children: _jsx(Loader, {}) })), !query.isLoading && tanTable.getRowModel().rows.length === 0 && (
171
- // Empty table
172
- _jsx(TableOverlay, { className: "cursor-not-allowed", children: !query.isFetching &&
173
- (query.isError ? (_jsxs("span", { className: "flex gap-3 justify-center items-center", children: [_jsx(Info, {}), _jsx("span", { children: "You don't have the required permissions. Please contact your admin." })] })) : !query.data?.data ? (_jsx(_Fragment, { children: "No results found." })) : (_jsx(_Fragment, { children: "Unknown error. Please contact customer support." }))) })), !query.isLoading && tanTable.getRowModel().rows.length !== 0 &&
174
- _jsx(TableContent, { className: "size-full" })] }), _jsxs("div", { className: "flex w-full justify-between border gap-icon p-icon overflow-x-auto", children: [_jsxs("div", { className: "flex gap-icon", children: [_jsx(ColumnPicker, {}), _jsx(PageSize, {})] }), _jsx(Paginator, {})] })] }) }));
175
- }
176
- /** Table overlay to be shown for loaders or other messages */
177
- function TableOverlay({ children, className, }) {
178
- return (_jsxs(_Fragment, { children: [_jsx("span", { className: cn(className, "absolute top-0 bg-card z-20 size-full text-sm flex items-center justify-center"), children: children }), _jsx("span", { className: "relative h-full w-0 block" })] }));
179
- }
180
- import { arrayMove, SortableContext, sortableKeyboardCoordinates, useSortable, verticalListSortingStrategy } from '@dnd-kit/sortable';
181
- function ColumnPicker() {
182
- const { tanTable } = useDataTable();
183
- const [activeId, setActiveId] = useState(null);
184
- const resourceFormatter = useResourceFormatter();
185
- const sensors = useSensors(useSensor(PointerSensor), useSensor(KeyboardSensor, {
186
- coordinateGetter: sortableKeyboardCoordinates,
187
- }));
188
- return (_jsx(DndContext, { sensors: sensors, collisionDetection: closestCenter, onDragStart: (event) => {
189
- const { active } = event;
190
- setActiveId(active.id.toString());
191
- }, onDragEnd: (event) => {
192
- const { active, over } = event;
193
- if (over && active.id !== over.id) {
194
- const columnOrder = tanTable.getState().columnOrder;
195
- const oldIndex = columnOrder.indexOf(active.id.toString());
196
- const newIndex = columnOrder.indexOf(over.id.toString());
197
- tanTable.setColumnOrder([...arrayMove(columnOrder, oldIndex, newIndex)]);
198
- }
199
- setActiveId(null);
200
- }, children: _jsxs(SortableContext, { items: tanTable.getState().columnOrder, strategy: verticalListSortingStrategy, children: [_jsxs(EasyMenu, { label: _jsxs(_Fragment, { children: [_jsx(Columns3, {}), "Columns"] }), selectionMode: "multiple", items: tanTable.getAllFlatColumns(), selectedKeys: tanTable.getIsAllColumnsVisible() ? 'all' : tanTable.getVisibleFlatColumns().map(c => c.id), children: [_jsx(MenuItem, { onAction: () => tanTable.toggleAllColumnsVisible(), className: 'italic', children: "(select all)" }), tanTable.getState().columnOrder.map(colId => {
201
- const col = tanTable.getAllFlatColumns().find(c => c.id === colId);
202
- if (!col)
203
- return null;
204
- return _jsx(SortableItem, { column: col }, col.id);
205
- })] }), _jsx(DragOverlay, { children: activeId ? _jsx("div", { className: "dropdown-item opacity-70 border-2 border-primary", children: resourceFormatter(activeId) }) : null })] }) }));
206
- function SortableItem({ column }) {
207
- const { attributes, listeners, setNodeRef, transform, transition, } = useSortable({ id: column.id });
208
- const style = {
209
- transform: CSS.Transform.toString(transform),
210
- transition,
211
- zIndex: '999'
212
- };
213
- return _jsxs(MenuItem, { ref: setNodeRef, style: style, ...attributes, id: column.id, onAction: () => column.toggleVisibility(), isDisabled: !column.getCanHide(), className: "flex items-center", children: [_jsx(GripVertical, { ...listeners, className: "size-icon cursor-grab" }), resourceFormatter(column.id), column.getIsSorted() && _jsx(SortIcon, { className: "size-icon", direction: column.getIsSorted() })] });
214
- }
215
- }
216
- import { ChevronFirst, ChevronLast, ChevronLeft, ChevronRight, } from "lucide-react";
217
- function Paginator() {
218
- const { tanTable, query } = useDataTable();
219
- const rowCount = query.data?.total ?? 0;
220
- return (_jsxs("div", { className: "flex items-center gap-2", children: [_jsx("span", { className: "whitespace-nowrap caption text-muted", children: `${tanTable.getState().pagination.pageIndex * tanTable.getState().pagination.pageSize + 1} - ${Math.min((tanTable.getState().pagination.pageIndex + 1) *
221
- tanTable.getState().pagination.pageSize, rowCount)} of ${rowCount?.toLocaleString()}` }), _jsx(Button, { onPress: () => tanTable.firstPage(), isDisabled: !tanTable.getCanPreviousPage(), variant: "neutral", size: "icon", children: _jsx(ChevronFirst, {}) }), _jsx(Button, { onPress: () => tanTable.previousPage(), isDisabled: !tanTable.getCanPreviousPage(), variant: "neutral", size: "icon", children: _jsx(ChevronLeft, {}) }), _jsx(Button, { onPress: () => tanTable.nextPage(), isDisabled: !tanTable.getCanNextPage(), variant: "neutral", size: "icon", children: _jsx(ChevronRight, {}) }), _jsx(Button, { onClick: () => tanTable.lastPage(), isDisabled: !tanTable.getCanNextPage(), variant: "neutral", size: "icon", children: _jsx(ChevronLast, {}) })] }));
222
- }
223
- function PageSize() {
224
- const { tanTable } = useDataTable();
225
- const PAGE_SIZES = [10, 20, 30, 40, 50];
226
- return (_jsx(EasyMenu, { label: tanTable.getState().pagination.pageSize.toString(), selectionMode: "single", selectedKeys: [tanTable.getState().pagination.pageSize.toString()], items: PAGE_SIZES.map(s => ({ id: s.toString(), value: s })), children: (items) => _jsx(MenuItem, { onAction: () => tanTable.setPageSize(items.value), children: items.value }) }));
227
- }
228
- import { RotateCw } from "lucide-react";
229
- function Actions({ tableActions }) {
230
- const { query, tanTable, searchQuery, setSearchQuery } = useDataTable();
231
- return (_jsxs("section", { className: "flex bg-card justify-between my-0 p-icon border gap-icon overflow-auto", children: [_jsxs("div", { className: "flex gap-icon", children: [_jsx(Button, { isPending: query.isFetching, onClick: () => query.refetch(), variant: "neutral", size: "icon", children: _jsx(RotateCw, {}) }), tableActions
232
- .filter(ta => ta.bulk === tanTable.getSelectedRowModel().rows.length > 0)
233
- .map((ta, i) => {
234
- const Icon = ta.icon;
235
- return (_jsx(Button, { type: "button", isDisabled: query.isFetching, className: "animate-in fade-in slide-in-from-left-15 duration-300 transition-transform", onPress: (e) => { ta.onClick(e, tanTable); }, size: 'icon', children: _jsx(Icon, {}) }, `${i}-${ta.bulk}`));
236
- })] }), _jsxs("div", { className: "flex gap-icon", children: [_jsx(DataTableFilter, {}), (_jsx(SearchField, { value: searchQuery, onChange: setSearchQuery }))] })] }));
237
- }
238
- import { closestCenter, DndContext, DragOverlay, KeyboardSensor, PointerSensor, useSensor, useSensors } from "@dnd-kit/core";
239
- import { CSS } from "@dnd-kit/utilities";
240
- import { flexRender } from "@tanstack/react-table";
241
- import { DataTableFilter } from "lib/components/data-table/data-table-filter";
242
- import { TABLE_CHECK_BOX_COLUMN, TABLE_DEFAULT_DATE_COLUMNS, TABLE_ID_COLUMN } from "lib/components/data-table/table-commons";
243
- import { SearchField } from "lib/components/inputs/searchfield";
244
- import { Button } from "lib/components/ui/button";
245
- import { Loader } from "lib/components/ui/loader";
246
- import { EasyMenu, MenuItem } from "lib/components/ui/menu";
247
- import { TableBody, TableCell, Table as TableComponent, TableHead, TableHeader, TableRow, } from "lib/components/ui/table";
248
- import { cn } from "lib/utils/primitives";
249
- import { useResourceFormatter } from "lib/utils/resource-names";
250
- import { merge } from "lodash-es";
251
- function SortIcon({ direction, ...props }) {
252
- if (direction === 'asc')
253
- return _jsx(ArrowDownNarrowWide, { ...props });
254
- else if (direction === 'desc')
255
- return _jsx(ArrowDownWideNarrow, { ...props });
256
- else
257
- return _jsx(ArrowUpDown, { ...props });
258
- }
259
- // TODO, automate checking valid HTML
260
- function TableContent({ className }) {
261
- const { tanTable } = useDataTable();
262
- const tableCellStyle = (isSticky, className) => cn("animate-in fade-in slide-in-from-top-10", "px-icon py-2 text-left text-sm font-medium whitespace-nowrap", isSticky && "bg-card sticky right-0 z-50 text-center", className);
263
- return (_jsxs(TableComponent, { className: cn(className), children: [_jsx(TableHeader, { className: "sticky top-0 z-10", children: tanTable.getHeaderGroups().map((headerGroup) => (_jsx(TableRow, { className: cn("h-input"), children: headerGroup.headers.map((header) => (_jsxs(TableHead, { className: tableCellStyle(false, "bg-card"), children: [!header.column.getCanSort() && !header.isPlaceholder
264
- && _jsx(_Fragment, { children: flexRender(header.column.columnDef.header, header.getContext()) }), header.column.getCanSort() && (_jsxs(Button, { variant: "ghost", className: "w-full !justify-start !px-1.5", onPress: header.column.getToggleSortingHandler(), children: [flexRender(header.column.columnDef.header, header.getContext()), _jsx(SortIcon, { direction: header.column.getIsSorted() })] }))] }, header.id))) }, headerGroup.id))) }), _jsx(TableBody, { className: "flex-1 overflow-y-auto relative", children: tanTable.getRowModel().rows.map((row) => (_jsx(TableRow, { className: cn("h-input transition-colors data-[selected=true]:bg-primary/10 hover:bg-muted-foreground/20"), "data-selected": row.getIsSelected(), children: row.getVisibleCells().map((cell) => (_jsx(TableCell, { className: tableCellStyle(cell.column.id === ACTIONS_COLUMN_ID), children: flexRender(cell.column.columnDef.cell, cell.getContext()) }, cell.id))) }, row.id))) })] }));
265
- }
@@ -1,137 +0,0 @@
1
- import { jsx as _jsx } from "react/jsx-runtime";
2
- import { createColumnHelper } from "@tanstack/react-table";
3
- import { Checkbox } from "lib/components/inputs/checkbox";
4
- const cH = createColumnHelper();
5
- export const TABLE_CHECK_BOX_COLUMN = [
6
- cH.accessor("checkbox", {
7
- header: ({ table }) => (_jsx(Checkbox, { isIndeterminate: table.getIsSomeRowsSelected() && !table.getIsAllPageRowsSelected(), isSelected: table.getIsAllPageRowsSelected() || table.getIsSomePageRowsSelected(), onChange: () => table.toggleAllPageRowsSelected(), "aria-label": "Select all" })),
8
- cell: ({ row }) => (_jsx(Checkbox, { isSelected: row.getIsSelected(), onChange: () => row.toggleSelected(), "aria-label": "Select row" })),
9
- enableSorting: false,
10
- enableHiding: false,
11
- }),
12
- ];
13
- export const TABLE_ID_COLUMN = [
14
- cH.accessor("id", {
15
- header: () => "ID",
16
- }),
17
- ];
18
- export const TABLE_DEFAULT_DATE_COLUMNS = [
19
- cH.accessor("createdAt", {
20
- header: () => "Creation Date",
21
- cell: ({ row }) => {
22
- const date = row.getValue("createdAt");
23
- return formatDate(date);
24
- },
25
- enableHiding: false,
26
- }),
27
- cH.accessor("updatedAt", {
28
- header: () => "Last Updated",
29
- cell: ({ row }) => {
30
- const date = row.getValue("updatedAt");
31
- return formatDate(date);
32
- },
33
- enableHiding: false,
34
- }),
35
- ];
36
- // TODO, i18n
37
- export function formatDate(date) {
38
- if (!date)
39
- return null;
40
- const _date = new Date(date);
41
- return new Intl.DateTimeFormat(undefined, {
42
- dateStyle: "medium",
43
- timeStyle: "short",
44
- }).format(_date);
45
- }
46
- /**
47
- * Format multiple license parameters (expired, suspended, revoked) into a single status
48
- */
49
- export function getLicenseStatus(license) {
50
- const licenseExpired = license.expiresAt && new Date(license.expiresAt) < new Date();
51
- // Status Column
52
- switch (true) {
53
- case license.revoked && license.suspended && licenseExpired:
54
- return "Revoked, Suspended, Expired";
55
- case license.revoked && license.suspended:
56
- return "Revoked, Suspended";
57
- case license.revoked && licenseExpired:
58
- return "Revoked, Expired";
59
- case license.suspended && licenseExpired:
60
- return "Suspended, Expired";
61
- case license.suspended:
62
- return "Suspended";
63
- case license.revoked:
64
- return "Revoked";
65
- case licenseExpired:
66
- return "Expired";
67
- default:
68
- return "Active";
69
- }
70
- }
71
- export function getValidityDisplay(validity) {
72
- if (validity === 0 || !validity) {
73
- return "Lifetime";
74
- }
75
- else {
76
- return secondsToDuration(validity);
77
- }
78
- }
79
- export function secondsToDuration(seconds) {
80
- //@ts-ignore
81
- const duration = intervalToDuration({
82
- start: 0,
83
- end: seconds * 1000,
84
- });
85
- const parts = [
86
- duration.years && `${duration.years}y`,
87
- duration.months && `${duration.months}m`,
88
- duration.days && `${duration.days}d`,
89
- duration.hours && `${duration.hours}h`,
90
- ];
91
- // Filter out undefined values and join
92
- return parts.filter(Boolean).join(" ").trim();
93
- }
94
- export function getValueFromData(data, accessor) {
95
- const accessors = accessor.toString().split(".");
96
- let value = data;
97
- for (const acc of accessors) {
98
- value = value?.[acc];
99
- }
100
- return value;
101
- }
102
- export const ALL_OS = {
103
- windows: "Windows",
104
- macos: "macOS",
105
- linux: "Linux",
106
- ios: "iOS",
107
- android: "Android",
108
- };
109
- export function createTableFetchFn(ctxclient, path) {
110
- return async (pagination, sorting, searching, filters) => {
111
- const query = {
112
- ...filters,
113
- page: pagination.pageIndex + 1,
114
- limit: pagination.pageSize,
115
- sort: generateSortParam(sorting[0]),
116
- search: searching,
117
- };
118
- // const pathParams = merge(_baseQueryObject, params);
119
- return ctxclient.GET(path, { query }).then((value) => {
120
- const rowCount = Number.parseInt(value.response.headers.get("Pagination-Count") || "0");
121
- return { total: rowCount, data: value.data };
122
- });
123
- };
124
- }
125
- function generateSortParam(sort) {
126
- if (sort) {
127
- if (sort.desc) {
128
- return `-${sort.id}`;
129
- }
130
- else {
131
- return `+${sort.id}`;
132
- }
133
- }
134
- else {
135
- return "-createdAt";
136
- }
137
- }
@@ -1,25 +0,0 @@
1
- import { Fragment as _Fragment, jsx as _jsx } from "react/jsx-runtime";
2
- import { Checkbox as AriaCheckbox, CheckboxGroup as AriaCheckboxGroup, composeRenderProps } from "react-aria-components";
3
- import { FormField, labelVariants } from "lib/components/inputs/field";
4
- import { useFieldContext } from "lib/utils/form-context";
5
- import { cn } from "lib/utils/primitives";
6
- import { Check, Minus } from "lucide-react";
7
- export const CheckboxGroup = AriaCheckboxGroup;
8
- export function Checkbox({ className, label, description, errorMessage, ...props }) {
9
- return (_jsx("div", { className: "group form-field", children: _jsx(FormField, { label: label, description: description, errorMessage: errorMessage, children: _jsx(AriaCheckbox, { className: composeRenderProps(className, (className) => cn("group/checkbox cursor-pointer focus-ring flex items-center gap-x-2",
10
- /* Disabled */
11
- "disabled-muted", labelVariants, className)), ...props, children: composeRenderProps(_jsx(_Fragment, {}), (_, renderProps) => (_jsx(_Fragment, { children: _jsx("div", { className: cn("flex size-input shrink-0 items-center bg-card justify-center border border-input text-current ring-offset-background",
12
- /* Selected */
13
- "group-data-[indeterminate]/checkbox:bg-primary group-data-[selected]/checkbox:bg-primary group-data-[indeterminate]/checkbox:text-primary-foreground group-data-[selected]/checkbox:text-primary-foreground",
14
- /* Disabled */
15
- "group-data-[disabled]/checkbox:cursor-not-allowed group-data-[disabled]/checkbox:opacity-50",
16
- /* Invalid */
17
- "group-data-[invalid]/checkbox:border-destructive group-data-[invalid]/checkbox:group-data-[selected]/checkbox:bg-destructive group-data-[invalid]/checkbox:group-data-[selected]/checkbox:text-destructive-foreground",
18
- /* Resets */
19
- "focus:outline-none focus-visible:outline-none"), children: renderProps.isIndeterminate ? (_jsx(Minus, { className: "size-icon" })) : renderProps.isSelected ? (_jsx(Check, { className: "size-icon" })) : null }) }))) }) }) }));
20
- }
21
- export function TfCheckbox({ ...props }) {
22
- const field = useFieldContext();
23
- return (_jsx(Checkbox, { isSelected: field.state.value, isDisabled: field.form.state.isSubmitting || props.isDisabled, onChange: () => field.handleChange(!field.state.value), onBlur: field.handleBlur, ...props }));
24
- }
25
- ;
@@ -1,22 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { CalendarIcon } from "lucide-react";
3
- import { DatePicker as AriaDatePicker, DateRangePicker as AriaDateRangePicker, Dialog as AriaDialog, composeRenderProps, Popover } from "react-aria-components";
4
- import { getLocalTimeZone, parseAbsolute } from "@internationalized/date";
5
- import { DateInput } from "lib/components/inputs/datefield";
6
- import { FieldGroup, FormField } from "lib/components/inputs/field";
7
- import { Button } from "lib/components/ui/button";
8
- import { Calendar, RangeCalendar } from "lib/components/ui/calendar";
9
- import { useFieldContext } from "lib/utils/form-context";
10
- import { getFieldErrorMessage } from "lib/utils/form-hook";
11
- import { cn } from "lib/utils/primitives";
12
- const DatePickerContent = ({ className, popoverClassName, ...props }) => (_jsx(Popover, { className: composeRenderProps(popoverClassName, (className) => cn("w-auto p-3", className)), children: _jsx(AriaDialog, { className: cn("flex w-full flex-col gap-y-2 outline-none sm:flex-row sm:gap-x-icon sm:gap-y-0", className), ...props }) }));
13
- export function DatePicker({ label, description, errorMessage, className, ...props }) {
14
- return (_jsxs(AriaDatePicker, { className: composeRenderProps(className, (className) => cn("group flex flex-col gap-2", className)), ...props, children: [_jsx(FormField, { label: label, description: description, errorMessage: errorMessage, children: _jsxs(FieldGroup, { "aria-label": label, children: [_jsx(DateInput, { className: "flex-1", variant: "ghost" }), _jsx(Button, { variant: "ghost", size: "icon", className: '-me-2 ms-2', children: _jsx(CalendarIcon, { "aria-hidden": true }) })] }) }), _jsx(DatePickerContent, { children: _jsx(Calendar, {}) })] }));
15
- }
16
- export function TfDatePicker({ ...props }) {
17
- const field = useFieldContext();
18
- return (_jsx(DatePicker, { hideTimeZone: true, value: field.state.value ? parseAbsolute(field.state.value, getLocalTimeZone()) : null, onChange: (v) => v ? field.handleChange(v.toAbsoluteString()) : field.handleChange(null), onBlur: field.handleBlur, isInvalid: !!getFieldErrorMessage(field), errorMessage: getFieldErrorMessage(field), ...props }));
19
- }
20
- export function DateRangePicker({ label, description, errorMessage, className, ...props }) {
21
- return (_jsxs(AriaDateRangePicker, { className: composeRenderProps(className, (className) => cn("group flex flex-col gap-2", className)), ...props, children: [_jsx(FormField, { label: label, errorMessage: errorMessage, description: description, children: _jsxs(FieldGroup, { children: [_jsx(DateInput, { variant: "ghost", slot: "start" }), _jsx("span", { "aria-hidden": true, className: "px-2 text-sm text-muted-foreground", children: "-" }), _jsx(DateInput, { className: "flex-1", variant: "ghost", slot: "end" }), _jsx(Button, { variant: "ghost", size: "icon", className: "mr-1 data-[focus-visible]:ring-offset-0", children: _jsx(CalendarIcon, { "aria-hidden": true }) })] }) }), _jsx(DatePickerContent, { children: _jsx(RangeCalendar, {}) })] }));
22
- }
@@ -1,25 +0,0 @@
1
- "use client";
2
- import { jsx as _jsx } from "react/jsx-runtime";
3
- import { DateField as AriaDateField, DateInput as AriaDateInput, DateSegment as AriaDateSegment, TimeField as AriaTimeField, composeRenderProps } from "react-aria-components";
4
- import { cn } from "lib/utils/primitives";
5
- import { fieldGroupVariants, FormField } from "./field";
6
- export function DateSegment({ className, ...props }) {
7
- return (_jsx(AriaDateSegment, { className: composeRenderProps(className, (className) => cn("inline caret-transparent outline-0",
8
- /* Placeholder */
9
- "data-[placeholder]:text-muted-foreground",
10
- /* Disabled */
11
- "disabled-muted",
12
- /* Focused */
13
- "data-[focused]:bg-accent data-[focused]:text-accent-foreground",
14
- /* Invalid */
15
- "data-[invalid]:data-[focused]:bg-destructive data-[invalid]:data-[focused]:data-[placeholder]:text-destructive-foreground data-[invalid]:data-[focused]:text-destructive-foreground data-[invalid]:data-[placeholder]:text-destructive data-[invalid]:text-destructive", className)), ...props }));
16
- }
17
- export function DateInput({ className, variant, ...props }) {
18
- return (_jsx(AriaDateInput, { className: composeRenderProps(className, (className) => cn(fieldGroupVariants({ variant }), "text-sm", className)), ...props, children: (segment) => _jsx(DateSegment, { segment: segment }) }));
19
- }
20
- export function DateField({ label, description, className, errorMessage, ...props }) {
21
- return (_jsx(AriaDateField, { className: composeRenderProps(className, (className) => cn("group form-field", className)), ...props, children: _jsx(FormField, { label: label, description: description, errorMessage: errorMessage, children: _jsx(DateInput, {}) }) }));
22
- }
23
- export function TimeField({ label, description, errorMessage, className, ...props }) {
24
- return (_jsx(AriaTimeField, { className: composeRenderProps(className, (className) => cn("group form-field", className)), ...props, children: _jsx(FormField, { label: label, description: description, errorMessage: errorMessage, children: _jsx(DateInput, {}) }) }));
25
- }
@@ -1,48 +0,0 @@
1
- "use client";
2
- import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
- import { cva } from "class-variance-authority";
4
- import { Group as AriaGroup, Label as AriaLabel, Text as AriaText, composeRenderProps } from "react-aria-components";
5
- import { cn } from "lib/utils/primitives";
6
- import { CircleX, Info } from "lucide-react";
7
- export const labelVariants = cva([
8
- "select-none text-sm font-medium leading-none",
9
- /* Disabled */
10
- "disabled-muted",
11
- /* Invalid */
12
- "group-data-[invalid]:text-destructive",
13
- ]);
14
- export function FieldLabel({ className, ...props }) {
15
- return (_jsx(AriaLabel, { className: cn(labelVariants(), className), ...props }));
16
- }
17
- export function FieldDescription({ className, children, ...props }) {
18
- return (_jsxs(AriaText, { className: cn("text-sm text-muted leading-tight", className), ...props, slot: "description", children: [children, _jsx(Info, { className: "inline size-2 align-text-top ms-0.5" })] }));
19
- }
20
- // TODO, if we were to use AriaFieldError, it would use the internal ValidationState Context object, which might be useful for composing inputs but
21
- // this would have significant overlap with what Tanstack Form is already doing for us. It has pros and cons, needs to be discussed and explored.
22
- export function FieldError({ className, children, ...props }) {
23
- return (_jsxs("div", { className: cn("text-sm leading-tight text-destructive duration-150 animate-in transition-transform slide-in-from-top-5 fade-in", className), ...props, children: [children, _jsx(CircleX, { className: "inline size-2 align-text-top ms-0.5" })] }));
24
- }
25
- export const fieldGroupVariants = cva("", {
26
- variants: {
27
- variant: {
28
- default: [
29
- // TODO standardize the padding here
30
- "relative flex h-input w-full items-center overflow-hidden border border-input bg-card px-2 py-2 text-sm ring-offset-background",
31
- /* Focus Within */
32
- "focus-ring",
33
- /* Disabled */
34
- "disabled-muted",
35
- ],
36
- ghost: "",
37
- },
38
- },
39
- defaultVariants: {
40
- variant: "default",
41
- },
42
- });
43
- export function FieldGroup({ className, variant, ...props }) {
44
- return (_jsx(AriaGroup, { className: composeRenderProps(className, (className) => cn(fieldGroupVariants({ variant }), className)), ...props }));
45
- }
46
- export function FormField({ label, description, errorMessage, children }) {
47
- return _jsxs(_Fragment, { children: [label && _jsx(FieldLabel, { children: label }), children, description && (_jsx(FieldDescription, { children: description })), errorMessage && _jsx(FieldError, { children: errorMessage })] });
48
- }
@@ -1,40 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
- import { useQuery } from "@tanstack/react-query";
3
- import { SearchField } from "lib/components/inputs/searchfield";
4
- import { Button } from "lib/components/ui/button";
5
- import { Loader } from "lib/components/ui/loader";
6
- import { Menu, MenuItem } from "lib/components/ui/menu";
7
- import { Popover, PopoverTrigger } from "lib/components/ui/popover";
8
- import { useFieldContext } from "lib/utils/form-context";
9
- import { useId, useState } from "react";
10
- import { Autocomplete } from 'react-aria-components';
11
- export function IdSearchInput({ value, disabled = false, searchFn, multiple, onChange, onBlur, accessor = 'id', idLookup }) {
12
- const id = useId();
13
- const [search, _setSearch] = useState('');
14
- const { data, isError, isFetching, error } = useQuery({
15
- queryKey: [id, search],
16
- queryFn: () => searchFn(search)
17
- });
18
- const namesQuery = useQuery({
19
- queryKey: [id, value],
20
- queryFn: () => idLookup(Array.from(value.keys()).map(id => id.toString())),
21
- enabled: idLookup && value.size > 0
22
- });
23
- const renderButtonLabel = () => {
24
- return namesQuery.data?.join(',');
25
- };
26
- return _jsx(_Fragment, { children: _jsxs(PopoverTrigger, { onOpenChange: (o) => {
27
- if (!o) {
28
- // searchInputRef.current?.focus();
29
- onBlur?.(value);
30
- }
31
- }, children: [_jsx(Button, { className: 'min-w-3xs', isDisabled: disabled, children: renderButtonLabel() }), _jsx(Popover, { className: 'p-2', children: _jsxs(Autocomplete, { inputValue: search, onInputChange: _setSearch, children: [_jsx(SearchField, { className: 'mb-icon', autoFocus: true }), isFetching && _jsx(Loader, { className: "p-input" }), !isFetching && !isError && _jsx(Menu, { selectedKeys: value, selectionMode: multiple ? "multiple" : 'single', onSelectionChange: (s) => {
32
- if (typeof (s) === 'string')
33
- return;
34
- onChange(s);
35
- }, className: 'text-sm', items: data, renderEmptyState: () => 'No results found.', children: (item) => (_jsx(MenuItem, { id: item[accessor], children: item.name }, item['id'])) }), isError && _jsx("div", { className: "text-destructive p-icon", children: error.message })] }) })] }) });
36
- }
37
- export function TfIdSearchInput({ disabled, ...props }) {
38
- const field = useFieldContext();
39
- return (_jsx(IdSearchInput, { ...props, disabled: disabled || field.form.state.isSubmitting, value: field.state.value, onBlur: _ => field.handleBlur(), onChange: (e) => field.handleChange(e) }));
40
- }
@@ -1,19 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { OTPInput, OTPInputContext } from "input-otp";
3
- import { cn } from "lib/utils/primitives";
4
- import { Minus } from "lucide-react";
5
- import * as React from "react";
6
- export function InputOTP({ className, containerClassName, ...props }) {
7
- return (_jsx(OTPInput, { containerClassName: cn("flex items-center gap-2 has-disabled:opacity-50", containerClassName), className: cn("disabled:cursor-not-allowed", className), ...props }));
8
- }
9
- export function InputOTPGroup({ className, ...props }) {
10
- return _jsx("div", { className: cn("flex items-center", className), ...props });
11
- }
12
- export function InputOTPSlot({ index, className, ...props }) {
13
- const inputOTPContext = React.use(OTPInputContext);
14
- const { char, hasFakeCaret, isActive } = inputOTPContext.slots[index];
15
- return (_jsxs("div", { className: cn("relative flex h-input w-9 items-center justify-center border-2 border-input body transition-all", isActive ? "z-10 border-2 border-primary" : "", className), ...props, children: [char, hasFakeCaret && (_jsx("div", { className: "pointer-events-none absolute inset-0 flex items-center justify-center", children: _jsx("div", { className: "h-icon w-px animate-caret-blink bg-foreground duration-1000" }) }))] }));
16
- }
17
- export function InputOTPSeparator({ ...props }) {
18
- return (_jsx("div", { role: "separator", ...props, children: _jsx(Minus, {}) }));
19
- }
@@ -1,18 +0,0 @@
1
- import { jsx as _jsx } from "react/jsx-runtime";
2
- import { FormField } from "lib/components/inputs/field";
3
- import { EasyMenu, MenuItem } from "lib/components/ui/menu";
4
- import { useFieldContext } from "lib/utils/form-context";
5
- import { getFieldErrorMessage } from "lib/utils/form-hook";
6
- export function MultiSelect({ items, value, onChange: setValue, label, errorMessage, description, ...props }) {
7
- return (_jsx("div", { className: "group form-field", children: _jsx(FormField, { label, description, errorMessage, children: _jsx(EasyMenu, { selectionMode: "multiple", selectedKeys: value, onSelectionChange: (v) => {
8
- if (typeof (v) === 'string')
9
- return;
10
- setValue(v);
11
- }, items: items, label: value.size, ...props, children: (item) => _jsx(MenuItem, { id: item.id, isDisabled: item?.disabled, children: item.label }, item.id) }) }) }));
12
- }
13
- ;
14
- export function TfMultiSelect({ ...props }) {
15
- const field = useFieldContext();
16
- return (_jsx(MultiSelect, { value: field.state.value, onChange: field.setValue, onClose: field.handleBlur, errorMessage: getFieldErrorMessage(field), ...props }));
17
- }
18
- ;
@@ -1,25 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { Input as AriaInput, NumberField as AriaNumberField, composeRenderProps } from "react-aria-components";
3
- import { Button } from "lib/components/ui/button";
4
- import { useFieldContext } from "lib/utils/form-context";
5
- import { getFieldErrorMessage } from "lib/utils/form-hook";
6
- import { cn } from "lib/utils/primitives";
7
- import { ChevronDown, ChevronUp } from "lucide-react";
8
- import { FieldGroup, FormField } from "./field";
9
- const ANumberField = AriaNumberField;
10
- function NumberFieldInput({ className, ...props }) {
11
- return (_jsx(AriaInput, { className: composeRenderProps(className, (className) => cn("w-fit min-w-0 flex-1 border-r border-transparent bg-card pr-2 outline-0 placeholder:text-muted-foreground [&::-webkit-search-cancel-button]:hidden", className)), ...props }));
12
- }
13
- function NumberFieldSteppers({ className, ...props }) {
14
- return (_jsxs("div", { className: cn("absolute right-0 flex h-full flex-col border-l", className), ...props, children: [_jsx(NumberFieldStepper, { slot: "increment", children: _jsx(ChevronUp, { "aria-hidden": true, className: "size-icon" }) }), _jsx("div", { className: "border-b" }), _jsx(NumberFieldStepper, { slot: "decrement", children: _jsx(ChevronDown, { "aria-hidden": true, className: "size-icon" }) })] }));
15
- }
16
- function NumberFieldStepper({ className, ...props }) {
17
- return (_jsx(Button, { className: composeRenderProps(className, (className) => cn("w-auto grow h-3 px-0.5 text-muted-foreground", className)), variant: "ghost", size: "none", ...props }));
18
- }
19
- export function NumberField({ label, description, errorMessage, className, ...props }) {
20
- return (_jsx(ANumberField, { className: composeRenderProps(className, (className) => cn("group form-field", className)), ...props, children: _jsx(FormField, { label: label, description: description, errorMessage: errorMessage, children: _jsxs(FieldGroup, { children: [_jsx(NumberFieldInput, {}), _jsx(NumberFieldSteppers, {})] }) }) }));
21
- }
22
- export function TfNumberField({ isDisabled, ...props }) {
23
- const field = useFieldContext();
24
- return (_jsx(NumberField, { isInvalid: !!getFieldErrorMessage(field), isDisabled: isDisabled || field.form.state.isSubmitting, value: field.state.value, id: field.name, onChange: field.handleChange, onBlur: field.handleBlur, errorMessage: getFieldErrorMessage(field), ...props }));
25
- }