@object-ui/plugin-detail 3.1.0 → 3.1.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 (63) hide show
  1. package/.turbo/turbo-build.log +41 -41
  2. package/CHANGELOG.md +11 -0
  3. package/dist/{AddressField-C07oUOY6.js → AddressField-B1iVr404.js} +1 -1
  4. package/dist/{AvatarField-VThNABzo.js → AvatarField-Duw4xOLZ.js} +1 -1
  5. package/dist/{BooleanField-CGHKBzAi.js → BooleanField-CZ4axVeq.js} +1 -1
  6. package/dist/{CodeField-Co_muhRR.js → CodeField-BSz-mk2v.js} +1 -1
  7. package/dist/{ColorField-DLid_tFz.js → ColorField-B522ad8m.js} +1 -1
  8. package/dist/{CurrencyField-Bw-LqANM.js → CurrencyField-Cwr3_pow.js} +1 -1
  9. package/dist/{DateField-BNHAzMB2.js → DateField-DCo6dxud.js} +1 -1
  10. package/dist/{DateTimeField-DjAyn_DQ.js → DateTimeField-BWfBuANO.js} +1 -1
  11. package/dist/{EmailField-xoNcSppb.js → EmailField-CpwbdVCU.js} +1 -1
  12. package/dist/{FileField-DbNJwjU2.js → FileField-DVAUAJ8e.js} +1 -1
  13. package/dist/{GeolocationField-C1AnS6VV.js → GeolocationField-DNCKitgo.js} +1 -1
  14. package/dist/{GridField-DATAHIKf.js → GridField-DSblZNfp.js} +1 -1
  15. package/dist/{ImageField-CEKJpyJp.js → ImageField-DBAlnMon.js} +1 -1
  16. package/dist/{LocationField-jDWXjlpx.js → LocationField-DsHsXA6R.js} +1 -1
  17. package/dist/{LookupField-DQ08L9UQ.js → LookupField-CsT0QQz2.js} +1 -1
  18. package/dist/{MasterDetailField-Dbk529Ea.js → MasterDetailField-Db8b7Gqs.js} +1 -1
  19. package/dist/{NumberField-BVroN9aV.js → NumberField-0IGp7lcA.js} +1 -1
  20. package/dist/{ObjectField-CT3l_IHW.js → ObjectField-BLApgJtS.js} +1 -1
  21. package/dist/{PasswordField-DweVLEE0.js → PasswordField-pHKyNlmo.js} +1 -1
  22. package/dist/{PercentField-ZpWUK97K.js → PercentField-CwgKmlIb.js} +1 -1
  23. package/dist/{PhoneField-mw-9fqZ_.js → PhoneField-lKtbYOdN.js} +1 -1
  24. package/dist/{QRCodeField-Cbb9ck59.js → QRCodeField-BTTasT3w.js} +1 -1
  25. package/dist/{RatingField-CSqgLS6t.js → RatingField-De2X-l44.js} +1 -1
  26. package/dist/{RichTextField-BpfBOd99.js → RichTextField-B5QnvUOr.js} +1 -1
  27. package/dist/{SelectField-B9Ei-5jl.js → SelectField-C9AZRHWu.js} +1 -1
  28. package/dist/{SignatureField-DgGpHnQ8.js → SignatureField-BgcEmYzd.js} +1 -1
  29. package/dist/{SliderField-C6HvOHd8.js → SliderField-BzrttVOY.js} +1 -1
  30. package/dist/{TextAreaField-BK3RgzY3.js → TextAreaField-DSE_CaU6.js} +1 -1
  31. package/dist/{TextField-Bvzx3atT.js → TextField-DFQ4T9PR.js} +1 -1
  32. package/dist/{TimeField-Cuz9-Uai.js → TimeField-F0cfmsps.js} +1 -1
  33. package/dist/{UrlField-B6XHTV73.js → UrlField-DLXrFIH-.js} +1 -1
  34. package/dist/{UserField-ooTul2d6.js → UserField-PXMmxJY9.js} +1 -1
  35. package/dist/{index-CnlyRfY_.js → index-qQ1C-yUR.js} +21560 -21045
  36. package/dist/index.js +20 -18
  37. package/dist/index.umd.cjs +31 -31
  38. package/dist/plugin-detail.css +1 -1
  39. package/dist/src/DetailSection.d.ts +2 -0
  40. package/dist/src/DetailSection.d.ts.map +1 -1
  41. package/dist/src/DetailView.d.ts.map +1 -1
  42. package/dist/src/HeaderHighlight.d.ts +18 -0
  43. package/dist/src/HeaderHighlight.d.ts.map +1 -0
  44. package/dist/src/RelatedList.d.ts +16 -0
  45. package/dist/src/RelatedList.d.ts.map +1 -1
  46. package/dist/src/SectionGroup.d.ts +21 -0
  47. package/dist/src/SectionGroup.d.ts.map +1 -0
  48. package/dist/src/index.d.ts +4 -0
  49. package/dist/src/index.d.ts.map +1 -1
  50. package/dist/src/useDetailTranslation.d.ts.map +1 -1
  51. package/package.json +6 -6
  52. package/src/DetailSection.tsx +8 -2
  53. package/src/DetailView.tsx +271 -61
  54. package/src/HeaderHighlight.tsx +67 -0
  55. package/src/RelatedList.tsx +287 -21
  56. package/src/SectionGroup.tsx +101 -0
  57. package/src/__tests__/DetailSection.test.tsx +1 -1
  58. package/src/__tests__/HeaderHighlight.test.tsx +68 -0
  59. package/src/__tests__/RelatedList.test.tsx +101 -7
  60. package/src/__tests__/SectionGroup.test.tsx +101 -0
  61. package/src/__tests__/roadmap-features.test.tsx +478 -0
  62. package/src/index.tsx +4 -0
  63. package/src/useDetailTranslation.ts +11 -0
@@ -1 +1 @@
1
- {"version":3,"file":"DetailView.d.ts","sourceRoot":"","sources":["../../src/DetailView.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAsC/B,OAAO,KAAK,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAGrE,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,gBAAgB,CAAC;IACzB,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;IACtB,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IACpB,qDAAqD;IACrD,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,kDAAkD;IAClD,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAChF;AAED,eAAO,MAAM,UAAU,EAAE,KAAK,CAAC,EAAE,CAAC,eAAe,CA+hBhD,CAAC"}
1
+ {"version":3,"file":"DetailView.d.ts","sourceRoot":"","sources":["../../src/DetailView.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AA4C/B,OAAO,KAAK,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAMrE,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,gBAAgB,CAAC;IACzB,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;IACtB,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IACpB,qDAAqD;IACrD,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,kDAAkD;IAClD,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAChF;AAED,eAAO,MAAM,UAAU,EAAE,KAAK,CAAC,EAAE,CAAC,eAAe,CAwuBhD,CAAC"}
@@ -0,0 +1,18 @@
1
+ import { HighlightField } from '../../types/src';
2
+ /**
3
+ * ObjectUI
4
+ * Copyright (c) 2024-present ObjectStack Inc.
5
+ *
6
+ * This source code is licensed under the MIT license found in the
7
+ * LICENSE file in the root directory of this source tree.
8
+ */
9
+ import * as React from 'react';
10
+ export interface HeaderHighlightProps {
11
+ fields: HighlightField[];
12
+ data?: any;
13
+ className?: string;
14
+ /** Object name for i18n field label resolution */
15
+ objectName?: string;
16
+ }
17
+ export declare const HeaderHighlight: React.FC<HeaderHighlightProps>;
18
+ //# sourceMappingURL=HeaderHighlight.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"HeaderHighlight.d.ts","sourceRoot":"","sources":["../../src/HeaderHighlight.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAGvD,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,cAAc,EAAE,CAAC;IACzB,IAAI,CAAC,EAAE,GAAG,CAAC;IACX,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,kDAAkD;IAClD,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,eAAO,MAAM,eAAe,EAAE,KAAK,CAAC,EAAE,CAAC,oBAAoB,CA6C1D,CAAC"}
@@ -16,10 +16,26 @@ export interface RelatedListProps {
16
16
  columns?: any[];
17
17
  className?: string;
18
18
  dataSource?: DataSource;
19
+ /** Object name for i18n field label resolution */
20
+ objectName?: string;
19
21
  /** Callback when "New" button is clicked */
20
22
  onNew?: () => void;
21
23
  /** Callback when "View All" button is clicked */
22
24
  onViewAll?: () => void;
25
+ /** Callback when a row Edit action is clicked */
26
+ onRowEdit?: (row: any) => void;
27
+ /** Callback when a row Delete action is clicked */
28
+ onRowDelete?: (row: any) => void;
29
+ /** Page size for pagination (enables pagination when set) */
30
+ pageSize?: number;
31
+ /** Enable column sorting */
32
+ sortable?: boolean;
33
+ /** Enable text filtering */
34
+ filterable?: boolean;
35
+ /** Whether the card is collapsible */
36
+ collapsible?: boolean;
37
+ /** Whether the card starts collapsed (requires collapsible=true) */
38
+ defaultCollapsed?: boolean;
23
39
  }
24
40
  export declare const RelatedList: React.FC<RelatedListProps>;
25
41
  //# sourceMappingURL=RelatedList.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"RelatedList.d.ts","sourceRoot":"","sources":["../../src/RelatedList.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAI/B,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAGnD,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC;IAChC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,GAAG,EAAE,CAAC;IACb,MAAM,CAAC,EAAE,GAAG,CAAC;IACb,OAAO,CAAC,EAAE,GAAG,EAAE,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,4CAA4C;IAC5C,KAAK,CAAC,EAAE,MAAM,IAAI,CAAC;IACnB,iDAAiD;IACjD,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;CACxB;AAED,eAAO,MAAM,WAAW,EAAE,KAAK,CAAC,EAAE,CAAC,gBAAgB,CAoHlD,CAAC"}
1
+ {"version":3,"file":"RelatedList.d.ts","sourceRoot":"","sources":["../../src/RelatedList.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAqB/B,OAAO,KAAK,EAAE,UAAU,EAAiB,MAAM,kBAAkB,CAAC;AAKlE,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC;IAChC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,GAAG,EAAE,CAAC;IACb,MAAM,CAAC,EAAE,GAAG,CAAC;IACb,OAAO,CAAC,EAAE,GAAG,EAAE,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,kDAAkD;IAClD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,4CAA4C;IAC5C,KAAK,CAAC,EAAE,MAAM,IAAI,CAAC;IACnB,iDAAiD;IACjD,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;IACvB,iDAAiD;IACjD,SAAS,CAAC,EAAE,CAAC,GAAG,EAAE,GAAG,KAAK,IAAI,CAAC;IAC/B,mDAAmD;IACnD,WAAW,CAAC,EAAE,CAAC,GAAG,EAAE,GAAG,KAAK,IAAI,CAAC;IACjC,6DAA6D;IAC7D,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,4BAA4B;IAC5B,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,4BAA4B;IAC5B,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,sCAAsC;IACtC,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,oEAAoE;IACpE,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B;AAED,eAAO,MAAM,WAAW,EAAE,KAAK,CAAC,EAAE,CAAC,gBAAgB,CA2VlD,CAAC"}
@@ -0,0 +1,21 @@
1
+ import { SectionGroup as SectionGroupType } from '../../types/src';
2
+ /**
3
+ * ObjectUI
4
+ * Copyright (c) 2024-present ObjectStack Inc.
5
+ *
6
+ * This source code is licensed under the MIT license found in the
7
+ * LICENSE file in the root directory of this source tree.
8
+ */
9
+ import * as React from 'react';
10
+ export interface SectionGroupProps {
11
+ group: SectionGroupType;
12
+ data?: any;
13
+ className?: string;
14
+ objectSchema?: any;
15
+ /** Object name for i18n field label resolution */
16
+ objectName?: string;
17
+ isEditing?: boolean;
18
+ onFieldChange?: (field: string, value: any) => void;
19
+ }
20
+ export declare const SectionGroup: React.FC<SectionGroupProps>;
21
+ //# sourceMappingURL=SectionGroup.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SectionGroup.d.ts","sourceRoot":"","sources":["../../src/SectionGroup.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAS/B,OAAO,KAAK,EAAE,YAAY,IAAI,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAEzE,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,gBAAgB,CAAC;IACxB,IAAI,CAAC,EAAE,GAAG,CAAC;IACX,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,GAAG,CAAC;IACnB,kDAAkD;IAClD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,KAAK,IAAI,CAAC;CACrD;AAED,eAAO,MAAM,YAAY,EAAE,KAAK,CAAC,EAAE,CAAC,iBAAiB,CAsEpD,CAAC"}
@@ -3,6 +3,8 @@ import { DetailSection } from './DetailSection';
3
3
  import { DetailTabs } from './DetailTabs';
4
4
  import { RelatedList } from './RelatedList';
5
5
  export { DetailView, DetailSection, DetailTabs, RelatedList };
6
+ export { SectionGroup } from './SectionGroup';
7
+ export { HeaderHighlight } from './HeaderHighlight';
6
8
  export { inferDetailColumns, isWideFieldType, applyAutoSpan, applyDetailAutoLayout } from './autoLayout';
7
9
  export { useDetailTranslation, DETAIL_DEFAULT_TRANSLATIONS, createSafeTranslationHook } from './useDetailTranslation';
8
10
  export { RecordComments } from './RecordComments';
@@ -26,6 +28,8 @@ export type { DetailViewProps } from './DetailView';
26
28
  export type { DetailSectionProps } from './DetailSection';
27
29
  export type { DetailTabsProps } from './DetailTabs';
28
30
  export type { RelatedListProps } from './RelatedList';
31
+ export type { SectionGroupProps } from './SectionGroup';
32
+ export type { HeaderHighlightProps } from './HeaderHighlight';
29
33
  export type { RecordCommentsProps } from './RecordComments';
30
34
  export type { ActivityTimelineProps, ActivityFilterType } from './ActivityTimeline';
31
35
  export type { InlineCreateRelatedProps, RelatedFieldDefinition, RelatedRecordOption } from './InlineCreateRelated';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.tsx"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"useDetailTranslation.d.ts","sourceRoot":"","sources":["../../src/useDetailTranslation.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH;;;;;;GAMG;AACH,wBAAgB,yBAAyB,CACvC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAChC,OAAO,EAAE,MAAM;aAQE,MAAM,YAAY,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;;;EA0B3D;AAED;;;GAGG;AACH,eAAO,MAAM,2BAA2B,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAkC9D,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,oBAAoB;aAxEd,MAAM,YAAY,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;;;CA2E3D,CAAC"}
1
+ {"version":3,"file":"useDetailTranslation.d.ts","sourceRoot":"","sources":["../../src/useDetailTranslation.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH;;;;;;GAMG;AACH,wBAAgB,yBAAyB,CACvC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAChC,OAAO,EAAE,MAAM;aAQE,MAAM,YAAY,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;;;EA0B3D;AAED;;;GAGG;AACH,eAAO,MAAM,2BAA2B,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CA6C9D,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,oBAAoB;aAnFd,MAAM,YAAY,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;;;CAsF3D,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@object-ui/plugin-detail",
3
- "version": "3.1.0",
3
+ "version": "3.1.1",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
6
  "description": "DetailView plugin for Object UI - comprehensive detail page with sections, tabs, and related lists",
@@ -25,11 +25,11 @@
25
25
  },
26
26
  "dependencies": {
27
27
  "lucide-react": "^0.576.0",
28
- "@object-ui/components": "3.1.0",
29
- "@object-ui/core": "3.1.0",
30
- "@object-ui/fields": "3.1.0",
31
- "@object-ui/react": "3.1.0",
32
- "@object-ui/types": "3.1.0"
28
+ "@object-ui/components": "3.1.1",
29
+ "@object-ui/fields": "3.1.1",
30
+ "@object-ui/core": "3.1.1",
31
+ "@object-ui/react": "3.1.1",
32
+ "@object-ui/types": "3.1.1"
33
33
  },
34
34
  "peerDependencies": {
35
35
  "react": "^18.0.0 || ^19.0.0",
@@ -29,6 +29,7 @@ import { getCellRenderer } from '@object-ui/fields';
29
29
  import type { DetailViewSection as DetailViewSectionType, DetailViewField, FieldMetadata } from '@object-ui/types';
30
30
  import { applyDetailAutoLayout } from './autoLayout';
31
31
  import { useDetailTranslation } from './useDetailTranslation';
32
+ import { useSafeFieldLabel } from '@object-ui/react';
32
33
 
33
34
  export interface DetailSectionProps {
34
35
  section: DetailViewSectionType;
@@ -36,6 +37,8 @@ export interface DetailSectionProps {
36
37
  className?: string;
37
38
  /** Object schema from DataSource for field type enrichment */
38
39
  objectSchema?: any;
40
+ /** Object name for i18n field label resolution */
41
+ objectName?: string;
39
42
  /** Whether inline editing is active */
40
43
  isEditing?: boolean;
41
44
  /** Callback when a field value changes during inline editing */
@@ -47,12 +50,14 @@ export const DetailSection: React.FC<DetailSectionProps> = ({
47
50
  data,
48
51
  className,
49
52
  objectSchema,
53
+ objectName,
50
54
  isEditing = false,
51
55
  onFieldChange,
52
56
  }) => {
53
57
  const [isCollapsed, setIsCollapsed] = React.useState(section.defaultCollapsed ?? false);
54
58
  const [copiedField, setCopiedField] = React.useState<string | null>(null);
55
59
  const { t } = useDetailTranslation();
60
+ const { fieldLabel } = useSafeFieldLabel();
56
61
 
57
62
  const handleCopyField = React.useCallback((fieldName: string, value: any) => {
58
63
  const textValue = value !== null && value !== undefined ? String(value) : '';
@@ -91,7 +96,8 @@ export const DetailSection: React.FC<DetailSectionProps> = ({
91
96
  if (objectDefField.currency && !enrichedField.currency) enrichedField.currency = objectDefField.currency;
92
97
  if (objectDefField.precision !== undefined && enrichedField.precision === undefined) enrichedField.precision = objectDefField.precision;
93
98
  if (objectDefField.format && !enrichedField.format) enrichedField.format = objectDefField.format;
94
- if (objectDefField.reference_to && !enrichedField.reference_to) enrichedField.reference_to = objectDefField.reference_to;
99
+ const refTarget = objectDefField.reference_to || objectDefField.reference;
100
+ if (refTarget && !enrichedField.reference_to) enrichedField.reference_to = refTarget;
95
101
  if (objectDefField.reference_field && !enrichedField.reference_field) enrichedField.reference_field = objectDefField.reference_field;
96
102
  }
97
103
  // Use type-aware cell renderer when field type is available (explicit or enriched)
@@ -110,7 +116,7 @@ export const DetailSection: React.FC<DetailSectionProps> = ({
110
116
  return (
111
117
  <div key={field.name} className={cn("space-y-1.5 group", spanClass)}>
112
118
  <div className="text-xs font-medium text-muted-foreground uppercase tracking-wide">
113
- {field.label || field.name}
119
+ {fieldLabel(objectName || '', field.name, field.label || field.name)}
114
120
  </div>
115
121
  {isEditing && !field.readonly ? (
116
122
  <div className="min-h-[44px] sm:min-h-0">
@@ -21,6 +21,10 @@ import {
21
21
  TooltipContent,
22
22
  TooltipProvider,
23
23
  TooltipTrigger,
24
+ Tabs,
25
+ TabsList,
26
+ TabsTrigger,
27
+ TabsContent,
24
28
  } from '@object-ui/components';
25
29
  import {
26
30
  ArrowLeft,
@@ -40,6 +44,8 @@ import {
40
44
  import { DetailSection } from './DetailSection';
41
45
  import { DetailTabs } from './DetailTabs';
42
46
  import { RelatedList } from './RelatedList';
47
+ import { SectionGroup } from './SectionGroup';
48
+ import { HeaderHighlight } from './HeaderHighlight';
43
49
  import { RecordComments } from './RecordComments';
44
50
  import { ActivityTimeline } from './ActivityTimeline';
45
51
  import { SchemaRenderer } from '@object-ui/react';
@@ -47,6 +53,9 @@ import { buildExpandFields } from '@object-ui/core';
47
53
  import type { DetailViewSchema, DataSource } from '@object-ui/types';
48
54
  import { useDetailTranslation } from './useDetailTranslation';
49
55
 
56
+ /** Default page size for related lists in the detail view */
57
+ const DEFAULT_RELATED_PAGE_SIZE = 5;
58
+
50
59
  export interface DetailViewProps {
51
60
  schema: DetailViewSchema;
52
61
  dataSource?: DataSource;
@@ -288,6 +297,42 @@ export const DetailView: React.FC<DetailViewProps> = ({
288
297
  return () => document.removeEventListener('keydown', handler);
289
298
  }, [schema.recordNavigation]);
290
299
 
300
+ // Auto-discover related lists from objectSchema reference fields
301
+ const discoveredRelated = React.useMemo(() => {
302
+ if (!schema.autoDiscoverRelated || !objectSchema?.fields) return [];
303
+ // Only auto-discover when no explicit related config is provided
304
+ if (schema.related && schema.related.length > 0) return [];
305
+ const refs: Array<{ title: string; type: 'list' | 'grid' | 'table'; objectName: string; referenceField: string }> = [];
306
+ const fields = objectSchema.fields;
307
+ for (const [fieldName, fieldDef] of Object.entries<any>(fields)) {
308
+ const refTarget = fieldDef?.reference_to || fieldDef?.reference;
309
+ if (
310
+ fieldDef &&
311
+ (fieldDef.type === 'lookup' || fieldDef.type === 'master_detail') &&
312
+ refTarget
313
+ ) {
314
+ refs.push({
315
+ title: fieldDef.label || fieldName.charAt(0).toUpperCase() + fieldName.slice(1),
316
+ type: 'table',
317
+ objectName: refTarget,
318
+ referenceField: fieldName,
319
+ });
320
+ }
321
+ }
322
+ return refs;
323
+ }, [schema.autoDiscoverRelated, schema.related, objectSchema]);
324
+
325
+ // Merge explicit and auto-discovered related lists
326
+ const effectiveRelated: NonNullable<DetailViewSchema['related']> = React.useMemo(() => {
327
+ if (schema.related && schema.related.length > 0) return schema.related;
328
+ return discoveredRelated.map((r) => ({
329
+ title: r.title,
330
+ type: r.type,
331
+ api: r.objectName,
332
+ data: [] as any[],
333
+ }));
334
+ }, [schema.related, discoveredRelated]);
335
+
291
336
  if (loading || schema.loading) {
292
337
  return (
293
338
  <div className={cn('space-y-4', className)}>
@@ -427,7 +472,7 @@ export const DetailView: React.FC<DetailViewProps> = ({
427
472
  <SchemaRenderer key={index} schema={action} data={data} />
428
473
  ))}
429
474
 
430
- {/* Inline Edit Toggle */}
475
+ {/* Inline Edit Toggle - hidden on mobile, accessible via more menu */}
431
476
  {inlineEdit && (
432
477
  <Tooltip>
433
478
  <TooltipTrigger asChild>
@@ -435,7 +480,7 @@ export const DetailView: React.FC<DetailViewProps> = ({
435
480
  variant={isInlineEditing ? 'default' : 'outline'}
436
481
  size="sm"
437
482
  onClick={handleInlineEditToggle}
438
- className="gap-2"
483
+ className="gap-2 hidden sm:inline-flex"
439
484
  >
440
485
  {isInlineEditing ? (
441
486
  <>
@@ -456,21 +501,21 @@ export const DetailView: React.FC<DetailViewProps> = ({
456
501
  </Tooltip>
457
502
  )}
458
503
 
459
- {/* Share Button */}
504
+ {/* Share Button - hidden on mobile, accessible via more menu */}
460
505
  <Tooltip>
461
506
  <TooltipTrigger asChild>
462
- <Button variant="outline" size="icon" onClick={handleShare}>
507
+ <Button variant="outline" size="icon" onClick={handleShare} className="hidden sm:inline-flex">
463
508
  <Share2 className="h-4 w-4" />
464
509
  </Button>
465
510
  </TooltipTrigger>
466
511
  <TooltipContent>{t('detail.share')}</TooltipContent>
467
512
  </Tooltip>
468
513
 
469
- {/* Edit Button */}
514
+ {/* Edit Button - hidden on mobile, accessible via more menu */}
470
515
  {schema.showEdit && (
471
516
  <Tooltip>
472
517
  <TooltipTrigger asChild>
473
- <Button variant="default" onClick={handleEdit} className="gap-2">
518
+ <Button variant="default" onClick={handleEdit} className="gap-2 hidden sm:inline-flex">
474
519
  <Edit className="h-4 w-4" />
475
520
  <span className="hidden sm:inline">{t('detail.edit')}</span>
476
521
  </Button>
@@ -492,6 +537,24 @@ export const DetailView: React.FC<DetailViewProps> = ({
492
537
  <TooltipContent>{t('detail.moreActions')}</TooltipContent>
493
538
  </Tooltip>
494
539
  <DropdownMenuContent align="end" className="w-[calc(100vw-2rem)] sm:w-48 max-h-[60vh] overflow-y-auto">
540
+ {/* Mobile-only: Share, Edit, Inline Edit */}
541
+ <DropdownMenuItem onClick={handleShare} className="sm:hidden">
542
+ <Share2 className="h-4 w-4 mr-2" />
543
+ {t('detail.share')}
544
+ </DropdownMenuItem>
545
+ {schema.showEdit && (
546
+ <DropdownMenuItem onClick={handleEdit} className="sm:hidden">
547
+ <Edit className="h-4 w-4 mr-2" />
548
+ {t('detail.edit')}
549
+ </DropdownMenuItem>
550
+ )}
551
+ {inlineEdit && (
552
+ <DropdownMenuItem onClick={handleInlineEditToggle} className="sm:hidden">
553
+ <Edit className="h-4 w-4 mr-2" />
554
+ {isInlineEditing ? t('detail.save') : t('detail.editInline')}
555
+ </DropdownMenuItem>
556
+ )}
557
+ <DropdownMenuSeparator className="sm:hidden" />
495
558
  <DropdownMenuItem onClick={handleDuplicate}>
496
559
  <Copy className="h-4 w-4 mr-2" />
497
560
  {t('detail.duplicate')}
@@ -528,70 +591,217 @@ export const DetailView: React.FC<DetailViewProps> = ({
528
591
  </div>
529
592
  )}
530
593
 
531
- {/* Sections */}
532
- {schema.sections && schema.sections.length > 0 && (
533
- <div className="space-y-3 sm:space-y-4">
534
- {schema.sections.map((section, index) => (
594
+ {/* Header Highlight Area */}
595
+ {schema.highlightFields && schema.highlightFields.length > 0 && (
596
+ <HeaderHighlight fields={schema.highlightFields} data={data} objectName={schema.objectName} />
597
+ )}
598
+
599
+ {/* Auto Tabs mode: wrap sections, related, activity into tabs */}
600
+ {schema.autoTabs && !schema.tabs?.length ? (
601
+ <Tabs defaultValue="details" className="w-full">
602
+ <TabsList className="w-full justify-start border-b rounded-none bg-transparent p-0">
603
+ <TabsTrigger
604
+ value="details"
605
+ className="relative rounded-none border-b-2 border-transparent data-[state=active]:border-primary data-[state=active]:bg-transparent"
606
+ >
607
+ {t('detail.details')}
608
+ </TabsTrigger>
609
+ {effectiveRelated.length > 0 && (
610
+ <TabsTrigger
611
+ value="related"
612
+ className="relative rounded-none border-b-2 border-transparent data-[state=active]:border-primary data-[state=active]:bg-transparent"
613
+ >
614
+ <span className="flex items-center gap-1.5">
615
+ {t('detail.related')}
616
+ <Badge variant="secondary" className="text-xs">{effectiveRelated.length}</Badge>
617
+ </span>
618
+ </TabsTrigger>
619
+ )}
620
+ {schema.activities && schema.activities.length > 0 && (
621
+ <TabsTrigger
622
+ value="activity"
623
+ className="relative rounded-none border-b-2 border-transparent data-[state=active]:border-primary data-[state=active]:bg-transparent"
624
+ >
625
+ <span className="flex items-center gap-1.5">
626
+ {t('detail.activity')}
627
+ <Badge variant="secondary" className="text-xs">{schema.activities.length}</Badge>
628
+ </span>
629
+ </TabsTrigger>
630
+ )}
631
+ </TabsList>
632
+
633
+ {/* Details Tab Content */}
634
+ <TabsContent value="details" className="mt-4">
635
+ <div className="space-y-3 sm:space-y-4">
636
+ {/* Section Groups */}
637
+ {schema.sectionGroups && schema.sectionGroups.length > 0 && (
638
+ schema.sectionGroups.map((group, index) => (
639
+ <SectionGroup
640
+ key={index}
641
+ group={group}
642
+ data={{ ...data, ...editedValues }}
643
+ objectSchema={objectSchema}
644
+ objectName={schema.objectName}
645
+ isEditing={isInlineEditing}
646
+ onFieldChange={handleInlineFieldChange}
647
+ />
648
+ ))
649
+ )}
650
+ {schema.sections && schema.sections.length > 0 && (
651
+ schema.sections.map((section, index) => (
652
+ <DetailSection
653
+ key={index}
654
+ section={section}
655
+ data={{ ...data, ...editedValues }}
656
+ objectSchema={objectSchema}
657
+ objectName={schema.objectName}
658
+ isEditing={isInlineEditing}
659
+ onFieldChange={handleInlineFieldChange}
660
+ />
661
+ ))
662
+ )}
663
+ {schema.fields && schema.fields.length > 0 && !schema.sections?.length && (
664
+ <DetailSection
665
+ section={{
666
+ fields: schema.fields,
667
+ columns: schema.columns,
668
+ }}
669
+ data={{ ...data, ...editedValues }}
670
+ objectSchema={objectSchema}
671
+ objectName={schema.objectName}
672
+ isEditing={isInlineEditing}
673
+ onFieldChange={handleInlineFieldChange}
674
+ />
675
+ )}
676
+ {/* Comments in details tab */}
677
+ {schema.comments && (
678
+ <RecordComments
679
+ comments={schema.comments}
680
+ onAddComment={schema.onAddComment}
681
+ />
682
+ )}
683
+ </div>
684
+ </TabsContent>
685
+
686
+ {/* Related Tab Content */}
687
+ {effectiveRelated.length > 0 && (
688
+ <TabsContent value="related" className="mt-4">
689
+ <div className="space-y-4">
690
+ {effectiveRelated.map((related, index) => (
691
+ <RelatedList
692
+ key={index}
693
+ title={related.title}
694
+ type={related.type}
695
+ api={related.api}
696
+ data={related.data}
697
+ columns={related.columns as any}
698
+ dataSource={dataSource}
699
+ objectName={related.api}
700
+ collapsible
701
+ pageSize={DEFAULT_RELATED_PAGE_SIZE}
702
+ />
703
+ ))}
704
+ </div>
705
+ </TabsContent>
706
+ )}
707
+
708
+ {/* Activity Tab Content */}
709
+ {schema.activities && schema.activities.length > 0 && (
710
+ <TabsContent value="activity" className="mt-4">
711
+ <ActivityTimeline activities={schema.activities} />
712
+ </TabsContent>
713
+ )}
714
+ </Tabs>
715
+ ) : (
716
+ <>
717
+ {/* Section Groups */}
718
+ {schema.sectionGroups && schema.sectionGroups.length > 0 && (
719
+ <div className="space-y-3 sm:space-y-4">
720
+ {schema.sectionGroups.map((group, index) => (
721
+ <SectionGroup
722
+ key={index}
723
+ group={group}
724
+ data={{ ...data, ...editedValues }}
725
+ objectSchema={objectSchema}
726
+ objectName={schema.objectName}
727
+ isEditing={isInlineEditing}
728
+ onFieldChange={handleInlineFieldChange}
729
+ />
730
+ ))}
731
+ </div>
732
+ )}
733
+
734
+ {/* Sections */}
735
+ {schema.sections && schema.sections.length > 0 && (
736
+ <div className="space-y-3 sm:space-y-4">
737
+ {schema.sections.map((section, index) => (
738
+ <DetailSection
739
+ key={index}
740
+ section={section}
741
+ data={{ ...data, ...editedValues }}
742
+ objectSchema={objectSchema}
743
+ objectName={schema.objectName}
744
+ isEditing={isInlineEditing}
745
+ onFieldChange={handleInlineFieldChange}
746
+ />
747
+ ))}
748
+ </div>
749
+ )}
750
+
751
+ {/* Direct Fields (if no sections) */}
752
+ {schema.fields && schema.fields.length > 0 && !schema.sections?.length && (
535
753
  <DetailSection
536
- key={index}
537
- section={section}
754
+ section={{
755
+ fields: schema.fields,
756
+ columns: schema.columns,
757
+ }}
538
758
  data={{ ...data, ...editedValues }}
539
759
  objectSchema={objectSchema}
760
+ objectName={schema.objectName}
540
761
  isEditing={isInlineEditing}
541
762
  onFieldChange={handleInlineFieldChange}
542
763
  />
543
- ))}
544
- </div>
545
- )}
546
-
547
- {/* Direct Fields (if no sections) */}
548
- {schema.fields && schema.fields.length > 0 && !schema.sections?.length && (
549
- <DetailSection
550
- section={{
551
- fields: schema.fields,
552
- columns: schema.columns,
553
- }}
554
- data={{ ...data, ...editedValues }}
555
- objectSchema={objectSchema}
556
- isEditing={isInlineEditing}
557
- onFieldChange={handleInlineFieldChange}
558
- />
559
- )}
560
-
561
- {/* Tabs */}
562
- {schema.tabs && schema.tabs.length > 0 && (
563
- <DetailTabs tabs={schema.tabs} data={data} />
564
- )}
764
+ )}
765
+
766
+ {/* Tabs */}
767
+ {schema.tabs && schema.tabs.length > 0 && (
768
+ <DetailTabs tabs={schema.tabs} data={data} />
769
+ )}
770
+
771
+ {/* Related Lists */}
772
+ {effectiveRelated.length > 0 && (
773
+ <div className="space-y-4">
774
+ <h2 className="text-xl font-semibold">{t('detail.related')}</h2>
775
+ {effectiveRelated.map((related, index) => (
776
+ <RelatedList
777
+ key={index}
778
+ title={related.title}
779
+ type={related.type}
780
+ api={related.api}
781
+ data={related.data}
782
+ columns={related.columns as any}
783
+ dataSource={dataSource}
784
+ objectName={related.api}
785
+ collapsible
786
+ pageSize={DEFAULT_RELATED_PAGE_SIZE}
787
+ />
788
+ ))}
789
+ </div>
790
+ )}
565
791
 
566
- {/* Related Lists */}
567
- {schema.related && schema.related.length > 0 && (
568
- <div className="space-y-4">
569
- <h2 className="text-xl font-semibold">{t('detail.related')}</h2>
570
- {schema.related.map((related, index) => (
571
- <RelatedList
572
- key={index}
573
- title={related.title}
574
- type={related.type}
575
- api={related.api}
576
- data={related.data}
577
- columns={related.columns as any}
578
- dataSource={dataSource}
792
+ {/* Comments */}
793
+ {schema.comments && (
794
+ <RecordComments
795
+ comments={schema.comments}
796
+ onAddComment={schema.onAddComment}
579
797
  />
580
- ))}
581
- </div>
582
- )}
583
-
584
- {/* Comments */}
585
- {schema.comments && (
586
- <RecordComments
587
- comments={schema.comments}
588
- onAddComment={schema.onAddComment}
589
- />
590
- )}
798
+ )}
591
799
 
592
- {/* Activity Timeline */}
593
- {schema.activities && schema.activities.length > 0 && (
594
- <ActivityTimeline activities={schema.activities} />
800
+ {/* Activity Timeline */}
801
+ {schema.activities && schema.activities.length > 0 && (
802
+ <ActivityTimeline activities={schema.activities} />
803
+ )}
804
+ </>
595
805
  )}
596
806
 
597
807
  {/* Custom Footer */}