@object-ui/app-shell 11.0.0 → 11.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -15,7 +15,7 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
15
15
  */
16
16
  import { useEffect, useState } from 'react';
17
17
  import { useLocation, useNavigate } from 'react-router-dom';
18
- import { Eye, X, Rocket, GitCompareArrows } from 'lucide-react';
18
+ import { Eye, X, Rocket, GitCompareArrows, Sparkles } from 'lucide-react';
19
19
  import { Button, cn } from '@object-ui/components';
20
20
  import { useObjectTranslation } from '@object-ui/i18n';
21
21
  import { usePreviewDrafts, markPreviewExit, PREVIEW_QUERY_FLAG } from './PreviewModeContext';
@@ -85,15 +85,19 @@ export function DraftPreviewBar() {
85
85
  // preview indicator. An UNKNOWN count (null — still loading or the fetch
86
86
  // failed) keeps the publish path: we only relax when we KNOW the count is zero.
87
87
  const noChanges = pendingCount === 0;
88
- return (_jsxs("div", { className: cn('sticky top-0 z-40 flex items-center gap-3 border-b px-4 py-2 text-sm', noChanges
88
+ return (_jsxs("div", { className: cn('sticky top-0 z-40 border-b', noChanges
89
89
  ? 'border-slate-200 bg-slate-50 text-slate-700 dark:border-slate-700/60 dark:bg-slate-900/40 dark:text-slate-300'
90
- : 'border-amber-300/70 bg-amber-50 text-amber-900 dark:border-amber-700/60 dark:bg-amber-950/40 dark:text-amber-200'), "data-testid": "draft-preview-bar", children: [_jsx(Eye, { className: "h-4 w-4 shrink-0" }), _jsx("p", { className: "min-w-0 flex-1 truncate", children: noChanges
91
- ? t('preview.draftBar.messageClean', {
92
- defaultValue: 'Draft preview — no unpublished changes; everything here is already live.',
93
- })
94
- : t('preview.draftBar.message', {
95
- defaultValue: 'Draft preview — you are seeing unpublished changes. Nothing here is live until you publish.',
96
- }) }), !noChanges && (_jsxs(_Fragment, { children: [_jsxs(Button, { size: "sm", variant: "outline", onClick: () => setChangesOpen(true), "data-testid": "draft-preview-changes", children: [_jsx(GitCompareArrows, { className: "mr-1 h-3.5 w-3.5" }), t('preview.draftBar.changes', { defaultValue: 'Changes' }), typeof pendingCount === 'number' ? ` (${pendingCount})` : ''] }), _jsxs(Button, { size: "sm", onClick: publish, disabled: publishing, "data-testid": "draft-preview-publish", children: [_jsx(Rocket, { className: "mr-1 h-3.5 w-3.5" }), publishing
97
- ? t('preview.draftBar.publishing', { defaultValue: 'Publishing…' })
98
- : t('preview.draftBar.publish', { defaultValue: 'Publish' })] }), _jsx(DraftChangesPanel, { open: changesOpen, onOpenChange: setChangesOpen })] })), _jsxs(Button, { size: "sm", variant: "outline", onClick: exit, "data-testid": "draft-preview-exit", children: [_jsx(X, { className: "mr-1 h-3.5 w-3.5" }), t('preview.draftBar.exit', { defaultValue: 'Exit preview' })] })] }));
90
+ : 'border-amber-300/70 bg-amber-50 text-amber-900 dark:border-amber-700/60 dark:bg-amber-950/40 dark:text-amber-200'), "data-testid": "draft-preview-bar", children: [_jsxs("div", { className: "flex items-center gap-3 px-4 py-2 text-sm", children: [_jsx(Eye, { className: "h-4 w-4 shrink-0" }), _jsx("p", { className: "min-w-0 flex-1 truncate", children: noChanges
91
+ ? t('preview.draftBar.messageClean', {
92
+ defaultValue: 'Draft preview — no unpublished changes; everything here is already live.',
93
+ })
94
+ : t('preview.draftBar.message', {
95
+ defaultValue: 'Draft preview — you are seeing unpublished changes. Nothing here is live until you publish.',
96
+ }) }), !noChanges && (_jsxs(Button, { size: "sm", variant: "outline", onClick: () => setChangesOpen(true), "data-testid": "draft-preview-changes", children: [_jsx(GitCompareArrows, { className: "mr-1 h-3.5 w-3.5" }), t('preview.draftBar.changes', { defaultValue: 'Changes' }), typeof pendingCount === 'number' ? ` (${pendingCount})` : ''] })), _jsxs(Button, { size: "sm", variant: "outline", onClick: exit, "data-testid": "draft-preview-exit", children: [_jsx(X, { className: "mr-1 h-3.5 w-3.5" }), t('preview.draftBar.exit', { defaultValue: 'Exit preview' })] })] }), !noChanges && (_jsxs(_Fragment, { children: [_jsxs("div", { className: "flex items-center gap-3 border-t border-amber-300/50 px-4 py-2.5 dark:border-amber-700/40", "data-testid": "draft-preview-sample-hint", children: [_jsx(Sparkles, { className: "h-5 w-5 shrink-0 text-amber-600 dark:text-amber-300", "aria-hidden": "true" }), _jsxs("div", { className: "min-w-0 flex-1", children: [_jsx("p", { className: "text-sm font-semibold leading-tight", children: t('preview.draftBar.sampleDataTitle', {
97
+ defaultValue: 'Sample data appears once you publish',
98
+ }) }), _jsx("p", { className: "text-xs leading-snug text-amber-800/80 dark:text-amber-200/70", children: t('preview.draftBar.sampleDataBody', {
99
+ defaultValue: 'You’re previewing your app’s structure. Publish to load example records and make it live.',
100
+ }) })] }), _jsxs(Button, { onClick: publish, disabled: publishing, "data-testid": "draft-preview-publish", className: "shrink-0 shadow-sm", children: [_jsx(Rocket, { className: "mr-1.5 h-4 w-4" }), publishing
101
+ ? t('preview.draftBar.publishing', { defaultValue: 'Publishing…' })
102
+ : t('preview.draftBar.publishCta', { defaultValue: 'Publish to see it live' })] })] }), _jsx(DraftChangesPanel, { open: changesOpen, onOpenChange: setChangesOpen })] }))] }));
99
103
  }
@@ -12,7 +12,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
12
12
  import { useState } from 'react';
13
13
  import { useParams, useSearchParams, useNavigate, useLocation } from 'react-router-dom';
14
14
  import { SchemaRenderer, useAdapter } from '@object-ui/react';
15
- import { Empty, EmptyTitle, EmptyDescription } from '@object-ui/components';
15
+ import { Empty, EmptyTitle, EmptyDescription, Spinner } from '@object-ui/components';
16
16
  import { FileText, Pencil } from 'lucide-react';
17
17
  import { useObjectTranslation } from '@object-ui/i18n';
18
18
  import { useAuth } from '@object-ui/auth';
@@ -33,7 +33,7 @@ export function PageView() {
33
33
  // is admin-only (mirrors the view/report/dashboard runtime editors).
34
34
  const { user } = useAuth();
35
35
  const isAdmin = user?.role === 'admin';
36
- const { pages, objects } = useMetadata();
36
+ const { pages, objects, getTypeStatus } = useMetadata();
37
37
  // ADR-0048 Phase 2 — prefer the page owned by the current app's package so
38
38
  // two packages shipping `page/<same-name>` each resolve within their own
39
39
  // container instead of by load order.
@@ -44,6 +44,16 @@ export function PageView() {
44
44
  const [refreshKey, setRefreshKey] = useState(0);
45
45
  const page = preferLocal(pages, pageName, activeApp?._packageId);
46
46
  if (!page) {
47
+ // `page` metadata is lazy-loaded: on the very first access `pages` is an
48
+ // empty array while the fetch is in flight, which would flash a false
49
+ // "page not found" (or a blank body) — exactly the post-signup landing
50
+ // race where the app's home page is the first thing rendered. Show a
51
+ // loading state until the `page` type is actually resolved, then trust the
52
+ // not-found. (getTypeStatus absent = hand-rolled context = always ready.)
53
+ const pageStatus = getTypeStatus?.('page');
54
+ if (pageStatus === 'idle' || pageStatus === 'loading') {
55
+ return (_jsx("div", { className: "h-full flex items-center justify-center p-8", "data-testid": "page-loading", children: _jsx(Spinner, { className: "h-5 w-5 text-muted-foreground" }) }));
56
+ }
47
57
  return (_jsx("div", { className: "h-full flex items-center justify-center p-8", 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(FileText, { className: "h-6 w-6 text-muted-foreground" }) }), _jsx(EmptyTitle, { children: t('empty.pageNotFound') }), _jsx(EmptyDescription, { children: t('empty.pageNotFoundDescription', { name: pageName }) })] }) }));
48
58
  }
49
59
  const params = Object.fromEntries(searchParams.entries());
@@ -1700,6 +1700,7 @@ export function RecordDetailView({ dataSource, objects, onEdit, objectNameOverri
1700
1700
  showReferenceRail: objectDef?.detail?.showReferenceRail === true || undefined,
1701
1701
  hideReferenceRail: objectDef?.detail?.hideReferenceRail === true || undefined,
1702
1702
  hideRelatedTab: objectDef?.detail?.hideRelatedTab === true || undefined,
1703
+ relatedLayout: objectDef?.detail?.relatedLayout === 'tabs' ? 'tabs' : undefined,
1703
1704
  ...(assignedSlots ? { slots: assignedSlots } : {}),
1704
1705
  });
1705
1706
  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: [recordPresence.length > 0 && (_jsx(PresenceAvatars, { users: recordPresence, size: "sm", maxVisible: 3, showStatus: true })), _jsx(ManagedByBadge, { managedBy: objectDef?.managedBy })] }), _jsx(RecordContextProvider, { objectName: objectName, recordId: pureRecordId, data: pageRecord, objectSchema: objectDef, dataSource: dataSource, embedded: embedded, headerSystemActions: synthSystemActions, isFavorite: isRecordFavorite, onToggleFavorite: favoriteRecord ? handleToggleRecordFavorite : undefined, children: _jsx(HighlightFieldsProvider, { children: _jsx(DiscussionContextProvider, { items: feedItems, onAddComment: handleAddComment, onAddReply: handleAddReply, onToggleReaction: handleToggleReaction, mentionSuggestions: mentionSuggestions, children: _jsxs(ActionProvider, { context: { record: pageRecord || {}, objectName, user: currentUser }, onConfirm: confirmHandler, onToast: toastHandler, onNavigate: navigateHandler, onParamCollection: paramCollectionHandler, onResultDialog: resultDialogHandler, onModal: modalHandler, handlers: { api: apiHandler, flow: flowHandler, script: serverActionHandler, approval: approvalHandler }, children: [_jsxs("div", { className: "flex-1 overflow-hidden flex flex-row", children: [_jsxs("div", { className: "flex-1 overflow-auto p-3 sm:p-4 lg:p-6 scroll-pb-48", children: [originFrom?.pathname && originFrom?.label && (_jsxs(Link, { to: originFrom.pathname, className: "inline-flex items-center gap-1 mb-3 text-sm text-muted-foreground hover:text-foreground transition-colors", children: [_jsx(ChevronLeft, { className: "h-4 w-4" }), _jsx("span", { children: originFrom.label })] })), _jsx(SchemaRenderer, { schema: renderedPage }), showAutoDiscussion && (_jsx("div", { className: "mt-6", children: _jsx(RecordChatterPanel, { config: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@object-ui/app-shell",
3
- "version": "11.0.0",
3
+ "version": "11.2.0",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
6
  "description": "Minimal application shell for ObjectUI - framework-agnostic rendering engine",
@@ -33,36 +33,36 @@
33
33
  "qrcode": "^1.5.4",
34
34
  "sonner": "^2.0.7",
35
35
  "zod": "^4.4.3",
36
- "@object-ui/auth": "11.0.0",
37
- "@object-ui/collaboration": "11.0.0",
38
- "@object-ui/components": "11.0.0",
39
- "@object-ui/core": "11.0.0",
40
- "@object-ui/data-objectstack": "11.0.0",
41
- "@object-ui/fields": "11.0.0",
42
- "@object-ui/i18n": "11.0.0",
43
- "@object-ui/layout": "11.0.0",
44
- "@object-ui/permissions": "11.0.0",
45
- "@object-ui/plugin-editor": "11.0.0",
46
- "@object-ui/providers": "11.0.0",
47
- "@object-ui/react": "11.0.0",
48
- "@object-ui/types": "11.0.0"
36
+ "@object-ui/auth": "11.2.0",
37
+ "@object-ui/collaboration": "11.2.0",
38
+ "@object-ui/components": "11.2.0",
39
+ "@object-ui/core": "11.2.0",
40
+ "@object-ui/data-objectstack": "11.2.0",
41
+ "@object-ui/fields": "11.2.0",
42
+ "@object-ui/i18n": "11.2.0",
43
+ "@object-ui/layout": "11.2.0",
44
+ "@object-ui/permissions": "11.2.0",
45
+ "@object-ui/plugin-editor": "11.2.0",
46
+ "@object-ui/providers": "11.2.0",
47
+ "@object-ui/react": "11.2.0",
48
+ "@object-ui/types": "11.2.0"
49
49
  },
50
50
  "peerDependencies": {
51
51
  "react": "^18.0.0 || ^19.0.0",
52
52
  "react-dom": "^18.0.0 || ^19.0.0",
53
53
  "react-router-dom": "^6.0.0 || ^7.0.0",
54
- "@object-ui/plugin-calendar": "^11.0.0",
55
- "@object-ui/plugin-charts": "^11.0.0",
56
- "@object-ui/plugin-chatbot": "^11.0.0",
57
- "@object-ui/plugin-dashboard": "^11.0.0",
58
- "@object-ui/plugin-designer": "^11.0.0",
59
- "@object-ui/plugin-detail": "^11.0.0",
60
- "@object-ui/plugin-form": "^11.0.0",
61
- "@object-ui/plugin-grid": "^11.0.0",
62
- "@object-ui/plugin-kanban": "^11.0.0",
63
- "@object-ui/plugin-list": "^11.0.0",
64
- "@object-ui/plugin-report": "^11.0.0",
65
- "@object-ui/plugin-view": "^11.0.0"
54
+ "@object-ui/plugin-calendar": "^11.2.0",
55
+ "@object-ui/plugin-charts": "^11.2.0",
56
+ "@object-ui/plugin-chatbot": "^11.2.0",
57
+ "@object-ui/plugin-dashboard": "^11.2.0",
58
+ "@object-ui/plugin-designer": "^11.2.0",
59
+ "@object-ui/plugin-detail": "^11.2.0",
60
+ "@object-ui/plugin-form": "^11.2.0",
61
+ "@object-ui/plugin-grid": "^11.2.0",
62
+ "@object-ui/plugin-kanban": "^11.2.0",
63
+ "@object-ui/plugin-list": "^11.2.0",
64
+ "@object-ui/plugin-report": "^11.2.0",
65
+ "@object-ui/plugin-view": "^11.2.0"
66
66
  },
67
67
  "devDependencies": {
68
68
  "@types/node": "^26.0.0",
@@ -75,18 +75,18 @@
75
75
  "sonner": "^2.0.7",
76
76
  "typescript": "^6.0.3",
77
77
  "vite": "^8.0.16",
78
- "@object-ui/plugin-calendar": "11.0.0",
79
- "@object-ui/plugin-charts": "11.0.0",
80
- "@object-ui/plugin-chatbot": "11.0.0",
81
- "@object-ui/plugin-dashboard": "11.0.0",
82
- "@object-ui/plugin-designer": "11.0.0",
83
- "@object-ui/plugin-detail": "11.0.0",
84
- "@object-ui/plugin-form": "11.0.0",
85
- "@object-ui/plugin-grid": "11.0.0",
86
- "@object-ui/plugin-kanban": "11.0.0",
87
- "@object-ui/plugin-list": "11.0.0",
88
- "@object-ui/plugin-report": "11.0.0",
89
- "@object-ui/plugin-view": "11.0.0"
78
+ "@object-ui/plugin-calendar": "11.2.0",
79
+ "@object-ui/plugin-charts": "11.2.0",
80
+ "@object-ui/plugin-chatbot": "11.2.0",
81
+ "@object-ui/plugin-dashboard": "11.2.0",
82
+ "@object-ui/plugin-designer": "11.2.0",
83
+ "@object-ui/plugin-detail": "11.2.0",
84
+ "@object-ui/plugin-form": "11.2.0",
85
+ "@object-ui/plugin-grid": "11.2.0",
86
+ "@object-ui/plugin-kanban": "11.2.0",
87
+ "@object-ui/plugin-list": "11.2.0",
88
+ "@object-ui/plugin-report": "11.2.0",
89
+ "@object-ui/plugin-view": "11.2.0"
90
90
  },
91
91
  "keywords": [
92
92
  "objectui",