@object-ui/app-shell 4.5.0 → 4.6.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.
@@ -47,8 +47,11 @@ const AUDIT_FIELD_NAMES = new Set(['created_at', 'created_by', 'updated_at', 'up
47
47
  const HIDDEN_SYSTEM_FIELD_NAMES = new Set([
48
48
  'organization_id', 'tenant_id', 'is_deleted', 'deleted_at',
49
49
  ]);
50
- export function RecordDetailView({ dataSource, objects, onEdit }) {
51
- const { appName, objectName, recordId } = useParams();
50
+ export function RecordDetailView({ dataSource, objects, onEdit, objectNameOverride, recordIdOverride, embedded }) {
51
+ const params = useParams();
52
+ const appName = params.appName;
53
+ const objectName = objectNameOverride ?? params.objectName;
54
+ const recordId = recordIdOverride ?? params.recordId;
52
55
  const { showDebug } = useMetadataInspector();
53
56
  const { user } = useAuth();
54
57
  const navigate = useNavigate();
@@ -64,8 +67,9 @@ export function RecordDetailView({ dataSource, objects, onEdit }) {
64
67
  const [recordTitle, setRecordTitle] = useState();
65
68
  const objectDef = objects.find((o) => o.name === objectName);
66
69
  // Publish record title to the navigation context so the top-bar breadcrumb
67
- // can display "Acme Platform Upgrade" instead of "#9U1_MmmxjiGR…".
68
- useRecordBreadcrumbTitle(recordTitle);
70
+ // can display "Acme Platform Upgrade" instead of "#9U1_MmmxjiGR…". Skip
71
+ // when embedded (drawer/split): the parent list route owns the breadcrumb.
72
+ useRecordBreadcrumbTitle(embedded ? undefined : recordTitle);
69
73
  // Use the URL recordId as-is — it contains the actual record id.
70
74
  // Navigation code passes `record.id || record._id` directly into the URL
71
75
  // without adding any prefix, so no stripping is needed.
@@ -734,7 +738,17 @@ export function RecordDetailView({ dataSource, objects, onEdit }) {
734
738
  title: sec.name ? sectionLabel(objectDef.name, sec.name, sec.title || sec.name) : sec.title,
735
739
  collapsible: sec.collapsible,
736
740
  defaultCollapsed: sec.defaultCollapsed,
737
- fields: (sec.fields || []).map((f) => {
741
+ fields: (sec.fields || [])
742
+ .filter((f) => {
743
+ // Honor `hidden: true` on a field def even when the form
744
+ // section explicitly lists it. Hidden fields are typically
745
+ // internal artifacts (e.g. database URL, environment id)
746
+ // that platform actions read but end-users shouldn't see.
747
+ const fieldName = typeof f === 'string' ? f : f.name;
748
+ const fieldDef = objectDef.fields?.[fieldName];
749
+ return !fieldDef?.hidden;
750
+ })
751
+ .map((f) => {
738
752
  const fieldName = typeof f === 'string' ? f : f.name;
739
753
  const fieldDef = objectDef.fields[fieldName];
740
754
  if (!fieldDef) {
@@ -760,7 +774,7 @@ export function RecordDetailView({ dataSource, objects, onEdit }) {
760
774
  // redundant "Details" heading).
761
775
  showBorder: false,
762
776
  fields: Object.keys(objectDef.fields || {})
763
- .filter(key => !AUDIT_FIELD_NAMES.has(key) && !HIDDEN_SYSTEM_FIELD_NAMES.has(key))
777
+ .filter(key => !AUDIT_FIELD_NAMES.has(key) && !HIDDEN_SYSTEM_FIELD_NAMES.has(key) && !objectDef.fields[key]?.hidden)
764
778
  .map(key => {
765
779
  const fieldDef = objectDef.fields[key];
766
780
  const refTarget = fieldDef.reference_to || fieldDef.reference;
@@ -954,7 +968,7 @@ export function RecordDetailView({ dataSource, objects, onEdit }) {
954
968
  type: 'detail-view',
955
969
  objectName: objectDef.name,
956
970
  resourceId: pureRecordId,
957
- showBack: true,
971
+ showBack: !embedded,
958
972
  onBack: 'history',
959
973
  // Hide the Edit button for objects whose lifecycle isn't user-managed
960
974
  // (approval requests, audit logs, better-auth tables, …). The
@@ -985,7 +999,7 @@ export function RecordDetailView({ dataSource, objects, onEdit }) {
985
999
  }),
986
1000
  };
987
1001
  // eslint-disable-next-line react-hooks/exhaustive-deps
988
- }, [objectDef?.name, pureRecordId, childRelatedData, actionRefreshKey, appName, navigate, dataSource, t, objectLabel, objects, historyEnabled, historyEntries, historyLoading, approvals.available, approvals.processes, approvals.canSubmit, approvals.canRecall, approvals.pendingRequest, approvals.latestRequest]);
1002
+ }, [objectDef?.name, pureRecordId, childRelatedData, actionRefreshKey, appName, navigate, dataSource, t, objectLabel, objects, historyEnabled, historyEntries, historyLoading, approvals.available, approvals.processes, approvals.canSubmit, approvals.canRecall, approvals.pendingRequest, approvals.latestRequest, embedded]);
989
1003
  if (isLoading) {
990
1004
  return _jsx(SkeletonDetail, {});
991
1005
  }
@@ -993,7 +1007,7 @@ export function RecordDetailView({ dataSource, objects, onEdit }) {
993
1007
  return (_jsx("div", { className: "flex h-full items-center justify-center p-4", children: _jsxs(Empty, { children: [_jsx("div", { className: "mx-auto mb-4 flex h-12 w-12 items-center justify-center rounded-full bg-muted", children: _jsx(Database, { className: "h-6 w-6 text-muted-foreground" }) }), _jsx(EmptyTitle, { children: t('empty.objectNotFound') }), _jsx(EmptyDescription, { children: t('empty.objectNotFoundDescription', { name: objectName }) })] }) }));
994
1008
  }
995
1009
  if (assignedPage) {
996
- return (_jsx(RecordContextProvider, { objectName: objectName, recordId: pureRecordId, data: pageRecord, objectSchema: objectDef, dataSource: dataSource, children: _jsx(ActionProvider, { context: { record: pageRecord || {}, objectName, user: currentUser }, onConfirm: confirmHandler, onToast: toastHandler, onNavigate: navigateHandler, onParamCollection: paramCollectionHandler, handlers: { api: apiHandler, flow: flowHandler, script: serverActionHandler, modal: serverActionHandler, approval: approvalHandler }, children: _jsx("div", { className: "bg-background p-3 sm:p-4 lg:p-6", children: _jsx(SchemaRenderer, { schema: assignedPage }) }) }) }));
1010
+ return (_jsx(RecordContextProvider, { objectName: objectName, recordId: pureRecordId, data: pageRecord, objectSchema: objectDef, dataSource: dataSource, embedded: embedded, children: _jsx(ActionProvider, { context: { record: pageRecord || {}, objectName, user: currentUser }, onConfirm: confirmHandler, onToast: toastHandler, onNavigate: navigateHandler, onParamCollection: paramCollectionHandler, handlers: { api: apiHandler, flow: flowHandler, script: serverActionHandler, modal: serverActionHandler, approval: approvalHandler }, children: _jsx("div", { className: "bg-background p-3 sm:p-4 lg:p-6", children: _jsx(SchemaRenderer, { schema: assignedPage }) }) }) }));
997
1011
  }
998
1012
  return (_jsxs("div", { className: "h-full bg-background overflow-hidden flex flex-col relative", children: [_jsxs("div", { className: "absolute top-2 sm:top-4 right-2 sm:right-4 z-50 flex items-center gap-2", children: [_jsx(ManagedByBadge, { managedBy: objectDef?.managedBy }), recordViewers.length > 0 && (_jsxs("div", { className: "flex items-center gap-1.5", title: t('recordDetail.viewersTooltip'), children: [_jsx(Users, { className: "h-3.5 w-3.5 text-muted-foreground" }), _jsx(PresenceAvatars, { users: recordViewers, size: "sm", maxVisible: 4, showStatus: true })] }))] }), _jsxs("div", { className: "flex-1 overflow-hidden flex flex-row", children: [_jsx("div", { className: "flex-1 overflow-auto p-3 sm:p-4 lg:p-6 scroll-pb-48", children: _jsx(ActionProvider, { context: { record: {}, objectName, user: currentUser }, onConfirm: confirmHandler, onToast: toastHandler, onNavigate: navigateHandler, onParamCollection: paramCollectionHandler, handlers: { api: apiHandler, flow: flowHandler, script: serverActionHandler, modal: serverActionHandler, approval: approvalHandler }, children: _jsx(DetailView, { schema: detailSchema, dataSource: dataSource, objectLabel: objectLabel({ name: objectDef.name, label: objectDef.label }), onDataLoaded: (record) => {
999
1013
  if (!record || typeof record !== 'object')
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@object-ui/app-shell",
3
- "version": "4.5.0",
3
+ "version": "4.6.0",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
6
  "description": "Minimal application shell for ObjectUI - framework-agnostic rendering engine",
@@ -27,34 +27,34 @@
27
27
  "dependencies": {
28
28
  "lucide-react": "^1.16.0",
29
29
  "sonner": "^2.0.7",
30
- "@object-ui/auth": "4.5.0",
31
- "@object-ui/collaboration": "4.5.0",
32
- "@object-ui/components": "4.5.0",
33
- "@object-ui/core": "4.5.0",
34
- "@object-ui/data-objectstack": "4.5.0",
35
- "@object-ui/fields": "4.5.0",
36
- "@object-ui/i18n": "4.5.0",
37
- "@object-ui/layout": "4.5.0",
38
- "@object-ui/permissions": "4.5.0",
39
- "@object-ui/react": "4.5.0",
40
- "@object-ui/types": "4.5.0"
30
+ "@object-ui/auth": "4.6.0",
31
+ "@object-ui/collaboration": "4.6.0",
32
+ "@object-ui/components": "4.6.0",
33
+ "@object-ui/core": "4.6.0",
34
+ "@object-ui/data-objectstack": "4.6.0",
35
+ "@object-ui/fields": "4.6.0",
36
+ "@object-ui/i18n": "4.6.0",
37
+ "@object-ui/layout": "4.6.0",
38
+ "@object-ui/permissions": "4.6.0",
39
+ "@object-ui/react": "4.6.0",
40
+ "@object-ui/types": "4.6.0"
41
41
  },
42
42
  "peerDependencies": {
43
43
  "react": "^18.0.0 || ^19.0.0",
44
44
  "react-dom": "^18.0.0 || ^19.0.0",
45
45
  "react-router-dom": "^6.0.0 || ^7.0.0",
46
- "@object-ui/plugin-calendar": "^4.5.0",
47
- "@object-ui/plugin-charts": "^4.5.0",
48
- "@object-ui/plugin-chatbot": "^4.5.0",
49
- "@object-ui/plugin-dashboard": "^4.5.0",
50
- "@object-ui/plugin-designer": "^4.5.0",
51
- "@object-ui/plugin-detail": "^4.5.0",
52
- "@object-ui/plugin-form": "^4.5.0",
53
- "@object-ui/plugin-grid": "^4.5.0",
54
- "@object-ui/plugin-kanban": "^4.5.0",
55
- "@object-ui/plugin-list": "^4.5.0",
56
- "@object-ui/plugin-report": "^4.5.0",
57
- "@object-ui/plugin-view": "^4.5.0"
46
+ "@object-ui/plugin-calendar": "^4.6.0",
47
+ "@object-ui/plugin-charts": "^4.6.0",
48
+ "@object-ui/plugin-chatbot": "^4.6.0",
49
+ "@object-ui/plugin-dashboard": "^4.6.0",
50
+ "@object-ui/plugin-designer": "^4.6.0",
51
+ "@object-ui/plugin-detail": "^4.6.0",
52
+ "@object-ui/plugin-form": "^4.6.0",
53
+ "@object-ui/plugin-grid": "^4.6.0",
54
+ "@object-ui/plugin-kanban": "^4.6.0",
55
+ "@object-ui/plugin-list": "^4.6.0",
56
+ "@object-ui/plugin-report": "^4.6.0",
57
+ "@object-ui/plugin-view": "^4.6.0"
58
58
  },
59
59
  "devDependencies": {
60
60
  "@types/node": "^25.9.0",