@declarion/react 0.1.65 → 0.1.68

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 (98) hide show
  1. package/README.md +32 -0
  2. package/dist-lib/api/agents.d.ts +18 -3
  3. package/dist-lib/api/auth-redirect.d.ts +3 -0
  4. package/dist-lib/api/auth.d.ts +14 -0
  5. package/dist-lib/api/client.d.ts +30 -0
  6. package/dist-lib/api/data.d.ts +12 -0
  7. package/dist-lib/api/events.d.ts +17 -0
  8. package/dist-lib/api/params.d.ts +9 -3
  9. package/dist-lib/components/agents/AgentChatPanel.d.ts +2 -1
  10. package/dist-lib/components/fields/EmailField.d.ts +1 -1
  11. package/dist-lib/components/fields/PhoneField.d.ts +2 -0
  12. package/dist-lib/components/fields/RichTextField.d.ts +2 -0
  13. package/dist-lib/components/fields/UrlField.d.ts +1 -1
  14. package/dist-lib/components/fields/cells/factories/badge.d.ts +2 -0
  15. package/dist-lib/components/fields/cells/factories/boolPill.d.ts +2 -0
  16. package/dist-lib/components/fields/cells/factories/code.d.ts +2 -0
  17. package/dist-lib/components/fields/cells/factories/email.d.ts +2 -0
  18. package/dist-lib/components/fields/cells/factories/host-icons.d.ts +9 -0
  19. package/dist-lib/components/fields/cells/factories/link.d.ts +2 -0
  20. package/dist-lib/components/fields/cells/factories/markdown.d.ts +2 -0
  21. package/dist-lib/components/fields/cells/factories/money.d.ts +2 -0
  22. package/dist-lib/components/fields/cells/factories/multilangInline.d.ts +2 -0
  23. package/dist-lib/components/fields/cells/factories/nextRun.d.ts +2 -0
  24. package/dist-lib/components/fields/cells/factories/number.d.ts +2 -0
  25. package/dist-lib/components/fields/cells/factories/passwordMask.d.ts +2 -0
  26. package/dist-lib/components/fields/cells/factories/phone.d.ts +2 -0
  27. package/dist-lib/components/fields/cells/factories/refLink.d.ts +2 -0
  28. package/dist-lib/components/fields/cells/factories/richTextPreview.d.ts +2 -0
  29. package/dist-lib/components/fields/cells/factories/statusPill.d.ts +2 -0
  30. package/dist-lib/components/fields/cells/factories/tagList.d.ts +2 -0
  31. package/dist-lib/components/fields/cells/factories/text.d.ts +2 -0
  32. package/dist-lib/components/fields/cells/factories/timestamp.d.ts +3 -0
  33. package/dist-lib/components/fields/cells/factories/url-helpers.d.ts +12 -0
  34. package/dist-lib/components/fields/cells/factories/url.d.ts +2 -0
  35. package/dist-lib/components/fields/cells/registry.d.ts +18 -0
  36. package/dist-lib/components/fields/index.d.ts +9 -3
  37. package/dist-lib/components/file-widgets/CircleImage.d.ts +2 -0
  38. package/dist-lib/components/file-widgets/DocumentCard.d.ts +2 -0
  39. package/dist-lib/components/file-widgets/FileList.d.ts +2 -0
  40. package/dist-lib/components/file-widgets/Grid.d.ts +2 -0
  41. package/dist-lib/components/file-widgets/ImageWidget.d.ts +12 -0
  42. package/dist-lib/components/file-widgets/LabeledSlots.d.ts +2 -0
  43. package/dist-lib/components/file-widgets/SquareImage.d.ts +2 -0
  44. package/dist-lib/components/file-widgets/WideBanner.d.ts +2 -0
  45. package/dist-lib/components/file-widgets/builtins.d.ts +1 -0
  46. package/dist-lib/components/file-widgets/cropper.d.ts +14 -0
  47. package/dist-lib/components/file-widgets/draft-scope.d.ts +22 -0
  48. package/dist-lib/components/file-widgets/helpers.d.ts +12 -0
  49. package/dist-lib/components/file-widgets/host.d.ts +23 -0
  50. package/dist-lib/components/file-widgets/index.d.ts +16 -0
  51. package/dist-lib/components/file-widgets/payload.d.ts +21 -0
  52. package/dist-lib/components/file-widgets/registry.d.ts +5 -0
  53. package/dist-lib/components/file-widgets/types.d.ts +15 -0
  54. package/dist-lib/components/file-widgets/upload.d.ts +25 -0
  55. package/dist-lib/components/file-widgets/value.d.ts +4 -0
  56. package/dist-lib/components/layout/ImpersonationBanner.d.ts +11 -0
  57. package/dist-lib/components/layout/ImpersonationFrame.d.ts +11 -0
  58. package/dist-lib/components/layout/ImpersonationStartModal.d.ts +22 -0
  59. package/dist-lib/components/layout/TenantChip.d.ts +9 -1
  60. package/dist-lib/components/list/QuickPeek.d.ts +13 -6
  61. package/dist-lib/components/pages/ExportMenu.d.ts +32 -0
  62. package/dist-lib/components/pages/SmartDetailPage.d.ts +1 -1
  63. package/dist-lib/components/pages/SmartListPage.d.ts +1 -1
  64. package/dist-lib/components/pages/auth/AuthShell.d.ts +17 -2
  65. package/dist-lib/components/pages/auth/Reset.d.ts +1 -0
  66. package/dist-lib/components/pages/exportRequest.d.ts +71 -0
  67. package/dist-lib/components/primitives/BrandGlyph.d.ts +8 -0
  68. package/dist-lib/components/primitives/BrandLogo.d.ts +1 -5
  69. package/dist-lib/components/primitives/Fields.d.ts +3 -3
  70. package/dist-lib/components/primitives/MenuItem.d.ts +2 -1
  71. package/dist-lib/components/primitives/index.d.ts +2 -0
  72. package/dist-lib/components/shared/EmptyState.d.ts +1 -1
  73. package/dist-lib/components/shell/CommandPalette.d.ts +2 -1
  74. package/dist-lib/declarion-glyph.svg +17 -0
  75. package/dist-lib/declarion-react.css +1 -1
  76. package/dist-lib/hooks/useAgentConversation.d.ts +9 -1
  77. package/dist-lib/hooks/useImpersonation.d.ts +23 -0
  78. package/dist-lib/hooks/useParams.d.ts +42 -1
  79. package/dist-lib/hooks/useUserLocale.d.ts +1 -0
  80. package/dist-lib/hooks/useVersionWatcher.d.ts +30 -0
  81. package/dist-lib/index.d.ts +8 -1
  82. package/dist-lib/index.js +9011 -4246
  83. package/dist-lib/index.js.map +1 -1
  84. package/dist-lib/lib/rich-text.d.ts +14 -0
  85. package/dist-lib/lib/safe-url.d.ts +1 -0
  86. package/dist-lib/lib/timestamp.d.ts +17 -0
  87. package/dist-lib/lib/versionTracker.d.ts +66 -0
  88. package/dist-lib/stores/appearance.d.ts +3 -0
  89. package/dist-lib/types/api.d.ts +65 -0
  90. package/dist-lib/types/fieldType.d.ts +2 -0
  91. package/dist-lib/types/files.d.ts +76 -0
  92. package/dist-lib/types/schema.d.ts +64 -0
  93. package/dist-lib/vite/declarion-glyph.svg +17 -0
  94. package/dist-lib/vite/fingerprint-plugin.d.ts +45 -0
  95. package/dist-lib/vite/index.d.ts +21 -0
  96. package/dist-lib/vite/index.js +52 -0
  97. package/dist-lib/vite/index.js.map +1 -0
  98. package/package.json +12 -4
package/README.md CHANGED
@@ -12,6 +12,38 @@ pnpm add @declarion/react
12
12
  pnpm add react react-dom
13
13
  ```
14
14
 
15
+ ## Subpath exports
16
+
17
+ | Import | Purpose |
18
+ |---|---|
19
+ | `@declarion/react` | Main React entry — components, hooks, types |
20
+ | `@declarion/react/styles.css` | Pre-compiled Tailwind output; import once at the SPA root |
21
+ | `@declarion/react/vite` | Node-only Vite plugin — opt into client staleness handling at build time |
22
+
23
+ ## Vite plugin: build identity for client staleness handling
24
+
25
+ The SDK ships with a tiny Vite plugin that emits `bundle-fingerprint.txt` next to `index.html` after every production build. The Declarion server reads it at boot and folds it into the build identity stamped on every `/api/*` response (`X-Declarion-Version`). The SDK's built-in version watcher detects drift on every API response, on focus/online/60s probe, and either silently invalidates the schema query (schema-only changes) or prompts the user to reload (asset/binary changes). Cross-tab coordination via `BroadcastChannel`.
26
+
27
+ Add the plugin to your consumer app's `vite.config.ts`:
28
+
29
+ ```ts
30
+ import { defineConfig } from "vite";
31
+ import react from "@vitejs/plugin-react";
32
+ import { declarionFingerprintPlugin } from "@declarion/react/vite";
33
+
34
+ export default defineConfig({
35
+ plugins: [react(), declarionFingerprintPlugin()],
36
+ });
37
+ ```
38
+
39
+ That's it — there is no client API to wire by hand. The version watcher mounts itself inside `<App>`, the response-header observer is built into `apiFetch`, and the toast slot reuses the existing Sonner `<Toaster/>`. The plugin works in every Declarion deployment mode (local SDK link, npm-pinned, prebuilt prod image) since it runs at consumer build time regardless of where the SDK itself comes from.
40
+
41
+ Consumers that haven't adopted the plugin yet degrade gracefully: the server logs once at boot, falls back to binary-only drift detection, and the rest of the system continues working — drift still gets detected, just classified more conservatively as "asset/binary" so the user gets a reload prompt rather than a silent invalidation.
42
+
43
+ Browser support requires `BroadcastChannel` for cross-tab coordination — Chrome 54+, Firefox 38+, Safari 15.4+. In environments without it, in-tab detection still works; cross-tab fan-out is silently skipped.
44
+
45
+ See [`docs/architecture.md`](https://github.com/disciplinedware/declarion/blob/main/docs/architecture.md) (section "Build identity & client staleness handling") for the full design rationale, fingerprint composition, RFC 7232 details (auth-variant ETag, weak-ETag handling), and the no-persistence invariant that prevents reload loops.
46
+
15
47
  ## License
16
48
 
17
49
  MIT. See `LICENSE`.
@@ -10,6 +10,7 @@ export type AgentContentBlock = {
10
10
  } | {
11
11
  type: "tool_result";
12
12
  id: string;
13
+ name?: string;
13
14
  output: unknown;
14
15
  is_error?: boolean;
15
16
  } | {
@@ -38,6 +39,14 @@ export type AgentContentBlock = {
38
39
  } | {
39
40
  type: "system";
40
41
  reason: string;
42
+ } | {
43
+ type: "decision";
44
+ tool_use_id?: string;
45
+ tool_code: string;
46
+ decision: "approved" | "rejected";
47
+ decided_by?: string;
48
+ decided_at?: string;
49
+ note?: string;
41
50
  };
42
51
  export interface AgentMessage {
43
52
  id: string;
@@ -46,6 +55,7 @@ export interface AgentMessage {
46
55
  role: AgentRole;
47
56
  content: AgentContentBlock[];
48
57
  created_at: string;
58
+ streaming?: boolean;
49
59
  }
50
60
  export type AgentInvocationStatus = "proposed" | "pending_approval" | "approved" | "rejected" | "running" | "succeeded" | "failed" | "canceled" | "interrupted";
51
61
  export interface AgentToolInvocation {
@@ -62,7 +72,9 @@ export interface AgentToolInvocation {
62
72
  edits?: Record<string, unknown>;
63
73
  };
64
74
  result?: unknown;
65
- audit_ref?: string;
75
+ audit_operation_id?: string;
76
+ reason?: string;
77
+ confidence?: number;
66
78
  }
67
79
  export type AgentConversationStatus = "active" | "canceling" | "interrupted" | "closed";
68
80
  export interface AgentConversation {
@@ -85,12 +97,15 @@ export interface AgentConversation {
85
97
  active_instance?: string;
86
98
  }
87
99
  export declare function createConversation(input: {
88
- agent_code: string;
100
+ agent_code?: string;
89
101
  context?: Record<string, unknown>;
90
102
  }): Promise<AgentConversation>;
91
- export declare function sendMessage(text: string, conversationId: string, seq: number): Promise<AgentMessage>;
103
+ export declare function sendMessage(text: string, conversationId: string, _seq?: number): Promise<AgentMessage>;
104
+ export declare function sendElicitResponse(conversationId: string, _seq: number | undefined, toolUseId: string, data: Record<string, unknown>): Promise<AgentMessage>;
92
105
  export declare function approveInvocation(id: string, edits?: Record<string, unknown>): Promise<void>;
93
106
  export declare function rejectInvocation(id: string, note?: string): Promise<void>;
94
107
  export declare function cancelConversation(id: string): Promise<void>;
95
108
  export declare function listConversations(): Promise<AgentConversation[]>;
109
+ export declare function rerunMessageTurn(conversationId: string): Promise<void>;
110
+ export declare function listPendingInvocations(conversationId: string): Promise<AgentToolInvocation[]>;
96
111
  export declare function loadHistory(conversationId: string): Promise<AgentMessage[]>;
@@ -0,0 +1,3 @@
1
+ export declare function sanitizeRedirectPath(value: string | null | undefined): string;
2
+ export declare function loginPathForRedirectPath(value: string | null | undefined): string;
3
+ export declare function loginPathForCurrentLocation(): string;
@@ -9,3 +9,17 @@ export declare function createTenant(code: string, name: string): Promise<Tenant
9
9
  export declare function logout(): Promise<void>;
10
10
  export declare function listSSOProviders(tenantCode?: string): Promise<SSOProvider[]>;
11
11
  export declare function ssoAuthorizeUrl(slug: string, tenantCode?: string, redirect?: string): string;
12
+ /**
13
+ * Impersonation client surface. Each call dispatches through
14
+ * POST /api/actions/{code} like every other auth handler. The server
15
+ * sets / clears the impersonation cookies via the LoginResult
16
+ * HTTPCustomizer; the client receives the public response shape
17
+ * (user / tenant / expires_at) and reloads the auth context.
18
+ */
19
+ export interface ImpersonationStartResponse extends LoginResponse {
20
+ impersonation_session_id: string;
21
+ session_expires_at: string;
22
+ }
23
+ export declare function impersonationStart(targetUserId: string, reason: string, durationMinutes?: number): Promise<ImpersonationStartResponse>;
24
+ export declare function impersonationStop(): Promise<LoginResponse>;
25
+ export declare function impersonationRevoke(sessionId: string): Promise<void>;
@@ -1,9 +1,39 @@
1
+ /** Signals that auth.refresh failed terminally (refresh cookie missing, token
2
+ * expired/reused, session revoked). Callers MUST stop retrying and route the
3
+ * user back to /login — retrying produces an infinite 401/4xx storm against
4
+ * the rate-limited refresh endpoint. Distinct from generic network errors so
5
+ * useSSE can branch on it. */
6
+ export declare class RefreshDeadError extends Error {
7
+ status: number;
8
+ constructor(status: number);
9
+ }
1
10
  export declare function ensureRefresh(): Promise<void>;
2
11
  type PersistentAuthFailureHandler = () => void;
3
12
  /** Replace the handler invoked on persistent 401. Intended for tests
4
13
  * and non-browser consumers. Returns the previous handler so callers
5
14
  * can restore it if needed. */
6
15
  export declare function setPersistentAuthFailureHandler(h: PersistentAuthFailureHandler): PersistentAuthFailureHandler;
16
+ /** Returns the currently registered persistent-auth-failure handler. useSSE
17
+ * reads this lazily so a setPersistentAuthFailureHandler() call from a test
18
+ * is observed by the SSE retry loop without re-importing the module. */
19
+ export declare function getPersistentAuthFailureHandler(): PersistentAuthFailureHandler;
20
+ export type ApiErrorReport = {
21
+ status: number;
22
+ code: string;
23
+ message: string;
24
+ };
25
+ type ApiErrorReporter = (report: ApiErrorReport) => void;
26
+ /** Replace the reporter invoked for every non-2xx response. Returns the
27
+ * previous reporter so callers can restore it. Tests should install a
28
+ * spy or no-op via this hook instead of stubbing `console.error`. */
29
+ export declare function setApiErrorReporter(r: ApiErrorReporter): ApiErrorReporter;
7
30
  export declare function apiFetch<T>(path: string, options?: RequestInit): Promise<T>;
31
+ export interface BlobResponse {
32
+ blob: Blob;
33
+ filename: string;
34
+ headers: Headers;
35
+ }
36
+ export declare function apiFetchBlob(path: string, options?: RequestInit): Promise<BlobResponse>;
37
+ export declare function parseContentDispositionFilename(headers: Headers): string;
8
38
  export declare function callHandler<R = unknown>(code: string, args?: unknown): Promise<R>;
9
39
  export {};
@@ -1,11 +1,23 @@
1
1
  import type { ListParams, ListResponse, DataResponse } from "../types/api";
2
2
  import type { PkValues } from "../types/schema";
3
+ import type { ExportRequest } from "../components/pages/exportRequest";
3
4
  export declare function listEntities(entity: string, params?: ListParams): Promise<ListResponse>;
4
5
  export declare function getEntity(entity: string, pkValues: PkValues | string): Promise<DataResponse>;
5
6
  export declare function createEntity(entity: string, data: Record<string, unknown>): Promise<DataResponse>;
6
7
  export declare function updateEntity(entity: string, pkValues: PkValues | string, data: Record<string, unknown>): Promise<DataResponse>;
7
8
  export declare function deleteEntity(entity: string, pkValues: PkValues | string): Promise<void>;
8
9
  export declare function restoreEntity(entity: string, pkValues: PkValues | string): Promise<void>;
10
+ /** Result of POST /api/data/{entity}/export. The server streams a CSV
11
+ * blob; the client gets the bytes plus the server-resolved filename
12
+ * (parsed from Content-Disposition by apiFetchBlob, with RFC 5987
13
+ * filename* preferred). Triggering the actual download (anchor click)
14
+ * is the caller's job — separation lets ExportMenu show the bytes in a
15
+ * toast when the browser blocks the download. */
16
+ export interface ExportResponse {
17
+ blob: Blob;
18
+ filename: string;
19
+ }
20
+ export declare function exportEntities(entity: string, body: ExportRequest): Promise<ExportResponse>;
9
21
  /**
10
22
  * Action request body is flat: top-level keys are handler params. The only
11
23
  * reserved control key is `_ids` (array of object IDs for single/batch
@@ -2,8 +2,25 @@ export type SSEEvent = {
2
2
  type: "entity_changed";
3
3
  entity: string;
4
4
  ids: string[];
5
+ objects?: Array<{
6
+ object_id?: string;
7
+ pk?: Record<string, string>;
8
+ }>;
5
9
  action: "created" | "updated" | "deleted" | "restored";
6
10
  } | {
7
11
  type: "session_refresh";
8
12
  };
13
+ export declare const agentBus: EventTarget;
14
+ export declare const AGENT_FRAME_EVENT = "agent-frame";
15
+ export declare const AGENT_MESSAGE_CHANGED_EVENT = "agent-message-changed";
16
+ export interface AgentFrameDetail {
17
+ convId: string;
18
+ kind: string;
19
+ turnId?: string;
20
+ payload?: Record<string, unknown>;
21
+ }
22
+ export declare function emitAgentFrame(detail: AgentFrameDetail): void;
23
+ export declare class SSEAuthError extends Error {
24
+ constructor();
25
+ }
9
26
  export declare function streamEvents(signal?: AbortSignal): AsyncGenerator<SSEEvent>;
@@ -1,11 +1,17 @@
1
- import type { PublicParamsResponse, ResolvedParam } from "../types/api";
1
+ import type { ParamLookup, PublicParamsResponse } from "../types/api";
2
2
  /**
3
3
  * Fetches the full pre-login envelope from /api/params/public:
4
- * {parameters, accents, branding}. Used by AuthShell to theme
4
+ * {parameters, accents, branding, meta}. Used by AuthShell to theme
5
5
  * unauthenticated screens before any user context exists.
6
6
  */
7
7
  export declare function fetchPublicParams(): Promise<PublicParamsResponse>;
8
- export declare function fetchParam(code: string): Promise<ResolvedParam>;
8
+ /**
9
+ * Looks up a single parameter from the platform. Always returns a
10
+ * `ParamLookup`; `found:false` signals "no value, use your default".
11
+ * Network/auth failures still throw - "missing" is normal, "broken"
12
+ * is an error.
13
+ */
14
+ export declare function fetchParam(code: string): Promise<ParamLookup>;
9
15
  /**
10
16
  * Persist a parameter override at user scope. Writes via the existing
11
17
  * subresource $params channel on the user entity (PATCH /api/data/user).
@@ -2,5 +2,6 @@ export interface AgentChatPanelProps {
2
2
  open: boolean;
3
3
  onClose: () => void;
4
4
  context?: string;
5
+ title?: string;
5
6
  }
6
- export declare function AgentChatPanel({ open, onClose, context }: AgentChatPanelProps): import("react/jsx-runtime").JSX.Element | null;
7
+ export declare function AgentChatPanel({ open, onClose, context, title }: AgentChatPanelProps): import("react/jsx-runtime").JSX.Element | null;
@@ -1,2 +1,2 @@
1
1
  import type { FieldRendererProps } from "./index";
2
- export declare function EmailField({ value, mode, onChange }: FieldRendererProps): import("react/jsx-runtime").JSX.Element;
2
+ export declare function EmailField({ value, onChange }: FieldRendererProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,2 @@
1
+ import type { FieldRendererProps } from "./index";
2
+ export declare function PhoneField({ value, onChange }: FieldRendererProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,2 @@
1
+ import type { FieldRendererProps } from "./index";
2
+ export declare function RichTextField(props: FieldRendererProps): import("react/jsx-runtime").JSX.Element;
@@ -1,2 +1,2 @@
1
1
  import type { FieldRendererProps } from "./index";
2
- export declare function UrlField({ field, value, mode, onChange }: FieldRendererProps): import("react/jsx-runtime").JSX.Element;
2
+ export declare function UrlField({ value, onChange }: FieldRendererProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,2 @@
1
+ import type { CellFactory } from "../registry";
2
+ export declare const badgeFactory: CellFactory;
@@ -0,0 +1,2 @@
1
+ import type { CellFactory } from "../registry";
2
+ export declare const boolPillFactory: CellFactory;
@@ -0,0 +1,2 @@
1
+ import type { CellFactory } from "../registry";
2
+ export declare const codeFactory: CellFactory;
@@ -0,0 +1,2 @@
1
+ import type { CellFactory } from "../registry";
2
+ export declare const emailFactory: CellFactory;
@@ -0,0 +1,9 @@
1
+ import { type FC, type SVGProps } from "react";
2
+ type IconFC = FC<SVGProps<SVGSVGElement>>;
3
+ export interface HostIconProps {
4
+ /** Canonical (after-www) hostname; pass null/empty to render the globe. */
5
+ domain: string | null | undefined;
6
+ }
7
+ export declare function HostIcon({ domain }: HostIconProps): React.ReactElement;
8
+ export declare const GENERIC_GLOBE: IconFC;
9
+ export {};
@@ -0,0 +1,2 @@
1
+ import type { CellFactory } from "../registry";
2
+ export declare const linkFactory: CellFactory;
@@ -0,0 +1,2 @@
1
+ import type { CellFactory } from "../registry";
2
+ export declare const markdownFactory: CellFactory;
@@ -0,0 +1,2 @@
1
+ import type { CellFactory } from "../registry";
2
+ export declare const moneyFactory: CellFactory;
@@ -0,0 +1,2 @@
1
+ import type { CellFactory } from "../registry";
2
+ export declare const multilangInlineFactory: CellFactory;
@@ -0,0 +1,2 @@
1
+ import type { CellFactory } from "../registry";
2
+ export declare const nextRunFactory: CellFactory;
@@ -0,0 +1,2 @@
1
+ import type { CellFactory } from "../registry";
2
+ export declare const numberFactory: CellFactory;
@@ -0,0 +1,2 @@
1
+ import type { CellFactory } from "../registry";
2
+ export declare const passwordMaskFactory: CellFactory;
@@ -0,0 +1,2 @@
1
+ import type { CellFactory } from "../registry";
2
+ export declare const phoneFactory: CellFactory;
@@ -0,0 +1,2 @@
1
+ import type { CellFactory } from "../registry";
2
+ export declare const refLinkFactory: CellFactory;
@@ -0,0 +1,2 @@
1
+ import type { CellFactory } from "../registry";
2
+ export declare const richTextPreviewFactory: CellFactory;
@@ -0,0 +1,2 @@
1
+ import type { CellFactory } from "../registry";
2
+ export declare const statusPillFactory: CellFactory;
@@ -0,0 +1,2 @@
1
+ import type { CellFactory } from "../registry";
2
+ export declare const tagListFactory: CellFactory;
@@ -0,0 +1,2 @@
1
+ import type { CellFactory } from "../registry";
2
+ export declare const textFactory: CellFactory;
@@ -0,0 +1,3 @@
1
+ import type { CellFactory } from "../registry";
2
+ export declare const timeAgoFactory: CellFactory;
3
+ export declare const timestampFullFactory: CellFactory;
@@ -0,0 +1,12 @@
1
+ export declare const LONG_TLD: RegExp;
2
+ export declare function looksLikeHostname(candidate: string): boolean;
3
+ export declare function normalizeUrl(raw: string): string | null;
4
+ export declare function parseDomain(href: string): string | null;
5
+ /**
6
+ * LinkedIn is the only host we special-case. Recognized path prefixes
7
+ * `/in/<slug>`, `/company/<slug>`, `/school/<slug>` render as `<prefix>/<slug>`.
8
+ * Any other linkedin.com URL (feed, jobs, posts, bare host) falls through to
9
+ * the default hostname rendering.
10
+ */
11
+ export declare function linkedinLabel(href: string, domain: string): string | null;
12
+ export declare function isValidUrl(href: string): boolean;
@@ -0,0 +1,2 @@
1
+ import type { CellFactory } from "../registry";
2
+ export declare const urlFactory: CellFactory;
@@ -0,0 +1,18 @@
1
+ import type { ReactNode } from "react";
2
+ import type { EntityField, Entity, Screen } from "../../../types/schema";
3
+ export type RowRecord = Record<string, unknown>;
4
+ export type CellRenderer = (value: unknown, record: RowRecord) => ReactNode;
5
+ export type RefsMap = Record<string, Record<string, Record<string, unknown>>>;
6
+ export interface CellResolveCtx {
7
+ field: EntityField;
8
+ fieldName: string;
9
+ entity?: Entity;
10
+ entities?: Record<string, Entity>;
11
+ screens?: Record<string, Screen>;
12
+ refs?: RefsMap | (() => RefsMap | undefined);
13
+ locale: string;
14
+ navigate?: (href: string) => void;
15
+ }
16
+ export type CellFactory = (ctx: CellResolveCtx) => CellRenderer;
17
+ export declare const REGISTRY_WIDGETS: readonly string[];
18
+ export declare function resolveCellRenderer(ctx: CellResolveCtx): CellRenderer;
@@ -1,7 +1,9 @@
1
- import type { EntityField } from "../../types/schema";
1
+ import type { EntityField, Entity, Screen } from "../../types/schema";
2
+ import { type FieldType } from "../../types/fieldType";
2
3
  export type RefsMap = Record<string, Record<string, Record<string, unknown>>>;
3
4
  export interface FieldRendererProps {
4
5
  field: EntityField;
6
+ entityCode?: string;
5
7
  fieldName: string;
6
8
  value: unknown;
7
9
  mode: "display" | "edit";
@@ -10,9 +12,13 @@ export interface FieldRendererProps {
10
12
  refs?: RefsMap;
11
13
  fill?: boolean;
12
14
  compact?: boolean;
15
+ entity?: Entity;
16
+ entities?: Record<string, Entity>;
17
+ screens?: Record<string, Screen>;
18
+ navigate?: (href: string) => void;
19
+ locale: string;
13
20
  }
14
21
  type FieldRenderer = React.ComponentType<FieldRendererProps>;
22
+ export declare const editRegistry: Record<FieldType, FieldRenderer>;
15
23
  export declare function renderField(props: FieldRendererProps): React.ReactNode;
16
- export declare function getFieldRenderer(type: string): FieldRenderer;
17
- export declare function hasFieldRenderer(key: string): boolean;
18
24
  export {};
@@ -0,0 +1,2 @@
1
+ import type { FileWidgetProps } from "./types";
2
+ export declare function CircleImage(props: FileWidgetProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,2 @@
1
+ import type { FileWidgetProps } from "./types";
2
+ export declare function DocumentCard(props: FileWidgetProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,2 @@
1
+ import type { FileWidgetProps } from "./types";
2
+ export declare function FileList(props: FileWidgetProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,2 @@
1
+ import type { FileWidgetProps } from "./types";
2
+ export declare function Grid(props: FileWidgetProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,12 @@
1
+ import { formatBytes } from "./upload";
2
+ import type { FileWidgetProps } from "./types";
3
+ export interface ImageWidgetVisualConfig {
4
+ shape: "square" | "circle" | "wide";
5
+ aspectRatio?: string;
6
+ width?: string;
7
+ }
8
+ export interface ImageWidgetInternalProps extends FileWidgetProps {
9
+ visual: ImageWidgetVisualConfig;
10
+ }
11
+ export declare function ImageWidget(props: ImageWidgetInternalProps): import("react/jsx-runtime").JSX.Element;
12
+ export { formatBytes };
@@ -0,0 +1,2 @@
1
+ import type { FileWidgetProps } from "./types";
2
+ export declare function LabeledSlots(props: FileWidgetProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,2 @@
1
+ import type { FileWidgetProps } from "./types";
2
+ export declare function SquareImage(props: FileWidgetProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,2 @@
1
+ import type { FileWidgetProps } from "./types";
2
+ export declare function WideBanner(props: FileWidgetProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1 @@
1
+ export declare function registerBuiltinFileWidgets(): void;
@@ -0,0 +1,14 @@
1
+ import type { ReactNode } from "react";
2
+ export interface CropperOptions {
3
+ aspectRatio?: number;
4
+ file: File;
5
+ }
6
+ export interface CropperResult {
7
+ blob: Blob;
8
+ filename: string;
9
+ }
10
+ export type ImageCropper = (opts: CropperOptions) => Promise<CropperResult>;
11
+ export declare function setImageCropper(c: ImageCropper | null): void;
12
+ export declare function getImageCropper(): ImageCropper;
13
+ export declare function setCropperRenderer(fn: ((node: ReactNode) => void) | null): void;
14
+ export declare function getCropperRenderer(): ((node: ReactNode) => void) | null;
@@ -0,0 +1,22 @@
1
+ import type { ReactNode } from "react";
2
+ export interface DraftEntry {
3
+ fileId: string;
4
+ discard: () => Promise<void> | void;
5
+ }
6
+ export interface FileDraftScopeApi {
7
+ registerDraft(entry: DraftEntry): void;
8
+ unregisterDraft(fileId: string): void;
9
+ hasDraft(fileId: string): boolean;
10
+ flushAllDrafts(): Promise<void>;
11
+ markCommitted(fileId: string): void;
12
+ }
13
+ export declare function FileDraftScope({ children }: {
14
+ children: ReactNode;
15
+ }): import("react/jsx-runtime").JSX.Element;
16
+ export declare function useFileDraftScope(): FileDraftScopeApi;
17
+ export declare function useDraftRegistration(): {
18
+ register: (fileId: string, discard: () => Promise<void> | void) => void;
19
+ unregister: (fileId: string) => void;
20
+ markCommitted: (fileId: string) => void;
21
+ isDraft: (fileId: string) => boolean;
22
+ };
@@ -0,0 +1,12 @@
1
+ import type { HydratedFile } from "./types";
2
+ export interface FocalPoint {
3
+ x: number;
4
+ y: number;
5
+ }
6
+ export declare function resolveFileAltText(file: HydratedFile | null, alt: string | undefined, fallback: string): string;
7
+ export declare function previewFileURL(file: HydratedFile): string | undefined;
8
+ export declare function downloadFileURL(file: HydratedFile): string | undefined;
9
+ export declare function preferredListThumbnailURL(file: HydratedFile | null, preferredDerivationKey?: string): string | undefined;
10
+ export declare function readFocalPoint(file: HydratedFile | null): FocalPoint | null;
11
+ export declare function focalPointObjectPosition(point: FocalPoint | null): string | undefined;
12
+ export declare function withFocalPoint(file: HydratedFile, point: FocalPoint): HydratedFile;
@@ -0,0 +1,23 @@
1
+ import type { ReactNode } from "react";
2
+ import type { Entity, Screen } from "../../types/schema";
3
+ import type { FileFieldDef, FileFieldValue } from "../../types/files";
4
+ import type { RefsMap } from "../../components/fields";
5
+ export declare function getEntityFileField(entity: Pick<Entity, "files">, fieldName: string): FileFieldDef | undefined;
6
+ export declare function getFileFieldValue(record: Record<string, unknown>, fieldName: string): FileFieldValue;
7
+ export declare function getSchemaFieldValue(entity: Pick<Entity, "fields" | "files">, record: Record<string, unknown>, fieldName: string): unknown;
8
+ export declare function serializeSchemaFieldValue(entity: Pick<Entity, "fields" | "files">, fieldName: string, value: unknown): unknown;
9
+ export declare function resolveSchemaFieldLabel(entity: Pick<Entity, "fields" | "files">, fieldName: string, entities?: Record<string, Entity>): string;
10
+ export declare function renderSchemaField(props: {
11
+ entity: Pick<Entity, "fields" | "files">;
12
+ entityCode?: string;
13
+ fieldName: string;
14
+ record: Record<string, unknown>;
15
+ mode: "display" | "edit";
16
+ onChange?: (value: unknown) => void;
17
+ refs?: RefsMap;
18
+ disabled?: boolean;
19
+ entities?: Record<string, Entity>;
20
+ screens?: Record<string, Screen>;
21
+ navigate?: (href: string) => void;
22
+ locale: string;
23
+ }): ReactNode;
@@ -0,0 +1,16 @@
1
+ export { SquareImage } from "./SquareImage";
2
+ export { CircleImage } from "./CircleImage";
3
+ export { WideBanner } from "./WideBanner";
4
+ export { Grid } from "./Grid";
5
+ export { DocumentCard } from "./DocumentCard";
6
+ export { FileList } from "./FileList";
7
+ export { LabeledSlots } from "./LabeledSlots";
8
+ export { registerFileWidget, getFileWidget, hasFileWidget, __resetFileWidgetRegistryForTests, } from "./registry";
9
+ export { getEntityFileField, getFileFieldValue, getSchemaFieldValue, serializeSchemaFieldValue, resolveSchemaFieldLabel, renderSchemaField, } from "./host";
10
+ export { buildFileFieldPatch, buildFilesPayload, collectCommittedFileIds, } from "./payload";
11
+ export { uploadFile, discardFile, validateClientSide, formatBytes, UploadError, } from "./upload";
12
+ export { setImageCropper, getImageCropper, setCropperRenderer, getCropperRenderer, } from "./cropper";
13
+ export type { ImageCropper, CropperOptions, CropperResult, } from "./cropper";
14
+ export { FileDraftScope, useFileDraftScope, useDraftRegistration, } from "./draft-scope";
15
+ export type { FileDraftScopeApi, DraftEntry, } from "./draft-scope";
16
+ export type { FileFieldDef, FileFieldDisplay, FileFieldMode, FileWidget, FileWidgetProps, HydratedFile, UploadProgress, UploadedFile, } from "./types";
@@ -0,0 +1,21 @@
1
+ import type { Entity } from "../../types/schema";
2
+ import type { FileFieldDef, FileFieldValue } from "../../types/files";
3
+ export interface FileSetItem {
4
+ file_id: string;
5
+ filename?: string;
6
+ slot?: string;
7
+ position?: number;
8
+ metadata?: Record<string, unknown>;
9
+ }
10
+ export interface FileFieldPatch {
11
+ clear?: true;
12
+ set?: FileSetItem[];
13
+ }
14
+ export declare function buildFileFieldPatch(field: FileFieldDef, value: FileFieldValue): FileFieldPatch;
15
+ export declare function buildFilesPayload(opts: {
16
+ entity: Pick<Entity, "files"> & Partial<Pick<Entity, "fields">>;
17
+ formData: Record<string, unknown>;
18
+ record: Record<string, unknown> | undefined;
19
+ isNew: boolean;
20
+ }): Record<string, FileFieldPatch>;
21
+ export declare function collectCommittedFileIds(payload: Record<string, FileFieldPatch>): string[];
@@ -0,0 +1,5 @@
1
+ import type { FileWidget } from "./types";
2
+ export declare function registerFileWidget(code: string, widget: FileWidget): void;
3
+ export declare function getFileWidget(code: string): FileWidget | undefined;
4
+ export declare function hasFileWidget(code: string): boolean;
5
+ export declare function __resetFileWidgetRegistryForTests(): void;
@@ -0,0 +1,15 @@
1
+ import type { FileFieldDef, FileFieldDisplay, FileFieldMode, FileFieldValue, HydratedFile, UploadProgress, UploadedFile } from "../../types/files";
2
+ export type { FileFieldDef, FileFieldDisplay, FileFieldMode, FileFieldValue, HydratedFile, UploadProgress, UploadedFile, };
3
+ export interface FileWidgetProps {
4
+ field: FileFieldDef;
5
+ fieldName: string;
6
+ entityCode?: string;
7
+ value: FileFieldValue;
8
+ mode: "display" | "edit";
9
+ onChange?: (next: FileFieldValue) => void;
10
+ disabled?: boolean;
11
+ alt?: string;
12
+ uploadFieldCode?: string;
13
+ uploadSlotCode?: string;
14
+ }
15
+ export type FileWidget = React.ComponentType<FileWidgetProps>;