torch-glare 2.3.0 → 2.4.1

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 (264) hide show
  1. package/README.md +8 -0
  2. package/apps/lib/components/ActionButton.tsx +7 -12
  3. package/apps/lib/components/ActionsGroup.tsx +4 -15
  4. package/apps/lib/components/AlertDialog.tsx +173 -191
  5. package/apps/lib/components/Avatar.tsx +13 -16
  6. package/apps/lib/components/Badge.tsx +7 -3
  7. package/apps/lib/components/BadgeField.tsx +76 -71
  8. package/apps/lib/components/Breadcrumb.tsx +49 -85
  9. package/apps/lib/components/Button.tsx +20 -19
  10. package/apps/lib/components/ButtonGroup.tsx +31 -41
  11. package/apps/lib/components/Calendar.tsx +51 -29
  12. package/apps/lib/components/Card.tsx +2 -13
  13. package/apps/lib/components/ChartBlockTool.ts +17 -52
  14. package/apps/lib/components/Checkbox.tsx +9 -16
  15. package/apps/lib/components/ContextMenu.tsx +110 -106
  16. package/apps/lib/components/CountBadge.tsx +4 -6
  17. package/apps/lib/components/DataTable.tsx +196 -216
  18. package/apps/lib/components/DataViews/DataViewRadio.tsx +10 -8
  19. package/apps/lib/components/DataViews/DataViewsConfigPanel.tsx +21 -55
  20. package/apps/lib/components/DataViews/DataViewsHeader.tsx +1 -3
  21. package/apps/lib/components/DataViews/DataViewsLayout.tsx +5 -12
  22. package/apps/lib/components/DataViews/FilterPanel.tsx +173 -150
  23. package/apps/lib/components/DataViews/HeaderSearch.tsx +1 -5
  24. package/apps/lib/components/DataViews/InboxView.tsx +22 -68
  25. package/apps/lib/components/DataViews/InboxViewCard.tsx +68 -77
  26. package/apps/lib/components/DataViews/KanbanView.tsx +8 -25
  27. package/apps/lib/components/DataViews/PanelControls.tsx +3 -13
  28. package/apps/lib/components/DataViews/SettingsPanel.tsx +83 -89
  29. package/apps/lib/components/DataViews/TableView.tsx +8 -28
  30. package/apps/lib/components/DataViews/TreeView.tsx +12 -40
  31. package/apps/lib/components/DataViews/badgeAdapter.ts +32 -28
  32. package/apps/lib/components/DataViews/fieldRenderers.tsx +106 -141
  33. package/apps/lib/components/DataViews/filters/DatePickerRangeFilter.tsx +87 -0
  34. package/apps/lib/components/DataViews/filters/DateRangePopover.tsx +39 -32
  35. package/apps/lib/components/DataViews/filters/PresetChips.tsx +15 -15
  36. package/apps/lib/components/DataViews/filters/RangeSliderWithInputs.tsx +69 -58
  37. package/apps/lib/components/DataViews/index.ts +26 -26
  38. package/apps/lib/components/DataViews/tree/TreeDrawer.tsx +12 -16
  39. package/apps/lib/components/DataViews/tree/TreeSidebar.tsx +28 -31
  40. package/apps/lib/components/DataViews/types.ts +111 -114
  41. package/apps/lib/components/DatePicker.tsx +198 -191
  42. package/apps/lib/components/Dialog.tsx +92 -105
  43. package/apps/lib/components/Divider.tsx +21 -24
  44. package/apps/lib/components/Drawer.tsx +79 -139
  45. package/apps/lib/components/DropdownMenu.tsx +144 -181
  46. package/apps/lib/components/FieldHint.tsx +4 -11
  47. package/apps/lib/components/Form.tsx +146 -155
  48. package/apps/lib/components/FormStepper.tsx +9 -39
  49. package/apps/lib/components/HeaderBar.tsx +119 -0
  50. package/apps/lib/components/ImageAttachment.tsx +111 -73
  51. package/apps/lib/components/InnerLabelField.tsx +20 -16
  52. package/apps/lib/components/Input.tsx +171 -172
  53. package/apps/lib/components/InputField.tsx +44 -45
  54. package/apps/lib/components/InputOTP.tsx +68 -69
  55. package/apps/lib/components/Label.tsx +31 -35
  56. package/apps/lib/components/LabelField.tsx +4 -5
  57. package/apps/lib/components/LabeledCheckBox.tsx +8 -12
  58. package/apps/lib/components/LabeledRadio.tsx +7 -5
  59. package/apps/lib/components/LinkButton.tsx +2 -9
  60. package/apps/lib/components/LoginButton.tsx +4 -9
  61. package/apps/lib/components/PasswordLevel.tsx +5 -5
  62. package/apps/lib/components/Popover.tsx +15 -33
  63. package/apps/lib/components/ProfileMenu.tsx +67 -72
  64. package/apps/lib/components/Radio.tsx +1 -5
  65. package/apps/lib/components/RadioCard.tsx +9 -28
  66. package/apps/lib/components/ScrollArea.tsx +45 -43
  67. package/apps/lib/components/SearchField.tsx +49 -39
  68. package/apps/lib/components/SearchableSelect.tsx +46 -52
  69. package/apps/lib/components/SearchableTable.tsx +199 -219
  70. package/apps/lib/components/SearchableTree.tsx +469 -0
  71. package/apps/lib/components/SearchableTreeDialog.tsx +493 -0
  72. package/apps/lib/components/SectionBlock.tsx +4 -16
  73. package/apps/lib/components/Select.tsx +53 -80
  74. package/apps/lib/components/SimpleSelect.tsx +196 -187
  75. package/apps/lib/components/Skeleton.tsx +9 -12
  76. package/apps/lib/components/SlideDatePicker.tsx +215 -166
  77. package/apps/lib/components/SpinLoading.tsx +33 -49
  78. package/apps/lib/components/Stepper.tsx +13 -56
  79. package/apps/lib/components/Switch.tsx +8 -10
  80. package/apps/lib/components/TabFormItem.tsx +3 -12
  81. package/apps/lib/components/TabSwitch.tsx +7 -34
  82. package/apps/lib/components/Table.tsx +60 -75
  83. package/apps/lib/components/TableDnDWrapper.ts +15 -48
  84. package/apps/lib/components/TextEditor.tsx +93 -104
  85. package/apps/lib/components/Textarea.tsx +8 -12
  86. package/apps/lib/components/Timeline.tsx +21 -41
  87. package/apps/lib/components/Toast.tsx +83 -83
  88. package/apps/lib/components/Toggle.tsx +112 -114
  89. package/apps/lib/components/ToggleButton.tsx +1 -1
  90. package/apps/lib/components/Tooltip.tsx +24 -19
  91. package/apps/lib/components/TransparentLabel.tsx +61 -62
  92. package/apps/lib/components/TreeDropDown.tsx +86 -52
  93. package/apps/lib/components/TreeFolder/TreeFolder.tsx +15 -48
  94. package/apps/lib/components/TreeFolder/TreeFolderBreadcrumb.tsx +16 -21
  95. package/apps/lib/components/TreeFolder/TreeFolderRow.tsx +9 -20
  96. package/apps/lib/components/TreeFolder/TreeFolderStyles.tsx +3 -3
  97. package/apps/lib/components/TreeFolder/icons.tsx +14 -17
  98. package/apps/lib/components/TreeFolder/index.ts +15 -8
  99. package/apps/lib/components/TreeFolder/treeFolderUtils.ts +47 -52
  100. package/apps/lib/components/TreeFolder/types.ts +32 -32
  101. package/apps/lib/components/TreeFolder/useTreeFolderDnD.ts +117 -123
  102. package/apps/lib/hooks/useActiveTreeItem.ts +52 -55
  103. package/apps/lib/hooks/useClickOutside.ts +21 -20
  104. package/apps/lib/hooks/useDataViewsState.ts +86 -80
  105. package/apps/lib/hooks/useIsMobile.ts +12 -12
  106. package/apps/lib/hooks/useResize.ts +54 -65
  107. package/apps/lib/hooks/useTagSelection.ts +201 -201
  108. package/apps/lib/layouts/CNLayout.tsx +181 -140
  109. package/apps/lib/layouts/DataViewCard.tsx +4 -18
  110. package/apps/lib/layouts/FieldSection.tsx +2 -6
  111. package/apps/lib/layouts/TreeSubLayout.tsx +24 -38
  112. package/apps/lib/providers/ThemeProvider.tsx +8 -23
  113. package/apps/lib/registry.json +1004 -0
  114. package/apps/lib/tsconfig.json +9 -0
  115. package/apps/lib/utils/cn.ts +1 -1
  116. package/apps/lib/utils/dataViews/columnUtils.ts +46 -44
  117. package/apps/lib/utils/dataViews/fieldUtils.ts +70 -71
  118. package/apps/lib/utils/dataViews/nestedDataUtils.tsx +129 -122
  119. package/apps/lib/utils/dataViews/pathUtils.ts +74 -67
  120. package/apps/lib/utils/dataViews/rangeUtils.ts +121 -112
  121. package/apps/lib/utils/dataViews/treeUtils.ts +204 -211
  122. package/apps/lib/utils/dateFormat.ts +64 -54
  123. package/apps/lib/utils/markdownParser.ts +2 -7
  124. package/apps/lib/utils/resize.ts +21 -25
  125. package/apps/lib/utils/types.ts +13 -13
  126. package/dist/bin/index.js +8 -2
  127. package/dist/bin/index.js.map +1 -1
  128. package/dist/src/shared/getAvailableFiles.d.ts.map +1 -1
  129. package/dist/src/shared/getAvailableFiles.js +6 -1
  130. package/dist/src/shared/getAvailableFiles.js.map +1 -1
  131. package/dist/src/shared/loadRegistry.d.ts +7 -0
  132. package/dist/src/shared/loadRegistry.d.ts.map +1 -0
  133. package/dist/src/shared/loadRegistry.js +31 -0
  134. package/dist/src/shared/loadRegistry.js.map +1 -0
  135. package/dist/src/shared/resolveInstallPlan.d.ts +12 -0
  136. package/dist/src/shared/resolveInstallPlan.d.ts.map +1 -0
  137. package/dist/src/shared/resolveInstallPlan.js +39 -0
  138. package/dist/src/shared/resolveInstallPlan.js.map +1 -0
  139. package/dist/src/types/main.d.ts +24 -0
  140. package/dist/src/types/main.d.ts.map +1 -1
  141. package/docs/README.md +10 -2
  142. package/docs/components/action-button.md +30 -24
  143. package/docs/components/actions-group.md +26 -20
  144. package/docs/components/alert-dialog.md +45 -45
  145. package/docs/components/avatar.md +6 -2
  146. package/docs/components/badge-field.md +6 -2
  147. package/docs/components/badge.md +7 -1
  148. package/docs/components/breadcrumb.md +15 -40
  149. package/docs/components/button-group.md +13 -10
  150. package/docs/components/button.md +58 -33
  151. package/docs/components/calendar.md +26 -19
  152. package/docs/components/card.md +19 -16
  153. package/docs/components/chart-block-tool.md +128 -0
  154. package/docs/components/checkbox.md +16 -8
  155. package/docs/components/cn-layout.md +7 -1
  156. package/docs/components/context-menu.md +47 -24
  157. package/docs/components/count-badge.md +7 -1
  158. package/docs/components/data-table.md +45 -33
  159. package/docs/components/data-views-config-panel.md +18 -14
  160. package/docs/components/data-views-layout.md +20 -17
  161. package/docs/components/date-picker.md +30 -23
  162. package/docs/components/dialog.md +43 -42
  163. package/docs/components/divider.md +10 -4
  164. package/docs/components/drawer.md +8 -33
  165. package/docs/components/dropdown-menu.md +51 -32
  166. package/docs/components/field-hint.md +37 -25
  167. package/docs/components/field-section.md +9 -3
  168. package/docs/components/form-stepper.md +6 -0
  169. package/docs/components/form.md +17 -20
  170. package/docs/components/header-bar.md +187 -0
  171. package/docs/components/image-attachment.md +33 -41
  172. package/docs/components/inbox-view.md +16 -5
  173. package/docs/components/inner-label-field.md +34 -24
  174. package/docs/components/input-field.md +18 -10
  175. package/docs/components/input-otp.md +14 -11
  176. package/docs/components/input.md +22 -16
  177. package/docs/components/kanban-view.md +15 -5
  178. package/docs/components/label-field.md +32 -22
  179. package/docs/components/label.md +43 -32
  180. package/docs/components/labeled-check-box.md +16 -8
  181. package/docs/components/labeled-radio.md +18 -11
  182. package/docs/components/link-button.md +7 -1
  183. package/docs/components/login-button.md +8 -2
  184. package/docs/components/password-level.md +37 -24
  185. package/docs/components/popover.md +26 -23
  186. package/docs/components/profile-menu.md +38 -27
  187. package/docs/components/radio-card.md +16 -9
  188. package/docs/components/radio.md +16 -8
  189. package/docs/components/scroll-area.md +6 -2
  190. package/docs/components/search-field.md +14 -6
  191. package/docs/components/searchable-select.md +19 -14
  192. package/docs/components/searchable-table.md +60 -41
  193. package/docs/components/searchable-tree-dialog.md +190 -0
  194. package/docs/components/searchable-tree.md +200 -0
  195. package/docs/components/section-block.md +130 -4
  196. package/docs/components/select.md +23 -18
  197. package/docs/components/simple-select.md +14 -10
  198. package/docs/components/skeleton.md +43 -33
  199. package/docs/components/slide-date-picker.md +37 -29
  200. package/docs/components/spin-loading.md +32 -23
  201. package/docs/components/stepper.md +6 -0
  202. package/docs/components/switch.md +14 -6
  203. package/docs/components/tab-form-item.md +7 -1
  204. package/docs/components/tab-switch.md +13 -6
  205. package/docs/components/table-dnd-wrapper.md +105 -0
  206. package/docs/components/table-view.md +15 -5
  207. package/docs/components/table.md +28 -28
  208. package/docs/components/text-editor.md +19 -13
  209. package/docs/components/textarea.md +15 -7
  210. package/docs/components/timeline.md +6 -0
  211. package/docs/components/toast.md +35 -26
  212. package/docs/components/toggle-button.md +24 -21
  213. package/docs/components/toggle.md +23 -15
  214. package/docs/components/tooltip.md +42 -30
  215. package/docs/components/transparent-label.md +29 -20
  216. package/docs/components/tree-drop-down.md +31 -23
  217. package/docs/components/tree-sub-layout.md +6 -2
  218. package/docs/components/tree-view.md +16 -5
  219. package/docs/explanation/architecture.md +54 -0
  220. package/docs/explanation/design-system.md +52 -0
  221. package/docs/how-to/data-views-from-backend-response.md +7 -4
  222. package/docs/how-to/guides.md +24 -18
  223. package/docs/migration/changelog.md +38 -0
  224. package/docs/reference/cli.md +87 -0
  225. package/docs/reference/components.md +11 -12
  226. package/docs/reference/hooks.md +8 -8
  227. package/docs/reference/providers.md +22 -22
  228. package/docs/reference/tailwind-plugins.md +2 -2
  229. package/docs/reference/theme.md +85 -0
  230. package/docs/reference/types.md +4 -4
  231. package/docs/reference/utilities.md +19 -26
  232. package/docs/tutorials/building-first-form.md +20 -13
  233. package/docs/tutorials/component-composition.md +34 -50
  234. package/docs/tutorials/getting-started.md +2 -2
  235. package/docs/tutorials/theming-basics.md +13 -10
  236. package/package.json +31 -3
  237. package/dist/src/commands/block.d.ts +0 -5
  238. package/dist/src/commands/block.d.ts.map +0 -1
  239. package/dist/src/commands/block.js +0 -255
  240. package/dist/src/commands/block.js.map +0 -1
  241. package/dist/src/shared/configureFonts.d.ts +0 -6
  242. package/dist/src/shared/configureFonts.d.ts.map +0 -1
  243. package/dist/src/shared/configureFonts.js +0 -106
  244. package/dist/src/shared/configureFonts.js.map +0 -1
  245. package/dist/src/shared/configureGlobalCss.d.ts +0 -6
  246. package/dist/src/shared/configureGlobalCss.d.ts.map +0 -1
  247. package/dist/src/shared/configureGlobalCss.js +0 -154
  248. package/dist/src/shared/configureGlobalCss.js.map +0 -1
  249. package/dist/src/shared/configureTailwind.d.ts +0 -7
  250. package/dist/src/shared/configureTailwind.d.ts.map +0 -1
  251. package/dist/src/shared/configureTailwind.js +0 -163
  252. package/dist/src/shared/configureTailwind.js.map +0 -1
  253. package/dist/src/shared/detectFramework.d.ts +0 -23
  254. package/dist/src/shared/detectFramework.d.ts.map +0 -1
  255. package/dist/src/shared/detectFramework.js +0 -119
  256. package/dist/src/shared/detectFramework.js.map +0 -1
  257. package/dist/src/shared/installBaseUtils.d.ts +0 -5
  258. package/dist/src/shared/installBaseUtils.d.ts.map +0 -1
  259. package/dist/src/shared/installBaseUtils.js +0 -79
  260. package/dist/src/shared/installBaseUtils.js.map +0 -1
  261. package/dist/src/shared/resolveAliases.d.ts +0 -24
  262. package/dist/src/shared/resolveAliases.d.ts.map +0 -1
  263. package/dist/src/shared/resolveAliases.js +0 -98
  264. package/dist/src/shared/resolveAliases.js.map +0 -1
@@ -0,0 +1,9 @@
1
+ {
2
+ "extends": "../tsconfig.json",
3
+ "compilerOptions": {
4
+ "noEmit": true,
5
+ "types": []
6
+ },
7
+ "include": ["**/*.ts", "**/*.tsx"],
8
+ "exclude": ["node_modules"]
9
+ }
@@ -2,5 +2,5 @@ import { clsx, type ClassValue } from "clsx";
2
2
  import { twMerge } from "tailwind-merge";
3
3
 
4
4
  export function cn(...inputs: ClassValue[]) {
5
- return twMerge(clsx(inputs));
5
+ return twMerge(clsx(inputs));
6
6
  }
@@ -1,28 +1,28 @@
1
- import type { DynamicColumnConfig, DynamicRecord } from "../../components/DataViews/types"
2
- import { isPlainObject } from "./nestedDataUtils"
1
+ import type { DynamicColumnConfig, DynamicRecord } from "../../components/DataViews/types";
2
+ import { isPlainObject } from "./nestedDataUtils";
3
3
 
4
4
  export function detectColumns(data: DynamicRecord[]): DynamicColumnConfig[] {
5
5
  if (!data || data.length === 0) {
6
- return []
6
+ return [];
7
7
  }
8
8
 
9
- const allKeys = new Set<string>()
9
+ const allKeys = new Set<string>();
10
10
  data.forEach((item) => {
11
- Object.keys(item).forEach((key) => allKeys.add(key))
12
- })
11
+ Object.keys(item).forEach((key) => allKeys.add(key));
12
+ });
13
13
 
14
- const columns: DynamicColumnConfig[] = []
15
- let order = 0
14
+ const columns: DynamicColumnConfig[] = [];
15
+ let order = 0;
16
16
 
17
17
  allKeys.forEach((key) => {
18
- if (key.startsWith("_")) return
18
+ if (key.startsWith("_")) return;
19
19
 
20
- const firstValue = data.find((item) => item[key] != null)?.[key]
20
+ const firstValue = data.find((item) => item[key] != null)?.[key];
21
21
 
22
- if (isPlainObject(firstValue)) return
23
- if (Array.isArray(firstValue) && firstValue.length > 0 && isPlainObject(firstValue[0])) return
22
+ if (isPlainObject(firstValue)) return;
23
+ if (Array.isArray(firstValue) && firstValue.length > 0 && isPlainObject(firstValue[0])) return;
24
24
 
25
- const type = inferColumnType(key, firstValue)
25
+ const type = inferColumnType(key, firstValue);
26
26
 
27
27
  columns.push({
28
28
  id: key,
@@ -30,54 +30,56 @@ export function detectColumns(data: DynamicRecord[]): DynamicColumnConfig[] {
30
30
  visible: true,
31
31
  order: order++,
32
32
  type,
33
+ });
34
+ });
35
+
36
+ return columns
37
+ .sort((a, b) => {
38
+ if (a.id === "id") return -1;
39
+ if (b.id === "id") return 1;
40
+ return a.label.localeCompare(b.label);
33
41
  })
34
- })
35
-
36
- return columns.sort((a, b) => {
37
- if (a.id === "id") return -1
38
- if (b.id === "id") return 1
39
- return a.label.localeCompare(b.label)
40
- }).map((col, idx) => ({ ...col, order: idx }))
42
+ .map((col, idx) => ({ ...col, order: idx }));
41
43
  }
42
44
 
43
45
  function inferColumnType(
44
46
  key: string,
45
- value: any
47
+ value: unknown,
46
48
  ): "text" | "number" | "date" | "badge" | "array" | "boolean" {
47
49
  if (key.toLowerCase().includes("date") || key.toLowerCase().includes("time")) {
48
- return "date"
50
+ return "date";
49
51
  }
50
52
  if (key.toLowerCase().includes("status") || key.toLowerCase().includes("priority")) {
51
- return "badge"
53
+ return "badge";
52
54
  }
53
55
  if (key.toLowerCase().includes("tag") || key.toLowerCase().includes("label")) {
54
- return "array"
56
+ return "array";
55
57
  }
56
58
 
57
59
  if (value === null || value === undefined) {
58
- return "text"
60
+ return "text";
59
61
  }
60
62
 
61
63
  if (typeof value === "boolean") {
62
- return "boolean"
64
+ return "boolean";
63
65
  }
64
66
 
65
67
  if (typeof value === "number") {
66
- return "number"
68
+ return "number";
67
69
  }
68
70
 
69
71
  if (Array.isArray(value)) {
70
- return "array"
72
+ return "array";
71
73
  }
72
74
 
73
75
  if (typeof value === "string") {
74
76
  if (!isNaN(Date.parse(value)) && /^\d{4}-\d{2}-\d{2}/.test(value)) {
75
- return "date"
77
+ return "date";
76
78
  }
77
- return "text"
79
+ return "text";
78
80
  }
79
81
 
80
- return "text"
82
+ return "text";
81
83
  }
82
84
 
83
85
  function formatLabel(key: string): string {
@@ -85,33 +87,33 @@ function formatLabel(key: string): string {
85
87
  return key
86
88
  .split("_")
87
89
  .map((word) => word.charAt(0).toUpperCase() + word.slice(1))
88
- .join(" ")
90
+ .join(" ");
89
91
  }
90
92
 
91
93
  return key
92
94
  .replace(/([A-Z])/g, " $1")
93
95
  .replace(/^./, (str) => str.toUpperCase())
94
- .trim()
96
+ .trim();
95
97
  }
96
98
 
97
99
  export function mergeColumns(
98
100
  detected: DynamicColumnConfig[],
99
- custom?: Partial<DynamicColumnConfig>[]
101
+ custom?: Partial<DynamicColumnConfig>[],
100
102
  ): DynamicColumnConfig[] {
101
103
  if (!custom || custom.length === 0) {
102
- return detected
104
+ return detected;
103
105
  }
104
106
 
105
- const merged = [...detected]
106
- const customMap = new Map(custom.map((col) => [col.id, col]))
107
+ const merged = [...detected];
108
+ const customMap = new Map(custom.map((col) => [col.id, col]));
107
109
 
108
110
  merged.forEach((col, idx) => {
109
- const customCol = customMap.get(col.id)
111
+ const customCol = customMap.get(col.id);
110
112
  if (customCol) {
111
- merged[idx] = { ...col, ...customCol }
112
- customMap.delete(col.id)
113
+ merged[idx] = { ...col, ...customCol };
114
+ customMap.delete(col.id);
113
115
  }
114
- })
116
+ });
115
117
 
116
118
  customMap.forEach((customCol) => {
117
119
  if (customCol.id) {
@@ -122,9 +124,9 @@ export function mergeColumns(
122
124
  order: customCol.order ?? merged.length,
123
125
  type: customCol.type || "text",
124
126
  render: customCol.render,
125
- })
127
+ });
126
128
  }
127
- })
129
+ });
128
130
 
129
- return merged.sort((a, b) => a.order - b.order)
131
+ return merged.sort((a, b) => a.order - b.order);
130
132
  }
@@ -4,11 +4,11 @@ import type {
4
4
  FieldType,
5
5
  DynamicColumnConfig,
6
6
  InboxConfig,
7
- } from "../../components/DataViews/types"
8
- import { findFirstDefined, formatPathLabel, getByPath } from "./pathUtils"
9
- import { isPlainObject, isCurrencyField, isRatingField } from "./nestedDataUtils"
7
+ } from "../../components/DataViews/types";
8
+ import { findFirstDefined, formatPathLabel, getByPath } from "./pathUtils";
9
+ import { isPlainObject, isCurrencyField, isRatingField } from "./nestedDataUtils";
10
10
 
11
- const ISO_DATE = /^\d{4}-\d{2}-\d{2}/
11
+ const ISO_DATE = /^\d{4}-\d{2}-\d{2}/;
12
12
 
13
13
  const KEY_HINTS: Array<[RegExp, FieldType]> = [
14
14
  [/(^|[._])status$/i, "enum-badge"],
@@ -20,46 +20,46 @@ const KEY_HINTS: Array<[RegExp, FieldType]> = [
20
20
  [/(^|[._])(image|thumbnail|photo|picture)$/i, "image"],
21
21
  [/(^|[._])tags?$|labels?$/i, "badge-array"],
22
22
  [/(date|time)$/i, "date-format"],
23
- ]
23
+ ];
24
24
 
25
- export function inferFieldType(path: string, value: any): FieldType {
25
+ export function inferFieldType(path: string, value: unknown): FieldType {
26
26
  for (const [re, type] of KEY_HINTS) {
27
- if (re.test(path)) return type
27
+ if (re.test(path)) return type;
28
28
  }
29
29
 
30
- if (isCurrencyField(path)) return "currency"
31
- if (isRatingField(path) && typeof value === "number" && value <= 5) return "star-rating"
30
+ if (isCurrencyField(path)) return "currency";
31
+ if (isRatingField(path) && typeof value === "number" && value <= 5) return "star-rating";
32
32
 
33
- if (value === null || value === undefined) return "text"
34
- if (typeof value === "boolean") return "boolean"
35
- if (typeof value === "number") return "number"
36
- if (Array.isArray(value)) return "badge-array"
33
+ if (value === null || value === undefined) return "text";
34
+ if (typeof value === "boolean") return "boolean";
35
+ if (typeof value === "number") return "number";
36
+ if (Array.isArray(value)) return "badge-array";
37
37
  if (typeof value === "string") {
38
- if (ISO_DATE.test(value) && !isNaN(Date.parse(value))) return "date-format"
39
- return "text"
38
+ if (ISO_DATE.test(value) && !isNaN(Date.parse(value))) return "date-format";
39
+ return "text";
40
40
  }
41
- return "text"
41
+ return "text";
42
42
  }
43
43
 
44
44
  export function detectFields(data: DynamicRecord[]): FieldConfig[] {
45
- if (!data || data.length === 0) return []
45
+ if (!data || data.length === 0) return [];
46
46
 
47
- const allKeys = new Set<string>()
47
+ const allKeys = new Set<string>();
48
48
  for (const item of data) {
49
49
  if (item && typeof item === "object") {
50
- for (const k of Object.keys(item)) allKeys.add(k)
50
+ for (const k of Object.keys(item)) allKeys.add(k);
51
51
  }
52
52
  }
53
53
 
54
- const fields: FieldConfig[] = []
55
- let order = 0
54
+ const fields: FieldConfig[] = [];
55
+ let order = 0;
56
56
 
57
57
  for (const key of allKeys) {
58
- if (key.startsWith("_")) continue
58
+ if (key.startsWith("_")) continue;
59
59
 
60
- const sample = findFirstDefined(data, key)
61
- if (isPlainObject(sample)) continue
62
- if (Array.isArray(sample) && sample.length > 0 && isPlainObject(sample[0])) continue
60
+ const sample = findFirstDefined(data, key);
61
+ if (isPlainObject(sample)) continue;
62
+ if (Array.isArray(sample) && sample.length > 0 && isPlainObject(sample[0])) continue;
63
63
 
64
64
  fields.push({
65
65
  path: key,
@@ -67,32 +67,29 @@ export function detectFields(data: DynamicRecord[]): FieldConfig[] {
67
67
  type: inferFieldType(key, sample),
68
68
  visible: true,
69
69
  order: order++,
70
- })
70
+ });
71
71
  }
72
72
 
73
73
  return fields
74
74
  .sort((a, b) => {
75
- if (a.path === "id") return -1
76
- if (b.path === "id") return 1
77
- return (a.label || "").localeCompare(b.label || "")
75
+ if (a.path === "id") return -1;
76
+ if (b.path === "id") return 1;
77
+ return (a.label || "").localeCompare(b.label || "");
78
78
  })
79
- .map((f, i) => ({ ...f, order: i }))
79
+ .map((f, i) => ({ ...f, order: i }));
80
80
  }
81
81
 
82
- export function mergeFields(
83
- detected: FieldConfig[],
84
- custom?: FieldConfig[],
85
- ): FieldConfig[] {
86
- if (!custom || custom.length === 0) return detected
82
+ export function mergeFields(detected: FieldConfig[], custom?: FieldConfig[]): FieldConfig[] {
83
+ if (!custom || custom.length === 0) return detected;
87
84
 
88
- const out = [...detected]
89
- const byPath = new Map(out.map((f, i) => [f.path, i]))
85
+ const out = [...detected];
86
+ const byPath = new Map(out.map((f, i) => [f.path, i]));
90
87
 
91
88
  for (const c of custom) {
92
- if (!c.path) continue
93
- const existing = byPath.get(c.path)
89
+ if (!c.path) continue;
90
+ const existing = byPath.get(c.path);
94
91
  if (existing != null) {
95
- out[existing] = { ...out[existing], ...c }
92
+ out[existing] = { ...out[existing], ...c };
96
93
  } else {
97
94
  out.push({
98
95
  ...c,
@@ -100,24 +97,27 @@ export function mergeFields(
100
97
  label: c.label ?? formatPathLabel(c.path),
101
98
  visible: c.visible ?? true,
102
99
  order: c.order ?? out.length,
103
- })
104
- byPath.set(c.path, out.length - 1)
100
+ });
101
+ byPath.set(c.path, out.length - 1);
105
102
  }
106
103
  }
107
104
 
108
105
  return out
109
106
  .map((f, i) => ({ ...f, order: f.order ?? i }))
110
- .sort((a, b) => (a.order ?? 0) - (b.order ?? 0))
107
+ .sort((a, b) => (a.order ?? 0) - (b.order ?? 0));
111
108
  }
112
109
 
113
110
  export function visibleFields(fields: FieldConfig[]): FieldConfig[] {
114
- return fields.filter((f) => f.type !== "hidden" && f.visible !== false)
111
+ return fields.filter((f) => f.type !== "hidden" && f.visible !== false);
115
112
  }
116
113
 
117
- export function fieldToColumn(field: FieldConfig, idx = 0): DynamicColumnConfig & {
118
- __field: FieldConfig
114
+ export function fieldToColumn(
115
+ field: FieldConfig,
116
+ idx = 0,
117
+ ): DynamicColumnConfig & {
118
+ __field: FieldConfig;
119
119
  } {
120
- const legacyType = mapFieldTypeToColumnType(field.type)
120
+ const legacyType = mapFieldTypeToColumnType(field.type);
121
121
  return {
122
122
  id: field.path,
123
123
  label: field.label ?? formatPathLabel(field.path),
@@ -126,7 +126,7 @@ export function fieldToColumn(field: FieldConfig, idx = 0): DynamicColumnConfig
126
126
  type: legacyType,
127
127
  render: field.render,
128
128
  __field: field,
129
- }
129
+ };
130
130
  }
131
131
 
132
132
  function mapFieldTypeToColumnType(t?: FieldType): DynamicColumnConfig["type"] {
@@ -136,63 +136,62 @@ function mapFieldTypeToColumnType(t?: FieldType): DynamicColumnConfig["type"] {
136
136
  case "number-format":
137
137
  case "progress-bar":
138
138
  case "star-rating":
139
- return "number"
139
+ return "number";
140
140
  case "date":
141
141
  case "date-format":
142
- return "date"
142
+ return "date";
143
143
  case "enum-badge":
144
144
  case "icon-text":
145
145
  case "two-line":
146
146
  case "link":
147
- return "badge"
147
+ return "badge";
148
148
  case "badge-array":
149
- return "array"
149
+ return "array";
150
150
  case "boolean":
151
- return "boolean"
151
+ return "boolean";
152
152
  default:
153
- return "text"
153
+ return "text";
154
154
  }
155
155
  }
156
156
 
157
- const STARRED_PATTERNS = ["isStarred", "starred", "favorite", "isFavorite", "pinned"]
158
- const READ_PATTERNS = ["isRead", "read", "seen", "viewed"]
159
- const ATTACHMENT_PATTERNS = ["hasAttachment", "hasAttachments", "attachments", "files"]
160
- const PRIORITY_PATTERNS = ["priority", "urgency", "level", "importance"]
157
+ const STARRED_PATTERNS = ["isStarred", "starred", "favorite", "isFavorite", "pinned"];
158
+ const READ_PATTERNS = ["isRead", "read", "seen", "viewed"];
159
+ const ATTACHMENT_PATTERNS = ["hasAttachment", "hasAttachments", "attachments", "files"];
160
+ const PRIORITY_PATTERNS = ["priority", "urgency", "level", "importance"];
161
161
 
162
162
  function pickField(sample: DynamicRecord, patterns: string[]): string | null {
163
163
  for (const p of patterns) {
164
- if (p in sample) return p
164
+ if (p in sample) return p;
165
165
  }
166
- return null
166
+ return null;
167
167
  }
168
168
 
169
169
  export function resolveInboxConfig(
170
170
  data: DynamicRecord[],
171
171
  user?: InboxConfig,
172
- ): Required<Omit<InboxConfig, "titlePath" | "previewPath">> & Pick<InboxConfig, "titlePath" | "previewPath"> {
173
- const sample = data?.[0] && typeof data[0] === "object" ? data[0] : {}
172
+ ): Required<Omit<InboxConfig, "titlePath" | "previewPath">> &
173
+ Pick<InboxConfig, "titlePath" | "previewPath"> {
174
+ const sample = data?.[0] && typeof data[0] === "object" ? data[0] : {};
174
175
 
175
176
  const auto = {
176
177
  starredField: pickField(sample, STARRED_PATTERNS),
177
178
  readField: pickField(sample, READ_PATTERNS),
178
179
  attachmentField: pickField(sample, ATTACHMENT_PATTERNS),
179
180
  priorityField: pickField(sample, PRIORITY_PATTERNS),
180
- }
181
+ };
181
182
 
182
183
  return {
183
184
  starredField: user?.starredField !== undefined ? user.starredField : auto.starredField,
184
185
  readField: user?.readField !== undefined ? user.readField : auto.readField,
185
- attachmentField: user?.attachmentField !== undefined ? user.attachmentField : auto.attachmentField,
186
+ attachmentField:
187
+ user?.attachmentField !== undefined ? user.attachmentField : auto.attachmentField,
186
188
  priorityField: user?.priorityField !== undefined ? user.priorityField : auto.priorityField,
187
189
  titlePath: user?.titlePath,
188
190
  previewPath: user?.previewPath,
189
- }
191
+ };
190
192
  }
191
193
 
192
- export function readInboxField(
193
- item: DynamicRecord,
194
- field: string | null | undefined,
195
- ): any {
196
- if (!field) return undefined
197
- return getByPath(item, field)
194
+ export function readInboxField(item: DynamicRecord, field: string | null | undefined): unknown {
195
+ if (!field) return undefined;
196
+ return getByPath(item, field);
198
197
  }