@object-ui/components 4.5.0 → 4.7.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.
@@ -44,6 +44,28 @@ export interface NavigationOverlayProps {
44
44
  * Popover trigger element (for popover mode).
45
45
  */
46
46
  popoverTrigger?: React.ReactNode;
47
+ /**
48
+ * Optional handler invoked when the user clicks the "Expand to full page"
49
+ * affordance in the drawer/modal header. Mirrors Linear / Notion / Airtable
50
+ * peek-to-full-page behavior — the consumer is responsible for closing the
51
+ * overlay and router-pushing to the full record route.
52
+ *
53
+ * When omitted, the expand button is not rendered.
54
+ */
55
+ onExpand?: () => void;
56
+ /** Optional label for the expand button (accessible name & tooltip). */
57
+ expandLabel?: string;
58
+ /**
59
+ * Optional storage key for persisting the user's manually-resized drawer
60
+ * width (drawer mode only). When provided, the drawer renders a drag
61
+ * handle on its left edge and remembers the resized width in
62
+ * `localStorage` across sessions. Use a stable, scoped key such as
63
+ * `'drawer-width:lead'` so different objects get independent widths.
64
+ *
65
+ * When omitted, the drag handle is hidden and width is fully controlled
66
+ * by the `width` prop / configured ceiling.
67
+ */
68
+ storageKey?: string;
47
69
  }
48
70
  /**
49
71
  * NavigationOverlay — renders record detail in the configured overlay mode.
@@ -0,0 +1,70 @@
1
+ /**
2
+ * ObjectUI
3
+ * Copyright (c) 2024-present ObjectStack Inc.
4
+ *
5
+ * This source code is licensed under the MIT license found in the
6
+ * LICENSE file in the root directory of this source tree.
7
+ *
8
+ * Module-scoped store for related-list counts displayed in tab badges
9
+ * (e.g. "Contacts (12)" on an Account detail). The store deduplicates
10
+ * concurrent probes for the same key, lets the renderer subscribe with
11
+ * `useSyncExternalStore`, and exposes invalidation hooks so other parts
12
+ * of the runtime (bulk delete, inline create, optimistic update) can
13
+ * keep the badges in sync without a full page refetch.
14
+ *
15
+ * Design notes:
16
+ * - One global Map keyed by `${objectName}::${relField}::${parentId}` so
17
+ * a count fetched by one tab strip is reused by every other consumer.
18
+ * - Subscribers receive *all* keyspace changes; coarse-grained but
19
+ * badges are cheap to re-render and avoids per-key subscription noise.
20
+ * - We deliberately avoid Zustand here — the surface area is one Map +
21
+ * an emit() — and the React binding uses the built-in
22
+ * `useSyncExternalStore` so we don't grow the dependency graph.
23
+ */
24
+ interface ProbeFn {
25
+ (objectName: string, query: {
26
+ where?: Record<string, unknown>;
27
+ limit?: number;
28
+ }): Promise<{
29
+ total?: number;
30
+ data?: unknown[];
31
+ } | unknown[] | {
32
+ length?: number;
33
+ }>;
34
+ }
35
+ declare function getCount(objectName: string, relField: string | undefined, parentId: string | undefined): number | undefined;
36
+ declare function setCount(objectName: string, relField: string | undefined, parentId: string | undefined, value: number): void;
37
+ /**
38
+ * Probe a count via the supplied finder. Deduplicates concurrent requests
39
+ * for the same key and caches the resulting number until invalidated.
40
+ */
41
+ declare function fetchCount(probe: ProbeFn, objectName: string, relField: string | undefined, parentId: string | undefined): Promise<number>;
42
+ /**
43
+ * Invalidate every cached count that involves the given object. Called by
44
+ * mutation paths (e.g. ObjectGrid's onBulkDelete callback, drawer save) so
45
+ * the badge updates without forcing a parent re-render.
46
+ *
47
+ * When `parentId` is supplied, only entries whose parentId matches are
48
+ * dropped — useful for "I just created one Contact under Account X".
49
+ */
50
+ declare function invalidate(objectName: string, parentId?: string): void;
51
+ declare function invalidateAll(): void;
52
+ /**
53
+ * Subscribe to the related-count store and read the count for a single
54
+ * (object, relField, parentId) triple. Returns `undefined` while the
55
+ * probe is in flight or before the first request.
56
+ */
57
+ export declare function useRelatedCount(objectName: string | undefined, relField: string | undefined, parentId: string | undefined): number | undefined;
58
+ /**
59
+ * Imperative store API for non-React callers (mutation handlers, tests).
60
+ * Prefer `useRelatedCount` in components.
61
+ */
62
+ export declare const RelatedCountStore: {
63
+ get: typeof getCount;
64
+ set: typeof setCount;
65
+ fetch: typeof fetchCount;
66
+ invalidate: typeof invalidate;
67
+ invalidateAll: typeof invalidateAll;
68
+ _reset: () => void;
69
+ };
70
+ export {};
@@ -12,6 +12,7 @@ export { useResizeObserver } from './hooks/use-resize-observer';
12
12
  export type { ElementSize } from './hooks/use-resize-observer';
13
13
  export { useExportJob } from './hooks/use-export-job';
14
14
  export type { UseExportJobOptions, UseExportJobReturn } from './hooks/use-export-job';
15
+ export { useRelatedCount, RelatedCountStore } from './hooks/related-count-store';
15
16
  export type { ControlType, ConfigField, ConfigSection, ConfigPanelSchema, } from './types/config-panel';
16
17
  export declare function initializeComponents(): boolean;
17
18
  export * from './debug';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@object-ui/components",
3
- "version": "4.5.0",
3
+ "version": "4.7.0",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
6
  "description": "Standard UI component library for Object UI, built with Shadcn UI + Tailwind CSS",
@@ -69,10 +69,10 @@
69
69
  "tailwind-merge": "^3.6.0",
70
70
  "tailwindcss-animate": "^1.0.7",
71
71
  "vaul": "^1.1.2",
72
- "@object-ui/core": "4.5.0",
73
- "@object-ui/i18n": "4.5.0",
74
- "@object-ui/react": "4.5.0",
75
- "@object-ui/types": "4.5.0"
72
+ "@object-ui/core": "4.7.0",
73
+ "@object-ui/i18n": "4.7.0",
74
+ "@object-ui/react": "4.7.0",
75
+ "@object-ui/types": "4.7.0"
76
76
  },
77
77
  "peerDependencies": {
78
78
  "react": "^18.0.0 || ^19.0.0",